From dd3b367bcd63a3422cc19d2b4cb0b8de4bc6efd5 Mon Sep 17 00:00:00 2001 From: dqzboy Date: Tue, 23 Jul 2024 20:21:59 +0800 Subject: [PATCH] feat: Add instructions for obtaining proxy acceleration to the UI panel. --- Dockerfile | 15 + hubcmdui/.DS_Store | Bin 0 -> 6148 bytes hubcmdui/README.md | 120 +++++ hubcmdui/config.json | 0 hubcmdui/package.json | 6 + hubcmdui/server.js | 140 ++++++ hubcmdui/users.json | 8 + hubcmdui/web/admin.html | 427 ++++++++++++++++++ .../web/index.html | 46 +- 9 files changed, 759 insertions(+), 3 deletions(-) create mode 100644 Dockerfile create mode 100644 hubcmdui/.DS_Store create mode 100644 hubcmdui/README.md create mode 100644 hubcmdui/config.json create mode 100644 hubcmdui/package.json create mode 100644 hubcmdui/server.js create mode 100644 hubcmdui/users.json create mode 100644 hubcmdui/web/admin.html rename HubCmdUI/docker-proxy.html => hubcmdui/web/index.html (84%) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c1e2e42 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +# 使用官方的 Node.js 运行时镜像作为基础镜像 +FROM node:lts-alpine + +# 设置工作目录 +WORKDIR /app +# 复制项目文件到工作目录 +COPY hubcmdui/ . +# 安装项目依赖 +RUN npm install + +# 暴露应用程序的端口 +EXPOSE 3000 + +# 运行应用程序 +CMD ["node", "server.js"] \ No newline at end of file diff --git a/hubcmdui/.DS_Store b/hubcmdui/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..198b05daa4747d624d8a55c7e5919b36d034bdbb GIT binary patch literal 6148 zcmeHKK}y6x5UkccEPC0a$9aL^4?ZC0 zL8_ssc0Bbkh39tY#r#s@w!_@rTePVkxV?;Wi@rYww;U3rMC)M94oO^&Z zZqVU!o8PVbi&cNS;&}Di9Tqq9IrV0%6N<&{%$F#KHHnH+Knm + 中文 | English +

+ +
+

+ +
+ Docker-Proxy 镜像代理加速快速获取命令UI面板. +

+
+ +
+ +[![Auth](https://img.shields.io/badge/Auth-dqzboy-ff69b4)](https://github.com/dqzboy) +[![GitHub contributors](https://img.shields.io/github/contributors/dqzboy/Docker-Proxy)](https://github.com/dqzboy/Docker-Proxy/graphs/contributors) +[![GitHub Issues](https://img.shields.io/github/issues/dqzboy/Docker-Proxy.svg)](https://github.com/dqzboy/Docker-Proxy/issues) +[![GitHub Pull Requests](https://img.shields.io/github/stars/dqzboy/Docker-Proxy)](https://github.com/dqzboy/Docker-Proxy) +[![HitCount](https://views.whatilearened.today/views/github/dqzboy/Docker-Proxy.svg)](https://github.com/dqzboy/Docker-Proxy) +[![GitHub license](https://img.shields.io/github/license/dqzboy/Docker-Proxy)](https://github.com/dqzboy/Docker-Proxy/blob/main/LICENSE) + + +📢 Docker Proxy-交流群 + +
+ +--- + +## 📝 本地运行 +#### 1. 克隆项目 +```bash +git clone git@github.com:dqzboy/Docker-Proxy.git +``` + +#### 2. 安装依赖 +```bash +cd Docker-Proxy/hubcmdui +npm install +``` + +#### 3. 启动服务 +```bash +node server.js +``` + +## 📦 Docker运行 + +- 如果不自行构建Docker镜像,可直接跳转第三步拉取镜像运行 + +#### 1. 克隆项目(可选) +```bash +git clone git@github.com:dqzboy/Docker-Proxy.git +``` + +#### 2. 构建镜像(可选) +```bash +cd Docker-Proxy + +docker build -t hubcmd-ui . +``` + +#### 3. 运行容器 +```bash +# 拉取镜像!如果你手动构建了镜像此步骤跳过 +docker pull dqzboy/hubcmd-ui:latest + +docker run -d -p 3000:3000 --name hubcmdui-server hubcmd-ui +``` + +--- + +## UI + +- 默认监听3000端口 + +> 浏览器输入 `服务器地址:3000` 访问前端 + + + + + +
+ +> 浏览器输入 `服务器地址/admin:3000` 访问后端页面 + + + + + +
+ + + + + +
+ +--- + +## 🫶 赞助 +如果你觉得这个项目对你有帮助,请给我点个Star。并且情况允许的话,可以给我一点点支持,总之非常感谢支持😊 + +> 项目作者自建公益服务:[服务地址查看](https://uk.dqzboy.xyz/) + + + + + + + + + + +
Alipay WeChat Pay
+ +--- + +## 😺 其他 + +开源不易,若你参考此项目或基于此项目修改可否麻烦在你的项目文档中标识此项目?谢谢你! \ No newline at end of file diff --git a/hubcmdui/config.json b/hubcmdui/config.json new file mode 100644 index 0000000..e69de29 diff --git a/hubcmdui/package.json b/hubcmdui/package.json new file mode 100644 index 0000000..fe22126 --- /dev/null +++ b/hubcmdui/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "express": "^4.19.2", + "express-session": "^1.18.0" + } +} diff --git a/hubcmdui/server.js b/hubcmdui/server.js new file mode 100644 index 0000000..2756a54 --- /dev/null +++ b/hubcmdui/server.js @@ -0,0 +1,140 @@ +// server.js +const express = require('express'); +const fs = require('fs').promises; +const path = require('path'); +const bodyParser = require('body-parser'); +const session = require('express-session'); + +const app = express(); +app.use(express.json()); +app.use(express.static('web')); +app.use(bodyParser.urlencoded({ extended: true })); +app.use(session({ + secret: 'OhTq3faqSKoxbV%NJV', + resave: false, + saveUninitialized: true, + cookie: { secure: false } // 设置为true如果使用HTTPS +})); + +app.get('/admin', (req, res) => { + res.sendFile(path.join(__dirname, 'web', 'admin.html')); +}); + +const CONFIG_FILE = path.join(__dirname, 'config.json'); +const USERS_FILE = path.join(__dirname, 'users.json'); + +// 读取配置 +async function readConfig() { + try { + const data = await fs.readFile(CONFIG_FILE, 'utf8'); + return JSON.parse(data); + } catch (error) { + if (error.code === 'ENOENT') { + return { + logo: '', + menuItems: [], + adImage: { url: '', link: '' } + }; + } + throw error; + } +} + +// 写入配置 +async function writeConfig(config) { + await fs.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf8'); +} + +// 读取用户 +async function readUsers() { + try { + const data = await fs.readFile(USERS_FILE, 'utf8'); + return JSON.parse(data); + } catch (error) { + if (error.code === 'ENOENT') { + return { + users: [{ username: 'root', password: 'admin' }] + }; + } + throw error; + } +} + +// 写入用户 +async function writeUsers(users) { + await fs.writeFile(USERS_FILE, JSON.stringify(users, null, 2), 'utf8'); +} + +// 登录验证 +app.post('/api/login', async (req, res) => { + const { username, password } = req.body; + const users = await readUsers(); + const user = users.users.find(u => u.username === username && u.password === password); + if (user) { + req.session.user = user; + res.json({ success: true }); + } else { + res.status(401).json({ error: 'Invalid credentials' }); + } +}); + +// 修改密码 +app.post('/api/change-password', async (req, res) => { + if (!req.session.user) { + return res.status(401).json({ error: 'Not logged in' }); + } + const { currentPassword, newPassword } = req.body; + const users = await readUsers(); + const user = users.users.find(u => u.username === req.session.user.username); + if (user && user.password === currentPassword) { + user.password = newPassword; + await writeUsers(users); + res.json({ success: true }); + } else { + res.status(401).json({ error: 'Invalid current password' }); + } +}); + +// 需要登录验证的中间件 +function requireLogin(req, res, next) { + if (req.session.user) { + next(); + } else { + res.status(401).json({ error: 'Not logged in' }); + } +} + +// API 端点:获取配置 +app.get('/api/config', requireLogin, async (req, res) => { + try { + const config = await readConfig(); + res.json(config); + } catch (error) { + res.status(500).json({ error: 'Failed to read config' }); + } +}); + +// API 端点:保存配置 +app.post('/api/config', requireLogin, async (req, res) => { + try { + await writeConfig(req.body); + res.json({ success: true }); + } catch (error) { + res.status(500).json({ error: 'Failed to save config' }); + } +}); + +// API 端点:检查会话状态 +app.get('/api/check-session', (req, res) => { + if (req.session.user) { + res.json({ success: true }); + } else { + res.status(401).json({ error: 'Not logged in' }); + } +}); + +// 启动服务器 +const PORT = process.env.PORT || 3000; +app.listen(PORT, () => { + console.log(`Server is running on http://localhost:${PORT}`); +}); \ No newline at end of file diff --git a/hubcmdui/users.json b/hubcmdui/users.json new file mode 100644 index 0000000..8759e56 --- /dev/null +++ b/hubcmdui/users.json @@ -0,0 +1,8 @@ +{ + "users": [ + { + "username": "root", + "password": "admin" + } + ] +} \ No newline at end of file diff --git a/hubcmdui/web/admin.html b/hubcmdui/web/admin.html new file mode 100644 index 0000000..d666541 --- /dev/null +++ b/hubcmdui/web/admin.html @@ -0,0 +1,427 @@ + + + + + + Docker 镜像代理加速 - 管理面板 + + + + + + + + + + + \ No newline at end of file diff --git a/HubCmdUI/docker-proxy.html b/hubcmdui/web/index.html similarity index 84% rename from HubCmdUI/docker-proxy.html rename to hubcmdui/web/index.html index 008cfc6..e51e7d6 100644 --- a/HubCmdUI/docker-proxy.html +++ b/hubcmdui/web/index.html @@ -247,7 +247,7 @@ @@ -268,6 +268,8 @@ // 设置当前年份 document.getElementById('currentYear').textContent = new Date().getFullYear(); + let proxyDomain = 'your_domain'; // 默认代理加速地址 + // 生成加速命令 function generateCommands() { const imageInput = document.getElementById('imageInput').value.trim(); @@ -275,8 +277,6 @@ alert('请输入 Docker 镜像'); return; } - // docker镜像加速地址,请把下面your_domain改为你实际的加速地址 - const proxyDomain = 'your_domain'; //例如:hub.baidu.com let [imageName, tag] = imageInput.split(':'); tag = tag || 'latest'; @@ -333,6 +333,46 @@ behavior: 'smooth' }); } + + // 获取并加载配置 + async function loadConfig() { + try { + const response = await fetch('/api/config'); + const config = await response.json(); + if (config.logo) { + document.querySelector('.logo').src = config.logo; + } + if (config.menuItems && Array.isArray(config.menuItems)) { + const navMenu = document.querySelector('.nav-menu'); + navMenu.innerHTML = ''; // 清空菜单 + config.menuItems.forEach(item => { + const a = document.createElement('a'); + a.href = item.link; + a.textContent = item.text; + if (item.newTab) { + a.target = '_blank'; + } + navMenu.appendChild(a); + }); + } + if (config.adImage && config.adImage.url) { + const adContainer = document.getElementById('adContainer'); + const adLink = adContainer.querySelector('a'); + const adImage = adContainer.querySelector('img'); + adLink.href = config.adImage.link; + adImage.src = config.adImage.url; + adImage.alt = config.adImage.alt || '广告图片'; + adContainer.style.display = 'flex'; + } + if (config.proxyDomain) { + proxyDomain = config.proxyDomain; + } + } catch (error) { + console.error('加载配置失败:', error); + } + } + + loadConfig(); \ No newline at end of file