diff --git a/Dockerfile b/Dockerfile index 815e2bb..afa480d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,6 @@ RUN go env -w GO111MODULE=on \ FROM alpine:latest -LABEL MAINTAINER="SliverHorn@sliver_horn@qq.com" # 设置时区 ENV TZ=Asia/Shanghai RUN apk update && apk add --no-cache tzdata openntpd \ diff --git a/config.docker.yaml b/config.docker.yaml index c1af7e0..51f0e10 100644 --- a/config.docker.yaml +++ b/config.docker.yaml @@ -16,12 +16,29 @@ zap: encode-level: LowercaseColorLevelEncoder stacktrace-key: stacktrace log-in-console: true + retention-day: -1 # redis configuration redis: + name: "hw" + addr: 120.46.165.63:6379 + password: "loser765911" db: 0 - addr: 177.7.0.14:6379 - password: "" + useCluster: false + clusterAddrs: + - 172.21.0.3:7000 + - 172.21.0.4:7001 + - 172.21.0.2:7002 +redis-list: + - name: cache + addr: 120.46.165.63:6379 + password: "loser765911" + db: 1 + useCluster: false + clusterAddrs: + - 172.21.0.3:7000 + - 172.21.0.4:7001 + - 172.21.0.2:7002 # mongo configuration mongo: @@ -30,6 +47,7 @@ mongo: database: '' username: '' password: '' + auth-source: '' min-pool-size: 0 max-pool-size: 100 socket-timeout-ms: 0 @@ -51,21 +69,25 @@ email: # system configuration system: - env: public # Change to "develop" to skip authentication for development mode + env: local # 修改为public可以关闭路由日志输出 addr: 8888 db-type: mysql - oss-type: local # 控制oss选择走本地还是 七牛等其他仓 自行增加其他oss仓可以在 server/utils/upload/upload.go 中 NewOss函数配置 - use-redis: false # 使用redis + oss-type: aliyun-oss # 控制oss选择走本地还是 七牛等其他仓 自行增加其他oss仓可以在 server/utils/upload/upload.go 中 NewOss函数配置 + use-redis: true # 使用redis use-mongo: false # 使用mongo use-multipoint: false # IP限制次数 一个小时15000次 iplimit-count: 15000 # IP限制一个小时 iplimit-time: 3600 + # 路由全局前缀 + router-prefix: "" + # 严格角色模式 打开后权限将会存在上下级关系 + use-strict-auth: false # captcha configuration captcha: - key-long: 6 + key-long: 4 img-width: 240 img-height: 80 open-captcha: 0 # 0代表一直开启,大于0代表限制次数 @@ -74,16 +96,19 @@ captcha: # mysql connect configuration # 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://gin-vue-admin.com/docs/first_master) mysql: - path: "" - port: "" - config: "" - db-name: "" - username: "" - password: "" + prefix: "" + port: "3366" + config: charset=utf8mb4&parseTime=True&loc=Local + db-name: lckt + username: lckt + password: loser765911. + path: 219.152.55.29 + engine: "" + log-mode: info max-idle-conns: 10 max-open-conns: 100 - log-mode: "" - log-zap: false + singular: false + log-zap: true # pgsql connect configuration # 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://gin-vue-admin.com/docs/first_master) @@ -98,10 +123,42 @@ pgsql: max-open-conns: 100 log-mode: "" log-zap: false - +oracle: + path: "" + port: "" + config: "" + db-name: "" + username: "" + password: "" + max-idle-conns: 10 + max-open-conns: 100 + log-mode: "" + log-zap: false +mssql: + path: "" + port: "" + config: "" + db-name: "" + username: "" + password: "" + max-idle-conns: 10 + max-open-conns: 100 + log-mode: "" + log-zap: false +sqlite: + path: "" + port: "" + config: "" + db-name: "" + username: "" + password: "" + max-idle-conns: 10 + max-open-conns: 100 + log-mode: "" + log-zap: false db-list: - disable: true # 是否禁用 - type: "" # 数据库的类型,目前支持mysql、pgsql + type: "" # 数据库的类型,目前支持mysql、pgsql、mssql、oracle alias-name: "" # 数据库的名称,注意: alias-name 需要在db-list中唯一 path: "" port: "" @@ -114,7 +171,6 @@ db-list: log-mode: "" log-zap: false - # local configuration local: path: uploads/file @@ -122,22 +178,11 @@ local: # autocode configuration autocode: - transfer-restart: true - # root 自动适配项目根目录 - # 请不要手动配置,他会在项目加载的时候识别出根路径 - root: "" - server: /server - server-plug: /plugin/%s - server-api: /api/v1/%s - server-initialize: /initialize - server-model: /model/%s - server-request: /model/%s/request/ - server-router: /router/%s - server-service: /service/%s - web: /web/src - web-api: /api - web-form: /view - web-table: /view + web: web/src + root: "" # root 自动适配项目根目录, 请不要手动配置,他会在项目加载的时候识别出根路径 + server: /lckt-server + module: 'git.echol.cn/loser/lckt' + ai-path: "https://ai.gin-vue-admin.com/{FUNC}/loser7659/c178e970-6a59-497d-96ed-86fee6b3285a" # AI服务路径 # qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址) qiniu: @@ -149,14 +194,24 @@ qiniu: secret-key: "" use-cdn-domains: false -# aliyun oss configuration -aliyun-oss: +# minio oss configuration +minio: endpoint: yourEndpoint access-key-id: yourAccessKeyId access-key-secret: yourAccessKeySecret bucket-name: yourBucketName - bucket-url: yourBucketUrl - base-path: yourBasePath + use-ssl: false + base-path: "" + bucket-url: "http://host:9000/yourBucketName" + +# aliyun oss configuration +aliyun-oss: + endpoint: oss-cn-hangzhou.aliyuncs.com + access-key-id: LTAI5tB3Mn5Y7mVo8h3zkf46 + access-key-secret: FtuHdFy4NFdVItEiNBnTun3Ddi8BMK + bucket-name: lckt + bucket-url: https://lckt.oss-cn-hangzhou.aliyuncs.com + base-path: lckt # tencent cos configuration tencent-cos: @@ -179,6 +234,15 @@ aws-s3: base-url: https://gin.vue.admin path-prefix: git.echol.cn/loser/lckt +# cloudflare r2 configuration +cloudflare-r2: + bucket: xxxx0bucket + base-url: https://gin.vue.admin.com + path: uploads + account-id: xxx_account_id + access-key-id: xxx_key_id + secret-access-key: xxx_secret_key + # huawei obs configuration hua-wei-obs: path: you-path @@ -191,30 +255,55 @@ hua-wei-obs: excel: dir: ./resource/excel/ -# timer task db clear table -Timer: - start: true - spec: "@daily" # 定时任务详细配置参考 https://pkg.go.dev/github.com/robfig/cron/v3 - detail: - - tableName: sys_operation_records - compareField: created_at - interval: 2160h - - tableName: jwt_blacklists - compareField: created_at - interval: 168h +# disk usage configuration +disk-list: + - mount-point: "/" # 跨域配置 # 需要配合 server/initialize/router.go -> `Router.Use(middleware.CorsByRules())` 使用 cors: - mode: whitelist # 放行模式: allow-all, 放行全部; whitelist, 白名单模式, 来自白名单内域名的请求添加 cors 头; strict-whitelist 严格白名单模式, 白名单外的请求一律拒绝 + mode: allow-all # 放行模式: allow-all, 放行全部; whitelist, 白名单模式, 来自白名单内域名的请求添加 cors 头; strict-whitelist 严格白名单模式, 白名单外的请求一律拒绝 whitelist: - allow-origin: example1.com - allow-headers: content-type - allow-methods: GET, POST + allow-headers: Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id + allow-methods: POST, GET expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type + allow-credentials: true # 布尔值 - allow-origin: example2.com allow-headers: content-type allow-methods: GET, POST expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type - allow-credentials: true # 布尔值 \ No newline at end of file + allow-credentials: true # 布尔值 +mcp: + name: GVA_MCP + version: v1.0.0 + sse_path: /sse + message_path: /message + url_prefix: '' + +wechat: + app-id: wx3d21df18d7f8f9fc + app-secret: 3ab19e9b6a5e155c25ac6457be650047 + token: kjeldcsdz2phfwfxnevsajnzsboho1ev + aes-key: PiqqlGdEblw5Gv1RJ5qcTnhKUjFw9YNkBMAX6CIw6Me + callback: https://api.gin-vue-admin.com/wechat/callback +pay-list: + - type: wxpay + alias-name: wxpay-1 + app-id: wx3d21df18d7f8f9fc + mch-id: 1646874753 + v3-key: 1a3sd8561d5179Df152D4789aD38wG9s + cert-path: /resource/cert/apiclient_cert.pem + key-path: /resource/cert/apiclient_key.pem + notify-url: http://lckt.hnlc5588.cn/app_order/notify + serial-no: 59A891FB403EC7A1CF2090DB9C8EC704BD43B101 + - type: wxpay2 + alias-name: wxpay-2 + app-id: 2 + mch-id: 2 + v3-key: 2 + cert-path: 2 + key-path: 2 + notify-url: 2 + serial-no: 2 \ No newline at end of file diff --git a/utils/upload/local_upload.go b/utils/upload/local_upload.go new file mode 100644 index 0000000..500c92a --- /dev/null +++ b/utils/upload/local_upload.go @@ -0,0 +1,157 @@ +package upload + +// UploadOSS OSS对象存储接口 +import ( + "errors" + "fmt" + "github.com/aliyun/aliyun-oss-go-sdk/oss" + "io/ioutil" + "os" + "strings" +) + +type Worker struct { + in chan string + done chan bool +} + +type Uploads struct { +} + +const endpoint = "oss-cn-hangzhou.aliyuncs.com" // oss endpoint +const accessKeyId = "LTAI5tB3Mn5Y7mVo8h3zkf46" // oss key +const accessKeySecret = "FtuHdFy4NFdVItEiNBnTun3Ddi8BMK" //oss secret +const bucketName = "lckt" //oss bucket名称 +const objectName = "avatar/" //oss远程目标地址 +const workerCount = 100 //设置最大并发数 +const suffix = "" //筛选目录下需要上传的格式 + +// 上传单个文件 +func (u *Uploads) UploadOne(path string) { + // 创建OSSClient实例。 + localFileName := path + split := strings.Split(localFileName, `\`) + length := len(split) + fileName := split[length-1 : length] + + client, err := oss.New(endpoint, accessKeyId, accessKeySecret) + if err != nil { + handleError(err) + } + // 获取存储空间。 + bucket, err := client.Bucket(bucketName) + if err != nil { + handleError(err) + } + up(bucket, objectName+fileName[0], localFileName) +} +func createWorker(bucket *oss.Bucket, objectName string, id int) Worker { + w := Worker{ + in: make(chan string), + done: make(chan bool), + } + go doWork(id, w.in, w.done, bucket, objectName) + return w +} + +// 并发上传目录下所有文件 +func (u *Uploads) UploadMany(path string) { + files, err := getAllFiles(path) + if err != nil { + handleError(err) + } + fileCount := len(files) + if fileCount == 0 { + handleError(errors.New("目录下没有指定文件,请重试!")) + } + client, err := oss.New(endpoint, accessKeyId, accessKeySecret) + if err != nil { + handleError(err) + } + bucket, err := client.Bucket(bucketName) + if err != nil { + handleError(err) + } + var workers [workerCount]Worker + for i := 0; i < fileCount; i++ { + workers[i] = createWorker(bucket, objectName, i) + } + for i := 0; i < fileCount; i++ { + workers[i].in <- files[i] + } + for i := 0; i < fileCount; i++ { + <-workers[i].done + } +} + +func handleError(err error) { + fmt.Println("Error:", err) + os.Exit(-1) +} + +func up(bucket *oss.Bucket, objectName string, localFileName string) { + // 上传文件。 + err := bucket.PutObjectFromFile(objectName, localFileName) + if err != nil { + handleError(err) + } +} + +func doWork(id int, c chan string, done chan bool, bucket *oss.Bucket, objectName string) { + for n := range c { + split := strings.Split(n, `\`) + length := len(split) + fileName := split[length-1 : length] + fmt.Printf("worker : %d, object: %s, uploading file %v \n", id, objectName, n) + up(bucket, objectName+fileName[0], n) + go func() { done <- true }() + } +} + +// 获取指定目录下的所有文件,包含子目录下的文件 +func getAllFiles(dirPth string) (files []string, err error) { + var dirs []string + dir, err := ioutil.ReadDir(dirPth) + if err != nil { + return nil, err + } + PthSep := string(os.PathSeparator) + for _, fi := range dir { + if fi.IsDir() { // 目录, 递归遍历 + dirs = append(dirs, dirPth+PthSep+fi.Name()) + getAllFiles(dirPth + PthSep + fi.Name()) + } else { + // 过滤指定格式 + if suffix != "" { + ok := strings.HasSuffix(fi.Name(), suffix) + if ok { + files = append(files, dirPth+PthSep+fi.Name()) + } + } else { + files = append(files, dirPth+PthSep+fi.Name()) + } + } + } + + return files, nil +} + +func InitOss() (*oss.Bucket, error) { + // 创建OSSClient实例。 + AccessKeyId := "LTAI5tB3Mn5Y7mVo8h3zkf46" + AccessKeySecret := "FtuHdFy4NFdVItEiNBnTun3Ddi8BMK" + Endpoint := "oss-cn-hangzhou.aliyuncs.com" + BucketName := "lckt" + client, err := oss.New(Endpoint, AccessKeyId, AccessKeySecret) + if err != nil { + return nil, err + } + + // 获取存储空间。 + bucket, err := client.Bucket(BucketName) + if err != nil { + return nil, err + } + + return bucket, nil +}