fix 代码生成树形虚拟表,微信模块

This commit is contained in:
yxh 2023-11-03 18:12:02 +08:00
parent e2b44392a3
commit d1e24c44f8
40 changed files with 8644 additions and 77 deletions

View File

@ -102,6 +102,7 @@ type ToolsGenTableColumnsEditReq struct {
TreeName string `p:"tree_name"`
ExcelPort string `p:"excelPort"`
UseSnowId string `p:"useSnowId"`
UseVirtual string `p:"useVirtual"`
}
type ToolsGenTableColumnsEditRes struct {

23
api/v1/wechat/demo.go Normal file
View File

@ -0,0 +1,23 @@
/*
* @desc:测试登录小程序后才能访问
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @Date: 2023/11/3 16:06
*/
package wechat
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/tiger1103/gfast/v3/api/v1/common"
)
type DemoReq struct {
g.Meta `path:"/demo" tags:"微信小程序测试" method:"get" summary:"测试"`
common.Author
}
type DemoRes struct {
common.EmptyRes
Info string `json:"info"`
}

44
api/v1/wechat/login.go Normal file
View File

@ -0,0 +1,44 @@
/*
* @desc:警务采集登陆了
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @Date: 2023/2/24 11:38
*/
package wechat
import (
"github.com/gogf/gf/v2/frame/g"
commonApi "github.com/tiger1103/gfast/v3/api/v1/common"
"github.com/tiger1103/gfast/v3/internal/app/system/model"
)
type WxUrlReq struct {
g.Meta `path:"/wxUrl" tags:"微信小程序登陆" method:"get" summary:"获取微信小程序url"`
}
type WxUrlRes struct {
g.Meta `mime:"application/json"`
Url string `json:"url"`
}
type WxLoginReq struct {
g.Meta `path:"/wxLogin" tags:"微信小程序登陆" method:"post" summary:"微信登录"`
Code string `p:"code" v:"required#code必须"`
PhoneCode string `p:"phoneCode"`
}
type WxLoginRes struct {
g.Meta `mime:"application/json"`
UserInfo *model.LoginUserRes `json:"userInfo"`
Token string `json:"token"`
}
type UserLoginOutReq struct {
g.Meta `path:"/logout" tags:"微信小程序登陆" method:"get" summary:"退出登录"`
commonApi.Author
}
type UserLoginOutRes struct {
}

11
go.mod
View File

@ -17,13 +17,16 @@ require (
github.com/shirou/gopsutil/v3 v3.23.2
github.com/sony/sonyflake v1.2.0
github.com/tencentyun/cos-go-sdk-v5 v0.7.34
github.com/tiger1103/gfast-cache v1.0.1
github.com/tiger1103/gfast-cache v1.0.2
github.com/tiger1103/gfast-token v1.0.4
github.com/xuri/excelize/v2 v2.7.1
golang.org/x/tools v0.6.0
)
require (
github.com/ArtisanCloud/PowerLibs/v3 v3.0.15 // indirect
github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7 // indirect
github.com/ArtisanCloud/PowerWeChat/v3 v3.1.8 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
@ -57,7 +60,7 @@ require (
github.com/mozillazg/go-httpheader v0.2.1 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pkg/errors v0.8.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/redis/go-redis/v9 v9.2.1 // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect
@ -78,7 +81,9 @@ require (
go.opentelemetry.io/otel/metric v1.18.0 // indirect
go.opentelemetry.io/otel/sdk v1.18.0 // indirect
go.opentelemetry.io/otel/trace v1.18.0 // indirect
go.uber.org/atomic v1.5.1 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.21.0 // indirect
golang.org/x/crypto v0.13.0 // indirect
golang.org/x/image v0.5.0 // indirect
golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect

32
go.sum
View File

@ -1,3 +1,9 @@
github.com/ArtisanCloud/PowerLibs/v3 v3.0.15 h1:EKWDvgu3y6S7OjT3ku7LEF6l5KpIKygBVVnbn2d+lns=
github.com/ArtisanCloud/PowerLibs/v3 v3.0.15/go.mod h1:KBO7ZQGTBjvYTveKY5M4QQpwxuoGBI0V2fZ4xP+TIuM=
github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7 h1:P+erNlErr+X2v7Et+yTWaTfIRhw+HfpAPdvNIEwk9Gw=
github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7/go.mod h1:VZQNCvcK/rldF3QaExiSl1gJEAkyc5/I8RLOd3WFZq4=
github.com/ArtisanCloud/PowerWeChat/v3 v3.1.8 h1:azjjwozzUNm1xnGXJIjfU7tjQeqDsTdnFJxAi+jtOpU=
github.com/ArtisanCloud/PowerWeChat/v3 v3.1.8/go.mod h1:N6ATGWtdjvnts0dzbe9AYxQ1aRuA1yuTTabcUTQPFZo=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
@ -8,6 +14,7 @@ github.com/aliyun/aliyun-oss-go-sdk v2.2.8+incompatible h1:6JF1bjhT0WN2srEmijfOF
github.com/aliyun/aliyun-oss-go-sdk v2.2.8+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/apache/rocketmq-client-go/v2 v2.1.1 h1:WY/LkOYSQaVyV+HOqdiIgF4LE3beZ/jwdSLKZlzpabw=
github.com/apache/rocketmq-client-go/v2 v2.1.1/go.mod h1:GZzExtXY9zpI6FfiVJYAhw2IXQtgnHUuWpULo7nr5lw=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/casbin/casbin/v2 v2.42.0 h1:EA0aE5PZnFSYY6WulzTScOo4YO6xrGAAZkXRLs8p2ME=
@ -124,6 +131,8 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
@ -166,6 +175,7 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
@ -182,6 +192,8 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tiger1103/gfast-cache v1.0.1 h1:82U4+DWeaM7BGuXgE9hOzCioiIupMZbvRqYHv+ALe6U=
github.com/tiger1103/gfast-cache v1.0.1/go.mod h1:LYOlyTyvlY5Pf1u6tqFrDgG+8zZFmAg5xuKFeehNcnI=
github.com/tiger1103/gfast-cache v1.0.2 h1:p+siY2qISzqowGQZvJjnXnrye7D50uVYyJvdBQbrbqk=
github.com/tiger1103/gfast-cache v1.0.2/go.mod h1:LYOlyTyvlY5Pf1u6tqFrDgG+8zZFmAg5xuKFeehNcnI=
github.com/tiger1103/gfast-token v1.0.4 h1:/tYnh2DjPzXVTfm0wHLR3V21JsTkm1HhiKKIfM6NobE=
github.com/tiger1103/gfast-token v1.0.4/go.mod h1:OurEktIaHPJes7lJsIjMo1yz1vSiBRGyV3T8muWytfo=
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
@ -196,6 +208,7 @@ github.com/xuri/excelize/v2 v2.7.1/go.mod h1:qc0+2j4TvAUrBw36ATtcTeC1VCM0fFdAXZO
github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/xuri/nfp v0.0.0-20230802015359-2d5eeba905e9 h1:jmhvNv5by7bXDzzjzBXaIWmEI4lMYfv5iJtI5Pw5/aM=
github.com/xuri/nfp v0.0.0-20230802015359-2d5eeba905e9/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
@ -209,8 +222,16 @@ go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo
go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0=
go.uber.org/atomic v1.5.1 h1:rsqfU5vBkVknbhUGbAUwQKR2H4ItV8tjJ+6kJX4cxHM=
go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
@ -221,12 +242,15 @@ golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
@ -234,14 +258,18 @@ golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -278,11 +306,14 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
@ -290,6 +321,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/yaml.v2 v2.2.8/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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -0,0 +1,10 @@
/*
* @desc:微信小程序
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @Date: 2023/11/3 15:31
*/
package boot
import _ "github.com/tiger1103/gfast/v3/internal/app/wechat/logic"

View File

@ -77,6 +77,7 @@ func (c *loginController) Login(ctx context.Context, req *system.UserLoginReq) (
if g.Cfg().MustGet(ctx, "gfToken.multiLogin").Bool() {
key = gconv.String(user.Id) + "-" + gmd5.MustEncryptString(user.UserName) + gmd5.MustEncryptString(user.UserPassword+ip+userAgent)
}
user.UserPassword = ""
token, err = service.GfToken().GenerateToken(ctx, key, user)
if err != nil {
g.Log().Error(ctx, err)

View File

@ -40,6 +40,7 @@ type SysUserColumns struct {
CreatedAt string // 创建时间
UpdatedAt string // 更新时间
DeletedAt string // 删除时间
OpenId string // 微信open id
}
// sysUserColumns holds the columns for table sys_user.
@ -65,6 +66,7 @@ var sysUserColumns = SysUserColumns{
CreatedAt: "created_at",
UpdatedAt: "updated_at",
DeletedAt: "deleted_at",
OpenId: "open_id",
}
// NewSysUserDao creates and returns a new DAO object for table data access.

View File

@ -40,6 +40,7 @@ type ToolsGenTableColumns struct {
ShowDetail string // 是否有查看详情功能
ExcelPort string // 是否有导入导出excel功能
UseSnowId string //主键是否使用雪花ID
UseVirtual string // 树表是否使用虚拟表
}
// toolsGenTableColumns holds the columns for table tools_gen_table.
@ -64,6 +65,7 @@ var toolsGenTableColumns = ToolsGenTableColumns{
ShowDetail: "show_detail",
ExcelPort: "excel_port",
UseSnowId: "use_snow_id",
UseVirtual: "use_virtual",
}
// NewToolsGenTableDao creates and returns a new DAO object for table data access.

View File

@ -96,6 +96,15 @@ func (s *sSysUser) GetUserByUsername(ctx context.Context, userName string) (user
return
}
func (s *sSysUser) GetUserByPhone(ctx context.Context, phone string) (user *model.LoginUserRes, err error) {
err = g.Try(ctx, func(ctx context.Context) {
err = dao.SysUser.Ctx(ctx).Fields(user).Where(dao.SysUser.Columns().Mobile, phone).
Scan(&user)
liberr.ErrIsNil(ctx, err, "登录失败,用户信息不存在")
})
return
}
// GetUserById 通过用户名获取用户信息
func (s *sSysUser) GetUserById(ctx context.Context, id uint64) (user *model.LoginUserRes, err error) {
err = g.Try(ctx, func(ctx context.Context) {
@ -127,12 +136,16 @@ func (s *sSysUser) LoginLog(ctx context.Context, params *model.LoginLogParams) {
}
}
func (s *sSysUser) UpdateLoginInfo(ctx context.Context, id uint64, ip string) (err error) {
func (s *sSysUser) UpdateLoginInfo(ctx context.Context, id uint64, ip string, openId ...string) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
_, err = dao.SysUser.Ctx(ctx).WherePri(id).Unscoped().Update(g.Map{
data := g.Map{
dao.SysUser.Columns().LastLoginIp: ip,
dao.SysUser.Columns().LastLoginTime: gtime.Now(),
})
}
if len(openId) > 0 && openId[0] != "" {
data[dao.SysUser.Columns().OpenId] = openId[0]
}
_, err = dao.SysUser.Ctx(ctx).WherePri(id).Unscoped().Update(data)
liberr.ErrIsNil(ctx, err, "更新用户登录信息失败")
})
return

View File

@ -371,6 +371,9 @@ func (s *sToolsGenTable) SaveEdit(ctx context.Context, req *system.ToolsGenTable
if req.UseSnowId != "" {
table.UseSnowId = gconv.Bool(req.UseSnowId)
}
if req.UseVirtual != ""{
table.UseVirtual = gconv.Bool(req.UseVirtual)
}
if req.TplCategory != "" {
table.TplCategory = req.TplCategory
}
@ -662,9 +665,14 @@ func (s *sToolsGenTable) GenData(ctx context.Context, tableId int64) (data g.Map
var tmpVue string
tmpFile := "vue/list-vue.template"
if extendData.TplCategory == "tree" {
if extendData.UseVirtual{
//使用虚拟表树表
tmpFile = "vue/tree-virtual-vue.template"
}else{
//树表
tmpFile = "vue/tree-vue.template"
}
}
if tmpVue, err = view.Parse(ctx, tmpFile, tplData); err == nil {
vueValue = tmpVue
vueValue, err = s.trimBreak(vueValue)

View File

@ -170,7 +170,7 @@ func (s *sToolsGenTableColumn) InitColumnField(column *entity.ToolsGenTableColum
column.ColSpan = 12
column.RowSpan = 1
column.IsRowStart = false
column.MinWidth = 100
column.MinWidth = 150
column.IsFixed = false
column.IsOverflowTooltip = false
column.IsCascade = false

View File

@ -33,4 +33,5 @@ type SysUser struct {
CreatedAt *gtime.Time // 创建时间
UpdatedAt *gtime.Time // 更新时间
DeletedAt *gtime.Time // 删除时间
OpenId interface{} // 微信小程序open id
}

View File

@ -32,4 +32,5 @@ type ToolsGenTable struct {
ShowDetail interface{} // 是否有查看详情功能
ExcelPort interface{} // 是否有导入导出excel功能
UseSnowId interface{} //主键是否使用雪花ID
UseVirtual interface{} //树表是否使用虚拟表
}

View File

@ -31,4 +31,5 @@ type SysUser struct {
CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"`
DeletedAt *gtime.Time `json:"deletedAt" description:"删除时间"`
OpenId string `json:"openId " description:"微信小程序open id"`
}

View File

@ -30,4 +30,5 @@ type ToolsGenTable struct {
ShowDetail bool `json:"showDetail" description:"是否有查看详情功能"`
ExcelPort bool `json:"excelPort" description:"是否有excel导入导出功能"`
UseSnowId bool `json:"useSnowId" description:"主键是否使用雪花ID"`
UseVirtual bool `json:"useVirtual" orm:"use_virtual" description:"树表是否使用虚拟表"`
}

View File

@ -16,6 +16,7 @@ import (
type LoginUserRes struct {
Id uint64 `orm:"id,primary" json:"id"` //
UserName string `orm:"user_name,unique" json:"userName"` // 用户名
Mobile string `orm:"mobile" json:"mobile"` //手机号
UserNickname string `orm:"user_nickname" json:"userNickname"` // 用户昵称
UserPassword string `orm:"user_password" json:"-"` // 登录密码;cmf_password加密
UserSalt string `orm:"user_salt" json:"-"` // 加密盐

View File

@ -37,6 +37,7 @@ type ToolsGenTableEx struct {
ShowDetail bool // 是否有查看详情功能
ExcelPort bool // 是否有导入导出excel功能
UseSnowId bool // 主键是否使用雪花ID
UseVirtual bool // 树表是否使用虚拟表
TreeCode string // 树编码字段
TreeParentCode string // 树父编码字段
TreeName string // 树名称字段

View File

@ -24,9 +24,10 @@ type (
NotCheckAuthAdminIds(ctx context.Context) *gset.Set
GetAdminUserByUsernamePassword(ctx context.Context, req *system.UserLoginReq) (user *model.LoginUserRes, err error)
GetUserByUsername(ctx context.Context, userName string) (user *model.LoginUserRes, err error)
GetUserByPhone(ctx context.Context, phone string) (user *model.LoginUserRes, err error)
GetUserById(ctx context.Context, id uint64) (user *model.LoginUserRes, err error)
LoginLog(ctx context.Context, params *model.LoginLogParams)
UpdateLoginInfo(ctx context.Context, id uint64, ip string) (err error)
UpdateLoginInfo(ctx context.Context, id uint64, ip string,openId ...string) (err error)
GetAdminRules(ctx context.Context, userId uint64) (menuList []*model.UserMenus, permissions []string, err error)
GetAdminRole(ctx context.Context, userId uint64, allRoleList []*entity.SysRole) (roles []*entity.SysRole, err error)
GetAdminRoleIds(ctx context.Context, userId uint64) (roleIds []uint, err error)

View File

@ -0,0 +1,13 @@
/*
* @desc:context 相关常量
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @Date: 2022/3/16 14:52
*/
package consts
const (
// CtxKey 上下文变量存储键名,前后端系统共享
CtxKey = "GFastContextWechat"
)

View File

@ -0,0 +1,23 @@
/*
* @desc:system base controller
* @company:云南奇讯科技有限公司
* @Author: yixiaohu
* @Date: 2022/3/4 18:12
*/
package controller
import (
"github.com/gogf/gf/v2/net/ghttp"
commonController "github.com/tiger1103/gfast/v3/internal/app/common/controller"
)
type BaseController struct {
commonController.BaseController
}
// Init 自动执行的初始化方法
func (c *BaseController) Init(r *ghttp.Request) {
c.BaseController.Init(r)
}

View File

@ -0,0 +1,24 @@
/*
* @desc:测试登录后才可以访问
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @Date: 2023/11/3 16:05
*/
package controller
import (
"context"
"github.com/tiger1103/gfast/v3/api/v1/wechat"
)
var Demo = new(demoController)
type demoController struct {
BaseController
}
func (c *demoController) Demo(ctx context.Context,req *wechat.DemoReq)(res *wechat.DemoRes,err error){
res = &wechat.DemoRes{Info: "hello word"}
return
}

View File

@ -0,0 +1,128 @@
/*
* @desc:用户登录
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @Date: 2023/2/24 11:39
*/
package controller
import (
"context"
"errors"
"fmt"
"github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram/auth/response"
resp "github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram/phoneNumber/response"
"github.com/gogf/gf/v2/crypto/gmd5"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/util/gconv"
"github.com/tiger1103/gfast/v3/api/v1/wechat"
systemModel "github.com/tiger1103/gfast/v3/internal/app/system/model"
systemService "github.com/tiger1103/gfast/v3/internal/app/system/service"
"github.com/tiger1103/gfast/v3/internal/app/wechat/service"
"github.com/tiger1103/gfast/v3/library/libUtils"
"github.com/tiger1103/gfast/v3/library/liberr"
)
var Login = new(loginController)
type loginController struct {
BaseController
}
func (c *loginController) WxUrl(ctx context.Context, req *wechat.WxUrlReq) (res *wechat.WxUrlRes, err error) {
res = new(wechat.WxUrlRes)
res.Url, err = service.Wechat().GetWxUrl(ctx)
return
}
func (c *loginController) WxLogin(ctx context.Context, req *wechat.WxLoginReq) (res *wechat.WxLoginRes, err error) {
var (
data *response.ResponseCode2Session
phoneData *resp.ResponseGetUserPhoneNumber
user *systemModel.LoginUserRes
token string
)
data, err = service.Wechat().Session(ctx, req.Code)
if err != nil {
return
}
if data.ResponseMiniProgram.ErrCode != 0 {
err = gerror.New(fmt.Sprintf("errCode: %d , errMsg: %s", data.ResponseMiniProgram.ErrCode, data.ResponseMiniProgram.ErrMsg))
return
}
phoneData, err = service.Wechat().GetUserPhoneNumber(ctx, req.PhoneCode)
if err != nil {
return
}
if phoneData.ErrCode != 0 {
err = gerror.New(fmt.Sprintf("errCode: %d , errMsg: %s", phoneData.ErrCode, phoneData.ErrMsg))
return
}
user, token, err = c.doLogin(ctx, phoneData.PhoneInfo.PhoneNumber, data.OpenID)
if err != nil {
return
}
res = &wechat.WxLoginRes{
UserInfo: user,
Token: token,
}
return
}
func (c *loginController) doLogin(ctx context.Context, phone, openId string) (user *systemModel.LoginUserRes, token string, err error) {
err = g.Try(ctx, func(ctx context.Context) {
ip := libUtils.GetClientIp(ctx)
userAgent := libUtils.GetUserAgent(ctx)
err = g.Try(ctx, func(ctx context.Context) {
//警员服务器未获取到,从本地获取
user, err = systemService.SysUser().GetUserByPhone(ctx, phone)
liberr.ErrIsNil(ctx, err)
if user == nil {
// 保存登录失败的日志信息
systemService.SysLoginLog().Invoke(gctx.New(), &systemModel.LoginLogParams{
Status: 0,
Username: phone,
Ip: ip,
UserAgent: userAgent,
Msg: "用户不存在",
Module: "微信小程序",
})
return
}
err = systemService.SysUser().UpdateLoginInfo(ctx, user.Id, ip, openId)
liberr.ErrIsNil(ctx, err)
})
if user == nil {
liberr.ErrIsNil(ctx, errors.New("用户不存在"))
}
// 报存登录成功的日志信息
systemService.SysLoginLog().Invoke(gctx.New(), &systemModel.LoginLogParams{
Status: 1,
Username: user.Mobile,
Ip: ip,
UserAgent: userAgent,
Msg: "登录成功",
Module: "微信小程序",
})
key := gconv.String(user.Id) + "-" + gmd5.MustEncryptString(gconv.String(user.Id)) + gmd5.MustEncryptString(user.Mobile)
if g.Cfg("wechat").MustGet(ctx, "gfToken.multiLogin").Bool() {
key = gconv.String(user.Id) + "-" + gmd5.MustEncryptString(gconv.String(user.Id)) + gmd5.MustEncryptString(user.Mobile+ip+userAgent)
}
user.UserPassword = ""
user.UserSalt = ""
token, err = service.GfToken().GenerateToken(ctx, key, user)
liberr.ErrIsNil(ctx, err, "登录失败,后端服务出现错误")
//用户在线状态保存
systemService.SysUserOnline().Invoke(gctx.New(), &systemModel.SysUserOnlineParams{
UserAgent: userAgent,
Uuid: gmd5.MustEncrypt(token),
Token: token,
Username: user.UserNickname,
Ip: ip,
})
})
return
}

View File

@ -0,0 +1,74 @@
/*
* @desc:context-service
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @Date: 2022/9/23 14:51
*/
package context
import (
"context"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/tiger1103/gfast/v3/internal/app/system/model"
"github.com/tiger1103/gfast/v3/internal/app/wechat/consts"
"github.com/tiger1103/gfast/v3/internal/app/wechat/service"
)
func init() {
service.RegisterContext(New())
}
type sContext struct{}
func New() service.IContext {
return &sContext{}
}
// Init 初始化上下文对象指针到上下文对象中,以便后续的请求流程中可以修改。
func (s *sContext) Init(r *ghttp.Request, customCtx *model.Context) {
r.SetCtxVar(consts.CtxKey, customCtx)
}
// Get 获得上下文变量如果没有设置那么返回nil
func (s *sContext) Get(ctx context.Context) *model.Context {
value := ctx.Value(consts.CtxKey)
if value == nil {
return nil
}
if localCtx, ok := value.(*model.Context); ok {
return localCtx
}
return nil
}
// SetUser 将上下文信息设置到上下文请求中,注意是完整覆盖
func (s *sContext) SetUser(ctx context.Context, ctxUser *model.ContextUser) {
s.Get(ctx).User = ctxUser
}
// GetLoginUser 获取当前登陆用户信息
func (s *sContext) GetLoginUser(ctx context.Context) *model.ContextUser {
context := s.Get(ctx)
if context == nil {
return nil
}
return context.User
}
// GetUserId 获取当前登录用户id
func (s *sContext) GetUserId(ctx context.Context) uint64 {
user := s.GetLoginUser(ctx)
if user != nil {
return user.Id
}
return 0
}
func (s *sContext) GetDeptId(ctx context.Context) uint64 {
user := s.GetLoginUser(ctx)
if user != nil {
return user.DeptId
}
return 0
}

View File

@ -0,0 +1,13 @@
/*
* @desc:logic注册
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @Date: 2023/2/24 11:48
*/
package logic
import _ "github.com/tiger1103/gfast/v3/internal/app/wechat/logic/token"
import _ "github.com/tiger1103/gfast/v3/internal/app/wechat/logic/context"
import _ "github.com/tiger1103/gfast/v3/internal/app/wechat/logic/middleware"
import _ "github.com/tiger1103/gfast/v3/internal/app/wechat/logic/wechat"

View File

@ -0,0 +1,49 @@
/*
* @desc:中间件
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @Date: 2022/9/23 15:05
*/
package middleware
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/util/gconv"
"github.com/tiger1103/gfast/v3/internal/app/system/model"
"github.com/tiger1103/gfast/v3/internal/app/wechat/service"
)
func init() {
service.RegisterMiddleware(New())
}
func New() service.IMiddleware {
return &sMiddleware{}
}
type sMiddleware struct{}
// Ctx 自定义上下文对象
func (s *sMiddleware) Ctx(r *ghttp.Request) {
ctx := r.GetCtx()
// 初始化登录用户信息
data, err := service.GfToken().ParseToken(r)
if err != nil {
// 执行下一步请求逻辑
r.Middleware.Next()
}
if data != nil {
context := new(model.Context)
err = gconv.Struct(data.Data, &context.User)
if err != nil {
g.Log().Error(ctx, err)
// 执行下一步请求逻辑
r.Middleware.Next()
}
service.Context().Init(r, context)
}
// 执行下一步请求逻辑
r.Middleware.Next()
}

View File

@ -0,0 +1,51 @@
/*
* @desc:token功能
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @Date: 2022/9/27 17:01
*/
package token
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/tiger1103/gfast-token/gftoken"
"github.com/tiger1103/gfast/v3/internal/app/common/consts"
commonModel "github.com/tiger1103/gfast/v3/internal/app/common/model"
"github.com/tiger1103/gfast/v3/internal/app/wechat/service"
"github.com/tiger1103/gfast/v3/library/liberr"
)
type sToken struct {
*gftoken.GfToken
}
func New() service.IGfToken {
var (
ctx = gctx.New()
opt *commonModel.TokenOptions
err = g.Cfg("wechat").MustGet(ctx, "gfToken").Struct(&opt)
fun gftoken.OptionFunc
)
liberr.ErrIsNil(ctx, err)
if opt.CacheModel == consts.CacheModelRedis {
fun = gftoken.WithGRedis()
} else {
fun = gftoken.WithGCache()
}
return &sToken{
GfToken: gftoken.NewGfToken(
gftoken.WithCacheKey(opt.CacheKey),
gftoken.WithTimeout(opt.Timeout),
gftoken.WithMaxRefresh(opt.MaxRefresh),
gftoken.WithMultiLogin(opt.MultiLogin),
gftoken.WithExcludePaths(opt.ExcludePaths),
fun,
),
}
}
func init() {
service.RegisterGToken(New())
}

View File

@ -0,0 +1,96 @@
/*
* @desc:微信小程序接口
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @Date: 2023/3/22 9:08
*/
package wechat
import (
"context"
"github.com/ArtisanCloud/PowerWeChat/v3/src/kernel"
"github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram"
"github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram/auth/response"
phoneNumberResp "github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram/phoneNumber/response"
"github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram/urlLink/request"
wxlinkResp "github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram/urlLink/response"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/tiger1103/gfast/v3/internal/app/wechat/service"
)
func init() {
service.RegisterWechat(New())
}
func New() service.IWechat {
var (
ctx = gctx.New()
cfg = g.Cfg("wechat")
)
miniProgramApp, err := miniProgram.NewMiniProgram(&miniProgram.UserConfig{
AppID: cfg.MustGet(ctx, "wechat.AppID").String(), // 小程序appid
Secret: cfg.MustGet(ctx, "wechat.Secret").String(), // 小程序app secret
HttpDebug: cfg.MustGet(ctx, "wechat.HttpDebug").Bool(),
AESKey: cfg.MustGet(ctx, "wechat.AesKey").String(),
Log: miniProgram.Log{
Level: cfg.MustGet(ctx, "wechat.Log.Leave").String(),
File: cfg.MustGet(ctx, "wechat.Log.File").String(),
Error: cfg.MustGet(ctx, "wechat.Log.Error").String(),
},
// 可选,不传默认走程序内存
Cache: kernel.NewRedisClient(&kernel.RedisOptions{
Addr: cfg.MustGet(ctx, "wechat.Cache.Addr").String(),
Password: cfg.MustGet(ctx, "wechat.Cache.Password").String(),
DB: cfg.MustGet(ctx, "wechat.Cache.DB").Int(),
}),
})
if err != nil {
panic(err)
}
return &sWechat{
miniProgramApp: miniProgramApp,
}
}
type sWechat struct {
miniProgramApp *miniProgram.MiniProgram
}
func (s *sWechat) Session(ctx context.Context, code string) (data *response.ResponseCode2Session, err error) {
data, err = s.miniProgramApp.Auth.Session(ctx, code)
return
}
func (s *sWechat) GetUserPhoneNumber(ctx context.Context, code string) (data *phoneNumberResp.ResponseGetUserPhoneNumber, err error) {
data, err = s.miniProgramApp.PhoneNumber.GetUserPhoneNumber(ctx, code)
return
}
// IsDebug 是否开发调试模式
func (s *sWechat) IsDebug(ctx context.Context) bool {
debug := g.Cfg("wechat").MustGet(ctx, "wechat.isDebug").Bool()
debug2 := g.Cfg("wechat").MustGet(ctx, "wechat.isDebug2").Bool()
return debug || debug2
}
func (s *sWechat) GetWxUrl(ctx context.Context) (url string, err error) {
var res *wxlinkResp.ResponseURLLinkGenerate
res, err = s.miniProgramApp.URLLink.Generate(ctx, &request.URLLinkGenerate{
EnvVersion: "release",
ExpireInterval: 1606737600,
Path: "pages/index/index",
Query: "",
})
if err != nil {
return
}
if res.ErrMsg != "ok" {
err = gerror.New("获取小程序url失败err:" + res.ErrMsg + ",errCode:" + res.Code)
return
}
url = res.URLLink
return
}

View File

@ -0,0 +1,23 @@
/*
* @desc:xxxx功能描述
* @company:云南奇讯科技有限公司
* @Author: yixiaohu<yxh669@qq.com>
* @Date: 2023/11/3 16:23
*/
package router
import (
"context"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/tiger1103/gfast/v3/internal/app/wechat/controller"
)
func (router *Router) BindDemoController(ctx context.Context, group *ghttp.RouterGroup) {
group.Group("/demo", func(group *ghttp.RouterGroup) {
group.Bind(
controller.Demo,
)
})
}

View File

@ -0,0 +1,37 @@
/*
* @desc:扶苗工作路由
* @company:云南奇讯科技有限公司
* @Author: yixiaohu
* @Date: 2022/2/18 17:34
*/
package router
import (
"context"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/tiger1103/gfast/v3/internal/app/wechat/controller"
"github.com/tiger1103/gfast/v3/internal/app/wechat/service"
"github.com/tiger1103/gfast/v3/library/libRouter"
)
var R = new(Router)
type Router struct{}
func (router *Router) BindController(ctx context.Context, group *ghttp.RouterGroup) {
group.Group("/wechat", func(group *ghttp.RouterGroup) {
group.Bind(
//登录
controller.Login,
)
//登录验证拦截
service.GfToken().Middleware(group)
//context拦截器
group.Middleware(service.Middleware().Ctx)
//自动绑定定义的控制器
if err := libRouter.RouterAutoBind(ctx, router, group); err != nil {
panic(err)
}
})
}

View File

@ -0,0 +1,35 @@
// ================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// You can delete these comments if you wish manually maintain this interface file.
// ================================================================================
package service
import (
"context"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/tiger1103/gfast/v3/internal/app/system/model"
)
type IContext interface {
Init(r *ghttp.Request, customCtx *model.Context)
Get(ctx context.Context) *model.Context
SetUser(ctx context.Context, ctxUser *model.ContextUser)
GetLoginUser(ctx context.Context) *model.ContextUser
GetUserId(ctx context.Context) uint64
GetDeptId(ctx context.Context) uint64
}
var localContext IContext
func Context() IContext {
if localContext == nil {
panic("implement not found for interface IContext, forgot register?")
}
return localContext
}
func RegisterContext(i IContext) {
localContext = i
}

View File

@ -0,0 +1,27 @@
// ================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// You can delete these comments if you wish manually maintain this interface file.
// ================================================================================
package service
import (
"github.com/gogf/gf/v2/net/ghttp"
)
type IMiddleware interface {
Ctx(r *ghttp.Request)
}
var localMiddleware IMiddleware
func Middleware() IMiddleware {
if localMiddleware == nil {
panic("implement not found for interface IMiddleware, forgot register?")
}
return localMiddleware
}
func RegisterMiddleware(i IMiddleware) {
localMiddleware = i
}

View File

@ -0,0 +1,38 @@
/*
* @desc:token功能
* @company:云南奇讯科技有限公司
* @Author: yixiaohu
* @Date: 2022/3/8 15:54
*/
package service
import (
"context"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/tiger1103/gfast-token/gftoken"
)
type IGfToken interface {
GenerateToken(ctx context.Context, key string, data interface{}) (keys string, err error)
Middleware(group *ghttp.RouterGroup) error
ParseToken(r *ghttp.Request) (*gftoken.CustomClaims, error)
IsLogin(r *ghttp.Request) (b bool, failed *gftoken.AuthFailed)
GetRequestToken(r *ghttp.Request) (token string)
RemoveToken(ctx context.Context, token string) (err error)
GetTokenData(ctx context.Context, token string) (tData *gftoken.TokenData, key string, err error)
}
var gt IGfToken
func RegisterGToken(gtk IGfToken) {
gt = gtk
}
func GfToken() IGfToken {
if gt == nil {
panic("implement not found for interface IGfToken, forgot register?")
}
return gt
}

View File

@ -0,0 +1,37 @@
// ================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// You can delete these comments if you wish manually maintain this interface file.
// ================================================================================
package service
import (
"context"
"github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram/auth/response"
phoneNumberResp "github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram/phoneNumber/response"
)
type (
IWechat interface {
Session(ctx context.Context, code string) (data *response.ResponseCode2Session, err error)
GetUserPhoneNumber(ctx context.Context, code string) (data *phoneNumberResp.ResponseGetUserPhoneNumber, err error)
IsDebug(ctx context.Context)bool
GetWxUrl(ctx context.Context) (url string,err error)
}
)
var (
localWechat IWechat
)
func Wechat() IWechat {
if localWechat == nil {
panic("implement not found for interface IWechat, forgot register?")
}
return localWechat
}
func RegisterWechat(i IWechat) {
localWechat = i
}

View File

@ -9,5 +9,5 @@ package consts
const (
Logo = `CiAgIF9fX19fX19fX19fXyAgICAgICAgICAgX18gCiAgLyBfX19fLyBfX19fL19fXyBfX19fX18vIC9fCiAvIC8gX18vIC9fICAvIF9fIGAvIF9fXy8gX18vCi8gL18vIC8gX18vIC8gL18vIChfXyAgKSAvXyAgClxfX19fL18vICAgIFxfXyxfL19fX18vXF9fLyAg`
Version = "3.2.9"
Version = "3.2.10"
)

11
internal/router/wechat.go Normal file
View File

@ -0,0 +1,11 @@
package router
import (
"context"
"github.com/gogf/gf/v2/net/ghttp"
wechat "github.com/tiger1103/gfast/v3/internal/app/wechat/router"
)
func (router *Router) BindWechatModuleController(ctx context.Context, group *ghttp.RouterGroup) {
wechat.R.BindController(ctx, group)
}

View File

@ -0,0 +1,25 @@
gfToken:
cacheKey: "WechatGfToken:"
timeOut: 2592000 #30天
maxRefresh: 1296000
multiLogin: true
encryptKey: "49c54195e750b04e74a8429b17896586"
cacheModel: "redis"
excludePaths:
- "/api/v1/wechat/login"
wechat:
AppID: "wx54888472b36230aa"
Secret: "0f805412db892087ffc5c5c2f2ae80a5"
HttpDebug: false
AesKey: "zUfVSOan3B5ZZZZZZ66ixY6OrB28MTS9OIiBLaq3q2PhNG"
isDebug: true
isDebug2: true
Log:
Level: "debug"
File: "./resource/log/wechat/wechat.log"
Error: "./resource/log/wechat/error.log"
Cache:
Type: 1 #0使用内存 1使用redis
Addr: "127.0.0.1:6379"
Password: ""
DB: 0

File diff suppressed because one or more lines are too long

View File

@ -10,7 +10,7 @@
<template #header>
<div v-drag="['.{{.table.ModuleName}}-{{.table.BusinessName|CaseCamelLower}}-edit .el-dialog', '.{{.table.ModuleName}}-{{.table.BusinessName|CaseCamelLower}}-edit .el-dialog__header']">{{"{{"}}(!formData.{{.table.PkColumn.HtmlField}} || formData.{{.table.PkColumn.HtmlField}}==0?'添加':'修改')+'{{.table.FunctionName}}'{{"}}"}}</div>
</template>
<el-form ref="formRef" :model="formData" :rules="rules">
<el-form ref="formRef" :model="formData" :rules="rules" label-width="120px">
{{if .table.IsPkInsertable}}
<el-form-item label="{{.table.PkColumn.ColumnComment}}" prop="{{.table.PkColumn.HtmlField}}">
<el-input v-model="formData.{{.table.PkColumn.HtmlField}}" placeholder="请输入{{.table.PkColumn.ColumnComment}}" v-bind:disabled="this.currentOp === 'edit'" />

View File

@ -0,0 +1,795 @@
<template>
{{$lens := .table.Columns|len}}
{{$businessName := .table.BusinessName | CaseCamelLower}}
{{$treeParentCode := .table.TreeParentCode}}
{{$treeCode := .table.TreeCode}}
{{$treeName := .table.TreeName}}
{{$plugin:=""}}
{{if ContainsI $.table.PackageName "plugins"}}
{{$plugin = "plugins/"}}
{{end}}
<div class="{{.table.ModuleName}}-{{.table.BusinessName|CaseCamelLower}}-container">
<el-card shadow="hover">
<div class="{{.table.ModuleName}}-{{.table.BusinessName|CaseCamelLower}}-search mb15">
<el-form :model="tableData.param" ref="queryRef" :inline="true" label-width="100px">
<el-row>
{{$colIndex := 0}}
{{range $index, $column := .table.QueryColumns}}
{{if and $column.IsQuery (ne $column.ColumnName "created_by") (ne $column.ColumnName "updated_by")}}
{{if eq $colIndex 2}}
<el-col :span="8" :class="!showAll ? 'colBlock' : 'colNone'">
<el-form-item>
<el-button type="primary" @click="{{$businessName}}List"><el-icon><ele-Search /></el-icon>搜索</el-button>
<el-button @click="resetQuery(queryRef)"><el-icon><ele-Refresh /></el-icon>重置</el-button>
<el-button type="primary" link @click="toggleSearch">
{{"{{"}} word {{"}}"}}
<el-icon v-show="showAll"><ele-ArrowUp/></el-icon>
<el-icon v-show="!showAll"><ele-ArrowDown /></el-icon>
</el-button>
</el-form-item>
</el-col>
{{end}}
{{if eq $column.HtmlType "input" "textarea"}}
<el-col :span="8" {{if lt $colIndex 2}}class="colBlock"{{else}}:class="showAll ? 'colBlock' : 'colNone'"{{end}}>
<el-form-item label="{{$column.ColumnComment}}" prop="{{$column.HtmlField}}">
<el-input
v-model="tableData.param.{{$column.HtmlField}}{{if eq $column.QueryType "BETWEEN"}}[0]{{end}}"
placeholder="请输入{{$column.ColumnComment}}"
clearable
{{if eq $column.QueryType "BETWEEN"}}style="width:100px"{{end}}
@keyup.enter.native="{{$businessName}}List"
/>
{{if eq $column.QueryType "BETWEEN"}} -
<el-input
v-model="tableData.param.{{$column.HtmlField}}[1]"
placeholder="请输入{{$column.ColumnComment}}"
clearable
style="width:100px"
@keyup.enter.native="{{$businessName}}List"
/>
{{end}}
</el-form-item>
</el-col>
{{$colIndex = ($colIndex | plus 1)}}
{{else if and (eq $column.HtmlType "select" "radio" "checkbox" "selects") (ne $column.DictType "") }}
<el-col :span="8" {{if lt $colIndex 2}}class="colBlock"{{else}}:class="showAll ? 'colBlock' : 'colNone'"{{end}}>
<el-form-item label="{{$column.ColumnComment}}" prop="{{$column.HtmlField}}">
<el-select v-model="tableData.param.{{$column.HtmlField}}" placeholder="请选择{{$column.ColumnComment}}" clearable >
<el-option
v-for="dict in {{$column.DictType}}"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
{{$colIndex = ($colIndex | plus 1)}}
{{else if and (eq $column.HtmlType "treeSelect" "treeSelects") (ne $column.LinkTableName "")}}
<el-col :span="8" {{if lt $colIndex 2}}class="colBlock"{{else}}:class="showAll ? 'colBlock' : 'colNone'"{{end}}>
<el-form-item label="{{$column.ColumnComment}}" prop="{{$column.HtmlField}}">
{{$tLabel:=""}}
{{$tValue:=""}}
{{range $li,$lc := $.table.LinkedTables}}
{{if eq $lc.TableName $column.LinkTableName}}
{{$tLabel = $lc.OptionsStruct.TreeName}}
{{$tValue = $lc.OptionsStruct.TreeCode}}
{{end}}
{{end}}
<el-cascader
v-model="tableData.param.{{$column.HtmlField}}"
placeholder="请选择"
:options="{{$column.HtmlField}}Options"
filterable
clearable
:props="{ label: '{{$tLabel}}',value: '{{$tValue}}',checkStrictly: true,emitPath: false }"
/>
</el-form-item>
</el-col>
{{$colIndex = ($colIndex | plus 1)}}
{{else if eq $column.HtmlType "date"}}
<el-col :span="8" {{if lt $colIndex 2}}class="colBlock"{{else}}:class="showAll ? 'colBlock' : 'colNone'"{{end}}>
<el-form-item label="{{$column.ColumnComment}}" prop="{{$column.HtmlField}}">
<el-date-picker
clearable style="width: 200px"
v-model="tableData.param.{{$column.HtmlField}}"
value-format="YYYY-MM-DD"
{{if eq $column.QueryType "BETWEEN"}}
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
{{else}}
type="date"
placeholder="选择{{$column.ColumnComment}}"
{{end}}
></el-date-picker>
</el-form-item>
</el-col>
{{$colIndex = ($colIndex | plus 1)}}
{{else if eq $column.HtmlType "datetime"}}
<el-col :span="8" {{if lt $colIndex 2}}class="colBlock"{{else}}:class="showAll ? 'colBlock' : 'colNone'"{{end}}>
<el-form-item label="{{$column.ColumnComment}}" prop="{{$column.HtmlField}}">
<el-date-picker
clearable style="width: 200px"
v-model="tableData.param.{{$column.HtmlField}}"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
{{if eq $column.QueryType "BETWEEN"}}
type="datetimerange"
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
{{else}}
type="datetime"
placeholder="选择{{$column.ColumnComment}}"
{{end}}
></el-date-picker>
</el-form-item>
</el-col>
{{$colIndex = ($colIndex | plus 1)}}
{{else if and (eq $column.HtmlType "select" "radio" "checkbox" "selects") (ne $column.LinkTableName "")}}
<el-col :span="8" {{if lt $colIndex 2}}class="colBlock"{{else}}:class="showAll ? 'colBlock' : 'colNone'"{{end}}>
<el-form-item label="{{$column.ColumnComment}}" prop="{{$column.HtmlField}}">
<el-select v-model="tableData.param.{{$column.HtmlField}}" placeholder="请选择{{$column.ColumnComment}}" clearable {{if $column.IsCascadeParent}}@change="query{{$column.ColumnName | CaseCamel}}Changed"{{end}}>
<el-option
{{if $column.IsCascade}}
v-for="item in {{$column.HtmlField}}QueryOptions"
{{else}}
v-for="item in {{$column.HtmlField}}Options"
{{end}}
:key="item.key"
:label="item.value"
:value="item.key"
/>
</el-select>
</el-form-item>
</el-col>
{{$colIndex = ($colIndex | plus 1)}}
{{else if and (eq $column.HtmlType "treeSelect" "treeSelects") (ne $column.LinkTableName "")}}
<el-col :span="8" {{if lt $colIndex 2}}class="colBlock"{{else}}:class="showAll ? 'colBlock' : 'colNone'"{{end}}>
<el-form-item label="{{$column.ColumnComment}}" prop="{{$column.HtmlField}}">
{{$tLabel:=""}}
{{$tValue:=""}}
{{range $li,$lc := $.table.LinkedTables}}
{{if eq $lc.TableName $column.LinkTableName}}
{{$tLabel = $lc.OptionsStruct.TreeName}}
{{$tValue = $lc.OptionsStruct.TreeCode}}
{{end}}
{{end}}
<el-cascader
v-model="tableData.param.{{$column.HtmlField}}"
placeholder="请选择"
:options="{{$column.HtmlField}}Options"
filterable
clearable
:props="{ label: '{{$tLabel}}',value: '{{$tValue}}',checkStrictly: true,emitPath: false }"
/>
</el-form-item>
</el-col>
{{$colIndex = ($colIndex | plus 1)}}
{{else}}
<el-col :span="8" {{if lt $colIndex 2}}class="colBlock"{{else}}:class="showAll ? 'colBlock' : 'colNone'"{{end}}>
<el-form-item label="{{$column.ColumnComment}}" prop="{{$column.HtmlField}}">
<el-select v-model="tableData.param.{{$column.HtmlField}}" placeholder="请选择{{$column.ColumnComment}}" clearable >
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
</el-col>
{{$colIndex = ($colIndex | plus 1)}}
{{end}}
{{end}}
{{end}}
{{if gt $colIndex 2}}
<el-col :span="8" :class="showAll ? 'colBlock' : 'colNone'">
<el-form-item>
<el-button type="primary" @click="{{$businessName}}List"><el-icon><ele-Search /></el-icon>搜索</el-button>
<el-button @click="resetQuery(queryRef)"><el-icon><ele-Refresh /></el-icon>重置</el-button>
<el-button type="primary" link @click="toggleSearch">
{{"{{"}} word {{"}}"}}
<el-icon v-show="showAll"><ele-ArrowUp/></el-icon>
<el-icon v-show="!showAll"><ele-ArrowDown /></el-icon>
</el-button>
</el-form-item>
</el-col>
{{else}}
<el-col :span="8" class="colBlock">
<el-form-item>
<el-button type="primary" @click="{{$businessName}}List"><el-icon><ele-Search /></el-icon>搜索</el-button>
<el-button @click="resetQuery(queryRef)"><el-icon><ele-Refresh /></el-icon>重置</el-button>
</el-form-item>
</el-col>
{{end}}
</el-row>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
@click="handleAdd"
v-auth="'{{.apiVersion}}/{{.table.ModuleName}}/{{$businessName}}/add'"
><el-icon><ele-Plus /></el-icon>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
:disabled="single"
@click="handleUpdate(null)"
v-auth="'{{.apiVersion}}/{{.table.ModuleName}}/{{$businessName}}/edit'"
><el-icon><ele-Edit /></el-icon>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
:disabled="multiple"
@click="handleDelete(null)"
v-auth="'{{.apiVersion}}/{{.table.ModuleName}}/{{$businessName}}/delete'"
><el-icon><ele-Delete /></el-icon>删除</el-button>
</el-col>
</el-row>
</div>
<div style="height: 800px;">
<el-auto-resizer>
<template #default="{ height, width }">
<el-table-v2
v-model:expanded-row-keys="expandedRowKeys"
:columns="columns"
:data="treeData"
:width="width"
:height="height"
:expand-column-key="expandColumnKey"
fixed
@row-expand="onRowExpanded"
@expanded-rows-change="onExpandedRowsChange"
/>
</template>
</el-auto-resizer>
</div>
</el-card>
<{{$plugin}}{{if ne $plugin ""}}{{.apiVersion|replace "/" "_"|CaseCamel}}{{else}}{{.apiVersion|replace "/" "_"|CaseCamelLower}}{{end}}{{.table.ModuleName|CaseCamel}}{{.table.ClassName}}Edit
ref="editRef"
{{range $index, $column := .table.Columns}}
{{if ne $column.DictType ""}}
:{{$column.HtmlField}}Options="{{$column.DictType}}"
{{else if ne $column.LinkTableName ""}}
{{if $column.IsCascade}}
{{/*级联处理*/}}
{{else}}
{{/*关联表处理*/}}
:{{$column.HtmlField}}Options="{{$column.HtmlField}}Options"
{{end}}
{{end}}
{{end}}
:{{$businessName}}Options="tableData.data"
@{{$businessName}}List="{{$businessName}}List"
></{{$plugin}}{{if ne $plugin ""}}{{.apiVersion|replace "/" "_"|CaseCamel}}{{else}}{{.apiVersion|replace "/" "_"|CaseCamelLower}}{{end}}{{.table.ModuleName|CaseCamel}}{{.table.ClassName}}Edit>
<{{$plugin}}{{if ne $plugin ""}}{{.apiVersion|replace "/" "_"|CaseCamel}}{{else}}{{.apiVersion|replace "/" "_"|CaseCamelLower}}{{end}}{{.table.ModuleName|CaseCamel}}{{.table.ClassName}}Detail
ref="detailRef"
{{range $index, $column := .table.Columns}}
{{if ne $column.DictType ""}}
:{{$column.HtmlField}}Options="{{$column.DictType}}"
{{else if ne $column.LinkTableName ""}}
{{if $column.IsCascade}}
{{/*级联处理*/}}
{{else}}
{{/*关联表处理*/}}
:{{$column.HtmlField}}Options="{{$column.HtmlField}}Options"
{{end}}
{{end}}
{{end}}
:{{$businessName}}Options="tableData.data"
@{{$businessName}}List="{{$businessName}}List"
></{{$plugin}}{{if ne $plugin ""}}{{.apiVersion|replace "/" "_"|CaseCamel}}{{else}}{{.apiVersion|replace "/" "_"|CaseCamelLower}}{{end}}{{.table.ModuleName|CaseCamel}}{{.table.ClassName}}Detail>
</div>
</template>
<script lang="ts">
{{$tokenImp := false}}
{{$imgsImp := false}}
{{$editImp := false }}
{{$fileImp := false}}
{{$getUserList:=false}}
{{range $index,$column:=.table.Columns}}
{{if eq $column.HtmlType "richtext"}}
{{$editImp = true}}
{{else if eq $column.HtmlType "imagefile"}}
{{$tokenImp = true}}
{{else if eq $column.HtmlType "images"}}
{{$imgsImp = true}}
{{else if eq $column.HtmlType "file" "files"}}
{{$fileImp = true}}
{{end}}
{{if eq $column.HtmlField "createdBy" "updatedBy"}}
{{$getUserList = true}}
{{end}}
{{end}}
{{/*去重处理*/}}
{{$hasImports:=newArray}}
import {ItemOptions} from "/@/api/items";
import {toRefs, reactive, onMounted, ref, defineComponent, computed,getCurrentInstance,toRaw,h,unref,FunctionalComponent} from 'vue';
import {ElMessageBox, ElMessage, FormInstance,RowExpandHandler,ExpandedRowsChangeHandler,TableV2FixedDir, Column, ElLink, ElIcon, ElCheckbox, CheckboxValueType,ElImage,ElTag} from 'element-plus';
import { EditPen,View,DeleteFilled } from '@element-plus/icons-vue'
import {
list{{.table.ClassName}},
get{{.table.ClassName}},
del{{.table.ClassName}},
add{{.table.ClassName}},
update{{.table.ClassName}},
{{range $index,$column:= .table.Columns}}
{{if and $column.IsStatus $column.IsList}}
change{{$.table.ClassName}}{{$column.GoField}},
{{end}}
{{end}}
{{if gt (len .table.LinkedTables) 0}}
linkedDataSearch
{{end}}
} from "/@/api/{{$plugin}}{{.table.ModuleName}}/{{$businessName}}";
import {
{{.table.ClassName}}TableColumns,
{{.table.ClassName}}InfoData,
{{.table.ClassName}}TableDataState,
{{range $ti, $linkedTable := .table.LinkedTables}}
Linked{{$.table.ClassName}}{{$linkedTable.ClassName}},
{{end}}
} from "/@/views/{{$plugin}}{{.table.ModuleName}}/{{$businessName}}/list/component/model"
import {{$plugin}}{{if ne $plugin ""}}{{.apiVersion|replace "/" "_"|CaseCamel}}{{else}}{{.apiVersion|replace "/" "_"|CaseCamelLower}}{{end}}{{.table.ModuleName|CaseCamel}}{{.table.ClassName}}Edit from "/@/views/{{$plugin}}{{.table.ModuleName}}/{{$businessName}}/list/component/edit.vue"
import {{$plugin}}{{if ne $plugin ""}}{{.apiVersion|replace "/" "_"|CaseCamel}}{{else}}{{.apiVersion|replace "/" "_"|CaseCamelLower}}{{end}}{{.table.ModuleName|CaseCamel}}{{.table.ClassName}}Detail from "/@/views/{{$plugin}}{{.table.ModuleName}}/{{$businessName}}/list/component/detail.vue"
import _ from 'lodash'
export default defineComponent({
name: "{{$plugin}}{{if ne $plugin ""}}{{.apiVersion|replace "/" "_"|CaseCamel}}{{else}}{{.apiVersion|replace "/" "_"|CaseCamelLower}}{{end}}{{.table.ModuleName|CaseCamel}}{{.table.ClassName}}List",
components:{
{{$plugin}}{{if ne $plugin ""}}{{.apiVersion|replace "/" "_"|CaseCamel}}{{else}}{{.apiVersion|replace "/" "_"|CaseCamelLower}}{{end}}{{.table.ModuleName|CaseCamel}}{{.table.ClassName}}Edit,
{{$plugin}}{{if ne $plugin ""}}{{.apiVersion|replace "/" "_"|CaseCamel}}{{else}}{{.apiVersion|replace "/" "_"|CaseCamelLower}}{{end}}{{.table.ModuleName|CaseCamel}}{{.table.ClassName}}Detail
},
setup() {
const {proxy} = <any>getCurrentInstance()
const loading = ref(false)
const queryRef = ref()
const editRef = ref();
const detailRef = ref();
// 是否显示所有搜索选项
const showAll = ref(false)
// 非单个禁用
const single = ref(true)
// 非多个禁用
const multiple =ref(true)
const word = computed(()=>{
if(showAll.value === false) {
//对文字进行处理
return "展开搜索";
} else {
return "收起搜索";
}
})
// 字典选项数据
{{$dictArr:=newArray}}
{{range $index, $column := .table.Columns}}
{{if and (ne $column.DictType "") (ne (inArray $dictArr $column.DictType) true)}}
{{$dictArr = append $dictArr $column.DictType}}
{{end}}
{{end}}
const {
{{range $index, $column := $dictArr}}
{{$column}},
{{end}}
} = proxy.useDict(
{{range $index, $column := $dictArr}}
'{{$column}}',
{{end}}
)
{{range $index, $column := .table.Columns}}
{{if ne $column.LinkTableName ""}}
{{if $column.IsCascade }}
// {{$column.HtmlField}}QueryOptions关联表数据
const {{$column.HtmlField}}QueryOptions = ref<Array<ItemOptions>>([])
// {{$column.HtmlField}}FormOptions关联表数据
const {{$column.HtmlField}}FormOptions = ref<Array<ItemOptions>>([])
{{else}}
// {{$column.HtmlField}}Options关联表数据
const {{$column.HtmlField}}Options = ref<Array<ItemOptions>>([])
{{end}}
{{end}}
{{end}}
const dataList = ref<Array<{{$.table.ClassName}}TableColumns>>([])
const state = reactive<{{.table.ClassName}}TableDataState>({
{{.table.PkColumn.HtmlField}}s:[],
tableData: {
data: [],
total: 0,
loading: false,
param: {
pageNum: 1,
pageSize: 10,
{{range $index, $column := .table.QueryColumns}}
{{if eq $column.QueryType "BETWEEN"}}
{{$column.HtmlField}}: [],
{{else}}
{{$column.HtmlField}}: undefined,
{{end}}{{end}}
dateRange: []
},
},
});
// 页面加载时
onMounted(() => {
initTableData();
});
// 初始化表格数据
const initTableData = () => {
{{if gt (len .table.LinkedTables) 0}}
linkedData()
{{end}}
{{$businessName}}List()
};
{{if gt (len .table.LinkedTables) 0}}
const linkedData = ()=>{
linkedDataSearch().then((res:any)=>{
{{range $index, $column := .table.Columns}}
{{if ne $column.LinkTableName ""}}
//关联{{$column.LinkTableName}}表选项
{{range $li,$lc := $.table.LinkedTables}}
{{if eq $lc.TableName $column.LinkTableName}}
{{if eq $lc.TplCategory "tree"}}
{{$column.HtmlField}}Options.value = proxy.handleTree(res.data.linked{{$.table.ClassName}}{{$column.LinkTableClass}}, '{{$lc.OptionsStruct.TreeCode}}', '{{$lc.OptionsStruct.TreeParentCode}}')
{{else}}
{{$column.HtmlField}}Options.value = proxy.setItems(res, '{{$column.LinkLabelId | CaseCamelLower}}', '{{$column.LinkLabelName | CaseCamelLower}}','linked{{$.table.ClassName}}{{$column.LinkTableClass}}')
{{end}}
{{end}}
{{end}}
{{end}}
{{end}}
})
}
{{end}}
/** 重置按钮操作 */
const resetQuery = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
{{$businessName}}List()
};
// 获取列表数据
const {{$businessName}}List = ()=>{
loading.value = true
list{{.table.ClassName}}(state.tableData.param).then((res:any)=>{
let list = res.data.list??[];
{{range $index,$column := .table.ListColumns}}
{{if eq $column.HtmlField "createdBy" "updatedBy"}}
list.map((item:any)=>{
{{if eq $column.HtmlField "createdBy"}}
item.createdBy = item?.createdUser.userNickname
{{end}}
{{if eq $column.HtmlField "updatedBy"}}
item.updatedBy = item?.updatedUser.userNickname
{{end}}
})
{{end}}
{{end}}
dataList.value = _.clone(res.data.list)
list = proxy.handleTree(res.data.list||[], "{{$treeCode}}", "{{$treeParentCode}}");
state.tableData.data = list;
loading.value = false
setVrData(list)
})
};
const toggleSearch = () => {
showAll.value = !showAll.value;
}
{{range $index, $column := .table.Columns}}
{{if ne $column.DictType ""}}
{{if eq $column.HtmlType "checkbox"}}
// {{$column.ColumnComment}}字典翻译
const {{$column.HtmlField}}Format = (row:{{$.table.ClassName}}TableColumns) => {
let {{$column.HtmlField}} = row.{{$column.HtmlField}}.split(",")
let data:Array<string> = [];
{{$column.HtmlField}}.map(item=>{
data.push(proxy.selectDictLabel({{$column.DictType}}.value, item))
})
return data.join(",")
}
{{else}}
// {{$column.ColumnComment}}字典翻译
const {{$column.HtmlField}}Format = (row:{{$.table.ClassName}}TableColumns) => {
return proxy.selectDictLabel({{$column.DictType}}.value, row.{{$column.HtmlField}});
}
{{end}}
{{end}}
{{end}}
// 多选框选中数据
const handleSelectionChange = (selection:Array<{{.table.ClassName}}InfoData>) => {
state.{{.table.PkColumn.HtmlField}}s = selection.map(item => item.{{.table.PkColumn.HtmlField}})
single.value = selection.length!=1
multiple.value = !selection.length
}
const handleAdd = ()=>{
editRef.value.openDialog()
}
const handleUpdate = (row: {{$.table.ClassName}}TableColumns) => {
if(!row){
row = dataList.value.find((item:{{$.table.ClassName}}TableColumns)=>{
return item.{{.table.PkColumn.HtmlField}} ===state.{{.table.PkColumn.HtmlField}}s[0]
}) as {{$.table.ClassName}}TableColumns
}
editRef.value.openDialog(toRaw(row));
};
const handleDelete = (row: {{$.table.ClassName}}TableColumns) => {
let msg = '你确定要删除所选数据?';
let {{.table.PkColumn.HtmlField}}:number[] = [] ;
if(row){
msg = `此操作将永久删除数据,是否继续?`
{{.table.PkColumn.HtmlField}} = [row.{{.table.PkColumn.HtmlField}}]
}else{
{{.table.PkColumn.HtmlField}} = state.{{.table.PkColumn.HtmlField}}s
}
if({{.table.PkColumn.HtmlField}}.length===0){
ElMessage.error('请选择要删除的数据。');
return
}
ElMessageBox.confirm(msg, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
del{{.table.ClassName}}({{.table.PkColumn.HtmlField}}).then(()=>{
ElMessage.success('删除成功');
{{$businessName}}List();
})
})
.catch(() => {});
}
const handleView = (row:{{$.table.ClassName}}TableColumns)=>{
detailRef.value.openDialog(toRaw(row));
}
//========================================================================================================
const columns = ref<Column[]>([])
const treeData = ref<any[]>([])
type SelectionCellProps = {
value: boolean
intermediate?: boolean
onChange: (value: CheckboxValueType) => void
}
const SelectionCell: FunctionalComponent<SelectionCellProps> = ({
value,
intermediate = false,
onChange,
}) => {
return h(ElCheckbox,{modelValue:value,indeterminate:intermediate,onChange:onChange})
}
const setVrData = (list:{{$.table.ClassName}}TableColumns[])=>{
const _columns:any[] = [
{key: 'selection',dataKey: '{{.table.PkColumn.HtmlField}}',title: ``,width:80,
{{if .table.PkColumn.IsFixed}}fixed: TableV2FixedDir.LEFT,{{end}}
headerCellRenderer:()=>{
let _data = unref(dataList.value)
const onChange = (value: CheckboxValueType) =>{
_data = _data.map((row:any) => {
row.checked = value
return row
})
treeData.value = proxy.handleTree(_data||[], "{{$treeCode}}", "{{$treeParentCode}}")
state.{{.table.PkColumn.HtmlField}}s = _data.map((item:any) => {
if(item.checked){
return item.{{.table.PkColumn.HtmlField}}
}
}).filter(item=>item!==undefined)
single.value = state.{{.table.PkColumn.HtmlField}}s.length!=1
multiple.value = !state.{{.table.PkColumn.HtmlField}}s.length
}
const allSelected = _data.every((row:any) => row.checked)
const containsChecked = _data.some((row:any) => row.checked)
return h(ElCheckbox,{value:allSelected,intermediate:containsChecked && !allSelected,onChange:onChange})
},
cellRenderer:({rowData: row})=>{
return h(SelectionCell, {value:row.checked,intermediate:false,onChange:(v:CheckboxValueType)=>{
row.checked=v
if(v){
state.{{.table.PkColumn.HtmlField}}s.push(row.{{.table.PkColumn.HtmlField}})
state.{{.table.PkColumn.HtmlField}}s = [...new Set(state.{{.table.PkColumn.HtmlField}}s)]
}else{
state.{{.table.PkColumn.HtmlField}}s = state.{{.table.PkColumn.HtmlField}}s.filter(item=>item!==row.{{.table.PkColumn.HtmlField}})
}
single.value = state.{{.table.PkColumn.HtmlField}}s.length!=1
multiple.value = !state.{{.table.PkColumn.HtmlField}}s.length
}
})
}
}
]
{{range $index, $column := .table.ListColumns}}
{{if $column.IsPk}}
_columns.push({key: '{{$column.HtmlField}}',dataKey: '{{$column.HtmlField}}',title: `{{$column.ColumnComment}}`,
{{if gt $column.MinWidth 0}}width:{{$column.MinWidth}},{{end}}
{{if $column.IsFixed}}fixed: TableV2FixedDir.LEFT,{{end}}
})
{{else if eq $column.HtmlType "date"}}
_columns.push({key: '{{$column.HtmlField}}',dataKey: '{{$column.HtmlField}}',title: `{{$column.ColumnComment}}`,
{{if gt $column.MinWidth 0}}width:{{$column.MinWidth}},{{end}}
{{if $column.IsFixed}}fixed: TableV2FixedDir.LEFT,{{end}}
cellRenderer: ({ cellData: {{$column.HtmlField}} }) => {
return h('span', proxy.parseTime({{$column.HtmlField}}, '{y}-{m}-{d}'));
}
})
{{else if eq $column.HtmlType "datetime"}}
_columns.push({key: '{{$column.HtmlField}}',dataKey: '{{$column.HtmlField}}',title: `{{$column.ColumnComment}}`,
{{if gt $column.MinWidth 0}}width:{{$column.MinWidth}},{{end}}
{{if $column.IsFixed}}fixed: TableV2FixedDir.LEFT,{{end}}
cellRenderer: ({ cellData: {{$column.HtmlField}} }) => {
return h('span', proxy.parseTime({{$column.HtmlField}}, '{y}-{m}-{d} {h}:{i}:{s}'));
}
})
{{else if eq $column.HtmlField "createdBy"}}
_columns.push({key: '{{$column.HtmlField}}',dataKey: '{{$column.HtmlField}}',title: `{{$column.ColumnComment}}`,
{{if gt $column.MinWidth 0}}width:{{$column.MinWidth}},{{end}}
{{if $column.IsFixed}}fixed: TableV2FixedDir.LEFT,{{end}}
})
{{else if eq $column.HtmlField "updatedBy"}}
_columns.push({key: '{{$column.HtmlField}}',dataKey: '{{$column.HtmlField}}',title: `{{$column.ColumnComment}}`,
{{if gt $column.MinWidth 0}}width:{{$column.MinWidth}},{{end}}
{{if $column.IsFixed}}fixed: TableV2FixedDir.LEFT,{{end}}
})
{{else if eq $column.HtmlType "imagefile"}}
_columns.push({key: '{{$column.HtmlField}}',dataKey: '{{$column.HtmlField}}',title: `{{$column.ColumnComment}}`,
{{if gt $column.MinWidth 0}}width:{{$column.MinWidth}},{{end}}
{{if $column.IsFixed}}fixed: TableV2FixedDir.LEFT,{{end}}
cellRenderer: ({cellData: {{$column.HtmlField}} }) => {
const children = []
if(!proxy.isEmpty({{$column.HtmlField}})){
children.push(h(ElImage,{fit:'contain',style:'width:50px;height:50px',src:proxy.getUpFileUrl({{$column.HtmlField}})}))
}
return ('div',children)
}
})
{{else if eq $column.HtmlType "selects" "checkbox" "treeSelects"}}
{{if ne $column.LinkTableName ""}}
_columns.push({key: '{{$column.HtmlField}}',dataKey: '{{$column.HtmlField}}',title: `{{$column.ColumnComment}}`,
{{if gt $column.MinWidth 0}}width:{{$column.MinWidth}},{{end}}
{{if $column.IsFixed}}fixed: TableV2FixedDir.LEFT,{{end}}
cellRenderer: ({cellData: {{$column.HtmlField}} }) => {
const children = []
if(linked{{$column.GoField}}){
linked{{$column.GoField}}.map(item=>{
children.push(h(ElTag,{class:"ml-2",type:'success'},[item.{{$column.LinkLabelName|CaseCamelLower}}]))
})
}
return ('div',children)
}
})
{{else if ne $column.DictType ""}}
_columns.push({key: '{{$column.HtmlField}}',dataKey: '{{$column.HtmlField}}',title: `{{$column.ColumnComment}}`,
{{if gt $column.MinWidth 0}}width:{{$column.MinWidth}},{{end}}
{{if $column.IsFixed}}fixed: TableV2FixedDir.LEFT,{{end}}
cellRenderer: ({rowData:row}) => {
return ('span',[{{$column.HtmlField}}Format(row)])
}
})
{{end}}
{{else if ne $column.LinkTableName ""}}
_columns.push({key: '{{$column.HtmlField}}',dataKey: 'linked{{$column.GoField}}.{{$column.LinkLabelName | CaseCamelLower}}',title: `{{$column.ColumnComment}}`,
{{if gt $column.MinWidth 0}}width:{{$column.MinWidth}},{{end}}
{{if $column.IsFixed}}fixed: TableV2FixedDir.LEFT,{{end}}
})
{{else if ne $column.DictType ""}}
_columns.push({key: '{{$column.HtmlField}}',dataKey: '{{$column.HtmlField}}',title: `{{$column.ColumnComment}}`,
{{if gt $column.MinWidth 0}}width:{{$column.MinWidth}},{{end}}
{{if $column.IsFixed}}fixed: TableV2FixedDir.LEFT,{{end}}
cellRenderer: ({rowData:row}) => {
return ('span',[{{$column.HtmlField}}Format(row)])
}
})
{{else if ne $column.HtmlField ""}}
_columns.push({key: '{{$column.HtmlField}}',dataKey: '{{$column.HtmlField}}',title: `{{$column.ColumnComment}}`,
{{if gt $column.MinWidth 0}}width:{{$column.MinWidth}},{{end}}
{{if $column.IsFixed}}fixed: TableV2FixedDir.LEFT,{{end}}
})
{{end}}
{{end}}
_columns.push({key: 'operations',dataKey: '{{$.table.PkColumn.HtmlField}}',title: `操作`,width:200,fixed: TableV2FixedDir.RIGHT,
cellRenderer: ({rowData:row,cellData:{{$.table.PkColumn.HtmlField}}}) => {
return h('div',{class:'tb-operations'},[
h(ElLink, { type: 'primary',underline:false, onClick: () => { handleView(row) } },
() => [
h(ElIcon, () => [h(View)]),
'详情'
],
),
h(ElLink, { type: 'primary',underline:false, onClick: () => { handleUpdate(row) } },
() => [
h(ElIcon, () => [h(EditPen)]),
'修改'
],
),
h(ElLink, { type: 'primary',underline:false, onClick: () => { handleDelete(row) } },
() => [
h(ElIcon, () => [h(DeleteFilled)]),
'删除'
],
)
])
}
})
columns.value = _columns
treeData.value = list
}
//=============================================================================================================
const expandColumnKey = '{{$treeCode}}'
const expandedRowKeys = ref<string[]>([])
const onRowExpanded = (exp: Parameters<RowExpandHandler<any>>[0]) => {
console.log('Expanded:', exp)
}
const onExpandedRowsChange = (
expandedKeys: Parameters<ExpandedRowsChangeHandler>[0]
) => {
console.log('expandedKeys:',expandedKeys)
}
return {
proxy,
editRef,
detailRef,
showAll,
loading,
single,
multiple,
word,
queryRef,
resetQuery,
{{$businessName}}List,
toggleSearch,
{{range $index, $column := .table.Columns}}
{{if ne $column.DictType ""}}
{{$column.HtmlField}}Format,
{{$column.DictType}},
{{end}}
{{if ne $column.LinkTableName ""}}
{{if $column.IsCascade}}
//级联关联{{$column.LinkTableName}}表选项
{{else}}
//关联表数据选项
{{$column.HtmlField}}Options,
//关联{{$column.LinkTableName}}表选项获取数据方法
{{end}}
{{end}}
{{end}}
handleSelectionChange,
handleAdd,
handleUpdate,
handleDelete,
{{if eq .table.ShowDetail "true"}}
handleView,
{{end}}
columns,
treeData,
expandedRowKeys,
onRowExpanded,
expandColumnKey,
onExpandedRowsChange,
...toRefs(state),
}
}
})
</script>
<style lang="scss" scoped>
.colBlock {
display: block;
}
.colNone {
display: none;
}
:deep(.tb-operations .el-link){
margin-left: 12px;
.el-icon{
margin-right: 5px;
}
}
</style>