Skip to content

Commit 1bfccd8

Browse files
committed
feat: 数据源增加Oracle/达梦支持,系统数据库多数据库,test.html登录修复
1. Bug修复: test.html 增加JWT登录机制,列表请求自动携带Bearer Token 2. 需求1: 数据源管理增加Oracle、达梦(DM)数据库类型 - 后端: MysqlNodeExecutor 增加 Oracle/DM 连接工厂 - 后端: BuildConnectionString 增加 Oracle/DM 连接串构建 - 前端: DataSourceList 增加Oracle/达梦选项和端口映射 - NuGet: 添加 Oracle.ManagedDataAccess.Core + DM.DmProvider 3. 需求2: 系统数据库支持多种数据库 (SQLite/SQLServer/MySQL/PostgreSQL) - 通过 DB_TYPE 环境变量切换数据库提供者 - 添加 EF Core SQLServer/MySQL/PostgreSQL 驱动包 - JuggleDbContext 大文本字段增加HasColumnType(text) 跨数据库兼容 - Program.cs 启动日志显示当前数据库类型
1 parent f54bab7 commit 1bfccd8

9 files changed

Lines changed: 306 additions & 140 deletions

File tree

Juggle.Api/Program.cs

Lines changed: 69 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,60 @@
2323
opts.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
2424
});
2525

26-
// SQLite + EF Core(支持 DB_PATH 环境变量,容器部署时指向挂载卷)
27-
var dbPath = Environment.GetEnvironmentVariable("DB_PATH")
28-
?? Path.Combine(Directory.GetCurrentDirectory(), "juggle.db");
29-
builder.Services.AddDbContext<JuggleDbContext>(opts =>
30-
opts.UseSqlite($"Data Source={dbPath}"));
26+
// ==================== 数据库配置(支持多种数据库) ====================
27+
// 通过环境变量切换:DB_TYPE=sqlite|sqlserver|mysql|postgresql
28+
// 连接字符串通过:DB_CONNECTION_STRING 或各数据库专属变量设置
29+
var dbType = (Environment.GetEnvironmentVariable("DB_TYPE") ?? "sqlite").ToLower();
30+
var dbConnStr = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING");
31+
32+
void ConfigureDbContext(DbContextOptionsBuilder opts)
33+
{
34+
switch (dbType)
35+
{
36+
case "sqlserver" or "mssql":
37+
var sqlServerConn = dbConnStr
38+
?? $"Server={Env("DB_HOST","localhost")},{Env("DB_PORT","1433")};Database={Env("DB_NAME","juggle")};User Id={Env("DB_USER","sa")};Password={Env("DB_PASS","Juggle@2026")};TrustServerCertificate=True;";
39+
opts.UseSqlServer(sqlServerConn);
40+
break;
41+
case "mysql":
42+
var mysqlConn = dbConnStr
43+
?? $"Server={Env("DB_HOST","localhost")};Port={Env("DB_PORT","3306")};Database={Env("DB_NAME","juggle")};User={Env("DB_USER","root")};Password={Env("DB_PASS","juggle")};CharSet=utf8mb4;";
44+
opts.UseMySql(mysqlConn, ServerVersion.AutoDetect(mysqlConn),
45+
mySql => { mySql.EnableRetryOnFailure(3); });
46+
break;
47+
case "postgresql" or "postgres":
48+
var pgConn = dbConnStr
49+
?? $"Host={Env("DB_HOST","localhost")};Port={Env("DB_PORT","5432")};Database={Env("DB_NAME","juggle")};Username={Env("DB_USER","postgres")};Password={Env("DB_PASS","juggle")};";
50+
opts.UseNpgsql(pgConn);
51+
break;
52+
default: // sqlite
53+
var dbPath = dbConnStr
54+
?? Environment.GetEnvironmentVariable("DB_PATH")
55+
?? Path.Combine(Directory.GetCurrentDirectory(), "juggle.db");
56+
opts.UseSqlite($"Data Source={dbPath}");
57+
break;
58+
}
59+
}
60+
61+
// 临时辅助函数
62+
static string Env(string key, string defaultValue) => Environment.GetEnvironmentVariable(key) ?? defaultValue;
63+
64+
/// <summary>隐藏连接字符串中的密码部分</summary>
65+
static string MaskPassword(string connStr)
66+
{
67+
if (string.IsNullOrEmpty(connStr)) return connStr;
68+
return System.Text.RegularExpressions.Regex.Replace(
69+
connStr,
70+
@"(Password|PWD|User Id.*?Password)\s*=\s*[^;]+",
71+
m => m.Value.Contains('=') ? m.Value.Substring(0, m.Value.IndexOf('=') + 1) + "***" : m.Value,
72+
System.Text.RegularExpressions.RegexOptions.IgnoreCase
73+
);
74+
}
75+
76+
builder.Services.AddDbContext<JuggleDbContext>(ConfigureDbContext);
77+
78+
// 如果不是 SQLite,则需要在启动时确保数据库已迁移
79+
// SQLite 使用 EnsureCreated,其他数据库使用 Migrate 或 EnsureCreated
3180

3281
// JWT 认证
3382
var jwtKey = builder.Configuration["Jwt:Key"] ?? "JuggleNet6SecretKey2026!";
@@ -116,98 +165,26 @@ await ctx.Response.WriteAsync(
116165
// ==================== 应用构建 ====================
117166
var app = builder.Build();
118167

119-
// 自动迁移数据库:EnsureCreated 仅在首次创建时建表
120-
// 对于已存在的数据库,补建后续迭代新增的表(幂等 CREATE TABLE IF NOT EXISTS)
168+
// 启动日志:显示数据库类型
169+
Console.WriteLine($"[Juggle] 系统数据库类型: {dbType.ToUpper()}");
170+
if (!string.IsNullOrEmpty(dbConnStr))
171+
Console.WriteLine($"[Juggle] 连接字符串: {MaskPassword(dbConnStr)}");
172+
173+
// ==================== 数据库初始化 ====================
174+
// SQLite: EnsureCreated 自动建表
175+
// SQLServer/MySQL/PostgreSQL: EnsureCreated 自动建表(生产环境建议改用 Migration)
121176
using (var scope = app.Services.CreateScope())
122177
{
123178
var db = scope.ServiceProvider.GetRequiredService<JuggleDbContext>();
124179
db.Database.EnsureCreated();
125180

126-
// 补建迭代四新增的三张表(若已存在则跳过)
127-
db.Database.ExecuteSqlRaw(@"
128-
CREATE TABLE IF NOT EXISTS t_flow_log (
129-
id INTEGER PRIMARY KEY AUTOINCREMENT,
130-
deleted INTEGER NOT NULL DEFAULT 0,
131-
created_at TEXT,
132-
created_by TEXT,
133-
updated_at TEXT,
134-
updated_by TEXT,
135-
flow_key TEXT,
136-
flow_name TEXT,
137-
version INTEGER,
138-
trigger_type TEXT,
139-
status TEXT,
140-
start_time TEXT,
141-
end_time TEXT,
142-
cost_ms INTEGER,
143-
error_message TEXT,
144-
input_json TEXT,
145-
output_json TEXT
146-
);");
147-
148-
db.Database.ExecuteSqlRaw(@"
149-
CREATE TABLE IF NOT EXISTS t_flow_node_log (
150-
id INTEGER PRIMARY KEY AUTOINCREMENT,
151-
deleted INTEGER NOT NULL DEFAULT 0,
152-
created_at TEXT,
153-
created_by TEXT,
154-
updated_at TEXT,
155-
updated_by TEXT,
156-
flow_log_id INTEGER,
157-
node_key TEXT,
158-
node_label TEXT,
159-
node_type TEXT,
160-
seq_no INTEGER,
161-
status TEXT,
162-
start_time TEXT,
163-
end_time TEXT,
164-
cost_ms INTEGER,
165-
input_snapshot TEXT,
166-
output_snapshot TEXT,
167-
detail TEXT,
168-
error_message TEXT
169-
);");
170-
171-
db.Database.ExecuteSqlRaw(@"
172-
CREATE TABLE IF NOT EXISTS t_static_variable (
173-
id INTEGER PRIMARY KEY AUTOINCREMENT,
174-
deleted INTEGER NOT NULL DEFAULT 0,
175-
created_at TEXT,
176-
created_by TEXT,
177-
updated_at TEXT,
178-
updated_by TEXT,
179-
var_code TEXT NOT NULL,
180-
var_name TEXT,
181-
data_type TEXT,
182-
value TEXT,
183-
default_value TEXT,
184-
description TEXT,
185-
group_name TEXT
186-
);");
187-
188-
// 补建流程定义分组字段
189-
try { db.Database.ExecuteSqlRaw("ALTER TABLE t_flow_definition ADD COLUMN group_name TEXT DEFAULT NULL;"); }
190-
catch { /* 列已存在则忽略 */ }
191-
192-
// 补建定时任务表
193-
db.Database.ExecuteSqlRaw(@"
194-
CREATE TABLE IF NOT EXISTS t_schedule_task (
195-
id INTEGER PRIMARY KEY AUTOINCREMENT,
196-
deleted INTEGER NOT NULL DEFAULT 0,
197-
created_at TEXT,
198-
created_by TEXT,
199-
updated_at TEXT,
200-
updated_by TEXT,
201-
flow_key TEXT,
202-
flow_name TEXT,
203-
cron_expression TEXT,
204-
input_json TEXT,
205-
status INTEGER NOT NULL DEFAULT 0,
206-
last_run_time TEXT,
207-
last_run_status TEXT,
208-
next_run_time TEXT,
209-
run_count INTEGER NOT NULL DEFAULT 0
210-
);");
181+
// 补建迭代新增字段/表(仅 SQLite 需要手动 ALTER TABLE,其他数据库由 Migration 处理)
182+
if (dbType == "sqlite")
183+
{
184+
// 补建流程定义分组字段
185+
try { db.Database.ExecuteSqlRaw("ALTER TABLE t_flow_definition ADD COLUMN group_name TEXT DEFAULT NULL;"); }
186+
catch { /* 列已存在则忽略 */ }
187+
}
211188
}
212189

213190
if (app.Environment.IsDevelopment())

0 commit comments

Comments
 (0)