Files
vps-management-bot/aff-monitor/db/migrate-004-pid-slug.js
2026-03-21 01:10:53 +08:00

87 lines
3.0 KiB
JavaScript
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.
/**
* Migration 004 — PID & Slug 字段
*
* - internal_pid: 系统内部编号,如 VPS-000001唯一自动生成
* - provider_pid: 商家产品 ID从购买链接自动解析如 pid=28
* - slug: 前台友好 URL唯一
*/
const Database = require('better-sqlite3');
const path = require('path');
require('dotenv').config({ path: path.join(__dirname, '..', '.env') });
const dbPath = path.resolve(__dirname, '..', process.env.DB_PATH || 'db/monitor.sqlite');
const db = new Database(dbPath);
db.pragma('journal_mode = WAL');
function ensureColumn(table, column, sql) {
const cols = db.prepare(`PRAGMA table_info(${table})`).all().map(c => c.name);
if (!cols.includes(column)) {
db.exec(`ALTER TABLE ${table} ADD COLUMN ${sql}`);
console.log(`+ ${table}.${column}`);
} else {
console.log(` ${table}.${column} (already exists)`);
}
}
// 添加新字段
ensureColumn('products', 'internal_pid', 'internal_pid TEXT');
ensureColumn('products', 'provider_pid', 'provider_pid TEXT');
ensureColumn('products', 'slug', 'slug TEXT');
// 创建唯一索引(如果尚不存在)
try {
db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_products_internal_pid ON products(internal_pid) WHERE internal_pid IS NOT NULL');
console.log('+ index: idx_products_internal_pid');
} catch (e) {
console.log(' index idx_products_internal_pid:', e.message);
}
try {
db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_products_slug ON products(slug) WHERE slug IS NOT NULL');
console.log('+ index: idx_products_slug');
} catch (e) {
console.log(' index idx_products_slug:', e.message);
}
// 为已有产品回填 internal_pid 和 slug
const { generateInternalPid, generateSlug, parseProviderPid } = require('../src/utils/pidHelper');
const products = db.prepare('SELECT id, name, merchant_id, url, buy_url, internal_pid, slug, provider_pid FROM products').all();
const updateStmt = db.prepare('UPDATE products SET internal_pid = ?, slug = ?, provider_pid = ? WHERE id = ?');
const getMerchantName = db.prepare('SELECT name FROM merchants WHERE id = ?');
const existingSlugs = new Set(
db.prepare("SELECT slug FROM products WHERE slug IS NOT NULL AND slug != ''").all().map(r => r.slug)
);
db.transaction(() => {
for (const p of products) {
let ipid = p.internal_pid;
let slug = p.slug;
let ppid = p.provider_pid;
// 生成 internal_pid
if (!ipid) {
ipid = generateInternalPid(db);
}
// 生成 slug
if (!slug) {
const merchant = getMerchantName.get(p.merchant_id);
const merchantName = merchant ? merchant.name : '';
slug = generateSlug(p.name, merchantName, existingSlugs);
existingSlugs.add(slug);
}
// 解析 provider_pid
if (!ppid) {
ppid = parseProviderPid(p.buy_url) || parseProviderPid(p.url) || null;
}
updateStmt.run(ipid, slug, ppid, p.id);
console.log(` product #${p.id}: internal_pid=${ipid}, slug=${slug}, provider_pid=${ppid || '(none)'}`);
}
})();
console.log('✅ migration-004 done:', dbPath);
db.close();