Rename to hkt.sh
This commit is contained in:
86
aff-monitor/db/migrate-004-pid-slug.js
Normal file
86
aff-monitor/db/migrate-004-pid-slug.js
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* 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();
|
||||
Reference in New Issue
Block a user