diff --git a/README.md b/README.md index 896c4462..99656ad6 100644 --- a/README.md +++ b/README.md @@ -311,6 +311,7 @@ Enter the user ID in input field number 4. The Telegram accounts with this id wi | `POST` | `"/resetAllTraffics"` | Reset traffics of all inbounds | | `POST` | `"/resetAllClientTraffics/:id"` | Reset traffics of all clients in an inbound | | `POST` | `"/delDepletedClients/:id"` | Delete inbound depleted clients (-1: all) | +| `POST` | `"/onlines"` | Get Online users ( list of emails ) | \*- The field `clientId` should be filled by: @@ -318,7 +319,9 @@ Enter the user ID in input field number 4. The Telegram accounts with this id wi - `client.password` for TROJAN - `client.email` for Shadowsocks -- [Postman Collection](https://gist.github.com/mehdikhody/9a862801a2e41f6b5fb6bbc7e1326044) + +- [API Documentation](https://documenter.getpostman.com/view/16802678/2s9YkgD5jm) +- [Run In Postman](https://app.getpostman.com/run-collection/16802678-1a4c9270-ac77-40ed-959a-7aa56dc4a415?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D16802678-1a4c9270-ac77-40ed-959a-7aa56dc4a415%26entityType%3Dcollection%26workspaceId%3D2cd38c01-c851-4a15-a972-f181c23359d9) # Environment Variables diff --git a/database/db.go b/database/db.go index aaeb8bd9..8bd0fb49 100644 --- a/database/db.go +++ b/database/db.go @@ -112,3 +112,12 @@ func IsSQLiteDB(file io.ReaderAt) (bool, error) { } return bytes.Equal(buf, signature), nil } + +func Checkpoint() error { + // Update WAL + err := db.Exec("PRAGMA wal_checkpoint;").Error + if err != nil { + return err + } + return nil +} diff --git a/database/model/model.go b/database/model/model.go index 087e8b07..c9f9c105 100644 --- a/database/model/model.go +++ b/database/model/model.go @@ -83,4 +83,5 @@ type Client struct { Enable bool `json:"enable" form:"enable"` TgID string `json:"tgId" form:"tgId"` SubID string `json:"subId" form:"subId"` + Reset int `json:"reset" form:"reset"` } diff --git a/docker-compose.yml b/docker-compose.yml index d1399a9b..b0a89399 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,5 @@ --- -version: "3.8" +version: "3" services: 3x-ui: diff --git a/go.mod b/go.mod index 9f4464b0..02c8802c 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21.4 require ( github.com/Calidity/gin-sessions v1.3.1 - github.com/Workiva/go-datastructures v1.1.1 + github.com/gin-contrib/gzip v0.0.6 github.com/gin-gonic/gin v1.9.1 github.com/goccy/go-json v0.10.2 github.com/mymmrac/telego v0.28.0 @@ -50,7 +50,6 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.17.2 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect - github.com/kr/text v0.2.0 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect github.com/mattn/go-isatty v0.0.19 // indirect diff --git a/go.sum b/go.sum index 1ee1a56c..c1a2c5aa 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,6 @@ github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8 github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/Calidity/gin-sessions v1.3.1 h1:nF3dCBWa7TZ4j26iYLwGRmzZy9YODhWoOS3fmi+snyE= github.com/Calidity/gin-sessions v1.3.1/go.mod h1:I0+QE6qkO50TeN/n6If6novvxHk4Isvr23U8EdvPdns= -github.com/Workiva/go-datastructures v1.1.1 h1:9G5u1UqKt6ABseAffHGNfbNQd7omRlWE5QaxNruzhE0= -github.com/Workiva/go-datastructures v1.1.1/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= @@ -56,8 +54,11 @@ github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67d github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4= github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= +github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= +github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= @@ -67,16 +68,21 @@ github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4 github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -137,6 +143,8 @@ github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/4 github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -144,6 +152,7 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= @@ -151,6 +160,7 @@ github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0g github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= @@ -180,11 +190,12 @@ github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWEr github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs= github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -205,6 +216,8 @@ github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -261,14 +274,14 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI= @@ -288,7 +301,7 @@ github.com/xtls/reality v0.0.0-20231112171332-de1173cf2b19 h1:capMfFYRgH9BCLd6A3 github.com/xtls/reality v0.0.0-20231112171332-de1173cf2b19/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE= github.com/xtls/xray-core v1.8.6 h1:tr3nk/fZnFfCsmgZv7B3RC72N5qUC88oMGVLlybDey8= github.com/xtls/xray-core v1.8.6/go.mod h1:hj2EB8rtcLdlTC8zxiWm5xL+C0k2Aie9Pk0mXtDEP6U= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= + github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= @@ -306,8 +319,7 @@ golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+ golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= + golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -316,7 +328,7 @@ golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUU golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= + golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -327,9 +339,8 @@ golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= + golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -342,7 +353,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= + golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -350,11 +361,9 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -366,6 +375,7 @@ golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= + golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -378,13 +388,11 @@ golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= + golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wireguard v0.0.0-20231022001213-2e0774f246fb h1:c5tyN8sSp8jSDxdCCDXVOpJwYXXhmTkNMt+g0zTSOic= @@ -411,11 +419,14 @@ google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -423,6 +434,7 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/sqlite v1.5.4 h1:IqXwXi8M/ZlPzH/947tn5uik3aYQslP9BVveoax0nV0= diff --git a/logger/logger.go b/logger/logger.go index 6e824c78..a1386b05 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -26,17 +26,15 @@ func InitLogger(level logging.Level) { var format logging.Formatter ppid := os.Getppid() - if ppid == 1 { - backend, err = logging.NewSyslogBackend("") - format = logging.MustStringFormatter( - `%{level} - %{message}`, - ) - } - if err != nil || ppid != 1 { + backend, err = logging.NewSyslogBackend("") + if err != nil { + println(err) backend = logging.NewLogBackend(os.Stderr, "", 0) - format = logging.MustStringFormatter( - `%{time:2006/01/02 15:04:05} %{level} - %{message}`, - ) + } + if ppid > 0 && err != nil { + format = logging.MustStringFormatter(`%{time:2006/01/02 15:04:05} %{level} - %{message}`) + } else { + format = logging.MustStringFormatter(`%{level} - %{message}`) } backendFormatter := logging.NewBackendFormatter(backend, format) diff --git a/sub/subService.go b/sub/subService.go index 4cb14030..251ef2e8 100644 --- a/sub/subService.go +++ b/sub/subService.go @@ -19,8 +19,9 @@ import ( type SubService struct { address string showInfo bool + remarkModel string inboundService service.InboundService - settingServics service.SettingService + settingService service.SettingService } func (s *SubService) GetSubs(subId string, host string, showInfo bool) ([]string, []string, error) { @@ -34,6 +35,10 @@ func (s *SubService) GetSubs(subId string, host string, showInfo bool) ([]string if err != nil { return nil, nil, err } + s.remarkModel, err = s.settingService.GetRemarkModel() + if err != nil { + s.remarkModel = "-ieo" + } for _, inbound := range inbounds { clients, err := s.inboundService.GetClients(inbound) if err != nil { @@ -53,6 +58,7 @@ func (s *SubService) GetSubs(subId string, host string, showInfo bool) ([]string json.Unmarshal([]byte(fallbackMaster.StreamSettings), &masterStream) stream["security"] = masterStream["security"] stream["tlsSettings"] = masterStream["tlsSettings"] + stream["externalProxy"] = masterStream["externalProxy"] modifiedStream, _ := json.MarshalIndent(stream, "", " ") inbound.StreamSettings = string(modifiedStream) } @@ -87,7 +93,7 @@ func (s *SubService) GetSubs(subId string, host string, showInfo bool) ([]string } } headers = append(headers, fmt.Sprintf("upload=%d; download=%d; total=%d; expire=%d", traffic.Up, traffic.Down, traffic.Total, traffic.ExpiryTime/1000)) - updateInterval, _ := s.settingServics.GetSubUpdates() + updateInterval, _ := s.settingService.GetSubUpdates() headers = append(headers, fmt.Sprintf("%d", updateInterval)) headers = append(headers, subId) return result, headers, nil @@ -96,7 +102,14 @@ func (s *SubService) GetSubs(subId string, host string, showInfo bool) ([]string func (s *SubService) getInboundsBySubId(subId string) ([]*model.Inbound, error) { db := database.GetDB() var inbounds []*model.Inbound - err := db.Model(model.Inbound{}).Preload("ClientStats").Where("settings like ? and enable = ?", fmt.Sprintf(`%%"subId": "%s"%%`, subId), true).Find(&inbounds).Error + err := db.Model(model.Inbound{}).Preload("ClientStats").Where(`id in ( + SELECT DISTINCT inbounds.id + FROM inbounds, + JSON_EACH(JSON_EXTRACT(inbounds.settings, '$.clients')) AS client + WHERE + protocol in ('vmess','vless','trojan','shadowsocks') + AND JSON_EXTRACT(client.value, '$.subId') = ? AND enable = ? + )`, subId, true).Find(&inbounds).Error if err != nil { return nil, err } @@ -196,7 +209,6 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string { } security, _ := stream["security"].(string) - var domains []interface{} obj["tls"] = security if security == "tls" { tlsSetting, _ := stream["tlsSettings"].(map[string]interface{}) @@ -208,24 +220,18 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string { } obj["alpn"] = strings.Join(alpn, ",") } + if sniValue, ok := searchKey(tlsSetting, "serverName"); ok { + obj["sni"], _ = sniValue.(string) + } + tlsSettings, _ := searchKey(tlsSetting, "settings") if tlsSetting != nil { - if sniValue, ok := searchKey(tlsSettings, "serverName"); ok { - obj["sni"], _ = sniValue.(string) - } if fpValue, ok := searchKey(tlsSettings, "fingerprint"); ok { obj["fp"], _ = fpValue.(string) } if insecure, ok := searchKey(tlsSettings, "allowInsecure"); ok { obj["allowInsecure"], _ = insecure.(bool) } - if domainSettings, ok := searchKey(tlsSettings, "domains"); ok { - domains, _ = domainSettings.([]interface{}) - } - } - serverName, _ := tlsSetting["serverName"].(string) - if serverName != "" { - obj["add"] = serverName } } @@ -239,16 +245,30 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string { } obj["id"] = clients[clientIndex].ID - if len(domains) > 0 { + externalProxies, _ := stream["externalProxy"].([]interface{}) + + if len(externalProxies) > 0 { links := "" - for index, d := range domains { - domain := d.(map[string]interface{}) - obj["ps"] = s.genRemark(inbound, email, domain["remark"].(string)) - obj["add"] = domain["domain"].(string) + for index, externalProxy := range externalProxies { + ep, _ := externalProxy.(map[string]interface{}) + newSecurity, _ := ep["forceTls"].(string) + newObj := map[string]interface{}{} + for key, value := range obj { + if !(newSecurity == "none" && (key == "alpn" || key == "sni" || key == "fp" || key == "allowInsecure")) { + newObj[key] = value + } + } + newObj["ps"] = s.genRemark(inbound, email, ep["remark"].(string)) + newObj["add"] = ep["dest"].(string) + newObj["port"] = int(ep["port"].(float64)) + + if newSecurity != "same" { + newObj["tls"] = newSecurity + } if index > 0 { links += "\n" } - jsonStr, _ := json.MarshalIndent(obj, "", " ") + jsonStr, _ := json.MarshalIndent(newObj, "", " ") links += "vmess://" + base64.StdEncoding.EncodeToString(jsonStr) } return links @@ -323,7 +343,6 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { } security, _ := stream["security"].(string) - var domains []interface{} if security == "tls" { params["security"] = "tls" tlsSetting, _ := stream["tlsSettings"].(map[string]interface{}) @@ -335,11 +354,12 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { if len(alpn) > 0 { params["alpn"] = strings.Join(alpn, ",") } + if sniValue, ok := searchKey(tlsSetting, "serverName"); ok { + params["sni"], _ = sniValue.(string) + } + tlsSettings, _ := searchKey(tlsSetting, "settings") if tlsSetting != nil { - if sniValue, ok := searchKey(tlsSettings, "serverName"); ok { - params["sni"], _ = sniValue.(string) - } if fpValue, ok := searchKey(tlsSettings, "fingerprint"); ok { params["fp"], _ = fpValue.(string) } @@ -348,19 +368,11 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { params["allowInsecure"] = "1" } } - if domainSettings, ok := searchKey(tlsSettings, "domains"); ok { - domains, _ = domainSettings.([]interface{}) - } } if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { params["flow"] = clients[clientIndex].Flow } - - serverName, _ := tlsSetting["serverName"].(string) - if serverName != "" { - address = serverName - } } if security == "reality" { @@ -389,11 +401,6 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { params["spx"] = spx } } - if serverName, ok := searchKey(realitySettings, "serverName"); ok { - if sname, ok := serverName.(string); ok && len(sname) > 0 { - address = sname - } - } } if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { @@ -412,7 +419,9 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { if len(alpn) > 0 { params["alpn"] = strings.Join(alpn, ",") } - + if sniValue, ok := searchKey(xtlsSetting, "serverName"); ok { + params["sni"], _ = sniValue.(string) + } xtlsSettings, _ := searchKey(xtlsSetting, "settings") if xtlsSetting != nil { if fpValue, ok := searchKey(xtlsSettings, "fingerprint"); ok { @@ -423,25 +432,55 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { params["allowInsecure"] = "1" } } - if sniValue, ok := searchKey(xtlsSettings, "serverName"); ok { - params["sni"], _ = sniValue.(string) - } } if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { params["flow"] = clients[clientIndex].Flow } - - serverName, _ := xtlsSetting["serverName"].(string) - if serverName != "" { - address = serverName - } } if security != "tls" && security != "reality" && security != "xtls" { params["security"] = "none" } + externalProxies, _ := stream["externalProxy"].([]interface{}) + + if len(externalProxies) > 0 { + links := "" + for index, externalProxy := range externalProxies { + ep, _ := externalProxy.(map[string]interface{}) + newSecurity, _ := ep["forceTls"].(string) + dest, _ := ep["dest"].(string) + port := int(ep["port"].(float64)) + link := fmt.Sprintf("vless://%s@%s:%d", uuid, dest, port) + + if newSecurity != "same" { + params["security"] = newSecurity + } else { + params["security"] = security + } + url, _ := url.Parse(link) + q := url.Query() + + for k, v := range params { + if !(newSecurity == "none" && (k == "alpn" || k == "sni" || k == "fp" || k == "allowInsecure")) { + q.Add(k, v) + } + } + + // Set the new query values on the URL + url.RawQuery = q.Encode() + + url.Fragment = s.genRemark(inbound, email, ep["remark"].(string)) + + if index > 0 { + links += "\n" + } + links += url.String() + } + return links + } + link := fmt.Sprintf("vless://%s@%s:%d", uuid, address, port) url, _ := url.Parse(link) q := url.Query() @@ -453,20 +492,6 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { // Set the new query values on the URL url.RawQuery = q.Encode() - if len(domains) > 0 { - links := "" - for index, d := range domains { - domain := d.(map[string]interface{}) - url.Fragment = s.genRemark(inbound, email, domain["remark"].(string)) - url.Host = fmt.Sprintf("%s:%d", domain["domain"].(string), port) - if index > 0 { - links += "\n" - } - links += url.String() - } - return links - } - url.Fragment = s.genRemark(inbound, email, "") return url.String() } @@ -534,7 +559,6 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string } security, _ := stream["security"].(string) - var domains []interface{} if security == "tls" { params["security"] = "tls" tlsSetting, _ := stream["tlsSettings"].(map[string]interface{}) @@ -546,11 +570,11 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string if len(alpn) > 0 { params["alpn"] = strings.Join(alpn, ",") } + if sniValue, ok := searchKey(tlsSetting, "serverName"); ok { + params["sni"], _ = sniValue.(string) + } tlsSettings, _ := searchKey(tlsSetting, "settings") if tlsSetting != nil { - if sniValue, ok := searchKey(tlsSettings, "serverName"); ok { - params["sni"], _ = sniValue.(string) - } if fpValue, ok := searchKey(tlsSettings, "fingerprint"); ok { params["fp"], _ = fpValue.(string) } @@ -559,14 +583,6 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string params["allowInsecure"] = "1" } } - if domainSettings, ok := searchKey(tlsSettings, "domains"); ok { - domains, _ = domainSettings.([]interface{}) - } - } - - serverName, _ := tlsSetting["serverName"].(string) - if serverName != "" { - address = serverName } } @@ -596,11 +612,6 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string params["spx"] = spx } } - if serverName, ok := searchKey(realitySettings, "serverName"); ok { - if sname, ok := serverName.(string); ok && len(sname) > 0 { - address = sname - } - } } if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { @@ -619,6 +630,9 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string if len(alpn) > 0 { params["alpn"] = strings.Join(alpn, ",") } + if sniValue, ok := searchKey(xtlsSetting, "serverName"); ok { + params["sni"], _ = sniValue.(string) + } xtlsSettings, _ := searchKey(xtlsSetting, "settings") if xtlsSetting != nil { @@ -630,25 +644,55 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string params["allowInsecure"] = "1" } } - if sniValue, ok := searchKey(xtlsSettings, "serverName"); ok { - params["sni"], _ = sniValue.(string) - } } if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { params["flow"] = clients[clientIndex].Flow } - - serverName, _ := xtlsSetting["serverName"].(string) - if serverName != "" { - address = serverName - } } if security != "tls" && security != "reality" && security != "xtls" { params["security"] = "none" } + externalProxies, _ := stream["externalProxy"].([]interface{}) + + if len(externalProxies) > 0 { + links := "" + for index, externalProxy := range externalProxies { + ep, _ := externalProxy.(map[string]interface{}) + newSecurity, _ := ep["forceTls"].(string) + dest, _ := ep["dest"].(string) + port := int(ep["port"].(float64)) + link := fmt.Sprintf("trojan://%s@%s:%d", password, dest, port) + + if newSecurity != "same" { + params["security"] = newSecurity + } else { + params["security"] = security + } + url, _ := url.Parse(link) + q := url.Query() + + for k, v := range params { + if !(newSecurity == "none" && (k == "alpn" || k == "sni" || k == "fp" || k == "allowInsecure")) { + q.Add(k, v) + } + } + + // Set the new query values on the URL + url.RawQuery = q.Encode() + + url.Fragment = s.genRemark(inbound, email, ep["remark"].(string)) + + if index > 0 { + links += "\n" + } + links += url.String() + } + return links + } + link := fmt.Sprintf("trojan://%s@%s:%d", password, address, port) url, _ := url.Parse(link) @@ -661,20 +705,6 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string // Set the new query values on the URL url.RawQuery = q.Encode() - if len(domains) > 0 { - links := "" - for index, d := range domains { - domain := d.(map[string]interface{}) - url.Fragment = s.genRemark(inbound, email, domain["remark"].(string)) - url.Host = fmt.Sprintf("%s:%d", domain["domain"].(string), port) - if index > 0 { - links += "\n" - } - links += url.String() - } - return links - } - url.Fragment = s.genRemark(inbound, email, "") return url.String() } @@ -744,10 +774,78 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st } } + security, _ := stream["security"].(string) + if security == "tls" { + params["security"] = "tls" + tlsSetting, _ := stream["tlsSettings"].(map[string]interface{}) + alpns, _ := tlsSetting["alpn"].([]interface{}) + var alpn []string + for _, a := range alpns { + alpn = append(alpn, a.(string)) + } + if len(alpn) > 0 { + params["alpn"] = strings.Join(alpn, ",") + } + if sniValue, ok := searchKey(tlsSetting, "serverName"); ok { + params["sni"], _ = sniValue.(string) + } + + tlsSettings, _ := searchKey(tlsSetting, "settings") + if tlsSetting != nil { + if fpValue, ok := searchKey(tlsSettings, "fingerprint"); ok { + params["fp"], _ = fpValue.(string) + } + if insecure, ok := searchKey(tlsSettings, "allowInsecure"); ok { + if insecure.(bool) { + params["allowInsecure"] = "1" + } + } + } + } + encPart := fmt.Sprintf("%s:%s", method, clients[clientIndex].Password) if method[0] == '2' { encPart = fmt.Sprintf("%s:%s:%s", method, inboundPassword, clients[clientIndex].Password) } + + externalProxies, _ := stream["externalProxy"].([]interface{}) + + if len(externalProxies) > 0 { + links := "" + for index, externalProxy := range externalProxies { + ep, _ := externalProxy.(map[string]interface{}) + newSecurity, _ := ep["forceTls"].(string) + dest, _ := ep["dest"].(string) + port := int(ep["port"].(float64)) + link := fmt.Sprintf("ss://%s@%s:%d", base64.StdEncoding.EncodeToString([]byte(encPart)), dest, port) + + if newSecurity != "same" { + params["security"] = newSecurity + } else { + params["security"] = security + } + url, _ := url.Parse(link) + q := url.Query() + + for k, v := range params { + if !(newSecurity == "none" && (k == "alpn" || k == "sni" || k == "fp" || k == "allowInsecure")) { + q.Add(k, v) + } + } + + // Set the new query values on the URL + url.RawQuery = q.Encode() + + url.Fragment = s.genRemark(inbound, email, ep["remark"].(string)) + + if index > 0 { + links += "\n" + } + links += url.String() + } + return links + } + link := fmt.Sprintf("ss://%s@%s:%d", base64.StdEncoding.EncodeToString([]byte(encPart)), address, inbound.Port) url, _ := url.Parse(link) q := url.Query() @@ -758,22 +856,36 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st // Set the new query values on the URL url.RawQuery = q.Encode() + url.Fragment = s.genRemark(inbound, email, "") return url.String() } func (s *SubService) genRemark(inbound *model.Inbound, email string, extra string) string { - var remark []string + separationChar := string(s.remarkModel[0]) + orderChars := s.remarkModel[1:] + orders := map[byte]string{ + 'i': "", + 'e': "", + 'o': "", + } if len(email) > 0 { - if len(inbound.Remark) > 0 { - remark = append(remark, inbound.Remark) + orders['e'] = email + } + if len(inbound.Remark) > 0 { + orders['i'] = inbound.Remark + } + if len(extra) > 0 { + orders['e'] = extra + } + + var remark []string + for i := 0; i < len(orderChars); i++ { + char := orderChars[i] + order, exists := orders[char] + if exists && order != "" { + remark = append(remark, order) } - remark = append(remark, email) - if len(extra) > 0 { - remark = append(remark, extra) - } - } else { - return inbound.Remark } if s.showInfo { @@ -790,7 +902,7 @@ func (s *SubService) genRemark(inbound *model.Inbound, email string, extra strin // Get remained days if statsExist { if !stats.Enable { - return fmt.Sprintf("⛔️N/A-%s", strings.Join(remark, "-")) + return fmt.Sprintf("⛔️N/A%s%s", separationChar, strings.Join(remark, separationChar)) } if vol := stats.Total - (stats.Up + stats.Down); vol > 0 { remark = append(remark, fmt.Sprintf("%s%s", common.FormatTraffic(vol), "📊")) @@ -804,7 +916,7 @@ func (s *SubService) genRemark(inbound *model.Inbound, email string, extra strin } } } - return strings.Join(remark, " : ") + return strings.Join(remark, separationChar) } func searchKey(data interface{}, key string) (interface{}, bool) { diff --git a/web/assets/Vazirmatn-UI-NL-Regular.woff2 b/web/assets/Vazirmatn-UI-NL-Regular.woff2 new file mode 100644 index 00000000..3ce577ae Binary files /dev/null and b/web/assets/Vazirmatn-UI-NL-Regular.woff2 differ diff --git a/web/assets/ant-design-vue@1.7.2/antd-with-locales.min.js b/web/assets/ant-design-vue@1.7.2/antd-with-locales.min.js deleted file mode 100644 index b21c967d..00000000 --- a/web/assets/ant-design-vue@1.7.2/antd-with-locales.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! For license information please see antd-with-locales.min.js.LICENSE.txt */ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("moment"),require("vue")):"function"==typeof define&&define.amd?define(["moment","vue"],t):"object"==typeof exports?exports.antd=t(require("moment"),require("vue")):e.antd=t(e.moment,e.Vue)}(window,(function(e,t){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i:i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=547)}([function(e,t,n){"use strict";var i=n(14),r=n.n(i),a=n(36),o=n.n(a),s=Object.prototype,c=s.toString,l=s.hasOwnProperty,u=/^\s*function (\w+)/,h=function(e){var t=null!=e?e.type?e.type:e:null,n=t&&t.toString().match(u);return n&&n[1]},d=function(e){if(null==e)return null;var t=e.constructor.toString().match(u);return t&&t[1]},f=Number.isInteger||function(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e},p=Array.isArray||function(e){return"[object Array]"===c.call(e)},v=function(e){return"[object Function]"===c.call(e)},m=function(e,t){var n;return Object.defineProperty(t,"_vueTypes_name",{enumerable:!1,writable:!1,value:e}),n=t,Object.defineProperty(n,"isRequired",{get:function(){return this.required=!0,this},enumerable:!1}),function(e){Object.defineProperty(e,"def",{value:function(e){return void 0===e&&void 0===this.default?(this.default=void 0,this):v(e)||g(this,e)?(this.default=p(e)||o()(e)?function(){return e}:e,this):(b(this._vueTypes_name+' - invalid default value: "'+e+'"',e),this)},enumerable:!1,writable:!1})}(t),v(t.validator)&&(t.validator=t.validator.bind(t)),t},g=function e(t,n){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=t,a=!0,s=void 0;o()(t)||(r={type:t});var c=r._vueTypes_name?r._vueTypes_name+" - ":"";return l.call(r,"type")&&null!==r.type&&(p(r.type)?(a=r.type.some((function(t){return e(t,n,!0)})),s=r.type.map((function(e){return h(e)})).join(" or ")):a="Array"===(s=h(r))?p(n):"Object"===s?o()(n):"String"===s||"Number"===s||"Boolean"===s||"Function"===s?d(n)===s:n instanceof r.type),a?l.call(r,"validator")&&v(r.validator)?((a=r.validator(n))||!1!==i||b(c+"custom validation failed"),a):a:(!1===i&&b(c+'value "'+n+'" should be of type "'+s+'"'),!1)},b=function(){},y={get any(){return m("any",{type:null})},get func(){return m("function",{type:Function}).def(C.func)},get bool(){return m("boolean",{type:Boolean}).def(C.bool)},get string(){return m("string",{type:String}).def(C.string)},get number(){return m("number",{type:Number}).def(C.number)},get array(){return m("array",{type:Array}).def(C.array)},get object(){return m("object",{type:Object}).def(C.object)},get integer(){return m("integer",{type:Number,validator:function(e){return f(e)}}).def(C.integer)},get symbol(){return m("symbol",{type:null,validator:function(e){return"symbol"===(void 0===e?"undefined":r()(e))}})},custom:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"custom validation failed";if("function"!=typeof e)throw new TypeError("[VueTypes error]: You must provide a function as argument");return m(e.name||"<>",{validator:function(){var n=e.apply(void 0,arguments);return n||b(this._vueTypes_name+" - "+t),n}})},oneOf:function(e){if(!p(e))throw new TypeError("[VueTypes error]: You must provide an array as argument");var t='oneOf - value should be one of "'+e.join('", "')+'"',n=e.reduce((function(e,t){return null!=t&&-1===e.indexOf(t.constructor)&&e.push(t.constructor),e}),[]);return m("oneOf",{type:n.length>0?n:null,validator:function(n){var i=-1!==e.indexOf(n);return i||b(t),i}})},instanceOf:function(e){return m("instanceOf",{type:e})},oneOfType:function(e){if(!p(e))throw new TypeError("[VueTypes error]: You must provide an array as argument");var t=!1,n=e.reduce((function(e,n){if(o()(n)){if("oneOf"===n._vueTypes_name)return e.concat(n.type||[]);if(n.type&&!v(n.validator)){if(p(n.type))return e.concat(n.type);e.push(n.type)}else v(n.validator)&&(t=!0);return e}return e.push(n),e}),[]);if(!t)return m("oneOfType",{type:n}).def(void 0);var i=e.map((function(e){return e&&p(e.type)?e.type.map(h):h(e)})).reduce((function(e,t){return e.concat(p(t)?t:[t])}),[]).join('", "');return this.custom((function(t){var n=e.some((function(e){return"oneOf"===e._vueTypes_name?!e.type||g(e.type,t,!0):g(e,t,!0)}));return n||b('oneOfType - value type should be one of "'+i+'"'),n})).def(void 0)},arrayOf:function(e){return m("arrayOf",{type:Array,validator:function(t){var n=t.every((function(t){return g(e,t)}));return n||b('arrayOf - value must be an array of "'+h(e)+'"'),n}})},objectOf:function(e){return m("objectOf",{type:Object,validator:function(t){var n=Object.keys(t).every((function(n){return g(e,t[n])}));return n||b('objectOf - value must be an object of "'+h(e)+'"'),n}})},shape:function(e){var t=Object.keys(e),n=t.filter((function(t){return e[t]&&!0===e[t].required})),i=m("shape",{type:Object,validator:function(i){var r=this;if(!o()(i))return!1;var a=Object.keys(i);return n.length>0&&n.some((function(e){return-1===a.indexOf(e)}))?(b('shape - at least one of required properties "'+n.join('", "')+'" is not present'),!1):a.every((function(n){if(-1===t.indexOf(n))return!0===r._vueTypes_isLoose||(b('shape - object is missing "'+n+'" property'),!1);var a=e[n];return g(a,i[n])}))}});return Object.defineProperty(i,"_vueTypes_isLoose",{enumerable:!1,writable:!0,value:!1}),Object.defineProperty(i,"loose",{get:function(){return this._vueTypes_isLoose=!0,this},enumerable:!1}),i}},C={func:void 0,bool:void 0,string:void 0,number:void 0,array:void 0,object:void 0,integer:void 0};Object.defineProperty(y,"sensibleDefaults",{enumerable:!1,set:function(e){!1===e?C={}:!0===e?C={func:void 0,bool:void 0,string:void 0,number:void 0,array:void 0,object:void 0,integer:void 0}:o()(e)&&(C=e)},get:function(){return C}});t.a=y},function(e,t,n){"use strict";n.d(t,"i",(function(){return T})),n.d(t,"h",(function(){return V})),n.d(t,"k",(function(){return P})),n.d(t,"f",(function(){return j})),n.d(t,"q",(function(){return H})),n.d(t,"u",(function(){return _})),n.d(t,"v",(function(){return L})),n.d(t,"c",(function(){return F})),n.d(t,"x",(function(){return A})),n.d(t,"s",(function(){return m})),n.d(t,"l",(function(){return k})),n.d(t,"g",(function(){return z})),n.d(t,"o",(function(){return x})),n.d(t,"m",(function(){return w})),n.d(t,"j",(function(){return M})),n.d(t,"e",(function(){return O})),n.d(t,"r",(function(){return S})),n.d(t,"y",(function(){return v})),n.d(t,"t",(function(){return E})),n.d(t,"w",(function(){return D})),n.d(t,"a",(function(){return p})),n.d(t,"p",(function(){return b})),n.d(t,"n",(function(){return y})),n.d(t,"d",(function(){return C}));var i=n(14),r=n.n(i),a=n(22),o=n.n(a),s=n(2),c=n.n(s),l=n(36),u=n.n(l),h=n(5),d=n.n(h);var f=/-(\w)/g,p=function(e){return e.replace(f,(function(e,t){return t?t.toUpperCase():""}))},v=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments[1],n={},i=/;(?![^(]*\))/g,r=/:(.+)/;return e.split(i).forEach((function(e){if(e){var i=e.split(r);if(i.length>1){var a=t?p(i[0].trim()):i[0].trim();n[a]=i[1].trim()}}})),n},m=function(e,t){return t in((e.$options||{}).propsData||{})},g=function(e){return e.data&&e.data.scopedSlots||{}},b=function(e){var t=e.componentOptions||{};e.$vnode&&(t=e.$vnode.componentOptions||{});var n=e.children||t.children||[],i={};return n.forEach((function(e){if(!_(e)){var t=e.data&&e.data.slot||"default";i[t]=i[t]||[],i[t].push(e)}})),c()({},i,g(e))},y=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"default",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return e.$scopedSlots&&e.$scopedSlots[t]&&e.$scopedSlots[t](n)||e.$slots[t]||[]},C=function(e){var t=e.componentOptions||{};return e.$vnode&&(t=e.$vnode.componentOptions||{}),e.children||t.children||[]},x=function(e){if(e.fnOptions)return e.fnOptions;var t=e.componentOptions;return e.$vnode&&(t=e.$vnode.componentOptions),t&&t.Ctor.options||{}},k=function(e){if(e.componentOptions){var t=e.componentOptions,n=t.propsData,i=void 0===n?{}:n,r=t.Ctor,a=((void 0===r?{}:r).options||{}).props||{},s={},l=!0,u=!1,h=void 0;try{for(var d,f=Object.entries(a)[Symbol.iterator]();!(l=(d=f.next()).done);l=!0){var p=d.value,v=o()(p,2),m=v[0],g=v[1],b=g.default;void 0!==b&&(s[m]="function"==typeof b&&"Function"!==(y=g.type,C=void 0,(C=y&&y.toString().match(/^\s*function (\w+)/))?C[1]:"")?b.call(e):b)}}catch(e){u=!0,h=e}finally{try{!l&&f.return&&f.return()}finally{if(u)throw h}}return c()({},s,i)}var y,C,x=e.$options,k=void 0===x?{}:x,z=e.$props;return function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n={};return Object.keys(e).forEach((function(i){(i in t||void 0!==e[i])&&(n[i]=e[i])})),n}(void 0===z?{}:z,k.propsData)},z=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:e,i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];if(e.$createElement){var r=e.$createElement,a=e[t];return void 0!==a?"function"==typeof a&&i?a(r,n):a:e.$scopedSlots[t]&&i&&e.$scopedSlots[t](n)||e.$scopedSlots[t]||e.$slots[t]||void 0}var o=e.context.$createElement,s=w(e)[t];if(void 0!==s)return"function"==typeof s&&i?s(o,n):s;var c=g(e)[t];if(void 0!==c)return"function"==typeof c&&i?c(o,n):c;var l=[],u=e.componentOptions||{};return(u.children||[]).forEach((function(e){e.data&&e.data.slot===t&&(e.data.attrs&&delete e.data.attrs.slot,"template"===e.tag?l.push(e.children):l.push(e))})),l.length?l:void 0},w=function(e){var t=e.componentOptions;return e.$vnode&&(t=e.$vnode.componentOptions),t&&t.propsData||{}},S=function(e,t){return w(e)[t]},O=function(e){var t=e.data;return e.$vnode&&(t=e.$vnode.data),t&&t.attrs||{}},M=function(e){var t=e.key;return e.$vnode&&(t=e.$vnode.key),t};function T(e){var t={};return e.componentOptions&&e.componentOptions.listeners?t=e.componentOptions.listeners:e.data&&e.data.on&&(t=e.data.on),c()({},t)}function V(e){var t={};return e.data&&e.data.on&&(t=e.data.on),c()({},t)}function P(e){return(e.$vnode?e.$vnode.componentOptions.listeners:e.$listeners)||{}}function j(e){var t={};e.data?t=e.data:e.$vnode&&e.$vnode.data&&(t=e.$vnode.data);var n=t.class||{},i=t.staticClass,r={};return i&&i.split(" ").forEach((function(e){r[e.trim()]=!0})),"string"==typeof n?n.split(" ").forEach((function(e){r[e.trim()]=!0})):Array.isArray(n)?d()(n).split(" ").forEach((function(e){r[e.trim()]=!0})):r=c()({},r,n),r}function H(e,t){var n={};e.data?n=e.data:e.$vnode&&e.$vnode.data&&(n=e.$vnode.data);var i=n.style||n.staticStyle;if("string"==typeof i)i=v(i,t);else if(t&&i){var r={};return Object.keys(i).forEach((function(e){return r[p(e)]=i[e]})),r}return i}function _(e){return!(e.tag||e.text&&""!==e.text.trim())}function L(e){return!e.tag}function F(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];return e.filter((function(e){return!_(e)}))}var E=function(e,t){return Object.keys(t).forEach((function(n){if(!e[n])throw new Error("not have "+n+" prop");e[n].def&&(e[n]=e[n].def(t[n]))})),e};function A(){var e=[].slice.call(arguments,0),t={};return e.forEach((function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=!0,i=!1,r=void 0;try{for(var a,s=Object.entries(e)[Symbol.iterator]();!(n=(a=s.next()).done);n=!0){var l=a.value,h=o()(l,2),d=h[0],f=h[1];t[d]=t[d]||{},u()(f)?c()(t[d],f):t[d]=f}}catch(e){i=!0,r=e}finally{try{!n&&s.return&&s.return()}finally{if(i)throw r}}})),t}function D(e){return e&&"object"===(void 0===e?"undefined":r()(e))&&"componentOptions"in e&&"context"in e&&void 0!==e.tag}t.b=m},function(e,t,n){"use strict";t.__esModule=!0;var i,r=n(247),a=(i=r)&&i.__esModule?i:{default:i};t.default=a.default||function(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:{},t=arguments[1],n="function"==typeof e?e(this.$data,this.$props):e;if(this.getDerivedStateFromProps){var i=this.getDerivedStateFromProps(Object(s.l)(this),o()({},this.$data,n));if(null===i)return;n=o()({},n,i||{})}o()(this.$data,n),this.$forceUpdate(),this.$nextTick((function(){t&&t()}))},__emit:function(){var e=[].slice.call(arguments,0),t=e[0],n=this.$listeners[t];if(e.length&&n)if(Array.isArray(n))for(var i=0,a=n.length;i0&&void 0!==arguments[0]?arguments[0]:[],t={};return e.forEach((function(e){t[e]=function(t){this._proxyVm._data[e]=t}})),t}(["prefixCls","csp","autoInsertSpaceInButton","locale","pageHeader","transformCellText"])),methods:{renderEmptyComponent:function(e,t){return(Object(c.g)(this,"renderEmpty",{},!1)||h)(e,t)},getPrefixCls:function(e,t){var n=this.$props.prefixCls,i=void 0===n?"ant":n;return t||(e?i+"-"+e:i)},renderProvider:function(e){return(0,this.$createElement)(f.b,{attrs:{locale:this.locale||e,_ANT_MARK__:f.a}},[this.$slots.default?Object(c.c)(this.$slots.default)[0]:null])}},render:function(){var e=this,t=arguments[0];return t(p.a,{scopedSlots:{default:function(t,n,i){return e.renderProvider(i)}}})}},m={getPrefixCls:function(e,t){return t||"ant-"+e},renderEmpty:h};v.install=function(e){e.use(d.a),e.component(v.name,v)};t.b=v},function(e,t,n){"use strict";var i=n(6),r=n.n(i),a=n(2),o=n.n(a),s=n(3),c=n.n(s),l=n(11),u=n.n(l),h=n(5),d=n.n(h),f=n(160),p=n(62),v={primaryColor:"#333",secondaryColor:"#E6E6E6"},m={name:"AntdIcon",props:["type","primaryColor","secondaryColor"],displayName:"IconVue",definitions:new p.a,data:function(){return{twoToneColorPalette:v}},add:function(){for(var e=arguments.length,t=Array(e),n=0;n1&&void 0!==arguments[1]?arguments[1]:v;if(e){var n=m.definitions.get(e);return n&&"function"==typeof n.icon&&(n=o()({},n,{icon:n.icon(t.primaryColor,t.secondaryColor)})),n}},setTwoToneColors:function(e){var t=e.primaryColor,n=e.secondaryColor;v.primaryColor=t,v.secondaryColor=n||Object(p.c)(t)},getTwoToneColors:function(){return o()({},v)},render:function(e){var t=this.$props,n=t.type,i=t.primaryColor,r=t.secondaryColor,a=void 0,s=v;if(i&&(s={primaryColor:i,secondaryColor:r||Object(p.c)(i)}),Object(p.d)(n))a=n;else if("string"==typeof n&&!(a=m.get(n,s)))return null;return a?(a&&"function"==typeof a.icon&&(a=o()({},a,{icon:a.icon(s.primaryColor,s.secondaryColor)})),Object(p.b)(e,a.icon,"svg-"+a.name,{attrs:{"data-icon":a.name,width:"1em",height:"1em",fill:"currentColor","aria-hidden":"true"},on:this.$listeners})):(Object(p.e)("type should be string or icon definiton, but got "+n),null)},install:function(e){e.component(m.name,m)}},g=m,b=n(0),y=n(12),C=n.n(y),x=n(1),k=new Set;var z=n(13),w={width:"1em",height:"1em",fill:"currentColor","aria-hidden":"true",focusable:"false"},S=/-fill$/,O=/-o$/,M=/-twotone$/;var T=n(26);function V(e){return g.setTwoToneColors({primaryColor:e})}var P=n(10);g.add.apply(g,u()(Object.keys(f).map((function(e){return f[e]})))),V("#1890ff");function j(e,t,n){var i,a=n.$props,s=n.$slots,l=Object(x.k)(n),u=a.type,h=a.component,f=a.viewBox,p=a.spin,v=a.theme,m=a.twoToneColor,b=a.rotate,y=a.tabIndex,C=Object(x.c)(s.default);C=0===C.length?void 0:C,Object(z.a)(Boolean(u||h||C),"Icon","Icon should have `type` prop or `component` prop or `children`.");var k=d()((i={},c()(i,"anticon",!0),c()(i,"anticon-"+u,!!u),i)),T=d()(c()({},"anticon-spin",!!p||"loading"===u)),V=b?{msTransform:"rotate("+b+"deg)",transform:"rotate("+b+"deg)"}:void 0,P={attrs:o()({},w,{viewBox:f}),class:T,style:V};f||delete P.attrs.viewBox;var j=y;void 0===j&&"click"in l&&(j=-1);var H={attrs:{"aria-label":u&&t.icon+": "+u,tabIndex:j},on:l,class:k,staticClass:""};return e("i",H,[function(){if(h)return e(h,P,[C]);if(C){Object(z.a)(Boolean(f)||1===C.length&&"use"===C[0].tag,"Icon","Make sure that you provide correct `viewBox` prop (default `0 0 1024 1024`) to the icon.");var t={attrs:o()({},w),class:T,style:V};return e("svg",r()([t,{attrs:{viewBox:f}}]),[C])}if("string"==typeof u){var n=u;if(v){var i=function(e){var t=null;return S.test(e)?t="filled":O.test(e)?t="outlined":M.test(e)&&(t="twoTone"),t}(u);Object(z.a)(!i||v===i,"Icon","The icon name '"+u+"' already specify a theme '"+i+"', the 'theme' prop '"+v+"' will be ignored.")}return n=function(e,t){var n=e;return"filled"===t?n+="-fill":"outlined"===t?n+="-o":"twoTone"===t?n+="-twotone":Object(z.a)(!1,"Icon","This icon '"+e+"' has unknown theme '"+t+"'"),n}(function(e){return e.replace(S,"").replace(O,"").replace(M,"")}(function(e){var t=e;switch(e){case"cross":t="close";break;case"interation":t="interaction";break;case"canlendar":t="calendar";break;case"colum-height":t="column-height"}return Object(z.a)(t===e,"Icon","Icon '"+e+"' was a typo and is now deprecated, please use '"+t+"' instead."),t}(n)),v||"outlined"),e(g,{attrs:{focusable:"false",type:n,primaryColor:m},class:T,style:V})}}()])}var H={name:"AIcon",props:{tabIndex:b.a.number,type:b.a.string,component:b.a.any,viewBox:b.a.any,spin:b.a.bool.def(!1),rotate:b.a.number,theme:b.a.oneOf(["filled","outlined","twoTone"]),twoToneColor:b.a.string,role:b.a.string},render:function(e){var t=this;return e(T.a,{attrs:{componentName:"Icon"},scopedSlots:{default:function(n){return j(e,n,t)}}})},createFromIconfontCN:function(e){var t=e.scriptUrl,n=e.extraCommonProps,i=void 0===n?{}:n;if("undefined"!=typeof document&&"undefined"!=typeof window&&"function"==typeof document.createElement&&"string"==typeof t&&t.length&&!k.has(t)){var r=document.createElement("script");r.setAttribute("src",t),r.setAttribute("data-namespace",t),k.add(t),document.body.appendChild(r)}return{functional:!0,name:"AIconfont",props:_.props,render:function(e,t){var n=t.props,r=t.slots,a=t.listeners,o=t.data,s=n.type,c=C()(n,["type"]),l=r().default,u=null;s&&(u=e("use",{attrs:{"xlink:href":"#"+s}})),l&&(u=l);var h=Object(x.x)(i,o,{props:c,on:a});return e(_,h,[u])}}},getTwoToneColor:function(){return g.getTwoToneColors().primaryColor}};H.setTwoToneColor=V,H.install=function(e){e.use(P.a),e.component(H.name,H)};var _=t.a=H},function(e,t,n){"use strict";n.d(t,"b",(function(){return h})),n.d(t,"a",(function(){return d}));var i=n(11),r=n.n(i),a=n(2),o=n.n(a),s=n(1),c=n(5),l=n.n(c);function u(e,t){var n=e.componentOptions,i=e.data,r={};n&&n.listeners&&(r=o()({},n.listeners));var a={};i&&i.on&&(a=o()({},i.on));var s=new e.constructor(e.tag,i?o()({},i,{on:a}):i,e.children,e.text,e.elm,e.context,n?o()({},n,{listeners:r}):n,e.asyncFactory);return s.ns=e.ns,s.isStatic=e.isStatic,s.key=e.key,s.isComment=e.isComment,s.fnContext=e.fnContext,s.fnOptions=e.fnOptions,s.fnScopeId=e.fnScopeId,s.isCloned=!0,t&&(e.children&&(s.children=h(e.children,!0)),n&&n.children&&(n.children=h(n.children,!0))),s}function h(e,t){for(var n=e.length,i=new Array(n),r=0;r1&&void 0!==arguments[1]?arguments[1]:{},n=arguments[2],i=e;if(Array.isArray(e)&&(i=Object(s.c)(e)[0]),!i)return null;var a=u(i,n),c=t.props,h=void 0===c?{}:c,d=t.key,f=t.on,p=void 0===f?{}:f,v=t.nativeOn,m=void 0===v?{}:v,g=t.children,b=t.directives,y=void 0===b?[]:b,C=a.data||{},x={},k={},z=t.attrs,w=void 0===z?{}:z,S=t.ref,O=t.domProps,M=void 0===O?{}:O,T=t.style,V=void 0===T?{}:T,P=t.class,j=void 0===P?{}:P,H=t.scopedSlots,_=void 0===H?{}:H;return k="string"==typeof C.style?Object(s.y)(C.style):o()({},C.style,k),k="string"==typeof V?o()({},k,Object(s.y)(k)):o()({},k,V),"string"==typeof C.class&&""!==C.class.trim()?C.class.split(" ").forEach((function(e){x[e.trim()]=!0})):Array.isArray(C.class)?l()(C.class).split(" ").forEach((function(e){x[e.trim()]=!0})):x=o()({},C.class,x),"string"==typeof j&&""!==j.trim()?j.split(" ").forEach((function(e){x[e.trim()]=!0})):x=o()({},x,j),a.data=o()({},C,{style:k,attrs:o()({},C.attrs,w),class:x,domProps:o()({},C.domProps,M),scopedSlots:o()({},C.scopedSlots,_),directives:[].concat(r()(C.directives||[]),r()(y))}),a.componentOptions?(a.componentOptions.propsData=a.componentOptions.propsData||{},a.componentOptions.listeners=a.componentOptions.listeners||{},a.componentOptions.propsData=o()({},a.componentOptions.propsData,h),a.componentOptions.listeners=o()({},a.componentOptions.listeners,p),g&&(a.componentOptions.children=g)):(g&&(a.children=g),a.data.on=o()({},a.data.on||{},p)),a.data.on=o()({},a.data.on||{},m),void 0!==d&&(a.key=d,a.data.key=d),"string"==typeof S&&(a.data.ref=S),a}},function(e,t,n){"use strict";var i=n(25),r=n.n(i),a=n(116),o=n(80);function s(e){return e.directive("ant-portal",{inserted:function(e,t){var n=t.value,i="function"==typeof n?n(e):n;i!==e.parentNode&&i.appendChild(e)},componentUpdated:function(e,t){var n=t.value,i="function"==typeof n?n(e):n;i!==e.parentNode&&i.appendChild(e)}})}var c={install:function(e){e.use(r.a,{name:"ant-ref"}),Object(a.a)(e),Object(o.a)(e),s(e)}},l={};l.install=function(e){l.Vue=e,e.use(c)};t.a=l},function(e,t,n){"use strict";t.__esModule=!0;var i,r=n(276),a=(i=r)&&i.__esModule?i:{default:i};t.default=function(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t=0||Object.prototype.hasOwnProperty.call(e,i)&&(n[i]=e[i]);return n}},function(e,t,n){"use strict";var i={};function r(e,t){0}function a(e,t,n){t||i[n]||(e(!1,n),i[n]=!0)}var o=function(e,t){a(r,e,t)};t.a=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";o(e,"[antdv: "+t+"] "+n)}},function(e,t,n){"use strict";t.__esModule=!0;var i=o(n(253)),r=o(n(263)),a="function"==typeof r.default&&"symbol"==typeof i.default?function(e){return typeof e}:function(e){return e&&"function"==typeof r.default&&e.constructor===r.default&&e!==r.default.prototype?"symbol":typeof e};function o(e){return e&&e.__esModule?e:{default:e}}t.default="function"==typeof r.default&&"symbol"===a(i.default)?function(e){return void 0===e?"undefined":a(e)}:function(e){return e&&"function"==typeof r.default&&e.constructor===r.default&&e!==r.default.prototype?"symbol":void 0===e?"undefined":a(e)}},function(t,n){t.exports=e},function(e,t,n){"use strict";var i=n(2),r=n.n(i);t.a=function(e,t){for(var n=r()({},e),i=0;i=0&&n.splice(i,1),n}function y(e,t){var n=e.slice();return-1===n.indexOf(t)&&n.push(t),n}function C(e){return e.split("-")}function x(e,t){return e+"-"+t}function k(e){return Object(v.o)(e).isTreeNode}function z(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];return e.filter(k)}function w(e){var t=Object(v.l)(e)||{},n=t.disabled,i=t.disableCheckbox,r=t.checkable;return!(!n&&!i)||!1===r}function S(e,t){!function n(i,r,a){var o=i?i.componentOptions.children:e,s=i?x(a.pos,r):0,c=z(o);if(i){var l=i.key;l||null!=l||(l=s);var u={node:i,index:r,pos:s,key:l,parentPos:a.node?a.pos:null};t(u)}c.forEach((function(e,t){n(e,t,{node:i,pos:s})}))}(null)}function O(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments[1],n=e.map(t);return 1===n.length?n[0]:n}function M(e,t){var n=Object(v.l)(t),i=n.eventKey,r=n.pos,a=[];return S(e,(function(e){var t=e.key;a.push(t)})),a.push(i||r),a}function T(e,t){var n=e.clientY,i=t.$refs.selectHandle.getBoundingClientRect(),r=i.top,a=i.bottom,o=i.height,s=Math.max(.25*o,2);return n<=r+s?-1:n>=a-s?1:0}function V(e,t){if(e)return t.multiple?e.slice():e.length?[e[0]]:e}var P=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return{props:Object(f.a)(e,["on","key","class","className","style"]),on:e.on||{},class:e.class||e.className,style:e.style,key:e.key}};function j(e,t,n){if(!t)return[];var i=(n||{}).processProps,r=void 0===i?P:i;return(Array.isArray(t)?t:[t]).map((function(t){var i=t.children,a=u()(t,["children"]),o=j(e,i,n);return e(p.a,r(a),[o])}))}function H(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.initWrapper,i=t.processEntity,r=t.onProcessFinished,a=new Map,o=new Map,s={posEntities:a,keyEntities:o};return n&&(s=n(s)||s),S(e,(function(e){var t=e.node,n=e.index,r=e.pos,c=e.key,l=e.parentPos,u={node:t,index:n,key:c,pos:r};a.set(r,u),o.set(c,u),u.parent=a.get(l),u.parent&&(u.parent.children=u.parent.children||[],u.parent.children.push(u)),i&&i(u,s)})),r&&r(s),s}function _(e){if(!e)return null;var t=void 0;if(Array.isArray(e))t={checkedKeys:e,halfCheckedKeys:void 0};else{if("object"!==(void 0===e?"undefined":c()(e)))return d()(!1,"`checkedKeys` is not an array or an object"),null;t={checkedKeys:e.checked||void 0,halfCheckedKeys:e.halfChecked||void 0}}return t}function L(e,t,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},r=new Map,a=new Map;function s(e){if(r.get(e)!==t){var i=n.get(e);if(i){var o=i.children,c=i.parent;if(!w(i.node)){var l=!0,u=!1;(o||[]).filter((function(e){return!w(e.node)})).forEach((function(e){var t=e.key,n=r.get(t),i=a.get(t);(n||i)&&(u=!0),n||(l=!1)})),t?r.set(e,l):r.set(e,!1),a.set(e,u),c&&s(c.key)}}}}function c(e){if(r.get(e)!==t){var i=n.get(e);if(i){var a=i.children;w(i.node)||(r.set(e,t),(a||[]).forEach((function(e){c(e.key)})))}}}function l(e){var i=n.get(e);if(i){var a=i.children,o=i.parent,l=i.node;r.set(e,t),w(l)||((a||[]).filter((function(e){return!w(e.node)})).forEach((function(e){c(e.key)})),o&&s(o.key))}else d()(!1,"'"+e+"' does not exist in the tree.")}(i.checkedKeys||[]).forEach((function(e){r.set(e,!0)})),(i.halfCheckedKeys||[]).forEach((function(e){a.set(e,!0)})),(e||[]).forEach((function(e){l(e)}));var u=[],h=[],f=!0,p=!1,v=void 0;try{for(var m,g=r[Symbol.iterator]();!(f=(m=g.next()).done);f=!0){var b=m.value,y=o()(b,2),C=y[0],x=y[1];x&&u.push(C)}}catch(e){p=!0,v=e}finally{try{!f&&g.return&&g.return()}finally{if(p)throw v}}var k=!0,z=!1,S=void 0;try{for(var O,M=a[Symbol.iterator]();!(k=(O=M.next()).done);k=!0){var T=O.value,V=o()(T,2),P=V[0],j=V[1];!r.get(P)&&j&&h.push(P)}}catch(e){z=!0,S=e}finally{try{!k&&M.return&&M.return()}finally{if(z)throw S}}return{checkedKeys:u,halfCheckedKeys:h}}function F(e,t){var n=new Map;return(e||[]).forEach((function(e){!function e(i){if(!n.get(i)){var r=t.get(i);if(r){n.set(i,!0);var a=r.parent,o=r.node,s=Object(v.l)(o);s&&s.disabled||a&&e(a.key)}}}(e)})),[].concat(r()(n.keys()))}},function(e,n){e.exports=t},function(e,t,n){(function(t){for(var i=n(289),r="undefined"==typeof window?t:window,a=["moz","webkit"],o="AnimationFrame",s=r["request"+o],c=r["cancel"+o]||r["cancelRequest"+o],l=0;!s&&l1&&void 0!==arguments[1]?arguments[1]:{},n=t.beforeEnter,a=t.enter,o=t.afterEnter,s=t.leave,c=t.afterLeave,l=t.appear,u=void 0===l||l,h=t.tag,d=t.nativeOn,f={props:{appear:u,css:!1},on:{beforeEnter:n||r,enter:a||function(t,n){Object(i.a)(t,e+"-enter",n)},afterEnter:o||r,leave:s||function(t,n){Object(i.a)(t,e+"-leave",n)},afterLeave:c||r},nativeOn:d};return h&&(f.tag=h),f}},function(e,t,n){"use strict";var i=function(){};e.exports=i},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={install:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.name||"ref";e.directive(n,{bind:function(t,n,i){e.nextTick((function(){n.value(i.componentInstance||t,i.key)})),n.value(i.componentInstance||t,i.key)},update:function(e,t,i,r){if(r.data&&r.data.directives){var a=r.data.directives.find((function(e){return e.name===n}));if(a&&a.value!==t.value)return a&&a.value(null,r.key),void t.value(i.componentInstance||e,i.key)}i.componentInstance===r.componentInstance&&i.elm===r.elm||t.value(i.componentInstance||e,i.key)},unbind:function(e,t,n){t.value(null,n.key)}})}}},function(e,t,n){"use strict";var i=n(2),r=n.n(i),a=n(0),o=n(37);t.a={name:"LocaleReceiver",props:{componentName:a.a.string.def("global"),defaultLocale:a.a.oneOfType([a.a.object,a.a.func]),children:a.a.func},inject:{localeData:{default:function(){return{}}}},methods:{getLocale:function(){var e=this.componentName,t=this.defaultLocale||o.a[e||"global"],n=this.localeData.antLocale,i=e&&n?n[e]:{};return r()({},"function"==typeof t?t():t,i||{})},getLocaleCode:function(){var e=this.localeData.antLocale,t=e&&e.locale;return e&&e.exist&&!t?o.a.locale:t}},render:function(){var e=this.$scopedSlots,t=this.children||e.default,n=this.localeData.antLocale;return t(this.getLocale(),this.getLocaleCode(),n)}}},function(e,t,n){"use strict";function i(e){return e.default||e}n.d(t,"a",(function(){return i}))},function(e,t){e.exports=function(e,t,n,i){var r=n?n.call(i,e,t):void 0;if(void 0!==r)return!!r;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var a=Object.keys(e),o=Object.keys(t);if(a.length!==o.length)return!1;for(var s=Object.prototype.hasOwnProperty.bind(t),c=0;c=0&&n.left>=0&&n.bottom>n.top&&n.right>n.left?n:null}function oe(e){var t,n,i;if(te.isWindow(e)||9===e.nodeType){var r=te.getWindow(e);t={left:te.getWindowScrollLeft(r),top:te.getWindowScrollTop(r)},n=te.viewportWidth(r),i=te.viewportHeight(r)}else t=te.offset(e),n=te.outerWidth(e),i=te.outerHeight(e);return t.width=n,t.height=i,t}function se(e,t){var n=t.charAt(0),i=t.charAt(1),r=e.width,a=e.height,o=e.left,s=e.top;return"c"===n?s+=a/2:"b"===n&&(s+=a),"c"===i?o+=r/2:"r"===i&&(o+=r),{left:o,top:s}}function ce(e,t,n,i,r){var a=se(t,n[1]),o=se(e,n[0]),s=[o.left-a.left,o.top-a.top];return{left:Math.round(e.left-s[0]+i[0]-r[0]),top:Math.round(e.top-s[1]+i[1]-r[1])}}function le(e,t,n){return e.leftn.right}function ue(e,t,n){return e.topn.bottom}function he(e,t,n){var i=[];return te.each(e,(function(e){i.push(e.replace(t,(function(e){return n[e]})))})),i}function de(e,t){return e[t]=-e[t],e}function fe(e,t){return(/%$/.test(e)?parseInt(e.substring(0,e.length-1),10)/100*t:parseInt(e,10))||0}function pe(e,t){e[0]=fe(e[0],t.width),e[1]=fe(e[1],t.height)}function ve(e,t,n,i){var r=n.points,a=n.offset||[0,0],o=n.targetOffset||[0,0],s=n.overflow,c=n.source||e;a=[].concat(a),o=[].concat(o);var l={},u=0,h=ae(c,!(!(s=s||{})||!s.alwaysByViewport)),d=oe(c);pe(a,d),pe(o,t);var f=ce(d,t,r,a,o),p=te.merge(d,f);if(h&&(s.adjustX||s.adjustY)&&i){if(s.adjustX&&le(f,d,h)){var v=he(r,/[lr]/gi,{l:"r",r:"l"}),m=de(a,0),g=de(o,0);(function(e,t,n){return e.left>n.right||e.left+t.widthn.bottom||e.top+t.height=n.left&&r.left+a.width>n.right&&(a.width-=r.left+a.width-n.right),i.adjustX&&r.left+a.width>n.right&&(r.left=Math.max(n.right-a.width,n.left)),i.adjustY&&r.top=n.top&&r.top+a.height>n.bottom&&(a.height-=r.top+a.height-n.bottom),i.adjustY&&r.top+a.height>n.bottom&&(r.top=Math.max(n.bottom-a.height,n.top)),te.mix(r,a)}(f,d,h,l))}return p.width!==d.width&&te.css(c,"width",te.width(c)+p.width-d.width),p.height!==d.height&&te.css(c,"height",te.height(c)+p.height-d.height),te.offset(c,{left:p.left,top:p.top},{useCssRight:n.useCssRight,useCssBottom:n.useCssBottom,useCssTransform:n.useCssTransform,ignoreShake:n.ignoreShake}),{points:r,offset:a,targetOffset:o,overflow:l}}function me(e,t,n){var i=n.target||t;return ve(e,oe(i),n,!function(e,t){var n=ae(e,t),i=oe(e);return!n||i.left+i.width<=n.left||i.top+i.height<=n.top||i.left>=n.right||i.top>=n.bottom}(i,n.overflow&&n.overflow.alwaysByViewport))}function ge(e,t,n){var i,r,a=te.getDocument(e),o=a.defaultView||a.parentWindow,s=te.getWindowScrollLeft(o),c=te.getWindowScrollTop(o),l=te.viewportWidth(o),u=te.viewportHeight(o);i="pageX"in t?t.pageX:s+t.clientX,r="pageY"in t?t.pageY:c+t.clientY;var h=i>=0&&i<=s+l&&r>=0&&r<=c+u;return ve(e,{left:i,top:r,width:0,height:0},function(e){for(var t=1;t1){var r="";i=e("div",{class:r},[this.$slots.default])}else i=this.$slots.default[0];return i}},Ve={props:{hiddenClassName:u.a.string.def(""),prefixCls:u.a.string,visible:u.a.bool},render:function(){var e=arguments[0],t=this.$props,n=t.prefixCls,i=t.visible,r=t.hiddenClassName,a={on:Object(d.k)(this)};return e("div",Me()([a,{class:i?"":r}]),[e(Te,{class:n+"-content",attrs:{visible:i}},[this.$slots.default])])}},Pe=n(47),je=n(4),He={name:"VCTriggerPopup",mixins:[je.a],props:{visible:u.a.bool,getClassNameFromAlign:u.a.func,getRootDomNode:u.a.func,align:u.a.any,destroyPopupOnHide:u.a.bool,prefixCls:u.a.string,getContainer:u.a.func,transitionName:u.a.string,animation:u.a.any,maskAnimation:u.a.string,maskTransitionName:u.a.string,mask:u.a.bool,zIndex:u.a.number,popupClassName:u.a.any,popupStyle:u.a.object.def((function(){return{}})),stretch:u.a.string,point:u.a.shape({pageX:u.a.number,pageY:u.a.number})},data:function(){return this.domEl=null,{stretchChecked:!1,targetWidth:void 0,targetHeight:void 0}},mounted:function(){var e=this;this.$nextTick((function(){e.rootNode=e.getPopupDomNode(),e.setStretchSize()}))},updated:function(){var e=this;this.$nextTick((function(){e.setStretchSize()}))},beforeDestroy:function(){this.$el.parentNode?this.$el.parentNode.removeChild(this.$el):this.$el.remove&&this.$el.remove()},methods:{onAlign:function(e,t){var n=this.$props.getClassNameFromAlign(t);this.currentAlignClassName!==n&&(this.currentAlignClassName=n,e.className=this.getClassName(n));var i=Object(d.k)(this);i.align&&i.align(e,t)},setStretchSize:function(){var e=this.$props,t=e.stretch,n=e.getRootDomNode,i=e.visible,r=this.$data,a=r.stretchChecked,o=r.targetHeight,s=r.targetWidth;if(t&&i){var c=n();if(c){var l=c.offsetHeight,u=c.offsetWidth;o===l&&s===u&&a||this.setState({stretchChecked:!0,targetHeight:l,targetWidth:u})}}else a&&this.setState({stretchChecked:!1})},getPopupDomNode:function(){return this.$refs.popupInstance?this.$refs.popupInstance.$el:null},getTargetElement:function(){return this.$props.getRootDomNode()},getAlignTarget:function(){var e=this.$props.point;return e||this.getTargetElement},getMaskTransitionName:function(){var e=this.$props,t=e.maskTransitionName,n=e.maskAnimation;return!t&&n&&(t=e.prefixCls+"-"+n),t},getTransitionName:function(){var e=this.$props,t=e.transitionName,n=e.animation;return t||("string"==typeof n?t=""+n:n&&n.props&&n.props.name&&(t=n.props.name)),t},getClassName:function(e){return this.$props.prefixCls+" "+this.$props.popupClassName+" "+e},getPopupElement:function(){var e=this,t=this.$createElement,n=this.$props,i=this.$slots,r=this.getTransitionName,o=this.$data,s=o.stretchChecked,c=o.targetHeight,l=o.targetWidth,u=n.align,h=n.visible,f=n.prefixCls,p=n.animation,v=n.popupStyle,m=n.getClassNameFromAlign,b=n.destroyPopupOnHide,y=n.stretch,C=this.getClassName(this.currentAlignClassName||m(u));h||(this.currentAlignClassName=null);var x={};y&&(-1!==y.indexOf("height")?x.height="number"==typeof c?c+"px":c:-1!==y.indexOf("minHeight")&&(x.minHeight="number"==typeof c?c+"px":c),-1!==y.indexOf("width")?x.width="number"==typeof l?l+"px":l:-1!==y.indexOf("minWidth")&&(x.minWidth="number"==typeof l?l+"px":l),s||setTimeout((function(){e.$refs.alignInstance&&e.$refs.alignInstance.forceAlign()}),0));var k={props:{prefixCls:f,visible:h},class:C,on:Object(d.k)(this),ref:"popupInstance",style:a()({},x,v,this.getZIndexStyle())},z={props:{appear:!0,css:!1}},w=r(),S=!!w,O={beforeEnter:function(){},enter:function(t,n){e.$nextTick((function(){e.$refs.alignInstance?e.$refs.alignInstance.$nextTick((function(){e.domEl=t,Object(Pe.a)(t,w+"-enter",n)})):n()}))},beforeLeave:function(){e.domEl=null},leave:function(e,t){Object(Pe.a)(e,w+"-leave",t)}};if("object"===(void 0===p?"undefined":g()(p))){S=!0;var M=p.on,T=void 0===M?{}:M,V=p.props,P=void 0===V?{}:V;z.props=a()({},z.props,P),z.on=a()({},O,T)}else z.on=O;return S||(z={}),t("transition",z,b?[h?t(Se,{attrs:{target:this.getAlignTarget(),monitorWindowResize:!0,align:u},key:"popup",ref:"alignInstance",on:{align:this.onAlign}},[t(Ve,k,[i.default])]):null]:[t(Se,{directives:[{name:"show",value:h}],attrs:{target:this.getAlignTarget(),monitorWindowResize:!0,disabled:!h,align:u},key:"popup",ref:"alignInstance",on:{align:this.onAlign}},[t(Ve,k,[i.default])])])},getZIndexStyle:function(){var e={},t=this.$props;return void 0!==t.zIndex&&(e.zIndex=t.zIndex),e},getMaskElement:function(){var e=this.$createElement,t=this.$props,n=null;if(t.mask){var i=this.getMaskTransitionName();n=e(Te,{directives:[{name:"show",value:t.visible}],style:this.getZIndexStyle(),key:"mask",class:t.prefixCls+"-mask",attrs:{visible:t.visible}}),i&&(n=e("transition",{attrs:{appear:!0,name:i}},[n]))}return n}},render:function(){var e=arguments[0],t=this.getMaskElement,n=this.getPopupElement;return e("div",[t(),n()])}};function _e(e,t,n){return n?e[0]===t[0]:e[0]===t[0]&&e[1]===t[1]}function Le(){}var Fe={props:{autoMount:u.a.bool.def(!0),autoDestroy:u.a.bool.def(!0),visible:u.a.bool,forceRender:u.a.bool.def(!1),parent:u.a.any,getComponent:u.a.func.isRequired,getContainer:u.a.func.isRequired,children:u.a.func.isRequired},mounted:function(){this.autoMount&&this.renderComponent()},updated:function(){this.autoMount&&this.renderComponent()},beforeDestroy:function(){this.autoDestroy&&this.removeContainer()},methods:{removeContainer:function(){this.container&&(this._component&&this._component.$destroy(),this.container.parentNode.removeChild(this.container),this.container=null,this._component=null)},renderComponent:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments[1],n=this.visible,i=this.forceRender,r=this.getContainer,a=this.parent,o=this;if(n||a._component||a.$refs._component||i){var s=this.componentEl;this.container||(this.container=r(),s=document.createElement("div"),this.componentEl=s,this.container.appendChild(s));var c={component:o.getComponent(e)};this._component?this._component.setComponent(c):this._component=new this.$root.constructor({el:s,parent:o,data:{_com:c},mounted:function(){this.$nextTick((function(){t&&t.call(o)}))},updated:function(){this.$nextTick((function(){t&&t.call(o)}))},methods:{setComponent:function(e){this.$data._com=e}},render:function(){return this.$data._com.component}})}}},render:function(){return this.children({renderComponent:this.renderComponent,removeContainer:this.removeContainer})}};s.a.use(l.a,{name:"ant-ref"});var Ee=["click","mousedown","touchstart","mouseenter","mouseleave","focus","blur","contextmenu"],Ae={name:"Trigger",mixins:[je.a],props:{action:u.a.oneOfType([u.a.string,u.a.arrayOf(u.a.string)]).def([]),showAction:u.a.any.def([]),hideAction:u.a.any.def([]),getPopupClassNameFromAlign:u.a.any.def((function(){return""})),afterPopupVisibleChange:u.a.func.def(Le),popup:u.a.any,popupStyle:u.a.object.def((function(){return{}})),prefixCls:u.a.string.def("rc-trigger-popup"),popupClassName:u.a.string.def(""),popupPlacement:u.a.string,builtinPlacements:u.a.object,popupTransitionName:u.a.oneOfType([u.a.string,u.a.object]),popupAnimation:u.a.any,mouseEnterDelay:u.a.number.def(0),mouseLeaveDelay:u.a.number.def(.1),zIndex:u.a.number,focusDelay:u.a.number.def(0),blurDelay:u.a.number.def(.15),getPopupContainer:u.a.func,getDocument:u.a.func.def((function(){return window.document})),forceRender:u.a.bool,destroyPopupOnHide:u.a.bool.def(!1),mask:u.a.bool.def(!1),maskClosable:u.a.bool.def(!0),popupAlign:u.a.object.def((function(){return{}})),popupVisible:u.a.bool,defaultPopupVisible:u.a.bool.def(!1),maskTransitionName:u.a.oneOfType([u.a.string,u.a.object]),maskAnimation:u.a.string,stretch:u.a.string,alignPoint:u.a.bool},provide:function(){return{vcTriggerContext:this}},inject:{vcTriggerContext:{default:function(){return{}}},savePopupRef:{default:function(){return Le}},dialogContext:{default:function(){return null}}},data:function(){var e=this,t=this.$props,n=void 0;return n=Object(d.s)(this,"popupVisible")?!!t.popupVisible:!!t.defaultPopupVisible,Ee.forEach((function(t){e["fire"+t]=function(n){e.fireEvents(t,n)}})),{prevPopupVisible:n,sPopupVisible:n,point:null}},watch:{popupVisible:function(e){void 0!==e&&(this.prevPopupVisible=this.sPopupVisible,this.sPopupVisible=e)}},deactivated:function(){this.setPopupVisible(!1)},mounted:function(){var e=this;this.$nextTick((function(){e.renderComponent(null),e.updatedCal()}))},updated:function(){var e=this;this.renderComponent(null,(function(){e.sPopupVisible!==e.prevPopupVisible&&e.afterPopupVisibleChange(e.sPopupVisible),e.prevPopupVisible=e.sPopupVisible})),this.$nextTick((function(){e.updatedCal()}))},beforeDestroy:function(){this.clearDelayTimer(),this.clearOutsideHandler(),clearTimeout(this.mouseDownTimeout)},methods:{updatedCal:function(){var e=this.$props;if(this.$data.sPopupVisible){var t=void 0;this.clickOutsideHandler||!this.isClickToHide()&&!this.isContextmenuToShow()||(t=e.getDocument(),this.clickOutsideHandler=Object(p.a)(t,"mousedown",this.onDocumentClick)),this.touchOutsideHandler||(t=t||e.getDocument(),this.touchOutsideHandler=Object(p.a)(t,"touchstart",this.onDocumentClick)),!this.contextmenuOutsideHandler1&&this.isContextmenuToShow()&&(t=t||e.getDocument(),this.contextmenuOutsideHandler1=Object(p.a)(t,"scroll",this.onContextmenuClose)),!this.contextmenuOutsideHandler2&&this.isContextmenuToShow()&&(this.contextmenuOutsideHandler2=Object(p.a)(window,"blur",this.onContextmenuClose))}else this.clearOutsideHandler()},onMouseenter:function(e){var t=this.$props.mouseEnterDelay;this.fireEvents("mouseenter",e),this.delaySetPopupVisible(!0,t,t?null:e)},onMouseMove:function(e){this.fireEvents("mousemove",e),this.setPoint(e)},onMouseleave:function(e){this.fireEvents("mouseleave",e),this.delaySetPopupVisible(!1,this.$props.mouseLeaveDelay)},onPopupMouseenter:function(){this.clearDelayTimer()},onPopupMouseleave:function(e){e&&e.relatedTarget&&!e.relatedTarget.setTimeout&&this._component&&this._component.getPopupDomNode&&Object(h.a)(this._component.getPopupDomNode(),e.relatedTarget)||this.delaySetPopupVisible(!1,this.$props.mouseLeaveDelay)},onFocus:function(e){this.fireEvents("focus",e),this.clearDelayTimer(),this.isFocusToShow()&&(this.focusTime=Date.now(),this.delaySetPopupVisible(!0,this.$props.focusDelay))},onMousedown:function(e){this.fireEvents("mousedown",e),this.preClickTime=Date.now()},onTouchstart:function(e){this.fireEvents("touchstart",e),this.preTouchTime=Date.now()},onBlur:function(e){Object(h.a)(e.target,e.relatedTarget||document.activeElement)||(this.fireEvents("blur",e),this.clearDelayTimer(),this.isBlurToHide()&&this.delaySetPopupVisible(!1,this.$props.blurDelay))},onContextmenu:function(e){e.preventDefault(),this.fireEvents("contextmenu",e),this.setPopupVisible(!0,e)},onContextmenuClose:function(){this.isContextmenuToShow()&&this.close()},onClick:function(e){if(this.fireEvents("click",e),this.focusTime){var t=void 0;if(this.preClickTime&&this.preTouchTime?t=Math.min(this.preClickTime,this.preTouchTime):this.preClickTime?t=this.preClickTime:this.preTouchTime&&(t=this.preTouchTime),Math.abs(t-this.focusTime)<20)return;this.focusTime=0}this.preClickTime=0,this.preTouchTime=0,this.isClickToShow()&&(this.isClickToHide()||this.isBlurToHide())&&e&&e.preventDefault&&e.preventDefault(),e&&e.domEvent&&e.domEvent.preventDefault();var n=!this.$data.sPopupVisible;(this.isClickToHide()&&!n||n&&this.isClickToShow())&&this.setPopupVisible(!this.$data.sPopupVisible,e)},onPopupMouseDown:function(){var e=this,t=this.vcTriggerContext,n=void 0===t?{}:t;this.hasPopupMouseDown=!0,clearTimeout(this.mouseDownTimeout),this.mouseDownTimeout=setTimeout((function(){e.hasPopupMouseDown=!1}),0),n.onPopupMouseDown&&n.onPopupMouseDown.apply(n,arguments)},onDocumentClick:function(e){if(!this.$props.mask||this.$props.maskClosable){var t=e.target,n=this.$el;Object(h.a)(n,t)||this.hasPopupMouseDown||this.close()}},getPopupDomNode:function(){return this._component&&this._component.getPopupDomNode?this._component.getPopupDomNode():null},getRootDomNode:function(){return this.$el},handleGetPopupClassFromAlign:function(e){var t=[],n=this.$props,i=n.popupPlacement,r=n.builtinPlacements,a=n.prefixCls,o=n.alignPoint,s=n.getPopupClassNameFromAlign;return i&&r&&t.push(function(e,t,n,i){var r=n.points;for(var a in e)if(e.hasOwnProperty(a)&&_e(e[a].points,r,i))return t+"-placement-"+a;return""}(r,a,e,o)),s&&t.push(s(e)),t.join(" ")},getPopupAlign:function(){var e=this.$props,t=e.popupPlacement,n=e.popupAlign,i=e.builtinPlacements;return t&&i?function(e,t,n){var i=e[t]||{};return a()({},i,n)}(i,t,n):n},savePopup:function(e){this._component=e,this.savePopupRef(e)},getComponent:function(){var e=this.$createElement,t={};this.isMouseEnterToShow()&&(t.mouseenter=this.onPopupMouseenter),this.isMouseLeaveToHide()&&(t.mouseleave=this.onPopupMouseleave),t.mousedown=this.onPopupMouseDown,t.touchstart=this.onPopupMouseDown;var n=this.handleGetPopupClassFromAlign,i=this.getRootDomNode,r=this.getContainer,o=this.$props,s=o.prefixCls,c=o.destroyPopupOnHide,l=o.popupClassName,u=o.action,h=o.popupAnimation,f=o.popupTransitionName,p=o.popupStyle,v=o.mask,m=o.maskAnimation,g=o.maskTransitionName,b=o.zIndex,y=o.stretch,C=o.alignPoint,x=this.$data,k=x.sPopupVisible,z=x.point,w={props:{prefixCls:s,destroyPopupOnHide:c,visible:k,point:C&&z,action:u,align:this.getPopupAlign(),animation:h,getClassNameFromAlign:n,stretch:y,getRootDomNode:i,mask:v,zIndex:b,transitionName:f,maskAnimation:m,maskTransitionName:g,getContainer:r,popupClassName:l,popupStyle:p},on:a()({align:Object(d.k)(this).popupAlign||Le},t),directives:[{name:"ant-ref",value:this.savePopup}]};return e(He,w,[Object(d.g)(this,"popup")])},getContainer:function(){var e=this.$props,t=this.dialogContext,n=document.createElement("div");return n.style.position="absolute",n.style.top="0",n.style.left="0",n.style.width="100%",(e.getPopupContainer?e.getPopupContainer(this.$el,t):e.getDocument().body).appendChild(n),this.popupContainer=n,n},setPopupVisible:function(e,t){var n=this.alignPoint,i=this.sPopupVisible;if(this.clearDelayTimer(),i!==e){Object(d.s)(this,"popupVisible")||this.setState({sPopupVisible:e,prevPopupVisible:i});var r=Object(d.k)(this);r.popupVisibleChange&&r.popupVisibleChange(e)}n&&t&&this.setPoint(t)},setPoint:function(e){this.$props.alignPoint&&e&&this.setState({point:{pageX:e.pageX,pageY:e.pageY}})},delaySetPopupVisible:function(e,t,n){var i=this,r=1e3*t;if(this.clearDelayTimer(),r){var a=n?{pageX:n.pageX,pageY:n.pageY}:null;this.delayTimer=Object(f.b)((function(){i.setPopupVisible(e,a),i.clearDelayTimer()}),r)}else this.setPopupVisible(e,n)},clearDelayTimer:function(){this.delayTimer&&(Object(f.a)(this.delayTimer),this.delayTimer=null)},clearOutsideHandler:function(){this.clickOutsideHandler&&(this.clickOutsideHandler.remove(),this.clickOutsideHandler=null),this.contextmenuOutsideHandler1&&(this.contextmenuOutsideHandler1.remove(),this.contextmenuOutsideHandler1=null),this.contextmenuOutsideHandler2&&(this.contextmenuOutsideHandler2.remove(),this.contextmenuOutsideHandler2=null),this.touchOutsideHandler&&(this.touchOutsideHandler.remove(),this.touchOutsideHandler=null)},createTwoChains:function(e){var t=function(){},n=Object(d.k)(this);return this.childOriginEvents[e]&&n[e]?this["fire"+e]:t=this.childOriginEvents[e]||n[e]||t},isClickToShow:function(){var e=this.$props,t=e.action,n=e.showAction;return-1!==t.indexOf("click")||-1!==n.indexOf("click")},isContextmenuToShow:function(){var e=this.$props,t=e.action,n=e.showAction;return-1!==t.indexOf("contextmenu")||-1!==n.indexOf("contextmenu")},isClickToHide:function(){var e=this.$props,t=e.action,n=e.hideAction;return-1!==t.indexOf("click")||-1!==n.indexOf("click")},isMouseEnterToShow:function(){var e=this.$props,t=e.action,n=e.showAction;return-1!==t.indexOf("hover")||-1!==n.indexOf("mouseenter")},isMouseLeaveToHide:function(){var e=this.$props,t=e.action,n=e.hideAction;return-1!==t.indexOf("hover")||-1!==n.indexOf("mouseleave")},isFocusToShow:function(){var e=this.$props,t=e.action,n=e.showAction;return-1!==t.indexOf("focus")||-1!==n.indexOf("focus")},isBlurToHide:function(){var e=this.$props,t=e.action,n=e.hideAction;return-1!==t.indexOf("focus")||-1!==n.indexOf("blur")},forcePopupAlign:function(){this.$data.sPopupVisible&&this._component&&this._component.$refs.alignInstance&&this._component.$refs.alignInstance.forceAlign()},fireEvents:function(e,t){this.childOriginEvents[e]&&this.childOriginEvents[e](t),this.__emit(e,t)},close:function(){this.setPopupVisible(!1)}},render:function(){var e=this,t=arguments[0],n=this.sPopupVisible,i=Object(d.c)(this.$slots.default),r=this.$props,a=r.forceRender,o=r.alignPoint;i.length>1&&Object(v.a)(!1,"Trigger $slots.default.length > 1, just support only one default",!0);var s=i[0];this.childOriginEvents=Object(d.h)(s);var c={props:{},nativeOn:{},key:"trigger"};return this.isContextmenuToShow()?c.nativeOn.contextmenu=this.onContextmenu:c.nativeOn.contextmenu=this.createTwoChains("contextmenu"),this.isClickToHide()||this.isClickToShow()?(c.nativeOn.click=this.onClick,c.nativeOn.mousedown=this.onMousedown,c.nativeOn.touchstart=this.onTouchstart):(c.nativeOn.click=this.createTwoChains("click"),c.nativeOn.mousedown=this.createTwoChains("mousedown"),c.nativeOn.touchstart=this.createTwoChains("onTouchstart")),this.isMouseEnterToShow()?(c.nativeOn.mouseenter=this.onMouseenter,o&&(c.nativeOn.mousemove=this.onMouseMove)):c.nativeOn.mouseenter=this.createTwoChains("mouseenter"),this.isMouseLeaveToHide()?c.nativeOn.mouseleave=this.onMouseleave:c.nativeOn.mouseleave=this.createTwoChains("mouseleave"),this.isFocusToShow()||this.isBlurToHide()?(c.nativeOn.focus=this.onFocus,c.nativeOn.blur=this.onBlur):(c.nativeOn.focus=this.createTwoChains("focus"),c.nativeOn.blur=function(t){!t||t.relatedTarget&&Object(h.a)(t.target,t.relatedTarget)||e.createTwoChains("blur")(t)}),this.trigger=Object(Ce.a)(s,c),t(Fe,{attrs:{parent:this,visible:n,autoMount:!1,forceRender:a,getComponent:this.getComponent,getContainer:this.getContainer,children:function(t){var n=t.renderComponent;return e.renderComponent=n,e.trigger}}})}};t.a=Ae},function(e,t,n){var i=n(34),r=n(349),a=n(198),o=Math.max,s=Math.min;e.exports=function(e,t,n){var c,l,u,h,d,f,p=0,v=!1,m=!1,g=!0;if("function"!=typeof e)throw new TypeError("Expected a function");function b(t){var n=c,i=l;return c=l=void 0,p=t,h=e.apply(i,n)}function y(e){return p=e,d=setTimeout(x,t),v?b(e):h}function C(e){var n=e-f;return void 0===f||n>=t||n<0||m&&e-p>=u}function x(){var e=r();if(C(e))return k(e);d=setTimeout(x,function(e){var n=t-(e-f);return m?s(n,u-(e-p)):n}(e))}function k(e){return d=void 0,g&&c?b(e):(c=l=void 0,h)}function z(){var e=r(),n=C(e);if(c=arguments,l=this,f=e,n){if(void 0===d)return y(f);if(m)return clearTimeout(d),d=setTimeout(x,t),b(f)}return void 0===d&&(d=setTimeout(x,t)),h}return t=a(t)||0,i(n)&&(v=!!n.leading,u=(m="maxWait"in n)?o(a(n.maxWait)||0,t):u,g="trailing"in n?!!n.trailing:g),z.cancel=function(){void 0!==d&&clearTimeout(d),p=0,c=f=l=d=void 0},z.flush=function(){return void 0===d?h:k(r())},z}},function(e,t,n){"use strict";var i=n(3),r=n.n(i),a=n(2),o=n.n(a),s=n(9),c=n(12),l=n.n(c),u=n(0),h=n(29),d={adjustX:1,adjustY:1},f=[0,0],p={left:{points:["cr","cl"],overflow:d,offset:[-4,0],targetOffset:f},right:{points:["cl","cr"],overflow:d,offset:[4,0],targetOffset:f},top:{points:["bc","tc"],overflow:d,offset:[0,-4],targetOffset:f},bottom:{points:["tc","bc"],overflow:d,offset:[0,4],targetOffset:f},topLeft:{points:["bl","tl"],overflow:d,offset:[0,-4],targetOffset:f},leftTop:{points:["tr","tl"],overflow:d,offset:[-4,0],targetOffset:f},topRight:{points:["br","tr"],overflow:d,offset:[0,-4],targetOffset:f},rightTop:{points:["tl","tr"],overflow:d,offset:[4,0],targetOffset:f},bottomRight:{points:["tr","br"],overflow:d,offset:[0,4],targetOffset:f},rightBottom:{points:["bl","br"],overflow:d,offset:[4,0],targetOffset:f},bottomLeft:{points:["tl","bl"],overflow:d,offset:[0,4],targetOffset:f},leftBottom:{points:["br","bl"],overflow:d,offset:[-4,0],targetOffset:f}},v={props:{prefixCls:u.a.string,overlay:u.a.any,trigger:u.a.any},updated:function(){var e=this.trigger;e&&e.forcePopupAlign()},render:function(){var e=arguments[0],t=this.overlay,n=this.prefixCls;return e("div",{class:n+"-inner",attrs:{role:"tooltip"}},["function"==typeof t?t():t])}},m=n(1);function g(){}var b={props:{trigger:u.a.any.def(["hover"]),defaultVisible:u.a.bool,visible:u.a.bool,placement:u.a.string.def("right"),transitionName:u.a.oneOfType([u.a.string,u.a.object]),animation:u.a.any,afterVisibleChange:u.a.func.def((function(){})),overlay:u.a.any,overlayStyle:u.a.object,overlayClassName:u.a.string,prefixCls:u.a.string.def("rc-tooltip"),mouseEnterDelay:u.a.number.def(0),mouseLeaveDelay:u.a.number.def(.1),getTooltipContainer:u.a.func,destroyTooltipOnHide:u.a.bool.def(!1),align:u.a.object.def((function(){return{}})),arrowContent:u.a.any.def(null),tipId:u.a.string,builtinPlacements:u.a.object},methods:{getPopupElement:function(){var e=this.$createElement,t=this.$props,n=t.prefixCls,i=t.tipId;return[e("div",{class:n+"-arrow",key:"arrow"},[Object(m.g)(this,"arrowContent")]),e(v,{key:"content",attrs:{trigger:this.$refs.trigger,prefixCls:n,id:i,overlay:Object(m.g)(this,"overlay")}})]},getPopupDomNode:function(){return this.$refs.trigger.getPopupDomNode()}},render:function(e){var t=Object(m.l)(this),n=t.overlayClassName,i=t.trigger,r=t.mouseEnterDelay,a=t.mouseLeaveDelay,s=t.overlayStyle,c=t.prefixCls,u=t.afterVisibleChange,d=t.transitionName,f=t.animation,v=t.placement,b=t.align,y=t.destroyTooltipOnHide,C=t.defaultVisible,x=t.getTooltipContainer,k=l()(t,["overlayClassName","trigger","mouseEnterDelay","mouseLeaveDelay","overlayStyle","prefixCls","afterVisibleChange","transitionName","animation","placement","align","destroyTooltipOnHide","defaultVisible","getTooltipContainer"]),z=o()({},k);Object(m.s)(this,"visible")&&(z.popupVisible=this.$props.visible);var w=Object(m.k)(this),S={props:o()({popupClassName:n,prefixCls:c,action:i,builtinPlacements:p,popupPlacement:v,popupAlign:b,getPopupContainer:x,afterPopupVisibleChange:u,popupTransitionName:d,popupAnimation:f,defaultPopupVisible:C,destroyPopupOnHide:y,mouseLeaveDelay:a,popupStyle:s,mouseEnterDelay:r},z),on:o()({},w,{popupVisibleChange:w.visibleChange||g,popupAlign:w.popupAlign||g}),ref:"trigger"};return e(h.a,S,[e("template",{slot:"popup"},[this.getPopupElement(e)]),this.$slots.default])}},y={adjustX:1,adjustY:1},C={adjustX:0,adjustY:0},x=[0,0];function k(e){return"boolean"==typeof e?e?y:C:o()({},C,e)}var z=n(7),w=n(55),S=Object(w.a)(),O={name:"ATooltip",model:{prop:"visible",event:"visibleChange"},props:o()({},S,{title:u.a.any}),inject:{configProvider:{default:function(){return z.a}}},data:function(){return{sVisible:!!this.$props.visible||!!this.$props.defaultVisible}},watch:{visible:function(e){this.sVisible=e}},methods:{onVisibleChange:function(e){Object(m.s)(this,"visible")||(this.sVisible=!this.isNoTitle()&&e),this.isNoTitle()||this.$emit("visibleChange",e)},getPopupDomNode:function(){return this.$refs.tooltip.getPopupDomNode()},getPlacements:function(){var e=this.$props,t=e.builtinPlacements,n=e.arrowPointAtCenter,i=e.autoAdjustOverflow;return t||function(e){var t=e.arrowWidth,n=void 0===t?5:t,i=e.horizontalArrowShift,r=void 0===i?16:i,a=e.verticalArrowShift,s=void 0===a?12:a,c=e.autoAdjustOverflow,l=void 0===c||c,u={left:{points:["cr","cl"],offset:[-4,0]},right:{points:["cl","cr"],offset:[4,0]},top:{points:["bc","tc"],offset:[0,-4]},bottom:{points:["tc","bc"],offset:[0,4]},topLeft:{points:["bl","tc"],offset:[-(r+n),-4]},leftTop:{points:["tr","cl"],offset:[-4,-(s+n)]},topRight:{points:["br","tc"],offset:[r+n,-4]},rightTop:{points:["tl","cr"],offset:[4,-(s+n)]},bottomRight:{points:["tr","bc"],offset:[r+n,4]},rightBottom:{points:["bl","cr"],offset:[4,s+n]},bottomLeft:{points:["tl","bc"],offset:[-(r+n),4]},leftBottom:{points:["br","cl"],offset:[-4,s+n]}};return Object.keys(u).forEach((function(t){u[t]=e.arrowPointAtCenter?o()({},u[t],{overflow:k(l),targetOffset:x}):o()({},p[t],{overflow:k(l)}),u[t].ignoreShake=!0})),u}({arrowPointAtCenter:n,verticalArrowShift:8,autoAdjustOverflow:i})},getDisabledCompatibleChildren:function(e){var t=this.$createElement,n=e.componentOptions&&e.componentOptions.Ctor.options||{};if((!0===n.__ANT_BUTTON||!0===n.__ANT_SWITCH||!0===n.__ANT_CHECKBOX)&&(e.componentOptions.propsData.disabled||""===e.componentOptions.propsData.disabled)||"button"===e.tag&&e.data&&e.data.attrs&&void 0!==e.data.attrs.disabled){var i=function(e,t){var n={},i=o()({},e);return t.forEach((function(t){e&&t in e&&(n[t]=e[t],delete i[t])})),{picked:n,omitted:i}}(Object(m.q)(e),["position","left","right","top","bottom","float","display","zIndex"]),r=i.picked,a=i.omitted,c=o()({display:"inline-block"},r,{cursor:"not-allowed",width:e.componentOptions.propsData.block?"100%":null}),l=o()({},a,{pointerEvents:"none"});return t("span",{style:c,class:Object(m.f)(e)},[Object(s.a)(e,{style:l,class:null})])}return e},isNoTitle:function(){var e=Object(m.g)(this,"title");return!e&&0!==e},getOverlay:function(){var e=Object(m.g)(this,"title");return 0===e?e:e||""},onPopupAlign:function(e,t){var n=this.getPlacements(),i=Object.keys(n).filter((function(e){return n[e].points[0]===t.points[0]&&n[e].points[1]===t.points[1]}))[0];if(i){var r=e.getBoundingClientRect(),a={top:"50%",left:"50%"};i.indexOf("top")>=0||i.indexOf("Bottom")>=0?a.top=r.height-t.offset[1]+"px":(i.indexOf("Top")>=0||i.indexOf("bottom")>=0)&&(a.top=-t.offset[1]+"px"),i.indexOf("left")>=0||i.indexOf("Right")>=0?a.left=r.width-t.offset[0]+"px":(i.indexOf("right")>=0||i.indexOf("Left")>=0)&&(a.left=-t.offset[0]+"px"),e.style.transformOrigin=a.left+" "+a.top}}},render:function(){var e=arguments[0],t=this.$props,n=this.$data,i=this.$slots,a=t.prefixCls,c=t.openClassName,l=t.getPopupContainer,u=this.configProvider.getPopupContainer,h=this.configProvider.getPrefixCls,d=h("tooltip",a),f=(i.default||[]).filter((function(e){return e.tag||""!==e.text.trim()}));f=1===f.length?f[0]:f;var p=n.sVisible;if(!Object(m.s)(this,"visible")&&this.isNoTitle()&&(p=!1),!f)return null;var v=this.getDisabledCompatibleChildren(Object(m.w)(f)?f:e("span",[f])),g=r()({},c||d+"-open",!0),y={props:o()({},t,{prefixCls:d,getTooltipContainer:l||u,builtinPlacements:this.getPlacements(),overlay:this.getOverlay(),visible:p}),ref:"tooltip",on:o()({},Object(m.k)(this),{visibleChange:this.onVisibleChange,popupAlign:this.onPopupAlign})};return e(b,y,[p?Object(s.a)(v,{class:g}):v])}},M=n(10);O.install=function(e){e.use(M.a),e.component(O.name,O)};t.a=O},function(e,t,n){"use strict";n.d(t,"a",(function(){return a})),n.d(t,"b",(function(){return o}));var i=["moz","ms","webkit"];var r=function(){if("undefined"==typeof window)return function(){};if(window.requestAnimationFrame)return window.requestAnimationFrame.bind(window);var e,t=i.filter((function(e){return e+"RequestAnimationFrame"in window}))[0];return t?window[t+"RequestAnimationFrame"]:(e=0,function(t){var n=(new Date).getTime(),i=Math.max(0,16-(n-e)),r=window.setTimeout((function(){t(n+i)}),i);return e=n+i,r})}(),a=function(e){return function(e){if("undefined"==typeof window)return null;if(window.cancelAnimationFrame)return window.cancelAnimationFrame(e);var t=i.filter((function(e){return e+"CancelAnimationFrame"in window||e+"CancelRequestAnimationFrame"in window}))[0];return t?(window[t+"CancelAnimationFrame"]||window[t+"CancelRequestAnimationFrame"]).call(this,e):clearTimeout(e)}(e.id)},o=function(e,t){var n=Date.now();var i={id:r((function a(){Date.now()-n>=t?e.call():i.id=r(a)}))};return i}},function(e,t,n){var i=n(217);e.exports=function(e,t,n){return null==e?e:i(e,t,n)}},function(e,t){e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},function(e,t){var n=Array.isArray;e.exports=n},function(e,t,n){var i=n(64),r=n(138),a=n(45),o=Function.prototype,s=Object.prototype,c=o.toString,l=s.hasOwnProperty,u=c.call(Object);e.exports=function(e){if(!a(e)||"[object Object]"!=i(e))return!1;var t=r(e);if(null===t)return!0;var n=l.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&c.call(n)==u}},function(e,t,n){"use strict";var i=n(85);t.a=i.a},function(e,t,n){"use strict";n.d(t,"a",(function(){return a})),n.d(t,"b",(function(){return o})),n.d(t,"c",(function(){return s})),n.d(t,"d",(function(){return c})),n.d(t,"g",(function(){return l})),n.d(t,"e",(function(){return h})),n.d(t,"f",(function(){return d}));var i=n(2),r=n.n(i);function a(){return!0}function o(e){return r()({},e,{lastModified:e.lastModified,lastModifiedDate:e.lastModifiedDate,name:e.name,size:e.size,type:e.type,uid:e.uid,percent:0,originFileObj:e})}function s(){var e=.1;return function(t){var n=t;return n>=.98||(n+=e,(e-=.01)<.001&&(e=.001)),n}}function c(e,t){var n=void 0!==e.uid?"uid":"name";return t.filter((function(t){return t[n]===e[n]}))[0]}function l(e,t){var n=void 0!==e.uid?"uid":"name",i=t.filter((function(t){return t[n]!==e[n]}));return i.length===t.length?null:i}var u=function(e){return!!e&&0===e.indexOf("image/")},h=function(e){if(u(e.type))return!0;var t=e.thumbUrl||e.url,n=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=e.split("/"),n=t[t.length-1],i=n.split(/#|\?/)[0];return(/\.[^./\\]*$/.exec(i)||[""])[0]}(t);return!(!/^data:image\//.test(t)&&!/(webp|svg|png|gif|jpg|jpeg|jfif|bmp|dpg|ico)$/i.test(n))||!/^data:/.test(t)&&!n};function d(e){return new Promise((function(t){if(u(e.type)){var n=document.createElement("canvas");n.width=200,n.height=200,n.style.cssText="position: fixed; left: 0; top: 0; width: 200px; height: 200px; z-index: 9999; display: none;",document.body.appendChild(n);var i=n.getContext("2d"),r=new Image;r.onload=function(){var e=r.width,a=r.height,o=200,s=200,c=0,l=0;e0},e.prototype.connect_=function(){i&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),s?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){i&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(e){var t=e.propertyName,n=void 0===t?"":t;o.some((function(e){return!!~n.indexOf(e)}))&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),l=function(e,t){for(var n=0,i=Object.keys(t);n0},e}(),x="undefined"!=typeof WeakMap?new WeakMap:new n,k=function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var n=c.getInstance(),i=new C(t,n,this);x.set(this,i)};["observe","unobserve","disconnect"].forEach((function(e){k.prototype[e]=function(){var t;return(t=x.get(this))[e].apply(t,arguments)}}));var z=void 0!==r.ResizeObserver?r.ResizeObserver:k;t.a=z}).call(this,n(137))},function(e,t,n){"use strict";t.__esModule=!0,t.default=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t,n){"use strict";var i=n(0),r=i.a.oneOf(["hover","focus","click","contextmenu"]);t.a=function(){return{trigger:i.a.oneOfType([r,i.a.arrayOf(r)]).def("hover"),visible:i.a.bool,defaultVisible:i.a.bool,placement:i.a.oneOf(["top","left","right","bottom","topLeft","topRight","bottomLeft","bottomRight","leftTop","leftBottom","rightTop","rightBottom"]).def("top"),transitionName:i.a.string.def("zoom-big-fast"),overlayStyle:i.a.object.def((function(){return{}})),overlayClassName:i.a.string,prefixCls:i.a.string,mouseEnterDelay:i.a.number.def(.1),mouseLeaveDelay:i.a.number.def(.1),getPopupContainer:i.a.func,arrowPointAtCenter:i.a.bool.def(!1),autoAdjustOverflow:i.a.oneOfType([i.a.bool,i.a.object]).def(!0),destroyTooltipOnHide:i.a.bool.def(!1),align:i.a.object.def((function(){return{}})),builtinPlacements:i.a.object}}},function(e,t,n){"use strict";n.d(t,"a",(function(){return s})),n.d(t,"b",(function(){return c}));var i=n(2),r=n.n(i),a=n(85),o=r()({},a.a.Modal);function s(e){o=e?r()({},o,e):r()({},a.a.Modal)}function c(){return o}},function(e,t,n){try{var i=n(182)}catch(e){i=n(182)}var r=/\s+/,a=Object.prototype.toString;function o(e){if(!e||!e.nodeType)throw new Error("A DOM element reference is required");this.el=e,this.list=e.classList}e.exports=function(e){return new o(e)},o.prototype.add=function(e){if(this.list)return this.list.add(e),this;var t=this.array();return~i(t,e)||t.push(e),this.el.className=t.join(" "),this},o.prototype.remove=function(e){if("[object RegExp]"==a.call(e))return this.removeMatching(e);if(this.list)return this.list.remove(e),this;var t=this.array(),n=i(t,e);return~n&&t.splice(n,1),this.el.className=t.join(" "),this},o.prototype.removeMatching=function(e){for(var t=this.array(),n=0;n0&&void 0!==arguments[0]?arguments[0]:{};return Object.keys(e).reduce((function(t,n){var i=e[n];switch(n){case"class":t.className=i,delete t.class;break;default:t[n]=i}return t}),{})}var f=function(){function e(){o()(this,e),this.collection={}}return c()(e,[{key:"clear",value:function(){this.collection={}}},{key:"delete",value:function(e){return delete this.collection[e]}},{key:"get",value:function(e){return this.collection[e]}},{key:"has",value:function(e){return Boolean(this.collection[e])}},{key:"set",value:function(e,t){return this.collection[e]=t,this}},{key:"size",get:function(){return Object.keys(this.collection).length}}]),e}();function p(e,t,n,i){return e(t.tag,i?r()({key:n},i,{attrs:r()({},d(t.attrs),i.attrs)}):{key:n,attrs:r()({},d(t.attrs))},(t.children||[]).map((function(i,r){return p(e,i,n+"-"+t.tag+"-"+r)})))}function v(e){return Object(l.generate)(e)[0]}function m(e,t){switch(t){case"fill":return e+"-fill";case"outline":return e+"-o";case"twotone":return e+"-twotone";default:throw new TypeError("Unknown theme type: "+t+", name: "+e)}}}).call(this,n(101))},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t,n){var i=n(74),r=n(274),a=n(275),o=i?i.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":o&&o in Object(e)?r(e):a(e)}},function(e,t,n){var i=n(306),r=n(309);e.exports=function(e,t){var n=r(e,t);return i(n)?n:void 0}},function(e,t){e.exports=function(e,t){return e===t||e!=e&&t!=t}},function(e,t,n){"use strict";var i=n(2),r=n.n(i),a=n(46),o=n(68),s={lang:r()({placeholder:"Select date",rangePlaceholder:["Start date","End date"]},a.a),timePickerLocale:r()({},o.a)};t.a=s},function(e,t,n){"use strict";t.a={placeholder:"Select time"}},function(e,t,n){e.exports=function(){"use strict";return function(e,t,n){(n=n||{}).childrenKeyName=n.childrenKeyName||"children";var i=e||[],r=[],a=0;do{var o=i.filter((function(e){return t(e,a)}))[0];if(!o)break;r.push(o),i=o[n.childrenKeyName]||[],a+=1}while(i.length>0);return r}}()},function(e,t,n){var i=n(51),r=n(90);e.exports=n(52)?function(e,t,n){return i.f(e,t,r(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){var i=n(88);e.exports=function(e){if(!i(e))throw TypeError(e+" is not an object!");return e}},function(e,t,n){var i=n(172),r=n(127);e.exports=function(e){return i(r(e))}},function(e,t){e.exports={}},function(e,t,n){var i=n(40).Symbol;e.exports=i},function(e,t,n){var i=n(142),r=n(143);e.exports=function(e,t,n,a){var o=!n;n||(n={});for(var s=-1,c=t.length;++s100?100:e}var b=function(e){var t=e.from,n=void 0===t?"#1890ff":t,i=e.to,r=void 0===i?"#1890ff":i,a=e.direction,o=void 0===a?"to right":a,s=p()(e,["from","to","direction"]);return 0!==Object.keys(s).length?{backgroundImage:"linear-gradient("+o+", "+function(e){var t=[],n=!0,i=!1,r=void 0;try{for(var a,o=Object.entries(e)[Symbol.iterator]();!(n=(a=o.next()).done);n=!0){var s=a.value,c=m()(s,2),l=c[0],u=c[1],h=parseFloat(l.replace(/%/g,""));if(isNaN(h))return{};t.push({key:h,value:u})}}catch(e){i=!0,r=e}finally{try{!n&&o.return&&o.return()}finally{if(i)throw r}}return(t=t.sort((function(e,t){return e.key-t.key}))).map((function(e){var t=e.key;return e.value+" "+t+"%"})).join(", ")}(s)+")"}:{backgroundImage:"linear-gradient("+o+", "+n+", "+r+")"}},y={functional:!0,render:function(e,t){var n=t.props,i=t.children,r=n.prefixCls,a=n.percent,s=n.successPercent,c=n.strokeWidth,l=n.size,u=n.strokeColor,h=n.strokeLinecap,d=void 0;d=u&&"string"!=typeof u?b(u):{background:u};var f=o()({width:g(a)+"%",height:(c||("small"===l?6:8))+"px",background:u,borderRadius:"square"===h?0:"100px"},d),p={width:g(s)+"%",height:(c||("small"===l?6:8))+"px",borderRadius:"square"===h?0:""},v=void 0!==s?e("div",{class:r+"-success-bg",style:p}):null;return e("div",[e("div",{class:r+"-outer"},[e("div",{class:r+"-inner"},[e("div",{class:r+"-bg",style:f}),v])]),i])}},C=n(6),x=n.n(C),k=n(18),z=n.n(k),w=n(25),S=n.n(w);var O=function(e){return{mixins:[e],updated:function(){var e=this,t=Date.now(),n=!1;Object.keys(this.paths).forEach((function(i){var r=e.paths[i];if(r){n=!0;var a=r.style;a.transitionDuration=".3s, .3s, .3s, .06s",e.prevTimeStamp&&t-e.prevTimeStamp<100&&(a.transitionDuration="0s, 0s")}})),n&&(this.prevTimeStamp=Date.now())}}},M=l.a.oneOfType([l.a.number,l.a.string]),T={percent:l.a.oneOfType([M,l.a.arrayOf(M)]),prefixCls:l.a.string,strokeColor:l.a.oneOfType([l.a.string,l.a.arrayOf(l.a.oneOfType([l.a.string,l.a.object])),l.a.object]),strokeLinecap:l.a.oneOf(["butt","round","square"]),strokeWidth:M,trailColor:l.a.string,trailWidth:M},V=o()({},T,{gapPosition:l.a.oneOf(["top","bottom","left","right"]),gapDegree:l.a.oneOfType([l.a.number,l.a.string,l.a.bool])}),P=o()({},{percent:0,prefixCls:"rc-progress",strokeColor:"#2db7f5",strokeLinecap:"round",strokeWidth:1,trailColor:"#D9D9D9",trailWidth:1},{gapPosition:"top"});z.a.use(S.a,{name:"ant-ref"});var j=0;function H(e){return+e.replace("%","")}function _(e){return Array.isArray(e)?e:[e]}function L(e,t,n,i){var r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,a=arguments[5],o=50-i/2,s=0,c=-o,l=0,u=-2*o;switch(a){case"left":s=-o,c=0,l=2*o,u=0;break;case"right":s=o,c=0,l=-2*o,u=0;break;case"bottom":c=o,u=2*o}var h="M 50,50 m "+s+","+c+"\n a "+o+","+o+" 0 1 1 "+l+","+-u+"\n a "+o+","+o+" 0 1 1 "+-l+","+u,d=2*Math.PI*o,f={stroke:n,strokeDasharray:t/100*(d-r)+"px "+d+"px",strokeDashoffset:"-"+(r/2+e/100*(d-r))+"px",transition:"stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s"};return{pathString:h,pathStyle:f}}var F=O({props:Object(u.t)(V,P),created:function(){this.paths={},this.gradientId=j,j+=1},methods:{getStokeList:function(){var e=this,t=this.$createElement,n=this.$props,i=n.prefixCls,r=n.percent,a=n.strokeColor,o=n.strokeWidth,s=n.strokeLinecap,c=n.gapDegree,l=n.gapPosition,u=_(r),h=_(a),d=0;return u.map((function(n,r){var a=h[r]||h[h.length-1],u="[object Object]"===Object.prototype.toString.call(a)?"url(#"+i+"-gradient-"+e.gradientId+")":"",f=L(d,n,a,o,c,l),p=f.pathString,v=f.pathStyle;return d+=n,t("path",{key:r,attrs:{d:p,stroke:u,"stroke-linecap":s,"stroke-width":0===n?0:o,"fill-opacity":"0"},class:i+"-circle-path",style:v,directives:[{name:"ant-ref",value:function(t){e.paths[r]=t}}]})}))}},render:function(){var e=arguments[0],t=this.$props,n=t.prefixCls,i=t.strokeWidth,r=t.trailWidth,a=t.gapDegree,o=t.gapPosition,s=t.trailColor,c=t.strokeLinecap,l=t.strokeColor,u=p()(t,["prefixCls","strokeWidth","trailWidth","gapDegree","gapPosition","trailColor","strokeLinecap","strokeColor"]),h=L(0,100,s,i,a,o),d=h.pathString,f=h.pathStyle;delete u.percent;var v=_(l),m=v.find((function(e){return"[object Object]"===Object.prototype.toString.call(e)})),g={attrs:{d:d,stroke:s,"stroke-linecap":c,"stroke-width":r||i,"fill-opacity":"0"},class:n+"-circle-trail",style:f};return e("svg",x()([{class:n+"-circle",attrs:{viewBox:"0 0 100 100"}},u]),[m&&e("defs",[e("linearGradient",{attrs:{id:n+"-gradient-"+this.gradientId,x1:"100%",y1:"0%",x2:"0%",y2:"0%"}},[Object.keys(m).sort((function(e,t){return H(e)-H(t)})).map((function(t,n){return e("stop",{key:n,attrs:{offset:t,"stop-color":m[t]}})}))])]),e("path",g),this.getStokeList().reverse()])}}),E={normal:"#108ee9",exception:"#ff5500",success:"#87d068"};function A(e){var t=e.percent,n=e.successPercent,i=g(t);if(!n)return i;var r=g(n);return[n,g(i-r)]}var D={functional:!0,render:function(e,t){var n,i,a,o,s,c=t.props,l=t.children,u=c.prefixCls,h=c.width,d=c.strokeWidth,f=c.trailColor,p=c.strokeLinecap,v=c.gapPosition,m=c.gapDegree,g=c.type,b=h||120,y={width:"number"==typeof b?b+"px":b,height:"number"==typeof b?b+"px":b,fontSize:.15*b+6},C=d||6,x=v||"dashboard"===g&&"bottom"||"top",k=m||"dashboard"===g&&75,z=(a=(i=c).progressStatus,o=i.successPercent,s=i.strokeColor||E[a],o?[E.success,s]:s),w="[object Object]"===Object.prototype.toString.call(z);return e("div",{class:(n={},r()(n,u+"-inner",!0),r()(n,u+"-circle-gradient",w),n),style:y},[e(F,{attrs:{percent:A(c),strokeWidth:C,trailWidth:C,strokeColor:z,strokeLinecap:p,trailColor:f,prefixCls:u,gapDegree:k,gapPosition:x}}),l])}},$=["normal","exception","active","success"],I=l.a.oneOf(["line","circle","dashboard"]),R=l.a.oneOf(["default","small"]),N={prefixCls:l.a.string,type:I,percent:l.a.number,successPercent:l.a.number,format:l.a.func,status:l.a.oneOf($),showInfo:l.a.bool,strokeWidth:l.a.number,strokeLinecap:l.a.oneOf(["butt","round","square"]),strokeColor:l.a.oneOfType([l.a.string,l.a.object]),trailColor:l.a.string,width:l.a.number,gapDegree:l.a.number,gapPosition:l.a.oneOf(["top","bottom","left","right"]),size:R},K={name:"AProgress",props:Object(u.t)(N,{type:"line",percent:0,showInfo:!0,trailColor:"#090b0e29",size:"default",gapDegree:0,strokeLinecap:"round"}),inject:{configProvider:{default:function(){return h.a}}},methods:{getPercentNumber:function(){var e=this.$props,t=e.successPercent,n=e.percent,i=void 0===n?0:n;return parseInt(void 0!==t?t.toString():i.toString(),10)},getProgressStatus:function(){var e=this.$props.status;return $.indexOf(e)<0&&this.getPercentNumber()>=100?"success":e||"normal"},renderProcessInfo:function(e,t){var n=this.$createElement,i=this.$props,r=i.showInfo,a=i.format,o=i.type,s=i.percent,c=i.successPercent;if(!r)return null;var l=void 0,u=a||this.$scopedSlots.format||function(e){return e+"%"},h="circle"===o||"dashboard"===o?"":"-circle";return a||this.$scopedSlots.format||"exception"!==t&&"success"!==t?l=u(g(s),g(c)):"exception"===t?l=n(d.a,{attrs:{type:"close"+h,theme:"line"===o?"filled":"outlined"}}):"success"===t&&(l=n(d.a,{attrs:{type:"check"+h,theme:"line"===o?"filled":"outlined"}})),n("span",{class:e+"-text",attrs:{title:"string"==typeof l?l:void 0}},[l])}},render:function(){var e,t=arguments[0],n=Object(u.l)(this),i=n.prefixCls,a=n.size,s=n.type,l=n.showInfo,h=this.configProvider.getPrefixCls,d=h("progress",i),f=this.getProgressStatus(),p=this.renderProcessInfo(d,f),v=void 0;if("line"===s){var m={props:o()({},n,{prefixCls:d})};v=t(y,m,[p])}else if("circle"===s||"dashboard"===s){var g={props:o()({},n,{prefixCls:d,progressStatus:f})};v=t(D,g,[p])}var b=c()(d,(e={},r()(e,d+"-"+("dashboard"===s?"circle":s),!0),r()(e,d+"-status-"+f,!0),r()(e,d+"-show-info",l),r()(e,d+"-"+a,a),e)),C={on:Object(u.k)(this),class:b};return t("div",C,[v])}},Y=n(10);K.install=function(e){e.use(Y.a),e.component(K.name,K)};t.a=K},function(e,t,n){"use strict";t.a={items_per_page:"/ page",jump_to:"Go to",jump_to_confirm:"confirm",page:"",prev_page:"Previous Page",next_page:"Next Page",prev_5:"Previous 5 Pages",next_5:"Next 5 Pages",prev_3:"Previous 3 Pages",next_3:"Next 3 Pages"}},function(e,t,n){"use strict";var i=n(67);t.a=i.a},function(e,t,n){var i=n(171),r=n(131);e.exports=Object.keys||function(e){return i(e,r)}},function(e,t){e.exports=!0},function(e,t){var n=0,i=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++n+i).toString(36))}},function(e,t){t.f={}.propertyIsEnumerable},function(e,t,n){var i=n(127);e.exports=function(e){return Object(i(e))}},function(e,t,n){"use strict";var i=n(255)(!0);n(174)(String,"String",(function(e){this._t=String(e),this._i=0}),(function(){var e,t=this._t,n=this._i;return n>=t.length?{value:void 0,done:!0}:(e=i(t,n),this._i+=e.length,{value:e,done:!1})}))},function(e,t){var n,i,r=e.exports={};function a(){throw new Error("setTimeout has not been defined")}function o(){throw new Error("clearTimeout has not been defined")}function s(e){if(n===setTimeout)return setTimeout(e,0);if((n===a||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:a}catch(e){n=a}try{i="function"==typeof clearTimeout?clearTimeout:o}catch(e){i=o}}();var c,l=[],u=!1,h=-1;function d(){u&&c&&(u=!1,c.length?l=c.concat(l):h=-1,l.length&&f())}function f(){if(!u){var e=s(d);u=!0;for(var t=l.length;t;){for(c=l,l=[];++h1)for(var n=1;n-1&&e%1==0&&e0;var a=function(e,t){for(var n=Object.create(null),i=e.split(","),r=0;r1),t})),s(e,u(e),n),l&&(n=r(n,7,c));for(var h=t.length;h--;)a(n,t[h]);return n}));e.exports=h},function(e,t,n){var i=n(368),r=n(110),a=n(111),o=a&&a.isRegExp,s=o?r(o):i;e.exports=s},function(e,t,n){"use strict";(function(e){function n(){return(n=Object.assign||function(e){for(var t=1;t=a)return e;switch(e){case"%s":return String(t[i++]);case"%d":return Number(t[i++]);case"%j":try{return JSON.stringify(t[i++])}catch(e){return"[Circular]"}break;default:return e}}));return o}return r}function d(e,t){return null==e||(!("array"!==t||!Array.isArray(e)||e.length)||!(!function(e){return"string"===e||"url"===e||"hex"===e||"email"===e||"date"===e||"pattern"===e}(t)||"string"!=typeof e||e))}function f(e,t,n){var i=0,r=e.length;!function a(o){if(o&&o.length)n(o);else{var s=i;i+=1,s()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,url:new RegExp("^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$","i"),hex:/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i},C={integer:function(e){return C.number(e)&&parseInt(e,10)===e},float:function(e){return C.number(e)&&!C.integer(e)},array:function(e){return Array.isArray(e)},regexp:function(e){if(e instanceof RegExp)return!0;try{return!!new RegExp(e)}catch(e){return!1}},date:function(e){return"function"==typeof e.getTime&&"function"==typeof e.getMonth&&"function"==typeof e.getYear&&!isNaN(e.getTime())},number:function(e){return!isNaN(e)&&"number"==typeof e},object:function(e){return"object"==typeof e&&!C.array(e)},method:function(e){return"function"==typeof e},email:function(e){return"string"==typeof e&&!!e.match(y.email)&&e.length<255},url:function(e){return"string"==typeof e&&!!e.match(y.url)},hex:function(e){return"string"==typeof e&&!!e.match(y.hex)}};var x={required:b,whitespace:function(e,t,n,i,r){(/^\s+$/.test(t)||""===t)&&i.push(h(r.messages.whitespace,e.fullField))},type:function(e,t,n,i,r){if(e.required&&void 0===t)b(e,t,n,i,r);else{var a=e.type;["integer","float","array","regexp","object","method","email","number","date","url","hex"].indexOf(a)>-1?C[a](t)||i.push(h(r.messages.types[a],e.fullField,e.type)):a&&typeof t!==e.type&&i.push(h(r.messages.types[a],e.fullField,e.type))}},range:function(e,t,n,i,r){var a="number"==typeof e.len,o="number"==typeof e.min,s="number"==typeof e.max,c=t,l=null,u="number"==typeof t,d="string"==typeof t,f=Array.isArray(t);if(u?l="number":d?l="string":f&&(l="array"),!l)return!1;f&&(c=t.length),d&&(c=t.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,"_").length),a?c!==e.len&&i.push(h(r.messages[l].len,e.fullField,e.len)):o&&!s&&ce.max?i.push(h(r.messages[l].max,e.fullField,e.max)):o&&s&&(ce.max)&&i.push(h(r.messages[l].range,e.fullField,e.min,e.max))},enum:function(e,t,n,i,r){e.enum=Array.isArray(e.enum)?e.enum:[],-1===e.enum.indexOf(t)&&i.push(h(r.messages.enum,e.fullField,e.enum.join(", ")))},pattern:function(e,t,n,i,r){if(e.pattern)if(e.pattern instanceof RegExp)e.pattern.lastIndex=0,e.pattern.test(t)||i.push(h(r.messages.pattern.mismatch,e.fullField,t,e.pattern));else if("string"==typeof e.pattern){new RegExp(e.pattern).test(t)||i.push(h(r.messages.pattern.mismatch,e.fullField,t,e.pattern))}}};function k(e,t,n,i,r){var a=e.type,o=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(d(t,a)&&!e.required)return n();x.required(e,t,i,o,r,a),d(t,a)||x.type(e,t,i,o,r)}n(o)}var z={string:function(e,t,n,i,r){var a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(d(t,"string")&&!e.required)return n();x.required(e,t,i,a,r,"string"),d(t,"string")||(x.type(e,t,i,a,r),x.range(e,t,i,a,r),x.pattern(e,t,i,a,r),!0===e.whitespace&&x.whitespace(e,t,i,a,r))}n(a)},method:function(e,t,n,i,r){var a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(d(t)&&!e.required)return n();x.required(e,t,i,a,r),void 0!==t&&x.type(e,t,i,a,r)}n(a)},number:function(e,t,n,i,r){var a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(""===t&&(t=void 0),d(t)&&!e.required)return n();x.required(e,t,i,a,r),void 0!==t&&(x.type(e,t,i,a,r),x.range(e,t,i,a,r))}n(a)},boolean:function(e,t,n,i,r){var a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(d(t)&&!e.required)return n();x.required(e,t,i,a,r),void 0!==t&&x.type(e,t,i,a,r)}n(a)},regexp:function(e,t,n,i,r){var a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(d(t)&&!e.required)return n();x.required(e,t,i,a,r),d(t)||x.type(e,t,i,a,r)}n(a)},integer:function(e,t,n,i,r){var a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(d(t)&&!e.required)return n();x.required(e,t,i,a,r),void 0!==t&&(x.type(e,t,i,a,r),x.range(e,t,i,a,r))}n(a)},float:function(e,t,n,i,r){var a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(d(t)&&!e.required)return n();x.required(e,t,i,a,r),void 0!==t&&(x.type(e,t,i,a,r),x.range(e,t,i,a,r))}n(a)},array:function(e,t,n,i,r){var a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(d(t,"array")&&!e.required)return n();x.required(e,t,i,a,r,"array"),d(t,"array")||(x.type(e,t,i,a,r),x.range(e,t,i,a,r))}n(a)},object:function(e,t,n,i,r){var a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(d(t)&&!e.required)return n();x.required(e,t,i,a,r),void 0!==t&&x.type(e,t,i,a,r)}n(a)},enum:function(e,t,n,i,r){var a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(d(t)&&!e.required)return n();x.required(e,t,i,a,r),void 0!==t&&x.enum(e,t,i,a,r)}n(a)},pattern:function(e,t,n,i,r){var a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(d(t,"string")&&!e.required)return n();x.required(e,t,i,a,r),d(t,"string")||x.pattern(e,t,i,a,r)}n(a)},date:function(e,t,n,i,r){var a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(d(t,"date")&&!e.required)return n();var o;if(x.required(e,t,i,a,r),!d(t,"date"))o=t instanceof Date?t:new Date(t),x.type(e,o,i,a,r),o&&x.range(e,o.getTime(),i,a,r)}n(a)},url:k,hex:k,email:k,required:function(e,t,n,i,r){var a=[],o=Array.isArray(t)?"array":typeof t;x.required(e,t,i,a,r,o),n(a)},any:function(e,t,n,i,r){var a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(d(t)&&!e.required)return n();x.required(e,t,i,a,r)}n(a)}};function w(){return{default:"Validation error on field %s",required:"%s is required",enum:"%s must be one of %s",whitespace:"%s cannot be empty",date:{format:"%s date %s is invalid for format %s",parse:"%s date could not be parsed, %s is invalid ",invalid:"%s date %s is invalid"},types:{string:"%s is not a %s",method:"%s is not a %s (function)",array:"%s is not an %s",object:"%s is not an %s",number:"%s is not a %s",date:"%s is not a %s",boolean:"%s is not a %s",integer:"%s is not an %s",float:"%s is not a %s",regexp:"%s is not a valid %s",email:"%s is not a valid %s",url:"%s is not a valid %s",hex:"%s is not a valid %s"},string:{len:"%s must be exactly %s characters",min:"%s must be at least %s characters",max:"%s cannot be longer than %s characters",range:"%s must be between %s and %s characters"},number:{len:"%s must equal %s",min:"%s cannot be less than %s",max:"%s cannot be greater than %s",range:"%s must be between %s and %s"},array:{len:"%s must be exactly %s in length",min:"%s cannot be less than %s in length",max:"%s cannot be greater than %s in length",range:"%s must be between %s and %s in length"},pattern:{mismatch:"%s value %s does not match pattern %s"},clone:function(){var e=JSON.parse(JSON.stringify(this));return e.clone=this.clone,e}}}var S=w();function O(e){this.rules=null,this._messages=S,this.define(e)}O.prototype={messages:function(e){return e&&(this._messages=g(w(),e)),this._messages},define:function(e){if(!e)throw new Error("Cannot configure a schema with no rules");if("object"!=typeof e||Array.isArray(e))throw new Error("Rules must be an object");var t,n;for(t in this.rules={},e)e.hasOwnProperty(t)&&(n=e[t],this.rules[t]=Array.isArray(n)?n:[n])},validate:function(e,t,i){var r=this;void 0===t&&(t={}),void 0===i&&(i=function(){});var a,o,s=e,c=t,l=i;if("function"==typeof c&&(l=c,c={}),!this.rules||0===Object.keys(this.rules).length)return l&&l(),Promise.resolve();if(c.messages){var d=this.messages();d===S&&(d=w()),g(d,c.messages),c.messages=d}else c.messages=this.messages();var f={};(c.keys||Object.keys(this.rules)).forEach((function(t){a=r.rules[t],o=s[t],a.forEach((function(i){var a=i;"function"==typeof a.transform&&(s===e&&(s=n({},s)),o=s[t]=a.transform(o)),(a="function"==typeof a?{validator:a}:n({},a)).validator=r.getValidationMethod(a),a.field=t,a.fullField=a.fullField||t,a.type=r.getType(a),a.validator&&(f[t]=f[t]||[],f[t].push({rule:a,value:o,source:s,field:t}))}))}));var p={};return v(f,c,(function(e,t){var i,r=e.rule,a=!("object"!==r.type&&"array"!==r.type||"object"!=typeof r.fields&&"object"!=typeof r.defaultField);function o(e,t){return n(n({},t),{},{fullField:r.fullField+"."+e})}function s(i){void 0===i&&(i=[]);var s=i;if(Array.isArray(s)||(s=[s]),!c.suppressWarning&&s.length&&O.warning("async-validator:",s),s.length&&r.message&&(s=[].concat(r.message)),s=s.map(m(r)),c.first&&s.length)return p[r.field]=1,t(s);if(a){if(r.required&&!e.value)return r.message?s=[].concat(r.message).map(m(r)):c.error&&(s=[c.error(r,h(c.messages.required,r.field))]),t(s);var l={};if(r.defaultField)for(var u in e.value)e.value.hasOwnProperty(u)&&(l[u]=r.defaultField);for(var d in l=n(n({},l),e.rule.fields))if(l.hasOwnProperty(d)){var f=Array.isArray(l[d])?l[d]:[l[d]];l[d]=f.map(o.bind(null,d))}var v=new O(l);v.messages(c.messages),e.rule.options&&(e.rule.options.messages=c.messages,e.rule.options.error=c.error),v.validate(e.value,e.rule.options||c,(function(e){var n=[];s&&s.length&&n.push.apply(n,s),e&&e.length&&n.push.apply(n,e),t(n.length?n:null)}))}else t(s)}a=a&&(r.required||!r.required&&e.value),r.field=e.field,r.asyncValidator?i=r.asyncValidator(r,e.value,s,e.source,c):r.validator&&(!0===(i=r.validator(r,e.value,s,e.source,c))?s():!1===i?s(r.message||r.field+" fails"):i instanceof Array?s(i):i instanceof Error&&s(i.message)),i&&i.then&&i.then((function(){return s()}),(function(e){return s(e)}))}),(function(e){!function(e){var t,n,i,r=[],a={};for(t=0;t0?i:n)(e)}},function(e,t,n){var i=n(130)("keys"),r=n(97);e.exports=function(e){return i[e]||(i[e]=r(e))}},function(e,t,n){var i=n(44),r=n(50),a=r["__core-js_shared__"]||(r["__core-js_shared__"]={});(e.exports=function(e,t){return a[e]||(a[e]=void 0!==t?t:{})})("versions",[]).push({version:i.version,mode:n(96)?"pure":"global",copyright:"© 2019 Denis Pushkarev (zloirock.ru)"})},function(e,t){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(e,t){t.f=Object.getOwnPropertySymbols},function(e,t,n){var i=n(51).f,r=n(63),a=n(39)("toStringTag");e.exports=function(e,t,n){e&&!r(e=n?e:e.prototype,a)&&i(e,a,{configurable:!0,value:t})}},function(e,t,n){n(260);for(var i=n(50),r=n(70),a=n(73),o=n(39)("toStringTag"),s="CSSRuleList,CSSStyleDeclaration,CSSValueList,ClientRectList,DOMRectList,DOMStringList,DOMTokenList,DataTransferItemList,FileList,HTMLAllCollection,HTMLCollection,HTMLFormElement,HTMLSelectElement,MediaList,MimeTypeArray,NamedNodeMap,NodeList,PaintRequestList,Plugin,PluginArray,SVGLengthList,SVGNumberList,SVGPathSegList,SVGPointList,SVGStringList,SVGTransformList,SourceBufferList,StyleSheetList,TextTrackCueList,TextTrackList,TouchList".split(","),c=0;c-1&&e%1==0&&e<=9007199254740991}},function(e,t){var n=Object.prototype;e.exports=function(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||n)}},function(e,t,n){var i=n(334),r=n(189),a=Object.prototype.propertyIsEnumerable,o=Object.getOwnPropertySymbols,s=o?function(e){return null==e?[]:(e=Object(e),i(o(e),(function(t){return a.call(e,t)})))}:r;e.exports=s},function(e,t){e.exports=function(e,t){for(var n=-1,i=t.length,r=e.length;++n0&&(t.percent=t.loaded/t.total*100),e.onProgress(t)});var n=new window.FormData;e.data&&Object.keys(e.data).forEach((function(t){var i=e.data[t];Array.isArray(i)?i.forEach((function(e){n.append(t+"[]",e)})):n.append(t,e.data[t])})),n.append(e.filename,e.file),t.onerror=function(t){e.onError(t)},t.onload=function(){if(t.status<200||t.status>=300)return e.onError(function(e, t){var n="cannot "+e.method+" "+e.action+" "+t.status+"'",i=new Error(n);return i.status=t.status,i.method=e.method,i.url=e.action,i}(e,t),p(t));e.onSuccess(p(t),t)},t.open(e.method,e.action,!0),e.withCredentials&&"withCredentials"in t&&(t.withCredentials=!0);var i=e.headers||{};for(var r in null!==i["X-Requested-With"]&&t.setRequestHeader("X-Requested-With","XMLHttpRequest"),i)i.hasOwnProperty(r)&&null!==i[r]&&t.setRequestHeader(r,i[r]);return t.send(n),{abort:function(){t.abort()}}}var m=+new Date,g=0;function b(){return"vc-upload-"+m+"-"+ ++g}var y=function(e, t){if(e&&t){var n=Array.isArray(t)?t:t.split(","),i=e.name||"",r=e.type||"",a=r.replace(/\/.*$/,"");return n.some((function(e){var t,n,o=e.trim();return"."===o.charAt(0)?(t=i.toLowerCase(),n=o.toLowerCase(),-1!==t.indexOf(n,t.length-n.length)):/\/\*$/.test(o)?a===o.replace(/\/.*$/,""):r===o}))}return!0};var C=function(e, t, n){var i=function e(i, r){r=r||"",i.isFile?i.file((function(e){n(e)&&(i.fullPath&&!e.webkitRelativePath&&(Object.defineProperties(e,{webkitRelativePath:{writable:!0}}),e.webkitRelativePath=i.fullPath.replace(/^\//,""),Object.defineProperties(e,{webkitRelativePath:{writable:!1}})),t([e]))})):i.isDirectory&&function(e, t){var n=e.createReader(),i=[];!function e(){n.readEntries((function(n){var r=Array.prototype.slice.apply(n);i=i.concat(r),!r.length?t(i):e()}))}()}(i,(function(t){t.forEach((function(t){e(t,""+r+i.name+"/")}))}))},r=!0,a=!1,o=void 0;try{for(var s,c=e[Symbol.iterator](); !(r=(s=c.next()).done); r=!0){i(s.value.webkitGetAsEntry())}}catch(e){a=!0,o=e}finally{try{!r&&c.return&&c.return()}finally{if(a)throw o}}},x={componentTag:a.a.string,prefixCls:a.a.string,name:a.a.string,multiple:a.a.bool,directory:a.a.bool,disabled:a.a.bool,accept:a.a.string,data:a.a.oneOfType([a.a.object,a.a.func]),action:a.a.oneOfType([a.a.string,a.a.func]),headers:a.a.object,beforeUpload:a.a.func,customRequest:a.a.func,withCredentials:a.a.bool,openFileDialogOnClick:a.a.bool,transformFile:a.a.func,method:a.a.string},k={inheritAttrs:!1,name:"ajaxUploader",mixins:[s.a],props:x,data:function(){return this.reqs={},{uid:b()}},mounted:function(){this._isMounted=!0},beforeDestroy:function(){this._isMounted=!1,this.abort()},methods:{onChange:function(e){var t=e.target.files;this.uploadFiles(t),this.reset()},onClick:function(){var e=this.$refs.fileInputRef;e&&e.click()},onKeyDown:function(e){"Enter"===e.key&&this.onClick()},onFileDrop:function(e){var t=this,n=this.$props.multiple;if(e.preventDefault(),"dragover"!==e.type)if(this.directory)C(e.dataTransfer.items,this.uploadFiles,(function(e){return y(e,t.accept)}));else{var i=h()(Array.prototype.slice.call(e.dataTransfer.files),(function(e){return y(e,t.accept)})),r=i[0],a=i[1];!1===n&&(r=r.slice(0,1)),this.uploadFiles(r),a.length&&this.$emit("reject",a)}},uploadFiles:function(e){var t=this,n=Array.prototype.slice.call(e);n.map((function(e){return e.uid=b(),e})).forEach((function(e){t.upload(e,n)}))},upload:function(e, t){var n=this;if(!this.beforeUpload)return setTimeout((function(){return n.post(e)}),0);var i=this.beforeUpload(e,t);i&&i.then?i.then((function(t){var i=Object.prototype.toString.call(t);return"[object File]"===i||"[object Blob]"===i?n.post(t):n.post(e)})).catch((function(e){console&&console.log(e)})):!1!==i&&setTimeout((function(){return n.post(e)}),0)},post:function(e){var t=this;if(this._isMounted){var n=this.$props,i=n.data,r=n.transformFile,a=void 0===r?function(e){return e}:r;new Promise((function(n){var i=t.action;if("function"==typeof i)return n(i(e));n(i)})).then((function(r){var o=e.uid,s=t.customRequest||v;Promise.resolve(a(e)).catch((function(e){console.error(e)})).then((function(a){"function"==typeof i&&(i=i(e));var c={action:r,filename:t.name,data:i,file:a,headers:t.headers,withCredentials:t.withCredentials,method:n.method||"post",onProgress:function(n){t.$emit("progress",n,e)},onSuccess:function(n, i){delete t.reqs[o],t.$emit("success",n,e,i)},onError:function(n, i){delete t.reqs[o],t.$emit("error",n,i,e)}};t.reqs[o]=s(c),t.$emit("start",e)}))}))}},reset:function(){this.setState({uid:b()})},abort:function(e){var t=this.reqs;if(e){var n=e;e&&e.uid&&(n=e.uid),t[n]&&t[n].abort&&t[n].abort(),delete t[n]}else Object.keys(t).forEach((function(e){t[e]&&t[e].abort&&t[e].abort(),delete t[e]}))}},render:function(){var e,t=arguments[0],n=this.$props,i=this.$attrs,a=n.componentTag,s=n.prefixCls,c=n.disabled,u=n.multiple,h=n.accept,d=n.directory,p=n.openFileDialogOnClick,v=f()((e={},l()(e,s,!0),l()(e,s+"-disabled",c),e)),m=c?{}:{click:p?this.onClick:function(){},keydown:p?this.onKeyDown:function(){},drop:this.onFileDrop,dragover:this.onFileDrop},g={on:r()({},Object(o.k)(this),m),attrs:{role:"button",tabIndex:c?null:"0"},class:v};return t(a,g,[t("input",{attrs:{id:i.id,type:"file",accept:h,directory:d?"directory":null,webkitdirectory:d?"webkitdirectory":null,multiple:u},ref:"fileInputRef",on:{click:function(e){return e.stopPropagation()},change:this.onChange},key:this.uid,style:{display:"none"}}),this.$slots.default])}},z=n(13),w={position:"absolute",top:0,opacity:0,filter:"alpha(opacity=0)",left:0,zIndex:9999},S={mixins:[s.a],props:{componentTag:a.a.string,disabled:a.a.bool,prefixCls:a.a.string,accept:a.a.string,multiple:a.a.bool,data:a.a.oneOfType([a.a.object,a.a.func]),action:a.a.oneOfType([a.a.string,a.a.func]),name:a.a.string},data:function(){return this.file={},{uploading:!1}},methods:{onLoad:function(){if(this.uploading){var e=this.file,t=void 0;try{var n=this.getIframeDocument(),i=n.getElementsByTagName("script")[0];i&&i.parentNode===n.body&&n.body.removeChild(i),t=n.body.innerHTML,this.$emit("success",t,e)}catch(n){Object(z.a)(!1,"cross domain error for Upload. Maybe server should return document.domain script. see Note from https://github.com/react-component/upload"),t="cross-domain",this.$emit("error",n,null,e)}this.endUpload()}},onChange:function(){var e=this,t=this.getFormInputNode(),n=this.file={uid:b(),name:t.value&&t.value.substring(t.value.lastIndexOf("\\")+1,t.value.length)};this.startUpload();var i=this.$props;if(!i.beforeUpload)return this.post(n);var r=i.beforeUpload(n);r&&r.then?r.then((function(){e.post(n)}),(function(){e.endUpload()})):!1!==r?this.post(n):this.endUpload()},getIframeNode:function(){return this.$refs.iframeRef},getIframeDocument:function(){return this.getIframeNode().contentDocument},getFormNode:function(){return this.getIframeDocument().getElementById("form")},getFormInputNode:function(){return this.getIframeDocument().getElementById("input")},getFormDataNode:function(){return this.getIframeDocument().getElementById("data")},getFileForMultiple:function(e){return this.multiple?[e]:e},getIframeHTML:function(e){var t="",n="";if(e){t=' - - + - - - - - - \ No newline at end of file + diff --git a/web/html/xui/client_bulk_modal.html b/web/html/xui/client_bulk_modal.html index d5c60b76..e0295110 100644 --- a/web/html/xui/client_bulk_modal.html +++ b/web/html/xui/client_bulk_modal.html @@ -1,122 +1,207 @@ {{define "clientsBulkModal"}} - + - - - Random - Random+Prefix - Random+Prefix+Num - Random+Prefix+Num+Postfix - Prefix+Num+Postfix [ BE CAREFUL! ] - -
- - {{ i18n "pages.client.first" }} - - - - {{ i18n "pages.client.last" }} - - - - {{ i18n "pages.client.prefix" }} - - - - {{ i18n "pages.client.postfix" }} - - - - {{ i18n "pages.client.clientCount" }} - - - - - Subscription + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{ i18n "pages.client.method" }} + + + Random + Random+Prefix + Random+Prefix+Num + Random+Prefix+Num+Postfix + Prefix+Num+Postfix + + +
{{ i18n "pages.client.first" }} + + + +
{{ i18n "pages.client.last" }} + + + +
{{ i18n "pages.client.prefix" }} + + + +
{{ i18n "pages.client.postfix" }} + + + +
{{ i18n "pages.client.clientCount" }} + + + +
Flow + + + {{ i18n "none" }} + [[ key ]] + + +
Subscription + + + + + + +
Telegram ID + + - - - - - - Telegram ID - - - - - - - -
- - - {{ i18n "pages.inbounds.IPLimit" }} - - - - - - - -
- - - {{ i18n "none" }} - [[ key ]] - - - - - {{ i18n "none" }} - [[ key ]] - - - - - {{ i18n "pages.inbounds.totalFlow" }} (GB) - - - - - - - -
- - - -
- - - - - - {{ i18n "pages.inbounds.expireDate" }} - - - - - - - +
+ + + +
+ + + + + +
+ + + + + {{ i18n "none" }} + [[ key ]] + + +
+ {{ i18n "pages.inbounds.totalFlow" }}(GB) + + + + + + + + +
{{ i18n "pages.client.delayedStart" }} + + + +
{{ i18n "pages.client.expireDays" }} + + + +
+ {{ i18n "pages.inbounds.expireDate" }} + + + + + + + + +
+ {{ i18n "pages.client.renew" }} + + + + + + + + +
diff --git a/web/html/xui/component/themeSwitch.html b/web/html/xui/component/themeSwitch.html index 7cbedecf..4d5412e2 100644 --- a/web/html/xui/component/themeSwitch.html +++ b/web/html/xui/component/themeSwitch.html @@ -1,8 +1,6 @@ {{define "component/themeSwitchTemplate"}} @@ -10,39 +8,17 @@ {{define "component/themeSwitcher"}} + + + + + {{template "component/themeSwitcher" .}} {{template "component/themeSwitcher" .}} {{template "textModal"}} {{template "component/themeSwitcher" .}} {{template "component/password" .}} {{template "component/setting"}} @@ -435,80 +302,12 @@ siderDrawer, themeSwitcher, spinning: false, + changeSecret: false, oldAllSetting: new AllSetting(), allSetting: new AllSetting(), saveBtnDisable: true, - user: new User(), + user: {}, lang: getLang(), - ipv4Settings: { - tag: "IPv4", - protocol: "freedom", - settings: { - domainStrategy: "UseIPv4" - } - }, - warpSettings: { - tag: "WARP", - protocol: "socks", - settings: { - servers: [ - { - address: "127.0.0.1", - port: 40000 - } - ] - } - }, - directSettings: { - tag: "direct", - protocol: "freedom" - }, - outboundDomainStrategies: ["AsIs", "UseIP", "UseIPv4", "UseIPv6"], - routingDomainStrategies: ["AsIs", "IPIfNonMatch", "IPOnDemand"], - settingsData: { - protocols: { - bittorrent: ["bittorrent"], - }, - ips: { - local: ["geoip:private"], - cn: ["geoip:cn"], - ir: ["ext:geoip_IR.dat:ir","ext:geoip_IR.dat:arvancloud","ext:geoip_IR.dat:derakcloud","ext:geoip_IR.dat:iranserver","ext:geoip_IR.dat:parspack"], - ru: ["geoip:ru"], - }, - domains: { - ads: [ - "geosite:category-ads-all", - "ext:geosite_IR.dat:category-ads-all" - ], - speedtest: ["geosite:speedtest"], - openai: ["geosite:openai"], - google: ["geosite:google"], - spotify: ["geosite:spotify"], - netflix: ["geosite:netflix"], - cn: [ - "geosite:cn", - "regexp:.*\\.cn$" - ], - ru: [ - "geosite:category-gov-ru", - "regexp:.*\\.ru$" - ], - ir: [ - "regexp:.*\\.ir$", - "regexp:.*\\.xn--mgba3a4f16a$", // .ایران - "ext:geosite_IR.dat:ir" // have rules to bypass all .ir domains. - ] - }, - familyProtectDNS: { - "servers": [ - "1.1.1.3", // https://developers.cloudflare.com/1.1.1.1/setup/ - "1.0.0.3", - "94.140.14.15", // https://adguard-dns.io/kb/general/dns-providers/ - "94.140.15.16" - ], - "queryStrategy": "UseIPv4" - }, - } }, methods: { loading(spinning = true) { @@ -521,6 +320,7 @@ if (msg.success) { this.oldAllSetting = new AllSetting(msg.obj); this.allSetting = new AllSetting(msg.obj); + app.changeRemarkSample(); this.saveBtnDisable = true; } await this.fetchUserSecret(); @@ -547,6 +347,7 @@ this.$confirm({ title: '{{ i18n "pages.settings.restartPanel" }}', content: '{{ i18n "pages.settings.restartPanelDesc" }}', + class: themeSwitcher.currentTheme, okText: '{{ i18n "sure" }}', cancelText: '{{ i18n "cancel" }}', onOk: () => resolve(), @@ -558,7 +359,9 @@ if (msg.success) { this.loading(true); await PromiseUtil.sleep(5000); - const { webCertFile, webKeyFile, webDomain: host, webPort: port, webBasePath: base } = this.allSetting; + var { webCertFile, webKeyFile, webDomain: host, webPort: port, webBasePath: base } = this.allSetting; + if (host == this.oldAllSetting.webDomain) host = null; + if (port == this.oldAllSetting.webPort) port = null; const isTLS = webCertFile !== "" || webKeyFile !== ""; const url = buildURL({ host, port, isTLS, base, path: "panel/settings" }); window.location.replace(url); @@ -591,12 +394,14 @@ return randomString; }, async getNewSecret() { - this.loading(true); - await PromiseUtil.sleep(600); - const newSecret = this.generateRandomString(64); - this.user.loginSecret = newSecret; - document.getElementById("token").textContent = newSecret; - this.loading(false); + if (!this.changeSecret) { + this.changeSecret = true; + this.user.loginSecret = ''; + const newSecret = this.generateRandomString(64); + await PromiseUtil.sleep(1000); + this.user.loginSecret = newSecret; + this.changeSecret = false; + } }, async toggleToken(value) { if (value) { @@ -605,83 +410,6 @@ this.user.loginSecret = ""; } }, - async resetXrayConfigToDefault() { - this.loading(true); - const msg = await HttpUtil.get("/panel/setting/getDefaultJsonConfig"); - this.loading(false); - if (msg.success) { - this.templateSettings = JSON.parse(JSON.stringify(msg.obj, null, 2)); - this.saveBtnDisable = true; - } - }, - syncRulesWithOutbound(tag, setting) { - const newTemplateSettings = {...this.templateSettings}; - const haveRules = newTemplateSettings.routing.rules.some((r) => r?.outboundTag === tag); - const outboundIndex = newTemplateSettings.outbounds.findIndex((o) => o.tag === tag); - if (!haveRules && outboundIndex >= 0) { - newTemplateSettings.outbounds.splice(outboundIndex, 1); - } - if (haveRules && outboundIndex === -1) { - newTemplateSettings.outbounds.push(setting); - } - this.templateSettings = newTemplateSettings; - }, - templateRuleGetter(routeSettings) { - const { property, outboundTag } = routeSettings; - let result = []; - if (this.templateSettings != null) { - this.templateSettings.routing.rules.forEach( - (routingRule) => { - if ( - routingRule.hasOwnProperty(property) && - routingRule.hasOwnProperty("outboundTag") && - routingRule.outboundTag === outboundTag - ) { - result.push(...routingRule[property]); - } - } - ); - } - return result; - }, - templateRuleSetter(routeSettings) { - const { data, property, outboundTag } = routeSettings; - const oldTemplateSettings = this.templateSettings; - const newTemplateSettings = oldTemplateSettings; - currentProperty = this.templateRuleGetter({ outboundTag, property }) - if (currentProperty.length == 0) { - const propertyRule = { - type: "field", - outboundTag, - [property]: data - }; - newTemplateSettings.routing.rules.push(propertyRule); - } - else { - const newRules = []; - insertedOnce = false; - newTemplateSettings.routing.rules.forEach( - (routingRule) => { - if ( - routingRule.hasOwnProperty(property) && - routingRule.hasOwnProperty("outboundTag") && - routingRule.outboundTag === outboundTag - ) { - if (!insertedOnce && data.length > 0) { - insertedOnce = true; - routingRule[property] = data; - newRules.push(routingRule); - } - } - else { - newRules.push(routingRule); - } - } - ); - newTemplateSettings.routing.rules = newRules; - } - this.templateSettings = newTemplateSettings; - } }, async mounted() { await this.getAllSetting(); @@ -690,429 +418,6 @@ this.saveBtnDisable = this.oldAllSetting.equals(this.allSetting); } }, - computed: { - templateSettings: { - get: function () { return this.allSetting.xrayTemplateConfig ? JSON.parse(this.allSetting.xrayTemplateConfig) : null; }, - set: function (newValue) { this.allSetting.xrayTemplateConfig = JSON.stringify(newValue, null, 2); }, - }, - inboundSettings: { - get: function () { return this.templateSettings ? JSON.stringify(this.templateSettings.inbounds, null, 2) : null; }, - set: function (newValue) { - newTemplateSettings = this.templateSettings; - newTemplateSettings.inbounds = JSON.parse(newValue); - this.templateSettings = newTemplateSettings; - }, - }, - outboundSettings: { - get: function () { return this.templateSettings ? JSON.stringify(this.templateSettings.outbounds, null, 2) : null; }, - set: function (newValue) { - newTemplateSettings = this.templateSettings; - newTemplateSettings.outbounds = JSON.parse(newValue); - this.templateSettings = newTemplateSettings; - }, - }, - routingRuleSettings: { - get: function () { return this.templateSettings ? JSON.stringify(this.templateSettings.routing.rules, null, 2) : null; }, - set: function (newValue) { - newTemplateSettings = this.templateSettings; - newTemplateSettings.routing.rules = JSON.parse(newValue); - this.templateSettings = newTemplateSettings; - }, - }, - freedomStrategy: { - get: function () { - if (!this.templateSettings) return "AsIs"; - freedomOutbound = this.templateSettings.outbounds.find((o) => o.protocol === "freedom" && !o.tag); - if (!freedomOutbound) return "AsIs"; - if (!freedomOutbound.settings || !freedomOutbound.settings.domainStrategy) return "AsIs"; - return freedomOutbound.settings.domainStrategy; - }, - set: function (newValue) { - newTemplateSettings = this.templateSettings; - freedomOutboundIndex = newTemplateSettings.outbounds.findIndex((o) => o.protocol === "freedom" && !o.tag); - if (!newTemplateSettings.outbounds[freedomOutboundIndex].settings) { - newTemplateSettings.outbounds[freedomOutboundIndex].settings = {"domainStrategy": newValue}; - } else { - newTemplateSettings.outbounds[freedomOutboundIndex].settings.domainStrategy = newValue; - } - this.templateSettings = newTemplateSettings; - } - }, - routingStrategy: { - get: function () { - if (!this.templateSettings || !this.templateSettings.routing || !this.templateSettings.routing.domainStrategy) return "AsIs"; - return this.templateSettings.routing.domainStrategy; - }, - set: function (newValue) { - newTemplateSettings = this.templateSettings; - newTemplateSettings.routing.domainStrategy = newValue; - this.templateSettings = newTemplateSettings; - } - }, - blockedIPs: { - get: function () { - return this.templateRuleGetter({ outboundTag: "blocked", property: "ip" }); - }, - set: function (newValue) { - this.templateRuleSetter({ outboundTag: "blocked", property: "ip", data: newValue }); - } - }, - blockedDomains: { - get: function () { - return this.templateRuleGetter({ outboundTag: "blocked", property: "domain" }); - }, - set: function (newValue) { - this.templateRuleSetter({ outboundTag: "blocked", property: "domain", data: newValue }); - } - }, - blockedProtocols: { - get: function () { - return this.templateRuleGetter({ outboundTag: "blocked", property: "protocol" }); - }, - set: function (newValue) { - this.templateRuleSetter({ outboundTag: "blocked", property: "protocol", data: newValue }); - } - }, - directIPs: { - get: function () { - return this.templateRuleGetter({ outboundTag: "direct", property: "ip" }); - }, - set: function (newValue) { - this.templateRuleSetter({ outboundTag: "direct", property: "ip", data: newValue }); - this.syncRulesWithOutbound("direct", this.directSettings); - } - }, - directDomains: { - get: function () { - return this.templateRuleGetter({ outboundTag: "direct", property: "domain" }); - }, - set: function (newValue) { - this.templateRuleSetter({ outboundTag: "direct", property: "domain", data: newValue }); - this.syncRulesWithOutbound("direct", this.directSettings); - } - }, - ipv4Domains: { - get: function () { - return this.templateRuleGetter({ outboundTag: "IPv4", property: "domain" }); - }, - set: function (newValue) { - this.templateRuleSetter({ outboundTag: "IPv4", property: "domain", data: newValue }); - this.syncRulesWithOutbound("IPv4", this.ipv4Settings); - } - }, - warpDomains: { - get: function () { - return this.templateRuleGetter({ outboundTag: "WARP", property: "domain" }); - }, - set: function (newValue) { - this.templateRuleSetter({ outboundTag: "WARP", property: "domain", data: newValue }); - this.syncRulesWithOutbound("WARP", this.warpSettings); - } - }, - manualBlockedIPs: { - get: function () { return JSON.stringify(this.blockedIPs, null, 2); }, - set: debounce(function (value) { this.blockedIPs = JSON.parse(value); }, 1000) - }, - manualBlockedDomains: { - get: function () { return JSON.stringify(this.blockedDomains, null, 2); }, - set: debounce(function (value) { this.blockedDomains = JSON.parse(value); }, 1000) - }, - manualDirectIPs: { - get: function () { return JSON.stringify(this.directIPs, null, 2); }, - set: debounce(function (value) { this.directIPs = JSON.parse(value); }, 1000) - }, - manualDirectDomains: { - get: function () { return JSON.stringify(this.directDomains, null, 2); }, - set: debounce(function (value) { this.directDomains = JSON.parse(value); }, 1000) - }, - manualIPv4Domains: { - get: function () { return JSON.stringify(this.ipv4Domains, null, 2); }, - set: debounce(function (value) { this.ipv4Domains = JSON.parse(value); }, 1000) - }, - manualWARPDomains: { - get: function () { return JSON.stringify(this.warpDomains, null, 2); }, - set: debounce(function (value) { this.warpDomains = JSON.parse(value); }, 1000) - }, - torrentSettings: { - get: function () { - return doAllItemsExist(this.settingsData.protocols.bittorrent, this.blockedProtocols); - }, - set: function (newValue) { - if (newValue) { - this.blockedProtocols = [...this.blockedProtocols, ...this.settingsData.protocols.bittorrent]; - } else { - this.blockedProtocols = this.blockedProtocols.filter(data => !this.settingsData.protocols.bittorrent.includes(data)); - } - }, - }, - privateIpSettings: { - get: function () { - return doAllItemsExist(this.settingsData.ips.local, this.blockedIPs); - }, - set: function (newValue) { - if (newValue) { - this.blockedIPs = [...this.blockedIPs, ...this.settingsData.ips.local]; - } else { - this.blockedIPs = this.blockedIPs.filter(data => !this.settingsData.ips.local.includes(data)); - } - }, - }, - AdsSettings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.ads, this.blockedDomains); - }, - set: function (newValue) { - if (newValue) { - this.blockedDomains = [...this.blockedDomains, ...this.settingsData.domains.ads]; - } else { - this.blockedDomains = this.blockedDomains.filter(data => !this.settingsData.domains.ads.includes(data)); - } - }, - }, - SpeedTestSettings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.speedtest, this.blockedDomains); - }, - set: function (newValue) { - if (newValue) { - this.blockedDomains = [...this.blockedDomains, ...this.settingsData.domains.speedtest]; - } else { - this.blockedDomains = this.blockedDomains.filter(data => !this.settingsData.domains.speedtest.includes(data)); - } - }, - }, - familyProtectSettings: { - get: function () { - if (!this.templateSettings || !this.templateSettings.dns || !this.templateSettings.dns.servers) return false; - return doAllItemsExist(this.templateSettings.dns.servers, this.settingsData.familyProtectDNS.servers); - }, - set: function (newValue) { - newTemplateSettings = this.templateSettings; - if (newValue) { - newTemplateSettings.dns = this.settingsData.familyProtectDNS; - } else { - delete newTemplateSettings.dns; - } - this.templateSettings = newTemplateSettings; - }, - }, - GoogleIPv4Settings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.google, this.ipv4Domains); - }, - set: function (newValue) { - if (newValue) { - this.ipv4Domains = [...this.ipv4Domains, ...this.settingsData.domains.google]; - } else { - this.ipv4Domains = this.ipv4Domains.filter(data => !this.settingsData.domains.google.includes(data)); - } - }, - }, - NetflixIPv4Settings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.netflix, this.ipv4Domains); - }, - set: function (newValue) { - if (newValue) { - this.ipv4Domains = [...this.ipv4Domains, ...this.settingsData.domains.netflix]; - } else { - this.ipv4Domains = this.ipv4Domains.filter(data => !this.settingsData.domains.netflix.includes(data)); - } - }, - }, - IRIpSettings: { - get: function () { - return doAllItemsExist(this.settingsData.ips.ir, this.blockedIPs); - }, - set: function (newValue) { - if (newValue) { - this.blockedIPs = [...this.blockedIPs, ...this.settingsData.ips.ir]; - } else { - this.blockedIPs = this.blockedIPs.filter(data => !this.settingsData.ips.ir.includes(data)); - } - } - }, - IRDomainSettings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.ir, this.blockedDomains); - }, - set: function (newValue) { - if (newValue) { - this.blockedDomains = [...this.blockedDomains, ...this.settingsData.domains.ir]; - } else { - this.blockedDomains = this.blockedDomains.filter(data => !this.settingsData.domains.ir.includes(data)); - } - } - }, - ChinaIpSettings: { - get: function () { - return doAllItemsExist(this.settingsData.ips.cn, this.blockedIPs); - }, - set: function (newValue) { - if (newValue) { - this.blockedIPs = [...this.blockedIPs, ...this.settingsData.ips.cn]; - } else { - this.blockedIPs = this.blockedIPs.filter(data => !this.settingsData.ips.cn.includes(data)); - } - } - }, - ChinaDomainSettings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.cn, this.blockedDomains); - }, - set: function (newValue) { - if (newValue) { - this.blockedDomains = [...this.blockedDomains, ...this.settingsData.domains.cn]; - } else { - this.blockedDomains = this.blockedDomains.filter(data => !this.settingsData.domains.cn.includes(data)); - } - } - }, - RussiaIpSettings: { - get: function () { - return doAllItemsExist(this.settingsData.ips.ru, this.blockedIPs); - }, - set: function (newValue) { - if (newValue) { - this.blockedIPs = [...this.blockedIPs, ...this.settingsData.ips.ru]; - } else { - this.blockedIPs = this.blockedIPs.filter(data => !this.settingsData.ips.ru.includes(data)); - } - } - }, - RussiaDomainSettings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.ru, this.blockedDomains); - }, - set: function (newValue) { - if (newValue) { - this.blockedDomains = [...this.blockedDomains, ...this.settingsData.domains.ru]; - } else { - this.blockedDomains = this.blockedDomains.filter(data => !this.settingsData.domains.ru.includes(data)); - } - } - }, - IRIpDirectSettings: { - get: function () { - return doAllItemsExist(this.settingsData.ips.ir, this.directIPs); - }, - set: function (newValue) { - if (newValue) { - this.directIPs = [...this.directIPs, ...this.settingsData.ips.ir]; - } else { - this.directIPs = this.directIPs.filter(data => !this.settingsData.ips.ir.includes(data)); - } - } - }, - IRDomainDirectSettings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.ir, this.directDomains); - }, - set: function (newValue) { - if (newValue) { - this.directDomains = [...this.directDomains, ...this.settingsData.domains.ir]; - } else { - this.directDomains = this.directDomains.filter(data => !this.settingsData.domains.ir.includes(data)); - } - } - }, - ChinaIpDirectSettings: { - get: function () { - return doAllItemsExist(this.settingsData.ips.cn, this.directIPs); - }, - set: function (newValue) { - if (newValue) { - this.directIPs = [...this.directIPs, ...this.settingsData.ips.cn]; - } else { - this.directIPs = this.directIPs.filter(data => !this.settingsData.ips.cn.includes(data)); - } - } - }, - ChinaDomainDirectSettings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.cn, this.directDomains); - }, - set: function (newValue) { - if (newValue) { - this.directDomains = [...this.directDomains, ...this.settingsData.domains.cn]; - } else { - this.directDomains = this.directDomains.filter(data => !this.settingsData.domains.cn.includes(data)); - } - } - }, - RussiaIpDirectSettings: { - get: function () { - return doAllItemsExist(this.settingsData.ips.ru, this.directIPs); - }, - set: function (newValue) { - if (newValue) { - this.directIPs = [...this.directIPs, ...this.settingsData.ips.ru]; - } else { - this.directIPs = this.directIPs.filter(data => !this.settingsData.ips.ru.includes(data)); - } - } - }, - RussiaDomainDirectSettings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.ru, this.directDomains); - }, - set: function (newValue) { - if (newValue) { - this.directDomains = [...this.directDomains, ...this.settingsData.domains.ru]; - } else { - this.directDomains = this.directDomains.filter(data => !this.settingsData.domains.ru.includes(data)); - } - } - }, - GoogleWARPSettings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.google, this.warpDomains); - }, - set: function (newValue) { - if (newValue) { - this.warpDomains = [...this.warpDomains, ...this.settingsData.domains.google]; - } else { - this.warpDomains = this.warpDomains.filter(data => !this.settingsData.domains.google.includes(data)); - } - }, - }, - OpenAIWARPSettings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.openai, this.warpDomains); - }, - set: function (newValue) { - if (newValue) { - this.warpDomains = [...this.warpDomains, ...this.settingsData.domains.openai]; - } else { - this.warpDomains = this.warpDomains.filter(data => !this.settingsData.domains.openai.includes(data)); - } - }, - }, - NetflixWARPSettings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.netflix, this.warpDomains); - }, - set: function (newValue) { - if (newValue) { - this.warpDomains = [...this.warpDomains, ...this.settingsData.domains.netflix]; - } else { - this.warpDomains = this.warpDomains.filter(data => !this.settingsData.domains.netflix.includes(data)); - } - }, - }, - SpotifyWARPSettings: { - get: function () { - return doAllItemsExist(this.settingsData.domains.spotify, this.warpDomains); - }, - set: function (newValue) { - if (newValue) { - this.warpDomains = [...this.warpDomains, ...this.settingsData.domains.spotify]; - } else { - this.warpDomains = this.warpDomains.filter(data => !this.settingsData.domains.spotify.includes(data)); - } - }, - }, - }, }); diff --git a/web/html/xui/xray.html b/web/html/xui/xray.html new file mode 100644 index 00000000..99b1878d --- /dev/null +++ b/web/html/xui/xray.html @@ -0,0 +1,1401 @@ + + +{{template "head" .}} + + + + + + + + + + + + + + + + + + + + {{ template "commonSider" . }} + + + + + + + + + {{ i18n "pages.xray.save" }} + {{ i18n "pages.xray.restart" }} + + Error in running xray-core + + + + + + + + + + + + + + + + {{ i18n "pages.settings.resetDefaultConfig" }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{ i18n "pages.xray.rules.add" }} + + + + + + + + + {{ i18n "pages.xray.outbound.addOutbound" }} + {{ i18n "pages.xray.outbound.addReverse" }} + + +

{{ i18n "pages.xray.Outbounds"}}

+ + + + + +
+ +

{{ i18n "pages.xray.outbound.reverse"}}

+ + + +
+
+
+ + + + {{ i18n "pages.xray.completeTemplate"}} + {{ i18n "pages.xray.Inbounds" }} + {{ i18n "pages.xray.Outbounds" }} + {{ i18n "pages.xray.Routings" }} + + + +
+
+
+
+
+
+{{template "js" .}} +{{template "component/themeSwitcher" .}} +{{template "component/setting"}} +{{template "ruleModal"}} +{{template "outModal"}} +{{template "reverseModal"}} + + + \ No newline at end of file diff --git a/web/html/xui/xray_outbound_modal.html b/web/html/xui/xray_outbound_modal.html new file mode 100644 index 00000000..2941e096 --- /dev/null +++ b/web/html/xui/xray_outbound_modal.html @@ -0,0 +1,127 @@ +{{define "outModal"}} + + {{template "form/outbound"}} + + +{{end}} diff --git a/web/html/xui/xray_reverse_modal.html b/web/html/xui/xray_reverse_modal.html new file mode 100644 index 00000000..b3a69cc3 --- /dev/null +++ b/web/html/xui/xray_reverse_modal.html @@ -0,0 +1,176 @@ +{{define "reverseModal"}} + + + + + + + + + + + + + + + + + +
{{ i18n "pages.xray.outbound.type" }} + + + [[ x ]] + + +
{{ i18n "pages.xray.outbound.tag" }} + + + +
{{ i18n "pages.xray.outbound.domain" }} + + + +
+
+
+ +{{end}} \ No newline at end of file diff --git a/web/html/xui/xray_rule_modal.html b/web/html/xui/xray_rule_modal.html new file mode 100644 index 00000000..a5fd2e54 --- /dev/null +++ b/web/html/xui/xray_rule_modal.html @@ -0,0 +1,277 @@ +{{define "ruleModal"}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Domain Matcher + + + [[ dm ]] + + +
Source IPs + + + + + + + + +
Source Port + + + + + + + + +
Network + + + [[ x ]] + + +
Protocol + + + [[ x ]] + + +
+ + Attributes + + + + + + + + - + + + +
IP + + + + + + + + +
Domain + + + + + + + + +
Port + + + + + + + + +
Inbound Tags + + + [[ tag ]] + + +
Outbound Tag + + + [[ tag ]] + + +
+
+
+ +{{end}} \ No newline at end of file diff --git a/web/service/inbound.go b/web/service/inbound.go index 1646b5ed..01d4eb57 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -168,9 +168,13 @@ func (s *InboundService) AddInbound(inbound *model.Inbound) (*model.Inbound, boo err = tx.Save(inbound).Error if err == nil { - for _, client := range clients { - s.AddClientStat(tx, inbound.Id, &client) + if len(inbound.ClientStats) == 0 { + for _, client := range clients { + s.AddClientStat(tx, inbound.Id, &client) + } } + } else { + return inbound, false, err } needRestart := false @@ -263,7 +267,18 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound, tag := oldInbound.Tag - err = s.updateClientTraffics(oldInbound, inbound) + db := database.GetDB() + tx := db.Begin() + + defer func() { + if err != nil { + tx.Rollback() + } else { + tx.Commit() + } + }() + + err = s.updateClientTraffics(tx, oldInbound, inbound) if err != nil { return inbound, false, err } @@ -304,11 +319,10 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound, } s.xrayApi.Close() - db := database.GetDB() - return inbound, needRestart, db.Save(oldInbound).Error + return inbound, needRestart, tx.Save(oldInbound).Error } -func (s *InboundService) updateClientTraffics(oldInbound *model.Inbound, newInbound *model.Inbound) error { +func (s *InboundService) updateClientTraffics(tx *gorm.DB, oldInbound *model.Inbound, newInbound *model.Inbound) error { oldClients, err := s.GetClients(oldInbound) if err != nil { return err @@ -318,17 +332,6 @@ func (s *InboundService) updateClientTraffics(oldInbound *model.Inbound, newInbo return err } - db := database.GetDB() - tx := db.Begin() - - defer func() { - if err != nil { - tx.Rollback() - } else { - tx.Commit() - } - }() - var emailExists bool for _, oldClient := range oldClients { @@ -601,7 +604,7 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin if len(clients[0].Email) > 0 { if len(oldEmail) > 0 { - err = s.UpdateClientStat(oldEmail, &clients[0]) + err = s.UpdateClientStat(tx, oldEmail, &clients[0]) if err != nil { return false, err } @@ -676,6 +679,13 @@ func (s *InboundService) AddTraffic(inboundTraffics []*xray.Traffic, clientTraff return err, false } + needRestart0, count, err := s.autoRenewClients(tx) + if err != nil { + logger.Warning("Error in renew clients:", err) + } else if count > 0 { + logger.Debugf("%v clients renewed", count) + } + needRestart1, count, err := s.disableInvalidClients(tx) if err != nil { logger.Warning("Error in disabling invalid clients:", err) @@ -689,7 +699,7 @@ func (s *InboundService) AddTraffic(inboundTraffics []*xray.Traffic, clientTraff } else if count > 0 { logger.Debugf("%v inbounds disabled", count) } - return nil, (needRestart1 || needRestart2) + return nil, (needRestart0 || needRestart1 || needRestart2) } func (s *InboundService) addInboundTraffic(tx *gorm.DB, traffics []*xray.Traffic) error { @@ -716,9 +726,15 @@ func (s *InboundService) addInboundTraffic(tx *gorm.DB, traffics []*xray.Traffic func (s *InboundService) addClientTraffic(tx *gorm.DB, traffics []*xray.ClientTraffic) (err error) { if len(traffics) == 0 { + // Empty onlineUsers + if p != nil { + p.SetOnlineClients(nil) + } return nil } + var onlineClients []string + emails := make([]string, 0, len(traffics)) for _, traffic := range traffics { emails = append(emails, traffic.Email) @@ -744,11 +760,19 @@ func (s *InboundService) addClientTraffic(tx *gorm.DB, traffics []*xray.ClientTr if dbClientTraffics[dbTraffic_index].Email == traffics[traffic_index].Email { dbClientTraffics[dbTraffic_index].Up += traffics[traffic_index].Up dbClientTraffics[dbTraffic_index].Down += traffics[traffic_index].Down + + // Add user in onlineUsers array on traffic + if traffics[traffic_index].Up+traffics[traffic_index].Down > 0 { + onlineClients = append(onlineClients, traffics[traffic_index].Email) + } break } } } + // Set onlineUsers + p.SetOnlineClients(onlineClients) + err = tx.Save(dbClientTraffics).Error if err != nil { logger.Warning("AddClientTraffic update data ", err) @@ -809,6 +833,102 @@ func (s *InboundService) adjustTraffics(tx *gorm.DB, dbClientTraffics []*xray.Cl return dbClientTraffics, nil } +func (s *InboundService) autoRenewClients(tx *gorm.DB) (bool, int64, error) { + // check for time expired + var traffics []*xray.ClientTraffic + now := time.Now().Unix() * 1000 + var err, err1 error + + err = tx.Model(xray.ClientTraffic{}).Where("reset > 0 and expiry_time > 0 and expiry_time <= ?", now).Find(&traffics).Error + if err != nil { + return false, 0, err + } + // return if there is no client to renew + if len(traffics) == 0 { + return false, 0, nil + } + + var inbound_ids []int + var inbounds []*model.Inbound + needRestart := false + var clientsToAdd []struct { + protocol string + tag string + client map[string]interface{} + } + + for _, traffic := range traffics { + inbound_ids = append(inbound_ids, traffic.InboundId) + } + err = tx.Model(model.Inbound{}).Where("id IN ?", inbound_ids).Find(&inbounds).Error + if err != nil { + return false, 0, err + } + for inbound_index := range inbounds { + settings := map[string]interface{}{} + json.Unmarshal([]byte(inbounds[inbound_index].Settings), &settings) + clients := settings["clients"].([]interface{}) + for client_index := range clients { + c := clients[client_index].(map[string]interface{}) + for traffic_index, traffic := range traffics { + if traffic.Email == c["email"].(string) { + newExpiryTime := traffic.ExpiryTime + for newExpiryTime < now { + newExpiryTime += (int64(traffic.Reset) * 86400000) + } + c["expiryTime"] = newExpiryTime + traffics[traffic_index].ExpiryTime = newExpiryTime + traffics[traffic_index].Down = 0 + traffics[traffic_index].Up = 0 + if !traffic.Enable { + traffics[traffic_index].Enable = true + clientsToAdd = append(clientsToAdd, + struct { + protocol string + tag string + client map[string]interface{} + }{ + protocol: string(inbounds[inbound_index].Protocol), + tag: inbounds[inbound_index].Tag, + client: c, + }) + } + clients[client_index] = interface{}(c) + break + } + } + } + settings["clients"] = clients + newSettings, err := json.MarshalIndent(settings, "", " ") + if err != nil { + return false, 0, err + } + inbounds[inbound_index].Settings = string(newSettings) + } + err = tx.Save(inbounds).Error + if err != nil { + return false, 0, err + } + err = tx.Save(traffics).Error + if err != nil { + return false, 0, err + } + if p != nil { + err1 = s.xrayApi.Init(p.GetAPIPort()) + if err1 != nil { + return true, int64(len(traffics)), nil + } + for _, clientToAdd := range clientsToAdd { + err1 = s.xrayApi.AddUser(clientToAdd.protocol, clientToAdd.tag, clientToAdd.client) + if err1 != nil { + needRestart = true + } + } + s.xrayApi.Close() + } + return needRestart, int64(len(traffics)), nil +} + func (s *InboundService) disableInvalidInbounds(tx *gorm.DB) (bool, int64, error) { now := time.Now().Unix() * 1000 needRestart := false @@ -881,6 +1001,17 @@ func (s *InboundService) disableInvalidClients(tx *gorm.DB) (bool, int64, error) return needRestart, count, err } +func (s *InboundService) GetInboundTags() (string, error) { + db := database.GetDB() + var inboundTags []string + err := db.Model(model.Inbound{}).Select("tag").Find(&inboundTags).Error + if err != nil && err != gorm.ErrRecordNotFound { + return "", err + } + tags, _ := json.Marshal(inboundTags) + return string(tags), nil +} + func (s *InboundService) MigrationRemoveOrphanedTraffics() { db := database.GetDB() db.Exec(` @@ -902,6 +1033,7 @@ func (s *InboundService) AddClientStat(tx *gorm.DB, inboundId int, client *model clientTraffic.Enable = true clientTraffic.Up = 0 clientTraffic.Down = 0 + clientTraffic.Reset = client.Reset result := tx.Create(&clientTraffic) err := result.Error if err != nil { @@ -910,16 +1042,15 @@ func (s *InboundService) AddClientStat(tx *gorm.DB, inboundId int, client *model return nil } -func (s *InboundService) UpdateClientStat(email string, client *model.Client) error { - db := database.GetDB() - - result := db.Model(xray.ClientTraffic{}). +func (s *InboundService) UpdateClientStat(tx *gorm.DB, email string, client *model.Client) error { + result := tx.Model(xray.ClientTraffic{}). Where("email = ?", email). Updates(map[string]interface{}{ "enable": true, "email": client.Email, "total": client.TotalGB, - "expiry_time": client.ExpiryTime}) + "expiry_time": client.ExpiryTime, + "reset": client.Reset}) err := result.Error if err != nil { return err @@ -1415,7 +1546,7 @@ func (s *InboundService) DelDepletedClients(id int) (err error) { } }() - whereText := "inbound_id " + whereText := "reset = 0 and inbound_id " if id < 0 { whereText += "> ?" } else { @@ -1669,9 +1800,53 @@ func (s *InboundService) MigrationRequirements() { // Remove orphaned traffics tx.Where("inbound_id = 0").Delete(xray.ClientTraffic{}) + + // Migrate old MultiDomain to External Proxy + var externalProxy []struct { + Id int + Port int + StreamSettings []byte + } + err = tx.Raw(`select id, port, stream_settings + from inbounds + WHERE protocol in ('vmess','vless','trojan') + AND json_extract(stream_settings, '$.security') = 'tls' + AND json_extract(stream_settings, '$.tlsSettings.settings.domains') IS NOT NULL`).Scan(&externalProxy).Error + if err != nil || len(externalProxy) == 0 { + return + } + + for _, ep := range externalProxy { + var reverses interface{} + var stream map[string]interface{} + json.Unmarshal(ep.StreamSettings, &stream) + if tlsSettings, ok := stream["tlsSettings"].(map[string]interface{}); ok { + if settings, ok := tlsSettings["settings"].(map[string]interface{}); ok { + if domains, ok := settings["domains"].([]interface{}); ok { + for _, domain := range domains { + if domainMap, ok := domain.(map[string]interface{}); ok { + domainMap["forceTls"] = "same" + domainMap["port"] = ep.Port + domainMap["dest"] = domainMap["domain"].(string) + delete(domainMap, "domain") + } + } + } + reverses = settings["domains"] + delete(settings, "domains") + } + } + stream["externalProxy"] = reverses + newStream, _ := json.MarshalIndent(stream, " ", " ") + tx.Model(model.Inbound{}).Where("id = ?", ep.Id).Update("stream_settings", newStream) + } } func (s *InboundService) MigrateDB() { s.MigrationRequirements() s.MigrationRemoveOrphanedTraffics() } + +func (s *InboundService) GetOnlineClinets() []string { + return p.GetOnlineClients() +} diff --git a/web/service/server.go b/web/service/server.go index d88fa098..822918a8 100644 --- a/web/service/server.go +++ b/web/service/server.go @@ -230,7 +230,7 @@ func (s *ServerService) GetStatus(lastStatus *Status) *Status { status.AppStats.Mem = rtm.Sys status.AppStats.Threads = uint32(runtime.NumGoroutine()) - if p.IsRunning() { + if p != nil && p.IsRunning() { status.AppStats.Uptime = p.GetUptime() } else { status.AppStats.Uptime = 0 @@ -380,14 +380,6 @@ func (s *ServerService) UpdateXray(version string) error { if err != nil { return err } - err = copyZipFile("geosite.dat", xray.GetGeositePath()) - if err != nil { - return err - } - err = copyZipFile("geoip.dat", xray.GetGeoipPath()) - if err != nil { - return err - } return nil @@ -435,6 +427,11 @@ func (s *ServerService) GetConfigJson() (interface{}, error) { } func (s *ServerService) GetDb() ([]byte, error) { + // Update by manually trigger a checkpoint operation + err := database.Checkpoint() + if err != nil { + return nil, err + } // Open the file for reading file, err := os.Open(config.GetDBPath()) if err != nil { diff --git a/web/service/setting.go b/web/service/setting.go index b1565e1f..8b60d166 100644 --- a/web/service/setting.go +++ b/web/service/setting.go @@ -31,8 +31,10 @@ var defaultValueMap = map[string]string{ "secret": random.Seq(32), "webBasePath": "/", "sessionMaxAge": "0", + "pageSize": "0", "expireDiff": "0", "trafficDiff": "0", + "remarkModel": "-ieo", "timeLocation": "Asia/Tehran", "tgBotEnable": "false", "tgBotToken": "", @@ -53,6 +55,7 @@ var defaultValueMap = map[string]string{ "subUpdates": "12", "subEncrypt": "true", "subShowInfo": "true", + "subURI": "", } type SettingService struct { @@ -70,7 +73,7 @@ func (s *SettingService) GetDefaultJsonConfig() (interface{}, error) { func (s *SettingService) GetAllSetting() (*entity.AllSetting, error) { db := database.GetDB() settings := make([]*model.Setting, 0) - err := db.Model(model.Setting{}).Find(&settings).Error + err := db.Model(model.Setting{}).Not("key = ?", "xrayTemplateConfig").Find(&settings).Error if err != nil { return nil, err } @@ -309,6 +312,10 @@ func (s *SettingService) GetSessionMaxAge() (int, error) { return s.getInt("sessionMaxAge") } +func (s *SettingService) GetRemarkModel() (string, error) { + return s.getString("remarkModel") +} + func (s *SettingService) GetSecretStatus() (bool, error) { return s.getBool("secretEnable") } @@ -406,6 +413,14 @@ func (s *SettingService) GetSubShowInfo() (bool, error) { return s.getBool("subShowInfo") } +func (s *SettingService) GetSubURI() (string, error) { + return s.getString("subURI") +} + +func (s *SettingService) GetPageSize() (int, error) { + return s.getInt("pageSize") +} + func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error { if err := allSetting.CheckValid(); err != nil { return err @@ -426,3 +441,71 @@ func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error { } return common.Combine(errs...) } + +func (s *SettingService) GetDefaultXrayConfig() (interface{}, error) { + var jsonData interface{} + err := json.Unmarshal([]byte(xrayTemplateConfig), &jsonData) + if err != nil { + return nil, err + } + return jsonData, nil +} + +func (s *SettingService) GetDefaultSettings(host string) (interface{}, error) { + type settingFunc func() (interface{}, error) + settings := map[string]settingFunc{ + "expireDiff": func() (interface{}, error) { return s.GetExpireDiff() }, + "trafficDiff": func() (interface{}, error) { return s.GetTrafficDiff() }, + "pageSize": func() (interface{}, error) { return s.GetPageSize() }, + "defaultCert": func() (interface{}, error) { return s.GetCertFile() }, + "defaultKey": func() (interface{}, error) { return s.GetKeyFile() }, + "tgBotEnable": func() (interface{}, error) { return s.GetTgbotenabled() }, + "subEnable": func() (interface{}, error) { return s.GetSubEnable() }, + "subURI": func() (interface{}, error) { return s.GetSubURI() }, + "remarkModel": func() (interface{}, error) { return s.GetRemarkModel() }, + } + + result := make(map[string]interface{}) + + for key, fn := range settings { + value, err := fn() + if err != nil { + return "", err + } + result[key] = value + } + + if result["subEnable"].(bool) && result["subURI"].(string) == "" { + subURI := "" + subPort, _ := s.GetSubPort() + subPath, _ := s.GetSubPath() + subDomain, _ := s.GetSubDomain() + subKeyFile, _ := s.GetSubKeyFile() + subCertFile, _ := s.GetSubCertFile() + subTLS := false + if subKeyFile != "" && subCertFile != "" { + subTLS = true + } + if subDomain == "" { + subDomain = strings.Split(host, ":")[0] + } + if subTLS { + subURI = "https://" + } else { + subURI = "http://" + } + if (subPort == 443 && subTLS) || (subPort == 80 && !subTLS) { + subURI += subDomain + } else { + subURI += fmt.Sprintf("%s:%d", subDomain, subPort) + } + if subPath[0] == byte('/') { + subURI += subPath + } else { + subURI += "/" + subPath + } + result["subURI"] = subURI + } + + return result, nil +} diff --git a/web/service/tgbot.go b/web/service/tgbot.go index b54ceb1c..0847e418 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -9,6 +9,7 @@ import ( "strings" "time" "x-ui/config" + "x-ui/database" "x-ui/database/model" "x-ui/logger" "x-ui/util/common" @@ -1417,6 +1418,12 @@ func (t *Tgbot) sendBackup(chatId int64) { output := t.I18nBot("tgbot.messages.backupTime", "Time=="+time.Now().Format("2006-01-02 15:04:05")) t.SendMsgToTgbot(chatId, output) + // Update by manually trigger a checkpoint operation + err := database.Checkpoint() + if err != nil { + logger.Warning("Error in trigger a checkpoint operation: ", err) + } + file, err := os.Open(config.GetDBPath()) if err != nil { logger.Warning("Error in opening db file for backup: ", err) diff --git a/web/service/xray.go b/web/service/xray.go index 2dbc092d..7233cec5 100644 --- a/web/service/xray.go +++ b/web/service/xray.go @@ -134,6 +134,32 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) { inbound.Settings = string(modifiedSettings) } + + if len(inbound.StreamSettings) > 0 { + // Unmarshal stream JSON + var stream map[string]interface{} + json.Unmarshal([]byte(inbound.StreamSettings), &stream) + + // Remove the "settings" field under "tlsSettings" and "realitySettings" + tlsSettings, ok1 := stream["tlsSettings"].(map[string]interface{}) + realitySettings, ok2 := stream["realitySettings"].(map[string]interface{}) + if ok1 || ok2 { + if ok1 { + delete(tlsSettings, "settings") + } else if ok2 { + delete(realitySettings, "settings") + } + } + + delete(stream, "externalProxy") + + newStream, err := json.MarshalIndent(stream, "", " ") + if err != nil { + return nil, err + } + inbound.StreamSettings = string(newStream) + } + inboundConfig := inbound.GenXrayInboundConfig() xrayConfig.InboundConfigs = append(xrayConfig.InboundConfigs, *inboundConfig) } diff --git a/web/service/xray_setting.go b/web/service/xray_setting.go new file mode 100644 index 00000000..4550bde2 --- /dev/null +++ b/web/service/xray_setting.go @@ -0,0 +1,28 @@ +package service + +import ( + _ "embed" + "encoding/json" + "x-ui/util/common" + "x-ui/xray" +) + +type XraySettingService struct { + SettingService +} + +func (s *XraySettingService) SaveXraySetting(newXraySettings string) error { + if err := s.CheckXrayConfig(newXraySettings); err != nil { + return err + } + return s.SettingService.saveSetting("xrayTemplateConfig", newXraySettings) +} + +func (s *XraySettingService) CheckXrayConfig(XrayTemplateConfig string) error { + xrayConfig := &xray.Config{} + err := json.Unmarshal([]byte(XrayTemplateConfig), xrayConfig) + if err != nil { + return common.NewError("xray template config invalid:", err) + } + return nil +} diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index 88ae4067..e704bf73 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -12,7 +12,7 @@ "protocol" = "Protocol" "search" = "Search" "filter" = "Filter" -"loading" = "Loading" +"loading" = "Loading..." "second" = "Second" "minute" = "Minute" "hour" = "Hour" @@ -37,7 +37,9 @@ "enabled" = "Enabled" "disabled" = "Disabled" "depleted" = "Depleted" -"depletingSoon" = "Depleting soon" +"depletingSoon" = "Depleting" +"offline" = "Offline" +"online" = "Online" "domainName" = "Domain name" "monitor" = "Listening IP" "certificate" = "Certificate" @@ -49,11 +51,13 @@ "usage" = "Usage" "secretToken" = "Secret Token" "remained" = "Remained" +"security" = "Security" [menu] "dashboard" = "System Status" "inbounds" = "Inbounds" "settings" = "Panel Settings" +"xray" = "Xray Settings" "logout" = "Logout" "link" = "Other" @@ -121,6 +125,8 @@ "modifyInbound" = "Modify Inbound" "deleteInbound" = "Delete Inbound" "deleteInboundContent" = "Confirm deletion of inbound?" +"deleteClient" = "Delete Client" +"deleteClientContent" = "Are you sure you want to delete client?" "resetTrafficContent" = "Confirm traffic reset?" "copyLink" = "Copy Link" "address" = "Address" @@ -132,8 +138,8 @@ "totalFlow" = "Total Flow" "leaveBlankToNeverExpire" = "Leave Blank to Never Expire" "noRecommendKeepDefault" = "No special requirements to maintain default settings" -"certificatePath" = "Certificate File Path" -"certificateContent" = "Certificate File Content" +"certificatePath" = "File Path" +"certificateContent" = "File Content" "publicKeyPath" = "Public Key Path" "publicKeyContent" = "Public Key Content" "keyPath" = "Private Key Path" @@ -169,6 +175,12 @@ "realityDesc" = "Xray core needs to be 1.8.0 or higher." "telegramDesc" = "use Telegram ID without @ or chat IDs ( you can get it here @userinfobot or use '/id' command in bot )" "subscriptionDesc" = "you can find your sub link on Details, also you can use the same name for several configurations" +"info" = "Info" +"same" = "Same" +"inboundData" = "Inbound's data" +"copyToClipboard" = "Copy to clipboard" +"import" = "Import" +"importInbound" = "Import an inbound" [pages.client] "add" = "Add Client" @@ -185,6 +197,8 @@ "delayedStart" = "Start after first use" "expireDays" = "Expire days" "days" = "day(s)" +"renew" = "Auto renew" +"renewDesc" = "Auto renew days after expiration. 0 = disable" [pages.inbounds.toasts] "obtain" = "Obtain" @@ -216,7 +230,6 @@ "resetDefaultConfig" = "Reset to Default Configuration" "panelSettings" = "Panel Settings" "securitySettings" = "Security Settings" -"xrayConfiguration" = "Xray Configuration" "TGBotSettings" = "Telegram Bot Settings" "panelListeningIP" = "Panel Listening IP" "panelListeningIPDesc" = "Leave blank by default to monitor all IPs." @@ -230,6 +243,10 @@ "privateKeyPathDesc" = "Fill in an absolute path starting with." "panelUrlPath" = "Panel URL Root Path" "panelUrlPathDesc" = "Must start with '/' and end with." +"pageSize" = "Pagination size" +"pageSizeDesc" = "Define page size for inbounds table. Set 0 to disable" +"remarkModel" = "Remark Model and Seperation charachter" +"sampleRemark" = "Sample remark" "oldUsername" = "Current Username" "currentPassword" = "Current Password" "newUsername" = "New Username" @@ -276,13 +293,16 @@ "subEncrypt" = "Encrypt configs" "subEncryptDesc" = "Encrypt the returned configs in subscription" "subShowInfo" = "Show usage info" -"subShowInfoDesc" = "Show remianed traffic and date after config name" +"subShowInfoDesc" = "Show remained traffic and date after config name" +"subURI" = "Reverse Proxy URI" +"subURIDesc" = "Change base URI of subscription URL for using on behind of proxies" -[pages.settings.templates] -"title" = "Templates" +[pages.xray] +"title" = "Xray Settings" +"save" = "Save Settings" +"restart" = "Restart Xray" "basicTemplate" = "Basic Template" "advancedTemplate" = "Advanced Template" -"completeTemplate" = "Complete Template" "generalConfigs" = "General Configs" "generalConfigsDesc" = "These options will provide general adjustments." "blockConfigs" = "Blocking Configs" @@ -355,14 +375,40 @@ "xrayConfigOutboundsDesc" = "Change the configuration template to define outgoing ways for this server." "xrayConfigRoutings" = "Configuration of routing rules." "xrayConfigRoutingsDesc" = "Change the configuration template to define routing rules for this server." -"manualLists" = "Manual Lists" -"manualListsDesc" = "Please use the JSON array format." -"manualBlockedIPs" = "List of Blocked IPs" -"manualBlockedDomains" = "List of Blocked Domains" -"manualDirectIPs" = "List of Direct IPs" -"manualDirectDomains" = "List of Direct Domains" -"manualIPv4Domains" = "List of IPv4 Domains" -"manualWARPDomains" = "List of WARP Domains" +"completeTemplate" = "All" +"Inbounds" = "Inbounds" +"Outbounds" = "Outbounds" +"Routings" = "Routing rules" +"RoutingsDesc" = "The priority of each rule is important!" + +[pages.xray.rules] +"first" = "First" +"last" = "Last" +"up" = "Up" +"down" = "Down" +"source" = "Source" +"dest" = "Destination" +"inbound" = "Inbound" +"outbound" = "Outbound" +"info" = "Info" +"add" = "Add Rule" +"edit" = "Edit Rule" +"useComma" = "Comma separated items" + +[pages.xray.outbound] +"addOutbound" = "Add outbound" +"addReverse" = "Add reverse" +"editOutbound" = "Edit outbound" +"editReverse" = "Edit reverse" +"tag" = "Tag" +"tagDesc" = "Unique tag" +"address" = "Address" +"reverse" = "Reverse" +"domain" = "Domain" +"type" = "Type" +"bridge" = "Bridge" +"portal" = "Portal" +"intercon" = "Interconnection" [pages.settings.security] "admin" = "Admin" @@ -406,7 +452,7 @@ "usage" = "❗ Please provide a text to search!" "getID" = "🆔 Your ID: {{ .ID }}" "helpAdminCommands" = "Search for a client email:\r\n/usage [Email]\r\n \r\nSearch for inbounds (with client stats):\r\n/inbound [Remark]" -"helpClientCommands" = "To search for statistics, just use folowing command:\r\n \r\n/usage [UUID|Password]\r\n \r\nUse UUID for vmess/vless and Password for Trojan." +"helpClientCommands" = "To search for statistics, just use the following command:\r\n \r\n/usage [UUID|Password]\r\n \r\nUse UUID for vmess/vless and Password for Trojan." [tgbot.messages] "cpuThreshold" = "🔴 The CPU usage {{ .Percent }}% is more than threshold {{ .Threshold }}%" diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml index 31cd2aff..b3a53ba4 100644 --- a/web/translation/translate.es_ES.toml +++ b/web/translation/translate.es_ES.toml @@ -12,7 +12,7 @@ "protocol" = "Protocolo" "search" = "Buscar" "filter" = "Filtrar" -"loading" = "Cargando" +"loading" = "Cargando..." "second" = "Segundo" "minute" = "Minuto" "hour" = "Hora" @@ -37,7 +37,9 @@ "enabled" = "Habilitado" "disabled" = "Deshabilitado" "depleted" = "Agotado" -"depletingSoon" = "Agotándose pronto" +"depletingSoon" = "Agotándose" +"offline" = "fuera de línea" +"online" = "en línea" "domainName" = "Nombre de dominio" "monitor" = "Listening IP" "certificate" = "Certificado" @@ -49,11 +51,13 @@ "usage" = "Uso" "secretToken" = "Token Secreto" "remained" = "Restante" +"security" = "Seguridad" [menu] "dashboard" = "Estado del Sistema" "inbounds" = "Entradas" "settings" = "Configuraciones" +"xray" = "Configuración Xray" "logout" = "Cerrar Sesión" "link" = "Otro" @@ -121,6 +125,8 @@ "modifyInbound" = "Modificar Entrada" "deleteInbound" = "Eliminar Entrada" "deleteInboundContent" = "¿Confirmar eliminación de entrada?" +"deleteClient" = "Eliminar cliente" +"deleteClientContent" = "¿Está seguro de que desea eliminar el cliente?" "resetTrafficContent" = "¿Confirmar restablecimiento de tráfico?" "copyLink" = "Copiar Enlace" "address" = "Dirección" @@ -132,8 +138,8 @@ "totalFlow" = "Flujo Total" "leaveBlankToNeverExpire" = "Dejar en Blanco para Nunca Expirar" "noRecommendKeepDefault" = "No hay requisitos especiales para mantener la configuración predeterminada" -"certificatePath" = "Ruta del Archivo de Certificado" -"certificateContent" = "Contenido del Archivo de Certificado" +"certificatePath" = "Ruta del Archivo" +"certificateContent" = "Contenido del Archivo" "publicKeyPath" = "Ruta de la Clave Pública" "publicKeyContent" = "Contenido de la Clave Pública" "keyPath" = "Ruta de la Clave Privada" @@ -169,6 +175,12 @@ "realityDesc" = "La versión del núcleo de Xray debe ser 1.8.0 o superior." "telegramDesc" = "Utiliza el ID de Telegram sin @ o los IDs de chat (puedes obtenerlo aquí @userinfobot o usando el comando '/id' en el bot)." "subscriptionDesc" = "Puedes encontrar tu enlace de suscripción en Detalles, también puedes usar el mismo nombre para varias configuraciones." +"info" = "Info" +"same" = "misma" +"inboundData" = "Datos de entrada" +"copyToClipboard" = "Copiar al portapapeles" +"import" = "Importar" +"importInbound" = "Importar un entrante" [pages.client] "add" = "Agregar Cliente" @@ -185,6 +197,8 @@ "delayedStart" = "Iniciar después del primer uso" "expireDays" = "Días de Expiración" "days" = "día(s)" +"renew" = "Renovación automática" +"renewDesc" = "Renovación automática días después del vencimiento. 0 = deshabilitar" [pages.inbounds.toasts] "obtain" = "Recibir" @@ -216,7 +230,6 @@ "resetDefaultConfig" = "Restablecer a Configuración Predeterminada" "panelSettings" = "Configuraciones del Panel" "securitySettings" = "Configuraciones de Seguridad" -"xrayConfiguration" = "Configuración de Xray" "TGBotSettings" = "Configuraciones de Bot de Telegram" "panelListeningIP" = "IP de Escucha del Panel" "panelListeningIPDesc" = "Dejar en blanco por defecto para monitorear todas las IPs." @@ -230,6 +243,10 @@ "privateKeyPathDesc" = "Complete con una ruta absoluta que comience con." "panelUrlPath" = "Ruta Raíz de la URL del Panel" "panelUrlPathDesc" = "Debe empezar con '/' y terminar con." +"pageSize" = "Tamaño de paginación" +"pageSizeDesc" = "Defina el tamaño de página para la tabla de entradas. Establezca 0 para desactivar" +"remarkModel" = "Modelo de observación y carácter de separación" +"sampleRemark" = "Observación de muestra" "oldUsername" = "Nombre de Usuario Actual" "currentPassword" = "Contraseña Actual" "newUsername" = "Nuevo Nombre de Usuario" @@ -277,12 +294,15 @@ "subEncryptDesc" = "Encriptar las configuraciones devueltas en la suscripción." "subShowInfo" = "Mostrar información de uso" "subShowInfoDesc" = "Mostrar tráfico restante y fecha después del nombre de configuración." +"subURI" = "URI de proxy inverso" +"subURIDesc" = "Cambiar el URI base de la URL de suscripción para usar detrás de los servidores proxy" -[pages.settings.templates] -"title" = "Plantillas" +[pages.xray] +"title" = "Xray Configuración" +"save" = "Guardar configuración" +"restart" = "Reiniciar Xray" "basicTemplate" = "Plantilla Básica" "advancedTemplate" = "Plantilla Avanzada" -"completeTemplate" = "Plantilla Completa" "generalConfigs" = "Configuraciones Generales" "generalConfigsDesc" = "Estas opciones proporcionarán ajustes generales." "blockConfigs" = "Configuraciones de Bloqueo" @@ -355,14 +375,40 @@ "xrayConfigOutboundsDesc" = "Cambia la plantilla de configuración para definir formas de salida para este servidor." "xrayConfigRoutings" = "Configuración de Reglas de Enrutamiento" "xrayConfigRoutingsDesc" = "Cambia la plantilla de configuración para definir reglas de enrutamiento para este servidor." -"manualLists" = "Listas Manuales" -"manualListsDesc" = "Por favor, utilice el formato de matriz JSON." -"manualBlockedIPs" = "Lista de IPs Bloqueadas" -"manualBlockedDomains" = "Lista de Dominios Bloqueados" -"manualDirectIPs" = "Lista de IPs Directas" -"manualDirectDomains" = "Lista de Dominios Directos" -"manualIPv4Domains" = "Lista de Dominios IPv4" -"manualWARPDomains" = "Lista de Dominios de WARP" +"completeTemplate" = "Todos" +"Inbounds" = "Entrante" +"Outbounds" = "Salidas" +"Routings" = "Reglas de enrutamiento" +"RoutingsDesc" = "¡La prioridad de cada regla es importante!" + +[pages.xray.rules] +"first" = "Primero" +"last" = "Último" +"up" = "arriba" +"down" = "abajo" +"source" = "Fuente" +"dest" = "Destino" +"inbound" = "Entrante" +"outbound" = "saliente" +"info" = "Información" +"add" = "Agregar regla" +"edit" = "Editar regla" +"useComma" = "Elementos separados por comas" + +[pages.xray.outbound] +"addOutbound" = "Agregar salida" +"addReverse" = "Agregar reverso" +"editOutbound" = "Editar salida" +"editReverse" = "Editar reverso" +"tag" = "Etiqueta" +"tagDesc" = "etiqueta única" +"address" = "Dirección" +"reverse" = "Reverso" +"domain" = "Dominio" +"type" = "Tipo" +"bridge" = "puente" +"portal" = "portal" +"intercon" = "Interconexión" [pages.settings.security] "admin" = "Administrador" diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index c95d135e..c0d2c59b 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -38,6 +38,8 @@ "disabled" = "غیرفعال" "depleted" = "منقضی" "depletingSoon" = "در حال انقضا" +"offline" = "آفلاین" +"online" = "آنلاین" "domainName" = "آدرس دامنه" "monitor" = "آی پی اتصال" "certificate" = "گواهی دیجیتال" @@ -49,11 +51,13 @@ "usage" = "استفاده" "secretToken" = "توکن امنیتی" "remained" = "باقیمانده" +"security" = "امنیت" [menu] "dashboard" = "وضعیت سیستم" "inbounds" = "سرویس ها" "settings" = "تنظیمات پنل" +"xray" = "الگوی ایکس‌ری" "logout" = "خروج" "link" = "دیگر" @@ -121,6 +125,8 @@ "modifyInbound" = "ویرایش سرویس" "deleteInbound" = "حذف سرویس" "deleteInboundContent" = "آیا مطمئن به حذف سرویس هستید ؟" +"deleteClient" = "حذف کاربر" +"deleteClientContent" = "آیا مطمئن به حذف کاربر هستید ؟" "resetTrafficContent" = "آیا مطمئن به ریست ترافیک هستید ؟" "copyLink" = "کپی لینک" "address" = "آدرس" @@ -169,6 +175,12 @@ "realityDesc" = "هسته Xray باید 1.8.0 و بالاتر باشد" "telegramDesc" = "از آیدی تلگرام بدون @ یا آیدی چت استفاده کنید (می توانید آن را از اینجا دریافت کنید @userinfobot یا در ربات دستور '/id' را وارد کنید)" "subscriptionDesc" = "می توانید ساب لینک خود را در جزئیات پیدا کنید، همچنین می توانید از همین نام برای چندین کانفیگ استفاده کنید" +"info" = "اطلاعات" +"same" = "همسان" +"inboundData" = "داده‌های سرویس" +"copyToClipboard" = "کپی در حافظه" +"import" = "وارد کردن" +"importInbound" = "وارد کردن یک سرویس" [pages.client] "add" = "کاربر جدید" @@ -185,6 +197,8 @@ "delayedStart" = "شروع بعد از اولین استفاده" "expireDays" = "روزهای اعتبار" "days" = "(روز)" +"renew" = "تمدید خودکار" +"renewDesc" = "روزهای تمدید خودکار پس از انقضا. 0 = غیرفعال" [pages.inbounds.toasts] "obtain" = "Obtain" @@ -216,7 +230,6 @@ "resetDefaultConfig" = "برگشت به تنظیمات پیشفرض" "panelSettings" = "تنظیمات پنل" "securitySettings" = "تنظیمات امنیتی" -"xrayConfiguration" = "تنظیمات Xray" "TGBotSettings" = "تنظیمات ربات تلگرام" "panelListeningIP" = "محدودیت آی پی پنل" "panelListeningIPDesc" = "برای استفاده از تمام آی‌پیها به طور پیش فرض خالی بگذارید" @@ -230,6 +243,10 @@ "privateKeyPathDesc" = "باید یک مسیر مطلق باشد که با / شروع می شود " "panelUrlPath" = "آدرس روت پنل" "panelUrlPathDesc" = "باید با '/' شروع شود و با '/' تمام شود" +"pageSize" = "اندازه صفحه بندی جدول" +"pageSizeDesc" = "اندازه صفحه را برای جدول سرویس ها تعریف کنید. 0: غیرفعال" +"remarkModel" = "نام کانفیگ و جداکننده" +"sampleRemark" = "نمونه نام" "oldUsername" = "نام کاربری فعلی" "currentPassword" = "رمز عبور فعلی" "newUsername" = "نام کاربری جدید" @@ -277,12 +294,15 @@ "subEncryptDesc" = "رمزگذاری کانفیگ های بازگشتی سابسکریپشن" "subShowInfo" = "نمایش اطلاعات مصرف" "subShowInfoDesc" = "ترافیک و زمان باقیمانده را در هر کانفیگ نمایش میدهد" +"subURI" = "آدرس پایه پروکسی معکوس" +"subURIDesc" = "آدرس پایه سابسکریپشن را برای استفاده در پشت پراکسی ها تغییر میدهد" -[pages.settings.templates] +[pages.xray] "title" = "الگوها" +"save" = "ذخیره تنظیمات" +"restart" = "ریستارت ایکس‌ری" "basicTemplate" = "بخش الگو پایه" "advancedTemplate" = "بخش الگو پیشرفته" -"completeTemplate" = "بخش الگو کامل" "generalConfigs" = "تنظیمات عمومی" "generalConfigsDesc" = "این تنظیمات میتواند ترافیک کلی سرویس را متاثر کند" "blockConfigs" = "مسدود سازی" @@ -355,14 +375,40 @@ "xrayConfigOutboundsDesc" = "میتوانید الگوی تنظیمات را برای خروجی اینترنت تنظیم نمایید" "xrayConfigRoutings" = "تنظیمات قوانین مسیریابی" "xrayConfigRoutingsDesc" = "میتوانید الگوی تنظیمات را برای مسیریابی تنظیم نمایید" -"manualLists" = "لیست های دستی" -"manualListsDesc" = "فرمت: JSON Array" -"manualBlockedIPs" = "لیست آی‌پی های مسدود شده" -"manualBlockedDomains" = "لیست دامنه های مسدود شده" -"manualDirectIPs" = "لیست آی‌پی های مستقیم" -"manualDirectDomains" = "لیست دامنه های مستقیم" -"manualIPv4Domains" = "لیست دامنه‌های IPv4" -"manualWARPDomains" = "لیست دامنه های WARP" +"completeTemplate" = "کامل" +"Inbounds" = "ورودی‌ها" +"Outbounds" = "خروجی‌ها" +"Routings" = "قوانین مسیریابی" +"RoutingsDesc" = "اولویت هر قانون مهم است!" + +[pages.xray.rules] +"first" = "اولین" +"last" = "آخرین" +"up" = "بالا" +"down" = "پایین" +"source" = "مبدا" +"dest" = "مقصد" +"inbound" = "ورودی" +"outbound" = "خروجی" +"info" = "اطلاعات" +"add" = "افزودن قانون" +"edit" = "ویرایش قانون" +"useComma" = "موارد جدا شده با کاما" + +[pages.xray.outbound] +"addOutbound" = "افزودن خروجی" +"addReverse" = "افزودن معکوس" +"editOutbound" = "ویرایش خروجی" +"editReverse" = "ویرایش معکوس" +"tag" = "برچسب" +"tagDesc" = "برچسب یگانه" +"address" = "آدرس" +"reverse" = "معکوس" +"domain" = "دامنه" +"type" = "نوع" +"bridge" = "پل" +"portal" = "پرتال" +"intercon" = "اتصال میانی" [pages.settings.security] "admin" = "مدیر" @@ -370,7 +416,7 @@ "loginSecurity" = "لاگین ایمن" "loginSecurityDesc" = "افزودن یک مرحله دیگر به فرآیند لاگین" "secretToken" = "توکن امنیتی" -"secretTokenDesc" = "این کد امنیتی را نزد خود در این جای امن نگه داری، بدون این کد امکان ورود به پنل را نخواهید داشت. امکان بازیابی آن وجود ندارد!" +"secretTokenDesc" = "این کد امنیتی را نزد خود در این جای امن نگه دارید، بدون این کد امکان ورود به پنل را نخواهید داشت. امکان بازیابی آن وجود ندارد!" [pages.settings.toasts] "modifySettings" = "ویرایش تنظیمات" diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index 5cb89a17..44c4608e 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -12,7 +12,7 @@ "protocol" = "Протокол" "search" = "Поиск" "filter" = "Фильтр" -"loading" = "Загрузка" +"loading" = "Загрузка..." "second" = "Секунда" "minute" = "Минута" "hour" = "Час" @@ -38,6 +38,8 @@ "disabled" = "Отключено" "depleted" = "Исчерпано" "depletingSoon" = "Почти исчерпано" +"offline" = "Офлайн" +"online" = "Онлайн" "domainName" = "Домен" "monitor" = "Порт IP" "certificate" = "Сертификат" @@ -49,11 +51,13 @@ "usage" = "Использование" "secretToken" = "Секретный токен" "remained" = "остались" +"security" = "Безопасность" [menu] "dashboard" = "Статус системы" "inbounds" = "Подключения" "settings" = "Настройки панели" +"xray" = "Xray Настройки" "logout" = "Выход" "link" = "Прочее" @@ -121,6 +125,8 @@ "modifyInbound" = "Изменить подключение" "deleteInbound" = "Удалить подключение" "deleteInboundContent" = "Подтвердите удаление подключения?" +"deleteClient" = "Удалить клиента" +"deleteClientContent" = "Вы уверены, что хотите удалить клиента?" "resetTrafficContent" = "Подтвердите сброс трафика?" "copyLink" = "Копировать ключ" "address" = "Адрес" @@ -132,8 +138,8 @@ "totalFlow" = "Общий расход" "leaveBlankToNeverExpire" = "Оставьте пустым, чтобы не истекало" "noRecommendKeepDefault" = "Нет требований для сохранения настроек по умолчанию" -"certificatePath" = "Путь файла сертификата" -"certificateContent" = "Содержимое файла сертификата" +"certificatePath" = "Путь файла" +"certificateContent" = "Содержимое файла" "publicKeyPath" = "Путь к публичному ключу" "publicKeyContent" = "Содержимое публичного ключа" "keyPath" = "Путь к приватному ключу" @@ -169,6 +175,12 @@ "realityDesc" = "Версия Xray должна быть не ниже 1.8.0" "telegramDesc" = "Используйте идентификатор Telegram без символа @ или идентификатора чата (можно получить его здесь @userinfobot или использовать команду '/id' в боте)" "subscriptionDesc" = "Вы можете найти свою ссылку подписки в разделе 'Подробнее', также вы можете использовать одно и то же имя для нескольких конфигураций" +"info" = "Информация" +"same" = "Тот же" +"inboundData" = "Входящие данные" +"copyToClipboard" = "Копировать в буфер обмена" +"import" = "Импортировать" +"importInbound" = "Импортировать входящее сообщение" [pages.client] "add" = "Добавить пользователя" @@ -185,6 +197,8 @@ "delayedStart" = "Начать с момента первого подключения" "expireDays" = "Срок действия" "days" = "дней" +"renew" = "Автопродление" +"renewDesc" = "Автоматическое продление через несколько дней после истечения срока действия. 0 = отключить" [pages.inbounds.toasts] "obtain" = "Получить" @@ -216,7 +230,6 @@ "resetDefaultConfig" = "Сбросить на конфигурацию по умолчанию" "panelSettings" = "Настройки панели" "securitySettings" = "Настройки безопасности" -"xrayConfiguration" = "Конфигурация Xray" "TGBotSettings" = "Настройки Telegram бота" "panelListeningIP" = "IP-адрес панели" "panelListeningIPDesc" = "Оставьте пустым для подключения с любого IP" @@ -225,11 +238,15 @@ "panelPort" = "Порт панели" "panelPortDesc" = "Порт, используемый для отображения этой панели" "publicKeyPath" = "Путь к файлу публичного ключа сертификата панели" -"publicKeyPathDesc" = "Введите полный путь, начинающийся с " +"publicKeyPathDesc" = "Введите полный путь, начинающийся с" "privateKeyPath" = "Путь к файлу приватного ключа сертификата панели" -"privateKeyPathDesc" = "Введите полный путь, начинающийся с " +"privateKeyPathDesc" = "Введите полный путь, начинающийся с" "panelUrlPath" = "Корневой путь URL адреса панели" -"panelUrlPathDesc" = "Должен начинаться с '/' и заканчиваться на " +"panelUrlPathDesc" = "Должен начинаться с '/' и заканчиваться на" +"pageSize" = "Размер нумерации страниц" +"pageSizeDesc" = "Определить размер страницы для входящей таблицы. Установите 0, чтобы отключить" +"remarkModel" = "Модель примечания и символ разделения" +"sampleRemark" = "Пример замечания" "oldUsername" = "Текущее имя пользователя" "currentPassword" = "Текущий пароль" "newUsername" = "Новое имя пользователя" @@ -277,12 +294,15 @@ "subEncryptDesc" = "Шифровать возвращенные конфиги в подписке" "subShowInfo" = "Показать информацию об использовании" "subShowInfoDesc" = "Показывать восстановленный трафик и дату после имени конфигурации" +"subURI" = "URI обратного прокси" +"subURIDesc" = "Изменить базовый URI URL-адреса подписки для использования за прокси-серверами" -[pages.settings.templates] -"title" = "Шаблоны" +[pages.xray] +"title" = "Xray Настройки" +"save" = "Сохранить настройки" +"restart" = "Перезапустить рентген" "basicTemplate" = "Базовый шаблон" "advancedTemplate" = "Расширенный шаблон" -"completeTemplate" = "Полный шаблон" "generalConfigs" = "Основные настройки" "generalConfigsDesc" = "Эти параметры описывают общие настройки" "blockConfigs" = "Блокировка конфигураций" @@ -355,14 +375,40 @@ "xrayConfigOutboundsDesc" = "Изменение шаблона конфигурации, чтобы определить исходящие пути для этого сервера" "xrayConfigRoutings" = "Настройка правил маршрутизации" "xrayConfigRoutingsDesc" = "Изменение шаблона конфигурации для определения правил маршрутизации для этого сервера" -"manualLists" = "Ручные списки" -"manualListsDesc" = "Пожалуйста, используйте формат массива JSON" -"manualBlockedIPs" = "Список заблокированных IP-адресов" -"manualBlockedDomains" = "Список заблокированных доменов" -"manualDirectIPs" = "Список прямых IP-адресов" -"manualDirectDomains" = "Список прямых доменов" -"manualIPv4Domains" = "Список доменов IPv4" -"manualWARPDomains" = "Список доменов WARP" +"completeTemplate" = "Все" +"Inbounds" = "Входящие" +"Outbounds" = "Исходящие" +"Routings" = "Правила маршрутизации" +"RoutingsDesc" = "Важен приоритет каждого правила!" + +[pages.xray.rules] +"first" = "Первый" +"last" = "Последний" +"up" = "Вверх" +"down" = "Вниз" +"source" = "Источник" +"dest" = "Пункт назначения" +"inbound" = "Входящий" +"outboun" = "Исходящий" +"info" = "Информация" +"add" = "Добавить правило" +"edit" = "Редактировать правило" +"useComma" = "Элементы, разделенные запятыми" + +[pages.xray.outbound] +"addOutbound" = "Добавить исходящий" +"addReverse" = "Добавить реверс" +"editOutbound" = "Изменить исходящий" +"editReverse" = "Редактировать реверс" +"tag" = "Тег" +"tagDesc" = "уникальный тег" +"address" = "Адрес" +"reverse" = "Обратный" +"domain" = "Домен" +"type" = "Тип" +"bridge" = "Мост" +"portal" = "Портал" +"intercon" = "Соединение" [pages.settings.security] "admin" = "Админ" diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index c71e0053..2032e95b 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -1,6 +1,6 @@ "username" = "Tên người dùng" "password" = "Mật khẩu" -"login" = "Đăng nhập" +"login" = "Đăng nhập..." "confirm" = "Xác nhận" "cancel" = "Hủy bỏ" "close" = "Đóng" @@ -37,7 +37,9 @@ "enabled" = "Đã kích hoạt" "disabled" = "Đã tắt" "depleted" = "Đã cạn kiệt" -"depletingSoon" = "Sắp cạn kiệt" +"depletingSoon" = "Đang cạn kiệt" +"offline" = "Ngoại tuyến" +"online" = "Ngoại tuyến" "domainName" = "Tên miền" "monitor" = "Listening IP" "certificate" = "Chứng chỉ" @@ -49,12 +51,14 @@ "usage" = "Sử dụng" "secretToken" = "secretToken" "remained" = "Còn lại" +"security" = "Bảo vệ" [menu] "dashboard" = "Trạng thái hệ thống" "inbounds" = "Inbounds" "settings" = "Cài đặt bảng điều khiển" "logout" = "Đăng xuất" +"xray" = "Xray Cài đặt" "link" = "Khác" [pages.login] @@ -121,6 +125,8 @@ "modifyInbound" = "Chỉnh sửa điểm vào (Inbound)" "deleteInbound" = "Xóa điểm vào (Inbound)" "deleteInboundContent" = "Xác nhận xóa điểm vào? (Inbound)" +"deleteClient" = "Xóa khách hàng" +"deleteClientContent" = "Bạn có chắc chắn muốn xóa ứng dụng khách không?" "resetTrafficContent" = "Xác nhận đặt lại lưu lượng?" "copyLink" = "Sao chép liên kết" "address" = "Địa chỉ" @@ -132,8 +138,8 @@ "totalFlow" = "Tổng lưu lượng" "leaveBlankToNeverExpire" = "Để trống để không bao giờ hết hạn" "noRecommendKeepDefault" = "Không yêu cầu đặc biệt để giữ nguyên cài đặt mặc định" -"certificatePath" = "Đường dẫn tập tin chứng chỉ" -"certificateContent" = "Nội dung tập tin chứng chỉ" +"certificatePath" = "Đường dẫn tập" +"certificateContent" = "Nội dung tập" "publicKeyPath" = "Đường dẫn khóa công khai" "publicKeyContent" = "Nội dung khóa công khai" "keyPath" = "Đường dẫn khóa riêng tư" @@ -169,6 +175,12 @@ "realityDesc" = "Xray core cần phiên bản 1.8.0 hoặc cao hơn." "telegramDesc" = "Sử dụng Telegram ID mà không cần ký hiệu @ hoặc chat IDs (bạn có thể nhận được nó ở đây @userinfobot hoặc sử dụng lệnh '/id' trong bot)" "subscriptionDesc" = "Bạn có thể tìm liên kết đăng ký của mình trong Chi tiết, cũng như bạn có thể sử dụng cùng tên cho nhiều cấu hình khác nhau" +"info" = "Thông tin" +"same" = "Giống nhau" +"inboundData" = "Dữ liệu gửi đến" +"copyToClipboard" = "Sao chép vào bảng nhớ tạm" +"import" = "Nhập" +"importInbound" = "Nhập hàng gửi về" [pages.client] "add" = "Thêm Client" @@ -185,6 +197,8 @@ "delayedStart" = "Bắt đầu sau khi sử dụng lần đầu" "expireDays" = "Số ngày hết hạn" "days" = "ngày" +"renew" = "Tự động gia hạn" +"renewDesc" = "Tự động gia hạn những ngày sau khi hết hạn. 0 = tắt" [pages.inbounds.toasts] "obtain" = "Nhận" @@ -216,7 +230,6 @@ "resetDefaultConfig" = "Đặt lại Cấu hình Mặc định" "panelSettings" = "Cài đặt Bảng điều khiển" "securitySettings" = "Cài đặt Bảo mật" -"xrayConfiguration" = "Cấu hình Xray" "TGBotSettings" = "Cài đặt Bot Telegram" "panelListeningIP" = "IP Nghe của Bảng điều khiển" "panelListeningIPDesc" = "Mặc định để trống để nghe tất cả các IP." @@ -230,6 +243,10 @@ "privateKeyPathDesc" = "Điền vào đường dẫn tuyệt đối bắt đầu với." "panelUrlPath" = "Đường dẫn gốc URL Bảng điều khiển" "panelUrlPathDesc" = "Phải bắt đầu bằng '/' và kết thúc bằng." +"pageSize" = "Kích thước phân trang" +"pageSizeDesc" = "Xác định kích thước trang cho bảng gửi đến. Đặt 0 để tắt" +"remarkModel" = "Ghi chú mô hình và ký tự phân tách" +"sampleRemark" = "Nhận xét mẫu" "oldUsername" = "Tên người dùng hiện tại" "currentPassword" = "Mật khẩu hiện tại" "newUsername" = "Tên người dùng mới" @@ -277,12 +294,15 @@ "subEncryptDesc" = "Mã hóa các cấu hình được trả về trong đăng ký" "subShowInfo" = "Hiển thị thông tin sử dụng" "subShowInfoDesc" = "Hiển thị lưu lượng truy cập còn lại và ngày sau tên cấu hình" +"subURI" = "URI proxy ngược" +"subURIDesc" = "Thay đổi URI cơ sở của URL đăng ký để sử dụng ở phía sau proxy" -[pages.settings.templates] -"title" = "Mẫu" +[pages.xray] +"title" = "Xray Cài đặt" +"save" = "Lưu cài đặt" +"restart" = "Khởi động lại Xray" "basicTemplate" = "Mẫu Cơ bản" "advancedTemplate" = "Mẫu Nâng cao" -"completeTemplate" = "Mẫu Đầy đủ" "generalConfigs" = "Cấu hình Chung" "generalConfigsDesc" = "Những tùy chọn này sẽ cung cấp điều chỉnh tổng quát." "blockConfigs" = "Cấu hình Chặn" @@ -355,14 +375,40 @@ "xrayConfigOutboundsDesc" = "Thay đổi mẫu cấu hình để xác định các cách ra đi cho máy chủ này." "xrayConfigRoutings" = "Cấu hình của Luật Định tuyến." "xrayConfigRoutingsDesc" = "Thay đổi mẫu cấu hình để xác định luật định tuyến cho máy chủ này." -"manualLists" = "Danh sách Thủ công" -"manualListsDesc" = "Vui lòng sử dụng định dạng mảng JSON." -"manualBlockedIPs" = "Danh sách IP bị Chặn" -"manualBlockedDomains" = "Danh sách Tên miền bị Chặn" -"manualDirectIPs" = "Danh sách IP Trực tiếp" -"manualDirectDomains" = "Danh sách Tên miền Trực tiếp" -"manualIPv4Domains" = "Danh sách Tên miền IPv4" -"manualWARPDomains" = "Danh sách Tên miền WARP" +"completeTemplate" = "All" +"Inbounds" = "Vào" +"Outbounds" = "Outbounds" +"Routings" = "Quy tắc định tuyến" +"RoutingsDesc" = "Mức độ ưu tiên của mỗi quy tắc đều quan trọng!" + +[pages.xray.rules] +"first" = "Đầu tiên" +"last" = "Cuối cùng" +"up" = "Lên" +"down" = "Xuống" +"source" = "Nguồn" +"dest" = "Đích" +"inbound" = "Vào" +"outbound" = "Ra ngoài" +"info" = "Thông tin" +"add" = "Thêm quy tắc" +"edit" = "Chỉnh sửa quy tắc" +"useComma" = "Các mục được phân tách bằng dấu phẩy" + +[pages.xray.outbound] +"addOutbound" = "Thêm thư đi" +"addReverse" = "Thêm đảo ngược" +"editOutbound" = "Chỉnh sửa gửi đi" +"editReverse" = "Chỉnh sửa ngược lại" +"tag" = "Thẻ" +"tagDesc" = "thẻ duy nhất" +"address" = "Địa chỉ" +"reverse" = "Đảo ngược" +"domain" = "Miền" +"type" = "Loại" +"bridge" = "Cầu" +"portal" = "Cổng thông tin" +"intercon" = "Kết nối" [pages.settings.security] "admin" = "Quản trị viên" diff --git a/web/translation/translate.zh_Hans.toml b/web/translation/translate.zh_Hans.toml index 1483b556..8cc05e09 100644 --- a/web/translation/translate.zh_Hans.toml +++ b/web/translation/translate.zh_Hans.toml @@ -12,7 +12,7 @@ "protocol" = "协议" "search" = "搜尋" "filter" = "过滤器" -"loading" = "加载中" +"loading" = "加载中..." "second" = "秒" "minute" = "分钟" "hour" = "小时" @@ -38,6 +38,8 @@ "disabled" = "关闭" "depleted" = "耗尽" "depletingSoon" = "即将耗尽" +"offline" = "离线" +"online" = "在线" "domainName" = "域名" "monitor" = "监听" "certificate" = "证书" @@ -49,11 +51,13 @@ "usage" = "用法" "secretToken" = "秘密令牌" "remained" = "仍然存在" +"security" = "安全" [menu] "dashboard" = "系统状态" "inbounds" = "入站列表" "settings" = "面板设置" +"xray" = "Xray 设置" "logout" = "退出登录" "link" = "其他" @@ -121,6 +125,8 @@ "modifyInbound" = "修改入站" "deleteInbound" = "删除入站" "deleteInboundContent" = "确定要删除入站吗?" +"deleteClient" = "删除客户端" +"deleteClientContent" = "您确定要删除客户端吗?" "resetTrafficContent" = "确定要重置流量吗?" "copyLink" = "复制链接" "address" = "地址" @@ -132,8 +138,8 @@ "totalFlow" = "总流量" "leaveBlankToNeverExpire" = "留空则永不到期" "noRecommendKeepDefault" = "没有特殊需求保持默认即可" -"certificatePath" = "证书文件路径" -"certificateContent" = "证书文件内容" +"certificatePath" = "文件路径" +"certificateContent" = "文件内容" "publicKeyPath" = "公钥文件路径" "publicKeyContent" = "公钥内容" "keyPath" = "密钥文件路径" @@ -169,6 +175,12 @@ "realityDesc" = "Xray核心需要1.8.0及以上版本" "telegramDesc" = "使用 Telegram ID,不包含 @ 符号或聊天 ID(可以在 @userinfobot 处获取,或在机器人中使用'/id'命令)" "subscriptionDesc" = "您可以在详细信息上找到您的子链接,也可以对多个配置使用相同的名称" +"info" = "信息" +"same" = "相同" +"inboundData" = "入站数据" +"copyToClipboard" = "复制到剪贴板" +"import"="导入" +"importInbound" = "导入入站" [pages.client] "add" = "添加客户端" @@ -185,6 +197,8 @@ "delayedStart" = "首次使用后开始" "expireDays" = "过期天数" "days" = "天" +"renew" = "自动续订" +"renewDesc" = "过期后自动续订。0 = 禁用" [pages.inbounds.toasts] "obtain" = "获取" @@ -216,7 +230,6 @@ "resetDefaultConfig" = "重置为默认配置" "panelSettings" = "面板配置" "securitySettings" = "安全设定" -"xrayConfiguration" = "xray 相关设置" "TGBotSettings" = "TG提醒相关设置" "panelListeningIP" = "面板监听 IP" "panelListeningIPDesc" = "默认留空监听所有 IP" @@ -230,6 +243,10 @@ "privateKeyPathDesc" = "填写一个 '/' 开头的绝对路径" "panelUrlPath" = "面板 url 根路径" "panelUrlPathDesc" = "必须以 '/' 开头,以 '/' 结尾" +"pageSize" = "分页大小" +"pageSizeDesc" = "定义入站表的页面大小。设置 0 表示禁用" +"remarkModel" = "备注模型和分隔符" +"sampleRemark" = "备注示例" "oldUsername" = "原用户名" "currentPassword" = "原密码" "newUsername" = "新用户名" @@ -277,12 +294,15 @@ "subEncryptDesc" = "在订阅中加密返回的配置" "subShowInfo" = "显示使用信息" "subShowInfoDesc" = "在配置名称后显示剩余流量和日期" +"subURI" = "反向代理 URI" +"subURIDesc" = "更改订阅 URL 的基本 URI 以在代理后面使用" -[pages.settings.templates] -"title" = "模板" +[pages.xray] +"title" = "Xray 设置" +"save" = "保存设置" +"restart" = "重新启动 Xray" "basicTemplate" = "基本模板" "advancedTemplate" = "高级模板部件" -"completeTemplate" = "Xray 配置的完整模板" "generalConfigs" = "通用配置" "generalConfigsDesc" = "这些选项将提供一般调整" "blockConfigs" = "阻塞配置" @@ -355,14 +375,40 @@ "xrayConfigOutboundsDesc" = "更改配置模板定义此服务器的传出方式" "xrayConfigRoutings" = "路由规则配置" "xrayConfigRoutingsDesc" = "更改配置模板为该服务器定义路由规则" -"manualLists" = "手动列表" -"manualListsDesc" = "请使用 JSON 数组格式" -"manualBlockedIPs" = "被阻止的 IP 列表" -"manualBlockedDomains" = "被阻止的域列表" -"manualDirectIPs" = "直接 IP 列表" -"manualDirectDomains" = "直接域列表" -"manualIPv4Domains" = "IPv4 域名列表" -"manualWARPDomains" = "WARP域名列表" +"completeTemplate" = "全部" +"Inbounds" = "界内" +"Outbounds" = "出站" +"Routings" = "路由规则" +"RoutingsDesc" = "每条规则的优先级都很重要" + +[pages.xray.rules] +"firsto" = "第一个" +"last" = "最后" +"up" = "向上" +"down" = "向下" +"source" = "来源" +"dest" = "目的地" +"inbound" = "入站" +"outbound" = "出站" +"info" = "信息" +"add" = "添加规则" +"edit" = "编辑规则" +"useComma" = "逗号分隔的项目" + +[pages.xray.outbound] +"addOutbound" = "添加出站" +"addReverse" = "添加反向" +"editOutbound" = "编辑出站" +"editReverse" = "编辑反向" +"tag" = "标签" +"tagDesc" = "独特的标签" +"address" = "地址" +"rreverse" = "反转" +"domain" = "域名" +"type" = "类型" +"bridge" = "桥" +"portal" = "门户" +"intercon" = "互连" [pages.settings.security] "admin" = "管理员" diff --git a/web/web.go b/web/web.go index abf2d6c1..51b7603c 100644 --- a/web/web.go +++ b/web/web.go @@ -25,6 +25,7 @@ import ( sessions "github.com/Calidity/gin-sessions" "github.com/Calidity/gin-sessions/cookie" + "github.com/gin-contrib/gzip" "github.com/gin-gonic/gin" "github.com/robfig/cron/v3" ) @@ -174,6 +175,7 @@ func (s *Server) initRouter() (*gin.Engine, error) { if err != nil { return nil, err } + engine.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPaths([]string{basePath + "panel/API/"}))) assetsBasePath := basePath + "assets/" store := cookie.NewStore(secret) diff --git a/xray/client_traffic.go b/xray/client_traffic.go index d1302da4..0f2389a0 100644 --- a/xray/client_traffic.go +++ b/xray/client_traffic.go @@ -9,4 +9,5 @@ type ClientTraffic struct { Down int64 `json:"down" form:"down"` ExpiryTime int64 `json:"expiryTime" form:"expiryTime"` Total int64 `json:"total" form:"total"` + Reset int `json:"reset" form:"reset" gorm:"default:0"` } diff --git a/xray/log_writer.go b/xray/log_writer.go new file mode 100644 index 00000000..c2f66e8f --- /dev/null +++ b/xray/log_writer.go @@ -0,0 +1,53 @@ +package xray + +import ( + "strings" + "x-ui/logger" +) + +func NewLogWriter() *LogWriter { + return &LogWriter{} +} + +type LogWriter struct { + lastLine string +} + +func (lw *LogWriter) Write(m []byte) (n int, err error) { + // Convert the data to a string + message := strings.TrimSpace(string(m)) + messages := strings.Split(message, "\n") + lw.lastLine = messages[len(messages)-1] + + for _, msg := range messages { + // Remove timestamp + messageBody := strings.TrimSpace(strings.SplitN(msg, " ", 3)[2]) + + // Find level in [] + startIndex := strings.Index(messageBody, "[") + endIndex := strings.Index(messageBody, "]") + if startIndex != -1 && endIndex != -1 { + level := strings.TrimSpace(messageBody[startIndex+1 : endIndex]) + msgBody := "XRAY: " + strings.TrimSpace(messageBody[endIndex+1:]) + + // Map the level to the appropriate logger function + switch level { + case "Debug": + logger.Debug(msgBody) + case "Info": + logger.Info(msgBody) + case "Warning": + logger.Warning(msgBody) + case "Error": + logger.Error(msgBody) + default: + logger.Debug("XRAY: " + msg) + } + } else if msg != "" { + logger.Debug("XRAY: " + msg) + return len(m), nil + } + } + + return len(m), nil +} diff --git a/xray/process.go b/xray/process.go index 2e545fba..9289362f 100644 --- a/xray/process.go +++ b/xray/process.go @@ -1,7 +1,6 @@ package xray import ( - "bufio" "bytes" "encoding/json" "errors" @@ -10,16 +9,12 @@ import ( "os" "os/exec" "runtime" - "strings" - "sync" "syscall" "time" "x-ui/config" "x-ui/logger" "x-ui/util/common" - - "github.com/Workiva/go-datastructures/queue" ) func GetBinaryName() string { @@ -98,8 +93,10 @@ type process struct { version string apiPort int + onlineClients []string + config *Config - lines *queue.Queue + logWriter *LogWriter exitErr error startTime time.Time } @@ -108,7 +105,7 @@ func newProcess(config *Config) *process { return &process{ version: "Unknown", config: config, - lines: queue.New(100), + logWriter: NewLogWriter(), startTime: time.Now(), } } @@ -128,17 +125,10 @@ func (p *process) GetErr() error { } func (p *process) GetResult() string { - if p.lines.Empty() && p.exitErr != nil { + if len(p.logWriter.lastLine) == 0 && p.exitErr != nil { return p.exitErr.Error() } - items, _ := p.lines.TakeUntil(func(item interface{}) bool { - return true - }) - lines := make([]string, 0, len(items)) - for _, item := range items { - lines = append(lines, item.(string)) - } - return strings.Join(lines, "\n") + return p.logWriter.lastLine } func (p *process) GetVersion() string { @@ -153,6 +143,14 @@ func (p *Process) GetConfig() *Config { return p.config } +func (p *Process) GetOnlineClients() []string { + return p.onlineClients +} + +func (p *Process) SetOnlineClients(users []string) { + p.onlineClients = users +} + func (p *Process) GetUptime() uint64 { return uint64(time.Since(p.startTime).Seconds()) } @@ -205,54 +203,14 @@ func (p *process) Start() (err error) { cmd := exec.Command(GetBinaryPath(), "-c", configPath) p.cmd = cmd - stdReader, err := cmd.StdoutPipe() - if err != nil { - return err - } - errReader, err := cmd.StderrPipe() - if err != nil { - return err - } - - var wg sync.WaitGroup - wg.Add(2) - - go func() { - defer wg.Done() - reader := bufio.NewReaderSize(stdReader, 8192) - for { - line, _, err := reader.ReadLine() - if err != nil { - return - } - if p.lines.Len() >= 100 { - p.lines.Get(1) - } - p.lines.Put(string(line)) - } - }() - - go func() { - defer wg.Done() - reader := bufio.NewReaderSize(errReader, 8192) - for { - line, _, err := reader.ReadLine() - if err != nil { - return - } - if p.lines.Len() >= 100 { - p.lines.Get(1) - } - p.lines.Put(string(line)) - } - }() + cmd.Stdout = p.logWriter + cmd.Stderr = p.logWriter go func() { err := cmd.Run() if err != nil { p.exitErr = err } - wg.Wait() }() p.refreshVersion()