切换主题
内核业务开发
内核业务适合放入主程序代码仓库中,由 webos v2 内核统一编译、迁移、鉴权和发布。典型功能包括系统管理、用户相关功能、插件管理、审计日志和长期稳定的业务模块。
内核业务开发的两个方向
webos v2 内核业务开发提供两种不同的开发模式,适用于不同的业务场景:
方向一:基础表管理 + 真实业务层(适合自有业务开发)
适用场景:公司内部业务系统开发,需要快速构建 CRUD 功能并在此基础上实现复杂业务逻辑。
核心特点:
- 通过代码生成器自动生成基础表的 CRUD 接口和页面
- 在生成的基础上编写真实业务逻辑层
- 基础表和真实业务层分离,便于维护
目录结构示例:
api/internal/model/your_business/
├── base_model1.go # 基础模型(自动生成)
├── base_model2.go # 基础模型(自动生成)
└── ...
api/internal/controller/api/your_business/
├── base_model1.go # 基础控制器(自动生成)
├── base_model2.go # 基础控制器(自动生成)
├── business_logic1.go # 真实业务层(手动开发)
└── business_logic2.go # 真实业务层(手动开发)
web/src/components/common/views/your_business/
├── base_model1/ # 基础页面(自动生成)
├── base_model2/ # 基础页面(自动生成)
├── business_logic1/ # 真实业务页面(手动开发)
└── business_logic2/ # 真实业务页面(手动开发)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
开发流程:
- 创建业务模型,运行代码生成器生成基础 CRUD
- 在
api/internal/fuse/controller.go中添加包的自动注入(重要步骤) - 在业务逻辑控制器中编写复杂业务逻辑,调用基础模型完成业务操作
- 前端在对应目录下开发真实业务页面
- 在菜单配置中添加业务入口
关键点:
- 必须在
api/internal/fuse/controller.go中导入你的业务包,例如:goimport ( _ "github.com/your/project/internal/controller/api/your_business" )1
2
3 - 这样 Go 的
init()函数才能被执行,控制器才能注册到路由中
方向二:接口抽象 + 熔断切换(适合框架二次包装售卖)
适用场景:将 webos v2 框架进行二次包装后售卖分发,需要能够快速切换不同版本的实现(如企业版/社区版)。
核心特点:
- 通过接口抽象定义标准能力
- 使用熔断机制在不同实现间切换
- 便于打包时快速切断或替换特定功能模块
目录结构示例:
api/internal/inface/your_module/
├── adapter.go # 接口定义
├── default_provider.go # 默认实现(社区版)
└── your_module_ee/ # 企业版实现
├── controller/ # 企业版控制器
├── model/ # 企业版模型
├── provider/ # 企业版提供者
└── fuse.go # 熔断注册
api/internal/fuse/
├── default_fuse.go # 默认熔断(社区版)
└── ee_fuse.go # 企业版熔断
web/src/components/common/inface/
└── your_module_ee/ # 企业版前端页面
├── module.vue
└── ...1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
开发流程:
- 在
api/internal/inface/下定义接口 - 提供默认实现,作为基础版本
- 在企业版子目录中提供增强实现
- 通过熔断文件注册,在启动时根据配置选择加载哪个实现
- 前端在
web/src/components/common/inface/下开发对应的企业版页面
两种方向的对比
| 特性 | 方向一(基础表+业务层) | 方向二(接口抽象+熔断) |
|---|---|---|
| 适用场景 | 自有业务系统开发 | 框架二次包装售卖 |
| 开发效率 | 高(自动生成CRUD) | 中(需设计接口) |
| 灵活性 | 中(基于生成代码扩展) | 高(可完全替换实现) |
| 维护成本 | 低(代码清晰分层) | 中(需维护多套实现) |
| 打包分发 | 不适合(代码耦合) | 适合(快速切断模块) |
选择建议:
- 如果是为公司内部开发业务系统,优先使用方向一,可以快速迭代
- 如果要将 webos v2 打包成产品售卖给多个客户,优先使用方向二,便于按需裁剪功能
三、创建数据库模型
模型放在 ../api/internal/model 下,建议按业务域分包,例如:
text
api/internal/model/
├── system/
├── user/
└── your_menu/
└── your_model.go1
2
3
4
5
2
3
4
5
一个可被生成器识别和自动迁移的模型需要包含:
base.BaseModel:提供ID、CreatedAt、UpdatedAt、DeletedAt。gorm:"column:...":生成器只处理带column的字段。// @model name=...:模型中文名。// @field name=...:字段中文名。- 可选标记:
// @select 1=启用 0=禁用、// @datetime、// @textarea。 TableName():明确表名。init()中调用base.RegisterMigrate(&YourModel{})。
示例:
go
package your_menu
// @model name=业务任务
type Task struct {
base.BaseModel
// @field name=任务名称
Name string `gorm:"column:name;size:100"`
// @field name=状态
// @select 1=启用 0=禁用
Status int `gorm:"column:status" json:"Status,string"`
// @field name=备注
// @textarea
Remark string `gorm:"column:remark;type:text"`
}
func (t *Task) TableName() string {
return "task"
}
func init() {
base.RegisterMigrate(&Task{})
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
注意:新增模型文件需要被 Go 编译器引用到,才能执行 init()。放在已有会被导入的模型包中最稳妥;新增包时需要确认启动链路或聚合导入中已经引入该包。
四、配置代码生成器
生成器入口在 ../util/template/code.go。当前逻辑会读取:
go
menu := "user"
list = []string{
"desktop_app",
}1
2
3
4
2
3
4
开发新功能时,把 menu 改为模型所在包名,把 list 改为模型文件名去掉 .go 后的蛇形名称。例如模型文件为:
text
api/internal/model/your_menu/task.go1
则配置为:
go
menu := "your_menu"
list = []string{
"task",
}1
2
3
4
2
3
4
生成器会读取模型并生成或更新:
../api/pkg/locales/model-zh.json../api/pkg/locales/model-en.json../api/internal/controller/api/{menu}/{model}.go../web/src/components/common/views/{menu}/{model}/index.vue../web/src/components/common/views/{menu}/{model}/edit.vue../web/src/components/common/views/{menu}/{model}/detail.vue../web/src/components/common/views/{menu}/{model}/import.vue
五、运行生成器
优先使用 VSCode 中的 V9os Code 调试配置。如果当前工作区没有该配置,可以进入 ../util 执行等价命令:
bash
go build -o v9os-code.exe template/code.go
./v9os-code.exe1
2
2
Linux/macOS 下可改为:
bash
go build -o v9os-code template/code.go
./v9os-code1
2
2
不要直接使用 go run template/code.go 作为替代方式。生成器会通过可执行文件所在目录反推 main 目录,go run 的临时目录可能导致路径定位错误。
生成后需要检查:
- 控制器是否出现在
api/internal/controller/api/{menu}。 - 前端页面是否出现在
web/src/components/common/views/{menu}/{model}。 - 中英文语言包是否新增了
model.{model}节点。 - 生成器是否覆盖了你手工改过的同名页面;生成前建议确认工作区状态。
六、触发数据库迁移
迁移由版本号变化触发。内核启动时会读取嵌入的 ../api/internal/config/version.json,并与运行目录 init.json 中的 version 比较:
- 两者不同:设置
NeedUpdate,启动后执行database.AutoMigrate(),再把运行目录init.json更新为当前版本。 - 两者相同:认为无需迁移,不会自动建新表。
开发时可选择任一种方式让版本号产生差异:
- 修改
../api/internal/config/version.json的version,例如从1.0.000改为1.0.001-dev。 - 修改运行目录中的
init.json的version,例如临时改为0。
只要版本号有变化即可,不要求语义版本递增。团队协作时建议统一修改 version.json,避免每个人本地行为不一致。
七、启动和验证
优先使用 VSCode 中的 Debug V9os。如果没有该调试配置,可以进入 ../api 执行:
bash
go run cmd/console/main.go1
验证清单:
- 后端启动日志中没有数据库、缓存、队列初始化错误。
- 数据库中出现新表或新增字段。
plugin、user、system等基础表存在,首次启动会创建默认管理员admin / 123456。- 访问前端开发端口后,菜单或页面能够打开生成的页面。
- 生成的分页、保存、详情、删除、导入、导出接口可调用。
八、继续定制业务
生成器给的是标准 CRUD 起点。常见后续工作包括:
- 在生成的控制器中补充业务校验、事务、权限和审计字段。
- 在前端
index.vue调整搜索项、表格列、批量动作和窗口尺寸。 - 在
edit.vue和detail.vue中替换控件,例如选择器、时间选择器、富文本或文件上传。 - 补充
model-en.json的英文翻译,生成器对英文缺失项会先使用中文字段名。 - 修改菜单注册或桌面快捷方式,让入口出现在目标外观中。
九、多语言和分布式注意事项
- 后端返回给用户看的文本优先走语言包,不要只写固定中文。
- 前端新增文案要进入
web/src/locales,页面中用$t或项目已有 i18n 工具读取。 - 涉及缓存、队列、锁、插件运行状态时,要考虑本地模式和 Redis/RocketMQ 等分布式模式。
- 涉及机器、插件白名单、远程节点的逻辑时,要确认单机和分布式部署下都能运行。