### Added

- [Files] Files can now be selected multiple files and downloaded, deleted, moved, etc.
- [Apps] Support to modify the application opening address.([#204](https://github.com/IceWhaleTech/CasaOS/issues/204))

### Changed

- [Apps] Hide the display of non-essential environment variables in the application.
- [System] Network, disk, cpu, memory, etc. information is modified to be pushed via socket.
- [System] Optimize opening speed.([#214](https://github.com/IceWhaleTech/CasaOS/issues/214))
### Fixed

- [System] Fixed the problem that sync data cannot submit the device ID ([#68](https://github.com/IceWhaleTech/CasaOS/issues/68))
- [Files] Fixed the code editor center alignment display problem.([#210](https://github.com/IceWhaleTech/CasaOS/issues/210))
- [Files] Fixed the problem of wrong name when downloading files.([#240](https://github.com/IceWhaleTech/CasaOS/issues/240))
- [System] Fixed the network display as a negative number problem.([#224](https://github.com/IceWhaleTech/CasaOS/issues/224))
This commit is contained in:
a624669980@163.com 2022-06-01 18:05:50 +08:00
parent 6ad22a2fdc
commit e172421b8c
60 changed files with 3613 additions and 2048 deletions

View File

@ -11,12 +11,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
### Removed
### Security
### Fixed
## [0.3.2-pre]
### Added
- [Files] Files can now be selected multiple files and downloaded, deleted, moved, etc.
- [Apps] Support to modify the application opening address.([#204](https://github.com/IceWhaleTech/CasaOS/issues/204))
### Changed
- [Apps] Hide the display of non-essential environment variables in the application.
- [System] Network, disk, cpu, memory, etc. information is modified to be pushed via socket.
- [System] Optimize opening speed.([#214](https://github.com/IceWhaleTech/CasaOS/issues/214))
### Fixed
- [System] Fixed the problem that sync data cannot submit the device ID ([#68](https://github.com/IceWhaleTech/CasaOS/issues/68))
- [Files] Fixed the code editor center alignment display problem.([#210](https://github.com/IceWhaleTech/CasaOS/issues/210))
- [Files] Fixed the problem of wrong name when downloading files.([#240](https://github.com/IceWhaleTech/CasaOS/issues/240))
- [System] Fixed the network display as a negative number problem.([#224](https://github.com/IceWhaleTech/CasaOS/issues/224))
## [0.3.1.1] - 2022-05-17
### Fixed

6
go.mod
View File

@ -7,6 +7,9 @@ require (
github.com/Microsoft/go-winio v0.5.0 // indirect
github.com/Microsoft/hcsshim v0.8.22 // indirect
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
github.com/ambelovsky/go-structs v1.1.0 // indirect
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 // indirect
github.com/bits-and-blooms/bitset v1.2.1 // indirect
github.com/containerd/containerd v1.5.7
github.com/containerd/continuity v0.2.0 // indirect
@ -29,6 +32,7 @@ require (
github.com/gomodule/redigo v1.8.5
github.com/google/go-github/v36 v36.0.0
github.com/google/uuid v1.3.0 // indirect
github.com/googollee/go-socket.io v1.6.2
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.4.2
github.com/jinzhu/copier v0.3.2
@ -39,6 +43,7 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.11 // indirect
github.com/mholt/archiver/v3 v3.5.1
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
@ -53,7 +58,6 @@ require (
github.com/sirupsen/logrus v1.8.1
github.com/smartystreets/assertions v1.2.0 // indirect
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/spf13/afero v1.2.2
github.com/swaggo/gin-swagger v1.3.0
github.com/swaggo/swag v1.7.3
github.com/tidwall/gjson v1.10.2

35
go.sum
View File

@ -99,6 +99,14 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
github.com/ambelovsky/go-structs v1.1.0 h1:LXj4/mHnYw0qhXQhOo96+ULGQ88H8qMcZd5SHef8boY=
github.com/ambelovsky/go-structs v1.1.0/go.mod h1:zN3RBXQvxgjjq/Q/WZS7p5AEK+qC9mNg7ycnvoQ63Ak=
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109 h1:Tp8GVfUOEmJftBqi4+/aXTwJzm24POo6wIHeuTqaT+Y=
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109/go.mod h1:MUREokfMKREm1fOm2babarrkYdk/dGHWY+ITC3qHHPQ=
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 h1:suVCm9PiIhz7ftTbWQNe7u2YjVfr8AEuUiNWKWApdMM=
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19/go.mod h1:o0+8DH+3X+FEOgSdNud0+8jJAsjtR9H3hF+O10Zcj/c=
github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc=
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
@ -289,6 +297,9 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8=
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b h1:NgNuLvW/gAFKU30ULWW0gtkCt56JfB7FrZ2zyo0wT8I=
@ -401,6 +412,7 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
@ -453,6 +465,9 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v1.8.4/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc=
github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@ -499,6 +514,8 @@ github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE0
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/googollee/go-socket.io v1.6.2 h1:olKLLHJtHz1IkL/OrTyNriZZvVQYEORNkJAqsOwPask=
github.com/googollee/go-socket.io v1.6.2/go.mod h1:0vGP8/dXR9SZUMMD4+xxaGo/lohOw3YWMh2WRiWeKxg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
@ -563,10 +580,15 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -619,10 +641,13 @@ github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsF
github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
@ -651,6 +676,8 @@ github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@ -711,6 +738,8 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM=
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -813,7 +842,6 @@ github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:Udh
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
@ -875,6 +903,9 @@ github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLY
github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU=
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I=
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
@ -893,6 +924,8 @@ github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

39
main.go
View File

@ -4,16 +4,18 @@ import (
"flag"
"fmt"
"net/http"
"strconv"
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/IceWhaleTech/CasaOS/pkg/cache"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/route"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/robfig/cron"
"gorm.io/gorm"
@ -46,6 +48,7 @@ func init() {
service.CancelList = make(map[string]string)
service.InternalInspection = make(map[string][]string)
service.NewVersionApp = make(map[string]string)
service.FileQueue = make(map[string]model.FileOperate)
route.InitFunction()
go service.SendIPToServer()
@ -66,12 +69,24 @@ func init() {
// @name Authorization
// @BasePath /v1
func main() {
service.NotifyMsg = make(chan notify.Message, 10)
if *showUserInfo {
fmt.Println("CasaOS User Info")
fmt.Println("UserName:" + config.UserInfo.UserName)
fmt.Println("Password:" + config.UserInfo.PWD)
return
}
p, _ := port.GetAvailablePort("tcp")
config.ServerInfo.SocketPort = strconv.Itoa(p)
go route.ScoketInit(p, service.NotifyMsg)
go func() {
for i := 0; i < 1000; i++ {
time.Sleep(2 * time.Second)
//service.NotifyMsg <- strconv.Itoa(i)
}
}()
//model.Setup()
//gredis.Setup()
r := route.InitRouter()
@ -86,18 +101,19 @@ func main() {
service.SendIPToServer()
service.LoopFriend()
service.MyService.App().CheckNewImage()
//service.MyService.App().CheckNewImage()
})
if err != nil {
fmt.Println(err)
}
err = cron2.AddFunc("0/1 * * * * *", func() {
notify := model2.AppNotify{}
notify.CustomId = ""
notify.Type = types.NOTIFY_TYPE_HEALTH_CHECK
go service.MyService.Notify().SendText(notify)
err = cron2.AddFunc("0/3 * * * * *", func() {
if service.ClientCount > 0 {
route.SendNetINfoBySocket()
route.SendCPUBySocket()
route.SendMemBySocket()
route.SendDiskBySocket()
route.SendUSBBySocket()
}
})
if err != nil {
fmt.Println(err)
@ -114,4 +130,7 @@ func main() {
s.ListenAndServe()
// if err := r.Run(fmt.Sprintf(":%v", config.ServerInfo.HttpPort)); err != nil {
// fmt.Println("failed run app: ", err)
// }
}

View File

@ -1,3 +1,13 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2021-10-08 10:29:08
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-25 19:17:45
* @FilePath: /CasaOS/middleware/gin.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package middleware
import (
@ -10,20 +20,16 @@ import (
func Cors() gin.HandlerFunc {
return func(c *gin.Context) {
method := c.Request.Method
//origin := c.Request.Header.Get("Origin") //请求头部
//if origin != "" {
//接收客户端发送的origin (重要!)
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Origin", "*")
//服务器支持的所有跨域请求的方法
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
//允许跨域设置可以返回其他子段,可以自定义字段
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language")
// 允许浏览器(客户端)可以解析的头部 (重要)
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
//c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With")
//设置缓存时间
c.Header("Access-Control-Max-Age", "172800")
//允许客户端传递校验信息比如 cookie (重要)
c.Header("Access-Control-Allow-Credentials", "true")
c.Set("content-type", "application/json")
//}

31
model/file.go Normal file
View File

@ -0,0 +1,31 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-20 16:27:12
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-30 18:24:42
* @FilePath: /CasaOS/model/file.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model
type FileOperate struct {
Type string `json:"type" binding:"required"`
Item []FileItem `json:"item" binding:"required"`
TotalSize int64 `json:"total_size"`
ProcessedSize int64 `json:"processed_size"`
To string `json:"to" binding:"required"`
}
type FileItem struct {
From string `json:"from" binding:"required"`
Finished bool `json:"finished"`
Size int64 `json:"size"`
ProcessedSize int64 `json:"processed_size"`
}
type FileUpdate struct {
FilePath string `json:"path" binding:"required"`
FileContent string `json:"content" binding:"required"`
}

View File

@ -127,4 +127,6 @@ type CustomizationPostData struct {
Privileged bool `json:"privileged"`
CapAdd []string `json:"cap_add"`
Cmd []string `json:"cmd"`
Protocol string `json:"protocol"`
Host string `json:"host"`
}

View File

@ -0,0 +1,21 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-27 15:01:58
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-31 14:51:21
* @FilePath: /CasaOS/model/notify/application.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package notify
type Application struct {
Name string `json:"name"`
State string `json:"state"`
Type string `json:"type"`
Icon string `json:"icon"`
Message string `json:"message"`
Finished bool `json:"finished"`
Success bool `json:"success"`
}

21
model/notify/file.go Normal file
View File

@ -0,0 +1,21 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-26 14:21:57
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-30 18:51:36
* @FilePath: /CasaOS/model/notify/file.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package notify
type File struct {
Finished bool `json:"finished"`
ProcessedSize int64 `json:"processed_size"`
ProcessingPath string `json:"processing_path"`
Status string `json:"status"`
TotalSize int64 `json:"total_size"`
Id string `json:"id"`
To string `json:"to"`
}

20
model/notify/message.go Normal file
View File

@ -0,0 +1,20 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-26 14:39:22
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-26 19:08:52
* @FilePath: /CasaOS/model/notify/message.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package notify
import (
f "github.com/ambelovsky/gosf"
)
type Message struct {
Path string `json:"path"`
Msg f.Message `json:"msg"`
}

16
model/notify/person.go Normal file
View File

@ -0,0 +1,16 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-27 18:42:42
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-27 18:43:08
* @FilePath: /CasaOS/model/notify/person.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package notify
type Person struct {
ShareId string `json:"share_id"`
Type string `json:"type"`
}

18
model/notify/result.go Normal file
View File

@ -0,0 +1,18 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-26 14:21:11
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-27 11:15:59
* @FilePath: /CasaOS/model/notify/result.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package notify
// Notify struct for Notify
type NotifyModel struct {
Data interface{} `json:"data"`
State string `json:"state"`
}

View File

@ -1,3 +1,13 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-30 16:43:59
* @FilePath: /CasaOS/model/sys_common.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model
import "time"
@ -31,6 +41,7 @@ type ServerModel struct {
Token string
UDPPort string
USBAutoMount string
SocketPort string
}
//服务配置

View File

@ -2,9 +2,11 @@ package file
import (
"bufio"
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"mime/multipart"
"os"
"path"
@ -12,6 +14,8 @@ import (
"path/filepath"
"strconv"
"strings"
"github.com/mholt/archiver/v3"
)
// GetSize get the file size
@ -332,3 +336,149 @@ func SpliceFiles(dir, path string, length int, startPoint int) error {
return nil
}
func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
switch t {
case "zip", "":
return ".zip", archiver.NewZip(), nil
case "tar":
return ".tar", archiver.NewTar(), nil
case "targz":
return ".tar.gz", archiver.NewTarGz(), nil
case "tarbz2":
return ".tar.bz2", archiver.NewTarBz2(), nil
case "tarxz":
return ".tar.xz", archiver.NewTarXz(), nil
case "tarlz4":
return ".tar.lz4", archiver.NewTarLz4(), nil
case "tarsz":
return ".tar.sz", archiver.NewTarSz(), nil
default:
return "", nil, errors.New("format not implemented")
}
}
func AddFile(ar archiver.Writer, path, commonPath string) error {
info, err := os.Stat(path)
if err != nil {
return err
}
if !info.IsDir() && !info.Mode().IsRegular() {
return nil
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
if path != commonPath {
filename := info.Name()
err = ar.Write(archiver.File{
FileInfo: archiver.FileInfo{
FileInfo: info,
CustomName: filename,
},
ReadCloser: file,
})
if err != nil {
return err
}
}
if info.IsDir() {
names, err := file.Readdirnames(0)
if err != nil {
return err
}
for _, name := range names {
err = AddFile(ar, filepath.Join(path, name), commonPath)
if err != nil {
log.Printf("Failed to archive %v", err)
}
}
}
return nil
}
func CommonPrefix(sep byte, paths ...string) string {
// Handle special cases.
switch len(paths) {
case 0:
return ""
case 1:
return path.Clean(paths[0])
}
// Note, we treat string as []byte, not []rune as is often
// done in Go. (And sep as byte, not rune). This is because
// most/all supported OS' treat paths as string of non-zero
// bytes. A filename may be displayed as a sequence of Unicode
// runes (typically encoded as UTF-8) but paths are
// not required to be valid UTF-8 or in any normalized form
// (e.g. "é" (U+00C9) and "é" (U+0065,U+0301) are different
// file names.
c := []byte(path.Clean(paths[0]))
// We add a trailing sep to handle the case where the
// common prefix directory is included in the path list
// (e.g. /home/user1, /home/user1/foo, /home/user1/bar).
// path.Clean will have cleaned off trailing / separators with
// the exception of the root directory, "/" (in which case we
// make it "//", but this will get fixed up to "/" bellow).
c = append(c, sep)
// Ignore the first path since it's already in c
for _, v := range paths[1:] {
// Clean up each path before testing it
v = path.Clean(v) + string(sep)
// Find the first non-common byte and truncate c
if len(v) < len(c) {
c = c[:len(v)]
}
for i := 0; i < len(c); i++ {
if v[i] != c[i] {
c = c[:i]
break
}
}
}
// Remove trailing non-separator characters and the final separator
for i := len(c) - 1; i >= 0; i-- {
if c[i] == sep {
c = c[:i]
break
}
}
return string(c)
}
func GetFileOrDirSize(path string) (int64, error) {
fileInfo, err := os.Stat(path)
if err != nil {
return 0, err
}
if fileInfo.IsDir() {
return DirSizeB(path + "/")
}
return fileInfo.Size(), nil
}
//getFileSize get file size by path(B)
func DirSizeB(path string) (int64, error) {
var size int64
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
if !info.IsDir() {
size += info.Size()
}
return err
})
return size, err
}

View File

@ -3,6 +3,7 @@ package route
import (
"encoding/xml"
"fmt"
"path/filepath"
"runtime"
"strconv"
"strings"
@ -79,14 +80,12 @@ func installSyncthing(appId string) {
appInfo.Tip = env_helper.ReplaceStringDefaultENV(appInfo.Tip)
}
appInfo.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
appInfo.MaxMemory = service.MyService.System().GetMemInfo().Total >> 20
id := uuid.NewV4().String()
installLog := model2.AppNotify{}
// step下载镜像
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, "", "")
if err != nil {
//pull image error
fmt.Println("pull image error", err, dockerImage, dockerImageVersion)
@ -142,14 +141,13 @@ func checkSystemApp() {
}
path := ""
for _, i := range info.HostConfig.Mounts {
if i.Target == "/config" {
for _, i := range info.Mounts {
if i.Destination == "/config" {
path = i.Source
break
}
}
content := file.ReadFullFile(path + "config.xml")
content := file.ReadFullFile(filepath.Join(path, "config.xml"))
syncConfig := &system_app.SyncConfig{}
xml.Unmarshal(content, &syncConfig)
config.SystemConfigInfo.SyncKey = syncConfig.Key

155
route/periodical.go Normal file
View File

@ -0,0 +1,155 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-27 15:55:36
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-27 18:57:40
* @FilePath: /CasaOS/route/periodical.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package route
import (
"reflect"
"strconv"
"strings"
"time"
"unsafe"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/service"
)
func SendNetINfoBySocket() {
netList := service.MyService.System().GetNetInfo()
newNet := []model.IOCountersStat{}
nets := service.MyService.System().GetNet(true)
for _, n := range netList {
for _, netCardName := range nets {
if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
item.Time = time.Now().Unix()
newNet = append(newNet, item)
break
}
}
}
service.MyService.Notify().SendNetInfoBySocket(newNet)
}
func SendCPUBySocket() {
cpu := service.MyService.System().GetCpuPercent()
num := service.MyService.System().GetCpuCoreNum()
cpuData := make(map[string]interface{})
cpuData["percent"] = cpu
cpuData["num"] = num
service.MyService.Notify().SendCPUInfoBySocket(cpuData)
}
func SendMemBySocket() {
service.MyService.Notify().SendMemInfoBySocket(service.MyService.System().GetMemInfo())
}
func SendDiskBySocket() {
list := service.MyService.Disk().LSBLK(true)
summary := model.Summary{}
healthy := true
findSystem := 0
for i := 0; i < len(list); i++ {
if len(list[i].Children) > 0 && findSystem == 0 {
for j := 0; j < len(list[i].Children); j++ {
if len(list[i].Children[j].Children) > 0 {
for _, v := range list[i].Children[j].Children {
if v.MountPoint == "/" {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
} else {
if list[i].Children[j].MountPoint == "/" {
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
}
}
if findSystem == 1 {
findSystem += 1
continue
}
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" {
temp := service.MyService.Disk().SmartCTL(list[i].Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) {
continue
}
//list[i].Temperature = temp.Temperature.Current
if !temp.SmartStatus.Passed {
healthy = false
}
if len(list[i].Children) > 0 {
for _, v := range list[i].Children {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
}
}
}
}
summary.Health = healthy
service.MyService.Notify().SendDiskInfoBySocket(summary)
}
func SendUSBBySocket() {
usbList := service.MyService.Disk().LSBLK(false)
usb := []model.DriveUSB{}
for _, v := range usbList {
if v.Tran == "usb" {
temp := model.DriveUSB{}
temp.Model = v.Model
temp.Name = v.Name
temp.Size = v.Size
mountTemp := true
if len(v.Children) == 0 {
mountTemp = false
}
for _, child := range v.Children {
if len(child.MountPoint) > 0 {
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
temp.Avail += avail
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
temp.Used += used
} else {
mountTemp = false
}
}
temp.Mount = mountTemp
usb = append(usb, temp)
}
}
service.MyService.Notify().SendUSBInfoBySocket(usb)
}

View File

@ -31,7 +31,6 @@ func InitRouter() *gin.Engine {
if swagHandler != nil {
r.GET("/swagger/*any", swagHandler)
}
r.POST("/v1/user/login", v1.Login)
r.GET("/v1/guide/check", v1.GetGuideCheck)
@ -43,6 +42,7 @@ func InitRouter() *gin.Engine {
r.GET("/v1/user/info", v1.GetUserInfo)
//get user info
r.GET("/v1/person/shareid", v1.GetPersonShareId)
r.GET("/v1/sys/socket/port", v1.GetSystemSocketPort)
v1Group := r.Group("/v1")
v1Group.Use(jwt2.JWT(swagHandler))
@ -127,7 +127,7 @@ func InitRouter() *gin.Engine {
//暂停或启动容器
v1AppGroup.PUT("/state/:id", v1.ChangAppState)
//安装app
v1AppGroup.POST("/install/:id", v1.InstallApp)
v1AppGroup.POST("/install", v1.InstallApp)
//卸载app
v1AppGroup.DELETE("/uninstall/:id", v1.UnInstallApp)
//获取安装进度
@ -164,6 +164,7 @@ func InitRouter() *gin.Engine {
v1SysGroup.PUT("/usb/off", v1.PutSystemOffUSBAutoMount)
v1SysGroup.PUT("/usb/on", v1.PutSystemOnUSBAutoMount)
v1SysGroup.GET("/usb", v1.GetSystemUSBAutoMount)
}
v1FileGroup := v1Group.Group("/file")
v1FileGroup.Use()
@ -178,7 +179,7 @@ func InitRouter() *gin.Engine {
v1FileGroup.POST("/create", v1.PostCreateFile)
v1FileGroup.GET("/download", v1.GetDownloadFile)
v1FileGroup.GET("/new/download", v1.GetFileDownloadNew)
v1FileGroup.GET("/download/*path", v1.GetDownloadSingleFile)
v1FileGroup.POST("/operate", v1.PostOperateFileOrDir)
v1FileGroup.DELETE("/delete", v1.DeleteFile)
v1FileGroup.PUT("/update", v1.PutFileContent)
@ -235,12 +236,12 @@ func InitRouter() *gin.Engine {
}
v1NotifyGroup := v1Group.Group("/notify")
v1NotifyGroup.Use()
{
v1NotifyGroup.GET("/ws", v1.NotifyWS)
v1NotifyGroup.PUT("/read/:id", v1.PutNotifyRead)
}
// v1NotifyGroup := v1Group.Group("/notify")
// v1NotifyGroup.Use()
// {
// v1NotifyGroup.GET("/ws", v1.NotifyWS)
// v1NotifyGroup.PUT("/read/:id", v1.PutNotifyRead)
// }
v1PersonGroup := v1Group.Group("/person")
v1PersonGroup.Use()

39
route/socket.go Normal file
View File

@ -0,0 +1,39 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-23 17:18:56
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-30 17:06:08
* @FilePath: /CasaOS/route/socket.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package route
import (
"time"
"github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/IceWhaleTech/CasaOS/service"
f "github.com/ambelovsky/gosf"
)
func ScoketInit(port int, msg chan notify.Message) {
f.OnConnect(func(c *f.Client, request *f.Request) {
service.ClientCount += 1
})
f.OnDisconnect(func(c *f.Client, request *f.Request) {
service.ClientCount -= 1
})
go func(msg chan notify.Message) {
for v := range msg {
f.Broadcast("", v.Path, &v.Msg)
time.Sleep(time.Millisecond * 300)
}
}(msg)
f.Startup(map[string]interface{}{
"port": port})
}

View File

@ -209,7 +209,7 @@ func AppInfo(c *gin.Context) {
// sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap))
// sort.DevSort(devOrder).Sort(info.Devices)
info.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
info.MaxMemory = service.MyService.System().GetMemInfo().Total >> 20
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
}

View File

@ -11,6 +11,7 @@ import (
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/docker"
upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp"
@ -143,10 +144,8 @@ func SpeedPush(c *gin.Context) {
// @Param env formData string false "环境变量"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /app/install/{id} [post]
// @Router /app/install [post]
func InstallApp(c *gin.Context) {
appId := c.Param("id")
language := c.GetHeader("Language")
var appInfo model.ServerAppList
m := model.CustomizationPostData{}
c.BindJSON(&m)
@ -156,7 +155,9 @@ func InstallApp(c *gin.Context) {
var dockerImageVersion string
//check app name is exist
if len(m.Protocol) == 0 {
m.Protocol = "http"
}
if m.Origin != "custom" {
oldName := m.Label
for i := 0; true; i++ {
@ -175,7 +176,7 @@ func InstallApp(c *gin.Context) {
}
//检查端口
//check port
if len(m.PortMap) > 0 && m.PortMap != "0" {
//c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
portMap, _ := strconv.Atoi(m.PortMap)
@ -196,21 +197,6 @@ func InstallApp(c *gin.Context) {
dockerImage = m.Image
dockerImageVersion = "latest"
}
if m.Origin != "custom" {
appInfo = service.MyService.Casa().GetServerAppInfo(appId, "", language)
} else {
appInfo.Title = m.Label
appInfo.Description = m.Description
appInfo.Icon = m.Icon
appInfo.ScreenshotLink = model.Strings{}
appInfo.NetworkModel = m.NetworkModel
appInfo.Tags = model.Strings{}
appInfo.Tagline = ""
appInfo.Index = m.Index
}
for _, u := range m.Ports {
@ -272,16 +258,16 @@ func InstallApp(c *gin.Context) {
m.CustomId = id
var relyMap = make(map[string]string)
go func() {
installLog := model2.AppNotify{}
installLog.State = 0
installLog.CustomId = m.Label
installLog.Message = "installing rely"
installLog.Class = types.NOTIFY_APP
installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
installLog.Id = uuid.NewV4().String()
service.MyService.Notify().AddLog(installLog)
// installLog := model2.AppNotify{}
// installLog.State = 0
// installLog.CustomId = m.Label
// installLog.Message = "installing rely"
// installLog.Class = types.NOTIFY_APP
// installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
// installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
// installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
// installLog.Id = uuid.NewV4().String()
// service.MyService.Notify().AddLog(installLog)
if m.Origin != "custom" {
for _, plugin := range appInfo.Plugins {
if plugin == "mysql" {
@ -314,24 +300,26 @@ func InstallApp(c *gin.Context) {
} else {
docker_base.MysqlDelete(mysqlContainerId)
installLog.State = 0
installLog.Message = err.Error()
service.MyService.Notify().UpdateLog(installLog)
// installLog.State = 0
// installLog.Message = err.Error()
// service.MyService.Notify().UpdateLog(installLog)
}
}
}
}
installLog.Message = "pulling"
service.MyService.Notify().UpdateLog(installLog)
// step下载镜像
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, m.Icon, m.Label)
if err != nil {
installLog.State = 0
installLog.Message = err.Error()
installLog.Type = types.NOTIFY_TYPE_ERROR
service.MyService.Notify().UpdateLog(installLog)
notify := notify.Application{}
notify.Icon = m.Icon
notify.Name = m.Label
notify.State = "PULLING"
notify.Type = "INSTALL"
notify.Success = false
notify.Finished = false
notify.Message = err.Error()
service.MyService.Notify().SendInstallAppBySocket(notify)
return
}
@ -339,35 +327,28 @@ func InstallApp(c *gin.Context) {
time.Sleep(time.Second)
}
//if {
//}
//step创建容器
// networkName, err := service.MyService.Docker().GetNetWorkNameByNetWorkID(appInfo.NetworkModel)
// if err != nil {
// //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
// installLog.State = 0
// installLog.Speed = 75
// installLog.Type = types.NOTIFY_TYPE_ERROR
// installLog.Message = err.Error()
// service.MyService.Notify().UpdateLog(installLog)
// return
// }
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m, appInfo.NetworkModel)
installLog.Name = appInfo.Title
installLog.Icon = appInfo.Icon
_, err = service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m, appInfo.NetworkModel)
if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
installLog.State = 0
installLog.Type = types.NOTIFY_TYPE_ERROR
installLog.Message = err.Error()
service.MyService.Notify().UpdateLog(installLog)
notify := notify.Application{}
notify.Icon = m.Icon
notify.Name = m.Label
notify.State = "STARTING"
notify.Type = "INSTALL"
notify.Success = false
notify.Finished = false
notify.Message = err.Error()
service.MyService.Notify().SendInstallAppBySocket(notify)
return
} else {
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"starting\",\"speed\":80}", 100)
installLog.Message = "starting"
service.MyService.Notify().UpdateLog(installLog)
notify := notify.Application{}
notify.Icon = m.Icon
notify.Name = m.Label
notify.State = "STARTING"
notify.Type = "INSTALL"
notify.Success = true
notify.Finished = false
service.MyService.Notify().SendInstallAppBySocket(notify)
}
// echo -e "hellow\nworld" >>
@ -376,23 +357,27 @@ func InstallApp(c *gin.Context) {
err = service.MyService.Docker().DockerContainerStart(m.Label)
if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
installLog.State = 0
installLog.Type = types.NOTIFY_TYPE_ERROR
installLog.Message = err.Error()
service.MyService.Notify().UpdateLog(installLog)
notify := notify.Application{}
notify.Icon = m.Icon
notify.Name = m.Label
notify.State = "STARTING"
notify.Type = "INSTALL"
notify.Success = false
notify.Finished = false
notify.Message = err.Error()
service.MyService.Notify().SendInstallAppBySocket(notify)
return
} else {
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"setting upnp\",\"speed\":90}", 100)
if m.Origin != CUSTOM {
installLog.Message = "setting upnp"
} else {
installLog.Message = "nearing completion"
}
service.MyService.Notify().UpdateLog(installLog)
// if m.Origin != CUSTOM {
// installLog.Message = "setting upnp"
// } else {
// installLog.Message = "nearing completion"
// }
// service.MyService.Notify().UpdateLog(installLog)
}
if m.Origin != CUSTOM {
//step:启动upnp
//step:enable upnp
if m.EnableUPNP {
upnp, err := upnp2.Gateway()
if err == nil {
@ -424,89 +409,49 @@ func InstallApp(c *gin.Context) {
}
}
if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":95}", 100)
installLog.State = 0
installLog.Type = types.NOTIFY_TYPE_ERROR
installLog.Message = err.Error()
service.MyService.Notify().UpdateLog(installLog)
} else {
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"checking\",\"speed\":95}", 100)
installLog.Message = "checking"
service.MyService.Notify().UpdateLog(installLog)
}
// if err != nil {
// //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":95}", 100)
// installLog.State = 0
// installLog.Type = types.NOTIFY_TYPE_ERROR
// installLog.Message = err.Error()
// service.MyService.Notify().UpdateLog(installLog)
// } else {
// //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"checking\",\"speed\":95}", 100)
// installLog.Message = "checking"
// service.MyService.Notify().UpdateLog(installLog)
// }
}
}
//step: 启动成功 检查容器状态确认启动成功
container, err := service.MyService.Docker().DockerContainerInfo(m.Label)
if err != nil && container.ContainerJSONBase.State.Running {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":100}", 100)
installLog.State = 0
installLog.Type = types.NOTIFY_TYPE_ERROR
installLog.Message = err.Error()
service.MyService.Notify().UpdateLog(installLog)
notify := notify.Application{}
notify.Icon = m.Icon
notify.Name = m.Label
notify.State = "INSTALLED"
notify.Type = "INSTALL"
notify.Success = false
notify.Finished = true
notify.Message = err.Error()
service.MyService.Notify().SendInstallAppBySocket(notify)
return
} else {
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"installed\",\"speed\":100}", 100)
installLog.Message = "installed"
service.MyService.Notify().UpdateLog(installLog)
notify := notify.Application{}
notify.Icon = m.Icon
notify.Name = m.Label
notify.State = "INSTALLED"
notify.Type = "INSTALL"
notify.Success = true
notify.Finished = true
service.MyService.Notify().SendInstallAppBySocket(notify)
}
rely := model.MapStrings{}
copier.Copy(&rely, &relyMap)
// if m.Origin != "custom" {
// for i := 0; i < len(m.Volumes); i++ {
// m.Volumes[i].Path = docker.GetDir(id, m.Volumes[i].Path)
// }
// }
portsStr, _ := json2.Marshal(m.Ports)
envsStr, _ := json2.Marshal(m.Envs)
volumesStr, _ := json2.Marshal(m.Volumes)
devicesStr, _ := json2.Marshal(m.Devices)
cmd, _ := json2.Marshal(m.Cmd)
capAdd, _ := json.Marshal(m.CapAdd)
//step: 保存数据到数据库
md := model2.AppListDBModel{
CustomId: "",
Title: appInfo.Title,
//ScreenshotLink: appInfo.ScreenshotLink,
Slogan: appInfo.Tagline,
Description: appInfo.Description,
//Tags: appInfo.Tags,
Icon: appInfo.Icon,
Version: dockerImageVersion,
ContainerId: containerId,
Image: dockerImage,
Index: appInfo.Index,
//Port: m.Port,
PortMap: m.PortMap,
Label: m.Label,
EnableUPNP: m.EnableUPNP,
Ports: string(portsStr),
Envs: string(envsStr),
Volumes: string(volumesStr),
Position: m.Position,
NetModel: appInfo.NetworkModel,
Restart: m.Restart,
CpuShares: m.CpuShares,
Memory: m.Memory,
Devices: string(devicesStr),
//Rely: rely,
Origin: m.Origin,
CreatedAt: strconv.FormatInt(time.Now().Unix(), 10),
UpdatedAt: strconv.FormatInt(time.Now().Unix(), 10),
Cmd: string(cmd),
CapAdd: string(capAdd),
HostName: m.HostName,
Privileged: m.Privileged,
}
//if appInfo.NetworkModel == "host" {
// m.PortMap = m.Port
//}
fmt.Println(md)
//service.MyService.App().SaveContainer(md)
config.CasaOSGlobalVariables.AppChange = true
@ -728,19 +673,15 @@ func UnInstallApp(c *gin.Context) {
return
}
//step删除容器
err = service.MyService.Docker().DockerContainerRemove(appId, false)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()})
return
}
//存在镜像正在使用的情况
// step删除镜像
service.MyService.Docker().DockerImageRemove(info.Image)
// stepremove image
service.MyService.Docker().DockerImageRemove(info.Config.Image)
//step: 删除本地数据
//service.MyService.App().RemoveContainerById(appId)
if info.Config.Labels["origin"] != "custom" {
fmt.Println(info.HostConfig.Mounts)
//step: 删除文件夹
@ -791,13 +732,14 @@ func UnInstallApp(c *gin.Context) {
//}
}
config.CasaOSGlobalVariables.AppChange = true
unInstallLog := model2.AppNotify{}
unInstallLog.State = 0
unInstallLog.CustomId = appId
unInstallLog.Message = "uninstalled"
unInstallLog.Id = uuid.NewV4().String()
service.MyService.Notify().UpdateLog(unInstallLog)
notify := notify.Application{}
notify.Icon = info.Config.Labels["icon"]
notify.Name = strings.ReplaceAll(info.Name, "/", "")
notify.State = "FINISHED"
notify.Type = "UNINSTALL"
notify.Success = true
notify.Finished = true
service.MyService.Notify().SendUninstallAppBySocket(notify)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
@ -1083,7 +1025,7 @@ func PutAppUpdate(c *gin.Context) {
}
imageLatest := strings.Split(inspect.Config.Image, ":")[0] + ":latest"
err = service.MyService.Docker().DockerPullImage(imageLatest, model2.AppNotify{})
err = service.MyService.Docker().DockerPullImage(imageLatest, "", "")
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
@ -1182,7 +1124,7 @@ func ContainerInfo(c *gin.Context) {
data := make(map[string]interface{}, 5)
data["app"] = appInfo
data["cpu"] = cpuModel
data["memory"] = service.MyService.ZiMa().GetMemInfo().Total
data["memory"] = service.MyService.System().GetMemInfo().Total
data["container"] = json2.RawMessage(containerInfo)
data["info"] = con
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
@ -1205,7 +1147,7 @@ func GetDockerInstallConfig(c *gin.Context) {
}
}
data["networks"] = list
data["memory"] = service.MyService.ZiMa().GetMemInfo()
data["memory"] = service.MyService.System().GetMemInfo()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
}
@ -1257,12 +1199,20 @@ func ContainerUpdateInfo(c *gin.Context) {
// json2.Unmarshal([]byte(appInfo.Envs), &envs)
for _, v := range info.Config.Env {
temp := model.Env{
Name: strings.Split(v, "=")[0],
Value: strings.Split(v, "=")[1],
showENV := info.Config.Labels["show_env"]
showENVList := strings.Split(showENV, ",")
showENVMap := make(map[string]string)
for _, name := range showENVList {
showENVMap[name] = "1"
}
envs = append(envs, temp)
if _, ok := showENVMap[v]; ok {
temp := model.Env{
Name: strings.Split(v, "=")[0],
Value: strings.Split(v, "=")[1],
}
envs = append(envs, temp)
}
}
var vol model.PathArray
@ -1309,6 +1259,7 @@ func ContainerUpdateInfo(c *gin.Context) {
m.Index = info.Config.Labels["index"]
m.Position = false
m.CustomId = info.Config.Labels["custom_id"]
m.Host = info.Config.Labels["host"]
if len(m.CustomId) == 0 {
m.CustomId = uuid.NewV4().String()
}
@ -1317,6 +1268,11 @@ func ContainerUpdateInfo(c *gin.Context) {
m.HostName = info.Config.Hostname
m.Privileged = info.HostConfig.Privileged
m.Protocol = info.Config.Labels["protocol"]
if m.Protocol == "" {
m.Protocol = "http"
}
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m})
}

View File

@ -6,20 +6,24 @@ import (
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"net/url"
url2 "net/url"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin"
"github.com/spf13/afero"
uuid "github.com/satori/go.uuid"
)
func downloadReadFile(c *gin.Context) {
@ -48,24 +52,6 @@ func downloadReadFile(c *gin.Context) {
}
}
func downloadWriteFile(c *gin.Context) {
//写文件
var filename = "./output1.csv"
file, err := os.Create(filename) //创建文件
if err != nil {
c.String(400, err.Error())
return
}
buf := bufio.NewWriter(file) //创建新的 Writer 对象
buf.WriteString("test")
buf.Flush()
defer file.Close()
//返回文件流
c.File(filename)
}
// @Summary 读取文件
// @Produce application/json
// @Accept application/json
@ -135,82 +121,106 @@ func GetLocalFile(c *gin.Context) {
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
// @Param path query string true "path of file"
// @Param t query string false "Compression format" Enums(zip,tar,targz)
// @Param files query string true "file list eg: filename1,filename2,filename3 "
// @Success 200 {string} string "ok"
// @Router /file/download [get]
func GetDownloadFile(c *gin.Context) {
filePath := c.Query("path")
if len(filePath) == 0 {
t := c.Query("t")
files := c.Query("files")
if len(files) == 0 {
c.JSON(http.StatusOK, model.Result{
Success: oasis_err2.INVALID_PARAMS,
Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS),
})
return
}
if !file.Exists(filePath) {
list := strings.Split(files, ",")
for _, v := range list {
if !file.Exists(v) {
c.JSON(http.StatusOK, model.Result{
Success: oasis_err2.FILE_DOES_NOT_EXIST,
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST),
})
return
}
}
c.Header("Content-Type", "application/octet-stream")
c.Header("Content-Transfer-Encoding", "binary")
c.Header("Cache-Control", "private")
// handles only single files not folders and multiple files
if len(list) == 1 {
filePath := list[0]
info, err := os.Stat(filePath)
if err != nil {
c.JSON(http.StatusOK, model.Result{
Success: oasis_err2.FILE_DOES_NOT_EXIST,
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST),
})
return
}
if !info.IsDir() {
//打开文件
fileTmp, _ := os.Open(filePath)
defer fileTmp.Close()
//获取文件的名称
fileName := path.Base(filePath)
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
c.File(filePath)
return
}
}
extension, ar, err := file.GetCompressionAlgorithm(t)
if err != nil {
c.JSON(http.StatusOK, model.Result{
Success: oasis_err2.FILE_DOES_NOT_EXIST,
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST),
Success: oasis_err2.INVALID_PARAMS,
Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS),
})
return
}
//打开文件
fileTmp, _ := os.Open(filePath)
defer fileTmp.Close()
//获取文件的名称
fileName := path.Base(filePath)
c.Header("Content-Type", "application/octet-stream")
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
c.Header("Content-Transfer-Encoding", "binary")
c.Header("Cache-Control", "no-cache")
c.File(filePath)
err = ar.Create(c.Writer)
if err != nil {
c.JSON(http.StatusOK, model.Result{
Success: oasis_err.ERROR,
Message: oasis_err2.GetMsg(oasis_err2.ERROR),
Data: err.Error(),
})
return
}
defer ar.Close()
commonDir := file.CommonPrefix(filepath.Separator, list...)
currentPath := filepath.Base(commonDir)
name := "_" + currentPath
name += extension
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(name))
for _, fname := range list {
err = file.AddFile(ar, fname, commonDir)
if err != nil {
log.Printf("Failed to archive %s: %v", fname, err)
}
}
}
// @Summary download
// @Produce application/json
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
// @Param path query string true "path of file"
// @Success 200 {string} string "ok"
// @Router /file/new/download [get]
func GetFileDownloadNew(c *gin.Context) {
filePath := c.Query("path")
if len(filePath) == 0 {
c.JSON(http.StatusOK, model.Result{
Success: oasis_err2.INVALID_PARAMS,
Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS),
})
return
}
if !file.Exists(filePath) {
c.JSON(http.StatusOK, model.Result{
Success: oasis_err2.FILE_DOES_NOT_EXIST,
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST),
})
return
}
//打开文件
fileStat, _ := os.Stat(filePath)
var AppFs = afero.NewOsFs()
fileT, _ := AppFs.Open(filePath)
//fileTmp, _ := os.Open(filePath)
//defer fileTmp.Close()
//获取文件的名称
//fileName := path.Base(filePath)
func GetDownloadSingleFile(c *gin.Context) {
filePath := c.Param("path")
fileTmp, _ := os.Open(filePath)
defer fileTmp.Close()
//c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
//在线
fileName := path.Base(filePath)
//c.Header("Content-Disposition", "inline")
// extraHeaders := map[string]string{
// "Content-Disposition": `attachment; filename="` + url2.PathEscape(fileName) + `"`,
// }
//c.Header("Cache-Control", "private")
//c.Header("Content-Type", "application/octet-stream")
http.ServeContent(c.Writer, c.Request, fileStat.Name(), fileStat.ModTime(), fileT)
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
c.File(filePath)
}
// @Summary 获取目录列表
@ -272,13 +282,15 @@ func DirPath(c *gin.Context) {
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
// @Param oldpath formData string true "path of old"
// @Param newpath formData string true "path of new"
// @Param oldpath body string true "path of old"
// @Param newpath body string true "path of new"
// @Success 200 {string} string "ok"
// @Router /file/rename [put]
func RenamePath(c *gin.Context) {
op := c.PostForm("oldpath")
np := c.PostForm("newpath")
json := make(map[string]string)
c.BindJSON(&json)
op := json["oldpath"]
np := json["newpath"]
if len(op) == 0 || len(np) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
@ -289,45 +301,59 @@ func RenamePath(c *gin.Context) {
// @Summary create folder
// @Produce application/json
// @Accept multipart/form-data
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
// @Param path formData string true "path of folder"
// @Param path body string true "path of folder"
// @Success 200 {string} string "ok"
// @Router /file/mkdir [post]
func MkdirAll(c *gin.Context) {
path := c.PostForm("path")
json := make(map[string]string)
c.BindJSON(&json)
path := json["path"]
var code int
if len(path) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
// decodedPath, err := url.QueryUnescape(path)
// if err != nil {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
// return
// }
code, _ = service.MyService.ZiMa().MkdirAll(path)
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
}
// @Summary create file
// @Produce application/json
// @Accept multipart/form-data
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
// @Param path formData string false "路径"
// @Param path body string true "path of folder (path need to url encode)"
// @Success 200 {string} string "ok"
// @Router /file/create [post]
func PostCreateFile(c *gin.Context) {
path := c.PostForm("path")
json := make(map[string]string)
c.BindJSON(&json)
path := json["path"]
var code int
if len(path) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
// decodedPath, err := url.QueryUnescape(path)
// if err != nil {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
// return
// }
code, _ = service.MyService.ZiMa().CreateFile(path)
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
}
// @Summary upload file
// @Produce application/json
// @Accept multipart/form-data
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
// @Param path formData string false "file path"
@ -432,90 +458,106 @@ func PostFileUpload(c *gin.Context) {
// @Summary copy or move file
// @Produce application/json
// @Accept multipart/form-data
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
// @Param from formData string true "from path"
// @Param to formData string true "to path"
// @Param type formData string true "action" Enums(move,copy)
// @Param body body model.FileOperate true "type:move,copy"
// @Success 200 {string} string "ok"
// @Router /file/operate [post]
func PostOperateFileOrDir(c *gin.Context) {
from := c.PostForm("from")
to := c.PostForm("to")
t := c.PostForm("type")
if len(from) == 0 || len(t) == 0 || len(to) == 0 {
list := model.FileOperate{}
c.BindJSON(&list)
if len(list.Item) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
if t == "move" {
lastPath := from[strings.LastIndex(from, "/")+1:]
if !file.CheckNotExist(to + "/" + lastPath) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_OR_DIR_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
return
}
err := os.Rename(from, to+"/"+lastPath)
var total int64 = 0
for i := 0; i < len(list.Item); i++ {
size, err := file.GetFileOrDirSize(list.Item[i].From)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
continue
}
} else if t == "copy" {
err := file.CopyDir(from, to)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
} else {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
list.Item[i].Size = size
total += size
}
list.TotalSize = total
list.ProcessedSize = 0
uid := uuid.NewV4().String()
service.FileQueue[uid] = list
if len(service.FileQueue) == 1 {
go service.MyService.Notify().SendFileOperateNotify()
go service.CheckFileStatus()
}
go service.FileOperate(list)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary delete file
// @Produce application/json
// @Accept multipart/form-data
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
// @Param path query string true "path"
// @Param body body string true "paths eg ["/a/b/c","/d/e/f"]"
// @Success 200 {string} string "ok"
// @Router /file/delete [delete]
func DeleteFile(c *gin.Context) {
path := c.Query("path")
//err := os.Remove(path)
err := os.RemoveAll(path)
if err != nil {
fmt.Println(err)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.FILE_DELETE_ERROR), Data: err})
paths := []string{}
c.BindJSON(&paths)
if len(paths) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
// path := c.Query("path")
// paths := strings.Split(path, ",")
for _, v := range paths {
err := os.RemoveAll(v)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.FILE_DELETE_ERROR), Data: err})
return
}
}
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary update file
// @Produce application/json
// @Accept multipart/form-data
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
// @Param path formData string true "path"
// @Param content formData string true "content"
// @Param path body string true "path"
// @Param content body string true "content"
// @Success 200 {string} string "ok"
// @Router /file/update [put]
func PutFileContent(c *gin.Context) {
path := c.PostForm("path")
content := c.PostForm("content")
if !file.Exists(path) {
fi := model.FileUpdate{}
c.BindJSON(&fi)
// path := c.PostForm("path")
// content := c.PostForm("content")
if !file.Exists(fi.FilePath) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
return
}
//err := os.Remove(path)
err := os.RemoveAll(path)
err := os.RemoveAll(fi.FilePath)
if err != nil {
fmt.Println(err)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.FILE_DELETE_ERROR), Data: err})
return
}
err = file.CreateFileAndWriteContent(path, content)
err = file.CreateFileAndWriteContent(fi.FilePath, fi.FileContent)
if err != nil {
fmt.Println(err)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err})

View File

@ -1,62 +1,5 @@
package v1
import (
"fmt"
"net/http"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
var upGrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
// @Summary websocket 接口,连接成功后发送一个"notify"字符串
// @Produce application/json
// @Accept application/json
// @Tags notify
// @Security ApiKeyAuth
// @Param token path string true "token"
// @Success 200 {string} string "ok"
// @Router /notify/ws [get]
func NotifyWS(c *gin.Context) {
//升级get请求为webSocket协议
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
return
}
defer ws.Close()
service.WebSocketConns = append(service.WebSocketConns, ws)
if !service.SocketRun {
service.SocketRun = true
service.SendMeg()
}
for {
mt, message, err := ws.ReadMessage()
fmt.Println(mt, message, err)
}
func aaa() {
}
// @Summary 标记notify已读
// @Produce application/json
// @Accept application/json
// @Tags notify
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /notify/read/{id} [put]
func PutNotifyRead(c *gin.Context) {
id := c.Param("id")
// if len(id) == 0 {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
// return
// }
fmt.Println(id)
service.MyService.Notify().MarkRead(id, types.NOTIFY_READ)
}

62
route/v1/notify_old.go Normal file
View File

@ -0,0 +1,62 @@
package v1
import (
"fmt"
"net/http"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
var upGrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
// @Summary websocket 接口,连接成功后发送一个"notify"字符串
// @Produce application/json
// @Accept application/json
// @Tags notify
// @Security ApiKeyAuth
// @Param token path string true "token"
// @Success 200 {string} string "ok"
// @Router /notify/ws [get]
func NotifyWS(c *gin.Context) {
//升级get请求为webSocket协议
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
return
}
defer ws.Close()
service.WebSocketConns = append(service.WebSocketConns, ws)
if !service.SocketRun {
service.SocketRun = true
service.SendMeg()
}
for {
mt, message, err := ws.ReadMessage()
fmt.Println(mt, message, err)
}
}
// @Summary 标记notify已读
// @Produce application/json
// @Accept application/json
// @Tags notify
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /notify/read/{id} [put]
func PutNotifyRead(c *gin.Context) {
id := c.Param("id")
// if len(id) == 0 {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
// return
// }
fmt.Println(id)
service.MyService.Notify().MarkRead(id, types.NOTIFY_READ)
}

View File

@ -452,18 +452,18 @@ func Info(c *gin.Context) {
}
}
data["usb"] = usb
cpu := service.MyService.ZiMa().GetCpuPercent()
num := service.MyService.ZiMa().GetCpuCoreNum()
cpu := service.MyService.System().GetCpuPercent()
num := service.MyService.System().GetCpuCoreNum()
cpuData := make(map[string]interface{})
cpuData["percent"] = cpu
cpuData["num"] = num
data["cpu"] = cpuData
data["mem"] = service.MyService.ZiMa().GetMemInfo()
data["mem"] = service.MyService.System().GetMemInfo()
//拼装网络信息
netList := service.MyService.ZiMa().GetNetInfo()
netList := service.MyService.System().GetNetInfo()
newNet := []model.IOCountersStat{}
nets := service.MyService.ZiMa().GetNet(true)
nets := service.MyService.System().GetNet(true)
for _, n := range netList {
for _, netCardName := range nets {
if n.Name == netCardName {
@ -480,3 +480,20 @@ func Info(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
}
// @Summary Get notification port
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/socket/port [get]
func GetSystemSocketPort(c *gin.Context) {
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
Data: config.ServerInfo.SocketPort,
})
}

View File

@ -1,3 +1,13 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2021-09-30 18:18:14
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-27 18:07:13
* @FilePath: /CasaOS/route/v1/zima_info.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package v1
import (
@ -21,8 +31,8 @@ import (
// @Router /zima/getcpuinfo [get]
func CupInfo(c *gin.Context) {
//检查参数是否正确
cpu := service.MyService.ZiMa().GetCpuPercent()
num := service.MyService.ZiMa().GetCpuCoreNum()
cpu := service.MyService.System().GetCpuPercent()
num := service.MyService.System().GetCpuCoreNum()
data := make(map[string]interface{})
data["percent"] = cpu
data["num"] = num
@ -40,7 +50,7 @@ func CupInfo(c *gin.Context) {
func MemInfo(c *gin.Context) {
//检查参数是否正确
mem := service.MyService.ZiMa().GetMemInfo()
mem := service.MyService.System().GetMemInfo()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: mem})
}
@ -65,11 +75,11 @@ func DiskInfo(c *gin.Context) {
// @Success 200 {string} string "ok"
// @Router /zima/getnetinfo [get]
func NetInfo(c *gin.Context) {
netList := service.MyService.ZiMa().GetNetInfo()
netList := service.MyService.System().GetNetInfo()
newNet := []model.IOCountersStat{}
for _, n := range netList {
for _, netCardName := range service.MyService.ZiMa().GetNet(true) {
for _, netCardName := range service.MyService.System().GetNet(true) {
if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))

View File

@ -215,6 +215,8 @@ func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppLi
Index: "/",
Image: "",
Type: v.Type,
Host: "",
Protocol: "",
NewVersion: false,
})
}
@ -239,6 +241,8 @@ func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppLi
Type: m.Labels["origin"],
//Slogan: m.Slogan,
//Rely: m.Rely,
Host: m.Labels["host"],
Protocol: m.Labels["protocol"],
})
} else {
unTranslation = append(unTranslation, model2.MyAppList{
@ -249,6 +253,8 @@ func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppLi
Id: m.ID,
Port: "",
NewVersion: false,
Host: "",
Protocol: "",
Image: m.Image,
})
}

View File

@ -83,17 +83,26 @@ func (o *casaService) GetServerList(index, size, tp, categoryId, key, language s
return
}
func (o *casaService) GetServerCategoryList() []model.ServerCategoryList {
func (o *casaService) GetServerCategoryList() (list []model.ServerCategoryList) {
keyName := fmt.Sprintf("category_list")
if result, ok := Cache.Get(keyName); ok {
res, ok := result.(string)
if ok {
json2.Unmarshal([]byte(gjson.Get(res, "data").String()), &list)
return list
}
}
head := make(map[string]string)
head["Authorization"] = GetToken()
listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/category", head)
list := []model.ServerCategoryList{}
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
if len(list) > 0 {
Cache.SetDefault(keyName, listS)
}
return list
}
func (o *casaService) GetServerAppInfo(id, t string, language string) model.ServerAppList {

View File

@ -7,11 +7,9 @@ import (
"encoding/binary"
json2 "encoding/json"
"fmt"
"reflect"
"syscall"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
types2 "github.com/IceWhaleTech/CasaOS/types"
"github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/containerd/containerd"
"github.com/containerd/containerd/cio"
"github.com/containerd/containerd/namespaces"
@ -44,7 +42,7 @@ import (
)
type DockerService interface {
DockerPullImage(imageName string, m model2.AppNotify) error
DockerPullImage(imageName string, icon, name string) error
IsExistImage(imageName string) bool
DockerContainerCreate(imageName string, m model.CustomizationPostData, net string) (containerId string, err error)
DockerContainerCopyCreate(info *types.ContainerJSON) (containerId string, err error)
@ -319,7 +317,7 @@ func (ds *dockerService) IsExistImage(imageName string) bool {
}
//安装镜像
func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) error {
func (ds *dockerService) DockerPullImage(imageName string, icon, name string) error {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
return err
@ -334,7 +332,8 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
return err
}
buf := make([]byte, 256)
//io.Copy()
buf := make([]byte, 2048*4)
for {
n, err := out.Read(buf)
if err != nil {
@ -343,11 +342,16 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
}
break
}
if !reflect.DeepEqual(m, model2.AppNotify{}) {
m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
m.State = 0
m.Message = string(buf[:n])
MyService.Notify().UpdateLog(m)
if len(icon) > 0 && len(name) > 0 {
notify := notify.Application{}
notify.Icon = icon
notify.Name = name
notify.State = "PULLING"
notify.Type = "INSTALL"
notify.Finished = false
notify.Success = true
notify.Message = string(buf[:n])
MyService.Notify().SendInstallAppBySocket(notify)
}
}
@ -433,12 +437,14 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
}
var envArr []string
var showENV []string
for _, e := range m.Envs {
if strings.HasPrefix(e.Value, "$") {
envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value, MyService.System().GetTimeZone()))
continue
}
if len(e.Value) > 0 {
showENV = append(showENV, e.Name)
if e.Value == "port_map" {
envArr = append(envArr, e.Name+"="+m.PortMap)
continue
@ -530,6 +536,9 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
config.Labels["desc"] = m.Description
config.Labels["index"] = m.Index
config.Labels["custom_id"] = m.CustomId
config.Labels["show_env"] = strings.Join(showENV, ",")
config.Labels["protocol"] = m.Protocol
config.Labels["host"] = m.Host
//config.Labels["order"] = strconv.Itoa(MyService.App().GetCasaOSCount() + 1)
hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net), Privileged: m.Privileged, CapAdd: m.CapAdd}
//if net != "host" {

View File

@ -1,38 +1,28 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2021-12-20 14:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-30 18:49:46
* @FilePath: /CasaOS/service/file.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package service
import (
"context"
"io"
"os"
"path/filepath"
"strings"
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
)
// type InteruptReader struct {
// r io.Reader
// interupt chan int
// }
// func NewInteruptReader(r io.Reader) InteruptReader {
// return InteruptReader{
// r,
// make(chan int),
// }
// }
// func (r InteruptReader) Read(p []byte) (n int, err error) {
// if r.r == nil {
// return 0, io.EOF
// }
// select {
// case <-r.interupt:
// return r.r.Read(p)
// default:
// r.r = nil
// return 0, io.EOF
// }
// }
// func (r InteruptReader) Cancel() {
// r.interupt <- 0
// }
var FileQueue map[string]model.FileOperate
type reader struct {
ctx context.Context
@ -83,3 +73,55 @@ func (w *writer) Write(p []byte) (n int, err error) {
return w.w.Write(p)
}
}
func FileOperate(list model.FileOperate) {
for _, v := range list.Item {
if list.Type == "move" {
lastPath := v.From[strings.LastIndex(v.From, "/")+1:]
if !file.CheckNotExist(list.To + "/" + lastPath) {
continue
}
err := os.Rename(v.From, list.To+"/"+lastPath)
if err != nil {
continue
}
} else if list.Type == "copy" {
err := file.CopyDir(v.From, list.To)
if err != nil {
continue
}
} else {
continue
}
}
}
// file move or copy and send notify
func CheckFileStatus() {
for {
if len(FileQueue) == 0 {
return
}
for k, v := range FileQueue {
var total int64 = 0
for i := 0; i < len(v.Item); i++ {
if !v.Item[i].Finished {
size, err := file.GetFileOrDirSize(v.To + "/" + filepath.Base(v.Item[i].From))
if err != nil {
continue
}
v.Item[i].ProcessedSize = size
if size == v.Item[i].Size {
v.Item[i].Finished = true
}
total += size
} else {
total += v.Item[i].ProcessedSize
}
}
v.ProcessedSize = total
FileQueue[k] = v
}
time.Sleep(time.Second * 3)
}
}

View File

@ -1,3 +1,13 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-30 17:33:21
* @FilePath: /CasaOS/service/model/o_container.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model
const CONTAINERTABLENAME = "o_container"
@ -64,4 +74,6 @@ type MyAppList struct {
Image string `json:"image"`
Volumes string `json:"volumes"`
NewVersion bool `json:"new_version"`
Host string `json:"host"`
Protocol string `json:"protocol"`
}

View File

@ -2,14 +2,23 @@ package service
import (
json2 "encoding/json"
"fmt"
"time"
model2 "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/ambelovsky/gosf"
socketio "github.com/googollee/go-socket.io"
"github.com/gorilla/websocket"
"github.com/shirou/gopsutil/v3/mem"
"gorm.io/gorm"
)
var NotifyMsg chan notify.Message
var ClientCount int = 0
type NotifyServer interface {
GetLog(id string) model.AppNotify
AddLog(log model.AppNotify)
@ -18,13 +27,208 @@ type NotifyServer interface {
DelLog(id string)
GetList(c int) (list []model.AppNotify)
MarkRead(id string, state int)
SendText(m model.AppNotify)
// SendText(m model.AppNotify)
SendUninstallAppBySocket(app notify.Application)
SendNetInfoBySocket(netList []model2.IOCountersStat)
SendCPUInfoBySocket(cpu map[string]interface{})
SendMemInfoBySocket(mem *mem.VirtualMemoryStat)
SendUSBInfoBySocket(list []model2.DriveUSB)
SendDiskInfoBySocket(disk model2.Summary)
SendPersonStatusBySocket(status notify.Person)
SendFileOperateNotify()
SendInstallAppBySocket(app notify.Application)
}
type notifyServer struct {
db *gorm.DB
}
// Send periodic broadcast messages
func (i *notifyServer) SendFileOperateNotify() {
for {
if len(FileQueue) == 0 {
return
}
listMsg := make(map[string]interface{})
model := notify.NotifyModel{}
model.State = "NORMAL"
list := []notify.File{}
for k, v := range FileQueue {
task := notify.File{}
task.Id = k
task.ProcessedSize = v.ProcessedSize
task.TotalSize = v.TotalSize
task.To = v.To
if task.ProcessedSize == 0 {
task.Status = "STARTING"
} else {
task.Status = "PROCESSING"
}
if v.ProcessedSize == v.TotalSize {
task.Finished = true
task.Status = "FINISHED"
delete(FileQueue, k)
list = append(list, task)
break
}
for _, v := range v.Item {
if v.Size != v.ProcessedSize {
task.ProcessingPath = v.From
break
}
}
list = append(list, task)
}
model.Data = list
listMsg["file_operate"] = model
msg := gosf.Message{}
msg.Success = true
msg.Body = listMsg
msg.Text = "file_operate"
notify := notify.Message{}
notify.Path = "file_operate"
notify.Msg = msg
NotifyMsg <- notify
time.Sleep(time.Second * 3)
}
}
func (i *notifyServer) SendPersonStatusBySocket(status notify.Person) {
body := make(map[string]interface{})
body["data"] = status
msg := gosf.Message{}
msg.Body = body
msg.Success = true
msg.Text = "person_status"
notify := notify.Message{}
notify.Path = "person_status"
notify.Msg = msg
NotifyMsg <- notify
}
func (i *notifyServer) SendDiskInfoBySocket(disk model2.Summary) {
body := make(map[string]interface{})
body["data"] = disk
msg := gosf.Message{}
msg.Body = body
msg.Success = true
msg.Text = "sys_disk"
notify := notify.Message{}
notify.Path = "sys_disk"
notify.Msg = msg
NotifyMsg <- notify
}
func (i *notifyServer) SendUSBInfoBySocket(list []model2.DriveUSB) {
body := make(map[string]interface{})
body["data"] = list
msg := gosf.Message{}
msg.Body = body
msg.Success = true
msg.Text = "sys_usb"
notify := notify.Message{}
notify.Path = "sys_usb"
notify.Msg = msg
NotifyMsg <- notify
}
func (i *notifyServer) SendMemInfoBySocket(mem *mem.VirtualMemoryStat) {
body := make(map[string]interface{})
body["data"] = mem
msg := gosf.Message{}
msg.Body = body
msg.Success = true
msg.Text = "sys_mem"
notify := notify.Message{}
notify.Path = "sys_mem"
notify.Msg = msg
NotifyMsg <- notify
}
func (i *notifyServer) SendInstallAppBySocket(app notify.Application) {
body := make(map[string]interface{})
body["data"] = app
msg := gosf.Message{}
msg.Body = body
msg.Success = true
msg.Text = "app_install"
notify := notify.Message{}
notify.Path = "app_install"
notify.Msg = msg
NotifyMsg <- notify
}
func (i *notifyServer) SendCPUInfoBySocket(cpu map[string]interface{}) {
body := make(map[string]interface{})
body["data"] = cpu
msg := gosf.Message{}
msg.Body = body
msg.Success = true
msg.Text = "sys_cpu"
notify := notify.Message{}
notify.Path = "sys_cpu"
notify.Msg = msg
NotifyMsg <- notify
}
func (i *notifyServer) SendNetInfoBySocket(netList []model2.IOCountersStat) {
body := make(map[string]interface{})
body["data"] = netList
msg := gosf.Message{}
msg.Body = body
msg.Success = true
msg.Text = "sys_net"
notify := notify.Message{}
notify.Path = "sys_net"
notify.Msg = msg
NotifyMsg <- notify
}
func (i *notifyServer) SendUninstallAppBySocket(app notify.Application) {
body := make(map[string]interface{})
body["data"] = app
msg := gosf.Message{}
msg.Body = body
msg.Success = true
msg.Text = "app_uninstall"
notify := notify.Message{}
notify.Path = "app_uninstall"
notify.Msg = msg
NotifyMsg <- notify
}
func (i *notifyServer) SSR() {
server := socketio.NewServer(nil)
fmt.Println(server)
}
func (i notifyServer) GetList(c int) (list []model.AppNotify) {
i.db.Where("class = ?", c).Where(i.db.Where("state = ?", types.NOTIFY_DYNAMICE).Or("state = ?", types.NOTIFY_UNREAD)).Find(&list)
return
@ -103,25 +307,25 @@ func SendMeg() {
// }
}
func (i notifyServer) SendText(m model.AppNotify) {
list := []model.AppNotify{}
list = append(list, m)
json, _ := json2.Marshal(list)
var temp []*websocket.Conn
for _, v := range WebSocketConns {
// func (i notifyServer) SendText(m model.AppNotify) {
// list := []model.AppNotify{}
// list = append(list, m)
// json, _ := json2.Marshal(list)
// var temp []*websocket.Conn
// for _, v := range WebSocketConns {
err := v.WriteMessage(1, json)
if err == nil {
temp = append(temp, v)
}
}
WebSocketConns = temp
// err := v.WriteMessage(1, json)
// if err == nil {
// temp = append(temp, v)
// }
// }
// WebSocketConns = temp
if len(WebSocketConns) == 0 {
SocketRun = false
}
// if len(WebSocketConns) == 0 {
// SocketRun = false
// }
}
// }
func NewNotifyService(db *gorm.DB) NotifyServer {
return &notifyServer{db: db}

View File

@ -1,14 +1,19 @@
package service
import (
"fmt"
"io/ioutil"
"net"
net2 "net"
"os"
"strconv"
"github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/mem"
"github.com/shirou/gopsutil/v3/net"
)
type SystemService interface {
@ -23,11 +28,46 @@ type SystemService interface {
ExecUSBAutoMountShell(state string)
UpAppOrderFile(str string)
GetAppOrderFile() []byte
GetNet(physics bool) []string
GetNetInfo() []net.IOCountersStat
GetCpuCoreNum() int
GetCpuPercent() float64
GetMemInfo() *mem.VirtualMemoryStat
}
type systemService struct {
log loger.OLog
}
func (c *systemService) GetMemInfo() *mem.VirtualMemoryStat {
memInfo, _ := mem.VirtualMemory()
memInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", memInfo.UsedPercent), 64)
return memInfo
}
func (c *systemService) GetCpuPercent() float64 {
percent, _ := cpu.Percent(0, false)
value, _ := strconv.ParseFloat(fmt.Sprintf("%.1f", percent[0]), 64)
return value
}
func (c *systemService) GetCpuCoreNum() int {
count, _ := cpu.Counts(false)
return count
}
func (c *systemService) GetNetInfo() []net.IOCountersStat {
parts, _ := net.IOCounters(true)
//fmt.Println(net.ConntrackStatsWithContext(true))
return parts
}
func (c *systemService) GetNet(physics bool) []string {
t := "1"
if physics {
t = "2"
}
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetNetCard " + t)
}
func (s *systemService) UpdateSystemVersion(version string) {
//command2.OnlyExec(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)
//s.log.Error(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)
@ -99,12 +139,12 @@ func (s *systemService) GetCasaOSLogs(lineNumber int) string {
func GetDeviceAllIP() []string {
var address []string
addrs, err := net.InterfaceAddrs()
addrs, err := net2.InterfaceAddrs()
if err != nil {
return address
}
for _, a := range addrs {
if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet, ok := a.(*net2.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To16() != nil {
address = append(address, ipNet.IP.String())
}

View File

@ -17,6 +17,7 @@ import (
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
@ -92,7 +93,7 @@ func UDPSendData(msg model.MessageModel, localFilePath string) error {
}
func Dial(msg model.MessageModel, server bool) (m model.MessageModel, err error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second)
defer cancel()
Message = make(chan model.MessageModel)
_, port, err := net.SplitHostPort(UDPConn.LocalAddr().String())
@ -236,20 +237,20 @@ func ReadContent(stream quic.Stream) {
Message <- m
break
} else if m.Type == types.PERSONGETIP {
notify := model2.AppNotify{}
notify.CustomId = m.From
notify := notify.Person{}
notify.ShareId = m.From
if len(m.Data.(string)) == 0 {
if _, ok := UDPAddressMap[m.From]; ok {
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LEAVE
go MyService.Notify().SendText(notify)
notify.Type = "OFFLINE"
go MyService.Notify().SendPersonStatusBySocket(notify)
}
delete(UDPAddressMap, m.From)
Message <- m
break
}
if _, ok := UDPAddressMap[m.From]; !ok {
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LIVE
go MyService.Notify().SendText(notify)
notify.Type = "ONLINE"
go MyService.Notify().SendPersonStatusBySocket(notify)
}
UDPAddressMap[m.From] = m.Data.(string)
if config.ServerInfo.Token != m.From && strings.Split(m.Data.(string), ":")[0] == strings.Split(UDPAddressMap[config.ServerInfo.Token], ":")[0] {
@ -330,10 +331,10 @@ func LoopFriend() {
data, err := Dial(msg, false)
if err != nil || reflect.DeepEqual(data, model.MessageModel{}) || len(data.Data.(string)) == 0 {
if oldIP == UDPAddressMap[list[i].Token] {
notify := model2.AppNotify{}
notify.CustomId = data.From
notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LEAVE
go MyService.Notify().SendText(notify)
notify := notify.Person{}
notify.ShareId = data.From
notify.Type = "LEAVE"
go MyService.Notify().SendPersonStatusBySocket(notify)
delete(UDPAddressMap, list[i].Token)

View File

@ -9,7 +9,6 @@ import (
"strconv"
"strings"
"time"
"unsafe"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
@ -19,18 +18,12 @@ import (
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/host"
"github.com/shirou/gopsutil/v3/mem"
"github.com/shirou/gopsutil/v3/net"
)
//系统信息
type ZiMaService interface {
GetCpuPercent() float64
GetCpuCoreNum() int
GetMemInfo() *mem.VirtualMemoryStat
GetDiskInfo() *disk.UsageStat
GetNetInfo() []net.IOCountersStat
GetNet(physics bool) []string
GetNetState(name string) string
GetSysInfo() host.InfoStat
GetDirPath(path string) []model.Path
@ -47,32 +40,12 @@ var NetArray [][]model.IOCountersStat
type zima struct {
}
//获取cpu占用率
func (c *zima) GetCpuPercent() float64 {
percent, _ := cpu.Percent(0, false)
value, _ := strconv.ParseFloat(fmt.Sprintf("%.1f", percent[0]), 64)
return value
}
//获取物理核心数
func (c *zima) GetCpuCoreNum() int {
count, _ := cpu.Counts(false)
return count
}
//cpu详情
func (c *zima) GetCpuInfo() []cpu.InfoStat {
info, _ := cpu.Info()
return info
}
//获取内存详情
func (c *zima) GetMemInfo() *mem.VirtualMemoryStat {
memInfo, _ := mem.VirtualMemory()
memInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", memInfo.UsedPercent), 64)
return memInfo
}
//获取硬盘详情
func (c *zima) GetDiskInfo() *disk.UsageStat {
path := "/"
@ -141,15 +114,6 @@ func (c *zima) GetSysInfo() host.InfoStat {
return *info
}
//shell脚本参数 {1:虚拟网卡 2:物理网卡}
func (c *zima) GetNet(physics bool) []string {
t := "1"
if physics {
t = "2"
}
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetNetCard " + t)
}
func (c *zima) GetDeviceTree() string {
return command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDeviceTree")
}
@ -159,13 +123,6 @@ func (c *zima) GetNetState(name string) string {
return command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;CatNetCardState " + name)
}
//网络信息
func (c *zima) GetNetInfo() []net.IOCountersStat {
parts, _ := net.IOCounters(true)
//fmt.Println(net.ConntrackStatsWithContext(true))
return parts
}
//mkdir
func (c *zima) MkdirAll(path string) (int, error) {
_, err := os.Stat(path)
@ -219,40 +176,40 @@ func NewZiMaService() ZiMaService {
return &zima{}
}
func LoopNet() {
netList := MyService.ZiMa().GetNetInfo()
// func LoopNet() {
// netList := MyService.ZiMa().GetNetInfo()
nets := MyService.ZiMa().GetNet(true)
num := 0
for i := 0; i < len(netList); i++ {
// nets := MyService.ZiMa().GetNet(true)
// num := 0
// for i := 0; i < len(netList); i++ {
for _, netCardName := range nets {
// for _, netCardName := range nets {
if netList[i].Name == netCardName {
var netArray []model.IOCountersStat
if len(NetArray) < (num + 1) {
netArray = []model.IOCountersStat{}
} else {
netArray = NetArray[num]
}
item := *(*model.IOCountersStat)(unsafe.Pointer(&netList[i]))
item.State = strings.TrimSpace(MyService.ZiMa().GetNetState(netList[i].Name))
item.Time = time.Now().Unix()
// if netList[i].Name == netCardName {
// var netArray []model.IOCountersStat
// if len(NetArray) < (num + 1) {
// netArray = []model.IOCountersStat{}
// } else {
// netArray = NetArray[num]
// }
// item := *(*model.IOCountersStat)(unsafe.Pointer(&netList[i]))
// item.State = strings.TrimSpace(MyService.ZiMa().GetNetState(netList[i].Name))
// item.Time = time.Now().Unix()
if len(netArray) >= 60 {
netArray = netArray[1:]
}
netArray = append(netArray, item)
if len(NetArray) < (num + 1) {
NetArray = append(NetArray, []model.IOCountersStat{})
}
// if len(netArray) >= 60 {
// netArray = netArray[1:]
// }
// netArray = append(netArray, item)
// if len(NetArray) < (num + 1) {
// NetArray = append(NetArray, []model.IOCountersStat{})
// }
NetArray[num] = netArray
// NetArray[num] = netArray
num++
break
}
}
// num++
// break
// }
// }
}
}
// }
// }

View File

@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-02-17 18:53:22
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-17 12:52:47
* @LastEditTime: 2022-06-01 18:05:37
* @FilePath: /CasaOS/types/system.go
* @Description:
* @Website: https://www.casaos.io
@ -10,6 +10,6 @@
*/
package types
const CURRENTVERSION = "0.3.1.1"
const CURRENTVERSION = "0.3.2"
const BODY = "<li>Fix the data loss problem when importing local applications</li>"
const BODY = "<li></li>"

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/ui/img/icon/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/ui/img/icon/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

View File

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#363636;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
@media ( prefers-color-scheme: dark ) {
.st0{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
}
</style>
<path class="st0" d="M12,22c5.5,0,10-4.5,10-10S17.5,2,12,2S2,6.5,2,12S6.5,22,12,22z"/>
<path class="st0" d="M12,22c3.9,0,7-3.1,7-7s-3.1-7-7-7s-7,3.1-7,7S8.1,22,12,22z"/>
<path class="st0" d="M12,22c2.2,0,4-1.8,4-4s-1.8-4-4-4s-4,1.8-4,4S9.8,22,12,22z"/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#363636;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
@media ( prefers-color-scheme: dark ) {
.st0{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
}
</style>
<path class="st0" d="M12,22c5.5,0,10-4.5,10-10S17.5,2,12,2S2,6.5,2,12S6.5,22,12,22z"/>
<path class="st0" d="M12,22c3.9,0,7-3.1,7-7s-3.1-7-7-7s-7,3.1-7,7S8.1,22,12,22z"/>
<path class="st0" d="M12,22c2.2,0,4-1.8,4-4s-1.8-4-4-4s-4,1.8-4,4S9.8,22,12,22z"/>
</svg>

Before

Width:  |  Height:  |  Size: 863 B

After

Width:  |  Height:  |  Size: 877 B

View File

@ -1,11 +1,11 @@
<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect opacity="0.32" x="0.435625" y="0.435625" width="71.1288" height="71.1288" rx="7.56437" fill="white" stroke="url(#paint0_linear_812_2050)" stroke-width="0.87125"/>
<path d="M36.0606 22L36.0239 50" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M22 36H50" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<defs>
<linearGradient id="paint0_linear_812_2050" x1="77.6757" y1="64.5405" x2="35.9839" y2="53.5747" gradientUnits="userSpaceOnUse">
<stop stop-color="#CBEFFF" stop-opacity="0.16"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
</defs>
</svg>
<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect opacity="0.32" x="0.435625" y="0.435625" width="71.1288" height="71.1288" rx="7.56437" fill="white" stroke="url(#paint0_linear_812_2050)" stroke-width="0.87125"/>
<path d="M36.0606 22L36.0239 50" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M22 36H50" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<defs>
<linearGradient id="paint0_linear_812_2050" x1="77.6757" y1="64.5405" x2="35.9839" y2="53.5747" gradientUnits="userSpaceOnUse">
<stop stop-color="#CBEFFF" stop-opacity="0.16"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 752 B

After

Width:  |  Height:  |  Size: 763 B

View File

@ -1,25 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
<g>
<g>
<g>
<path fill="#A4C639" d="M32,0c17.7,0,32,14.3,32,32S49.7,64,32,64S0,49.7,0,32S14.3,0,32,0z"/>
</g>
</g>
<g>
<g>
<path fill="#FFFFFF" d="M16.6,24.6c-1.4,0-2.6,1.2-2.6,2.6L14,38c0,1.4,1.2,2.6,2.6,2.6c1.5,0,2.6-1.2,2.6-2.6l0-10.9
C19.3,25.7,18.1,24.6,16.6,24.6 M37.8,14.8l1.8-3.3c0.1-0.2,0-0.4-0.1-0.5c-0.2-0.1-0.4,0-0.5,0.1l-1.9,3.3
c-1.6-0.7-3.3-1.1-5.1-1.1c-1.8,0-3.6,0.4-5.1,1.1L25,11.2C24.9,11,24.7,11,24.5,11c-0.2,0.1-0.2,0.3-0.1,0.5l1.8,3.3
c-3.6,1.8-6,5.3-6,9.3l23.6,0C43.8,20.2,41.4,16.7,37.8,14.8 M26.6,19.9c-0.5,0-1-0.4-1-1c0-0.5,0.4-1,1-1c0.5,0,1,0.4,1,1
C27.6,19.5,27.2,19.9,26.6,19.9 M37.4,19.9c-0.5,0-1-0.4-1-1c0-0.5,0.4-1,1-1c0.5,0,1,0.4,1,1C38.4,19.5,37.9,19.9,37.4,19.9
M20.3,25.1l0,16.8c0,1.5,1.3,2.8,2.8,2.8l1.9,0l0,5.7c0,1.4,1.2,2.6,2.6,2.6c1.5,0,2.6-1.2,2.6-2.6l0-5.7l3.5,0l0,5.7
c0,1.4,1.2,2.6,2.6,2.6c1.5,0,2.6-1.2,2.6-2.6l0-5.7l1.9,0c1.5,0,2.8-1.2,2.8-2.8l0-16.8L20.3,25.1z M50,27.2
c0-1.4-1.2-2.6-2.6-2.6c-1.4,0-2.6,1.2-2.6,2.6l0,10.9c0,1.4,1.2,2.6,2.6,2.6c1.4,0,2.6-1.2,2.6-2.6L50,27.2z"/>
</g>
</g>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
<g>
<g>
<g>
<path fill="#A4C639" d="M32,0c17.7,0,32,14.3,32,32S49.7,64,32,64S0,49.7,0,32S14.3,0,32,0z"/>
</g>
</g>
<g>
<g>
<path fill="#FFFFFF" d="M16.6,24.6c-1.4,0-2.6,1.2-2.6,2.6L14,38c0,1.4,1.2,2.6,2.6,2.6c1.5,0,2.6-1.2,2.6-2.6l0-10.9
C19.3,25.7,18.1,24.6,16.6,24.6 M37.8,14.8l1.8-3.3c0.1-0.2,0-0.4-0.1-0.5c-0.2-0.1-0.4,0-0.5,0.1l-1.9,3.3
c-1.6-0.7-3.3-1.1-5.1-1.1c-1.8,0-3.6,0.4-5.1,1.1L25,11.2C24.9,11,24.7,11,24.5,11c-0.2,0.1-0.2,0.3-0.1,0.5l1.8,3.3
c-3.6,1.8-6,5.3-6,9.3l23.6,0C43.8,20.2,41.4,16.7,37.8,14.8 M26.6,19.9c-0.5,0-1-0.4-1-1c0-0.5,0.4-1,1-1c0.5,0,1,0.4,1,1
C27.6,19.5,27.2,19.9,26.6,19.9 M37.4,19.9c-0.5,0-1-0.4-1-1c0-0.5,0.4-1,1-1c0.5,0,1,0.4,1,1C38.4,19.5,37.9,19.9,37.4,19.9
M20.3,25.1l0,16.8c0,1.5,1.3,2.8,2.8,2.8l1.9,0l0,5.7c0,1.4,1.2,2.6,2.6,2.6c1.5,0,2.6-1.2,2.6-2.6l0-5.7l3.5,0l0,5.7
c0,1.4,1.2,2.6,2.6,2.6c1.5,0,2.6-1.2,2.6-2.6l0-5.7l1.9,0c1.5,0,2.8-1.2,2.8-2.8l0-16.8L20.3,25.1z M50,27.2
c0-1.4-1.2-2.6-2.6-2.6c-1.4,0-2.6,1.2-2.6,2.6l0,10.9c0,1.4,1.2,2.6,2.6,2.6c1.4,0,2.6-1.2,2.6-2.6L50,27.2z"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,28 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 64 64" style="enable-background:new 0 0 64 64;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F4F4F4;}
.st1{opacity:0.1;fill-rule:evenodd;clip-rule:evenodd;fill:url(#SVGID_1_);enable-background:new ;}
.st2{fill:#999999;}
</style>
<g id="图层_1">
<g transform="scale(.26458)">
<path class="st0" d="M49.1,15.1h143.6c10.4,0,18.9,8.5,18.9,18.9v173.9c0,10.4-8.5,18.9-18.9,18.9H49.1
c-10.4,0-18.9-8.5-18.9-18.9V34C30.2,23.6,38.7,15.1,49.1,15.1z"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-957.3084" y1="2609.5137" x2="-955.1654" y2="2607.3706" gradientTransform="matrix(2.3333 0 0 -2.3333 2411.3325 6281.5693)">
<stop offset="0" style="stop-color:#000000"/>
<stop offset="1" style="stop-color:#000000;stop-opacity:0"/>
</linearGradient>
<path class="st1" d="M211.7,173.9l-52.9,52.9h34c10.5,0,18.9-8.4,18.9-18.9V173.9z"/>
</g>
</g>
<g id="图层_2">
<path class="st2" d="M41.1,31.4c0-4.2,3.4-6.2,3.6-6.3c-2-2.9-5-3.3-6.1-3.3c-2.6-0.3-5.1,1.5-6.4,1.5c-1.3,0-3.3-1.5-5.5-1.4
c-2.8,0-5.4,1.6-6.9,4.2c-2.9,5.1-0.8,12.6,2.1,16.8c1.4,2,3.1,4.3,5.3,4.2c2.1-0.1,2.9-1.4,5.4-1.4c2.5,0,3.3,1.4,5.5,1.3
c2.3,0,3.7-2.1,5.1-4.1c1.6-2.3,2.3-4.6,2.3-4.7C45.5,38.1,41.1,36.4,41.1,31.4L41.1,31.4z M36.9,19c1.2-1.4,1.9-3.4,1.7-5.3
c-1.7,0.1-3.7,1.1-4.9,2.5c-1.1,1.2-2,3.2-1.8,5.1C33.8,21.5,35.7,20.5,36.9,19L36.9,19z"/>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 64 64" style="enable-background:new 0 0 64 64;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F4F4F4;}
.st1{opacity:0.1;fill-rule:evenodd;clip-rule:evenodd;fill:url(#SVGID_1_);enable-background:new ;}
.st2{fill:#999999;}
</style>
<g id="图层_1">
<g transform="scale(.26458)">
<path class="st0" d="M49.1,15.1h143.6c10.4,0,18.9,8.5,18.9,18.9v173.9c0,10.4-8.5,18.9-18.9,18.9H49.1
c-10.4,0-18.9-8.5-18.9-18.9V34C30.2,23.6,38.7,15.1,49.1,15.1z"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-957.3084" y1="2609.5137" x2="-955.1654" y2="2607.3706" gradientTransform="matrix(2.3333 0 0 -2.3333 2411.3325 6281.5693)">
<stop offset="0" style="stop-color:#000000"/>
<stop offset="1" style="stop-color:#000000;stop-opacity:0"/>
</linearGradient>
<path class="st1" d="M211.7,173.9l-52.9,52.9h34c10.5,0,18.9-8.4,18.9-18.9V173.9z"/>
</g>
</g>
<g id="图层_2">
<path class="st2" d="M41.1,31.4c0-4.2,3.4-6.2,3.6-6.3c-2-2.9-5-3.3-6.1-3.3c-2.6-0.3-5.1,1.5-6.4,1.5c-1.3,0-3.3-1.5-5.5-1.4
c-2.8,0-5.4,1.6-6.9,4.2c-2.9,5.1-0.8,12.6,2.1,16.8c1.4,2,3.1,4.3,5.3,4.2c2.1-0.1,2.9-1.4,5.4-1.4c2.5,0,3.3,1.4,5.5,1.3
c2.3,0,3.7-2.1,5.1-4.1c1.6-2.3,2.3-4.6,2.3-4.7C45.5,38.1,41.1,36.4,41.1,31.4L41.1,31.4z M36.9,19c1.2-1.4,1.9-3.4,1.7-5.3
c-1.7,0.1-3.7,1.1-4.9,2.5c-1.1,1.2-2,3.2-1.8,5.1C33.8,21.5,35.7,20.5,36.9,19L36.9,19z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
</style>
<path class="st0" d="M12,22c5.5,0,10-4.5,10-10S17.5,2,12,2S2,6.5,2,12S6.5,22,12,22z"/>
<path class="st0" d="M12,22c3.9,0,7-3.1,7-7s-3.1-7-7-7s-7,3.1-7,7S8.1,22,12,22z"/>
<path class="st0" d="M12,22c2.2,0,4-1.8,4-4s-1.8-4-4-4s-4,1.8-4,4S9.8,22,12,22z"/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
</style>
<path class="st0" d="M12,22c5.5,0,10-4.5,10-10S17.5,2,12,2S2,6.5,2,12S6.5,22,12,22z"/>
<path class="st0" d="M12,22c3.9,0,7-3.1,7-7s-3.1-7-7-7s-7,3.1-7,7S8.1,22,12,22z"/>
<path class="st0" d="M12,22c2.2,0,4-1.8,4-4s-1.8-4-4-4s-4,1.8-4,4S9.8,22,12,22z"/>
</svg>

Before

Width:  |  Height:  |  Size: 729 B

After

Width:  |  Height:  |  Size: 740 B

View File

@ -1,39 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 120 120" style="enable-background:new 0 0 120 120;" xml:space="preserve">
<style type="text/css">
.st0{fill:url(#SVGID_1_);}
.st1{fill:url(#SVGID_2_);}
.st2{fill:url(#SVGID_3_);}
</style>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="60" y1="122" x2="60" y2="2" gradientTransform="matrix(1 0 0 -1 0 122)">
<stop offset="0" style="stop-color:#5A9CFF"/>
<stop offset="0.879" style="stop-color:#2A23D5"/>
<stop offset="1" style="stop-color:#4A3CEC"/>
</linearGradient>
<path class="st0" d="M0,60C0,26.9,26.9,0,60,0l0,0c33.1,0,60,26.9,60,60l0,0c0,33.1-26.9,60-60,60l0,0C26.9,120,0,93.1,0,60L0,60z"
/>
<g>
<g>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="59.9999" y1="82" x2="59.9997" y2="29" gradientTransform="matrix(1 0 0 -1 0 122)">
<stop offset="3.509020e-02" style="stop-color:#FFFFFF"/>
<stop offset="0.5256" style="stop-color:#B0D4FF"/>
<stop offset="0.8371" style="stop-color:#DEEDFF"/>
<stop offset="1" style="stop-color:#FEFEFF"/>
</linearGradient>
<path class="st1" d="M75.1,42.1c0,8.4-6.8,15.1-15.1,15.1c-8.4,0-15.1-6.8-15.1-15.1S51.6,27,60,27C68.4,27,75.1,33.8,75.1,42.1z"
/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="60" y1="82" x2="59.9998" y2="29" gradientTransform="matrix(1 0 0 -1 0 122)">
<stop offset="3.509020e-02" style="stop-color:#FFFFFF"/>
<stop offset="0.5256" style="stop-color:#B0D4FF"/>
<stop offset="0.8371" style="stop-color:#DEEDFF"/>
<stop offset="1" style="stop-color:#FEFEFF"/>
</linearGradient>
<path class="st2" d="M34.4,71.7c6.9-5.6,15.8-9,25.6-9c9.8,0,18.7,3.4,25.6,9c3.9,3.2,3.9,9.1,0,12.3c-6.9,5.6-15.8,9-25.6,9
c-9.8,0-18.7-3.4-25.6-9C30.5,80.8,30.5,74.9,34.4,71.7z"/>
</g>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 120 120" style="enable-background:new 0 0 120 120;" xml:space="preserve">
<style type="text/css">
.st0{fill:url(#SVGID_1_);}
.st1{fill:url(#SVGID_2_);}
.st2{fill:url(#SVGID_3_);}
</style>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="60" y1="122" x2="60" y2="2" gradientTransform="matrix(1 0 0 -1 0 122)">
<stop offset="0" style="stop-color:#5A9CFF"/>
<stop offset="0.879" style="stop-color:#2A23D5"/>
<stop offset="1" style="stop-color:#4A3CEC"/>
</linearGradient>
<path class="st0" d="M0,60C0,26.9,26.9,0,60,0l0,0c33.1,0,60,26.9,60,60l0,0c0,33.1-26.9,60-60,60l0,0C26.9,120,0,93.1,0,60L0,60z"
/>
<g>
<g>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="59.9999" y1="82" x2="59.9997" y2="29" gradientTransform="matrix(1 0 0 -1 0 122)">
<stop offset="3.509020e-02" style="stop-color:#FFFFFF"/>
<stop offset="0.5256" style="stop-color:#B0D4FF"/>
<stop offset="0.8371" style="stop-color:#DEEDFF"/>
<stop offset="1" style="stop-color:#FEFEFF"/>
</linearGradient>
<path class="st1" d="M75.1,42.1c0,8.4-6.8,15.1-15.1,15.1c-8.4,0-15.1-6.8-15.1-15.1S51.6,27,60,27C68.4,27,75.1,33.8,75.1,42.1z"
/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="60" y1="82" x2="59.9998" y2="29" gradientTransform="matrix(1 0 0 -1 0 122)">
<stop offset="3.509020e-02" style="stop-color:#FFFFFF"/>
<stop offset="0.5256" style="stop-color:#B0D4FF"/>
<stop offset="0.8371" style="stop-color:#DEEDFF"/>
<stop offset="1" style="stop-color:#FEFEFF"/>
</linearGradient>
<path class="st2" d="M34.4,71.7c6.9-5.6,15.8-9,25.6-9c9.8,0,18.7,3.4,25.6,9c3.9,3.2,3.9,9.1,0,12.3c-6.9,5.6-15.8,9-25.6,9
c-9.8,0-18.7-3.4-25.6-9C30.5,80.8,30.5,74.9,34.4,71.7z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1,121 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1"
id="图层_1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 64 64"
style="enable-background:new 0 0 64 64;" xml:space="preserve">
<style type="text/css">
.st0{fill:#5E4AA6;}
.st1{fill:url(#SVGID_1_);}
.st2{opacity:1.000000e-03;fill:#1E5992;enable-background:new ;}
.st3{fill:url(#SVGID_2_);}
.st4{opacity:0.3;fill:url(#SVGID_3_);enable-background:new ;}
.st5{fill:url(#SVGID_4_);}
.st6{fill:url(#SVGID_5_);}
.st7{fill:url(#SVGID_6_);}
</style>
<g>
<rect x="-1248.6" y="-1241.1" class="st0" width="0" height="0"/>
<rect x="-1179.7" y="-1233.1" class="st0" width="0" height="0"/>
<rect x="-1156.6" y="-1258.9" class="st0" width="0" height="0"/>
<rect x="-1167.3" y="-1232.2" class="st0" width="0" height="0"/>
<g transform="translate(.000295 -.00032978)">
<rect x="-1248.6" y="-1241.1" class="st0" width="0" height="0"/>
<rect x="-1179.7" y="-1233.1" class="st0" width="0" height="0"/>
<rect x="-1156.6" y="-1258.9" class="st0" width="0" height="0"/>
<rect x="-1167.3" y="-1232.2" class="st0" width="0" height="0"/>
<rect x="-1242.7" y="-1249" class="st0" width="0" height="0"/>
</g>
<rect x="-1248.6" y="-1241.1" class="st0" width="0" height="0"/>
<rect x="-1179.7" y="-1233.1" class="st0" width="0" height="0"/>
<rect x="-1156.6" y="-1258.9" class="st0" width="0" height="0"/>
<rect x="-1167.3" y="-1232.2" class="st0" width="0" height="0"/>
<rect x="-1242.7" y="-1249" class="st0" width="0" height="0"/>
<g transform="translate(2.95e-4,-3.2978e-4)">
<rect x="-1248.6" y="-1241.1" class="st0" width="0" height="0"/>
<rect x="-1179.7" y="-1233.1" class="st0" width="0" height="0"/>
<rect x="-1156.6" y="-1258.9" class="st0" width="0" height="0"/>
<rect x="-1167.3" y="-1232.2" class="st0" width="0" height="0"/>
<rect x="-1242.7" y="-1249" class="st0" width="0" height="0"/>
</g>
</g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-363.3979" y1="913.4439" x2="-363.3979" y2="911.0629" gradientTransform="matrix(3.7796 0 0 -3.7796 1405.5416 3462.4551)">
<stop offset="0" style="stop-color:#0272CB"/>
<stop offset="1" style="stop-color:#0768BA"/>
</linearGradient>
<path image-rendering="auto" shape-rendering="auto" color-rendering="auto" class="st1" d="M4.6,8.5c-1.4,0-2.5,1.2-2.5,2.8v11.2
c0,0.1,0,0.2,0,0.3v30c0,1.5,1.1,2.8,2.5,2.8h55c1.4,0,2.5-1.2,2.5-2.8V17.2c0-1.5-1.1-2.8-2.5-2.8v0h-31l-3.4-4.2
c0,0-1.4-1.8-4-1.8h-5L4.6,8.5z"/>
<path class="st2" d="M31.6,14.4c-0.4,0-1.2-0.1-2,0.4c-2.8,1.4-2.9,2.2-5.9,2.7H5c-0.8,0-1.6,0.3-2.1,0.9c-0.5,0.5-0.8,1.3-0.9,2.1
v1c0-0.8,0.3-1.5,0.9-2.1c0.5-0.5,1.3-0.9,2.1-0.9h18.7c3-0.5,3.1-1.3,5.9-2.7c0.8-0.4,1.5-0.4,2-0.4h27.9c0.7,0,1.3,0.3,1.8,0.8
c0.5,0.5,0.7,1.2,0.7,1.9v-1c0-0.8-0.3-1.4-0.7-1.9c-0.5-0.5-1.1-0.8-1.8-0.8h-4.4H31.6z M2.1,22.4c0,0.1,0,0.2,0,0.3v1
c0-0.1,0-0.2,0-0.3V22.4z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="95.1452" y1="43.801" x2="128.3352" y2="9.648" gradientTransform="matrix(1 0 0 -1 -75.9965 65.4973)">
<stop offset="0" style="stop-color:#27AEE9"/>
<stop offset="1" style="stop-color:#0669BC"/>
</linearGradient>
<path class="st3" d="M28.5,15.5c0,0-1.4,1.8-4.4,3c-0.1,0-0.2,0-0.4,0.1H5c-0.8,0-1.6,0.3-2.1,0.9c-0.5,0.5-0.8,1.3-0.9,2.1v2
c0,0.1,0,0.2,0,0.3v28c0,0.8,0.3,1.4,0.7,1.9c0.5,0.5,1.1,0.8,1.8,0.8h55c0.7,0,1.3-0.3,1.8-0.8c0.5-0.5,0.7-1.2,0.7-1.9V18.2
c0-0.8-0.3-1.4-0.7-1.9c-0.5-0.5-1.1-0.8-1.8-0.8H31.3L28.5,15.5z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-389.233" y1="932.0934" x2="-373.3582" y2="932.0934" gradientTransform="matrix(3.7796 0 0 -3.7796 1473.188 3543.282)">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0"/>
</linearGradient>
<path class="st4" d="M28.5,15.5c0,0-1.4,1.8-4.4,3c-0.1,0-0.2,0-0.4,0.1H5c-0.8,0-1.6,0.3-2.1,0.9c-0.5,0.5-0.8,1.3-0.9,2.1v1.5
c0-0.8,0.3-1.5,0.9-2.1C3.5,20.3,4.2,20,5,20h18.7c0.1,0,0.3,0,0.4-0.1c2.9-1,4.9-3,4.9-3h30.5c0.7,0,1.3,0.3,1.8,0.8
c0.5,0.5,0.7,1.2,0.7,1.9v-1.5c0-0.8-0.3-1.4-0.7-1.9c-0.5-0.5-1.1-0.8-1.8-0.8H31.3H28.5z M2.1,23.4c0,0.1,0,0.2,0,0.3v1.5
c0-0.1,0-0.2,0-0.3V23.4z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-389.2331" y1="923.2966" x2="-373.3582" y2="923.2966" gradientTransform="matrix(3.7796 0 0 -3.7796 1473.188 3543.2234)">
<stop offset="0" style="stop-color:#0A5BA8;stop-opacity:0.9961"/>
<stop offset="1" style="stop-color:#104A8C;stop-opacity:0.9961"/>
</linearGradient>
<path image-rendering="auto" shape-rendering="auto" color-rendering="auto" class="st5" d="M2,51.6v1.1c0,0.8,0.3,1.4,0.7,1.9
c0.5,0.5,1.1,0.8,1.8,0.8h55c0.7,0,1.3-0.3,1.8-0.8c0.5-0.5,0.7-1.2,0.7-1.9v-1.1c0,0.8-0.3,1.4-0.7,1.9c-0.5,0.5-1.1,0.8-1.8,0.8
h-55c-0.7,0-1.3-0.3-1.8-0.8S2,52.4,2,51.6z"/>
<g>
<image style="overflow:visible;opacity:0.25;" width="34" height="44" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAsCAYAAAAATWqyAAAACXBIWXMAAAsSAAALEgHS3X78AAAA
GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA/JJREFUeNrMmFtv00AQhX2LyYUk
pS0VIEA88P9/ES8IqZTShtI0JXHsmE31TXW6dRzb7UMtHSVO1rvHM2cuu0HwQq6wwX/hM61Vep97
iYQgAqGgKwHDBpQ+IX9yWzx26IGE+y5kbMHCIXdYg0JI3V2JRypi8b7D0GHkMOC3uCORgsX/OSwc
bh2W/HZvGZ9IDImJw7HDEd/7kGljFVtkzcLXDpcOF/yvbronotYYQeKLwyeHE4exwyvGBHWi84hu
F1o5zB3OHX7weyEuuiOcePowIkeQ+OrwwWEKkdATnopORR7K2C2Rv1g2gNQNbsog88AiIffmmreQ
+Ohw4JB6Ps+BEkmAairDooEQ6jPunnCVRnoIdIIlpnyPxd9m8gwy9lKpRN4rEX6JJSa7xJ9U5I9Y
Jk1FpDmKv+LNrrlXIkN5gQPcbC63+SrTQbIjmemggtC7RfFnCO83vl4xbmuB17h0K/B3iH5oOtgx
fyURX/m5xP8Fqv/u8JNQXHgWMaG/FzEeY5W8rmQkDRLRDdbYkvgGkXN8nnliTXHZgmftGnrh2prI
ku8ziGxxymK56EldaBFlgt2K9RAXdiayYuIZmrjEQgVuGLNQAOk51rth7BRXpURaKyKlR2RDpFxh
8g2mfgemkiPOwIqx9twYCxVVlbfOIsY+A5oJI6LjhOx7yDMznpnLcwvRWCpVt7FrAknjVsJtgphJ
zTVjxi4lY0Ze+S+0wLUlEkpvkgg2kpBKWWgFLO1rcoylBrUiEsmbJ2TLiYSlpfuFRJeJ+RayZrXX
aCoSQo2IaKq30v8G9WcsOpBK+hdcQOYfz45I85bqN3WdXl1mjSUPmAZ6fNrbhpLA5rgmwQpHpPtD
7ld1Xd4+In2vYk6xSgyWEt5Grsfin8BbXBM+hUjK29hbHkvqzrHGBncE/DcktD9DxGpNJ4somQGT
j6VeWJT0JULe8H2CW6z6jrBi0iVqNHwTyQ+aW+ztB5BY8oyR1n6k7Bq+fhhbYxMKmVx+n3AfisAH
kneW+7r/fUQCb9cXSQmIvIa79PpW08N6nzWaEvHzSyATR+KyoOK/TdN9UBsiVaTKHZmy9Qa+K5Gg
7UJBAzG+iCvZs2/deGh7+c+XTTs0XdyOETLZMkQdiNhGbC19zaPeJKkgkUurZ9U1kF1cWyIZc8yZ
cyWEyl1ECmkNZ/SfATUl7Xg+kkHijDlvZPP9iEgp3ZZtK0+lKR7tqxU1RHIsMWPOK9mqVh7UqDV+
MeCSqps+8cTI5v3D5kytUmsRK/NX0i4+5QwtZ+Fb6eofWCSsaZbTpo1vAzK6G8iqOvuw5jTAP958
6hlr1fFmuS9FP/dhb6ND3xdx/RdgADBglifWgXLhAAAAAElFTkSuQmCC" transform="matrix(1 0 0 1 15 15)">
</image>
<g>
<g>
<g>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="32" y1="21.5142" x2="32" y2="51.1873">
<stop offset="0" style="stop-color:#FBFDFE"/>
<stop offset="0.9716" style="stop-color:#C6E8F5"/>
</linearGradient>
<path class="st6" d="M22.9,51.9h18.2c1,0,1.8-0.8,1.8-1.8V22.7c0-1-0.8-1.8-1.8-1.8H22.9c-1,0-1.8,0.8-1.8,1.8v27.4
C21.1,51.1,21.9,51.9,22.9,51.9z M39.8,49.7c-0.6,0-1.1-0.5-1.1-1.1c0-0.6,0.5-1.1,1.1-1.1c0.6,0,1.1,0.5,1.1,1.1
C40.9,49.3,40.4,49.7,39.8,49.7z M39.8,23.4c0.6,0,1.1,0.5,1.1,1.1s-0.5,1.1-1.1,1.1c-0.6,0-1.1-0.5-1.1-1.1
S39.2,23.4,39.8,23.4z M32,24.2c4.6,0,8.4,3.7,8.4,8.4s-3.7,8.4-8.4,8.4c-0.7,0-1.4-0.1-2.1-0.3l1.6-2.7
c0.5-0.8-0.4-1.7-1.2-1.2l-3.6,2.1c0,0,0,0,0,0c-1.8-1.5-2.9-3.8-2.9-6.4C23.6,27.9,27.4,24.2,32,24.2z M24.4,23.4
c0.6,0,1.1,0.5,1.1,1.1s-0.5,1.1-1.1,1.1s-1.1-0.5-1.1-1.1S23.8,23.4,24.4,23.4z M24.4,47.6c0.6,0,1.1,0.5,1.1,1.1
c0,0.6-0.5,1.1-1.1,1.1s-1.1-0.5-1.1-1.1C23.3,48.1,23.8,47.6,24.4,47.6z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="31.9994" y1="32.4788" x2="32.0716" y2="36.9457">
<stop offset="0" style="stop-color:#FBFDFE"/>
<stop offset="1" style="stop-color:#C6E8F5"/>
</linearGradient>
<circle class="st7" cx="32" cy="32.5" r="2.2"/>
</g>
</g>
</g>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1"
id="图层_1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 64 64"
style="enable-background:new 0 0 64 64;" xml:space="preserve">
<style type="text/css">
.st0{fill:#5E4AA6;}
.st1{fill:url(#SVGID_1_);}
.st2{opacity:1.000000e-03;fill:#1E5992;enable-background:new ;}
.st3{fill:url(#SVGID_2_);}
.st4{opacity:0.3;fill:url(#SVGID_3_);enable-background:new ;}
.st5{fill:url(#SVGID_4_);}
.st6{fill:url(#SVGID_5_);}
.st7{fill:url(#SVGID_6_);}
</style>
<g>
<rect x="-1248.6" y="-1241.1" class="st0" width="0" height="0"/>
<rect x="-1179.7" y="-1233.1" class="st0" width="0" height="0"/>
<rect x="-1156.6" y="-1258.9" class="st0" width="0" height="0"/>
<rect x="-1167.3" y="-1232.2" class="st0" width="0" height="0"/>
<g transform="translate(.000295 -.00032978)">
<rect x="-1248.6" y="-1241.1" class="st0" width="0" height="0"/>
<rect x="-1179.7" y="-1233.1" class="st0" width="0" height="0"/>
<rect x="-1156.6" y="-1258.9" class="st0" width="0" height="0"/>
<rect x="-1167.3" y="-1232.2" class="st0" width="0" height="0"/>
<rect x="-1242.7" y="-1249" class="st0" width="0" height="0"/>
</g>
<rect x="-1248.6" y="-1241.1" class="st0" width="0" height="0"/>
<rect x="-1179.7" y="-1233.1" class="st0" width="0" height="0"/>
<rect x="-1156.6" y="-1258.9" class="st0" width="0" height="0"/>
<rect x="-1167.3" y="-1232.2" class="st0" width="0" height="0"/>
<rect x="-1242.7" y="-1249" class="st0" width="0" height="0"/>
<g transform="translate(2.95e-4,-3.2978e-4)">
<rect x="-1248.6" y="-1241.1" class="st0" width="0" height="0"/>
<rect x="-1179.7" y="-1233.1" class="st0" width="0" height="0"/>
<rect x="-1156.6" y="-1258.9" class="st0" width="0" height="0"/>
<rect x="-1167.3" y="-1232.2" class="st0" width="0" height="0"/>
<rect x="-1242.7" y="-1249" class="st0" width="0" height="0"/>
</g>
</g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-363.3979" y1="913.4439" x2="-363.3979" y2="911.0629" gradientTransform="matrix(3.7796 0 0 -3.7796 1405.5416 3462.4551)">
<stop offset="0" style="stop-color:#0272CB"/>
<stop offset="1" style="stop-color:#0768BA"/>
</linearGradient>
<path image-rendering="auto" shape-rendering="auto" color-rendering="auto" class="st1" d="M4.6,8.5c-1.4,0-2.5,1.2-2.5,2.8v11.2
c0,0.1,0,0.2,0,0.3v30c0,1.5,1.1,2.8,2.5,2.8h55c1.4,0,2.5-1.2,2.5-2.8V17.2c0-1.5-1.1-2.8-2.5-2.8v0h-31l-3.4-4.2
c0,0-1.4-1.8-4-1.8h-5L4.6,8.5z"/>
<path class="st2" d="M31.6,14.4c-0.4,0-1.2-0.1-2,0.4c-2.8,1.4-2.9,2.2-5.9,2.7H5c-0.8,0-1.6,0.3-2.1,0.9c-0.5,0.5-0.8,1.3-0.9,2.1
v1c0-0.8,0.3-1.5,0.9-2.1c0.5-0.5,1.3-0.9,2.1-0.9h18.7c3-0.5,3.1-1.3,5.9-2.7c0.8-0.4,1.5-0.4,2-0.4h27.9c0.7,0,1.3,0.3,1.8,0.8
c0.5,0.5,0.7,1.2,0.7,1.9v-1c0-0.8-0.3-1.4-0.7-1.9c-0.5-0.5-1.1-0.8-1.8-0.8h-4.4H31.6z M2.1,22.4c0,0.1,0,0.2,0,0.3v1
c0-0.1,0-0.2,0-0.3V22.4z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="95.1452" y1="43.801" x2="128.3352" y2="9.648" gradientTransform="matrix(1 0 0 -1 -75.9965 65.4973)">
<stop offset="0" style="stop-color:#27AEE9"/>
<stop offset="1" style="stop-color:#0669BC"/>
</linearGradient>
<path class="st3" d="M28.5,15.5c0,0-1.4,1.8-4.4,3c-0.1,0-0.2,0-0.4,0.1H5c-0.8,0-1.6,0.3-2.1,0.9c-0.5,0.5-0.8,1.3-0.9,2.1v2
c0,0.1,0,0.2,0,0.3v28c0,0.8,0.3,1.4,0.7,1.9c0.5,0.5,1.1,0.8,1.8,0.8h55c0.7,0,1.3-0.3,1.8-0.8c0.5-0.5,0.7-1.2,0.7-1.9V18.2
c0-0.8-0.3-1.4-0.7-1.9c-0.5-0.5-1.1-0.8-1.8-0.8H31.3L28.5,15.5z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-389.233" y1="932.0934" x2="-373.3582" y2="932.0934" gradientTransform="matrix(3.7796 0 0 -3.7796 1473.188 3543.282)">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0"/>
</linearGradient>
<path class="st4" d="M28.5,15.5c0,0-1.4,1.8-4.4,3c-0.1,0-0.2,0-0.4,0.1H5c-0.8,0-1.6,0.3-2.1,0.9c-0.5,0.5-0.8,1.3-0.9,2.1v1.5
c0-0.8,0.3-1.5,0.9-2.1C3.5,20.3,4.2,20,5,20h18.7c0.1,0,0.3,0,0.4-0.1c2.9-1,4.9-3,4.9-3h30.5c0.7,0,1.3,0.3,1.8,0.8
c0.5,0.5,0.7,1.2,0.7,1.9v-1.5c0-0.8-0.3-1.4-0.7-1.9c-0.5-0.5-1.1-0.8-1.8-0.8H31.3H28.5z M2.1,23.4c0,0.1,0,0.2,0,0.3v1.5
c0-0.1,0-0.2,0-0.3V23.4z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-389.2331" y1="923.2966" x2="-373.3582" y2="923.2966" gradientTransform="matrix(3.7796 0 0 -3.7796 1473.188 3543.2234)">
<stop offset="0" style="stop-color:#0A5BA8;stop-opacity:0.9961"/>
<stop offset="1" style="stop-color:#104A8C;stop-opacity:0.9961"/>
</linearGradient>
<path image-rendering="auto" shape-rendering="auto" color-rendering="auto" class="st5" d="M2,51.6v1.1c0,0.8,0.3,1.4,0.7,1.9
c0.5,0.5,1.1,0.8,1.8,0.8h55c0.7,0,1.3-0.3,1.8-0.8c0.5-0.5,0.7-1.2,0.7-1.9v-1.1c0,0.8-0.3,1.4-0.7,1.9c-0.5,0.5-1.1,0.8-1.8,0.8
h-55c-0.7,0-1.3-0.3-1.8-0.8S2,52.4,2,51.6z"/>
<g>
<image style="overflow:visible;opacity:0.25;" width="34" height="44" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAsCAYAAAAATWqyAAAACXBIWXMAAAsSAAALEgHS3X78AAAA
GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA/JJREFUeNrMmFtv00AQhX2LyYUk
pS0VIEA88P9/ES8IqZTShtI0JXHsmE31TXW6dRzb7UMtHSVO1rvHM2cuu0HwQq6wwX/hM61Vep97
iYQgAqGgKwHDBpQ+IX9yWzx26IGE+y5kbMHCIXdYg0JI3V2JRypi8b7D0GHkMOC3uCORgsX/OSwc
bh2W/HZvGZ9IDImJw7HDEd/7kGljFVtkzcLXDpcOF/yvbronotYYQeKLwyeHE4exwyvGBHWi84hu
F1o5zB3OHX7weyEuuiOcePowIkeQ+OrwwWEKkdATnopORR7K2C2Rv1g2gNQNbsog88AiIffmmreQ
+Ohw4JB6Ps+BEkmAairDooEQ6jPunnCVRnoIdIIlpnyPxd9m8gwy9lKpRN4rEX6JJSa7xJ9U5I9Y
Jk1FpDmKv+LNrrlXIkN5gQPcbC63+SrTQbIjmemggtC7RfFnCO83vl4xbmuB17h0K/B3iH5oOtgx
fyURX/m5xP8Fqv/u8JNQXHgWMaG/FzEeY5W8rmQkDRLRDdbYkvgGkXN8nnliTXHZgmftGnrh2prI
ku8ziGxxymK56EldaBFlgt2K9RAXdiayYuIZmrjEQgVuGLNQAOk51rth7BRXpURaKyKlR2RDpFxh
8g2mfgemkiPOwIqx9twYCxVVlbfOIsY+A5oJI6LjhOx7yDMznpnLcwvRWCpVt7FrAknjVsJtgphJ
zTVjxi4lY0Ze+S+0wLUlEkpvkgg2kpBKWWgFLO1rcoylBrUiEsmbJ2TLiYSlpfuFRJeJ+RayZrXX
aCoSQo2IaKq30v8G9WcsOpBK+hdcQOYfz45I85bqN3WdXl1mjSUPmAZ6fNrbhpLA5rgmwQpHpPtD
7ld1Xd4+In2vYk6xSgyWEt5Grsfin8BbXBM+hUjK29hbHkvqzrHGBncE/DcktD9DxGpNJ4somQGT
j6VeWJT0JULe8H2CW6z6jrBi0iVqNHwTyQ+aW+ztB5BY8oyR1n6k7Bq+fhhbYxMKmVx+n3AfisAH
kneW+7r/fUQCb9cXSQmIvIa79PpW08N6nzWaEvHzSyATR+KyoOK/TdN9UBsiVaTKHZmy9Qa+K5Gg
7UJBAzG+iCvZs2/deGh7+c+XTTs0XdyOETLZMkQdiNhGbC19zaPeJKkgkUurZ9U1kF1cWyIZc8yZ
cyWEyl1ECmkNZ/SfATUl7Xg+kkHijDlvZPP9iEgp3ZZtK0+lKR7tqxU1RHIsMWPOK9mqVh7UqDV+
MeCSqps+8cTI5v3D5kytUmsRK/NX0i4+5QwtZ+Fb6eofWCSsaZbTpo1vAzK6G8iqOvuw5jTAP958
6hlr1fFmuS9FP/dhb6ND3xdx/RdgADBglifWgXLhAAAAAElFTkSuQmCC" transform="matrix(1 0 0 1 15 15)">
</image>
<g>
<g>
<g>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="32" y1="21.5142" x2="32" y2="51.1873">
<stop offset="0" style="stop-color:#FBFDFE"/>
<stop offset="0.9716" style="stop-color:#C6E8F5"/>
</linearGradient>
<path class="st6" d="M22.9,51.9h18.2c1,0,1.8-0.8,1.8-1.8V22.7c0-1-0.8-1.8-1.8-1.8H22.9c-1,0-1.8,0.8-1.8,1.8v27.4
C21.1,51.1,21.9,51.9,22.9,51.9z M39.8,49.7c-0.6,0-1.1-0.5-1.1-1.1c0-0.6,0.5-1.1,1.1-1.1c0.6,0,1.1,0.5,1.1,1.1
C40.9,49.3,40.4,49.7,39.8,49.7z M39.8,23.4c0.6,0,1.1,0.5,1.1,1.1s-0.5,1.1-1.1,1.1c-0.6,0-1.1-0.5-1.1-1.1
S39.2,23.4,39.8,23.4z M32,24.2c4.6,0,8.4,3.7,8.4,8.4s-3.7,8.4-8.4,8.4c-0.7,0-1.4-0.1-2.1-0.3l1.6-2.7
c0.5-0.8-0.4-1.7-1.2-1.2l-3.6,2.1c0,0,0,0,0,0c-1.8-1.5-2.9-3.8-2.9-6.4C23.6,27.9,27.4,24.2,32,24.2z M24.4,23.4
c0.6,0,1.1,0.5,1.1,1.1s-0.5,1.1-1.1,1.1s-1.1-0.5-1.1-1.1S23.8,23.4,24.4,23.4z M24.4,47.6c0.6,0,1.1,0.5,1.1,1.1
c0,0.6-0.5,1.1-1.1,1.1s-1.1-0.5-1.1-1.1C23.3,48.1,23.8,47.6,24.4,47.6z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="31.9994" y1="32.4788" x2="32.0716" y2="36.9457">
<stop offset="0" style="stop-color:#FBFDFE"/>
<stop offset="1" style="stop-color:#C6E8F5"/>
</linearGradient>
<circle class="st7" cx="32" cy="32.5" r="2.2"/>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -1,113 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1"
id="图层_1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 64 64"
style="enable-background:new 0 0 64 64;" xml:space="preserve">
<style type="text/css">
.st0{fill:#5E4AA6;}
.st1{fill:url(#SVGID_1_);}
.st2{opacity:1.000000e-03;fill:#1E5992;enable-background:new ;}
.st3{fill:url(#SVGID_2_);}
.st4{opacity:0.3;fill:url(#SVGID_3_);enable-background:new ;}
.st5{fill:url(#SVGID_4_);}
.st6{fill:url(#SVGID_5_);}
</style>
<g>
<polygon class="st0" points="-1248.6,-1241.1 -1248.6,-1241.1 -1248.6,-1241.1 "/>
<polygon class="st0" points="-1179.7,-1233.1 -1179.7,-1233.1 -1179.7,-1233.1 "/>
<polygon class="st0" points="-1156.6,-1258.9 -1156.6,-1258.9 -1156.6,-1258.9 "/>
<polygon class="st0" points="-1167.3,-1232.2 -1167.3,-1232.2 -1167.3,-1232.2 "/>
<g transform="translate(.000295 -.00032978)">
<polygon class="st0" points="-1248.6,-1241.1 -1248.6,-1241.1 -1248.6,-1241.1 "/>
<polygon class="st0" points="-1179.7,-1233.1 -1179.7,-1233.1 -1179.7,-1233.1 "/>
<polygon class="st0" points="-1156.6,-1258.9 -1156.6,-1258.9 -1156.6,-1258.9 "/>
<polygon class="st0" points="-1167.3,-1232.2 -1167.3,-1232.2 -1167.3,-1232.2 "/>
<polygon class="st0" points="-1242.7,-1249 -1242.7,-1249 -1242.7,-1249 "/>
</g>
<polygon class="st0" points="-1248.6,-1241.1 -1248.6,-1241.1 -1248.6,-1241.1 "/>
<polygon class="st0" points="-1179.7,-1233.1 -1179.7,-1233.1 -1179.7,-1233.1 "/>
<polygon class="st0" points="-1156.6,-1258.9 -1156.6,-1258.9 -1156.6,-1258.9 "/>
<polygon class="st0" points="-1167.3,-1232.2 -1167.3,-1232.2 -1167.3,-1232.2 "/>
<polygon class="st0" points="-1242.7,-1249 -1242.7,-1249 -1242.7,-1249 "/>
<g transform="translate(2.95e-4,-3.2978e-4)">
<polygon class="st0" points="-1248.6,-1241.1 -1248.6,-1241.1 -1248.6,-1241.1 "/>
<polygon class="st0" points="-1179.7,-1233.1 -1179.7,-1233.1 -1179.7,-1233.1 "/>
<polygon class="st0" points="-1156.6,-1258.9 -1156.6,-1258.9 -1156.6,-1258.9 "/>
<polygon class="st0" points="-1167.3,-1232.2 -1167.3,-1232.2 -1167.3,-1232.2 "/>
<polygon class="st0" points="-1242.7,-1249 -1242.7,-1249 -1242.7,-1249 "/>
</g>
</g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-753.1828" y1="651.0814" x2="-753.1828" y2="653.4623" gradientTransform="matrix(3.7796 0 0 3.7796 2878.7295 -2450.8245)">
<stop offset="0" style="stop-color:#0272CB"/>
<stop offset="1" style="stop-color:#0768BA"/>
</linearGradient>
<path image-rendering="auto" shape-rendering="auto" color-rendering="auto" class="st1" d="M4.5,8.5C3.1,8.5,2,9.7,2,11.2v11.2
c0,0.1,0,0.2,0,0.3v30c0,1.5,1.1,2.8,2.5,2.8h55c1.4,0,2.5-1.2,2.5-2.8V17.2c0-1.5-1.1-2.8-2.5-2.8l0,0h-31l-3.4-4.2
c0,0-1.4-1.8-4-1.8h-5L4.5,8.5z"/>
<path class="st2" d="M31.6,14.4c-0.4,0-1.2-0.1-2,0.4c-2.8,1.4-2.9,2.2-5.9,2.7H5c-0.8,0-1.6,0.3-2.1,0.9c-0.6,0.5-0.9,1.2-0.9,2v1
c0-0.8,0.3-1.5,0.9-2.1c0.5-0.5,1.3-0.9,2.1-0.9h18.7c3-0.5,3.1-1.3,5.9-2.7c0.8-0.4,1.5-0.4,2-0.4h27.9c0.7,0,1.3,0.3,1.8,0.8
S62,17.3,62,18v-1c0-0.8-0.3-1.4-0.7-1.9c-0.5-0.5-1.1-0.8-1.8-0.8h-4.4L31.6,14.4L31.6,14.4z M2,22.4c0,0.1,0,0.2,0,0.3v1
c0-0.1,0-0.2,0-0.3V22.4z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="95.0853" y1="2392.217" x2="128.2754" y2="2426.3699" gradientTransform="matrix(1 0 0 1 -75.9965 -2370.5027)">
<stop offset="0" style="stop-color:#27AEE9"/>
<stop offset="1" style="stop-color:#0669BC"/>
</linearGradient>
<path class="st3" d="M28.5,15.5c0,0-1.4,1.8-4.4,3c-0.1,0-0.2,0-0.4,0.1H5c-0.8,0-1.6,0.3-2.1,0.9C2.4,20,2,20.7,2,21.5v2
c0,0.1,0,0.2,0,0.3v28c0,0.8,0.3,1.4,0.7,1.9c0.5,0.5,1.1,0.8,1.8,0.8h55c0.7,0,1.3-0.3,1.8-0.8s0.7-1.2,0.7-1.9V18.2
c0-0.8-0.3-1.4-0.7-1.9c-0.5-0.5-1.1-0.8-1.8-0.8H31.2L28.5,15.5z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-779.0179" y1="632.4208" x2="-763.1432" y2="632.4208" gradientTransform="matrix(3.7796 0 0 3.7796 2946.376 -2369.9976)">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0"/>
</linearGradient>
<path class="st4" d="M28.5,15.5c0,0-1.4,1.8-4.4,3c-0.1,0-0.2,0-0.4,0.1H5c-0.8,0-1.6,0.3-2.1,0.9C2.4,20,2,20.7,2,21.5V23
c0-0.8,0.3-1.5,0.9-2.1C3.4,20.3,4.2,20,5,20h18.7c0.1,0,0.3,0,0.4-0.1c2.9-1,4.9-3,4.9-3h30.5c0.7,0,1.3,0.3,1.8,0.8
s0.7,1.2,0.7,1.9v-1.5c0-0.8-0.3-1.4-0.7-1.9c-0.5-0.5-1.1-0.8-1.8-0.8H31.2h-2.7V15.5z M2,23.4c0,0.1,0,0.2,0,0.3v1.5
c0-0.1,0-0.2,0-0.3V23.4z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-779.0179" y1="641.2203" x2="-763.1432" y2="641.2203" gradientTransform="matrix(3.7796 0 0 3.7796 2946.376 -2370.0562)">
<stop offset="0" style="stop-color:#0A5BA8;stop-opacity:0.9961"/>
<stop offset="1" style="stop-color:#104A8C;stop-opacity:0.9961"/>
</linearGradient>
<path image-rendering="auto" shape-rendering="auto" color-rendering="auto" class="st5" d="M2,51.6v1.1c0,0.8,0.3,1.4,0.7,1.9
c0.5,0.5,1.1,0.8,1.8,0.8h55c0.7,0,1.3-0.3,1.8-0.8s0.7-1.2,0.7-1.9v-1.1c0,0.8-0.3,1.4-0.7,1.9c-0.5,0.5-1.1,0.8-1.8,0.8h-55
c-0.7,0-1.3-0.3-1.8-0.8S2,52.4,2,51.6z"/>
<g>
<image style="overflow:visible;opacity:0.25;" width="33" height="45" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAtCAYAAAAgJgIUAAAACXBIWXMAAAsSAAALEgHS3X78AAAA
GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABD9JREFUeNrMmAlv20YQhcXLoi6f
cRzkQAv0//+m1i6ay67pIxYjiuR2CXwDvNCURSpOUgMPNKnl7tuZN8dyNPof/AXP/K77WSQCELbe
bwjUXN2PJBGCyCMGIYuXoOK+7jtpNJBwMz7xmHgsPPY95tzHYpFB1ogGEAghMPU49HjhceZxAqFE
XDLIEvFAK4zZ/SuPtx4vPVKPrx6X/B4IiXUfi8QDhNjsdOZx7PHG4w+ujWVyjwPGNbooRB9bXRMP
cNseJBrzv/b4zeMdz3KssPJ48PiCddYSMd9FImRciitOscAbyMxYMIDArUcGkRUWedIacU9XmB4W
uOOE6yHumOCCDJ188LiGVCEidbuSsKhIWXBBWE55ZmKcStgusFCKS0aSPx5ZJX4igYVCwBBjFYuA
SsQXoBsjc4BWAq4rCD1KZtGGnVtSGjPpTHZ5zAK205DJl+jggf8riapENvcomUUdBGIWt4UPxcTm
/5RdW4IqIJCLBiyxTZkvEsupa74hoVGwQHwvJSvuM1ncyh1OLOEgNxcBH7KhAIKFuMWpJnTSKRO8
IzO+gFhFKFZMdA/MbWsINJY6Yt5m3A2bcvKORU3VFqbpYE4u+B2cSSK6Jg9Y/K8gNuI+lSjaw+RT
rhlzp2LNUZclzB0HuOItCWmMv1PI3kiErEWcY+Yzizp2a+GctPqQ5uriDaU6FVEecb9k5xYBgSxi
FlFdpTKm7hJkWxObOqdQmhfLEboTs8QaclY1E8ZGPDct5KIF15WsnEy64oVcdlgIylbJrhlXSNKy
zTQ6+uTxGTcupbB9Q8KSRykmz5hgn+e5KHvFu04WM1IrFgp5ryHwj8dHSOTt6hq1UrUmLEtGewzO
iYwv7DhBwBYJIxmfYPJm/HuPvyByKe/XmzKmamEPWEjV4oqQfHCMpSwrTiSBPeCCc48LLHErucZt
6zG1ek5YIBELWaN7KnXExFiy2yt2f0Fpz7r00KfRNdckYpVZK3zn/G7izFj0AqgbVl2d1iYSrker
f8DVMmNj/n9Z9BwYgfsuN/SxhGvV/Uiq6xwyE+kXrhDhnyLE5tkdv5eb+s34icULdqcnrrG4opax
X1nsipC8JLy3EniqvXNSLR+EwJzyfMpVBWaJroBUu5Ma3Og6qYwFu1lK/ahFtBFuURdZoep1Uo+3
aGLUKj6VRE0kYTsVsWoCi/ocuoccAwMJ16QVujUkjiRsUzm1V9vywNDPCO2GNRDNpNJ/xh3fMHa2
hBOhrhGd6SNnjJXzcpcPJX1JlCx+TxheYvIQ/5eEZCZhud6UnIaScC0St+SBfUlSM37P+tSJXS1R
Sz+RIcYRteCzNLJ3EPgbqyy3Jamh0WHNyr1o4IbUPGaRJc+upXkp+7gjGBAZejqbyElMT2G5CFaz
5bN9vetqfjUzVhIhg6Jk6CdEPbG3v2Vq1R0Uos/9RXfnr7q//O8/AQYAxhWve3m9fqQAAAAASUVO
RK5CYII=" transform="matrix(1 0 0 1 16 15)">
</image>
<g>
<g>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="32.3842" y1="22.1772" x2="32.3842" y2="51.1664">
<stop offset="0" style="stop-color:#FBFDFE"/>
<stop offset="0.9716" style="stop-color:#C6E8F5"/>
</linearGradient>
<path class="st6" d="M28.6,34.1c0-1.7-1.4-3.2-3.1-3.2c-1.8,0-3.3,1.4-3.3,3.2c0,1.4,0.9,2.6,2.2,3v1.2c0,0.7,0.4,1.5,1,1.9
l6.2,4.7c-1.6,0.5-2.7,1.9-2.7,3.6c0,2.1,1.7,3.8,3.8,3.8s3.8-1.7,3.8-3.8c0-1.7-1.2-3.2-2.8-3.7v-1.8l5.7-3.9c0.6-0.4,1-1.2,1-2
v-1.7h0.6c0.9,0,1.7-0.8,1.7-1.7V31c0-0.9-0.8-1.7-1.7-1.7h-3.3c-0.9,0-1.7,0.8-1.7,1.7v2.8c0,0.9,0.8,1.7,1.7,1.7h0.6v1.9
l-4.7,3.3V28.2h1.7c1.2,0,1.9-1.3,1.3-2.3L34,21.7c-0.7-1.1-2.2-1.1-2.9,0l-2.6,4.2c-0.6,1,0.1,2.3,1.3,2.3h1.8v14.3l-5.2-3.9
v-1.4C27.6,36.7,28.6,35.5,28.6,34.1z"/>
</g>
</g>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1"
id="图层_1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 64 64"
style="enable-background:new 0 0 64 64;" xml:space="preserve">
<style type="text/css">
.st0{fill:#5E4AA6;}
.st1{fill:url(#SVGID_1_);}
.st2{opacity:1.000000e-03;fill:#1E5992;enable-background:new ;}
.st3{fill:url(#SVGID_2_);}
.st4{opacity:0.3;fill:url(#SVGID_3_);enable-background:new ;}
.st5{fill:url(#SVGID_4_);}
.st6{fill:url(#SVGID_5_);}
</style>
<g>
<polygon class="st0" points="-1248.6,-1241.1 -1248.6,-1241.1 -1248.6,-1241.1 "/>
<polygon class="st0" points="-1179.7,-1233.1 -1179.7,-1233.1 -1179.7,-1233.1 "/>
<polygon class="st0" points="-1156.6,-1258.9 -1156.6,-1258.9 -1156.6,-1258.9 "/>
<polygon class="st0" points="-1167.3,-1232.2 -1167.3,-1232.2 -1167.3,-1232.2 "/>
<g transform="translate(.000295 -.00032978)">
<polygon class="st0" points="-1248.6,-1241.1 -1248.6,-1241.1 -1248.6,-1241.1 "/>
<polygon class="st0" points="-1179.7,-1233.1 -1179.7,-1233.1 -1179.7,-1233.1 "/>
<polygon class="st0" points="-1156.6,-1258.9 -1156.6,-1258.9 -1156.6,-1258.9 "/>
<polygon class="st0" points="-1167.3,-1232.2 -1167.3,-1232.2 -1167.3,-1232.2 "/>
<polygon class="st0" points="-1242.7,-1249 -1242.7,-1249 -1242.7,-1249 "/>
</g>
<polygon class="st0" points="-1248.6,-1241.1 -1248.6,-1241.1 -1248.6,-1241.1 "/>
<polygon class="st0" points="-1179.7,-1233.1 -1179.7,-1233.1 -1179.7,-1233.1 "/>
<polygon class="st0" points="-1156.6,-1258.9 -1156.6,-1258.9 -1156.6,-1258.9 "/>
<polygon class="st0" points="-1167.3,-1232.2 -1167.3,-1232.2 -1167.3,-1232.2 "/>
<polygon class="st0" points="-1242.7,-1249 -1242.7,-1249 -1242.7,-1249 "/>
<g transform="translate(2.95e-4,-3.2978e-4)">
<polygon class="st0" points="-1248.6,-1241.1 -1248.6,-1241.1 -1248.6,-1241.1 "/>
<polygon class="st0" points="-1179.7,-1233.1 -1179.7,-1233.1 -1179.7,-1233.1 "/>
<polygon class="st0" points="-1156.6,-1258.9 -1156.6,-1258.9 -1156.6,-1258.9 "/>
<polygon class="st0" points="-1167.3,-1232.2 -1167.3,-1232.2 -1167.3,-1232.2 "/>
<polygon class="st0" points="-1242.7,-1249 -1242.7,-1249 -1242.7,-1249 "/>
</g>
</g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-753.1828" y1="651.0814" x2="-753.1828" y2="653.4623" gradientTransform="matrix(3.7796 0 0 3.7796 2878.7295 -2450.8245)">
<stop offset="0" style="stop-color:#0272CB"/>
<stop offset="1" style="stop-color:#0768BA"/>
</linearGradient>
<path image-rendering="auto" shape-rendering="auto" color-rendering="auto" class="st1" d="M4.5,8.5C3.1,8.5,2,9.7,2,11.2v11.2
c0,0.1,0,0.2,0,0.3v30c0,1.5,1.1,2.8,2.5,2.8h55c1.4,0,2.5-1.2,2.5-2.8V17.2c0-1.5-1.1-2.8-2.5-2.8l0,0h-31l-3.4-4.2
c0,0-1.4-1.8-4-1.8h-5L4.5,8.5z"/>
<path class="st2" d="M31.6,14.4c-0.4,0-1.2-0.1-2,0.4c-2.8,1.4-2.9,2.2-5.9,2.7H5c-0.8,0-1.6,0.3-2.1,0.9c-0.6,0.5-0.9,1.2-0.9,2v1
c0-0.8,0.3-1.5,0.9-2.1c0.5-0.5,1.3-0.9,2.1-0.9h18.7c3-0.5,3.1-1.3,5.9-2.7c0.8-0.4,1.5-0.4,2-0.4h27.9c0.7,0,1.3,0.3,1.8,0.8
S62,17.3,62,18v-1c0-0.8-0.3-1.4-0.7-1.9c-0.5-0.5-1.1-0.8-1.8-0.8h-4.4L31.6,14.4L31.6,14.4z M2,22.4c0,0.1,0,0.2,0,0.3v1
c0-0.1,0-0.2,0-0.3V22.4z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="95.0853" y1="2392.217" x2="128.2754" y2="2426.3699" gradientTransform="matrix(1 0 0 1 -75.9965 -2370.5027)">
<stop offset="0" style="stop-color:#27AEE9"/>
<stop offset="1" style="stop-color:#0669BC"/>
</linearGradient>
<path class="st3" d="M28.5,15.5c0,0-1.4,1.8-4.4,3c-0.1,0-0.2,0-0.4,0.1H5c-0.8,0-1.6,0.3-2.1,0.9C2.4,20,2,20.7,2,21.5v2
c0,0.1,0,0.2,0,0.3v28c0,0.8,0.3,1.4,0.7,1.9c0.5,0.5,1.1,0.8,1.8,0.8h55c0.7,0,1.3-0.3,1.8-0.8s0.7-1.2,0.7-1.9V18.2
c0-0.8-0.3-1.4-0.7-1.9c-0.5-0.5-1.1-0.8-1.8-0.8H31.2L28.5,15.5z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-779.0179" y1="632.4208" x2="-763.1432" y2="632.4208" gradientTransform="matrix(3.7796 0 0 3.7796 2946.376 -2369.9976)">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0"/>
</linearGradient>
<path class="st4" d="M28.5,15.5c0,0-1.4,1.8-4.4,3c-0.1,0-0.2,0-0.4,0.1H5c-0.8,0-1.6,0.3-2.1,0.9C2.4,20,2,20.7,2,21.5V23
c0-0.8,0.3-1.5,0.9-2.1C3.4,20.3,4.2,20,5,20h18.7c0.1,0,0.3,0,0.4-0.1c2.9-1,4.9-3,4.9-3h30.5c0.7,0,1.3,0.3,1.8,0.8
s0.7,1.2,0.7,1.9v-1.5c0-0.8-0.3-1.4-0.7-1.9c-0.5-0.5-1.1-0.8-1.8-0.8H31.2h-2.7V15.5z M2,23.4c0,0.1,0,0.2,0,0.3v1.5
c0-0.1,0-0.2,0-0.3V23.4z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-779.0179" y1="641.2203" x2="-763.1432" y2="641.2203" gradientTransform="matrix(3.7796 0 0 3.7796 2946.376 -2370.0562)">
<stop offset="0" style="stop-color:#0A5BA8;stop-opacity:0.9961"/>
<stop offset="1" style="stop-color:#104A8C;stop-opacity:0.9961"/>
</linearGradient>
<path image-rendering="auto" shape-rendering="auto" color-rendering="auto" class="st5" d="M2,51.6v1.1c0,0.8,0.3,1.4,0.7,1.9
c0.5,0.5,1.1,0.8,1.8,0.8h55c0.7,0,1.3-0.3,1.8-0.8s0.7-1.2,0.7-1.9v-1.1c0,0.8-0.3,1.4-0.7,1.9c-0.5,0.5-1.1,0.8-1.8,0.8h-55
c-0.7,0-1.3-0.3-1.8-0.8S2,52.4,2,51.6z"/>
<g>
<image style="overflow:visible;opacity:0.25;" width="33" height="45" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAtCAYAAAAgJgIUAAAACXBIWXMAAAsSAAALEgHS3X78AAAA
GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABD9JREFUeNrMmAlv20YQhcXLoi6f
cRzkQAv0//+m1i6ay67pIxYjiuR2CXwDvNCURSpOUgMPNKnl7tuZN8dyNPof/AXP/K77WSQCELbe
bwjUXN2PJBGCyCMGIYuXoOK+7jtpNJBwMz7xmHgsPPY95tzHYpFB1ogGEAghMPU49HjhceZxAqFE
XDLIEvFAK4zZ/SuPtx4vPVKPrx6X/B4IiXUfi8QDhNjsdOZx7PHG4w+ujWVyjwPGNbooRB9bXRMP
cNseJBrzv/b4zeMdz3KssPJ48PiCddYSMd9FImRciitOscAbyMxYMIDArUcGkRUWedIacU9XmB4W
uOOE6yHumOCCDJ188LiGVCEidbuSsKhIWXBBWE55ZmKcStgusFCKS0aSPx5ZJX4igYVCwBBjFYuA
SsQXoBsjc4BWAq4rCD1KZtGGnVtSGjPpTHZ5zAK205DJl+jggf8riapENvcomUUdBGIWt4UPxcTm
/5RdW4IqIJCLBiyxTZkvEsupa74hoVGwQHwvJSvuM1ncyh1OLOEgNxcBH7KhAIKFuMWpJnTSKRO8
IzO+gFhFKFZMdA/MbWsINJY6Yt5m3A2bcvKORU3VFqbpYE4u+B2cSSK6Jg9Y/K8gNuI+lSjaw+RT
rhlzp2LNUZclzB0HuOItCWmMv1PI3kiErEWcY+Yzizp2a+GctPqQ5uriDaU6FVEecb9k5xYBgSxi
FlFdpTKm7hJkWxObOqdQmhfLEboTs8QaclY1E8ZGPDct5KIF15WsnEy64oVcdlgIylbJrhlXSNKy
zTQ6+uTxGTcupbB9Q8KSRykmz5hgn+e5KHvFu04WM1IrFgp5ryHwj8dHSOTt6hq1UrUmLEtGewzO
iYwv7DhBwBYJIxmfYPJm/HuPvyByKe/XmzKmamEPWEjV4oqQfHCMpSwrTiSBPeCCc48LLHErucZt
6zG1ek5YIBELWaN7KnXExFiy2yt2f0Fpz7r00KfRNdckYpVZK3zn/G7izFj0AqgbVl2d1iYSrker
f8DVMmNj/n9Z9BwYgfsuN/SxhGvV/Uiq6xwyE+kXrhDhnyLE5tkdv5eb+s34icULdqcnrrG4opax
X1nsipC8JLy3EniqvXNSLR+EwJzyfMpVBWaJroBUu5Ma3Og6qYwFu1lK/ahFtBFuURdZoep1Uo+3
aGLUKj6VRE0kYTsVsWoCi/ocuoccAwMJ16QVujUkjiRsUzm1V9vywNDPCO2GNRDNpNJ/xh3fMHa2
hBOhrhGd6SNnjJXzcpcPJX1JlCx+TxheYvIQ/5eEZCZhud6UnIaScC0St+SBfUlSM37P+tSJXS1R
Sz+RIcYRteCzNLJ3EPgbqyy3Jamh0WHNyr1o4IbUPGaRJc+upXkp+7gjGBAZejqbyElMT2G5CFaz
5bN9vetqfjUzVhIhg6Jk6CdEPbG3v2Vq1R0Uos/9RXfnr7q//O8/AQYAxhWve3m9fqQAAAAASUVO
RK5CYII=" transform="matrix(1 0 0 1 16 15)">
</image>
<g>
<g>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="32.3842" y1="22.1772" x2="32.3842" y2="51.1664">
<stop offset="0" style="stop-color:#FBFDFE"/>
<stop offset="0.9716" style="stop-color:#C6E8F5"/>
</linearGradient>
<path class="st6" d="M28.6,34.1c0-1.7-1.4-3.2-3.1-3.2c-1.8,0-3.3,1.4-3.3,3.2c0,1.4,0.9,2.6,2.2,3v1.2c0,0.7,0.4,1.5,1,1.9
l6.2,4.7c-1.6,0.5-2.7,1.9-2.7,3.6c0,2.1,1.7,3.8,3.8,3.8s3.8-1.7,3.8-3.8c0-1.7-1.2-3.2-2.8-3.7v-1.8l5.7-3.9c0.6-0.4,1-1.2,1-2
v-1.7h0.6c0.9,0,1.7-0.8,1.7-1.7V31c0-0.9-0.8-1.7-1.7-1.7h-3.3c-0.9,0-1.7,0.8-1.7,1.7v2.8c0,0.9,0.8,1.7,1.7,1.7h0.6v1.9
l-4.7,3.3V28.2h1.7c1.2,0,1.9-1.3,1.3-2.3L34,21.7c-0.7-1.1-2.2-1.1-2.9,0l-2.6,4.2c-0.6,1,0.1,2.3,1.3,2.3h1.8v14.3l-5.2-3.9
v-1.4C27.6,36.7,28.6,35.5,28.6,34.1z"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -1,25 +1,25 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="200.000000pt" height="200.000000pt" viewBox="0 0 200.000000 200.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M875 1894 c-11 -2 -51 -11 -88 -20 -341 -78 -610 -364 -673 -714 -82
-459 197 -902 647 -1030 94 -27 277 -37 378 -21 303 47 575 261 690 540 55
133 66 192 65 361 -1 136 -4 165 -27 235 -36 116 -62 170 -123 261 -123 186
-347 336 -566 379 -42 8 -276 15 -303 9z m250 -168 c11 -2 42 -9 70 -16 131
-30 288 -135 387 -260 160 -201 198 -506 93 -745 l-22 -50 2 80 c3 180 -64
351 -184 476 -209 216 -544 260 -807 105 -201 -117 -326 -347 -319 -587 l2
-74 -19 44 c-63 140 -80 332 -44 476 24 94 87 219 147 292 109 133 290 238
448 259 25 3 47 7 49 9 5 4 173 -3 197 -9z m8 -501 c33 -8 85 -31 116 -50 227
-137 305 -418 183 -651 l-21 -39 -1 35 c-9 251 -245 439 -490 389 -186 -38
-323 -200 -330 -389 l-1 -35 -23 45 c-101 194 -61 429 99 578 130 122 292 162
468 117z m-27 -499 c182 -85 183 -345 1 -438 -53 -27 -161 -26 -215 1 -146 75
-180 267 -69 390 63 69 190 90 283 47z"/>
</g>
</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="200.000000pt" height="200.000000pt" viewBox="0 0 200.000000 200.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M875 1894 c-11 -2 -51 -11 -88 -20 -341 -78 -610 -364 -673 -714 -82
-459 197 -902 647 -1030 94 -27 277 -37 378 -21 303 47 575 261 690 540 55
133 66 192 65 361 -1 136 -4 165 -27 235 -36 116 -62 170 -123 261 -123 186
-347 336 -566 379 -42 8 -276 15 -303 9z m250 -168 c11 -2 42 -9 70 -16 131
-30 288 -135 387 -260 160 -201 198 -506 93 -745 l-22 -50 2 80 c3 180 -64
351 -184 476 -209 216 -544 260 -807 105 -201 -117 -326 -347 -319 -587 l2
-74 -19 44 c-63 140 -80 332 -44 476 24 94 87 219 147 292 109 133 290 238
448 259 25 3 47 7 49 9 5 4 173 -3 197 -9z m8 -501 c33 -8 85 -31 116 -50 227
-137 305 -418 183 -651 l-21 -39 -1 35 c-9 251 -245 439 -490 389 -186 -38
-323 -200 -330 -389 l-1 -35 -23 45 c-101 194 -61 429 99 578 130 122 292 162
468 117z m-27 -499 c182 -85 183 -345 1 -438 -53 -27 -161 -26 -215 1 -146 75
-180 267 -69 390 63 69 190 90 283 47z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,159 +1,159 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
id="Capa_1"
x="0px"
y="0px"
viewBox="0 0 407 407"
style="enable-background:new 0 0 407 407;"
xml:space="preserve"><metadata
id="metadata36"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs34"><linearGradient
xlink:href="#SVGID_1_"
id="linearGradient46"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
x1="203.7169"
y1="7.7039"
x2="203.7169"
y2="402.0255" /><linearGradient
xlink:href="#SVGID_1_"
id="linearGradient48"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
x1="203.7169"
y1="7.7039"
x2="203.7169"
y2="402.0255" />
<linearGradient
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
y2="402.02551"
x2="203.7169"
y1="7.7038999"
x1="203.7169"
gradientUnits="userSpaceOnUse"
id="linearGradient120"><stop
id="stop6-9"
style="stop-color:#F2F2F2"
offset="0" /><stop
id="stop8-1"
style="stop-color:#F7F7F7"
offset="0.5963" /><stop
id="stop10-7"
style="stop-color:#FEFEFE"
offset="1" /></linearGradient><filter
style="color-interpolation-filters:sRGB"
id="filter1002"
x="-0.013201674"
width="1.0264033"
y="-0.013198327"
height="1.0263967"><feGaussianBlur
stdDeviation="2.168925"
id="feGaussianBlur1004" /></filter></defs>
<style
type="text/css"
id="style2">
.st0{fill:url(#SVGID_1_);}
.st1{fill:#515151;}
</style>
<g
transform="matrix(1,0,0,0.98477354,0,6.0829719)"
id="g15-0"
style="fill:#4d4d4d;filter:url(#filter1002)"><linearGradient
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
y2="402.02551"
x2="203.7169"
y1="7.7038999"
x1="203.7169"
gradientUnits="userSpaceOnUse"
id="linearGradient91"><stop
id="stop85"
style="stop-color:#F2F2F2"
offset="0" /><stop
id="stop87"
style="stop-color:#F7F7F7"
offset="0.5963" /><stop
id="stop89"
style="stop-color:#FEFEFE"
offset="1" /></linearGradient><path
style="fill:#4d4d4d"
id="path13-7"
d="M 400.9,202.3 C 400.9,92.3 313.8,5.1 203.7,5.1 93.7,5.2 6.6,92.3 6.6,202.3 c 0,110 87.1,197.2 197.2,197.2 110.1,0 197.1,-87.1 197.1,-197.2 z"
class="st0" /><path
style="fill:#4d4d4d"
class="st0"
d="M 400.9,202.3 C 400.9,92.3 313.8,5.1 203.7,5.1 93.7,5.2 6.6,92.3 6.6,202.3 c 0,110 87.1,197.2 197.2,197.2 110.1,0 197.1,-87.1 197.1,-197.2 z"
id="path40-7" /></g><g
id="g15">
<linearGradient
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
y2="402.02551"
x2="203.7169"
y1="7.7038999"
x1="203.7169"
gradientUnits="userSpaceOnUse"
id="SVGID_1_">
<stop
id="stop6"
style="stop-color:#F2F2F2"
offset="0" />
<stop
id="stop8"
style="stop-color:#F7F7F7"
offset="0.5963" />
<stop
id="stop10"
style="stop-color:#FEFEFE"
offset="1" />
</linearGradient>
<path
style="fill:url(#linearGradient46)"
id="path13"
d="M 400.9,202.3 C 400.9,92.3 313.8,5.1 203.7,5.1 93.7,5.2 6.6,92.3 6.6,202.3 c 0,110 87.1,197.2 197.2,197.2 110.1,0 197.1,-87.1 197.1,-197.2 z"
class="st0" />
<path
style="fill:url(#linearGradient48)"
class="st0"
d="M 400.9,202.3 C 400.9,92.3 313.8,5.1 203.7,5.1 93.7,5.2 6.6,92.3 6.6,202.3 c 0,110 87.1,197.2 197.2,197.2 110.1,0 197.1,-87.1 197.1,-197.2 z"
id="path40" /></g><g
id="g27">
<path
style="fill:#515151"
id="path17"
d="m 223.7,137.8 h 0.2 v 6.9 h 7.9 v -28.5 c 0,-2.1 -0.4,-3.9 -1.2,-5.6 -0.8,-1.7 -1.9,-3.1 -3.4,-4.3 -1.5,-1.2 -3.2,-2.1 -5.3,-2.7 -2.1,-0.6 -4.3,-1 -6.9,-1 -2.3,0 -4.5,0.3 -6.5,1 -2,0.6 -3.7,1.5 -5.2,2.7 -1.5,1.2 -2.6,2.5 -3.5,4.1 -0.9,1.6 -1.3,3.3 -1.4,5.1 h 7.8 c 0.2,-0.9 0.5,-1.7 1,-2.4 0.5,-0.7 1.1,-1.4 1.8,-1.9 0.7,-0.5 1.6,-0.9 2.6,-1.2 1,-0.3 2,-0.4 3.1,-0.4 2.8,0 4.9,0.6 6.5,1.9 1.5,1.2 2.3,3.1 2.3,5.5 v 3.2 l -11.2,0.6 c -5.2,0.3 -9.1,1.5 -11.8,3.6 -2.7,2.1 -4.1,4.9 -4.1,8.6 0,1.9 0.3,3.6 1,5.1 0.7,1.5 1.7,2.8 2.9,3.9 1.2,1.1 2.7,1.9 4.4,2.5 1.7,0.6 3.6,0.9 5.7,0.9 1.4,0 2.8,-0.2 4.1,-0.5 1.3,-0.3 2.6,-0.8 3.7,-1.5 1.1,-0.6 2.1,-1.4 3.1,-2.3 1,-1.2 1.8,-2.2 2.4,-3.3 z m -3.2,-2 c -1,0.8 -2.1,1.5 -3.4,2 -1.3,0.5 -2.8,0.7 -4.3,0.7 -2.4,0 -4.3,-0.5 -5.7,-1.6 -1.4,-1.1 -2.1,-2.5 -2.1,-4.3 0,-1.8 0.7,-3.3 2.2,-4.3 1.4,-1 3.6,-1.6 6.5,-1.8 l 10.1,-0.7 v 3.2 c 0,1.4 -0.3,2.6 -0.8,3.8 -0.8,1.2 -1.5,2.2 -2.5,3 z"
class="st1" />
<path
style="fill:#515151"
id="path19"
d="m 278.5,228.7 -13.7,-3.4 c -16.7,-4.2 -23.6,-9.7 -23.6,-18.9 0,-11.7 10.9,-19.8 26.7,-19.8 15.8,0 26.5,8 27.7,21 h 17.9 c -0.7,-21.6 -19,-36.7 -45.2,-36.7 -26.8,0 -45.7,15 -45.7,36.5 0,17.5 10.6,28.2 34.1,34 l 16.3,4 c 16.7,4.2 23.9,10.4 23.9,20.6 0,11.8 -11.9,20.4 -28.4,20.4 -17.2,0 -29.8,-8.6 -31.2,-21.7 h -18 c 1.3,22.8 20.2,37.3 47.9,37.3 29.7,0 48.4,-14.7 48.4,-38.3 -0.3,-18.4 -11,-28.7 -37.1,-35 z"
class="st1" />
<path
style="fill:#515151"
id="path21"
d="m 187.7,144.7 v -28.3 c 0,-2.1 -0.3,-4 -1,-5.6 -0.7,-1.6 -1.5,-3.1 -2.7,-4.3 -1.2,-1.2 -2.6,-2.1 -4.3,-2.8 -1.7,-0.7 -3.5,-1 -5.6,-1 -1.5,0 -2.9,0.2 -4.2,0.6 -1.3,0.4 -2.6,0.9 -3.7,1.6 -1.1,0.7 -2.1,1.6 -3,2.5 -0.9,0.9 -1.6,2.1 -2.1,3.4 h -0.2 c -0.8,-2.6 -2.3,-4.6 -4.3,-6 -2,-1.4 -4.5,-2.1 -7.4,-2.1 -1.3,0 -2.6,0.2 -3.9,0.5 -1.2,0.3 -2.3,0.8 -3.4,1.5 -1,0.7 -1.9,1.4 -2.7,2.4 -0.8,0.9 -1.4,2 -1.9,3.1 h -0.2 v -7 h -7.9 v 41.6 h 7.8 v -25.5 c 0,-1.3 0.7,-2.6 1.1,-3.7 0.4,-1.1 1,-2.1 1.8,-3 0.8,-0.8 1.7,-1.5 2.8,-2 1.1,-0.5 2.3,-0.7 3.5,-0.7 1.2,0 2.3,0.2 3.3,0.6 1,0.4 1.8,0.9 2.5,1.6 0.7,0.7 1.2,1.5 1.6,2.5 0.4,1 0.6,2.1 0.6,3.2 v 27 h 8.2 V 119 c 0,-1.3 0.2,-2.6 0.7,-3.7 0.4,-1.1 1,-2.1 1.8,-2.9 0.8,-0.8 1.7,-1.4 2.7,-1.9 1.1,-0.4 2.2,-0.7 3.5,-0.7 2.6,0 4.6,0.8 6,2.2 1.4,1.5 2.1,3.6 2.1,6.3 v 26.3 z"
class="st1" />
<path
style="fill:#515151"
id="path23"
d="m 147.4,170.9 c -36.3,0 -59.1,25.3 -59.1,65.6 0,40.3 22.8,65.6 59.1,65.6 36.3,0 59.1,-25.3 59.1,-65.6 -0.1,-40.3 -22.8,-65.6 -59.1,-65.6 z m 0,115 c -24.9,0 -40.5,-19.1 -40.5,-49.4 0,-30.4 15.6,-49.5 40.5,-49.5 24.8,0 40.5,19.1 40.5,49.5 -0.1,30.3 -15.7,49.4 -40.5,49.4 z"
class="st1" />
<path
style="fill:#515151"
id="path25"
d="m 252.1,113.5 c 1,-1.2 2.1,-2.2 3.5,-2.9 1.4,-0.7 2.9,-1 4.6,-1 1.4,0 2.7,0.2 3.8,0.6 1.1,0.4 2.1,0.9 3,1.6 0.8,0.7 1.5,1.5 2,2.5 0.5,1 0.9,2 1.1,3.1 h 7.9 c -0.2,-2 -0.7,-3.9 -1.6,-5.7 -0.9,-1.8 -2.1,-3.3 -3.6,-4.7 -1.5,-1.3 -3.4,-2.4 -5.5,-3.2 -2.1,-0.8 -4.5,-1.2 -7.2,-1.2 -2.9,0 -5.6,0.5 -8,1.5 -2.4,1 -4.4,2.4 -6.1,4.3 -1.7,1.9 -3,4.1 -3.9,6.7 -0.9,2.6 -1.4,5.5 -1.4,8.8 0,3.3 0.5,6.3 1.4,8.9 0.9,2.6 2.3,4.9 4,6.7 1.7,1.8 3.8,3.2 6.2,4.2 2.4,1 5.1,1.5 8,1.5 2.5,0 4.8,-0.4 6.9,-1 2.1,-0.6 3.9,-1.7 5.5,-2.9 1.5,-1.3 2.8,-2.8 3.8,-4.6 1,-1.8 1.6,-3.8 1.8,-5.9 h -7.9 c -0.5,2.5 -1.6,4.3 -3.3,5.6 -1.7,1.3 -3.9,1.9 -6.6,1.9 -1.7,0 -3.2,-0.3 -4.6,-1 -1.4,-0.6 -2.6,-1.6 -3.5,-2.8 -1,-1.2 -1.7,-2.7 -2.3,-4.5 -0.5,-1.8 -0.8,-3.8 -0.8,-6 0,-2.2 0.3,-4.1 0.8,-5.9 0.3,-1.9 1,-3.4 2,-4.6 z"
class="st1" />
</g>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
id="Capa_1"
x="0px"
y="0px"
viewBox="0 0 407 407"
style="enable-background:new 0 0 407 407;"
xml:space="preserve"><metadata
id="metadata36"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs34"><linearGradient
xlink:href="#SVGID_1_"
id="linearGradient46"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
x1="203.7169"
y1="7.7039"
x2="203.7169"
y2="402.0255" /><linearGradient
xlink:href="#SVGID_1_"
id="linearGradient48"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
x1="203.7169"
y1="7.7039"
x2="203.7169"
y2="402.0255" />
<linearGradient
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
y2="402.02551"
x2="203.7169"
y1="7.7038999"
x1="203.7169"
gradientUnits="userSpaceOnUse"
id="linearGradient120"><stop
id="stop6-9"
style="stop-color:#F2F2F2"
offset="0" /><stop
id="stop8-1"
style="stop-color:#F7F7F7"
offset="0.5963" /><stop
id="stop10-7"
style="stop-color:#FEFEFE"
offset="1" /></linearGradient><filter
style="color-interpolation-filters:sRGB"
id="filter1002"
x="-0.013201674"
width="1.0264033"
y="-0.013198327"
height="1.0263967"><feGaussianBlur
stdDeviation="2.168925"
id="feGaussianBlur1004" /></filter></defs>
<style
type="text/css"
id="style2">
.st0{fill:url(#SVGID_1_);}
.st1{fill:#515151;}
</style>
<g
transform="matrix(1,0,0,0.98477354,0,6.0829719)"
id="g15-0"
style="fill:#4d4d4d;filter:url(#filter1002)"><linearGradient
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
y2="402.02551"
x2="203.7169"
y1="7.7038999"
x1="203.7169"
gradientUnits="userSpaceOnUse"
id="linearGradient91"><stop
id="stop85"
style="stop-color:#F2F2F2"
offset="0" /><stop
id="stop87"
style="stop-color:#F7F7F7"
offset="0.5963" /><stop
id="stop89"
style="stop-color:#FEFEFE"
offset="1" /></linearGradient><path
style="fill:#4d4d4d"
id="path13-7"
d="M 400.9,202.3 C 400.9,92.3 313.8,5.1 203.7,5.1 93.7,5.2 6.6,92.3 6.6,202.3 c 0,110 87.1,197.2 197.2,197.2 110.1,0 197.1,-87.1 197.1,-197.2 z"
class="st0" /><path
style="fill:#4d4d4d"
class="st0"
d="M 400.9,202.3 C 400.9,92.3 313.8,5.1 203.7,5.1 93.7,5.2 6.6,92.3 6.6,202.3 c 0,110 87.1,197.2 197.2,197.2 110.1,0 197.1,-87.1 197.1,-197.2 z"
id="path40-7" /></g><g
id="g15">
<linearGradient
gradientTransform="matrix(1,0,0,-1,0,407.2074)"
y2="402.02551"
x2="203.7169"
y1="7.7038999"
x1="203.7169"
gradientUnits="userSpaceOnUse"
id="SVGID_1_">
<stop
id="stop6"
style="stop-color:#F2F2F2"
offset="0" />
<stop
id="stop8"
style="stop-color:#F7F7F7"
offset="0.5963" />
<stop
id="stop10"
style="stop-color:#FEFEFE"
offset="1" />
</linearGradient>
<path
style="fill:url(#linearGradient46)"
id="path13"
d="M 400.9,202.3 C 400.9,92.3 313.8,5.1 203.7,5.1 93.7,5.2 6.6,92.3 6.6,202.3 c 0,110 87.1,197.2 197.2,197.2 110.1,0 197.1,-87.1 197.1,-197.2 z"
class="st0" />
<path
style="fill:url(#linearGradient48)"
class="st0"
d="M 400.9,202.3 C 400.9,92.3 313.8,5.1 203.7,5.1 93.7,5.2 6.6,92.3 6.6,202.3 c 0,110 87.1,197.2 197.2,197.2 110.1,0 197.1,-87.1 197.1,-197.2 z"
id="path40" /></g><g
id="g27">
<path
style="fill:#515151"
id="path17"
d="m 223.7,137.8 h 0.2 v 6.9 h 7.9 v -28.5 c 0,-2.1 -0.4,-3.9 -1.2,-5.6 -0.8,-1.7 -1.9,-3.1 -3.4,-4.3 -1.5,-1.2 -3.2,-2.1 -5.3,-2.7 -2.1,-0.6 -4.3,-1 -6.9,-1 -2.3,0 -4.5,0.3 -6.5,1 -2,0.6 -3.7,1.5 -5.2,2.7 -1.5,1.2 -2.6,2.5 -3.5,4.1 -0.9,1.6 -1.3,3.3 -1.4,5.1 h 7.8 c 0.2,-0.9 0.5,-1.7 1,-2.4 0.5,-0.7 1.1,-1.4 1.8,-1.9 0.7,-0.5 1.6,-0.9 2.6,-1.2 1,-0.3 2,-0.4 3.1,-0.4 2.8,0 4.9,0.6 6.5,1.9 1.5,1.2 2.3,3.1 2.3,5.5 v 3.2 l -11.2,0.6 c -5.2,0.3 -9.1,1.5 -11.8,3.6 -2.7,2.1 -4.1,4.9 -4.1,8.6 0,1.9 0.3,3.6 1,5.1 0.7,1.5 1.7,2.8 2.9,3.9 1.2,1.1 2.7,1.9 4.4,2.5 1.7,0.6 3.6,0.9 5.7,0.9 1.4,0 2.8,-0.2 4.1,-0.5 1.3,-0.3 2.6,-0.8 3.7,-1.5 1.1,-0.6 2.1,-1.4 3.1,-2.3 1,-1.2 1.8,-2.2 2.4,-3.3 z m -3.2,-2 c -1,0.8 -2.1,1.5 -3.4,2 -1.3,0.5 -2.8,0.7 -4.3,0.7 -2.4,0 -4.3,-0.5 -5.7,-1.6 -1.4,-1.1 -2.1,-2.5 -2.1,-4.3 0,-1.8 0.7,-3.3 2.2,-4.3 1.4,-1 3.6,-1.6 6.5,-1.8 l 10.1,-0.7 v 3.2 c 0,1.4 -0.3,2.6 -0.8,3.8 -0.8,1.2 -1.5,2.2 -2.5,3 z"
class="st1" />
<path
style="fill:#515151"
id="path19"
d="m 278.5,228.7 -13.7,-3.4 c -16.7,-4.2 -23.6,-9.7 -23.6,-18.9 0,-11.7 10.9,-19.8 26.7,-19.8 15.8,0 26.5,8 27.7,21 h 17.9 c -0.7,-21.6 -19,-36.7 -45.2,-36.7 -26.8,0 -45.7,15 -45.7,36.5 0,17.5 10.6,28.2 34.1,34 l 16.3,4 c 16.7,4.2 23.9,10.4 23.9,20.6 0,11.8 -11.9,20.4 -28.4,20.4 -17.2,0 -29.8,-8.6 -31.2,-21.7 h -18 c 1.3,22.8 20.2,37.3 47.9,37.3 29.7,0 48.4,-14.7 48.4,-38.3 -0.3,-18.4 -11,-28.7 -37.1,-35 z"
class="st1" />
<path
style="fill:#515151"
id="path21"
d="m 187.7,144.7 v -28.3 c 0,-2.1 -0.3,-4 -1,-5.6 -0.7,-1.6 -1.5,-3.1 -2.7,-4.3 -1.2,-1.2 -2.6,-2.1 -4.3,-2.8 -1.7,-0.7 -3.5,-1 -5.6,-1 -1.5,0 -2.9,0.2 -4.2,0.6 -1.3,0.4 -2.6,0.9 -3.7,1.6 -1.1,0.7 -2.1,1.6 -3,2.5 -0.9,0.9 -1.6,2.1 -2.1,3.4 h -0.2 c -0.8,-2.6 -2.3,-4.6 -4.3,-6 -2,-1.4 -4.5,-2.1 -7.4,-2.1 -1.3,0 -2.6,0.2 -3.9,0.5 -1.2,0.3 -2.3,0.8 -3.4,1.5 -1,0.7 -1.9,1.4 -2.7,2.4 -0.8,0.9 -1.4,2 -1.9,3.1 h -0.2 v -7 h -7.9 v 41.6 h 7.8 v -25.5 c 0,-1.3 0.7,-2.6 1.1,-3.7 0.4,-1.1 1,-2.1 1.8,-3 0.8,-0.8 1.7,-1.5 2.8,-2 1.1,-0.5 2.3,-0.7 3.5,-0.7 1.2,0 2.3,0.2 3.3,0.6 1,0.4 1.8,0.9 2.5,1.6 0.7,0.7 1.2,1.5 1.6,2.5 0.4,1 0.6,2.1 0.6,3.2 v 27 h 8.2 V 119 c 0,-1.3 0.2,-2.6 0.7,-3.7 0.4,-1.1 1,-2.1 1.8,-2.9 0.8,-0.8 1.7,-1.4 2.7,-1.9 1.1,-0.4 2.2,-0.7 3.5,-0.7 2.6,0 4.6,0.8 6,2.2 1.4,1.5 2.1,3.6 2.1,6.3 v 26.3 z"
class="st1" />
<path
style="fill:#515151"
id="path23"
d="m 147.4,170.9 c -36.3,0 -59.1,25.3 -59.1,65.6 0,40.3 22.8,65.6 59.1,65.6 36.3,0 59.1,-25.3 59.1,-65.6 -0.1,-40.3 -22.8,-65.6 -59.1,-65.6 z m 0,115 c -24.9,0 -40.5,-19.1 -40.5,-49.4 0,-30.4 15.6,-49.5 40.5,-49.5 24.8,0 40.5,19.1 40.5,49.5 -0.1,30.3 -15.7,49.4 -40.5,49.4 z"
class="st1" />
<path
style="fill:#515151"
id="path25"
d="m 252.1,113.5 c 1,-1.2 2.1,-2.2 3.5,-2.9 1.4,-0.7 2.9,-1 4.6,-1 1.4,0 2.7,0.2 3.8,0.6 1.1,0.4 2.1,0.9 3,1.6 0.8,0.7 1.5,1.5 2,2.5 0.5,1 0.9,2 1.1,3.1 h 7.9 c -0.2,-2 -0.7,-3.9 -1.6,-5.7 -0.9,-1.8 -2.1,-3.3 -3.6,-4.7 -1.5,-1.3 -3.4,-2.4 -5.5,-3.2 -2.1,-0.8 -4.5,-1.2 -7.2,-1.2 -2.9,0 -5.6,0.5 -8,1.5 -2.4,1 -4.4,2.4 -6.1,4.3 -1.7,1.9 -3,4.1 -3.9,6.7 -0.9,2.6 -1.4,5.5 -1.4,8.8 0,3.3 0.5,6.3 1.4,8.9 0.9,2.6 2.3,4.9 4,6.7 1.7,1.8 3.8,3.2 6.2,4.2 2.4,1 5.1,1.5 8,1.5 2.5,0 4.8,-0.4 6.9,-1 2.1,-0.6 3.9,-1.7 5.5,-2.9 1.5,-1.3 2.8,-2.8 3.8,-4.6 1,-1.8 1.6,-3.8 1.8,-5.9 h -7.9 c -0.5,2.5 -1.6,4.3 -3.3,5.6 -1.7,1.3 -3.9,1.9 -6.6,1.9 -1.7,0 -3.2,-0.3 -4.6,-1 -1.4,-0.6 -2.6,-1.6 -3.5,-2.8 -1,-1.2 -1.7,-2.7 -2.3,-4.5 -0.5,-1.8 -0.8,-3.8 -0.8,-6 0,-2.2 0.3,-4.1 0.8,-5.9 0.3,-1.9 1,-3.4 2,-4.6 z"
class="st1" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -1,54 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 429 117.3" enable-background="new 0 0 429 117.3" xml:space="preserve">
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="58.666" y1="117.332" x2="58.666" y2="-9.094947e-13">
<stop offset="0" style="stop-color:#0882C8"/>
<stop offset="1" style="stop-color:#26B6DB"/>
</linearGradient>
<circle fill="url(#SVGID_1_)" cx="58.7" cy="58.7" r="58.7"/>
<g>
<circle fill="none" stroke="#FFFFFF" stroke-width="6" stroke-miterlimit="10" cx="58.7" cy="58.5" r="43.7"/>
<g>
<path fill="#FFFFFF" d="M94.7,47.8c4.7,1.6,9.8-0.9,11.4-5.6c1.6-4.7-0.9-9.8-5.6-11.4c-4.7-1.6-9.8,0.9-11.4,5.6
C87.5,41.1,90,46.2,94.7,47.8z"/>
<line fill="none" stroke="#FFFFFF" stroke-width="6" stroke-miterlimit="10" x1="97.6" y1="39.4" x2="67.5" y2="64.4"/>
</g>
<g>
<path fill="#FFFFFF" d="M77.6,91c-0.4,4.9,3.2,9.3,8.2,9.8c5,0.4,9.3-3.2,9.8-8.2c0.4-4.9-3.2-9.3-8.2-9.8
C82.4,82.4,78,86,77.6,91z"/>
<line fill="none" stroke="#FFFFFF" stroke-width="6" stroke-miterlimit="10" x1="86.5" y1="91.8" x2="67.5" y2="64.4"/>
</g>
<path fill="#FFFFFF" d="M60,69.3c2.7,4.2,8.3,5.4,12.4,2.7c4.2-2.7,5.4-8.3,2.7-12.4c-2.7-4.2-8.3-5.4-12.4-2.7
C58.5,59.5,57.3,65.1,60,69.3z"/>
<g>
<path fill="#FFFFFF" d="M21.2,61.4c-4.3-2.5-9.8-1.1-12.3,3.1c-2.5,4.3-1.1,9.8,3.1,12.3c4.3,2.5,9.8,1.1,12.3-3.1
C26.8,69.5,25.4,64,21.2,61.4z"/>
<line fill="none" stroke="#FFFFFF" stroke-width="6" stroke-miterlimit="10" x1="16.6" y1="69.1" x2="67.5" y2="64.4"/>
</g>
</g>
</g>
<g>
<path fill="#0891D1" d="M163.8,50.2c-0.6-0.7-6.3-4.1-11.4-4.1c-3.4,0-5.2,1.2-5.2,3.5c0,2.9,3.2,3.7,8.9,5.2
c8.2,2.2,13.3,5,13.3,12.9c0,9.7-7.8,13-16,13c-6.2,0-13.1-2-18.2-5.3l4.3-8.6c0.8,0.8,7.5,5,14,5c3.5,0,5.2-1.1,5.2-3.2
c0-3.2-4.4-4-10.3-5.8c-7.9-2.4-11.5-5.3-11.5-11.8c0-9,7.2-13.9,15.7-13.9c6.1,0,11.6,2.5,15.4,4.7L163.8,50.2z"/>
<path fill="#0891D1" d="M175,85.1c1.7,0.5,3.3,0.8,4.4,0.8c2,0,3.3-1.5,4.2-5.5l-11.9-31.5h9.8l7.4,23.3l6.3-23.3h8.9l-12.1,36.6
c-1.7,5.3-6.2,8.7-11.8,8.8c-1.7,0-3.5-0.2-5.3-0.9V85.1z"/>
<path fill="#0891D1" d="M239.3,80.3h-9.6V62.6c0-4.1-1.7-5.9-4.3-5.9c-2.6,0-5.8,2.3-7,5.6v18.1h-9.6V48.8h8.6v5.3
c2.3-3.7,6.8-5.9,12.2-5.9c8.2,0,9.5,6.7,9.5,11.9V80.3z"/>
<path fill="#0891D1" d="M261.6,48.2c7.2,0,12.3,3.4,14.8,8.3l-9.4,2.8c-1.2-1.9-3.1-3-5.5-3c-4,0-7,3.2-7,8.2c0,5,3.1,8.3,7,8.3
c2.4,0,4.6-1.3,5.5-3.1l9.4,2.9c-2.3,4.9-7.6,8.3-14.8,8.3c-10.6,0-16.9-7.7-16.9-16.4S250.9,48.2,261.6,48.2z"/>
<path fill="#0891D1" d="M302.1,78.7c-2.6,1.1-6.2,2.3-9.7,2.3c-4.7,0-8.8-2.3-8.8-8.4V56.1h-4v-7.3h4v-10h9.6v10h6.4v7.3h-6.4v13.1
c0,2.1,1.2,2.9,2.8,2.9c1.4,0,3-0.6,4.2-1.1L302.1,78.7z"/>
<path fill="#0891D1" d="M337.2,80.3h-9.6V62.6c0-4.1-1.8-5.9-4.6-5.9c-2.3,0-5.5,2.2-6.7,5.6v18.1h-9.6V36.5h9.6v17.6
c2.3-3.7,6.3-5.9,10.9-5.9c8.5,0,9.9,6.5,9.9,11.9V80.3z"/>
<path fill="#0891D1" d="M343.4,45.2v-8.7h9.6v8.7H343.4z M343.4,80.3V48.8h9.6v31.5H343.4z"/>
<path fill="#0891D1" d="M389.9,80.3h-9.6V62.6c0-4.1-1.7-5.9-4.3-5.9c-2.6,0-5.8,2.3-7,5.6v18.1h-9.6V48.8h8.6v5.3
c2.3-3.7,6.8-5.9,12.2-5.9c8.2,0,9.5,6.7,9.5,11.9V80.3z"/>
<path fill="#0891D1" d="M395.5,64.6c0-9.2,6-16.3,14.6-16.3c4.7,0,8.4,2.2,10.6,5.8v-5.2h8.3v29.3c0,9.6-7.5,15.5-18.2,15.5
c-6.8,0-11.5-2.3-15-6.3l5.1-5.2c2.3,2.6,6,4.3,9.9,4.3c4.6,0,8.6-2.4,8.6-8.3v-3.1c-1.9,3.5-5.9,5.3-10,5.3
C401.1,80.5,395.5,73.3,395.5,64.6z M419.4,68.5v-6.6c-1.3-3.3-4.2-5.5-7.1-5.5c-4.1,0-7,4-7,8.4c0,4.6,3.2,8,7.5,8
C415.7,72.8,418.1,71,419.4,68.5z"/>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 429 117.3" enable-background="new 0 0 429 117.3" xml:space="preserve">
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="58.666" y1="117.332" x2="58.666" y2="-9.094947e-13">
<stop offset="0" style="stop-color:#0882C8"/>
<stop offset="1" style="stop-color:#26B6DB"/>
</linearGradient>
<circle fill="url(#SVGID_1_)" cx="58.7" cy="58.7" r="58.7"/>
<g>
<circle fill="none" stroke="#FFFFFF" stroke-width="6" stroke-miterlimit="10" cx="58.7" cy="58.5" r="43.7"/>
<g>
<path fill="#FFFFFF" d="M94.7,47.8c4.7,1.6,9.8-0.9,11.4-5.6c1.6-4.7-0.9-9.8-5.6-11.4c-4.7-1.6-9.8,0.9-11.4,5.6
C87.5,41.1,90,46.2,94.7,47.8z"/>
<line fill="none" stroke="#FFFFFF" stroke-width="6" stroke-miterlimit="10" x1="97.6" y1="39.4" x2="67.5" y2="64.4"/>
</g>
<g>
<path fill="#FFFFFF" d="M77.6,91c-0.4,4.9,3.2,9.3,8.2,9.8c5,0.4,9.3-3.2,9.8-8.2c0.4-4.9-3.2-9.3-8.2-9.8
C82.4,82.4,78,86,77.6,91z"/>
<line fill="none" stroke="#FFFFFF" stroke-width="6" stroke-miterlimit="10" x1="86.5" y1="91.8" x2="67.5" y2="64.4"/>
</g>
<path fill="#FFFFFF" d="M60,69.3c2.7,4.2,8.3,5.4,12.4,2.7c4.2-2.7,5.4-8.3,2.7-12.4c-2.7-4.2-8.3-5.4-12.4-2.7
C58.5,59.5,57.3,65.1,60,69.3z"/>
<g>
<path fill="#FFFFFF" d="M21.2,61.4c-4.3-2.5-9.8-1.1-12.3,3.1c-2.5,4.3-1.1,9.8,3.1,12.3c4.3,2.5,9.8,1.1,12.3-3.1
C26.8,69.5,25.4,64,21.2,61.4z"/>
<line fill="none" stroke="#FFFFFF" stroke-width="6" stroke-miterlimit="10" x1="16.6" y1="69.1" x2="67.5" y2="64.4"/>
</g>
</g>
</g>
<g>
<path fill="#0891D1" d="M163.8,50.2c-0.6-0.7-6.3-4.1-11.4-4.1c-3.4,0-5.2,1.2-5.2,3.5c0,2.9,3.2,3.7,8.9,5.2
c8.2,2.2,13.3,5,13.3,12.9c0,9.7-7.8,13-16,13c-6.2,0-13.1-2-18.2-5.3l4.3-8.6c0.8,0.8,7.5,5,14,5c3.5,0,5.2-1.1,5.2-3.2
c0-3.2-4.4-4-10.3-5.8c-7.9-2.4-11.5-5.3-11.5-11.8c0-9,7.2-13.9,15.7-13.9c6.1,0,11.6,2.5,15.4,4.7L163.8,50.2z"/>
<path fill="#0891D1" d="M175,85.1c1.7,0.5,3.3,0.8,4.4,0.8c2,0,3.3-1.5,4.2-5.5l-11.9-31.5h9.8l7.4,23.3l6.3-23.3h8.9l-12.1,36.6
c-1.7,5.3-6.2,8.7-11.8,8.8c-1.7,0-3.5-0.2-5.3-0.9V85.1z"/>
<path fill="#0891D1" d="M239.3,80.3h-9.6V62.6c0-4.1-1.7-5.9-4.3-5.9c-2.6,0-5.8,2.3-7,5.6v18.1h-9.6V48.8h8.6v5.3
c2.3-3.7,6.8-5.9,12.2-5.9c8.2,0,9.5,6.7,9.5,11.9V80.3z"/>
<path fill="#0891D1" d="M261.6,48.2c7.2,0,12.3,3.4,14.8,8.3l-9.4,2.8c-1.2-1.9-3.1-3-5.5-3c-4,0-7,3.2-7,8.2c0,5,3.1,8.3,7,8.3
c2.4,0,4.6-1.3,5.5-3.1l9.4,2.9c-2.3,4.9-7.6,8.3-14.8,8.3c-10.6,0-16.9-7.7-16.9-16.4S250.9,48.2,261.6,48.2z"/>
<path fill="#0891D1" d="M302.1,78.7c-2.6,1.1-6.2,2.3-9.7,2.3c-4.7,0-8.8-2.3-8.8-8.4V56.1h-4v-7.3h4v-10h9.6v10h6.4v7.3h-6.4v13.1
c0,2.1,1.2,2.9,2.8,2.9c1.4,0,3-0.6,4.2-1.1L302.1,78.7z"/>
<path fill="#0891D1" d="M337.2,80.3h-9.6V62.6c0-4.1-1.8-5.9-4.6-5.9c-2.3,0-5.5,2.2-6.7,5.6v18.1h-9.6V36.5h9.6v17.6
c2.3-3.7,6.3-5.9,10.9-5.9c8.5,0,9.9,6.5,9.9,11.9V80.3z"/>
<path fill="#0891D1" d="M343.4,45.2v-8.7h9.6v8.7H343.4z M343.4,80.3V48.8h9.6v31.5H343.4z"/>
<path fill="#0891D1" d="M389.9,80.3h-9.6V62.6c0-4.1-1.7-5.9-4.3-5.9c-2.6,0-5.8,2.3-7,5.6v18.1h-9.6V48.8h8.6v5.3
c2.3-3.7,6.8-5.9,12.2-5.9c8.2,0,9.5,6.7,9.5,11.9V80.3z"/>
<path fill="#0891D1" d="M395.5,64.6c0-9.2,6-16.3,14.6-16.3c4.7,0,8.4,2.2,10.6,5.8v-5.2h8.3v29.3c0,9.6-7.5,15.5-18.2,15.5
c-6.8,0-11.5-2.3-15-6.3l5.1-5.2c2.3,2.6,6,4.3,9.9,4.3c4.6,0,8.6-2.4,8.6-8.3v-3.1c-1.9,3.5-5.9,5.3-10,5.3
C401.1,80.5,395.5,73.3,395.5,64.6z M419.4,68.5v-6.6c-1.3-3.3-4.2-5.5-7.1-5.5c-4.1,0-7,4-7,8.4c0,4.6,3.2,8,7.5,8
C415.7,72.8,418.1,71,419.4,68.5z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -1,34 +1,34 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="robots" content="noindex">
<script>
if (document.URL.indexOf("ui") === -1) {
window.location.replace("ui")
}
</script>
<link rel="apple-touch-icon" sizes="180x180" href="/ui/img/icon/apple-touch-icon.png">
<link rel="manifest" href="/ui/site.webmanifest">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="/ui/favicon.svg" type="image/svg+xml">
<title>
CasaOS
</title>
<link href="/ui/js/0.js" rel="prefetch"><link href="/ui/js/1.js" rel="prefetch"><link href="/ui/js/2.js" rel="prefetch"><link href="/ui/js/3.js" rel="prefetch"><link href="/ui/js/4.js" rel="prefetch"><link href="/ui/js/5.js" rel="prefetch"><link href="/ui/js/6.js" rel="prefetch"><link href="/ui/js/7.js" rel="prefetch"><link href="/ui/js/app.js" rel="preload" as="script"><link href="/ui/js/chunk-vendors.js" rel="preload" as="script"></head>
<body>
<noscript>
<strong>We're sorry but CasaOS doesn't work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<script type="text/javascript" src="/ui/js/chunk-vendors.js"></script><script type="text/javascript" src="/ui/js/app.js"></script></body>
</html>
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="robots" content="noindex">
<script>
if (document.URL.indexOf("ui") === -1) {
window.location.replace("ui")
}
</script>
<link rel="apple-touch-icon" sizes="180x180" href="/ui/img/icon/apple-touch-icon.png">
<link rel="manifest" href="/ui/site.webmanifest">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="/ui/favicon.svg" type="image/svg+xml">
<title>
CasaOS
</title>
<link href="/ui/js/0.js" rel="prefetch"><link href="/ui/js/1.js" rel="prefetch"><link href="/ui/js/2.js" rel="prefetch"><link href="/ui/js/3.js" rel="prefetch"><link href="/ui/js/4.js" rel="prefetch"><link href="/ui/js/5.js" rel="prefetch"><link href="/ui/js/6.js" rel="prefetch"><link href="/ui/js/7.js" rel="prefetch"><link href="/ui/js/app.js" rel="preload" as="script"><link href="/ui/js/chunk-vendors.js" rel="preload" as="script"></head>
<body>
<noscript>
<strong>We're sorry but CasaOS doesn't work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<script type="text/javascript" src="/ui/js/chunk-vendors.js"></script><script type="text/javascript" src="/ui/js/app.js"></script></body>
</html>

View File

@ -168,7 +168,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/objectSpread2 */ \"./node_modules/@babel/runtime/helpers/esm/objectSpread2.js\");\n/* harmony import */ var vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vee-validate/dist/rules */ \"./node_modules/vee-validate/dist/rules.js\");\n/* harmony import */ var vee_validate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vee-validate */ \"./node_modules/vee-validate/dist/vee-validate.esm.js\");\n/* harmony import */ var is_valid_hostname__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! is-valid-hostname */ \"./node_modules/is-valid-hostname/index.js\");\n/* harmony import */ var is_valid_hostname__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(is_valid_hostname__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var uuid_validate__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! uuid-validate */ \"./node_modules/uuid-validate/index.js\");\n/* harmony import */ var uuid_validate__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(uuid_validate__WEBPACK_IMPORTED_MODULE_4__);\n\n\n\n\n\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"required\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"required\"]), {}, {\n message: \"This field is required\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"email\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"email\"]), {}, {\n message: \"This field must be a valid email\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"confirmed\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"confirmed\"]), {}, {\n message: \"This field confirmation does not match\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"length\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"length\"]), {}, {\n message: \"This field must have 2 options\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"min\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"min\"]), {}, {\n message: \"This field must have more than {length} characters\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])('rfc1123', {\n validate: function validate(value) {\n return is_valid_hostname__WEBPACK_IMPORTED_MODULE_3___default()(value);\n },\n message: 'You entered an invalid RFC1123 hostname'\n});\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])('uuid', {\n validate: function validate(value) {\n return uuid_validate__WEBPACK_IMPORTED_MODULE_4___default()(value);\n },\n message: 'You entered an invalid share ID'\n});\n\n//# sourceURL=webpack:///./src/plugins/vee-validate.js?");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var E_Company_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/objectSpread2 */ \"./node_modules/@babel/runtime/helpers/esm/objectSpread2.js\");\n/* harmony import */ var vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vee-validate/dist/rules */ \"./node_modules/vee-validate/dist/rules.js\");\n/* harmony import */ var vee_validate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vee-validate */ \"./node_modules/vee-validate/dist/vee-validate.esm.js\");\n/* harmony import */ var is_valid_hostname__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! is-valid-hostname */ \"./node_modules/is-valid-hostname/index.js\");\n/* harmony import */ var is_valid_hostname__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(is_valid_hostname__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var uuid_validate__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! uuid-validate */ \"./node_modules/uuid-validate/index.js\");\n/* harmony import */ var uuid_validate__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(uuid_validate__WEBPACK_IMPORTED_MODULE_4__);\n\n\n\n\n\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"required\", Object(E_Company_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(E_Company_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"required\"]), {}, {\n message: \"This field is required\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"email\", Object(E_Company_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(E_Company_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"email\"]), {}, {\n message: \"This field must be a valid email\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"confirmed\", Object(E_Company_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(E_Company_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"confirmed\"]), {}, {\n message: \"This field confirmation does not match\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"length\", Object(E_Company_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(E_Company_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"length\"]), {}, {\n message: \"This field must have 2 options\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"min\", Object(E_Company_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(E_Company_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"min\"]), {}, {\n message: \"This field must have more than {length} characters\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])('rfc1123', {\n validate: function validate(value) {\n return is_valid_hostname__WEBPACK_IMPORTED_MODULE_3___default()(value);\n },\n message: 'You entered an invalid RFC1123 hostname'\n});\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])('uuid', {\n validate: function validate(value) {\n return uuid_validate__WEBPACK_IMPORTED_MODULE_4___default()(value);\n },\n message: 'You entered an invalid share ID'\n});\n\n//# sourceURL=webpack:///./src/plugins/vee-validate.js?");
/***/ })

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -41,7 +41,7 @@ eval("/* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {/* globals
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("module.exports = __webpack_require__.p + \"img/default-avatar.ab3b9bda.svg\";\n\n//# sourceURL=webpack:///./src/assets/img/account/default-avatar.svg?");
eval("module.exports = __webpack_require__.p + \"img/default-avatar.d92cd43a.svg\";\n\n//# sourceURL=webpack:///./src/assets/img/account/default-avatar.svg?");
/***/ })

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
User-agent: *
User-agent: *
Disallow: /

View File

@ -1,14 +1,14 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/ui/img/icon/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/ui/img/icon/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

View File

@ -1,17 +1,17 @@
/*
* @Author: Jerryk jerry@icewhale.org
* @Date: 2022-02-18 10:20:10
* @LastEditors: Jerryk jerry@icewhale.org
* @LastEditTime: 2022-05-16 14:56:14
* @FilePath: \CasaOS-UI\public\static.go
* @Description:
*
* Copyright (c) 2022 by IceWhale, All Rights Reserved.
*/
package web
import "embed"
//go:embed index.html favicon.svg browserconfig.xml site.webmanifest robots.txt img js fonts *.worker.js
var Static embed.FS
/*
* @Author: Jerryk jerry@icewhale.org
* @Date: 2022-02-18 10:20:10
* @LastEditors: Jerryk jerry@icewhale.org
* @LastEditTime: 2022-05-16 14:56:14
* @FilePath: \CasaOS-UI\public\static.go
* @Description:
*
* Copyright (c) 2022 by IceWhale, All Rights Reserved.
*/
package web
import "embed"
//go:embed index.html favicon.svg browserconfig.xml site.webmanifest robots.txt img js fonts *.worker.js
var Static embed.FS