已开启
feat: 消息全部功能实现 #23
jiax0274创建于 2025年11月28日
feat: 消息全部功能实现 #23
已开启
jiax0274创建于 2025年11月28日
共 508 个文件变更+19732-823415
@@ -1,29 +0,0 @@
1-docker/data/mysql/
2-docker/data/mysql/*
3-docker/data/grafana/
4-docker/data/grafana/*
5-docker/data/prometheus/
6-docker/data/prometheus/*
7-docker/data/redis/
8-docker/data/redis/*
9-docker/data/etcd/
10-docker/data/etcd/*
11-docker/data/elasticsearch/
12-docker/data/elasticsearch/*
13-docker/data/kafka/
14-docker/data/kafka/*
15-docker/data/kibana/
16-docker/data/kibana/*
17- 
18-.git
19-.gitignore
20-.env
21-*.md
22-.editorconfig
23-.golangci.yml
24-docker-compose.yml
25-docker-compose.ci.yml
26-README.md
27-/test
28-/.github
29-*.log
@@ -1,18 +0,0 @@
1-#### 这个 PR 的类型是什么?
2-<!--
3-添加以下类型的一种:
4- 
5-build: 影响构建系统或外部依赖项的更改 (常用 scope: gulp, broccoli, npm)
6-ci: 更改我们的 CI 配置文件和脚本 (常用 scope: Travis, Circle, BrowserStack, SauceLabs)
7-docs: 只包含文档的更改
8-feat: 一个新的特性
9-optimize: 对已有代码的优化
10-fix: 修正 bug
11-perf: 对代码的性能提升
12-refactor: 重构,或代码更改既没有修复错误也没有添加功能
13-style: 不影响代码含义的更改 (空白行/空格, 格式优化, 缺失的分号, etc.)
14-test: 添加缺失的测试或更正现有的测试
15-chore: 构建过程或辅助工具和库(如文档生成)的变更
16--->
17- 
18- 
@@ -1,42 +0,0 @@
1-name: Build and Push Docker Image
2- 
3-on:
4- workflow_dispatch:
5- inputs:
6- service:
7- description: "Select the service to build"
8- required: true
9- type: choice
10- options:
11- - gateway
12- - user
13- - assistant
14- - commodity
15- - cart
16- - order
17- - payment
18- 
19-jobs:
20- build:
21- runs-on: ubuntu-latest
22- 
23- steps:
24- - name: Check out the code
25- uses: actions/checkout@v4
26- 
27- - name: Log in to Alibaba Cloud Docker Registry
28- uses: docker/login-action@v3
29- with:
30- registry: ${{ secrets.ALIYUN_DOCKER_REGISTRY }}
31- username: ${{ secrets.ALIYUN_DOCKER_USER }}
32- password: ${{ secrets.ALIYUN_DOCKER_PASSWORD }}
33- 
34- - name: Ensure build script is executable
35- run: chmod +x ./hack/image-build-and-push.sh
36- 
37- - name: Convert service name to lowercase
38- run: echo "SERVICE=$(echo '${{ github.event.inputs.service }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
39- 
40- - name: Build and Push Docker Image
41- run: |
42- cd $GITHUB_WORKSPACE && bash ./hack/image-build-and-push.sh $SERVICE
@@ -1,64 +0,0 @@
1-name: CI
2- 
3-on:
4- push:
5- branches:
6- - main
7- - dev
8- pull_request:
9- branches:
10- - main
11- - dev
12- 
13-permissions:
14- contents: read
15- 
16-jobs:
17- fmt:
18- name: Format
19- runs-on: ubuntu-latest
20- steps:
21- - uses: actions/checkout@v4
22- - uses: actions/setup-go@v5
23- with:
24- go-version-file: go.mod
25- cache: false
26- - name: Check Go modules
27- run: |
28- go mod tidy && git add go.* &&
29- git diff --cached --exit-code || (echo 'Please run "go mod tidy" to sync Go modules' && exit 1);
30- - name: Verify gofumpt
31- run: |
32- echo "refer to https://github.com/mvdan/gofumpt for detailed info" &&
33- GO111MODULE=on go install mvdan.cc/gofumpt@latest &&
34- make fmt && git add pkg cmd &&
35- git diff --cached --exit-code || (echo 'Please run "make fmt" to verify fmt' && exit 1);
36- 
37- vet:
38- name: Vet
39- runs-on: ubuntu-latest
40- steps:
41- - uses: actions/checkout@v4
42- - uses: actions/setup-go@v5
43- with:
44- go-version-file: go.mod
45- cache: false
46- - name: Verify govet
47- run: |
48- make vet && git add pkg cmd &&
49- git diff --cached --exit-code || (echo 'Please run "make vet" to verify govet' && exit 1);
50- 
51- lint:
52- name: lint
53- runs-on: ubuntu-latest
54- steps:
55- - uses: actions/checkout@v4
56- - uses: actions/setup-go@v5
57- with:
58- go-version-file: go.mod
59- cache: false
60- - name: golangci-lint
61- uses: golangci/golangci-lint-action@v6
62- with:
63- version: latest
64- args: --timeout=10m
@@ -1,43 +0,0 @@
1-name: "CodeQL"
2- 
3-on:
4- push:
5- branches:
6- - main
7- - dev
8- pull_request:
9- branches:
10- - main
11- - dev
12- 
13-jobs:
14- analyze:
15- name: Analyze
16- runs-on: ubuntu-latest
17- timeout-minutes: 360
18- permissions:
19- actions: read
20- contents: read
21- security-events: write
22- 
23- strategy:
24- fail-fast: false
25- matrix:
26- language: [ 'go' ]
27- 
28- steps:
29- - name: Checkout infrastructure
30- uses: actions/checkout@v4
31- 
32- - name: Initialize CodeQL
33- uses: github/codeql-action/init@v3
34- with:
35- languages: ${{ matrix.language }}
36- 
37- - name: Autobuild
38- uses: github/codeql-action/autobuild@v3
39- 
40- - name: Perform CodeQL Analysis
41- uses: github/codeql-action/analyze@v3
42- with:
43- category: "/language:${{matrix.language}}"
@@ -1,36 +0,0 @@
1-name: Run govulncheck
2- 
3-on:
4- push:
5- branches:
6- - develop
7- paths:
8- - "**"
9- - "!**.md"
10- pull_request:
11- paths:
12- - "**"
13- - "!**.md"
14- 
15-jobs:
16- vulncheck-check:
17- runs-on: ubuntu-latest
18- env:
19- GO111MODULE: on
20- steps:
21- - name: Fetch Repository
22- uses: actions/checkout@v4
23- 
24- - name: Install Go
25- uses: actions/setup-go@v5
26- with:
27- go-version: stable
28- check-latest: true
29- cache: false
30- 
31- - name: Install Govulncheck
32- run: go install golang.org/x/vuln/cmd/govulncheck@latest
33- 
34- - name: Run Govulncheck
35- run: govulncheck ./...
36- 
M.gitignore+43-48
@@ -1,50 +1,45 @@
1-*.o1+# Miscellaneous
2-*.a2+*.class
3-*.so
4-_obj
5-config/config.yaml
6-config/config.yaml.bak
7-_test
8-*.[568vq]
9-[568vq].out
10-*.cgo1.go
11-*.cgo2.c
12-src/storage/
13-_cgo_defun.c
14-_cgo_gotypes.go
15-_cgo_export.*
16-_testmain.go
17-*.exe
18-*.exe~
19-*.test
20-*.prof
21-*.rar
22-*.zip
23-*.gz
24-*.psd
25-*.bmd
26-*.cfg
27-*.pptx
28*.log3*.log
29-*nohup.out4+*.pyc
30-*settings.pyc5+*.swp
31-*.sublime-project
32-*.sublime-workspace
33-!.gitkeep.DS_Store
34-/.idea
35-/.vscode
36-/output
37-*.local.yml
38-dumped_hertz_remote_config.json
39-docker/data/
40-docker/data/mysql/
41-docker/data/mysql/*
42-node_modules/
43-dist/
44.DS_Store6.DS_Store
45-.env.local7+.atom/
46-.env.*.local8+.build/
47-npm-debug.log*9+.buildlog/
48-yarn-debug.log*10+.history
49-yarn-error.log*11+.svn/
50-.env12+.swiftpm/
13+migrate_working_dir/
14+ 
15+# IntelliJ related
16+*.iml
17+*.ipr
18+*.iws
19+.idea/
20+ 
21+# The .vscode folder contains launch configuration and tasks you configure in
22+# VS Code which you may wish to be included in version control, so this line
23+# is commented out by default.
24+#.vscode/
25+ 
26+# Flutter/Dart/Pub related
27+**/doc/api/
28+**/ios/Flutter/.last_build_id
29+.dart_tool/
30+.flutter-plugins-dependencies
31+.pub-cache/
32+.pub/
33+/build/
34+/coverage/
35+ 
36+# Symbolication related
37+app.*.symbols
38+ 
39+# Obfuscation related
40+app.*.map.json
41+ 
42+# Android Studio will place build artifacts here
43+/android/app/debug
44+/android/app/profile
45+/android/app/release
@@ -1,223 +0,0 @@
1-# options for analysis running
2-run:
3- # default concurrency is the available CPU number
4- concurrency: 16
5- # timeout for analysis, e.g. 30s, 5m, default is 1m
6- timeout: 10m
7- # exit code when at least one issue was found, default is 1
8- issues-exit-code: 1
9- # include test files or not, default is true
10- tests: true
11- # which dirs to skip: they won't be analyzed;
12- # can use regexp here: generated.*, regexp is applied on full path;
13- # default value is empty list, but next dirs are always skipped independently
14- # from this option's value:
15- # third_party$, testdata$, examples$, Godeps$, builtin$
16- # skip-dirs:
17- 
18-# output configuration options
19-output:
20- # print lines of code with issue, default is true
21- print-issued-lines: true
22- # print linter name in the end of issue text, default is true
23- print-linter-name: true
24- 
25- 
26-# all available settings of specific linters
27-linters-settings:
28- nakedret:
29- # Make an issue if func has more lines of code than this setting, and it has naked returns.
30- # Default: 30
31- max-func-lines: 31
32- gofmt:
33- # simplify code: gofmt with `-s` option, true by default
34- simplify: true
35- goimports:
36- # put imports beginning with prefix after 3rd-party packages;
37- # it's a comma-separated list of prefixes
38- local-prefixes: github.com/west2-online
39- gci:
40- # Section configuration to compare against.
41- # Section names are case-insensitive and may contain parameters in ().
42- # The default order of sections is `standard > default > custom > blank > dot > alias > localmodule`,
43- # If `custom-order` is `true`, it follows the order of `sections` option.
44- # Default: ["standard", "default"]
45- sections:
46- - standard # Standard section: captures all standard packages.
47- - default # Default section: contains all imports that could not be matched to another section type.
48- - prefix(github.com/west2-online) # Custom section: groups all imports with the specified Prefix.
49- # - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled.
50- # - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled.
51- # - alias # Alias section: contains all alias imports. This section is not present unless explicitly enabled.
52- # - localmodule # Local module section: contains all local packages. This section is not present unless explicitly enabled.
53- # Skip generated files.
54- # Default: true
55- skip-generated: true
56- # Enable custom order of sections.
57- # If `true`, make the section order the same as the order of `sections`.
58- # Default: false
59- custom-order: true
60- # Drops lexical ordering for custom sections.
61- # Default: false
62- no-lex-order: true
63- nilnil:
64- # List of return types to check.
65- # Default: ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"]
66- checked-types:
67- - ptr
68- - func
69- - iface
70- - map
71- - chan
72- - uintptr
73- - unsafeptr
74- errorlint:
75- # Check whether fmt.Errorf uses the %w verb for formatting errors.
76- # See the https://github.com/polyfloyd/go-errorlint for caveats.
77- errorf: true
78- # Permit more than 1 %w verb, valid per Go 1.20 (Requires errorf:true)
79- # Default: true
80- errorf-multi: true
81- # Check for plain type assertions and type switches.
82- # Default: true
83- asserts: true
84- # Check for plain error comparisons.
85- # Default: true
86- comparison: true
87- # Allowed errors.
88- # Default: []
89- allowed-errors:
90- - err: "io.EOF"
91- fun: "example.com/pkg.Read"
92- # Allowed error "wildcards".
93- # Default: []
94- allowed-errors-wildcard:
95- - err: "github.com/west2-online/domtok/pkg/errno"
96- fun: "github.com/west2-online/domtok/pkg/errno"
97- misspell:
98- # Correct spellings using locale preferences for US or UK.
99- # Default is to use a neutral variety of English.
100- # Setting locale to US will correct the British spelling of 'colour' to 'color'.
101- locale: US
102- staticcheck:
103- checks:
104- - all
105- - -SA1019
106- lll:
107- # Max line length, lines longer will be reported.
108- # '\t' is counted as 1 character by default, and can be changed with the tab-width option.
109- # Default: 120.
110- line-length: 160
111- # Tab width in spaces.
112- # Default: 1
113- tab-width: 1
114- mnd:
115- # List of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.
116- # Default: ["argument", "case", "condition", "operation", "return", "assign"]
117- checks:
118- - argument
119- - case
120- - condition
121- - operation
122- - return
123- - assign
124- # List of numbers to exclude from analysis.
125- # The numbers should be written as string.
126- # Values always ignored: "1", "1.0", "0" and "0.0"
127- # Default: []
128- ignored-numbers:
129- - '0666'
130- - '0755'
131- - '42'
132- # List of file patterns to exclude from analysis.
133- # Values always ignored: `.+_test.go`
134- # Default: []
135- ignored-files:
136- - 'magic1_.+\.go$'
137- # List of function patterns to exclude from analysis.
138- # Following functions are always ignored: `time.Date`,
139- # `strconv.FormatInt`, `strconv.FormatUint`, `strconv.FormatFloat`,
140- # `strconv.ParseInt`, `strconv.ParseUint`, `strconv.ParseFloat`.
141- # Default: []
142- ignored-functions:
143- - '^math\.'
144- - '^http\.StatusText$'
145- makezero:
146- # Allow only slices initialized with a length of zero.
147- # Default: false
148- always: false
149- nestif:
150- # Minimal complexity of if statements to report.
151- # Default: 5
152- min-complexity: 6
153- tagalign:
154- # Align and sort can be used together or separately.
155- #
156- # Whether enable align. If true, the struct tags will be aligned.
157- # e.g.:
158- # type FooBar struct {
159- # Bar string `json:"bar" validate:"required"`
160- # FooFoo int8 `json:"foo_foo" validate:"required"`
161- # }
162- # will be formatted to:
163- # type FooBar struct {
164- # Bar string `json:"bar" validate:"required"`
165- # FooFoo int8 `json:"foo_foo" validate:"required"`
166- # }
167- # Default: true.
168- align: true
169- # Whether enable tags sort.
170- # If true, the tags will be sorted by name in ascending order.
171- # e.g.: `xml:"bar" json:"bar" validate:"required"` -> `json:"bar" validate:"required" xml:"bar"`
172- # Default: true
173- sort: true
174- # Specify the order of tags, the other tags will be sorted by name.
175- # This option will be ignored if `sort` is false.
176- # Default: []
177- order:
178- - json
179- - yaml
180- - yml
181- - toml
182- - mapstructure
183- - binding
184- - validate
185- # Whether enable strict style.
186- # In this style, the tags will be sorted and aligned in the dictionary order,
187- # and the tags with the same name will be aligned together.
188- # Note: This option will be ignored if 'align' or 'sort' is false.
189- # Default: false
190- strict: true
191- 
192-linters:
193- fast: false
194- disable-all: true
195- enable:
196- - errcheck # 错误检查
197- - staticcheck # 静态检查
198- - unused # 检查未使用的变量、常量、函数和类型
199- - misspell # 检查常见的拼写错误的英文单词
200- - nolintlint # 报告不正确或不充分的 nolint 指令
201- - goimports # 检查包导入是否按 goimport 命令格式化
202- - nakedret # 检查具有裸返回(func with naked returns)的函数包体是否过大
203- - unconvert # 删除不必要的类型转换
204- - whitespace # 检查不必要的换行符
205- - govet # 与 go vet 大致相同
206- - gosimple # 简化代码
207- - ineffassign # 检测现有变量的赋值何时未被使用
208- - gocritic # 提供诊断功能,检查错误、性能和样式问题
209- - importas # 强制使用一致的包导入别名
210- - gci # 控制包导入顺序
211- - errorlint # 检查错误处理代码合规性
212- - nilerr # 检查当产生错误时仍然返回 nil 的情况
213- - asciicheck # 检查非 ASCII 字符
214- - copyloopvar # 检查循环变量是否在闭包中被复制
215- - decorder # 检查类型、常量、变量和函数的声明顺序和数量
216- - forcetypeassert # 查找强制类型断言
217- - lll # 检查行的长度
218- - mnd # 检查魔数,魔数应该尽量放置在常量中
219- - inamedparam # 检查函数参数的命名
220- - makezero # 检查是否存在非零长初始化的切片
221- - mirror # 报告 bytes/strings 的错误 mirror 用法
222- - nestif # 检查是否存在深度嵌套的 if
223- - tagalign # 检查结构体标签是否对齐,支持自动修正
D.hz+0-6
@@ -1,6 +0,0 @@
1-// Code generated by hz. DO NOT EDIT.
2- 
3-hz version: v0.9.7
4-handlerDir: ./app/gateway/handler
5-modelDir: ./app/gateway/model
6-routerDir: ./app/gateway/router
A.metadata+30-0
@@ -0,0 +1,30 @@
1+# This file tracks properties of this Flutter project.
2+# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+#
4+# This file should be version controlled and should not be manually edited.
5+ 
6+version:
7+ revision: "adc901062556672b4138e18a4dc62a4be8f4b3c2"
8+ channel: "stable"
9+ 
10+project_type: app
11+ 
12+# Tracks metadata for the flutter migrate command
13+migration:
14+ platforms:
15+ - platform: root
16+ create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
17+ base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
18+ - platform: android
19+ create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
20+ base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
21+ 
22+ # User provided section
23+ 
24+ # List of Local paths (relative to this file) that should be
25+ # ignored by the migrate tool.
26+ #
27+ # Files that are not part of the templates will be ignored by default.
28+ unmanaged_files:
29+ - 'lib/main.dart'
30+ - 'ios/Runner.xcodeproj/project.pbxproj'
A.trae/rules/project_rules.md+248-0文件内容审核中,请稍后刷新重试
DMakefile+0-178
@@ -1,178 +0,0 @@
1-# 辅助工具安装列表
2-# 执行 go install github.com/cloudwego/hertz/cmd/hz@latest
3-# 执行 go install github.com/cloudwego/kitex/tool/cmd/kitex@latest
4-# 执行 go install golang.org/x/tools/cmd/goimports@latest
5-# 执行 go install golang.org/x/vuln/cmd/govulncheck@latest
6-# 执行 go install mvdan.cc/gofumpt@latest
7-# 访问 https://golangci-lint.run/welcome/install/ 以查看安装 golangci-lint 的方法
8- 
9-# 默认输出帮助信息
10-.DEFAULT_GOAL := help
11-# 检查 tmux 是否存在
12-TMUX_EXISTS := $(shell command -v tmux)
13-# 项目 MODULE 名
14-MODULE = github.com/yxrxy/videoHub
15-# 当前架构
16-ARCH := $(shell uname -m)
17-PREFIX = "[Makefile]"
18-# 目录相关
19-DIR = $(shell pwd)
20-CMD = $(DIR)/cmd
21-CONFIG_PATH = $(DIR)/config
22-IDL_PATH = $(DIR)/idl
23-OUTPUT_PATH = $(DIR)/output
24- 
25-# 服务名
26-SERVICES := gateway user social interaction video note
27-service = $(word 1, $@)
28- 
29-all:
30- @make user
31- @make social
32- @make interaction
33- @make video
34- @make gateway
35- 
36-.PHONY: help
37-help:
38- @echo "Available targets:"
39- @echo " {service name} : Build a specific service (e.g., make social). use BUILD_ONLY=1 to avoid auto bootstrap."
40- @echo " Available service list: [${SERVICES}]"
41- @echo " env-up : Start the docker-compose environment."
42- @echo " env-down : Stop the docker-compose environment."
43- @echo " kitex-gen-% : Generate Kitex service code for a specific service."
44- @echo " kitex-update-% : Update Kitex generated code for a specific service."
45- @echo " hertz-gen-api : Generate Hertz scaffold based on the API IDL."
46- @echo " test : Run unit tests for the project."
47- @echo " clean : Remove the 'output' directories and related binaries."
48- 
49-# 启动必要的环境,比如 etcd、mysql
50-.PHONY: env-up
51-env-up:
52- @ docker compose -f ./docker/docker-compose.yml up -d videohub-mysql videohub-redis videohub-etcd kafka otel-collector elasticsearch kibana jaeger prometheus grafana
53- @echo "$(PREFIX) - Jaeger UI: http://localhost:16686"
54- @echo "$(PREFIX) - Prometheus: http://localhost:9090"
55- @echo "$(PREFIX) - Grafana: http://localhost:3080 (admin/admin)"
56- @echo "$(PREFIX) - Node Exporter: http://localhost:9100"
57- @echo "$(PREFIX) - AlertManager: http://localhost:9093"
58- 
59-# 关闭必要的环境,但不清理 data(位于 docker/data 目录中)
60-.PHONY: env-down
61-env-down:
62- @ cd ./docker && docker compose down
63- 
64-# 基于 idl 生成相关的 go 语言描述文件
65-.PHONY: kitex-gen-%
66-kitex-gen-%:
67- @ kitex -module "${MODULE}" \
68- -thrift no_default_serdes \
69- ${IDL_PATH}/$*.thrift
70- @ go mod tidy
71- 
72-# 生成基于 Hertz 的脚手架
73-.PHONY: hz-%
74-hz-%:
75- hz update -idl ${IDL_PATH}/api/$*.thrift
76- 
77-# 构建指定对象,构建后在没有给 BUILD_ONLY 参的情况下会自动运行,需要熟悉 tmux 环境
78-.PHONY: $(SERVICES)
79-$(SERVICES):
80- @if [ -z "$(TMUX_EXISTS)" ]; then \
81- echo "$(PREFIX) tmux is not installed. Please install tmux first."; \
82- exit 1; \
83- fi
84- @if [ -z "$$TMUX" ]; then \
85- echo "$(PREFIX) you are not in tmux, press ENTER to start tmux environment."; \
86- read -r; \
87- if tmux has-session -t videohub 2>/dev/null; then \
88- echo "$(PREFIX) Tmux session 'videohub' already exists. Attaching to session and running command."; \
89- tmux attach-session -t videohub; \
90- tmux send-keys -t videohub "make $(service)" C-m; \
91- else \
92- echo "$(PREFIX) No tmux session found. Creating a new session."; \
93- tmux new-session -s videohub "make $(service); $$SHELL"; \
94- fi; \
95- else \
96- echo "$(PREFIX) Build $(service) target..."; \
97- mkdir -p output; \
98- bash $(DIR)/docker/script/build.sh $(service); \
99- echo "$(PREFIX) Build $(service) target completed"; \
100- fi
101-ifndef BUILD_ONLY
102- @echo "$(PREFIX) Automatic run server"
103- @if tmux list-windows -F '#{window_name}' | grep -q "^videohub-$(service)$$"; then \
104- echo "$(PREFIX) Window 'videohub-$(service)' already exists. Reusing the window."; \
105- tmux select-window -t "videohub-$(service)"; \
106- else \
107- echo "$(PREFIX) Window 'videohub-$(service)' does not exist. Creating a new window."; \
108- tmux new-window -n "videohub-$(service)"; \
109- tmux split-window -h ; \
110- tmux select-layout -t "videohub-$(service)" even-horizontal; \
111- fi
112- @echo "$(PREFIX) Running $(service) service in tmux..."
113- @tmux send-keys -t videohub-$(service).0 'export SERVICE=$(service) && bash ./docker/script/entrypoint.sh' C-m
114- @tmux select-pane -t videohub-$(service).1
115-endif
116- 
117-# 清除所有的构建产物
118-.PHONY: clean
119-clean:
120- @find . -type d -name "output" -exec rm -rf {} + -print
121- 
122-# 清除所有构建产物、compose 环境和它的数据
123-.PHONY: clean-all
124-clean-all: clean
125- @echo "$(PREFIX) Checking if docker-compose services are running..."
126- @docker-compose -f ./docker/docker-compose.yml ps -q | grep '.' && docker-compose -f ./docker/docker-compose.yml down || echo "$(PREFIX) No services are running."
127- @echo "$(PREFIX) Removing docker data..."
128- rm -rf ./docker/data
129- 
130-# 格式化代码,我们使用 gofumpt,是 fmt 的严格超集
131-.PHONY: fmt
132-fmt:
133- gofumpt -l -w .
134- 
135-# 优化 import 顺序结构
136-.PHONY: import
137-import:
138- goimports -w -local github.com/west2-online .
139- 
140-# 检查可能的错误
141-.PHONY: vet
142-vet:
143- go vet ./...
144- 
145-# 代码格式校验
146-.PHONY: lint
147-lint:
148- golangci-lint run --config=./.golangci.yml --tests --allow-parallel-runners --show-stats --print-resources-usage
149- 
150-# 检查依赖漏洞
151-.PHONY: vulncheck
152-vulncheck:
153- govulncheck ./...
154- 
155-.PHONY: tidy
156-tidy:
157- go mod tidy
158- 
159-# 前端服务相关命令
160-.PHONY: frontend frontend-stop frontend-build
161- 
162-# 启动前端服务
163-frontend:
164- @echo "$(PREFIX) Building and starting frontend service..."
165- @cd docker && docker compose up -d frontend
166- @echo "$(PREFIX) Frontend service is running at http://localhost:80"
167- 
168-# 停止前端服务
169-frontend-stop:
170- @echo "$(PREFIX) Stopping frontend service..."
171- @cd docker && docker compose stop frontend && docker compose rm -f frontend
172- @echo "$(PREFIX) Frontend service has been stopped"
173- 
174-# 构建前端服务
175-frontend-build:
176- @echo "$(PREFIX) Building frontend service..."
177- @cd docker && docker compose build --no-cache frontend
178- @echo "$(PREFIX) Frontend service build completed"
MREADME.md+22-475
@@ -1,484 +1,31 @@
1-# VideoHub1+# ZiTok Frontend
2 2 
3-API文档: https://2pr5l6um26.apifox.cn3+## 主题管理系统
4 4 
5-## 服务接口列表5+本项目已采用统一的主题管理架构:
6 6 
7-### 1. 用户服务 (UserService)7+- 主题配置:`lib/shared/styles/app_colors.dart` 与 `lib/shared/styles/app_theme.dart`
8-- Register8+- 状态管理:`lib/shared/providers/app_provider.dart`
9-- Login9+- 设置页面集成:`lib/features/user/presentation/pages/settingsPage.dart`
10-- GetUserInfo
11-- UploadAvatar
12-- RefreshToken
13 10 
14-### 2. 视频服务 (VideoService)11+### 使用方式
15-- Publish
16-- List
17-- Detail
18-- GetHotVideos
19-- Delete
20-- IncrementVisitCount
21-- IncrementLikeCount
22-- Search
23-- SemanticSearch
24 12 
25-### 3. 互动服务 (InteractionService)13+- 在 `MaterialApp` 中使用:
26-- Like14+ ```dart
27-- GetLikes15+ MaterialApp(
28-- Comment16+ theme: context.watch<AppProvider>().currentTheme,
29-- GetComments17+ )
30-- DeleteComment18+ ```
31-- LikeComment19+- 切换主题:
20+ ```dart
21+ context.read<AppProvider>().setThemeMode(AppThemeMode.dark); // 或 light/system
22+ ```
23+- 主题切换按钮示例:`lib/shared/widgets/theme_toggle.dart`
32 24 
33-### 4. 社交服务 (SocialService)25+### 持久化
34-- PrivateChat
35-- RoomChat
36-- CreateChatRoom
37 26 
38-## 技术栈27+主题与语言设置通过 `SharedPreferences` 持久化,实现于 `lib/core/storage/app_storage.dart`。
39 28 
40-### 后端29+### 测试
41-- **语言与框架**: Go 1.21, Kitex(RPC), Hertz(HTTP), Thrift(IDL)
42-- **数据存储**: MySQL(GORM), Redis, Elasticsearch
43-- **中间件**: Kafka, etcd, JWT
44-- **AI与搜索**: OpenAI API, 向量检索
45-- **监控**: OpenTelemetry
46-- **部署**: Docker, Docker Compose
47 30 
48-### 前端31+主题切换的Widget测试位于 `test/theme_test.dart`,验证 `MaterialApp` 的 `ThemeData` 会随 `AppProvider` 的模式更新。
49-- **框架**: Vue 3
50-- **构建工具**: Vite
51-- **UI组件库**: Element Plus
52-- **状态管理**: Pinia
53-- **路由**: Vue Router
54-- **HTTP客户端**: Axios
55-- **样式**: SCSS
56-- **包管理器**: npm
57- 
58-## 系统架构
59- 
60-基于微服务架构,划分为用户、视频、互动和社交四个核心服务,通过Gateway统一入口处理请求。服务间通过Kitex RPC框架通信,使用etcd进行服务发现。
61- 
62-## 核心实现
63- 
64-### 视频服务
65-- 基于OpenAI的语义搜索功能
66-- 视频元数据提取和标签管理
67-- 热门视频排行榜(访问量、点赞数)
68- 
69-### 缓存策略
70-- 热门视频使用Redis缓存
71-- 用户令牌缓存
72-- 点赞、访问量等计数器使用Redis实现
73-- 热门排行榜使用Redis Sorted Set
74-- 分服务的Redis DB隔离(用户服务DB0、视频服务DB1、社交服务DB2)
75- 
76-### 异步处理
77-- 视频上传后通过Kafka消息队列异步处理
78-- 视频封面生成、元数据提取(时长、分辨率)
79-- 异步数据写入与统计更新
80-- 异步更新Elasticsearch索引和向量数据库
81- 
82-### 社交功能
83-- 基于WebSocket的实时聊天
84-- 支持私聊消息和聊天室
85-- 聊天记录持久化存储
86- 
87-### 搜索功能
88-- 基于Elasticsearch的全文搜索
89-- 集成OpenAI API的语义搜索
90-- 支持多字段复合查询
91-- 搜索结果缓存优化
92- 
93-### 安全性
94-- JWT用户认证
95-- API访问频率限制
96-- 视频内容安全检查
@@ -0,0 +1 @@
1+include: package:flutter_lints/flutter.yaml
@@ -0,0 +1,14 @@
1+gradle-wrapper.jar
2+/.gradle
3+/captures/
4+/gradlew
5+/gradlew.bat
6+/local.properties
7+GeneratedPluginRegistrant.java
8+.cxx/
9+ 
10+# Remember to never publicly share your keystore.
11+# See https://flutter.dev/to/reference-keystore
12+key.properties
13+**/*.keystore
14+**/*.jks
Aandroid/app/build.gradle.kts+44-0文件内容审核中,请稍后刷新重试
@@ -0,0 +1,7 @@
1+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+ <!-- The INTERNET permission is required for development. Specifically,
3+ the Flutter tool needs it to communicate with the running application
4+ to allow setting breakpoints, to provide hot reload, etc.
5+ -->
6+ <uses-permission android:name="android.permission.INTERNET"/>
7+</manifest>
Aandroid/app/src/main/AndroidManifest.xml+47-0文件内容审核中,请稍后刷新重试
Aandroid/app/src/main/kotlin/com/example/frontend/MainActivity.kt+5-0文件内容审核中,请稍后刷新重试
Aandroid/app/src/main/kotlin/com/example/zitok/MainActivity.kt+5-0文件内容审核中,请稍后刷新重试
@@ -0,0 +1,12 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<!-- Modify this file to customize your launch splash screen -->
3+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4+ <item android:drawable="?android:colorBackground" />
5+ 
6+ <!-- You can insert your own image assets here -->
7+ <!-- <item>
8+ <bitmap
9+ android:gravity="center"
10+ android:src="@mipmap/launch_image" />
11+ </item> -->
12+</layer-list>
@@ -0,0 +1,12 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<!-- Modify this file to customize your launch splash screen -->
3+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4+ <item android:drawable="@android:color/white" />
5+ 
6+ <!-- You can insert your own image assets here -->
7+ <!-- <item>
8+ <bitmap
9+ android:gravity="center"
10+ android:src="@mipmap/launch_image" />
11+ </item> -->
12+</layer-list>
@@ -0,0 +1,18 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<resources>
3+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
4+ <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
5+ <!-- Show a splash screen on the activity. Automatically removed when
6+ the Flutter engine draws its first frame -->
7+ <item name="android:windowBackground">@drawable/launch_background</item>
8+ </style>
9+ <!-- Theme applied to the Android Window as soon as the process has started.
10+ This theme determines the color of the Android Window while your
11+ Flutter UI initializes, as well as behind your Flutter UI while its
12+ running.
13+ 
14+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
15+ <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
16+ <item name="android:windowBackground">?android:colorBackground</item>
17+ </style>
18+</resources>
@@ -0,0 +1,18 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<resources>
3+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
4+ <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
5+ <!-- Show a splash screen on the activity. Automatically removed when
6+ the Flutter engine draws its first frame -->
7+ <item name="android:windowBackground">@drawable/launch_background</item>
8+ </style>
9+ <!-- Theme applied to the Android Window as soon as the process has started.
10+ This theme determines the color of the Android Window while your
11+ Flutter UI initializes, as well as behind your Flutter UI while its
12+ running.
13+ 
14+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
15+ <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
16+ <item name="android:windowBackground">?android:colorBackground</item>
17+ </style>
18+</resources>
Aandroid/app/src/main/res/xml/network_security_config.xml+6-0文件内容审核中,请稍后刷新重试
@@ -0,0 +1,7 @@
1+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+ <!-- The INTERNET permission is required for development. Specifically,
3+ the Flutter tool needs it to communicate with the running application
4+ to allow setting breakpoints, to provide hot reload, etc.
5+ -->
6+ <uses-permission android:name="android.permission.INTERNET"/>
7+</manifest>
@@ -0,0 +1,24 @@
1+allprojects {
2+ repositories {
3+ google()
4+ mavenCentral()
5+ }
6+}
7+ 
8+val newBuildDir: Directory =
9+ rootProject.layout.buildDirectory
10+ .dir("../../build")
11+ .get()
12+rootProject.layout.buildDirectory.value(newBuildDir)
13+ 
14+subprojects {
15+ val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
16+ project.layout.buildDirectory.value(newSubprojectBuildDir)
17+}
18+subprojects {
19+ project.evaluationDependsOn(":app")
20+}
21+ 
22+tasks.register<Delete>("clean") {
23+ delete(rootProject.layout.buildDirectory)
24+}
@@ -0,0 +1,3 @@
1+org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
2+android.useAndroidX=true
3+android.enableJetifier=true
@@ -0,0 +1,5 @@
1+distributionBase=GRADLE_USER_HOME
2+distributionPath=wrapper/dists
3+zipStoreBase=GRADLE_USER_HOME
4+zipStorePath=wrapper/dists
5+distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
Aandroid/settings.gradle.kts+27-0文件内容审核中,请稍后刷新重试
@@ -1,149 +0,0 @@
1-// Code generated by hertz generator.
2- 
3-package interaction
4- 
5-import (
6- "context"
7- 
8- "github.com/cloudwego/hertz/pkg/app"
9- api "github.com/yxrxy/videoHub/app/gateway/model/interaction"
10- "github.com/yxrxy/videoHub/app/gateway/pack"
11- "github.com/yxrxy/videoHub/app/gateway/rpc"
12- "github.com/yxrxy/videoHub/kitex_gen/interaction"
13- "github.com/yxrxy/videoHub/pkg/errno"
14-)
15- 
16-// Like .
17-// @router /api/v1/video/:video_id/like [POST]
18-func Like(ctx context.Context, c *app.RequestContext) {
19- var err error
20- var req api.LikeRequest
21- err = c.BindAndValidate(&req)
22- if err != nil {
23- pack.RespError(c, errno.ParamVerifyError.WithError(err))
24- return
25- }
26- err = rpc.LikeVideoRPC(ctx, &interaction.LikeRequest{
27- VideoId: req.VideoID,
28- })
29- if err != nil {
30- pack.RespError(c, err)
31- return
32- }
33- pack.RespSuccess(c)
34-}
35- 
36-// GetLikes .
37-// @router /api/v1/video/:video_id/likes [GET]
38-func GetLikes(ctx context.Context, c *app.RequestContext) {
39- var err error
40- var req api.GetLikesRequest
41- err = c.BindAndValidate(&req)
42- if err != nil {
43- pack.RespError(c, errno.ParamVerifyError.WithError(err))
44- return
45- }
46- 
47- resp, _, err := rpc.GetLikesRPC(ctx, &interaction.GetLikesRequest{
48- VideoId: req.VideoID,
49- Page: req.Page,
50- Size: req.Size,
51- })
52- if err != nil {
53- pack.RespError(c, err)
54- return
55- }
56- pack.RespData(c, resp)
57-}
58- 
59-// Comment .
60-// @router /api/v1/video/:video_id/comment [POST]
61-func Comment(ctx context.Context, c *app.RequestContext) {
62- var err error
63- var req api.CommentRequest
64- err = c.BindAndValidate(&req)
65- if err != nil {
66- pack.RespError(c, errno.ParamVerifyError.WithError(err))
67- return
68- }
69- if req.ParentID == nil {
70- defaultValue := int64(-1)
71- req.ParentID = &defaultValue
72- }
73- err = rpc.CommentVideoRPC(ctx, &interaction.CommentRequest{
74- VideoId: req.VideoID,
75- Content: req.Content,
76- ParentId: req.ParentID,
77- })
78- if err != nil {
79- pack.RespError(c, err)
80- return
81- }
82- pack.RespSuccess(c)
83-}
84- 
85-// GetComments .
86-// @router /api/v1/video/:video_id/comments [GET]
87-func GetComments(ctx context.Context, c *app.RequestContext) {
88- var err error
89- var req api.GetCommentsRequest
90- err = c.BindAndValidate(&req)
91- if err != nil {
92- pack.RespError(c, errno.ParamVerifyError.WithError(err))
93- return
94- }
95- 
96- resp, _, err := rpc.GetCommentsRPC(ctx, &interaction.GetCommentsRequest{
97- VideoId: req.VideoID,
98- Page: req.Page,
99- Size: req.Size,
100- CommentId: req.CommentID,
101- })
102- if err != nil {
103- pack.RespError(c, err)
104- return
105- }
106- pack.RespData(c, resp)
107-}
108- 
109-// DeleteComment .
110-// @router /api/v1/comment/:comment_id [DELETE]
111-func DeleteComment(ctx context.Context, c *app.RequestContext) {
112- var err error
113- var req api.DeleteCommentRequest
114- err = c.BindAndValidate(&req)
115- if err != nil {
116- pack.RespError(c, errno.ParamVerifyError.WithError(err))
117- return
118- }
119- 
120- err = rpc.DeleteCommentRPC(ctx, &interaction.DeleteCommentRequest{
121- CommentId: req.CommentID,
122- })
123- if err != nil {
124- pack.RespError(c, err)
125- return
126- }
127- pack.RespSuccess(c)
128-}
129- 
130-// LikeComment .
131-// @router /api/v1/comment/:comment_id/like [POST]
132-func LikeComment(ctx context.Context, c *app.RequestContext) {
133- var err error
134- var req api.LikeCommentRequest
135- err = c.BindAndValidate(&req)
136- if err != nil {
137- pack.RespError(c, errno.ParamVerifyError.WithError(err))
138- return
139- }
140- 
141- err = rpc.LikeCommentRPC(ctx, &interaction.LikeCommentRequest{
142- CommentId: req.CommentID,
143- })
144- if err != nil {
145- pack.RespError(c, err)
146- return
147- }
148- pack.RespSuccess(c)
149-}
@@ -1,189 +0,0 @@
1-package notes
2- 
3-import (
4- "context"
5- "strconv"
6- 
7- "github.com/cloudwego/hertz/pkg/app"
8- 
9- "github.com/yxrxy/videoHub/app/gateway/pack"
10- "github.com/yxrxy/videoHub/app/gateway/rpc"
11- "github.com/yxrxy/videoHub/kitex_gen/notes"
12- "github.com/yxrxy/videoHub/pkg/errno"
13-)
14- 
15-// CreateNote 创建笔记
16-// @router /api/v1/note/create [POST]
17-func CreateNote(ctx context.Context, c *app.RequestContext) {
18- var req notes.CreateNoteRequest
19- err := c.BindAndValidate(&req)
20- if err != nil {
21- pack.RespError(c, errno.ParamVerifyError.WithError(err))
22- return
23- }
24- 
25- // 获取用户ID
26- userID, exists := c.Get("userID")
27- if !exists {
28- pack.RespError(c, errno.AuthInvalid)
29- return
30- }
31- req.UserId = userID.(int64)
32- 
33- resp, err := rpc.CreateNoteRPC(ctx, &req)
34- if err != nil {
35- pack.RespError(c, err)
36- return
37- }
38- 
39- pack.RespData(c, map[string]interface{}{
40- "note_id": resp.NoteId,
41- })
42-}
43- 
44-// DeleteNote 删除笔记
45-// @router /api/v1/note/delete [POST]
46-func DeleteNote(ctx context.Context, c *app.RequestContext) {
47- var req notes.DeleteNoteRequest
48- err := c.BindAndValidate(&req)
49- if err != nil {
50- pack.RespError(c, errno.ParamVerifyError.WithError(err))
51- return
52- }
53- 
54- // 获取用户ID
55- userID, exists := c.Get("userID")
56- if !exists {
57- pack.RespError(c, errno.AuthInvalid)
58- return
59- }
60- req.UserId = userID.(int64)
61- 
62- _, err = rpc.DeleteNoteRPC(ctx, &req)
63- if err != nil {
64- pack.RespError(c, err)
65- return
66- }
67- 
68- pack.RespSuccess(c)
69-}
70- 
71-// GetVideoNotes 获取视频的笔记列表
72-// @router /api/v1/note/video [GET]
73-func GetVideoNotes(ctx context.Context, c *app.RequestContext) {
74- videoIDStr := c.Query("videoId")
75- videoID, err := strconv.ParseInt(videoIDStr, 10, 64)
76- if err != nil {
77- pack.RespError(c, errno.ParamVerifyError.WithError(err))
78- return
79- }
80- 
81- pageStr := c.DefaultQuery("page", "1")
82- page, _ := strconv.Atoi(pageStr)
83- pageSizeStr := c.DefaultQuery("pageSize", "10")
84- pageSize, _ := strconv.Atoi(pageSizeStr)
85- 
86- pageInt32 := int32(page)
87- pageSizeInt32 := int32(pageSize)
88- 
89- req := &notes.GetNotesRequest{
90- VideoId: videoID,
91- Page: &pageInt32,
92- Size: &pageSizeInt32,
93- }
94- 
95- resp, err := rpc.GetNotesRPC(ctx, req)
96- if err != nil {
97- pack.RespError(c, err)
98- return
99- }
100- 
101- pack.RespData(c, resp)
102-}
103- 
104-// GetUserNotes 获取用户的笔记列表
105-// @router /api/v1/note/user [GET]
106-func GetUserNotes(ctx context.Context, c *app.RequestContext) {
107- userIDStr := c.Query("userId")
108- userID, err := strconv.ParseInt(userIDStr, 10, 64)
109- if err != nil {
110- pack.RespError(c, errno.ParamVerifyError.WithError(err))
111- return
112- }
113- 
114- pageStr := c.DefaultQuery("page", "1")
115- page, _ := strconv.Atoi(pageStr)
116- pageSizeStr := c.DefaultQuery("pageSize", "10")
117- pageSize, _ := strconv.Atoi(pageSizeStr)
118- 
119- pageInt32 := int32(page)
120- pageSizeInt32 := int32(pageSize)
121- 
122- req := &notes.GetUserNotesRequest{
123- UserId: userID,
124- Page: &pageInt32,
125- Size: &pageSizeInt32,
126- }
127- 
128- resp, err := rpc.GetUserNotesRPC(ctx, req)
129- if err != nil {
130- pack.RespError(c, err)
131- return
132- }
133- 
134- pack.RespData(c, resp)
135-}
136- 
137-// LikeNote 点赞笔记
138-// @router /api/v1/note/like [POST]
139-func LikeNote(ctx context.Context, c *app.RequestContext) {
140- var req notes.LikeNoteRequest
141- err := c.BindAndValidate(&req)
142- if err != nil {
143- pack.RespError(c, errno.ParamVerifyError.WithError(err))
144- return
145- }
146- 
147- // 获取用户ID
148- userID, exists := c.Get("userID")
149- if !exists {
150- pack.RespError(c, errno.AuthInvalid)
151- return
152- }
153- req.UserId = userID.(int64)
154- 
155- _, err = rpc.LikeNoteRPC(ctx, &req)
156- if err != nil {
157- pack.RespError(c, err)
158- return
159- }
160- 
161- pack.RespSuccess(c)
162-}
163- 
164-// FavoriteNote 收藏笔记
165-// @router /api/v1/note/favorite [POST]
166-func FavoriteNote(ctx context.Context, c *app.RequestContext) {
167- var req notes.FavoriteNoteRequest
168- err := c.BindAndValidate(&req)
169- if err != nil {
170- pack.RespError(c, errno.ParamVerifyError.WithError(err))
171- return
172- }
173- 
174- // 获取用户ID
175- userID, exists := c.Get("userID")
176- if !exists {
177- pack.RespError(c, errno.AuthInvalid)
178- return
179- }
180- req.UserId = userID.(int64)
181- 
182- _, err = rpc.FavoriteNoteRPC(ctx, &req)
183- if err != nil {
184- pack.RespError(c, err)
185- return
186- }
187- 
188- pack.RespSuccess(c)
189-}
@@ -1,600 +0,0 @@
1-// Code generated by hertz generator.
2- 
3-package social
4- 
5-import (
6- "context"
7- "encoding/json"
8- "fmt"
9- "strconv"
10- "sync"
11- "time"
12- 
13- "github.com/cloudwego/hertz/pkg/app"
14- "github.com/cloudwego/hertz/pkg/protocol/consts"
15- "github.com/cloudwego/kitex/pkg/klog"
16- "github.com/hertz-contrib/websocket"
17- api "github.com/yxrxy/videoHub/app/gateway/model/social"
18- "github.com/yxrxy/videoHub/app/gateway/pack"
19- "github.com/yxrxy/videoHub/app/gateway/rpc"
20- "github.com/yxrxy/videoHub/app/gateway/service/ws"
21- "github.com/yxrxy/videoHub/kitex_gen/social"
22- "github.com/yxrxy/videoHub/pkg/errno"
23- "github.com/yxrxy/videoHub/pkg/jwt"
24-)
25- 
26-var (
27- globalManager *ws.Manager
28- globalService *ws.WsService
29- once sync.Once
30-)
31- 
32-func initGlobalManager() {
33- once.Do(func() {
34- globalManager = ws.NewManager()
35- globalService = ws.NewWsService(globalManager)
36- go globalService.Start(context.Background())
37- })
38-}
39- 
40-// SendPrivateMessage .
41-// @router /api/v1/social/private/message [POST]
42-func SendPrivateMessage(ctx context.Context, c *app.RequestContext) {
43- var err error
44- var req api.SendPrivateMessageRequest
45- err = c.BindAndValidate(&req)
46- if err != nil {
47- pack.RespError(c, errno.ParamVerifyError.WithError(err))
48- return
49- }
50- err = globalService.SendPrivateMessage(req.SenderID, req.ReceiverID, req.Content)
51- if err != nil {
52- pack.RespError(c, err)
53- return
54- }
55- pack.RespSuccess(c)
56-}
57- 
58-// GetPrivateMessages .
59-// @router /api/v1/social/private/messages [GET]
60-func GetPrivateMessages(ctx context.Context, c *app.RequestContext) {
61- var err error
62- var req api.GetPrivateMessagesRequest
63- err = c.BindAndValidate(&req)
64- if err != nil {
65- pack.RespError(c, errno.ParamVerifyError.WithError(err))
66- return
67- }
68- resp, _, err := rpc.GetPrivateMessagesRPC(ctx, &social.GetPrivateMessagesRequest{
69- UserId: req.UserID,
70- OtherUserId: req.OtherUserID,
71- Page: req.Page,
72- Size: req.Size,
73- })
74- if err != nil {
75- pack.RespError(c, err)
76- return
77- }
78- pack.RespData(c, resp)
79-}
80- 
81-// CreateChatRoom .
82-// @router /api/v1/social/chatroom [POST]
83-func CreateChatRoom(ctx context.Context, c *app.RequestContext) {
84- var err error
85- var req api.CreateChatRoomRequest
86- err = c.BindAndValidate(&req)
87- if err != nil {
88- pack.RespError(c, errno.ParamVerifyError.WithError(err))
89- return
90- }
91- 
92- resp, err := rpc.CreateChatRoomRPC(ctx, &social.CreateChatRoomRequest{
93- CreatorId: req.CreatorID,
94- Name: req.Name,
95- Type: req.Type,
96- MemberIds: req.MemberIds,
97- })
98- if err != nil {
99- pack.RespError(c, err)
100- return
@@ -1,226 +0,0 @@
1-// Code generated by hertz generator.
2- 
3-package user
4- 
5-import (
6- "context"
7- "io"
8- 
9- "github.com/cloudwego/hertz/pkg/app"
10- 
11- api "github.com/yxrxy/videoHub/app/gateway/model/user"
12- "github.com/yxrxy/videoHub/app/gateway/pack"
13- "github.com/yxrxy/videoHub/app/gateway/rpc"
14- "github.com/yxrxy/videoHub/kitex_gen/user"
15- "github.com/yxrxy/videoHub/pkg/errno"
16-)
17- 
18-// Register .
19-// @router /api/v1/user/register [POST]
20-func Register(ctx context.Context, c *app.RequestContext) {
21- var err error
22- var req api.RegisterRequest
23- err = c.BindAndValidate(&req)
24- if err != nil {
25- pack.RespError(c, errno.ParamVerifyError.WithError(err))
26- return
27- }
28- 
29- resp, err := rpc.RegisterRPC(ctx, &user.RegisterRequest{
30- Username: req.Username,
31- Password: req.Password,
32- Email: req.Email, // 新增字段
33- })
34- if err != nil {
35- pack.RespError(c, err)
36- return
37- }
38- pack.RespData(c, map[string]any{
39- "user_id": resp,
40- })
41-}
42- 
43-// Login .
44-// @router /api/v1/user/login [POST]
45-func Login(ctx context.Context, c *app.RequestContext) {
46- var err error
47- var req api.LoginRequest
48- err = c.BindAndValidate(&req)
49- if err != nil {
50- pack.RespError(c, errno.ParamVerifyError.WithError(err))
51- return
52- }
53- resp, err := rpc.LoginRPC(ctx, &user.LoginRequest{
54- Username: req.Username,
55- Password: req.Password,
56- })
57- if err != nil {
58- pack.RespError(c, err)
59- return
60- }
61- c.Header("Authorization", "Bearer "+resp.Token)
62- c.Header("RefreshToken", resp.RefreshToken)
63- 
64- pack.RespData(c, map[string]any{
65- "user_id": resp.UserId,
66- "token": resp.Token,
67- "refresh_token": resp.RefreshToken,
68- })
69-}
70- 
71-// RefreshToken .
72-// @router /api/v1/user/token/refresh [POST]
73-func RefreshToken(ctx context.Context, c *app.RequestContext) {
74- var err error
75- var req api.RefreshTokenRequest
76- err = c.BindAndValidate(&req)
77- if err != nil {
78- pack.RespError(c, errno.ParamVerifyError.WithError(err))
79- return
80- }
81- 
82- // Extract refresh token from header
83- refreshToken := req.RefreshToken
84- if refreshToken == "" {
85- pack.RespError(c, errno.NewErrNo(errno.AuthNoTokenCode, "未提供刷新令牌"))
86- return
87- }
88- 
89- resp, err := rpc.RefreshTokenRPC(ctx, &user.RefreshTokenRequest{
90- UserId: req.UserID,
91- RefreshToken: refreshToken,
92- })
93- if err != nil {
94- pack.RespError(c, err)
95- return
96- }
97- 
98- // Set tokens in response headers
99- c.Header("Authorization", "Bearer "+resp.Token)
100- c.Header("RefreshToken", resp.RefreshToken)
101- 
102- pack.RespData(c, resp)
103-}
104- 
105-// GetUserInfo .
106-// @router /api/v1/user/info/:user_id [GET]
107-func GetUserInfo(ctx context.Context, c *app.RequestContext) {
108- var err error
109- var req api.UserInfoRequest
110- err = c.BindAndValidate(&req)
111- if err != nil {
112- pack.RespError(c, errno.ParamVerifyError.WithError(err))
113- return
114- }
115- resp, err := rpc.GetUserInfoRPC(ctx, &user.UserInfoRequest{
116- UserId: req.UserID,
117- })
118- if err != nil {
119- pack.RespError(c, err)
120- return
121- }
122- pack.RespData(c, resp)
123-}
124- 
125-// UploadAvatar ..
126-// @router /api/v1/user/avatar [POST]
127-func UploadAvatar(ctx context.Context, c *app.RequestContext) {
128- var err error
129- 
130- fileHeader, err := c.FormFile("avatar_data")
131- if err != nil {
132- pack.RespError(c, errno.ParamVerifyError.WithError(err))
133- return
134- }
135- 
136- file, err := fileHeader.Open()
137- if err != nil {
138- pack.RespError(c, errno.ParamVerifyError.WithError(err))
139- return
140- }
141- defer file.Close()
142- 
143- avatarData, err := io.ReadAll(file)
144- if err != nil {
145- pack.RespError(c, errno.ParamVerifyError.WithError(err))
146- return
147- }
148- 
149- resp, err := rpc.UploadAvatarRPC(ctx, &user.UploadAvatarRequest{
150- AvatarData: avatarData,
151- ContentType: fileHeader.Header.Get("Content-Type"),
152- })
153- if err != nil {
154- pack.RespError(c, err)
155- return
156- }
157- 
158- pack.RespData(c, resp)
159-}
160- 
161-// UpdateUserInfo .
162-// @router /api/v1/user/info [PUT]
163-func UpdateUserInfo(ctx context.Context, c *app.RequestContext) {
164- var err error
165- var req api.UpdateUserInfoRequest
166- err = c.BindAndValidate(&req)
167- if err != nil {
168- pack.RespError(c, errno.ParamVerifyError.WithError(err))
169- return
170- }
171- 
172- // 调用 RPC 更新信息
173- resp, err := rpc.UpdateUserInfoRPC(ctx, &user.UpdateUserInfoRequest{
174- Username: req.Username,
175- Password: req.Password,
176- Signature: req.Signature,
177- Gender: req.Gender,
178- Birthday: req.Birthday,
179- Email: req.Email,
180- })
181- 
182- if err != nil {
183- pack.RespError(c, err)
184- return
185- }
186- 
187- pack.RespData(c, resp) // 或 resp.Base
188-}
189- 
190-// UploadBackground .
191-// @router /api/v1/user/background [POST]
192-func UploadBackground(ctx context.Context, c *app.RequestContext) {
193- var err error
194- 
195- // 与 UploadAvatar 逻辑类似,读取背景图文件
196- fileHeader, err := c.FormFile("background_data")
197- if err != nil {
198- pack.RespError(c, errno.ParamVerifyError.WithError(err))
199- return
200- }
201- 
202- file, err := fileHeader.Open()
203- if err != nil {
204- pack.RespError(c, errno.ParamVerifyError.WithError(err))
205- return
206- }
207- defer file.Close()
208- 
209- backgroundData, err := io.ReadAll(file)
210- if err != nil {
211- pack.RespError(c, errno.ParamVerifyError.WithError(err))
212- return
213- }
214- 
215- // 调用 RPC
216- resp, err := rpc.UploadBackgroundRPC(ctx, &user.UploadBackgroundRequest{
217- BackgroundData: backgroundData,
218- ContentType: fileHeader.Header.Get("Content-Type"),
219- })
220- if err != nil {
221- pack.RespError(c, err)
222- return
223- }
224- 
225- pack.RespData(c, resp) // 返回更新后的 User
226-}
Adocs/components.md+115-0文件内容审核中,请稍后刷新重试
Adocs/用户模块.openapi.json+1147-0文件内容审核中,请稍后刷新重试
Adocs/视频模块.openapi.json+1225-0文件内容审核中,请稍后刷新重试
Dgo.mod+0-166
Dgo.sum+0-738
Aios/Runner.xcodeproj/project.pbxproj+616-0文件内容审核中,请稍后刷新重试
Aios/Runner/Info.plist+49-0文件内容审核中,请稍后刷新重试
Apubspec.lock+1210-0