1
This commit is contained in:
134
scripts/add_account_list_menu.js
Normal file
134
scripts/add_account_list_menu.js
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* 添加"账号列表"菜单项到用户管理菜单下
|
||||
* 执行 SQL 插入操作
|
||||
*/
|
||||
|
||||
const Framework = require('../framework/node-core-framework.js');
|
||||
const frameworkConfig = require('../config/framework.config.js');
|
||||
|
||||
async function addAccountListMenu() {
|
||||
console.log('🔄 开始添加"账号列表"菜单项...\n');
|
||||
|
||||
try {
|
||||
// 初始化框架
|
||||
console.log('正在初始化框架...');
|
||||
const framework = await Framework.init(frameworkConfig);
|
||||
const models = Framework.getModels();
|
||||
|
||||
if (!models) {
|
||||
throw new Error('无法获取模型列表');
|
||||
}
|
||||
|
||||
// 从任意模型获取 sequelize 实例
|
||||
const Sequelize = require('sequelize');
|
||||
const firstModel = Object.values(models)[0];
|
||||
if (!firstModel || !firstModel.sequelize) {
|
||||
throw new Error('无法获取数据库连接');
|
||||
}
|
||||
const sequelize = firstModel.sequelize;
|
||||
|
||||
// 检查是否已存在
|
||||
const [existing] = await sequelize.query(
|
||||
`SELECT id, name FROM sys_menu WHERE parent_id = 120 AND path = 'pla_account' AND is_delete = 0`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
if (existing) {
|
||||
console.log(`⚠️ 菜单项已存在 (ID: ${existing.id}, 名称: ${existing.name})`);
|
||||
console.log('✅ 无需重复添加\n');
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行插入
|
||||
const [result] = await sequelize.query(
|
||||
`INSERT INTO sys_menu (
|
||||
name,
|
||||
parent_id,
|
||||
model_id,
|
||||
form_id,
|
||||
icon,
|
||||
path,
|
||||
component,
|
||||
api_path,
|
||||
is_show_menu,
|
||||
is_show,
|
||||
type,
|
||||
sort,
|
||||
create_time,
|
||||
last_modify_time,
|
||||
is_delete
|
||||
) VALUES (
|
||||
'账号列表',
|
||||
120,
|
||||
0,
|
||||
0,
|
||||
'md-list',
|
||||
'pla_account',
|
||||
'account/pla_account.vue',
|
||||
'account/pla_account_server.js',
|
||||
1,
|
||||
1,
|
||||
'页面',
|
||||
1,
|
||||
NOW(),
|
||||
NOW(),
|
||||
0
|
||||
)`,
|
||||
{ type: Sequelize.QueryTypes.INSERT }
|
||||
);
|
||||
|
||||
console.log('✅ "账号列表"菜单项添加成功!\n');
|
||||
|
||||
// 验证插入结果(通过 path 查询)
|
||||
const [menus] = await sequelize.query(
|
||||
`SELECT id, name, parent_id, path, component, api_path, sort
|
||||
FROM sys_menu
|
||||
WHERE parent_id = 120 AND path = 'pla_account' AND is_delete = 0`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
const menu = menus && menus.length > 0 ? menus[0] : null;
|
||||
|
||||
if (menu) {
|
||||
console.log('📋 菜单项详情:');
|
||||
console.log(` 名称: ${menu.name}`);
|
||||
console.log(` 父菜单ID: ${menu.parent_id}`);
|
||||
console.log(` 路由路径: ${menu.path}`);
|
||||
console.log(` 组件路径: ${menu.component}`);
|
||||
console.log(` API路径: ${menu.api_path}`);
|
||||
console.log(` 排序: ${menu.sort}\n`);
|
||||
}
|
||||
|
||||
// 显示用户管理菜单下的所有子菜单
|
||||
const [children] = await sequelize.query(
|
||||
`SELECT id, name, path, sort, is_show_menu
|
||||
FROM sys_menu
|
||||
WHERE parent_id = 120 AND is_delete = 0
|
||||
ORDER BY sort`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
console.log('📋 用户管理菜单下的所有子菜单:');
|
||||
children.forEach(child => {
|
||||
const visible = child.is_show_menu ? '✅' : '🔒';
|
||||
console.log(` ${visible} ${child.name} (ID: ${child.id}, 路径: ${child.path}, 排序: ${child.sort})`);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 添加失败:', error.message);
|
||||
console.error('\n详细错误:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行添加
|
||||
addAccountListMenu()
|
||||
.then(() => {
|
||||
console.log('\n✨ 操作完成!');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('\n💥 执行失败:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
109
scripts/add_job_types_data.js
Normal file
109
scripts/add_job_types_data.js
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* 添加职位类型数据
|
||||
* 添加 web全栈工程师 和 售前工程师 两条记录
|
||||
*/
|
||||
|
||||
const Framework = require('../framework/node-core-framework.js');
|
||||
const frameworkConfig = require('../config/framework.config.js');
|
||||
|
||||
async function addJobTypesData() {
|
||||
console.log('🔄 开始添加职位类型数据...\n');
|
||||
|
||||
try {
|
||||
// 初始化框架
|
||||
console.log('正在初始化框架...');
|
||||
await Framework.init(frameworkConfig);
|
||||
const models = Framework.getModels();
|
||||
|
||||
if (!models || !models.job_types) {
|
||||
throw new Error('无法获取 job_types 模型');
|
||||
}
|
||||
|
||||
const job_types = models.job_types;
|
||||
|
||||
// 1. 添加 web全栈工程师
|
||||
const [webFullStack, created1] = await job_types.findOrCreate({
|
||||
where: { name: 'web全栈工程师' },
|
||||
defaults: {
|
||||
name: 'web全栈工程师',
|
||||
description: 'Web全栈开发工程师,掌握前后端技术栈',
|
||||
commonSkills: JSON.stringify([
|
||||
'Vue', 'React', 'Angular', 'JavaScript', 'TypeScript', 'Node.js',
|
||||
'Express', 'Koa', 'NestJS', 'Webpack', 'Vite',
|
||||
'HTML5', 'CSS3', 'Sass', 'Less',
|
||||
'MySQL', 'MongoDB', 'Redis',
|
||||
'Git', 'Docker', 'Linux',
|
||||
'RESTful API', 'GraphQL', 'WebSocket'
|
||||
]),
|
||||
excludeKeywords: JSON.stringify([
|
||||
'外包', '外派', '驻场', '销售', '客服',
|
||||
'地推', '推广', '市场', '运营'
|
||||
]),
|
||||
is_enabled: 1,
|
||||
sort_order: 1
|
||||
}
|
||||
});
|
||||
|
||||
if (created1) {
|
||||
console.log('✅ 添加成功:web全栈工程师');
|
||||
} else {
|
||||
console.log('⚠️ 已存在:web全栈工程师');
|
||||
}
|
||||
|
||||
// 2. 添加 售前工程师
|
||||
const [preSales, created2] = await job_types.findOrCreate({
|
||||
where: { name: '售前工程师' },
|
||||
defaults: {
|
||||
name: '售前工程师',
|
||||
description: '售前技术支持工程师,负责技术方案设计和客户沟通',
|
||||
commonSkills: JSON.stringify([
|
||||
'技术方案', '产品演示', '客户沟通', '需求分析',
|
||||
'技术咨询', '解决方案', 'PPT制作', '技术文档',
|
||||
'项目管理', '商务谈判', '行业知识'
|
||||
]),
|
||||
excludeKeywords: JSON.stringify([
|
||||
'纯销售', '电话销售', '地推', '推广',
|
||||
'客服', '文员', '行政'
|
||||
]),
|
||||
is_enabled: 1,
|
||||
sort_order: 2
|
||||
}
|
||||
});
|
||||
|
||||
if (created2) {
|
||||
console.log('✅ 添加成功:售前工程师');
|
||||
} else {
|
||||
console.log('⚠️ 已存在:售前工程师');
|
||||
}
|
||||
|
||||
// 显示所有职位类型
|
||||
console.log('\n📋 当前所有职位类型:');
|
||||
const allTypes = await job_types.findAll({
|
||||
where: { is_enabled: 1 },
|
||||
order: [['sort_order', 'ASC'], ['id', 'ASC']]
|
||||
});
|
||||
|
||||
allTypes.forEach((type, index) => {
|
||||
const data = type.toJSON();
|
||||
console.log(` ${index + 1}. ${data.name} (ID: ${data.id}, 排序: ${data.sort_order})`);
|
||||
});
|
||||
|
||||
console.log('\n✨ 操作完成!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 添加失败:', error.message);
|
||||
console.error('\n详细错误:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行添加
|
||||
addJobTypesData()
|
||||
.then(() => {
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('\n💥 执行失败:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
149
scripts/add_job_types_menu.js
Normal file
149
scripts/add_job_types_menu.js
Normal file
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* 添加"职位类型管理"菜单项到系统设置菜单下
|
||||
* 执行 SQL 插入操作
|
||||
*/
|
||||
|
||||
const Framework = require('../framework/node-core-framework.js');
|
||||
const frameworkConfig = require('../config/framework.config.js');
|
||||
|
||||
async function addJobTypesMenu() {
|
||||
console.log('🔄 开始添加"职位类型管理"菜单项...\n');
|
||||
|
||||
try {
|
||||
// 初始化框架
|
||||
console.log('正在初始化框架...');
|
||||
const framework = await Framework.init(frameworkConfig);
|
||||
const models = Framework.getModels();
|
||||
|
||||
if (!models) {
|
||||
throw new Error('无法获取模型列表');
|
||||
}
|
||||
|
||||
// 从任意模型获取 sequelize 实例
|
||||
const Sequelize = require('sequelize');
|
||||
const firstModel = Object.values(models)[0];
|
||||
if (!firstModel || !firstModel.sequelize) {
|
||||
throw new Error('无法获取数据库连接');
|
||||
}
|
||||
const sequelize = firstModel.sequelize;
|
||||
|
||||
// 先查找系统设置菜单的ID(通常 parent_id 为 0 或特定的系统菜单ID)
|
||||
// 需要根据实际情况调整查询条件
|
||||
const [systemMenu] = await sequelize.query(
|
||||
`SELECT id FROM sys_menu WHERE (name LIKE '%系统%' OR name LIKE '%设置%') AND parent_id = 0 AND is_delete = 0 LIMIT 1`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
let parentId = 0;
|
||||
if (systemMenu && systemMenu.id) {
|
||||
parentId = systemMenu.id;
|
||||
console.log(`找到系统设置菜单,ID: ${parentId}`);
|
||||
} else {
|
||||
// 如果没有找到,尝试查找 system_config 菜单的父菜单
|
||||
const [configMenu] = await sequelize.query(
|
||||
`SELECT parent_id FROM sys_menu WHERE path = 'system_config' AND is_delete = 0 LIMIT 1`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
if (configMenu && configMenu.parent_id) {
|
||||
parentId = configMenu.parent_id;
|
||||
console.log(`从系统配置菜单获取父菜单ID: ${parentId}`);
|
||||
} else {
|
||||
console.log('未找到系统设置菜单,将使用 parent_id = 0');
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否已存在
|
||||
const [existing] = await sequelize.query(
|
||||
`SELECT id, name FROM sys_menu WHERE path = 'job_types' AND is_delete = 0`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
if (existing) {
|
||||
console.log(`⚠️ 菜单项已存在 (ID: ${existing.id}, 名称: ${existing.name})`);
|
||||
console.log('✅ 无需重复添加\n');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取最大排序值
|
||||
const [maxSort] = await sequelize.query(
|
||||
`SELECT MAX(sort) as maxSort FROM sys_menu WHERE parent_id = ${parentId} AND is_delete = 0`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
const nextSort = (maxSort && maxSort.maxSort ? maxSort.maxSort : 0) + 1;
|
||||
|
||||
// 执行插入
|
||||
await sequelize.query(
|
||||
`INSERT INTO sys_menu (
|
||||
name,
|
||||
parent_id,
|
||||
model_id,
|
||||
form_id,
|
||||
icon,
|
||||
path,
|
||||
component,
|
||||
api_path,
|
||||
is_show_menu,
|
||||
is_show,
|
||||
type,
|
||||
sort,
|
||||
create_time,
|
||||
last_modify_time,
|
||||
is_delete
|
||||
) VALUES (
|
||||
'职位类型管理',
|
||||
${parentId},
|
||||
0,
|
||||
0,
|
||||
'md-briefcase',
|
||||
'job_types',
|
||||
'system/job_types.vue',
|
||||
'system/job_types_server.js',
|
||||
1,
|
||||
1,
|
||||
'页面',
|
||||
${nextSort},
|
||||
NOW(),
|
||||
NOW(),
|
||||
0
|
||||
)`,
|
||||
{ type: Sequelize.QueryTypes.INSERT }
|
||||
);
|
||||
|
||||
console.log('✅ "职位类型管理"菜单项添加成功!\n');
|
||||
|
||||
// 验证插入结果
|
||||
const [menu] = await sequelize.query(
|
||||
`SELECT id, name, parent_id, path, component, api_path, sort
|
||||
FROM sys_menu
|
||||
WHERE path = 'job_types' AND is_delete = 0`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
if (menu) {
|
||||
console.log('📋 菜单项详情:');
|
||||
console.log(` 名称: ${menu.name}`);
|
||||
console.log(` 父菜单ID: ${menu.parent_id}`);
|
||||
console.log(` 路由路径: ${menu.path}`);
|
||||
console.log(` 组件路径: ${menu.component}`);
|
||||
console.log(` API路径: ${menu.api_path}`);
|
||||
console.log(` 排序: ${menu.sort}\n`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 添加失败:', error.message);
|
||||
console.error('\n详细错误:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行添加
|
||||
addJobTypesMenu()
|
||||
.then(() => {
|
||||
console.log('\n✨ 操作完成!');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('\n💥 执行失败:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
120
scripts/sync_job_postings_table.js
Normal file
120
scripts/sync_job_postings_table.js
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* 同步 job_postings 表结构
|
||||
* 用于创建或更新数据库表
|
||||
*/
|
||||
|
||||
const Sequelize = require('sequelize');
|
||||
|
||||
// 加载配置
|
||||
const config = require('../config/config');
|
||||
const dbConfig = config.db;
|
||||
|
||||
async function syncJobPostingsTable() {
|
||||
console.log('🔄 开始同步 job_postings 表结构...\n');
|
||||
|
||||
try {
|
||||
// 创建 Sequelize 实例
|
||||
const sequelize = new Sequelize(
|
||||
dbConfig.database,
|
||||
dbConfig.username,
|
||||
dbConfig.password,
|
||||
{
|
||||
host: dbConfig.host,
|
||||
port: dbConfig.port,
|
||||
dialect: dbConfig.dialect,
|
||||
logging: false
|
||||
}
|
||||
);
|
||||
|
||||
// 测试连接
|
||||
await sequelize.authenticate();
|
||||
console.log('✅ 数据库连接成功\n');
|
||||
|
||||
// 加载模型定义
|
||||
const job_postings = require('../api/model/job_postings')(sequelize);
|
||||
|
||||
// 同步表结构(alter: true 会自动添加缺失的字段,保留现有数据)
|
||||
console.log('⚠️ 注意:使用 alter: true 模式同步(保留现有数据)');
|
||||
console.log('如果需要完全重建表,请修改为 force: true\n');
|
||||
|
||||
await job_postings.sync({ alter: true });
|
||||
|
||||
console.log('✅ job_postings 表同步成功!\n');
|
||||
|
||||
// 显示表结构
|
||||
const tableInfo = await sequelize.query(
|
||||
`DESCRIBE job_postings`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
console.log('📋 当前表结构:');
|
||||
console.table(tableInfo.map(field => ({
|
||||
字段名: field.Field,
|
||||
类型: field.Type,
|
||||
允许空: field.Null,
|
||||
默认值: field.Default
|
||||
})));
|
||||
|
||||
// 检查关键字段
|
||||
const requiredFields = [
|
||||
'id',
|
||||
'sn_code',
|
||||
'platform',
|
||||
'keyword',
|
||||
'encryptBossId',
|
||||
'jobId',
|
||||
'jobTitle',
|
||||
'companyId',
|
||||
'companyName',
|
||||
'companySize',
|
||||
'companyIndustry',
|
||||
'salary',
|
||||
'jobRequirements',
|
||||
'jobDescription',
|
||||
'location',
|
||||
'experience',
|
||||
'education',
|
||||
'aiMatchScore',
|
||||
'applyStatus',
|
||||
'chatStatus',
|
||||
'originalData'
|
||||
];
|
||||
const existingFields = tableInfo.map(f => f.Field);
|
||||
|
||||
console.log('\n🔍 检查关键字段:');
|
||||
const missingFields = [];
|
||||
requiredFields.forEach(field => {
|
||||
const exists = existingFields.includes(field);
|
||||
console.log(` ${exists ? '✅' : '❌'} ${field}`);
|
||||
if (!exists) {
|
||||
missingFields.push(field);
|
||||
}
|
||||
});
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
console.log('\n⚠️ 缺少以下字段:', missingFields.join(', '));
|
||||
console.log('建议:重新运行同步或手动添加这些字段');
|
||||
} else {
|
||||
console.log('\n✅ 所有必需字段都存在!');
|
||||
}
|
||||
|
||||
// 关闭连接
|
||||
await sequelize.close();
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 同步失败:', error.message);
|
||||
console.error('\n详细错误:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 执行同步
|
||||
syncJobPostingsTable()
|
||||
.then(() => {
|
||||
console.log('\n✨ 同步完成!');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('\n💥 执行失败:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
97
scripts/sync_job_types.js
Normal file
97
scripts/sync_job_types.js
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* 同步职位类型表结构
|
||||
* 创建 job_types 表并添加 job_type_id 字段到 pla_account 表
|
||||
*/
|
||||
|
||||
const Framework = require('../framework/node-core-framework.js');
|
||||
const frameworkConfig = require('../config/framework.config.js');
|
||||
|
||||
async function syncJobTypes() {
|
||||
try {
|
||||
console.log('[同步职位类型] 开始同步...');
|
||||
|
||||
// 初始化框架
|
||||
await Framework.init(frameworkConfig);
|
||||
|
||||
const models = Framework.getModels();
|
||||
const { job_types, pla_account } = models;
|
||||
|
||||
if (!job_types) {
|
||||
throw new Error('无法获取 job_types 模型');
|
||||
}
|
||||
|
||||
if (!pla_account) {
|
||||
throw new Error('无法获取 pla_account 模型');
|
||||
}
|
||||
|
||||
// 从模型获取 sequelize 实例
|
||||
const sequelize = job_types.sequelize;
|
||||
if (!sequelize) {
|
||||
throw new Error('无法获取 sequelize 实例');
|
||||
}
|
||||
|
||||
// 1. 同步 job_types 表
|
||||
console.log('[同步职位类型] 同步 job_types 表...');
|
||||
await job_types.sync({ alter: true });
|
||||
console.log('[同步职位类型] job_types 表同步完成');
|
||||
|
||||
// 2. 同步 pla_account 表(会自动添加 job_type_id 字段)
|
||||
console.log('[同步职位类型] 同步 pla_account 表...');
|
||||
await pla_account.sync({ alter: true });
|
||||
console.log('[同步职位类型] pla_account 表同步完成');
|
||||
|
||||
// 3. 检查 pla_account 表是否有 job_type_id 字段
|
||||
console.log('[同步职位类型] 检查 pla_account 表结构...');
|
||||
const Sequelize = require('sequelize');
|
||||
const tableInfo = await sequelize.query("DESCRIBE pla_account", { type: Sequelize.QueryTypes.SELECT });
|
||||
const hasJobTypeId = Array.isArray(tableInfo) && tableInfo.some(field => field.Field === 'job_type_id');
|
||||
|
||||
if (hasJobTypeId) {
|
||||
console.log('[同步职位类型] ✅ pla_account 表已存在 job_type_id 字段');
|
||||
} else {
|
||||
console.log('[同步职位类型] ⚠️ pla_account 表未找到 job_type_id 字段,可能需要手动添加');
|
||||
}
|
||||
|
||||
// 4. 显示表结构
|
||||
console.log('\n[同步职位类型] job_types 表结构:');
|
||||
const jobTypesInfo = await sequelize.query("DESCRIBE job_types", { type: Sequelize.QueryTypes.SELECT });
|
||||
if (Array.isArray(jobTypesInfo)) {
|
||||
console.table(jobTypesInfo.map(field => ({
|
||||
字段名: field.Field,
|
||||
类型: field.Type,
|
||||
允许空: field.Null,
|
||||
键: field.Key,
|
||||
默认值: field.Default,
|
||||
注释: field.Comment || ''
|
||||
})));
|
||||
}
|
||||
|
||||
console.log('\n[同步职位类型] pla_account 表 job_type_id 字段:');
|
||||
const plaAccountInfo = await sequelize.query("DESCRIBE pla_account", { type: Sequelize.QueryTypes.SELECT });
|
||||
if (Array.isArray(plaAccountInfo)) {
|
||||
const jobTypeIdField = plaAccountInfo.find(field => field.Field === 'job_type_id');
|
||||
if (jobTypeIdField) {
|
||||
console.table([{
|
||||
字段名: jobTypeIdField.Field,
|
||||
类型: jobTypeIdField.Type,
|
||||
允许空: jobTypeIdField.Null,
|
||||
键: jobTypeIdField.Key,
|
||||
默认值: jobTypeIdField.Default,
|
||||
注释: jobTypeIdField.Comment || ''
|
||||
}]);
|
||||
} else {
|
||||
console.log(' ⚠️ 未找到 job_type_id 字段');
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\n[同步职位类型] 同步完成!');
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
console.error('[同步职位类型] 同步失败:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 执行同步
|
||||
syncJobTypes();
|
||||
|
||||
117
scripts/sync_pla_account_fields.js
Normal file
117
scripts/sync_pla_account_fields.js
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* 同步 pla_account 表的新字段
|
||||
* 添加自动投递、自动沟通、自动活跃等配置字段
|
||||
*/
|
||||
|
||||
const Framework = require('../framework/node-core-framework.js');
|
||||
const frameworkConfig = require('../config/framework.config.js');
|
||||
|
||||
async function syncPlaAccountFields() {
|
||||
console.log('🔄 开始同步 pla_account 表字段...\n');
|
||||
|
||||
try {
|
||||
// 初始化框架
|
||||
console.log('正在初始化框架...');
|
||||
const framework = await Framework.init(frameworkConfig);
|
||||
const models = Framework.getModels();
|
||||
|
||||
if (!models) {
|
||||
throw new Error('无法获取模型列表');
|
||||
}
|
||||
|
||||
// 从任意模型获取 sequelize 实例
|
||||
const Sequelize = require('sequelize');
|
||||
const firstModel = Object.values(models)[0];
|
||||
if (!firstModel || !firstModel.sequelize) {
|
||||
throw new Error('无法获取数据库连接');
|
||||
}
|
||||
const sequelize = firstModel.sequelize;
|
||||
|
||||
// 获取 pla_account 模型
|
||||
const pla_account = models.pla_account;
|
||||
if (!pla_account) {
|
||||
throw new Error('无法获取 pla_account 模型');
|
||||
}
|
||||
|
||||
console.log('正在同步表结构(使用 alter: true 模式,保留现有数据)...\n');
|
||||
await pla_account.sync({ alter: true });
|
||||
|
||||
console.log('✅ pla_account 表同步成功!\n');
|
||||
|
||||
// 显示表结构
|
||||
const tableInfo = await sequelize.query(
|
||||
`DESCRIBE pla_account`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
console.log('📋 当前表结构:');
|
||||
console.table(tableInfo.map(field => ({
|
||||
字段名: field.Field,
|
||||
类型: field.Type,
|
||||
允许空: field.Null,
|
||||
默认值: field.Default,
|
||||
注释: field.Comment || ''
|
||||
})));
|
||||
|
||||
// 检查新增字段
|
||||
const newFields = [
|
||||
'auto_deliver',
|
||||
'page_count',
|
||||
'max_deliver',
|
||||
'min_salary',
|
||||
'max_salary',
|
||||
'filter_keywords',
|
||||
'exclude_keywords',
|
||||
'auto_chat',
|
||||
'chat_interval',
|
||||
'auto_reply',
|
||||
'chat_strategy',
|
||||
'auto_active',
|
||||
'active_interval',
|
||||
'active_actions'
|
||||
];
|
||||
|
||||
const existingFields = tableInfo.map(f => f.Field);
|
||||
|
||||
console.log('\n🔍 检查新增字段:');
|
||||
const missingFields = [];
|
||||
newFields.forEach(field => {
|
||||
const exists = existingFields.includes(field);
|
||||
console.log(` ${exists ? '✅' : '❌'} ${field}`);
|
||||
if (!exists) {
|
||||
missingFields.push(field);
|
||||
}
|
||||
});
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
console.log('\n⚠️ 以下字段未添加:', missingFields.join(', '));
|
||||
console.log('建议:重新运行同步或手动添加这些字段');
|
||||
} else {
|
||||
console.log('\n✅ 所有新增字段都已存在!');
|
||||
}
|
||||
|
||||
// 显示字段统计
|
||||
console.log('\n📊 字段统计:');
|
||||
console.log(` 总字段数: ${existingFields.length}`);
|
||||
console.log(` 自动投递相关: ${newFields.filter(f => ['auto_deliver', 'page_count', 'max_deliver', 'min_salary', 'max_salary', 'filter_keywords', 'exclude_keywords'].includes(f) && existingFields.includes(f)).length}/7`);
|
||||
console.log(` 自动沟通相关: ${newFields.filter(f => ['auto_chat', 'chat_interval', 'auto_reply', 'chat_strategy'].includes(f) && existingFields.includes(f)).length}/4`);
|
||||
console.log(` 自动活跃相关: ${newFields.filter(f => ['auto_active', 'active_interval', 'active_actions'].includes(f) && existingFields.includes(f)).length}/3`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 同步失败:', error.message);
|
||||
console.error('\n详细错误:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行同步
|
||||
syncPlaAccountFields()
|
||||
.then(() => {
|
||||
console.log('\n✨ 同步完成!');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('\n💥 执行失败:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
67
scripts/sync_pla_account_is_enabled.js
Normal file
67
scripts/sync_pla_account_is_enabled.js
Normal file
@@ -0,0 +1,67 @@
|
||||
const Framework = require('../framework/node-core-framework.js');
|
||||
const frameworkConfig = require('../config/framework.config.js');
|
||||
const Sequelize = require('sequelize');
|
||||
|
||||
async function syncPlaAccountIsEnabled() {
|
||||
console.log('🔄 开始同步 pla_account 表 is_enabled 字段...\n');
|
||||
try {
|
||||
const framework = await Framework.init(frameworkConfig);
|
||||
const models = Framework.getModels();
|
||||
|
||||
if (!models) {
|
||||
throw new Error('无法获取模型列表');
|
||||
}
|
||||
|
||||
const pla_account = models.pla_account;
|
||||
if (!pla_account) {
|
||||
throw new Error('无法获取 pla_account 模型');
|
||||
}
|
||||
|
||||
console.log('正在同步表结构(使用 alter: true 模式,保留现有数据)...\n');
|
||||
await pla_account.sync({ alter: true });
|
||||
|
||||
console.log('✅ pla_account 表同步成功!\n');
|
||||
|
||||
// 显示表结构
|
||||
const sequelize = pla_account.sequelize;
|
||||
const tableInfo = await sequelize.query(
|
||||
`DESCRIBE pla_account`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
console.table(tableInfo.map(field => ({
|
||||
字段名: field.Field,
|
||||
类型: field.Type,
|
||||
允许空: field.Null,
|
||||
默认值: field.Default,
|
||||
注释: field.Comment || ''
|
||||
})));
|
||||
|
||||
// 检查 is_enabled 字段是否存在
|
||||
const isEnabledField = tableInfo.find(field => field.Field === 'is_enabled');
|
||||
if (isEnabledField) {
|
||||
console.log('\n✅ is_enabled 字段已存在');
|
||||
console.log(` 类型: ${isEnabledField.Type}`);
|
||||
console.log(` 默认值: ${isEnabledField.Default}`);
|
||||
console.log(` 注释: ${isEnabledField.Comment || '无'}\n`);
|
||||
} else {
|
||||
console.warn('\n⚠️ is_enabled 字段不存在,可能需要手动添加\n');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 同步失败:', error.message);
|
||||
console.error('\n详细错误:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
syncPlaAccountIsEnabled()
|
||||
.then(() => {
|
||||
console.log('✅ 同步完成');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('❌ 同步失败');
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
105
scripts/sync_resume_table.js
Normal file
105
scripts/sync_resume_table.js
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* 同步 resume_info 表结构
|
||||
* 用于创建或更新数据库表
|
||||
*/
|
||||
|
||||
const db = require('../api/middleware/dbProxy');
|
||||
|
||||
async function syncResumeTable() {
|
||||
console.log('🔄 开始同步 resume_info 表结构...\n');
|
||||
|
||||
try {
|
||||
// 获取模型
|
||||
const resume_info = db.getModel('resume_info');
|
||||
|
||||
if (!resume_info) {
|
||||
console.error('❌ 无法获取 resume_info 模型');
|
||||
return;
|
||||
}
|
||||
|
||||
// 同步表结构(force: true 会删除并重建表,慎用!)
|
||||
// 如果表已存在且有数据,请使用 alter: true
|
||||
console.log('⚠️ 注意:使用 alter: true 模式同步(保留现有数据)');
|
||||
console.log('如果需要完全重建表,请修改为 force: true\n');
|
||||
|
||||
await resume_info.sync({ alter: true });
|
||||
|
||||
console.log('✅ resume_info 表同步成功!\n');
|
||||
|
||||
// 显示表结构
|
||||
const tableInfo = await db.models.sequelize.query(
|
||||
`DESCRIBE resume_info`,
|
||||
{ type: db.models.sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
console.log('📋 当前表结构:');
|
||||
console.table(tableInfo.map(field => ({
|
||||
字段名: field.Field,
|
||||
类型: field.Type,
|
||||
允许空: field.Null,
|
||||
默认值: field.Default
|
||||
})));
|
||||
|
||||
// 检查关键字段
|
||||
const requiredFields = [
|
||||
'id',
|
||||
'sn_code',
|
||||
'account_id',
|
||||
'platform',
|
||||
'fullName',
|
||||
'gender',
|
||||
'age',
|
||||
'phone',
|
||||
'email',
|
||||
'education',
|
||||
'workYears',
|
||||
'expectedPosition',
|
||||
'expectedSalary',
|
||||
'skills',
|
||||
'projectExperience',
|
||||
'workExperience',
|
||||
'aiSkillTags',
|
||||
'aiStrengths',
|
||||
'aiWeaknesses',
|
||||
'aiCareerSuggestion',
|
||||
'aiCompetitiveness',
|
||||
'originalData',
|
||||
'isActive',
|
||||
'syncTime'
|
||||
];
|
||||
const existingFields = tableInfo.map(f => f.Field);
|
||||
|
||||
console.log('\n🔍 检查关键字段:');
|
||||
const missingFields = [];
|
||||
requiredFields.forEach(field => {
|
||||
const exists = existingFields.includes(field);
|
||||
console.log(` ${exists ? '✅' : '❌'} ${field}`);
|
||||
if (!exists) {
|
||||
missingFields.push(field);
|
||||
}
|
||||
});
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
console.log('\n⚠️ 缺少以下字段:', missingFields.join(', '));
|
||||
console.log('建议:重新运行同步或手动添加这些字段');
|
||||
} else {
|
||||
console.log('\n✅ 所有必需字段都存在!');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 同步失败:', error.message);
|
||||
console.error('\n详细错误:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 执行同步
|
||||
syncResumeTable()
|
||||
.then(() => {
|
||||
console.log('\n✨ 同步完成!');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('\n💥 执行失败:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user