Files
asset_assistant/frontend/create.py
2025-11-12 16:44:02 +08:00

93 lines
19 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
from pathlib import Path
# 定义项目根目录(脚本所在目录下的 asset-assistant-system
PROJECT_ROOT = Path(__file__).parent / "asset-assistant-system"
# 定义需要创建的目录列表
DIRECTORIES = [
"dist",
"src/assets/css",
"src/assets/css/components",
"src/assets/js/config",
"src/assets/js/core",
"src/assets/js/components",
"src/assets/icons",
"src/pages/modules",
"src/template"
]
# 定义需要创建的文件列表(路径: 文件初始内容)
FILES = {
# CSS 文件
"src/assets/css/dark-theme.css": "/* 暗夜模式主题样式 */\nbody.dark-theme {\n background-color: #1e1e1e;\n color: #f5f5f5;\n}\n",
"src/assets/css/common.css": "/* 通用样式 */\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n font-family: 'Arial', sans-serif;\n}\n\n.container {\n width: 100%;\n max-width: 1200px;\n margin: 0 auto;\n padding: 0 20px;\n}\n",
# JS 配置文件
"src/assets/js/config/menu.js": "/* 菜单配置 */\nexport const menuConfig = [\n {\n path: '/dashboard',\n name: '数据概览',\n icon: 'dashboard',\n auth: true\n },\n {\n path: '/asset-list',\n name: '资产列表',\n icon: 'assets',\n auth: true\n }\n];\n",
"src/assets/js/config/theme.js": "/* 主题配置 */\nexport const themeConfig = {\n defaultTheme: 'light',\n darkThemeClass: 'dark-theme',\n themeStorageKey: 'asset_system_theme'\n};\n",
"src/assets/js/config/system.js": "/* 系统配置 */\nexport const systemConfig = {\n appName: '资产辅助系统',\n version: '1.0.0',\n baseUrl: '/',\n timeout: 5000\n};\n",
# JS 核心功能
"src/assets/js/core/auth.js": "/* 权限验证 */\nimport { systemConfig } from '../config/system.js';\n\nexport const Auth = {\n // 检查是否登录\n isLogin() {\n return localStorage.getItem('token') !== null;\n },\n // 登录\n login(token) {\n localStorage.setItem('token', token);\n },\n // 退出登录\n logout() {\n localStorage.removeItem('token');\n window.location.href = `${systemConfig.baseUrl}login.html`;\n }\n};\n",
"src/assets/js/core/loader.js": "/* 加载器 */\nexport const Loader = {\n show() {\n const loader = document.createElement('div');\n loader.id = 'app-loader';\n loader.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(255,255,255,0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 9999;\n `;\n loader.innerHTML = '<div>加载中...</div>';\n document.body.appendChild(loader);\n },\n hide() {\n const loader = document.getElementById('app-loader');\n if (loader) loader.remove();\n }\n};\n",
"src/assets/js/core/message.js": "/* 消息提示 */\nexport const Message = {\n success(content) {\n this.showMessage(content, 'success');\n },\n error(content) {\n this.showMessage(content, 'error');\n },\n showMessage(content, type) {\n const message = document.createElement('div');\n message.style.cssText = `\n position: fixed;\n top: 20px;\n right: 20px;\n padding: 10px 20px;\n border-radius: 4px;\n color: white;\n z-index: 9998;\n transition: all 0.3s;\n `;\n message.style.backgroundColor = type === 'success' ? '#4CAF50' : '#f44336';\n message.textContent = content;\n document.body.appendChild(message);\n setTimeout(() => message.remove(), 3000);\n }\n};\n",
"src/assets/js/core/router.js": "/* 路由管理 */\nimport { Auth } from './auth.js';\nimport { systemConfig } from '../config/system.js';\n\nexport const Router = {\n // 跳转页面\n push(path) {\n // 验证权限\n if (path !== '/login' && !Auth.isLogin()) {\n window.location.href = `${systemConfig.baseUrl}login.html`;\n return;\n }\n window.location.href = `${systemConfig.baseUrl}${path.startsWith('/') ? path.slice(1) : path}`;\n },\n // 获取当前路径\n getCurrentPath() {\n return window.location.pathname.replace(systemConfig.baseUrl, '');\n }\n};\n",
# JS 组件
"src/assets/js/components/sidebar.js": "/* 侧边栏组件 */\nimport { menuConfig } from '../config/menu.js';\nimport { Router } from '../core/router.js';\n\nexport function renderSidebar() {\n const sidebar = document.createElement('div');\n sidebar.className = 'sidebar';\n \n // 渲染菜单\n const menuHtml = menuConfig.map(item => `\n <div class=\"menu-item\" onclick=\"Router.push('${item.path}')\">\n <i class=\"icon-${item.icon}\"></i>\n <span>${item.name}</span>\n </div>\n `).join('');\n \n sidebar.innerHTML = menuHtml;\n return sidebar;\n}\n",
"src/assets/js/components/header.js": "/* 顶部导航组件 */\nimport { systemConfig } from '../config/system.js';\nimport { Auth } from '../core/auth.js';\nimport { themeConfig } from '../config/theme.js';\n\nexport function renderHeader() {\n const header = document.createElement('div');\n header.className = 'header';\n \n header.innerHTML = `\n <div class=\"app-name\">${systemConfig.appName}</div>\n <div class=\"header-actions\">\n <button onclick=\"toggleTheme()\">切换主题</button>\n <button onclick=\"Auth.logout()\">退出登录</button>\n </div>\n `;\n \n return header;\n}\n\n// 主题切换函数\nfunction toggleTheme() {\n const body = document.body;\n if (body.classList.contains(themeConfig.darkThemeClass)) {\n body.classList.remove(themeConfig.darkThemeClass);\n localStorage.setItem(themeConfig.themeStorageKey, 'light');\n } else {\n body.classList.add(themeConfig.darkThemeClass);\n localStorage.setItem(themeConfig.themeStorageKey, 'dark');\n }\n}\n",
"src/assets/js/components/loading.js": "/* 加载动画组件 */\nexport function renderLoading() {\n const loading = document.createElement('div');\n loading.className = 'loading';\n loading.innerHTML = `\n <div class=\"spinner\"></div>\n <div class=\"loading-text\">加载中...</div>\n `;\n return loading;\n}\n",
# 应用入口
"src/assets/js/app.js": "/* 应用入口 */\nimport { renderHeader } from './components/header.js';\nimport { renderSidebar } from './components/sidebar.js';\nimport { Auth } from './core/auth.js';\nimport { Router } from './core/router.js';\nimport { themeConfig } from './config/theme.js';\n\n// 初始化应用\nfunction initApp() {\n // 检查登录状态\n if (!Auth.isLogin() && window.location.pathname.indexOf('login.html') === -1) {\n Router.push('/login.html');\n return;\n }\n \n // 初始化主题\n initTheme();\n \n // 渲染公共组件(非登录页)\n if (window.location.pathname.indexOf('login.html') === -1) {\n renderCommonComponents();\n }\n}\n\n// 初始化主题\nfunction initTheme() {\n const savedTheme = localStorage.getItem(themeConfig.themeStorageKey) || themeConfig.defaultTheme;\n if (savedTheme === 'dark') {\n document.body.classList.add(themeConfig.darkThemeClass);\n }\n}\n\n// 渲染公共组件(头部和侧边栏)\nfunction renderCommonComponents() {\n const header = renderHeader();\n const sidebar = renderSidebar();\n \n document.body.appendChild(header);\n document.body.appendChild(sidebar);\n \n // 创建主内容区域\n const mainContent = document.createElement('div');\n mainContent.className = 'main-content';\n document.body.appendChild(mainContent);\n}\n\n// 页面加载完成后初始化\nwindow.addEventListener('DOMContentLoaded', initApp);\n",
# HTML 页面
"src/pages/login.html": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>资产辅助系统 - 登录</title>\n <link rel=\"stylesheet\" href=\"../assets/css/common.css\">\n <link rel=\"stylesheet\" href=\"../assets/css/dark-theme.css\">\n</head>\n<body>\n <div class=\"container\">\n <div class=\"login-form\">\n <h2>资产辅助系统</h2>\n <div class=\"form-group\">\n <label>用户名</label>\n <input type=\"text\" id=\"username\" placeholder=\"请输入用户名\">\n </div>\n <div class=\"form-group\">\n <label>密码</label>\n <input type=\"password\" id=\"password\" placeholder=\"请输入密码\">\n </div>\n <button onclick=\"handleLogin()\">登录</button>\n </div>\n </div>\n\n <script type=\"module\">\n import { Auth } from '../assets/js/core/auth.js';\n import { Router } from '../assets/js/core/router.js';\n import { Message } from '../assets/js/core/message.js';\n\n function handleLogin() {\n const username = document.getElementById('username').value;\n const password = document.getElementById('password').value;\n\n if (!username || !password) {\n Message.error('用户名和密码不能为空');\n return;\n }\n\n // 模拟登录验证\n if (username === 'admin' && password === '123456') {\n Auth.login('mock-token-123456');\n Message.success('登录成功');\n setTimeout(() => Router.push('index.html'), 1000);\n } else {\n Message.error('用户名或密码错误');\n }\n }\n </script>\n</body>\n</html>",
"src/pages/index.html": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>资产辅助系统 - 主页</title>\n <link rel=\"stylesheet\" href=\"../assets/css/common.css\">\n <link rel=\"stylesheet\" href=\"../assets/css/dark-theme.css\">\n <style>\n .header { height: 60px; background: #2c3e50; color: white; display: flex; align-items: center; justify-content: space-between; padding: 0 20px; }\n .sidebar { width: 200px; height: calc(100vh - 60px); background: #34495e; position: fixed; left: 0; top: 60px; }\n .menu-item { color: white; padding: 15px 20px; cursor: pointer; transition: background 0.3s; }\n .menu-item:hover { background: #2c3e50; }\n .main-content { margin-left: 200px; padding: 20px; min-height: calc(100vh - 60px); }\n </style>\n</head>\n<body>\n <!-- 公共组件会通过 app.js 自动渲染 -->\n <div class=\"main-content\">\n <h1>欢迎使用资产辅助系统</h1>\n <p>请选择左侧菜单进行操作</p>\n </div>\n\n <script type=\"module\" src=\"../assets/js/app.js\"></script>\n</body>\n</html>",
"src/pages/modules/dashboard.html": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>数据概览 - 资产辅助系统</title>\n <link rel=\"stylesheet\" href=\"../../assets/css/common.css\">\n <link rel=\"stylesheet\" href=\"../../assets/css/dark-theme.css\">\n <style>\n .dashboard-cards { display: flex; gap: 20px; margin-top: 20px; }\n .card { flex: 1; padding: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }\n .dark-theme .card { background: #2c3e50; color: white; }\n </style>\n</head>\n<body>\n <div class=\"main-content\">\n <h2>数据概览</h2>\n <div class=\"dashboard-cards\">\n <div class=\"card\">\n <h3>总资产数</h3>\n <p>1,286</p>\n </div>\n <div class=\"card\">\n <h3>在线设备</h3>\n <p>952</p>\n </div>\n <div class=\"card\">\n <h3>待处理工单</h3>\n <p>36</p>\n </div>\n </div>\n </div>\n\n <script type=\"module\" src=\"../../assets/js/app.js\"></script>\n</body>\n</html>",
"src/pages/modules/asset-list.html": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>资产列表 - 资产辅助系统</title>\n <link rel=\"stylesheet\" href=\"../../assets/css/common.css\">\n <link rel=\"stylesheet\" href=\"../../assets/css/dark-theme.css\">\n <style>\n .asset-table { width: 100%; border-collapse: collapse; margin-top: 20px; }\n .asset-table th, .asset-table td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }\n .dark-theme .asset-table th, .dark-theme .asset-table td { border-bottom-color: #34495e; }\n .asset-table th { background: #f5f5f5; }\n .dark-theme .asset-table th { background: #34495e; }\n .btn { padding: 6px 12px; border: none; border-radius: 4px; cursor: pointer; }\n .btn-detail { background: #3498db; color: white; }\n </style>\n</head>\n<body>\n <div class=\"main-content\">\n <h2>资产列表</h2>\n <table class=\"asset-table\">\n <thead>\n <tr>\n <th>资产ID</th>\n <th>资产名称</th>\n <th>资产类型</th>\n <th>状态</th>\n <th>操作</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td>ASSET-001</td>\n <td>服务器-Web01</td>\n <td>服务器</td>\n <td>运行中</td>\n <td><button class=\"btn btn-detail\" onclick=\"goToDetail('ASSET-001')\">查看详情</button></td>\n </tr>\n <tr>\n <td>ASSET-002</td>\n <td>交换机-SW02</td>\n <td>网络设备</td>\n <td>运行中</td>\n <td><button class=\"btn btn-detail\" onclick=\"goToDetail('ASSET-002')\">查看详情</button></td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <script type=\"module\">\n import { Router } from '../../assets/js/core/router.js';\n window.goToDetail = function(assetId) {\n Router.push(`asset-detail.html?id=${assetId}`);\n }\n </script>\n <script type=\"module\" src=\"../../assets/js/app.js\"></script>\n</body>\n</html>",
"src/pages/modules/asset-detail.html": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>资产详情 - 资产辅助系统</title>\n <link rel=\"stylesheet\" href=\"../../assets/css/common.css\">\n <link rel=\"stylesheet\" href=\"../../assets/css/dark-theme.css\">\n <style>\n .asset-detail { margin-top: 20px; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }\n .dark-theme .asset-detail { background: #2c3e50; }\n .detail-item { margin-bottom: 15px; display: flex; }\n .detail-label { width: 120px; font-weight: bold; }\n .btn-back { margin-top: 20px; padding: 8px 16px; background: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer; }\n </style>\n</head>\n<body>\n <div class=\"main-content\">\n <h2>资产详情</h2>\n <div class=\"asset-detail\">\n <div class=\"detail-item\">\n <div class=\"detail-label\">资产ID</div>\n <div id=\"asset-id\">--</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">资产名称:</div>\n <div id=\"asset-name\">--</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">资产类型:</div>\n <div id=\"asset-type\">--</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">购买日期:</div>\n <div>2024-01-15</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">状态:</div>\n <div style=\"color: #27ae60;\">运行中</div>\n </div>\n </div>\n <button class=\"btn-back\" onclick=\"goBack()\">返回列表</button>\n </div>\n\n <script type=\"module\">\n import { Router } from '../../assets/js/core/router.js';\n\n // 获取资产ID参数\n function getAssetId() {\n const params = new URLSearchParams(window.location.search);\n return params.get('id') || '';\n }\n\n // 初始化详情数据\n function initDetail() {\n const assetId = getAssetId();\n if (!assetId) return;\n\n document.getElementById('asset-id').textContent = assetId;\n \n // 模拟根据ID获取资产名称和类型\n const assetMap = {\n 'ASSET-001': { name: '服务器-Web01', type: '服务器' },\n 'ASSET-002': { name: '交换机-SW02', type: '网络设备' }\n };\n\n const asset = assetMap[assetId] || { name: '未知资产', type: '未知类型' };\n document.getElementById('asset-name').textContent = asset.name;\n document.getElementById('asset-type').textContent = asset.type;\n }\n\n function goBack() {\n Router.push('asset-list.html');\n }\n\n // 初始化\n initDetail();\n </script>\n <script type=\"module\" src=\"../../assets/js/app.js\"></script>\n</body>\n</html>",
# 根目录文件
".gitignore": "# 依赖\nnode_modules/\n.pnp/\n.pnp.js\n\n# 构建产物\ndist/\n\n# 环境变量\n.env\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\n# 日志\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# 编辑器配置\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# 操作系统文件\n.DS_Store\nThumbs.db",
"index.html": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>资产辅助系统</title>\n <!-- 自动跳转到登录页 -->\n <meta http-equiv=\"refresh\" content=\"0;url=src/pages/login.html\">\n</head>\n<body>\n <p>正在跳转到登录页... 如果没有自动跳转,请<a href=\"src/pages/login.html\">点击这里</a></p>\n</body>\n</html>",
"package.json": "{\n \"name\": \"asset-assistant-system\",\n \"version\": \"1.0.0\",\n \"description\": \"资产辅助管理系统\",\n \"main\": \"index.html\",\n \"scripts\": {\n \"dev\": \"serve\",\n \"build\": \"echo '构建脚本待实现'\",\n \"test\": \"echo '测试脚本待实现'\"\n },\n \"keywords\": [\"asset\", \"management\", \"system\"],\n \"author\": \"\",\n \"license\": \"MIT\",\n \"devDependencies\": {\n \"serve\": \"^14.2.3\"\n }\n}"
}
def create_project_structure():
"""创建项目目录结构和文件"""
try:
# 1. 创建根目录
PROJECT_ROOT.mkdir(exist_ok=True)
print(f"✅ 创建项目根目录: {PROJECT_ROOT}")
# 2. 创建所有子目录
for dir_path in DIRECTORIES:
full_dir_path = PROJECT_ROOT / dir_path
full_dir_path.mkdir(parents=True, exist_ok=True)
print(f"✅ 创建目录: {full_dir_path}")
# 3. 创建所有文件并写入初始内容
for file_path, content in FILES.items():
full_file_path = PROJECT_ROOT / file_path
# 确保文件所在目录存在(防止遗漏)
full_file_path.parent.mkdir(parents=True, exist_ok=True)
# 写入文件内容
with open(full_file_path, 'w', encoding='utf-8') as f:
f.write(content)
print(f"✅ 创建文件: {full_file_path}")
print("\n🎉 项目结构创建完成!")
print(f"📁 项目路径: {PROJECT_ROOT}")
print("\n💡 后续操作建议:")
print(" 1. 进入项目目录: cd asset-assistant-system")
print(" 2. 安装依赖: npm install")
print(" 3. 启动开发服务器: npm run dev")
print(" 4. 访问: http://localhost:3000")
except Exception as e:
print(f"\n❌ 创建项目结构时出错: {e}")
if __name__ == "__main__":
create_project_structure()