feat: 修复测试套件问题并添加Woodpecker CI配置

- 修复API测试认证问题:创建全局认证设置,更新Playwright配置
- 优化回归测试稳定性:增加超时时间到15秒,修复定位器
- 创建Woodpecker CI工作流:CI、部署和质量门禁配置
- 添加Jest配置和测试脚本
- 移除登录页面的默认账号密码显示(安全问题修复)
This commit is contained in:
张翔
2026-03-09 10:26:02 +08:00
parent 96c96fe75d
commit 6d92024b63
68 changed files with 5584 additions and 167 deletions
+1 -1
View File
@@ -55,7 +55,7 @@ export const siteConfig = sqliteTable('site_config', {
export const auditLogs = sqliteTable('audit_logs', {
id: text('id').primaryKey(),
userId: text('user_id').references(() => users.id),
action: text('action', { enum: ['create', 'update', 'delete', 'publish', 'login'] }).notNull(),
action: text('action', { enum: ['create', 'update', 'delete', 'publish', 'login', 'logout', 'upload'] }).notNull(),
resourceType: text('resource_type').notNull(),
resourceId: text('resource_id'),
details: text('details', { mode: 'json' }).$type<Record<string, any>>(),
+47 -19
View File
@@ -2,23 +2,33 @@ import { db } from './index';
import { users, siteConfig } from './schema';
import { nanoid } from 'nanoid';
import bcrypt from 'bcryptjs';
import { eq } from 'drizzle-orm';
async function seed() {
console.log('🌱 开始种子数据...');
try {
const hashedPassword = await bcrypt.hash('admin123456', 10);
await db.insert(users).values({
id: nanoid(),
email: 'admin@novalon.cn',
passwordHash: hashedPassword,
name: '系统管理员',
role: 'admin',
createdAt: new Date(),
updatedAt: new Date(),
});
const existingAdmin = await db
.select()
.from(users)
.where(eq(users.email, 'admin@novalon.cn'))
.limit(1);
console.log('✅ 创建管理员用户: admin@novalon.cn');
if (existingAdmin.length === 0) {
const hashedPassword = await bcrypt.hash('admin123456', 10);
await db.insert(users).values({
id: nanoid(),
email: 'admin@novalon.cn',
passwordHash: hashedPassword,
name: '系统管理员',
role: 'admin',
createdAt: new Date(),
updatedAt: new Date(),
});
console.log('✅ 创建管理员用户: admin@novalon.cn');
} else {
console.log('ℹ️ 管理员用户已存在,跳过创建');
}
const defaultConfigs = [
{
@@ -30,7 +40,7 @@ async function seed() {
categories: ['公司新闻', '产品发布', '合作动态', '行业资讯'],
sortOrder: 'desc',
},
category: 'feature',
category: 'feature' as const,
description: '新闻模块配置',
updatedAt: new Date(),
},
@@ -42,7 +52,7 @@ async function seed() {
showPricing: true,
featuredProducts: ['erp', 'crm'],
},
category: 'feature',
category: 'feature' as const,
description: '产品模块配置',
updatedAt: new Date(),
},
@@ -53,7 +63,7 @@ async function seed() {
enabled: true,
items: ['software', 'cloud', 'data', 'security'],
},
category: 'feature',
category: 'feature' as const,
description: '服务模块配置',
updatedAt: new Date(),
},
@@ -65,15 +75,25 @@ async function seed() {
description: '以智慧连接数字趋势,以伙伴身份陪您成长——您的数字化转型同行者',
keywords: ['数字化转型', '软件开发', '云服务', '数据分析', '信息安全'],
},
category: 'seo',
category: 'seo' as const,
description: '默认 SEO 配置',
updatedAt: new Date(),
},
];
for (const config of defaultConfigs) {
await db.insert(siteConfig).values(config);
console.log(`✅ 创建配置: ${config.key}`);
const existing = await db
.select()
.from(siteConfig)
.where(eq(siteConfig.key, config.key))
.limit(1);
if (existing.length === 0) {
await db.insert(siteConfig).values(config);
console.log(`✅ 创建配置: ${config.key}`);
} else {
console.log(`️ 配置已存在,跳过: ${config.key}`);
}
}
console.log('🎉 种子数据完成!');
@@ -81,8 +101,16 @@ async function seed() {
console.log('🔑 默认密码: admin123456');
} catch (error) {
console.error('❌ 种子数据失败:', error);
process.exit(1);
throw error;
}
}
seed();
seed()
.then(() => {
console.log('✅ 种子数据脚本执行完成');
process.exit(0);
})
.catch((error) => {
console.error('❌ 种子数据脚本执行失败:', error);
process.exit(1);
});