在上篇文章中我们以platform
模块为例,详细记录了从创建model到编写页面的全过程。相信读者已经对编写流程有了一个大致的了解。
不难发现,整个项目分为多层:controller、service、dao等等,并且存在着大量模板代码,手动一个个文件编写费事费力,还容易出错。GoFrame其实为我们提供了cli工具,可以方便快捷的生成例如model、service等代码。
对整个项目而言,其实这还远远不够,我们还有例如controller、service、前端等模板代码需要编写,这时候编写一个简单的代码生成器就会方便很多。
因为本项目代码生成器不是重点,因此不考虑项目中集成,仅是作为一个工具存在。因为方便快捷作为第一考虑因素。
因此我们选用python作为主语言、结合jinja模板引擎快速生成模板代码。
系统核心组件包括:
database:
host: 127.0.0.1
port: 3306
user: root
password: 123456
dbname: softhub
code_generator:
# 生成类型:frontend-前端, backend-后端, all-全部
generate_type: all
# 表配置
tables:
- name: ds_platform # 表名
comment: "平台管理" # 表注释
generate_type: all # 可选:frontend, backend, all
frontend:
template_name: "gfast前端模板2"
output_path: "D:/output/frontend"
primary_name: "name" # 主键名称
backend:
template_name: "gfast模板"
output_path: "D:/output/backend"
package: "platform" # 包名
package_path: "github.com/tiger1103/gfast/v3" # 包路径前缀
配置模块管理
class ConfigUtil:
def __init__(self, config_path: Path):
self.config_path = config_path
def read_config(self) -> Dict[str, Any]:
with open(self.config_path, 'r', encoding='utf-8') as f:
return yaml.safe_load(f)
使用YAML配置文件管理:
class InspectUtils:
def __init__(self, engine):
self.engine = engine
self.inspector = inspect(engine)
def get_infos(self, table_name: str) -> Dict[str, Any]:
columns = self.inspector.get_columns(table_name)
# 处理字段信息...
return {
'table_name': table_name,
'columns': columns,
# 其他元数据...
}
# 设置模板路径
template_base_path = Path('template')
template_path = template_base_path.joinpath(template_name)
# 渲染模板
templates = Environment(loader=FileSystemLoader(template_path),
lstrip_blocks=True,
trim_blocks=True)
tl = templates.get_template(template)
render_str = tl.render(infos)
def _get_go_type(self, sql_type: str) -> str:
"""将SQL类型转换为Go类型"""
sql_type = sql_type.lower()
if 'int' in sql_type:
return 'int'
elif 'varchar' in sql_type or 'char' in sql_type or 'text' in sql_type:
return 'string'
elif 'time' in sql_type or 'date' in sql_type:
return '*gtime.Time'
# 其他类型处理...
# 渲染相对路径
relative_path = Template(str(item_template_path.parent
.relative_to(template_path))
.render(file_info)
# 渲染文件名
template_stem = item_template_path.stem
if '.' in template_stem:
name_part, ext = template_stem.rsplit('.', 1)
file_name = Template(name_part).render(file_info) + '.' + ext
# 跳过已存在的router.go和logic.go文件
if Path(file_path).exists() and
(str(item_template_path.stem) in ["router.go", "logic.go"]):
continue
修改config\application.yml
配置
python code_generator.py
import logging as log
import os
from datetime import datetime
from pathlib import Path
from typing import Dict, Any, List
from jinja2 import Environment, FileSystemLoader, Template
import sqlalchemy as sa
from sqlalchemy import inspect
import yaml
# 配置日志
log.basicConfig(level=log.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
class ConfigUtil:
def __init__(self, config_path: Path):
self.config_path = config_path
def read_config(self) -> Dict[str, Any]:
with open(self.config_path, 'r', encoding='utf-8') as f:
return yaml.safe_load(f)
class InspectUtils:
def __init__(self, engine):
self.engine = engine
self.inspector = inspect(engine)
self.tables = self.inspector.get_table_names()
def get_infos(self, table_name: str) -> Dict[str, Any]:
columns = self.inspector.get_columns(table_name)
primary_keys = self.inspector.get_pk_constraint(table_name)
foreign_keys = self.inspector.get_foreign_keys(table_name)
# 处理字段信息
field_info = []
for column in columns:
# 获取字段类型
type_name = str(column['type'])
go_type = self._get_go_type(type_name)
# 处理字段名
name = column['name']
camel_name = ''.join(word.capitalize() for word in name.split('_'))
if camel_name and camel_name[0].isupper():
camel_name = camel_name[0].lower() + camel_name[1:]
field_info.append({
'name': name,
'camelName': camel_name,
'firstUpperName': ''.join(word.capitalize() for word in name.split('_')),
'type': go_type,
'comment': column.get('comment', ''),
'nullable': column.get('nullable', False)
})
return {
'table_name': table_name,
'columns': columns,
'primary_keys': primary_keys,
'foreign_keys': foreign_keys,
'field_info': field_info
}
def _get_go_type(self, sql_type: str) -> str:
"""将SQL类型转换为Go类型"""
sql_type = sql_type.lower()
if 'int' in sql_type:
return 'int'
elif 'varchar' in sql_type or 'char' in sql_type or 'text' in sql_type:
return 'string'
elif 'float' in sql_type or 'double' in sql_type or 'decimal' in sql_type:
return 'float64'
elif 'bool' in sql_type:
return 'bool'
elif 'time' in sql_type or 'date' in sql_type:
return '*gtime.Time'
else:
return 'string'
def get_file_info(self, table_name: str) -> Dict[str, str]:
first_upper_name = ''.join(word.capitalize() for word in table_name.split('_'))
return {
'table_name': table_name,
'table_name_camel': ''.join(word.capitalize() for word in table_name.split('_')),
'table_name_lower': table_name.lower(),
'name': table_name,
'first_upper_name': first_upper_name
}
def get_connection(config: Dict[str, Any]):
return sa.create_engine(
f"mysql+pymysql://{config['user']}:{config['password']}@{config['host']}:{config['port']}/{config['dbname']}"
)
def generate_code(config_map: Dict[str, Any], table_config: Dict[str, Any]):
template_name = config_map['template_name']
table_name = config_map['table_name']
output_path = config_map['output_path']
package = config_map.get('package', 'template')
package_path = config_map.get('package_path', 'github.com/tiger1103/gfast/v3')
# 读取配置
config_path = Path('config/application.yml').resolve()
config_util = ConfigUtil(config_path)
config = config_util.read_config()
# 连接数据库
engine = get_connection(config['database'])
iu = InspectUtils(engine)
# 获取表信息
infos = iu.get_infos(table_name)
# 添加前端信息
front_info = {
'search_columns': [
{"camelName": "name", "comment": "变量名称", "type": "string"}
]
}
if "primary_name" in config_map:
front_info['primaryName'] = config_map['primary_name']
infos['front_info'] = front_info
# 添加包信息
package_info = {
'api': f"{package_path}/api/v1/{package}",
'service': f"{package_path}/internal/app/{package}/service",
'dao': f"{package_path}/internal/app/{package}/dao",
'liberr': f"{package_path}/library/liberr",
'libUtils': f"{package_path}/library/libUtils",
'consts': f"{package_path}/internal/app/system/consts",
'model': f"{package_path}/internal/app/{package}/model",
'entity': f"{package_path}/internal/app/{package}/model/entity",
'utils': f"{package_path}/internal/app/{package}/utils",
'common': f"{package_path}/internal/app/{package}/common",
'commonDao': f"{package_path}/internal/app/common/dao",
'commonEntity': f"{package_path}/internal/app/common/model/entity",
'commonApi': f"{package_path}/api/v1/common",
'do': f"{package_path}/internal/app/{package}/model/do",
'SystemS': f"{package_path}/internal/app/system/service",
'dao_internal': f"{package_path}/internal/app/{package}/dao/internal",
'package': package,
'packageFirstUpper': package.capitalize()
}
infos['package_info'] = package_info
# 获取文件信息
file_info = iu.get_file_info(table_name)
file_info['package'] = package
file_info['packageFirstUpper'] = package.capitalize()
# 添加表信息
table_info = {
'name': table_name,
'lowerName': table_name.lower(),
'upperName': table_name.upper(),
'firstUpperName': ''.join(word.capitalize() for word in table_name.split('_')),
'camelName': ''.join(word.capitalize() for word in table_name.split('_'))[0].lower() + ''.join(word.capitalize() for word in table_name.split('_'))[1:],
'comment': table_config.get('comment', ''),
'columns': infos['columns'],
'primaryKeys': infos['primary_keys'],
'foreignKeys': infos['foreign_keys']
}
infos['table_info'] = table_info
# 设置模板路径
template_base_path = Path('template')
template_path = template_base_path.joinpath(template_name)
# 设置输出路径
output_path = Path(output_path).resolve()
if not output_path.exists():
output_path.mkdir(parents=True)
# 渲染模板
templates = Environment(loader=FileSystemLoader(template_path), lstrip_blocks=True, trim_blocks=True)
for template in templates.list_templates():
tl = templates.get_template(template)
item_template_path = Path(tl.filename)
# 渲染相对路径
relative_path = Template(str(item_template_path.parent.relative_to(template_path))).render(file_info)
log.info(f"Processing template: {relative_path}")
# 渲染文件名(保持原始扩展名)
template_stem = item_template_path.stem # 获取不带.j2的文件名
if '.' in template_stem: # 如果文件名中包含扩展名
name_part, ext = template_stem.rsplit('.', 1) # 分离名称和扩展名
file_name = Template(name_part).render(file_info) + '.' + ext
else:
file_name = Template(template_stem).render(file_info)
render_str = tl.render(infos)
parent_output = output_path.joinpath(relative_path)
if not parent_output.exists():
parent_output.mkdir(parents=True)
file_path = parent_output.joinpath(file_name)
log.info(f"Generating file: {file_path}")
# 跳过已存在的router.go和logic.go文件
if Path(file_path).exists() and (str(item_template_path.stem) in ["router.go", "logic.go"]):
continue
with open(file_path, 'w', encoding='utf-8') as f:
f.write(render_str)
def main():
# 读取配置
config_path = Path('config/application.yml').resolve()
config_util = ConfigUtil(config_path)
config = config_util.read_config()
# 获取生成器配置
generator_config = config['code_generator']
generate_type = generator_config['generate_type']
# 处理每个表的配置
for table_config in generator_config['tables']:
table_name = table_config['name']
table_generate_type = table_config.get('generate_type', generate_type)
# 生成前端代码
if table_generate_type in ['frontend', 'all']:
frontend_config = table_config['frontend']
config_map = {
'template_name': frontend_config['template_name'],
'table_name': table_name,
'output_path': frontend_config['output_path'],
'primary_name': frontend_config['primary_name']
}
generate_code(config_map, table_config)
# 生成后端代码
if table_generate_type in ['backend', 'all']:
backend_config = table_config['backend']
config_map = {
'template_name': backend_config['template_name'],
'table_name': table_name,
'output_path': backend_config['output_path'],
'package': backend_config['package'],
'package_path': backend_config['package_path']
}
generate_code(config_map, table_config)
if __name__ == "__main__":
main()
项目结构
gfast模板:
- api
- api\v1
- api\v1\{{package}}
- api\v1\{{package}}\{{name}}.go.j2
- internal
- internal\app
- internal\app\{{package}}
- internal\app\{{package}}\controller
- internal\app\{{package}}\controller\{{name}}.go.j2
- internal\app\{{package}}\dao
- internal\app\{{package}}\dao\internal
- internal\app\{{package}}\dao\internal\{{name}}.go.j2
- internal\app\{{package}}\dao\{{name}}.go.j2
- internal\app\{{package}}\logic
- internal\app\{{package}}\logic\logic.go.j2
- internal\app\{{package}}\logic\{{name}}
- internal\app\{{package}}\logic\{{name}}\{{name}}.go.j2
- internal\app\{{package}}\model
- internal\app\{{package}}\model\do
- internal\app\{{package}}\model\do\{{name}}.go.j2
- internal\app\{{package}}\model\entity
- internal\app\{{package}}\model\entity\{{name}}.go.j2
- internal\app\{{package}}\model\{{name}}.go.j2
- internal\app\{{package}}\router
- internal\app\{{package}}\router\router.go.j2
- internal\app\{{package}}\service
- internal\app\{{package}}\service\{{name}}.go.j2
代码内容
api\v1{{package}}{{name}}.go.j2
package template
import (
"github.com/gogf/gf/v2/frame/g"
commonApi "{{package_info.commonApi}}"
model "{{package_info.model}}"
)
type {{table_info.firstUpperName}}AddReq struct {
g.Meta `path:"/{{table_info.camelName}}/add" method:"post" tags:"{{table_info.comment}}" summary:"{{table_info.comment}}-新增"`
{% for item in field_info %}
{% if item.camelName not in ['id','createdBy','updatedBy','createdAt','updatedAt'] %}
{{ item.firstUpperName }} {{ item.type }} `json:"{{ item.camelName }}" v:"required#{{ item.comment }}不能为空"`
{% endif %}
{% endfor %}
}
type {{table_info.firstUpperName}}AddRes struct {
g.Meta `mime:"application/json" example:"string"`
}
type {{table_info.firstUpperName}}DelReq struct {
g.Meta `path:"/{{table_info.camelName}}/del" method:"delete" tags:"{{table_info.comment}}" summary:"{{table_info.comment}}-删除"`
Id uint `json:"id" v:"required#id不能为空"`
}
type {{table_info.firstUpperName}}DelRes struct {
g.Meta `mime:"application/json" example:"string"`
}
type {{table_info.firstUpperName}}BatchDelReq struct {
g.Meta `path:"/{{table_info.camelName}}/batchdel" method:"delete" tags:"{{table_info.comment}}" summary:"{{table_info.comment}}-批量删除"`
Ids []uint `json:"id" v:"required#id不能为空"`
}
type {{table_info.firstUpperName}}BatchDelRes struct {
g.Meta `mime:"application/json" example:"string"`
}
type {{table_info.firstUpperName}}EditReq struct {
g.Meta `path:"/{{table_info.camelName}}/edit" method:"put" tags:"{{table_info.comment}}" summary:"{{table_info.comment}}-修改"`
{% for item in field_info %}
{% if item.camelName not in ['createdBy','updatedBy','createdAt','updatedAt'] %}
{{ item.firstUpperName }} {{ item.type }} `json:"{{ item.camelName }}" v:"required#{{ item.comment }}不能为空"`
{% endif %}
{% endfor %}
}
type {{table_info.firstUpperName}}EditRes struct {
g.Meta `mime:"application/json" example:"string"`
}
type {{table_info.firstUpperName}}ListReq struct {
g.Meta `path:"/{{table_info.camelName}}/list" method:"get" tags:"{{table_info.comment}}" summary:"{{table_info.comment}}-列表"`
commonApi.PageReq
{% for item in field_info %}
{% if item.camelName not in ['id','createdBy','updatedBy','createdAt','updatedAt'] %}
{{ item.firstUpperName }} {{ item.type }} `json:"{{ item.camelName }}" v:"required#{{ item.comment }}不能为空"`
{% endif %}
{% endfor %}
}
type {{table_info.firstUpperName}}ListRes struct {
g.Meta `mime:"application/json" example:"string"`
commonApi.ListRes
{{table_info.firstUpperName}}List []*model.{{table_info.firstUpperName}}Info `json:"{{table_info.camelName}}List"`
}
type {{table_info.firstUpperName}}DetailReq struct {
g.Meta `path:"/{{table_info.camelName}}/detail" method:"get" tags:"{{table_info.comment}}" summary:"{{table_info.comment}}-详情"`
Id uint `json:"id" v:"required#id不能为空"`
}
type {{table_info.firstUpperName}}DetailRes struct {
g.Meta `mime:"application/json" example:"string"`
*model.{{table_info.firstUpperName}}Info
}
internal\app{{package}}\controller{{name}}.go.j2
package controller
import (
"context"
api "{{package_info.api}}"
service "{{package_info.service}}"
consts "{{package_info.consts}}"
)
var {{table_info.firstUpperName}} = {{table_info.camelName}}Controller{}
type {{table_info.camelName}}Controller struct {
BaseController
}
func (c *{{table_info.camelName}}Controller) Add(ctx context.Context, req *api.{{table_info.firstUpperName}}AddReq) (res *api.{{table_info.firstUpperName}}AddRes, err error) {
res = new(api.{{table_info.firstUpperName}}AddRes)
err = service.{{table_info.firstUpperName}}().Add(ctx, req)
return
}
func (c *{{table_info.camelName}}Controller) List(ctx context.Context, req *api.{{table_info.firstUpperName}}ListReq) (res *api.{{table_info.firstUpperName}}ListRes, err error) {
res = new(api.{{table_info.firstUpperName}}ListRes)
if req.PageSize == 0 {
req.PageSize = consts.PageSize
}
if req.PageNum == 0 {
req.PageNum = 1
}
total, {{table_info.camelName}}s, err := service.{{table_info.firstUpperName}}().List(ctx, req)
res.Total = total
res.CurrentPage = req.PageNum
res.{{table_info.firstUpperName}}List = {{table_info.camelName}}s
return
}
func (c *{{table_info.camelName}}Controller) Get(ctx context.Context, req *api.{{table_info.firstUpperName}}DetailReq) (res *api.{{table_info.firstUpperName}}DetailRes, err error) {
res = new(api.{{table_info.firstUpperName}}DetailRes)
service.{{table_info.firstUpperName}}().GetById(ctx, req.Id)
return
}
func (c *{{table_info.camelName}}Controller) Edit(ctx context.Context, req *api.{{table_info.firstUpperName}}EditReq) (res *api.{{table_info.firstUpperName}}EditRes, err error) {
err = service.{{table_info.firstUpperName}}().Edit(ctx, req)
return
}
func (c *{{table_info.camelName}}Controller) Delete(ctx context.Context, req *api.{{table_info.firstUpperName}}DelReq) (res *api.{{table_info.firstUpperName}}DelRes, err error) {
err = service.{{table_info.firstUpperName}}().Delete(ctx, req.Id)
return
}
func (c *{{table_info.camelName}}Controller) BatchDelete(ctx context.Context, req *api.{{table_info.firstUpperName}}BatchDelReq) (res *api.{{table_info.firstUpperName}}BatchDelRes, err error) {
err = service.{{table_info.firstUpperName}}().BatchDelete(ctx, req.Ids)
return
}
internal\app{{package}}\dao\internal{{name}}.go.j2
// ==========================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// {{table_info.firstUpperName}}Dao is the data access object for table cts_voice.
type {{table_info.firstUpperName}}Dao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns {{table_info.firstUpperName}}Columns // columns contains all the column names of Table for convenient usage.
}
// {{table_info.firstUpperName}}Columns defines and stores column names for table {{table_info.Name}}.
type {{table_info.firstUpperName}}Columns struct {
{% for item in field_info %}
{{ item.firstUpperName }} string //{{ item.comment }}
{% endfor %}
}
// {{table_info.camelName}}Columns holds the columns for table {{table_info.Name}}.
var {{table_info.camelName}}Columns = {{table_info.firstUpperName}}Columns{
{% for item in field_info %}
{{ item.firstUpperName }}: "{{ item.name }}",
{% endfor %}
}
// New{{table_info.firstUpperName}}Dao creates and returns a new DAO object for table data access.
func New{{table_info.firstUpperName}}Dao() *{{table_info.firstUpperName}}Dao {
return &{{table_info.firstUpperName}}Dao{
group: "default",
table: "{{table_info.name}}",
columns: {{table_info.camelName}}Columns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *{{table_info.firstUpperName}}Dao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *{{table_info.firstUpperName}}Dao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *{{table_info.firstUpperName}}Dao) Columns() {{table_info.firstUpperName}}Columns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *{{table_info.firstUpperName}}Dao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *{{table_info.firstUpperName}}Dao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *{{table_info.firstUpperName}}Dao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}
internal\app{{package}}\dao{{name}}.go.j2
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
import (
internal "{{package_info.dao_internal}}"
)
// internal{{table_info.firstUpperName}}Dao is internal type for wrapping internal DAO implements.
type internal{{table_info.firstUpperName}}Dao = *internal.{{table_info.firstUpperName}}Dao
// {{table_info.camelName}}Dao is the data access object for table {{table_info.Name}}.
// You can define custom methods on it to extend its functionality as you wish.
type {{table_info.camelName}}Dao struct {
internal{{table_info.firstUpperName}}Dao
}
var (
// {{table_info.firstUpperName}}Dao is globally public accessible object for table cts_voice operations.
{{table_info.firstUpperName}} = {{table_info.camelName}}Dao{
internal.New{{table_info.firstUpperName}}Dao(),
}
)
// Fill with you ideas below.
internal\app{{package}}\logic\logic.go.j2
package logic
import _ "github.com/tiger1103/gfast/v3/internal/app/{{package_info.package}}/logic/{{table_info.name}}"
internal\app{{package}}\logic{{name}}{{name}}.go.j2
package {{table_info.name}}
import (
"context"
"fmt"
"github.com/gogf/gf/v2/frame/g"
api "{{package_info.api}}"
dao "{{package_info.dao}}"
model "{{package_info.model}}"
do "{{package_info.do}}"
service "{{package_info.service}}"
SystemS "{{package_info.SystemS}}"
liberr "{{package_info.liberr}}"
)
func init() {
service.Register{{table_info.firstUpperName}}(New())
}
func New() *s{{table_info.firstUpperName}} {
return &s{{table_info.firstUpperName}}{}
}
type s{{table_info.firstUpperName}} struct {
}
func (s s{{table_info.firstUpperName}}) List(ctx context.Context, req *api.{{table_info.firstUpperName}}ListReq) (total interface{}, {{table_info.camelName}}List []*model.{{table_info.firstUpperName}}Info, err error) {
err = g.Try(ctx, func(ctx context.Context) {
m := dao.{{table_info.firstUpperName}}.Ctx(ctx)
columns := dao.{{table_info.firstUpperName}}.Columns()
//TODO 根据实际情况修改
{% for item in field_info %}
{% if item.camelName not in ['id','createdBy','updatedBy','createdAt','updatedAt'] %}
if req.{{ item.firstUpperName }} != "" {
m = m.Where(columns.{{ item.firstUpperName }}+" = ?", req.{{ item.firstUpperName }})
// like
//m = m.Where(fmt.Sprintf("%s like ?", columns.{{ item.firstUpperName }}), "%"+req.{{ item.firstUpperName }}+"%")
}
{% endif %}
{% endfor %}
total, err = m.Count()
liberr.ErrIsNil(ctx, err, "获取{{table_info.comment}}列表失败")
orderBy := req.OrderBy
if orderBy == "" {
orderBy = "created_at desc"
}
err = m.Page(req.PageNum, req.PageSize).Order(orderBy).Scan(&{{table_info.camelName}}List)
liberr.ErrIsNil(ctx, err, "获取{{table_info.comment}}列表失败")
})
return
}
func (s s{{table_info.firstUpperName}}) Add(ctx context.Context, req *api.{{table_info.firstUpperName}}AddReq) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
// TODO 查询是否已经存在
// add
_, err = dao.{{table_info.firstUpperName}}.Ctx(ctx).Insert(do.{{table_info.firstUpperName}}{
{% for item in field_info %}
{% if item.camelName not in ['id','createdBy','updatedBy','createdAt','updatedAt'] %}
{{ item.firstUpperName }}: req.{{ item.firstUpperName }}, // {{ item.comment }}
{% endif %}
{% endfor %}
CreatedBy: SystemS.Context().GetUserId(ctx),
UpdatedBy: SystemS.Context().GetUserId(ctx),
})
liberr.ErrIsNil(ctx, err, "新增{{table_info.comment}}失败")
})
return
}
func (s s{{table_info.firstUpperName}}) Edit(ctx context.Context, req *api.{{table_info.firstUpperName}}EditReq) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
_, err = s.GetById(ctx, req.Id)
liberr.ErrIsNil(ctx, err, "获取{{table_info.comment}}失败")
//TODO 根据名称等查询是否存在
//编辑
_, err = dao.{{table_info.firstUpperName}}.Ctx(ctx).WherePri(req.Id).Update(do.{{table_info.firstUpperName}}{
{% for item in field_info %}
{% if item.camelName not in ['createdBy','updatedBy','createdAt','updatedAt'] %}
{{ item.firstUpperName }}: req.{{ item.firstUpperName }}, // {{ item.comment }}
{% endif %}
{% endfor %}
})
liberr.ErrIsNil(ctx, err, "修改{{table_info.comment}}失败")
})
return
}
func (s s{{table_info.firstUpperName}}) Delete(ctx context.Context, id uint) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
_, err = dao.{{table_info.firstUpperName}}.Ctx(ctx).WherePri(id).Delete()
liberr.ErrIsNil(ctx, err, "删除{{table_info.comment}}失败")
})
return
}
func (s s{{table_info.firstUpperName}}) BatchDelete(ctx context.Context, ids []uint) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
_, err = dao.{{table_info.firstUpperName}}.Ctx(ctx).Where(dao.{{table_info.firstUpperName}}.Columns().Id+" in(?)", ids).Delete()
liberr.ErrIsNil(ctx, err, "批量删除{{table_info.comment}}失败")
})
return
}
func (s s{{table_info.firstUpperName}}) GetById(ctx context.Context, id uint) (res *model.{{table_info.firstUpperName}}Info, err error) {
err = g.Try(ctx, func(ctx context.Context) {
err = dao.{{table_info.firstUpperName}}.Ctx(ctx).Where(fmt.Sprintf("%s=?", dao.{{table_info.firstUpperName}}.Columns().Id), id).Scan(&res)
liberr.ErrIsNil(ctx, err, "获取{{table_info.comment}}失败")
})
return
}
internal\app{{package}}\model\do{{name}}.go.j2
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/frame/g"
)
// {{table_info.firstUpperName}} is the golang structure of table {{table_info.name}} for DAO operations like Where/Data.
type {{table_info.firstUpperName}} struct {
g.Meta `orm:"table:{{table_info.name}}, do:true"`
{% for item in field_info %}
{{ item.firstUpperName }} interface{} //{{ item.comment }}
{% endfor %}
}
internal\app{{package}}\model\entity{{name}}.go.j2
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import "github.com/gogf/gf/v2/os/gtime"
// {{table_info.firstUpperName}} is the golang structure for table {{table_info.name}}.
type {{table_info.firstUpperName}} struct {
{% for item in field_info %}
{{ item.firstUpperName }} {{ item.type }} `json:"{{ item.camelName }}" description:"{{ item.comment }}"`
{% endfor %}
}
internal\app{{package}}\model{{name}}.go.j2
package model
import "github.com/gogf/gf/v2/os/gtime"
type {{table_info.firstUpperName}}Info struct {
{% for item in field_info %}
{{ item.firstUpperName }} {{ item.type }} `orm:"{{item.name}}" json:"{{item.camelName}}"` // {{ item.comment }}
{% endfor %}
}
internal\app{{package}}\router\router.go.j2
/*
* @desc:后台路由
* @company:云南奇讯科技有限公司
* @Author: yixiaohu
* @Date: 2022/2/18 17:34
*/
package router
import (
"context"
"github.com/gogf/gf/v2/net/ghttp"
_ "github.com/tiger1103/gfast/v3/internal/app/{{package_info.package}}/logic"
"github.com/tiger1103/gfast/v3/internal/app/{{package_info.package}}/controller"
"github.com/tiger1103/gfast/v3/internal/app/system/service"
"github.com/tiger1103/gfast/v3/library/libRouter"
)
var R = new(Router)
type Router struct{}
func (router *Router) BindController(ctx context.Context, group *ghttp.RouterGroup) {
group.Group("/{{package_info.package}}", func(group *ghttp.RouterGroup) {
//登录验证拦截
service.GfToken().Middleware(group)
//context拦截器
group.Middleware(service.Middleware().Ctx, service.Middleware().Auth)
//后台操作日志记录
group.Hook("/*", ghttp.HookAfterOutput, service.OperateLog().OperationLog)
group.Bind(
controller.{{table_info.firstUpperName}},
)
//自动绑定定义的控制器
if err := libRouter.RouterAutoBind(ctx, router, group); err != nil {
panic(err)
}
})
}
internal\app{{package}}\service{{name}}.go.j2
package service
import (
"context"
api "{{package_info.api}}"
model "{{package_info.model}}"
)
type I{{table_info.firstUpperName}} interface {
List(ctx context.Context, req *api.{{table_info.firstUpperName}}ListReq) (total interface{}, res []*model.{{table_info.firstUpperName}}Info, err error)
Add(ctx context.Context, req *api.{{table_info.firstUpperName}}AddReq) (err error)
Edit(ctx context.Context, req *api.{{table_info.firstUpperName}}EditReq) (err error)
Delete(ctx context.Context, id uint) (err error)
BatchDelete(ctx context.Context, ids []uint) (err error)
GetById(ctx context.Context, id uint) (res *model.{{table_info.firstUpperName}}Info, err error)
}
var local{{table_info.firstUpperName}} I{{table_info.firstUpperName}}
func {{table_info.firstUpperName}}() I{{table_info.firstUpperName}} {
if local{{table_info.firstUpperName}} == nil {
panic("implement not found for interface I{{table_info.firstUpperName}}, forgot register?")
}
return local{{table_info.firstUpperName}}
}
func Register{{table_info.firstUpperName}}(i I{{table_info.firstUpperName}}) {
local{{table_info.firstUpperName}} = i
}
项目结构
gfast前端模板2:
- src
- src\api
- src\api\{{package}}
- src\api\{{package}}\{{camel_name}}
- src\api\{{package}}\{{camel_name}}\index.ts.j2
- src\views
- src\views\{{package}}
- src\views\{{package}}\{{camel_name}}
- src\views\{{package}}\{{camel_name}}\component
- src\views\{{package}}\{{camel_name}}\component\edit{{first_upper_name}}.vue.j2
- src\views\{{package}}\{{camel_name}}\index.vue.j2
代码内容
src\api{{package}}{{camel_name}}\index.ts.j2
import request from '/@/utils/request';
export function get{{table_info.firstUpperName}}List(query?:Object) {
return request({
url: '/api/v1/{{package_info.package}}/{{table_info.camelName}}/list',
method: 'get',
params:query
})
}
export function add{{table_info.firstUpperName}}(data:object) {
return request({
url: '/api/v1/{{package_info.package}}/{{table_info.camelName}}/add',
method: 'post',
data:data
})
}
export function edit{{table_info.firstUpperName}}(data:object) {
return request({
url: '/api/v1/{{package_info.package}}/{{table_info.camelName}}/edit',
method: 'put',
data:data
})
}
export function delete{{table_info.firstUpperName}}(id:number) {
return request({
url: '/api/v1/{{package_info.package}}/{{table_info.camelName}}/del',
method: 'delete',
data:{id}
})
}
export function batchDelete{{table_info.firstUpperName}}(ids:number[]) {
return request({
url: '/api/v1/{{package_info.package}}/{{table_info.camelName}}/batchdel',
method: 'delete',
data:{ids}
})
}
src\views{{package}}{{camel_name}}\component\edit{{first_upper_name}}.vue.j2
{{'{{'}}(state.formData.id===0?'添加':'修改')+'{{table_info.comment}}'{{'}}'}}
{% for item in field_info %}
{% if item.camelName not in ['id', 'createdBy','updatedBy','createdAt','updatedAt'] %}
{% endif %}
{% endfor %}
src\views{{package}}{{camel_name}}\index.vue.j2
{% for item in front_info.serach_columns %}
{% endfor %}
查询
新增{{table_info.comment}}
删除{{table_info.comment}}
{% for item in field_info %}
{% if item.camelName not in ['id', 'createdBy','updatedBy','createdAt','updatedAt'] %}
{% endif %}
{% endfor %}
修改
删除