feat: 添加工作流取消与临时文件管理功能

- 新增临时文件(FileTemp)的实体、DAO和DTO,支持文件临时存储与批量操作
- 实现工作流执行取消功能,使用sync.Map管理context.CancelFunc,支持按会话取消运行中的流程
- 将流程执行状态"暂停"变更为"取消",并处理取消导致的错误
- 引入IsDialogue标识区分对话模式,调整判断/文案/图片节点的表单数据组装逻辑
- 重构ComposeMessagesReq,使用BuildType替代IsBuild和ModelTypeId
- 优化HTML内容提取逻辑,修复文案纯文本与图片URL的标签过滤及标签命名
- 在结果汇总节点中使用事务更新执行状态并批量保存输出文件记录
This commit is contained in:
2026-05-15 09:37:23 +08:00
parent 2c3cbab11d
commit b1ee117f6c
18 changed files with 730 additions and 336 deletions

View File

@@ -9,7 +9,6 @@ import (
"io"
"mime/multipart"
"net/http"
"strings"
commonHttp "gitea.com/red-future/common/http"
"gitea.com/red-future/common/utils"
@@ -17,7 +16,7 @@ import (
"github.com/gogf/gf/v2/util/gconv"
)
func GetIsChatModel(ctx context.Context) (*flowDto.GetIsChatModelRes, error) {
func GetIsChatModel(ctx context.Context) (res *flowDto.GetIsChatModelRes, err error) {
headers := make(map[string]string)
if r := g.RequestFromCtx(ctx); r != nil {
for k, v := range r.Request.Header {
@@ -26,13 +25,9 @@ func GetIsChatModel(ctx context.Context) (*flowDto.GetIsChatModelRes, error) {
}
}
}
res := new(flowDto.GetIsChatModelRes)
err := commonHttp.Get(ctx, "model-gateway/model/getIsChatModel", headers, res, nil)
if err != nil {
return nil, err
}
return res, nil
res = new(flowDto.GetIsChatModelRes)
err = commonHttp.Get(ctx, "model-gateway/model/getIsChatModel", headers, res, nil)
return
}
func CreateGatewayTask(ctx context.Context, req *flowDto.CreateTaskReq) (string, error) {
@@ -53,7 +48,7 @@ func CreateGatewayTask(ctx context.Context, req *flowDto.CreateTaskReq) (string,
return res.TaskId, nil
}
func ComposeMessages(ctx context.Context, req *flowDto.ComposeMessagesReq) (*flowDto.ComposeMessagesRes, error) {
func ComposeMessages(ctx context.Context, req *flowDto.ComposeMessagesReq) (res *flowDto.ComposeMessagesRes, err error) {
headers := make(map[string]string)
if r := g.RequestFromCtx(ctx); r != nil {
for k, v := range r.Request.Header {
@@ -62,13 +57,9 @@ func ComposeMessages(ctx context.Context, req *flowDto.ComposeMessagesReq) (*flo
}
}
}
res := new(flowDto.ComposeMessagesRes)
err := commonHttp.Post(ctx, "prompts-core/prompt/composeMessages", headers, res, &req)
if err != nil {
return nil, err
}
return res, nil
res = new(flowDto.ComposeMessagesRes)
err = commonHttp.Post(ctx, "prompts-core/prompt/composeMessages", headers, res, &req)
return
}
func GatewayTask(ctx context.Context, epicycleId int64, model string, content map[string]any) (any, error) {
@@ -169,77 +160,3 @@ func Upload(ctx context.Context, req *dto.UploadFileBytesReq) (*dto.UploadFileBy
g.Log().Infof(ctx, "[Upload] success url=%s size=%d", res.FileURL, res.FileSize)
return res, nil
}
func buildMergeHtml(texts []string, images []string) string {
html := strings.Builder{}
html.WriteString(`
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background: #fff;
color: #333;
}
.container {
max-width: 960px;
margin: 0 auto;
}
/* 图片:完全贴边,无额外间距 */
.image-block {
width: 100%;
margin: 0;
padding: 0;
}
.image-block img {
width: 100%;
height: auto;
display: block;
border-radius: 0;
}
/* 文案:极致紧凑 */
.text-block {
margin: 0;
padding: 16px; /* 仅保留内边距,不设外边距 */
line-height: 1.6;
font-size: 14px;
color: #444;
white-space: pre-wrap;
}
/* 分割线:完全去掉,改用内边距自然分隔 */
</style>
</head>
<body>
<div class="container">
`)
// 1. 先渲染图片(无任何上下边距,占满宽度)
if len(images) > 0 {
html.WriteString(`<div class="image-block">`)
for _, img := range images {
html.WriteString(fmt.Sprintf(`<img src="%s" alt="" />`, img))
}
html.WriteString(`</div>`)
}
// 2. 渲染文案(紧贴图片下方,仅用内边距留白)
if len(texts) > 0 {
html.WriteString(`<div class="text-block">`)
// 段落之间用 <br> 而不是 <br><br>,减少空行
html.WriteString(strings.Join(texts, "<br>"))
html.WriteString(`</div>`)
}
html.WriteString(`
</div>
</body>
</html>
`)
return html.String()
}