### Install Web Frontend Dependencies Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-installation.md Navigate to the web directory and install project dependencies using pnpm. ```shell cd web # 首先确定你以安装node16.0以上版本并安装了包[npm、pnpm],否则可能会出现一些未知报错 # 安装依赖 pnpm install ``` -------------------------------- ### Start Web Frontend Service Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-installation.md Start the web frontend development server using pnpm. ```shell pnpm run dev ``` -------------------------------- ### Start Server Service Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-installation.md Navigate to the server directory, update dependencies, and start the server using GoFrame CLI. ```shell cd server # 设置国内代理,如果已经设置好了代理可以跳过 go env -w GOPROXY=https://goproxy.io,direct # 更新包 go mod tidy # 查看命令行方法 go run main.go help # 启动所有服务 go run main.go # 热编译启动: gf run main.go ``` -------------------------------- ### Local Preview with live-server Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/web-deploy.md Install and use the `live-server` package for local previewing. Navigate to the 'dist' directory and run the command. You can specify a port if needed. ```shell # 1.全局安装live-server npm -g install live-server # 2. 进入打包的后目录 cd ./dist # 本地预览,默认端口8080 live-server # 指定端口 live-server --port 9000 ``` -------------------------------- ### Go Logging Examples Source: https://github.com/bufanyun/hotgo/blob/v2.0/AGENTS.md Demonstrates the usage of different logging levels (Info, Warning, Panic) with contextual information and structured data. ```go // Info:记录正常流程关键事件 g.Log().Infof(ctx, "用户登录成功 uid:%d ip:%s", member.Id, ip) // Info:记录外部调用结果 g.Log().Info(ctx, "支付回调处理完成", g.Map{"orderId": orderId, "status": status}) // Warning:外部接口失败但已降级处理 g.Log().Warningf(ctx, "短信发送失败,已跳过 mobile:%s err:%+v", mobile, err) // Warning:业务异常但不中断流程 g.Log().Warning(ctx, "用户余额不足,跳过自动扣款", g.Map{"uid": uid, "balance": balance}) // Panic:启动时核心配置缺失 g.Log().Panicf(ctx, "缓存未初始化,无法启动: %+v", err) ``` -------------------------------- ### Nginx Configuration for Gzip and Brotli Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/web-deploy.md Example Nginx configuration to enable both gzip and brotli compression. Ensure the necessary Nginx modules are installed for brotli support. ```nginx http { # 开启gzip gzip on; # 开启gzip_static # gzip_static 开启后可能会报错,需要安装相应的模块, 具体安装方式可以自行查询 # 只有这个开启,vue文件打包的.gz文件才会有效果,否则不需要开启gzip进行打包 gzip_static on; gzip_proxied any; gzip_min_length 1k; gzip_buffers 4 16k; #如果nginx中使用了多层代理 必须设置这个才可以开启gzip。 gzip_http_version 1.0; gzip_comp_level 2; gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; gzip_vary off; gzip_disable "MSIE [1-6]\."; # 开启 brotli压缩 # 需要安装对应的nginx模块,具体安装方式可以自行查询 # 可以与gzip共存不会冲突 brotli on; brotli_comp_level 6; brotli_buffers 16 8k; brotli_min_length 20; brotli_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml; } ``` -------------------------------- ### Verify Golang Installation Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-environment.md Checks if Golang is installed and displays its version. Requires Golang version 1.23 or higher. ```bash go version ``` -------------------------------- ### Get Module Info Inside Addon Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/addon-helper.md Example of how to retrieve the current addon module's skeleton information from within the module itself. ```go package main import ( "fmt" "hotgo/addons/hgexample/global" ) func test() { fmt.Printf("当前插件模块是:%+v", global.GetSkeleton()) } ``` -------------------------------- ### Install HGExample Addon Source: https://github.com/bufanyun/hotgo/blob/v2.0/server/addons/hgexample/README.MD This code snippet is used to register the hgexample addon within the HotGo modules. Ensure HotGo version 2.11.4 or higher is installed. ```go package modules import _ "hotgo/addons/hgexample" ``` -------------------------------- ### Verify pnpm Installation Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-environment.md Checks if pnpm is installed and displays its version. This confirms the frontend environment setup. ```bash pnpm -v ``` -------------------------------- ### Global Middleware Setup Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/sys-middleware.md Initializes essential global middleware for request context, CORS, IP blacklisting, demo mode limitations, input pre-filtering, and response handling. These should generally be loaded in the order shown due to dependencies. ```go package main import ( "hotgo/internal/service" ) func main() { // 初始化请求上下文,一般需要第一个进行加载,后续中间件存在依赖关系 service.Middleware().Ctx() // 跨域中间件,自动处理跨域问题 service.Middleware().CORS() // IP黑名单中间件,如果请求IP被后台拉黑,所有请求将被拒绝 service.Middleware().Blacklist() // 演示系統操作限制,当开启演示模式时,所有POST请求将被拒绝 service.Middleware().DemoLimit() // 请求输入预处理,api使用gf规范路由并且XxxReq结构体实现了validate.Filter接口即可隐式预处理 service.Middleware().PreFilter() // HTTP响应预处理,在业务处理完成后,对响应结果进行格式化和错误过滤,将处理后的数据发送给请求方 sservice.Middleware().ResponseHandler() } ``` -------------------------------- ### One-Click Compilation with Make Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-deploy.md Use this command to perform a one-click build if you have the Make environment installed. ```shell cd server && make build ``` -------------------------------- ### Install pnpm Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-environment.md Installs pnpm globally using npm. Ensure Node.js is installed and its version is 16.0 or higher. ```bash npm install -g pnpm ``` -------------------------------- ### Sending a Message to the Queue Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/sys-queue.md Example of how to send a message to a specific topic in the queue. Ensure the message data structure matches the expected format for the consumer. ```go package main import ( "fmt" "hotgo/internal/consts" "hotgo/internal/library/queue" "hotgo/internal/model/entity" ) func test() { data := &entity.SysLog{ //... } if err := queue.Push(consts.QueueLogTopic, data); err != nil { fmt.Printf("queue.Push err:%+v", err) } } ``` -------------------------------- ### Basic TCP Message Send/Receive Example Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/sys-tcp-server.md Demonstrates a basic TCP message exchange between a client and server, including request and response structures, router registration, and RPC handling. ```go package tcp_test import ( "context" "fmt" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/test/gtest" hotgo "hotgo/internal/library/network/tcp" testing "testing" time "time" ) var T *testing.T // 声明一个全局的 *testing.T 变量 type TestMsgReq struct { Name string `json:"name"` } type TestMsgRes struct { hotgo.ServerRes } type TestRPCMsgReq struct { Name string `json:"name"` } type TestRPCMsgRes struct { hotgo.ServerRes } func onTestMsg(ctx context.Context, req *TestMsgReq) { fmt.Printf("服务器收到消息 ==> onTestMsg:%+v\n", req) conn := hotgo.ConnFromCtx(ctx) gtest.C(T, func(t *gtest.T) { t.AssertNE(conn, nil) }) res := new(TestMsgRes) res.Message = fmt.Sprintf("你的名字:%v", req.Name) conn.Send(ctx, res) } func onResponseTestMsg(ctx context.Context, req *TestMsgRes) { fmt.Printf("客户端收到响应消息 ==> TestMsgRes:%+v\n", req) err := req.GetError() gtest.C(T, func(t *gtest.T) { t.AssertNil(err) }) } func onTestRPCMsg(ctx context.Context, req *TestRPCMsgReq) (res *TestRPCMsgRes, err error) { fmt.Printf("服务器收到消息 ==> onTestRPCMsg:%+v\n", req) res = new(TestRPCMsgRes) res.Message = fmt.Sprintf("你的名字:%v", req.Name) return } func startTCPServer() { serv := hotgo.NewServer(&hotgo.ServerConfig{ Name: "hotgo", Addr: ":8002", }) // 注册路由 serv.RegisterRouter( onTestMsg, ) // 注册RPC路由 serv.RegisterRPCRouter( onTestRPCMsg, ) // 服务监听 err := serv.Listen() gtest.C(T, func(t *gtest.T) { t.AssertNil(err) }) } // 一个基本的消息收发 func TestSendMsg(t *testing.T) { T = t go startTCPServer() ctx := gctx.New() client := hotgo.NewClient(&hotgo.ClientConfig{ Addr: "127.0.0.1:8002", }) // 注册路由 client.RegisterRouter( onResponseTestMsg, ) go func() { err := client.Start() gtest.C(T, func(t *gtest.T) { t.AssertNil(err) }) }() // 确保服务都启动完成 time.Sleep(time.Second * 1) // 拿到客户端的连接 conn := client.Conn() gtest.C(T, func(t *gtest.T) { t.AssertNE(conn, nil) }) // 向服务器发送tcp消息,不会阻塞程序执行 err = conn.Send(ctx, &TestMsgReq{Name: "Tom"}) gtest.C(T, func(t *gtest.T) { t.AssertNil(err) }) // 向服务器发送rpc消息,会等待服务器响应结果,直到拿到结果或响应超时才会继续 var res TestRPCMsgRes if err = conn.RequestScan(ctx, &TestRPCMsgReq{Name: "Tony"}, &res); err != nil { gtest.C(T, func(t *gtest.T) { t.AssertNil(err) }) } fmt.Printf("客户端收到RPC消息响应 ==> TestRPCMsgRes:%+v\n", res) time.Sleep(time.Second * 1) } ``` -------------------------------- ### Nginx Configuration for History Mode (Subdirectory) Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/web-deploy.md Example Nginx configuration for deploying with HTML5 History mode when the application is served from a subdirectory. Adjust `location` and `try_files` to match your subdirectory. ```nginx server { listen 80; server_name localhost; location /sub/ { # 这里是vue打包文件dist内的文件的存放路径 alias /srv/www/project/; index index.html index.htm; try_files $uri $uri/ /sub/index.html; } } ``` -------------------------------- ### Sending Messages with Go Queue Library Source: https://github.com/bufanyun/hotgo/blob/v2.0/AGENTS.md Examples of sending immediate and delayed messages using the `queue` package. Delayed message functionality is dependent on the specific driver (Redis/RocketMQ). ```go // 即时消息 queue.Push(consts.QueueMyTopic, data) // 延迟消息(仅 redis/rocketmq 驱动支持) queue.SendDelayMsg(consts.QueueMyTopic, data, 10) // redis: 延迟秒数;rocketmq: 延迟级别 ``` -------------------------------- ### HotGo Server and Web Development Hot Compilation Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/code-curd-join.md Start the HotGo server and web client using hot compilation for automatic updates. This is the recommended method for development. ```shell # Server cd server gf run main.go # Web client cd web pnpm run dev 或 npm run dev ``` -------------------------------- ### Implement a Basic WebSocket Message Handler Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/sys-websocket-server.md An example implementation of the EventHandler interface that logs received messages and echoes them back to the client. This handler is registered for the 'admin/addons/hgexample/testMessage' event. ```go package handler import ( "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/frame/g" "hotgo/internal/websocket" ) var ( Index = cIndex{} ) type cIndex struct{} // TestMessage 测试消息 func (c *cIndex) TestMessage(client *websocket.Client, req *websocket.WRequest) { g.Log().Infof(client.Context(), "收到客户端测试消息:%v", gjson.New(req).String()) // 将收到的消息原样发送给客户端 websocket.SendSuccess(client, req.Event, req.Data) } ``` -------------------------------- ### Plugin Entry Point (main.go) Source: https://github.com/bufanyun/hotgo/blob/v2.0/AGENTS.md Defines the main entry point for a plugin, including its metadata and startup logic. The `init()` function registers the module with the addon system. ```go package import ( "context" "github.com/gogf/gf/v2/net/ghttp" _ "hotgo/addons//crons" "hotgo/addons//global" _ "hotgo/addons//logic" _ "hotgo/addons//queues" "hotgo/addons//router" "hotgo/internal/library/addons" "hotgo/internal/service" "sync" ) type module struct { skeleton *addons.Skeleton ctx context.Context sync.Mutex } func init() { newModule() } func newModule() { m := &module{ skeleton: &addons.Skeleton{ Label: "插件显示名", Name: "", // 与目录名一致 Group: 1, Brief: "简介", Description: "详细描述", Author: "作者", Version: "v1.0.0", }, ctx: gctx.New(), } addons.RegisterModule(m) } func (m *module) Start(option *addons.Option) (err error) { global.Init(m.ctx, m.skeleton) option.Server.Group("/", func(group *ghttp.RouterGroup) { group.Middleware(service.Middleware().Addon) router.Admin(m.ctx, group) router.Api(m.ctx, group) }) return } // 其余方法:Stop、Ctx、GetSkeleton、Install、Upgrade、UnInstall(默认留空) ``` -------------------------------- ### Verify Node.js Installation Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-environment.md Checks if Node.js is installed and displays its version. Requires Node.js version 16.0 or higher. ```bash node -v ``` -------------------------------- ### Preview Project Build Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/web-deploy.md Use these commands to preview your built project locally before deployment. The first command builds and then previews, while the second directly previews the 'dist' directory. ```shell # 先打包在进行预览 pnpm run preview 或 npm run preview # 直接预览本地 dist 文件目录 pnpm run preview:dist 或 npm run preview:dist ``` -------------------------------- ### Build Project Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/web-deploy.md Execute this command to build your project for deployment. A 'dist' folder will be generated containing the build artifacts. ```shell pnpm run build 或 npm run build ``` -------------------------------- ### Manual Compilation Steps Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-deploy.md Follow these steps for manual compilation, including cleaning previous web resources, compiling the web project, and then compiling the server. ```shell cd server # 切换到服务端目录下 rm -rf ./resource/public/admin/ # 删除之前的web资源 mkdir ./resource/public/admin/ # 重新创建web资源存放目录,除首次编译后续可以跳过执行此步骤 cd ../web && pnpm run build # 切换到web项目下,编译web项目 \cp -rf ./dist/* ../server/resource/public/admin/ # 将编译好的web资源复制到server对应的资源存放路径下 cd ../server # 切换回服务端目录下 echo "y" | gf build # 编译hotgo服务端 # 不出意外你已经编译好了hotgo可执行文件! ``` -------------------------------- ### Tree Select Component Setup Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/web-form.md Defines the setup for a Vue component using the Tree Select. It includes sample data for options and a handler for value updates. ```vue export default defineComponent({ setup () { return { handleUpdateValue ( value: string | number | Array | null, option: TreeSelectOption | null | Array ) { console.log(value, option) }, options: [ { label: 'Rubber Soul', key: 'Rubber Soul', children: [ { label: "Everybody's Got Something to Hide Except Me and My Monkey", key: "Everybody's Got Something to Hide Except Me and My Monkey" }, { label: 'Drive My Car', key: 'Drive My Car', disabled: true }, { label: 'Norwegian Wood', key: 'Norwegian Wood' }, { label: "You Won't See", key: "You Won't See", disabled: true }, { label: 'Nowhere Man', key: 'Nowhere Man' }, { label: 'Think For Yourself', key: 'Think For Yourself' }, { label: 'The Word', key: 'The Word' }, { label: 'Michelle', key: 'Michelle', disabled: true }, { label: 'What goes on', key: 'What goes on' }, { label: 'Girl', key: 'Girl' }, { label: "I'm looking through you", key: "I'm looking through you" }, { label: 'In My Life', key: 'In My Life' }, { label: 'Wait', key: 'Wait' } ] }, { label: 'Let It Be', key: 'Let It Be Album', children: [ { label: 'Two Of Us', key: 'Two Of Us' }, { label: 'Dig A Pony', key: 'Dig A Pony' }, { label: 'Across The Universe', key: 'Across The Universe' }, { label: 'I Me Mine', key: 'I Me Mine' }, { label: 'Dig It', key: 'Dig It' }, { label: 'Let It Be', key: 'Let It Be' }, { label: 'Maggie Mae', key: 'Maggie Mae' }, { label: "I've Got A Feeling", key: "I've Got A Feeling" }, { label: 'One After 909', key: 'One After 909' }, { label: 'The Long And Winding Road', key: 'The Long And Winding Road' }, { label: 'For You Blue', key: 'For You Blue' }, { label: 'Get Back', key: 'Get Back' } ] } ] } } }) ``` -------------------------------- ### Backend: Define and Register Constants and Options Source: https://github.com/bufanyun/hotgo/blob/v2.0/AGENTS.md Define constants for enum values and create corresponding options using style functions. Register these options in the init() function. ```go const ( XxxStatusEnabled = 1 // 启用 XxxStatusDisable = 2 // 禁用 ) var XxxStatusOptions = []*model.Option{ dict.GenSuccessOption(XxxStatusEnabled, "启用"), dict.GenWarningOption(XxxStatusDisable, "禁用"), } func init() { dict.RegisterEnums("XxxStatusOptions", "XXX状态选项", XxxStatusOptions) } ``` -------------------------------- ### Implicit Plugin Registration Source: https://github.com/bufanyun/hotgo/blob/v2.0/AGENTS.md Explains how to implicitly register a plugin by creating a Go file in `server/addons/modules/` that contains a single line of anonymous import for the plugin. ```go package modules import _ "hotgo/addons/" ``` -------------------------------- ### Time Range Picker Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/web-form.md A component for selecting a start and end time. Use when a time interval is needed. ```vue ``` -------------------------------- ### Date Range Picker Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/web-form.md A component for selecting a start and end date. Use when a date interval is required. ```vue ``` -------------------------------- ### 创建新插件目录结构 Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/addon-flow.md 成功创建插件后,会在指定目录下生成默认文件结构。插件名假设为 hgexample。 ```shell 1. /server/addons/hgexample/ # 插件模块目录 2. /server/addons/modules/hgexample.go # 隐式注册插件文件 3. /server/resource/addons/hgexample # 静态资源和页面模板目录,属于扩展功能选项,勾选对应选项后才会生成 4. /web/src/api/addons/hgexample # webApi目录 5. /web/src/views/addons/hgexample # web页面目录 # 默认情况下没有为web页面生成菜单权限,因为在实际场景中插件不一定需要用到web页面,所以如有需要请手动到后台 权限管理 -> 菜单权限->自行添加菜单和配置权限 ``` -------------------------------- ### Single Select Dropdown Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/web-form.md Demonstrates a basic single-select dropdown with options. Includes an example of a disabled select component. ```vue ``` -------------------------------- ### Backend: Use Dictionaries in Logic Layer Source: https://github.com/bufanyun/hotgo/blob/v2.0/AGENTS.md Retrieve option labels and validate option keys using the dict package in the backend Logic layer. ```go // 获取标签文本 label := dict.GetOptionLabel(consts.XxxStatusOptions, in.Status) // 校验是否为合法值 if !dict.HasOptionKey(consts.XxxStatusOptions, in.Status) { return gerror.New("状态值不合法") } ``` -------------------------------- ### Configure Relationship for Category ID Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/sys-code.md Example configuration to associate the `category_id` field in `hg_test_table` with the `id` field in `hg_test_category`. ```json { "join": [ { "field": "category_id", "type": "belongsTo", "model": "TestCategory", "key": "id", "columns": [ { "field": "name", "label": "分类名称" } ] } ] } ``` -------------------------------- ### 配置多个数据库的生成器 Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/code-config.md 在`server/hack/config.yaml`中配置多个数据库连接,包括数据库链接、分组、排除的表、前缀等。 ```yaml gen: dao: - link: "mysql:hotgo:hg123456.@tcp(127.0.0.1:3306)/hotgo?loc=Local&parseTime=true" group: "default" # 分组 使用hotgo代码生成功能时必须填 tablesEx: "hg_sys_addons_install" # 指定当前数据库中需要排除代码生成的数据表。 removePrefix: "hg_" descriptionTag: true noModelComment: true jsonCase: "CamelLower" gJsonSupport: true clear: false - link: "mysql:hotgo2:hg123456.@tcp(127.0.0.1:3306)/hotgo2?loc=Local&parseTime=true" group: "default2" # 分组 使用hotgo代码生成功能时必须填 tablesEx: "hg_sys_addons_install" # 指定当前数据库中需要排除代码生成的数据表。 removePrefix: "" descriptionTag: true noModelComment: true jsonCase: "CamelLower" gJsonSupport: true clear: false ``` -------------------------------- ### Get Module Info Outside Addon Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/addon-helper.md Demonstrates how to check if a request is from an addon and retrieve addon information from outside the module. ```go package main import ( "context" "fmt" "hotgo/internal/library/addons" "hotgo/internal/library/contexts" ) func test(ctx context.Context) { fmt.Printf("当前是否为插件请求:%v", contexts.IsAddonRequest(ctx)) if contexts.IsAddonRequest(ctx) { fmt.Printf("当前插件名称:%v", contexts.GetAddonName(ctx)) fmt.Printf("当前插件信息:%v", addons.GetModule(contexts.GetAddonName(ctx))) } } ``` -------------------------------- ### 生产环境配置 Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-issue.md 在生产环境且不需要开发工具功能时,可将 manifest/config/config.yaml 中的 system.mode 改为 product。 ```yaml get cli configuration file:hack/config.yaml, err:cannot find "hack/config.yaml" in following paths: ``` -------------------------------- ### Common WebSocket Server Methods Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/sys-websocket-server.md Demonstrates common methods for sending messages to clients, retrieving client information, and sending success or error responses. ```go func test() { websocket.SendToAll() // 发送全部客户端 websocket.SendToClientID() // 发送单个客户端 websocket.SendToUser() // 发送单个用户 websocket.SendToTag() // 发送某个标签、群组 client := websocket.Manager().GetClient(id) // 通过连接ID获取客户端连接 client := websocket.Manager().GetUserClient(userId) // 通过用户ID获取客户端连接,因为用户是可多端登录的,这里返回的是一个切片 websocket.SendSuccess(client, "admin/addons/hgexample/testMessage", "消息内容") // 向指定客户端发送一条成功的消息 websocket.SendError(client, "admin/addons/hgexample/testMessage", gerror.New("错误内容")) // 向指定客户端发送一条失败的消息 } ``` -------------------------------- ### Register WebSocket Message Handlers Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/sys-websocket-server.md Registers custom message handlers with the WebSocket server. This example registers the TestMessage handler for the 'admin/addons/hgexample/testMessage' event. ```go package router import ( "context" "github.com/gogf/gf/v2/net/ghttp" "hotgo/addons/hgexample/controller/websocket" "hotgo/addons/hgexample/controller/websocket/handler" ws "hotgo/internal/websocket" ) // WebSocket ws路由配置 func WebSocket(ctx context.Context, group *ghttp.RouterGroup) { // 注册消息路由 ws.RegisterMsg(ws.EventHandlers{ "admin/addons/hgexample/testMessage": handler.Index.TestMessage, // 测试消息 }) // 这里"admin/addons/hgexample/testMessage"代表的是一个消息处理ID,可以自定义。建议的格式是和HTTP接口格式保持一致,这样还可以便于对用户请求的消息进行权限验证 // 客户端连接后,向WebSocket服务器发送event为"admin/addons/hgexample/testMessage"的消息时,会调用TestMessage方法 } ``` -------------------------------- ### Get Cache Data Source: https://github.com/bufanyun/hotgo/blob/v2.0/AGENTS.md Retrieve data from the cache using `cache.Instance().Get`. Handle potential errors and check if the value is nil (cache miss). ```Go import ( "hotgo/internal/library/cache" "github.com/gogf/gf/v2/os/gcache" "time" ) // 获取缓存 val, err := cache.Instance().Get(ctx, "user:info:1") if err != nil || val.IsNil() { // 缓存未命中,查数据库 } ``` -------------------------------- ### 注册支付回调方法 Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/sys-payment.md 在server/internal/logic/pay/notify.go文件中注册支付成功回调方法。当订单支付成功并验签通过后,会自动回调到指定的业务订单分组方法。 ```go package global import ( "hotgo/internal/consts" "hotgo/internal/library/payment" "hotgo/internal/service" ) // RegisterNotifyCall 注册支付成功回调方法 func (s *sPay) RegisterNotifyCall() { payment.RegisterNotifyCallMap(map[string]payment.NotifyCallFunc{ consts.OrderGroupAdminOrder: service.AdminOrder().PayNotify, // 后台充值订单 // ... }) } ``` -------------------------------- ### Enable Both Gzip and Brotli Compression Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/web-deploy.md Set `VITE_BUILD_COMPRESS='brotli,gzip'` to generate both `.gz` and `.br` files during the build process. ```shell # 根据自己路径来配置更改 # 例如部署在nginx /next/路径下 则VITE_PUBLIC_PATH=/next/ VITE_PUBLIC_PATH=/ VITE_BUILD_COMPRESS='brotli,gzip' ``` -------------------------------- ### Nginx Configuration for API Proxy (Cross-Origin) Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/web-deploy.md Example Nginx configuration to proxy API requests from `/api` to your backend server. This is essential for handling cross-origin requests in a production environment. ```nginx server { listen 8080; server_name localhost; # 接口代理,用于解决跨域问题 location /api { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 后台接口地址 proxy_pass http://110.110.1.1:8080/api; proxy_redirect default; add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Headers X-Requested-With; add_header Access-Control-Allow-Methods GET,POST,OPTIONS; } } ``` -------------------------------- ### 获取用户部门类型 Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/sys-tenant.md 在用户登录成功后,server端可通过上下文来获取用户部门类型来确定用户身份。此代码定义了获取和判断用户部门类型的函数。 ```go package contexts import ( "context" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "hotgo/internal/consts" "hotgo/internal/model" ) // GetDeptType 获取用户部门类型 func GetDeptType(ctx context.Context) string { user := GetUser(ctx) if user == nil { return "" } return user.DeptType } // IsCompanyDept 是否为公司部门 func IsCompanyDept(ctx context.Context) bool { return GetDeptType(ctx) == consts.DeptTypeCompany } // IsTenantDept 是否为租户部门 func IsTenantDept(ctx context.Context) bool { return GetDeptType(ctx) == consts.DeptTypeTenant } // IsMerchantDept 是否为商户部门 func IsMerchantDept(ctx context.Context) bool { return GetDeptType(ctx) == consts.DeptTypeMerchant } // IsUserDept 是否为普通用户部门 func IsUserDept(ctx context.Context) bool { return GetDeptType(ctx) == consts.DeptTypeUser } ``` -------------------------------- ### Enable Gzip Compression Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/web-deploy.md Set `VITE_BUILD_COMPRESS='gzip'` in your environment configuration to generate `.gz` files during the build process. This speeds up page loading when used with Nginx's `gzip_static`. ```shell # 根据自己路径来配置更改 # 例如部署在nginx /next/路径下 则VITE_PUBLIC_PATH=/next/ VITE_PUBLIC_PATH=/ VITE_BUILD_COMPRESS='gzip' ``` -------------------------------- ### TCP Server Interceptor Example Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/sys-tcp-server.md Registering multiple interceptors for both server and client to handle various scenarios during message processing. Interceptors execute sequentially and can halt further processing by returning an error. ```go package main import ( "context" "github.com/gogf/gf/v2/frame/g" hotgo "hotgo/internal/library/network/tcp" ) func main() { serv = tcp.NewServer(&tcp.ServerConfig{ Name: "hotgo", Addr: ":8002", }) // 注册拦截器 // 执行顺序是从前到后,即Interceptor -> Interceptor2 -> Interceptor3。如果中间有任意一个抛出错误,则会中断后续处理 serv.RegisterInterceptor(Interceptor, Interceptor2, Interceptor3) // 服务监听 if err := serv.Listen(); err != nil { if !serv.IsClose() { g.Log().Warningf(ctx, "TCPServer Listen err:%v", err) } } } func Interceptor(ctx context.Context, msg *tcp.Message) (err error) { // 可以在拦截器中通过上下文拿到连接 conn := tcp.ConnFromCtx(ctx) // 拿到原始请求消息 g.Dump(msg) // 如果想要中断后续处理只需返回一个错误即可,但注意两种情况 // tcp消息:如果你还想对该消息进行回复应在拦截器中进行处理,例如:conn.Send(ctx, 回复消息内容) // rpc消息:返回一个错误后系统会将错误自动回复到rpc响应中,无需单独处理 return } func Interceptor2(ctx context.Context, msg *tcp.Message) (err error) { // ... return } func Interceptor3(ctx context.Context, msg *tcp.Message) (err error) { // ... return } ``` -------------------------------- ### 配置数据库连接和代码生成器 Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/code-config.md 在`server/manifest/config/config.yaml`中配置数据库连接(如`default`和`default2`)以及代码生成器的白名单IP、可选数据库等。 ```yaml database: logger: level: "all" stdout: true default: link: "mysql:hotgo:hg123456.@tcp(127.0.0.1:3306)/hotgo?loc=Local&parseTime=true" # link: "pgsql:postgres:hg123456@tcp(127.0.0.1:5432)/hotgo" debug: true Prefix: "hg_" default2: link: "mysql:hotgo2:hg123456.@tcp(127.0.0.1:3306)/hotgo2?loc=Local&parseTime=true" debug: true Prefix: "" ``` ```yaml hggen: allowedIPs: ["127.0.0.1", "*"] # 白名单,*代表所有,只有允许的IP后台才能使用生成代码功能 selectDbs: [ "default", "default2" ] # 可选生成表的数据库配置名称,支持多库 disableTables : ["hg_sys_gen_codes","hg_admin_role_casbin"] # 禁用的表,禁用以后将不会在选择表中看到 delimiters: ["@{, "] # 模板引擎变量分隔符号 ``` -------------------------------- ### Nginx Configuration for Static File Deployment Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/web-deploy.md Example Nginx configuration for serving static files from the 'dist' directory. It includes caching control for HTML files to prevent stale content after updates. ```nginx location / { # 不缓存html,防止程序更新后缓存继续生效 if ($request_filename ~* .*\](htm|html)$) { add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate"; access_log on; } # 这里是vue打包文件dist内的文件的存放路径 root /srv/www/project/; index index.html index.htm; } ``` -------------------------------- ### Custom Response with ghttp.ExitAll() Source: https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/sys-middleware.md This example demonstrates how to send a custom response and terminate all further HTTP processing using ghttp.ExitAll(). Use this when you need to completely control the response and prevent any subsequent middleware or handlers from executing. ```go package main import ( "github.com/gogf/gf/v2/net/ghttp" ) func main() { r := new(ghttp.Request) // 当前请求对象 // 清空响应 r.Response.ClearBuffer() // 写入响应 r.Response.Write("自定义响应内容") // 终止后续http处理 r.ExitAll() } ```