代码调整优化

This commit is contained in:
meilin.huang
2021-09-08 17:55:57 +08:00
parent 00f053573e
commit 318005f459
32 changed files with 209 additions and 355 deletions

40
go.mod
View File

@@ -1,6 +1,6 @@
module mayfly-go
go 1.16
go 1.17
require (
// jwt
@@ -10,18 +10,48 @@ require (
github.com/gorilla/websocket v1.4.2
//
github.com/mojocn/base64Captcha v1.3.4
github.com/onsi/ginkgo v1.16.4 // indirect
github.com/onsi/gomega v1.13.0 // indirect
github.com/pkg/sftp v1.13.1
//
github.com/robfig/cron/v3 v3.0.1
github.com/sirupsen/logrus v1.8.1
// jsonschemal校验
// jsonschemal校验
github.com/xeipuuv/gojsonschema v1.2.0
// ssh
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
// gorm
gorm.io/driver/mysql v1.0.5
gorm.io/gorm v1.21.11
)
require (
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.13.0 // indirect
github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/go-playground/validator/v10 v10.4.1 // indirect
github.com/go-sql-driver/mysql v1.5.0 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.2 // indirect
github.com/json-iterator/go v1.1.11 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/leodido/go-urn v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.13 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/onsi/ginkgo v1.16.4 // indirect
github.com/onsi/gomega v1.10.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
golang.org/x/image v0.0.0-20190802002840-cff245a6509b // indirect
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
golang.org/x/text v0.3.5 // indirect
google.golang.org/protobuf v1.26.0 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

40
go.sum
View File

@@ -50,18 +50,27 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mojocn/base64Captcha v1.3.4 h1:9+MZzjNSfBHniYOIpoP4xyDDPCXy14JIjsEFf89PlNw=
github.com/mojocn/base64Captcha v1.3.4/go.mod h1:wAQCKEc5bDujxKRmbT6/vTnTt5CjStQ8bRfPWUuz/iY=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
@@ -69,13 +78,11 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs=
@@ -110,8 +117,9 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 h1:TbGuee8sSq15Iguxu4deQ7+Bqq/d2rsQejGcEtADAMQ=
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -119,8 +127,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -136,7 +144,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -145,8 +153,8 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
@@ -164,8 +172,9 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
@@ -175,8 +184,9 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.0.5 h1:WAAmvLK2rG0tCOqrf5XcLi2QUwugd4rcVJ/W3aoon9o=
gorm.io/driver/mysql v1.0.5/go.mod h1:N1OIhHAIhx5SunkMGqWbGFVeh4yTNWKmMo1GOAsohLI=
gorm.io/gorm v1.21.3/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=

View File

@@ -3,7 +3,7 @@ import Axios from 'axios';
import { ResultEnum } from './enums'
import Api from './Api';
import config from './config';
import { getSession, removeSession } from './utils/storage';
import { getSession } from './utils/storage';
import { templateResolve } from './utils/string';
import { ElMessage } from 'element-plus';

View File

@@ -1,6 +1,6 @@
<template>
<div>
<el-dialog :title="title" v-model="visible" :show-close="false" :before-close="cancel" width="35%">
<el-dialog :title="title" v-model="dialogVisible" :show-close="false" :before-close="cancel" width="35%">
<el-form :model="form" ref="dbForm" :rules="rules" label-width="85px" size="small">
<el-form-item prop="projectId" label="项目:" required>
<el-select style="width: 100%" v-model="form.projectId" placeholder="请选择项目" @change="changeProject" filterable>
@@ -79,7 +79,7 @@ export default defineComponent({
setup(props: any, { emit }) {
const dbForm: any = ref(null);
const state = reactive({
visible: false,
dialogVisible: false,
projects: [],
envs: [],
form: {
@@ -161,8 +161,8 @@ export default defineComponent({
},
});
watch(props, async (newValue, oldValue) => {
state.visible = newValue.visible;
watch(props, async (newValue) => {
state.dialogVisible = newValue.visible;
state.projects = newValue.projects;
if (newValue.db) {
getEnvs(newValue.db.projectId);
@@ -198,7 +198,7 @@ export default defineComponent({
const btnOk = async () => {
dbForm.value.validate((valid: boolean) => {
if (valid) {
dbApi.saveDb.request(state.form).then((res: any) => {
dbApi.saveDb.request(state.form).then(() => {
ElMessage.success('保存成功');
emit('val-change', state.form);
state.btnLoading = true;

View File

@@ -1,6 +1,6 @@
<template>
<div class="file-manage">
<el-dialog :title="title" v-model="visible" :show-close="true" :before-close="handleClose" width="800px">
<el-dialog :title="title" v-model="dialogVisible" :show-close="true" :before-close="handleClose" width="800px">
<div class="toolbar">
<div style="float: right">
<el-button v-auth="'machine:file:add'" type="primary" @click="add" icon="el-icon-plus" size="mini" plain>添加</el-button>
@@ -51,7 +51,7 @@
<el-dialog :title="tree.title" v-model="tree.visible" :close-on-click-modal="false" width="680px">
<div style="height: 45vh; overflow: auto">
<el-tree ref="fileTree" :load="loadNode" :props="props" lazy node-key="id" :expand-on-click-node="false">
<el-tree v-if="tree.visible" ref="fileTree" :load="loadNode" :props="props" lazy node-key="id" :expand-on-click-node="false">
<template #default="{ node, data }">
<span class="custom-tree-node">
<span v-if="data.type == 'd' && !node.expanded">
@@ -142,7 +142,7 @@
<template #footer>
<div class="dialog-footer">
<el-button v-auth="'machine:file:write'" type="primary" @click="updateContent" size="mini"> </el-button>
<el-button v-auth="'machine:file:write'" type="primary" @click="updateContent" size="mini"> </el-button>
<el-button @click="fileContent.contentVisible = false" size="mini"> </el-button>
</div>
</template>
@@ -175,7 +175,6 @@ export default defineComponent({
const addFile = machineApi.addConf;
const delFile = machineApi.delConf;
const updateFileContent = machineApi.updateFileContent;
const uploadFile = machineApi.uploadFile;
const files = machineApi.files;
const fileTree: any = ref(null);
const token = getSession('token');
@@ -202,7 +201,7 @@ export default defineComponent({
};
const state = reactive({
visible: false,
dialogVisible: false,
form: {
id: null,
type: null,
@@ -235,11 +234,11 @@ export default defineComponent({
},
});
watch(props, (newValue, oldValue) => {
watch(props, (newValue) => {
if (newValue.machineId) {
getFiles();
}
state.visible = newValue.visible;
state.dialogVisible = newValue.visible;
});
const getFiles = async () => {
@@ -284,7 +283,7 @@ export default defineComponent({
machineId: props.machineId,
id: row.id,
})
.then((res) => {
.then(() => {
state.fileTable.splice(idx, 1);
});
});
@@ -297,7 +296,6 @@ export default defineComponent({
if (row.type == 1) {
state.tree.folder = row;
state.tree.title = row.name;
const treeNode = (state.tree.node.childNodes = []);
loadNode(state.tree.node, state.tree.resolve);
state.tree.visible = true;
return;
@@ -428,7 +426,7 @@ export default defineComponent({
path: file,
machineId: props.machineId,
})
.then((res) => {
.then(() => {
ElMessage.success('删除成功');
fileTree.value.remove(node);
});
@@ -448,7 +446,7 @@ export default defineComponent({
a.click();
};
const getUploadFile = (data: any) => {
const getUploadFile = () => {
return `${config.baseApiUrl}/machines/${props.machineId}/files/${state.tree.folder.id}/upload?token=${token}`;
};

View File

@@ -1,6 +1,6 @@
<template>
<div>
<el-dialog :title="title" v-model="visible" :show-close="false" :before-close="cancel" width="35%">
<el-dialog :title="title" v-model="dialogVisible" :show-close="false" :before-close="cancel" width="35%">
<el-form :model="form" ref="machineForm" :rules="rules" label-width="85px" size="small">
<!-- <el-form-item prop="projectId" label="项目:" required>
<el-select style="width: 100%" v-model="form.projectId" placeholder="请选择项目" @change="changeProject" filterable>
@@ -47,9 +47,8 @@
</template>
<script lang="ts">
import { toRefs, reactive, watch, onMounted, defineComponent, ref } from 'vue';
import { toRefs, reactive, watch, defineComponent, ref } from 'vue';
import { machineApi } from './api';
import { projectApi } from '../project/api.ts';
import { ElMessage } from 'element-plus';
export default defineComponent({
@@ -68,7 +67,7 @@ export default defineComponent({
setup(props: any, { emit }) {
const machineForm: any = ref(null);
const state = reactive({
visible: false,
dialogVisible: false,
form: {
id: null,
name: null,
@@ -130,8 +129,8 @@ export default defineComponent({
},
});
watch(props, async (newValue, oldValue) => {
state.visible = newValue.visible;
watch(props, async (newValue) => {
state.dialogVisible = newValue.visible;
if (newValue.machine) {
state.form = { ...newValue.machine };
} else {
@@ -142,7 +141,7 @@ export default defineComponent({
const btnOk = async () => {
machineForm.value.validate((valid: boolean) => {
if (valid) {
machineApi.saveMachine.request(state.form).then((res: any) => {
machineApi.saveMachine.request(state.form).then(() => {
ElMessage.success('保存成功');
emit('val-change', state.form);
state.btnLoading = true;

View File

@@ -22,8 +22,15 @@
size="mini"
>删除</el-button
>
<el-button v-auth="'machine:file'" type="success" :disabled="currentId == null" @click="fileManage(currentData)" size="mini" plain
>文件管理</el-button
<el-button
v-auth="'machine:file'"
type="success"
icon="el-icon-files"
:disabled="currentId == null"
@click="fileManage(currentData)"
size="mini"
plain
>文件</el-button
>
</div>
@@ -47,24 +54,30 @@
{{ `${scope.row.ip}:${scope.row.port}` }}
</template>
</el-table-column>
<el-table-column prop="username" label="用户名" :min-width="45"></el-table-column>
<el-table-column prop="ip" label="hasCli" min-width="60">
<template #default="scope">
{{ `${scope.row.hasCli ? '是' : '否'}` }}
</template>
</el-table-column>
<el-table-column prop="username" label="用户名" :min-width="55"></el-table-column>
<el-table-column prop="createTime" label="创建时间" min-width="160">
<template #default="scope">
{{ $filters.dateFormat(scope.row.createTime) }}
</template>
</el-table-column>
<el-table-column prop="creator" label="创建者" min-width="50"></el-table-column>
<el-table-column prop="updateTime" label="更新时间" min-width="160">
<el-table-column prop="creator" label="创建者" min-width="55"></el-table-column>
<!-- <el-table-column prop="updateTime" label="更新时间" min-width="160">
<template #default="scope">
{{ $filters.dateFormat(scope.row.updateTime) }}
</template>
</el-table-column>
<el-table-column prop="modifier" label="修改者" :min-width="50"></el-table-column>
<el-table-column label="操作" min-width="200px">
<el-table-column prop="modifier" label="修改者" :min-width="55"></el-table-column> -->
<el-table-column label="操作" min-width="260">
<template #default="scope">
<!-- <el-button type="primary" @click="monitor(scope.row.id)" icom="el-icon-tickets" size="mini" plain>监控</el-button> -->
<el-button type="success" @click="serviceManager(scope.row)" size="mini" plain>脚本管理</el-button>
<el-button v-auth="'machine:terminal'" type="success" @click="showTerminal(scope.row)" size="mini" plain>终端</el-button>
<el-button type="success" @click="serviceManager(scope.row)" size="mini" plain>脚本</el-button>
<el-button v-auth="'machine:terminal'" type="primary" @click="showTerminal(scope.row)" size="mini" plain>终端</el-button>
<el-button :disabled="!scope.row.hasCli" type="danger" @click="closeCli(scope.row)" size="mini" plain>关闭连接</el-button>
</template>
</el-table-column>
</el-table>
@@ -192,6 +205,12 @@ export default defineComponent({
window.open(href, '_blank');
};
const closeCli = async (row: any) => {
await machineApi.closeCli.request({ id: row.id });
ElMessage.success('关闭成功');
search();
};
const openFormDialog = (redis: any) => {
let dialogTitle;
if (redis) {
@@ -252,6 +271,7 @@ export default defineComponent({
showTerminal,
openFormDialog,
deleteMachine,
closeCli,
serviceManager,
submitSuccess,
fileManage,

View File

@@ -2,7 +2,7 @@
<div class="mock-data-dialog">
<el-dialog
:title="title"
v-model="visible"
v-model="dialogVisible"
:close-on-click-modal="false"
:before-close="cancel"
:show-close="true"
@@ -87,7 +87,7 @@ export default defineComponent({
const mockDataForm: any = ref(null);
const state = reactive({
visible: false,
dialogVisible: false,
submitDisabled: false,
form: {
id: null,
@@ -101,14 +101,14 @@ export default defineComponent({
btnLoading: false,
});
watch(props, (newValue, oldValue) => {
watch(props, (newValue) => {
if (newValue.data) {
state.form = { ...newValue.data };
} else {
state.form = {} as any;
state.form.script = '';
}
state.visible = newValue.visible;
state.dialogVisible = newValue.visible;
});
const btnOk = () => {
@@ -120,13 +120,13 @@ export default defineComponent({
notEmpty(state.form.description, '描述不能为空');
notEmpty(state.form.script, '内容不能为空');
machineApi.saveScript.request(state.form).then(
(res: any) => {
() => {
ElMessage.success('保存成功');
emit('submitSuccess');
state.submitDisabled = false;
cancel();
},
(e: any) => {
() => {
state.submitDisabled = false;
}
);

View File

@@ -1,6 +1,6 @@
<template>
<div class="file-manage">
<el-dialog :title="title" v-model="visible" :destroy-on-close="true" :show-close="true" :before-close="handleClose" width="60%">
<el-dialog :title="title" v-model="dialogVisible" :destroy-on-close="true" :show-close="true" :before-close="handleClose" width="60%">
<div class="toolbar">
<div style="float: left">
<el-select v-model="type" @change="getScripts" size="mini" placeholder="请选择">
@@ -128,7 +128,7 @@ export default defineComponent({
setup(props: any, context) {
const paramsForm: any = ref(null);
const state = reactive({
visible: false,
dialogVisible: false,
type: 0,
currentId: null,
currentData: null,
@@ -155,11 +155,11 @@ export default defineComponent({
},
});
watch(props, (newValue, oldValue) => {
watch(props, (newValue) => {
if (props.machineId) {
getScripts();
}
state.visible = newValue.visible;
state.dialogVisible = newValue.visible;
});
const getScripts = async () => {
@@ -271,7 +271,7 @@ export default defineComponent({
machineId: props.machineId,
scriptId: row.id,
})
.then((res) => {
.then(() => {
getScripts();
});
// 删除配置文件

View File

@@ -4,11 +4,11 @@ export const machineApi = {
// 获取权限列表
list: Api.create("/machines", 'get'),
info: Api.create("/machines/{id}/sysinfo", 'get'),
top: Api.create("/machines/{id}/top", 'get'),
closeCli: Api.create("/machines/{id}/close-cli", 'delete'),
// 保存按钮
saveMachine: Api.create("/machines", 'post'),
// 删除机器
del: Api.create("/machines/delete/{id}", 'delete'),
del: Api.create("/machines/{id}", 'delete'),
scripts: Api.create("/machines/{machineId}/scripts", 'get'),
runScript: Api.create("/machines/{machineId}/scripts/{scriptId}/run", 'get'),
saveScript: Api.create("/machines/{machineId}/scripts", 'post'),

View File

@@ -120,7 +120,7 @@ export default defineComponent({
}
};
const changeRedis = (redisId: any) => {
const changeRedis = () => {
resetScanParam();
state.keys = [];
state.dbsize = 0;
@@ -201,7 +201,7 @@ export default defineComponent({
// this.valueDialog.value = {}
// }
const update = (key: string) => {};
// const update = (key: string) => {};
const del = (key: string) => {
ElMessageBox.confirm(`此操作将删除对应的key , 是否继续?`, '提示', {
@@ -217,12 +217,12 @@ export default defineComponent({
key,
id,
})
.then((res) => {
.then(() => {
ElMessage.success('删除成功!');
scan();
});
})
.catch((err) => {});
.catch(() => {});
};
const ttlConveter = (ttl: any) => {

View File

@@ -1,6 +1,6 @@
<template>
<div>
<el-dialog :title="title" v-model="visible" :show-close="true" width="35%" @close="close()">
<el-dialog :title="title" v-model="dialogVisible" :show-close="true" width="35%" @close="close()">
<el-collapse>
<el-collapse-item title="Server(Redis服务器的一般信息)" name="server">
<div class="row">
@@ -163,13 +163,13 @@ export default defineComponent({
},
setup(props: any, { emit }) {
const state = reactive({
visible: false,
dialogVisible: false,
});
watch(
() => props.visible,
(val) => {
state.visible = val;
state.dialogVisible = val;
}
);

View File

@@ -1,6 +1,6 @@
<template>
<div>
<el-dialog :title="title" v-model="visible" :show-close="false" :before-close="cancel" width="35%">
<el-dialog :title="title" v-model="dialogVisible" :show-close="false" :before-close="cancel" width="35%">
<el-form :model="form" ref="redisForm" :rules="rules" label-width="85px" size="small">
<el-form-item prop="projectId" label="项目:" required>
<el-select style="width: 100%" v-model="form.projectId" placeholder="请选择项目" @change="changeProject" filterable>
@@ -65,7 +65,7 @@ export default defineComponent({
setup(props: any, { emit }) {
const redisForm: any = ref(null);
const state = reactive({
visible: false,
dialogVisible: false,
projects: [],
envs: [],
form: {
@@ -111,8 +111,8 @@ export default defineComponent({
},
});
watch(props, async (newValue, oldValue) => {
state.visible = newValue.visible;
watch(props, async (newValue) => {
state.dialogVisible = newValue.visible;
state.projects = newValue.projects;
if (newValue.redis) {
getEnvs(newValue.redis.projectId);
@@ -148,7 +148,7 @@ export default defineComponent({
const btnOk = async () => {
redisForm.value.validate((valid: boolean) => {
if (valid) {
redisApi.saveRedis.request(state.form).then((res: any) => {
redisApi.saveRedis.request(state.form).then(() => {
ElMessage.success('保存成功');
emit('val-change', state.form);
state.btnLoading = true;

View File

@@ -1,12 +1,12 @@
<template>
<el-dialog :title="keyValue.key" v-model="visible" :before-close="cancel" :show-close="false" width="800px">
<el-dialog :title="keyValue.key" v-model="dialogVisible" :before-close="cancel" :show-close="false" width="800px">
<el-form>
<el-form-item>
<!-- <el-input v-model="keyValue.value" type="textarea" :autosize="{ minRows: 10, maxRows: 20 }" autocomplete="off"></el-input> -->
</el-form-item>
<vue3-json-editor v-model="keyValue.jsonValue" @json-change="valueChange" :show-btns="false" :expandedOnStart="true" />
<vue3-json-editor v-model="keyValue2.jsonValue" @json-change="valueChange" :show-btns="false" :expandedOnStart="true" />
</el-form>
<template #footer>
<div class="dialog-footer">
@@ -41,8 +41,8 @@ export default defineComponent({
},
setup(props: any, { emit }) {
const state = reactive({
visible: false,
keyValue: {} as any,
dialogVisible: false,
keyValue2: {} as any,
});
const cancel = () => {
emit('update:visible', false);
@@ -52,32 +52,32 @@ export default defineComponent({
watch(
() => props.visible,
(val) => {
state.visible = val;
state.dialogVisible = val;
}
);
watch(
() => props.keyValue,
(val) => {
state.keyValue = val;
state.keyValue2 = val;
if (typeof val.value == 'string') {
state.keyValue.jsonValue = JSON.parse(val.value)
state.keyValue2.jsonValue = JSON.parse(val.value)
} else {
state.keyValue.jsonValue = val.value;
state.keyValue2.jsonValue = val.value;
}
}
);
const saveValue = async () => {
isTrue(state.keyValue.type == 'string', '暂不支持除string外其他类型修改');
isTrue(state.keyValue2.type == 'string', '暂不支持除string外其他类型修改');
await redisApi.saveStringValue.request(state.keyValue);
await redisApi.saveStringValue.request(state.keyValue2);
ElMessage.success('保存成功');
cancel();
};
const valueChange = (val: any) => {
state.keyValue.value = JSON.stringify(val);
state.keyValue2.value = JSON.stringify(val);
};
return {

View File

@@ -1,6 +1,6 @@
<template>
<div class="account-dialog">
<el-dialog :title="title" v-model="visible" :show-close="false" width="35%">
<el-dialog :title="title" v-model="dialogVisible" :before-close="cancel" :show-close="false" width="35%">
<el-form :model="form" ref="accountForm" :rules="rules" label-width="85px" size="small">
<el-form-item prop="username" label="用户名:" required>
<el-input :disabled="edit" v-model.trim="form.username" placeholder="请输入账号用户名" auto-complete="off"></el-input>
@@ -26,7 +26,6 @@
<script lang="ts">
import { toRefs, reactive, watch, defineComponent, ref } from 'vue';
import { accountApi } from '../api';
import enums from '../enums';
import { ElMessage } from 'element-plus';
export default defineComponent({
@@ -45,6 +44,7 @@ export default defineComponent({
setup(props: any, { emit }) {
const accountForm: any = ref(null);
const state = reactive({
dialogVisible: false,
edit: false,
form: {
id: null,
@@ -71,12 +71,13 @@ export default defineComponent({
},
});
watch(props, (newValue, oldValue) => {
watch(props, (newValue) => {
if (newValue.account) {
state.form = { ...newValue.account };
} else {
state.form = {} as any;
}
state.dialogVisible = newValue.visible;
});
const btnOk = async () => {
@@ -84,7 +85,7 @@ export default defineComponent({
accountForm.value.validate((valid: boolean) => {
if (valid) {
p.request(state.form).then((res: any) => {
p.request(state.form).then(() => {
ElMessage.success('操作成功');
emit('val-change', state.form);
state.btnLoading = true;

View File

@@ -1,112 +0,0 @@
<template>
<div class="role-list">
<div class="toolbar">
<el-button
:disabled="currentId == null"
@click="deleteAccount()"
type="danger"
icon="el-icon-delete"
size="mini"
>删除</el-button>
<div style="float: right">
<el-select size="small" style=" width:120px" v-model="query.type" placeholder="状态">
<el-option label="全部" :value="null"></el-option>
<el-option
v-for="item in enums.logType"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
<el-input
placeholder="请输入账号名"
size="small"
style="width: 140px"
v-model="query.creator"
@clear="query.creator = null"
clearable
></el-input>
<el-button @click="search(true)" type="success" icon="el-icon-search" size="mini"></el-button>
</div>
</div>
<el-table :data="datas" border ref="table" show-overflow-tooltip>
<el-table-column min-width="600" prop="operation" label="操作记录" show-overflow-tooltip></el-table-column>
<el-table-column min-width="80" prop="type" label="操作类型" align="center">
<template slot-scope="scope">
<el-tag type="info" effect="plain">{{ enums.logType.getLabelByValue(scope.row.type) }}</el-tag>
</template>
</el-table-column>
<el-table-column min-width="115" prop="creator" label="操作账号"></el-table-column>
<el-table-column min-width="160" prop="createTime" label="操作时间"></el-table-column>
</el-table>
<el-pagination
@current-change="handlePageChange"
style="text-align: center;"
background
layout="prev, pager, next, total, jumper"
:total="total"
:current-page.sync="query.pageNum"
:page-size="query.pageSize"
/>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import HelpHint from '@/components/help-hint/HelpHint.vue'
import { logApi } from '../api'
import enums from '../enums'
@Component({
name: 'LogList',
components: {
HelpHint
}
})
export default class LogList extends Vue {
enums = enums
currentId = null
currentData = null
query = {
pageNum: 1,
pageSize: 10,
creator: null,
type: null
}
datas = []
total = null
mounted() {
this.search(false)
}
choose(item: any) {
if (!item) {
return
}
this.currentId = item.id
this.currentData = item
}
async search(resetPageNum: boolean) {
if (resetPageNum) {
this.query.pageNum = 1
}
let res = await logApi.list.request(this.query)
this.datas = res.list
this.total = res.total
}
handlePageChange(curPage: number) {
this.query.pageNum = curPage
this.search(false)
}
}
</script>
<style lang="less">
.el-tooltip__popper {
font-size: 14px;
max-width: 50%;
} /*设置显示隐藏部分内容按50%显示*/
</style>

View File

@@ -1 +0,0 @@
export { default } from './LogList.vue';

View File

@@ -1,21 +0,0 @@
import Permission from "../../common/Permission";
export const resourcePermission = {
resource: Permission.code("resource"),
save: Permission.code("resource:save"),
update: Permission.code("resource:update"),
del: Permission.code("resource:delete")
}
export const rolePermission = {
role: Permission.code("role"),
del: Permission.code("role:delete"),
saveResources: Permission.code("role:saveResources")
}
export const accountPermission = {
account: Permission.code("account"),
changeStatus: Permission.code("account:changeStatus"),
del: Permission.code("account:delete"),
saveRoles: Permission.code("account:saveRoles")
}

View File

@@ -1,6 +1,6 @@
<template>
<div class="menu-dialog">
<el-dialog :title="title" :destroy-on-close="true" v-model="visible" width="700px">
<el-dialog :title="title" :destroy-on-close="true" v-model="dialogVisible" width="700px">
<el-form :model="form" :inline="true" ref="menuForm" :rules="rules" label-width="95px" size="small">
<el-form-item prop="type" label="类型" required>
<el-select v-model="form.type" :disabled="typeDisabled" placeholder="请选择" width="50px">
@@ -121,7 +121,7 @@ export default defineComponent({
value: false,
},
],
visible: false,
dialogVisible: false,
//弹出框对象
dialogForm: {
title: '',
@@ -172,8 +172,8 @@ export default defineComponent({
},
});
watch(props, (newValue, oldValue) => {
state.visible = newValue.visible;
watch(props, (newValue) => {
state.dialogVisible = newValue.visible;
if (newValue.data) {
state.form = { ...newValue.data };
} else {
@@ -210,7 +210,7 @@ export default defineComponent({
submitForm.weight = parseInt(submitForm.weight as any);
menuForm.value.validate((valid: any) => {
if (valid) {
resourceApi.save.request(submitForm).then((res) => {
resourceApi.save.request(submitForm).then(() => {
emit('val-change', submitForm);
state.btnLoading = true;
ElMessage.success('保存成功');

View File

@@ -140,7 +140,6 @@
import { toRefs, reactive, onMounted, defineComponent } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import ResourceEdit from './ResourceEdit.vue';
import { resourcePermission } from '../permissions';
import enums from '../enums';
import { resourceApi } from '../api';
@@ -261,7 +260,7 @@ export default defineComponent({
state.dialogForm.title = '修改“' + data.name + '”菜单';
};
const valChange = (data: any) => {
const valChange = () => {
search();
state.dialogForm.visible = false;
};

View File

@@ -1,6 +1,6 @@
<template>
<div>
<el-dialog :title="'分配“' + role.name + '”菜单&权限'" v-model="visible" :before-close="cancel" :show-close="false" width="400px">
<el-dialog :title="'分配“' + role.name + '”菜单&权限'" v-model="dialogVisible" :before-close="cancel" :show-close="false" width="400px">
<el-tree
style="height: 50vh; overflow: auto"
ref="menuTree"
@@ -58,7 +58,7 @@ export default defineComponent({
const menuTree: any = ref(null);
const state = reactive({
visible: false,
dialogVisible: false,
defaultProps: {
children: 'children',
label: 'name',
@@ -67,8 +67,8 @@ export default defineComponent({
watch(
() => props.visible,
(newValue, oldValue) => {
state.visible = newValue;
(newValue) => {
state.dialogVisible = newValue;
}
);

View File

@@ -51,7 +51,7 @@ export default defineComponent({
btnLoading: false,
});
watch(props, (newValue, oldValue) => {
watch(props, (newValue) => {
state.visible = newValue.visible;
if (newValue.data) {
state.form = { ...newValue.data };

View File

@@ -1,6 +1,6 @@
<template>
<div>
<el-dialog @close="closeDialog" :title="title" :before-close="closeDialog" v-model="visible" width="400px">
<el-dialog @close="closeDialog" :title="title" :before-close="closeDialog" v-model="dialogVisible" width="400px">
<el-tree style="height: 50vh; overflow: auto" :data="resources" node-key="id" :props="defaultProps" :expand-on-click-node="false">
<template #default="{ node, data }">
<span class="custom-tree-node">
@@ -36,7 +36,7 @@ export default defineComponent({
setup(props: any, { emit }) {
const { proxy } = getCurrentInstance() as any;
const state = reactive({
visible: false,
dialogVisible: false,
defaultProps: {
children: 'children',
label: 'name',
@@ -45,8 +45,8 @@ export default defineComponent({
watch(
() => props.visible,
(newValue, oldValue) => {
state.visible = newValue;
(newValue) => {
state.dialogVisible = newValue;
}
);
@@ -66,7 +66,7 @@ export default defineComponent({
closeOnClickModal: true,
showConfirmButton: false,
}
).catch((r) => {});
).catch(() => {});
return;
};

View File

@@ -30,7 +30,7 @@ const viteConfig: UserConfig = {
target: 'http://localhost:8888',
ws: true,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '/api'),
rewrite: (path) => path.replace(/^\/api/, '/'),
},
},
},

View File

@@ -30,7 +30,12 @@ type Machine struct {
}
func (m *Machine) Machines(rc *ctx.ReqCtx) {
rc.ResData = m.MachineApp.GetMachineList(new(entity.Machine), ginx.GetPageParam(rc.GinCtx), new([]vo.MachineVO))
res := m.MachineApp.GetMachineList(new(entity.Machine), ginx.GetPageParam(rc.GinCtx), new([]*vo.MachineVO))
list := res.List.(*[]*vo.MachineVO)
for _, mv := range *list {
mv.HasCli = machine.HasCli(*mv.Id)
}
rc.ResData = res
}
func (m *Machine) SaveMachine(rc *ctx.ReqCtx) {
@@ -46,14 +51,14 @@ func (m *Machine) SaveMachine(rc *ctx.ReqCtx) {
}
func (m *Machine) DeleteMachine(rc *ctx.ReqCtx) {
id := uint64(ginx.PathParamInt(rc.GinCtx, "id"))
id := uint64(ginx.PathParamInt(rc.GinCtx, "machineId"))
rc.ReqParam = id
m.MachineApp.Delete(id)
}
// top命令信息
func (m *Machine) Top(rc *ctx.ReqCtx) {
rc.ResData = m.MachineApp.GetCli(GetMachineId(rc.GinCtx)).GetTop()
// 关闭机器客户端
func (m *Machine) CloseCli(rc *ctx.ReqCtx) {
machine.DeleteCli(GetMachineId(rc.GinCtx))
}
func (m *Machine) WsSSH(g *gin.Context) {
@@ -78,9 +83,7 @@ func (m *Machine) WsSSH(g *gin.Context) {
rows := ginx.QueryInt(g, "rows", 40)
sws, err := machine.NewLogicSshWsSession(cols, rows, m.MachineApp.GetCli(GetMachineId(g)), wsConn)
if sws == nil {
panic(biz.NewBizErr("连接失败"))
}
biz.ErrIsNilAppendErr(err, "连接失败:%s")
defer sws.Close()
quitChan := make(chan bool, 3)

View File

@@ -50,7 +50,7 @@ func (r *Redis) RedisInfo(rc *ctx.ReqCtx) {
i := 0
length := len(datas)
parseMap := make(map[string]map[string]string, 0)
parseMap := make(map[string]map[string]string)
for {
if i >= length {
break
@@ -60,7 +60,7 @@ func (r *Redis) RedisInfo(rc *ctx.ReqCtx) {
i++
key = strings.Trim(key, " ")
sectionMap := make(map[string]string, 0)
sectionMap := make(map[string]string)
for {
if i >= length || !strings.Contains(datas[i], ":") {
break
@@ -156,41 +156,6 @@ func (r *Redis) GetSetValue(rc *ctx.ReqCtx) {
rc.ResData = res
}
func (r *Redis) Test(rc *ctx.ReqCtx) {
schema := `{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Product",
"description": "A product from Acme's catalog",
"type": "object",
"properties": {
"id": {
"description": "The unique identifier for a product",
"type": "integer"
},
"name": {
"description": "Name of the product",
"type": "string"
},
"price": {
"type": "number",
"minimum": 0,
"exclusiveMinimum": true
}
},
"required": ["id", "name", "price"]
}
`
// 获取请求报文的内容长度
len := rc.GinCtx.Request.ContentLength
// 新建一个字节切片,长度与请求报文的内容长度相同
body := make([]byte, len)
// 读取 r 的请求主体,并将具体内容读入 body 中
rc.GinCtx.Request.Body.Read(body)
err := utils.ValidJsonString(schema, string(body))
biz.ErrIsNilAppendErr(err, "%s")
}
func (r *Redis) SetStringValue(rc *ctx.ReqCtx) {
g := rc.GinCtx
keyValue := new(form.KeyValue)

View File

@@ -15,7 +15,7 @@ type AccountVO struct {
type MachineVO struct {
//models.BaseModel
Id *int64 `json:"id"`
Id *uint64 `json:"id"`
Name *string `json:"name"`
Username *string `json:"username"`
Ip *string `json:"ip"`
@@ -26,6 +26,7 @@ type MachineVO struct {
UpdateTime *time.Time `json:"updateTime"`
Modifier *string `json:"modifier"`
ModifierId *int64 `json:"modifierId"`
HasCli bool `json:"hasCli" gorm:"-"`
}
type MachineScriptVO struct {

View File

@@ -53,7 +53,7 @@ func (m *machineAppImpl) Save(me *entity.Machine) {
biz.IsTrue(oldMachine.Id == me.Id, "该机器信息已存在")
}
// 关闭连接
machine.Close(me.Id)
machine.DeleteCli(me.Id)
m.machineRepo.UpdateById(me)
} else {
biz.IsTrue(err != nil, "该机器信息已存在")
@@ -64,7 +64,7 @@ func (m *machineAppImpl) Save(me *entity.Machine) {
// 根据条件获取机器信息
func (m *machineAppImpl) Delete(id uint64) {
// 关闭连接
machine.Close(id)
machine.DeleteCli(id)
model.Tx(
func(db *gorm.DB) error {
// 删除machine表信息

View File

@@ -154,7 +154,7 @@ func (m *machineFileAppImpl) RemoveFile(fileId uint64, path string) {
sftpCli := m.getSftpCli(machineId)
file, err := sftpCli.Open(path)
biz.ErrIsNilAppendErr(err, "打开文件失败: %s")
fi, err := file.Stat()
fi, _ := file.Stat()
if fi.IsDir() {
err = sftpCli.RemoveDirectory(path)
} else {

View File

@@ -3,7 +3,6 @@ package machine
import (
"errors"
"fmt"
"io"
"mayfly-go/base/biz"
"mayfly-go/base/cache"
"mayfly-go/base/global"
@@ -29,10 +28,22 @@ type Cli struct {
var cliCache = cache.NewTimedCache(30*time.Minute, 5*time.Second).
WithUpdateAccessTime(true).
OnEvicted(func(key interface{}, value interface{}) {
global.Log.Info(fmt.Sprintf("删除机器连接缓存 id: %d", key))
value.(*Cli).Close()
})
// 是否存在指定id的客户端连接
func HasCli(machineId uint64) bool {
if _, ok := cliCache.Get(machineId); ok {
return true
}
return false
}
// 删除指定机器客户端,并关闭客户端连接
func DeleteCli(id uint64) {
cliCache.Delete(id)
}
// 从缓存中获取客户端信息,不存在则回调获取机器信息函数,并新建
func GetCli(machineId uint64, getMachine func(uint64) *entity.Machine) (*Cli, error) {
cli, err := cliCache.ComputeIfAbsent(machineId, func(key interface{}) (interface{}, error) {
@@ -42,6 +53,7 @@ func GetCli(machineId uint64, getMachine func(uint64) *entity.Machine) (*Cli, er
}
return c, nil
})
if cli != nil {
return cli.(*Cli), err
}
@@ -54,7 +66,7 @@ func newClient(machine *entity.Machine) (*Cli, error) {
return nil, errors.New("机器不存在")
}
global.Log.Infof("机器连接:%s:%d", machine.Ip, machine.Port)
global.Log.Infof("[%s]机器连接:%s:%d", machine.Name, machine.Ip, machine.Port)
cli := new(Cli)
cli.machine = machine
err := cli.connect()
@@ -109,11 +121,15 @@ func TestConn(m *entity.Machine) error {
// 关闭client和并从缓存中移除
func (c *Cli) Close() {
m := c.machine
global.Log.Info(fmt.Sprintf("关闭机器客户端连接-> id: %d, name: %s, ip: %s", m.Id, m.Name, m.Ip))
if c.client != nil {
c.client.Close()
c.client = nil
}
if c.sftpClient != nil {
c.sftpClient.Close()
c.sftpClient = nil
}
}
@@ -164,53 +180,3 @@ func (c *Cli) Run(shell string) (*string, error) {
res := string(buf)
return &res, nil
}
//执行带交互的命令
func (c *Cli) RunTerminal(shell string, stdout, stderr io.Writer) error {
session, err := c.GetSession()
if err != nil {
return err
}
//defer session.Close()
// fd := int(os.Stdin.Fd())
// oldState, err := terminal.MakeRaw(fd)
// if err != nil {
// panic(err)
// }
// defer terminal.Restore(fd, oldState)
// writer, err := session.StdinPipe()
biz.ErrIsNilAppendErr(err, "获取session stdin 错误:%s")
session.Stdout = stdout
session.Stderr = stderr
// termWidth, termHeight, err := terminal.GetSize(fd)
// if err != nil {
// panic(err)
// }
// Set up terminal modes
// modes := ssh.TerminalModes{
// ssh.ECHO: 1, // enable echoing
// ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
// ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
// }
// // Request pseudo terminal
// if err := session.RequestPty("xterm-256color", 400, 800, modes); err != nil {
// return err
// }
session.Shell()
session.Wait()
// writer.Write([]byte(shell))
session.Run(shell)
return nil
}
// 关闭指定机器的连接
func Close(id uint64) {
if cli, ok := cliCache.Get(id); ok {
cli.(*Cli).Close()
}
}

View File

@@ -24,14 +24,15 @@ func InitMachineRouter(router *gin.RouterGroup) {
})
delMachine := ctx.NewLogInfo("删除机器")
db.DELETE("/delete/:id", func(c *gin.Context) {
db.DELETE(":machineId", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).
WithLog(delMachine).
Handle(m.DeleteMachine)
})
db.GET(":machineId/top", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).Handle(m.Top)
closeCli := ctx.NewLogInfo("关闭机器客户端")
db.DELETE(":machineId/close-cli", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(closeCli).Handle(m.CloseCli)
})
db.GET(":machineId/terminal", m.WsSSH)

View File

@@ -70,10 +70,5 @@ func InitRedisRouter(router *gin.RouterGroup) {
redis.POST(":id/hash-value", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).Handle(rs.SetStringValue)
})
// 设置hash类型值
redis.POST("test", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithNeedToken(false).Handle(rs.Test)
})
}
}