312 lines
14 KiB
SQL
312 lines
14 KiB
SQL
-- ============================================================
|
||
-- 应用商店数据库 —— 建表 + 初始数据
|
||
-- 数据库: my_panel
|
||
-- 字符集: utf8mb4
|
||
-- ============================================================
|
||
|
||
-- ─── 主表 ───
|
||
CREATE TABLE IF NOT EXISTS app_templates (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
app_key VARCHAR(64) NOT NULL UNIQUE COMMENT '唯一标识 (redis / mysql)',
|
||
name VARCHAR(128) NOT NULL COMMENT '显示名称',
|
||
tagline VARCHAR(256) DEFAULT NULL COMMENT '一句话描述',
|
||
description TEXT DEFAULT NULL COMMENT '详细描述',
|
||
icon VARCHAR(32) DEFAULT NULL COMMENT '图标标识 (redis / mysql)',
|
||
category VARCHAR(64) DEFAULT NULL COMMENT '分类',
|
||
image VARCHAR(256) NOT NULL COMMENT 'Docker 镜像',
|
||
container_name VARCHAR(128) NOT NULL COMMENT '容器名称',
|
||
network VARCHAR(128) DEFAULT '' COMMENT 'Docker 网络',
|
||
restart VARCHAR(32) DEFAULT 'always' COMMENT '重启策略',
|
||
hostname VARCHAR(128) DEFAULT '' COMMENT '容器主机名',
|
||
workdir VARCHAR(256) DEFAULT '' COMMENT '工作目录',
|
||
command TEXT DEFAULT NULL COMMENT '启动命令',
|
||
extra_args TEXT DEFAULT NULL COMMENT '额外 docker run 参数模板 (含 {{}} 占位符)',
|
||
sort_order INT DEFAULT 0 COMMENT '排序权重',
|
||
is_active TINYINT(1) DEFAULT 1 COMMENT '是否上架 1=是 0=否',
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用模板主表';
|
||
|
||
-- ─── 子表:端口映射 ───
|
||
CREATE TABLE IF NOT EXISTS app_ports (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
template_id INT NOT NULL,
|
||
host_port VARCHAR(16) NOT NULL COMMENT '宿主机端口',
|
||
container_port VARCHAR(16) NOT NULL COMMENT '容器端口',
|
||
protocol VARCHAR(8) DEFAULT 'tcp' COMMENT '协议',
|
||
sort_order INT DEFAULT 0,
|
||
FOREIGN KEY (template_id) REFERENCES app_templates(id) ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
|
||
-- ─── 子表:挂载卷 ───
|
||
CREATE TABLE IF NOT EXISTS app_volumes (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
template_id INT NOT NULL,
|
||
host_path VARCHAR(512) NOT NULL COMMENT '宿主机路径',
|
||
container_path VARCHAR(512) NOT NULL COMMENT '容器路径',
|
||
mode VARCHAR(4) DEFAULT 'rw' COMMENT '读写模式',
|
||
sort_order INT DEFAULT 0,
|
||
FOREIGN KEY (template_id) REFERENCES app_templates(id) ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
|
||
-- ─── 子表:环境变量 ───
|
||
CREATE TABLE IF NOT EXISTS app_envs (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
template_id INT NOT NULL,
|
||
env_key VARCHAR(256) NOT NULL COMMENT '变量名',
|
||
env_value TEXT DEFAULT NULL COMMENT '变量值 (含 {{}} 占位符)',
|
||
sort_order INT DEFAULT 0,
|
||
FOREIGN KEY (template_id) REFERENCES app_templates(id) ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
|
||
-- ─── 子表:自动创建目录 ───
|
||
CREATE TABLE IF NOT EXISTS app_mkdirs (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
template_id INT NOT NULL,
|
||
dir_path VARCHAR(512) NOT NULL COMMENT '宿主机目录',
|
||
sort_order INT DEFAULT 0,
|
||
FOREIGN KEY (template_id) REFERENCES app_templates(id) ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
|
||
-- ─── 子表:自动写入配置文件 ───
|
||
CREATE TABLE IF NOT EXISTS app_write_files (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
template_id INT NOT NULL,
|
||
file_path VARCHAR(512) NOT NULL COMMENT '宿主机文件路径',
|
||
file_content LONGTEXT NOT NULL COMMENT '文件内容 (含 {{}} 占位符)',
|
||
sort_order INT DEFAULT 0,
|
||
FOREIGN KEY (template_id) REFERENCES app_templates(id) ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
|
||
-- ─── 子表:用户参数 ───
|
||
CREATE TABLE IF NOT EXISTS app_params (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
template_id INT NOT NULL,
|
||
param_key VARCHAR(64) NOT NULL COMMENT '参数键',
|
||
label VARCHAR(128) NOT NULL COMMENT '显示标签',
|
||
type VARCHAR(16) DEFAULT 'text' COMMENT 'text/password/number',
|
||
placeholder VARCHAR(256) DEFAULT NULL,
|
||
default_value VARCHAR(256) DEFAULT '' COMMENT '默认值',
|
||
required TINYINT(1) DEFAULT 0 COMMENT '是否必填',
|
||
options TEXT DEFAULT NULL COMMENT '下拉选项 JSON 数组 [{"value":"","label":""}]',
|
||
show_when VARCHAR(128) DEFAULT NULL COMMENT '条件显示 param_key:value',
|
||
sort_order INT DEFAULT 0,
|
||
FOREIGN KEY (template_id) REFERENCES app_templates(id) ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
|
||
|
||
-- ============================================================
|
||
-- 初始数据:Redis 模板
|
||
-- ============================================================
|
||
INSERT INTO app_templates (app_key, name, tagline, description, icon, category, image, container_name, network, restart, hostname, workdir, command, sort_order, is_active)
|
||
VALUES ('redis', 'Redis', '高性能内存数据库 / 缓存',
|
||
'Redis 是开源的内存数据结构存储,用作数据库、缓存、消息队列和流引擎。支持字符串、哈希、列表、集合等多种数据结构。',
|
||
'redis', '缓存', 'redis:8.10.0', 'redis', '', 'always', 'redis', '/data',
|
||
'redis-server /etc/redis/redis.conf', 1, 1);
|
||
|
||
SET @redis_id = LAST_INSERT_ID();
|
||
|
||
INSERT INTO app_ports (template_id, host_port, container_port, protocol, sort_order) VALUES
|
||
(@redis_id, '6379', '6379', 'tcp', 0);
|
||
|
||
INSERT INTO app_volumes (template_id, host_path, container_path, mode, sort_order) VALUES
|
||
(@redis_id, '/opt/redis/data', '/data', 'rw', 0),
|
||
(@redis_id, '/opt/redis/conf/redis.conf', '/etc/redis/redis.conf', 'rw', 1),
|
||
(@redis_id, '/opt/redis/logs', '/logs', 'rw', 2);
|
||
|
||
INSERT INTO app_mkdirs (template_id, dir_path, sort_order) VALUES
|
||
(@redis_id, '/opt/redis/data', 0),
|
||
(@redis_id, '/opt/redis/conf', 1),
|
||
(@redis_id, '/opt/redis/logs', 2);
|
||
|
||
INSERT INTO app_write_files (template_id, file_path, file_content, sort_order) VALUES
|
||
(@redis_id, '/opt/redis/conf/redis.conf',
|
||
'# Redis 配置文件
|
||
bind 0.0.0.0
|
||
protected-mode no
|
||
port 6379
|
||
tcp-backlog 511
|
||
timeout 0
|
||
tcp-keepalive 300
|
||
daemonize no
|
||
supervised no
|
||
pidfile /var/run/redis_6379.pid
|
||
loglevel notice
|
||
logfile ""
|
||
databases 16
|
||
always-show-logo yes
|
||
save 900 1
|
||
save 300 10
|
||
save 60 10000
|
||
stop-writes-on-bgsave-error yes
|
||
rdbcompression yes
|
||
rdbchecksum yes
|
||
dbfilename dump.rdb
|
||
dir /data
|
||
appendonly no
|
||
appendfilename "appendonly.aof"
|
||
appendfsync everysec
|
||
no-appendfsync-on-rewrite no
|
||
auto-aof-rewrite-percentage 100
|
||
auto-aof-rewrite-min-size 64mb
|
||
# 密码(部署时替换,留空则无密码)
|
||
{{REDIS_PASSWORD_LINE}}', 0);
|
||
|
||
INSERT INTO app_params (template_id, param_key, label, type, placeholder, default_value, required, sort_order) VALUES
|
||
(@redis_id, 'REDIS_PASSWORD', 'Redis 密码', 'password', '留空则无密码', '', 0, 0),
|
||
(@redis_id, 'PORT', '宿主机端口', 'number', '6379', '6379', 1, 1);
|
||
|
||
|
||
-- ============================================================
|
||
-- 初始数据:MySQL 模板
|
||
-- ============================================================
|
||
INSERT INTO app_templates (app_key, name, tagline, description, icon, category, image, container_name, network, restart, hostname, workdir, command, sort_order, is_active)
|
||
VALUES ('mysql', 'MySQL', '关系型数据库',
|
||
'MySQL 是最流行的开源关系型数据库管理系统,支持事务、存储过程、触发器、视图等完整 SQL 功能。此模板基于 MySQL 8.4 LTS。',
|
||
'mysql', '数据库', 'mysql:8.4.11', 'mysql', '', 'always', 'mysql', '/', '', 2, 1);
|
||
|
||
SET @mysql_id = LAST_INSERT_ID();
|
||
|
||
INSERT INTO app_ports (template_id, host_port, container_port, protocol, sort_order) VALUES
|
||
(@mysql_id, '3306', '3306', 'tcp', 0);
|
||
|
||
INSERT INTO app_volumes (template_id, host_path, container_path, mode, sort_order) VALUES
|
||
(@mysql_id, '/opt/mysql/data', '/var/lib/mysql', 'rw', 0),
|
||
(@mysql_id, '/opt/mysql/conf/my.cnf', '/etc/my.cnf', 'rw', 1),
|
||
(@mysql_id, '/opt/mysql/log', '/var/log/mysql', 'rw', 2),
|
||
(@mysql_id, '/etc/timezone', '/etc/timezone', 'ro', 3),
|
||
(@mysql_id, '/etc/localtime', '/etc/localtime', 'ro', 4);
|
||
|
||
INSERT INTO app_envs (template_id, env_key, env_value, sort_order) VALUES
|
||
(@mysql_id, 'MYSQL_ROOT_PASSWORD', '{{MYSQL_ROOT_PASSWORD}}', 0);
|
||
|
||
INSERT INTO app_mkdirs (template_id, dir_path, sort_order) VALUES
|
||
(@mysql_id, '/opt/mysql/data', 0),
|
||
(@mysql_id, '/opt/mysql/conf', 1),
|
||
(@mysql_id, '/opt/mysql/log', 2);
|
||
|
||
INSERT INTO app_write_files (template_id, file_path, file_content, sort_order) VALUES
|
||
(@mysql_id, '/opt/mysql/conf/my.cnf',
|
||
'# MySQL 配置文件
|
||
[mysqld]
|
||
pid-file = /var/run/mysqld/mysqld.pid
|
||
socket = /var/run/mysqld/mysqld.sock
|
||
datadir = /var/lib/mysql
|
||
secure-file-priv= NULL
|
||
|
||
# 字符集
|
||
character-set-server = utf8mb4
|
||
collation-server = utf8mb4_unicode_ci
|
||
|
||
# 最大连接数
|
||
max_connections = 200
|
||
|
||
# Innodb
|
||
innodb_buffer_pool_size = 128M
|
||
innodb_log_file_size = 48M
|
||
innodb_flush_log_at_trx_commit = 1
|
||
|
||
# 日志
|
||
log-error = /var/log/mysql/error.log
|
||
slow_query_log = 1
|
||
slow_query_log_file = /var/log/mysql/slow.log
|
||
long_query_time = 2
|
||
|
||
# 端口
|
||
port = 3306
|
||
|
||
[client]
|
||
default-character-set = utf8mb4
|
||
|
||
[mysql]
|
||
default-character-set = utf8mb4', 0);
|
||
|
||
INSERT INTO app_params (template_id, param_key, label, type, placeholder, default_value, required, sort_order) VALUES
|
||
(@mysql_id, 'MYSQL_ROOT_PASSWORD', 'Root 密码', 'password', '设置 root 用户密码', '', 1, 0),
|
||
(@mysql_id, 'PORT', '宿主机端口', 'number', '3306', '3306', 1, 1);
|
||
|
||
|
||
-- ============================================================
|
||
-- 初始数据:Halo 模板
|
||
-- ============================================================
|
||
INSERT INTO app_templates (app_key, name, tagline, description, icon, category, image, container_name, network, restart, hostname, workdir, command, extra_args, sort_order, is_active)
|
||
VALUES ('halo', 'Halo', '强大易用的开源建站工具',
|
||
'Halo 是一款开源的建站工具,支持博客、CMS、企业官网等多种场景。内置主题管理、插件系统、多用户、SEO 等功能。社区版基于开源仓库构建,免费使用。',
|
||
'halo', '建站', 'registry.fit2cloud.com/halo/halo:2.26', 'halo', '', 'always', 'halo', '', '', '{{HALO_DB_ARGS}}', 3, 1);
|
||
|
||
SET @halo_id = LAST_INSERT_ID();
|
||
|
||
INSERT INTO app_ports (template_id, host_port, container_port, protocol, sort_order) VALUES
|
||
(@halo_id, '{{PORT}}', '8090', 'tcp', 0);
|
||
|
||
INSERT INTO app_volumes (template_id, host_path, container_path, mode, sort_order) VALUES
|
||
(@halo_id, '/opt/halo/data', '/root/.halo2', 'rw', 0);
|
||
|
||
INSERT INTO app_envs (template_id, env_key, env_value, sort_order) VALUES
|
||
(@halo_id, 'JVM_OPTS', '-Xmx{{JVM_MAX}} -Xms{{JVM_MIN}}', 0);
|
||
|
||
INSERT INTO app_mkdirs (template_id, dir_path, sort_order) VALUES
|
||
(@halo_id, '/opt/halo/data', 0);
|
||
|
||
INSERT INTO app_params (template_id, param_key, label, type, placeholder, default_value, required, options, show_when, sort_order) VALUES
|
||
(@halo_id, 'PORT', '宿主机端口', 'number', '8090', '8090', 1, NULL, NULL, 0),
|
||
(@halo_id, 'JVM_MAX', 'JVM 最大内存', 'text', '256m', '256m', 1, NULL, NULL, 1),
|
||
(@halo_id, 'JVM_MIN', 'JVM 初始内存', 'text', '256m', '256m', 1, NULL, NULL, 2),
|
||
(@halo_id, 'DB_TYPE', '数据库', 'select', 'H2 内置数据库', 'h2', 1, '[{"value":"h2","label":"H2 内置数据库(零配置)"},{"value":"mysql","label":"MySQL 外部数据库"}]', NULL, 3),
|
||
(@halo_id, 'DB_HOST', 'MySQL 地址', 'text', '127.0.0.1', '127.0.0.1', 0, NULL, 'DB_TYPE:mysql', 4),
|
||
(@halo_id, 'DB_PORT', 'MySQL 端口', 'number', '3306', '3306', 0, NULL, 'DB_TYPE:mysql', 5),
|
||
(@halo_id, 'DB_NAME', 'MySQL 库名', 'text', 'halodb', 'halodb', 0, NULL, 'DB_TYPE:mysql', 6),
|
||
(@halo_id, 'DB_USER', 'MySQL 用户名', 'text', 'root', 'root', 0, NULL, 'DB_TYPE:mysql', 7),
|
||
(@halo_id, 'DB_PASSWORD', 'MySQL 密码', 'password', '数据库密码', '', 0, NULL, 'DB_TYPE:mysql', 8);
|
||
|
||
-- Halo 的 extra_args ({{HALO_DB_ARGS}}) 由前端 tplWithDerived 函数动态解析,
|
||
-- 根据 DB_TYPE 参数自动生成 MySQL 连接环境变量或留空(H2 模式)
|
||
|
||
|
||
-- ============================================================
|
||
-- 客户端版本管理表
|
||
-- ============================================================
|
||
CREATE TABLE IF NOT EXISTS app_version (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
version VARCHAR(32) NOT NULL UNIQUE COMMENT '版本号 (如 v0.0.1)',
|
||
download_url VARCHAR(512) NOT NULL COMMENT '下载地址',
|
||
release_notes TEXT DEFAULT NULL COMMENT '更新说明',
|
||
is_latest TINYINT(1) DEFAULT 0 COMMENT '是否为最新版本 1=是 0=否',
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户端版本管理';
|
||
|
||
-- 初始版本数据:v0.0.1
|
||
INSERT INTO app_version (version, download_url, release_notes, is_latest, created_at)
|
||
VALUES ('v0.0.1', 'https://114.66.55.63:3001/download/wfj-panel-v0.0.1.exe',
|
||
'WFJ Panel 首个版本 v0.0.1
|
||
|
||
功能列表:
|
||
- SSH 远程服务器连接管理
|
||
- 服务器概览监控(CPU/内存/硬盘/网络/进程)
|
||
- 远程文件管理(上传/下载/新建/删除)
|
||
- 交互式终端(xterm.js)
|
||
- Docker 容器管理(概览/容器列表/镜像/应用商店/任务中心/配置/网络/卷)
|
||
- 应用商店一键部署(Redis/MySQL/Halo)
|
||
- 系统防火墙管理(firewalld/ufw/iptables)', 0, NOW());
|
||
|
||
-- v0.0.2
|
||
INSERT INTO app_version (version, download_url, release_notes, is_latest, created_at)
|
||
VALUES ('v0.0.2', 'https://114.66.55.63:3001/download/wfj-panel-v0.0.2.exe',
|
||
'WFJ Panel v0.0.2 更新
|
||
|
||
新增功能:
|
||
- 应用商店新增 Java 应用模板(支持选择 Java 版本、自定义启动命令、端口映射、路径可视化选择)
|
||
- 运行时类容器支持重复部署(自动生成不重复容器名)
|
||
- 应用商店参数新增 path 类型(远程目录浏览器选择宿主机路径)
|
||
|
||
问题修复:
|
||
- 修复任务中心显示占位符 {{CONTAINER_NAME}} 未替换的问题
|
||
- 修复端口映射容器端口占位符未替换导致部署失败的问题
|
||
- 修复 execDeploy 超时后 SSH stream 未销毁导致 channel 泄漏
|
||
- 修复 select 类型参数无默认值时部署按钮误判为必填项未填而置灰
|
||
- docker pull 超时从 5 分钟提升到 10 分钟
|
||
|
||
其他改进:
|
||
- 窗口标题由 SSH Panel 改为 WFJ Panel
|
||
- 登录页 LOGO 改为 WFJ Panel', 1, NOW());
|