diff --git a/.gitea/workflows/build-push.yml b/.gitea/workflows/build-push.yml index a9b11fa..836c0da 100644 --- a/.gitea/workflows/build-push.yml +++ b/.gitea/workflows/build-push.yml @@ -1,24 +1,24 @@ -name: Build image -on: [push] -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: http://192.168.31.55:13000/timerzz/setup-go@v4 - env: - HTTPS_PROXY: http://192.168.31.55:10809 - with: - go-version: '1.22.x' - - uses: http://192.168.31.55:13000/timerzz/checkout@v4 - - uses: http://192.168.31.55:13000/timerzz/setup-ko@v0.6 - with: - version: v0.15.4 - env: - KO_DOCKER_REPO: 192.168.31.55:5000/kedaya/article - HTTP_PROXY: http://192.168.31.55:10809 - HTTPS_PROXY: http://192.168.31.55:10809 - - run: ko build --bare ./cmd - env: - KO_DOCKER_REPO: 192.168.31.55:5000/kedaya/article - HTTP_PROXY: http://192.168.31.55:10809 +name: Build image +on: [push] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: http://192.168.31.55:13000/timerzz/setup-go@v4 + env: + HTTPS_PROXY: http://192.168.31.55:10809 + with: + go-version: '1.22.x' + - uses: http://192.168.31.55:13000/timerzz/checkout@v4 + - uses: http://192.168.31.55:13000/timerzz/setup-ko@v0.6 + with: + version: v0.15.4 + env: + KO_DOCKER_REPO: 192.168.31.55:5000/kedaya/article + HTTP_PROXY: http://192.168.31.55:10809 + HTTPS_PROXY: http://192.168.31.55:10809 + - run: ko build --bare ./cmd + env: + KO_DOCKER_REPO: 192.168.31.55:5000/kedaya/article + HTTP_PROXY: http://192.168.31.55:10809 HTTPS_PROXY: http://192.168.31.55:10809 \ No newline at end of file diff --git a/.ko.yaml b/.ko.yaml index b6cf940..877574e 100644 --- a/.ko.yaml +++ b/.ko.yaml @@ -1,16 +1,16 @@ -defaultPlatforms: - - linux/amd64 -defaultBaseImage: alpine:latest -builds: - - id: article - dir: . # default is . - main: ./cmd - env: - - CGO_ENABLED=0 - - GOPROXY=https://goproxy.cn,direct - - GOPRIVATE=gitea.timerzz.com - - GONOSUMDB=gitea.timerzz.com - - GONOPROXY=gitea.timerzz.com - ldflags: - - -s -w - - -extldflags "-static" +defaultPlatforms: + - linux/amd64 +defaultBaseImage: alpine:latest +builds: + - id: article + dir: . # default is . + main: ./cmd + env: + - CGO_ENABLED=0 + - GOPROXY=https://goproxy.cn,direct + - GOPRIVATE=gitea.timerzz.com + - GONOSUMDB=gitea.timerzz.com + - GONOPROXY=gitea.timerzz.com + ldflags: + - -s -w + - -extldflags "-static" diff --git a/build/build-chart.sh b/build/build-chart.sh new file mode 100644 index 0000000..179eccc --- /dev/null +++ b/build/build-chart.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# 打包 Helm Chart +helm package chart/ + +# 获取最新生成的包名 +chart_package=$(ls -t *.tgz | head -n 1) + +# 推送 Helm Chart 到 OCI 仓库 +helm push $chart_package oci://registry.timerzz.com:20443/helm-charts + +# 删除生成的包 +rm -f $chart_package \ No newline at end of file diff --git a/build/chart/.helmignore b/build/chart/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/build/chart/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/build/chart/Chart.yaml b/build/chart/Chart.yaml new file mode 100644 index 0000000..70ea9b5 --- /dev/null +++ b/build/chart/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: article +description: 可达鸭海淘商品后端 + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 1.0.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "v1.0.0" diff --git a/build/chart/templates/NOTES.txt b/build/chart/templates/NOTES.txt new file mode 100644 index 0000000..b971993 --- /dev/null +++ b/build/chart/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "chart.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch its status by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "chart.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "chart.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "chart.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/build/chart/templates/_helpers.tpl b/build/chart/templates/_helpers.tpl new file mode 100644 index 0000000..7ba5edc --- /dev/null +++ b/build/chart/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "chart.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "chart.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "chart.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "chart.labels" -}} +helm.sh/chart: {{ include "chart.chart" . }} +{{ include "chart.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "chart.selectorLabels" -}} +app.kubernetes.io/name: {{ include "chart.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "chart.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "chart.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/build/chart/templates/deployment.yaml b/build/chart/templates/deployment.yaml new file mode 100644 index 0000000..b30053b --- /dev/null +++ b/build/chart/templates/deployment.yaml @@ -0,0 +1,78 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "chart.fullname" . }} + labels: + {{- include "chart.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "chart.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "chart.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "chart.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/build/chart/templates/hpa.yaml b/build/chart/templates/hpa.yaml new file mode 100644 index 0000000..a91f61b --- /dev/null +++ b/build/chart/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "chart.fullname" . }} + labels: + {{- include "chart.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "chart.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/build/chart/templates/ingress.yaml b/build/chart/templates/ingress.yaml new file mode 100644 index 0000000..89ec883 --- /dev/null +++ b/build/chart/templates/ingress.yaml @@ -0,0 +1,43 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "chart.fullname" . }} + labels: + {{- include "chart.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.ingress.className }} + ingressClassName: {{ . }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- with .pathType }} + pathType: {{ . }} + {{- end }} + backend: + service: + name: {{ include "chart.fullname" $ }} + port: + number: {{ $.Values.service.port }} + {{- end }} + {{- end }} +{{- end }} diff --git a/build/chart/templates/service.yaml b/build/chart/templates/service.yaml new file mode 100644 index 0000000..dfc5b3a --- /dev/null +++ b/build/chart/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "chart.fullname" . }} + labels: + {{- include "chart.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "chart.selectorLabels" . | nindent 4 }} diff --git a/build/chart/templates/serviceaccount.yaml b/build/chart/templates/serviceaccount.yaml new file mode 100644 index 0000000..1df9350 --- /dev/null +++ b/build/chart/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "chart.serviceAccountName" . }} + labels: + {{- include "chart.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/build/chart/templates/tests/test-connection.yaml b/build/chart/templates/tests/test-connection.yaml new file mode 100644 index 0000000..8dfed87 --- /dev/null +++ b/build/chart/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "chart.fullname" . }}-test-connection" + labels: + {{- include "chart.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "chart.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/build/chart/values.yaml b/build/chart/values.yaml new file mode 100644 index 0000000..8511f9b --- /dev/null +++ b/build/chart/values.yaml @@ -0,0 +1,150 @@ +# Default values for chart. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ +replicaCount: 1 + +# This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ +image: + repository: registry.timerzz.com:20443/kedaya/article + # This sets the pull policy for images. + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "latest" + +# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +imagePullSecrets: [] +# This is to override the chart name. +nameOverride: "" +fullnameOverride: "" + +# This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ +serviceAccount: + # Specifies whether a service account should be created + create: false + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +# This is for setting Kubernetes Annotations to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +podAnnotations: {} +# This is for setting Kubernetes Labels to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +# This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ +service: + # This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types + type: ClusterIP + # This sets the ports more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#field-spec-ports + port: 80 + +# This block is for setting up the ingress for more information can be found here: https://kubernetes.io/docs/concepts/services-networking/ingress/ +ingress: + enabled: true + className: "kubesphere-router-cluster" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: ht.timerzz.com + paths: + - path: /api/v2/articles + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +# This is to setup the liveness and readiness probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ +livenessProbe: + httpGet: + path: /living + port: 80 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 3 + successThreshold: 1 + failureThreshold: 3 +readinessProbe: + httpGet: + path: /ready + port: 80 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 3 + successThreshold: 1 + failureThreshold: 3 + +# This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/ +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: host-time + hostPath: + path: /etc/localtime + type: '' + - name: volume-shck44 + configMap: + name: online + items: + - key: db + path: db.yaml + defaultMode: 420 +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: host-time + readOnly: true + mountPath: /etc/localtime + - name: volume-shck44 + readOnly: true + mountPath: /cfg +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/cmd/article.go b/cmd/article.go index 8453060..d383b26 100644 --- a/cmd/article.go +++ b/cmd/article.go @@ -1,56 +1,56 @@ -package main - -import ( - "context" - "flag" - "os" - "os/signal" - - "gitea.timerzz.com/kedaya_haitao/article/service" - "gitea.timerzz.com/kedaya_haitao/common/pkg/database" - "gitea.timerzz.com/kedaya_haitao/common/pkg/web" - "gitea.timerzz.com/kedaya_haitao/common/structs/storage" - "github.com/gofiber/fiber/v3" - "github.com/gofiber/fiber/v3/middleware/cors" - "github.com/gofiber/fiber/v3/middleware/recover" - - "github.com/golang/glog" -) - -func main() { - flag.Parse() - glog.Info(">>> BEGIN INIT<<<") - ctx, cancel := signal.NotifyContext(context.Background(), os.Kill, os.Interrupt) - defer cancel() - // 初始化数据库 - db, err := database.InitDefaultDatabase() - if err != nil { - glog.Fatalf("init database failed: %v", err) - } - // 初始化服务 - r := fiber.New(fiber.Config{ErrorHandler: web.ErrHandle}) - r.Use(cors.New(), recover.New()) - - stg := storage.NewStorage(db) - _ = stg.Article().AutoMigrate() - - svc := []web.Register{ - web.NewProbe(), - service.NewArticle(stg), - } - - for _, s := range svc { - s.Registry(r) - } - - port := os.Getenv("PORT") - if port == "" { - port = "80" - } - if err = r.Listen(":"+port, fiber.ListenConfig{ - EnablePrintRoutes: true, - GracefulContext: ctx, - }); err != nil { - glog.Warningf("service over: %v", err) - } -} +package main + +import ( + "context" + "flag" + "os" + "os/signal" + + "gitea.timerzz.com/kedaya_haitao/article/service" + "gitea.timerzz.com/kedaya_haitao/common/pkg/database" + "gitea.timerzz.com/kedaya_haitao/common/pkg/web" + "gitea.timerzz.com/kedaya_haitao/common/structs/storage" + "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/middleware/cors" + "github.com/gofiber/fiber/v3/middleware/recover" + + "github.com/golang/glog" +) + +func main() { + flag.Parse() + glog.Info(">>> BEGIN INIT<<<") + ctx, cancel := signal.NotifyContext(context.Background(), os.Kill, os.Interrupt) + defer cancel() + // 初始化数据库 + db, err := database.InitDefaultDatabase() + if err != nil { + glog.Fatalf("init database failed: %v", err) + } + // 初始化服务 + r := fiber.New(fiber.Config{ErrorHandler: web.ErrHandle}) + r.Use(cors.New(), recover.New()) + + stg := storage.NewStorage(db) + _ = stg.Article().AutoMigrate() + + svc := []web.Register{ + web.NewProbe(), + service.NewArticle(stg), + } + + for _, s := range svc { + s.Registry(r) + } + + port := os.Getenv("PORT") + if port == "" { + port = "80" + } + if err = r.Listen(":"+port, fiber.ListenConfig{ + EnablePrintRoutes: true, + GracefulContext: ctx, + }); err != nil { + glog.Warningf("service over: %v", err) + } +} diff --git a/go.mod b/go.mod index f7dce82..d45ffe5 100644 --- a/go.mod +++ b/go.mod @@ -1,36 +1,36 @@ -module gitea.timerzz.com/kedaya_haitao/article - -go 1.22.5 - -require ( - gitea.timerzz.com/kedaya_haitao/common v0.0.0-20241202121425-6def3252d85c - github.com/gofiber/fiber/v3 v3.0.0-beta.3 - github.com/golang/glog v1.2.2 -) - -require ( - github.com/andybalholm/brotli v1.1.0 // indirect - github.com/expr-lang/expr v1.16.9 // indirect - github.com/gofiber/utils/v2 v2.0.0-beta.4 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/pgx/v5 v5.4.3 // indirect - github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.5 // indirect - github.com/klauspost/compress v1.17.9 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/samber/lo v1.39.0 // indirect - github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.55.0 // indirect - github.com/valyala/tcplisten v1.0.0 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - gorm.io/driver/postgres v1.5.7 // indirect - gorm.io/gorm v1.25.10 // indirect -) +module gitea.timerzz.com/kedaya_haitao/article + +go 1.22.5 + +require ( + gitea.timerzz.com/kedaya_haitao/common v0.0.0-20241202121425-6def3252d85c + github.com/gofiber/fiber/v3 v3.0.0-beta.3 + github.com/golang/glog v1.2.2 +) + +require ( + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/expr-lang/expr v1.16.9 // indirect + github.com/gofiber/utils/v2 v2.0.0-beta.4 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgx/v5 v5.4.3 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/samber/lo v1.39.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.55.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + gorm.io/driver/postgres v1.5.7 // indirect + gorm.io/gorm v1.25.10 // indirect +) diff --git a/go.sum b/go.sum index 468dab7..557ce1c 100644 --- a/go.sum +++ b/go.sum @@ -1,81 +1,81 @@ -gitea.timerzz.com/kedaya_haitao/common v0.0.0-20241202091018-277d73739be8 h1:AJo3Y3icJb8wcjeSnx6SjkHFdBKYm5lFscEuo6O4dDM= -gitea.timerzz.com/kedaya_haitao/common v0.0.0-20241202091018-277d73739be8/go.mod h1:BIz+IMGznPiyLnV1+Ntw1zf8rEIcbymmGq+EfvDsSgE= -gitea.timerzz.com/kedaya_haitao/common v0.0.0-20241202121425-6def3252d85c h1:WELIrLlcOud0cutzPiZnroF3Z39Surcae7W8sx2XZi0= -gitea.timerzz.com/kedaya_haitao/common v0.0.0-20241202121425-6def3252d85c/go.mod h1:BIz+IMGznPiyLnV1+Ntw1zf8rEIcbymmGq+EfvDsSgE= -github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= -github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/expr-lang/expr v1.16.9 h1:WUAzmR0JNI9JCiF0/ewwHB1gmcGw5wW7nWt8gc6PpCI= -github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= -github.com/gofiber/fiber/v3 v3.0.0-beta.3 h1:7Q2I+HsIqnIEEDB+9oe7Gadpakh6ZLhXpTYz/L20vrg= -github.com/gofiber/fiber/v3 v3.0.0-beta.3/go.mod h1:kcMur0Dxqk91R7p4vxEpJfDWZ9u5IfvrtQc8Bvv/JmY= -github.com/gofiber/utils/v2 v2.0.0-beta.4 h1:1gjbVFFwVwUb9arPcqiB6iEjHBwo7cHsyS41NeIW3co= -github.com/gofiber/utils/v2 v2.0.0-beta.4/go.mod h1:sdRsPU1FXX6YiDGGxd+q2aPJRMzpsxdzCXo9dz+xtOY= -github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= -github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= -github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= -github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= -github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= -github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -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/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA= -github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8= -github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM= -github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= -github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= -golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= -gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= -gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= -gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gitea.timerzz.com/kedaya_haitao/common v0.0.0-20241202091018-277d73739be8 h1:AJo3Y3icJb8wcjeSnx6SjkHFdBKYm5lFscEuo6O4dDM= +gitea.timerzz.com/kedaya_haitao/common v0.0.0-20241202091018-277d73739be8/go.mod h1:BIz+IMGznPiyLnV1+Ntw1zf8rEIcbymmGq+EfvDsSgE= +gitea.timerzz.com/kedaya_haitao/common v0.0.0-20241202121425-6def3252d85c h1:WELIrLlcOud0cutzPiZnroF3Z39Surcae7W8sx2XZi0= +gitea.timerzz.com/kedaya_haitao/common v0.0.0-20241202121425-6def3252d85c/go.mod h1:BIz+IMGznPiyLnV1+Ntw1zf8rEIcbymmGq+EfvDsSgE= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/expr-lang/expr v1.16.9 h1:WUAzmR0JNI9JCiF0/ewwHB1gmcGw5wW7nWt8gc6PpCI= +github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= +github.com/gofiber/fiber/v3 v3.0.0-beta.3 h1:7Q2I+HsIqnIEEDB+9oe7Gadpakh6ZLhXpTYz/L20vrg= +github.com/gofiber/fiber/v3 v3.0.0-beta.3/go.mod h1:kcMur0Dxqk91R7p4vxEpJfDWZ9u5IfvrtQc8Bvv/JmY= +github.com/gofiber/utils/v2 v2.0.0-beta.4 h1:1gjbVFFwVwUb9arPcqiB6iEjHBwo7cHsyS41NeIW3co= +github.com/gofiber/utils/v2 v2.0.0-beta.4/go.mod h1:sdRsPU1FXX6YiDGGxd+q2aPJRMzpsxdzCXo9dz+xtOY= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= +github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +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/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA= +github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8= +github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= +gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= +gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= +gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= diff --git a/service/article_svc.go b/service/article_svc.go index dc386c4..7ae8a0b 100644 --- a/service/article_svc.go +++ b/service/article_svc.go @@ -1,217 +1,217 @@ -package service - -import ( - "fmt" - "strconv" - "strings" - - "gitea.timerzz.com/kedaya_haitao/common/pkg/web" - "gitea.timerzz.com/kedaya_haitao/common/structs/storage" - "gitea.timerzz.com/kedaya_haitao/common/structs/utils" - v2 "gitea.timerzz.com/kedaya_haitao/common/structs/v2" - "github.com/gofiber/fiber/v3" - "github.com/samber/lo" - "gorm.io/gorm" -) - -type Article struct { - storage *storage.Storage -} - -func NewArticle(storage *storage.Storage) *Article { - return &Article{ - storage: storage, - } -} - -func (s *Article) Registry(r fiber.Router) { - api := r.Group("/api/v2") - api.Get("articles", s.List) - api.Get("articles/u/:id", s.Get) - api.Get("articles/dict/brand", s.BrandDict) - api.Patch("articles", s.Update) - api.Get("articles/provider/history/:id", s.ProviderHistory) - api.Get("articles/seller/history/:id", s.SellerHistory) - api.Patch("articles/provider", s.UpdateProviderArticle) - api.Patch("articles/seller", s.UpdateSellerArticle) - - //屏蔽相关操作 - api.Get("articles/ban", s.ListBanArticle) - api.Post("articles/ban/:ids", s.BanArticle) - api.Delete("articles/ban/:ids", s.LiftBanArticle) -} - -func (s *Article) List(c fiber.Ctx) error { - var q storage.FindArticleQuery - if err := c.Bind().Query(&q); err != nil { - return err - } - q.SetBan(false) - var query = storage.NewPageListQuery(&q) - if err := c.Bind().Query(query); err != nil { - return err - } - articles, total, err := s.storage.Article().List(*query, q.SortScope) - if err != nil { - return err - } - return c.JSON(web.NewResponse(web.NewListResponse(total, articles))) -} - -func (s *Article) Get(c fiber.Ctx) error { - id := c.Params("id") - if id == "" { - return fiber.NewError(fiber.StatusBadRequest, "id is required") - } - i, _ := strconv.Atoi(id) - query := storage.NewGetArticleQuery().SetID(uint(i)) - article, err := s.storage.Article().Get(query) - if err != nil { - return err - } - return c.JSON(web.NewResponse(article)) -} - -func (s *Article) Update(c fiber.Ctx) error { - var article v2.Article - if err := c.Bind().JSON(&article); err != nil { - return err - } - if article.ID == 0 { - return fiber.NewError(fiber.StatusBadRequest, "id is required") - } - if err := s.storage.Article().Update(article); err != nil { - return err - } - return c.JSON(web.NewResponse(article)) -} - -func (s *Article) BrandDict(c fiber.Ctx) error { - var dict = []utils.Dict{ - { - Key: string(v2.Brand_Coach), - Title: fmt.Sprintf("蔻驰/%s", v2.Brand_Coach), - Value: v2.Brand_Coach, - }, - } - return c.JSON(web.NewResponse(dict)) -} - -// 获取供应商历史价格 -func (s *Article) ProviderHistory(c fiber.Ctx) error { - i := c.Params("id") - id, _ := strconv.Atoi(i) - if id == 0 { - return fiber.NewError(fiber.StatusBadRequest, "id is required") - } - prices, err := s.storage.ProviderArticle().ProviderPrice(uint(id)) - if err != nil { - return err - } - return c.JSON(web.NewResponse(prices)) -} - -// 获取销售商历史价格 -func (s *Article) SellerHistory(c fiber.Ctx) error { - i := c.Params("id") - id, _ := strconv.Atoi(i) - if id == 0 { - return fiber.NewError(fiber.StatusBadRequest, "id is required") - } - prices, err := s.storage.SellerArticle().SellerPrice(uint(id)) - if err != nil { - return err - } - return c.JSON(web.NewResponse(prices)) -} - -func (s *Article) UpdateProviderArticle(c fiber.Ctx) error { - var article v2.ProviderArticle - if err := c.Bind().JSON(&article); err != nil { - return err - } - if err := s.storage.ProviderArticle().Update(article); err != nil { - return err - } - return c.JSON(web.NewResponse(article)) -} - -func (s *Article) UpdateSellerArticle(c fiber.Ctx) error { - var article v2.SellerArticle - if err := c.Bind().JSON(&article); err != nil { - return err - } - if err := s.storage.SellerArticle().Update(article); err != nil { - return err - } - return c.JSON(web.NewResponse(article)) -} - -// BanArticle 禁用商品 -func (s *Article) BanArticle(c fiber.Ctx) error { - ids := c.Params("ids") - if ids == "" { - return fiber.NewError(fiber.StatusBadRequest, "ids is required") - } - idList := lo.Map(strings.Split(ids, ","), func(item string, index int) int { - id, _ := strconv.Atoi(item) - return id - }) - - err := s.storage.DB().Transaction(func(tx *gorm.DB) (err error) { - if err = tx.Model(&v2.Article{}).Select("ban", "exclude").Where("id IN ?", idList).Updates(map[string]interface{}{"ban": true, "exclude": true}).Error; err != nil { - return err - } - if err = tx.Model(&v2.ProviderArticle{}).Where("article_id IN ?", idList).Update("exclude", true).Error; err != nil { - return err - } - return tx.Model(&v2.SellerArticle{}).Where("article_id IN ?", idList).Update("exclude", true).Error - }) - if err != nil { - return err - } - return c.JSON(web.NewResponse("ok")) -} - -// 解禁商品 -func (s *Article) LiftBanArticle(c fiber.Ctx) error { - ids := c.Params("ids") - if ids == "" { - return fiber.NewError(fiber.StatusBadRequest, "ids is required") - } - idList := lo.Map(strings.Split(ids, ","), func(item string, index int) int { - id, _ := strconv.Atoi(item) - return id - }) - - err := s.storage.DB().Transaction(func(tx *gorm.DB) (err error) { - if err = tx.Model(&v2.Article{}).Select("ban", "exclude").Where("id IN ?", idList).Updates(map[string]interface{}{"ban": false, "exclude": false}).Error; err != nil { - return err - } - if err = tx.Model(&v2.ProviderArticle{}).Where("article_id IN ?", idList).Update("exclude", false).Error; err != nil { - return err - } - return tx.Model(&v2.SellerArticle{}).Where("article_id IN ?", idList).Update("exclude", false).Error - }) - if err != nil { - return err - } - return c.JSON(web.NewResponse("ok")) -} - -func (s *Article) ListBanArticle(c fiber.Ctx) error { - var q storage.FindArticleQuery - if err := c.Bind().Query(&q); err != nil { - return err - } - q.SetBan(true) - var query = storage.NewPageListQuery(&q) - if err := c.Bind().Query(query); err != nil { - return err - } - articles, total, err := s.storage.Article().List(*query, q.SortScope) - if err != nil { - return err - } - return c.JSON(web.NewResponse(web.NewListResponse(total, articles))) -} +package service + +import ( + "fmt" + "strconv" + "strings" + + "gitea.timerzz.com/kedaya_haitao/common/pkg/web" + "gitea.timerzz.com/kedaya_haitao/common/structs/storage" + "gitea.timerzz.com/kedaya_haitao/common/structs/utils" + v2 "gitea.timerzz.com/kedaya_haitao/common/structs/v2" + "github.com/gofiber/fiber/v3" + "github.com/samber/lo" + "gorm.io/gorm" +) + +type Article struct { + storage *storage.Storage +} + +func NewArticle(storage *storage.Storage) *Article { + return &Article{ + storage: storage, + } +} + +func (s *Article) Registry(r fiber.Router) { + api := r.Group("/api/v2") + api.Get("articles", s.List) + api.Get("articles/u/:id", s.Get) + api.Get("articles/dict/brand", s.BrandDict) + api.Patch("articles", s.Update) + api.Get("articles/provider/history/:id", s.ProviderHistory) + api.Get("articles/seller/history/:id", s.SellerHistory) + api.Patch("articles/provider", s.UpdateProviderArticle) + api.Patch("articles/seller", s.UpdateSellerArticle) + + //屏蔽相关操作 + api.Get("articles/ban", s.ListBanArticle) + api.Post("articles/ban/:ids", s.BanArticle) + api.Delete("articles/ban/:ids", s.LiftBanArticle) +} + +func (s *Article) List(c fiber.Ctx) error { + var q storage.FindArticleQuery + if err := c.Bind().Query(&q); err != nil { + return err + } + q.SetBan(false) + var query = storage.NewPageListQuery(&q) + if err := c.Bind().Query(query); err != nil { + return err + } + articles, total, err := s.storage.Article().List(*query, q.SortScope) + if err != nil { + return err + } + return c.JSON(web.NewResponse(web.NewListResponse(total, articles))) +} + +func (s *Article) Get(c fiber.Ctx) error { + id := c.Params("id") + if id == "" { + return fiber.NewError(fiber.StatusBadRequest, "id is required") + } + i, _ := strconv.Atoi(id) + query := storage.NewGetArticleQuery().SetID(uint(i)) + article, err := s.storage.Article().Get(query) + if err != nil { + return err + } + return c.JSON(web.NewResponse(article)) +} + +func (s *Article) Update(c fiber.Ctx) error { + var article v2.Article + if err := c.Bind().JSON(&article); err != nil { + return err + } + if article.ID == 0 { + return fiber.NewError(fiber.StatusBadRequest, "id is required") + } + if err := s.storage.Article().Update(article); err != nil { + return err + } + return c.JSON(web.NewResponse(article)) +} + +func (s *Article) BrandDict(c fiber.Ctx) error { + var dict = []utils.Dict{ + { + Key: string(v2.Brand_Coach), + Title: fmt.Sprintf("蔻驰/%s", v2.Brand_Coach), + Value: v2.Brand_Coach, + }, + } + return c.JSON(web.NewResponse(dict)) +} + +// 获取供应商历史价格 +func (s *Article) ProviderHistory(c fiber.Ctx) error { + i := c.Params("id") + id, _ := strconv.Atoi(i) + if id == 0 { + return fiber.NewError(fiber.StatusBadRequest, "id is required") + } + prices, err := s.storage.ProviderArticle().ProviderPrice(uint(id)) + if err != nil { + return err + } + return c.JSON(web.NewResponse(prices)) +} + +// 获取销售商历史价格 +func (s *Article) SellerHistory(c fiber.Ctx) error { + i := c.Params("id") + id, _ := strconv.Atoi(i) + if id == 0 { + return fiber.NewError(fiber.StatusBadRequest, "id is required") + } + prices, err := s.storage.SellerArticle().SellerPrice(uint(id)) + if err != nil { + return err + } + return c.JSON(web.NewResponse(prices)) +} + +func (s *Article) UpdateProviderArticle(c fiber.Ctx) error { + var article v2.ProviderArticle + if err := c.Bind().JSON(&article); err != nil { + return err + } + if err := s.storage.ProviderArticle().Update(article); err != nil { + return err + } + return c.JSON(web.NewResponse(article)) +} + +func (s *Article) UpdateSellerArticle(c fiber.Ctx) error { + var article v2.SellerArticle + if err := c.Bind().JSON(&article); err != nil { + return err + } + if err := s.storage.SellerArticle().Update(article); err != nil { + return err + } + return c.JSON(web.NewResponse(article)) +} + +// BanArticle 禁用商品 +func (s *Article) BanArticle(c fiber.Ctx) error { + ids := c.Params("ids") + if ids == "" { + return fiber.NewError(fiber.StatusBadRequest, "ids is required") + } + idList := lo.Map(strings.Split(ids, ","), func(item string, index int) int { + id, _ := strconv.Atoi(item) + return id + }) + + err := s.storage.DB().Transaction(func(tx *gorm.DB) (err error) { + if err = tx.Model(&v2.Article{}).Select("ban", "exclude").Where("id IN ?", idList).Updates(map[string]interface{}{"ban": true, "exclude": true}).Error; err != nil { + return err + } + if err = tx.Model(&v2.ProviderArticle{}).Where("article_id IN ?", idList).Update("exclude", true).Error; err != nil { + return err + } + return tx.Model(&v2.SellerArticle{}).Where("article_id IN ?", idList).Update("exclude", true).Error + }) + if err != nil { + return err + } + return c.JSON(web.NewResponse("ok")) +} + +// 解禁商品 +func (s *Article) LiftBanArticle(c fiber.Ctx) error { + ids := c.Params("ids") + if ids == "" { + return fiber.NewError(fiber.StatusBadRequest, "ids is required") + } + idList := lo.Map(strings.Split(ids, ","), func(item string, index int) int { + id, _ := strconv.Atoi(item) + return id + }) + + err := s.storage.DB().Transaction(func(tx *gorm.DB) (err error) { + if err = tx.Model(&v2.Article{}).Select("ban", "exclude").Where("id IN ?", idList).Updates(map[string]interface{}{"ban": false, "exclude": false}).Error; err != nil { + return err + } + if err = tx.Model(&v2.ProviderArticle{}).Where("article_id IN ?", idList).Update("exclude", false).Error; err != nil { + return err + } + return tx.Model(&v2.SellerArticle{}).Where("article_id IN ?", idList).Update("exclude", false).Error + }) + if err != nil { + return err + } + return c.JSON(web.NewResponse("ok")) +} + +func (s *Article) ListBanArticle(c fiber.Ctx) error { + var q storage.FindArticleQuery + if err := c.Bind().Query(&q); err != nil { + return err + } + q.SetBan(true) + var query = storage.NewPageListQuery(&q) + if err := c.Bind().Query(query); err != nil { + return err + } + articles, total, err := s.storage.Article().List(*query, q.SortScope) + if err != nil { + return err + } + return c.JSON(web.NewResponse(web.NewListResponse(total, articles))) +}