2026-06-18 11:15:12 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 示例数据种子脚本
|
2026-06-23 10:40:10 +08:00
|
|
|
|
* 为 云睿资产管理系统写入演示数据(幂等,可重复执行)
|
2026-06-23 10:27:47 +08:00
|
|
|
|
*
|
|
|
|
|
|
* 本地:node scripts/seed-example-data.js
|
2026-06-23 10:40:10 +08:00
|
|
|
|
* Docker:docker exec yunrui_asset-backend node scripts/seed-example-data.js
|
2026-06-18 11:15:12 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
require('dotenv').config({ path: require('path').join(__dirname, '..', '.env') });
|
|
|
|
|
|
|
2026-06-23 10:27:47 +08:00
|
|
|
|
const bcrypt = require('bcryptjs');
|
2026-06-18 11:15:12 +08:00
|
|
|
|
const { sequelize } = require('../db');
|
|
|
|
|
|
const Room = require('../models/Room');
|
|
|
|
|
|
const Rack = require('../models/Rack');
|
2026-06-23 10:27:47 +08:00
|
|
|
|
const Device = require('../models/Device');
|
2026-06-18 11:15:12 +08:00
|
|
|
|
const Business = require('../models/Business');
|
2026-06-23 10:27:47 +08:00
|
|
|
|
const DeviceBusiness = require('../models/DeviceBusiness');
|
|
|
|
|
|
const Warehouse = require('../models/Warehouse');
|
|
|
|
|
|
const User = require('../models/User');
|
2026-06-18 11:15:12 +08:00
|
|
|
|
const Role = require('../models/Role');
|
2026-06-23 10:27:47 +08:00
|
|
|
|
const UserRole = require('../models/UserRole');
|
|
|
|
|
|
const ConsumableCategory = require('../models/ConsumableCategory');
|
|
|
|
|
|
const Consumable = require('../models/Consumable');
|
|
|
|
|
|
const Ticket = require('../models/Ticket');
|
|
|
|
|
|
|
|
|
|
|
|
const SEED_MARKER_ROOM = '北京通州一号机房';
|
|
|
|
|
|
const DEMO_ADMIN = { username: 'admin', password: 'admin123', realName: '系统管理员', email: 'admin@example.com' };
|
|
|
|
|
|
|
|
|
|
|
|
const DEFAULT_ROLES = [
|
|
|
|
|
|
{
|
|
|
|
|
|
roleId: 'role_admin',
|
|
|
|
|
|
roleName: '管理员',
|
|
|
|
|
|
roleCode: 'admin',
|
|
|
|
|
|
description: '系统管理员,拥有所有权限',
|
|
|
|
|
|
permissions: ['*'],
|
|
|
|
|
|
status: 'active',
|
|
|
|
|
|
sort: 1,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
roleId: 'role_operator',
|
|
|
|
|
|
roleName: '运维人员',
|
|
|
|
|
|
roleCode: 'operator',
|
|
|
|
|
|
description: '负责日常运维操作',
|
|
|
|
|
|
permissions: ['devices:read', 'devices:write', 'racks:read', 'rooms:read', 'consumables:read', 'consumables:write'],
|
|
|
|
|
|
status: 'active',
|
|
|
|
|
|
sort: 2,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
roleId: 'role_viewer',
|
|
|
|
|
|
roleName: '只读用户',
|
|
|
|
|
|
roleCode: 'viewer',
|
|
|
|
|
|
description: '仅能查看数据',
|
|
|
|
|
|
permissions: ['devices:read', 'racks:read', 'rooms:read', 'consumables:read'],
|
|
|
|
|
|
status: 'active',
|
|
|
|
|
|
sort: 3,
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
async function upsertRole(roleData) {
|
|
|
|
|
|
const [role] = await Role.findOrCreate({ where: { roleCode: roleData.roleCode }, defaults: roleData });
|
|
|
|
|
|
if (role.roleId !== roleData.roleId) {
|
|
|
|
|
|
await role.update(roleData);
|
|
|
|
|
|
}
|
|
|
|
|
|
return role;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function ensureAdminUser() {
|
|
|
|
|
|
for (const roleData of DEFAULT_ROLES) {
|
|
|
|
|
|
await upsertRole(roleData);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const adminRole = await Role.findOne({ where: { roleCode: 'admin' } });
|
|
|
|
|
|
const hashedPassword = await bcrypt.hash(DEMO_ADMIN.password, 10);
|
|
|
|
|
|
|
|
|
|
|
|
const [admin] = await User.findOrCreate({
|
|
|
|
|
|
where: { username: DEMO_ADMIN.username },
|
|
|
|
|
|
defaults: {
|
|
|
|
|
|
password: hashedPassword,
|
|
|
|
|
|
email: DEMO_ADMIN.email,
|
|
|
|
|
|
realName: DEMO_ADMIN.realName,
|
|
|
|
|
|
status: 'active',
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const existingLink = await UserRole.findOne({ where: { UserId: admin.userId, RoleId: adminRole.roleId } });
|
|
|
|
|
|
if (!existingLink) {
|
|
|
|
|
|
await UserRole.create({ UserId: admin.userId, RoleId: adminRole.roleId });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return admin;
|
|
|
|
|
|
}
|
2026-06-18 11:15:12 +08:00
|
|
|
|
|
|
|
|
|
|
async function seedData() {
|
|
|
|
|
|
try {
|
2026-06-23 10:27:47 +08:00
|
|
|
|
console.log('连接数据库...');
|
|
|
|
|
|
await sequelize.authenticate();
|
2026-06-18 11:15:12 +08:00
|
|
|
|
await sequelize.sync();
|
|
|
|
|
|
|
2026-06-23 10:27:47 +08:00
|
|
|
|
const marker = await Room.findOne({ where: { name: SEED_MARKER_ROOM } });
|
|
|
|
|
|
if (marker && process.env.SEED_FORCE !== '1') {
|
|
|
|
|
|
console.log(`示例数据已存在(机房: ${SEED_MARKER_ROOM}),跳过写入。`);
|
|
|
|
|
|
console.log('如需强制重新写入,请设置环境变量 SEED_FORCE=1');
|
|
|
|
|
|
const admin = await ensureAdminUser();
|
|
|
|
|
|
console.log(`演示账号: ${DEMO_ADMIN.username} / ${DEMO_ADMIN.password} (${admin.userId})`);
|
|
|
|
|
|
process.exit(0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log('开始写入示例数据...\n');
|
|
|
|
|
|
|
|
|
|
|
|
const admin = await ensureAdminUser();
|
|
|
|
|
|
console.log(`✓ 角色与管理员账号 (${DEMO_ADMIN.username} / ${DEMO_ADMIN.password})`);
|
|
|
|
|
|
|
|
|
|
|
|
const [room1] = await Room.findOrCreate({
|
|
|
|
|
|
where: { name: SEED_MARKER_ROOM },
|
|
|
|
|
|
defaults: {
|
|
|
|
|
|
location: '北京市通州区马驹桥',
|
|
|
|
|
|
area: 500,
|
|
|
|
|
|
capacity: 100,
|
|
|
|
|
|
status: 'active',
|
|
|
|
|
|
description: '公司核心数据中心,具备双路供电及精密空调系统。',
|
|
|
|
|
|
gridRows: 8,
|
|
|
|
|
|
gridCols: 12,
|
|
|
|
|
|
},
|
2026-06-18 11:15:12 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-06-23 10:27:47 +08:00
|
|
|
|
const [room2] = await Room.findOrCreate({
|
|
|
|
|
|
where: { name: '上海浦东二号机房' },
|
|
|
|
|
|
defaults: {
|
|
|
|
|
|
location: '上海市浦东新区张江高科',
|
|
|
|
|
|
area: 320,
|
|
|
|
|
|
capacity: 60,
|
|
|
|
|
|
status: 'active',
|
|
|
|
|
|
description: '华东区域灾备机房,承载核心业务冗余部署。',
|
|
|
|
|
|
gridRows: 6,
|
|
|
|
|
|
gridCols: 10,
|
|
|
|
|
|
},
|
2026-06-18 11:15:12 +08:00
|
|
|
|
});
|
2026-06-23 10:27:47 +08:00
|
|
|
|
console.log(`✓ 机房: ${room1.name}, ${room2.name}`);
|
2026-06-18 11:15:12 +08:00
|
|
|
|
|
2026-06-23 10:27:47 +08:00
|
|
|
|
const rackDefs = [
|
|
|
|
|
|
{ rackId: 'RCK_SEED_A01', name: 'A-01', roomId: room1.roomId, height: 42, maxPower: 8000, rowPos: 1, colPos: 1 },
|
|
|
|
|
|
{ rackId: 'RCK_SEED_A02', name: 'A-02', roomId: room1.roomId, height: 42, maxPower: 8000, rowPos: 1, colPos: 2 },
|
|
|
|
|
|
{ rackId: 'RCK_SEED_B01', name: 'B-01', roomId: room1.roomId, height: 42, maxPower: 6000, rowPos: 2, colPos: 1 },
|
|
|
|
|
|
{ rackId: 'RCK_SEED_C01', name: 'C-01', roomId: room2.roomId, height: 42, maxPower: 8000, rowPos: 1, colPos: 1 },
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
const racks = {};
|
|
|
|
|
|
for (const def of rackDefs) {
|
|
|
|
|
|
const [rack] = await Rack.findOrCreate({ where: { rackId: def.rackId }, defaults: def });
|
|
|
|
|
|
racks[def.name] = rack;
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log(`✓ 机柜: ${rackDefs.map(r => r.name).join(', ')}`);
|
|
|
|
|
|
|
|
|
|
|
|
const businessDefs = [
|
|
|
|
|
|
{ businessId: 'BIZ_SEED_001', name: '云端计算核心', description: '负责核心云端计算资源的分配与管理。' },
|
|
|
|
|
|
{ businessId: 'BIZ_SEED_002', name: '企业办公平台', description: 'OA、邮件、协作等企业内部应用。' },
|
|
|
|
|
|
{ businessId: 'BIZ_SEED_003', name: '数据分析服务', description: '大数据分析与报表平台。' },
|
|
|
|
|
|
];
|
|
|
|
|
|
const businesses = {};
|
|
|
|
|
|
for (const def of businessDefs) {
|
|
|
|
|
|
const [biz] = await Business.findOrCreate({ where: { businessId: def.businessId }, defaults: def });
|
|
|
|
|
|
businesses[def.businessId] = biz;
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log(`✓ 业务: ${businessDefs.map(b => b.name).join(', ')}`);
|
|
|
|
|
|
|
|
|
|
|
|
const [warehouse] = await Warehouse.findOrCreate({
|
|
|
|
|
|
where: { name: '通州备件库房' },
|
|
|
|
|
|
defaults: {
|
|
|
|
|
|
location: '北京通州一号机房 B 区',
|
|
|
|
|
|
capacity: 200,
|
|
|
|
|
|
status: 'active',
|
|
|
|
|
|
description: '存放待上架及退役备件设备。',
|
|
|
|
|
|
},
|
2026-06-18 11:15:12 +08:00
|
|
|
|
});
|
2026-06-23 10:27:47 +08:00
|
|
|
|
console.log(`✓ 库房: ${warehouse.name}`);
|
2026-06-18 11:15:12 +08:00
|
|
|
|
|
2026-06-23 10:27:47 +08:00
|
|
|
|
const deviceDefs = [
|
|
|
|
|
|
{
|
|
|
|
|
|
deviceId: 'DEV_SEED_001',
|
|
|
|
|
|
name: 'Web-01',
|
|
|
|
|
|
type: 'server',
|
|
|
|
|
|
model: 'Dell PowerEdge R750',
|
|
|
|
|
|
serialNumber: 'SN-DELL-R750-001',
|
|
|
|
|
|
rackId: racks['A-01'].rackId,
|
|
|
|
|
|
position: 1,
|
|
|
|
|
|
height: 2,
|
|
|
|
|
|
powerConsumption: 450,
|
|
|
|
|
|
status: 'online',
|
|
|
|
|
|
ipAddress: '10.10.1.101',
|
|
|
|
|
|
description: '核心 Web 应用服务器',
|
|
|
|
|
|
businessId: 'BIZ_SEED_001',
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
deviceId: 'DEV_SEED_002',
|
|
|
|
|
|
name: 'DB-01',
|
|
|
|
|
|
type: 'server',
|
|
|
|
|
|
model: 'Dell PowerEdge R750',
|
|
|
|
|
|
serialNumber: 'SN-DELL-R750-002',
|
|
|
|
|
|
rackId: racks['A-01'].rackId,
|
|
|
|
|
|
position: 3,
|
|
|
|
|
|
height: 2,
|
|
|
|
|
|
powerConsumption: 520,
|
|
|
|
|
|
status: 'online',
|
|
|
|
|
|
ipAddress: '10.10.1.102',
|
|
|
|
|
|
description: 'MySQL 主库',
|
|
|
|
|
|
businessId: 'BIZ_SEED_001',
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
deviceId: 'DEV_SEED_003',
|
|
|
|
|
|
name: 'SW-Core-01',
|
|
|
|
|
|
type: 'switch',
|
|
|
|
|
|
model: 'Huawei CE6857',
|
|
|
|
|
|
serialNumber: 'SN-HW-CE6857-001',
|
|
|
|
|
|
rackId: racks['A-01'].rackId,
|
|
|
|
|
|
position: 40,
|
|
|
|
|
|
height: 1,
|
|
|
|
|
|
powerConsumption: 180,
|
|
|
|
|
|
status: 'online',
|
|
|
|
|
|
ipAddress: '10.10.0.1',
|
|
|
|
|
|
description: '核心交换机',
|
|
|
|
|
|
businessId: 'BIZ_SEED_001',
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
deviceId: 'DEV_SEED_004',
|
|
|
|
|
|
name: 'OA-App-01',
|
|
|
|
|
|
type: 'server',
|
|
|
|
|
|
model: 'Lenovo SR650',
|
|
|
|
|
|
serialNumber: 'SN-LENOVO-SR650-001',
|
|
|
|
|
|
rackId: racks['A-02'].rackId,
|
|
|
|
|
|
position: 5,
|
|
|
|
|
|
height: 2,
|
|
|
|
|
|
powerConsumption: 380,
|
|
|
|
|
|
status: 'online',
|
|
|
|
|
|
ipAddress: '10.20.1.50',
|
|
|
|
|
|
description: 'OA 应用服务器',
|
|
|
|
|
|
businessId: 'BIZ_SEED_002',
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
deviceId: 'DEV_SEED_005',
|
|
|
|
|
|
name: 'BI-Node-01',
|
|
|
|
|
|
type: 'server',
|
|
|
|
|
|
model: 'HPE ProLiant DL380',
|
|
|
|
|
|
serialNumber: 'SN-HPE-DL380-001',
|
|
|
|
|
|
rackId: racks['B-01'].rackId,
|
|
|
|
|
|
position: 10,
|
|
|
|
|
|
height: 2,
|
|
|
|
|
|
powerConsumption: 490,
|
|
|
|
|
|
status: 'maintenance',
|
|
|
|
|
|
ipAddress: '10.30.1.10',
|
|
|
|
|
|
description: '数据分析计算节点',
|
|
|
|
|
|
businessId: 'BIZ_SEED_003',
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
deviceId: 'DEV_SEED_006',
|
|
|
|
|
|
name: 'DR-Storage-01',
|
|
|
|
|
|
type: 'storage',
|
|
|
|
|
|
model: 'NetApp FAS2750',
|
|
|
|
|
|
serialNumber: 'SN-NETAPP-FAS2750-001',
|
|
|
|
|
|
rackId: racks['C-01'].rackId,
|
|
|
|
|
|
position: 20,
|
|
|
|
|
|
height: 4,
|
|
|
|
|
|
powerConsumption: 600,
|
|
|
|
|
|
status: 'online',
|
|
|
|
|
|
ipAddress: '10.40.1.20',
|
|
|
|
|
|
description: '灾备存储阵列',
|
|
|
|
|
|
businessId: 'BIZ_SEED_001',
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
deviceId: 'DEV_SEED_007',
|
|
|
|
|
|
name: 'Spare-R750',
|
|
|
|
|
|
type: 'server',
|
|
|
|
|
|
model: 'Dell PowerEdge R750',
|
|
|
|
|
|
serialNumber: 'SN-DELL-R750-SPARE',
|
|
|
|
|
|
warehouseId: warehouse.warehouseId,
|
|
|
|
|
|
sourceType: 'warehouse',
|
|
|
|
|
|
height: 2,
|
|
|
|
|
|
powerConsumption: 0,
|
|
|
|
|
|
status: 'offline',
|
|
|
|
|
|
description: '待上架备用服务器',
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
const devices = {};
|
|
|
|
|
|
for (const def of deviceDefs) {
|
|
|
|
|
|
const { businessId, ...deviceData } = def;
|
|
|
|
|
|
const [device] = await Device.findOrCreate({ where: { deviceId: def.deviceId }, defaults: deviceData });
|
|
|
|
|
|
devices[def.deviceId] = device;
|
|
|
|
|
|
|
|
|
|
|
|
if (businessId) {
|
|
|
|
|
|
await DeviceBusiness.findOrCreate({
|
|
|
|
|
|
where: { deviceId: def.deviceId, businessId },
|
|
|
|
|
|
defaults: { isPrimary: true },
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log(`✓ 设备: ${deviceDefs.length} 台(含 1 台库房备件)`);
|
|
|
|
|
|
|
|
|
|
|
|
const consumableCategories = [
|
|
|
|
|
|
{ name: '线缆', description: '网络与电源线缆', sortOrder: 1 },
|
|
|
|
|
|
{ name: '光模块', description: 'SFP/SFP+/QSFP 光模块', sortOrder: 2 },
|
|
|
|
|
|
{ name: '硬盘', description: '企业级硬盘与 SSD', sortOrder: 3 },
|
|
|
|
|
|
];
|
|
|
|
|
|
for (const cat of consumableCategories) {
|
|
|
|
|
|
await ConsumableCategory.findOrCreate({ where: { name: cat.name }, defaults: cat });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const consumableDefs = [
|
|
|
|
|
|
{ consumableId: 'CON_SEED_001', name: '六类网线 3m', category: '线缆', unit: '根', currentStock: 120, minStock: 20, unitPrice: 15.0, location: '通州备件库房 A 架' },
|
|
|
|
|
|
{ consumableId: 'CON_SEED_002', name: 'SFP+ 10G 光模块', category: '光模块', unit: '个', currentStock: 32, minStock: 10, unitPrice: 280.0, location: '通州备件库房 B 架' },
|
|
|
|
|
|
{ consumableId: 'CON_SEED_003', name: '1.92TB SSD', category: '硬盘', unit: '块', currentStock: 8, minStock: 5, unitPrice: 1800.0, location: '通州备件库房 C 架' },
|
|
|
|
|
|
];
|
|
|
|
|
|
for (const def of consumableDefs) {
|
|
|
|
|
|
await Consumable.findOrCreate({ where: { consumableId: def.consumableId }, defaults: def });
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log(`✓ 耗材: ${consumableDefs.length} 种`);
|
|
|
|
|
|
|
|
|
|
|
|
const ticketDefs = [
|
|
|
|
|
|
{
|
|
|
|
|
|
ticketId: 'TKT_SEED_001',
|
|
|
|
|
|
title: 'DB-01 磁盘 IO 延迟偏高',
|
|
|
|
|
|
deviceId: 'DEV_SEED_002',
|
|
|
|
|
|
deviceName: 'DB-01',
|
|
|
|
|
|
deviceModel: 'Dell PowerEdge R750',
|
|
|
|
|
|
serialNumber: 'SN-DELL-R750-002',
|
|
|
|
|
|
faultCategory: '性能问题',
|
|
|
|
|
|
priority: 'high',
|
|
|
|
|
|
status: 'in_progress',
|
|
|
|
|
|
description: '数据库主库磁盘 IO 等待时间持续超过 50ms,需排查存储性能。',
|
|
|
|
|
|
reporterId: admin.userId,
|
|
|
|
|
|
reporterName: admin.realName,
|
|
|
|
|
|
assigneeId: admin.userId,
|
|
|
|
|
|
assigneeName: admin.realName,
|
|
|
|
|
|
location: '北京通州一号机房 / A-01',
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
ticketId: 'TKT_SEED_002',
|
|
|
|
|
|
title: 'BI-Node-01 计划维护',
|
|
|
|
|
|
deviceId: 'DEV_SEED_005',
|
|
|
|
|
|
deviceName: 'BI-Node-01',
|
|
|
|
|
|
deviceModel: 'HPE ProLiant DL380',
|
|
|
|
|
|
serialNumber: 'SN-HPE-DL380-001',
|
|
|
|
|
|
faultCategory: '例行维护',
|
|
|
|
|
|
priority: 'low',
|
|
|
|
|
|
status: 'pending',
|
|
|
|
|
|
description: '月度固件升级与内存巡检。',
|
|
|
|
|
|
reporterId: admin.userId,
|
|
|
|
|
|
reporterName: admin.realName,
|
|
|
|
|
|
location: '北京通州一号机房 / B-01',
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
ticketId: 'TKT_SEED_003',
|
|
|
|
|
|
title: '核心交换机端口异常',
|
|
|
|
|
|
deviceId: 'DEV_SEED_003',
|
|
|
|
|
|
deviceName: 'SW-Core-01',
|
|
|
|
|
|
deviceModel: 'Huawei CE6857',
|
|
|
|
|
|
serialNumber: 'SN-HW-CE6857-001',
|
|
|
|
|
|
faultCategory: '网络故障',
|
|
|
|
|
|
priority: 'critical',
|
|
|
|
|
|
status: 'completed',
|
|
|
|
|
|
description: 'Gi0/0/24 端口频繁 flapping,已更换光模块。',
|
|
|
|
|
|
reporterId: admin.userId,
|
|
|
|
|
|
reporterName: admin.realName,
|
|
|
|
|
|
assigneeId: admin.userId,
|
|
|
|
|
|
assigneeName: admin.realName,
|
|
|
|
|
|
location: '北京通州一号机房 / A-01',
|
|
|
|
|
|
resolution: '更换 SFP+ 光模块后端口恢复正常。',
|
|
|
|
|
|
completionDate: new Date(),
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
for (const def of ticketDefs) {
|
|
|
|
|
|
await Ticket.findOrCreate({ where: { ticketId: def.ticketId }, defaults: def });
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log(`✓ 工单: ${ticketDefs.length} 条`);
|
|
|
|
|
|
|
|
|
|
|
|
console.log('\n示例数据写入完成!');
|
|
|
|
|
|
console.log('────────────────────────────────────');
|
|
|
|
|
|
console.log(`登录账号: ${DEMO_ADMIN.username}`);
|
|
|
|
|
|
console.log(`登录密码: ${DEMO_ADMIN.password}`);
|
|
|
|
|
|
console.log(`前端地址: http://localhost:${process.env.FRONTEND_PORT || 12000}`);
|
|
|
|
|
|
console.log('────────────────────────────────────');
|
2026-06-18 11:15:12 +08:00
|
|
|
|
process.exit(0);
|
|
|
|
|
|
} catch (error) {
|
2026-06-23 10:27:47 +08:00
|
|
|
|
console.error('示例数据写入失败:', error);
|
2026-06-18 11:15:12 +08:00
|
|
|
|
process.exit(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
seedData();
|