com um clique
create-service
创建 Uniplat 领域服务(DomainService)
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Menu
创建 Uniplat 领域服务(DomainService)
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Baseado na classificação ocupacional SOC
读取并分析 PRD 需求文档,提取要点和任务拆分。在 dev-flow 流程的第 1 步自动加载。
Uniplat 低代码平台编码规范速查。在 Uniplat 项目中进行任何开发任务时参考。
编码实现方法论:垂直切片 + TDD 核心循环。在 dev-flow 流程的第 5 步自动加载。
生成开发总结文档,记录交付物、依赖、设计要点。在 dev-flow 流程的第 8 步自动加载。
编码实现方法论:垂直切片,逐步推进。
在指定子项目目录下创建 Uniplat 数据模型脚手架(JSON 元数据 + Groovy 钩子文件)
| name | create-service |
| description | 创建 Uniplat 领域服务(DomainService) |
| version | 1.0.3 |
本 skill 用于创建 Uniplat 领域服务(自定义 API),文件位于子项目的
services/目录下。
$ARGUMENTS 应包含:
passport_api、client_apigetUsersInfo、queryOrders示例:
passport_api → 创建 passport_api 服务report_api /path/to/subproject generate_monthly → 创建带方法的报告服务用 AskUserQuestion 询问:
服务名:passport_api
子项目目录:/path/to/subproject
方法:
- getUsersInfo: 批量获取用户信息
- queryOrders: 查询订单
文件路径:<子项目>/services/<service_name>.groovy
package services
import com.example.report.uniplat.gateway.GatewayContext
import com.example.report.uniplat.host.Host
import com.example.report.uniplat.engine.DO.DataObject
import com.example.report.utils.AssertUtils
import com.example.report.utils.StringUtils
class {{service_name}} {
/**
* {{methodLabel}}
*
* 请求参数(body):
* - param1: 说明
*
* 返回:
* - 结果说明
*/
def {{methodName}}(GatewayContext ctx) {
def host = Host.getInstance()
// 获取 body 参数
def body = ctx.getBody()
def param1 = body.get("param1")?.toString()
// 获取查询参数(URL 参数)
// def queryParam = ctx.parameters["key"]?.getAt(0)
// 获取用户信息
def user = host.getUser()
def userId = user.id
// 获取数据模型
def model = host.getDataModel("{{RelatedModel}}")
// 查询数据
def list = model.queryDataList([status: 1, is_del: 0])
// 返回结果(平台自动包装为 ApiResult)
return list.list.collect { item ->
[
id : item.getKeyValue(),
name : item.name.value,
status: item.status.display
]
}
}
/**
* 另一个方法示例
*/
def {{anotherMethod}}(GatewayContext ctx) {
def host = Host.getInstance()
def body = ctx.getBody()
def id = body.get("id")?.toString()
AssertUtils.isTrue(StringUtils.notEmptyString(id), "ID不能为空")
def model = host.getDataModel("{{RelatedModel}}")
def obj = model.getByKeyField(id as long)
AssertUtils.isTrue(obj != null, "数据不存在")
// 更新数据
obj.update([
status : 1,
update_time: host.getTimestamp()
])
return [
result: 0,
msg : "操作成功",
data : [id: obj.getKeyValue(), name: obj.name.value]
]
}
}
完成后展示:
服务已创建:
文件:services/passport_api.groovy
方法:
- getUsersInfo
- queryOrders
API 端点:
POST /general/project/{subproject}/service/passport_api/getUsersInfo
领域服务(DomainService,绑定子项目/领域)——共 7 种,路径前缀 /general/project(SOA 除外),方法参数用对应上下文类:
| 类型 | 端点 | 上下文类 | 认证 |
|---|---|---|---|
| 标准服务 | /general/project/{子项目}/service/{类}/{方法} | GatewayContext | 需认证 |
| 匿名服务 | /general/project/{子项目}/service/anonymous/{类}/{方法} | AnonymousGatewayContext | 免登录 |
| 内部服务 | /general/project/{子项目}/internal_service/{类}/{方法} | InternalDomainServiceContext | 内部 Token |
| SOA 服务 | /soa/{子项目}/{类}/{方法} | GatewayContext | SOA 集成 |
| SSE 流式 | /general/project/{子项目}/stream/{类}/{方法} | StreamApiContext | 需认证 |
| 匿名流式 | /general/project/{子项目}/stream/anonymous/{类}/{方法} | AnonymousStreamApiContext | 免登录 |
| MVC 控制器 | /general/project/{子项目}/ctrl/{类}/{方法} | ControllerContext | MVC 风格 |
例(匿名服务):POST /general/project/biz_spview/service/anonymous/tools_api/it_year_result
模型服务(ModelService,绑定具体模型)——入口是模型名,自动拿到对应 DataModel:
| 类型 | 端点 | 上下文类 |
|---|---|---|
| 模型服务 | /general/model/{模型}/service/{方法} | ModelServiceContext |
| 匿名模型服务 | /general/model/{模型}/service/anonymous/{方法} | AnonymousModelServiceContext |
// 模型服务写在模型的 .groovy 里,参数用 ModelServiceContext
import com.example.report.uniplat.models.service.ModelServiceContext
def exportData(ModelServiceContext ctx) {
def model = ctx.dataModel // 自动绑定当前模型
def list = model.queryDataList([is_del: 0])
return list.asList().collect { [id: it.getKeyValue(), name: it.getValue("name")] }
}
DomainService 与 ModelService 的区别:前者绑定领域(
services/下、参数GatewayContext),后者绑定模型(写在模型 groovy 里、参数ModelServiceContext)。
def query(GatewayContext ctx) {
def host = Host.getInstance()
def body = ctx.getBody()
def page = (body.get("page") ?: "1") as int
def size = (body.get("size") ?: "20") as int
def conditions = [is_del: 0]
if (body.get("status")) {
conditions.status = body.get("status") as int
}
def model = host.getDataModel("system_user")
def list = model.queryDataList(conditions)
def total = list.count()
def items = list.list.drop((page - 1) * size).take(size)
return [
result: 0,
data : items.collect { [id: it.getKeyValue(), name: it.name.value] },
total : total,
page : page,
size : size
]
}
def batchUpdate(GatewayContext ctx) {
def host = Host.getInstance()
def body = ctx.getBody()
def ids = body.get("ids")?.toString()?.split(",")?.collect { it.trim() as long }
AssertUtils.isTrue(ids != null && ids.size() > 0, "请选择要操作的数据")
def model = host.getDataModel("system_user")
def now = host.getTimestamp()
def operator = host.getUser().id as long
ids.each { id ->
def obj = model.getByKeyField(id)
if (obj) {
obj.update([
status : 1,
update_time: now,
update_by : operator
])
}
}
return [result: 0, msg: "操作成功", count: ids.size()]
}
def crossModel(GatewayContext ctx) {
def host = Host.getInstance()
def body = ctx.getBody()
def userModel = host.getDataModel("system_user")
def orgModel = host.getDataModel("system_org")
def user = userModel.getByKeyField(body.get("userId") as long)
def org = orgModel.getByKeyField(body.get("orgId") as long)
AssertUtils.isTrue(user != null, "用户不存在")
AssertUtils.isTrue(org != null, "组织不存在")
return [result: 0, msg: "操作成功"]
}
def callModelMethod(GatewayContext ctx) {
def host = Host.getInstance()
def body = ctx.getBody()
// 调用模型 Groovy 中的方法
def result = host.invokeModelFunc(
"system_user",
"getUserDisplay",
body.get("userId") as long
)
return [result: 0, data: result]
}
import com.example.report.db.DataSourceFactory
import com.example.report.db.DbConsts
def queryWithSql(GatewayContext ctx) {
def body = ctx.getBody()
def status = body.get("status") as int
def ds = DataSourceFactory.getDataSource(DbConsts.HOST)
def results = ds.queryForList(
"SELECT * FROM system_user WHERE status = ? AND is_del = 0",
status
)
return results
}
import com.example.report.db.DataSourceFactory
import com.example.report.db.DbConsts
def transactional(GatewayContext ctx) {
def host = Host.getInstance()
def body = ctx.getBody()
DataSourceFactory.transaction(DbConsts.HOST, {
def model = host.getDataModel("system_user")
def obj = model.getByKeyField(body.get("id") as long)
obj.update([status: 1])
// 更多操作...
} as Runnable)
return [result: 0, msg: "操作成功"]
}
// body 参数(两种写法皆可)
ctx.getBody() // Map 请求体
ctx.getBody().get("key") // 取 body 参数
ctx.body.key // 直接属性访问 body 字段(真实项目常用)
ctx.getBody(SomeDto.class) // 直接反序列化为 DTO
// URL 参数:类型化取参(推荐)
ctx.getStringParam("key") // 字符串
ctx.getStringParam("key", "默认") // 带默认值
ctx.getIntParam("page", 0) // 整数 + 默认
ctx.getLongParam("id") // 长整数
ctx.getBigDecimalParam("amount") // BigDecimal
ctx.parameters // Map<String, String[]> 原始 URL 参数(值是数组)
ctx.parameters["key"]?.getAt(0) // 取第一个原始 URL 参数
// 其他
ctx.getRequest() // 或 ctx.request,HttpServletRequest
ctx.request.getHeader("X-xxx") // 获取请求头
ctx.pathValue // 路径参数
ctx.host // Host(等价 Host.getInstance())
def host = ctx.host // 或 Host.getInstance()
host.getUser() // 当前用户(也可 ctx.host.user)
host.getTimestamp() // 当前时间戳
host.getDataModel("system_user") // 取数据模型
host.invokeModelFunc("模型", "方法", args) // 调用模型 Groovy 方法
host.callUtilMethod("子项目", "工具类", "方法", args...) // 调用领域工具类方法
services/ 直放用 package services;放在子目录(如 services/system/)则用多级包 package services.systempassport_api.groovy → class passport_apidef(参考项目实测);⚠️ 部分文档写 static Object f(GatewayContext),以参考项目的实例 def 为准GatewayContext、匿名 AnonymousGatewayContext、流式 StreamApiContext、模型服务 ModelServiceContext(见「服务端点与类型」)ctx.getBody().get("key") 或 ctx.body.key 皆可;URL 参数用 ctx.getStringParam/getIntParam/getLongParamctx.hostnew ApiResult<>(data)_api 后缀