/** * Sync lobster menus for tenant DB (sys_menu + company_menu) * Usage: node scripts/sync-lobster-menus-tenant.js [dbName] [audit|sync] */ const mysql = require('mysql2/promise') const { LOBSTER_MENUS, TENANT_COMPANY_MENU_EXCLUDE } = require('./lobster-menu-definitions') const DB_CFG = { host: 'cq-cdb-8fjmemkb.sql.tencentcdb.com', port: 27220, user: 'root', password: 'Ylrz_1q2w3e4r5t6y', multipleStatements: true, charset: 'utf8mb4' } const TARGET_DB = process.argv[2] || 'fs_tenant_cs1' const COMPANY_MENU_EXCLUDE = TENANT_COMPANY_MENU_EXCLUDE const COMPANY_MENU_IDS = LOBSTER_MENUS.filter(m => !COMPANY_MENU_EXCLUDE.has(m.id)).map(m => m.id) async function upsertSysMenu(conn, m) { const [ex] = await conn.query('SELECT menu_id FROM sys_menu WHERE menu_id = ?', [m.id]) if (!ex.length) { await conn.query( `INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, menu_type, icon, visible, status, is_frame, is_cache, perms, create_by, create_time, remark) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, '0', 0, 0, ?, 'admin', NOW(), 'lobster sync')`, [m.id, m.name, m.parent, m.order, m.path, m.component, m.type, m.icon, m.visible, m.perms] ) return 'insert' } await conn.query( `UPDATE sys_menu SET menu_name=?, parent_id=?, order_num=?, path=?, component=?, menu_type=?, icon=?, visible=?, status='0', perms=? WHERE menu_id=?`, [m.name, m.parent, m.order, m.path, m.component, m.type, m.icon, m.visible, m.perms, m.id] ) return 'update' } async function upsertCompanyMenu(conn, m) { const [ex] = await conn.query('SELECT menu_id FROM company_menu WHERE menu_id = ?', [m.id]) if (!ex.length) { await conn.query( `INSERT INTO company_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, company_id, remark) VALUES (?, ?, ?, ?, ?, ?, 0, 0, ?, ?, '0', ?, ?, 'admin', NOW(), NULL, 'lobster sync')`, [m.id, m.name, m.parent, m.order, m.path, m.component, m.type, m.visible, m.perms, m.icon] ) return 'insert' } await conn.query( `UPDATE company_menu SET menu_name=?, parent_id=?, order_num=?, path=?, component=?, menu_type=?, icon=?, visible=?, status='0', perms=? WHERE menu_id=?`, [m.name, m.parent, m.order, m.path, m.component, m.type, m.icon, m.visible, m.perms, m.id] ) return 'update' } async function audit(conn) { const ids = LOBSTER_MENUS.map(m => m.id) const [sysRows] = await conn.query( `SELECT menu_id, menu_name, path, component, visible FROM sys_menu WHERE menu_id IN (${ids.join(',')}) ORDER BY order_num, menu_id` ) const [cmRows] = await conn.query( `SELECT menu_id, menu_name, path, component, visible FROM company_menu WHERE menu_id IN (${COMPANY_MENU_IDS.join(',')}) ORDER BY order_num, menu_id` ) console.log('\n=== sys_menu === count', sysRows.length, '/', LOBSTER_MENUS.length) sysRows.forEach(r => console.log(` ${r.menu_id}\t${r.menu_name}\t${r.path}\t${r.component}`)) const missSys = LOBSTER_MENUS.filter(m => !sysRows.find(r => r.menu_id === m.id)) if (missSys.length) console.log('missing sys:', missSys.map(m => m.id + ':' + m.name).join(', ')) console.log('\n=== company_menu === count', cmRows.length, '/', COMPANY_MENU_IDS.length) cmRows.forEach(r => console.log(` ${r.menu_id}\t${r.menu_name}\t${r.path}`)) const missCm = COMPANY_MENU_IDS.filter(id => !cmRows.find(r => r.menu_id === id)) if (missCm.length) console.log('missing company:', missCm.join(', ')) } async function sync(conn) { await conn.query('DELETE FROM sys_role_menu WHERE menu_id IN (29923, 2999, 29937, 29938, 29939, 29946, 29947, 3005)') await conn.query('DELETE FROM company_role_menu WHERE menu_id IN (29923, 2999, 29933, 29937, 29938, 29939, 29946, 29947, 3005)') await conn.query("DELETE FROM company_menu WHERE menu_id IN (29923, 2999, 29933, 29937, 29938, 29939, 29946, 29947, 3005) OR path IN ('execution-config', 'dashboard', 'evolution', 'token-stats') OR component IN ('lobster/summary-config/index', 'lobster/model-route/index', 'lobster/execution-config/index', 'lobster/dashboard/index', 'lobster/evolution/index', 'lobster/token-stats/index')") await conn.query("DELETE FROM sys_menu WHERE menu_id IN (29923, 2999, 29937, 29938, 29939, 29946, 29947, 3005) OR path IN ('execution-config', 'dashboard', 'evolution', 'token-stats') OR component IN ('lobster/summary-config/index', 'lobster/model-route/index', 'lobster/execution-config/index', 'lobster/dashboard/index', 'lobster/evolution/index', 'lobster/token-stats/index')") await conn.query('DROP TABLE IF EXISTS company_lobster_summary_config') let sysIns = 0; let sysUpd = 0; let cmIns = 0; let cmUpd = 0 for (const m of LOBSTER_MENUS) { const r = await upsertSysMenu(conn, m) if (r === 'insert') sysIns++; else sysUpd++ } for (const id of COMPANY_MENU_IDS) { const m = LOBSTER_MENUS.find(x => x.id === id) const companyMenu = id === 29934 ? { ...m, perms: 'workflow:lobster:query' } : m const r = await upsertCompanyMenu(conn, companyMenu) if (r === 'insert') cmIns++; else cmUpd++ } await conn.query(`UPDATE sys_menu SET visible='1' WHERE menu_id IN (29936,29922,29948,29926)`) await conn.query(`UPDATE company_menu SET visible='1' WHERE menu_id IN (29922,29948,29926)`) await conn.query(` INSERT IGNORE INTO sys_role_menu (role_id, menu_id) SELECT DISTINCT srm.role_id, m.menu_id FROM sys_role_menu srm CROSS JOIN (SELECT menu_id FROM sys_menu WHERE parent_id = 29900 OR menu_id = 29900) m WHERE srm.menu_id = 29900 `) await conn.query(` INSERT IGNORE INTO sys_role_menu (role_id, menu_id) SELECT 1, menu_id FROM sys_menu WHERE parent_id = 29900 OR menu_id = 29900 `) await conn.query(` INSERT IGNORE INTO company_role_menu (role_id, menu_id) SELECT DISTINCT crm.role_id, m.menu_id FROM company_role_menu crm CROSS JOIN (SELECT menu_id FROM company_menu WHERE parent_id = 29900 OR menu_id = 29900) m WHERE crm.menu_id = 29900 `) console.log(`\nSync: sys +${sysIns}/~${sysUpd}, company +${cmIns}/~${cmUpd}`) } async function main() { const mode = process.argv[3] || 'sync' const conn = await mysql.createConnection({ ...DB_CFG, database: TARGET_DB }) console.log('DB:', TARGET_DB, 'mode:', mode) await audit(conn) if (mode === 'sync') { await sync(conn) await audit(conn) } await conn.end() } main().catch(e => { console.error(e); process.exit(1) })