-[访问Atlas Cloud官网](https://www.atlascloud.ai?ref=89F97E) · [编程计划优惠](https://www.atlascloud.ai/console/coding-plan)
+[访问Atlas Cloud官网](https://www.atlascloud.ai?ref=89F97E&utm_source=github&utm_campaign=ruoyi-drama) · [编程计划优惠](https://www.atlascloud.ai/console/coding-plan)
全模态 AI 推理平台,为开发者提供统一的 AI API,支持视频生成、图像生成和大语言模型。一次接入,即可访问 **300+ 精选模型**。
-[火山引擎 CodingPlan 开发者计划](https://www.volcengine.com/activity/codingplan?utm_campaign=hw&utm_content=hw&utm_medium=devrel_tool_web&utm_source=OWO&utm_term=ageerle-ruoyi-ai)
-火山引擎是字节跳动旗下的云与 AI 服务平台,火山方舟提供豆包大模型、DeepSeek 等多种模型的 API 接入,为开发者提供一站式 AI 开发与推理服务。
+[注册即领2500万Tokens,立即前往](https://www.volcengine.com/activity/ai618?utm_campaign=hw&utm_content=hw&utm_medium=devrel_tool_web&utm_source=OWO&utm_term=ageerle-ruoyi-ai)
+享字节自研豆包模型+满血版开源 SOTA模型,覆盖文本、VLM、图像生成,全模态一站配齐:Seed-2.1、Seedream-5.0、GLM-5.2、DeepSeek等。不止编程、更能解决 Agent 复杂长程任务!
## 💬 社区交流
diff --git a/README_EN.md b/README_EN.md
index 8865116b..5c68afa3 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -47,6 +47,9 @@
| 🔧 Backend | [ruoyi-ai](https://github.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitee.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitcode.com/ageerle/ruoyi-ai) |
| 🎨 User Frontend | [ruoyi-web](https://github.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitee.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitcode.com/ageerle/ruoyi-web) |
| 🛠️ Admin Panel | [ruoyi-admin](https://github.com/ageerle/ruoyi-admin) | [ruoyi-admin](https://gitee.com/ageerle/ruoyi-admin) | [ruoyi-admin](https://gitcode.com/ageerle/ruoyi-admin) |
+| 🎬 Drama | [ruoyi-drama](https://github.com/ageerle/ruoyi-drama) | [ruoyi-drama](https://gitee.com/ageerle/ruoyi-drama) | |
+| 🤖 Copilot | [ruoyi-copilot](https://github.com/ageerle/ruoyi-copilot) | [ruoyi-copilot](https://gitee.com/ageerle/ruoyi-copilot) | [ruoyi-copilot](https://gitcode.com/ageerle/ruoyi-copilot) |
+| 📱 Mini-App | [ruoyi-uniapp](https://github.com/ageerle/ruoyi-uniapp) | [ruoyi-uniapp](https://gitee.com/ageerle/ruoyi-uniapp) | [ruoyi-uniapp](https://gitcode.com/ageerle/ruoyi-uniapp) |
### Partner Projects
| Project Name | GitHub Repository | Gitee Repository |
@@ -175,6 +178,34 @@ docker-compose -f docker-compose-all.yaml logs -f [service-name]
docker-compose -f docker-compose-all.yaml restart [service-name]
```
+### MiniMax Configuration
+
+The built-in MiniMax provider accepts one API Host value and selects the matching protocol adapter. Use a Base URL from this table:
+
+| Region | OpenAI-compatible Base URL | Anthropic-compatible Base URL |
+| --- | --- | --- |
+| Global | `https://api.minimax.io/v1` | `https://api.minimax.io/anthropic` |
+| China | `https://api.minimaxi.com/v1` | `https://api.minimaxi.com/anthropic` |
+
+For Anthropic-compatible requests, configure the Base URL ending in `/anthropic`. Do not append `/v1` or `/v1/messages`; the provider adapter derives the request path internally.
+
+| Model ID | Total context | Input modalities | Thinking |
+| --- | ---: | --- | --- |
+| `MiniMax-M3` | 1,000,000 tokens | Text, image, video | Adaptive or disabled |
+| `MiniMax-M2.7` | 204,800 tokens | Text | Always on |
+
+Current pay-as-you-go prices are in USD per million tokens:
+
+| Model | Service tier and input range | Input | Output | Cache read | Cache write |
+| --- | --- | ---: | ---: | ---: | ---: |
+| `MiniMax-M3` | Standard, up to 512,000 input tokens | $0.30 | $1.20 | $0.06 | Not listed |
+| `MiniMax-M3` | Standard, over 512,000 input tokens | $0.60 | $2.40 | $0.12 | Not listed |
+| `MiniMax-M3` | Priority, up to 512,000 input tokens | $0.45 | $1.80 | $0.09 | Not listed |
+| `MiniMax-M3` | Priority, over 512,000 input tokens | $0.90 | $3.60 | $0.18 | Not listed |
+| `MiniMax-M2.7` | Standard | $0.30 | $1.20 | $0.06 | $0.375 |
+
+See the [official API overview](https://platform.minimax.io/docs/api-reference/api-overview) and [pay-as-you-go pricing](https://platform.minimax.io/docs/guides/pricing-paygo) for current details.
+
## 📚 Documentation
Want to learn more about installation, deployment, configuration, and secondary development?
diff --git a/docs/docker/milvus/docker-compose.yml b/docs/docker/milvus/docker-compose.yml
index 43fe699c..a917c996 100644
--- a/docs/docker/milvus/docker-compose.yml
+++ b/docs/docker/milvus/docker-compose.yml
@@ -1,8 +1,6 @@
-version: '3.5'
-
services:
etcd:
- container_name: milvus-etcd
+ container_name: ruoyi-rag-milvus-etcd
image: quay.io/coreos/etcd:v3.5.18
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
@@ -19,14 +17,11 @@ services:
retries: 3
minio:
- container_name: milvus-minio
+ container_name: ruoyi-rag-milvus-minio
image: minio/minio:RELEASE.2023-03-20T20-16-18Z
environment:
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
- ports:
- - "9001:9001"
- - "9000:9000"
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data
command: minio server /minio_data --console-address ":9001"
@@ -37,7 +32,7 @@ services:
retries: 3
standalone:
- container_name: milvus-standalone
+ container_name: ruoyi-rag-milvus
image: milvusdb/milvus:v2.5.7
command: ["milvus", "run", "standalone"]
security_opt:
@@ -61,7 +56,7 @@ services:
- "minio"
attu:
- container_name: attu
+ container_name: ruoyi-rag-attu
image: zilliz/attu:v2.5.7
environment:
MILVUS_URL: milvus-standalone:19530
@@ -72,4 +67,4 @@ services:
networks:
default:
- name: milvus
\ No newline at end of file
+ name: ruoyi-rag-milvus
diff --git a/docs/docker/qdrant/docker-compose.yml b/docs/docker/qdrant/docker-compose.yml
index d17c9fd8..eed546f8 100644
--- a/docs/docker/qdrant/docker-compose.yml
+++ b/docs/docker/qdrant/docker-compose.yml
@@ -1,12 +1,20 @@
---
services:
qdrant:
- image: qdrant/qdrant:latest
+ container_name: ruoyi-rag-qdrant
+ image: qdrant/qdrant:v1.17.0
ports:
- 6333:6333
- 6334:6334
volumes:
- qdrant_data:/qdrant/storage
+ healthcheck:
+ test: ["CMD-SHELL", "bash -c 'exec 3<>/dev/tcp/127.0.0.1/6333 && printf \"GET /healthz HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n\" >&3 && grep -q \"200 OK\" <&3'"]
+ interval: 10s
+ timeout: 5s
+ retries: 12
+ start_period: 10s
+ restart: unless-stopped
volumes:
qdrant_data:
...
diff --git a/docs/docker/ruoyi-ai/Dockerfile.backend b/docs/docker/ruoyi-ai/Dockerfile.backend
index 87eb5626..3cd7ce5c 100644
--- a/docs/docker/ruoyi-ai/Dockerfile.backend
+++ b/docs/docker/ruoyi-ai/Dockerfile.backend
@@ -20,6 +20,22 @@ RUN mvn clean package -Pprod -DskipTests
# 最终运行镜像
FROM eclipse-temurin:17-jre-alpine
+RUN set -eux; \
+ apk add --no-cache ffmpeg; \
+ for filter in scale pad fps setsar format tpad trim settb setpts xfade \
+ aresample aformat apad atrim asetpts anullsrc concat acrossfade; do \
+ ffmpeg -hide_banner -filters 2>/dev/null | grep -Eq "[[:space:]]${filter}[[:space:]]"; \
+ done; \
+ ffmpeg -hide_banner -h filter=xfade 2>&1 | grep -q dissolve; \
+ ffmpeg -hide_banner -h filter=xfade 2>&1 | grep -q fadeblack; \
+ ffmpeg -hide_banner -h filter=xfade 2>&1 | grep -q slideleft; \
+ ffmpeg -hide_banner -encoders 2>/dev/null | grep -Eq '[[:space:]]libx264[[:space:]]'; \
+ ffmpeg -hide_banner -encoders 2>/dev/null | grep -Eq '[[:space:]]aac[[:space:]]'; \
+ ffprobe -hide_banner -version >/dev/null
+
+ENV FFMPEG_PATH=/usr/bin/ffmpeg \
+ FFPROBE_PATH=/usr/bin/ffprobe
+
# 设置工作目录
WORKDIR /app
@@ -27,10 +43,10 @@ WORKDIR /app
COPY --from=builder /build/ruoyi-admin/target/ruoyi-admin.jar ./ruoyi-admin.jar
# 创建日志目录
-RUN mkdir -p /ruoyi/server/logs
+RUN mkdir -p /ruoyi/server/logs /ruoyi/server/temp
# 暴露端口
EXPOSE 6039
# 启动命令
-ENTRYPOINT ["java", "-jar", "ruoyi-admin.jar", "--spring.profiles.active=prod"]
+ENTRYPOINT ["java", "-Djava.io.tmpdir=/ruoyi/server/temp", "-jar", "ruoyi-admin.jar", "--spring.profiles.active=prod"]
diff --git a/docs/docker/ruoyi-ai/Dockerfile.mysql b/docs/docker/ruoyi-ai/Dockerfile.mysql
index d5fcecb7..a7b11679 100644
--- a/docs/docker/ruoyi-ai/Dockerfile.mysql
+++ b/docs/docker/ruoyi-ai/Dockerfile.mysql
@@ -1,16 +1,14 @@
# 基于官方MySQL 8.0镜像构建自定义镜像
# 构建命令: docker build -t registry.cn-hangzhou.aliyuncs.com/ruoyi-ai/mysql:v3 -f Dockerfile.mysql .
-FROM mysql:8.0.33
+FROM mysql:8.0
# 设置时区
ENV TZ=Asia/Shanghai
-# 复制初始化脚本和SQL文件到镜像中
-COPY docs/script/docker/mysql/init/init-db.sh /docker-entrypoint-initdb.d/init-db.sh
-COPY docs/script/sql/ruoyi-ai-v3_mysql8.sql /docker-entrypoint-initdb.d/ruoyi-ai-v3_mysql8.sql
-
-# 设置脚本可执行权限
-RUN chmod +x /docker-entrypoint-initdb.d/init-db.sh
+# MySQL 官方入口会按文件名顺序执行初始化目录中的 SQL。
+# ruoyi-ai.sql 会导入 MYSQL_DATABASE,snail_job_mysql.sql 会自行创建并切换数据库。
+COPY docs/script/sql/ruoyi-ai.sql /docker-entrypoint-initdb.d/01-ruoyi-ai.sql
+COPY docs/script/sql/snail_job_mysql.sql /docker-entrypoint-initdb.d/02-snail-job.sql
# MySQL启动参数
CMD ["--default-authentication-plugin=mysql_native_password", \
@@ -18,4 +16,4 @@ CMD ["--default-authentication-plugin=mysql_native_password", \
"--collation-server=utf8mb4_general_ci", \
"--explicit_defaults_for_timestamp=true", \
"--lower_case_table_names=1", \
- "--skip-ssl"]
\ No newline at end of file
+ "--skip-ssl"]
diff --git a/docs/docker/ruoyi-ai/docker-compose-all.yaml b/docs/docker/ruoyi-ai/docker-compose-all.yaml
index b9f330c1..21c781a5 100644
--- a/docs/docker/ruoyi-ai/docker-compose-all.yaml
+++ b/docs/docker/ruoyi-ai/docker-compose-all.yaml
@@ -12,8 +12,6 @@
#
# 镜像仓库地址: crpi-31mraxd99y2gqdgr.cn-beijing.personal.cr.aliyuncs.com/ruoyi_ai
-version: '3.8'
-
services:
# ==================== MySQL 数据库 ====================
mysql:
@@ -30,7 +28,10 @@ services:
volumes:
- mysql-data:/var/lib/mysql
healthcheck:
- test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot"]
+ # Force TCP: during first-time initialization MySQL exposes a temporary
+ # socket-only server. A socket ping would mark the service healthy before
+ # the real network listener (used by the backend) is ready.
+ test: ["CMD", "mysqladmin", "ping", "--protocol=tcp", "-h", "127.0.0.1", "-u", "root", "-proot"]
interval: 15s
timeout: 10s
retries: 10
@@ -177,4 +178,4 @@ volumes:
weaviate-data:
minio-data:
logs-data:
- upload-data:
\ No newline at end of file
+ upload-data:
diff --git a/docs/docker/ruoyi-ai/docker-compose.yaml b/docs/docker/ruoyi-ai/docker-compose.yaml
index eac534d8..96c4e949 100644
--- a/docs/docker/ruoyi-ai/docker-compose.yaml
+++ b/docs/docker/ruoyi-ai/docker-compose.yaml
@@ -21,8 +21,8 @@ services:
MYSQL_DATABASE: ruoyi-ai-agent
TZ: Asia/Shanghai
volumes:
- - ./docs/script/docker/mysql/init/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh:ro
- - ./docs/script/sql/ruoyi-ai-v3_mysql8.sql:/docker-entrypoint-initdb.d/ruoyi-ai-v3_mysql8.sql:ro
+ - ../../script/sql/ruoyi-ai.sql:/docker-entrypoint-initdb.d/01-ruoyi-ai.sql:ro
+ - ../../script/sql/snail_job_mysql.sql:/docker-entrypoint-initdb.d/02-snail-job.sql:ro
- mysql-data:/var/lib/mysql
command:
--default-authentication-plugin=mysql_native_password
@@ -32,7 +32,9 @@ services:
--lower_case_table_names=1
--skip-ssl
healthcheck:
- test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot"]
+ # Do not let the socket-only initialization server satisfy the check.
+ # The backend connects over TCP and must wait for that listener.
+ test: ["CMD", "mysqladmin", "ping", "--protocol=tcp", "-h", "127.0.0.1", "-u", "root", "-proot"]
interval: 15s
timeout: 10s
retries: 10
diff --git a/docs/docker/weaviate/docker-compose.yml b/docs/docker/weaviate/docker-compose.yml
index 4504591e..6b6acb47 100644
--- a/docs/docker/weaviate/docker-compose.yml
+++ b/docs/docker/weaviate/docker-compose.yml
@@ -5,12 +5,12 @@ services:
- --host
- 0.0.0.0
- --port
- - '6038'
+ - '8080'
- --scheme
- http
- image: semitechnologies/weaviate:1.19.7
+ image: semitechnologies/weaviate:1.30.0
ports:
- - 6038:6038
+ - 28080:8080
- 50051:50051
volumes:
- weaviate_data:/var/lib/weaviate
diff --git a/docs/image/wx06.png b/docs/image/wx06.png
index 209d3a23..58eb0144 100644
Binary files a/docs/image/wx06.png and b/docs/image/wx06.png differ
diff --git a/docs/script/docker/mysql/init/init-db.sh b/docs/script/docker/mysql/init/init-db.sh
deleted file mode 100644
index 46b6fc6a..00000000
--- a/docs/script/docker/mysql/init/init-db.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-# 数据库初始化脚本
-# 使用 --force 参数确保即使出错也继续执行
-
-echo "开始初始化数据库..."
-
-# 使用 --force 参数忽略错误继续执行
-mysql -uroot -proot ruoyi-ai-agent --force < /docker-entrypoint-initdb.d/ruoyi-ai-v3_mysql8.sql
-
-echo "数据库初始化完成"
diff --git a/docs/script/install-ffmpeg-windows.ps1 b/docs/script/install-ffmpeg-windows.ps1
new file mode 100644
index 00000000..e6b5b63f
--- /dev/null
+++ b/docs/script/install-ffmpeg-windows.ps1
@@ -0,0 +1,86 @@
+[CmdletBinding()]
+param(
+ [switch]$Force
+)
+
+$ErrorActionPreference = 'Stop'
+
+function Find-Executable([string]$Name) {
+ $command = Get-Command $Name -ErrorAction SilentlyContinue
+ if ($command) {
+ return $command.Source
+ }
+
+ $roots = @(
+ (Join-Path $env:LOCALAPPDATA 'Microsoft\WinGet\Packages'),
+ (Join-Path $env:USERPROFILE 'scoop\apps\ffmpeg'),
+ 'C:\ProgramData\chocolatey\bin',
+ 'C:\ffmpeg'
+ )
+ foreach ($root in $roots) {
+ if (-not (Test-Path $root)) { continue }
+ $match = Get-ChildItem -Path $root -Filter "$Name.exe" -Recurse -ErrorAction SilentlyContinue |
+ Select-Object -First 1 -ExpandProperty FullName
+ if ($match) { return $match }
+ }
+ return $null
+}
+
+$ffmpeg = Find-Executable 'ffmpeg'
+$ffprobe = Find-Executable 'ffprobe'
+
+if ($Force -or -not $ffmpeg -or -not $ffprobe) {
+ $winget = Get-Command winget -ErrorAction SilentlyContinue
+ if (-not $winget) {
+ throw '未找到 winget。请先从 Microsoft Store 安装“应用安装程序”,或使用项目 Dockerfile 运行后端。'
+ }
+
+ Write-Host '正在通过 winget 安装 FFmpeg...' -ForegroundColor Cyan
+ & winget install --id Gyan.FFmpeg --exact --source winget `
+ --accept-package-agreements --accept-source-agreements
+ if ($LASTEXITCODE -ne 0) {
+ throw "winget 安装失败,退出码: $LASTEXITCODE"
+ }
+
+ $ffmpeg = Find-Executable 'ffmpeg'
+ $ffprobe = Find-Executable 'ffprobe'
+}
+
+if (-not $ffmpeg -or -not $ffprobe) {
+ throw 'FFmpeg 已安装但未能定位 ffmpeg.exe 或 ffprobe.exe。请重新打开 PowerShell 后再次运行脚本。'
+}
+
+$binDirectory = Split-Path -Parent $ffmpeg
+[Environment]::SetEnvironmentVariable('FFMPEG_PATH', $ffmpeg, 'User')
+[Environment]::SetEnvironmentVariable('FFPROBE_PATH', $ffprobe, 'User')
+
+$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
+$pathParts = @($userPath -split ';' | Where-Object { $_ })
+if ($pathParts -notcontains $binDirectory) {
+ $newPath = (@($pathParts) + $binDirectory) -join ';'
+ [Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
+}
+
+$env:FFMPEG_PATH = $ffmpeg
+$env:FFPROBE_PATH = $ffprobe
+if (($env:Path -split ';') -notcontains $binDirectory) {
+ $env:Path = "$binDirectory;$env:Path"
+}
+
+Write-Host "ffmpeg: $ffmpeg" -ForegroundColor Green
+Write-Host "ffprobe: $ffprobe" -ForegroundColor Green
+
+& $ffmpeg -hide_banner -version | Select-Object -First 1
+& $ffprobe -hide_banner -version | Select-Object -First 1
+
+$encoders = & $ffmpeg -hide_banner -encoders 2>&1 | Out-String
+if ($encoders -notmatch '\blibx264\b') {
+ throw '当前 FFmpeg 不包含 libx264 编码器,无法满足短剧合成配置。'
+}
+if ($encoders -notmatch '\baac\b') {
+ throw '当前 FFmpeg 不包含 AAC 编码器,无法满足短剧合成配置。'
+}
+
+Write-Host ''
+Write-Host '安装与配置完成。请完全重启 IntelliJ IDEA 和 ruoyi-ai 后端服务。' -ForegroundColor Yellow
+Write-Host '重启后,Spring 将从 FFMPEG_PATH 和 FFPROBE_PATH 读取绝对路径。'
\ No newline at end of file
diff --git a/docs/script/sql/ruoyi-ai-v3_mysql8.sql b/docs/script/sql/ruoyi-ai.sql
similarity index 72%
rename from docs/script/sql/ruoyi-ai-v3_mysql8.sql
rename to docs/script/sql/ruoyi-ai.sql
index 89ea2af7..0fae0fde 100644
--- a/docs/script/sql/ruoyi-ai-v3_mysql8.sql
+++ b/docs/script/sql/ruoyi-ai.sql
@@ -11,12 +11,45 @@
Target Server Version : 80045 (8.0.45)
File Encoding : 65001
- Date: 21/05/2026 11:03:49
+ Date: 14/07/2026 21:36:39
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
+-- ----------------------------
+-- Table structure for agent_info
+-- ----------------------------
+DROP TABLE IF EXISTS `agent_info`;
+CREATE TABLE `agent_info` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '智能体ID',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户ID',
+ `agent_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '智能体名称',
+ `agent_describe` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '智能体描述(下拉展示用)',
+ `agent_show` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '展示图标/头像URL',
+ `model_id` bigint NOT NULL COMMENT '绑定的聊天模型ID(chat_model.id, category=chat)',
+ `enable_thinking` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '是否启用深度思考(ReAct多子Agent):0 否 1 是',
+ `system_prompt` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '自定义系统提示词',
+ `mcp_tool_ids` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '关联MCP工具ID列表(JSON数组,[Long])',
+ `skill_names` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '关联磁盘技能名列表(JSON数组,[String])',
+ `knowledge_ids` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '关联知识库ID列表(JSON数组,[Long])',
+ `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '状态:0 正常 1 停用',
+ `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
+ `create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门',
+ `create_by` bigint NULL DEFAULT NULL COMMENT '创建者',
+ `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+ `update_by` bigint NULL DEFAULT NULL COMMENT '更新者',
+ `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_agent_tenant_id`(`tenant_id` ASC) USING BTREE,
+ INDEX `idx_agent_model_id`(`model_id` ASC) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '智能体信息表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of agent_info
+-- ----------------------------
+INSERT INTO `agent_info` VALUES (1, 0, '对话智能体', '对话智能体', NULL, 2000585866022060033, '0', '你是一个乐于助人的通用 AI 助手,请用简洁、准确的中文回答用户的问题。', '[]', '[\"docx\"]', '[]', '0', '系统初始化的默认智能体,自动绑定首个启用的对话模型', 103, 1, '2026-07-14 16:12:21', 1, '2026-07-14 16:18:04');
+
-- ----------------------------
-- Table structure for chat_message
-- ----------------------------
@@ -42,6 +75,8 @@ CREATE TABLE `chat_message` (
-- ----------------------------
-- Records of chat_message
-- ----------------------------
+INSERT INTO `chat_message` VALUES (2076944340894203905, 2076944338398593026, 1, '你好', 'user', 0, 'deepseek-v4-flash', 103, 1, '2026-07-14 16:18:13', 1, '2026-07-14 16:18:13', NULL, 0);
+INSERT INTO `chat_message` VALUES (2076944348947267585, 2076944338398593026, 1, '你好!有什么可以帮你的吗?', 'assistant', 0, 'deepseek-v4-flash', -1, -1, '2026-07-14 16:18:15', -1, '2026-07-14 16:18:15', NULL, 0);
-- ----------------------------
-- Table structure for chat_model
@@ -70,9 +105,18 @@ CREATE TABLE `chat_model` (
-- ----------------------------
-- Records of chat_model
-- ----------------------------
-INSERT INTO `chat_model` (`id`, `category`, `model_name`, `provider_code`, `model_describe`, `model_dimension`, `model_show`, `api_host`, `api_key`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`, `tenant_id`) VALUES (2000585866022060033, 'chat', 'zai-org/glm-5.1', 'atlas', 'zai-org/glm-5.1', NULL, 'Y', 'https://api.atlascloud.ai/v1', 'sk_xx', 103, 1, '2025-12-15 23:16:54', 1, '2026-03-15 19:18:48', '对话模型', 0);
-INSERT INTO `chat_model` (`id`, `category`, `model_name`, `provider_code`, `model_describe`, `model_dimension`, `model_show`, `api_host`, `api_key`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`, `tenant_id`) VALUES (2007528268536287233, 'vector', 'embedding-3', 'zhipu', 'embedding-3', 2048, 'N', 'https://open.bigmodel.cn', 'sk_xx', 103, 1, '2026-01-04 03:03:32', 1, '2026-03-15 19:18:51', '向量模型', 0);
-INSERT INTO `chat_model` (`id`, `category`, `model_name`, `provider_code`, `model_describe`, `model_dimension`, `model_show`, `api_host`, `api_key`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`, `tenant_id`) VALUES (2045071617578237953, 'rerank', 'rerank', 'zhipu', 'rerank', NULL, 'N', 'https://open.bigmodel.cn', 'sk_xx', 103, 1, '2026-04-17 17:27:24', 1, '2026-04-20 15:21:48', '重排序模型', 0);
+INSERT INTO `chat_model` VALUES (2000585866022060033, 'chat', 'deepseek-v4-flash', 'deepseek', 'deepseek-v4-flash', NULL, 'Y', 'https://api.deepseek.com', 'sk_xx', 103, 1, '2025-12-15 23:16:54', 1, '2026-03-15 19:18:48', '对话模型', 0);
+INSERT INTO `chat_model` VALUES (2007528268536287233, 'vector', 'embedding-3', 'zhipu', 'embedding-3', 2048, 'N', 'https://open.bigmodel.cn', 'sk_xx', 103, 1, '2026-01-04 03:03:32', 1, '2026-03-15 19:18:51', '向量模型', 0);
+INSERT INTO `chat_model` VALUES (2045071617578237953, 'rerank', 'rerank', 'zhipu', 'rerank', NULL, 'N', 'https://open.bigmodel.cn', 'sk_xx', 103, 1, '2026-04-17 17:27:24', 1, '2026-04-20 15:21:48', '重排序模型', 0);
+INSERT INTO `chat_model` VALUES (2000585866022060003, 'chat', 'deepseek-ai/deepseek-v4-flash', 'atlas', 'deepseek-v4-flash', NULL, 'Y', 'https://api.atlascloud.ai/v1', 'sk_xx', 103, 1, '2025-12-15 23:16:54', 1, '2026-03-15 19:18:48', '对话模型', 0);
+INSERT INTO `chat_model` VALUES (2050000000000000001, 'video', 'bytedance/seedance-2.0/text-to-video', 'atlas', 'Seedance 2.0 文生视频(字节跳动)', NULL, 'Y', 'https://api.atlascloud.ai/v1', 'sk_xx', 103, 1, '2026-06-17 18:39:20', 1, '2026-06-17 18:39:20', 'Atlas Cloud 视频模型 - Seedance 2.0', 0);
+INSERT INTO `chat_model` VALUES (2060622000000000001, 'image', 'openai/gpt-image-2/text-to-image', 'atlas', 'GPT-IMAGE-2 文生图', NULL, 'Y', 'https://api.atlascloud.ai/v1', 'sk_xx', 103, 1, '2026-06-22 14:45:54', 1, '2026-06-22 14:45:54', 'Atlas Cloud 图片模型 - 文生图,支持三视图、角色设定、场景图', 0);
+INSERT INTO `chat_model` VALUES (2060622000000000002, 'image', 'openai/gpt-image-2/edit', 'atlas', 'GPT-IMAGE-2 图生图编辑', NULL, 'Y', 'https://api.atlascloud.ai/v1', 'sk_xx', 103, 1, '2026-06-22 14:45:54', 1, '2026-06-22 14:45:54', 'Atlas Cloud 图片模型 - 图生图/编辑,支持基于参考图修改风格、纹理等', 0);
+INSERT INTO `chat_model` VALUES (2060622000000000003, 'video', 'bytedance/seedance-2.0/image-to-video', 'atlas', 'Seedance 2.0 图生视频(字节跳动)', NULL, 'Y', 'https://api.atlascloud.ai/v1', 'sk_xx', 103, 1, '2026-06-22 17:24:07', 1, '2026-06-22 17:24:07', 'Atlas Cloud 视频模型 - Seedance 2.0 图生视频,接收参考图+提示词生成视频', 0);
+INSERT INTO `chat_model` VALUES (2060622000000000004, 'video', 'bytedance/seedance-2.0/reference-to-video', 'atlas', 'Seedance 2.0 多参考图生视频(字节跳动)', NULL, 'Y', 'https://api.atlascloud.ai/v1', 'sk_xx', 103, 1, '2026-06-22 20:24:44', 1, '2026-06-22 20:24:44', 'Atlas Cloud 视频模型 - Seedance 2.0 多参考图生视频,接收多张参考图+带@imageN标记的提示词生成视频', 0);
+INSERT INTO `chat_model` VALUES (2070700000000000002, 'chat', 'dify-chat', 'dify', 'Dify Chat App', NULL, 'Y', 'https://api.dify.ai/v1', '替换为你的DIFY_APP_API_KEY', 103, 1, '2026-07-14 11:03:44', 1, '2026-07-14 11:03:44', 'Dify 聊天应用;api_key 为 Dify App API Key,model_name 可按应用名修改', 0);
+INSERT INTO `chat_model` VALUES (2070700000000000004, 'chat', '替换为你的COZE_BOT_ID', 'coze', 'Coze Bot', NULL, 'Y', 'https://api.coze.cn', '替换为你的COZE_PAT', 103, 1, '2026-07-14 11:03:38', 1, '2026-07-14 11:03:38', 'Coze 聊天 Bot;model_name 为 Coze Bot ID,api_key 为 PAT 或 OAuth access token', 0);
+INSERT INTO `chat_model` VALUES (2070700000000000010, 'audio', 'bytedance/seed-audio-1.0', 'atlas', 'Seed Audio 1.0 语音生成(字节跳动)', NULL, 'Y', 'https://api.atlascloud.ai/v1', 'sk_xx', 103, 1, '2026-07-16 18:00:00', 1, '2026-07-16 18:00:00', 'Atlas Cloud 语音模型 - 支持多角色对白配音,references 指定 speaker 音色,text 中用 @audioN 引用', 0);
-- ----------------------------
-- Table structure for chat_provider
@@ -82,7 +126,7 @@ CREATE TABLE `chat_provider` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`provider_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '厂商名称',
`provider_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '厂商编码',
- `provider_icon` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '厂商图标',
+ `provider_icon` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '厂商图标',
`provider_desc` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '厂商描述',
`api_host` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'API地址',
`status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '状态(0正常 1停用)',
@@ -100,19 +144,21 @@ CREATE TABLE `chat_provider` (
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `unique_provider_code`(`provider_code` ASC, `tenant_id` ASC, `del_flag` ASC) USING BTREE,
INDEX `idx_status`(`status` ASC) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 2045727230803255298 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '厂商管理表' ROW_FORMAT = DYNAMIC;
+) ENGINE = InnoDB AUTO_INCREMENT = 2070700000000000004 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '厂商管理表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of chat_provider
-- ----------------------------
-INSERT INTO `chat_provider` VALUES (11, '深度求索', 'deepseek', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/04/19/5ba8c30f153246898a4d7dc7b846de8d.png', 'DeepSeek官方API', 'https://api.deepseek.com', '0', 0, 103, '2026-04-19 12:52:34', '1', '1', '2026-04-19 13:13:25', 'DeepSeek官方API', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (12, '智谱AI', 'zhipu', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/04/19/da071783c9284fdd9ed1ce1b57b3c75c.png', '智谱AI大模型服务', 'https://open.bigmodel.cn', '0', 4, 103, '2025-12-14 21:48:11', '1', '1', '2026-04-19 13:14:00', '智谱AI厂商', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (13, '小米MIMO', 'xiaomi', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/04/19/18dd39365ce244e3ae5e030da036760e.png', '小米官方API', 'https://api.xiaomimimo.com/v1', '0', 3, 103, '2026-04-19 12:48:24', '1', '1', '2026-04-19 13:14:22', '小米官方API', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (14, '阿里云百炼', 'qianwen', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/de2aa7e649de44f3ba5c6380ac6acd04.png', '阿里云百炼大模型服务', 'https://dashscope.aliyuncs.com', '0', 2, 103, '2025-12-14 21:48:11', '1', '1', '2026-02-25 20:49:13', '阿里云厂商', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (15, 'Atlas Cloud', 'atlas', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/04/19/atlascloud.png', '全模态AI推理平台', 'https://api.atlascloud.ai/v1', '0', 5, 103, '2025-12-15 23:13:42', '1', '1', '2026-02-25 20:49:01', 'Atlas Cloud AI平台', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (16, 'MiniMax', 'minimax', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/04/19/fdc712e90e0e4d78b05862ad230884e5.png', 'MiniMax大模型服务,支持M2.7、M2.5等模型', 'https://api.minimax.io/v1', '0', 6, 103, '2026-04-19 12:50:12', '1', '1', '2026-04-19 13:14:59', 'MiniMax厂商', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (17, 'ollama', 'ollama', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/afecabebc8014d80b0f06b4796a74c5d.png', 'ollama大模型', 'http://127.0.0.1:11434', '0', 7, 103, '2025-12-14 21:48:11', '1', '1', '2026-02-25 20:48:48', 'ollama厂商', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (18, '自定义厂商', 'custom_api', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/04/19/c1a8e122510f4e2f90deb36958af710b.png', 'OPENAI兼容格式', '自定义', '0', 8, 103, '2026-04-19 12:35:57', '1', '1', '2026-04-19 13:17:20', 'OPENAI兼容格式', NULL, '0', NULL, 0);
+INSERT INTO `chat_provider` VALUES (11, '深度求索', 'deepseek', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/04/19/5ba8c30f153246898a4d7dc7b846de8d.png', 'DeepSeek官方API', 'https://api.deepseek.com', '0', 0, 103, '2026-04-19 12:52:34', '1', '1', '2026-04-19 13:13:25', 'DeepSeek官方API', NULL, '0', NULL, 0);
+INSERT INTO `chat_provider` VALUES (12, '智谱AI', 'zhipu', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/04/19/da071783c9284fdd9ed1ce1b57b3c75c.png', '智谱AI大模型服务', 'https://open.bigmodel.cn', '0', 4, 103, '2025-12-14 21:48:11', '1', '1', '2026-04-19 13:14:00', '智谱AI厂商', NULL, '0', NULL, 0);
+INSERT INTO `chat_provider` VALUES (13, '小米MIMO', 'xiaomi', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/04/19/18dd39365ce244e3ae5e030da036760e.png', '小米官方API', 'https://api.xiaomimimo.com/v1', '0', 3, 103, '2026-04-19 12:48:24', '1', '1', '2026-04-19 13:14:22', '小米官方API', NULL, '0', NULL, 0);
+INSERT INTO `chat_provider` VALUES (14, '阿里云百炼', 'qianwen', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/02/25/de2aa7e649de44f3ba5c6380ac6acd04.png', '阿里云百炼大模型服务', 'https://dashscope.aliyuncs.com', '0', 2, 103, '2025-12-14 21:48:11', '1', '1', '2026-02-25 20:49:13', '阿里云厂商', NULL, '0', NULL, 0);
+INSERT INTO `chat_provider` VALUES (15, 'Atlas Cloud', 'atlas', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/04/19/atlascloud.png', '全模态AI推理平台', 'https://api.atlascloud.ai/v1', '0', 5, 103, '2025-12-15 23:13:42', '1', '1', '2026-02-25 20:49:01', 'Atlas Cloud AI平台', NULL, '0', NULL, 0);
+INSERT INTO `chat_provider` VALUES (16, 'MiniMax', 'minimax', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/04/19/fdc712e90e0e4d78b05862ad230884e5.png', 'MiniMax model service supporting MiniMax-M3 and MiniMax-M2.7', 'https://api.minimax.io/v1', '0', 6, 103, '2026-04-19 12:50:12', '1', '1', '2026-04-19 13:14:59', 'MiniMax provider', NULL, '0', NULL, 0);
+INSERT INTO `chat_provider` VALUES (17, 'ollama', 'ollama', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/02/25/afecabebc8014d80b0f06b4796a74c5d.png', 'ollama大模型', 'http://127.0.0.1:11434', '0', 7, 103, '2025-12-14 21:48:11', '1', '1', '2026-02-25 20:48:48', 'ollama厂商', NULL, '0', NULL, 0);
+INSERT INTO `chat_provider` VALUES (18, '自定义厂商', 'custom_api', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/04/19/c1a8e122510f4e2f90deb36958af710b.png', 'OPENAI兼容格式', '自定义', '0', 8, 103, '2026-04-19 12:35:57', '1', '1', '2026-04-19 13:17:20', 'OPENAI兼容格式', NULL, '0', NULL, 0);
+INSERT INTO `chat_provider` VALUES (2070700000000000001, 'Dify', 'dify', NULL, 'Dify 应用 API 服务', 'https://api.dify.ai/v1', '0', 9, 103, '2026-07-14 11:03:44', '1', '1', '2026-07-14 11:03:44', 'Dify 应用 API 服务商', NULL, '0', NULL, 0);
+INSERT INTO `chat_provider` VALUES (2070700000000000003, 'Coze', 'coze', NULL, 'Coze Bot API 服务', 'https://api.coze.cn', '0', 10, 103, '2026-07-14 11:03:38', '1', '1', '2026-07-14 11:03:38', 'Coze Bot API 服务商', NULL, '0', NULL, 0);
-- ----------------------------
-- Table structure for chat_session
@@ -137,6 +183,13 @@ CREATE TABLE `chat_session` (
-- ----------------------------
-- Records of chat_session
-- ----------------------------
+INSERT INTO `chat_session` VALUES (2076944338398593026, 1, '你好', '你好', '103', 1, '2026-07-14 16:18:13', 1, '2026-07-14 16:18:13', '你好', NULL, 0);
+INSERT INTO `chat_session` VALUES (2076957117012561921, 1, '测试工作流', NULL, '103', 1, '2026-07-14 17:08:59', 1, '2026-07-14 17:08:59', NULL, NULL, 0);
+INSERT INTO `chat_session` VALUES (2076958796772593665, 1, '测试工作流', NULL, '103', 1, '2026-07-14 17:15:40', 1, '2026-07-14 17:15:40', NULL, NULL, 0);
+INSERT INTO `chat_session` VALUES (2076958822525620225, 1, '测试工作流', NULL, '103', 1, '2026-07-14 17:15:46', 1, '2026-07-14 17:15:46', NULL, NULL, 0);
+INSERT INTO `chat_session` VALUES (2076964726549565441, 1, '测试工作流', NULL, '103', 1, '2026-07-14 17:39:14', 1, '2026-07-14 17:39:14', NULL, NULL, 0);
+INSERT INTO `chat_session` VALUES (2076964778940616705, 1, '测试工作流', NULL, '103', 1, '2026-07-14 17:39:26', 1, '2026-07-14 17:39:26', NULL, NULL, 0);
+INSERT INTO `chat_session` VALUES (2076971705284218881, 1, '你好2阿', '你好2阿', '103', 1, '2026-07-14 18:06:57', 1, '2026-07-14 18:06:57', '你好2阿', NULL, 0);
-- ----------------------------
-- Table structure for flow_category
@@ -1078,7 +1131,8 @@ CREATE TABLE `knowledge_attach` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`knowledge_id` bigint NOT NULL COMMENT '知识库ID',
`oss_id` bigint NULL DEFAULT NULL COMMENT '对象存储ID',
- `doc_id` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文档ID',
+ `doc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文档ID',
+ `file_hash` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件SHA-256摘要',
`name` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '附件名称',
`type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '附件类型',
`create_dept` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '部门',
@@ -1090,7 +1144,8 @@ CREATE TABLE `knowledge_attach` (
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户Id',
`status` tinyint NULL DEFAULT 0 COMMENT '解析状态: 0待解析, 1解析中, 2已解析, 3解析失败',
PRIMARY KEY (`id`) USING BTREE,
- UNIQUE INDEX `idx_kname`(`knowledge_id` ASC, `name` ASC) USING BTREE
+ UNIQUE INDEX `idx_kname`(`knowledge_id` ASC, `name` ASC) USING BTREE,
+ UNIQUE INDEX `uk_knowledge_file_hash`(`knowledge_id`, `file_hash`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2033199209203183619 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '知识库附件' ROW_FORMAT = DYNAMIC;
-- ----------------------------
@@ -1103,8 +1158,9 @@ CREATE TABLE `knowledge_attach` (
DROP TABLE IF EXISTS `knowledge_fragment`;
CREATE TABLE `knowledge_fragment` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `fid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '向量库片段ID',
`idx` int NOT NULL COMMENT '片段索引下标',
- `doc_id` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文档ID',
+ `doc_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文档ID',
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '文档内容',
`create_dept` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '部门',
`create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '创建人',
@@ -1115,6 +1171,9 @@ CREATE TABLE `knowledge_fragment` (
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户Id',
`knowledge_id` bigint NULL DEFAULT NULL COMMENT '知识库ID',
PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_fid`(`fid`) USING BTREE,
+ INDEX `idx_doc_id`(`doc_id`) USING BTREE,
+ INDEX `idx_knowledge_id`(`knowledge_id`) USING BTREE,
FULLTEXT INDEX `ft_content`(`content`) WITH PARSER `ngram`
) ENGINE = InnoDB AUTO_INCREMENT = 2033199209131880451 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '知识片段' ROW_FORMAT = DYNAMIC;
@@ -1153,7 +1212,9 @@ CREATE TABLE `knowledge_info` (
`enable_hybrid` tinyint(1) NULL DEFAULT 0 COMMENT '是否启用混合检索',
`hybrid_alpha` double NULL DEFAULT 0.5 COMMENT '混合检索权重比例 (0.0=纯向量, 1.0=纯关键词)',
`system_prompt` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '系统提示词',
- PRIMARY KEY (`id`) USING BTREE
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_tenant_user` (`tenant_id`, `user_id`) USING BTREE,
+ INDEX `idx_tenant_share` (`tenant_id`, `share`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2033198818050781187 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '知识库' ROW_FORMAT = DYNAMIC;
-- ----------------------------
@@ -1235,17 +1296,290 @@ CREATE TABLE `mcp_tool_info` (
INDEX `idx_type`(`type` ASC) USING BTREE,
INDEX `idx_status`(`status` ASC) USING BTREE,
INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'MCP工具表' ROW_FORMAT = DYNAMIC;
+) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'MCP工具表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of mcp_tool_info
-- ----------------------------
-INSERT INTO `mcp_tool_info` VALUES (1, 'edit_file', '', 'BUILTIN', 'ENABLED', NULL, '000000', -1, -1, '2026-02-24 20:19:41', -1, '2026-03-10 21:21:09', '0');
-INSERT INTO `mcp_tool_info` VALUES (2, 'list_directory', '', 'BUILTIN', 'ENABLED', NULL, '000000', -1, -1, '2026-02-24 20:19:41', -1, '2026-03-10 21:21:09', '0');
-INSERT INTO `mcp_tool_info` VALUES (3, 'read_file', '', 'BUILTIN', 'ENABLED', NULL, '000000', -1, -1, '2026-02-24 20:19:41', -1, '2026-03-10 21:21:09', '0');
-INSERT INTO `mcp_tool_info` VALUES (4, 'query_all_tables', '', 'BUILTIN', 'ENABLED', NULL, '000000', -1, -1, '2026-03-10 21:21:09', -1, '2026-03-10 21:21:09', '0');
-INSERT INTO `mcp_tool_info` VALUES (5, 'execute_sql_query', '', 'BUILTIN', 'ENABLED', NULL, '000000', -1, -1, '2026-03-10 21:21:09', -1, '2026-03-10 21:21:09', '0');
-INSERT INTO `mcp_tool_info` VALUES (6, 'query_table_schema', '', 'BUILTIN', 'ENABLED', NULL, '000000', -1, -1, '2026-03-10 21:21:09', -1, '2026-03-10 21:21:09', '0');
+INSERT INTO `mcp_tool_info` VALUES (1, 'edit_file', '', 'BUILTIN', 'ENABLED', NULL, '000000', -1, -1, '2026-02-24 20:19:41', -1, '2026-06-22 16:34:29', '0');
+INSERT INTO `mcp_tool_info` VALUES (2, 'list_directory', '', 'BUILTIN', 'ENABLED', NULL, '000000', -1, -1, '2026-02-24 20:19:41', -1, '2026-06-22 16:34:29', '0');
+INSERT INTO `mcp_tool_info` VALUES (3, 'read_file', '', 'BUILTIN', 'ENABLED', NULL, '000000', -1, -1, '2026-02-24 20:19:41', -1, '2026-06-22 16:34:29', '0');
+INSERT INTO `mcp_tool_info` VALUES (4, 'query_all_tables', '', 'BUILTIN', 'ENABLED', NULL, '000000', -1, -1, '2026-03-10 21:21:09', -1, '2026-06-22 16:34:29', '0');
+INSERT INTO `mcp_tool_info` VALUES (5, 'execute_sql_query', '', 'BUILTIN', 'ENABLED', NULL, '000000', -1, -1, '2026-03-10 21:21:09', -1, '2026-06-22 16:34:29', '0');
+INSERT INTO `mcp_tool_info` VALUES (6, 'query_table_schema', '', 'BUILTIN', 'ENABLED', NULL, '000000', -1, -1, '2026-03-10 21:21:09', -1, '2026-06-22 16:34:29', '0');
+INSERT INTO `mcp_tool_info` VALUES (7, 'bing-cn-mcp-server', '必应中文联网查询工具,支持实时搜索和网页内容抓取。内置工具:bing_search、fetch_webpage。', 'LOCAL', 'ENABLED', '{\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"bing-cn-mcp\"\n ]\n}\n', '000000', -1, -1, '2026-06-22 16:33:22', -1, '2026-06-22 16:33:22', '0');
+
+-- ----------------------------
+-- Table structure for short_drama_character
+-- ----------------------------
+DROP TABLE IF EXISTS `short_drama_character`;
+CREATE TABLE `short_drama_character` (
+ `id` bigint NOT NULL COMMENT '主键',
+ `project_id` bigint NOT NULL COMMENT '项目ID',
+ `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色名',
+ `aliases` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '别名/称呼(逗号分隔)',
+ `introduction` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '角色介绍(身份、关系、称呼映射)',
+ `role_level` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'B' COMMENT '角色层级:S/A/B/C/D',
+ `gender` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '性别',
+ `age_range` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '年龄段(如:约二十五岁)',
+ `personality_tags` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '性格标签(逗号分隔)',
+ `costume_tier` int NULL DEFAULT 2 COMMENT '服装华丽度1-5',
+ `visual_description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '视觉外貌描述(详细,用于图片生成)',
+ `reference_image_url` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '角色参考图URL',
+ `create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门',
+ `create_by` bigint NULL DEFAULT NULL COMMENT '创建者',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_by` bigint NULL DEFAULT NULL COMMENT '更新者',
+ `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户Id',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_project_id`(`project_id` ASC) USING BTREE,
+ INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '短剧角色表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of short_drama_character
+-- ----------------------------
+INSERT INTO `short_drama_character` VALUES (2075609273630703616, 2075608659739787264, '队医', '', '峨眉队跟队医师,负责队员伤病的现场处理与康复监督。在钰珑脚踝旧伤复发时为其做紧急处理。无特定人际称呼,队员通常只喊「医生」或「队医」。', 'C', '女', '约三十岁', '温柔,细心', 2, '鹅蛋脸线条柔和,双眼皮杏眼明亮有神,小巧挺拔的鼻梁,薄厚适中的嘴唇微抿,柳叶眉自然舒展。乌黑过肩直发扎成利落低马尾,额前碎发自然垂落。身形修长匀称,穿简洁白色短袖Polo衫,左胸有队徽刺绣,搭配卡其色工装长裤和白色运动鞋,腰间斜挎急救小包。', NULL, -1, -1, '2026-07-10 23:53:08', -1, '2026-07-10 23:53:08', 0);
+INSERT INTO `short_drama_character` VALUES (2075609329431724032, 2075608659739787264, '徐风', '徐教练', '峨眉队前任功夫教练,决赛前转投对手东亚商联,成为贯穿剧情的主要对手。曾是双双与钰珑的授业者,后利用对她们的了解反制旧部。被队员普遍称呼为「徐教练」。', 'A', '男', '约三十五岁', '高冷,腹黑,专业,野心', 3, '脸型棱角分明,下颌线条锋利。细长眼型,双眼皮,高挺精致的鼻梁,薄唇平直,眉峰上扬的剑眉浓黑有型,右眼尾点缀一颗小痣。乌黑短发以利落背头后梳,露出饱满额头,发质柔顺服帖。身形修长,高挑匀称。身穿深灰色高支羊毛西装,剪裁修身,肩线平直,内搭黑色精纺高领毛衣,下身同色西裤线条流畅,脚著黑色牛津皮鞋。鼻梁上架一副极细金属框运动墨镜,左手腕佩戴银色纤薄腕表。', NULL, -1, -1, '2026-07-10 23:53:22', -1, '2026-07-10 23:53:22', 0);
+INSERT INTO `short_drama_character` VALUES (2075609380031807488, 2075608659739787264, '钰珑', '', '峨眉女足主力前锋,曾深度依赖徐风传授的功夫射门技术,后在双双引导下融入团队体系。与双双为挚友,视徐风为前恩师后对手。被双双及其他队友直呼「钰珑」。', 'A', '女', '约二十四岁', '直爽,冲动,坚韧,热情', 2, '钰珑生着一张轮廓分明的瓜子脸,浓黑剑眉斜抬,衬出几分不驯。眼形偏窄的杏眼微微上挑,单眼皮收紧眼尾,转折处利落带锋。鼻梁小巧挺直,嘴唇薄厚适中,下颌角附近有一道浅淡旧伤痕。一头乌黑长发高高束成马尾,额前碎发桀骜翘起,发尾带着自然微卷。身形修长结实,肩背紧绷,常年奔跑的线条紧致流畅。她穿着白色速干运动背心、深灰色运动短裤,脚踩抓地强劲的黑色跑鞋。右脚踝始终缠着防护绷带,步态间略带拖沓,却像随时要蹬地冲出。手腕戴一只简约的黑色运动手表。', NULL, -1, -1, '2026-07-10 23:53:34', -1, '2026-07-10 23:53:34', 0);
+INSERT INTO `short_drama_character` VALUES (2075609601688190976, 2075608659739787264, '双双', '', '故事女主角,峨眉女足队长,球队战术核心与精神领袖。前锋钰珑的队友兼好友,前教练徐风曾执教的队员。被队友称呼为「队长」,被钰珑直接叫名字「双双」。', 'S', '女', '约二十五岁', '冷静,果断,温柔,坚毅', 2, '瓜子脸,线条利落分明。一双眼裂纤长的丹凤眼,眼尾如燕尾般锐利上扬,内眼角尖细,双眼皮折痕深刻清晰,注视时自带压迫感。鼻梁挺直高耸,鼻翼收窄,鼻尖精致小巧。双唇薄而轮廓分明,上唇弓形,下唇微微内收。眉骨高隆,眉形为天然剑眉,眉头略粗,眉峰微挑,眉尾收得细长利落。鼻梁中段偏左有一颗极浅小痣。一头乌黑长发在脑后高高束成利落马尾,扎紧于顶骨后方,用黑色弹力绳固定,发丝柔顺垂坠,发尾齐整落至肩胛骨下缘,额前无一丝刘海,露出光洁额头。体型修长而匀称,身姿高挑挺拔。上身穿一件白色速干圆领运动短袖T恤,面料带有微透气网眼,外罩一件深蓝色立领轻型教练夹克,拉链半开,袖口设有魔术贴收束,左臂佩戴红色弹性针织队长袖标,表面印有白色「CAPTAIN」字样。下身为黑色弹力紧身运动长裤,高腰设计,膝盖处有拼接剪裁,脚踝处有短拉链。脚蹬一双白色轻量跑步鞋,鞋面为透气网布拼接合成革,鞋带系紧,鞋底防滑纹理清晰。左手腕佩戴一块简约黑色运动电子手表。', NULL, -1, -1, '2026-07-10 23:54:27', -1, '2026-07-10 23:54:27', 0);
+INSERT INTO `short_drama_character` VALUES (2077008099927412736, 2077007721974484992, '百货经理', '经理', '百货公司经理,在工商检查时出现,对小明提出的信息平台方案表示认可并推动放行。角色身份为商业系统干部,被小明称为「经理」。', 'C', '男', '约四十岁', '务实,深谙利益,精明', 3, '方形脸,浓黑剑眉,双眼皮,眼神锐利,鼻梁高挺,嘴唇线条分明。乌黑三七分背头,整齐服帖。身形匀称,身高适中。身穿藏青色修身西装外套,内搭白色衬衫,深灰色西裤,黑色系带皮鞋,手腕佩戴简约钢带手表。', NULL, -1, -1, '2026-07-14 20:31:35', -1, '2026-07-14 20:31:35', 0);
+INSERT INTO `short_drama_character` VALUES (2077008101332504576, 2077007721974484992, '老陈', '陈厂长', '工厂厂长,小明的关键支持者和合作伙伴。性格谨慎但敢于冒险,信任小明的能力。被小明称为「陈厂长」,被工人和下属称为「厂长」或「老陈」。', 'A', '男', '约五十岁', '谨慎,务实,有魄力,正直', 2, '长方脸型,轮廓分明,额间有浅横纹,颧骨平直。浓眉微斜,眉尾稍疏,单眼皮细长眼,眼窝微陷,目光专注。鼻梁高直,鼻翼内收,唇形薄而线条清晰,下唇中央有浅凹痕。下巴方圆,无明显痣疤。发色花白,短发偏分,发质硬而蓬松,略见鬓角银丝。身形匀称中等,肩背挺直。上身着灰色中山装,领口紧扣齐整,左下口袋别一支钢笔。下装深灰西裤,裤线笔直,脚穿黑色系带皮鞋,鞋面光亮。无多余配饰。', NULL, -1, -1, '2026-07-14 20:31:35', -1, '2026-07-14 20:31:35', 0);
+INSERT INTO `short_drama_character` VALUES (2077008104104939520, 2077007721974484992, '小明', '无', '故事核心主角,从2025年穿越回1985年的重生者。原本是50岁的失意中年,穿越后成为年轻工人。老陈的合作伙伴,被团队成员称为「小明」或「同志」,被老陈直呼「小明」。', 'S', '男', '约二十五岁(实际心理年龄五十岁)', '远见,执着,果断,坚毅', 2, '轮廓分明的瓜子脸,下颌线条利落。深邃的双眼皮眼睛眼型偏长,目光沉静;鼻梁高挺笔直;嘴唇厚薄适中,唇峰清晰;浓密的剑眉斜飞入鬓。右侧眉尾处一颗小痣。发色乌黑,及耳的长度微卷自然蓬松,额前碎发刘海随意散落。身形修长挺拔,身高约一米七八。穿着简约白色棉质衬衫,袖口卷至小臂,搭配深灰色直筒长裤与黑色帆布鞋。', NULL, -1, -1, '2026-07-14 20:31:36', -1, '2026-07-14 20:31:36', 0);
+
+-- ----------------------------
+-- Table structure for short_drama_character_appearance
+-- ----------------------------
+DROP TABLE IF EXISTS `short_drama_character_appearance`;
+CREATE TABLE `short_drama_character_appearance` (
+ `id` bigint NOT NULL COMMENT '主键',
+ `character_id` bigint NOT NULL COMMENT '角色ID',
+ `appearance_index` int NOT NULL DEFAULT 0 COMMENT '形象序号(0=主形象)',
+ `change_reason` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '初始形象' COMMENT '变化原因',
+ `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '形象视觉描述',
+ `reference_image_url` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '形象参考图URL',
+ `create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门',
+ `create_by` bigint NULL DEFAULT NULL COMMENT '创建者',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_by` bigint NULL DEFAULT NULL COMMENT '更新者',
+ `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户Id',
+ `image_urls` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '生成图片URL列表(JSON数组)',
+ `image_descriptions` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '每张图片对应的提示词(JSON数组)',
+ `selected_image_index` int NULL DEFAULT 0 COMMENT '当前选中的图片索引',
+ `previous_image_urls` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '上一轮图片URL列表(撤销用,JSON数组)',
+ `previous_descriptions` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '上一轮提示词列表(撤销用,JSON数组)',
+ `voice` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '音色名(如 zh_male_taocheng_uranus_bigtts),用于该形象对白配音',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_character_appearance`(`character_id` ASC, `appearance_index` ASC) USING BTREE,
+ INDEX `idx_character_id`(`character_id` ASC) USING BTREE,
+ INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '短剧角色子形象表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of short_drama_character_appearance
+-- ----------------------------
+INSERT INTO `short_drama_character_appearance` (`id`, `character_id`, `appearance_index`, `change_reason`, `description`, `reference_image_url`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`, `image_urls`, `image_descriptions`, `selected_image_index`, `previous_image_urls`, `previous_descriptions`) VALUES (2075609273836224512, 2075609273630703616, 0, '初始形象', '鹅蛋脸线条柔和,双眼皮杏眼明亮有神,小巧挺拔的鼻梁,薄厚适中的嘴唇微抿,柳叶眉自然舒展。乌黑过肩直发扎成利落低马尾,额前碎发自然垂落。身形修长匀称,穿简洁白色短袖Polo衫,左胸有队徽刺绣,搭配卡其色工装长裤和白色运动鞋,腰间斜挎急救小包。', NULL, -1, -1, '2026-07-10 23:53:08', -1, '2026-07-10 23:53:08', 0, NULL, NULL, 0, NULL, NULL);
+INSERT INTO `short_drama_character_appearance` (`id`, `character_id`, `appearance_index`, `change_reason`, `description`, `reference_image_url`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`, `image_urls`, `image_descriptions`, `selected_image_index`, `previous_image_urls`, `previous_descriptions`) VALUES (2075609329570136064, 2075609329431724032, 0, '初始形象', '脸型棱角分明,下颌线条锋利。细长眼型,双眼皮,高挺精致的鼻梁,薄唇平直,眉峰上扬的剑眉浓黑有型,右眼尾点缀一颗小痣。乌黑短发以利落背头后梳,露出饱满额头,发质柔顺服帖。身形修长,高挑匀称。身穿深灰色高支羊毛西装,剪裁修身,肩线平直,内搭黑色精纺高领毛衣,下身同色西裤线条流畅,脚著黑色牛津皮鞋。鼻梁上架一副极细金属框运动墨镜,左手腕佩戴银色纤薄腕表。', NULL, -1, -1, '2026-07-10 23:53:22', -1, '2026-07-10 23:53:22', 0, NULL, NULL, 0, NULL, NULL);
+INSERT INTO `short_drama_character_appearance` (`id`, `character_id`, `appearance_index`, `change_reason`, `description`, `reference_image_url`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`, `image_urls`, `image_descriptions`, `selected_image_index`, `previous_image_urls`, `previous_descriptions`) VALUES (2075609380207968256, 2075609380031807488, 0, '初始形象', '钰珑生着一张轮廓分明的瓜子脸,浓黑剑眉斜抬,衬出几分不驯。眼形偏窄的杏眼微微上挑,单眼皮收紧眼尾,转折处利落带锋。鼻梁小巧挺直,嘴唇薄厚适中,下颌角附近有一道浅淡旧伤痕。一头乌黑长发高高束成马尾,额前碎发桀骜翘起,发尾带着自然微卷。身形修长结实,肩背紧绷,常年奔跑的线条紧致流畅。她穿着白色速干运动背心、深灰色运动短裤,脚踩抓地强劲的黑色跑鞋。右脚踝始终缠着防护绷带,步态间略带拖沓,却像随时要蹬地冲出。手腕戴一只简约的黑色运动手表。', NULL, -1, -1, '2026-07-10 23:53:34', -1, '2026-07-10 23:53:34', 0, NULL, NULL, 0, NULL, NULL);
+INSERT INTO `short_drama_character_appearance` (`id`, `character_id`, `appearance_index`, `change_reason`, `description`, `reference_image_url`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`, `image_urls`, `image_descriptions`, `selected_image_index`, `previous_image_urls`, `previous_descriptions`) VALUES (2075609601822408704, 2075609601688190976, 0, '初始形象', '瓜子脸,线条利落分明。一双眼裂纤长的丹凤眼,眼尾如燕尾般锐利上扬,内眼角尖细,双眼皮折痕深刻清晰,注视时自带压迫感。鼻梁挺直高耸,鼻翼收窄,鼻尖精致小巧。双唇薄而轮廓分明,上唇弓形,下唇微微内收。眉骨高隆,眉形为天然剑眉,眉头略粗,眉峰微挑,眉尾收得细长利落。鼻梁中段偏左有一颗极浅小痣。一头乌黑长发在脑后高高束成利落马尾,扎紧于顶骨后方,用黑色弹力绳固定,发丝柔顺垂坠,发尾齐整落至肩胛骨下缘,额前无一丝刘海,露出光洁额头。体型修长而匀称,身姿高挑挺拔。上身穿一件白色速干圆领运动短袖T恤,面料带有微透气网眼,外罩一件深蓝色立领轻型教练夹克,拉链半开,袖口设有魔术贴收束,左臂佩戴红色弹性针织队长袖标,表面印有白色「CAPTAIN」字样。下身为黑色弹力紧身运动长裤,高腰设计,膝盖处有拼接剪裁,脚踝处有短拉链。脚蹬一双白色轻量跑步鞋,鞋面为透气网布拼接合成革,鞋带系紧,鞋底防滑纹理清晰。左手腕佩戴一块简约黑色运动电子手表。', NULL, -1, -1, '2026-07-10 23:54:27', -1, '2026-07-10 23:54:27', 0, NULL, NULL, 0, NULL, NULL);
+INSERT INTO `short_drama_character_appearance` (`id`, `character_id`, `appearance_index`, `change_reason`, `description`, `reference_image_url`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`, `image_urls`, `image_descriptions`, `selected_image_index`, `previous_image_urls`, `previous_descriptions`) VALUES (2077008100070019072, 2077008099927412736, 0, '初始形象', '方形脸,浓黑剑眉,双眼皮,眼神锐利,鼻梁高挺,嘴唇线条分明。乌黑三七分背头,整齐服帖。身形匀称,身高适中。身穿藏青色修身西装外套,内搭白色衬衫,深灰色西裤,黑色系带皮鞋,手腕佩戴简约钢带手表。', 'https://atlas-media.oss-us-west-1.aliyuncs.com/images/dd7454cd25a6486aa5c7c3f8c7085041-3742113260bb4ee9.jpg', -1, -1, '2026-07-14 20:31:35', 1, '2026-07-14 20:38:50', 0, '[\"https://atlas-media.oss-us-west-1.aliyuncs.com/images/dd7454cd25a6486aa5c7c3f8c7085041-3742113260bb4ee9.jpg\"]', '[\"真实电影级画面质感,真实现实场景,色彩饱满通透,画面干净精致,真实感,character design sheet, multiple views reference sheet, front view / side view / back view full body, clean white background, no props, no text. 方形脸,浓黑剑眉,双眼皮,眼神锐利,鼻梁高挺,嘴唇线条分明。乌黑三七分背头,整齐服帖。身形匀称,身高适中。身穿藏青色修身西装外套,内搭白色衬衫,深灰色西裤,黑色系带皮鞋,手腕佩戴简约钢带手表。。角色设定图,画面分为左右两个区域:【左侧区域】占约1/3宽度,是角色的正面特写(完整正脸,最具辨识度的正面形态);【右侧区域】占约2/3宽度,是角色三视图横向排列(从左到右依次为:正面全身、侧面全身、背面全身),三视图高度一致。纯白色背景,无其他元素。\"]', 0, NULL, NULL);
+INSERT INTO `short_drama_character_appearance` (`id`, `character_id`, `appearance_index`, `change_reason`, `description`, `reference_image_url`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`, `image_urls`, `image_descriptions`, `selected_image_index`, `previous_image_urls`, `previous_descriptions`) VALUES (2077008101487693824, 2077008101332504576, 0, '初始形象', '长方脸型,轮廓分明,额间有浅横纹,颧骨平直。浓眉微斜,眉尾稍疏,单眼皮细长眼,眼窝微陷,目光专注。鼻梁高直,鼻翼内收,唇形薄而线条清晰,下唇中央有浅凹痕。下巴方圆,无明显痣疤。发色花白,短发偏分,发质硬而蓬松,略见鬓角银丝。身形匀称中等,肩背挺直。上身着灰色中山装,领口紧扣齐整,左下口袋别一支钢笔。下装深灰西裤,裤线笔直,脚穿黑色系带皮鞋,鞋面光亮。无多余配饰。', 'https://atlas-media.oss-us-west-1.aliyuncs.com/images/4729daf662de42c0a3472bc05043529c-01a8aaf57a08ea21.jpg', -1, -1, '2026-07-14 20:31:35', 1, '2026-07-14 20:38:50', 0, '[\"https://atlas-media.oss-us-west-1.aliyuncs.com/images/4729daf662de42c0a3472bc05043529c-01a8aaf57a08ea21.jpg\"]', '[\"真实电影级画面质感,真实现实场景,色彩饱满通透,画面干净精致,真实感,character design sheet, multiple views reference sheet, front view / side view / back view full body, clean white background, no props, no text. 长方脸型,轮廓分明,额间有浅横纹,颧骨平直。浓眉微斜,眉尾稍疏,单眼皮细长眼,眼窝微陷,目光专注。鼻梁高直,鼻翼内收,唇形薄而线条清晰,下唇中央有浅凹痕。下巴方圆,无明显痣疤。发色花白,短发偏分,发质硬而蓬松,略见鬓角银丝。身形匀称中等,肩背挺直。上身着灰色中山装,领口紧扣齐整,左下口袋别一支钢笔。下装深灰西裤,裤线笔直,脚穿黑色系带皮鞋,鞋面光亮。无多余配饰。。角色设定图,画面分为左右两个区域:【左侧区域】占约1/3宽度,是角色的正面特写(完整正脸,最具辨识度的正面形态);【右侧区域】占约2/3宽度,是角色三视图横向排列(从左到右依次为:正面全身、侧面全身、背面全身),三视图高度一致。纯白色背景,无其他元素。\"]', 0, NULL, NULL);
+INSERT INTO `short_drama_character_appearance` (`id`, `character_id`, `appearance_index`, `change_reason`, `description`, `reference_image_url`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`, `image_urls`, `image_descriptions`, `selected_image_index`, `previous_image_urls`, `previous_descriptions`) VALUES (2077008104272711680, 2077008104104939520, 0, '初始形象', '轮廓分明的瓜子脸,下颌线条利落。深邃的双眼皮眼睛眼型偏长,目光沉静;鼻梁高挺笔直;嘴唇厚薄适中,唇峰清晰;浓密的剑眉斜飞入鬓。右侧眉尾处一颗小痣。发色乌黑,及耳的长度微卷自然蓬松,额前碎发刘海随意散落。身形修长挺拔,身高约一米七八。穿着简约白色棉质衬衫,袖口卷至小臂,搭配深灰色直筒长裤与黑色帆布鞋。', 'https://atlas-media.oss-us-west-1.aliyuncs.com/images/aab75b6b-865d-4825-8eee-9e3a45ccec62.png', -1, -1, '2026-07-14 20:31:36', 1, '2026-07-14 20:38:50', 0, '[\"https://atlas-media.oss-us-west-1.aliyuncs.com/images/aab75b6b-865d-4825-8eee-9e3a45ccec62.png\"]', '[\"真实电影级画面质感,真实现实场景,色彩饱满通透,画面干净精致,真实感,character design sheet, multiple views reference sheet, front view / side view / back view full body, clean white background, no props, no text. 轮廓分明的瓜子脸,下颌线条利落。深邃的双眼皮眼睛眼型偏长,目光沉静;鼻梁高挺笔直;嘴唇厚薄适中,唇峰清晰;浓密的剑眉斜飞入鬓。右侧眉尾处一颗小痣。发色乌黑,及耳的长度微卷自然蓬松,额前碎发刘海随意散落。身形修长挺拔,身高约一米七八。穿着简约白色棉质衬衫,袖口卷至小臂,搭配深灰色直筒长裤与黑色帆布鞋。。角色设定图,画面分为左右两个区域:【左侧区域】占约1/3宽度,是角色的正面特写(完整正脸,最具辨识度的正面形态);【右侧区域】占约2/3宽度,是角色三视图横向排列(从左到右依次为:正面全身、侧面全身、背面全身),三视图高度一致。纯白色背景,无其他元素。\"]', 0, NULL, NULL);
+
+-- ----------------------------
+-- Table structure for short_drama_location
+-- ----------------------------
+DROP TABLE IF EXISTS `short_drama_location`;
+CREATE TABLE `short_drama_location` (
+ `id` bigint NOT NULL COMMENT '主键',
+ `project_id` bigint NOT NULL COMMENT '项目ID',
+ `name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '场景名(如:客厅_白天)',
+ `summary` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '场景简要说明',
+ `has_crowd` tinyint(1) NULL DEFAULT 0 COMMENT '是否有背景人群',
+ `crowd_description` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '背景人群描述',
+ `available_slots` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '可站位置列表(JSON数组)',
+ `descriptions` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '场景描述列表(JSON数组,3条差异化描述)',
+ `reference_image_url` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '场景全景参考图URL',
+ `create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门',
+ `create_by` bigint NULL DEFAULT NULL COMMENT '创建者',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_by` bigint NULL DEFAULT NULL COMMENT '更新者',
+ `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户Id',
+ `image_urls` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '生成图片URL列表(JSON数组)',
+ `image_descriptions` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '每张图片对应的提示词(JSON数组)',
+ `selected_image_index` int NULL DEFAULT 0 COMMENT '当前选中的图片索引',
+ `previous_image_urls` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '上一轮图片URL列表(撤销用,JSON数组)',
+ `previous_descriptions` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '上一轮提示词列表(撤销用,JSON数组)',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_project_id`(`project_id` ASC) USING BTREE,
+ INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '短剧场景表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of short_drama_location
+-- ----------------------------
+INSERT INTO `short_drama_location` VALUES (2075609601935654912, 2075608659739787264, '峨眉队训练基地_傍晚', '金色夕阳下的足球训练场,质朴的草地与球门构成核心训练区', 1, '远处有模糊的队员正在进行抢圈练习,人影被拉长', '[\"土场中央中圈开球点的位置\",\"远端球门右侧角旗区附近的位置\",\"场边简易长条凳与战术板之间的空地\"]', '[\"「峨眉队训练基地傍晚」傍晚的余晖将整片土场染成浓郁的金色,宽广的球场向远处延伸,边界由低矮的铁丝围栏框定。左侧设置一座标准尺寸的球门,白色球网微微颤动,右侧对等位置的球门轮廓在逆光中略显模糊。四周几盏简易训练灯尚未点亮,整个空间被暖调的自然光笼罩,光从西侧斜射过来,将球门阴影长长地拖在东侧草坪上。中圈弧线清晰可见,两侧边线外留有宽敞的跑动通道,场边零散放着几个训练标志盘和水瓶。\",\"「峨眉队训练基地傍晚」土质训练场开阔而硬朗,天空半边橙红半边浅紫。镜头从底线角球区拉开,可以看到两座球门、两侧边线以及远处低矮平房的轮廓。西边的斜阳穿过球门网,在泥土地上投出网格状的影子。场地中央被踩实的黄土露出些许草根,四周则还留着稀疏的绿草。场边一侧摆着一条木质长凳,旁边立着一块可移动的战术白板,为这片朴素的空间增添了几分专业气息。空旷的球场除了风声,只剩远处模糊的呼喝与足球撞击的闷响。\",\"「峨眉队训练基地傍晚」广角俯瞰下,整个训练基地被夕阳包裹,像一座独立于时间之外的金色擂台。两座标准足球门遥相对望,球门后的拦网高而完整。中圈向外辐射,中轴线上的草稀而坚实。光线从画面右侧灌入,将左侧的球门区域照得最亮,右侧则稍稍藏在阴影里。场边零散堆放着几件训练背心和几只足球,没有围观的观众,只有空间本身在等待下一场奔跑。远处的训练队员身影模糊成小小的剪影,在远处半场进行着无声的抢圈游戏。\"]', NULL, -1, -1, '2026-07-10 23:54:27', -1, '2026-07-10 23:54:27', 0, NULL, NULL, 0, NULL, NULL);
+INSERT INTO `short_drama_location` VALUES (2075609601960820736, 2075608659739787264, '球队更衣室_夜', '赛前赛后使用的长方形更衣室,木凳、储物柜和散落的球衣构成封闭空间', 0, '', '[\"中央长条木凳前方的过道空间\",\"靠近门口储物柜与墙壁之间的角落\",\"另一侧更衣柜前空出的站立区域\"]', '[\"「球队更衣室夜」封闭的长方形房间,天花板上的日光灯管发出冷白色的光,照亮了整间屋子。三面墙壁装着浅绿色金属储物柜,柜门大多虚掩或敞开,里面挂着几件换下的球衣,左侧墙壁上挂着一块白板,上面还留着隐约的战术标记。房间中央横置一条厚重的长条木凳,凳面磨损光滑,周围散落着几双球鞋和护腿板。光从顶部均匀洒下,地面是深灰色的防滑地胶,靠门的角落扔着几件绿色训练背心。门口一方空间相对空阔,连着一条通往淋浴区的走廊。\",\"「球队更衣室夜」灯光通明,更衣室被冷色调充满。正对面的储物柜墙几乎占据了整个视野,柜子编号清晰,其中几个柜门开着,球衣搭在柜沿外边。中央的木凳长度几乎横贯房间,凳下塞着几个运动包。左侧墙角立着一面战术白板,笔迹被擦去大半,残留的弧线隐约可见。右侧是另一排储物柜,柜门反光出冷白的灯管倒影。整个空间静静封闭,只有头顶排风扇发出轻微的嗡鸣,地面清洁但带有些许草屑,门口的通道空出明显的站立空间。\",\"「球队更衣室夜」紧凑但有序的球队更衣室,三面排列着标准体育储物柜,中间一条厚木长凳将空间划为两半。日光灯从天花中央铺开,柜门的金属边框反射出明亮光线。左侧柜组上方的墙壁挂着一面简朴的电子钟,时间显示在晚间。长凳上扔着一双刚脱下的球袜,地板在灯下呈现出深灰色橡胶纹理。靠门口的区域相对整洁,空出的地面足够两人并肩站立,那一侧的门把手还带些微使用过的痕迹。整个房间弥漫着一种刚结束训练的沉默,等待被下一句话打破。\"]', NULL, -1, -1, '2026-07-10 23:54:27', -1, '2026-07-10 23:54:27', 0, NULL, NULL, 0, NULL, NULL);
+INSERT INTO `short_drama_location` VALUES (2075609602027929600, 2075608659739787264, '训练场_日', '白天的足球训练场,阳光充足,设有球门、绳梯和战术布置区域,空旷而专注', 0, '', '[\"禁区弧顶正对球门的罚球点附近\",\"中圈开球点周围的开阔区域\",\"场边摆放战术板与训练器材的教练区域\"]', '[\"「训练场日」白日下的标准足球场,草坪修剪整齐,浓绿色向远处铺展。遥相对望的两座白色球门在午后阳光下十分醒目,近端球门的网子绑得紧实。场地中央的中圈白线清晰,禁区线、边线等标记一丝不苟。右侧边线外摆着一架绳梯和几个锥形标志桶,还有一块战术白板支在折叠支架上。阳光从偏南方向照射,将球门立柱的影子投在草皮上。整个训练场除了远处围栏外偶尔经过的人影,场内一片空旷,只剩下训练器材静待使用。\",\"「训练场日」晴朗天气下,训练场被明亮的光线填满,没有观众,只有训练的味道。从底线角度望过去,纵深极强:近处角球弧的弧线、中圈、远方另一侧球门的全景尽收眼底。场地偏左的位置安放着一组红白相间的训练桩,右侧边线附近零星散落着足球。光线柔和地从画面左上方射入,草尖泛出微光。战术白板立在阴凉一侧,上面画着交叉跑位的弧线和点位标记,旁边放着一只医疗箱和几瓶喷雾,这方空间留有足够的站立和讲解余地。\",\"「训练场日」俯瞰的训练场呈现出清晰的几何线条,白色的场地标记在阳光下异常鲜明。两座球门对称分布于两端,禁区的矩形线条和中圈圆环完整。靠近远端球门的一侧,绳梯铺在阴影与阳光的交界处,橙色的标志碟在绿色背景上跳跃。画面中没有风吹动的痕迹,只有光从南偏西的方向大面积洒下,使得左侧球门区域更亮,右侧微暗。边线外的教练区空着,战术板上的弧线图被画得用力,旁边几件荧光训练背心堆在地上,等着一场无声的预演。\"]', NULL, -1, -1, '2026-07-10 23:54:27', -1, '2026-07-10 23:54:27', 0, NULL, NULL, 0, NULL, NULL);
+INSERT INTO `short_drama_location` VALUES (2075609602099232768, 2075608659739787264, '亚冠决赛球场_夜', '盛大的亚冠决赛夜球场,灯光璀璨,看台满座,记分牌显示着紧张的下半场比分', 1, '看台上密密麻麻的观众,挥舞着旗帜和围巾,形成人浪与声浪', '[\"中圈弧附近的开阔地带\",\"禁区外正对球门的任意球主罚点\",\"靠近客队教练区一侧的边线区域\"]', '[\"「亚冠决赛球场夜」灯火如昼的巨型体育场,草皮在夜间照明下泛出整齐的墨绿。四面看台坐满了观众,数万人的衣色和旗帜连成涌动的人海,模糊的面孔只看得见张开的嘴巴和举起的围巾。巨大的电子记分牌高悬于一侧看台上方,红色的数字显示下半场72分钟,比分暂为悬殊的落后。两座球门背后,摄影记者长枪短炮已对准禁区。光线来自顶棚密集的灯阵,无死角照亮整个场地,使场边的教练区、替补席和第四官员席都清晰可见。草地中圈弧线被踩得微脏,比赛正进入最窒息的时间。\",\"「亚冠决赛球场夜」从高空俯瞰,这座宏大的足球圣殿被灯光分割成无数块面。绿茵场居于正中,被一圈暗红色的跑道环绕,再往外是层层叠叠的看台,人群如密织的织物铺满每一块区域。左侧球门后方的看台爆发出一片摇动的旗海,右侧观众席则因紧张而微微前倾。记分牌上,时间与比分在夜色中极其刺目。教练区空空地等着下一个指令,边线旁的摄影机摇臂缓缓移动。光从顶棚巨大的灯架倾泻而下,在草皮上几乎没有影子,整个赛场明如白昼,气氛却重如铅水。\",\"「亚冠决赛球场夜」镜头从角球区低角度向上拉升,首先看到近处被蹭掉几条草痕的角旗杆,然后中景闯入密实的禁区线,接着整座球场的壮阔扑面而来。看台组成一道陡峭的人墙,无数手臂在挥舞,助威声浪似有形物质充满空气。正对面远端球门上方,记分牌的数字亮得发烫,时间在流逝,比分残酷。教练区域设置在中线旁,简易的白色画线框内放着水壶和战术纸条。球场灯光从四面八方浇筑,使得场上即将发生的一切都无从遁形,只留下宽广的草皮等待下一脚触球。\"]', NULL, -1, -1, '2026-07-10 23:54:27', -1, '2026-07-10 23:54:27', 0, NULL, NULL, 0, NULL, NULL);
+INSERT INTO `short_drama_location` VALUES (2075609602162147328, 2075608659739787264, '球场_伤停补时阶段', '同片决赛球场,但已进入伤停补时,气氛沸腾至顶点,人墙与禁区形成焦点', 1, '全场观众几乎全部站立,紧张地注视着场内,呐喊与屏息交替', '[\"禁区弧前方任意球人墙后的区域\",\"中圈附近等待反击的空旷地带\",\"对方球门远角一侧的包抄路线区域\"]', '[\"「球场伤停补时阶段」伤停补时的灯光仿佛更加灼热,整个体育场被推至沸点。草坪上,禁区前沿排着紧密的人墙,球员们肩并着肩,手臂护住胸前,形成一道移动的屏障。远处的球门在这一刻显得格外宽阔,门柱的影子硬朗地打在草皮上。看台上所有观众都站了起来,无数的身影形成一圈颤抖的轮廓,模糊的旗帜在夜风中猎猎作响。记分牌上的数字显示着3:3的平局,时间刻度停在伤停补时。光从顶棚强力射出,将禁区弧顶的罚球点照得如同舞台中央,四周的空气几乎凝固。\",\"「球场伤停补时阶段」广角定格在球门与禁区之间,人墙严阵以待,守门员在门线前压低重心,整座体育场的视线都聚焦于罚球点。左侧看台无声地亮起一片手机灯光,右侧球迷则咬住围巾。草地被踩踏出无数重叠的足迹,尤其是禁区线附近草皮翻起几道浅痕。球门右上角网窝静止,等待撞击。教练区空无一人,但第四官员举起的电子牌清晰可辨。光从正上方与左右顶棚交织投下,把每一个远近空间填满,唯有远端的底线角旗处在微微的阴影中,为即将可能发生的反抢留出视觉余地。\",\"「球场伤停补时阶段」补时中的决赛草场弥漫着接近终局的肃杀感。中圈到禁区弧这一段区域被无形的手攥紧,人墙背后,球门远角的空间仿佛在主动收缩。看台化为巨大的黑红色背景,点缀着无数晃动的小点。球场中央地带相对空虚,只有几名中场球员的站位拉开宽度,形成随时可以冲刺的空档。远处的角旗区和边线在强烈灯光下泛白,教练区的白线边界依旧清晰,战术纸条散落在地。这个广阔的空间里,下一个呼吸就可能决定所有。顶光无遮无拦,把即将落下的射门路线照得坦坦荡荡。\"]', NULL, -1, -1, '2026-07-10 23:54:27', -1, '2026-07-10 23:54:27', 0, NULL, NULL, 0, NULL, NULL);
+INSERT INTO `short_drama_location` VALUES (2077008104339820544, 2077007721974484992, '现代办公室_夜', '深夜的现代办公室,电脑屏幕亮光,桌面杂乱,电水壶和插座位于角落。', 0, '', '[\"办公桌前椅子的正前方位置\",\"门口内侧靠墙的空地\",\"电水壶倾倒处的桌子左侧空地\"]', '[\"「现代办公室_夜」深夜的办公室,空间约二十平米,深灰色地毯覆盖地面,左侧是两扇玻璃窗,窗外城市霓虹灯隐约。右侧墙壁悬挂企业标语,下方是文件柜。中央一张深色办公桌,电脑屏幕为唯一光源,桌面散落纸张和水杯。天花板荧光灯未开,光线从电脑屏幕向右前方散射。前景桌子右侧有空地,左侧靠窗也有站立空间。\",\"「现代办公室_夜」一个中等规模的现代办公室,后墙整面白色,中央挂钟指针指向11点。左侧墙壁有白色百叶窗,光线从窗外微光透入与电脑屏幕蓝光混合。右侧墙壁是嵌入式书架,书本整齐排列。办公桌位于房间中央偏后,桌上一台显示器、电水壶、凌乱文件。天花板吊灯未亮,整体光线昏暗。门口处有一块可站人区域,桌子左侧也有空位。\",\"「现代办公室_夜」约二十平米的封闭办公室,三面墙壁可见:正面墙有白色防火板,左侧墙为玻璃隔断(窗外黑色夜空),右侧墙为木质护墙板。地面铺深色橡胶地板。办公桌位于房间中央稍靠右,桌上电脑亮着,电水壶倒在桌边,插座位在桌下墙角。天花板中央有方形灯槽但未开灯。门口与桌子之间有两米见方的空白区域,可以站立一人;窗户左侧也有约一米宽的通道。\"]', 'https://atlas-media.oss-us-west-1.aliyuncs.com/images/e927b16c08d64b72a0039fcc6232c626-d9b1460b47849a88.jpg', -1, -1, '2026-07-14 20:31:36', 1, '2026-07-14 20:38:50', 0, '[\"https://atlas-media.oss-us-west-1.aliyuncs.com/images/e927b16c08d64b72a0039fcc6232c626-d9b1460b47849a88.jpg\"]', '[\"宽广空间全景,[\\\"「现代办公室_夜」深夜的办公室,空间约二十平米,深灰色地毯覆盖地面,左侧是两扇玻璃窗,窗外城市霓虹灯隐约。右侧墙壁悬挂企业标语,下方是文件柜。中央一张深色办公桌,电脑屏幕为唯一光源,桌面散落纸张和水杯。天花板荧光灯未开,光线从电脑屏幕向右前方散射。前景桌子右侧有空地,左侧靠窗也有站立空间。\\\",\\\"「现代办公室_夜」一个中等规模的现代办公室,后墙整面白色,中央挂钟指针指向11点。左侧墙壁有白色百叶窗,光线从窗外微光透入与电脑屏幕蓝光混合。右侧墙壁是嵌入式书架,书本整齐排列。办公桌位于房间中央偏后,桌上一台显示器、电水壶、凌乱文件。天花板吊灯未亮,整体光线昏暗。门口处有一块可站人区域,桌子左侧也有空位。\\\",\\\"「现代办公室_夜」约二十平米的封闭办公室,三面墙壁可见:正面墙有白色防火板,左侧墙为玻璃隔断(窗外黑色夜空),右侧墙为木质护墙板。地面铺深色橡胶地板。办公桌位于房间中央稍靠右,桌上电脑亮着,电水壶倒在桌边,插座位在桌下墙角。天花板中央有方形灯槽但未开灯。门口与桌子之间有两米见方的空白区域,可以站立一人;窗户左侧也有约一米宽的通道。\\\"],禁止出现任何角色,纯背景板真实电影级画面质感,真实现实场景,色彩饱满通透,画面干净精致,真实感\"]', 0, NULL, NULL);
+INSERT INTO `short_drama_location` VALUES (2077008104394346496, 2077007721974484992, '小巷_日_1985', '八十年代老式小巷,石板路面,墙上有红色标语,二八自行车靠在墙边。', 0, '', '[\"巷口地面中央位置\",\"右侧墙边二八自行车旁的空地\",\"左侧墙标语下方的台阶处\"]', '[\"「小巷_日_1985」一条狭窄的老式小巷,宽约三米,两侧是青砖老墙,墙高约四米,墙面斑驳。右侧墙上用红漆写着「时间就是金钱」的标语,字迹清晰。地面是水泥路面,有些裂缝。巷口方向有一辆黑色的二八自行车斜靠在墙边。光线从巷口一端射入,形成明暗对比。巷子中央地面可以站立,左侧墙根下也有约一米宽的通道。\",\"「小巷_日_1985」巷子长约五十米,两端可见开阔。左侧墙壁爬满半枯的爬山虎,右墙每隔几米有木质门窗(紧闭)。地面是青石板铺成,略有水渍。巷子尽头有一棵老槐树伸出墙头。阳光从头顶偏左照下,在地面投下窗格阴影。巷口方向有一辆老式二八自行车,车把挂着布包。巷子中央空旷处可站人,右侧自行车旁也有空间。\",\"「小巷_日_1985」宽度不足三米的小巷,两侧墙壁均用灰砖砌成,左墙上有模糊的「工业学大庆」标语残迹,右墙新刷了白色石灰。地面为水泥抹平,中央微微隆起。巷口处堆着几个空木箱。远处可见巷子拐角,墙上挂着一个老式电表箱。光线从正上方偏东方向照入,地面光影斑驳。巷口木箱旁、巷子中央靠近右墙位置均有可供落脚的平坦地面。\"]', 'https://atlas-media.oss-us-west-1.aliyuncs.com/images/c1ef1eeb2a64424798068602a181c0cc-e1074ab882e7517b.jpg', -1, -1, '2026-07-14 20:31:36', 1, '2026-07-14 20:38:50', 0, '[\"https://atlas-media.oss-us-west-1.aliyuncs.com/images/c1ef1eeb2a64424798068602a181c0cc-e1074ab882e7517b.jpg\"]', '[\"宽广空间全景,[\\\"「小巷_日_1985」一条狭窄的老式小巷,宽约三米,两侧是青砖老墙,墙高约四米,墙面斑驳。右侧墙上用红漆写着「时间就是金钱」的标语,字迹清晰。地面是水泥路面,有些裂缝。巷口方向有一辆黑色的二八自行车斜靠在墙边。光线从巷口一端射入,形成明暗对比。巷子中央地面可以站立,左侧墙根下也有约一米宽的通道。\\\",\\\"「小巷_日_1985」巷子长约五十米,两端可见开阔。左侧墙壁爬满半枯的爬山虎,右墙每隔几米有木质门窗(紧闭)。地面是青石板铺成,略有水渍。巷子尽头有一棵老槐树伸出墙头。阳光从头顶偏左照下,在地面投下窗格阴影。巷口方向有一辆老式二八自行车,车把挂着布包。巷子中央空旷处可站人,右侧自行车旁也有空间。\\\",\\\"「小巷_日_1985」宽度不足三米的小巷,两侧墙壁均用灰砖砌成,左墙上有模糊的「工业学大庆」标语残迹,右墙新刷了白色石灰。地面为水泥抹平,中央微微隆起。巷口处堆着几个空木箱。远处可见巷子拐角,墙上挂着一个老式电表箱。光线从正上方偏东方向照入,地面光影斑驳。巷口木箱旁、巷子中央靠近右墙位置均有可供落脚的平坦地面。\\\"],禁止出现任何角色,纯背景板真实电影级画面质感,真实现实场景,色彩饱满通透,画面干净精致,真实感\"]', 0, NULL, NULL);
+INSERT INTO `short_drama_location` VALUES (2077008104432095232, 2077007721974484992, '街道办门口_日', '街道办事处门口,有传达室和铁门,门口台阶下是水泥路,对面有行道树。', 0, '', '[\"街道办门口台阶正下方的位置\",\"传达室窗户左侧墙边\",\"路对面人行道靠近电线杆处\"]', '[\"「街道办门口_日」一栋灰砖二层小楼,门口上方挂着「XX街道办事处」木牌。楼前有三级水泥台阶,台阶两侧铁质扶手。左侧是传达室,小窗户上方有遮阳棚。门前空地为水泥路面,约十平方米,对面是普通的居民楼围墙,墙脚种着冬青。光线从右上方斜照,在台阶上形成阴影。台阶正下方中央、传达室窗边、路对面冬青旁都有平坦可站区域。\",\"「街道办门口_日」政府机关式的老旧建筑,门口为两扇对开铁栅栏门,门内是院落。门外台阶较宽,约五级,两侧有花盆。右侧墙面上贴着红色通知栏。地面为水磨石,有些破损。远处街道上有电线杆和停着的二八大杠自行车。阳光从左侧高层建筑缝隙中射下,照亮铁门局部。台阶中段、传达室门口左侧、路对面树下空地均可站立。\",\"「街道办门口_日」典型八十年代街道办公点,单层门厅带歇山顶。门厅前有宽大平台,平台边缘有低矮水泥护栏。传达室位于左侧,窗口很小。平台下是水泥马路,马路对面是砖砌围墙,墙上有「为人民服务」标语。光线从东南方照射,平台右侧有树影。平台上中央区域、传达室窗口下方、马路对面围墙根处均可落位。\"]', 'https://atlas-media.oss-us-west-1.aliyuncs.com/images/ee4c0cd60f6b43f3a459937e0272cc88-1f5cd218d1905a4d.jpg', -1, -1, '2026-07-14 20:31:36', 1, '2026-07-14 20:38:50', 0, '[\"https://atlas-media.oss-us-west-1.aliyuncs.com/images/ee4c0cd60f6b43f3a459937e0272cc88-1f5cd218d1905a4d.jpg\"]', '[\"宽广空间全景,[\\\"「街道办门口_日」一栋灰砖二层小楼,门口上方挂着「XX街道办事处」木牌。楼前有三级水泥台阶,台阶两侧铁质扶手。左侧是传达室,小窗户上方有遮阳棚。门前空地为水泥路面,约十平方米,对面是普通的居民楼围墙,墙脚种着冬青。光线从右上方斜照,在台阶上形成阴影。台阶正下方中央、传达室窗边、路对面冬青旁都有平坦可站区域。\\\",\\\"「街道办门口_日」政府机关式的老旧建筑,门口为两扇对开铁栅栏门,门内是院落。门外台阶较宽,约五级,两侧有花盆。右侧墙面上贴着红色通知栏。地面为水磨石,有些破损。远处街道上有电线杆和停着的二八大杠自行车。阳光从左侧高层建筑缝隙中射下,照亮铁门局部。台阶中段、传达室门口左侧、路对面树下空地均可站立。\\\",\\\"「街道办门口_日」典型八十年代街道办公点,单层门厅带歇山顶。门厅前有宽大平台,平台边缘有低矮水泥护栏。传达室位于左侧,窗口很小。平台下是水泥马路,马路对面是砖砌围墙,墙上有「为人民服务」标语。光线从东南方照射,平台右侧有树影。平台上中央区域、传达室窗口下方、马路对面围墙根处均可落位。\\\"],禁止出现任何角色,纯背景板真实电影级画面质感,真实现实场景,色彩饱满通透,画面干净精致,真实感\"]', 0, NULL, NULL);
+INSERT INTO `short_drama_location` VALUES (2077008104465649664, 2077007721974484992, '废弃仓库_日', '空旷的旧仓库内部,水泥地面,墙面有老标语,中央放置一张木桌和两把椅子。', 0, '', '[\"木桌左侧椅子前方的位置\",\"仓库大门内侧正对门的位置\",\"右侧墙「工业学大庆」标语下方\"]', '[\"「废弃仓库_日」高大空旷的老仓库,内部面积约两百平米,顶棚为弧形钢架,高约八米。地面是水泥抹平,有多处裂缝和油渍。前墙(南墙)有一排高窗,玻璃蒙尘,光线从窗中斜射入形成光柱。后墙正中写有红色大字「工业学大庆」,字迹斑驳。仓库中央放着一张老式木桌,两侧各一把木椅。左侧墙边堆着几个空铁桶。右墙下靠近标语处有一块干净地面,木桌前后也有空间。\",\"「废弃仓库_日」长方形仓库,东西走向,北侧墙面有一扇双开铁皮大门,半开着。室内光线从大门和南墙高窗进入,混合照亮。地面为灰色水泥,有推车压痕。仓库左侧靠墙有木架,架上零散工具。右侧墙有白色涂料脱落,露出红砖。中央木桌桌面放着两盒烟和几张纸。桌椅周围有约两米见方空地。大门内侧、桌子前方、右侧墙根可站人。\",\"「废弃仓库_日」仓库内部宽畅,纵深约四十米,天花板可见裸露木桁架和瓦片。墙面为抹灰白墙,部分脱落,露出砖块。南侧高窗透入冷色天光,地面有光斑。北侧大门关闭,有门缝透光。仓库中央偏左摆放一张旧木桌,桌面摆放烟盒和铅笔。左侧墙边有生锈铁架。右侧墙「工业学大庆」标语下方地面干净。桌子前侧、左侧铁架旁、右侧标语下均有可供人物站立的平整区域。\"]', 'https://atlas-media.oss-us-west-1.aliyuncs.com/images/22364ee6ea8649788330827d67015aaf-390fb3c2f4c24ee7.jpg', -1, -1, '2026-07-14 20:31:36', 1, '2026-07-14 20:38:50', 0, '[\"https://atlas-media.oss-us-west-1.aliyuncs.com/images/22364ee6ea8649788330827d67015aaf-390fb3c2f4c24ee7.jpg\"]', '[\"宽广空间全景,[\\\"「废弃仓库_日」高大空旷的老仓库,内部面积约两百平米,顶棚为弧形钢架,高约八米。地面是水泥抹平,有多处裂缝和油渍。前墙(南墙)有一排高窗,玻璃蒙尘,光线从窗中斜射入形成光柱。后墙正中写有红色大字「工业学大庆」,字迹斑驳。仓库中央放着一张老式木桌,两侧各一把木椅。左侧墙边堆着几个空铁桶。右墙下靠近标语处有一块干净地面,木桌前后也有空间。\\\",\\\"「废弃仓库_日」长方形仓库,东西走向,北侧墙面有一扇双开铁皮大门,半开着。室内光线从大门和南墙高窗进入,混合照亮。地面为灰色水泥,有推车压痕。仓库左侧靠墙有木架,架上零散工具。右侧墙有白色涂料脱落,露出红砖。中央木桌桌面放着两盒烟和几张纸。桌椅周围有约两米见方空地。大门内侧、桌子前方、右侧墙根可站人。\\\",\\\"「废弃仓库_日」仓库内部宽畅,纵深约四十米,天花板可见裸露木桁架和瓦片。墙面为抹灰白墙,部分脱落,露出砖块。南侧高窗透入冷色天光,地面有光斑。北侧大门关闭,有门缝透光。仓库中央偏左摆放一张旧木桌,桌面摆放烟盒和铅笔。左侧墙边有生锈铁架。右侧墙「工业学大庆」标语下方地面干净。桌子前侧、左侧铁架旁、右侧标语下均有可供人物站立的平整区域。\\\"],禁止出现任何角色,纯背景板真实电影级画面质感,真实现实场景,色彩饱满通透,画面干净精致,真实感\"]', 0, NULL, NULL);
+INSERT INTO `short_drama_location` VALUES (2077008104541147136, 2077007721974484992, '工厂办公室_日', '八十年代工厂办公室,木制办公桌、转盘电话、文件柜,窗外可见厂区。', 0, '', '[\"办公桌前椅子正前方的位置\",\"窗台下方靠墙的空地\",\"门口内侧文件柜旁\"]', '[\"「工厂办公室_日」一间十五平米的老式办公室,水泥地面刷了绿色油漆,略有磨损。正面墙有木框玻璃窗,窗外是工厂院落,可见烟囱和车间屋顶。窗下放着一张深褐色办公桌,桌面有玻璃板压着照片,一部黑色转盘电话放在右侧。左侧墙立着铁皮文件柜,绿色漆。右墙贴着生产进度表。阳光从窗外照射进来,在桌面形成光斑。桌前空地约两平米,窗台下、门口文件柜旁也有空间。\",\"「工厂办公室_日」房间方正,南墙整面为窗户,光线充足。窗户为老式钢窗,窗外有梧桐树枝叶。屋顶为白色涂料,日光灯管一支亮着。地面铺设浅色地板革,有磨损。办公桌靠东墙放置,桌上有笔筒、茶杯和电话。西墙有木制衣架和镜子。北墙门边有铁皮柜。桌前方地板、西墙衣架旁、北墙柜前均可落位。\",\"「工厂办公室_日」约十二平米的办公空间,乳胶漆墙面局部发黄。南侧窗户透入明亮日光,照射在东侧白色墙壁上。办公桌为深棕色三抽屉木桌,居中放置,桌上电话、台历、一部老式计算机。右侧墙角有饮水机和水桶。左侧墙角放置扫帚和簸箕。门在西墙。地板为红砖铺成,铺垫草席。桌前方、门口左侧墙角、右墙饮水机旁都有站立空间。\"]', 'https://atlas-media.oss-us-west-1.aliyuncs.com/images/86f032880f2e43409a9df446490e7032-6d12c0e8763f4c3e.jpg', -1, -1, '2026-07-14 20:31:36', 1, '2026-07-14 20:38:51', 0, '[\"https://atlas-media.oss-us-west-1.aliyuncs.com/images/86f032880f2e43409a9df446490e7032-6d12c0e8763f4c3e.jpg\"]', '[\"宽广空间全景,[\\\"「工厂办公室_日」一间十五平米的老式办公室,水泥地面刷了绿色油漆,略有磨损。正面墙有木框玻璃窗,窗外是工厂院落,可见烟囱和车间屋顶。窗下放着一张深褐色办公桌,桌面有玻璃板压着照片,一部黑色转盘电话放在右侧。左侧墙立着铁皮文件柜,绿色漆。右墙贴着生产进度表。阳光从窗外照射进来,在桌面形成光斑。桌前空地约两平米,窗台下、门口文件柜旁也有空间。\\\",\\\"「工厂办公室_日」房间方正,南墙整面为窗户,光线充足。窗户为老式钢窗,窗外有梧桐树枝叶。屋顶为白色涂料,日光灯管一支亮着。地面铺设浅色地板革,有磨损。办公桌靠东墙放置,桌上有笔筒、茶杯和电话。西墙有木制衣架和镜子。北墙门边有铁皮柜。桌前方地板、西墙衣架旁、北墙柜前均可落位。\\\",\\\"「工厂办公室_日」约十二平米的办公空间,乳胶漆墙面局部发黄。南侧窗户透入明亮日光,照射在东侧白色墙壁上。办公桌为深棕色三抽屉木桌,居中放置,桌上电话、台历、一部老式计算机。右侧墙角有饮水机和水桶。左侧墙角放置扫帚和簸箕。门在西墙。地板为红砖铺成,铺垫草席。桌前方、门口左侧墙角、右墙饮水机旁都有站立空间。\\\"],禁止出现任何角色,纯背景板真实电影级画面质感,真实现实场景,色彩饱满通透,画面干净精致,真实感\"]', 0, NULL, NULL);
+INSERT INTO `short_drama_location` VALUES (2077008104583090176, 2077007721974484992, '出租屋_夜', '狭小的出租屋,室内有床、桌子和黑板,黑板画着时间轴,灯光昏暗。', 0, '', '[\"黑板前方半米处地面\",\"桌子右侧靠墙位置\",\"门口内侧的空地\"]', '[\"「出租屋_夜」一间约十平米的单间,水泥地面,白灰墙面陈旧泛黄。北墙上有小窗户,挂着花布窗帘。东墙摆放一张单人木床,铺着格子床单。西墙靠着一张方桌,桌面散落纸笔和茶杯。南墙立着一块小黑板,黑板用粉笔画着时间轴和文字。屋顶悬着一盏白炽灯泡,发出昏黄光线,向下照射。床前、黑板前、桌子右侧均有可站立空地。\",\"「出租屋_夜」逼仄的出租屋,空间狭小,内有双层铁床靠左墙,下铺放行李。房间中央是一张折叠桌,桌上有电炉和锅。右墙钉着一块黑板,黑板边角有残缺,上面用粉笔写着「1985-2000」等字样。地面为砖地,不平整。灯光从屋顶一盏裸露灯泡发出,光线偏黄,在墙角形成阴影。桌子前方空地、双层床铺下方前端、黑板的左侧均可落位。\",\"「出租屋_夜」低矮的出租屋,层高约两米五,屋顶有木梁。西墙有一扇木门,门边有挂锁。南墙是大面积窗户,但被报纸糊住。北墙放置一个老旧衣柜,柜门敞开。中央一张矮方桌,桌上有手绘图纸和圆珠笔。地面铺着塑料地板革,已有破损。灯光从屋顶日光灯管发出,白色冷光,照亮全屋。黑板挂于东墙,上面时间轴清晰。桌子周围、衣柜前、门口都有站人空间。\"]', 'https://atlas-media.oss-us-west-1.aliyuncs.com/images/1c3fe372d8c34a28ad4d157e973a8342-acdc977ee2a76eab.jpg', -1, -1, '2026-07-14 20:31:36', 1, '2026-07-14 20:38:51', 0, '[\"https://atlas-media.oss-us-west-1.aliyuncs.com/images/1c3fe372d8c34a28ad4d157e973a8342-acdc977ee2a76eab.jpg\"]', '[\"宽广空间全景,[\\\"「出租屋_夜」一间约十平米的单间,水泥地面,白灰墙面陈旧泛黄。北墙上有小窗户,挂着花布窗帘。东墙摆放一张单人木床,铺着格子床单。西墙靠着一张方桌,桌面散落纸笔和茶杯。南墙立着一块小黑板,黑板用粉笔画着时间轴和文字。屋顶悬着一盏白炽灯泡,发出昏黄光线,向下照射。床前、黑板前、桌子右侧均有可站立空地。\\\",\\\"「出租屋_夜」逼仄的出租屋,空间狭小,内有双层铁床靠左墙,下铺放行李。房间中央是一张折叠桌,桌上有电炉和锅。右墙钉着一块黑板,黑板边角有残缺,上面用粉笔写着「1985-2000」等字样。地面为砖地,不平整。灯光从屋顶一盏裸露灯泡发出,光线偏黄,在墙角形成阴影。桌子前方空地、双层床铺下方前端、黑板的左侧均可落位。\\\",\\\"「出租屋_夜」低矮的出租屋,层高约两米五,屋顶有木梁。西墙有一扇木门,门边有挂锁。南墙是大面积窗户,但被报纸糊住。北墙放置一个老旧衣柜,柜门敞开。中央一张矮方桌,桌上有手绘图纸和圆珠笔。地面铺着塑料地板革,已有破损。灯光从屋顶日光灯管发出,白色冷光,照亮全屋。黑板挂于东墙,上面时间轴清晰。桌子周围、衣柜前、门口都有站人空间。\\\"],禁止出现任何角色,纯背景板真实电影级画面质感,真实现实场景,色彩饱满通透,画面干净精致,真实感\"]', 0, NULL, NULL);
+INSERT INTO `short_drama_location` VALUES (2077008104604061696, 2077007721974484992, '百货大楼门口_日', '八十年代百货大楼正门,台阶宽大,门口有立柱,橱窗陈列商品,街道上有行人。', 1, '几位穿着中山装和军便装的市民站在台阶上下,有的正在看橱窗,有的在交谈。', '[\"百货大楼正门台阶最高一级中央\",\"右侧立柱旁的地面\",\"台阶下左侧报栏前\",\"对面人行道树下\"]', '[\"「百货大楼门口_日」一栋三层百货大楼,正立面贴白色瓷砖,一层为玻璃橱窗,展示布料、搪瓷盆等商品。楼顶立着「百货大楼」红色大字。门前有五级水磨石台阶,两侧有方形立柱,柱身贴着宣传画。台阶下是宽敞的马路,路边有梧桐树。光学从东南方照来,大楼正面明亮,橱窗玻璃反光。台阶上、立柱旁、报栏前、对面树荫下均有可供人物站立的空间。\",\"「百货大楼门口_日」八十年代百货商场大门,门楣上方有遮雨棚,棚下悬挂「为人民服务」标语。大门为三扇玻璃推拉门,门内可见柜台。左右两侧橱窗内陈列着自行车、缝纫机等展品。门前广场铺着六边形水泥砖,有数根电线杆。光线充足,阳光从右后方照射,左前方有阴影。大门正前方台阶、右侧电线杆附近、左侧橱窗旁均可作为人物落位点。\",\"「百货大楼门口_日」大型百货商店正门区域,建筑为现代主义风格,立面简洁。大门前有宽阔平台,平台四角有花坛,内种月季。地面为水磨石,洁净明亮。左侧有一块公告栏,贴着红色海报。远处可见公交站台,有行人等车。光线从正头顶略偏南,地面有微弱阴影。平台中央、左侧公告栏前、右侧花坛旁均有平坦地面适合站立。\"]', 'https://atlas-media.oss-us-west-1.aliyuncs.com/images/c94f6cb0c4364d5db271b9606c2bde94-101b8d0c012901fe.jpg', -1, -1, '2026-07-14 20:31:36', 1, '2026-07-14 20:38:51', 0, '[\"https://atlas-media.oss-us-west-1.aliyuncs.com/images/c94f6cb0c4364d5db271b9606c2bde94-101b8d0c012901fe.jpg\"]', '[\"宽广空间全景,[\\\"「百货大楼门口_日」一栋三层百货大楼,正立面贴白色瓷砖,一层为玻璃橱窗,展示布料、搪瓷盆等商品。楼顶立着「百货大楼」红色大字。门前有五级水磨石台阶,两侧有方形立柱,柱身贴着宣传画。台阶下是宽敞的马路,路边有梧桐树。光学从东南方照来,大楼正面明亮,橱窗玻璃反光。台阶上、立柱旁、报栏前、对面树荫下均有可供人物站立的空间。\\\",\\\"「百货大楼门口_日」八十年代百货商场大门,门楣上方有遮雨棚,棚下悬挂「为人民服务」标语。大门为三扇玻璃推拉门,门内可见柜台。左右两侧橱窗内陈列着自行车、缝纫机等展品。门前广场铺着六边形水泥砖,有数根电线杆。光线充足,阳光从右后方照射,左前方有阴影。大门正前方台阶、右侧电线杆附近、左侧橱窗旁均可作为人物落位点。\\\",\\\"「百货大楼门口_日」大型百货商店正门区域,建筑为现代主义风格,立面简洁。大门前有宽阔平台,平台四角有花坛,内种月季。地面为水磨石,洁净明亮。左侧有一块公告栏,贴着红色海报。远处可见公交站台,有行人等车。光线从正头顶略偏南,地面有微弱阴影。平台中央、左侧公告栏前、右侧花坛旁均有平坦地面适合站立。\\\"],禁止出现任何角色,纯背景板真实电影级画面质感,真实现实场景,色彩饱满通透,画面干净精致,真实感\"]', 0, NULL, NULL);
+INSERT INTO `short_drama_location` VALUES (2077008104675364864, 2077007721974484992, '厂庆礼堂_夜', '工厂礼堂内部,舞台上有麦克风,台下长凳坐满工人,红灯笼和横幅装饰。', 1, '几十名穿着蓝色工装的工人整齐坐在长凳上,面向舞台,表情喜悦。', '[\"舞台中央麦克风架前方位置\",\"舞台左侧幕布旁\",\"观众席前排中间走道\",\"礼堂后门入口处\"]', '[\"「厂庆礼堂_夜」一座中型礼堂,空间约三百平米,两侧墙壁挂满红色锦旗和奖状。舞台为砖砌,高约一米,铺着红色地毯,中央立着麦克风,背景幕布为深红色绒布,上方悬挂「厂庆联欢晚会」横幅。观众席摆着二十排长木凳,坐满穿工装的工人。屋顶悬挂多盏白炽灯和串串红灯笼,灯光暖黄。舞台侧方、观众席中间走廊、后门口均有空地可站人。\",\"「厂庆礼堂_夜」礼堂内部呈长方形,前高后低,地板为水泥磨光。天花板有木横梁,垂吊着彩带和纸花。舞台左后侧有上台台阶,右侧放置锣鼓乐器。台下长凳密集排列,过道狭窄,工人拥挤而坐,有些站着。礼堂后墙有双开木门,紧闭。光线主要来自舞台上的聚光灯和两侧壁灯,明亮温暖。舞台中央地面、右侧锣鼓旁、后墙门边有可落位空间。\",\"「厂庆礼堂_夜」宽大的老式礼堂,墙面下半部刷绿色墙裙,上半部白墙。窗户用深色帘幕遮住。舞台台口有弧形边缘,台上有两张木椅和一张讲台。台前摆满花篮。观众席中央过道约一米宽,两侧长凳坐满人。天花板中央一盏大吊灯,四周小灯,整体照明均匀。舞台正前方、左侧幕布缺口处、礼堂后门旁均可站立。\"]', 'https://atlas-media.oss-us-west-1.aliyuncs.com/images/a9295d479fef45f198bffd3ef850eacd-588538d1e9d8e094.jpg', -1, -1, '2026-07-14 20:31:36', 1, '2026-07-14 20:38:51', 0, '[\"https://atlas-media.oss-us-west-1.aliyuncs.com/images/a9295d479fef45f198bffd3ef850eacd-588538d1e9d8e094.jpg\"]', '[\"宽广空间全景,[\\\"「厂庆礼堂_夜」一座中型礼堂,空间约三百平米,两侧墙壁挂满红色锦旗和奖状。舞台为砖砌,高约一米,铺着红色地毯,中央立着麦克风,背景幕布为深红色绒布,上方悬挂「厂庆联欢晚会」横幅。观众席摆着二十排长木凳,坐满穿工装的工人。屋顶悬挂多盏白炽灯和串串红灯笼,灯光暖黄。舞台侧方、观众席中间走廊、后门口均有空地可站人。\\\",\\\"「厂庆礼堂_夜」礼堂内部呈长方形,前高后低,地板为水泥磨光。天花板有木横梁,垂吊着彩带和纸花。舞台左后侧有上台台阶,右侧放置锣鼓乐器。台下长凳密集排列,过道狭窄,工人拥挤而坐,有些站着。礼堂后墙有双开木门,紧闭。光线主要来自舞台上的聚光灯和两侧壁灯,明亮温暖。舞台中央地面、右侧锣鼓旁、后墙门边有可落位空间。\\\",\\\"「厂庆礼堂_夜」宽大的老式礼堂,墙面下半部刷绿色墙裙,上半部白墙。窗户用深色帘幕遮住。舞台台口有弧形边缘,台上有两张木椅和一张讲台。台前摆满花篮。观众席中央过道约一米宽,两侧长凳坐满人。天花板中央一盏大吊灯,四周小灯,整体照明均匀。舞台正前方、左侧幕布缺口处、礼堂后门旁均可站立。\\\"],禁止出现任何角色,纯背景板真实电影级画面质感,真实现实场景,色彩饱满通透,画面干净精致,真实感\"]', 0, NULL, NULL);
+INSERT INTO `short_drama_location` VALUES (2077008104721502208, 2077007721974484992, '工厂大门_晨', '清晨工厂大门,新挂牌「华夏信息服务中心」,自行车棚,远处烟囱冒烟。', 1, '几名穿着蓝色工装的工人推着自行车或步行进入厂门,路边有早点摊的模糊身影。', '[\"厂门口新挂牌下方正中间\",\"右侧自行车棚外侧\",\"左侧传达室门口台阶\",\"马路对面老槐树旁\"]', '[\"「工厂大门_晨」工厂大门为铁制对开栅栏门,门柱为红砖砌成,左侧门柱上挂着崭新白底黑字牌子「华夏信息服务中心」。进门可见一条水泥路通向厂区。右侧有一排自行车棚,棚内停着几十辆自行车。远处工厂烟囱缓缓冒白烟,背景是朦胧的晨曦天空。阳光从东方斜照,拉长门柱影子。大门正下方、自行车棚外面、左侧传达室门口、马路对面树荫下均有平坦地面。\",\"「工厂大门_晨」晨曦中的老工厂入口,灰砖围墙高约三米,大门敞开。左侧传达室为平房,窗户透出灯光。门右侧墙上贴着红色通知。路面是水泥铺设,有些许落叶。厂内远处可见车间屋顶和冒烟烟囱。天空泛鱼肚白,东边有朝霞。光线从右前方射来,门牌上的字清晰反光。大门中央、传达室左侧空地、路边电线杆旁都可以站人。\",\"「工厂大门_晨」工厂正门区域,宽阔的厂前空地上矗立着新立的招牌。大门两侧各有一棵法国梧桐,枝叶繁茂。地面为柏油路,路中央画有白色虚线。厂门内侧两边是花坛,种着冬青。远处厂房轮廓在晨雾中若隐若现,烟囱吐烟。光线柔和,晨光从建筑物缝隙中洒落。招牌下方、左侧花坛旁、右侧梧桐树下均是可站立的空旷位置。\"]', 'https://atlas-media.oss-us-west-1.aliyuncs.com/images/50f5cc1fb8e74dac95d589c23dc2daf7-7fb4da35d3075e95.jpg', -1, -1, '2026-07-14 20:31:36', 1, '2026-07-14 20:38:51', 0, '[\"https://atlas-media.oss-us-west-1.aliyuncs.com/images/50f5cc1fb8e74dac95d589c23dc2daf7-7fb4da35d3075e95.jpg\"]', '[\"宽广空间全景,[\\\"「工厂大门_晨」工厂大门为铁制对开栅栏门,门柱为红砖砌成,左侧门柱上挂着崭新白底黑字牌子「华夏信息服务中心」。进门可见一条水泥路通向厂区。右侧有一排自行车棚,棚内停着几十辆自行车。远处工厂烟囱缓缓冒白烟,背景是朦胧的晨曦天空。阳光从东方斜照,拉长门柱影子。大门正下方、自行车棚外面、左侧传达室门口、马路对面树荫下均有平坦地面。\\\",\\\"「工厂大门_晨」晨曦中的老工厂入口,灰砖围墙高约三米,大门敞开。左侧传达室为平房,窗户透出灯光。门右侧墙上贴着红色通知。路面是水泥铺设,有些许落叶。厂内远处可见车间屋顶和冒烟烟囱。天空泛鱼肚白,东边有朝霞。光线从右前方射来,门牌上的字清晰反光。大门中央、传达室左侧空地、路边电线杆旁都可以站人。\\\",\\\"「工厂大门_晨」工厂正门区域,宽阔的厂前空地上矗立着新立的招牌。大门两侧各有一棵法国梧桐,枝叶繁茂。地面为柏油路,路中央画有白色虚线。厂门内侧两边是花坛,种着冬青。远处厂房轮廓在晨雾中若隐若现,烟囱吐烟。光线柔和,晨光从建筑物缝隙中洒落。招牌下方、左侧花坛旁、右侧梧桐树下均是可站立的空旷位置。\\\"],禁止出现任何角色,纯背景板真实电影级画面质感,真实现实场景,色彩饱满通透,画面干净精致,真实感\"]', 0, NULL, NULL);
+
+-- ----------------------------
+-- Table structure for short_drama_audio
+-- ----------------------------
+DROP TABLE IF EXISTS `short_drama_audio`;
+CREATE TABLE `short_drama_audio` (
+ `id` bigint NOT NULL COMMENT '主键',
+ `project_id` bigint NOT NULL COMMENT '项目ID',
+ `name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '语音资产名称',
+ `audio_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'narration' COMMENT '语音类型:narration(旁白)/dialogue(对白)',
+ `text` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '语音文案(生成语音用的文本)',
+ `voice` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '音色(如 alloy/onyx)',
+ `audio_oss_id` bigint NULL DEFAULT NULL COMMENT '音频文件OSS ID',
+ `audio_url` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '音频文件URL',
+ `linked_storyboard_id` bigint NULL DEFAULT NULL COMMENT '对白关联的分镜ID(NULL=全局旁白)',
+ `duration_seconds` int NULL DEFAULT NULL COMMENT '音频时长(秒)',
+ `create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门',
+ `create_by` bigint NULL DEFAULT NULL COMMENT '创建者',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_by` bigint NULL DEFAULT NULL COMMENT '更新者',
+ `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户Id',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_project_id`(`project_id` ASC) USING BTREE,
+ INDEX `idx_linked_storyboard_id`(`linked_storyboard_id` ASC) USING BTREE,
+ INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '短剧语音资产表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for short_drama_project
+-- ----------------------------
+DROP TABLE IF EXISTS `short_drama_project`;
+CREATE TABLE `short_drama_project` (
+ `id` bigint NOT NULL COMMENT '主键',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `project_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '项目名称',
+ `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '项目描述',
+ `status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'draft' COMMENT '状态:draft/active/archived',
+ `create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门',
+ `create_by` bigint NULL DEFAULT NULL COMMENT '创建者',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_by` bigint NULL DEFAULT NULL COMMENT '更新者',
+ `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户Id',
+ `art_style` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'realistic' COMMENT '视觉风格:american-comic=美漫, chinese-comic=国漫, japanese-anime=日系, realistic=写实',
+ `composed_video_oss_id` bigint NULL DEFAULT NULL COMMENT '最新成片OSS对象ID',
+ `compose_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '合成状态:NULL未合成,pending/processing/done/failed',
+ `compose_job_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '当前合成任务标识(并发防重)',
+ `compose_progress` int NOT NULL DEFAULT 0 COMMENT '合成进度:0-100',
+ `compose_transition_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'dissolve' COMMENT '转场类型:none/dissolve/fade/slide',
+ `compose_transition_duration_seconds` decimal(6, 3) NOT NULL DEFAULT 0.500 COMMENT '单次转场时长(秒)',
+ `compose_aspect_ratio` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '9:16' COMMENT '成片画幅:9:16/16:9/1:1',
+ `composed_video_duration_seconds` decimal(12, 3) NULL DEFAULT NULL COMMENT '最终成片实际时长(秒,ffprobe测量)',
+ `compose_error_message` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '最近一次合成失败原因',
+ `composed_at` datetime NULL DEFAULT NULL COMMENT '最近一次合成完成时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_user_id`(`user_id` ASC) USING BTREE,
+ INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '短剧项目表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of short_drama_project
+-- ----------------------------
+INSERT INTO `short_drama_project` VALUES (2077007721974484992, 1, '短剧项目', '50岁失意中年小明意外穿越到1985年,利用未来知识创业,在时代洪流中改写命运,最终留下并影响一代人。', 'draft', -1, -1, '2026-07-14 20:30:05', -1, '2026-07-14 20:51:14', 0, 'realistic', NULL, 'done', NULL, 100, 'fade', 0.300, '9:16', 32.267, NULL, '2026-07-14 20:51:14');
+
+-- ----------------------------
+-- Table structure for short_drama_script
+-- ----------------------------
+DROP TABLE IF EXISTS `short_drama_script`;
+CREATE TABLE `short_drama_script` (
+ `id` bigint NOT NULL COMMENT '主键',
+ `project_id` bigint NOT NULL COMMENT '项目ID',
+ `script_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '剧本名称',
+ `script_text` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '剧本文本',
+ `outline_text` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '大纲文本',
+ `tone` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '风格/基调',
+ `source_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'manual' COMMENT '来源:manual/ai',
+ `create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门',
+ `create_by` bigint NULL DEFAULT NULL COMMENT '创建者',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_by` bigint NULL DEFAULT NULL COMMENT '更新者',
+ `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户Id',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_project_id`(`project_id` ASC) USING BTREE,
+ INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '短剧剧本表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of short_drama_script
+-- ----------------------------
+INSERT INTO `short_drama_script` VALUES (2077007722058371072, 2077007721974484992, '重启1985', '1. 内景 现代办公室 夜\n\n办公室昏暗,只有电脑屏幕亮着。50岁的小明穿着皱巴巴的衬衫,盯着屏幕上的辞退邮件。他拿起手机,看到妻子发来的离婚协议截图。手抖着放下手机,碰倒桌上的电水壶,水洒在插座上。火花闪过,小明倒在椅子上。\n\n2. 外景 小巷 日 1985年\n\n小明醒来,发现自己躺在地上,身穿80年代蓝色工装。他摸着脸——没有皱纹。旁边老式自行车铃响,一个年轻人喊:“小明,上班迟到了!”小明看着路口的二八自行车,墙上的标语“时间就是金钱”,愣住。他低头看手腕上的电子表:1985年6月。他深吸一口气,眼神从迷茫变成坚定:“再来一次。”\n\n3. 外景 街道办门口 日\n\n小明拿着一叠手写方案,站在街道办门口。门卫拦住他。小明:“同志,我有商业计划,能帮工厂接全国订单!”门卫:“胡闹!”推他出去。小明捡起散落的纸,抬头看到路对面一个穿中山装的中年男人(老陈)正在看他的方案。老陈:“你这上面写的‘电商’是啥?”小明眼睛一亮:“陈厂长,我能让您仓库里的积压货三天卖掉。”\n\n4. 内景 废弃仓库 日\n\n老陈和小明对面坐着。桌上摆着两盒烟。老陈:“我信你一次,但怎么弄?”小明在纸上画:“用电话线连电脑,搞个库存信息库。我写程序。”老陈:“钱呢?”小明:“我先拉商户,您出设备。”老陈犹豫后点头。小明看着仓库墙上的“工业学大庆”,低声:“这次一定要成。”\n\n5. 内景 工厂办公室 日\n\n办公桌上电话响起。老陈接起,脸色变白。挂断后对小明:“国营百货举报我们投机倒把,工商明天来查。”小明快速翻看账本:“我们走的是信息服务,不是倒卖。”老陈:“没人认可这个。”小明:“明天我来说。”\n\n6. 内景 小明的出租屋 夜\n\n团队成员(两个年轻人)拍桌:“不干了,风险太大!”老陈沉默。小明拿出一块黑板,画出时间轴:“1985年,电脑刚进中国,我们的优势是信息差。不做商品买卖,做平台——帮工厂和供销社匹配库存。”他指着黑板:“明天工商来,我就说这是‘技术咨询’。”老陈抬头:“你哪来的这些?”小明:“梦里学的。”\n\n7. 外景 百货大楼门口 日\n\n工商人员和小明、老陈站在门口。小明拿出一份表格:“这是通过我们信息服务成交的订单,全部有记录,不碰资金,只收咨询费。”工商人员翻看,递给旁边一个戴眼镜的中年人(百货公司经理)。经理看了后低声:“这方法能帮我们清库存?”小明:“三天见效。”经理点头。工商人员收起表格:“先观察。”\n\n8. 内景 厂庆礼堂 夜\n\n工人坐满长凳。老陈上台:“感谢小明的信息平台,咱们工厂活了。”台下鼓掌。小明站在侧台,看着灯光下兴奋的面孔。他手摸到口袋里的现代身份证——早已发黄。他默默撕碎。主持人:“请小明同志讲话!”小明上前,拿着话筒停顿三秒:“各位,未来三十年,互联网会改变一切。今天,我们从这里开始。”台下掌声雷动。\n\n9. 外景 工厂大门 晨\n\n阳光照在新挂牌上:“华夏信息服务中心”。小明推着自行车出来,老陈追上:“下一步?”小明:“跑遍全国,建数据库。”老陈笑:“疯了。”小明跨上车:“1985年,疯的人才能赢。”他蹬车远去,街道两旁的工厂烟囱开始冒烟。', '1.现代办公室夜,小明被老板辞退,回家发现妻子要离婚,绝望中碰倒电水壶触电。2.1985年小巷外景清晨,小明醒来发现变成25岁身体,确认穿越,决定利用记忆创业。3.街道办外景日,小明推销‘互联网购物’概念,被当成疯子赶出,遇到工厂副厂长老陈愿意听。4.废弃仓库内景,小明说服老陈入股,用记忆设计简易电商系统,团队组建。5.工厂办公室内景,初获订单,却遭国营百货公司经理举报,面临查封危机。6.小作家中内景夜,团队内讧,老陈动摇,小明用未来管理经验分析市场,决定转型做信息中介。7.百货大楼外景日,小明带团队利用数据库帮商家库存匹配,化解危机,赢取首个大客户。8.厂庆礼堂内景夜,小明站在台上,回想现代生活,决定留下,带领工人转型。9.同场景,小明讲话,镜头拉远,工厂转型成功。', '现实与励志', 'llm', -1, -1, '2026-07-14 20:30:05', -1, '2026-07-14 20:30:05', 0);
+
+-- ----------------------------
+-- Table structure for short_drama_storyboard
+-- ----------------------------
+DROP TABLE IF EXISTS `short_drama_storyboard`;
+CREATE TABLE `short_drama_storyboard` (
+ `id` bigint NOT NULL COMMENT '主键',
+ `project_id` bigint NOT NULL COMMENT '项目ID',
+ `script_id` bigint NOT NULL COMMENT '剧本ID',
+ `scene_no` int NOT NULL COMMENT '分镜序号',
+ `scene_title` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '分镜标题',
+ `scene_text` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '分镜说明',
+ `scene_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'daily' COMMENT '场景类型:daily/emotion/action/epic/suspense',
+ `shot_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '镜头景别:如平视中景/俯拍远景',
+ `camera_move` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '镜头运动:如缓推/固定/跟随/环绕',
+ `characters_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '镜头角色列表JSON:[{name,appearance,slot}]',
+ `location_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '场景名称(匹配资产库)',
+ `photography_rules` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '摄影规则JSON',
+ `acting_notes` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '表演指导JSON',
+ `continuity_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '镜头连续性JSON:起始状态、结束状态、动作承接、空间锚点、在场人物',
+ `source_text` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '原文片段',
+ `image_prompt` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '图片生成提示词',
+ `duration_seconds` int NOT NULL DEFAULT 15 COMMENT '时长秒数',
+ `video_prompt` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '视频提示词',
+ `video_url` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '视频地址',
+ `video_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '视频生成任务ID',
+ `video_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'pending' COMMENT '视频状态:pending/generating/done/failed',
+ `last_frame_url` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '上一镜末帧URL(同场景连续镜头首帧承接用)',
+ `create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门',
+ `create_by` bigint NULL DEFAULT NULL COMMENT '创建者',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_by` bigint NULL DEFAULT NULL COMMENT '更新者',
+ `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户Id',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_script_scene`(`script_id` ASC, `scene_no` ASC) USING BTREE,
+ INDEX `idx_project_id`(`project_id` ASC) USING BTREE,
+ INDEX `idx_script_id`(`script_id` ASC) USING BTREE,
+ INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '短剧分镜表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of short_drama_storyboard
+-- ----------------------------
+INSERT INTO `short_drama_storyboard` (`id`, `project_id`, `script_id`, `scene_no`, `scene_title`, `scene_text`, `scene_type`, `shot_type`, `camera_move`, `characters_json`, `location_name`, `photography_rules`, `acting_notes`, `continuity_json`, `source_text`, `image_prompt`, `duration_seconds`, `video_prompt`, `video_url`, `video_id`, `video_status`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`) VALUES (2077008643517599744, 2077007721974484992, 2077007722058371072, 1, '辞退邮件与触电穿越', '深夜办公室,电脑屏幕亮光映照50岁小明苍老疲惫的脸,他盯着屏幕上的辞退邮件,眼神失焦。他拿起手机看到离婚协议截图,手开始颤抖,手机滑落。他试图扶住桌子,手肘碰倒旁边电水壶,水洒向插座,火花迸溅,小明身体后仰倒在椅子上,画面渐黑。', 'suspense', '平视近景', '缓推至固定', '[{\"name\":\"小明\",\"appearance\":\"初始形象\",\"slot\":\"办公桌前\"}]', '现代办公室_夜', '{\"panel_number\":1,\"scene_summary\":\"深夜办公室,电脑屏幕亮光映照50岁小明苍老疲惫的脸,他盯着屏幕上的辞退邮件,眼神失焦。他拿起手机看到离婚协议截图,手开始颤抖,手机滑落。他试图扶住桌子,手肘碰倒旁边电水壶,水洒向插座,火花迸溅,小明身体后仰倒在椅子上,画面渐黑。\",\"lighting\":{\"direction\":\"根据场景主光方向保持连续\",\"quality\":\"低调硬光,保留阴影层次\"},\"characters\":[{\"name\":\"小明\",\"screen_position\":\"办公桌前\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"}],\"depth_of_field\":\"中浅景深,保留环境压迫感\",\"color_tone\":\"冷暗色调\"}', '[{\"name\":\"小明\",\"acting\":\"控制呼吸与眨眼频率,用迟疑、停顿和缓慢转头制造紧张感,按前段、中段、后段完成三个连续表演节拍\"}]', '{\"start_state\":\"新场景建立:现代办公室_夜,重新交代人物位置、朝向与环境\",\"end_state\":\"小明倒在椅子上,身体后仰,火花在插座处闪烁,画面渐黑\",\"continuity_action\":\"小明身体失去平衡向后倒,火花仍在闪烁\",\"spatial_anchor\":\"小明位于画面中央偏左,办公桌桌面杂乱的纸张和电脑屏幕占据右半,电水壶翻倒在桌角\",\"present_characters\":[\"小明\"],\"scene_number\":1,\"segment_number\":1,\"segment_goal\":\"建立小明被辞退后的绝望状态并触发穿越\",\"segment_result\":\"小明触电倒下,穿越启动\",\"bridge_in\":\"开场建立办公室环境与人物状态\",\"bridge_out\":\"火花和倒下的动作形成视觉钩子,画面切黑\",\"beat_type\":\"trigger\",\"narrative_cause\":\"小明收到辞退邮件和离婚协议,情绪崩溃导致意外\",\"character_goal\":\"缓解内心痛苦,但无意识动作导致触电\",\"story_action\":\"手抖放下手机,碰倒水壶,水溅到插座引发火花\",\"story_result\":\"小明触电昏迷,穿越时空\",\"next_hook\":\"下一镜头需要展示小明醒来后的新环境\"}', '办公室昏暗,只有电脑屏幕亮着。50岁的小明穿着皱巴巴的衬衫,盯着屏幕上的辞退邮件。他拿起手机,看到妻子发来的离婚协议截图。手抖着放下手机,碰倒桌上的电水壶,水洒在插座上。火花闪过,小明倒在椅子上。', '小明坐在深夜办公室的办公桌前,电脑屏幕蓝光照亮他苍老疲惫的脸,桌上散落纸张,他手中拿着手机看着离婚协议截图,旁边的电水壶摇摇欲坠,背景黑暗,气氛压抑。', 8, '深夜办公室,中年男子坐在办公桌前,电脑屏幕光映照脸庞,他盯着屏幕,眼神失焦。他拿起手机看向屏幕,手开始颤抖,手机滑落。他试图扶住桌子,手肘碰倒旁边的电水壶,水洒向插座,火花迸溅,他身体后仰倒在椅子上。镜头从平视中景缓缓推近至脸部特写,然后固定,画面渐黑。', 'https://atlas-media.oss-us-west-1.aliyuncs.com/videos/cgt-20260714203912-pshlw-0.mp4', '472c35ef433744c8a4cbd35a438ad35e', 'done', -1, -1, '2026-07-14 20:33:44', -1, '2026-07-14 20:41:42', 0);
+INSERT INTO `short_drama_storyboard` (`id`, `project_id`, `script_id`, `scene_no`, `scene_title`, `scene_text`, `scene_type`, `shot_type`, `camera_move`, `characters_json`, `location_name`, `photography_rules`, `acting_notes`, `continuity_json`, `source_text`, `image_prompt`, `duration_seconds`, `video_prompt`, `video_url`, `video_id`, `video_status`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`) VALUES (2077008643727314944, 2077007721974484992, 2077007722058371072, 2, '重生1985', '小明躺在地上,睁开眼,阳光刺眼。他坐起身,低头看见自己穿着蓝色工装,手背皮肤光滑无皱纹。他摸自己的脸,感觉紧致年轻。旁边老式自行车铃响,一个年轻人骑车路过喊“小明,上班迟到了!”小明看向路口停着的二八自行车和墙上红色标语“时间就是金钱”,低头看手腕电子表显示1985.6,他深吸一口气,眼神从迷茫变成坚定,低语“再来一次”。', 'emotion', '平视近景转特写', '缓推加环绕', '[{\"name\":\"小明\",\"appearance\":\"初始形象\",\"slot\":\"地面中央\"}]', '小巷_日_1985', '{\"panel_number\":2,\"scene_summary\":\"小明躺在地上,睁开眼,阳光刺眼。他坐起身,低头看见自己穿着蓝色工装,手背皮肤光滑无皱纹。他摸自己的脸,感觉紧致年轻。旁边老式自行车铃响,一个年轻人骑车路过喊“小明,上班迟到了!”小明看向路口停着的二八自行车和墙上红色标语“时间就是金钱”,低头看手腕电子表显示1985.6,他深吸一口气,眼神从迷茫变成坚定,低语“再来一次”。\",\"lighting\":{\"direction\":\"根据场景主光方向保持连续\",\"quality\":\"柔和侧光,突出面部情绪\"},\"characters\":[{\"name\":\"小明\",\"screen_position\":\"地面中央\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"}],\"depth_of_field\":\"浅景深,突出角色表情\",\"color_tone\":\"克制柔和色调\"}', '[{\"name\":\"小明\",\"acting\":\"表情逐步变化,先克制呼吸,再通过眼神和细微肢体释放情绪,按前段、中段、后段完成三个连续表演节拍\"}]', '{\"start_state\":\"新场景建立:小巷_日_1985,重新交代人物位置、朝向与环境\",\"end_state\":\"小明站立,眼神坚定,低头看电子表,嘴唇微动说“再来一次”\",\"continuity_action\":\"小明视线从手表移向前方街道,准备行动\",\"spatial_anchor\":\"小明位于小巷中央地面,左侧墙上有红色标语,右侧有自行车和骑车年轻人,背景是老旧居民楼\",\"present_characters\":[\"小明\",\"年轻人(群众)\"],\"scene_number\":2,\"segment_number\":1,\"segment_goal\":\"展示小明穿越后醒来发现变成年轻模样\",\"segment_result\":\"小明确认自己回到1985年,眼神由迷茫变坚定\",\"bridge_in\":\"画面从黑场渐亮,小明面部特写从模糊到清晰\",\"bridge_out\":\"小明深吸一口气并说出内心决定,视线看向前方街道\",\"beat_type\":\"reaction\",\"narrative_cause\":\"小明触电昏迷,穿越时空\",\"character_goal\":\"确认自身状态和时代\",\"story_action\":\"坐起、摸脸、看周围、看电子表\",\"story_result\":\"小明确定自己重生,产生第二次人生的决心\",\"next_hook\":\"下一镜头展示小明带着方案前往街道办\"}', '小明醒来,发现自己躺在地上,身穿80年代蓝色工装。他摸着脸——没有皱纹。旁边老式自行车铃响,一个年轻人喊:“小明,上班迟到了!”小明看着路口的二八自行车,墙上的标语“时间就是金钱”,愣住。他低头看手腕上的电子表:1985年6月。他深吸一口气,眼神从迷茫变成坚定:“再来一次。”', '小明坐在小巷地面,身穿蓝色工装,阳光从巷口射入照亮他的脸,他摸着自己年轻的脸庞,眼神迷茫;背景是青砖墙和红色标语,一辆老式自行车靠在墙边。', 10, '年轻男子躺在地面上,阳光刺眼,他缓缓睁开眼,然后坐起身,低头看自己双手和蓝色工装,摸自己的脸,表情从迷茫到惊讶。旁边传来自行车铃声,他转头看向巷口的二八自行车和「时间就是金钱」标语,再低头看手腕上的电子表,眼神从迷茫变为坚定。镜头从全景缓慢推近至脸部特写,同时环绕拍摄,最后固定。', 'https://atlas-media.oss-us-west-1.aliyuncs.com/videos/cgt-20260714203913-lxtrb-0.mp4', 'b3b6843f0b78433893608675852797bd', 'done', -1, -1, '2026-07-14 20:33:44', -1, '2026-07-14 20:47:08', 0);
+INSERT INTO `short_drama_storyboard` (`id`, `project_id`, `script_id`, `scene_no`, `scene_title`, `scene_text`, `scene_type`, `shot_type`, `camera_move`, `characters_json`, `location_name`, `photography_rules`, `acting_notes`, `continuity_json`, `source_text`, `image_prompt`, `duration_seconds`, `video_prompt`, `video_url`, `video_id`, `video_status`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`) VALUES (2077008643781840896, 2077007721974484992, 2077007722058371072, 3, '街道办受阻遇老陈', '街道办门口,小明拿着一叠手写方案快步走向大门。门卫伸出手臂挡住他。小明急切地解释“同志,我有商业计划,能帮工厂接全国订单!”门卫皱眉推他出去,纸张散落一地。小明蹲下慌乱捡纸。路对面一个穿中山装的中年男人(老陈)弯腰捡起一张,看着上面的字,抬头问:“你这上面写的‘电商’是啥?”小明抬头,眼睛一亮:“陈厂长,我能让您仓库里的积压货三天卖掉。”', 'daily', '平视中景', '轻微跟随', '[{\"name\":\"小明\",\"appearance\":\"初始形象\",\"slot\":\"门口台阶下\"},{\"name\":\"老陈\",\"appearance\":\"初始形象\",\"slot\":\"路对面人行道\"}]', '街道办门口_日', '{\"panel_number\":3,\"scene_summary\":\"街道办门口,小明拿着一叠手写方案快步走向大门。门卫伸出手臂挡住他。小明急切地解释“同志,我有商业计划,能帮工厂接全国订单!”门卫皱眉推他出去,纸张散落一地。小明蹲下慌乱捡纸。路对面一个穿中山装的中年男人(老陈)弯腰捡起一张,看着上面的字,抬头问:“你这上面写的‘电商’是啥?”小明抬头,眼睛一亮:“陈厂长,我能让您仓库里的积压货三天卖掉。”\",\"lighting\":{\"direction\":\"根据场景主光方向保持连续\",\"quality\":\"自然柔光,肤色与环境协调\"},\"characters\":[{\"name\":\"小明\",\"screen_position\":\"门口台阶下\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"},{\"name\":\"老陈\",\"screen_position\":\"路对面人行道\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"}],\"depth_of_field\":\"中等景深,兼顾角色与环境\",\"color_tone\":\"自然统一色调\"}', '[{\"name\":\"小明\",\"acting\":\"保持自然呼吸和目光交流,动作从起始状态平滑过渡到结束状态,按前段、中段、后段完成三个连续表演节拍\"},{\"name\":\"老陈\",\"acting\":\"保持自然呼吸和目光交流,动作从起始状态平滑过渡到结束状态,按前段、中段、后段完成三个连续表演节拍\"}]', '{\"start_state\":\"新场景建立:街道办门口_日,重新交代人物位置、朝向与环境\",\"end_state\":\"小明蹲在地上抬头看向老陈,老陈站在路对面手持一张纸,两人视线交汇\",\"continuity_action\":\"小明视线锁定老陈,准备进一步解释\",\"spatial_anchor\":\"街道办铁门在画面左侧,门卫站在台阶上;小明在台阶下中央;老陈在画面右侧路对面行道树旁\",\"present_characters\":[\"小明\",\"老陈\",\"门卫(群众)\"],\"scene_number\":3,\"segment_number\":1,\"segment_goal\":\"小明尝试进入街道办被门卫阻拦,吸引老陈注意\",\"segment_result\":\"老陈捡起散落的方案并开始询问\",\"bridge_in\":\"小明拿着方案走向街道办大门,眼神充满希望\",\"bridge_out\":\"老陈目光落在方案上,问题引发后续对话\",\"beat_type\":\"trigger\",\"narrative_cause\":\"小明确定自己重生,产生第二次人生的决心\",\"character_goal\":\"进入街道办寻求支持\",\"story_action\":\"小明上前解释,被推倒,捡纸时发现老陈在看方案\",\"story_result\":\"老陈对方案产生好奇并主动与小明对话\",\"next_hook\":\"下一镜头展示两人在废弃仓库深入讨论\"}', '小明拿着一叠手写方案,站在街道办门口。门卫拦住他。小明:“同志,我有商业计划,能帮工厂接全国订单!”门卫:“胡闹!”推他出去。小明捡起散落的纸,抬头看到路对面一个穿中山装的中年男人(老陈)正在看他的方案。老陈:“你这上面写的‘电商’是啥?”小明眼睛一亮:“陈厂长,我能让您仓库里的积压货三天卖掉。”', '小明站在街道办门口台阶下,手拿一叠方案,表情急切;门卫站在台阶上伸手阻拦;路对面老陈穿中山装低头看纸,阳光从右上方照射。', 8, '年轻男子拿着一叠手写方案快步走向街道办大门,门卫伸出手臂阻挡。年轻男子急切地解释,门卫皱眉推他出去,纸张散落。年轻男子蹲下慌乱捡纸。路对面一位中年男子弯腰捡起一张纸,看着上面,抬头问话。镜头平视跟随年轻男子移动,然后切换到越肩视角展示门卫的阻拦动作。', 'https://atlas-media.oss-us-west-1.aliyuncs.com/videos/cgt-20260714203920-6rw8b-0.mp4', '7173c12461574b8abd063c46fc625ebe', 'done', -1, -1, '2026-07-14 20:33:44', -1, '2026-07-14 20:47:09', 0);
+INSERT INTO `short_drama_storyboard` (`id`, `project_id`, `script_id`, `scene_no`, `scene_title`, `scene_text`, `scene_type`, `shot_type`, `camera_move`, `characters_json`, `location_name`, `photography_rules`, `acting_notes`, `continuity_json`, `source_text`, `image_prompt`, `duration_seconds`, `video_prompt`, `video_url`, `video_id`, `video_status`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`) VALUES (2077008643823783936, 2077007721974484992, 2077007722058371072, 4, '仓库达成合作', '废弃仓库内,一张木桌两把椅子,小明和老陈对面而坐。桌上摆着两盒烟,老陈抽出一根点燃:“我信你一次,但怎么弄?”小明拿起笔在纸上画示意图:“用电话线连电脑,搞个库存信息库。我写程序。”老陈皱眉:“钱呢?”小明:“我先拉商户,您出设备。”老陈抖了抖烟灰,沉默几秒后点头。小明转头看向墙上的标语“工业学大庆”,低声:“这次一定要成。”', 'daily', '平视中景', '缓推', '[{\"name\":\"小明\",\"appearance\":\"初始形象\",\"slot\":\"桌子一侧\"},{\"name\":\"老陈\",\"appearance\":\"初始形象\",\"slot\":\"桌子另一侧\"}]', '废弃仓库_日', '{\"panel_number\":4,\"scene_summary\":\"废弃仓库内,一张木桌两把椅子,小明和老陈对面而坐。桌上摆着两盒烟,老陈抽出一根点燃:“我信你一次,但怎么弄?”小明拿起笔在纸上画示意图:“用电话线连电脑,搞个库存信息库。我写程序。”老陈皱眉:“钱呢?”小明:“我先拉商户,您出设备。”老陈抖了抖烟灰,沉默几秒后点头。小明转头看向墙上的标语“工业学大庆”,低声:“这次一定要成。”\",\"lighting\":{\"direction\":\"根据场景主光方向保持连续\",\"quality\":\"自然柔光,肤色与环境协调\"},\"characters\":[{\"name\":\"小明\",\"screen_position\":\"桌子一侧\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"},{\"name\":\"老陈\",\"screen_position\":\"桌子另一侧\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"}],\"depth_of_field\":\"中等景深,兼顾角色与环境\",\"color_tone\":\"自然统一色调\"}', '[{\"name\":\"小明\",\"acting\":\"保持自然呼吸和目光交流,动作从起始状态平滑过渡到结束状态,按前段、中段、后段完成三个连续表演节拍\"},{\"name\":\"老陈\",\"acting\":\"保持自然呼吸和目光交流,动作从起始状态平滑过渡到结束状态,按前段、中段、后段完成三个连续表演节拍\"}]', '{\"start_state\":\"新场景建立:废弃仓库_日,重新交代人物位置、朝向与环境\",\"end_state\":\"老陈点头,小明目光从墙上标语收回,表情坚定\",\"continuity_action\":\"小明视线从标语移回老陈,准备下一步计划\",\"spatial_anchor\":\"桌子位于仓库中央,小明坐画面左侧,老陈坐右侧,后面墙上有标语,水泥地面空旷\",\"present_characters\":[\"小明\",\"老陈\"],\"scene_number\":4,\"segment_number\":1,\"segment_goal\":\"小明与老陈在仓库达成合作意向\",\"segment_result\":\"老陈决定信任小明,提供设备支持\",\"bridge_in\":\"两人对面而坐,桌上两盒烟,老陈面露犹豫\",\"bridge_out\":\"老陈点头,小明看向墙上标语,低声坚定信念\",\"beat_type\":\"action\",\"narrative_cause\":\"老陈对方案产生好奇并主动与小明对话\",\"character_goal\":\"说服老陈提供设备支持\",\"story_action\":\"小明画图解释技术方案,提出资源分工\",\"story_result\":\"老陈同意合作,小明获得初步资源\",\"next_hook\":\"下一镜头展示工厂办公室内新进展与危机\"}', '老陈和小明对面坐着。桌上摆着两盒烟。老陈:“我信你一次,但怎么弄?”小明在纸上画:“用电话线连电脑,搞个库存信息库。我写程序。”老陈:“钱呢?”小明:“我先拉商户,您出设备。”老陈犹豫后点头。小明看着仓库墙上的“工业学大庆”,低声:“这次一定要成。”', '小明和老陈在废弃仓库的旧木桌对面而坐,桌上两盒烟和散落的纸张;老陈夹烟沉思,小明执笔画示意图;背景墙上红色大字「工业学大庆」,高窗透入光线。', 8, '年轻男子和中年男子对面坐在木桌两侧,桌上摆着两盒烟。中年男子抽出一根点燃,年轻男子拿起笔在纸上画图并说话。中年男子皱眉问话,年轻男子抬头回答,伸手指向纸面。中年男子抖烟灰后点头。年轻男子转头看向墙上的标语,低声自语。镜头从两人的中景缓缓推近至年轻男子的脸部,然后固定。', NULL, 'd4665ee140f34673914292855d389d38', 'generating', -1, -1, '2026-07-14 20:33:44', -1, '2026-07-14 20:39:20', 0);
+INSERT INTO `short_drama_storyboard` (`id`, `project_id`, `script_id`, `scene_no`, `scene_title`, `scene_text`, `scene_type`, `shot_type`, `camera_move`, `characters_json`, `location_name`, `photography_rules`, `acting_notes`, `continuity_json`, `source_text`, `image_prompt`, `duration_seconds`, `video_prompt`, `video_url`, `video_id`, `video_status`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`) VALUES (2077008643874115584, 2077007721974484992, 2077007722058371072, 5, '工商检查危机', '工厂办公室内,木制办公桌上转盘电话响起。老陈拿起听筒,脸色逐渐变白,手指捏紧话筒。挂断后他转身对旁边椅子上的小明说:“国营百货举报我们投机倒把,工商明天来查。”小明快速翻看桌上的账本,抬起头:“我们走的是信息服务,不是倒卖。”老陈叹气:“没人认可这个。”小明合上账本,直视老陈:“明天我来说。”', 'suspense', '平视近景', '缓推', '[{\"name\":\"老陈\",\"appearance\":\"初始形象\",\"slot\":\"办公桌后\"},{\"name\":\"小明\",\"appearance\":\"初始形象\",\"slot\":\"办公桌旁椅子\"}]', '工厂办公室_日', '{\"panel_number\":5,\"scene_summary\":\"工厂办公室内,木制办公桌上转盘电话响起。老陈拿起听筒,脸色逐渐变白,手指捏紧话筒。挂断后他转身对旁边椅子上的小明说:“国营百货举报我们投机倒把,工商明天来查。”小明快速翻看桌上的账本,抬起头:“我们走的是信息服务,不是倒卖。”老陈叹气:“没人认可这个。”小明合上账本,直视老陈:“明天我来说。”\",\"lighting\":{\"direction\":\"根据场景主光方向保持连续\",\"quality\":\"低调硬光,保留阴影层次\"},\"characters\":[{\"name\":\"老陈\",\"screen_position\":\"办公桌后\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"},{\"name\":\"小明\",\"screen_position\":\"办公桌旁椅子\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"}],\"depth_of_field\":\"中浅景深,保留环境压迫感\",\"color_tone\":\"冷暗色调\"}', '[{\"name\":\"老陈\",\"acting\":\"控制呼吸与眨眼频率,用迟疑、停顿和缓慢转头制造紧张感\"},{\"name\":\"小明\",\"acting\":\"控制呼吸与眨眼频率,用迟疑、停顿和缓慢转头制造紧张感\"}]', '{\"start_state\":\"新场景建立:工厂办公室_日,重新交代人物位置、朝向与环境\",\"end_state\":\"小明合上账本,直视老陈,表情自信;老陈眉头紧锁但不再反驳\",\"continuity_action\":\"小明视线坚定,老陈目光仍带忧虑但转向信任\",\"spatial_anchor\":\"老陈位于画面左侧办公桌后,小明在右侧椅子,窗外可见厂区烟囱,文件柜靠墙\",\"present_characters\":[\"小明\",\"老陈\"],\"scene_number\":5,\"segment_number\":1,\"segment_goal\":\"工厂办公室内老陈接到工商查处的电话,小明提出应对\",\"segment_result\":\"小明决定亲自去面对工商检查\",\"bridge_in\":\"办公室电话铃响打破平静,老陈接听表情变化\",\"bridge_out\":\"老陈看向小明,小明坚定地说“明天我来说”\",\"beat_type\":\"trigger\",\"narrative_cause\":\"老陈同意合作,小明获得初步资源\",\"character_goal\":\"让老陈相信自己能解决危机\",\"story_action\":\"小明解释模式合法性,并主动承担交涉责任\",\"story_result\":\"老陈部分安心,小明获得应对危机的授权\",\"next_hook\":\"下一镜头展示出租屋内团队内部争吵与统一思想\"}', '办公桌上电话响起。老陈接起,脸色变白。挂断后对小明:“国营百货举报我们投机倒把,工商明天来查。”小明快速翻看账本:“我们走的是信息服务,不是倒卖。”老陈:“没人认可这个。”小明:“明天我来说。”', '工厂办公室内,老陈坐在办公桌后接电话,脸色凝重;小明坐在侧面椅子上翻看账本,窗外可见工厂烟囱;桌上转盘电话和文件散落。', 7, '办公桌上黑色转盘电话响起。中年男子坐在桌后拿起听筒,脸色逐渐变白,手指捏紧话筒。他挂断后转身对旁边的年轻男子说话。年轻男子快速翻看账本,抬起头直视对方回话,然后合上账本。镜头从电话特写缓慢推近至中年男子面部,再缓拉到两人中景。', 'https://atlas-media.oss-us-west-1.aliyuncs.com/videos/cgt-20260714203917-gnb2m-0.mp4', '61edb37e979a426f9e8272786243c243', 'done', -1, -1, '2026-07-14 20:33:44', -1, '2026-07-14 20:41:08', 0);
+INSERT INTO `short_drama_storyboard` (`id`, `project_id`, `script_id`, `scene_no`, `scene_title`, `scene_text`, `scene_type`, `shot_type`, `camera_move`, `characters_json`, `location_name`, `photography_rules`, `acting_notes`, `continuity_json`, `source_text`, `image_prompt`, `duration_seconds`, `video_prompt`, `video_url`, `video_id`, `video_status`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`) VALUES (2077008643920252928, 2077007721974484992, 2077007722058371072, 6, '出租屋统一思想', '狭小出租屋,灯光昏暗。两个年轻团队成员拍桌站起:“不干了,风险太大!”老陈坐在床边沉默,低头看地面。小明从墙角拿起一块黑板放在桌上,画出一条时间轴,标注1985年,指向电脑图标。他转头对大家说:“1985年,电脑刚进中国,我们的优势是信息差。不做商品买卖,做平台——帮工厂和供销社匹配库存。”他指着黑板:“明天工商来,我就说这是‘技术咨询’。”老陈抬头,皱眉问:“你哪来的这些?”小明停顿一下:“梦里学的。”', 'emotion', '平视近景转特写', '缓推加环绕', '[{\"name\":\"小明\",\"appearance\":\"初始形象\",\"slot\":\"桌边站立\"},{\"name\":\"老陈\",\"appearance\":\"初始形象\",\"slot\":\"床边坐着\"}]', '出租屋_夜', '{\"panel_number\":6,\"scene_summary\":\"狭小出租屋,灯光昏暗。两个年轻团队成员拍桌站起:“不干了,风险太大!”老陈坐在床边沉默,低头看地面。小明从墙角拿起一块黑板放在桌上,画出一条时间轴,标注1985年,指向电脑图标。他转头对大家说:“1985年,电脑刚进中国,我们的优势是信息差。不做商品买卖,做平台——帮工厂和供销社匹配库存。”他指着黑板:“明天工商来,我就说这是‘技术咨询’。”老陈抬头,皱眉问:“你哪来的这些?”小明停顿一下:“梦里学的。”\",\"lighting\":{\"direction\":\"根据场景主光方向保持连续\",\"quality\":\"柔和侧光,突出面部情绪\"},\"characters\":[{\"name\":\"小明\",\"screen_position\":\"桌边站立\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"},{\"name\":\"老陈\",\"screen_position\":\"床边坐着\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"}],\"depth_of_field\":\"浅景深,突出角色表情\",\"color_tone\":\"克制柔和色调\"}', '[{\"name\":\"小明\",\"acting\":\"表情逐步变化,先克制呼吸,再通过眼神和细微肢体释放情绪,按前段、中段、后段完成三个连续表演节拍\"},{\"name\":\"老陈\",\"acting\":\"表情逐步变化,先克制呼吸,再通过眼神和细微肢体释放情绪,按前段、中段、后段完成三个连续表演节拍\"}]', '{\"start_state\":\"新场景建立:出租屋_夜,重新交代人物位置、朝向与环境\",\"end_state\":\"老陈抬头看向小明,两个年轻人停止争吵望向黑板,小黑板上画有时间轴和“电脑”字样\",\"continuity_action\":\"小明手指还指着黑板上的“技术咨询”,等待异议\",\"spatial_anchor\":\"画面中央是一张桌子,黑板靠在桌上,小明站在桌子左侧画黑板,老陈坐在右侧床边,两个年轻人站在桌子远端\",\"present_characters\":[\"小明\",\"老陈\",\"两个年轻人(群众)\"],\"scene_number\":6,\"segment_number\":1,\"segment_goal\":\"出租屋内团队成员因风险而退缩,小明用时间轴规划说服大家\",\"segment_result\":\"老陈和小明达成共识,团队重拾信心\",\"bridge_in\":\"出租屋内两个年轻人拍桌起身,气氛紧张\",\"bridge_out\":\"老陈抬头看小明,眼神中带着疑惑与信任\",\"beat_type\":\"decision\",\"narrative_cause\":\"老陈部分安心,小明获得应对危机的授权\",\"character_goal\":\"稳定团队,统一认知\",\"story_action\":\"小明画出时间轴,解释信息差优势和应对策略\",\"story_result\":\"团队情绪稳定,老陈虽疑惑但接受解释\",\"next_hook\":\"下一镜头展示百货大楼门口工商检查的结果\"}', '团队成员(两个年轻人)拍桌:“不干了,风险太大!”老陈沉默。小明拿出一块黑板,画出时间轴:“1985年,电脑刚进中国,我们的优势是信息差。不做商品买卖,做平台——帮工厂和供销社匹配库存。”他指着黑板:“明天工商来,我就说这是‘技术咨询’。”老陈抬头:“你哪来的这些?”小明:“梦里学的。”', '出租屋内,小明站在桌子左侧画黑板,黑板上粉笔写着时间轴和「电脑」字样;老陈坐在床边抬头看;两个年轻人站在桌子远端,表情从愤怒转为倾听;昏黄灯光下气氛紧张。', 10, '狭小出租屋内,两个年轻人拍桌站起情绪激动。中年男子坐在床边低头沉默。年轻男子从墙角拿起一块黑板放在桌上,用粉笔画出一条时间轴,标注1985和电脑图标,转头对大家说话并指向黑板。中年男子抬起头皱眉问话,年轻男子停顿后回答。镜头从全景缓慢推近至年轻男子面部特写,然后环绕拍摄黑板上的时间轴。', NULL, NULL, 'pending', -1, -1, '2026-07-14 20:33:44', -1, '2026-07-14 20:33:44', 0);
+INSERT INTO `short_drama_storyboard` (`id`, `project_id`, `script_id`, `scene_no`, `scene_title`, `scene_text`, `scene_type`, `shot_type`, `camera_move`, `characters_json`, `location_name`, `photography_rules`, `acting_notes`, `continuity_json`, `source_text`, `image_prompt`, `duration_seconds`, `video_prompt`, `video_url`, `video_id`, `video_status`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`) VALUES (2077008643978973184, 2077007721974484992, 2077007722058371072, 7, '工商检查通过', '百货大楼门口台阶上,工商人员和穿藏青色西装的中年经理站在一起。小明从公文包拿出一叠表格递过去:“这是通过我们信息服务成交的订单,全部有记录,不碰资金,只收咨询费。”工商人员翻看后递给旁边的百货经理。经理推了推眼镜细看,低声问小明:“这方法能帮我们清库存?”小明点头:“三天见效。”经理转向工商人员点了点头。工商人员收起表格:“先观察。”', 'daily', '平视中景', '轻微跟随', '[{\"name\":\"小明\",\"appearance\":\"初始形象\",\"slot\":\"台阶上右侧\"},{\"name\":\"老陈\",\"appearance\":\"初始形象\",\"slot\":\"台阶上小明身后\"},{\"name\":\"百货经理\",\"appearance\":\"初始形象\",\"slot\":\"台阶上中央\"}]', '百货大楼门口_日', '{\"panel_number\":7,\"scene_summary\":\"百货大楼门口台阶上,工商人员和穿藏青色西装的中年经理站在一起。小明从公文包拿出一叠表格递过去:“这是通过我们信息服务成交的订单,全部有记录,不碰资金,只收咨询费。”工商人员翻看后递给旁边的百货经理。经理推了推眼镜细看,低声问小明:“这方法能帮我们清库存?”小明点头:“三天见效。”经理转向工商人员点了点头。工商人员收起表格:“先观察。”\",\"lighting\":{\"direction\":\"根据场景主光方向保持连续\",\"quality\":\"自然柔光,肤色与环境协调\"},\"characters\":[{\"name\":\"小明\",\"screen_position\":\"台阶上右侧\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"},{\"name\":\"老陈\",\"screen_position\":\"台阶上小明身后\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"},{\"name\":\"百货经理\",\"screen_position\":\"台阶上中央\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"}],\"depth_of_field\":\"中等景深,兼顾角色与环境\",\"color_tone\":\"自然统一色调\"}', '[{\"name\":\"小明\",\"acting\":\"保持自然呼吸和目光交流,动作从起始状态平滑过渡到结束状态,按前段、中段、后段完成三个连续表演节拍\"},{\"name\":\"老陈\",\"acting\":\"保持自然呼吸和目光交流,动作从起始状态平滑过渡到结束状态,按前段、中段、后段完成三个连续表演节拍\"},{\"name\":\"百货经理\",\"acting\":\"保持自然呼吸和目光交流,动作从起始状态平滑过渡到结束状态,按前段、中段、后段完成三个连续表演节拍\"}]', '{\"start_state\":\"新场景建立:百货大楼门口_日,重新交代人物位置、朝向与环境\",\"end_state\":\"工商人员收起表格,经理向小明点头,小明露出微笑\",\"continuity_action\":\"小明视线跟随工商人员离开,准备下一步行动\",\"spatial_anchor\":\"百货大楼正门台阶为背景,工商人员在中央偏左,经理在左侧,小明在右侧,老陈在小明后方半步\",\"present_characters\":[\"小明\",\"老陈\",\"百货经理\",\"工商人员(群众)\"],\"scene_number\":7,\"segment_number\":1,\"segment_goal\":\"工商检查现场,小明用订单记录证明信息服务合法性,获得百货经理认可\",\"segment_result\":\"工商同意观察,项目得以继续\",\"bridge_in\":\"百货大楼门口,工商人员和小明、老陈站立,气氛凝重\",\"bridge_out\":\"工商人员收起表格,经理点头,危机解除\",\"beat_type\":\"result\",\"narrative_cause\":\"团队情绪稳定,老陈虽疑惑但接受解释\",\"character_goal\":\"用事实凭证打消工商疑虑\",\"story_action\":\"小明出示订单记录并解释运营模式\",\"story_result\":\"工商暂缓处理,项目获得官方默许\",\"next_hook\":\"下一镜头展示庆功礼堂的成果与小明的情感时刻\"}', '工商人员和小明、老陈站在门口。小明拿出一份表格:“这是通过我们信息服务成交的订单,全部有记录,不碰资金,只收咨询费。”工商人员翻看,递给旁边一个戴眼镜的中年人(百货公司经理)。经理看了后低声:“这方法能帮我们清库存?”小明:“三天见效。”经理点头。工商人员收起表格:“先观察。”', '小明站在百货大楼门口台阶上,从公文包中拿出表格递给工商人员;老陈站在他身后;旁边穿藏青色西装的百货经理低头查看表格;阳光照亮大楼立面。', 8, '百货大楼门口台阶上,工商人员和穿西装的中年男子站在一起。年轻男子从公文包拿出一叠表格递出并说话。工商人员翻看后递给旁边的经理。经理推了推眼镜细看,低声问年轻男子,年轻男子点头回答。经理转向工商人员点头。工商人员收起表格。镜头平视跟随年轻男子的动作,使用越肩视角展示表格内容。', NULL, NULL, 'pending', -1, -1, '2026-07-14 20:33:44', -1, '2026-07-14 20:33:44', 0);
+INSERT INTO `short_drama_storyboard` (`id`, `project_id`, `script_id`, `scene_no`, `scene_title`, `scene_text`, `scene_type`, `shot_type`, `camera_move`, `characters_json`, `location_name`, `photography_rules`, `acting_notes`, `continuity_json`, `source_text`, `image_prompt`, `duration_seconds`, `video_prompt`, `video_url`, `video_id`, `video_status`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`) VALUES (2077008644041887744, 2077007721974484992, 2077007722058371072, 8, '厂庆宣言互联网愿景', '厂庆礼堂,红灯笼和横幅装饰,舞台上麦克风前,老陈对着台下说:“感谢小明的信息平台,咱们工厂活了。”台下工人鼓掌。小明站在侧台阴影里,手伸进口袋摸到发黄的现代身份证,他看着灯光下兴奋的面孔,默默将身份证撕碎。主持人喊:“请小明同志讲话!”小明走上舞台中央,拿起话筒,停顿三秒:“各位,未来三十年,互联网会改变一切。今天,我们从这里开始。”台下掌声雷动。', 'epic', '大远景转特写', '俯拍后缓降推近', '[{\"name\":\"小明\",\"appearance\":\"初始形象\",\"slot\":\"舞台上中央\"},{\"name\":\"老陈\",\"appearance\":\"初始形象\",\"slot\":\"舞台侧边\"}]', '厂庆礼堂_夜', '{\"panel_number\":8,\"scene_summary\":\"厂庆礼堂,红灯笼和横幅装饰,舞台上麦克风前,老陈对着台下说:“感谢小明的信息平台,咱们工厂活了。”台下工人鼓掌。小明站在侧台阴影里,手伸进口袋摸到发黄的现代身份证,他看着灯光下兴奋的面孔,默默将身份证撕碎。主持人喊:“请小明同志讲话!”小明走上舞台中央,拿起话筒,停顿三秒:“各位,未来三十年,互联网会改变一切。今天,我们从这里开始。”台下掌声雷动。\",\"lighting\":{\"direction\":\"根据场景主光方向保持连续\",\"quality\":\"大范围自然光,突出空间规模\"},\"characters\":[{\"name\":\"小明\",\"screen_position\":\"舞台上中央\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"},{\"name\":\"老陈\",\"screen_position\":\"舞台侧边\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"}],\"depth_of_field\":\"深景深,清晰展现环境规模\",\"color_tone\":\"宏大通透色调\"}', '[{\"name\":\"小明\",\"acting\":\"动作沉稳有力量,视线跟随环境或对手变化,保持画面张力,按前段、中段、后段完成三个连续表演节拍\"},{\"name\":\"老陈\",\"acting\":\"动作沉稳有力量,视线跟随环境或对手变化,保持画面张力,按前段、中段、后段完成三个连续表演节拍\"}]', '{\"start_state\":\"新场景建立:厂庆礼堂_夜,重新交代人物位置、朝向与环境\",\"end_state\":\"小明站在舞台中央举起话筒,台下工人站立鼓掌,老陈在侧台微笑\",\"continuity_action\":\"小明视线扫过全场,准备下台开始新阶段\",\"spatial_anchor\":\"舞台在画面中央靠上,台下长凳坐满工人,小明位于舞台中央,老陈在舞台左侧靠边\",\"present_characters\":[\"小明\",\"老陈\",\"工人(群众)\",\"主持人(群众)\"],\"scene_number\":8,\"segment_number\":1,\"segment_goal\":\"厂庆礼堂中老陈表扬小明,小明撕碎现代身份证并发表讲话\",\"segment_result\":\"小明公开宣告互联网未来愿景,全体工人热烈鼓掌\",\"bridge_in\":\"礼堂内工人坐满长凳,老陈在台上讲话\",\"bridge_out\":\"掌声雷动中,小明眼神坚定望向未来\",\"beat_type\":\"action\",\"narrative_cause\":\"工商暂缓处理,项目获得官方默许\",\"character_goal\":\"激励团队并宣告新方向\",\"story_action\":\"小明撕碎现代身份证,上台演讲\",\"story_result\":\"全体工人被鼓舞,小明确立新一代领导地位\",\"next_hook\":\"下一镜头展示清晨新挂牌和下一步计划\"}', '工人坐满长凳。老陈上台:“感谢小明的信息平台,咱们工厂活了。”台下鼓掌。小明站在侧台,看着灯光下兴奋的面孔。他手摸到口袋里的现代身份证——早已发黄。他默默撕碎。主持人:“请小明同志讲话!”小明上前,拿着话筒停顿三秒:“各位,未来三十年,互联网会改变一切。今天,我们从这里开始。”台下掌声雷动。', '厂庆礼堂内,舞台中央老陈握着话筒讲话,台下工人鼓掌;小明站在侧幕阴影中,手中捏着撕碎的身份证,灯光照亮舞台,红灯笼和横幅装饰,气氛热烈。', 10, '礼堂内工人坐满长凳,舞台中央中年男子在讲话,台下鼓掌。年轻男子站在侧台阴影中,手伸进口袋掏出一张发黄的身份证,默默撕碎。主持人喊话,年轻男子走上舞台中央,拿起话筒停顿三秒后说话,台下掌声雷动。镜头从礼堂大远景俯拍开始,然后缓缓下降并推近至年轻男子面部特写。', NULL, NULL, 'pending', -1, -1, '2026-07-14 20:33:44', -1, '2026-07-14 20:33:44', 0);
+INSERT INTO `short_drama_storyboard` (`id`, `project_id`, `script_id`, `scene_no`, `scene_title`, `scene_text`, `scene_type`, `shot_type`, `camera_move`, `characters_json`, `location_name`, `photography_rules`, `acting_notes`, `continuity_json`, `source_text`, `image_prompt`, `duration_seconds`, `video_prompt`, `video_url`, `video_id`, `video_status`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `tenant_id`) VALUES (2077008644113190912, 2077007721974484992, 2077007722058371072, 9, '新征程启程', '清晨,阳光照在工厂大门新挂牌上,金边字体“华夏信息服务中心”。小明推着自行车走出来,老陈从后面追上:“下一步?”小明跨上车:“跑遍全国,建数据库。”老陈笑着摇头:“疯了。”小明回以笑容:“1985年,疯的人才能赢。”他蹬车远去,街道两旁的工厂烟囱开始冒烟,晨光中骑车背影越来越小。', 'epic', '大远景', '缓拉升起', '[{\"name\":\"小明\",\"appearance\":\"初始形象\",\"slot\":\"工厂大门前\"},{\"name\":\"老陈\",\"appearance\":\"初始形象\",\"slot\":\"门口台阶上\"}]', '工厂大门_晨', '{\"panel_number\":9,\"scene_summary\":\"清晨,阳光照在工厂大门新挂牌上,金边字体“华夏信息服务中心”。小明推着自行车走出来,老陈从后面追上:“下一步?”小明跨上车:“跑遍全国,建数据库。”老陈笑着摇头:“疯了。”小明回以笑容:“1985年,疯的人才能赢。”他蹬车远去,街道两旁的工厂烟囱开始冒烟,晨光中骑车背影越来越小。\",\"lighting\":{\"direction\":\"根据场景主光方向保持连续\",\"quality\":\"大范围自然光,突出空间规模\"},\"characters\":[{\"name\":\"小明\",\"screen_position\":\"工厂大门前\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"},{\"name\":\"老陈\",\"screen_position\":\"门口台阶上\",\"posture\":\"保持符合当前动作的自然姿态\",\"facing\":\"面向动作目标或对话对象\"}],\"depth_of_field\":\"深景深,清晰展现环境规模\",\"color_tone\":\"宏大通透色调\"}', '[{\"name\":\"小明\",\"acting\":\"动作沉稳有力量,视线跟随环境或对手变化,保持画面张力,按前段、中段、后段完成三个连续表演节拍\"},{\"name\":\"老陈\",\"acting\":\"动作沉稳有力量,视线跟随环境或对手变化,保持画面张力,按前段、中段、后段完成三个连续表演节拍\"}]', '{\"start_state\":\"新场景建立:工厂大门_晨,重新交代人物位置、朝向与环境\",\"end_state\":\"小明骑车远去的背影在街道尽头,烟囱冒烟,晨光笼罩\",\"continuity_action\":\"小明继续蹬车,老陈目送,街道向前延伸\",\"spatial_anchor\":\"工厂大门在画面左侧,新挂牌醒目;小明骑车向右远去,街道两旁有工厂围墙和烟囱;老陈站在门口台阶上\",\"present_characters\":[\"小明\",\"老陈\"],\"scene_number\":9,\"segment_number\":1,\"segment_goal\":\"新挂牌的清晨,小明与老陈对话后骑车远去,象征新征程\",\"segment_result\":\"小明骑车远去,烟囱冒烟,新的一天开始\",\"bridge_in\":\"阳光照在新挂牌上,小明推车出现\",\"bridge_out\":\"镜头定格在远去的背影和工厂烟囱,留下开放节奏\",\"beat_type\":\"result\",\"narrative_cause\":\"全体工人被鼓舞,小明确立新一代领导地位\",\"character_goal\":\"确定下一阶段行动计划\",\"story_action\":\"小明跨上自行车说出全国数据库计划\",\"story_result\":\"小明开始实际行动,留下奋斗的背影\",\"next_hook\":\"故事结束,无下一镜头\"}', '阳光照在新挂牌上:“华夏信息服务中心”。小明推着自行车出来,老陈追上:“下一步?”小明:“跑遍全国,建数据库。”老陈笑:“疯了。”小明跨上车:“1985年,疯的人才能赢。”他蹬车远去,街道两旁的工厂烟囱开始冒烟。', '清晨阳光照射工厂大门新挂牌「华夏信息服务中心」,小明推自行车站在门口,老陈站在台阶上微笑;远处烟囱冒烟,天空泛鱼肚白,街道延伸向远方。', 10, '清晨阳光照在工厂大门新挂牌上,金色字体「华夏信息服务中心」。年轻男子推自行车从门内走出,中年男子从后面追上,两人对话。年轻男子跨上自行车,蹬车远去,街道两旁的工厂烟囱开始冒烟,晨光中骑车背影越来越小。镜头从新挂牌特写缓缓拉远并升起,展现工厂全貌和远去的背影。', NULL, NULL, 'pending', -1, -1, '2026-07-14 20:33:44', -1, '2026-07-14 20:33:44', 0);
-- ----------------------------
-- Table structure for sj_distributed_lock
@@ -1953,6 +2287,15 @@ INSERT INTO `sys_config` VALUES (2018858143803641859, '154726', '用户管理-
INSERT INTO `sys_config` VALUES (2018858143803641860, '154726', '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 103, 1, '2026-02-04 09:24:25', 1, '2026-02-04 09:24:25', '深色主题theme-dark,浅色主题theme-light');
INSERT INTO `sys_config` VALUES (2018858143803641861, '154726', '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 103, 1, '2026-02-04 09:24:25', 1, '2026-02-04 09:24:25', '是否开启注册用户功能(true开启,false关闭)');
INSERT INTO `sys_config` VALUES (2018858143803641862, '154726', 'OSS预览列表资源开关', 'sys.oss.previewListResource', 'true', 'Y', 103, 1, '2026-02-04 09:24:25', 1, '2026-02-04 09:24:25', 'true:开启, false:关闭');
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2027192921483309058, '000000', 'HTTP请求节点响应模板', 'node.httpRequest.template', '✅ HTTP请求节点:结束响应 - ', 'Y', 103, 1, '2026-02-27 09:23:51', 1, '2026-02-27 09:31:41', NULL);
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2027193296990957569, '000000', '文生图节点响应模板', 'node.image.template', '🎨 文生图节点:结束响应 - 图片URL: ', 'Y', 103, 1, '2026-02-27 09:25:20', 1, '2026-02-27 09:31:52', NULL);
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2027193820393959425, '000000', '发送邮箱节点响应模板', 'node.mailsend.template', '📧 发送邮箱节点:结束响应 - ', 'Y', 103, 1, '2026-02-27 09:27:25', 1, '2026-02-27 09:32:05', NULL);
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2027194134438277122, '000000', '结束节点响应模板', 'node.end.template', '🔚 流程已执行完毕,如果您有其他需求,请随时重新发起请求。', 'Y', 103, 1, '2026-02-27 09:28:40', 1, '2026-02-27 09:32:53', NULL);
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2027206492573335554, '000000', '人机交互节点响应模板', 'node.humanFeedback.template', '👤 人机交互节点:等待用户操作 - ', 'Y', 103, 1, '2026-02-27 10:17:46', 1, '2026-02-27 10:17:46', NULL);
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2027208880369647617, '000000', '条件分支节点响应模板', 'node.switch.template', '🔀 条件分支节点:触发 -> 跳转到节点 ', 'Y', 103, 1, '2026-02-27 10:27:15', 1, '2026-02-27 10:35:54', NULL);
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2027213914603995137, '000000', '大模型回答节点响应模板', 'node.llmAnswer.template', '🤖 LLM 节点 生成回答:', 'Y', 103, 1, '2026-02-27 10:47:16', 1, '2026-02-27 10:52:40', NULL);
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2027214387000066050, '000000', '关键词提取响应模板', 'node.keywordExtractor.template', '🔑 关键词提取节点 处理完成 : ', 'Y', 103, 1, '2026-02-27 10:49:08', 1, '2026-02-27 10:52:08', NULL);
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2027217577397391361, '000000', '工作流异常响应模板', 'node.exception.template', '🛑 工作流发生异常:', 'N', 103, 1, '2026-02-27 11:01:49', 1, '2026-02-27 11:02:01', NULL);
-- ----------------------------
-- Table structure for sys_dept
@@ -2165,6 +2508,37 @@ CREATE TABLE `sys_logininfor` (
-- ----------------------------
-- Records of sys_logininfor
-- ----------------------------
+INSERT INTO `sys_logininfor` VALUES (2067087010153709570, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-06-17 11:28:42');
+INSERT INTO `sys_logininfor` VALUES (2067120324839292929, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-06-17 13:41:05');
+INSERT INTO `sys_logininfor` VALUES (2067178210017693697, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-06-17 17:31:06');
+INSERT INTO `sys_logininfor` VALUES (2067439136780369921, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-06-18 10:47:56');
+INSERT INTO `sys_logininfor` VALUES (2067509245943230465, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-06-18 15:26:31');
+INSERT INTO `sys_logininfor` VALUES (2067515184486297601, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-06-18 15:50:07');
+INSERT INTO `sys_logininfor` VALUES (2067536325229756417, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-06-18 17:14:08');
+INSERT INTO `sys_logininfor` VALUES (2067599466735149057, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-06-18 21:25:02');
+INSERT INTO `sys_logininfor` VALUES (2068942142755569665, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-06-22 14:20:21');
+INSERT INTO `sys_logininfor` VALUES (2068963471252791297, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-06-22 15:45:06');
+INSERT INTO `sys_logininfor` VALUES (2068986934684389377, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-06-22 17:18:20');
+INSERT INTO `sys_logininfor` VALUES (2069012061732057090, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '1', '密码输入错误1次', '2026-06-22 18:58:11');
+INSERT INTO `sys_logininfor` VALUES (2069012086394564609, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-06-22 18:58:16');
+INSERT INTO `sys_logininfor` VALUES (2069034797917339649, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-06-22 20:28:31');
+INSERT INTO `sys_logininfor` VALUES (2075512593476263937, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-10 17:28:58');
+INSERT INTO `sys_logininfor` VALUES (2075536378350891010, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-10 19:03:29');
+INSERT INTO `sys_logininfor` VALUES (2075536785592643586, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-10 19:05:06');
+INSERT INTO `sys_logininfor` VALUES (2075539196780572674, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-10 19:14:41');
+INSERT INTO `sys_logininfor` VALUES (2075539270906507265, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-10 19:14:59');
+INSERT INTO `sys_logininfor` VALUES (2075544342642126850, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-10 19:35:08');
+INSERT INTO `sys_logininfor` VALUES (2075603310492020737, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-10 23:29:27');
+INSERT INTO `sys_logininfor` VALUES (2075608688223178753, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-10 23:50:49');
+INSERT INTO `sys_logininfor` VALUES (2076851040791674882, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-14 10:07:29');
+INSERT INTO `sys_logininfor` VALUES (2076867711472353281, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-14 11:13:43');
+INSERT INTO `sys_logininfor` VALUES (2076916180597719042, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-14 14:26:19');
+INSERT INTO `sys_logininfor` VALUES (2076935225945997313, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-14 15:42:00');
+INSERT INTO `sys_logininfor` VALUES (2076944166545375233, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-14 16:17:32');
+INSERT INTO `sys_logininfor` VALUES (2076955097467768833, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-14 17:00:58');
+INSERT INTO `sys_logininfor` VALUES (2076972033710804993, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-14 18:08:16');
+INSERT INTO `sys_logininfor` VALUES (2077003517935505409, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-14 20:13:22');
+INSERT INTO `sys_logininfor` VALUES (2077008039416188930, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-07-14 20:31:20');
-- ----------------------------
-- Table structure for sys_menu
@@ -2320,6 +2694,13 @@ INSERT INTO `sys_menu` VALUES (2014, 'MCP市场删除', 2010, 4, '#', '', '', 1,
INSERT INTO `sys_menu` VALUES (2015, 'MCP市场刷新', 2010, 5, '#', '', '', 1, 0, 'F', '0', '0', 'mcp:market:refresh', '#', 103, 1, '2026-02-24 20:02:47', NULL, NULL, '');
INSERT INTO `sys_menu` VALUES (2016, 'MCP工具加载', 2010, 6, '#', '', '', 1, 0, 'F', '0', '0', 'mcp:market:load', '#', 103, 1, '2026-02-24 20:02:47', NULL, NULL, '');
INSERT INTO `sys_menu` VALUES (2017, 'MCP市场导出', 2010, 7, '#', '', '', 1, 0, 'F', '0', '0', 'mcp:market:export', '#', 103, 1, '2026-02-24 20:02:47', NULL, NULL, '');
+INSERT INTO `sys_menu` VALUES (3000, '智能体管理', 0, 1, 'agent', '', '', 1, 0, 'M', '0', '0', '', 'mdi:robot', 103, 1, '2026-07-07 21:37:37', NULL, NULL, '智能体管理目录');
+INSERT INTO `sys_menu` VALUES (3001, '智能体列表', 3000, 1, 'agent', 'agent/agent/index', '', 1, 0, 'C', '0', '0', 'agent:agent:list', 'mdi:robot-outline', 103, 1, '2026-07-07 21:37:37', NULL, NULL, '智能体列表菜单');
+INSERT INTO `sys_menu` VALUES (3002, '智能体查询', 3001, 1, '#', '', '', 1, 0, 'F', '0', '0', 'agent:agent:query', '#', 103, 1, '2026-07-07 21:37:37', NULL, NULL, '');
+INSERT INTO `sys_menu` VALUES (3003, '智能体新增', 3001, 2, '#', '', '', 1, 0, 'F', '0', '0', 'agent:agent:add', '#', 103, 1, '2026-07-07 21:37:37', NULL, NULL, '');
+INSERT INTO `sys_menu` VALUES (3004, '智能体修改', 3001, 3, '#', '', '', 1, 0, 'F', '0', '0', 'agent:agent:edit', '#', 103, 1, '2026-07-07 21:37:37', NULL, NULL, '');
+INSERT INTO `sys_menu` VALUES (3005, '智能体删除', 3001, 4, '#', '', '', 1, 0, 'F', '0', '0', 'agent:agent:remove', '#', 103, 1, '2026-07-07 21:37:37', NULL, NULL, '');
+INSERT INTO `sys_menu` VALUES (3006, '智能体导出', 3001, 5, '#', '', '', 1, 0, 'F', '0', '0', 'agent:agent:export', '#', 103, 1, '2026-07-07 21:37:37', NULL, NULL, '');
INSERT INTO `sys_menu` VALUES (11616, '工作流', 0, 6, 'workflow', '', '', 1, 0, 'M', '0', '0', '', 'mdi:workflow-outline', 103, 1, '2026-01-05 14:39:33', 1, '2026-01-05 14:56:07', '');
INSERT INTO `sys_menu` VALUES (11618, '我的任务', 0, 7, 'task', '', '', 1, 0, 'M', '0', '0', '', 'carbon:task-approved', 103, 1, '2026-01-05 14:39:33', NULL, NULL, '');
INSERT INTO `sys_menu` VALUES (11619, '我的待办', 11618, 2, 'taskWaiting', 'workflow/task/taskWaiting', '', 1, 1, 'C', '0', '0', '', 'ri:todo-line', 103, 1, '2026-01-05 14:39:33', NULL, NULL, '');
@@ -2429,6 +2810,15 @@ CREATE TABLE `sys_oper_log` (
-- ----------------------------
-- Records of sys_oper_log
-- ----------------------------
+INSERT INTO `sys_oper_log` VALUES (2056756437140963329, '000000', 'OSS对象存储', 1, 'org.ruoyi.system.controller.system.SysOssController.upload()', 'POST', 1, 'admin', '研发部门', '/resource/oss/upload', '127.0.0.1', '内网IP', '', '', 1, '上传文件失败,请检查配置信息:[software.amazon.awssdk.services.s3.model.S3Exception: The access key Id format you provided is invalid. (Service: S3, Status Code: 403, Request ID: NmEwYzdmNTFfOGEzMTI3MGJfOGE2Y19lNDUyZDk=)]', '2026-05-19 23:18:42', 2621);
+INSERT INTO `sys_oper_log` VALUES (2076944303757836289, '000000', '智能体管理', 2, 'org.ruoyi.controller.agent.AgentController.edit()', 'PUT', 1, 'admin', '研发部门', '/agent/agent', '127.0.0.1', '内网IP', '{\"id\":\"1\",\"agentName\":\"对话智能体\",\"agentDescribe\":\"对话智能体\",\"modelId\":\"2000585866022060033\",\"enableThinking\":\"0\",\"systemPrompt\":\"你是一个乐于助人的通用 AI 助手,请用简洁、准确的中文回答用户的问题。\",\"mcpToolIds\":[],\"skillNames\":[\"docx\"],\"knowledgeIds\":[],\"status\":\"0\",\"remark\":\"系统初始化的默认智能体,自动绑定首个启用的对话模型\"}', '{\"code\":200,\"msg\":\"操作成功\"}', 0, '', '2026-07-14 16:18:04', 23);
+INSERT INTO `sys_oper_log` VALUES (2076944338465701889, '000000', '会话管理', 1, 'org.ruoyi.controller.chat.ChatSessionController.add()', 'POST', 1, 'admin', '研发部门', '/system/session', '127.0.0.1', '内网IP', '{\"id\":\"2076944338398593026\",\"userId\":\"1\",\"sessionTitle\":\"你好\",\"sessionContent\":\"你好\",\"remark\":\"你好\"}', '{\"code\":200,\"msg\":\"操作成功\",\"data\":\"2076944338398593026\"}', 0, '', '2026-07-14 16:18:13', 19);
+INSERT INTO `sys_oper_log` VALUES (2076957117130002434, '000000', '会话管理', 1, 'org.ruoyi.controller.chat.ChatSessionController.add()', 'POST', 1, 'admin', '研发部门', '/system/session', '127.0.0.1', '内网IP', '{\"id\":\"2076957117012561921\",\"userId\":\"1\",\"sessionTitle\":\"测试工作流\"}', '{\"code\":200,\"msg\":\"操作成功\",\"data\":\"2076957117012561921\"}', 0, '', '2026-07-14 17:08:59', 24);
+INSERT INTO `sys_oper_log` VALUES (2076958796898422785, '000000', '会话管理', 1, 'org.ruoyi.controller.chat.ChatSessionController.add()', 'POST', 1, 'admin', '研发部门', '/system/session', '127.0.0.1', '内网IP', '{\"id\":\"2076958796772593665\",\"userId\":\"1\",\"sessionTitle\":\"测试工作流\"}', '{\"code\":200,\"msg\":\"操作成功\",\"data\":\"2076958796772593665\"}', 0, '', '2026-07-14 17:15:40', 18);
+INSERT INTO `sys_oper_log` VALUES (2076958822575951874, '000000', '会话管理', 1, 'org.ruoyi.controller.chat.ChatSessionController.add()', 'POST', 1, 'admin', '研发部门', '/system/session', '127.0.0.1', '内网IP', '{\"id\":\"2076958822525620225\",\"userId\":\"1\",\"sessionTitle\":\"测试工作流\"}', '{\"code\":200,\"msg\":\"操作成功\",\"data\":\"2076958822525620225\"}', 0, '', '2026-07-14 17:15:46', 15);
+INSERT INTO `sys_oper_log` VALUES (2076964726599897090, '000000', '会话管理', 1, 'org.ruoyi.controller.chat.ChatSessionController.add()', 'POST', 1, 'admin', '研发部门', '/system/session', '127.0.0.1', '内网IP', '{\"id\":\"2076964726549565441\",\"userId\":\"1\",\"sessionTitle\":\"测试工作流\"}', '{\"code\":200,\"msg\":\"操作成功\",\"data\":\"2076964726549565441\"}', 0, '', '2026-07-14 17:39:14', 9);
+INSERT INTO `sys_oper_log` VALUES (2076964779045474305, '000000', '会话管理', 1, 'org.ruoyi.controller.chat.ChatSessionController.add()', 'POST', 1, 'admin', '研发部门', '/system/session', '127.0.0.1', '内网IP', '{\"id\":\"2076964778940616705\",\"userId\":\"1\",\"sessionTitle\":\"测试工作流\"}', '{\"code\":200,\"msg\":\"操作成功\",\"data\":\"2076964778940616705\"}', 0, '', '2026-07-14 17:39:26', 23);
+INSERT INTO `sys_oper_log` VALUES (2076971705414242305, '000000', '会话管理', 1, 'org.ruoyi.controller.chat.ChatSessionController.add()', 'POST', 1, 'admin', '研发部门', '/system/session', '127.0.0.1', '内网IP', '{\"id\":\"2076971705284218881\",\"userId\":\"1\",\"sessionTitle\":\"你好2阿\",\"sessionContent\":\"你好2阿\",\"remark\":\"你好2阿\"}', '{\"code\":200,\"msg\":\"操作成功\",\"data\":\"2076971705284218881\"}', 0, '', '2026-07-14 18:06:57', 24);
-- ----------------------------
-- Table structure for sys_oss
@@ -2454,18 +2844,18 @@ CREATE TABLE `sys_oss` (
-- ----------------------------
-- Records of sys_oss
-- ----------------------------
-INSERT INTO `sys_oss` VALUES (2026580908423340033, '000000', '2026/02/25/9219d6d71a6d45e19192014609d92dc9.png', 'logo.png', '.png', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/9219d6d71a6d45e19192014609d92dc9.png', '{\"fileSize\":\"183613\",\"contentType\":\"image/png\"}', 103, '2026-02-25 16:51:55', 1, '2026-02-25 16:51:55', 1, 'qcloud');
-INSERT INTO `sys_oss` VALUES (2026640059920883713, '000000', '2026/02/25/01091be272334383a1efd9bc22b73ee6.png', 'openai.png', '.png', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/01091be272334383a1efd9bc22b73ee6.png', '{\"fileSize\":\"11297\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:46:58', 1, '2026-02-25 20:46:58', 1, 'qcloud');
-INSERT INTO `sys_oss` VALUES (2026640515967557633, '000000', '2026/02/25/afecabebc8014d80b0f06b4796a74c5d.png', 'ollama.png', '.png', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/afecabebc8014d80b0f06b4796a74c5d.png', '{\"fileSize\":\"8746\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:48:47', 1, '2026-02-25 20:48:47', 1, 'qcloud');
-INSERT INTO `sys_oss` VALUES (2026640548213366785, '000000', '2026/02/25/e16429a462e54e14a1d36673146b9e3c.png', 'ppio-color.png', '.png', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/e16429a462e54e14a1d36673146b9e3c.png', '{\"fileSize\":\"7382\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:48:55', 1, '2026-02-25 20:48:55', 1, 'qcloud');
-INSERT INTO `sys_oss` VALUES (2026640572443860993, '000000', '2026/02/25/049bb6a507174f73bba4b8d8b9e55b8a.png', 'ppio-color.png', '.png', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/049bb6a507174f73bba4b8d8b9e55b8a.png', '{\"fileSize\":\"7382\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:49:00', 1, '2026-02-25 20:49:00', 1, 'qcloud');
-INSERT INTO `sys_oss` VALUES (2026640621945036802, '000000', '2026/02/25/de2aa7e649de44f3ba5c6380ac6acd04.png', 'bailian-color.png', '.png', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/de2aa7e649de44f3ba5c6380ac6acd04.png', '{\"fileSize\":\"5901\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:49:12', 1, '2026-02-25 20:49:12', 1, 'qcloud');
-INSERT INTO `sys_oss` VALUES (2033120065673043969, '000000', '2026/03/15/68c4d853814e444982c2517ffabac0f3.jpg', '9b75e600b2df6160261a507055eabfdf.jpg', '.jpg', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/03/15/68c4d853814e444982c2517ffabac0f3.jpg', '{\"fileSize\":\"28027\",\"contentType\":\"image/jpeg\"}', 103, '2026-03-15 17:56:12', 1, '2026-03-15 17:56:12', 1, 'qcloud');
-INSERT INTO `sys_oss` VALUES (2033169884118593537, '000000', '2026/03/15/4b7e93a72bf04805ae59985cc0845ef1.png', 'logo.png', '.png', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/03/15/4b7e93a72bf04805ae59985cc0845ef1.png', '{\"fileSize\":\"61537\",\"contentType\":\"image/png\"}', 103, '2026-03-15 21:14:10', 1, '2026-03-15 21:14:10', 1, 'qcloud');
-INSERT INTO `sys_oss` VALUES (2033198191581147137, '000000', '2026/03/15/66d9e6d216c74652bb466a13d24f4440.txt', 'ruoyi-ai介绍.txt', '.txt', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/03/15/66d9e6d216c74652bb466a13d24f4440.txt', '{\"fileSize\":\"1166\",\"contentType\":\"text/plain\"}', 103, '2026-03-15 23:06:39', 1, '2026-03-15 23:06:39', 1, 'qcloud');
-INSERT INTO `sys_oss` VALUES (2033198447232364546, '000000', '2026/03/15/ae1b1e0d363e4bc1b3321d696453fdbf.txt', 'ruoyi-ai介绍.txt', '.txt', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/03/15/ae1b1e0d363e4bc1b3321d696453fdbf.txt', '{\"fileSize\":\"1166\",\"contentType\":\"text/plain\"}', 103, '2026-03-15 23:07:39', 1, '2026-03-15 23:07:39', 1, 'qcloud');
-INSERT INTO `sys_oss` VALUES (2033198841211727874, '000000', '2026/03/15/83564059b4f643b69a1e0ea727d17364.txt', 'ruoyi-ai介绍.txt', '.txt', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/03/15/83564059b4f643b69a1e0ea727d17364.txt', '{\"fileSize\":\"1166\",\"contentType\":\"text/plain\"}', 103, '2026-03-15 23:09:13', 1, '2026-03-15 23:09:13', 1, 'qcloud');
-INSERT INTO `sys_oss` VALUES (2033199209064771586, '000000', '2026/03/15/695360eb380d43d6af34e8a308c09696.txt', 'ruoyi-ai介绍.txt', '.txt', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/03/15/695360eb380d43d6af34e8a308c09696.txt', '{\"fileSize\":\"1166\",\"contentType\":\"text/plain\"}', 103, '2026-03-15 23:10:41', 1, '2026-03-15 23:10:41', 1, 'qcloud');
+INSERT INTO `sys_oss` VALUES (2026580908423340033, '000000', '2026/02/25/9219d6d71a6d45e19192014609d92dc9.png', 'logo.png', '.png', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/02/25/9219d6d71a6d45e19192014609d92dc9.png', '{\"fileSize\":\"183613\",\"contentType\":\"image/png\"}', 103, '2026-02-25 16:51:55', 1, '2026-02-25 16:51:55', 1, 'qcloud');
+INSERT INTO `sys_oss` VALUES (2026640059920883713, '000000', '2026/02/25/01091be272334383a1efd9bc22b73ee6.png', 'openai.png', '.png', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/02/25/01091be272334383a1efd9bc22b73ee6.png', '{\"fileSize\":\"11297\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:46:58', 1, '2026-02-25 20:46:58', 1, 'qcloud');
+INSERT INTO `sys_oss` VALUES (2026640515967557633, '000000', '2026/02/25/afecabebc8014d80b0f06b4796a74c5d.png', 'ollama.png', '.png', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/02/25/afecabebc8014d80b0f06b4796a74c5d.png', '{\"fileSize\":\"8746\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:48:47', 1, '2026-02-25 20:48:47', 1, 'qcloud');
+INSERT INTO `sys_oss` VALUES (2026640548213366785, '000000', '2026/02/25/e16429a462e54e14a1d36673146b9e3c.png', 'ppio-color.png', '.png', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/02/25/e16429a462e54e14a1d36673146b9e3c.png', '{\"fileSize\":\"7382\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:48:55', 1, '2026-02-25 20:48:55', 1, 'qcloud');
+INSERT INTO `sys_oss` VALUES (2026640572443860993, '000000', '2026/02/25/049bb6a507174f73bba4b8d8b9e55b8a.png', 'ppio-color.png', '.png', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/02/25/049bb6a507174f73bba4b8d8b9e55b8a.png', '{\"fileSize\":\"7382\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:49:00', 1, '2026-02-25 20:49:00', 1, 'qcloud');
+INSERT INTO `sys_oss` VALUES (2026640621945036802, '000000', '2026/02/25/de2aa7e649de44f3ba5c6380ac6acd04.png', 'bailian-color.png', '.png', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/02/25/de2aa7e649de44f3ba5c6380ac6acd04.png', '{\"fileSize\":\"5901\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:49:12', 1, '2026-02-25 20:49:12', 1, 'qcloud');
+INSERT INTO `sys_oss` VALUES (2033120065673043969, '000000', '2026/03/15/68c4d853814e444982c2517ffabac0f3.jpg', '9b75e600b2df6160261a507055eabfdf.jpg', '.jpg', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/03/15/68c4d853814e444982c2517ffabac0f3.jpg', '{\"fileSize\":\"28027\",\"contentType\":\"image/jpeg\"}', 103, '2026-03-15 17:56:12', 1, '2026-03-15 17:56:12', 1, 'qcloud');
+INSERT INTO `sys_oss` VALUES (2033169884118593537, '000000', '2026/03/15/4b7e93a72bf04805ae59985cc0845ef1.png', 'logo.png', '.png', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/03/15/4b7e93a72bf04805ae59985cc0845ef1.png', '{\"fileSize\":\"61537\",\"contentType\":\"image/png\"}', 103, '2026-03-15 21:14:10', 1, '2026-03-15 21:14:10', 1, 'qcloud');
+INSERT INTO `sys_oss` VALUES (2033198191581147137, '000000', '2026/03/15/66d9e6d216c74652bb466a13d24f4440.txt', 'ruoyi-ai介绍.txt', '.txt', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/03/15/66d9e6d216c74652bb466a13d24f4440.txt', '{\"fileSize\":\"1166\",\"contentType\":\"text/plain\"}', 103, '2026-03-15 23:06:39', 1, '2026-03-15 23:06:39', 1, 'qcloud');
+INSERT INTO `sys_oss` VALUES (2033198447232364546, '000000', '2026/03/15/ae1b1e0d363e4bc1b3321d696453fdbf.txt', 'ruoyi-ai介绍.txt', '.txt', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/03/15/ae1b1e0d363e4bc1b3321d696453fdbf.txt', '{\"fileSize\":\"1166\",\"contentType\":\"text/plain\"}', 103, '2026-03-15 23:07:39', 1, '2026-03-15 23:07:39', 1, 'qcloud');
+INSERT INTO `sys_oss` VALUES (2033198841211727874, '000000', '2026/03/15/83564059b4f643b69a1e0ea727d17364.txt', 'ruoyi-ai介绍.txt', '.txt', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/03/15/83564059b4f643b69a1e0ea727d17364.txt', '{\"fileSize\":\"1166\",\"contentType\":\"text/plain\"}', 103, '2026-03-15 23:09:13', 1, '2026-03-15 23:09:13', 1, 'qcloud');
+INSERT INTO `sys_oss` VALUES (2033199209064771586, '000000', '2026/03/15/695360eb380d43d6af34e8a308c09696.txt', 'ruoyi-ai介绍.txt', '.txt', 'https://example-1234567890.cos.ap-guangzhou.myqcloud.com/2026/03/15/695360eb380d43d6af34e8a308c09696.txt', '{\"fileSize\":\"1166\",\"contentType\":\"text/plain\"}', 103, '2026-03-15 23:10:41', 1, '2026-03-15 23:10:41', 1, 'qcloud');
-- ----------------------------
-- Table structure for sys_oss_config
@@ -2501,7 +2891,7 @@ CREATE TABLE `sys_oss_config` (
INSERT INTO `sys_oss_config` VALUES (1, '000000', 'minio', 'ruoyi', 'ruoyi123', 'ruoyi', '', '127.0.0.1:9000', '', 'N', '', '1', '1', '', 103, 1, '2026-02-03 05:14:52', 1, '2026-02-25 15:44:13', NULL);
INSERT INTO `sys_oss_config` VALUES (2, '000000', 'qiniu', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 's3-cn-north-1.qiniucs.com', '', 'N', '', '1', '1', '', 103, 1, '2026-02-03 05:14:52', 1, '2026-02-03 05:14:52', NULL);
INSERT INTO `sys_oss_config` VALUES (3, '000000', 'aliyun', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 'oss-cn-beijing.aliyuncs.com', '', 'N', '', '1', '1', '', 103, 1, '2026-02-03 05:14:52', 1, '2026-02-03 05:14:52', NULL);
-INSERT INTO `sys_oss_config` VALUES (4, '000000', 'qcloud', 'xx', 'xx', 'ruoyiai-1254149996', '', 'cos.ap-guangzhou.myqcloud.com', '', 'Y', 'ap-guangzhou', '1', '0', '', 103, 1, '2026-02-03 05:14:52', 1, '2026-03-15 17:56:06', '');
+INSERT INTO `sys_oss_config` VALUES (4, '000000', 'qcloud', 'xx', 'xx', 'example-1234567890', '', 'cos.ap-guangzhou.myqcloud.com', '', 'Y', 'ap-guangzhou', '1', '0', '', 103, 1, '2026-02-03 05:14:52', 1, '2026-03-15 17:56:06', '');
INSERT INTO `sys_oss_config` VALUES (5, '000000', 'image', 'ruoyi', 'ruoyi123', 'ruoyi', 'image', '127.0.0.1:9000', '', 'N', '', '1', '1', '', 103, 1, '2026-02-03 05:14:53', 1, '2026-02-03 05:14:53', NULL);
-- ----------------------------
@@ -2948,7 +3338,7 @@ CREATE TABLE `sys_user` (
-- ----------------------------
-- Records of sys_user
-- ----------------------------
-INSERT INTO `sys_user` VALUES (1, '000000', 103, 'admin', 'admin', 'sys_user', 'ageerle@163.com', '15888888888', '1', NULL, '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', '2026-05-19 23:16:57', 103, 1, '2026-02-05 09:22:12', -1, '2026-05-19 23:16:57', '管理员', NULL, 0.00);
+INSERT INTO `sys_user` VALUES (1, '000000', 103, 'admin', 'admin', 'sys_user', 'ageerle@163.com', '15888888888', '1', NULL, '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', '2026-07-14 20:31:20', 103, 1, '2026-02-05 09:22:12', -1, '2026-07-14 20:31:20', '管理员', NULL, 0.00);
INSERT INTO `sys_user` VALUES (3, '000000', 108, 'test', '本部门及以下 密码666666', 'sys_user', '', '', '0', NULL, '$2a$10$b8yUzN0C71sbz.PhNOCgJe.Tu1yWC3RNrTyjSQ8p1W0.aaUXUJ.Ne', '0', '0', '127.0.0.1', '2026-02-05 09:22:12', 103, 1, '2026-02-05 09:22:12', 3, '2026-02-05 09:22:12', NULL, NULL, 0.00);
INSERT INTO `sys_user` VALUES (4, '000000', 102, 'test1', '仅本人 密码666666', 'sys_user', '', '', '0', NULL, '$2a$10$b8yUzN0C71sbz.PhNOCgJe.Tu1yWC3RNrTyjSQ8p1W0.aaUXUJ.Ne', '0', '0', '127.0.0.1', '2026-02-05 09:22:12', 103, 1, '2026-02-05 09:22:12', 4, '2026-02-05 09:22:12', NULL, NULL, 0.00);
diff --git a/docs/script/sql/snail_job_mysql.sql b/docs/script/sql/snail_job_mysql.sql
new file mode 100644
index 00000000..322cccae
--- /dev/null
+++ b/docs/script/sql/snail_job_mysql.sql
@@ -0,0 +1,545 @@
+SET NAMES utf8mb4;
+
+DROP DATABASE IF EXISTS snail_job;
+CREATE DATABASE snail_job;
+USE snail_job;
+
+CREATE TABLE `sj_namespace`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `name` varchar(64) NOT NULL COMMENT '名称',
+ `unique_id` varchar(64) NOT NULL COMMENT '唯一id',
+ `description` varchar(256) NOT NULL DEFAULT '' COMMENT '描述',
+ `deleted` tinyint(4) NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_name` (`name`),
+ UNIQUE KEY `uk_unique_id` (`unique_id`)
+) ENGINE = InnoDB
+ DEFAULT CHARSET = utf8mb4 COMMENT ='命名空间';
+
+INSERT INTO `sj_namespace` (`id`, `name`, `unique_id`, `create_dt`, `update_dt`, `deleted`)
+VALUES (1, 'Default', '764d604ec6fc45f68cd92514c40e9e1a', now(), now(), 0);
+
+
+CREATE TABLE `sj_group_config`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL DEFAULT '' COMMENT '组名称',
+ `description` varchar(256) NOT NULL DEFAULT '' COMMENT '组描述',
+ `token` varchar(64) NOT NULL DEFAULT 'SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT' COMMENT 'token',
+ `group_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '组状态 0、未启用 1、启用',
+ `version` int(11) NOT NULL COMMENT '版本号',
+ `group_partition` int(11) NOT NULL COMMENT '分区',
+ `id_generator_mode` tinyint(4) NOT NULL DEFAULT 1 COMMENT '唯一id生成模式 默认号段模式',
+ `init_scene` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否初始化场景 0:否 1:是',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_namespace_id_group_name` (`namespace_id`, `group_name`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='组配置'
+;
+
+CREATE TABLE `sj_notify_config`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `notify_name` varchar(64) NOT NULL DEFAULT '' COMMENT '通知名称',
+ `system_task_type` tinyint(4) NOT NULL DEFAULT 3 COMMENT '任务类型 1. 重试任务 2. 重试回调 3、JOB任务 4、WORKFLOW任务',
+ `notify_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '通知状态 0、未启用 1、启用',
+ `recipient_ids` varchar(128) NOT NULL COMMENT '接收人id列表',
+ `notify_threshold` int(11) NOT NULL DEFAULT 0 COMMENT '通知阈值',
+ `notify_scene` tinyint(4) NOT NULL DEFAULT 0 COMMENT '通知场景',
+ `rate_limiter_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '限流状态 0、未启用 1、启用',
+ `rate_limiter_threshold` int(11) NOT NULL DEFAULT 0 COMMENT '每秒限流阈值',
+ `description` varchar(256) NOT NULL DEFAULT '' COMMENT '描述',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_namespace_id_group_name_scene_name` (`namespace_id`, `group_name`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='通知配置'
+;
+
+CREATE TABLE `sj_notify_recipient`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `recipient_name` varchar(64) NOT NULL COMMENT '接收人名称',
+ `notify_type` tinyint(4) NOT NULL DEFAULT 0 COMMENT '通知类型 1、钉钉 2、邮件 3、企业微信 4 飞书 5 webhook',
+ `notify_attribute` varchar(512) NOT NULL COMMENT '配置属性',
+ `description` varchar(256) NOT NULL DEFAULT '' COMMENT '描述',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_namespace_id` (`namespace_id`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='告警通知接收人'
+;
+
+CREATE TABLE `sj_retry_dead_letter`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `group_id` bigint(20) NOT NULL COMMENT '组Id',
+ `scene_name` varchar(64) NOT NULL COMMENT '场景名称',
+ `scene_id` bigint(20) NOT NULL COMMENT '场景ID',
+ `idempotent_id` varchar(64) NOT NULL COMMENT '幂等id',
+ `biz_no` varchar(64) NOT NULL DEFAULT '' COMMENT '业务编号',
+ `executor_name` varchar(512) NOT NULL DEFAULT '' COMMENT '执行器名称',
+ -- jackson 兼容历史数据 预计1.8.0默认改为fury
+ `serializer_name` varchar(32) NOT NULL DEFAULT 'jackson' COMMENT '执行方法参数序列化器名称',
+ `args_str` text NOT NULL COMMENT '执行方法参数',
+ `ext_attrs` text NOT NULL COMMENT '扩展字段',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_namespace_id_group_name_scene_name` (`namespace_id`, `group_name`, `scene_name`),
+ KEY `idx_idempotent_id` (`idempotent_id`),
+ KEY `idx_biz_no` (`biz_no`),
+ KEY `idx_create_dt` (`create_dt`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='死信队列表'
+;
+
+CREATE TABLE `sj_retry`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `group_id` bigint(20) NOT NULL COMMENT '组Id',
+ `scene_name` varchar(64) NOT NULL COMMENT '场景名称',
+ `scene_id` bigint(20) NOT NULL COMMENT '场景ID',
+ `idempotent_id` varchar(64) NOT NULL COMMENT '幂等id',
+ `biz_no` varchar(64) NOT NULL DEFAULT '' COMMENT '业务编号',
+ `executor_name` varchar(512) NOT NULL DEFAULT '' COMMENT '执行器名称',
+ `args_str` text NOT NULL COMMENT '执行方法参数',
+ `ext_attrs` text NOT NULL COMMENT '扩展字段',
+ -- jackson 兼容历史数据 预计1.8.0默认改为fury
+ `serializer_name` varchar(32) NOT NULL DEFAULT 'jackson' COMMENT '执行方法参数序列化器名称',
+ `next_trigger_at` bigint(13) NOT NULL COMMENT '下次触发时间',
+ `retry_count` int(11) NOT NULL DEFAULT 0 COMMENT '重试次数',
+ `retry_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '重试状态 0、重试中 1、成功 2、最大重试次数',
+ `task_type` tinyint(4) NOT NULL DEFAULT 1 COMMENT '任务类型 1、重试数据 2、回调数据',
+ `bucket_index` int(11) NOT NULL DEFAULT 0 COMMENT 'bucket',
+ `parent_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '父节点id',
+ `deleted` bigint(20) NOT NULL DEFAULT 0 COMMENT '逻辑删除',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_biz_no` (`biz_no`),
+ KEY `idx_idempotent_id` (`idempotent_id`),
+ KEY `idx_retry_status_bucket_index` (`retry_status`, `bucket_index`),
+ KEY `idx_parent_id` (`parent_id`),
+ KEY `idx_create_dt` (`create_dt`),
+ UNIQUE KEY `uk_scene_tasktype_idempotentid_deleted` (`scene_id`, `task_type`, `idempotent_id`, `deleted`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='重试信息表'
+;
+
+CREATE TABLE `sj_retry_task`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `scene_name` varchar(64) NOT NULL COMMENT '场景名称',
+ `retry_id` bigint(20) NOT NULL COMMENT '重试信息Id',
+ `ext_attrs` text NOT NULL COMMENT '扩展字段',
+ `task_status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '重试状态',
+ `task_type` tinyint(4) NOT NULL DEFAULT 1 COMMENT '任务类型 1、重试数据 2、回调数据',
+ `operation_reason` tinyint(4) NOT NULL DEFAULT 0 COMMENT '操作原因',
+ `client_info` varchar(128) DEFAULT NULL COMMENT '客户端地址 clientId#ip:port',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_group_name_scene_name` (`namespace_id`, `group_name`, `scene_name`),
+ KEY `task_status` (`task_status`),
+ KEY `idx_create_dt` (`create_dt`),
+ KEY `idx_retry_id` (`retry_id`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='重试任务表'
+;
+
+CREATE TABLE `sj_retry_task_log_message`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `retry_id` bigint(20) NOT NULL COMMENT '重试信息Id',
+ `retry_task_id` bigint(20) NOT NULL COMMENT '重试任务Id',
+ `message` longtext NOT NULL COMMENT '异常信息',
+ `log_num` int(11) NOT NULL DEFAULT 1 COMMENT '日志数量',
+ `real_time` bigint(13) NOT NULL DEFAULT 0 COMMENT '上报时间',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_namespace_id_group_name_retry_task_id` (`namespace_id`, `group_name`, `retry_task_id`),
+ KEY `idx_create_dt` (`create_dt`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='任务调度日志信息记录表'
+;
+
+CREATE TABLE `sj_retry_scene_config`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `scene_name` varchar(64) NOT NULL COMMENT '场景名称',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `scene_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '组状态 0、未启用 1、启用',
+ `max_retry_count` int(11) NOT NULL DEFAULT 5 COMMENT '最大重试次数',
+ `back_off` tinyint(4) NOT NULL DEFAULT 1 COMMENT '1、默认等级 2、固定间隔时间 3、CRON 表达式',
+ `trigger_interval` varchar(16) NOT NULL DEFAULT '' COMMENT '间隔时长',
+ `notify_ids` varchar(128) NOT NULL DEFAULT '' COMMENT '通知告警场景配置id列表',
+ `deadline_request` bigint(20) unsigned NOT NULL DEFAULT 60000 COMMENT 'Deadline Request 调用链超时 单位毫秒',
+ `executor_timeout` int(11) unsigned NOT NULL DEFAULT 5 COMMENT '任务执行超时时间,单位秒',
+ `route_key` tinyint(4) NOT NULL DEFAULT 4 COMMENT '路由策略',
+ `block_strategy` tinyint(4) NOT NULL DEFAULT 1 COMMENT '阻塞策略 1、丢弃 2、覆盖 3、并行',
+ `cb_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '回调状态 0、不开启 1、开启',
+ `cb_trigger_type` tinyint(4) NOT NULL DEFAULT 1 COMMENT '1、默认等级 2、固定间隔时间 3、CRON 表达式',
+ `cb_max_count` int(11) NOT NULL DEFAULT 16 COMMENT '回调的最大执行次数',
+ `cb_trigger_interval` varchar(16) NOT NULL DEFAULT '' COMMENT '回调的最大执行次数',
+ `owner_id` bigint(20) NULL DEFAULT NULL COMMENT '负责人id',
+ `labels` varchar(512) NULL DEFAULT '' COMMENT '标签',
+ `description` varchar(256) NOT NULL DEFAULT '' COMMENT '描述',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_namespace_id_group_name_scene_name` (`namespace_id`, `group_name`, `scene_name`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='场景配置'
+;
+
+CREATE TABLE `sj_server_node`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `host_id` varchar(64) NOT NULL COMMENT '主机id',
+ `host_ip` varchar(64) NOT NULL COMMENT '机器ip',
+ `host_port` int(16) NOT NULL COMMENT '机器端口',
+ `expire_at` datetime NOT NULL COMMENT '过期时间',
+ `node_type` tinyint(4) NOT NULL COMMENT '节点类型 1、客户端 2、是服务端',
+ `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT '扩展字段',
+ `labels` varchar(512) NULL DEFAULT '' COMMENT '标签',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`),
+ KEY `idx_expire_at_node_type` (`expire_at`, `node_type`),
+ UNIQUE KEY `uk_host_id_host_ip` (`host_id`, `host_ip`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='服务器节点'
+;
+
+CREATE TABLE `sj_distributed_lock`
+(
+ `name` varchar(64) NOT NULL COMMENT '锁名称',
+ `lock_until` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '锁定时长',
+ `locked_at` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '锁定时间',
+ `locked_by` varchar(255) NOT NULL COMMENT '锁定者',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`name`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='锁定表'
+;
+
+CREATE TABLE `sj_system_user`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `username` varchar(64) NOT NULL COMMENT '账号',
+ `password` varchar(128) NOT NULL COMMENT '密码',
+ `role` tinyint(4) NOT NULL DEFAULT 0 COMMENT '角色:1-普通用户、2-管理员',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_username` (`username`) USING BTREE
+) ENGINE = InnoDB
+ DEFAULT CHARSET = utf8mb4 COMMENT ='系统用户表';
+
+-- pwd: admin
+INSERT INTO `sj_system_user` (username, password, role)
+VALUES ('admin', '465c194afb65670f38322df087f0a9bb225cc257e43eb4ac5a0c98ef5b3173ac', 2);
+
+CREATE TABLE `sj_system_user_permission`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `system_user_id` bigint(20) NOT NULL COMMENT '系统用户id',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_namespace_id_group_name_system_user_id` (`namespace_id`, `group_name`, `system_user_id`)
+) ENGINE = InnoDB
+ DEFAULT CHARSET = utf8mb4 COMMENT ='系统用户权限表';
+
+-- 分布式调度DDL
+CREATE TABLE `sj_job`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `job_name` varchar(64) NOT NULL COMMENT '名称',
+ `args_str` text DEFAULT NULL COMMENT '执行方法参数',
+ `args_type` tinyint(4) NOT NULL DEFAULT 1 COMMENT '参数类型 ',
+ `next_trigger_at` bigint(13) NOT NULL COMMENT '下次触发时间',
+ `job_status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '任务状态 0、关闭、1、开启',
+ `task_type` tinyint(4) NOT NULL DEFAULT 1 COMMENT '任务类型 1、集群 2、广播 3、切片',
+ `route_key` tinyint(4) NOT NULL DEFAULT 4 COMMENT '路由策略',
+ `executor_type` tinyint(4) NOT NULL DEFAULT 1 COMMENT '执行器类型',
+ `executor_info` varchar(255) DEFAULT NULL COMMENT '执行器名称',
+ `trigger_type` tinyint(4) NOT NULL COMMENT '触发类型 1.CRON 表达式 2. 固定时间',
+ `trigger_interval` varchar(255) NOT NULL COMMENT '间隔时长',
+ `block_strategy` tinyint(4) NOT NULL DEFAULT 1 COMMENT '阻塞策略 1、丢弃 2、覆盖 3、并行 4、恢复',
+ `executor_timeout` int(11) NOT NULL DEFAULT 0 COMMENT '任务执行超时时间,单位秒',
+ `max_retry_times` int(11) NOT NULL DEFAULT 0 COMMENT '最大重试次数',
+ `parallel_num` int(11) NOT NULL DEFAULT 1 COMMENT '并行数',
+ `retry_interval` int(11) NOT NULL DEFAULT 0 COMMENT '重试间隔(s)',
+ `bucket_index` int(11) NOT NULL DEFAULT 0 COMMENT 'bucket',
+ `resident` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否是常驻任务',
+ `notify_ids` varchar(128) NOT NULL DEFAULT '' COMMENT '通知告警场景配置id列表',
+ `owner_id` bigint(20) NULL DEFAULT NULL COMMENT '负责人id',
+ `labels` varchar(512) NULL DEFAULT '' COMMENT '标签',
+ `description` varchar(256) NOT NULL DEFAULT '' COMMENT '描述',
+ `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT '扩展字段',
+ `deleted` tinyint(4) NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`),
+ KEY `idx_job_status_bucket_index` (`job_status`, `bucket_index`),
+ KEY `idx_create_dt` (`create_dt`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='任务信息';
+
+CREATE TABLE `sj_job_log_message`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `job_id` bigint(20) NOT NULL COMMENT '任务信息id',
+ `task_batch_id` bigint(20) NOT NULL COMMENT '任务批次id',
+ `task_id` bigint(20) NOT NULL COMMENT '调度任务id',
+ `message` longtext NOT NULL COMMENT '调度信息',
+ `log_num` int(11) NOT NULL DEFAULT 1 COMMENT '日志数量',
+ `real_time` bigint(13) NOT NULL DEFAULT 0 COMMENT '上报时间',
+ `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT '扩展字段',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_task_batch_id_task_id` (`task_batch_id`, `task_id`),
+ KEY `idx_create_dt` (`create_dt`),
+ KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='调度日志';
+
+CREATE TABLE `sj_job_task`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `job_id` bigint(20) NOT NULL COMMENT '任务信息id',
+ `task_batch_id` bigint(20) NOT NULL COMMENT '调度任务id',
+ `parent_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '父执行器id',
+ `task_status` tinyint NOT NULL DEFAULT 0 COMMENT '执行的状态 0、失败 1、成功',
+ `retry_count` int(11) NOT NULL DEFAULT 0 COMMENT '重试次数',
+ `mr_stage` tinyint DEFAULT NULL COMMENT '动态分片所处阶段 1:map 2:reduce 3:mergeReduce',
+ `leaf` tinyint NOT NULL DEFAULT '1' COMMENT '叶子节点',
+ `task_name` varchar(255) NOT NULL DEFAULT '' COMMENT '任务名称',
+ `client_info` varchar(128) DEFAULT NULL COMMENT '客户端地址 clientId#ip:port',
+ `wf_context` text DEFAULT NULL COMMENT '工作流全局上下文',
+ `result_message` text NOT NULL COMMENT '执行结果',
+ `args_str` text DEFAULT NULL COMMENT '执行方法参数',
+ `args_type` tinyint NOT NULL DEFAULT 1 COMMENT '参数类型 ',
+ `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT '扩展字段',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_task_batch_id_task_status` (`task_batch_id`, `task_status`),
+ KEY `idx_create_dt` (`create_dt`),
+ KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='任务实例';
+
+CREATE TABLE `sj_job_task_batch`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `job_id` bigint(20) NOT NULL COMMENT '任务id',
+ `workflow_node_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '工作流节点id',
+ `parent_workflow_node_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '工作流任务父批次id',
+ `workflow_task_batch_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '工作流任务批次id',
+ `task_batch_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '任务批次状态 0、失败 1、成功',
+ `operation_reason` tinyint(4) NOT NULL DEFAULT 0 COMMENT '操作原因',
+ `execution_at` bigint(13) NOT NULL DEFAULT 0 COMMENT '任务执行时间',
+ `system_task_type` tinyint(4) NOT NULL DEFAULT 3 COMMENT '任务类型 3、JOB任务 4、WORKFLOW任务',
+ `parent_id` varchar(64) NOT NULL DEFAULT '' COMMENT '父节点',
+ `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT '扩展字段',
+ `deleted` tinyint(4) NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_job_id_task_batch_status` (`job_id`, `task_batch_status`),
+ KEY `idx_create_dt` (`create_dt`),
+ KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`),
+ KEY `idx_workflow_task_batch_id_workflow_node_id` (`workflow_task_batch_id`, `workflow_node_id`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='任务批次';
+
+CREATE TABLE `sj_job_summary`
+(
+ `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` VARCHAR(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '组名称',
+ `business_id` bigint NOT NULL COMMENT '业务id (job_id或workflow_id)',
+ `system_task_type` tinyint(4) NOT NULL DEFAULT 3 COMMENT '任务类型 3、JOB任务 4、WORKFLOW任务',
+ `trigger_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '统计时间',
+ `success_num` int NOT NULL DEFAULT 0 COMMENT '执行成功-日志数量',
+ `fail_num` int NOT NULL DEFAULT 0 COMMENT '执行失败-日志数量',
+ `fail_reason` varchar(512) NOT NULL DEFAULT '' COMMENT '失败原因',
+ `stop_num` int NOT NULL DEFAULT 0 COMMENT '执行失败-日志数量',
+ `stop_reason` varchar(512) NOT NULL DEFAULT '' COMMENT '失败原因',
+ `cancel_num` int NOT NULL DEFAULT 0 COMMENT '执行失败-日志数量',
+ `cancel_reason` varchar(512) NOT NULL DEFAULT '' COMMENT '失败原因',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_namespace_id_group_name_business_id` (`namespace_id`, `group_name`, business_id),
+ UNIQUE KEY `uk_trigger_at_system_task_type_business_id` (`trigger_at`, `system_task_type`, `business_id`) USING BTREE
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 1
+ DEFAULT CHARSET = utf8mb4 COMMENT ='DashBoard_Job';
+
+CREATE TABLE `sj_retry_summary`
+(
+ `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` VARCHAR(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '组名称',
+ `scene_name` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '场景名称',
+ `trigger_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '统计时间',
+ `running_num` int NOT NULL DEFAULT 0 COMMENT '重试中-日志数量',
+ `finish_num` int NOT NULL DEFAULT 0 COMMENT '重试完成-日志数量',
+ `max_count_num` int NOT NULL DEFAULT 0 COMMENT '重试到达最大次数-日志数量',
+ `suspend_num` int NOT NULL DEFAULT 0 COMMENT '暂停重试-日志数量',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_trigger_at` (`trigger_at`),
+ UNIQUE KEY `uk_scene_name_trigger_at` (`namespace_id`, `group_name`, `scene_name`, `trigger_at`) USING BTREE
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 1
+ DEFAULT CHARSET = utf8mb4 COMMENT ='DashBoard_Retry';
+
+CREATE TABLE `sj_workflow`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `workflow_name` varchar(64) NOT NULL COMMENT '工作流名称',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `workflow_status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '工作流状态 0、关闭、1、开启',
+ `trigger_type` tinyint(4) NOT NULL COMMENT '触发类型 1.CRON 表达式 2. 固定时间',
+ `trigger_interval` varchar(255) NOT NULL COMMENT '间隔时长',
+ `next_trigger_at` bigint NOT NULL COMMENT '下次触发时间',
+ `block_strategy` tinyint(4) NOT NULL DEFAULT 1 COMMENT '阻塞策略 1、丢弃 2、覆盖 3、并行',
+ `executor_timeout` int(11) NOT NULL DEFAULT 0 COMMENT '任务执行超时时间,单位秒',
+ `description` varchar(256) NOT NULL DEFAULT '' COMMENT '描述',
+ `flow_info` text DEFAULT NULL COMMENT '流程信息',
+ `wf_context` text DEFAULT NULL COMMENT '上下文',
+ `notify_ids` varchar(128) NOT NULL DEFAULT '' COMMENT '通知告警场景配置id列表',
+ `bucket_index` int(11) NOT NULL DEFAULT 0 COMMENT 'bucket',
+ `version` int(11) NOT NULL COMMENT '版本号',
+ `owner_id` bigint(20) NULL DEFAULT NULL COMMENT '负责人id',
+ `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT '扩展字段',
+ `deleted` tinyint(4) NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_create_dt` (`create_dt`),
+ KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='工作流';
+
+CREATE TABLE `sj_workflow_node`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `node_name` varchar(64) NOT NULL COMMENT '节点名称',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `job_id` bigint(20) NOT NULL COMMENT '任务信息id',
+ `workflow_id` bigint(20) NOT NULL COMMENT '工作流ID',
+ `node_type` tinyint(4) NOT NULL DEFAULT 1 COMMENT '1、任务节点 2、条件节点',
+ `expression_type` tinyint(4) NOT NULL DEFAULT 0 COMMENT '1、SpEl、2、Aviator 3、QL',
+ `fail_strategy` tinyint(4) NOT NULL DEFAULT 1 COMMENT '失败策略 1、跳过 2、阻塞',
+ `workflow_node_status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '工作流节点状态 0、关闭、1、开启',
+ `priority_level` int(11) NOT NULL DEFAULT 1 COMMENT '优先级',
+ `node_info` text DEFAULT NULL COMMENT '节点信息 ',
+ `version` int(11) NOT NULL COMMENT '版本号',
+ `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT '扩展字段',
+ `deleted` tinyint(4) NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_create_dt` (`create_dt`),
+ KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='工作流节点';
+
+CREATE TABLE `sj_workflow_task_batch`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `workflow_id` bigint(20) NOT NULL COMMENT '工作流任务id',
+ `task_batch_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '任务批次状态 0、失败 1、成功',
+ `operation_reason` tinyint(4) NOT NULL DEFAULT 0 COMMENT '操作原因',
+ `flow_info` text DEFAULT NULL COMMENT '流程信息',
+ `wf_context` text DEFAULT NULL COMMENT '全局上下文',
+ `execution_at` bigint(13) NOT NULL DEFAULT 0 COMMENT '任务执行时间',
+ `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT '扩展字段',
+ `version` int(11) NOT NULL DEFAULT 1 COMMENT '版本号',
+ `deleted` tinyint(4) NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_job_id_task_batch_status` (`workflow_id`, `task_batch_status`),
+ KEY `idx_create_dt` (`create_dt`),
+ KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='工作流批次';
+
+CREATE TABLE `sj_job_executor`
+(
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
+ `group_name` varchar(64) NOT NULL COMMENT '组名称',
+ `executor_info` varchar(256) NOT NULL COMMENT '任务执行器名称',
+ `executor_type` varchar(3) NOT NULL COMMENT '1:java 2:python 3:go',
+ `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+ PRIMARY KEY (`id`),
+ KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`),
+ KEY `idx_create_dt` (`create_dt`)
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 0
+ DEFAULT CHARSET = utf8mb4 COMMENT ='任务执行器信息';
diff --git a/docs/script/sql/update/2026-07-20-knowledge-fragment-fid.sql b/docs/script/sql/update/2026-07-20-knowledge-fragment-fid.sql
new file mode 100644
index 00000000..0bb5c264
--- /dev/null
+++ b/docs/script/sql/update/2026-07-20-knowledge-fragment-fid.sql
@@ -0,0 +1,58 @@
+-- RAG metadata migration (MySQL 8). Safe to execute repeatedly.
+-- 注意:MySQL 8 不支持 ALTER TABLE ... ADD COLUMN IF NOT EXISTS(仅 MariaDB 支持),
+-- 因此列的增量添加统一用 information_schema 守卫 + PREPARE 实现幂等。
+SET @add_file_hash_col = IF(EXISTS(
+ SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE()
+ AND table_name = 'knowledge_attach' AND column_name = 'file_hash'),
+ 'SELECT 1',
+ 'ALTER TABLE `knowledge_attach` ADD COLUMN `file_hash` varchar(64) NULL DEFAULT NULL COMMENT ''文件SHA-256摘要'' AFTER `doc_id`');
+PREPARE stmt FROM @add_file_hash_col; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+ALTER TABLE `knowledge_attach`
+ MODIFY COLUMN `doc_id` varchar(32) NULL DEFAULT NULL COMMENT '文档ID';
+
+SET @add_file_hash = IF(EXISTS(
+ SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE()
+ AND table_name = 'knowledge_attach' AND index_name = 'uk_knowledge_file_hash'),
+ 'SELECT 1', 'ALTER TABLE `knowledge_attach` ADD UNIQUE INDEX `uk_knowledge_file_hash` (`knowledge_id`, `file_hash`)');
+PREPARE stmt FROM @add_file_hash; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+SET @add_fid_col = IF(EXISTS(
+ SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE()
+ AND table_name = 'knowledge_fragment' AND column_name = 'fid'),
+ 'SELECT 1',
+ 'ALTER TABLE `knowledge_fragment` ADD COLUMN `fid` varchar(32) NULL DEFAULT NULL COMMENT ''向量库片段ID'' AFTER `id`');
+PREPARE stmt FROM @add_fid_col; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+ALTER TABLE `knowledge_fragment`
+ MODIFY COLUMN `doc_id` varchar(32) NULL DEFAULT NULL COMMENT '文档ID';
+
+UPDATE `knowledge_fragment`
+SET `fid` = LOWER(MD5(CONCAT('knowledge_fragment:', `id`)))
+WHERE `fid` IS NULL OR `fid` = '';
+
+SET @drop_idx_fid = IF(EXISTS(
+ SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE()
+ AND table_name = 'knowledge_fragment' AND index_name = 'idx_fid'),
+ 'ALTER TABLE `knowledge_fragment` DROP INDEX `idx_fid`', 'SELECT 1');
+PREPARE stmt FROM @drop_idx_fid; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+SET @add_uk_fid = IF(EXISTS(
+ SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE()
+ AND table_name = 'knowledge_fragment' AND index_name = 'uk_fid'),
+ 'SELECT 1', 'ALTER TABLE `knowledge_fragment` ADD UNIQUE INDEX `uk_fid` (`fid`)');
+PREPARE stmt FROM @add_uk_fid; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+ALTER TABLE `knowledge_fragment` MODIFY COLUMN `fid` varchar(32) NOT NULL COMMENT '向量库片段ID';
+
+SET @add_tenant_user = IF(EXISTS(
+ SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE()
+ AND table_name = 'knowledge_info' AND index_name = 'idx_tenant_user'),
+ 'SELECT 1', 'ALTER TABLE `knowledge_info` ADD INDEX `idx_tenant_user` (`tenant_id`, `user_id`)');
+PREPARE stmt FROM @add_tenant_user; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+SET @add_tenant_share = IF(EXISTS(
+ SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE()
+ AND table_name = 'knowledge_info' AND index_name = 'idx_tenant_share'),
+ 'SELECT 1', 'ALTER TABLE `knowledge_info` ADD INDEX `idx_tenant_share` (`tenant_id`, `share`)');
+PREPARE stmt FROM @add_tenant_share; EXECUTE stmt; DEALLOCATE PREPARE stmt;
diff --git a/docs/script/sql/update/2026-07-21-chat-provider-icon-length.sql b/docs/script/sql/update/2026-07-21-chat-provider-icon-length.sql
new file mode 100644
index 00000000..88f6fcb9
--- /dev/null
+++ b/docs/script/sql/update/2026-07-21-chat-provider-icon-length.sql
@@ -0,0 +1,7 @@
+-- 加宽 chat_provider.provider_icon 字段 (对应 issue IHPUDA)
+-- 背景:文件系统使用 minio 私有桶时,厂商图标存的是带签名的临时访问 URL,
+-- 长度常超过 255,导致「Data too long for column 'provider_icon'」。
+-- MODIFY COLUMN 可重复执行。
+
+ALTER TABLE `chat_provider`
+ MODIFY COLUMN `provider_icon` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '厂商图标';
diff --git a/docs/script/sql/update/2026-07-21-sys-config-node-template.sql b/docs/script/sql/update/2026-07-21-sys-config-node-template.sql
new file mode 100644
index 00000000..ed1c5721
--- /dev/null
+++ b/docs/script/sql/update/2026-07-21-sys-config-node-template.sql
@@ -0,0 +1,41 @@
+-- 补充工作流节点消息模板配置 (对应 issue IJX5VV)
+-- 背景:NodeMessageTemplateEnum 依赖以下 9 个 sys_config 键,缺失时
+-- WorkflowMessageUtil.getNodeMessageTemplate 会抛出「请先配置该节点的响应模板」。
+-- 这批配置在历史提交 20d531c0 中存在,SQL 脚本合并重命名时遗失,此处恢复。
+-- 幂等:按 config_key + tenant_id 判重,可重复执行。
+
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+SELECT 2027192921483309058, '000000', 'HTTP请求节点响应模板', 'node.httpRequest.template', '✅ HTTP请求节点:结束响应 - ', 'Y', 103, 1, '2026-02-27 09:23:51', 1, '2026-02-27 09:31:41', NULL
+FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_config` WHERE `config_key` = 'node.httpRequest.template' AND `tenant_id` = '000000');
+
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+SELECT 2027193296990957569, '000000', '文生图节点响应模板', 'node.image.template', '🎨 文生图节点:结束响应 - 图片URL: ', 'Y', 103, 1, '2026-02-27 09:25:20', 1, '2026-02-27 09:31:52', NULL
+FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_config` WHERE `config_key` = 'node.image.template' AND `tenant_id` = '000000');
+
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+SELECT 2027193820393959425, '000000', '发送邮箱节点响应模板', 'node.mailsend.template', '📧 发送邮箱节点:结束响应 - ', 'Y', 103, 1, '2026-02-27 09:27:25', 1, '2026-02-27 09:32:05', NULL
+FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_config` WHERE `config_key` = 'node.mailsend.template' AND `tenant_id` = '000000');
+
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+SELECT 2027194134438277122, '000000', '结束节点响应模板', 'node.end.template', '🔚 流程已执行完毕,如果您有其他需求,请随时重新发起请求。', 'Y', 103, 1, '2026-02-27 09:28:40', 1, '2026-02-27 09:32:53', NULL
+FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_config` WHERE `config_key` = 'node.end.template' AND `tenant_id` = '000000');
+
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+SELECT 2027206492573335554, '000000', '人机交互节点响应模板', 'node.humanFeedback.template', '👤 人机交互节点:等待用户操作 - ', 'Y', 103, 1, '2026-02-27 10:17:46', 1, '2026-02-27 10:17:46', NULL
+FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_config` WHERE `config_key` = 'node.humanFeedback.template' AND `tenant_id` = '000000');
+
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+SELECT 2027208880369647617, '000000', '条件分支节点响应模板', 'node.switch.template', '🔀 条件分支节点:触发 -> 跳转到节点 ', 'Y', 103, 1, '2026-02-27 10:27:15', 1, '2026-02-27 10:35:54', NULL
+FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_config` WHERE `config_key` = 'node.switch.template' AND `tenant_id` = '000000');
+
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+SELECT 2027213914603995137, '000000', '大模型回答节点响应模板', 'node.llmAnswer.template', '🤖 LLM 节点 生成回答:', 'Y', 103, 1, '2026-02-27 10:47:16', 1, '2026-02-27 10:52:40', NULL
+FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_config` WHERE `config_key` = 'node.llmAnswer.template' AND `tenant_id` = '000000');
+
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+SELECT 2027214387000066050, '000000', '关键词提取响应模板', 'node.keywordExtractor.template', '🔑 关键词提取节点 处理完成 : ', 'Y', 103, 1, '2026-02-27 10:49:08', 1, '2026-02-27 10:52:08', NULL
+FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_config` WHERE `config_key` = 'node.keywordExtractor.template' AND `tenant_id` = '000000');
+
+INSERT INTO `sys_config` (`config_id`, `tenant_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+SELECT 2027217577397391361, '000000', '工作流异常响应模板', 'node.exception.template', '🛑 工作流发生异常:', 'N', 103, 1, '2026-02-27 11:01:49', 1, '2026-02-27 11:02:01', NULL
+FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_config` WHERE `config_key` = 'node.exception.template' AND `tenant_id` = '000000');
diff --git a/docs/script/sql/update/updat-0419.sql b/docs/script/sql/update/updat-0419.sql
deleted file mode 100644
index f744f8a5..00000000
--- a/docs/script/sql/update/updat-0419.sql
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- Navicat Premium Dump SQL
-
- Source Server : localhost-mysql
- Source Server Type : MySQL
- Source Server Version : 80045 (8.0.45)
- Source Host : localhost:3306
- Source Schema : ruoyi-ai
-
- Target Server Type : MySQL
- Target Server Version : 80045 (8.0.45)
- File Encoding : 65001
-
- Date: 19/04/2026 13:36:41
-*/
-
-SET NAMES utf8mb4;
-SET FOREIGN_KEY_CHECKS = 0;
-
--- ----------------------------
--- Table structure for chat_model
--- ----------------------------
-DROP TABLE IF EXISTS `chat_model`;
-CREATE TABLE `chat_model` (
- `id` bigint NOT NULL COMMENT '主键',
- `category` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型分类',
- `model_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型名称',
- `provider_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型供应商',
- `model_describe` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型描述',
- `model_dimension` int NULL DEFAULT NULL COMMENT '模型维度',
- `model_show` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否显示',
- `api_host` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '请求地址',
- `api_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密钥',
- `create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门',
- `create_by` bigint NULL DEFAULT NULL COMMENT '创建者',
- `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
- `update_by` bigint NULL DEFAULT NULL COMMENT '更新者',
- `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
- `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
- `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户Id',
- PRIMARY KEY (`id`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '模型管理' ROW_FORMAT = DYNAMIC;
-
--- ----------------------------
--- Records of chat_model
--- ----------------------------
-INSERT INTO `chat_model` VALUES (2000585866022060033, 'chat', 'zai-org/glm-5', 'ppio', 'zai-org/glm-5', NULL, 'Y', 'https://api.ppio.com/openai', 'sk_xx', 103, 1, '2025-12-15 23:16:54', 1, '2026-03-15 19:18:48', 'DeepSeek-V3.2 是一款在高效推理、复杂推理能力与智能体场景中表现突出的领先模型。其基于 DeepSeek Sparse Attention(DSA)稀疏注意力机制,在显著降低计算开销的同时优化长上下文性能;通过可扩展强化学习框架,整体能力达到 GPT-5 同级,高算力版本 V3.2-Speciale 更在推理表现上接近 Gemini-3.0-Pro;同时,模型依托大型智能体任务合成管线,具备更强的工具调用与多步骤决策能力,并在 2025 年 IMO 与 IOI 中取得金牌级表现。作为 MaaS 平台,我们已对 DeepSeek-V3.2 完成深度适配,通过动态调度、批处理加速、低延迟推理与企业级 SLA 保障,进一步增强其在企业生产环境中的稳定性、性价比与可控性,适用于搜索、问答、智能体、代码、数据处理等多类高价值场景。', 0);
-INSERT INTO `chat_model` VALUES (2007528268536287233, 'vector', 'baai/bge-m3', 'ppio', 'bge-m3', 1024, 'N', 'https://api.ppio.com/openai', 'sk_xx', 103, 1, '2026-01-04 03:03:32', 1, '2026-03-15 19:18:51', 'BGE-M3 是一款具备多维度能力的文本嵌入模型,可同时实现密集检索、多向量检索和稀疏检索三大核心功能。该模型设计上兼容超过100种语言,并支持从短句到长达8192词元的长文本等多种输入形式。在跨语言检索任务中,BGE-M3展现出显著优势,其性能在MIRACL、MKQA等国际基准测试中位居前列。此外,针对长文档检索场景,该模型在MLDR、NarritiveQA等数据集上的表现同样达到行业领先水平。', 0);
-INSERT INTO `chat_model` VALUES (2045735140488847361, 'chat', 'deepseek-chat', 'custom_api', 'deepseek-chat', NULL, NULL, 'https://api.deepseek.com', 'sk_xx', 103, 1, '2026-04-19 13:24:00', 1, '2026-04-19 13:24:00', 'deepseek对话模型', 0);
-
--- ----------------------------
--- Table structure for chat_provider
--- ----------------------------
-DROP TABLE IF EXISTS `chat_provider`;
-CREATE TABLE `chat_provider` (
- `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
- `provider_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '厂商名称',
- `provider_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '厂商编码',
- `provider_icon` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '厂商图标',
- `provider_desc` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '厂商描述',
- `api_host` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'API地址',
- `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '状态(0正常 1停用)',
- `sort_order` int NULL DEFAULT 0 COMMENT '排序',
- `create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门',
- `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
- `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
- `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
- `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
- `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
- `version` int NULL DEFAULT NULL COMMENT '版本',
- `del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '删除标志',
- `update_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '更新IP',
- `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户Id',
- PRIMARY KEY (`id`) USING BTREE,
- UNIQUE INDEX `unique_provider_code`(`provider_code` ASC, `tenant_id` ASC, `del_flag` ASC) USING BTREE,
- INDEX `idx_status`(`status` ASC) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 2045727230803255298 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '厂商管理表' ROW_FORMAT = DYNAMIC;
-
--- ----------------------------
--- Records of chat_provider
--- ----------------------------
-INSERT INTO `chat_provider` VALUES (1, 'OpenAI', 'openai', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/01091be272334383a1efd9bc22b73ee6.png', 'OpenAI官方API服务商', 'https://api.openai.com', '0', 1, 103, '2025-12-14 21:48:11', '1', '1', '2026-02-25 20:46:59', 'OpenAI厂商', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (11, '深度求索', 'deepseek', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/04/19/5ba8c30f153246898a4d7dc7b846de8d.png', 'DeepSeek官方API', 'https://api.deepseek.com', '0', 0, 103, '2026-04-19 12:52:34', '1', '1', '2026-04-19 13:13:25', 'DeepSeek官方API', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (12, '智谱AI', 'zhipu', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/04/19/da071783c9284fdd9ed1ce1b57b3c75c.png', '智谱AI大模型服务', 'https://open.bigmodel.cn', '0', 4, 103, '2025-12-14 21:48:11', '1', '1', '2026-04-19 13:14:00', '智谱AI厂商', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (13, '小米MIMO', 'xiaomi', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/04/19/18dd39365ce244e3ae5e030da036760e.png', '小米官方API', 'https://api.xiaomimimo.com/anthropic/v1/messages', '0', 3, 103, '2026-04-19 12:48:24', '1', '1', '2026-04-19 13:14:22', '小米官方API', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (14, '阿里云百炼', 'qianwen', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/de2aa7e649de44f3ba5c6380ac6acd04.png', '阿里云百炼大模型服务', 'https://dashscope.aliyuncs.com', '0', 2, 103, '2025-12-14 21:48:11', '1', '1', '2026-02-25 20:49:13', '阿里云厂商', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (15, 'PPIO', 'ppio', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/049bb6a507174f73bba4b8d8b9e55b8a.png', 'api聚合厂商', 'https://api.ppinfra.com/openai', '0', 5, 103, '2025-12-15 23:13:42', '1', '1', '2026-02-25 20:49:01', 'api聚合厂商', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (16, 'MiniMax', 'minimax', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/04/19/fdc712e90e0e4d78b05862ad230884e5.png', 'MiniMax大模型服务,支持M2.7、M2.5等模型', 'https://api.minimax.io/v1', '0', 6, 103, '2026-04-19 12:50:12', '1', '1', '2026-04-19 13:14:59', 'MiniMax厂商', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (17, 'ollama', 'ollama', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/afecabebc8014d80b0f06b4796a74c5d.png', 'ollama大模型', 'http://127.0.0.1:11434', '0', 7, 103, '2025-12-14 21:48:11', '1', '1', '2026-02-25 20:48:48', 'ollama厂商', NULL, '0', NULL, 0);
-INSERT INTO `chat_provider` VALUES (18, '自定义厂商', 'custom_api', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/04/19/c1a8e122510f4e2f90deb36958af710b.png', 'OPENAI兼容格式', '自定义', '0', 8, 103, '2026-04-19 12:35:57', '1', '1', '2026-04-19 13:17:20', 'OPENAI兼容格式', NULL, '0', NULL, 0);
-
-SET FOREIGN_KEY_CHECKS = 1;
diff --git a/docs/script/sql/update/updat-0420.sql b/docs/script/sql/update/updat-0420.sql
deleted file mode 100644
index 628a6b5c..00000000
--- a/docs/script/sql/update/updat-0420.sql
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- Navicat Premium Dump SQL
-
- Source Server : localhost-mysql
- Source Server Type : MySQL
- Source Server Version : 80045 (8.0.45)
- Source Host : localhost:3306
- Source Schema : ruoyi-ai
-
- Target Server Type : MySQL
- Target Server Version : 80045 (8.0.45)
- File Encoding : 65001
-
- Date: 20/04/2026 15:30:00
-*/
-
-SET NAMES utf8mb4;
-SET FOREIGN_KEY_CHECKS = 0;
-
--- ----------------------------
--- 新增:重排序模型(chat_model)
--- ----------------------------
-INSERT INTO `chat_model`
-(id, category, model_name, provider_code, model_describe, model_dimension, model_show, api_host, api_key, create_dept, create_by, create_time, update_by, update_time, remark, tenant_id)
-VALUES(2045071617578237953, 'rerank', 'rerank', 'zhipu', '智谱重排序', NULL, 'Y', 'https://open.bigmodel.cn', 'e9xx', 103, 1, '2026-04-17 17:27:24', 1, '2026-04-20 15:21:48', '智谱重排序', 0);
-
-INSERT INTO `chat_model`
-(id, category, model_name, provider_code, model_describe, model_dimension, model_show, api_host, api_key, create_dept, create_by, create_time, update_by, update_time, remark, tenant_id)
-VALUES(2046119803482902530, 'rerank', 'qwen3-rerank', 'qianwen', '千问3重排序', NULL, NULL, 'https://dashscope.aliyuncs.com', 'sk-xx', 103, 1, '2026-04-20 14:52:31', 1, '2026-04-20 15:03:13', '千问3文本重排序', 0);
-
--- ----------------------------
--- 新增:字典类型 - 重排序模型分类
--- ----------------------------
-INSERT INTO `sys_dict_data`
-(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark)
-VALUES(2045070879435259905, '000000', 4, '重排序', 'rerank', 'chat_model_category', NULL, '#000000', 'N', 103, 1, '2026-04-17 17:24:28', 1, '2026-04-19 01:02:20', '重排序模型');
-
--- ----------------------------
--- 修改表:knowledge_info 增加重排序相关字段
--- ----------------------------
-ALTER TABLE `knowledge_info` ADD COLUMN `enable_rerank` tinyint DEFAULT 0 NULL COMMENT '是否启用重排序(0否 1是)';
-ALTER TABLE `knowledge_info` ADD COLUMN `rerank_score_threshold` double NULL COMMENT '重排序相关性分数阈值';
-ALTER TABLE `knowledge_info` ADD COLUMN `rerank_top_n` int NULL COMMENT '重排序后返回的文档数量';
-ALTER TABLE `knowledge_info` ADD COLUMN `rerank_model` varchar(100) NULL COMMENT '重排序模型名称';
-
-SET FOREIGN_KEY_CHECKS = 1;
\ No newline at end of file
diff --git a/docs/script/sql/update/updat-0423.sql b/docs/script/sql/update/updat-0423.sql
deleted file mode 100644
index 4ed14430..00000000
--- a/docs/script/sql/update/updat-0423.sql
+++ /dev/null
@@ -1,14 +0,0 @@
--- 为知识库信息表新增检索配置字段 (剔除了已存在的重排字段)
-ALTER TABLE knowledge_info
- ADD COLUMN similarity_threshold DOUBLE DEFAULT 0.5 COMMENT '相似度阈值'
-AFTER retrieve_limit;
-
-ALTER TABLE knowledge_info ADD COLUMN enable_hybrid tinyint(1) DEFAULT 0 COMMENT '是否启用混合检索';
-ALTER TABLE knowledge_info ADD COLUMN hybrid_alpha double DEFAULT 0.5 COMMENT '混合检索权重比例 (0.0=纯向量, 1.0=纯关键词)';
-
--- 为知识片段表增加全文索引及关联ID
-ALTER TABLE knowledge_fragment ADD COLUMN knowledge_id bigint COMMENT '知识库ID';
-ALTER TABLE knowledge_fragment ADD FULLTEXT INDEX ft_content (content) WITH PARSER ngram;
-
--- 为知识库附件表增加解析状态字段
-ALTER TABLE `knowledge_attach` ADD COLUMN `status` TINYINT DEFAULT 0 COMMENT '解析状态: 0待解析, 1解析中, 2已解析, 3解析失败';
diff --git a/pom.xml b/pom.xml
index 4441852f..c1102289 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
+ * 框架自动生成 JSON Schema 并强制 LLM 返回符合结构的数据,无需手工 parse。
+ *
+ * @author ageerle
+ */
+public interface ShortDramaScriptAgent {
+
+ @SystemMessage("""
+ 你是顶级短剧编剧和创意总监。请根据用户的一个创意想法,创作完整的短剧剧本。
+
+ 【核心原则 - 最高优先级】
+ 1. 剧本必须完整、有张力、有画面感
+ 2. 角色要有鲜明性格,不是工具人
+ 3. 情节紧凑,每句台词都推动剧情
+ 4. 场景描写具体,让分镜师能直接画出画面
+ 5. 对话自然有力,避免废话
+
+ 【剧本格式】
+ 使用标准剧本格式,包含以下元素:
+ 1. 场景头(Scene Heading):内景/外景+地点+时间,如"内景 客厅 清晨"
+ 2. 场景描述(Scene Description):简洁描述场景环境、布局、关键道具
+ 3. 动作描述(Action):描述角色的动作、表情、行为,连续段落形式
+ 4. 对话(Dialogue):角色名: 台词内容
+ 5. 画外音(Voiceover):旁白、独白、回忆中的声音
+
+ 【剧本长度要求】
+ - scriptText:1000-3000字,含完整的开场、冲突发展、高潮、结尾
+ - outlineText:400-800字,概述完整故事线
+
+ 【角色塑造要求】
+ - 每个角色要有明确的性格标签(如:霸道总裁、温柔女医、腹黑谋士)
+ - 角色之间要有清晰的关系和冲突
+ - 对话要符合角色性格
+
+ 【情节要求】
+ - 必须有清晰的冲突和反转
+ - 情绪节奏要有起伏(紧张→舒缓→爆发)
+ - 结尾要有记忆点(反转/留白/情感升华)
+ """)
+ @UserMessage("用户期望项目名:{{projectName}}\n用户创意:{{idea}}")
+ ShortDramaScriptResult polish(@V("projectName") String projectName, @V("idea") String idea);
+}
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/agent/SqlAgent.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/agent/SqlAgent.java
index e21b61c1..6cadc94c 100644
--- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/agent/SqlAgent.java
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/agent/SqlAgent.java
@@ -30,6 +30,9 @@ public interface SqlAgent {
- You MUST ALWAYS use queryAllTables first to query all tables in the database before executing any SQL queries
- Only after understanding the database schema can you construct and execute appropriate SQL queries
- This is mandatory and applies to all queries without exception
+ - If queryAllTables returns NO tables or an empty list, you MUST NOT call executeSql or queryTableSchema
+ - When no tables are available, inform the user: "当前未配置可查询的数据库表,请联系管理员配置"
+ - NEVER attempt to execute any SQL query (including SELECT * FROM xxx) without first confirming available tables
""")
@UserMessage("""
Answer the following question: {{query}}
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/agent/tool/ExecuteSqlQueryTool.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/agent/tool/ExecuteSqlQueryTool.java
index 1b9079f1..a17bf545 100644
--- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/agent/tool/ExecuteSqlQueryTool.java
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/agent/tool/ExecuteSqlQueryTool.java
@@ -8,9 +8,14 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import javax.sql.DataSource;
+import org.ruoyi.agent.manager.TableSchemaManager;
import org.ruoyi.common.core.utils.SpringUtils;
import org.springframework.stereotype.Component;
@@ -54,6 +59,22 @@ public class ExecuteSqlQueryTool implements BuiltinToolProvider {
return "Error: Only SELECT queries are allowed for security reasons";
}
+ // 校验表白名单:未配置表时直接拒绝,已配置则校验 SQL 中引用的表
+ TableSchemaManager schemaManager = SpringUtils.getBean(TableSchemaManager.class);
+ List
+ * langchain4j 的 ShellSkills 通过 FileSystemSkillLoader 从磁盘加载 SKILL.md,
+ * 路径硬编码在 ChatServiceFacade 中。抽到此工具类供智能体管理端与聊天流程共用,
+ * 避免两处路径漂移。
+ *
+ * @author ruoyi team
+ */
+public final class SkillsPathResolver {
+
+ private SkillsPathResolver() {
+ }
+
+ /**
+ * skills 目录相对项目根目录的路径
+ */
+ private static final String SKILLS_RELATIVE_PATH = "ruoyi-admin/src/main/resources/skills";
+
+ /**
+ * 返回磁盘 skills 目录的绝对路径
+ */
+ public static Path resolveSkillsPath() {
+ String userDir = System.getProperty("user.dir");
+ return Path.of(userDir, SKILLS_RELATIVE_PATH);
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/constant/ShortDramaImageConstants.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/constant/ShortDramaImageConstants.java
new file mode 100644
index 00000000..619b7bef
--- /dev/null
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/constant/ShortDramaImageConstants.java
@@ -0,0 +1,72 @@
+package org.ruoyi.constant;
+
+/**
+ * 短剧图片资产常量 — 三视图 prompt 工程
+ *
+ * @author ruoyi
+ */
+public final class ShortDramaImageConstants {
+
+ private ShortDramaImageConstants() {}
+
+ /**
+ * 角色三视图 prompt 前缀,生图时自动拼到用户 prompt 之前。
+ * 把风格和构图指令放最前面,避免被角色描述稀释导致画风漂移。
+ */
+ public static final String CHARACTER_PROMPT_PREFIX =
+ "character design sheet, multiple views reference sheet, " +
+ "front view / side view / back view full body, " +
+ "clean white background, no props, no text. ";
+
+ /**
+ * 角色三视图 prompt 后缀,生图时自动追加到用户 prompt 之后。
+ * 左侧1/3正面特写 + 右侧2/3三视图横向排列(正面全身、侧面全身、背面全身)。
+ */
+ public static final String CHARACTER_PROMPT_SUFFIX =
+ "。角色设定图,画面分为左右两个区域:" +
+ "【左侧区域】占约1/3宽度,是角色的正面特写" +
+ "(完整正脸,最具辨识度的正面形态);" +
+ "【右侧区域】占约2/3宽度,是角色三视图横向排列" +
+ "(从左到右依次为:正面全身、侧面全身、背面全身)," +
+ "三视图高度一致。纯白色背景,无其他元素。";
+
+ /** 场景图 prompt 前缀 */
+ public static final String LOCATION_PROMPT_PREFIX = "宽广空间全景,";
+
+ /** 场景图 prompt 后缀 */
+ public static final String LOCATION_PROMPT_SUFFIX = ",禁止出现任何角色,纯背景板";
+
+ /** 每个资产最多保留的图片变体数量 */
+ public static final int MAX_IMAGE_VARIANTS = 20;
+
+ // ==================== 视觉风格 ====================
+
+ /** 项目视觉风格 → 生图 prompt 后缀映射,确保同项目所有图片风格一致 */
+ public static final java.util.Map 第一阶段 {@code /coding/**} 在 {@code application.yml} 的 security.excludes 中,
+ * 免鉴权直连。Controller 只做参数绑定 + 同步取 userId(Sa-Token 异步上下文丢失,
+ * 见 SecurityConfig 注释)+ 转发 Service。
+ *
+ * @author ageerle
+ */
+@Validated
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/coding")
+public class CodingController {
+
+ private final ICodingService codingService;
+ private final CodingWorkspaceService workspaceService;
+ private final IChatModelService chatModelService;
+
+ /**
+ * 编程对话(SSE 流式)
+ *
+ * @param bo 请求参数(prompt / model / workspacePath)
+ * @return SseEmitter
+ */
+ @PostMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
+ public SseEmitter chat(@Valid @RequestBody CodingRequestBo bo) {
+ // 同步线程取 userId;第一阶段免鉴权,可能为 null
+ Long userId = LoginHelper.getUserId();
+ return codingService.chat(bo, userId);
+ }
+
+ @GetMapping("/workspace")
+ public R
+ * 一个智能体聚合:一个聊天模型 + 一组 MCP 工具 + 一组磁盘技能 + 一组知识库 + 自定义提示词
+ * 关联以 JSON 数组字符串列存储:mcp_tool_ids / skill_names / knowledge_ids
+ *
+ * @author ruoyi team
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("agent_info")
+public class Agent extends TenantEntity {
+
+ /**
+ * 智能体ID
+ */
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 智能体名称
+ */
+ private String agentName;
+
+ /**
+ * 智能体描述(下拉展示用)
+ */
+ private String agentDescribe;
+
+ /**
+ * 展示图标/头像URL
+ */
+ private String agentShow;
+
+ /**
+ * 绑定的聊天模型ID(chat_model.id, category=chat)
+ */
+ private Long modelId;
+
+ /**
+ * 是否启用深度思考(ReAct多子Agent):0 否 1 是
+ */
+ private String enableThinking;
+
+ /**
+ * 自定义系统提示词
+ */
+ private String systemPrompt;
+
+ /**
+ * 关联MCP工具ID列表(JSON数组,[Long])
+ */
+ private String mcpToolIds;
+
+ /**
+ * 关联磁盘技能名列表(JSON数组,[String])
+ */
+ private String skillNames;
+
+ /**
+ * 关联知识库ID列表(JSON数组,[Long])
+ */
+ private String knowledgeIds;
+
+ /**
+ * 状态:0 正常 1 停用
+ */
+ private String status;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+}
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/knowledge/KnowledgeAttach.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/knowledge/KnowledgeAttach.java
index 2d836f88..4b244efa 100644
--- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/knowledge/KnowledgeAttach.java
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/knowledge/KnowledgeAttach.java
@@ -37,6 +37,9 @@ public class KnowledgeAttach extends BaseEntity {
*/
private String docId;
+ /** SHA-256 content digest used for upload idempotency. */
+ private String fileHash;
+
/**
* 附件名称
*/
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/knowledge/KnowledgeFragment.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/knowledge/KnowledgeFragment.java
index d184a10a..1fa84aca 100644
--- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/knowledge/KnowledgeFragment.java
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/knowledge/KnowledgeFragment.java
@@ -27,6 +27,11 @@ public class KnowledgeFragment extends BaseEntity {
@TableId(value = "id")
private Long id;
+ /**
+ * 向量库片段ID(与向量库中的 fid 元数据对应,用于向量定位与混合检索融合)
+ */
+ private String fid;
+
/**
* 文档ID-用于关联文本块信息
*/
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaAudio.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaAudio.java
new file mode 100644
index 00000000..dd02f16b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaAudio.java
@@ -0,0 +1,47 @@
+package org.ruoyi.domain.entity.shortdrama;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.ruoyi.common.mybatis.core.domain.BaseEntity;
+
+import java.io.Serial;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("short_drama_audio")
+public class ShortDramaAudio extends BaseEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id")
+ private Long id;
+
+ private Long projectId;
+
+ /** 语音资产名称 */
+ private String name;
+
+ /** 语音类型:narration(旁白)/dialogue(对白) */
+ private String audioType;
+
+ /** 语音文案(生成语音用的文本) */
+ private String text;
+
+ /** 音色(如 alloy/onyx) */
+ private String voice;
+
+ /** 音频文件OSS ID */
+ private Long audioOssId;
+
+ /** 音频文件URL */
+ private String audioUrl;
+
+ /** 对白关联的分镜ID(NULL=全局旁白) */
+ private Long linkedStoryboardId;
+
+ /** 音频时长(秒) */
+ private Integer durationSeconds;
+}
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaCharacter.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaCharacter.java
new file mode 100644
index 00000000..25472e44
--- /dev/null
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaCharacter.java
@@ -0,0 +1,43 @@
+package org.ruoyi.domain.entity.shortdrama;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.ruoyi.common.mybatis.core.domain.BaseEntity;
+
+import java.io.Serial;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("short_drama_character")
+public class ShortDramaCharacter extends BaseEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id")
+ private Long id;
+
+ private Long projectId;
+
+ private String name;
+
+ private String aliases;
+
+ private String introduction;
+
+ private String roleLevel;
+
+ private String gender;
+
+ private String ageRange;
+
+ private String personalityTags;
+
+ private Integer costumeTier;
+
+ private String visualDescription;
+
+ private String referenceImageUrl;
+}
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaCharacterAppearance.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaCharacterAppearance.java
new file mode 100644
index 00000000..53360596
--- /dev/null
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaCharacterAppearance.java
@@ -0,0 +1,49 @@
+package org.ruoyi.domain.entity.shortdrama;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.ruoyi.common.mybatis.core.domain.BaseEntity;
+
+import java.io.Serial;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("short_drama_character_appearance")
+public class ShortDramaCharacterAppearance extends BaseEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id")
+ private Long id;
+
+ private Long characterId;
+
+ private Integer appearanceIndex;
+
+ private String changeReason;
+
+ private String description;
+
+ private String referenceImageUrl;
+
+ /** 生成图片URL列表(JSON数组) */
+ private String imageUrls;
+
+ /** 每张图片对应的提示词(JSON数组) */
+ private String imageDescriptions;
+
+ /** 当前选中的图片索引 */
+ private Integer selectedImageIndex;
+
+ /** 上一轮图片URL列表(撤销用,JSON数组) */
+ private String previousImageUrls;
+
+ /** 上一轮提示词列表(撤销用,JSON数组) */
+ private String previousDescriptions;
+
+ /** 音色名(如 zh_male_taocheng_uranus_bigtts),用于该形象的对白配音 */
+ private String voice;
+}
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaLocation.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaLocation.java
new file mode 100644
index 00000000..7ae05126
--- /dev/null
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaLocation.java
@@ -0,0 +1,52 @@
+package org.ruoyi.domain.entity.shortdrama;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.ruoyi.common.mybatis.core.domain.BaseEntity;
+
+import java.io.Serial;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("short_drama_location")
+public class ShortDramaLocation extends BaseEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id")
+ private Long id;
+
+ private Long projectId;
+
+ private String name;
+
+ private String summary;
+
+ private Boolean hasCrowd;
+
+ private String crowdDescription;
+
+ private String availableSlots;
+
+ private String descriptions;
+
+ private String referenceImageUrl;
+
+ /** 生成图片URL列表(JSON数组) */
+ private String imageUrls;
+
+ /** 每张图片对应的提示词(JSON数组) */
+ private String imageDescriptions;
+
+ /** 当前选中的图片索引 */
+ private Integer selectedImageIndex;
+
+ /** 上一轮图片URL列表(撤销用,JSON数组) */
+ private String previousImageUrls;
+
+ /** 上一轮提示词列表(撤销用,JSON数组) */
+ private String previousDescriptions;
+}
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaProject.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaProject.java
new file mode 100644
index 00000000..529c3cdd
--- /dev/null
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaProject.java
@@ -0,0 +1,53 @@
+package org.ruoyi.domain.entity.shortdrama;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.ruoyi.common.mybatis.core.domain.BaseEntity;
+
+import java.io.Serial;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("short_drama_project")
+public class ShortDramaProject extends BaseEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id")
+ private Long id;
+
+ private Long userId;
+
+ private String projectName;
+
+ private String description;
+
+ private String status;
+
+ private String artStyle;
+
+ private Long composedVideoOssId;
+
+ private String composeStatus;
+
+ private String composeJobId;
+
+ private Integer composeProgress;
+
+ private String composeTransitionType;
+
+ private BigDecimal composeTransitionDurationSeconds;
+
+ private String composeAspectRatio;
+
+ private BigDecimal composedVideoDurationSeconds;
+
+ private String composeErrorMessage;
+
+ private Date composedAt;
+}
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaScript.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaScript.java
new file mode 100644
index 00000000..7a5b0e60
--- /dev/null
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaScript.java
@@ -0,0 +1,33 @@
+package org.ruoyi.domain.entity.shortdrama;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.ruoyi.common.mybatis.core.domain.BaseEntity;
+
+import java.io.Serial;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("short_drama_script")
+public class ShortDramaScript extends BaseEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id")
+ private Long id;
+
+ private Long projectId;
+
+ private String scriptName;
+
+ private String scriptText;
+
+ private String outlineText;
+
+ private String tone;
+
+ private String sourceType;
+}
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaStoryboard.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaStoryboard.java
new file mode 100644
index 00000000..5a2e2004
--- /dev/null
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/shortdrama/ShortDramaStoryboard.java
@@ -0,0 +1,64 @@
+package org.ruoyi.domain.entity.shortdrama;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.ruoyi.common.mybatis.core.domain.BaseEntity;
+
+import java.io.Serial;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("short_drama_storyboard")
+public class ShortDramaStoryboard extends BaseEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id")
+ private Long id;
+
+ private Long projectId;
+
+ private Long scriptId;
+
+ private Integer sceneNo;
+
+ private String sceneTitle;
+
+ private String sceneText;
+
+ private String sceneType;
+
+ private String shotType;
+
+ private String cameraMove;
+
+ private String charactersJson;
+
+ private String locationName;
+
+ private String photographyRules;
+
+ private String actingNotes;
+
+ private String continuityJson;
+
+ private String sourceText;
+
+ private String imagePrompt;
+
+ private Integer durationSeconds;
+
+ private String videoPrompt;
+
+ private String videoUrl;
+
+ private String videoId;
+
+ private String videoStatus;
+
+ /** 上一镜末帧URL(同场景连续镜头首帧承接用) */
+ private String lastFrameUrl;
+}
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/vo/agent/AgentVo.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/vo/agent/AgentVo.java
new file mode 100644
index 00000000..102d83a5
--- /dev/null
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/vo/agent/AgentVo.java
@@ -0,0 +1,121 @@
+package org.ruoyi.domain.vo.agent;
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 智能体视图对象
+ *
+ * 注意:不使用 @AutoMapper,因为 entity 的 mcpToolIds/skillNames/knowledgeIds 是 JSON 字符串列,
+ * 而 VO 是 List 类型,MapStruct 无法双向自动转换。由 AgentServiceImpl.toVo 手动组装。
+ *
+ * @author ruoyi team
+ */
+@Data
+@ExcelIgnoreUnannotated
+public class AgentVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 智能体ID
+ */
+ @ExcelProperty(value = "智能体ID")
+ private Long id;
+
+ /**
+ * 智能体名称
+ */
+ @ExcelProperty(value = "智能体名称")
+ private String agentName;
+
+ /**
+ * 智能体描述
+ */
+ @ExcelProperty(value = "智能体描述")
+ private String agentDescribe;
+
+ /**
+ * 展示图标/头像URL
+ */
+ private String agentShow;
+
+ /**
+ * 绑定的聊天模型ID
+ */
+ @ExcelProperty(value = "绑定模型ID")
+ private Long modelId;
+
+ /**
+ * 绑定的聊天模型名称(关联展示)
+ */
+ @ExcelProperty(value = "绑定模型")
+ private String modelName;
+
+ /**
+ * 是否启用深度思考:0 否 1 是
+ */
+ @ExcelProperty(value = "深度思考")
+ private String enableThinking;
+
+ /**
+ * 自定义系统提示词
+ */
+ private String systemPrompt;
+
+ /**
+ * 关联MCP工具ID列表
+ */
+ private List> queryList(AgentBo bo) {
+ return R.ok(agentService.queryList(bo));
+ }
+
+ /**
+ * 导出智能体列表
+ */
+ @SaCheckPermission("agent:agent:export")
+ @Log(title = "智能体管理", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(AgentBo bo, HttpServletResponse response) {
+ List
> agentOptions() {
+ return R.ok(agentService.queryEnabledOptions());
+ }
+
+ /**
+ * 列出磁盘上可用的 Skills(供管理端表单勾选)
+ */
+ @SaCheckPermission("agent:agent:list")
+ @GetMapping("/skillOptions")
+ public R
> skillOptions() {
+ return R.ok(agentService.listSkillOptions());
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/chat/ChatModelController.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/chat/ChatModelController.java
index adf4322b..42d3b5fd 100644
--- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/chat/ChatModelController.java
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/chat/ChatModelController.java
@@ -8,7 +8,9 @@ import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.ruoyi.common.chat.service.chat.IChatModelService;
import org.ruoyi.common.chat.domain.bo.chat.ChatModelBo;
+import org.ruoyi.common.chat.domain.bo.chat.ModelBatchKeyBo;
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
+import org.ruoyi.common.core.utils.StringUtils;
import org.ruoyi.enums.ChatModeType;
import org.ruoyi.enums.ModelType;
import org.springframework.web.bind.annotation.*;
@@ -54,7 +56,9 @@ public class ChatModelController extends BaseController {
*/
@GetMapping("/modelList")
public R
> modelList(ChatModelBo bo) {
- bo.setCategory(ModelType.CHAT.getKey());
+ if (StringUtils.isBlank(bo.getCategory())) {
+ bo.setCategory(ModelType.CHAT.getKey());
+ }
return R.ok(chatModelService.queryList(bo));
}
@@ -118,6 +122,17 @@ public class ChatModelController extends BaseController {
return toAjax(chatModelService.updateByBo(bo));
}
+ /**
+ * 按厂商批量更新密钥
+ */
+ @SaCheckPermission("system:model:edit")
+ @Log(title = "模型管理", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping("/batchKeyByProvider")
+ public R
> models() {
+ // 编程对话只能用聊天模型,按 category=chat 过滤
+ ChatModelBo bo = new ChatModelBo();
+ bo.setCategory(ModelType.CHAT.getKey());
+ List
> retrieval(@RequestBody KnowledgeFragmentBo bo) {
return R.ok(knowledgeFragmentService.retrieval(bo));
}
diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/shortdrama/ShortDramaController.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/shortdrama/ShortDramaController.java
new file mode 100644
index 00000000..6ecd69a3
--- /dev/null
+++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/shortdrama/ShortDramaController.java
@@ -0,0 +1,408 @@
+package org.ruoyi.controller.shortdrama;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.ruoyi.common.chat.entity.media.MediaGenerationResponse;
+import org.ruoyi.common.core.domain.R;
+import org.ruoyi.common.core.exception.ServiceException;
+import org.ruoyi.common.core.service.OssService;
+import org.ruoyi.common.satoken.utils.LoginHelper;
+import org.ruoyi.domain.bo.shortdrama.ShortDramaCharacterBo;
+import org.ruoyi.domain.bo.shortdrama.ShortDramaCharacterAppearanceBo;
+import org.ruoyi.domain.bo.shortdrama.ShortDramaComposeVideoBo;
+import org.ruoyi.domain.bo.shortdrama.ShortDramaAudioBo;
+import org.ruoyi.domain.bo.shortdrama.ShortDramaLocationBo;
+import org.ruoyi.domain.bo.shortdrama.ShortDramaProjectBo;
+import org.ruoyi.domain.bo.shortdrama.ShortDramaScriptBo;
+import org.ruoyi.domain.bo.shortdrama.ShortDramaStoryboardBo;
+import org.ruoyi.domain.bo.shortdrama.ShortDramaIdeaBo;
+import org.ruoyi.domain.vo.shortdrama.ShortDramaCharacterVo;
+import org.ruoyi.domain.vo.shortdrama.ShortDramaCharacterAppearanceVo;
+import org.ruoyi.domain.vo.shortdrama.ShortDramaComposeVideoVo;
+import org.ruoyi.domain.vo.shortdrama.ShortDramaDetailVo;
+import org.ruoyi.domain.vo.shortdrama.ShortDramaAudioVo;
+import org.ruoyi.domain.vo.shortdrama.ShortDramaLocationVo;
+import org.ruoyi.domain.vo.shortdrama.ShortDramaProjectVo;
+import org.ruoyi.domain.vo.shortdrama.ShortDramaScriptVo;
+import org.ruoyi.domain.vo.shortdrama.ShortDramaStoryboardVo;
+import org.ruoyi.service.shortdrama.IShortDramaService;
+import org.ruoyi.service.shortdrama.IShortDramaVideoComposeService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+@Validated
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/short-drama")
+public class ShortDramaController {
+
+ private final IShortDramaService shortDramaService;
+
+ private final IShortDramaVideoComposeService videoComposeService;
+
+ private final OssService ossService;
+
+ // ==================== 项目 ====================
+
+ @GetMapping("/projects")
+ public R
> projects() {
+ return R.ok(shortDramaService.listProjects(LoginHelper.getUserId()));
+ }
+
+ @GetMapping("/{projectId}")
+ public R
> generate(@NotNull @RequestParam Long projectId,
+ @NotNull @RequestParam Long scriptId,
+ @RequestParam(required = false) String model) {
+ return R.ok(shortDramaService.generateStoryboards(projectId, scriptId, model, LoginHelper.getUserId()));
+ }
+
+ @PostMapping("/storyboard")
+ public R
> generateAllVideos(@NotNull @PathVariable Long projectId,
+ @NotBlank @RequestParam String model) {
+ return R.ok(shortDramaService.generateAllVideos(projectId, model, LoginHelper.getUserId()));
+ }
+
+ @PostMapping("/{projectId}/compose-video")
+ public R
> planStoryboard(@NotNull @PathVariable Long projectId,
+ @NotNull @RequestParam Long scriptId,
+ @RequestParam(required = false) String model) {
+ return R.ok(shortDramaService.planStoryboard(projectId, scriptId, model, LoginHelper.getUserId()));
+ }
+
+ /** Phase 3-6: SSE 流式生成分镜,持续推送规划和细化进度 */
+ @PostMapping("/{projectId}/plan-storyboard/stream")
+ public SseEmitter planStoryboardStream(@NotNull @PathVariable Long projectId,
+ @NotNull @RequestParam Long scriptId,
+ @RequestParam(required = false) String model) {
+ return shortDramaService.planStoryboardStream(projectId, scriptId, model, LoginHelper.getUserId());
+ }
+
+ /** Phase 4: 重新生成摄影规则 */
+ @PostMapping("/{projectId}/photography-rules")
+ public R
> generatePhotographyRules(@NotNull @PathVariable Long projectId,
+ @NotNull @RequestParam Long scriptId) {
+ return R.ok(shortDramaService.generatePhotographyRules(projectId, scriptId, LoginHelper.getUserId()));
+ }
+
+ /** Phase 5: 重新生成表演指导 */
+ @PostMapping("/{projectId}/acting-directions")
+ public R
> generateActingDirections(@NotNull @PathVariable Long projectId,
+ @NotNull @RequestParam Long scriptId) {
+ return R.ok(shortDramaService.generateActingDirections(projectId, scriptId, LoginHelper.getUserId()));
+ }
+
+ // ==================== 角色管理 ====================
+
+ @PostMapping("/character")
+ public R
> listAudios(@NotNull @RequestParam Long projectId) {
+ return R.ok(shortDramaService.listAudios(projectId, LoginHelper.getUserId()));
+ }
+
+ @PostMapping("/audio/{audioId}/generate-speech")
+ public R