44406b72db
Moteva-style AI design workbench replica. Home prompt creates a project; the project page provides an infinite canvas with node drag, zoom/pan, a design chat panel, history replay, image asset upload, and project save/regenerate. - Backend: go-zero, DDD layering, sqlc/pgx, optional PostgreSQL; memory or Redis cache; asynq job queue; MinIO/S3/R2/OSS object storage; sky-valley/pi agent runtime adapter. - Frontend: Next.js App Router + Vite artifact build, TypeScript, i18n, shadcn/ui components, auth (OTP/Turnstile/Google/WeChat). - Deploy: Docker Compose and k3s manifests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
170 lines
6.3 KiB
SQL
170 lines
6.3 KiB
SQL
-- name: ListProjects :many
|
|
SELECT id, user_id, title, brief, status, thumbnail, updated_at
|
|
FROM projects
|
|
WHERE user_id = $1
|
|
ORDER BY updated_at DESC;
|
|
|
|
-- name: ListProjectsPage :many
|
|
SELECT id, user_id, title, brief, status, thumbnail, updated_at
|
|
FROM projects
|
|
WHERE user_id = $1
|
|
ORDER BY updated_at DESC
|
|
LIMIT $2 OFFSET $3;
|
|
|
|
-- name: GetProject :one
|
|
SELECT id, user_id, title, brief, status, thumbnail, canvas, version, snapshot_id, last_thread_id, viewport_x, viewport_y, viewport_k, updated_at
|
|
FROM projects
|
|
WHERE id = $1 AND user_id = $2;
|
|
|
|
-- name: LockProject :one
|
|
SELECT id, user_id, version
|
|
FROM projects
|
|
WHERE id = $1 AND user_id = $2
|
|
FOR UPDATE;
|
|
|
|
-- name: DeleteProject :exec
|
|
DELETE FROM projects
|
|
WHERE id = $1 AND user_id = $2;
|
|
|
|
-- name: UpsertProject :exec
|
|
INSERT INTO projects (id, user_id, title, brief, status, thumbnail, canvas, version, snapshot_id, last_thread_id, viewport_x, viewport_y, viewport_k, updated_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
|
|
ON CONFLICT (id) DO UPDATE SET
|
|
user_id = EXCLUDED.user_id,
|
|
title = EXCLUDED.title,
|
|
brief = EXCLUDED.brief,
|
|
status = EXCLUDED.status,
|
|
thumbnail = EXCLUDED.thumbnail,
|
|
canvas = EXCLUDED.canvas,
|
|
version = EXCLUDED.version,
|
|
snapshot_id = EXCLUDED.snapshot_id,
|
|
last_thread_id = EXCLUDED.last_thread_id,
|
|
viewport_x = EXCLUDED.viewport_x,
|
|
viewport_y = EXCLUDED.viewport_y,
|
|
viewport_k = EXCLUDED.viewport_k,
|
|
updated_at = EXCLUDED.updated_at;
|
|
|
|
-- name: CreateCanvasSnapshot :exec
|
|
INSERT INTO canvas_snapshots (id, project_id, user_id, version, canvas, viewport_json, nodes_json, connections_json, created_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
ON CONFLICT (id) DO UPDATE SET
|
|
project_id = EXCLUDED.project_id,
|
|
user_id = EXCLUDED.user_id,
|
|
version = EXCLUDED.version,
|
|
canvas = EXCLUDED.canvas,
|
|
viewport_json = EXCLUDED.viewport_json,
|
|
nodes_json = EXCLUDED.nodes_json,
|
|
connections_json = EXCLUDED.connections_json,
|
|
created_at = EXCLUDED.created_at;
|
|
|
|
-- name: GetCanvasSnapshot :one
|
|
SELECT id, project_id, user_id, version, canvas, viewport_json, nodes_json, connections_json, created_at
|
|
FROM canvas_snapshots
|
|
WHERE id = $1 AND project_id = $2 AND user_id = $3;
|
|
|
|
-- name: UpdateProjectCanvasSnapshot :exec
|
|
UPDATE projects
|
|
SET thumbnail = $3,
|
|
canvas = $4,
|
|
version = $5,
|
|
snapshot_id = $6,
|
|
viewport_x = $7,
|
|
viewport_y = $8,
|
|
viewport_k = $9,
|
|
updated_at = $10
|
|
WHERE id = $1 AND user_id = $2;
|
|
|
|
-- name: ListNodesByProject :many
|
|
SELECT id, project_id, user_id, node_type, title, x, y, width, height, content, tone, status, sort_order, parent_id, layer_role, font_size, font_family, font_weight, color, text_align, line_height, letter_spacing, text_decoration, text_transform, opacity, fill_color, stroke_color, stroke_width, stroke_style, flip_x, flip_y, rotation
|
|
FROM canvas_nodes
|
|
WHERE project_id = $1 AND user_id = $2
|
|
ORDER BY sort_order ASC, id ASC;
|
|
|
|
-- name: DeleteNodesByProject :exec
|
|
DELETE FROM canvas_nodes
|
|
WHERE project_id = $1 AND user_id = $2;
|
|
|
|
-- name: UpsertCanvasNode :exec
|
|
INSERT INTO canvas_nodes (id, project_id, user_id, node_type, title, x, y, width, height, content, tone, status, sort_order, parent_id, layer_role, font_size, font_family, font_weight, color, text_align, line_height, letter_spacing, text_decoration, text_transform, opacity, fill_color, stroke_color, stroke_width, stroke_style, flip_x, flip_y, rotation)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32)
|
|
ON CONFLICT (id) DO UPDATE SET
|
|
project_id = EXCLUDED.project_id,
|
|
user_id = EXCLUDED.user_id,
|
|
node_type = EXCLUDED.node_type,
|
|
title = EXCLUDED.title,
|
|
x = EXCLUDED.x,
|
|
y = EXCLUDED.y,
|
|
width = EXCLUDED.width,
|
|
height = EXCLUDED.height,
|
|
content = EXCLUDED.content,
|
|
tone = EXCLUDED.tone,
|
|
status = EXCLUDED.status,
|
|
sort_order = EXCLUDED.sort_order,
|
|
parent_id = EXCLUDED.parent_id,
|
|
layer_role = EXCLUDED.layer_role,
|
|
font_size = EXCLUDED.font_size,
|
|
font_family = EXCLUDED.font_family,
|
|
font_weight = EXCLUDED.font_weight,
|
|
color = EXCLUDED.color,
|
|
text_align = EXCLUDED.text_align,
|
|
line_height = EXCLUDED.line_height,
|
|
letter_spacing = EXCLUDED.letter_spacing,
|
|
text_decoration = EXCLUDED.text_decoration,
|
|
text_transform = EXCLUDED.text_transform,
|
|
opacity = EXCLUDED.opacity,
|
|
fill_color = EXCLUDED.fill_color,
|
|
stroke_color = EXCLUDED.stroke_color,
|
|
stroke_width = EXCLUDED.stroke_width,
|
|
stroke_style = EXCLUDED.stroke_style,
|
|
flip_x = EXCLUDED.flip_x,
|
|
flip_y = EXCLUDED.flip_y,
|
|
rotation = EXCLUDED.rotation;
|
|
|
|
-- name: ListConnectionsByProject :many
|
|
SELECT id, project_id, user_id, from_node_id, to_node_id
|
|
FROM canvas_connections
|
|
WHERE project_id = $1 AND user_id = $2
|
|
ORDER BY id;
|
|
|
|
-- name: DeleteConnectionsByProject :exec
|
|
DELETE FROM canvas_connections
|
|
WHERE project_id = $1 AND user_id = $2;
|
|
|
|
-- name: CreateConnection :exec
|
|
INSERT INTO canvas_connections (id, project_id, user_id, from_node_id, to_node_id)
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
ON CONFLICT (id) DO UPDATE SET
|
|
project_id = EXCLUDED.project_id,
|
|
user_id = EXCLUDED.user_id,
|
|
from_node_id = EXCLUDED.from_node_id,
|
|
to_node_id = EXCLUDED.to_node_id;
|
|
|
|
-- name: ListMessagesByProject :many
|
|
SELECT id, project_id, user_id, role, message_type, title, content, thread_id, action_id, step_id, tool_call_id, name, tool_hint, status, created_at
|
|
FROM agent_messages
|
|
WHERE project_id = $1 AND user_id = $2
|
|
ORDER BY created_at ASC;
|
|
|
|
-- name: DeleteMessagesByProject :exec
|
|
DELETE FROM agent_messages
|
|
WHERE project_id = $1 AND user_id = $2;
|
|
|
|
-- name: CreateMessage :exec
|
|
INSERT INTO agent_messages (id, project_id, user_id, role, message_type, title, content, thread_id, action_id, step_id, tool_call_id, name, tool_hint, status, created_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
|
|
ON CONFLICT (id) DO UPDATE SET
|
|
project_id = EXCLUDED.project_id,
|
|
user_id = EXCLUDED.user_id,
|
|
role = EXCLUDED.role,
|
|
message_type = EXCLUDED.message_type,
|
|
title = EXCLUDED.title,
|
|
content = EXCLUDED.content,
|
|
thread_id = EXCLUDED.thread_id,
|
|
action_id = EXCLUDED.action_id,
|
|
step_id = EXCLUDED.step_id,
|
|
tool_call_id = EXCLUDED.tool_call_id,
|
|
name = EXCLUDED.name,
|
|
tool_hint = EXCLUDED.tool_hint,
|
|
status = EXCLUDED.status,
|
|
created_at = EXCLUDED.created_at;
|