chore: initial import

This commit is contained in:
2026-04-19 14:05:40 +08:00
commit 89e9eae36e
81 changed files with 37363 additions and 0 deletions
+103
View File
@@ -0,0 +1,103 @@
const path = require('path');
require('dotenv').config({ path: path.join(__dirname, '../.env') });
const db = require('../db');
const bcrypt = require('bcryptjs');
const fs = require('fs');
const setup = async () => {
try {
console.log('--- 科技成果转化系统 部署工具 ---');
// 1. 执行完整建表语句
console.log('正在初始化数据库表结构...');
const sqlPath = path.join(__dirname, '../../database/schema.sql');
if (!fs.existsSync(sqlPath)) {
throw new Error(`找不到 SQL 文件: ${sqlPath}`);
}
const sql = fs.readFileSync(sqlPath, 'utf8');
// 简单的 SQL 分割逻辑,按分号分割
const statements = sql.split(';').filter(s => s.trim());
for (let statement of statements) {
try {
await db.query(statement);
} catch (e) {
// 忽略“已存在”类的错误
if (!e.message.includes('already exists')) {
console.log(`执行语句时提示: ${e.message}`);
}
}
}
// 2. 初始化默认部门
console.log('正在初始化默认部门...');
const defaultDepts = [
'院领导', '卫星中心综合部', '卫星中心生产部', '卫星中心研发部', '大数据中心',
'生产保障部', '生产技术部', '土地调查监测室', '森林调查监测室', '湿地调查监测室',
'专业调查室', '权籍调查室', '碳汇研究中心', '权益研究中心', '科技与档案室',
'办公室', '党群工作部', '待定'
];
for (const dept of defaultDepts) {
await db.query('INSERT INTO departments (name) VALUES ($1) ON CONFLICT (name) DO NOTHING', [dept]);
}
// 3. 初始化字典表数据
console.log('正在初始化字典表数据...');
const dictData = {
dict_organizations: ['黑龙江省自然资源权益调查监测院','黑龙江省自然资源卫星应用技术中心','黑龙江省自然资源权益调查监测院(黑龙江省自然资源卫星应用技术中心)','待定'],
dict_award_types: ['国家级', '省部级', '社会力量', '其他', '待定'],
dict_award_levels: ['一等奖', '二等奖', '三等奖', '其他', '待定'],
dict_paper_types: ['Nature/Science/Cell', 'CCF A类会议','SCI一区期刊','SCI二区期刊', 'CCF B类会议','CCF C类会议','SCI三区期刊','SCI四区期刊','EI源刊', '中文核心期刊', 'EI会议', '普通期刊', '普通会议', '待定'],
dict_standard_types: ['国家标准', '国际标准', '行业标准', '地方标准', '待定'],
dict_project_categories: ['科技', '财政', '横向', '成果转化', '待定']
};
for (const [tableName, values] of Object.entries(dictData)) {
for (const val of values) {
await db.query(`INSERT INTO ${tableName} (name) VALUES ($1) ON CONFLICT (name) DO NOTHING`, [val]);
}
}
// 4. 创建初始超级管理员
const adminPhone = '18888888888';
const adminPass = 'admin123';
const salt = await bcrypt.genSalt(10);
const passwordHash = await bcrypt.hash(adminPass, salt);
console.log('正在创建初始超级管理员...');
await db.query(
`INSERT INTO users (username, password_hash, role, real_name, department, dept_status)
VALUES ($1, $2, $3, $4, $5, $6)
ON CONFLICT (username) DO UPDATE SET role = 'super_admin'`,
[adminPhone, passwordHash, 'super_admin', '系统管理员', null, 'verified']
);
// 5. 创建初始系统维护员
const maintainerPhone = '19999999999';
const maintainerPass = 'maintainer123';
const maintainerHash = await bcrypt.hash(maintainerPass, salt);
console.log('正在创建初始系统维护员...');
await db.query(
`INSERT INTO users (username, password_hash, role, real_name, department, dept_status)
VALUES ($1, $2, $3, $4, $5, $6)
ON CONFLICT (username) DO UPDATE SET role = 'maintainer'`,
[maintainerPhone, maintainerHash, 'maintainer', '系统维护员', null, 'verified']
);
console.log('\n-----------------------------------');
console.log('部署成功!');
console.log(`初始超管账号: ${adminPhone} / ${adminPass}`);
console.log(`初始维护员账号: ${maintainerPhone} / ${maintainerPass}`);
console.log('-----------------------------------');
process.exit(0);
} catch (err) {
console.error('\n部署失败:', err);
process.exit(1);
}
};
setup();