();
102 | map.put("name", "admin");
103 | map.put("role", "ADMIN");
104 | map.put("uid", "1");
105 | BaseResponseDTO baseResponseDTO = new BaseResponseDTO();
106 | baseResponseDTO.setData(map);
107 | return baseResponseDTO;
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/examples/javaapp/src/main/java/io/github/dunwu/web/controller/HelloController.java:
--------------------------------------------------------------------------------
1 | package io.github.dunwu.web.controller;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.bind.annotation.RequestMethod;
6 | import org.springframework.web.bind.annotation.RequestParam;
7 | import org.springframework.web.servlet.ModelAndView;
8 |
9 | /**
10 | * spring mvc 的第一个程序
11 | *
12 | * @author Zhang Peng
13 | * @since 2016.07.29
14 | */
15 | @Controller
16 | @RequestMapping(value = "/hello")
17 | public class HelloController {
18 |
19 | /**
20 | *
21 | * 在本例中,Spring将会将数据传给 hello.jsp
22 | *
23 | * 访问形式:http://localhost:8080/hello?name=张三
24 | */
25 | @RequestMapping(value = "/name", method = RequestMethod.GET)
26 | public ModelAndView hello(@RequestParam("name") String name) {
27 | ModelAndView mav = new ModelAndView();
28 | mav.addObject("message", "你好," + name);
29 | mav.setViewName("hello");
30 | return mav;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/examples/javaapp/src/main/java/io/github/dunwu/web/controller/IndexController.java:
--------------------------------------------------------------------------------
1 | /**
2 | * The Apache License 2.0 Copyright (c) 2016 Zhang Peng
3 | */
4 | package io.github.dunwu.web.controller;
5 |
6 | import org.springframework.stereotype.Controller;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.RequestMethod;
9 | import org.springframework.web.servlet.ModelAndView;
10 |
11 | /**
12 | * @author Zhang Peng
13 | * @since 2017/4/12.
14 | */
15 | @Controller
16 | public class IndexController {
17 |
18 | /**
19 | *
20 | * 返回 ModelAndView 对象到视图层。在本例中,视图解析器解析视图名为 index,会自动关联到 index.jsp。
21 | *
22 | * 访问形式:http://localhost:8080/
23 | */
24 | @RequestMapping(value = "/", method = RequestMethod.GET)
25 | public ModelAndView index() {
26 | ModelAndView mav = new ModelAndView();
27 | mav.setViewName("index");
28 | return mav;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/examples/javaapp/src/main/java/io/github/dunwu/web/dto/BaseResponseDTO.java:
--------------------------------------------------------------------------------
1 | package io.github.dunwu.web.dto;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.List;
6 |
7 | public class BaseResponseDTO {
8 |
9 | private final List messages = new ArrayList<>();
10 |
11 | private Integer code = DEFAULT_RESPONSE_RESULT.SUCCESS.value();
12 |
13 | private T data;
14 |
15 | public BaseResponseDTO() {
16 | }
17 |
18 | public BaseResponseDTO(T dto) {
19 | this.data = dto;
20 | }
21 |
22 | public Integer getCode() {
23 | return code;
24 | }
25 |
26 | public void setCode(Integer code) {
27 | this.code = code;
28 | }
29 |
30 | public void addError(String error) {
31 | this.messages.add(error);
32 | }
33 |
34 | public void addErrors(String[] errors) {
35 | this.addErrors(Arrays.asList(errors));
36 | }
37 |
38 | public void addErrors(List errorList) {
39 | this.messages.addAll(errorList);
40 | }
41 |
42 | public void removeError(String error) {
43 | this.messages.remove(error);
44 | }
45 |
46 | public List getMessages() {
47 | return messages;
48 | }
49 |
50 | public T getData() {
51 | return data;
52 | }
53 |
54 | public void setData(T data) {
55 | this.data = data;
56 | }
57 |
58 | public enum DEFAULT_RESPONSE_RESULT {
59 |
60 | SUCCESS(0, "[]"), // 成功
61 | AUTHEN_FAIL(-1, "认证失败"), // 认证失败
62 | AUTHOR_FAIL(-2, "权限不足"), // 授权不足
63 | PARAM_CHECK_FAIL(-3, ""), // 参数校验失败,错误信息交由业务逻辑处理
64 | RESOURCE_NOT_EXIST(-4, "请求资源不存在"), // 请求资源不存在
65 | SYSTEM_ERROR(-5, "系统错误"),
66 | DATA_MALFORMAT(-6, "请求参数数据格式不正确"),
67 | REQMETHOD_ERROR(-7, "请求方法不正确"),
68 | TYPE_MISMATCH(-8, "请求参数类型不匹配"),
69 | MISS_REQUEST_PARAM(-9, "请求参数缺失");
70 |
71 | private final Integer value;
72 |
73 | private final String desc;
74 |
75 | DEFAULT_RESPONSE_RESULT(int value, String desc) {
76 | this.value = value;
77 | this.desc = desc;
78 | }
79 |
80 | public int value() {
81 | return value;
82 | }
83 |
84 | public String desc() {
85 | return desc;
86 | }
87 |
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/examples/javaapp/src/main/java/io/github/dunwu/web/dto/MenuDTO.java:
--------------------------------------------------------------------------------
1 | package io.github.dunwu.web.dto;
2 |
3 | import org.apache.commons.lang3.builder.CompareToBuilder;
4 | import org.apache.commons.lang3.builder.EqualsBuilder;
5 | import org.apache.commons.lang3.builder.HashCodeBuilder;
6 |
7 | import java.util.Arrays;
8 | import java.util.Set;
9 | import java.util.TreeSet;
10 |
11 | public class MenuDTO implements Cloneable, Comparable {
12 |
13 | private final Set children = new TreeSet();
14 |
15 | private String key;
16 |
17 | private String title;
18 |
19 | private String icon;
20 |
21 | private String type;
22 |
23 | private String url;
24 |
25 | public MenuDTO() {
26 | }
27 |
28 | public MenuDTO(String key, String title, String icon, String type, String url) {
29 | this.key = key;
30 | this.title = title;
31 | this.icon = icon;
32 | this.type = type;
33 | this.url = url;
34 | }
35 |
36 | public MenuDTO clone() throws CloneNotSupportedException {
37 | super.clone();
38 | MenuDTO menuDTO = new MenuDTO();
39 | menuDTO.setType(type);
40 | menuDTO.setKey(key);
41 | menuDTO.setTitle(title);
42 | menuDTO.setIcon(icon);
43 | menuDTO.setUrl(url);
44 | menuDTO.setUrl(url);
45 | return menuDTO;
46 | }
47 |
48 | public String getKey() {
49 | return key;
50 | }
51 |
52 | public void setKey(String key) {
53 | this.key = key;
54 | }
55 |
56 | public String getTitle() {
57 | return title;
58 | }
59 |
60 | public void setTitle(String title) {
61 | this.title = title;
62 | }
63 |
64 | public String getIcon() {
65 | return icon;
66 | }
67 |
68 | public void setIcon(String icon) {
69 | this.icon = icon;
70 | }
71 |
72 | public String getType() {
73 | return type;
74 | }
75 |
76 | public void setType(String type) {
77 | this.type = type;
78 | }
79 |
80 | public String getUrl() {
81 | return url;
82 | }
83 |
84 | public void setUrl(String url) {
85 | this.url = url;
86 | }
87 |
88 | public Set getChildren() {
89 | return children;
90 | }
91 |
92 | public void addChild(MenuDTO child) {
93 | this.children.add(child);
94 | }
95 |
96 | public void addChildren(Set children) {
97 | this.children.addAll(children);
98 | }
99 |
100 | public void addChildren(MenuDTO[] children) {
101 | this.children.addAll(Arrays.asList(children));
102 | }
103 |
104 | @Override
105 | public boolean equals(Object obj) {
106 | boolean equals = false;
107 | if (obj instanceof MenuDTO) {
108 | MenuDTO menuDTO = (MenuDTO) obj;
109 | equals = (new EqualsBuilder().append(url, menuDTO.getUrl())).isEquals();
110 | }
111 | return equals;
112 | }
113 |
114 | @Override
115 | public int hashCode() {
116 | return new HashCodeBuilder(17, 37).append(url).toHashCode();
117 | }
118 |
119 | @Override
120 | public int compareTo(MenuDTO otherMenuDTO) {
121 | return new CompareToBuilder().append(key, otherMenuDTO.getKey())
122 | .append(url, otherMenuDTO.getUrl())
123 | .toComparison();
124 | }
125 |
126 | }
127 |
--------------------------------------------------------------------------------
/examples/javaapp/src/main/resources/spring/spring-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/examples/javaapp/src/main/resources/tomcat/conf/server.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 |
11 |
14 |
15 |
16 |
19 |
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/examples/javaapp/src/main/webapp/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Main-Class: io.github.dunwu.Main
3 |
--------------------------------------------------------------------------------
/examples/javaapp/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | spring-embed-tomcat-demo-helloworld
5 |
6 |
7 |
8 | spring-servlet
9 | org.springframework.web.servlet.DispatcherServlet
10 | 1
11 |
12 | contextConfigLocation
13 | classpath:spring/spring-servlet.xml
14 |
15 |
16 |
17 | spring-servlet
18 | /
19 |
20 |
21 |
22 |
23 |
24 |
25 | encodingFilter
26 | org.springframework.web.filter.CharacterEncodingFilter
27 |
28 | encoding
29 | UTF-8
30 |
31 |
32 | forceEncoding
33 | true
34 |
35 |
36 |
37 | encodingFilter
38 | /*
39 | REQUEST
40 | FORWARD
41 |
42 |
43 |
44 | CorsFilter
45 | io.github.dunwu.filter.CorsFilter
46 |
47 | headerKey
48 | Host
49 |
50 |
51 | regex
52 |
53 | ((http://)|(https://))?(\w*\.)*(\S)*
54 |
55 |
56 |
57 | CorsFilter
58 | /*
59 |
60 |
61 |
62 |
63 | /views/jsp/index.jsp
64 |
65 |
66 |
--------------------------------------------------------------------------------
/examples/javaapp/src/main/webapp/views/jsp/hello.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
2 | <%
3 | String path = request.getContextPath();
4 | String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
5 | %>
6 |
7 |
8 |
9 |
10 | HelloController
11 |
12 |
13 | ${message}
14 | 回到首页
15 |
16 |
17 |
--------------------------------------------------------------------------------
/examples/javaapp/src/main/webapp/views/jsp/index.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
2 | <%
3 | String domain = request.getScheme() + "://" + request.getServerName() + request.getContextPath();
4 | String host = request.getRemoteHost();
5 | // int port = request.getServerPort();
6 | Integer port = Integer.valueOf(System.getProperty("tomcat.connector.port"));
7 |
8 |
9 | %>
10 |
11 |
12 |
13 |
14 | spring-embed-tomcat-demo
15 |
16 |
17 |
18 | spring-embed-tomcat-demo
19 | <%out.print("当前服务器信息:");%>
20 |
21 | - <%out.print("domain:" + domain);%>
22 | - <%out.print("host:" + host);%>
23 | - <%out.print("port:" + port);%>
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/conf.d/demo01.conf:
--------------------------------------------------------------------------------
1 | #-------------------------------------------
2 | # 简单的反向代理示例
3 | #-------------------------------------------
4 |
5 | upstream demo01_server {
6 | server 127.0.0.1:9010;
7 | }
8 |
9 | server {
10 | listen 80;
11 | server_name www.demo01.com;
12 |
13 | charset utf-8;
14 | proxy_connect_timeout 180;
15 | proxy_send_timeout 180;
16 | proxy_read_timeout 180;
17 | proxy_set_header Host $host;
18 | proxy_set_header X-Forwarded-For $remote_addr;
19 |
20 | # root /home/nginx/demos;
21 | root ../../../javaapp/src/main/webapp;
22 |
23 | location / {
24 | proxy_pass http://demo01_server;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/conf.d/demo02.conf:
--------------------------------------------------------------------------------
1 | #-------------------------------------------
2 | # 负载均衡示例
3 | #-------------------------------------------
4 |
5 | # 设定负载均衡的服务器列表
6 | upstream demo02-server {
7 | # weigth参数表示权值,权值越高被分配到的几率越大
8 | server 127.0.0.1:9021 weight=5;
9 | server 127.0.0.1:9022 weight=1;
10 | server 127.0.0.1:9023 weight=6;
11 | }
12 |
13 | server {
14 | listen 80;
15 | server_name www.demo02.com;
16 |
17 | charset utf-8;
18 | proxy_connect_timeout 180;
19 | proxy_send_timeout 180;
20 | proxy_read_timeout 180;
21 | proxy_set_header Host $host;
22 | proxy_set_header X-Forwarded-For $remote_addr;
23 |
24 | # root /home/nginx/demos;
25 | root ../../../javaapp/src/main/webapp;
26 |
27 | location / {
28 | proxy_pass http://demo02-server;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/conf.d/demo03.conf:
--------------------------------------------------------------------------------
1 | #-------------------------------------------
2 | # 多应用共用一个主域名,不同上下文的示例
3 | #-------------------------------------------
4 |
5 | upstream home-server {
6 | server 127.0.0.1:9030;
7 | }
8 |
9 | upstream product-server {
10 | server 127.0.0.1:9031;
11 | }
12 |
13 | upstream user-server {
14 | server 127.0.0.1:9032;
15 | }
16 |
17 | server {
18 | listen 80;
19 | server_name www.demo03.com;
20 |
21 | charset utf-8;
22 | proxy_connect_timeout 180;
23 | proxy_send_timeout 180;
24 | proxy_read_timeout 180;
25 | proxy_set_header Host $host;
26 | proxy_set_header X-Forwarded-For $remote_addr;
27 |
28 | # root /home/nginx/demos;
29 | root ../../../javaapp/src/main/webapp;
30 |
31 | location / {
32 | proxy_pass http://home-server;
33 | }
34 |
35 | location /product/{
36 | proxy_pass http://product-server;
37 | }
38 |
39 | location /user/ {
40 | proxy_pass http://user-server;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/conf.d/demo04.conf:
--------------------------------------------------------------------------------
1 | #-------------------------------------------
2 | # 前后端分离示例
3 | # root 为前端文件路径
4 | # upstream backend 配置后端服务器访问地址
5 | #-------------------------------------------
6 |
7 | upstream backend {
8 | server 127.0.0.1:9040;
9 | }
10 |
11 | server {
12 | listen 80;
13 | server_name www.demo04.com;
14 |
15 | # windows 下前后端分离场景,使用相对路径无法被识别,暂时搞不定
16 | root D:/Codes/ZP/Others/nginx-tutorial/demos/reactapp/dist;
17 |
18 | location ~ ^/api/ {
19 | proxy_pass http://backend;
20 | rewrite "^/api/(.*)$" /$1 break;
21 | }
22 |
23 | location ~* \.(json|txt|js|css|jpg|jpeg|gif|png|svg|ico|eot|otf|woff|woff2|ttf)$ {}
24 | }
25 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/conf.d/demo05.conf:
--------------------------------------------------------------------------------
1 | #-------------------------------------------
2 | # 设置文件服务器
3 | # root 为提供文件服务的根路径
4 | # Nginx 启动后,访问 http://localhost:9050
5 | #-------------------------------------------
6 |
7 | autoindex on;# 显示目录
8 | autoindex_exact_size on;# 显示文件大小
9 | autoindex_localtime on;# 显示文件时间
10 |
11 | server {
12 | charset utf-8,gbk; # windows 服务器下设置后,依然乱码,暂时无解
13 | listen 9050 default_server;
14 | listen [::]:9050 default_server;
15 | server_name _;
16 | root D:;
17 | }
18 |
19 | upstream demo05_server {
20 | server 127.0.0.1:9050;
21 | }
22 |
23 | server {
24 | listen 80;
25 | server_name www.demo05.com;
26 |
27 | charset utf-8;
28 | proxy_connect_timeout 180;
29 | proxy_send_timeout 180;
30 | proxy_read_timeout 180;
31 |
32 | location / {
33 | proxy_pass http://demo05_server;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/conf.d/demo06.conf:
--------------------------------------------------------------------------------
1 | #-------------------------------------------
2 | # 设置文件服务器
3 | # root 为提供文件服务的根路径
4 | #-------------------------------------------
5 |
6 | server {
7 | server_name www.demo06.com; # 你的域名或者 ip
8 | root D:/Codes/ZP/Others/nginx-tutorial/demos/reactadmin/build; # 你的克隆到的项目路径
9 | index index.html; # 显示首页
10 | location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|js|pdf|txt){
11 | root D:/Codes/ZP/Others/nginx-tutorial/demos/reactadmin/build;
12 | } # 静态文件访问
13 | }
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/fastcgi.conf:
--------------------------------------------------------------------------------
1 |
2 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
3 | fastcgi_param QUERY_STRING $query_string;
4 | fastcgi_param REQUEST_METHOD $request_method;
5 | fastcgi_param CONTENT_TYPE $content_type;
6 | fastcgi_param CONTENT_LENGTH $content_length;
7 |
8 | fastcgi_param SCRIPT_NAME $fastcgi_script_name;
9 | fastcgi_param REQUEST_URI $request_uri;
10 | fastcgi_param DOCUMENT_URI $document_uri;
11 | fastcgi_param DOCUMENT_ROOT $document_root;
12 | fastcgi_param SERVER_PROTOCOL $server_protocol;
13 | fastcgi_param REQUEST_SCHEME $scheme;
14 | fastcgi_param HTTPS $https if_not_empty;
15 |
16 | fastcgi_param GATEWAY_INTERFACE CGI/1.1;
17 | fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
18 |
19 | fastcgi_param REMOTE_ADDR $remote_addr;
20 | fastcgi_param REMOTE_PORT $remote_port;
21 | fastcgi_param SERVER_ADDR $server_addr;
22 | fastcgi_param SERVER_PORT $server_port;
23 | fastcgi_param SERVER_NAME $server_name;
24 |
25 | # PHP only, required if PHP was built with --enable-force-cgi-redirect
26 | fastcgi_param REDIRECT_STATUS 200;
27 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/fastcgi_params:
--------------------------------------------------------------------------------
1 |
2 | fastcgi_param QUERY_STRING $query_string;
3 | fastcgi_param REQUEST_METHOD $request_method;
4 | fastcgi_param CONTENT_TYPE $content_type;
5 | fastcgi_param CONTENT_LENGTH $content_length;
6 |
7 | fastcgi_param SCRIPT_NAME $fastcgi_script_name;
8 | fastcgi_param REQUEST_URI $request_uri;
9 | fastcgi_param DOCUMENT_URI $document_uri;
10 | fastcgi_param DOCUMENT_ROOT $document_root;
11 | fastcgi_param SERVER_PROTOCOL $server_protocol;
12 | fastcgi_param REQUEST_SCHEME $scheme;
13 | fastcgi_param HTTPS $https if_not_empty;
14 |
15 | fastcgi_param GATEWAY_INTERFACE CGI/1.1;
16 | fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
17 |
18 | fastcgi_param REMOTE_ADDR $remote_addr;
19 | fastcgi_param REMOTE_PORT $remote_port;
20 | fastcgi_param SERVER_ADDR $server_addr;
21 | fastcgi_param SERVER_PORT $server_port;
22 | fastcgi_param SERVER_NAME $server_name;
23 |
24 | # PHP only, required if PHP was built with --enable-force-cgi-redirect
25 | fastcgi_param REDIRECT_STATUS 200;
26 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/koi-utf:
--------------------------------------------------------------------------------
1 |
2 | # This map is not a full koi8-r <> utf8 map: it does not contain
3 | # box-drawing and some other characters. Besides this map contains
4 | # several koi8-u and Byelorussian letters which are not in koi8-r.
5 | # If you need a full and standard map, use contrib/unicode2nginx/koi-utf
6 | # map instead.
7 |
8 | charset_map koi8-r utf-8 {
9 |
10 | 80 E282AC ; # euro
11 |
12 | 95 E280A2 ; # bullet
13 |
14 | 9A C2A0 ; #
15 |
16 | 9E C2B7 ; # ·
17 |
18 | A3 D191 ; # small yo
19 | A4 D194 ; # small Ukrainian ye
20 |
21 | A6 D196 ; # small Ukrainian i
22 | A7 D197 ; # small Ukrainian yi
23 |
24 | AD D291 ; # small Ukrainian soft g
25 | AE D19E ; # small Byelorussian short u
26 |
27 | B0 C2B0 ; # °
28 |
29 | B3 D081 ; # capital YO
30 | B4 D084 ; # capital Ukrainian YE
31 |
32 | B6 D086 ; # capital Ukrainian I
33 | B7 D087 ; # capital Ukrainian YI
34 |
35 | B9 E28496 ; # numero sign
36 |
37 | BD D290 ; # capital Ukrainian soft G
38 | BE D18E ; # capital Byelorussian short U
39 |
40 | BF C2A9 ; # (C)
41 |
42 | C0 D18E ; # small yu
43 | C1 D0B0 ; # small a
44 | C2 D0B1 ; # small b
45 | C3 D186 ; # small ts
46 | C4 D0B4 ; # small d
47 | C5 D0B5 ; # small ye
48 | C6 D184 ; # small f
49 | C7 D0B3 ; # small g
50 | C8 D185 ; # small kh
51 | C9 D0B8 ; # small i
52 | CA D0B9 ; # small j
53 | CB D0BA ; # small k
54 | CC D0BB ; # small l
55 | CD D0BC ; # small m
56 | CE D0BD ; # small n
57 | CF D0BE ; # small o
58 |
59 | D0 D0BF ; # small p
60 | D1 D18F ; # small ya
61 | D2 D180 ; # small r
62 | D3 D181 ; # small s
63 | D4 D182 ; # small t
64 | D5 D183 ; # small u
65 | D6 D0B6 ; # small zh
66 | D7 D0B2 ; # small v
67 | D8 D18C ; # small soft sign
68 | D9 D18B ; # small y
69 | DA D0B7 ; # small z
70 | DB D188 ; # small sh
71 | DC D18D ; # small e
72 | DD D189 ; # small shch
73 | DE D187 ; # small ch
74 | DF D18A ; # small hard sign
75 |
76 | E0 D0AE ; # capital YU
77 | E1 D090 ; # capital A
78 | E2 D091 ; # capital B
79 | E3 D0A6 ; # capital TS
80 | E4 D094 ; # capital D
81 | E5 D095 ; # capital YE
82 | E6 D0A4 ; # capital F
83 | E7 D093 ; # capital G
84 | E8 D0A5 ; # capital KH
85 | E9 D098 ; # capital I
86 | EA D099 ; # capital J
87 | EB D09A ; # capital K
88 | EC D09B ; # capital L
89 | ED D09C ; # capital M
90 | EE D09D ; # capital N
91 | EF D09E ; # capital O
92 |
93 | F0 D09F ; # capital P
94 | F1 D0AF ; # capital YA
95 | F2 D0A0 ; # capital R
96 | F3 D0A1 ; # capital S
97 | F4 D0A2 ; # capital T
98 | F5 D0A3 ; # capital U
99 | F6 D096 ; # capital ZH
100 | F7 D092 ; # capital V
101 | F8 D0AC ; # capital soft sign
102 | F9 D0AB ; # capital Y
103 | FA D097 ; # capital Z
104 | FB D0A8 ; # capital SH
105 | FC D0AD ; # capital E
106 | FD D0A9 ; # capital SHCH
107 | FE D0A7 ; # capital CH
108 | FF D0AA ; # capital hard sign
109 | }
110 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/koi-win:
--------------------------------------------------------------------------------
1 |
2 | charset_map koi8-r windows-1251 {
3 |
4 | 80 88 ; # euro
5 |
6 | 95 95 ; # bullet
7 |
8 | 9A A0 ; #
9 |
10 | 9E B7 ; # ·
11 |
12 | A3 B8 ; # small yo
13 | A4 BA ; # small Ukrainian ye
14 |
15 | A6 B3 ; # small Ukrainian i
16 | A7 BF ; # small Ukrainian yi
17 |
18 | AD B4 ; # small Ukrainian soft g
19 | AE A2 ; # small Byelorussian short u
20 |
21 | B0 B0 ; # °
22 |
23 | B3 A8 ; # capital YO
24 | B4 AA ; # capital Ukrainian YE
25 |
26 | B6 B2 ; # capital Ukrainian I
27 | B7 AF ; # capital Ukrainian YI
28 |
29 | B9 B9 ; # numero sign
30 |
31 | BD A5 ; # capital Ukrainian soft G
32 | BE A1 ; # capital Byelorussian short U
33 |
34 | BF A9 ; # (C)
35 |
36 | C0 FE ; # small yu
37 | C1 E0 ; # small a
38 | C2 E1 ; # small b
39 | C3 F6 ; # small ts
40 | C4 E4 ; # small d
41 | C5 E5 ; # small ye
42 | C6 F4 ; # small f
43 | C7 E3 ; # small g
44 | C8 F5 ; # small kh
45 | C9 E8 ; # small i
46 | CA E9 ; # small j
47 | CB EA ; # small k
48 | CC EB ; # small l
49 | CD EC ; # small m
50 | CE ED ; # small n
51 | CF EE ; # small o
52 |
53 | D0 EF ; # small p
54 | D1 FF ; # small ya
55 | D2 F0 ; # small r
56 | D3 F1 ; # small s
57 | D4 F2 ; # small t
58 | D5 F3 ; # small u
59 | D6 E6 ; # small zh
60 | D7 E2 ; # small v
61 | D8 FC ; # small soft sign
62 | D9 FB ; # small y
63 | DA E7 ; # small z
64 | DB F8 ; # small sh
65 | DC FD ; # small e
66 | DD F9 ; # small shch
67 | DE F7 ; # small ch
68 | DF FA ; # small hard sign
69 |
70 | E0 DE ; # capital YU
71 | E1 C0 ; # capital A
72 | E2 C1 ; # capital B
73 | E3 D6 ; # capital TS
74 | E4 C4 ; # capital D
75 | E5 C5 ; # capital YE
76 | E6 D4 ; # capital F
77 | E7 C3 ; # capital G
78 | E8 D5 ; # capital KH
79 | E9 C8 ; # capital I
80 | EA C9 ; # capital J
81 | EB CA ; # capital K
82 | EC CB ; # capital L
83 | ED CC ; # capital M
84 | EE CD ; # capital N
85 | EF CE ; # capital O
86 |
87 | F0 CF ; # capital P
88 | F1 DF ; # capital YA
89 | F2 D0 ; # capital R
90 | F3 D1 ; # capital S
91 | F4 D2 ; # capital T
92 | F5 D3 ; # capital U
93 | F6 C6 ; # capital ZH
94 | F7 C2 ; # capital V
95 | F8 DC ; # capital soft sign
96 | F9 DB ; # capital Y
97 | FA C7 ; # capital Z
98 | FB D8 ; # capital SH
99 | FC DD ; # capital E
100 | FD D9 ; # capital SHCH
101 | FE D7 ; # capital CH
102 | FF DA ; # capital hard sign
103 | }
104 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/mime.types:
--------------------------------------------------------------------------------
1 |
2 | types {
3 | text/html html htm shtml;
4 | text/css css;
5 | text/xml xml;
6 | image/gif gif;
7 | image/jpeg jpeg jpg;
8 | application/javascript js;
9 | application/atom+xml atom;
10 | application/rss+xml rss;
11 |
12 | text/mathml mml;
13 | text/plain txt;
14 | text/vnd.sun.j2me.app-descriptor jad;
15 | text/vnd.wap.wml wml;
16 | text/x-component htc;
17 |
18 | image/png png;
19 | image/svg+xml svg svgz;
20 | image/tiff tif tiff;
21 | image/vnd.wap.wbmp wbmp;
22 | image/webp webp;
23 | image/x-icon ico;
24 | image/x-jng jng;
25 | image/x-ms-bmp bmp;
26 |
27 | application/font-woff woff;
28 | application/java-archive jar war ear;
29 | application/json json;
30 | application/mac-binhex40 hqx;
31 | application/msword doc;
32 | application/pdf pdf;
33 | application/postscript ps eps ai;
34 | application/rtf rtf;
35 | application/vnd.apple.mpegurl m3u8;
36 | application/vnd.google-earth.kml+xml kml;
37 | application/vnd.google-earth.kmz kmz;
38 | application/vnd.ms-excel xls;
39 | application/vnd.ms-fontobject eot;
40 | application/vnd.ms-powerpoint ppt;
41 | application/vnd.oasis.opendocument.graphics odg;
42 | application/vnd.oasis.opendocument.presentation odp;
43 | application/vnd.oasis.opendocument.spreadsheet ods;
44 | application/vnd.oasis.opendocument.text odt;
45 | application/vnd.openxmlformats-officedocument.presentationml.presentation
46 | pptx;
47 | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
48 | xlsx;
49 | application/vnd.openxmlformats-officedocument.wordprocessingml.document
50 | docx;
51 | application/vnd.wap.wmlc wmlc;
52 | application/x-7z-compressed 7z;
53 | application/x-cocoa cco;
54 | application/x-java-archive-diff jardiff;
55 | application/x-java-jnlp-file jnlp;
56 | application/x-makeself run;
57 | application/x-perl pl pm;
58 | application/x-pilot prc pdb;
59 | application/x-rar-compressed rar;
60 | application/x-redhat-package-manager rpm;
61 | application/x-sea sea;
62 | application/x-shockwave-flash swf;
63 | application/x-stuffit sit;
64 | application/x-tcl tcl tk;
65 | application/x-x509-ca-cert der pem crt;
66 | application/x-xpinstall xpi;
67 | application/xhtml+xml xhtml;
68 | application/xspf+xml xspf;
69 | application/zip zip;
70 |
71 | application/octet-stream bin exe dll;
72 | application/octet-stream deb;
73 | application/octet-stream dmg;
74 | application/octet-stream iso img;
75 | application/octet-stream msi msp msm;
76 |
77 | audio/midi mid midi kar;
78 | audio/mpeg mp3;
79 | audio/ogg ogg;
80 | audio/x-m4a m4a;
81 | audio/x-realaudio ra;
82 |
83 | video/3gpp 3gpp 3gp;
84 | video/mp2t ts;
85 | video/mp4 mp4;
86 | video/mpeg mpeg mpg;
87 | video/quicktime mov;
88 | video/webm webm;
89 | video/x-flv flv;
90 | video/x-m4v m4v;
91 | video/x-mng mng;
92 | video/x-ms-asf asx asf;
93 | video/x-ms-wmv wmv;
94 | video/x-msvideo avi;
95 | }
96 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/nginx.conf:
--------------------------------------------------------------------------------
1 | worker_processes 1;
2 | error_log logs/nginx-error.log info;
3 | events {
4 | worker_connections 1024;
5 | }
6 |
7 | http {
8 | default_type application/octet-stream;
9 | log_format main '$remote_addr - $remote_user [$time_local] "$request" '
10 | '$status $body_bytes_sent "$http_referer" '
11 | '"$http_user_agent" "$http_x_forwarded_for"';
12 | access_log logs/nginx-http-access.log;
13 | sendfile on;
14 | rewrite_log on;
15 | keepalive_timeout 180;
16 |
17 | client_max_body_size 20m;
18 | client_body_buffer_size 128k;
19 |
20 | #common header set
21 | proxy_http_version 1.1;
22 | proxy_set_header Host $host;
23 | proxy_set_header X-Real-IP $remote_addr;
24 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
25 | proxy_set_header X-Forwarded-Proto $scheme;
26 | proxy_set_header Upgrade $http_upgrade;
27 | proxy_set_header Connection "upgrade";
28 |
29 | include mime.types;
30 | include conf.d/*.conf;
31 | }
32 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/scgi_params:
--------------------------------------------------------------------------------
1 |
2 | scgi_param REQUEST_METHOD $request_method;
3 | scgi_param REQUEST_URI $request_uri;
4 | scgi_param QUERY_STRING $query_string;
5 | scgi_param CONTENT_TYPE $content_type;
6 |
7 | scgi_param DOCUMENT_URI $document_uri;
8 | scgi_param DOCUMENT_ROOT $document_root;
9 | scgi_param SCGI 1;
10 | scgi_param SERVER_PROTOCOL $server_protocol;
11 | scgi_param REQUEST_SCHEME $scheme;
12 | scgi_param HTTPS $https if_not_empty;
13 |
14 | scgi_param REMOTE_ADDR $remote_addr;
15 | scgi_param REMOTE_PORT $remote_port;
16 | scgi_param SERVER_PORT $server_port;
17 | scgi_param SERVER_NAME $server_name;
18 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/uwsgi_params:
--------------------------------------------------------------------------------
1 |
2 | uwsgi_param QUERY_STRING $query_string;
3 | uwsgi_param REQUEST_METHOD $request_method;
4 | uwsgi_param CONTENT_TYPE $content_type;
5 | uwsgi_param CONTENT_LENGTH $content_length;
6 |
7 | uwsgi_param REQUEST_URI $request_uri;
8 | uwsgi_param PATH_INFO $document_uri;
9 | uwsgi_param DOCUMENT_ROOT $document_root;
10 | uwsgi_param SERVER_PROTOCOL $server_protocol;
11 | uwsgi_param REQUEST_SCHEME $scheme;
12 | uwsgi_param HTTPS $https if_not_empty;
13 |
14 | uwsgi_param REMOTE_ADDR $remote_addr;
15 | uwsgi_param REMOTE_PORT $remote_port;
16 | uwsgi_param SERVER_PORT $server_port;
17 | uwsgi_param SERVER_NAME $server_name;
18 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/conf/win-utf:
--------------------------------------------------------------------------------
1 |
2 | # This map is not a full windows-1251 <> utf8 map: it does not
3 | # contain Serbian and Macedonian letters. If you need a full map,
4 | # use contrib/unicode2nginx/win-utf map instead.
5 |
6 | charset_map windows-1251 utf-8 {
7 |
8 | 82 E2809A ; # single low-9 quotation mark
9 |
10 | 84 E2809E ; # double low-9 quotation mark
11 | 85 E280A6 ; # ellipsis
12 | 86 E280A0 ; # dagger
13 | 87 E280A1 ; # double dagger
14 | 88 E282AC ; # euro
15 | 89 E280B0 ; # per mille
16 |
17 | 91 E28098 ; # left single quotation mark
18 | 92 E28099 ; # right single quotation mark
19 | 93 E2809C ; # left double quotation mark
20 | 94 E2809D ; # right double quotation mark
21 | 95 E280A2 ; # bullet
22 | 96 E28093 ; # en dash
23 | 97 E28094 ; # em dash
24 |
25 | 99 E284A2 ; # trade mark sign
26 |
27 | A0 C2A0 ; #
28 | A1 D18E ; # capital Byelorussian short U
29 | A2 D19E ; # small Byelorussian short u
30 |
31 | A4 C2A4 ; # currency sign
32 | A5 D290 ; # capital Ukrainian soft G
33 | A6 C2A6 ; # borken bar
34 | A7 C2A7 ; # section sign
35 | A8 D081 ; # capital YO
36 | A9 C2A9 ; # (C)
37 | AA D084 ; # capital Ukrainian YE
38 | AB C2AB ; # left-pointing double angle quotation mark
39 | AC C2AC ; # not sign
40 | AD C2AD ; # soft hypen
41 | AE C2AE ; # (R)
42 | AF D087 ; # capital Ukrainian YI
43 |
44 | B0 C2B0 ; # °
45 | B1 C2B1 ; # plus-minus sign
46 | B2 D086 ; # capital Ukrainian I
47 | B3 D196 ; # small Ukrainian i
48 | B4 D291 ; # small Ukrainian soft g
49 | B5 C2B5 ; # micro sign
50 | B6 C2B6 ; # pilcrow sign
51 | B7 C2B7 ; # ·
52 | B8 D191 ; # small yo
53 | B9 E28496 ; # numero sign
54 | BA D194 ; # small Ukrainian ye
55 | BB C2BB ; # right-pointing double angle quotation mark
56 |
57 | BF D197 ; # small Ukrainian yi
58 |
59 | C0 D090 ; # capital A
60 | C1 D091 ; # capital B
61 | C2 D092 ; # capital V
62 | C3 D093 ; # capital G
63 | C4 D094 ; # capital D
64 | C5 D095 ; # capital YE
65 | C6 D096 ; # capital ZH
66 | C7 D097 ; # capital Z
67 | C8 D098 ; # capital I
68 | C9 D099 ; # capital J
69 | CA D09A ; # capital K
70 | CB D09B ; # capital L
71 | CC D09C ; # capital M
72 | CD D09D ; # capital N
73 | CE D09E ; # capital O
74 | CF D09F ; # capital P
75 |
76 | D0 D0A0 ; # capital R
77 | D1 D0A1 ; # capital S
78 | D2 D0A2 ; # capital T
79 | D3 D0A3 ; # capital U
80 | D4 D0A4 ; # capital F
81 | D5 D0A5 ; # capital KH
82 | D6 D0A6 ; # capital TS
83 | D7 D0A7 ; # capital CH
84 | D8 D0A8 ; # capital SH
85 | D9 D0A9 ; # capital SHCH
86 | DA D0AA ; # capital hard sign
87 | DB D0AB ; # capital Y
88 | DC D0AC ; # capital soft sign
89 | DD D0AD ; # capital E
90 | DE D0AE ; # capital YU
91 | DF D0AF ; # capital YA
92 |
93 | E0 D0B0 ; # small a
94 | E1 D0B1 ; # small b
95 | E2 D0B2 ; # small v
96 | E3 D0B3 ; # small g
97 | E4 D0B4 ; # small d
98 | E5 D0B5 ; # small ye
99 | E6 D0B6 ; # small zh
100 | E7 D0B7 ; # small z
101 | E8 D0B8 ; # small i
102 | E9 D0B9 ; # small j
103 | EA D0BA ; # small k
104 | EB D0BB ; # small l
105 | EC D0BC ; # small m
106 | ED D0BD ; # small n
107 | EE D0BE ; # small o
108 | EF D0BF ; # small p
109 |
110 | F0 D180 ; # small r
111 | F1 D181 ; # small s
112 | F2 D182 ; # small t
113 | F3 D183 ; # small u
114 | F4 D184 ; # small f
115 | F5 D185 ; # small kh
116 | F6 D186 ; # small ts
117 | F7 D187 ; # small ch
118 | F8 D188 ; # small sh
119 | F9 D189 ; # small shch
120 | FA D18A ; # small hard sign
121 | FB D18B ; # small y
122 | FC D18C ; # small soft sign
123 | FD D18D ; # small e
124 | FE D18E ; # small yu
125 | FF D18F ; # small ya
126 | }
127 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/contrib/README:
--------------------------------------------------------------------------------
1 |
2 | geo2nginx.pl by Andrei Nigmatulin
3 |
4 | The perl script to convert CSV geoip database ( free download
5 | at http://www.maxmind.com/app/geoip_country ) to format, suitable
6 | for use by the ngx_http_geo_module.
7 |
8 |
9 | unicode2nginx by Maxim Dounin
10 |
11 | The perl script to convert unicode mappings ( available
12 | at http://www.unicode.org/Public/MAPPINGS/ ) to the nginx
13 | configuration file format.
14 | Two generated full maps for windows-1251 and koi8-r.
15 |
16 |
17 | vim by Evan Miller
18 |
19 | Syntax highlighting of nginx configuration for vim, to be
20 | placed into ~/.vim/.
21 |
22 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/contrib/geo2nginx.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl -w
2 |
3 | # (c) Andrei Nigmatulin, 2005
4 | #
5 | # this script provided "as is", without any warranties. use it at your own risk.
6 | #
7 | # special thanx to Andrew Sitnikov for perl port
8 | #
9 | # this script converts CSV geoip database (free download at http://www.maxmind.com/app/geoip_country)
10 | # to format, suitable for use with nginx_http_geo module (http://sysoev.ru/nginx)
11 | #
12 | # for example, line with ip range
13 | #
14 | # "62.16.68.0","62.16.127.255","1041253376","1041268735","RU","Russian Federation"
15 | #
16 | # will be converted to four subnetworks:
17 | #
18 | # 62.16.68.0/22 RU;
19 | # 62.16.72.0/21 RU;
20 | # 62.16.80.0/20 RU;
21 | # 62.16.96.0/19 RU;
22 |
23 |
24 | use warnings;
25 | use strict;
26 |
27 | while( ){
28 | if (/"[^"]+","[^"]+","([^"]+)","([^"]+)","([^"]+)"/){
29 | print_subnets($1, $2, $3);
30 | }
31 | }
32 |
33 | sub print_subnets {
34 | my ($a1, $a2, $c) = @_;
35 | my $l;
36 | while ($a1 <= $a2) {
37 | for ($l = 0; ($a1 & (1 << $l)) == 0 && ($a1 + ((1 << ($l + 1)) - 1)) <= $a2; $l++){};
38 | print long2ip($a1) . "/" . (32 - $l) . " " . $c . ";\n";
39 | $a1 += (1 << $l);
40 | }
41 | }
42 |
43 | sub long2ip {
44 | my $ip = shift;
45 |
46 | my $str = 0;
47 |
48 | $str = ($ip & 255);
49 |
50 | $ip >>= 8;
51 | $str = ($ip & 255).".$str";
52 |
53 | $ip >>= 8;
54 | $str = ($ip & 255).".$str";
55 |
56 | $ip >>= 8;
57 | $str = ($ip & 255).".$str";
58 | }
59 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/contrib/unicode2nginx/unicode-to-nginx.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl -w
2 |
3 | # Convert unicode mappings to nginx configuration file format.
4 |
5 | # You may find useful mappings in various places, including
6 | # unicode.org official site:
7 | #
8 | # http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT
9 | # http://www.unicode.org/Public/MAPPINGS/VENDORS/MISC/KOI8-R.TXT
10 |
11 | # Needs perl 5.6 or later.
12 |
13 | # Written by Maxim Dounin, mdounin@mdounin.ru
14 |
15 | ###############################################################################
16 |
17 | require 5.006;
18 |
19 | while (<>) {
20 | # Skip comments and empty lines
21 |
22 | next if /^#/;
23 | next if /^\s*$/;
24 | chomp;
25 |
26 | # Convert mappings
27 |
28 | if (/^\s*0x(..)\s*0x(....)\s*(#.*)/) {
29 | # Mapping "#"
30 | my $cs_code = $1;
31 | my $un_code = $2;
32 | my $un_name = $3;
33 |
34 | # Produce UTF-8 sequence from character code;
35 |
36 | my $un_utf8 = join('',
37 | map { sprintf("%02X", $_) }
38 | unpack("U0C*", pack("U", hex($un_code)))
39 | );
40 |
41 | print " $cs_code $un_utf8 ; $un_name\n";
42 |
43 | } else {
44 | warn "Unrecognized line: '$_'";
45 | }
46 | }
47 |
48 | ###############################################################################
49 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/contrib/vim/ftdetect/nginx.vim:
--------------------------------------------------------------------------------
1 | au BufRead,BufNewFile *.nginx set ft=nginx
2 | au BufRead,BufNewFile */etc/nginx/* set ft=nginx
3 | au BufRead,BufNewFile */usr/local/nginx/conf/* set ft=nginx
4 | au BufRead,BufNewFile nginx.conf set ft=nginx
5 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/contrib/vim/ftplugin/nginx.vim:
--------------------------------------------------------------------------------
1 | setlocal commentstring=#\ %s
2 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/contrib/vim/indent/nginx.vim:
--------------------------------------------------------------------------------
1 | if exists("b:did_indent")
2 | finish
3 | endif
4 | let b:did_indent = 1
5 |
6 | setlocal indentexpr=
7 |
8 | " cindent actually works for nginx' simple file structure
9 | setlocal cindent
10 | " Just make sure that the comments are not reset as defs would be.
11 | setlocal cinkeys-=0#
12 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/docs/LICENSE:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2002-2018 Igor Sysoev
3 | * Copyright (C) 2011-2018 Nginx, Inc.
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 | * SUCH DAMAGE.
26 | */
27 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/docs/PCRE.LICENCE:
--------------------------------------------------------------------------------
1 | PCRE LICENCE
2 | ------------
3 |
4 | PCRE is a library of functions to support regular expressions whose syntax
5 | and semantics are as close as possible to those of the Perl 5 language.
6 |
7 | Release 8 of PCRE is distributed under the terms of the "BSD" licence, as
8 | specified below. The documentation for PCRE, supplied in the "doc"
9 | directory, is distributed under the same terms as the software itself. The data
10 | in the testdata directory is not copyrighted and is in the public domain.
11 |
12 | The basic library functions are written in C and are freestanding. Also
13 | included in the distribution is a set of C++ wrapper functions, and a
14 | just-in-time compiler that can be used to optimize pattern matching. These
15 | are both optional features that can be omitted when the library is built.
16 |
17 |
18 | THE BASIC LIBRARY FUNCTIONS
19 | ---------------------------
20 |
21 | Written by: Philip Hazel
22 | Email local part: ph10
23 | Email domain: cam.ac.uk
24 |
25 | University of Cambridge Computing Service,
26 | Cambridge, England.
27 |
28 | Copyright (c) 1997-2018 University of Cambridge
29 | All rights reserved.
30 |
31 |
32 | PCRE JUST-IN-TIME COMPILATION SUPPORT
33 | -------------------------------------
34 |
35 | Written by: Zoltan Herczeg
36 | Email local part: hzmester
37 | Emain domain: freemail.hu
38 |
39 | Copyright(c) 2010-2018 Zoltan Herczeg
40 | All rights reserved.
41 |
42 |
43 | STACK-LESS JUST-IN-TIME COMPILER
44 | --------------------------------
45 |
46 | Written by: Zoltan Herczeg
47 | Email local part: hzmester
48 | Emain domain: freemail.hu
49 |
50 | Copyright(c) 2009-2018 Zoltan Herczeg
51 | All rights reserved.
52 |
53 |
54 | THE C++ WRAPPER FUNCTIONS
55 | -------------------------
56 |
57 | Contributed by: Google Inc.
58 |
59 | Copyright (c) 2007-2012, Google Inc.
60 | All rights reserved.
61 |
62 |
63 | THE "BSD" LICENCE
64 | -----------------
65 |
66 | Redistribution and use in source and binary forms, with or without
67 | modification, are permitted provided that the following conditions are met:
68 |
69 | * Redistributions of source code must retain the above copyright notice,
70 | this list of conditions and the following disclaimer.
71 |
72 | * Redistributions in binary form must reproduce the above copyright
73 | notice, this list of conditions and the following disclaimer in the
74 | documentation and/or other materials provided with the distribution.
75 |
76 | * Neither the name of the University of Cambridge nor the name of Google
77 | Inc. nor the names of their contributors may be used to endorse or
78 | promote products derived from this software without specific prior
79 | written permission.
80 |
81 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
82 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
84 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
85 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
86 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
87 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
88 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
89 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
90 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
91 | POSSIBILITY OF SUCH DAMAGE.
92 |
93 | End
94 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/docs/README:
--------------------------------------------------------------------------------
1 |
2 | Documentation is available at http://nginx.org
3 |
4 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/docs/zlib.LICENSE:
--------------------------------------------------------------------------------
1 | (C) 1995-2017 Jean-loup Gailly and Mark Adler
2 |
3 | This software is provided 'as-is', without any express or implied
4 | warranty. In no event will the authors be held liable for any damages
5 | arising from the use of this software.
6 |
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 |
11 | 1. The origin of this software must not be misrepresented; you must not
12 | claim that you wrote the original software. If you use this software
13 | in a product, an acknowledgment in the product documentation would be
14 | appreciated but is not required.
15 | 2. Altered source versions must be plainly marked as such, and must not be
16 | misrepresented as being the original software.
17 | 3. This notice may not be removed or altered from any source distribution.
18 |
19 | Jean-loup Gailly Mark Adler
20 | jloup@gzip.org madler@alumni.caltech.edu
21 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/html/50x.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Error
5 |
12 |
13 |
14 | An error occurred.
15 | Sorry, the page you are looking for is currently unavailable.
16 | Please try again later.
17 | If you are the system administrator of this resource then you should check
18 | the error log for details.
19 | Faithfully yours, nginx.
20 |
21 |
22 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Welcome to nginx!
5 |
12 |
13 |
14 | Welcome to nginx!
15 | If you see this page, the nginx web server is successfully installed and
16 | working. Further configuration is required.
17 |
18 | For online documentation and support please refer to
19 | nginx.org.
20 | Commercial support is available at
21 | nginx.com.
22 |
23 | Thank you for using nginx.
24 |
25 |
26 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/nginx-start.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | rem 1. 如果目录不存在 logs 目录,则创建
4 | if not exist %~dp0logs (
5 | echo %~dp0logs is not exists, create it.
6 | md %~dp0logs
7 | )
8 |
9 | rem 2. 如果目录不存在 temp 目录,则创建
10 | if not exist %~dp0temp (
11 | echo %~dp0temp is not exists, create it.
12 | md %~dp0temp
13 | )
14 |
15 | rem 3. 指定 conf/nginx.conf ,启动 nginx
16 | nginx.exe -t -c conf/nginx.conf
17 | start nginx
18 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/nginx-stop.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | nginx.exe -s stop
4 |
--------------------------------------------------------------------------------
/examples/nginx-1.14.0/nginx.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunwu/nginx-tutorial/452bc2d0d3b74d0d40cab700cab278a9b6bc5f2a/examples/nginx-1.14.0/nginx.exe
--------------------------------------------------------------------------------
/examples/nginx.conf:
--------------------------------------------------------------------------------
1 | # ----------------------------------------------------
2 | # 本文件是 nginx-1.14.0 的默认配置文件
3 | # 我对一些重要参数加了中文注释
4 | # ----------------------------------------------------
5 |
6 | # 运行用户
7 | #user nobody;
8 |
9 | # 启动进程,通常设置成和 CPU 的数量相等
10 | worker_processes 1;
11 |
12 | # 全局错误日志
13 | #error_log logs/error.log;
14 | #error_log logs/error.log notice;
15 | #error_log logs/error.log info;
16 |
17 | # PID 文件,记录当前启动的 nginx 的进程 ID
18 | #pid logs/nginx.pid;
19 |
20 | # 工作模式及连接数上限
21 | events {
22 | worker_connections 1024; #单个后台 worker process 进程的最大并发链接数
23 | }
24 |
25 | # 设定 http 服务器,利用它的反向代理功能提供负载均衡支持
26 | http {
27 | # 设定 mime 类型(邮件支持类型),类型由 mime.types 文件定义
28 | include mime.types;
29 | default_type application/octet-stream;
30 |
31 | # 设定日志格式
32 | #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
33 | # '$status $body_bytes_sent "$http_referer" '
34 | # '"$http_user_agent" "$http_x_forwarded_for"';
35 |
36 | #access_log logs/access.log main;
37 |
38 | # sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用,
39 | # 必须设为 on,如果用来进行下载等应用磁盘 IO 重负载应用,可设置为 off,以平衡磁盘与网络 I/O 处理速度,降低系统的 uptime。
40 | sendfile on;
41 | #tcp_nopush on;
42 |
43 | # 连接超时时间
44 | #keepalive_timeout 0;
45 | keepalive_timeout 65;
46 |
47 | # gzip 压缩开关
48 | #gzip on;
49 |
50 | # 设定实际的服务器列表
51 | server {
52 | # 监听 80 端口,80 端口是知名端口号,用于HTTP协议
53 | listen 80;
54 |
55 | # 定义使用的访问域名(host)
56 | server_name localhost;
57 |
58 | # 编码格式
59 | #charset utf-8;
60 |
61 | #access_log logs/host.access.log main;
62 |
63 | # 反向代理的路径(和 upstream 绑定),location 后面设置映射的路径
64 | location / {
65 | root html;
66 | index index.html index.htm;
67 | }
68 |
69 | #error_page 404 /404.html;
70 |
71 | # redirect server error pages to the static page /50x.html
72 | #
73 | error_page 500 502 503 504 /50x.html;
74 | location = /50x.html {
75 | root html;
76 | }
77 |
78 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80
79 | #
80 | #location ~ \.php$ {
81 | # proxy_pass http://127.0.0.1;
82 | #}
83 |
84 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
85 | #
86 | #location ~ \.php$ {
87 | # root html;
88 | # fastcgi_pass 127.0.0.1:9000;
89 | # fastcgi_index index.php;
90 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
91 | # include fastcgi_params;
92 | #}
93 |
94 | # deny access to .htaccess files, if Apache's document root
95 | # concurs with nginx's one
96 | #
97 | #location ~ /\.ht {
98 | # deny all;
99 | #}
100 | }
101 |
102 |
103 | # another virtual host using mix of IP-, name-, and port-based configuration
104 | #
105 | #server {
106 | # listen 8000;
107 | # listen somename:8080;
108 | # server_name somename alias another.alias;
109 |
110 | # location / {
111 | # root html;
112 | # index index.html index.htm;
113 | # }
114 | #}
115 |
116 |
117 | # HTTPS server
118 | #
119 | #server {
120 | # listen 443 ssl;
121 | # server_name localhost;
122 |
123 | # ssl_certificate cert.pem;
124 | # ssl_certificate_key cert.key;
125 |
126 | # ssl_session_cache shared:SSL:1m;
127 | # ssl_session_timeout 5m;
128 |
129 | # ssl_ciphers HIGH:!aNULL:!MD5;
130 | # ssl_prefer_server_ciphers on;
131 |
132 | # location / {
133 | # root html;
134 | # index index.html index.htm;
135 | # }
136 | #}
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/examples/reactadmin/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/examples/reactadmin/README.md:
--------------------------------------------------------------------------------
1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
2 |
3 | ## Available Scripts
4 |
5 | In the project directory, you can run:
6 |
7 | ### `npm start`
8 |
9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
11 |
12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console.
14 |
15 | ### `npm test`
16 |
17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
19 |
20 | ### `npm run build`
21 |
22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance.
24 |
25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed!
27 |
28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
29 |
30 | ### `npm run eject`
31 |
32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
33 |
34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
35 |
36 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
37 |
38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
39 |
40 | ## Learn More
41 |
42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
43 |
44 | To learn React, check out the [React documentation](https://reactjs.org/).
45 |
46 | ### Code Splitting
47 |
48 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
49 |
50 | ### Analyzing the Bundle Size
51 |
52 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
53 |
54 | ### Making a Progressive Web App
55 |
56 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
57 |
58 | ### Advanced Configuration
59 |
60 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
61 |
62 | ### Deployment
63 |
64 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
65 |
66 | ### `npm run build` fails to minify
67 |
68 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
69 |
--------------------------------------------------------------------------------
/examples/reactadmin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-admin",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.7.0",
7 | "react-dom": "^16.7.0",
8 | "react-scripts": "2.1.3"
9 | },
10 | "scripts": {
11 | "start": "react-scripts start",
12 | "build": "react-scripts build",
13 | "test": "react-scripts test",
14 | "eject": "react-scripts eject"
15 | },
16 | "eslintConfig": {
17 | "extends": "react-app"
18 | },
19 | "browserslist": [
20 | ">0.2%",
21 | "not dead",
22 | "not ie <= 11",
23 | "not op_mini all"
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/examples/reactadmin/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunwu/nginx-tutorial/452bc2d0d3b74d0d40cab700cab278a9b6bc5f2a/examples/reactadmin/public/favicon.ico
--------------------------------------------------------------------------------
/examples/reactadmin/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
15 |
16 |
25 | React App
26 |
27 |
28 |
29 |
30 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/examples/reactadmin/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/examples/reactadmin/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | animation: App-logo-spin infinite 20s linear;
7 | height: 40vmin;
8 | }
9 |
10 | .App-header {
11 | background-color: #282C34;
12 | min-height: 100vh;
13 | display: flex;
14 | flex-direction: column;
15 | align-items: center;
16 | justify-content: center;
17 | font-size: calc(10px + 2vmin);
18 | color: white;
19 | }
20 |
21 | .App-link {
22 | color: #61DAFB;
23 | }
24 |
25 | @keyframes App-logo-spin {
26 | from {
27 | transform: rotate(0deg);
28 | }
29 | to {
30 | transform: rotate(360deg);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/examples/reactadmin/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import logo from './logo.svg'
3 | import './App.css'
4 |
5 | class App extends Component {
6 | render() {
7 | return (
8 | < div
9 | className = 'App' >
10 | < header
11 | className = 'App-header' >
12 | < img
13 | src = { logo }
14 | className = 'App-logo'
15 | alt = 'logo' / >
16 | < p >
17 | Edit < code > src / App.js < /code> and save to reload.
18 | < /p>
19 | < a
20 | className = 'App-link'
21 | href = 'https://reactjs.org'
22 | target = '_blank'
23 | rel = 'noopener noreferrer'
24 | >
25 | Learn
26 | React
27 | < /a>
28 | < /header>
29 | < /div>
30 | )
31 |
32 | }
33 | }
34 |
35 | export default App
36 |
--------------------------------------------------------------------------------
/examples/reactadmin/src/App.test.js:
--------------------------------------------------------------------------------
1 | import ReactDOM from 'react-dom'
2 | import App from './App'
3 |
4 | it('renders without crashing', () => {
5 | const div = document.createElement('div')
6 | ReactDOM.render( < App / >, div
7 | )
8 |
9 | ReactDOM.unmountComponentAtNode(div)
10 | })
11 |
--------------------------------------------------------------------------------
/examples/reactadmin/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
5 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
6 | sans-serif;
7 | -webkit-font-smoothing: antialiased;
8 | -moz-osx-font-smoothing: grayscale;
9 | }
10 |
11 | code {
12 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
13 | monospace;
14 | }
15 |
--------------------------------------------------------------------------------
/examples/reactadmin/src/index.js:
--------------------------------------------------------------------------------
1 | import ReactDOM from 'react-dom'
2 | import './index.css'
3 | import App from './App'
4 | import * as serviceWorker from './serviceWorker'
5 |
6 | ReactDOM.render( < App / >, document.getElementById('root')
7 | )
8 |
9 |
10 | // If you want your app to work offline and load faster, you can change
11 | // unregister() to register() below. Note this comes with some pitfalls.
12 | // Learn more about service workers: http://bit.ly/CRA-PWA
13 | serviceWorker.unregister()
14 |
--------------------------------------------------------------------------------
/examples/reactadmin/src/logo.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/examples/reactadmin/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read http://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.1/8 is considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | )
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href)
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config)
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit http://bit.ly/CRA-PWA'
47 | )
48 | })
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config)
52 | }
53 | })
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing
63 | if (installingWorker == null) {
64 | return
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
75 | )
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration)
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.')
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration)
90 | }
91 | }
92 | }
93 | }
94 | }
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error)
98 | })
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl)
104 | .then(response => {
105 | // Ensure service worker exists, and that we really are getting a JS file.
106 | const contentType = response.headers.get('content-type')
107 | if (
108 | response.status === 404 ||
109 | (contentType != null && contentType.indexOf('javascript') === -1)
110 | ) {
111 | // No service worker found. Probably a different app. Reload the page.
112 | navigator.serviceWorker.ready.then(registration => {
113 | registration.unregister().then(() => {
114 | window.location.reload()
115 | })
116 | })
117 | } else {
118 | // Service worker found. Proceed as normal.
119 | registerValidSW(swUrl, config)
120 | }
121 | })
122 | .catch(() => {
123 | console.log(
124 | 'No internet connection found. App is running in offline mode.'
125 | )
126 | })
127 | }
128 |
129 | export function unregister() {
130 | if ('serviceWorker' in navigator) {
131 | navigator.serviceWorker.ready.then(registration => {
132 | registration.unregister()
133 | })
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/examples/reactapp/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "env",
5 | {
6 | "modules": false
7 | }
8 | ],
9 | "react",
10 | "stage-0"
11 | ],
12 | "plugins": [
13 | "react-hot-loader/babel",
14 | "syntax-dynamic-import",
15 | "transform-runtime",
16 | [
17 | "import",
18 | [
19 | {
20 | "libraryName": "antd",
21 | "style": "css"
22 | }
23 | ]
24 | ]
25 | ],
26 | "env": {
27 | "test": {
28 | "presets": [
29 | "env",
30 | "react",
31 | "stage-0"
32 | ]
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/examples/reactapp/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 | # 所有文件换行以 Unix like 风格(LF),win 格式特定的除外(bat)
5 | # 缩进 java 4 个空格,其他所有文件 2 个空格
6 |
7 | root = true
8 |
9 | [*]
10 | # Unix-style newlines with a newline ending every file
11 | end_of_line = lf
12 |
13 | # Change these settings to your own preference
14 | indent_style = space
15 | indent_size = 2
16 |
17 | # We recommend you to keep these unchanged
18 | charset = utf-8
19 | trim_trailing_whitespace = true
20 | insert_final_newline = true
21 |
22 | [*.bat]
23 | end_of_line = crlf
24 |
25 | [*.java]
26 | indent_style = space
27 | indent_size = 4
28 |
29 | [*.md]
30 | trim_trailing_whitespace = false
31 |
--------------------------------------------------------------------------------
/examples/reactapp/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "eslint-config-airbnb"
4 | ],
5 | "parser": "babel-eslint",
6 | "globals": {
7 | "Action": false,
8 | "__DEV__": false,
9 | "__DEV__LOG__": false,
10 | "__DEV__LOG__DIFF__": true,
11 | "__DEV__IMMUTABLE_CHECK__": false,
12 | "__PROD__": false,
13 | "__DEBUG__": false,
14 | "__DEBUG_NEW_WINDOW__": false,
15 | "__BASENAME__": false,
16 | "Image": {},
17 | "FileReader": {},
18 | "Request": {},
19 | "fetch": {},
20 | "XMLHttpRequest": {}
21 | },
22 | "rules": {
23 | "arrow-body-style": [
24 | "off"
25 | ],
26 | "global-require": [
27 | "warn"
28 | ],
29 | "no-underscore-dangle": [
30 | "off"
31 | ],
32 | "no-case-declarations": [
33 | "warn"
34 | ],
35 | "max-len": [
36 | "warn",
37 | 120,
38 | {
39 | "ignoreUrls": true
40 | }
41 | ],
42 | "no-unused-vars": [
43 | "warn"
44 | ],
45 | "no-nested-ternary": [
46 | "warn"
47 | ],
48 | "no-class-assign": [
49 | "off"
50 | ],
51 | "no-use-before-define": [
52 | "error",
53 | {
54 | "functions": false,
55 | "classes": true
56 | }
57 | ],
58 | "new-cap": [
59 | "error",
60 | {
61 | "capIsNewExceptions": [
62 | "List",
63 | "Map",
64 | "OrderedMap",
65 | "Set",
66 | "OrderedSet",
67 | "Stack",
68 | "Range",
69 | "Repeat",
70 | "Record",
71 | "Seq"
72 | ]
73 | }
74 | ],
75 | "linebreak-style": [
76 | "off"
77 | ],
78 | "import/prefer-default-export": [
79 | "off"
80 | ],
81 | "react/prefer-stateless-function": [
82 | "off"
83 | ],
84 | "react/jsx-curly-spacing": [
85 | "off"
86 | ],
87 | "react/forbid-prop-types": [
88 | "off"
89 | ],
90 | "react/no-unused-prop-types": [
91 | "warn"
92 | ]
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/examples/reactapp/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 |
3 | # plan text
4 | *.txt text
5 | *.java text
6 | *.scala text
7 | *.groovy text
8 | *.gradle text
9 | *.xml text
10 | *.xsd text
11 | *.tld text
12 | *.yaml text
13 | *.yml text
14 | *.wsdd text
15 | *.wsdl text
16 | *.jsp text
17 | *.jspf text
18 | *.js text
19 | *.jsx text
20 | *.json text
21 | *.css text
22 | *.less text
23 | *.sql text
24 | *.properties text
25 |
26 | # unix style
27 | *.sh text eol=lf
28 |
29 | # win style
30 | *.bat text eol=crlf
31 |
32 | # don't handle
33 | *.der -text
34 | *.jks -text
35 | *.pfx -text
36 | *.map -text
37 | *.patch -text
38 | *.dat -text
39 | *.data -text
40 | *.db -text
41 |
42 | # binary
43 | *.jar binary
44 | *.war binary
45 | *.zip binary
46 | *.tar binary
47 | *.tar.gz binary
48 | *.gz binary
49 | *.apk binary
50 | *.bin binary
51 | *.exe binary
52 |
53 | # 图片
54 | *.png binary
55 | *.jpg binary
56 | *.ico binary
57 | *.gif binary
58 |
59 | # 音视频
60 | *.mp3 binary
61 | *.swf binary
62 |
63 | # other doc
64 | *.pdf binary
65 | *.doc binary
66 | *.docx binary
67 | *.xls binary
68 | *.xlsx binary
69 |
--------------------------------------------------------------------------------
/examples/reactapp/.gitignore:
--------------------------------------------------------------------------------
1 | # project
2 | node_modules
3 |
4 | # build
5 | dist/
6 | coverage
7 |
8 | # IDE files
9 | .idea/
10 | *.iml
11 | .ipr
12 | .iws
13 |
14 | # temp and sys
15 | *~
16 | ~*
17 | *.diff
18 | *.patch
19 | *.bak
20 | .DS_Store
21 | Thumbs.db
22 | *.log
23 |
24 | # other
25 | .project
26 | .*proj
27 | .svn/
28 | *.swp
29 | *.swo
30 | *.pyc
31 | *.pyo
32 |
--------------------------------------------------------------------------------
/examples/reactapp/config/app.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file app 的全局配置
3 | * @author Zhang Peng
4 | */
5 |
6 | module.exports = {
7 |
8 | /**
9 | * 打印日志开关
10 | */
11 | log: true,
12 |
13 | http: {
14 |
15 | /**
16 | * 请求超时时间
17 | */
18 | timeout: 5000,
19 |
20 | /**
21 | * 服务器的host
22 | */
23 | baseURL: '/api'
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/examples/reactapp/config/webpack.config.base.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Zhang Peng on 2017/6/14.
3 | */
4 | const path = require('path')
5 | const webpack = require('webpack')
6 | const HtmlWebpackPlugin = require('html-webpack-plugin')
7 |
8 |
9 | module.exports = {
10 |
11 | // 这里应用程序开始执行
12 | // webpack 开始打包
13 | // 本例中 entry 为多入口
14 | entry: {
15 | // 第三方库
16 | vendor: ['babel-polyfill']
17 | },
18 |
19 | // webpack 如何输出结果的相关选项
20 | output: {
21 | // 所有输出文件的目标路径
22 | // 必须是绝对路径(使用 Node.js 的 path 模块)
23 | path: path.resolve(__dirname, '../dist'),
24 |
25 | // 「入口分块(entry chunk)」的文件名模板(出口分块?)
26 | // filename: "bundle.min.js",
27 | // filename: "[name].js", // 用于多个入口点(entry point)(出口点?)
28 | // filename: "[chunkhash].js", // 用于长效缓存
29 | filename: '[name].[hash:8].js',
30 |
31 | // 「source map 位置」的文件名模板
32 | sourceMapFilename: '[name].map'
33 | },
34 |
35 | // 关于模块配置
36 | module: {
37 |
38 | // 模块规则(配置 loader、解析器等选项)
39 | rules: [
40 | // 这里是匹配条件,每个选项都接收一个正则表达式或字符串
41 | // test 和 include 具有相同的作用,都是必须匹配选项
42 | // exclude 是必不匹配选项(优先于 test 和 include)
43 | // 最佳实践:
44 | // - 只在 test 和 文件名匹配 中使用正则表达式
45 | // - 在 include 和 exclude 中使用绝对路径数组
46 | // - 尽量避免 exclude,更倾向于使用 include
47 | {
48 | // 语义解释器,将 js/jsx 文件中的 es2015/react 语法自动转为浏览器可识别的 Javascript 语法
49 | test: /\.jsx?$/,
50 | include: path.resolve(__dirname, '../src'),
51 | exclude: /node_modules/,
52 |
53 | // 应该应用的 loader,它相对上下文解析
54 | // 为了更清晰,`-loader` 后缀在 webpack 2 中不再是可选的
55 | // 查看 webpack 1 升级指南。
56 | loader: 'babel-loader'
57 | },
58 |
59 | {
60 | // css 加载
61 | test: /\.css$/,
62 | use: ['style-loader', 'css-loader']
63 | },
64 |
65 | {
66 | // less 加载
67 | test: /\.less$/,
68 | use: ['style-loader', 'css-loader', 'less-loader']
69 | },
70 |
71 | {
72 | // 字体加载
73 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
74 | loader: 'url-loader',
75 | options: {
76 | limit: 10000,
77 | name: 'static/fonts/[name].[hash:8].[ext]'
78 | }
79 | }
80 | ]
81 | },
82 |
83 | // 解析模块请求的选项
84 | // (不适用于对 loader 解析)
85 | resolve: {
86 | // 使用的扩展名
87 | extensions: ['.js', '.jsx', '.json'],
88 |
89 | alias: {
90 | '@': path.resolve(__dirname, '../src')
91 | }
92 | },
93 |
94 | // 附加插件列表
95 | plugins: [
96 |
97 | /**
98 | * https://doc.webpack-china.org/plugins/html-webpack-plugin/
99 | * 用于简化 HTML 文件(index.html)的创建,提供访问 bundle 的服务
100 | */
101 | new HtmlWebpackPlugin({
102 | title: 'reactapp',
103 | template: 'public/index.html',
104 | favicon: 'public/favicon.ico'
105 | }),
106 |
107 |
108 | // 将多个入口起点之间共享的公共模块,生成为一些 chunk,并且分离到单独的 bundle 中
109 | new webpack.optimize.CommonsChunkPlugin({
110 | name: 'vendor' // 指定公共 bundle 的名字
111 | })
112 | ]
113 | }
114 |
--------------------------------------------------------------------------------
/examples/reactapp/config/webpack.config.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Zhang Peng on 2017/6/14.
3 | */
4 | const path = require('path')
5 | const webpack = require('webpack')
6 | const webpackMerge = require('webpack-merge')
7 | const OpenBrowserPlugin = require('open-browser-webpack-plugin')
8 | const baseWebpackConfig = require('./webpack.config.base')
9 |
10 | module.exports = webpackMerge(baseWebpackConfig, {
11 | // 这里应用程序开始执行
12 | // webpack 开始打包
13 | // 本例中 entry 为多入口
14 | entry: {
15 | main: [
16 | // App 入口
17 | path.resolve(__dirname, '../src/index'),
18 |
19 | // 开启 React 代码的模块热替换(HMR)
20 | 'react-hot-loader/patch',
21 |
22 | // 为 webpack-dev-server 的环境打包代码
23 | // 然后连接到指定服务器域名与端口
24 | 'webpack-dev-server/client?http://localhost:9000',
25 |
26 | // 为热替换(HMR)打包好代码
27 | // only- 意味着只有成功更新运行代码才会执行热替换(HMR)
28 | 'webpack/hot/only-dev-server'
29 | ]
30 | },
31 |
32 | output: {
33 | // 对于热替换(HMR)是必须的,让 webpack 知道在哪里载入热更新的模块(chunk)
34 | publicPath: '/'
35 | },
36 |
37 | // 关于模块配置
38 | module: {
39 |
40 | // 模块规则(配置 loader、解析器等选项)
41 | rules: [
42 |
43 | {
44 | // 图片加载 + 图片压缩
45 | test: /\.(png|svg|jpg|gif|ico)$/,
46 | loader: 'url-loader',
47 | options: {
48 | limit: 10000,
49 | name: 'static/images/[name].[hash:8].[ext]'
50 | }
51 | }
52 | ]
53 | },
54 |
55 | // 附加插件列表
56 | plugins: [
57 |
58 | // 定义环境变量
59 | new webpack.DefinePlugin({
60 | 'process.env.NODE_ENV': JSON.stringify('development')
61 | }),
62 |
63 | // 开启全局的模块热替换(HMR)
64 | new webpack.HotModuleReplacementPlugin(),
65 |
66 | // 当模块热替换(HMR)时在浏览器控制台输出对用户更友好的模块名字信息
67 | new webpack.NamedModulesPlugin(),
68 |
69 | // 自动打开浏览器
70 | new OpenBrowserPlugin({
71 | url: 'http://localhost:9000'
72 | })
73 | ],
74 |
75 | // 通过在浏览器调试工具(browser devtools)中添加元信息(meta info)增强调试
76 | // devtool: "source-map", // 牺牲了构建速度的 `source-map' 是最详细的
77 | // devtool: "inline-source-map", // 嵌入到源文件中
78 | // devtool: "eval-source-map", // 将 SourceMap 嵌入到每个模块中
79 | // devtool: "hidden-source-map", // SourceMap 不在源文件中引用
80 | // devtool: "cheap-source-map", // 没有模块映射(module mappings)的 SourceMap 低级变体(cheap-variant)
81 | devtool: 'eval-source-map', // 有模块映射(module mappings)的 SourceMap 低级变体
82 | // devtool: "eval", // 没有模块映射,而是命名模块。以牺牲细节达到最快。
83 |
84 | devServer: {
85 | contentBase: [path.join(__dirname, '../dist')],
86 | compress: true,
87 | port: 9000, // 启动端口号
88 | hot: true, // 启用 webpack 的模块热替换特性
89 | inline: true,
90 | publicPath: '/', // 和上文 output 的“publicPath”值保持一致
91 | historyApiFallback: true
92 | }
93 | })
94 |
--------------------------------------------------------------------------------
/examples/reactapp/config/webpack.config.prod.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Zhang Peng on 2017/6/14.
3 | */
4 | const path = require('path')
5 | const webpack = require('webpack')
6 | const webpackMerge = require('webpack-merge')
7 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
8 | const baseWebpackConfig = require('./webpack.config.base')
9 |
10 | module.exports = webpackMerge(baseWebpackConfig, {
11 | // 这里应用程序开始执行
12 | // webpack 开始打包
13 | // 本例中 entry 为多入口
14 | entry: {
15 | main: [
16 | // App 入口
17 | path.resolve(__dirname, '../src/index')
18 | ]
19 | },
20 |
21 | // 关于模块配置
22 | module: {
23 |
24 | // 模块规则(配置 loader、解析器等选项)
25 | rules: [
26 | {
27 | // 图片加载 + 图片压缩
28 | test: /\.(png|svg|jpg|gif|ico)$/,
29 | loaders: [
30 | {
31 | loader: 'url-loader',
32 | options: {
33 | limit: 10000,
34 | name: 'static/images/[name].[hash:8].[ext]'
35 | }
36 | },
37 |
38 | {
39 | loader: 'image-webpack-loader',
40 | query: {
41 | progressive: true,
42 | pngquant: {
43 | quality: '65-90',
44 | speed: 4
45 | }
46 | }
47 | }
48 |
49 | ]
50 | }
51 | ]
52 | },
53 |
54 | // 附加插件列表
55 | plugins: [
56 |
57 | // 定义环境变量
58 | new webpack.DefinePlugin({
59 | 'process.env.NODE_ENV': JSON.stringify('production')
60 | }),
61 |
62 | // 加载选项插件
63 | new webpack.LoaderOptionsPlugin({
64 | minimize: true,
65 | debug: false
66 | }),
67 |
68 | // 压缩 js 插件
69 | new webpack.optimize.UglifyJsPlugin({
70 | output: {
71 | comments: false // remove all comments
72 | },
73 | compress: {
74 | warnings: false
75 | }
76 | }),
77 |
78 | // 将样式文件独立打包
79 | new ExtractTextPlugin('styles.css')
80 | ]
81 | })
82 |
--------------------------------------------------------------------------------
/examples/reactapp/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reactapp",
3 | "version": "0.0.1",
4 | "description": "reactapp",
5 | "main": "index.js",
6 | "scripts": {
7 | "clean": "rimraf ./dist",
8 | "lint": "eslint --ext .js,.jsx src",
9 | "dev": "webpack-dev-server --config config/webpack.config.dev.js --color",
10 | "prod": "npm run clean && webpack --config config/webpack.config.prod.js --color",
11 | "start": "if-env NODE_ENV=production && npm run prod || npm run dev"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/dunwu/react-admin.git"
16 | },
17 | "author": "Zhang Peng",
18 | "license": "MIT",
19 | "engines": {
20 | "node": ">= 4.0.0",
21 | "npm": ">= 3.0.0"
22 | },
23 | "dependencies": {
24 | "antd": "^2.12.1",
25 | "axios": "^0.19.0",
26 | "isomorphic-fetch": "^2.2.1",
27 | "less": "^2.7.1",
28 | "lodash": "^4.16.4",
29 | "moment": "^2.18.1",
30 | "prop-types": "^15.5.10",
31 | "react": "^15.6.1",
32 | "react-dom": "^15.6.1",
33 | "react-redux": "^5.0.0",
34 | "react-router": "^4.1.0",
35 | "react-router-dom": "^4.1.1",
36 | "redux": "^3.7.2",
37 | "redux-thunk": "^2.2.0",
38 | "reqwest": "^2.0.5"
39 | },
40 | "devDependencies": {
41 | "axios-mock-adapter": "^1.7.1",
42 | "babel-core": "^6.25.0",
43 | "babel-loader": "^7.1.0",
44 | "babel-plugin-import": "^1.2.1",
45 | "babel-plugin-syntax-dynamic-import": "^6.18.0",
46 | "babel-plugin-transform-runtime": "^6.15.0",
47 | "babel-polyfill": "^6.23.0",
48 | "babel-preset-env": "^1.5.2",
49 | "babel-preset-react": "^6.24.1",
50 | "babel-preset-stage-0": "^6.24.1",
51 | "css-loader": "^0.25.0",
52 | "eslint": "3.7.1",
53 | "eslint-config-airbnb": "12.0.0",
54 | "eslint-plugin-import": "1.16.0",
55 | "eslint-plugin-jsx-a11y": "2.2.3",
56 | "eslint-plugin-react": "6.3.0",
57 | "extract-text-webpack-plugin": "^2.1.2",
58 | "file-loader": "^0.9.0",
59 | "html-webpack-plugin": "^2.24.1",
60 | "if-env": "^1.0.0",
61 | "image-webpack-loader": "^3.3.1",
62 | "less-loader": "^2.2.3",
63 | "open-browser-webpack-plugin": "^0.0.5",
64 | "react-hot-loader": "^3.0.0-beta.7",
65 | "redux-devtools": "^3.4.0",
66 | "redux-devtools-dock-monitor": "^1.0.1",
67 | "redux-devtools-log-monitor": "^1.0.2",
68 | "redux-logger": "^3.0.6",
69 | "redux-mock-store": "^1.2.3",
70 | "rimraf": "^2.6.1",
71 | "style-loader": "^0.18.2",
72 | "url-loader": "^0.5.7",
73 | "webpack": "^3.5.5",
74 | "webpack-dev-server": "^2.7.1",
75 | "webpack-merge": "^4.1.0"
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/examples/reactapp/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunwu/nginx-tutorial/452bc2d0d3b74d0d40cab700cab278a9b6bc5f2a/examples/reactapp/public/favicon.ico
--------------------------------------------------------------------------------
/examples/reactapp/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <%= htmlWebpackPlugin.options.title %>
5 |
6 |
7 |
8 |
9 |
10 |
11 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/examples/reactapp/scripts/build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ln -s /app/ck-puck-front/node_modules/ node_modules
4 | nvm use 8.1.0
5 | npm set registry http://192.168.51.44
6 | npm install
7 | npm run build
8 | rm -rf /app/ck-puck-front/dist
9 | mkdir -p /app/ck-puck-front/dist
10 | cp -Rf ./dist /app/ck-puck-front/
11 |
--------------------------------------------------------------------------------
/examples/reactapp/src/common/apiutils/ajaxCommon.js:
--------------------------------------------------------------------------------
1 | import { Modal } from 'antd'
2 | import _ from 'lodash'
3 |
4 | import { COMMON_REQUEST_ERROR } from '../../redux/constants/commonActionTypes'
5 |
6 | export const REQ_BASE_URL = '/api'
7 |
8 | export const METHODS = {
9 | GET: 'GET',
10 | HEAD: 'HEAD',
11 | POST: 'POST',
12 | PUT: 'PUT',
13 | DEL: 'DEL',
14 | OPTIONS: 'OPTIONS',
15 | PATCH: 'PATCH'
16 | }
17 |
18 | export const REQ_TYPE = {
19 | HTML: 'html',
20 | JSON: 'json',
21 | JSONP: 'jsonp'
22 | }
23 |
24 | export const CACHE_TYPE = {
25 | DEFAULT: 'default',
26 | NO_STORE: 'no-store',
27 | RELOAD: 'reload',
28 | NO_CACHE: 'no-cache',
29 | FORCE_CACHE: 'force-cache'
30 | }
31 |
32 | export const ERROR_HANDLER_TYPE = {
33 | NO: 'NO', // ['NO' | undefined | false ] 不处理
34 | SYSTEM: 'SYSTEM', // ['SYSTEM'] 只处理系统预料外的返回(not json)
35 | SYSTEM_AND_AUTH: 'SYSTEM_AND_AUTH', // [true, 'SYSTEM_AND_AUTH'] 处理上一步,与 认证失败 (比较常用,所以单独列出,用true)
36 | ALL: 'ALL' // [no errorHandler | 'ALL'] 所有
37 | }
38 |
39 | export const defaultOptions = {
40 | url: null,
41 | method: METHODS.GET,
42 | headers: {},
43 | data: null,
44 | type: null,
45 | contentType: null,
46 | crossOrigin: null,
47 | onSuccess: () => {
48 | },
49 | onError: () => {
50 | },
51 | cache: CACHE_TYPE.NO_CACHE
52 | }
53 |
54 | // 在 defaultOptions 基础上多出来的, request plan text,response json
55 | export const defaultJsonOptions = _.merge({}, defaultOptions, {
56 | headers: {
57 | Accept: 'application/json, text/plain, */*',
58 | 'Cache-Control': 'no-cache'
59 | },
60 | type: REQ_TYPE.JSON
61 | })
62 |
63 | // 在 defaultJsonOptions 基础上多出来的, request response 皆是 json
64 | export const defaultBiJsonOptions = _.merge({}, defaultJsonOptions, {
65 | headers: {
66 | 'Content-Type': 'application/json;charset=UTF-8'
67 | },
68 | reqType: REQ_TYPE.JSON
69 | })
70 |
71 | // 获取真正请求的 URL
72 | export function getRealUrl(url) {
73 | if (!!url && !url.startsWith('http')) {
74 | return REQ_BASE_URL + url
75 | }
76 | return url
77 | }
78 |
79 | /**
80 | * 展示认证错误
81 | * @private
82 | */
83 | function _showAuthError() {
84 | Modal.error({
85 | title: '认证失败',
86 | // eslint-disable-next-line react/jsx-filename-extension
87 | content: ( < p > 您现在处于非认证状态!!!<
88 | br / >
89 | 如果想保留本页状态,请在 < a
90 | href = '/login'
91 | target = 'blank' > 新页面登陆 < /a> 。
92 | { /* 否则在 当前页登陆 。 */ }
93 | < /p>),
94 | })
95 |
96 | }
97 |
98 | /**
99 | * 防抖展示认证错误(一段时间内仅一次)
100 | * @type {Function}
101 | */
102 | const showAuthError = _.debounce(_showAuthError, 500, {
103 | leading: true,
104 | trailing: false
105 | })
106 |
107 | /**
108 | * 展示服务端错误信息
109 | * @param e
110 | */
111 | function _showServerError(e) {
112 | Modal.error({
113 | title: '服务端错误!',
114 | content: `服务端错误。服务端可能未正确部署或由于其他原因响应失败!请保留现场并联系开发人员。错误信息: ${e}`
115 | })
116 | }
117 |
118 | /**
119 | * 防抖展示服务端错误(一段时间内仅一次)
120 | * @type {Function}
121 | */
122 | const showServerError = _.debounce(_showServerError, 500, {
123 | leading: true,
124 | trailing: false
125 | })
126 |
127 | /**
128 | * 包装错误处理。所有服务端应用(非业务)非 ret 预计错误与认证错误统一处理。
129 | * 其他根据情况,如果未传入错误处理函数或错误处理函数返回 true,则接管处理。
130 | * 用于处理 api 请求未传入错误处理函数的情况。
131 | * 如果传入 dispatch,则会 dispatch 公共 action。
132 | * 如果无 dispatch,则 console.log error
133 | * @param errorHandler
134 | * @param dispatch
135 | * @returns {function()}
136 | */
137 | export function wrapErrorHandler(errorHandler, dispatch) {
138 | return (e) => {
139 | let handlerLevel = 1000 // 默认都处理
140 | // 先看是否传入 errorHandler,如果传入,则执行用户 errorHandler,并根据处理结果设置新的 handlerLevel
141 | if (_.isFunction(errorHandler)) {
142 | handlerLevel = _getErrorHandlerLevel(errorHandler(e))
143 | }
144 |
145 | if (handlerLevel > 0 && e instanceof XMLHttpRequest) {
146 | // 服务端应用(非业务)非 ret 预计错误处理,如 404,400,500,非返回 json 错误
147 | showServerError(e.responseText)
148 | } else if (handlerLevel > 10 && e.ret === -1) {
149 | // 认证失败,该登陆未登录
150 | showAuthError()
151 | } else if (handlerLevel > 100 && dispatch) {
152 | dispatch({ type: COMMON_REQUEST_ERROR, payload: e })
153 | } else if (handlerLevel > 100) {
154 | const msg = e.ret ? `[code]${e.ret}, [msg]${e.msg}` : JSON.stringify(e)
155 | // eslint-disable-next-line no-console
156 | console.error(`请求出错: ${msg}`)
157 | }
158 | }
159 | }
160 |
161 | function _getErrorHandlerLevel(type) {
162 | if (type === ERROR_HANDLER_TYPE.SYSTEM) {
163 | return 10
164 | } else if (type === ERROR_HANDLER_TYPE.SYSTEM_AND_AUTH || type === true) {
165 | return 100
166 | } else if (type === ERROR_HANDLER_TYPE.ALL) {
167 | return 1000
168 | }
169 | return 0
170 | }
171 |
--------------------------------------------------------------------------------
/examples/reactapp/src/common/apiutils/apiCreator.js:
--------------------------------------------------------------------------------
1 | const createApi = fetchFunc => options => (...args) => {
2 | let finalOpts
3 | const argsName = ['options', 'successCallBack', 'errorCallBack', 'dispatch']
4 | // options 可以是 url,或完整的 options 对象
5 | if (typeof options === 'string') {
6 | finalOpts = { url: options }
7 | } else {
8 | finalOpts = { ...options }
9 | }
10 |
11 | const temArgs = {}
12 | if (args) {
13 | // args 第一个参数,options 可以忽略
14 | let i = 0
15 | if (args[0] !== null && typeof args[0] === 'object') {
16 | i = 1
17 | finalOpts = Object.assign(finalOpts, args[0])
18 | }
19 |
20 | // eslint-disable-next-line no-plusplus
21 | for (let j = i; j < args.length; j++) {
22 | // eslint-disable-next-line no-mixed-operators
23 | temArgs[argsName[j - i + 1]] = args[j]
24 | }
25 | }
26 |
27 | if (temArgs.successCallBack) {
28 | finalOpts.onSuccess = temArgs.successCallBack
29 | }
30 |
31 | if (temArgs.errorCallBack) {
32 | finalOpts.onError = temArgs.errorCallBack
33 | }
34 | fetchFunc(finalOpts, temArgs.dispatch)
35 | }
36 |
37 | export default createApi
38 |
--------------------------------------------------------------------------------
/examples/reactapp/src/common/apiutils/errorUtils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 错误处理帮助类
3 | */
4 | import { Message } from 'antd'
5 | import _ from 'lodash'
6 |
7 | import { ERROR_HANDLER_TYPE } from './index'
8 |
9 | /**
10 | * 处理业务类型的错误(-3),通过 message 的方式展现
11 | * @param e
12 | * @param callBack
13 | * @return {boolean}
14 | */
15 | export function messageBizError(e, callBack) {
16 | let continueHandler = true
17 | if (e && e.ret === -3) {
18 | // 业务错误
19 | Message.error(e.msg, 4.5)
20 | continueHandler = ERROR_HANDLER_TYPE.NO
21 | }
22 | if (_.isFunction(callBack)) {
23 | callBack({ error: e })
24 | }
25 | return continueHandler
26 | }
27 |
--------------------------------------------------------------------------------
/examples/reactapp/src/common/apiutils/fetchAJAX.js:
--------------------------------------------------------------------------------
1 | import 'isomorphic-fetch'
2 | import { defaultJsonOptions, defaultOptions, getRealUrl, REQ_TYPE, wrapErrorHandler } from './ajaxCommon'
3 |
4 | function handleStatus(res) {
5 | if (res.ok) {
6 | return res
7 | }
8 | throw new Error({ result: res.status })
9 | }
10 |
11 | // json 有固定的格式,所以固定处理方法
12 | function handleJson(data) {
13 | // noinspection JSUnresolvedVariable
14 | if (data.ret === 0) {
15 | return data.data
16 | }
17 | throw new Error(data)
18 | }
19 |
20 | export function doFetch(options = {}, dispatch) {
21 | const opts = {
22 | ...defaultOptions,
23 | ...options,
24 | onError: wrapErrorHandler(options.onError, dispatch)
25 | }
26 |
27 | // 根据配置创建 Request 对象
28 | const req = new Request(getRealUrl(opts.url), {
29 | method: opts.method,
30 | headers: opts.headers,
31 | body: opts.data,
32 | cache: opts.cache,
33 | redirect: 'follow',
34 | mode: 'cors'
35 | })
36 |
37 | if (!__DEV__) {
38 | req.credentials = 'include'
39 | }
40 |
41 | // 请求
42 | // FIXME 应该根据 response 类型自动判断是否 Json 请求
43 | let tempRes = fetch(req).then(handleStatus)
44 | if (options.type === REQ_TYPE.JSON) {
45 | tempRes = tempRes.then(res => res.json()).then(handleJson)
46 | }
47 | tempRes.then(options.onSuccess).catch(options.onError)
48 | }
49 |
50 | export function doFetchJson(options = {}, dispatch) {
51 | const opts = { ...defaultJsonOptions, ...options }
52 | doFetch(opts, dispatch)
53 | }
54 |
--------------------------------------------------------------------------------
/examples/reactapp/src/common/apiutils/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * export 一个 API,底层的实现可能会改(如,切换为 reqwest/superagent/fetch)
3 | */
4 | import { CACHE_TYPE, ERROR_HANDLER_TYPE, METHODS, REQ_TYPE } from './ajaxCommon'
5 | import { doBiJsonFetch, doFetch, doFetchJson } from './reqwestAJAX'
6 | import createApi from './apiCreator'
7 |
8 | /**
9 | * 创建一个 API 函数,结果可以是任何形式。如果是响应是 JSON 会自动转换,类似于 #createFetchJson 结果。
10 | * 但是,请求头不指名 Json : Accept:text/javascript, text/html, application/xml, text/xml, *\/*
11 | */
12 | const createFetch = createApi(doFetch)
13 |
14 | /**
15 | * 创建一个 API 函数,明确指明函数用于获取 Json 格式数据。如果结果不符合格式会转到错误处理
16 | * 请求头:Accept:application/json, text/plain, *\/*
17 | */
18 | const createFetchJson = createApi(doFetchJson)
19 |
20 | // 创建一个 API 函数, 指明客户端、服务端 内容体(content body)都是 Json 格式。
21 | // 在 #createFetchJson 的基础上添加:Content-Type: application/json;charset=UTF-8,
22 | // 同时,如果请求 data 为 Object类型会通过 JSON.stringify 转换
23 | const createBiJsonFetch = createApi(doBiJsonFetch)
24 |
25 | /**
26 | * 将 api 转换为返回 Promise 方式, 不处理 error。 如果处理 error, 请君自new
27 | * @private
28 | */
29 | const createPromiseAPI = api => (data) => {
30 | return new Promise((resolve) => {
31 | api({ data }, rs => resolve(rs))
32 | })
33 | }
34 |
35 | const API = {
36 | METHODS,
37 | REQ_TYPE,
38 | CACHE_TYPE,
39 | ERROR_HANDLER_TYPE,
40 | doFetch,
41 | doFetchJson,
42 | createFetch,
43 | createFetchJson,
44 | createBiJsonFetch,
45 | createPromiseAPI
46 | }
47 |
48 | export default API
49 |
--------------------------------------------------------------------------------
/examples/reactapp/src/common/apiutils/reqwestAJAX.js:
--------------------------------------------------------------------------------
1 | import reqwest from 'reqwest'
2 | import _ from 'lodash'
3 | import {
4 | defaultBiJsonOptions,
5 | defaultJsonOptions,
6 | defaultOptions,
7 | getRealUrl,
8 | METHODS,
9 | REQ_TYPE,
10 | wrapErrorHandler
11 | } from './ajaxCommon'
12 |
13 | function _doFetch(options = {}, dispatch, defaultMergeOption = {}) {
14 | const opts = _.merge({}, defaultMergeOption, options, {
15 | url: getRealUrl(options.url),
16 | error: wrapErrorHandler(options.onError, dispatch)
17 | })
18 |
19 | const method = opts.method && opts.method.toUpperCase()
20 | const data = opts.data
21 | if (METHODS.GET === method && opts.processData !== false && !_.isString(data)) {
22 | // get 请求,配置 processData 不为否,data 不为 String 则预处理
23 | const newData = { ...data, ts: new Date().getTime() } // 加入时间戳,防止浏览器缓存
24 | opts.data = reqwest.toQueryString(newData, true) // traditional 方式,保证数组符合 spring mvc 的传参方式。
25 | }
26 |
27 | opts.success = (res) => {
28 | const doSuc = options.onSuccess ? options.onSuccess : defaultOptions.onSuccess // reqwest 名字不同
29 | if (opts.type === REQ_TYPE.JSON || typeof res === 'object') {
30 | // noinspection JSUnresolvedVariable
31 | if (res.result === 0 || res.ret === 0) {
32 | doSuc(res.data)
33 | } else {
34 | opts.error(res)
35 | }
36 | } else {
37 | doSuc(res)
38 | }
39 | }
40 |
41 | reqwest(opts)
42 | }
43 |
44 | export function doFetch(options = {}, dispatch) {
45 | _doFetch(options, dispatch, defaultOptions)
46 | }
47 |
48 | export function doFetchJson(options = {}, dispatch) {
49 | _doFetch(options, dispatch, defaultJsonOptions)
50 | }
51 |
52 | export function doBiJsonFetch(options = {}, dispatch) {
53 | let opts = options
54 | if (typeof opts.data === 'object') {
55 | opts = { ...options, data: JSON.stringify(opts.data) }
56 | }
57 | _doFetch(opts, dispatch, defaultBiJsonOptions)
58 | }
59 |
--------------------------------------------------------------------------------
/examples/reactapp/src/components/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 本项目二次封装的 UI 组件入口
3 | * @author Zhang Peng
4 | */
5 |
6 | /****************************** 布局组件 ******************************/
7 | export { default as Header } from './layout/Header/Header'
8 | export { default as Sidebar } from './layout/Sidebar/Sidebar'
9 | export { default as Content } from './layout/Content/Content'
10 | export { default as Footer } from './layout/Footer/Footer'
11 | export { default as Breadcrumb } from './layout/Breadcrumb/Breadcrumb'
12 |
--------------------------------------------------------------------------------
/examples/reactapp/src/components/layout/Breadcrumb/Breadcrumb.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 面包屑组件
3 | * @author Zhang Peng
4 | * @see https://github.com/facebook/prop-types
5 | * @see https://ant.design/components/breadcrumb-cn/
6 | * @see https://ant.design/components/icon-cn/
7 | */
8 | import { Breadcrumb, Icon } from 'antd'
9 | import PropTypes from 'prop-types'
10 | import React from 'react'
11 | import './Breadcrumb.less'
12 |
13 | /**
14 | * 面包屑组件
15 | * @class
16 | */
17 | class CustomBreadcrumb extends React.PureComponent {
18 | static propTypes = {
19 | data: PropTypes.array
20 | }
21 |
22 | static defaultProps = {
23 | data: []
24 | }
25 |
26 | render() {
27 | const { data } = this.props
28 | const breadcrumbItems = data.map((item) => {
29 | return (
30 |
31 |
32 | {item.title}
33 |
34 | )
35 | })
36 |
37 | return (
38 |
39 |
40 |
41 |
42 | Home
43 |
44 | {breadcrumbItems}
45 |
46 |
47 | )
48 | }
49 | }
50 |
51 | export default CustomBreadcrumb
52 |
--------------------------------------------------------------------------------
/examples/reactapp/src/components/layout/Breadcrumb/Breadcrumb.less:
--------------------------------------------------------------------------------
1 | .ant-layout-breadcrumb {
2 | z-index: 200;
3 | line-height: 64px;
4 |
5 | .ant-breadcrumb-link {
6 | font-size: 16px;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/examples/reactapp/src/components/layout/Content/Content.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 内容布局组件
3 | * @author Zhang Peng
4 | * @see https://ant.design/components/layout-cn/
5 | * @see https://ant.design/components/card-cn/
6 | */
7 | import { Card, Layout } from 'antd'
8 | import React from 'react'
9 |
10 | import './Content.less'
11 |
12 | const { Content } = Layout
13 |
14 | /**
15 | * 内容布局组件
16 | * @class
17 | */
18 | class CustomContent extends React.PureComponent {
19 | constructor(props) {
20 | super(props)
21 | }
22 |
23 | render() {
24 | return (
25 |
26 |
27 | {this.props.children}
28 |
29 |
30 | )
31 | }
32 | }
33 |
34 | export default CustomContent
35 |
--------------------------------------------------------------------------------
/examples/reactapp/src/components/layout/Content/Content.less:
--------------------------------------------------------------------------------
1 | .ant-layout-content {
2 | background: #fff;
3 | padding: 24px;
4 | }
5 |
--------------------------------------------------------------------------------
/examples/reactapp/src/components/layout/Footer/Footer.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 底部布局组件
3 | * @author Zhang Peng
4 | * @see https://ant.design/components/layout-cn/
5 | */
6 | import { Layout } from 'antd'
7 | import React from 'react'
8 |
9 | import './index.less'
10 |
11 | const { Footer } = Layout
12 |
13 | /**
14 | * 底部布局组件
15 | * @class
16 | */
17 | class CustomFooter extends React.PureComponent {
18 | render() {
19 | return (
20 |
23 | )
24 | }
25 | }
26 |
27 | export default CustomFooter
28 |
--------------------------------------------------------------------------------
/examples/reactapp/src/components/layout/Footer/index.less:
--------------------------------------------------------------------------------
1 | .ant-layout-footer {
2 | height: 64px;
3 | line-height: 32px;
4 | text-align: center;
5 | font-size: 14px;
6 | color: #999;
7 | background: #fff;
8 | border-top: 1px solid #e9e9e9;
9 | width: 100%;
10 | }
11 |
--------------------------------------------------------------------------------
/examples/reactapp/src/components/layout/Header/Header.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 顶部布局组件
3 | * @author Zhang Peng
4 | * @see https://ant.design/components/layout-cn/
5 | */
6 | import { Avatar, Badge, Col, Dropdown, Icon, Layout, Menu, Popover, Row } from 'antd'
7 | import React from 'react'
8 | import { Link, withRouter } from 'react-router-dom'
9 | import PropTypes from 'prop-types'
10 | import { connect } from 'react-redux'
11 | import { bindActionCreators } from 'redux'
12 |
13 | import './Header.less'
14 | import Breadcrumb from '../Breadcrumb/Breadcrumb'
15 | import { fetchProfile, logout } from '../../../redux/actions/auth'
16 |
17 | const { Header } = Layout
18 |
19 | const content = (
20 |
21 |
Content
22 |
Content
23 |
Content
24 |
Content
25 |
Content
26 |
27 | )
28 |
29 | const mapStateToProps = (state) => {
30 | const { auth, menu } = state
31 | return {
32 | auth: auth ? auth : null,
33 | navpath: menu.navpath
34 | }
35 | }
36 |
37 | const mapDispatchToProps = (dispatch) => {
38 | return { actions: bindActionCreators({ fetchProfile, logout }, dispatch) }
39 | }
40 |
41 | /**
42 | * 顶部布局组件
43 | * @class
44 | */
45 | class CustomHeader extends React.PureComponent {
46 | static propTypes = {
47 | auth: PropTypes.object,
48 | actions: PropTypes.object,
49 | navpath: PropTypes.array
50 | }
51 | static defaultProps = {
52 | auth: null,
53 | actions: null,
54 | navpath: []
55 | }
56 |
57 | componentWillMount() {
58 | const { actions } = this.props
59 | actions.fetchProfile()
60 | }
61 |
62 | handleLogOut = () => {
63 | const { actions } = this.props
64 | actions.logout().payload.promise.then(() => {
65 | this.props.history.replace('/login')
66 | })
67 | }
68 |
69 | render() {
70 | const { auth, navpath } = this.props
71 | let username = ''
72 | if (auth.user) {
73 | if (auth.user.data) {
74 | username = auth.user.data.name
75 | }
76 | }
77 |
78 | const menu = (
79 |
91 | )
92 |
93 | return (
94 |
124 | )
125 | }
126 | }
127 |
128 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(CustomHeader))
129 |
130 |
--------------------------------------------------------------------------------
/examples/reactapp/src/components/layout/Header/Header.less:
--------------------------------------------------------------------------------
1 | .ant-layout-header {
2 | top: 0;
3 | right: 0;
4 | //height: 64px;
5 | //padding: 25px;
6 | z-index: 150;
7 | background: #fff;
8 | box-shadow: 0 0 1px 0 rgba(0, 0, 0, .3), 0 0 6px 2px rgba(0, 0, 0, .15);
9 | }
10 |
11 | .header-icon {
12 | margin: 0 15px;
13 |
14 | i {
15 | font-size: 20px;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/reactapp/src/components/layout/Sidebar/Sidebar.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 侧边导航栏组件
3 | * @author Zhang Peng
4 | * @see https://ant.design/components/layout-cn/
5 | */
6 | import { Icon, Layout, Menu } from 'antd'
7 | import PropTypes from 'prop-types'
8 | import React from 'react'
9 | import { connect } from 'react-redux'
10 | import { matchPath, withRouter } from 'react-router'
11 | import { Link } from 'react-router-dom'
12 | import { bindActionCreators } from 'redux'
13 |
14 | import './Sidebar.less'
15 | import logoImg from './antd.svg'
16 | import { refreshMenu, refreshNavPath } from '../../../redux/actions/menu'
17 |
18 | const { Sider } = Layout
19 |
20 | const isActive = (path, history) => {
21 | return matchPath(path, {
22 | path: history.location.pathname,
23 | exact: true,
24 | strict: false
25 | })
26 | }
27 |
28 | /**
29 | * 侧边导航栏组件。侧边栏采用的响应式布局方式,页面大小收缩到一定程度,侧边栏会隐藏。
30 | * @class
31 | */
32 | class CustomSidebar extends React.PureComponent {
33 | static propTypes = {
34 | items: PropTypes.array
35 | }
36 | static defaultProps = {
37 | items: []
38 | }
39 |
40 | state = {
41 | openKey: 'sub0',
42 | activeKey: 'menu0',
43 | mode: 'inline'
44 | }
45 |
46 | componentDidMount() {
47 | this.props.getAllMenu()
48 | }
49 |
50 | componentWillReceiveProps(nextProps) {
51 | Array.isArray(nextProps.items) && nextProps.items.map((item, i) => {
52 | Array.isArray(item.children) && item.children.map((node) => {
53 | if (node.url && isActive(node.url, this.props.history)) {
54 | this.menuClickHandle({
55 | key: 'menu' + node.key,
56 | keyPath: ['menu' + node.key, 'sub' + item.key]
57 | })
58 | }
59 | })
60 | })
61 | }
62 |
63 | menuClickHandle = (item) => {
64 | this.setState({
65 | activeKey: item.key
66 | })
67 | this.props.updateNavPath(item.keyPath, item.key)
68 | }
69 |
70 | render() {
71 | const { items, history } = this.props
72 | let { activeKey, openKey } = this.state
73 |
74 | const _menuProcess = (nodes, pkey) => {
75 | return Array.isArray(nodes) && nodes.map((item, i) => {
76 | const menu = _menuProcess(item.children, item.key)
77 | if (item.url && isActive(item.url, history)) {
78 | activeKey = 'menu' + item.key
79 | openKey = 'sub' + pkey
80 | }
81 |
82 | switch (item.type) {
83 |
84 | case 'SubMenu':
85 | return (
86 | {item.title}}
89 | >
90 | {menu}
91 |
92 | )
93 | case 'ItemGroup':
94 | return (
95 | {item.title}}
98 | >
99 | {menu}
100 |
101 | )
102 | case 'Divider':
103 | return (
104 |
105 | )
106 | case 'Item':
107 | default:
108 | return (
109 |
110 | {
111 | item.url ? {item.icon && }{item.title} :
112 | {item.icon && }{item.title}
113 | }
114 |
115 | )
116 | break
117 | }
118 | })
119 | }
120 |
121 | const menu = _menuProcess(items)
122 |
123 | return (
124 | /**
125 | * 响应式布局
126 | * 说明:配置 breakpoint 属性即生效,视窗宽度小于 breakpoint 时 Sider 缩小为 collapsedWidth 宽度,
127 | * 若将 collapsedWidth 设置为零,会出现特殊 trigger。
128 | */
129 |
133 |
134 |
135 |

136 |
Ant Design
137 |
138 |
139 |
147 |
148 | )
149 | }
150 | }
151 |
152 | function mapStateToProps(state) {
153 | return {
154 | items: state.menu.items
155 | }
156 | }
157 |
158 | function mapDispatchToProps(dispatch) {
159 | return {
160 | getAllMenu: bindActionCreators(refreshMenu, dispatch),
161 | updateNavPath: bindActionCreators(refreshNavPath, dispatch)
162 | }
163 | }
164 |
165 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(CustomSidebar))
166 |
--------------------------------------------------------------------------------
/examples/reactapp/src/components/layout/Sidebar/Sidebar.less:
--------------------------------------------------------------------------------
1 | .ant-layout-sider {
2 | height: 100%;
3 | width: 300px;
4 | }
5 |
6 | .ant-layout-logo {
7 | width: 200px;
8 | height: 64px;
9 | color: #108ee9;
10 | display: table-cell;
11 | vertical-align: middle;
12 |
13 | .logo-container {
14 | width: 150px;
15 | margin: 0 auto;
16 |
17 | img {
18 | width: 40px;
19 | height: 40px;
20 | margin-right: 12px;
21 | margin-top: 12px;
22 | }
23 |
24 | span {
25 | float: right;
26 | margin-top: 20px;
27 | font-size: 16px;
28 | font-family: Raleway, Hiragino Sans GB, sans-serif;
29 | text-transform: uppercase;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/examples/reactapp/src/components/layout/Sidebar/antd.svg:
--------------------------------------------------------------------------------
1 |
2 |
40 |
--------------------------------------------------------------------------------
/examples/reactapp/src/containers/Core/CoreContainer.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 应用的核心容器组件
3 | * @author Zhang Peng
4 | * @see https://ant.design/components/layout-cn/
5 | */
6 | import { Layout } from 'antd'
7 | import React from 'react'
8 | import { Redirect, Route } from 'react-router-dom'
9 |
10 | import './CoreContainer.less'
11 | import { authHOC } from '../../utils'
12 | import { ChildRoutes } from '../../routes'
13 | import { Content, Footer, Header, Sidebar } from '../../components'
14 |
15 | /**
16 | * 应用的核心容器组件
17 | * 控制整个页面的布局。整体采用的是侧边布局。
18 | * @class
19 | */
20 | class CoreContainer extends React.PureComponent {
21 | render() {
22 | return (
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | {ChildRoutes.map((route, index) => (
31 |
32 | ))}
33 |
34 |
35 |
36 |
37 |
38 | )
39 | }
40 | }
41 |
42 | export default CoreContainer
43 |
--------------------------------------------------------------------------------
/examples/reactapp/src/containers/Core/CoreContainer.less:
--------------------------------------------------------------------------------
1 | #root, div[data-reactroot] {
2 | height: 100%;
3 | }
4 |
5 | .ant-layout-has-sider {
6 | height: 100%;
7 |
8 | .ant-layout-container {
9 | padding-top: 30px;
10 | padding-bottom: 30px;
11 | padding-left: 50px;
12 | padding-right: 50px;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/reactapp/src/containers/Core/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "CoreContainer",
3 | "version": "0.0.0",
4 | "private": true,
5 | "main": "./CoreContainer.jsx"
6 | }
7 |
--------------------------------------------------------------------------------
/examples/reactapp/src/containers/Root/ReduxDevTools.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file Redux 开发工具
3 | * @author Zhang Peng
4 | * @see https://github.com/gaearon/redux-devtools
5 | * @see https://github.com/gaearon/redux-devtools-dock-monitor
6 | * @see https://github.com/gaearon/redux-devtools-log-monitor
7 | */
8 | import React from 'react'
9 | // Exported from redux-devtools
10 | import { createDevTools } from 'redux-devtools'
11 | // Monitors are separate packages, and you can make a custom one
12 | import LogMonitor from 'redux-devtools-log-monitor'
13 | import DockMonitor from 'redux-devtools-dock-monitor'
14 |
15 | /**
16 | * Redux 开发工具组件
17 | * @class
18 | */
19 | // createDevTools takes a monitor and produces a DevTools component
20 | const ReduxDevTools = createDevTools(
21 | // Monitors are individually adjustable with props.
22 | // Consult their repositories to learn about those props.
23 | // Here, we put LogMonitor inside a DockMonitor.
24 | // Note: DockMonitor is visible by default.
25 |
28 |
29 |
30 | )
31 | export default ReduxDevTools
32 |
--------------------------------------------------------------------------------
/examples/reactapp/src/containers/Root/RootContainer.dev.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 开发环境的 Root 容器
3 | * @author Zhang Peng
4 | * @see http://gaearon.github.io/react-hot-loader/getstarted/
5 | */
6 | import React from 'react'
7 | import { Provider } from 'react-redux'
8 | import { HashRouter as Router } from 'react-router-dom'
9 |
10 | import Routes from '../../routes'
11 | import ReduxDevTools from './ReduxDevTools'
12 | import configureStore from '../../redux/store/configureStore'
13 |
14 | const store = configureStore()
15 |
16 | /**
17 | * 开发环境的 Root 容器,会包含 Redux 的开发工具
18 | * @class
19 | */
20 | class RootContainer extends React.PureComponent {
21 | render() {
22 | if (!this.routes) this.routes = Routes
23 | return (
24 |
25 |
26 |
27 |
28 |
29 |
30 | )
31 | }
32 | }
33 |
34 | export default RootContainer
35 |
--------------------------------------------------------------------------------
/examples/reactapp/src/containers/Root/RootContainer.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file Root 容器模块是 antd-admin 的根组件
3 | * @author Zhang Peng
4 | * @see http://gaearon.github.io/react-hot-loader/getstarted/
5 | */
6 | if (process.env.NODE_ENV === 'development') {
7 | module.exports = require('./RootContainer.dev')
8 | console.log('[development] Root.dev started.')
9 | } else {
10 | module.exports = require('./RootContainer.prod')
11 | console.log('[production] Root.prod started.')
12 | }
13 |
--------------------------------------------------------------------------------
/examples/reactapp/src/containers/Root/RootContainer.prod.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 生产环境的 Root 容器
3 | * @author Zhang Peng
4 | * @see http://gaearon.github.io/react-hot-loader/getstarted/
5 | */
6 | import React from 'react'
7 | import { Provider } from 'react-redux'
8 | import { HashRouter as Router } from 'react-router-dom'
9 |
10 | import Routes from '../../routes'
11 | import configureStore from '../../redux/store/configureStore'
12 |
13 | const store = configureStore()
14 |
15 | /**
16 | * 生产环境的 Root 容器
17 | * @class
18 | */
19 | class RootContainer extends React.PureComponent {
20 | render() {
21 | if (!this.routes) this.routes = Routes
22 | return (
23 |
24 |
25 |
26 | )
27 | }
28 | }
29 |
30 | export default RootContainer
31 |
--------------------------------------------------------------------------------
/examples/reactapp/src/index.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file App 的总入口
3 | * @author Zhang Peng
4 | * @see http://gaearon.github.io/react-hot-loader/getstarted/
5 | */
6 | import 'react-hot-loader/patch'
7 | import React from 'react'
8 | import ReactDOM from 'react-dom'
9 | import { AppContainer } from 'react-hot-loader'
10 |
11 | import RootContainer from './containers/Root/RootContainer'
12 |
13 | const render = Component => {
14 | ReactDOM.render(
15 |
16 |
17 | ,
18 | document.getElementById('root')
19 | )
20 | }
21 |
22 | // 初次启动 App
23 | render(RootContainer)
24 |
25 | // 热替换启动 App
26 | if (module.hot) {
27 | module.hot.accept('./containers/Root/RootContainer', () => {
28 | const NextRootContainer = require('./containers/Root/RootContainer')
29 | render(NextRootContainer)
30 | })
31 | }
32 |
--------------------------------------------------------------------------------
/examples/reactapp/src/redux/actions/auth.js:
--------------------------------------------------------------------------------
1 | const webapi = require('../../webapi')
2 | import { FETCH_PROFILE, LOGIN, LOGOUT, UID_NOT_FOUND } from '../constants/authActionType'
3 |
4 | export const fetchProfile = () => {
5 | let uid = window.localStorage.getItem('uid')
6 |
7 | if (uid === undefined) {
8 | return { type: UID_NOT_FOUND }
9 | }
10 |
11 | return {
12 | type: FETCH_PROFILE,
13 | payload: {
14 | promise: webapi.get('/my')
15 | }
16 | }
17 | }
18 |
19 | export const login = (username, password) => {
20 | return {
21 | type: LOGIN,
22 | payload: {
23 | promise: webapi.put('/login', {
24 | username: username,
25 | password: password
26 | })
27 | }
28 | }
29 | }
30 |
31 | export const logout = () => {
32 | return {
33 | type: LOGOUT,
34 | payload: {
35 | promise: webapi.get('/logout')
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/examples/reactapp/src/redux/actions/menu.js:
--------------------------------------------------------------------------------
1 | const webapi = require('../../webapi')
2 | import { REFRESH_MENU, REFRESH_NAVPATH } from '../constants/menuActionType'
3 |
4 | export const refreshNavPath = (path, key) => {
5 | return {
6 | type: REFRESH_NAVPATH,
7 | payload: {
8 | data: path,
9 | key: key
10 | }
11 | }
12 | }
13 |
14 | export const refreshMenu = () => {
15 | return {
16 | type: REFRESH_MENU,
17 | payload: {
18 | promise: webapi.get('/menu')
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/examples/reactapp/src/redux/constants/authActionType.js:
--------------------------------------------------------------------------------
1 | export const LOGIN = 'LOGIN'
2 | export const LOGOUT = 'LOGOUT'
3 | export const FETCH_PROFILE = 'FETCH_PROFILE'
4 | export const UID_NOT_FOUND = 'UID_NOT_FOUND'
5 |
6 | export const LOGIN_PENDING = 'LOGIN_PENDING'
7 | export const LOGIN_SUCCESS = 'LOGIN_SUCCESS'
8 | export const LOGIN_FAILED = 'LOGIN_FAILED'
9 |
10 | export const LOGOUT_PENDING = 'LOGOUT_PENDING'
11 | export const LOGOUT_SUCCESS = 'LOGOUT_SUCCESS'
12 | export const LOGOUT_FAILED = 'LOGOUT_FAILED'
13 |
14 | export const FETCH_PROFILE_PENDING = 'FETCH_PROFILE_PENDING'
15 | export const FETCH_PROFILE_SUCCESS = 'FETCH_PROFILE_SUCCESS'
16 | export const FETCH_PROFILE_FAILED = 'FETCH_PROFILE_FAILED'
17 |
--------------------------------------------------------------------------------
/examples/reactapp/src/redux/constants/commonActionTypes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 公共的请求失败 Action 。用于 api 请求未传入错误处理函数。
3 | * 如果传入 dispatch,则会 dispatch 该 action。
4 | * 如果无 dispatch,则 console.log error
5 | * @type {string}
6 | */
7 | export const COMMON_REQUEST_ERROR = 'COMMON_REQUEST_ERROR'
8 |
9 | /**
10 | * 公共的 SpinModal action。用于控制统一的过度形式的模态框展示。
11 | * 各类型,配合 payload 中的 type 等字段控制。
12 | * @type {string}
13 | */
14 | export const COMMON_SPIN_MODAL = 'COMMON_SPIN_MODAL'
15 |
16 | /**
17 | * 公共的 SpinModal action。用于控制统一的过度形式的模态框消失。
18 | * @type {string}
19 | */
20 | export const COMMON_SPIN_MODAL_DIS = 'COMMON_SPIN_MODAL_DIS'
21 |
22 | // 校验
23 | export const COMMON_VALIDATE_FAIL = 'COMMON_VALIDATE_FAIL'
24 |
25 | /**
26 | * 公共的页面离开(跳转)确认功能开关
27 | * @type {string}
28 | */
29 | export const COMMON_LEAVE_CONFIRM_ON = 'COMMON_LEAVE_CONFIRM_ON'
30 | export const COMMON_LEAVE_CONFIRM_OFF = 'COMMON_LEAVE_CONFIRM_OFF'
31 |
--------------------------------------------------------------------------------
/examples/reactapp/src/redux/constants/menuActionType.js:
--------------------------------------------------------------------------------
1 | export const REFRESH_MENU = 'REFRESH_MENU'
2 | export const REFRESH_NAVPATH = 'REFRESH_NAVPATH'
3 | export const REFRESH_MENU_SUCCESS = 'REFRESH_MENU_SUCCESS'
4 | export const REFRESH_MENU_FAILED = 'REFRESH_MENU_FAILED'
5 |
--------------------------------------------------------------------------------
/examples/reactapp/src/redux/middlewares/promiseMiddleware.js:
--------------------------------------------------------------------------------
1 | const defaultTypes = ['PENDING', 'FULFILLED', 'REJECTED']
2 |
3 | const isPromise = (value) => {
4 | if (value !== null && typeof value === 'object') {
5 | return value.promise && typeof value.promise.then === 'function'
6 | }
7 | }
8 |
9 | function createPromiseMiddleware(config = {}) {
10 | const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypes
11 |
12 | return (_ref) => {
13 | const dispatch = _ref.dispatch
14 |
15 | return next => action => {
16 | if (!isPromise(action.payload)) {
17 | return next(action)
18 | }
19 |
20 | const { type, payload, meta } = action
21 | const { promise, data } = payload
22 | const [PENDING, FULFILLED, REJECTED] = (meta || {}).promiseTypeSuffixes || promiseTypeSuffixes
23 |
24 | /**
25 | * Dispatch the first async handler. This tells the
26 | * reducer that an async action has been dispatched.
27 | */
28 | next({
29 | type: `${type}_${PENDING}`,
30 | ...!!data ? { payload: data } : {},
31 | ...!!meta ? { meta } : {}
32 | })
33 |
34 | const isAction = resolved => resolved && (resolved.meta || resolved.payload)
35 | const isThunk = resolved => typeof resolved === 'function'
36 | const getResolveAction = isError => ({
37 | type: `${type}_${isError ? REJECTED : FULFILLED}`,
38 | ...!!meta ? { meta } : {},
39 | ...!!isError ? { error: true } : {}
40 | })
41 |
42 | /**
43 | * Re-dispatch one of:
44 | * 1. a thunk, bound to a resolved/rejected object containing ?meta and type
45 | * 2. the resolved/rejected object, if it looks like an action, merged into action
46 | * 3. a resolve/rejected action with the resolve/rejected object as a payload
47 | */
48 | action.payload.promise = promise.then(
49 | (resolved = {}) => {
50 | const resolveAction = getResolveAction()
51 | return dispatch(isThunk(resolved) ? resolved.bind(null, resolveAction) : {
52 | ...resolveAction,
53 | ...isAction(resolved) ? resolved : {
54 | ...!!resolved && { payload: resolved }
55 | }
56 | })
57 | },
58 | (rejected = {}) => {
59 | const resolveAction = getResolveAction(true)
60 | return dispatch(isThunk(rejected) ? rejected.bind(null, resolveAction) : {
61 | ...resolveAction,
62 | ...isAction(rejected) ? rejected : {
63 | ...!!rejected && { payload: rejected }
64 | }
65 | })
66 | }
67 | )
68 |
69 | return action
70 | }
71 | }
72 | }
73 |
74 | const promise = createPromiseMiddleware({ promiseTypeSuffixes: ['PENDING', 'SUCCESS', 'FAILED'] })
75 | export default promise
76 |
--------------------------------------------------------------------------------
/examples/reactapp/src/redux/reducers/auth.js:
--------------------------------------------------------------------------------
1 | import {
2 | FETCH_PROFILE_SUCCESS,
3 | LOGIN_FAILED,
4 | LOGIN_PENDING,
5 | LOGIN_SUCCESS,
6 | LOGOUT_SUCCESS
7 | } from '../constants/authActionType'
8 |
9 | const initialState = {
10 | user: null,
11 | loggingIn: false,
12 | loggingOut: false,
13 | message: null
14 | }
15 |
16 | const auth = (state = initialState, action = {}) => {
17 | switch (action.type) {
18 | case LOGIN_PENDING:
19 | return Object.assign({}, state, {
20 | loggingIn: true
21 | })
22 | case LOGIN_SUCCESS:
23 | let user = action.payload.data
24 | window.localStorage.setItem('uid', user.uid)
25 | return Object.assign({}, state, {
26 | user: user,
27 | loggingIn: false,
28 | message: null
29 | })
30 | case LOGIN_FAILED:
31 | return {
32 | ...state,
33 | loggingIn: false,
34 | user: null,
35 | message: action.payload.response.data.message
36 | }
37 | case LOGOUT_SUCCESS:
38 | window.localStorage.removeItem('uid')
39 | return {
40 | ...state,
41 | loggingOut: false,
42 | user: null,
43 | message: null
44 | }
45 | case FETCH_PROFILE_SUCCESS:
46 | return Object.assign({}, state, {
47 | user: action.payload.data,
48 | loggingIn: false,
49 | message: null
50 | })
51 | default:
52 | return state
53 | }
54 | }
55 | export default auth
56 |
--------------------------------------------------------------------------------
/examples/reactapp/src/redux/reducers/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Zhang Peng on 2017/7/6.
3 | */
4 | import { combineReducers } from 'redux'
5 | import auth from './auth'
6 | import menu from './menu'
7 |
8 | const rootReducer = combineReducers({
9 | auth,
10 | menu
11 | })
12 | export default rootReducer
13 |
--------------------------------------------------------------------------------
/examples/reactapp/src/redux/reducers/menu.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash'
2 |
3 | import { REFRESH_MENU_SUCCESS, REFRESH_NAVPATH } from '../constants/menuActionType'
4 |
5 | const initialState = {
6 | items: [],
7 | navpath: []
8 | }
9 |
10 | const menu = (state = initialState, action = {}) => {
11 | switch (action.type) {
12 | case REFRESH_MENU_SUCCESS:
13 | return Object.assign({}, initialState, {
14 | items: action.payload.data.data
15 | })
16 | case REFRESH_NAVPATH:
17 | let navpath = [], tmpOb, tmpKey, children
18 | if (Array.isArray(action.payload.data)) {
19 | action.payload.data.reverse().map((item) => {
20 | if (item.indexOf('sub') !== -1) {
21 | tmpKey = item.replace('sub', '')
22 | tmpOb = _.find(state.items, function(o) {
23 | return o.key == tmpKey
24 | })
25 | children = tmpOb.children
26 | navpath.push({
27 | key: tmpOb.key,
28 | title: tmpOb.title,
29 | icon: tmpOb.icon,
30 | type: tmpOb.type,
31 | url: tmpOb.url
32 | })
33 | }
34 | if (item.indexOf('menu') !== -1) {
35 | tmpKey = item.replace('menu', '')
36 | if (children) {
37 | tmpOb = _.find(children, function(o) {
38 | return o.key == tmpKey
39 | })
40 | navpath.push({
41 | key: tmpOb.key,
42 | title: tmpOb.title,
43 | icon: tmpOb.icon,
44 | type: tmpOb.type,
45 | url: tmpOb.url
46 | })
47 | }
48 | }
49 | })
50 | }
51 | return Object.assign({}, state, {
52 | currentIndex: action.payload.key * 1,
53 | navpath: navpath
54 | })
55 | default:
56 | return state
57 | }
58 | }
59 | export default menu
60 |
--------------------------------------------------------------------------------
/examples/reactapp/src/redux/store/configureStore.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 开发环境的 Store 构造器
3 | * @author Zhang Peng
4 | * @see https://github.com/gaearon/redux-devtools/blob/master/docs/Walkthrough.md
5 | */
6 |
7 | import { applyMiddleware, compose, createStore } from 'redux'
8 | import { persistState } from 'redux-devtools'
9 | import logger from 'redux-logger'
10 | import thunk from 'redux-thunk'
11 |
12 | import DevTools from '../../containers/Root/ReduxDevTools'
13 | import promise from '../middlewares/promiseMiddleware'
14 | import reducers from '../reducers'
15 |
16 | const enhancer = compose(
17 | // Middleware you want to use in development:
18 | applyMiddleware(thunk, logger, promise),
19 | // Required! Enable Redux DevTools with the monitors you chose
20 | DevTools.instrument(),
21 | // Optional. Lets you write ?debug_session= in address bar to persist debug sessions
22 | persistState(getDebugSessionKey())
23 | )
24 |
25 | function getDebugSessionKey() {
26 | // You can write custom logic here!
27 | // By default we try to read the key from ?debug_session= in the address bar
28 | const matches = window.location.href.match(/[?&]debug_session=([^&]+)\b/)
29 | return (matches && matches.length > 0) ? matches[1] : null
30 | }
31 |
32 | /**
33 | * 开发环境的 Store 构造方法。与生产环境的 Store 构造方法相比,将创建的 Store 中多了开发工具。
34 | * @param {Object} initialState 初始状态
35 | * @returns {Store} Redux 的状态容器,一个应用只有一个
36 | */
37 | function configureStore(initialState) {
38 | // Note: only Redux >= 3.1.0 supports passing enhancer as third argument.
39 | // See https://github.com/reactjs/redux/releases/tag/v3.1.0
40 | const store = createStore(reducers, initialState, enhancer)
41 |
42 | // Hot reload reducers (requires Webpack or Browserify HMR to be enabled)
43 | if (module.hot) {
44 | module.hot.accept('../reducers', () =>
45 | store.replaceReducer(require('../reducers'))
46 | )
47 | }
48 |
49 | return store
50 | }
51 |
52 | export default configureStore
53 |
--------------------------------------------------------------------------------
/examples/reactapp/src/redux/store/configureStore.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file Redux 创建Store入口,区分开发、生产环境
3 | * @author Zhang Peng
4 | * @see https://github.com/gaearon/redux-devtools/blob/master/docs/Walkthrough.md
5 | */
6 | // Use DefinePlugin (Webpack) or loose-envify (Browserify)
7 | // together with Uglify to strip the dev branch in prod build.
8 | if (process.env.NODE_ENV === 'development') {
9 | module.exports = require('./configureStore.dev').default
10 | } else {
11 | module.exports = require('./configureStore.prod').default
12 | }
13 |
--------------------------------------------------------------------------------
/examples/reactapp/src/redux/store/configureStore.prod.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 生产环境的 Store 构造器
3 | * @author Zhang Peng
4 | * @see https://github.com/gaearon/redux-devtools/blob/master/docs/Walkthrough.md
5 | */
6 |
7 | import { applyMiddleware, createStore } from 'redux'
8 | import thunk from 'redux-thunk'
9 |
10 | import promise from '../middlewares/promiseMiddleware'
11 | import reducers from '../reducers'
12 |
13 | const enhancer = applyMiddleware(thunk, promise)
14 |
15 | /**
16 | * 生产环境的 Store 构造方法。
17 | * @param {Object} initialState 初始状态
18 | * @returns {Store} Redux 的状态容器,一个应用只有一个
19 | */
20 | function configureStore(initialState) {
21 | return createStore(reducers, initialState, enhancer)
22 | }
23 |
24 | export default configureStore
25 |
--------------------------------------------------------------------------------
/examples/reactapp/src/routes/index.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file React Router 入口。
3 | * 本项目使用 React Router 4.x
4 | * @author Zhang Peng
5 | * @see https://reacttraining.com/react-router/
6 | * @see https://reacttraining.cn/
7 | */
8 | import React from 'react'
9 | import { Route, Switch } from 'react-router-dom'
10 |
11 | import CoreContainer from '../containers/Core'
12 | import Login from '../views/pages/login/Login'
13 |
14 | /**
15 | * 子路由表
16 | */
17 | export const ChildRoutes = [
18 | {
19 | 'path': '/pages/home',
20 | 'component': require('../views/pages/home/Home').default,
21 | 'exactly': true
22 | },
23 | {
24 | 'path': '/pages/mailbox',
25 | 'component': require('../views/pages/mail/Mailbox').default
26 | },
27 | {
28 | 'path': '/pages/user',
29 | 'component': require('../views/pages/user/User').default
30 | }
31 | ]
32 |
33 | /**
34 | * 默认路由
35 | * @type {XML}
36 | */
37 | const Routes = (
38 |
39 |
40 |
41 |
42 | )
43 | export default Routes
44 |
--------------------------------------------------------------------------------
/examples/reactapp/src/utils/asyncLoadHOC.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 提供异步加载组件功能的高阶组件方法
3 | * @author Zhang Peng
4 | * @see https://segmentfault.com/a/1190000009820646
5 | */
6 |
7 | import React from 'react'
8 |
9 | let Component = null
10 | export const asyncLoadHOC = loadComponent => (
11 |
12 | class AsyncComponent extends React.Component {
13 |
14 | static hasLoadedComponent() {
15 | return Component !== null
16 | }
17 |
18 | componentWillMount() {
19 | if (AsyncComponent.hasLoadedComponent()) {
20 | return
21 | }
22 |
23 | loadComponent().then(
24 | module => module.default
25 | ).then((comp) => {
26 | Component = comp
27 | }).catch((err) => {
28 | console.error(`Cannot load component in `)
29 | throw err
30 | })
31 | }
32 |
33 | render() {
34 | return (Component) ?
35 | <
36 | Component
37 | {...
38 | this.props
39 | }
40 | /> : null;
41 | }
42 | }
43 | )
44 |
--------------------------------------------------------------------------------
/examples/reactapp/src/utils/authHOC.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 对组件进行认证的方法
3 | * @author Zhang Peng
4 | * @see http://efe.baidu.com/blog/mixins-are-dead-long-live-the-composition/
5 | * @see https://zhuanlan.zhihu.com/p/24776678
6 | * @see https://segmentfault.com/a/1190000004598113
7 | */
8 | import React from 'react'
9 | import { withRouter } from 'react-router-dom'
10 |
11 | /**
12 | * 校验方法
13 | * 如果不是登录状态,并且history路径名不是/login,将history置为/login
14 | * @param props {PropsType} 组件的props
15 | */
16 | const validate = props => {
17 | const { history } = props
18 | const isLoggedIn = !!window.localStorage.getItem('uid')
19 | if (!isLoggedIn && history.location.pathname !== '/login') {
20 | history.replace('/login')
21 | }
22 | }
23 |
24 | /**
25 | * 对组件进行认证的方法
26 | * 使用 React 高阶组件技术包裹传入的组件,对组件中的 props 进行校验
27 | * @param WrappedComponent {React.Component} 传入的组件
28 | * @returns {withRouter}
29 | */
30 | const authHOC = WrappedComponent => {
31 | class Authenticate extends React.Component {
32 | componentWillMount() {
33 | validate(this.props)
34 | }
35 |
36 | componentWillReceiveProps(nextProps) {
37 | if (nextProps.location !== this.props.location) {
38 | validate(nextProps)
39 | }
40 | }
41 |
42 | render() {
43 | return
44 | }
45 | }
46 |
47 | return withRouter(Authenticate)
48 | }
49 | export default authHOC
50 |
--------------------------------------------------------------------------------
/examples/reactapp/src/utils/http.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 封装支持 promise 的 http 请求工具
3 | * @author Zhang Peng
4 | * @see https://github.com/mzabriskie/axios
5 | * @see http://www.jianshu.com/p/df464b26ae58
6 | */
7 |
8 | const axios = require('axios')
9 | const qs = require('qs')
10 |
11 | import config from '../../config/app.config'
12 |
13 | // 本项目中 axios 的默认全局配置
14 | axios.defaults.timeout = config.http.timeout
15 | axios.defaults.baseURL = config.http.baseURL
16 |
17 | axios.defaults.headers.get['Content-Type'] = 'application/json'
18 | axios.defaults.headers.post['Content-Type'] = 'application/json'
19 | axios.defaults.headers.put['Content-Type'] = 'application/json'
20 |
21 | // 本项目的默认配置
22 | const defaultConfig = {
23 | //`url` 是请求的服务器地址
24 | // url: '/user',
25 |
26 | //`method` 是请求资源的方式
27 | // method: 'get', //default
28 |
29 | //如果`url`不是绝对地址,那么`baseURL`将会加到`url`的前面
30 | //当`url`是相对地址的时候,设置`baseURL`会非常的方便
31 | baseURL: config.http.baseURL,
32 |
33 | //`transformRequest` 选项允许我们在请求发送到服务器之前对请求的数据做出一些改动
34 | //该选项只适用于以下请求方式:`put/post/patch`
35 | //数组里面的最后一个函数必须返回一个字符串、-一个`ArrayBuffer`或者`Stream`
36 |
37 | transformRequest: [function(data) {
38 | // 序列化
39 | if (data) {
40 | console.log('[request after stringify] data: ', JSON.stringify(data))
41 | return JSON.stringify(data)
42 | }
43 | }],
44 |
45 | //`transformResponse` 选项允许我们在数据传送到`then/catch`方法之前对数据进行改动
46 | transformResponse: [function(data) {
47 | // 反序列化
48 | if (data) {
49 | console.log('[response after parse] data: ', JSON.parse(data))
50 | return JSON.parse(data)
51 | }
52 | }],
53 |
54 | //`headers`选项是需要被发送的自定义请求头信息
55 | headers: { 'X-Requested-With': 'XMLHttpRequest' },
56 |
57 | //`params`选项是要随请求一起发送的请求参数----一般链接在URL后面
58 | //他的类型必须是一个纯对象或者是URLSearchParams对象
59 | // params: {
60 | // ID: 12345
61 | // },
62 |
63 | //`paramsSerializer`是一个可选的函数,起作用是让参数(params)序列化
64 | //例如(https://www.npmjs.com/package/qs,http://api.jquery.com/jquery.param)
65 | paramsSerializer: function(params) {
66 | const content = qs.stringify(params, { arrayFormat: 'brackets' })
67 | console.log('[http] params 序列化后:', content)
68 | return content
69 | },
70 |
71 | //`data`选项是作为一个请求体而需要被发送的数据
72 | //该选项只适用于方法:`put/post/patch`
73 | //当没有设置`transformRequest`选项时dada必须是以下几种类型之一
74 | //string/plain/object/ArrayBuffer/ArrayBufferView/URLSearchParams
75 | //仅仅浏览器:FormData/File/Bold
76 | //仅node:Stream
77 | // data: {
78 | // firstName: "Fred"
79 | // },
80 |
81 | //`timeout` 选项定义了请求发出的延迟毫秒数
82 | //如果请求花费的时间超过延迟的时间,那么请求会被终止
83 | timeout: config.http.timeout,
84 |
85 | //`withCredentails`选项表明了是否是跨域请求
86 | // withCredentials: false,//default
87 |
88 | //`adapter`适配器选项允许自定义处理请求,这会使得测试变得方便
89 | //返回一个promise,并提供验证返回
90 | // adapter: function (config) {
91 | // /*..........*/
92 | // },
93 |
94 | //`auth` 表明HTTP基础的认证应该被使用,并提供证书
95 | //这会设置一个authorization头(header),并覆盖你在header设置的Authorization头信息
96 | // auth: {
97 | // username: "zhangsan",
98 | // password: "s00sdkf"
99 | // },
100 |
101 | //返回数据的格式
102 | //其可选项是arraybuffer,blob,document,json,text,stream
103 | // responseType: 'json',//default
104 |
105 | //
106 | xsrfCookieName: 'XSRF-TOKEN',//default
107 | xsrfHeaderName: 'X-XSRF-TOKEN',//default
108 |
109 | //`onUploadProgress`上传进度事件
110 | onUploadProgress: function(progressEvent) {
111 | },
112 |
113 | //下载进度的事件
114 | onDownloadProgress: function(progressEvent) {
115 | },
116 |
117 | //相应内容的最大值
118 | maxContentLength: 2000,
119 |
120 | //`validateStatus`定义了是否根据http相应状态码,来resolve或者reject promise
121 | //如果`validateStatus`返回true(或者设置为`null`或者`undefined`),那么promise的状态将会是resolved,否则其状态就是rejected
122 | validateStatus: function(status) {
123 | return status >= 200 && status < 300//default
124 | }
125 |
126 | //`maxRedirects`定义了在nodejs中重定向的最大数量
127 | // maxRedirects: 5,//default
128 |
129 | //`httpAgent/httpsAgent`定义了当发送http/https请求要用到的自定义代理
130 | //keeyAlive在选项中没有被默认激活
131 | // httpAgent: new http.Agent({ keeyAlive: true }),
132 | // httpsAgent: new https.Agent({ keeyAlive: true }),
133 |
134 | //proxy定义了主机名字和端口号,
135 | //`auth`表明http基本认证应该与proxy代理链接,并提供证书
136 | //这将会设置一个`Proxy-Authorization` header,并且会覆盖掉已经存在的`Proxy-Authorization` header
137 | // proxy: {
138 | // host: '127.0.0.1',
139 | // port: 9000,
140 | // auth: {
141 | // username: 'skda',
142 | // password: 'radsd'
143 | // }
144 | // },
145 |
146 | //`cancelToken`定义了一个用于取消请求的cancel token
147 | //详见cancelation部分
148 | // cancelToken: new CancelToken(function (cancel) {
149 | // })
150 | }
151 | // 使用默认配置初始化的请求
152 | const http = axios.create(defaultConfig)
153 | export default http
154 |
--------------------------------------------------------------------------------
/examples/reactapp/src/utils/index.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @file 工具类总入口
3 | * @desc 工具类总入口。
4 | * 原则上工具类都要在此注册,然后提供给外部模块
5 | * @author Zhang Peng
6 | */
7 |
8 | export { default as authHOC } from './authHOC'
9 |
--------------------------------------------------------------------------------
/examples/reactapp/src/views/pages/home/Home.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Zhang Peng on 2017/7/21.
3 | */
4 | import React from 'react'
5 | import './Home.less'
6 |
7 | import logo from './logo.svg'
8 |
9 | export default class Home extends React.Component {
10 | static propTypes = {}
11 | static defaultProps = {}
12 |
13 | render() {
14 | return (
15 |
16 |
17 |
18 | Welcome to REACT ADMIN
19 |
20 |
21 | REACT ADMIN is developing。。。
22 |
23 |
24 | )
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/examples/reactapp/src/views/pages/home/Home.less:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | min-height: 600px;
4 | }
5 |
6 | .App-logo {
7 | animation: App-logo-spin infinite 20s linear;
8 | height: 80px;
9 | }
10 |
11 | .App-header {
12 | background-color: #ffebcc;
13 | height: 150px;
14 | padding: 20px;
15 | color: white;
16 | }
17 |
18 | .App-title {
19 | font-size: 1.5em;
20 | }
21 |
22 | .App-intro {
23 | font-size: large;
24 | }
25 |
26 | @keyframes App-logo-spin {
27 | from {
28 | transform: rotate(0deg);
29 | }
30 | to {
31 | transform: rotate(360deg);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/examples/reactapp/src/views/pages/home/logo.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/examples/reactapp/src/views/pages/login/Login.jsx:
--------------------------------------------------------------------------------
1 | import { Button, Card, Col, Form, Icon, Input, message, Row } from 'antd'
2 | import PropTypes from 'prop-types'
3 | import React from 'react'
4 | import { connect } from 'react-redux'
5 | import { withRouter } from 'react-router-dom'
6 | import { bindActionCreators } from 'redux'
7 |
8 | import { login } from '../../../redux/actions/auth'
9 | import loginLogo from './login-logo.png'
10 |
11 | import './Login.less'
12 |
13 | const FormItem = Form.Item
14 |
15 | const propTypes = {
16 | user: PropTypes.object,
17 | loggingIn: PropTypes.bool,
18 | message: PropTypes.string
19 | }
20 |
21 | function hasErrors(fieldsError) {
22 | return Object.keys(fieldsError).some(field => fieldsError[field])
23 | }
24 |
25 | class Login extends React.Component {
26 |
27 | constructor(props) {
28 | super(props)
29 | this.state = {
30 | loading: false
31 | }
32 | }
33 |
34 | componentDidMount() {
35 | // To disabled submit button at the beginning.
36 | this.props.form.validateFields()
37 | }
38 |
39 | handleSubmit(e) {
40 | e.preventDefault()
41 |
42 | this.setState({
43 | loading: true
44 | })
45 |
46 | const data = this.props.form.getFieldsValue()
47 | this.props.login(data.user, data.password).payload.promise.then(response => {
48 | this.setState({
49 | loading: false
50 | })
51 |
52 | if (response.error) {
53 | console.warn('login failed: ', response.payload.message)
54 | } else {
55 | let result = response.payload.data
56 | console.log('login result:', result)
57 | if (result) {
58 | if (0 !== result.code) {
59 | let str = ''
60 | if (Array.isArray(result.messages)) {
61 | result.messages.map((item) => {
62 | str = str + item + '\n'
63 | })
64 | }
65 | message.error('登录失败: \n' + str)
66 | } else {
67 | console.info('[Login] res.payload.data: ', result)
68 | message.success('欢迎你,' + result.data.name)
69 | this.props.history.replace('/')
70 | }
71 |
72 | }
73 | }
74 | }).catch(err => {
75 | console.error('[Login] err: ', err)
76 | this.setState({
77 | loading: false
78 | })
79 | })
80 | this.props.form.validateFields((err, values) => {
81 | if (!err) {
82 | console.info('提交表单信息', values)
83 | } else {
84 | console.error(err)
85 | }
86 | })
87 | }
88 |
89 | render() {
90 | const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched, setFieldsValue } = this.props.form
91 | // Only show error after a field is touched.
92 | const userNameError = isFieldTouched('userName') && getFieldError('userName')
93 | const passwordError = isFieldTouched('password') && getFieldError('password')
94 |
95 | return (
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | React 管理系统
106 |
107 |
108 |
109 |
110 |
142 |
143 |
144 | )
145 | }
146 | }
147 |
148 | Login.propTypes = propTypes
149 |
150 | Login = Form.create()(Login)
151 |
152 | function mapStateToProps(state) {
153 | const { auth } = state
154 | if (auth.user) {
155 | return { user: auth.user, loggingIn: auth.loggingIn, message: '' }
156 | }
157 |
158 | return { user: null, loggingIn: auth.loggingIn, message: auth.message }
159 | }
160 |
161 | function mapDispatchToProps(dispatch) {
162 | return {
163 | login: bindActionCreators(login, dispatch)
164 | }
165 | }
166 |
167 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Login))
168 |
--------------------------------------------------------------------------------
/examples/reactapp/src/views/pages/login/Login.less:
--------------------------------------------------------------------------------
1 | .login-row {
2 | width: 100%;
3 | height: 100%;
4 | background-image: url("bg.jpg");
5 | background-size: cover;
6 |
7 | .login-form {
8 | background: #F3F9F9;
9 | border-radius: 18px;
10 |
11 | .input {
12 | width: 300px;
13 | size: 18px;
14 |
15 | .anticon-close-circle {
16 | cursor: pointer;
17 | color: #ccc;
18 | transition: color 0.3s;
19 | font-size: 12px;
20 | }
21 |
22 | .anticon-close-circle:hover {
23 | color: #999;
24 | }
25 |
26 | .anticon-close-circle:active {
27 | color: #666;
28 | }
29 | }
30 |
31 | .btn-login {
32 | width: 300px;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/examples/reactapp/src/views/pages/login/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunwu/nginx-tutorial/452bc2d0d3b74d0d40cab700cab278a9b6bc5f2a/examples/reactapp/src/views/pages/login/bg.jpg
--------------------------------------------------------------------------------
/examples/reactapp/src/views/pages/login/login-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunwu/nginx-tutorial/452bc2d0d3b74d0d40cab700cab278a9b6bc5f2a/examples/reactapp/src/views/pages/login/login-logo.png
--------------------------------------------------------------------------------
/examples/reactapp/src/views/pages/mail/Mailbox.jsx:
--------------------------------------------------------------------------------
1 | import { Table } from 'antd'
2 | import React from 'react'
3 |
4 | const columns = [{
5 | title: 'Name',
6 | dataIndex: 'name'
7 | }, {
8 | title: 'Age',
9 | dataIndex: 'age'
10 | }, {
11 | title: 'Address',
12 | dataIndex: 'address'
13 | }]
14 | const data = [{
15 | key: '1',
16 | name: 'John Brown',
17 | age: 32,
18 | address: 'New York No. 1 Lake Park'
19 | }, {
20 | key: '2',
21 | name: 'Jim Green',
22 | age: 42,
23 | address: 'London No. 1 Lake Park'
24 | }, {
25 | key: '3',
26 | name: 'Joe Black',
27 | age: 32,
28 | address: 'Sidney No. 1 Lake Park'
29 | }, {
30 | key: '4',
31 | name: 'Joe Black',
32 | age: 32,
33 | address: 'Sidney No. 1 Lake Park'
34 | }, {
35 | key: '5',
36 | name: 'Joe Black',
37 | age: 32,
38 | address: 'Sidney No. 1 Lake Park'
39 | }]
40 |
41 | export default class MailboxPage extends React.Component {
42 | render() {
43 | return (
44 |
47 | )
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/examples/reactapp/src/views/pages/user/User.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Alert, Button, Col, Input, Row, Select, Table } from 'antd'
3 | import './User.less'
4 |
5 | const { Option, OptGroup } = Select
6 |
7 | const columns = [{
8 | title: 'Name',
9 | dataIndex: 'name',
10 | filters: [{
11 | text: 'Joe',
12 | value: 'Joe'
13 | }, {
14 | text: 'Jim',
15 | value: 'Jim'
16 | }, {
17 | text: 'Submenu',
18 | value: 'Submenu',
19 | children: [{
20 | text: 'Green',
21 | value: 'Green'
22 | }, {
23 | text: 'Black',
24 | value: 'Black'
25 | }]
26 | }],
27 | // specify the condition of filtering result
28 | // here is that finding the name started with `value`
29 | onFilter: (value, record) => record.name.indexOf(value) === 0,
30 | sorter: (a, b) => a.name.length - b.name.length
31 | }, {
32 | title: 'Age',
33 | dataIndex: 'age',
34 | sorter: (a, b) => a.age - b.age
35 | }, {
36 | title: 'Address',
37 | dataIndex: 'address',
38 | filters: [{
39 | text: 'London',
40 | value: 'London'
41 | }, {
42 | text: 'New York',
43 | value: 'New York'
44 | }],
45 | filterMultiple: false,
46 | onFilter: (value, record) => record.address.indexOf(value) === 0,
47 | sorter: (a, b) => a.address.length - b.address.length
48 | }]
49 |
50 | const data = [{
51 | key: '1',
52 | name: 'John Brown',
53 | age: 32,
54 | address: 'New York No. 1 Lake Park'
55 | }, {
56 | key: '2',
57 | name: 'Jim Green',
58 | age: 42,
59 | address: 'London No. 1 Lake Park'
60 | }, {
61 | key: '3',
62 | name: 'Joe Black',
63 | age: 32,
64 | address: 'Sidney No. 1 Lake Park'
65 | }, {
66 | key: '4',
67 | name: 'Jim Red',
68 | age: 32,
69 | address: 'London No. 2 Lake Park'
70 | }]
71 |
72 | function onChange(pagination, filters, sorter) {
73 | console.log('params', pagination, filters, sorter)
74 | }
75 |
76 | export default class UserView extends React.Component {
77 | render() {
78 | return (
79 |
80 |
81 |
82 | 工号:
83 |
84 | 姓名:
85 |
86 | 部门:
87 |
88 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | 状态:
107 |
108 |
113 |
114 | 修改时间:
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
137 |
138 |
139 |
140 |
141 |
142 | )
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/examples/reactapp/src/views/pages/user/User.less:
--------------------------------------------------------------------------------
1 | .user-view-row {
2 | padding-bottom: 15px;
3 | }
4 |
--------------------------------------------------------------------------------
/examples/reactapp/src/webapi/mock/index.js:
--------------------------------------------------------------------------------
1 | const axios = require('axios')
2 | const MockAdapter = require('axios-mock-adapter')
3 | const mockAxios = axios.create()
4 |
5 | // mock 数据
6 | const mock = new MockAdapter(mockAxios)
7 | mock.onPut('/login').reply(config => {
8 | let postData = JSON.parse(config.data)
9 | console.info('[mock]', postData)
10 | if (postData.username === 'admin' && postData.password === '123456') {
11 | let result = require('./user')
12 | console.info('[mock result]', result)
13 | return [200, result]
14 | } else {
15 | return [500, { message: 'Incorrect user or password' }]
16 | }
17 | })
18 | mock.onGet('/logout').reply(200, {})
19 | mock.onGet('/my').reply(200, require('./user'))
20 | mock.onGet('/menu').reply(200, require('./menu'))
21 |
22 | export default mockAxios
23 |
--------------------------------------------------------------------------------
/examples/reactapp/src/webapi/mock/menu.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'code': 0,
3 | 'messages': [
4 | '成功'
5 | ],
6 | 'data': [
7 | {
8 | 'key': 0,
9 | 'title': 'Home',
10 | 'icon': 'home',
11 | 'type': 'Item',
12 | 'url': '/pages/home',
13 | 'children': []
14 | },
15 | {
16 | 'key': 1,
17 | 'title': 'Pages',
18 | 'icon': 'user',
19 | 'type': 'SubMenu',
20 | 'url': null,
21 | 'children': [
22 | {
23 | 'key': 11,
24 | 'title': 'Mailbox',
25 | 'icon': 'mail',
26 | 'type': 'Item',
27 | 'url': '/pages/mailbox',
28 | 'children': []
29 | },
30 | {
31 | 'key': 12,
32 | 'title': 'User',
33 | 'icon': 'user',
34 | 'type': 'Item',
35 | 'url': '/pages/user',
36 | 'children': []
37 | }
38 | ]
39 | },
40 | {
41 | 'key': 2,
42 | 'title': 'Others',
43 | 'icon': 'coffee',
44 | 'type': 'SubMenu',
45 | 'url': null,
46 | 'children': [
47 | {
48 | 'key': 21,
49 | 'title': 'Group1',
50 | 'icon': 'windows-o',
51 | 'type': 'ItemGroup',
52 | 'url': null,
53 | 'children': [
54 | {
55 | 'key': 22,
56 | 'title': 'Group1-1',
57 | 'icon': null,
58 | 'type': 'Item',
59 | 'url': '/pages/home',
60 | 'children': []
61 | }
62 | ]
63 | },
64 | {
65 | 'key': 23,
66 | 'title': 'Divider',
67 | 'icon': null,
68 | 'type': 'Divider',
69 | 'url': null,
70 | 'children': []
71 | },
72 | {
73 | 'key': 24,
74 | 'title': 'Group2',
75 | 'icon': 'apple-o',
76 | 'type': 'ItemGroup',
77 | 'url': null,
78 | 'children': [
79 | {
80 | 'key': 25,
81 | 'title': 'Group2-1',
82 | 'icon': null,
83 | 'type': 'Item',
84 | 'url': '/pages/home',
85 | 'children': []
86 | }
87 | ]
88 | }
89 | ]
90 | }
91 | ]
92 | }
93 |
--------------------------------------------------------------------------------
/examples/reactapp/src/webapi/mock/user.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | code: 0,
3 | messages: ['成功'],
4 | data: { uid: '1', role: 'ADMIN', name: 'admin' }
5 | }
6 |
--------------------------------------------------------------------------------
/examples/reactapp/src/webapi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webapi",
3 | "version": "0.0.0",
4 | "private": true,
5 | "main": "./webapi.js"
6 | }
7 |
--------------------------------------------------------------------------------
/examples/reactapp/src/webapi/webapi.js:
--------------------------------------------------------------------------------
1 | if (process.env.NODE_ENV === 'development') {
2 | module.exports = require('./mock').default
3 | } else {
4 | module.exports = require('../utils/http').default
5 | }
6 |
--------------------------------------------------------------------------------
/examples/scripts/build-javaapp.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | rem -------------------------------------------------
3 | rem 本脚本用于编译打包 JavaWebApp
4 | rem 环境要求:Maven + JDK8
5 | rem -------------------------------------------------
6 |
7 | pushd %~dp0..\javaapp
8 | call mvn clean package -Dmaven.test.skip=true
9 | popd
10 |
11 | pause
12 |
--------------------------------------------------------------------------------
/examples/scripts/build-reactadmin.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | rem -------------------------------------------------
3 | rem The script is use to package reactadmin
4 | rem Env: Nodejs 8.x
5 | rem -------------------------------------------------
6 |
7 | pushd %~dp0..\reactadmin
8 |
9 | echo ">>>> 1. Delete node_modules"
10 | rd /s /q node_modules
11 |
12 | echo ">>>> 2. npm install"
13 | rem 安装本地依赖
14 | call npm install
15 |
16 | echo ">>>> 3. npm run prod"
17 | rem 构建生产环境,构建的静态资源文件在 dist 目录
18 | call npm run build
19 |
20 | popd
21 |
22 | pause
23 |
--------------------------------------------------------------------------------
/examples/scripts/build-reactapp.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | rem -------------------------------------------------
3 | rem The script is use to package JavaWebApp
4 | rem Env: Nodejs 8.x
5 | rem -------------------------------------------------
6 |
7 | pushd %~dp0..\reactapp
8 |
9 | echo ">>>> 1. Delete node_modules"
10 | rd /s /q node_modules
11 |
12 | echo ">>>> 2. npm install"
13 | rem 安装本地依赖
14 | call npm install
15 |
16 | echo ">>>> 3. npm run prod"
17 | rem 构建生产环境,构建的静态资源文件在 dist 目录
18 | call npm run prod
19 |
20 | popd
21 |
22 | pause
23 |
--------------------------------------------------------------------------------
/examples/scripts/demo01-start.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | rem -------------------------------------------------
3 | rem 启动 Demo1
4 | rem 1. 启动 Nginx
5 | rem 2. 启动一个 JavaApp,访问地址为:localhost:9010
6 | rem -------------------------------------------------
7 |
8 | echo ">>>> 1. Start nginx"
9 | pushd %~dp0..\nginx-1.14.0
10 | call nginx-start.bat
11 | popd
12 |
13 | echo ">>>> 2. Start javaapp - localhost:9010"
14 | pushd %~dp0..\javaapp
15 | call java -Dtomcat.connector.port=9010 -cp "target/JavaWebApp/WEB-INF/classes;target/JavaWebApp/WEB-INF/lib/*" io.github.dunwu.Main
16 | popd
17 |
18 | pause
19 |
20 |
21 |
--------------------------------------------------------------------------------
/examples/scripts/demo02-start.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | rem -----------------------------------------------------------------------------
3 | rem Demo02 - 负载均衡配置(Nginx/demos/nginx-1.14.0/conf/demos/demo02.conf)
4 | rem 1. 启动 Nginx
5 | rem 2. 启动三个 JavaApp,访问地址分别为:
6 | rem localhost:9021
7 | rem localhost:9022
8 | rem localhost:9023
9 | rem -----------------------------------------------------------------------------
10 |
11 | echo ">>>> 1. Start nginx"
12 | pushd %~dp0..\nginx-1.14.0
13 | call nginx-start.bat
14 | popd
15 |
16 | echo ">>>> 2. Start 3 java app: localhost:9021, localhost:9022, localhost:9023"
17 | pushd %~dp0..\javaapp
18 | start /min java -Dtomcat.connector.port=9021 -cp "target/JavaWebApp/WEB-INF/classes;target/JavaWebApp/WEB-INF/lib/*" io.github.dunwu.Main
19 | start /min java -Dtomcat.connector.port=9022 -cp "target/JavaWebApp/WEB-INF/classes;target/JavaWebApp/WEB-INF/lib/*" io.github.dunwu.Main
20 | start /min java -Dtomcat.connector.port=9023 -cp "target/JavaWebApp/WEB-INF/classes;target/JavaWebApp/WEB-INF/lib/*" io.github.dunwu.Main
21 | popd
22 |
23 | pause
24 |
25 |
26 |
--------------------------------------------------------------------------------
/examples/scripts/demo03-start.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | rem -----------------------------------------------------------------------------
3 | rem Demo03 - 网站有多个 webapp 的配置(Nginx/demos/nginx-1.14.0/conf/demos/demo03.conf)
4 | rem 1. 启动 Nginx
5 | rem 2. 启动三个 JavaApp,访问地址分别为:
6 | rem localhost:9030/
7 | rem localhost:9031/product
8 | rem localhost:9032/user
9 | rem -----------------------------------------------------------------------------
10 |
11 | echo ">>>> 1. Start nginx"
12 | pushd %~dp0..\nginx-1.14.0
13 | call nginx-start.bat
14 | popd
15 |
16 | echo ">>>> 2. Start 3 java app: localhost:9030, localhost:9031/product, localhost:9032/user"
17 | pushd %~dp0..\javaapp
18 | start /min java -Dtomcat.connector.port=9030 -Dtomcat.context.path=/ -cp "target/JavaWebApp/WEB-INF/classes;target/JavaWebApp/WEB-INF/lib/*" io.github.dunwu.Main
19 | start /min java -Dtomcat.connector.port=9031 -Dtomcat.context.path=/product -cp "target/JavaWebApp/WEB-INF/classes;target/JavaWebApp/WEB-INF/lib/*" io.github.dunwu.Main
20 | start /min java -Dtomcat.connector.port=9032 -Dtomcat.context.path=/user -cp "target/JavaWebApp/WEB-INF/classes;target/JavaWebApp/WEB-INF/lib/*" io.github.dunwu.Main
21 | popd
22 |
23 | pause
24 |
25 |
--------------------------------------------------------------------------------
/examples/scripts/demo04-start.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | rem -----------------------------------------------------------------------------
3 | rem Demo04 - 动静分离
4 | rem 1. 启动 Nginx
5 | rem 2. 启动一个 JavaApp,访问地址分别为:
6 | rem localhost:9040
7 | rem -----------------------------------------------------------------------------
8 |
9 | echo ">>>> 1. Start nginx"
10 | pushd %~dp0..\nginx-1.14.0
11 | call nginx-start.bat
12 | popd
13 |
14 | echo ">>>> 2. Start 3 java app: localhost:9040"
15 | pushd %~dp0..\javaapp
16 | start /min java -Dtomcat.connector.port=9040 -cp "target/JavaWebApp/WEB-INF/classes;target/JavaWebApp/WEB-INF/lib/*" io.github.dunwu.Main
17 | popd
18 | pause
19 |
20 |
21 |
--------------------------------------------------------------------------------
/examples/scripts/demo05-start.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | rem -----------------------------------------------------------------------------
3 | rem Demo05 - 使用 Nginx 搭建文件服务器
4 | rem 1. 启动 Nginx
5 | rem 2. 访问地址:
6 | rem localhost:9050
7 | rem -----------------------------------------------------------------------------
8 |
9 | echo ">>>> 1. Start nginx"
10 | pushd %~dp0..\nginx-1.14.0
11 | call nginx-start.bat
12 | popd
13 |
14 |
15 |
--------------------------------------------------------------------------------
/examples/scripts/demo06-start.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | rem -----------------------------------------------------------------------------
3 | rem Demo06 - 使用 Nginx 访问静态站点
4 | rem 1. 启动 Nginx
5 | rem 2. 访问地址:
6 | rem www.demo06.com
7 | rem -----------------------------------------------------------------------------
8 |
9 | echo ">>>> 1. Start nginx"
10 | pushd %~dp0..\nginx-1.14.0
11 | call nginx-start.bat
12 | popd
13 |
14 |
15 |
--------------------------------------------------------------------------------
/examples/scripts/startup.sh:
--------------------------------------------------------------------------------
1 | nohup java -Dtomcat.context.path=/app -Dtomcat.connector.port=8091 -cp "./../target/JavaWebApp/WEB-INF/classes;./../target/JavaWebApp/WEB-INF/lib/*" https://github.com/dunwu > 'console.log' 2>&1 &
2 |
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://prettier.io/docs/en/options.html
3 | * @see https://prettier.io/docs/en/configuration.html
4 | */
5 | module.exports = {
6 | tabWidth: 2, semi: false, singleQuote: true
7 | }
8 |
--------------------------------------------------------------------------------