feat✨: generate a typed .ts API module instead of .js (PRD 010 F5)

Rewrite template/v4/js.go.template (renamed to ts.go.template) to emit
TypeScript matching go-admin-ui's src/api/demo/product.ts: an interface
per row and per query params, typed CRUD functions, and a del{Class}
that takes Id[] like useRemove expects. GoType maps to number for
int/int64/float32/float64 and string otherwise, since go-admin-ui's
request() types the {code,data,msg} envelope rather than the payload.

Preview's response map key changes from template/js.go.template to
template/api.ts.template so its Tab label matches the new content;
NOActionsGen writes the file with a .ts extension.

Verified end to end: generated a real table's output, copied it into
go-admin-ui and ran vue-tsc --noEmit and eslint against it - both clean.
This commit is contained in:
zhangwenjian
2026-09-19 13:55:56 +08:00
parent aa7a92664d
commit 28eba92077
3 changed files with 81 additions and 53 deletions
+6 -6
View File
@@ -45,10 +45,10 @@ func (e Gen) Preview(c *gin.Context) {
e.Error(500, err, fmt.Sprintf("api模版读取失败!错误详情:%s", err.Error()))
return
}
t3, err := template.ParseFiles("template/v4/js.go.template")
t3, err := template.ParseFiles("template/v4/ts.go.template")
if err != nil {
log.Error(err)
e.Error(500, err, fmt.Sprintf("js模版读取失败!错误详情:%s", err.Error()))
e.Error(500, err, fmt.Sprintf("ts模版读取失败!错误详情:%s", err.Error()))
return
}
t4, err := template.ParseFiles("template/v4/vue.go.template")
@@ -102,7 +102,7 @@ func (e Gen) Preview(c *gin.Context) {
mp := make(map[string]interface{})
mp["template/model.go.template"] = b1.String()
mp["template/api.go.template"] = b2.String()
mp["template/js.go.template"] = b3.String()
mp["template/api.ts.template"] = b3.String()
mp["template/vue.go.template"] = b4.String()
mp["template/router.go.template"] = b5.String()
mp["template/dto.go.template"] = b6.String()
@@ -191,10 +191,10 @@ func (e Gen) NOActionsGen(c *gin.Context, tab tools.SysTables) {
e.Error(500, err, fmt.Sprintf("路由模版失败!错误详情:%s", err.Error()))
return
}
t4, err := template.ParseFiles(basePath + "js.go.template")
t4, err := template.ParseFiles(basePath + "ts.go.template")
if err != nil {
log.Error(err)
e.Error(500, err, fmt.Sprintf("js模版解析失败!错误详情:%s", err.Error()))
e.Error(500, err, fmt.Sprintf("ts模版解析失败!错误详情:%s", err.Error()))
return
}
t5, err := template.ParseFiles(basePath + "vue.go.template")
@@ -245,7 +245,7 @@ func (e Gen) NOActionsGen(c *gin.Context, tab tools.SysTables) {
pkg.FileCreate(b1, "./app/"+tab.PackageName+"/models/"+tab.TBName+".go")
pkg.FileCreate(b2, "./app/"+tab.PackageName+"/apis/"+tab.TBName+".go")
pkg.FileCreate(b3, "./app/"+tab.PackageName+"/router/"+tab.TBName+".go")
pkg.FileCreate(b4, config.GenConfig.FrontPath+"/api/"+tab.PackageName+"/"+tab.MLTBName+".js")
pkg.FileCreate(b4, config.GenConfig.FrontPath+"/api/"+tab.PackageName+"/"+tab.MLTBName+".ts")
pkg.FileCreate(b5, config.GenConfig.FrontPath+"/views/"+tab.PackageName+"/"+tab.MLTBName+"/index.vue")
pkg.FileCreate(b6, "./app/"+tab.PackageName+"/service/dto/"+tab.TBName+".go")
pkg.FileCreate(b7, "./app/"+tab.PackageName+"/service/"+tab.TBName+".go")
-47
View File
@@ -1,47 +0,0 @@
import request from '@/utils/request'
// 查询{{.ClassName}}列表
export function list{{.ClassName}}(query) {
return request({
url: '/api/v1/{{.ModuleName}}',
method: 'get',
params: query
})
}
// 查询{{.ClassName}}详细
export function get{{.ClassName}} ({{.PkJsonField}}) {
return request({
url: '/api/v1/{{.ModuleName}}/' + {{.PkJsonField}},
method: 'get'
})
}
// 新增{{.ClassName}}
export function add{{.ClassName}}(data) {
return request({
url: '/api/v1/{{.ModuleName}}',
method: 'post',
data: data
})
}
// 修改{{.ClassName}}
export function update{{.ClassName}}(data) {
return request({
url: '/api/v1/{{.ModuleName}}/'+data.{{.PkJsonField}},
method: 'put',
data: data
})
}
// 删除{{.ClassName}}
export function del{{.ClassName}}(data) {
return request({
url: '/api/v1/{{.ModuleName}}',
method: 'delete',
data: data
})
}
+75
View File
@@ -0,0 +1,75 @@
import request from '@/utils/request'
import type { ApiResponse, PageQuery, PageResult, Id } from '@/types/api'
export interface {{.ClassName}} {
{{- range .Columns}}
{{.JsonField}}?: {{if eq .GoType "int" -}}
number
{{- else if eq .GoType "int64" -}}
number
{{- else if eq .GoType "float32" -}}
number
{{- else if eq .GoType "float64" -}}
number
{{- else -}}
string
{{- end}}
{{- end}}
}
export interface {{.ClassName}}Query {
{{- range .Columns}}
{{- if eq .IsQuery "1"}}
{{.JsonField}}?: {{if eq .GoType "int" -}}
number
{{- else if eq .GoType "int64" -}}
number
{{- else if eq .GoType "float32" -}}
number
{{- else if eq .GoType "float64" -}}
number
{{- else -}}
string
{{- end}}
{{- end}}
{{- end}}
}
export function list{{.ClassName}}(query: {{.ClassName}}Query & PageQuery) {
return request<ApiResponse<PageResult<{{.ClassName}}>>>({
url: '/api/v1/{{.ModuleName}}',
method: 'get',
params: query
})
}
export function get{{.ClassName}}({{.PkJsonField}}: number) {
return request<ApiResponse<{{.ClassName}}>>({
url: '/api/v1/{{.ModuleName}}/' + {{.PkJsonField}},
method: 'get'
})
}
export function add{{.ClassName}}(data: {{.ClassName}}) {
return request<ApiResponse<{{.ClassName}}>>({
url: '/api/v1/{{.ModuleName}}',
method: 'post',
data
})
}
export function update{{.ClassName}}(data: {{.ClassName}}) {
return request<ApiResponse<{{.ClassName}}>>({
url: '/api/v1/{{.ModuleName}}/' + data.{{.PkJsonField}},
method: 'put',
data
})
}
export function del{{.ClassName}}(ids: Id[]) {
return request<ApiResponse<null>>({
url: '/api/v1/{{.ModuleName}}',
method: 'delete',
data: { ids: ids.map(Number) }
})
}