Files
happy-export/backend/db/schema.sql
T
Drsakura b9d6296591 feat(workspace): 日历瘦身 + 右侧「今日 to do / 选中日待办」双面板
日历
- 行高 92→72px,行程条只留 2 条(超出折成 +N 并压缩成小 chip),标题区与周标同步收窄
- 选中态重做:去掉了原来生硬的 2px 内描边,改成单元格内嵌圆角环 + 淡入缩放动画;
  「今天」改为日号描边圆环,与「选中」的实心日号区分开
- 侧栏宽度不足时(≤1200px)自动改为上下排布

右侧新增两块
- 「今日 to do」:备忘录性质。底部常驻加号输入框,回车即建;建完前面出现勾选框,
  勾选后划线变淡并沉到已完成组末尾(输入框始终在最后一行);可取消勾选回到未完成组;
  悬浮出现删除按钮;列表过长可滚动,勾选后自动滚进视野
- 「待办事项」:显示日历上选中那天的日程与节日(未选中时默认今天),
  带优先级点与说明,右上角「新建」直接为该日添加日程
- 原左栏重复的 [TASK QUEUE] 面板移到这里后删除,避免同名面板出现两次

后端
- todos 增加 list 列(schedule 日历日程 / memo 备忘录待办),老库启动时自动补列
- GET /api/todos 支持 list=memo;POST 支持 list,memo 不写日期
- 新增 PATCH /api/todos/:id(勾选完成/取消、改标题等)与 DELETE /api/todos/:id
2026-09-10 23:35:20 +08:00

404 lines
11 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- ========================================
-- 外贸供应链管理系统数据库结构
-- ========================================
-- ================== 供应商与SKU管理 ==================
CREATE TABLE IF NOT EXISTS suppliers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
short_name TEXT,
contact_person TEXT,
phone TEXT,
email TEXT,
address TEXT,
website TEXT,
payment_terms TEXT,
main_categories TEXT,
notes TEXT,
created_at TEXT NOT NULL,
updated_at TEXT
);
CREATE TABLE IF NOT EXISTS product_groups (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
group_key TEXT,
brand TEXT,
category TEXT,
description TEXT,
supplier_id INTEGER REFERENCES suppliers(id),
created_at TEXT NOT NULL,
updated_at TEXT
);
CREATE TABLE IF NOT EXISTS products (
sku TEXT PRIMARY KEY,
display_sku TEXT,
name TEXT,
name_en TEXT,
brand TEXT,
category TEXT,
spec TEXT,
price REAL,
currency TEXT DEFAULT 'CNY',
moq INTEGER,
description TEXT,
supplier_id INTEGER REFERENCES suppliers(id),
contract_id INTEGER REFERENCES contracts(id),
group_id INTEGER REFERENCES product_groups(id),
parse_method TEXT DEFAULT 'rules',
last_updated TEXT,
source_contract TEXT,
confidence TEXT DEFAULT 'high',
created_at TEXT NOT NULL,
updated_at TEXT
);
-- 自定义参数(包装参数、产品规格等)
CREATE TABLE IF NOT EXISTS item_attributes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
group_id INTEGER REFERENCES product_groups(id),
sku TEXT,
name TEXT NOT NULL,
value TEXT,
sort INTEGER DEFAULT 0
);
-- 阶梯价格表
CREATE TABLE IF NOT EXISTS tier_prices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sku TEXT NOT NULL,
supplier_id INTEGER REFERENCES suppliers(id),
moq_from INTEGER NOT NULL,
moq_to INTEGER,
price REAL NOT NULL,
currency TEXT DEFAULT 'CNY',
valid_from TEXT,
valid_until TEXT,
quote_id INTEGER REFERENCES supplier_quotes(id),
notes TEXT,
created_at TEXT NOT NULL,
updated_at TEXT
);
-- 供应商报价记录
CREATE TABLE IF NOT EXISTS supplier_quotes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
supplier_id INTEGER REFERENCES suppliers(id),
quote_no TEXT,
quote_date TEXT NOT NULL,
valid_until TEXT,
currency TEXT DEFAULT 'CNY',
payment_terms TEXT,
notes TEXT,
pdf_file TEXT,
status TEXT DEFAULT 'active',
created_at TEXT NOT NULL,
updated_at TEXT
);
-- 价格历史
CREATE TABLE IF NOT EXISTS price_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sku TEXT NOT NULL,
old_price REAL,
new_price REAL,
old_moq INTEGER,
new_moq INTEGER,
currency TEXT,
supplier_id INTEGER REFERENCES suppliers(id),
source_contract TEXT,
confidence TEXT,
changed_at TEXT NOT NULL
);
-- 合同
CREATE TABLE IF NOT EXISTS contracts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
filename TEXT NOT NULL,
supplier_id INTEGER REFERENCES suppliers(id),
file_type TEXT,
source_path TEXT,
column_report TEXT,
terms TEXT,
parse_method TEXT DEFAULT 'rules',
ai_rejected INTEGER DEFAULT 0,
processed_at TEXT NOT NULL,
rows_matched INTEGER DEFAULT 0,
rows_new INTEGER DEFAULT 0,
status TEXT,
notes TEXT
);
-- 产品图片
CREATE TABLE IF NOT EXISTS product_images (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sku TEXT NOT NULL,
filename TEXT NOT NULL,
original_name TEXT,
is_primary INTEGER DEFAULT 0,
group_id INTEGER REFERENCES product_groups(id),
created_at TEXT NOT NULL
);
-- ================== 客户管理(CRM) ==================
CREATE TABLE IF NOT EXISTS customers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company TEXT NOT NULL,
company_en TEXT,
country TEXT,
industry TEXT,
website TEXT,
address TEXT,
phone TEXT,
email TEXT,
rating TEXT,
status TEXT DEFAULT 'active',
owner_id INTEGER REFERENCES users(id),
source TEXT,
tags TEXT,
notes TEXT,
created_at TEXT NOT NULL,
updated_at TEXT,
last_contact_at TEXT
);
CREATE TABLE IF NOT EXISTS contacts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
customer_id INTEGER NOT NULL REFERENCES customers(id),
name TEXT NOT NULL,
name_en TEXT,
position TEXT,
department TEXT,
email TEXT,
phone TEXT,
whatsapp TEXT,
wechat TEXT,
is_primary INTEGER DEFAULT 0,
notes TEXT,
created_at TEXT NOT NULL,
updated_at TEXT
);
-- 商机
CREATE TABLE IF NOT EXISTS deals (
id INTEGER PRIMARY KEY AUTOINCREMENT,
customer_id INTEGER NOT NULL REFERENCES customers(id),
title TEXT NOT NULL,
amount REAL,
currency TEXT DEFAULT 'USD',
stage TEXT NOT NULL,
probability INTEGER,
expected_close_date TEXT,
actual_close_date TEXT,
products TEXT,
owner_id INTEGER REFERENCES users(id),
status TEXT DEFAULT 'open',
notes TEXT,
created_at TEXT NOT NULL,
updated_at TEXT
);
-- 跟进活动
CREATE TABLE IF NOT EXISTS activities (
id INTEGER PRIMARY KEY AUTOINCREMENT,
customer_id INTEGER REFERENCES customers(id),
deal_id INTEGER REFERENCES deals(id),
order_id INTEGER REFERENCES orders(id),
activity_type TEXT NOT NULL,
subject TEXT,
content TEXT,
files TEXT,
next_action TEXT,
next_action_date TEXT,
created_by INTEGER REFERENCES users(id),
created_at TEXT NOT NULL
);
-- 待办事项
CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
description TEXT,
due_date TEXT,
priority TEXT DEFAULT 'medium',
status TEXT DEFAULT 'pending',
list TEXT NOT NULL DEFAULT 'schedule',
customer_id INTEGER REFERENCES customers(id),
deal_id INTEGER REFERENCES deals(id),
order_id INTEGER REFERENCES orders(id),
assigned_to INTEGER REFERENCES users(id),
created_by INTEGER REFERENCES users(id),
created_at TEXT NOT NULL,
completed_at TEXT
);
-- ================== 订单管理 ==================
CREATE TABLE IF NOT EXISTS orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
order_no TEXT NOT NULL UNIQUE,
customer_id INTEGER NOT NULL REFERENCES customers(id),
order_date TEXT NOT NULL,
delivery_date TEXT,
payment_terms TEXT,
total_amount REAL,
currency TEXT DEFAULT 'USD',
status TEXT DEFAULT 'draft',
owner_id INTEGER REFERENCES users(id),
notes TEXT,
created_at TEXT NOT NULL,
updated_at TEXT
);
CREATE TABLE IF NOT EXISTS order_items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
order_id INTEGER NOT NULL REFERENCES orders(id),
sku TEXT NOT NULL,
product_name TEXT,
qty INTEGER NOT NULL,
unit_price REAL NOT NULL,
total_price REAL NOT NULL,
currency TEXT DEFAULT 'USD',
notes TEXT,
created_at TEXT NOT NULL
);
-- ================== 客户报价单 ==================
CREATE TABLE IF NOT EXISTS customer_quotations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
quote_no TEXT NOT NULL UNIQUE,
customer_id INTEGER NOT NULL REFERENCES customers(id),
quote_date TEXT NOT NULL,
valid_until TEXT,
currency TEXT DEFAULT 'USD',
payment_terms TEXT,
delivery_terms TEXT,
status TEXT DEFAULT 'draft',
notes TEXT,
created_by INTEGER REFERENCES users(id),
created_at TEXT NOT NULL,
updated_at TEXT
);
CREATE TABLE IF NOT EXISTS quotation_items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
quotation_id INTEGER NOT NULL REFERENCES customer_quotations(id),
sku TEXT NOT NULL,
product_name TEXT,
product_name_en TEXT,
spec TEXT,
qty INTEGER NOT NULL,
unit_price REAL NOT NULL,
total_price REAL NOT NULL,
currency TEXT DEFAULT 'USD',
notes TEXT,
created_at TEXT NOT NULL
);
-- ================== 自动获客(新客开发) ==================
CREATE TABLE IF NOT EXISTS prospect_runs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
product_keywords TEXT,
countries TEXT,
customer_types TEXT,
exclude_keywords TEXT,
sources TEXT,
result_limit INTEGER DEFAULT 100,
status TEXT DEFAULT 'draft',
owner_id INTEGER REFERENCES users(id),
created_at TEXT NOT NULL,
completed_at TEXT
);
CREATE TABLE IF NOT EXISTS prospect_leads (
id INTEGER PRIMARY KEY AUTOINCREMENT,
run_id INTEGER REFERENCES prospect_runs(id),
company TEXT NOT NULL,
website TEXT,
country TEXT,
business TEXT,
contact TEXT,
email TEXT,
phone TEXT,
description TEXT,
icp_score INTEGER,
confidence INTEGER,
source TEXT,
source_url TEXT,
status TEXT DEFAULT 'new',
owner_id INTEGER REFERENCES users(id),
customer_id INTEGER REFERENCES customers(id),
created_at TEXT NOT NULL
);
-- ================== 系统管理 ==================
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
display_name TEXT,
email TEXT,
role TEXT DEFAULT 'user',
is_active INTEGER NOT NULL DEFAULT 1,
created_at TEXT NOT NULL,
last_login_at TEXT,
failed_count INTEGER NOT NULL DEFAULT 0,
locked_until TEXT
);
CREATE TABLE IF NOT EXISTS sessions (
id TEXT PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id),
created_at TEXT NOT NULL,
last_seen_at TEXT NOT NULL,
expires_at TEXT NOT NULL,
user_agent TEXT,
ip TEXT
);
CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT
);
CREATE TABLE IF NOT EXISTS audit_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
at TEXT NOT NULL,
username TEXT,
action TEXT NOT NULL,
detail TEXT,
ip TEXT,
user_agent TEXT,
ok INTEGER NOT NULL DEFAULT 1
);
-- ================== 索引 ==================
CREATE INDEX IF NOT EXISTS idx_products_supplier ON products(supplier_id);
CREATE INDEX IF NOT EXISTS idx_products_group ON products(group_id);
CREATE INDEX IF NOT EXISTS idx_products_name ON products(name);
CREATE INDEX IF NOT EXISTS idx_tier_prices_sku ON tier_prices(sku);
CREATE INDEX IF NOT EXISTS idx_price_history_sku ON price_history(sku);
CREATE INDEX IF NOT EXISTS idx_customers_owner ON customers(owner_id);
CREATE INDEX IF NOT EXISTS idx_customers_country ON customers(country);
CREATE INDEX IF NOT EXISTS idx_contacts_customer ON contacts(customer_id);
CREATE INDEX IF NOT EXISTS idx_deals_customer ON deals(customer_id);
CREATE INDEX IF NOT EXISTS idx_deals_owner ON deals(owner_id);
CREATE INDEX IF NOT EXISTS idx_activities_customer ON activities(customer_id);
CREATE INDEX IF NOT EXISTS idx_activities_deal ON activities(deal_id);
CREATE INDEX IF NOT EXISTS idx_orders_customer ON orders(customer_id);
CREATE INDEX IF NOT EXISTS idx_order_items_order ON order_items(order_id);
CREATE INDEX IF NOT EXISTS idx_quotations_customer ON customer_quotations(customer_id);
CREATE INDEX IF NOT EXISTS idx_quotation_items_quotation ON quotation_items(quotation_id);
CREATE INDEX IF NOT EXISTS idx_prospect_leads_run ON prospect_leads(run_id);
CREATE INDEX IF NOT EXISTS idx_sessions_user ON sessions(user_id);
CREATE INDEX IF NOT EXISTS idx_sessions_exp ON sessions(expires_at);
CREATE INDEX IF NOT EXISTS idx_audit_at ON audit_log(at);