feat: AI 驱动的配方研发智能平台 v0.1
核心功能: - M3 配方记录: 创建/编辑/详情/可视化编辑/AI提取/版本历史/版本对比 - M1 颜色引擎: D3.js 色相环/滑条微调/ΔE计算/取色棒/AI配色推荐 - M2 可视化编辑器: ECharts饼图/成分滑条/AI预测/雷达图/仪表盘 - M4 配方推演: 约束设置/SSE推演/方案对比/散点图 - 平台: NL智能搜索/项目管理/CSV导出/JWT认证/全局搜索 技术栈: - 前端: React + Vite + Tailwind CSS 4 + Zustand + TanStack Query - 后端: Fastify 5 + Prisma 7 + PostgreSQL + pgvector - AI: OpenAI/DeepSeek API 调用 + Prompt模板 + 缓存/降级/限流 - 测试: Vitest 42 tests (26 API集成 + 16 色彩模块)
This commit is contained in:
198
backend/prisma/migrations/0001_init/migration.sql
Normal file
198
backend/prisma/migrations/0001_init/migration.sql
Normal file
@@ -0,0 +1,198 @@
|
||||
-- CreateSchema
|
||||
CREATE SCHEMA IF NOT EXISTS "public";
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "UserRole" AS ENUM ('engineer', 'admin');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "IngredientCategory" AS ENUM ('emulsifier', 'humectant', 'thickener', 'preservative', 'antioxidant', 'fragrance', 'colorant', 'ph_adjuster', 'sunscreen', 'surfactant', 'emollient', 'other');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "users" (
|
||||
"id" TEXT NOT NULL,
|
||||
"username" TEXT NOT NULL,
|
||||
"password_hash" TEXT NOT NULL,
|
||||
"role" "UserRole" NOT NULL DEFAULT 'engineer',
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "users_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "projects" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"created_by" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "projects_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "formulas" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"project_id" TEXT,
|
||||
"current_version" INTEGER NOT NULL DEFAULT 1,
|
||||
"created_by" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||
"embedding" vector(1536),
|
||||
|
||||
CONSTRAINT "formulas_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "formula_versions" (
|
||||
"id" TEXT NOT NULL,
|
||||
"formula_id" TEXT NOT NULL,
|
||||
"version_number" INTEGER NOT NULL,
|
||||
"description" TEXT,
|
||||
"snapshot_data" JSONB NOT NULL,
|
||||
"created_by" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "formula_versions_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ingredients" (
|
||||
"id" TEXT NOT NULL,
|
||||
"inci_name" TEXT NOT NULL,
|
||||
"chinese_name" TEXT NOT NULL,
|
||||
"function_category" "IngredientCategory" NOT NULL,
|
||||
"supplier" TEXT,
|
||||
"unit" TEXT NOT NULL DEFAULT 'kg',
|
||||
"unit_price" DECIMAL(10,2),
|
||||
"description" TEXT,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "ingredients_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "phases" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"formula_id" TEXT NOT NULL,
|
||||
"sort_order" INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
CONSTRAINT "phases_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "formula_ingredients" (
|
||||
"id" TEXT NOT NULL,
|
||||
"formula_version_id" TEXT NOT NULL,
|
||||
"phase_id" TEXT,
|
||||
"ingredient_id" TEXT NOT NULL,
|
||||
"percentage" DECIMAL(5,2) NOT NULL,
|
||||
"process_notes" TEXT,
|
||||
|
||||
CONSTRAINT "formula_ingredients_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "color_formulas" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"target_lab" JSONB NOT NULL,
|
||||
"actual_lab" JSONB,
|
||||
"delta_e" DOUBLE PRECISION,
|
||||
"colorant_composition" JSONB,
|
||||
"formula_id" TEXT,
|
||||
"created_by" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "color_formulas_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ai_audit_logs" (
|
||||
"id" TEXT NOT NULL,
|
||||
"capability" TEXT NOT NULL,
|
||||
"model_name" TEXT NOT NULL,
|
||||
"prompt_hash" TEXT NOT NULL,
|
||||
"tokens_used" INTEGER,
|
||||
"duration_ms" INTEGER,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "ai_audit_logs_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "users_username_key" ON "users"("username");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "formulas_project_id_idx" ON "formulas"("project_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "formulas_created_by_idx" ON "formulas"("created_by");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "formula_versions_formula_id_idx" ON "formula_versions"("formula_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "formula_versions_formula_id_version_number_key" ON "formula_versions"("formula_id", "version_number");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ingredients_function_category_idx" ON "ingredients"("function_category");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "phases_formula_id_idx" ON "phases"("formula_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "formula_ingredients_formula_version_id_idx" ON "formula_ingredients"("formula_version_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "formula_ingredients_ingredient_id_idx" ON "formula_ingredients"("ingredient_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "color_formulas_formula_id_idx" ON "color_formulas"("formula_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "color_formulas_created_by_idx" ON "color_formulas"("created_by");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ai_audit_logs_capability_idx" ON "ai_audit_logs"("capability");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ai_audit_logs_created_at_idx" ON "ai_audit_logs"("created_at");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "projects" ADD CONSTRAINT "projects_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "formulas" ADD CONSTRAINT "formulas_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "formulas" ADD CONSTRAINT "formulas_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "formula_versions" ADD CONSTRAINT "formula_versions_formula_id_fkey" FOREIGN KEY ("formula_id") REFERENCES "formulas"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "formula_versions" ADD CONSTRAINT "formula_versions_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "phases" ADD CONSTRAINT "phases_formula_id_fkey" FOREIGN KEY ("formula_id") REFERENCES "formula_versions"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "formula_ingredients" ADD CONSTRAINT "formula_ingredients_formula_version_id_fkey" FOREIGN KEY ("formula_version_id") REFERENCES "formula_versions"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "formula_ingredients" ADD CONSTRAINT "formula_ingredients_phase_id_fkey" FOREIGN KEY ("phase_id") REFERENCES "phases"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "formula_ingredients" ADD CONSTRAINT "formula_ingredients_ingredient_id_fkey" FOREIGN KEY ("ingredient_id") REFERENCES "ingredients"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "color_formulas" ADD CONSTRAINT "color_formulas_formula_id_fkey" FOREIGN KEY ("formula_id") REFERENCES "formulas"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "color_formulas" ADD CONSTRAINT "color_formulas_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
1
backend/prisma/migrations/0002_pgvector/migration.sql
Normal file
1
backend/prisma/migrations/0002_pgvector/migration.sql
Normal file
@@ -0,0 +1 @@
|
||||
CREATE INDEX IF NOT EXISTS formulas_embedding_idx ON formulas USING hnsw (embedding vector_cosine_ops);
|
||||
2
backend/prisma/migrations/migration_lock.toml
Normal file
2
backend/prisma/migrations/migration_lock.toml
Normal file
@@ -0,0 +1,2 @@
|
||||
# Please do not edit this file manually
|
||||
provider = "postgresql"
|
||||
Reference in New Issue
Block a user