mirror of https://github.com/fatedier/frp
				
				
				
			
						commit
						da78e3f52e
					
				
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -1 +1 @@
 | 
			
		|||
<!DOCTYPE html> <html lang=en> <head> <meta charset=utf-8> <title>frps dashboard</title> <link rel="shortcut icon" href="favicon.ico"></head> <body> <div id=app></div> <script type="text/javascript" src="manifest.js?33af4addd27a494b40c1"></script><script type="text/javascript" src="vendor.js?c2d294f9c0a40fd7073a"></script><script type="text/javascript" src="index.js?a0da222d4e0f906bc057"></script></body> </html> 
 | 
			
		||||
<!DOCTYPE html> <html lang=en> <head> <meta charset=utf-8> <title>frps dashboard</title> <link rel="shortcut icon" href="favicon.ico"></head> <body> <div id=app></div> <script type="text/javascript" src="manifest.js?b90a32ccfb87def61aaa"></script><script type="text/javascript" src="vendor.js?f04985ef00f520142368"></script></body> </html> 
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -1 +1 @@
 | 
			
		|||
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,a){for(var u,i,f,l=0,s=[];l<t.length;l++)i=t[l],o[i]&&s.push(o[i][0]),o[i]=0;for(u in c)Object.prototype.hasOwnProperty.call(c,u)&&(e[u]=c[u]);for(r&&r(t,c,a);s.length;)s.shift()();if(a)for(l=0;l<a.length;l++)f=n(n.s=a[l]);return f};var t={},o={2:0};n.e=function(e){function r(){u.onerror=u.onload=null,clearTimeout(i);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var a=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,n.nc&&u.setAttribute("nonce",n.nc),u.src=n.p+""+e+".js?"+{0:"a0da222d4e0f906bc057",1:"c2d294f9c0a40fd7073a"}[e];var i=setTimeout(r,12e4);return u.onerror=u.onload=r,a.appendChild(u),c},n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="",n.oe=function(e){throw console.error(e),e}}([]);
 | 
			
		||||
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,u,c){for(var i,a,f,l=0,s=[];l<t.length;l++)a=t[l],o[a]&&s.push(o[a][0]),o[a]=0;for(i in u)Object.prototype.hasOwnProperty.call(u,i)&&(e[i]=u[i]);for(r&&r(t,u,c);s.length;)s.shift()();if(c)for(l=0;l<c.length;l++)f=n(n.s=c[l]);return f};var t={},o={1:0};n.e=function(e){function r(){i.onerror=i.onload=null,clearTimeout(a);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var u=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=u;var c=document.getElementsByTagName("head")[0],i=document.createElement("script");i.type="text/javascript",i.charset="utf-8",i.async=!0,i.timeout=12e4,n.nc&&i.setAttribute("nonce",n.nc),i.src=n.p+""+e+".js?"+{0:"f04985ef00f520142368"}[e];var a=setTimeout(r,12e4);return i.onerror=i.onload=r,c.appendChild(i),u},n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="",n.oe=function(e){throw console.error(e),e}}([]);
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -272,6 +272,12 @@ func (pxy *XtcpProxy) InWorkConn(conn frpNet.Conn) {
 | 
			
		|||
	}
 | 
			
		||||
	clientConn.SetReadDeadline(time.Time{})
 | 
			
		||||
	clientConn.Close()
 | 
			
		||||
 | 
			
		||||
	if natHoleRespMsg.Error != "" {
 | 
			
		||||
		pxy.Error("natHoleRespMsg get error info: %s", natHoleRespMsg.Error)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pxy.Trace("get natHoleRespMsg, sid [%s], client address [%s]", natHoleRespMsg.Sid, natHoleRespMsg.ClientAddr)
 | 
			
		||||
 | 
			
		||||
	// Send sid to visitor udp address.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -235,6 +235,11 @@ func (sv *XtcpVisitor) handleConn(userConn frpNet.Conn) {
 | 
			
		|||
	visitorConn.SetReadDeadline(time.Time{})
 | 
			
		||||
	pool.PutBuf(buf)
 | 
			
		||||
 | 
			
		||||
	if natHoleRespMsg.Error != "" {
 | 
			
		||||
		sv.Error("natHoleRespMsg get error info: %s", natHoleRespMsg.Error)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sv.Trace("get natHoleRespMsg, sid [%s], client address [%s]", natHoleRespMsg.Sid, natHoleRespMsg.ClientAddr)
 | 
			
		||||
 | 
			
		||||
	// Close visitorConn, so we can use it's local address.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,6 +69,7 @@ var (
 | 
			
		|||
	sk                string
 | 
			
		||||
	serverName        string
 | 
			
		||||
	bindAddr          string
 | 
			
		||||
	bindPort          int
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,6 +40,7 @@ func init() {
 | 
			
		|||
	stcpCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip")
 | 
			
		||||
	stcpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port")
 | 
			
		||||
	stcpCmd.PersistentFlags().StringVarP(&bindAddr, "bind_addr", "", "", "bind addr")
 | 
			
		||||
	stcpCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "", 0, "bind port")
 | 
			
		||||
	stcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
 | 
			
		||||
	stcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -69,6 +70,7 @@ var stcpCmd = &cobra.Command{
 | 
			
		|||
		cfg.LocalIp = localIp
 | 
			
		||||
		cfg.LocalPort = localPort
 | 
			
		||||
		cfg.BindAddr = bindAddr
 | 
			
		||||
		cfg.BindPort = bindPort
 | 
			
		||||
		cfg.UseEncryption = useEncryption
 | 
			
		||||
		cfg.UseCompression = useCompression
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,6 +40,7 @@ func init() {
 | 
			
		|||
	xtcpCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip")
 | 
			
		||||
	xtcpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port")
 | 
			
		||||
	xtcpCmd.PersistentFlags().StringVarP(&bindAddr, "bind_addr", "", "", "bind addr")
 | 
			
		||||
	xtcpCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "", 0, "bind port")
 | 
			
		||||
	xtcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
 | 
			
		||||
	xtcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -69,6 +70,7 @@ var xtcpCmd = &cobra.Command{
 | 
			
		|||
		cfg.LocalIp = localIp
 | 
			
		||||
		cfg.LocalPort = localPort
 | 
			
		||||
		cfg.BindAddr = bindAddr
 | 
			
		||||
		cfg.BindPort = bindPort
 | 
			
		||||
		cfg.UseEncryption = useEncryption
 | 
			
		||||
		cfg.UseCompression = useCompression
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -81,7 +81,7 @@ func init() {
 | 
			
		|||
	rootCmd.PersistentFlags().StringVarP(&logWay, "log_way", "", "console", "log way")
 | 
			
		||||
	rootCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level")
 | 
			
		||||
	rootCmd.PersistentFlags().Int64VarP(&logMaxDays, "log_max_days", "", 3, "log_max_days")
 | 
			
		||||
	rootCmd.PersistentFlags().StringVarP(&token, "token", "", "", "auth token")
 | 
			
		||||
	rootCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token")
 | 
			
		||||
	rootCmd.PersistentFlags().Int64VarP(&authTimeout, "auth_timeout", "", 900, "auth timeout")
 | 
			
		||||
	rootCmd.PersistentFlags().StringVarP(&subDomainHost, "subdomain_host", "", "", "subdomain host")
 | 
			
		||||
	rootCmd.PersistentFlags().Int64VarP(&maxPortsPerClient, "max_ports_per_client", "", 0, "max ports per client")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -262,7 +262,7 @@ func (cfg *DomainConf) checkForSvr() (err error) {
 | 
			
		|||
 | 
			
		||||
	if cfg.SubDomain != "" {
 | 
			
		||||
		if subDomainHost == "" {
 | 
			
		||||
			return fmt.Errorf("subdomain is not supported because this feature is not enabled by frps")
 | 
			
		||||
			return fmt.Errorf("subdomain is not supported because this feature is not enabled in remote frps")
 | 
			
		||||
		}
 | 
			
		||||
		if strings.Contains(cfg.SubDomain, ".") || strings.Contains(cfg.SubDomain, "*") {
 | 
			
		||||
			return fmt.Errorf("'.' and '*' is not supported in subdomain")
 | 
			
		||||
| 
						 | 
				
			
			@ -509,7 +509,7 @@ func (cfg *HttpProxyConf) CheckForCli() (err error) {
 | 
			
		|||
 | 
			
		||||
func (cfg *HttpProxyConf) CheckForSvr() (err error) {
 | 
			
		||||
	if vhostHttpPort == 0 {
 | 
			
		||||
		err = fmt.Errorf("type [http] not support when vhost_http_port is not set")
 | 
			
		||||
		return fmt.Errorf("type [http] not support when vhost_http_port is not set")
 | 
			
		||||
	}
 | 
			
		||||
	if err = cfg.DomainConf.checkForSvr(); err != nil {
 | 
			
		||||
		err = fmt.Errorf("proxy [%s] domain conf check error: %v", cfg.ProxyName, err)
 | 
			
		||||
| 
						 | 
				
			
			@ -675,6 +675,10 @@ func (cfg *StcpProxyConf) CheckForCli() (err error) {
 | 
			
		|||
			err = fmt.Errorf("bind_addr shouldn't be empty")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if cfg.BindPort == 0 {
 | 
			
		||||
			err = fmt.Errorf("bind_port should be set")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -777,6 +781,10 @@ func (cfg *XtcpProxyConf) CheckForCli() (err error) {
 | 
			
		|||
			err = fmt.Errorf("bind_addr shouldn't be empty")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if cfg.BindPort == 0 {
 | 
			
		||||
			err = fmt.Errorf("bind_port should be set")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -163,6 +163,7 @@ type NatHoleResp struct {
 | 
			
		|||
	Sid         string `json:"sid"`
 | 
			
		||||
	VisitorAddr string `json:"visitor_addr"`
 | 
			
		||||
	ClientAddr  string `json:"client_addr"`
 | 
			
		||||
	Error       string `json:"error"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NatHoleSid struct {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -106,10 +106,21 @@ func (nc *NatHoleController) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDP
 | 
			
		|||
	}
 | 
			
		||||
	nc.mu.Lock()
 | 
			
		||||
	clientCfg, ok := nc.clientCfgs[m.ProxyName]
 | 
			
		||||
	if !ok || m.SignKey != util.GetAuthKey(clientCfg.Sk, m.Timestamp) {
 | 
			
		||||
	if !ok {
 | 
			
		||||
		nc.mu.Unlock()
 | 
			
		||||
		errInfo := fmt.Sprintf("xtcp server for [%s] doesn't exist", m.ProxyName)
 | 
			
		||||
		log.Debug(errInfo)
 | 
			
		||||
		nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if m.SignKey != util.GetAuthKey(clientCfg.Sk, m.Timestamp) {
 | 
			
		||||
		nc.mu.Unlock()
 | 
			
		||||
		errInfo := fmt.Sprintf("xtcp connection of [%s] auth failed", m.ProxyName)
 | 
			
		||||
		log.Debug(errInfo)
 | 
			
		||||
		nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	nc.sessions[sid] = session
 | 
			
		||||
	nc.mu.Unlock()
 | 
			
		||||
	log.Trace("handle visitor message, sid [%s]", sid)
 | 
			
		||||
| 
						 | 
				
			
			@ -130,7 +141,7 @@ func (nc *NatHoleController) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDP
 | 
			
		|||
	// Wait client connections.
 | 
			
		||||
	select {
 | 
			
		||||
	case <-session.NotifyCh:
 | 
			
		||||
		resp := nc.GenNatHoleResponse(raddr, session)
 | 
			
		||||
		resp := nc.GenNatHoleResponse(session, "")
 | 
			
		||||
		log.Trace("send nat hole response to visitor")
 | 
			
		||||
		nc.listener.WriteToUDP(resp, raddr)
 | 
			
		||||
	case <-time.After(time.Duration(NatHoleTimeout) * time.Second):
 | 
			
		||||
| 
						 | 
				
			
			@ -149,16 +160,27 @@ func (nc *NatHoleController) HandleClient(m *msg.NatHoleClient, raddr *net.UDPAd
 | 
			
		|||
	session.ClientAddr = raddr
 | 
			
		||||
	session.NotifyCh <- struct{}{}
 | 
			
		||||
 | 
			
		||||
	resp := nc.GenNatHoleResponse(raddr, session)
 | 
			
		||||
	resp := nc.GenNatHoleResponse(session, "")
 | 
			
		||||
	log.Trace("send nat hole response to client")
 | 
			
		||||
	nc.listener.WriteToUDP(resp, raddr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (nc *NatHoleController) GenNatHoleResponse(raddr *net.UDPAddr, session *NatHoleSession) []byte {
 | 
			
		||||
func (nc *NatHoleController) GenNatHoleResponse(session *NatHoleSession, errInfo string) []byte {
 | 
			
		||||
	var (
 | 
			
		||||
		sid         string
 | 
			
		||||
		visitorAddr string
 | 
			
		||||
		clientAddr  string
 | 
			
		||||
	)
 | 
			
		||||
	if session != nil {
 | 
			
		||||
		sid = session.Sid
 | 
			
		||||
		visitorAddr = session.VisitorAddr.String()
 | 
			
		||||
		clientAddr = session.ClientAddr.String()
 | 
			
		||||
	}
 | 
			
		||||
	m := &msg.NatHoleResp{
 | 
			
		||||
		Sid:         session.Sid,
 | 
			
		||||
		VisitorAddr: session.VisitorAddr.String(),
 | 
			
		||||
		ClientAddr:  session.ClientAddr.String(),
 | 
			
		||||
		Sid:         sid,
 | 
			
		||||
		VisitorAddr: visitorAddr,
 | 
			
		||||
		ClientAddr:  clientAddr,
 | 
			
		||||
		Error:       errInfo,
 | 
			
		||||
	}
 | 
			
		||||
	b := bytes.NewBuffer(nil)
 | 
			
		||||
	err := msg.WriteMsg(b, m)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var version string = "0.19.0"
 | 
			
		||||
var version string = "0.19.1"
 | 
			
		||||
 | 
			
		||||
func Full() string {
 | 
			
		||||
	return version
 | 
			
		||||
| 
						 | 
				
			
			@ -48,8 +48,8 @@ func Minor(v string) int64 {
 | 
			
		|||
 | 
			
		||||
// add every case there if server will not accept client's protocol and return false
 | 
			
		||||
func Compat(client string) (ok bool, msg string) {
 | 
			
		||||
	if LessThan(client, "0.10.0") {
 | 
			
		||||
		return false, "Please upgrade your frpc version to at least 0.10.0"
 | 
			
		||||
	if LessThan(client, "0.18.0") {
 | 
			
		||||
		return false, "Please upgrade your frpc version to at least 0.18.0"
 | 
			
		||||
	}
 | 
			
		||||
	return true, ""
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,5 +61,5 @@ func TestCompact(t *testing.T) {
 | 
			
		|||
	assert.True(ok)
 | 
			
		||||
 | 
			
		||||
	ok, _ = Compat("0.10.0")
 | 
			
		||||
	assert.True(ok)
 | 
			
		||||
	assert.False(ok)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,7 +49,6 @@ func getHostFromAddr(addr string) (host string) {
 | 
			
		|||
 | 
			
		||||
type HttpReverseProxy struct {
 | 
			
		||||
	proxy *ReverseProxy
 | 
			
		||||
	tr    *http.Transport
 | 
			
		||||
 | 
			
		||||
	vhostRouter *VhostRouters
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,14 @@
 | 
			
		|||
{
 | 
			
		||||
    "presets": [
 | 
			
		||||
        ["es2015", { "modules": false }]
 | 
			
		||||
    ],
 | 
			
		||||
    "plugins": [
 | 
			
		||||
        [
 | 
			
		||||
            "component",
 | 
			
		||||
            {
 | 
			
		||||
                "libraryName": "element-ui",
 | 
			
		||||
                "styleLibraryName": "theme-chalk"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -10,9 +10,9 @@
 | 
			
		|||
  "dependencies": {
 | 
			
		||||
    "bootstrap": "^3.3.7",
 | 
			
		||||
    "echarts": "^3.5.0",
 | 
			
		||||
    "element-ui": "^1.2.5",
 | 
			
		||||
    "element-ui": "^2.3.8",
 | 
			
		||||
    "humanize-plus": "^1.8.2",
 | 
			
		||||
    "vue": "^2.2.4",
 | 
			
		||||
    "vue": "^2.5.16",
 | 
			
		||||
    "vue-resource": "^1.2.1",
 | 
			
		||||
    "vue-router": "^2.3.0",
 | 
			
		||||
    "whatwg-fetch": "^2.0.3"
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +25,7 @@
 | 
			
		|||
    "babel-core": "^6.21.0",
 | 
			
		||||
    "babel-eslint": "^7.1.1",
 | 
			
		||||
    "babel-loader": "^6.4.0",
 | 
			
		||||
    "babel-plugin-component": "^1.1.1",
 | 
			
		||||
    "babel-preset-es2015": "^6.13.2",
 | 
			
		||||
    "css-loader": "^0.27.0",
 | 
			
		||||
    "eslint": "^3.12.2",
 | 
			
		||||
| 
						 | 
				
			
			@ -33,15 +34,15 @@
 | 
			
		|||
    "file-loader": "^0.10.1",
 | 
			
		||||
    "html-loader": "^0.4.5",
 | 
			
		||||
    "html-webpack-plugin": "^2.24.1",
 | 
			
		||||
    "less": "^2.7.2",
 | 
			
		||||
    "less-loader": "^3.0.0",
 | 
			
		||||
    "less": "^3.0.4",
 | 
			
		||||
    "less-loader": "^4.1.0",
 | 
			
		||||
    "postcss-loader": "^1.3.3",
 | 
			
		||||
    "rimraf": "^2.5.4",
 | 
			
		||||
    "style-loader": "^0.13.2",
 | 
			
		||||
    "url-loader": "^0.5.8",
 | 
			
		||||
    "vue-loader": "^11.1.4",
 | 
			
		||||
    "url-loader": "^1.0.1",
 | 
			
		||||
    "vue-loader": "^15.0.10",
 | 
			
		||||
    "vue-template-compiler": "^2.1.8",
 | 
			
		||||
    "webpack": "^2.2.0-rc.4",
 | 
			
		||||
    "webpack-dev-server": "^2.11.0"
 | 
			
		||||
    "webpack-dev-server": "^3.1.4"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
  <div>
 | 
			
		||||
    <el-table :data="proxies" :default-sort="{prop: 'name', order: 'ascending'}" style="width: 100%">
 | 
			
		||||
      <el-table-column type="expand">
 | 
			
		||||
        <template scope="props">
 | 
			
		||||
        <template slot-scope="props">
 | 
			
		||||
          <el-popover
 | 
			
		||||
            ref="popover4"
 | 
			
		||||
            placement="right"
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +79,7 @@
 | 
			
		|||
      label="status"
 | 
			
		||||
      prop="status"
 | 
			
		||||
      sortable>
 | 
			
		||||
      <template scope="scope">
 | 
			
		||||
      <template slot-scope="scope">
 | 
			
		||||
        <el-tag type="success" v-if="scope.row.status === 'online'">{{ scope.row.status }}</el-tag>
 | 
			
		||||
        <el-tag type="danger" v-else>{{ scope.row.status }}</el-tag>
 | 
			
		||||
      </template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
  <div>
 | 
			
		||||
    <el-table :data="proxies" :default-sort="{prop: 'name', order: 'ascending'}" style="width: 100%">
 | 
			
		||||
      <el-table-column type="expand">
 | 
			
		||||
        <template scope="props">
 | 
			
		||||
        <template slot-scope="props">
 | 
			
		||||
          <el-popover
 | 
			
		||||
            ref="popover4"
 | 
			
		||||
            placement="right"
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +73,7 @@
 | 
			
		|||
      label="status"
 | 
			
		||||
      prop="status"
 | 
			
		||||
      sortable>
 | 
			
		||||
      <template scope="scope">
 | 
			
		||||
      <template slot-scope="scope">
 | 
			
		||||
        <el-tag type="success" v-if="scope.row.status === 'online'">{{ scope.row.status }}</el-tag>
 | 
			
		||||
        <el-tag type="danger" v-else>{{ scope.row.status }}</el-tag>
 | 
			
		||||
      </template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
  <div>
 | 
			
		||||
    <el-table :data="proxies" :default-sort="{prop: 'name', order: 'ascending'}" style="width: 100%">
 | 
			
		||||
      <el-table-column type="expand">
 | 
			
		||||
        <template scope="props">
 | 
			
		||||
        <template slot-scope="props">
 | 
			
		||||
          <el-popover
 | 
			
		||||
            ref="popover4"
 | 
			
		||||
            placement="right"
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +70,7 @@
 | 
			
		|||
      label="status"
 | 
			
		||||
      prop="status"
 | 
			
		||||
      sortable>
 | 
			
		||||
      <template scope="scope">
 | 
			
		||||
      <template slot-scope="scope">
 | 
			
		||||
        <el-tag type="success" v-if="scope.row.status === 'online'">{{ scope.row.status }}</el-tag>
 | 
			
		||||
        <el-tag type="danger" v-else>{{ scope.row.status }}</el-tag>
 | 
			
		||||
      </template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
  <div>
 | 
			
		||||
    <el-table :data="proxies" :default-sort="{prop: 'name', order: 'ascending'}" style="width: 100%">
 | 
			
		||||
      <el-table-column type="expand">
 | 
			
		||||
        <template scope="props">
 | 
			
		||||
        <template slot-scope="props">
 | 
			
		||||
          <el-popover
 | 
			
		||||
            ref="popover4"
 | 
			
		||||
            placement="right"
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +70,7 @@
 | 
			
		|||
      label="status"
 | 
			
		||||
      prop="status"
 | 
			
		||||
      sortable>
 | 
			
		||||
      <template scope="scope">
 | 
			
		||||
      <template slot-scope="scope">
 | 
			
		||||
        <el-tag type="success" v-if="scope.row.status === 'online'">{{ scope.row.status }}</el-tag>
 | 
			
		||||
        <el-tag type="danger" v-else>{{ scope.row.status }}</el-tag>
 | 
			
		||||
      </template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,14 +1,43 @@
 | 
			
		|||
import Vue from 'vue'
 | 
			
		||||
import ElementUI from 'element-ui'
 | 
			
		||||
import locale from 'element-ui/lib/locale/lang/en'
 | 
			
		||||
import 'element-ui/lib/theme-default/index.css'
 | 
			
		||||
//import ElementUI from 'element-ui'
 | 
			
		||||
import {
 | 
			
		||||
    Button,
 | 
			
		||||
    Form,
 | 
			
		||||
    FormItem,
 | 
			
		||||
    Row,
 | 
			
		||||
    Col,
 | 
			
		||||
    Table,
 | 
			
		||||
    TableColumn,
 | 
			
		||||
    Popover,
 | 
			
		||||
    Menu,
 | 
			
		||||
    Submenu,
 | 
			
		||||
    MenuItem,
 | 
			
		||||
    Tag
 | 
			
		||||
} from 'element-ui'
 | 
			
		||||
import lang from 'element-ui/lib/locale/lang/en'
 | 
			
		||||
import locale from 'element-ui/lib/locale'
 | 
			
		||||
import 'element-ui/lib/theme-chalk/index.css'
 | 
			
		||||
import './utils/less/custom.less'
 | 
			
		||||
 | 
			
		||||
import App from './App.vue'
 | 
			
		||||
import router from './router'
 | 
			
		||||
import 'whatwg-fetch'
 | 
			
		||||
 | 
			
		||||
Vue.use(ElementUI, { locale })
 | 
			
		||||
locale.use(lang)
 | 
			
		||||
 | 
			
		||||
Vue.use(Button)
 | 
			
		||||
Vue.use(Form)
 | 
			
		||||
Vue.use(FormItem)
 | 
			
		||||
Vue.use(Row)
 | 
			
		||||
Vue.use(Col)
 | 
			
		||||
Vue.use(Table)
 | 
			
		||||
Vue.use(TableColumn)
 | 
			
		||||
Vue.use(Popover)
 | 
			
		||||
Vue.use(Menu)
 | 
			
		||||
Vue.use(Submenu)
 | 
			
		||||
Vue.use(MenuItem)
 | 
			
		||||
Vue.use(Tag)
 | 
			
		||||
 | 
			
		||||
Vue.config.productionTip = false
 | 
			
		||||
 | 
			
		||||
new Vue({
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
import Vue from 'vue'
 | 
			
		||||
import ElementUI from 'element-ui'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,13 +1,13 @@
 | 
			
		|||
const path = require('path')
 | 
			
		||||
var webpack = require('webpack')
 | 
			
		||||
var HtmlWebpackPlugin = require('html-webpack-plugin')
 | 
			
		||||
var VueLoaderPlugin = require('vue-loader/lib/plugin')
 | 
			
		||||
var url = require('url')
 | 
			
		||||
var publicPath = ''
 | 
			
		||||
 | 
			
		||||
module.exports = (options = {}) => ({
 | 
			
		||||
    entry: {
 | 
			
		||||
        vendor: './src/vendor',
 | 
			
		||||
        index: './src/main.js'
 | 
			
		||||
        vendor: './src/main'
 | 
			
		||||
    },
 | 
			
		||||
    output: {
 | 
			
		||||
        path: path.resolve(__dirname, 'dist'),
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ module.exports = (options = {}) => ({
 | 
			
		|||
    module: {
 | 
			
		||||
        rules: [{
 | 
			
		||||
            test: /\.vue$/,
 | 
			
		||||
            use: ['vue-loader']
 | 
			
		||||
            loader: 'vue-loader'
 | 
			
		||||
        }, {
 | 
			
		||||
            test: /\.js$/,
 | 
			
		||||
            use: ['babel-loader'],
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +71,21 @@ module.exports = (options = {}) => ({
 | 
			
		|||
        new HtmlWebpackPlugin({
 | 
			
		||||
            favicon: 'src/assets/favicon.ico',
 | 
			
		||||
            template: 'src/index.html'
 | 
			
		||||
        })
 | 
			
		||||
        }),
 | 
			
		||||
        new webpack.NormalModuleReplacementPlugin(/element-ui[\/\\]lib[\/\\]locale[\/\\]lang[\/\\]zh-CN/, 'element-ui/lib/locale/lang/en'),
 | 
			
		||||
        new webpack.DefinePlugin({
 | 
			
		||||
            'process.env': {
 | 
			
		||||
                NODE_ENV: '"production"'
 | 
			
		||||
            }
 | 
			
		||||
        }),
 | 
			
		||||
        new webpack.optimize.UglifyJsPlugin({
 | 
			
		||||
            sourceMap: false,
 | 
			
		||||
            comments: false,
 | 
			
		||||
            compress: {
 | 
			
		||||
                warnings: false
 | 
			
		||||
            }
 | 
			
		||||
        }),
 | 
			
		||||
        new VueLoaderPlugin()
 | 
			
		||||
    ],
 | 
			
		||||
    devServer: {
 | 
			
		||||
        host: '127.0.0.1',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue