优化安装脚本

This commit is contained in:
CN-JS-HuiBai
2026-04-05 15:23:08 +08:00
parent d7f8db89a3
commit 035ebd8d40
6 changed files with 181 additions and 23 deletions

View File

@@ -1,5 +1,5 @@
HOST=0.0.0.0
PORT=3000
PORT=3051
REFRESH_INTERVAL=5000
# Valkey/Redis Cache Configuration

View File

@@ -121,4 +121,122 @@ else
echo -e "Check logs with: ${BLUE}journalctl -u data-wall -xe${NC}"
fi
# 10. Reverse Proxy Configuration
echo -ne "${YELLOW}Do you want to configure a reverse proxy (Nginx/Caddy)? (y/n): ${NC}"
read -r CONF_PROXY
if [[ "$CONF_PROXY" =~ ^[Yy]$ ]]; then
echo -e "${BLUE}=== Reverse Proxy Configuration ===${NC}"
# Get Domain
echo -ne "Enter your domain name (e.g., monitor.example.com): "
read -r DOMAIN
if [ -z "$DOMAIN" ]; then
echo -e "${RED}Error: Domain cannot be empty. Skipping proxy configuration.${NC}"
else
# Get Port from .env
PORT=$(grep "^PORT=" .env | cut -d'=' -f2)
PORT=${PORT:-3000}
# Choose Proxy
echo -e "Select Proxy Type:"
echo -e " 1) Caddy (Automatic SSL, easy to use)"
echo -e " 2) Nginx (Advanced, manual SSL)"
echo -ne "Choose (1/2): "
read -r PROXY_TYPE
# Enable HTTPS?
echo -ne "Enable HTTPS (SSL)? (y/n): "
read -r ENABLE_HTTPS
if [ "$PROXY_TYPE" == "1" ]; then
# Caddy Config
CADDY_FILE="Caddyfile"
echo -e "${BLUE}Generating Caddyfile...${NC}"
if [[ "$ENABLE_HTTPS" =~ ^[Yy]$ ]]; then
cat <<EOF > "$CADDY_FILE"
$DOMAIN {
reverse_proxy localhost:$PORT
}
EOF
else
cat <<EOF > "$CADDY_FILE"
http://$DOMAIN {
reverse_proxy localhost:$PORT
}
EOF
fi
chown "$REAL_USER":"$REAL_USER" "$CADDY_FILE"
echo -e "${GREEN}Caddyfile generated at $PROJECT_DIR/$CADDY_FILE${NC}"
echo -e "${YELLOW}Tip: Ensure Caddy is installed and pointing to this file.${NC}"
elif [ "$PROXY_TYPE" == "2" ]; then
# Nginx Config
echo -ne "Enter Nginx configuration export path (default: ./${DOMAIN}.conf): "
read -r NGINX_PATH
NGINX_PATH=${NGINX_PATH:-"./${DOMAIN}.conf"}
echo -e "${BLUE}Generating Nginx configuration...${NC}"
if [[ "$ENABLE_HTTPS" =~ ^[Yy]$ ]]; then
echo -ne "Enter SSL Certificate Path: "
read -r SSL_CERT
echo -ne "Enter SSL Key Path: "
read -r SSL_KEY
cat <<EOF > "$NGINX_PATH"
server {
listen 80;
server_name $DOMAIN;
return 301 https://\$host\$request_uri;
}
server {
listen 443 ssl http2;
server_name $DOMAIN;
ssl_certificate $SSL_CERT;
ssl_certificate_key $SSL_KEY;
location / {
proxy_pass http://localhost:$PORT;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EOF
else
cat <<EOF > "$NGINX_PATH"
server {
listen 80;
server_name $DOMAIN;
location / {
proxy_pass http://localhost:$PORT;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EOF
fi
chown "$REAL_USER":"$REAL_USER" "$NGINX_PATH"
echo -e "${GREEN}Nginx config generated at $NGINX_PATH${NC}"
echo -e "${YELLOW}Tip: You can symlink this to /etc/nginx/sites-enabled/ to activate.${NC}"
else
echo -e "${YELLOW}Unknown proxy type selected. Skipping.${NC}"
fi
fi
fi
echo -e "${BLUE}================================================${NC}"
echo -e "${GREEN}Setup completed successfully!${NC}"

View File

@@ -395,9 +395,12 @@
style="padding: 10px 14px; background: var(--bg-input); border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-primary);">
<option value="dark">默认夜间模式</option>
<option value="light">默认白天模式</option>
<option value="auto">跟随浏览器/系统</option>
</select>
</div>
<div class="form-group" style="margin-top: 15px; display: flex; align-items: center; gap: 10px;">
<input type="checkbox" id="show95BandwidthInput" style="width: 18px; height: 18px; cursor: pointer;">
<label for="show95BandwidthInput" style="cursor: pointer; user-select: none;">24h趋势图默认显示 95计费线</label>
</div>
<div class="form-actions" style="margin-top: 25px; display: flex; justify-content: flex-end;">
<button class="btn btn-add" id="btnSaveSiteSettings">保存设置</button>
</div>

View File

@@ -48,6 +48,7 @@
logoText: document.getElementById('logoText'),
logoIconContainer: document.getElementById('logoIconContainer'),
defaultThemeInput: document.getElementById('defaultThemeInput'),
show95BandwidthInput: document.getElementById('show95BandwidthInput'),
// Auth & Theme elements
themeToggle: document.getElementById('themeToggle'),
sunIcon: document.querySelector('.sun-icon'),
@@ -218,6 +219,7 @@
dom.siteTitleInput.value = window.SITE_SETTINGS.title || '';
dom.logoUrlInput.value = window.SITE_SETTINGS.logo_url || '';
dom.defaultThemeInput.value = window.SITE_SETTINGS.default_theme || 'dark';
dom.show95BandwidthInput.checked = !!window.SITE_SETTINGS.show_95_bandwidth;
}
loadSiteSettings();
@@ -903,9 +905,19 @@
// Update inputs
dom.pageNameInput.value = settings.page_name || '';
dom.siteTitleInput.value = settings.title || '';
dom.logoUrlInput.value = settings.logo_url || '';
dom.defaultThemeInput.value = settings.default_theme || 'dark';
if (settings.title) dom.siteTitleInput.value = settings.title;
if (settings.logo_url) dom.logoUrlInput.value = settings.logo_url;
if (settings.default_theme) dom.defaultThemeInput.value = settings.default_theme;
if (settings.show_95_bandwidth !== undefined) {
dom.show95BandwidthInput.checked = !!settings.show_95_bandwidth;
if (networkChart) {
networkChart.showP95 = !!settings.show_95_bandwidth;
if (dom.legendP95) {
dom.legendP95.classList.toggle('disabled', !networkChart.showP95);
}
networkChart.draw();
}
}
// Apply to UI
applySiteSettings(settings);
@@ -957,6 +969,17 @@
</svg>
`;
}
// P95 setting
if (settings.show_95_bandwidth !== undefined) {
if (networkChart) {
networkChart.showP95 = !!settings.show_95_bandwidth;
if (dom.legendP95) {
dom.legendP95.classList.toggle('disabled', !networkChart.showP95);
}
networkChart.draw();
}
}
}
async function saveSiteSettings() {
@@ -970,7 +993,8 @@
page_name: dom.pageNameInput.value.trim(),
title: dom.siteTitleInput.value.trim(),
logo_url: dom.logoUrlInput.value.trim(),
default_theme: dom.defaultThemeInput.value
default_theme: dom.defaultThemeInput.value,
show_95_bandwidth: dom.show95BandwidthInput.checked ? 1 : 0
};
dom.btnSaveSiteSettings.disabled = true;

View File

@@ -36,6 +36,15 @@ async function checkAndFixDatabase() {
}
console.log(`[Database Integrity] ✅ Missing tables created.`);
}
// Check for new columns in site_settings
const [columns] = await db.query("SHOW COLUMNS FROM site_settings");
const columnNames = columns.map(c => c.Field);
if (!columnNames.includes('show_95_bandwidth')) {
console.log(`[Database Integrity] ⚠️ Missing column 'show_95_bandwidth' in 'site_settings'. Adding it...`);
await db.query("ALTER TABLE site_settings ADD COLUMN show_95_bandwidth TINYINT(1) DEFAULT 0 AFTER default_theme");
console.log(`[Database Integrity] ✅ Column 'show_95_bandwidth' added.`);
}
} catch (err) {
console.error('[Database Integrity] ❌ Error checking integrity:', err.message);
}
@@ -75,12 +84,13 @@ async function createTable(tableName) {
title VARCHAR(255) DEFAULT '数据可视化展示大屏',
logo_url TEXT,
default_theme VARCHAR(20) DEFAULT 'dark',
show_95_bandwidth TINYINT(1) DEFAULT 0,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
`);
await db.query(`
INSERT IGNORE INTO site_settings (id, page_name, title, default_theme)
VALUES (1, '数据可视化展示大屏', '数据可视化展示大屏', 'dark')
INSERT IGNORE INTO site_settings (id, page_name, title, default_theme, show_95_bandwidth)
VALUES (1, '数据可视化展示大屏', '数据可视化展示大屏', 'dark', 0)
`);
break;
case 'traffic_stats':

View File

@@ -216,12 +216,13 @@ app.post('/api/setup/init', async (req, res) => {
title VARCHAR(255) DEFAULT '数据可视化展示大屏',
logo_url TEXT,
default_theme VARCHAR(20) DEFAULT 'dark',
show_95_bandwidth TINYINT(1) DEFAULT 0,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
`);
await connection.query(`
INSERT IGNORE INTO site_settings (id, page_name, title, default_theme)
VALUES (1, '数据可视化展示大屏', '数据可视化展示大屏', 'dark')
INSERT IGNORE INTO site_settings (id, page_name, title, default_theme, show_95_bandwidth)
VALUES (1, '数据可视化展示大屏', '数据可视化展示大屏', 'dark', 0)
`);
await connection.end();
@@ -487,7 +488,8 @@ app.get('/api/settings', async (req, res) => {
return res.json({
page_name: '数据可视化展示大屏',
title: '数据可视化展示大屏',
logo_url: null
logo_url: null,
show_95_bandwidth: 0
});
}
res.json(rows[0]);
@@ -499,18 +501,19 @@ app.get('/api/settings', async (req, res) => {
// Update site settings
app.post('/api/settings', requireAuth, async (req, res) => {
const { page_name, title, logo_url, default_theme } = req.body;
try {
await db.query(
`INSERT INTO site_settings (id, page_name, title, logo_url, default_theme)
VALUES (1, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
page_name = VALUES(page_name),
title = VALUES(title),
logo_url = VALUES(logo_url),
default_theme = VALUES(default_theme)`,
[page_name, title, logo_url, default_theme]
);
const { page_name, title, logo_url, default_theme, show_95_bandwidth } = req.body;
try {
await db.query(
`INSERT INTO site_settings (id, page_name, title, logo_url, default_theme, show_95_bandwidth)
VALUES (1, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
page_name = VALUES(page_name),
title = VALUES(title),
logo_url = VALUES(logo_url),
default_theme = VALUES(default_theme),
show_95_bandwidth = VALUES(show_95_bandwidth)`,
[page_name, title, logo_url, default_theme, show_95_bandwidth ? 1 : 0]
);
res.json({ success: true });
} catch (err) {
console.error('Error updating settings:', err);