UNPKG

bytefun

Version:

一个打通了原型设计、UI设计与代码转换、跨平台原生代码开发等的平台

1,815 lines (1,575 loc) 96 kB
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>32号旅游APP 后端API管理系统</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } :root { --bg-primary: #1B1B1B; --bg-secondary: #232323; --bg-tertiary: #2C2C2C; --bg-four: #323232; --text-primary: #FFFFFF; --text-secondary: #8E8E93; --border-color: #2C2C2C; --border-hover-color: #4D4D4D; --input-bg: #232323; --success-color: #34C759; --warning-color: #FF9500; --error-color: #67211d; --error-hover-color: #8a2420; --primary-color: #303d4b; --primary-hover-color: #485b70; } [data-theme="light"] { --bg-primary: #FDFDFD; --bg-secondary: #F5F5F5; --bg-tertiary: #E8E8E8; --bg-four: #e4e4e4; --bg-text: #E8E8E8; --text-primary: #1C1C1E; --text-secondary: #6D6D70; --border-color: #D1D1D6; --border-hover-color: #cdcdd2; --input-bg: #FFFFFF; } body { font-family: 'Poppins', 'Arial', sans-serif; background-color: var(--bg-primary); color: var(--text-primary); line-height: 1.6; transition: background-color 0.3s ease, color 0.3s ease; } .container { margin: 0 auto; padding: 12px; max-width: 1400px; } .header { text-align: center; margin-bottom: 24px; padding: 20px; background: linear-gradient(135deg, #007AFF, #5856D6); color: white; border-radius: 12px; position: relative; } /* 悬浮模块列表容器 */ .floating-modules-container { position: fixed; top: 20px; left: 20px; right: 120px; z-index: 100; } /* 右侧按钮组 */ .right-button-group { position: fixed; top: 20px; right: 20px; display: flex; flex-direction: column; gap: 12px; z-index: 101; } .right-btn { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 8px; padding: 3px 6px; cursor: pointer; font-size: 12px; color: var(--text-primary); transition: all 0.3s ease; display: flex; align-items: center; gap: 6px; min-width: 90px; justify-content: center; } .right-btn:hover { background: var(--bg-tertiary); border-color: var(--primary-color); } .right-btn.add-module { background: var(--primary-color); color: white; } .right-btn.add-module:hover { background: var(--primary-hover-color); } .right-btn.save { background: var(--primary-color); color: white; } .right-btn.save:hover { background: var(--primary-hover-color); } /* 右下角悬浮添加API按钮 */ .floating-add-api-btn { position: fixed; bottom: 30px; right: 30px; width: 40px; height: 40px; background: var(--primary-color); color: white; border: none; border-radius: 50%; cursor: pointer; font-size: 18px; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; z-index: 1000; } .floating-add-api-btn:hover { background: #0056CC; transform: scale(1.1); box-shadow: 0 6px 25px rgba(0, 122, 255, 0.4); } .floating-add-api-btn:active { transform: scale(0.95); } .floating-modules-list { display: flex; gap: 12px; overflow-x: auto; background-color: var(--bg-primary); padding: 4px 6px; border-radius: 10px; scrollbar-width: thin; scrollbar-color: var(--border-color) transparent; } .floating-modules-list::-webkit-scrollbar { height: 6px; } .floating-modules-list::-webkit-scrollbar-track { background: transparent; } .floating-modules-list::-webkit-scrollbar-thumb { background: var(--border-color); border-radius: 3px; } .floating-modules-list::-webkit-scrollbar-thumb:hover { background: var(--text-secondary); } .floating-module-item { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 8px; padding-right: 5px; padding-left: 8px; padding-top: 4px; padding-bottom: 4px; cursor: pointer; transition: all 0.3s ease; flex-shrink: 0; display: flex; align-items: center; justify-content: space-between; } .floating-module-item:hover { background: var(--bg-tertiary); border-color: var(--primary-color); } .floating-module-item.active { background: var(--primary-color); border-color: var(--primary-color); color: white; } .floating-module-info { flex: 1; display: flex; align-items: center; gap: 8px; } .floating-module-name { font-size: 13px; font-weight: 500; color: inherit; } .floating-api-count { background: rgba(255, 255, 255, 0.2); color: inherit; padding: 2px 6px; border-radius: 10px; font-size: 10px; font-weight: 600; } .floating-module-item.active .floating-api-count { background: rgba(255, 255, 255, 0.3); } .floating-module-actions { display: flex; } .floating-action-btn { background: transparent; border: none; color: var(--text-secondary); cursor: pointer; padding: 4px; border-radius: 4px; font-size: 12px; transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; } .floating-action-btn:hover { background: rgba(255, 255, 255, 0.1); color: var(--text-primary); } .floating-module-item.active .floating-action-btn { color: rgba(255, 255, 255, 0.8); } .floating-module-item.active .floating-action-btn:hover { color: white; background: rgba(255, 255, 255, 0.2); } .floating-action-btn.delete:hover { color: var(--error-color); background: rgba(255, 59, 48, 0.1); } .header h1 { font-size: 24px; font-weight: 700; margin-bottom: 8px; } .header p { font-size: 16px; opacity: 0.9; } .header-controls { position: absolute; top: 20px; right: 20px; display: flex; gap: 12px; } .header-btn { background: rgba(255, 255, 255, 0.2); border: 1px solid rgba(255, 255, 255, 0.3); border-radius: 8px; padding: 8px 16px; cursor: pointer; font-size: 14px; color: white; transition: all 0.3s ease; display: flex; align-items: center; gap: 6px; } .header-btn:hover { background: rgba(255, 255, 255, 0.3); } .top-module-card { background: var(--bg-secondary); border-radius: 12px; padding: 20px; margin-bottom: 20px; border: 1px solid var(--border-color); margin-top: 20px; } .module-section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } .module-section-title { font-size: 16px; font-weight: 600; color: var(--text-primary); } .module-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; } .module-grid-item { background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: 8px; padding-left: 16px; padding-top: 16px; padding-bottom: 30px; padding-right: 10px; cursor: pointer; transition: all 0.3s ease; position: relative; } .module-grid-item:hover { background-color: var(--bg-four); } .module-grid-item.active { border-color: var(--primary-color); background: var(--bg-primary); box-shadow: 0 4px 12px rgba(0, 122, 255, 0.15); } .add-module-btn { background: var(--primary-color); color: white; border: none; padding: 8px; border-radius: 6px; cursor: pointer; font-size: 12px; display: flex; align-items: center; gap: 4px; transition: all 0.3s ease; } .add-module-btn:hover { background: var(--primary-hover-color); } .module-grid-info { flex: 1; } .module-grid-name { font-size: 14px; font-weight: 600; color: var(--text-primary); margin-bottom: 6px; line-height: 1.3; } .edit-btn { position: absolute; bottom: 8px; right: 60px; } .delete-btn { position: absolute; bottom: 8px; right: 8px; } .module-grid-action-btn { background: transparent; border: 1px solid var(--border-color); color: var(--text-secondary); cursor: pointer; padding: 2px 6px; border-radius: 3px; font-size: 10px; transition: all 0.3s ease; display: flex; align-items: center; gap: 2px; } .module-grid-action-btn:hover { color: var(--text-primary); border: 1px solid transparent; } .delete-btn:hover { color: var(--error-color); border: 1px solid transparent; } .api-count { background: var(--primary-color); color: white; padding: 2px 8px; border-radius: 12px; font-size: 11px; margin-left: 3px; } .content-area { background: var(--bg-secondary); border-radius: 8px; padding: 16px; border: 1px solid var(--border-color); overflow-y: auto; min-width: 0; } .content-header { display: flex; justify-content: space-between; align-items: center; padding-bottom: 16px; border-bottom: 1px solid var(--border-color); } .content-title { font-size: 15px; font-weight: 600; color: var(--text-primary); } .add-api-btn { background: var(--primary-color); color: white; border: none; padding: 8px; border-radius: 8px; cursor: pointer; font-size: 12px; display: flex; align-items: center; gap: 6px; transition: all 0.3s ease; } .add-api-btn:hover { background: var(--primary-hover-color); } .api-list { display: grid; gap: 16px; margin-top: 50px; } .api-item { background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: 6px; padding: 16px; transition: all 0.3s ease; } .api-item:hover { border-color: var(--primary-color); } .api-header { display: flex; justify-content: space-between; align-items: flex-start; max-width: 600px; } .api-basic-info { flex: 1; } .api-name-row { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; } .api-name-input { font-size: 14px; font-weight: 600; color: var(--text-primary); line-height: 1.3; background: transparent; border: none; outline: none; padding: 3px 6px; width: auto; min-width: 100px; max-width: 300px; } .api-name-input:focus { background: var(--input-bg); border: 1px solid var(--primary-color); border-radius: 4px; } .api-delete-btn { background: transparent; border: 1px solid var(--border-color); color: var(--text-secondary); cursor: pointer; padding: 4px 8px; border-radius: 4px; font-size: 12px; transition: all 0.3s ease; display: flex; align-items: center; gap: 4px; flex-shrink: 0; } .api-delete-btn:hover { color: var(--error-color); border-color: var(--error-color); background: rgba(255, 59, 48, 0.1); } .api-path { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; } .method-select { background: var(--input-bg); border: 1px solid var(--border-color); border-radius: 4px; padding: 4px 8px; color: var(--text-primary); font-size: 12px; font-weight: 600; text-transform: uppercase; } .api-path-input { background: transparent; border: none; outline: none; color: var(--text-secondary); font-family: 'Monaco', monospace; font-size: 14px; padding: 2px 4px; min-width: 300px; } .api-path-input:focus { background: var(--input-bg); border: 1px solid var(--primary-color); border-radius: 4px; } .auth-checkbox { display: flex; align-items: center; gap: 4px; font-size: 12px; color: var(--text-secondary); } .auth-checkbox input { width: 14px; height: 14px; } .method-tag { padding: 3px 6px; border-radius: 4px; font-size: 11px; font-weight: 600; text-transform: uppercase; } /* 自定义复选框样式 */ .custom-checkbox { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; user-select: none; } .custom-checkbox input[type="checkbox"] { display: none; } .custom-checkbox .checkbox-icon { width: 16px; height: 16px; border: 1px solid var(--border-color); border-radius: 3px; display: flex; align-items: center; justify-content: center; background: var(--input-bg); transition: all 0.3s ease; font-size: 10px; color: transparent; } .custom-checkbox input[type="checkbox"]:checked+.checkbox-icon { background: var(--primary-color); border-color: var(--primary-color); color: white; } .custom-checkbox:hover .checkbox-icon { border-color: var(--primary-color); } /* 自定义下拉选择框样式 */ .custom-select { position: relative; display: inline-block; } .custom-select select { appearance: none; -webkit-appearance: none; -moz-appearance: none; background: var(--input-bg); border: 1px solid var(--border-color); border-radius: 6px; padding: 8px 30px 8px 12px; color: var(--text-primary); font-size: 12px; cursor: pointer; width: 100%; transition: all 0.3s ease; } /* 自定义下拉选项样式 */ .custom-select select option { background: var(--bg-secondary); color: var(--text-primary); padding: 8px 12px; border: none; font-size: 12px; } .custom-select select option:hover { background: var(--bg-tertiary); color: var(--text-primary); } .custom-select select option:checked, .custom-select select option:selected { background: var(--primary-color); color: white; } /* Firefox 特殊处理 */ @-moz-document url-prefix() { .custom-select select { background-image: none; } .custom-select select option { background-color: var(--bg-secondary); color: var(--text-primary); } .custom-select select option:hover { background-color: var(--bg-tertiary) !important; } .custom-select select option:checked { background-color: var(--primary-color) !important; color: white !important; } } /* WebKit 浏览器特殊处理 */ @media screen and (-webkit-min-device-pixel-ratio:0) { .custom-select select { background-image: none; } .custom-select select option { background: var(--bg-secondary); color: var(--text-primary); } } .method-select { min-width: 80px; max-width: 100px; } .param-select { min-width: 90px; max-width: 120px; } .custom-select select:focus { outline: none; border-color: var(--primary-color); box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.1); } .custom-select::after { content: '\f107'; font-family: 'Font Awesome 6 Free'; font-weight: 900; position: absolute; right: 8px; top: 50%; transform: translateY(-50%); color: var(--text-secondary); pointer-events: none; transition: transform 0.3s ease; z-index: 1; } .custom-select:hover::after { color: var(--text-primary); } .custom-select:focus-within::after { transform: translateY(-50%) rotate(180deg); color: var(--primary-color); } /* 自定义下拉菜单样式 */ .custom-dropdown { position: relative; display: inline-block; } .dropdown-button { background: var(--input-bg); border: 1px solid var(--border-color); border-radius: 6px; padding: 8px 30px 8px 12px; color: var(--text-primary); font-size: 12px; cursor: pointer; display: flex; align-items: center; justify-content: space-between; min-width: 80px; transition: all 0.3s ease; } .dropdown-button:hover { border-color: var(--primary-color); } .dropdown-button.active { border-color: var(--primary-color); box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.1); } .dropdown-arrow { margin-left: 8px; transition: transform 0.3s ease; } .dropdown-button.active .dropdown-arrow { transform: rotate(180deg); } .dropdown-menu { position: absolute; top: 100%; left: 0; right: 0; background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 6px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); z-index: 1000; opacity: 0; visibility: hidden; transform: translateY(-10px); transition: all 0.3s ease; max-height: 200px; overflow-y: auto; } .dropdown-menu.show { opacity: 1; visibility: visible; transform: translateY(0); } .dropdown-item { padding: 8px 12px; cursor: pointer; transition: background-color 0.2s ease; font-size: 12px; color: var(--text-primary); } .dropdown-item:hover { background: var(--bg-tertiary); } .dropdown-item.selected { background: var(--primary-color); color: white; } /* 自定义确认对话框 */ .confirm-dialog-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.6); display: flex; align-items: center; justify-content: center; z-index: 2000; opacity: 0; visibility: hidden; transition: opacity 0.3s ease, visibility 0.3s ease; } .confirm-dialog-overlay.show { opacity: 1; visibility: visible; } .confirm-dialog { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 16px; padding: 24px; min-width: 400px; max-width: 500px; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4); transform: scale(0.9) translateY(-20px); transition: transform 0.3s ease; } .confirm-dialog-overlay.show .confirm-dialog { transform: scale(1) translateY(0); } .confirm-dialog-header { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; } .confirm-dialog-icon { width: 48px; height: 48px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 20px; flex-shrink: 0; } .confirm-dialog-icon.warning { background: rgba(255, 149, 0, 0.1); color: var(--warning-color); } .confirm-dialog-icon.danger { background: rgba(255, 59, 48, 0.1); color: var(--error-color); } .confirm-dialog-icon.info { background: rgba(0, 122, 255, 0.1); color: var(--primary-color); } .confirm-dialog-title { font-size: 18px; font-weight: 600; color: var(--text-primary); margin: 0; } .confirm-dialog-message { color: var(--text-secondary); font-size: 14px; line-height: 1.5; margin-bottom: 24px; } .confirm-dialog-actions { display: flex; gap: 12px; justify-content: flex-end; } .confirm-dialog-btn { padding: 10px 20px; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.3s ease; min-width: 80px; } .confirm-dialog-btn.cancel { background: var(--bg-tertiary); color: var(--text-primary); border: 1px solid var(--border-color); } .confirm-dialog-btn.cancel:hover { background: var(--bg-primary); } .confirm-dialog-btn.confirm { background: var(--error-color); color: white; } .confirm-dialog-btn.confirm:hover { background: #E5342B; } .confirm-dialog-btn.primary { background: var(--primary-color); color: white; } .confirm-dialog-btn.primary:hover { background: #0056CC; } .method-get { background: #E3F2FD; color: #1976D2; } .method-post { background: #E8F5E8; color: #388E3C; } .method-put { background: #FFF3E0; color: #F57C00; } .method-delete { background: #FFEBEE; color: #D32F2F; } .api-path-text { font-family: 'Monaco', monospace; font-size: 14px; color: var(--text-secondary); } .api-actions { display: flex; gap: 8px; } .api-action-btn { background: transparent; border: 1px solid var(--border-color); color: var(--text-secondary); cursor: pointer; padding: 6px 12px; border-radius: 6px; font-size: 12px; transition: all 0.3s ease; display: flex; align-items: center; gap: 4px; } .api-action-btn:hover { color: var(--text-primary); border: 1px solid transparent; } .api-action-btn.delete:hover { color: var(--error-color); border: 1px solid transparent; } .auth-badge { padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 600; text-transform: uppercase; } .auth-required { background: #FFEBEE; color: #D32F2F; } .auth-not-required { background: #E8F5E8; color: #388E3C; } .api-details { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 12px; } .detail-section { background: var(--bg-primary); border-radius: 4px; padding: 12px; } .response-textarea { width: 100%; min-height: auto; background: var(--bg-primary); border: none; border-radius: 0; padding: 12px; color: var(--text-primary); font-family: 'Monaco', 'Consolas', monospace; font-size: 12px; line-height: 1.4; resize: none; overflow: hidden; transition: none; } .response-textarea:focus { outline: none; } .detail-header { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; } .detail-title { font-size: 13px; font-weight: 600; color: var(--text-primary); } .add-param-btn-inline { background: var(--primary-color); color: white; border: none; padding: 4px 8px; border-radius: 4px; cursor: pointer; font-size: 10px; display: flex; align-items: center; gap: 3px; transition: all 0.3s ease; } .add-param-btn-inline:hover { background: var(--primary-hover-color); } .param-edit-item { display: grid; grid-template-columns: 1fr 100px 80px 1fr 30px; gap: 8px; padding-bottom: 8px; align-items: center; } .param-edit-item:last-child { border-bottom: none; } .param-input { background: transparent; border: none; outline: none; color: var(--text-primary); font-size: 13px; padding: 4px; } .param-input:focus { background: var(--input-bg); border: 1px solid var(--primary-color); border-radius: 4px; } .param-select { background: var(--input-bg); border: 1px solid var(--border-color); border-radius: 4px; padding: 4px; color: var(--text-primary); font-size: 12px; } .required-checkbox { display: flex; align-items: center; gap: 4px; font-size: 11px; color: var(--text-secondary); } .required-checkbox input { width: 12px; height: 12px; } .param-desc-input { background: transparent; border: none; outline: none; color: var(--text-secondary); font-size: 12px; padding: 4px; } .param-desc-input:focus { background: var(--input-bg); border: 1px solid var(--primary-color); border-radius: 4px; } .remove-param-btn { background: var(--error-color); color: white; border: none; border-radius: 4px; padding: 4px; cursor: pointer; font-size: 10px; display: flex; align-items: center; justify-content: center; } .remove-param-btn:hover { background: var(--error-hover-color); } .param-item { display: flex; justify-content: space-between; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--border-color); } .param-item:last-child { border-bottom: none; } .param-name { font-family: 'Monaco', monospace; font-size: 13px; color: var(--text-primary); } .param-type { font-size: 12px; color: var(--text-secondary); } .param-required { background: var(--error-color); color: white; padding: 2px 6px; border-radius: 4px; font-size: 10px; } .empty-state { text-align: center; padding: 60px 20px; color: var(--text-secondary); } .empty-state i { font-size: 48px; margin-bottom: 16px; opacity: 0.5; } .empty-state h3 { font-size: 18px; margin-bottom: 8px; } .empty-state p { font-size: 14px; } /* 模态框样式 */ .modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; z-index: 1000; opacity: 0; visibility: hidden; transition: opacity 0.3s ease, visibility 0.3s ease; } .modal-overlay.show { opacity: 1; visibility: visible; } .modal { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 12px; padding: 24px; min-width: 500px; max-width: 800px; max-height: 80vh; overflow-y: auto; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); transform: scale(0.9); transition: transform 0.3s ease; } .modal-overlay.show .modal { transform: scale(1); } .modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 16px; border-bottom: 1px solid var(--border-color); } .modal-title { font-size: 20px; font-weight: 600; color: var(--text-primary); } .modal-close { background: transparent; border: none; color: var(--text-secondary); cursor: pointer; font-size: 20px; padding: 4px; } .modal-close:hover { color: var(--text-primary); } .form-group { margin-bottom: 20px; } .form-label { display: block; font-size: 14px; font-weight: 500; color: var(--text-primary); margin-bottom: 8px; } .form-input { width: 100%; padding: 12px; border: 1px solid var(--border-color); border-radius: 6px; background: var(--input-bg); color: var(--text-primary); font-size: 14px; transition: border-color 0.3s ease; } .form-input:focus { outline: none; border-color: var(--primary-color); } .form-textarea { min-height: 80px; resize: vertical; } .form-select { width: 100%; padding: 12px; border: 1px solid var(--border-color); border-radius: 6px; background: var(--input-bg); color: var(--text-primary); font-size: 14px; cursor: pointer; } .form-checkbox { display: flex; align-items: center; gap: 8px; } .form-checkbox input { width: 16px; height: 16px; } .modal-actions { display: flex; gap: 12px; justify-content: flex-end; margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--border-color); } .btn { padding: 10px 20px; border: none; border-radius: 6px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.3s ease; } .btn-primary { background: var(--primary-color); color: white; } .btn-primary:hover { background: #0056CC; } .btn-secondary { background: var(--bg-tertiary); color: var(--text-primary); border: 1px solid var(--border-color); } .btn-secondary:hover { background: var(--bg-primary); } .params-list { border: 1px solid var(--border-color); border-radius: 6px; background: var(--bg-primary); } .param-row { display: grid; grid-template-columns: 1fr 100px 80px 60px 40px; gap: 12px; padding: 12px; border-bottom: 1px solid var(--border-color); align-items: center; } .param-row:last-child { border-bottom: none; } .param-row.header { background: var(--bg-tertiary); font-weight: 600; font-size: 12px; color: var(--text-secondary); } .param-input { padding: 6px 8px; border: 1px solid var(--border-color); border-radius: 4px; background: var(--input-bg); color: var(--text-primary); font-size: 12px; } .param-select { padding: 6px 8px; border: 1px solid var(--border-color); border-radius: 4px; background: var(--input-bg); color: var(--text-primary); font-size: 12px; } .remove-param-btn { background: var(--error-color); color: white; border: none; border-radius: 4px; padding: 4px; cursor: pointer; font-size: 12px; } .add-param-btn { background: var(--success-color); color: white; border: none; border-radius: 6px; padding: 8px 12px; cursor: pointer; font-size: 12px; margin-top: 8px; display: flex; align-items: center; gap: 4px; } @media (max-width: 1024px) { .module-grid { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 12px; } .content-area { padding: 12px; } .api-item { padding: 12px; } .api-details { grid-template-columns: 1fr; gap: 8px; } } @media (max-width: 768px) { .top-controls { top: 10px; right: 10px; gap: 8px; } .control-btn { font-size: 12px; padding: 6px 12px; } .module-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; } .content-area { padding: 12px; border-radius: 6px; } } @media (max-width: 480px) { .container { padding: 8px; } .top-controls { top: 8px; right: 8px; gap: 6px; } .control-btn { font-size: 11px; padding: 4px 8px; } .top-module-card { padding: 12px; margin-bottom: 16px; border-radius: 8px; margin-top: 50px; } .module-section-title { font-size: 16px; } .module-grid { grid-template-columns: 1fr; gap: 8px; } .module-grid-item { padding: 12px; } .content-header { padding-bottom: 8px; } .content-title { font-size: 16px; } .add-api-btn { padding: 8px 12px; font-size: 12px; } } </style> </head> <body> <div class="container"> <!-- 悬浮业务模块列表 --> <div class="floating-modules-container"> <div class="floating-modules-list" id="floatingModulesList"> <!-- 动态生成模块列表 --> </div> </div> <!-- 右侧按钮组 --> <div class="right-button-group"> <button class="right-btn add-module" onclick="showAddModuleModal()"> <i class="fas fa-plus"></i> <span>添加模块</span> </button> <button class="right-btn save" onclick="saveConfig()"> <i class="fas fa-save"></i> <span>保存</span> </button> <button class="right-btn theme-toggle" onclick="toggleTheme()"> <i class="fas fa-sun"></i> <span id="theme-text">亮色模式</span> </button> </div> <!-- 主内容区 - API列表 --> <div class="content-area"> <div class="content-header" style="display: none;"> <h2 class="content-title" id="contentTitle">选择一个模块查看API接口</h2> <button class="add-api-btn" id="addApiBtn" onclick="showAddApiModal()" style="display: none;"> <i class="fas fa-plus"></i> 添加API接口 </button> </div> <div class="api-list" id="apiList"> <div class="empty-state"> <i class="fas fa-cube"></i> <h3>请选择一个业务模块</h3> <p>从上方选择一个业务模块来查看和管理其API接口</p> </div> </div> </div> <!-- 右下角悬浮添加API按钮 --> <button class="floating-add-api-btn" id="floatingAddApiBtn" onclick="showAddApiModal()" style="display: none;" title="添加API接口"> <i class="fas fa-plus"></i> </button> </div> <!-- 添加/编辑模块模态框 --> <div class="modal-overlay" id="moduleModal"> <div class="modal"> <div class="modal-header"> <h3 class="modal-title" id="moduleModalTitle">添加业务模块</h3> <button class="modal-close" onclick="hideModuleModal()"> <i class="fas fa-times"></i> </button> </div> <form id="moduleForm"> <div class="form-group"> <label class="form-label">模块英文名称</label> <input type="text" class="form-input" id="moduleEnName" placeholder="例如:accountBizModule" required> </div> <div class="form-group"> <label class="form-label">模块中文名称</label> <input type="text" class="form-input" id="moduleCnName" placeholder="例如:账号系统业务模块" required> </div> <div class="form-group"> <label class="form-label">模块描述</label> <textarea class="form-input form-textarea" id="moduleDescription" placeholder="描述该模块的主要功能和业务范围"></textarea> </div> <div class="modal-actions"> <button type="button" class="btn btn-secondary" onclick="hideModuleModal()">取消</button> <button type="submit" class="btn btn-primary">保存</button> </div> </form> </div> </div> <!-- 添加/编辑API模态框 --> <div class="modal-overlay" id="apiModal"> <div class="modal"> <div class="modal-header"> <h3 class="modal-title" id="apiModalTitle">添加API接口</h3> <button class="modal-close" onclick="hideApiModal()"> <i class="fas fa-times"></i> </button> </div> <form id="apiForm"> <div class="form-group"> <label class="form-label">API英文名称</label> <input type="text" class="form-input" id="apiEnName" placeholder="例如:sendSmsCode" required> </div> <div class="form-group"> <label class="form-label">API中文名称</label> <input type="text" class="form-input" id="apiName" placeholder="例如:发送短信验证码" required> </div> <div class="form-group"> <label class="form-label">请求方法</label> <div class="custom-select"> <select class="form-select" id="apiMethod" required> <option value="GET">GET</option> <option value="POST">POST</option> <option value="PUT">PUT</option> <option value="DELETE">DELETE</option> </select> </div> </div> </div> <div class="form-group"> <label class="form-label">API路径</label> <input type="text" class="form-input" id="apiPath" placeholder="例如:/client/biz/auth/send/code" required> </div> <div class="form-group"> <label class="custom-checkbox form-checkbox"> <input type="checkbox" id="apiAuth"> <span class="checkbox-icon"><i class="fas fa-check"></i></span> <span class="form-label">需要身份验证</span> </label> </div> <div class="form-group"> <label class="form-label">请求参数</label> <div class="params-list" id="paramsList"> <div class="param-row header"> <div>参数名称</div> <div>参数类型</div> <div>是否必需</div> <div>描述</div> <div>操作</div> </div> </div> <button type="button" class="add-param-btn" onclick="addParameterToModal()"> <i class="fas fa-plus"></i> 添加参数 </button> </div> <div class="form-group"> <label class="form-label">响应结构</label> <textarea class="form-input form-textarea response-textarea" id="apiResponse" oninput="autoResize(this)" placeholder="请输入响应结构的JSON格式,例如:\n{\n \" code\": 0,\n \"msg\": \"success\",\n \"data\": {}\n}"></textarea> </div> <div class="modal-actions"> <button type="button" class="btn btn-secondary" onclick="hideApiModal()">取消</button> <button type="submit" class="btn btn-primary">保存</button> </div> </form> </div> </div> <!-- 自定义确认对话框 --> <div class="confirm-dialog-overlay" id="confirmDialog"> <div class="confirm-dialog"> <div class="confirm-dialog-header"> <div class="confirm-dialog-icon" id="confirmIcon"> <i class="fas fa-exclamation-triangle"></i> </div> <h3 class="confirm-dialog-title" id="confirmTitle">确认操作</h3> </div> <div class="confirm-dialog-message" id="confirmMessage"> 您确定要执行此操作吗? </div> <div class="confirm-dialog-actions"> <button class="confirm-dialog-btn cancel" onclick="hideConfirmDialog(false)">取消</button> <button class="confirm-dialog-btn confirm" id="confirmBtn" onclick="hideConfirmDialog(true)">确认</button> </div> </div> </div> <script> // 全局变量 let apiConfig = { projectName: "32号旅游", moduleList: [] }; let currentModuleIndex = -1; let editingModuleIndex = -1; let editingApiIndex = -1; // 初始化 document.addEventListener('DOMContentLoaded', function () { loadConfig(); renderModuleList(); // 默认选中第一个业务模块 if (apiConfig.moduleList && apiConfig.moduleList.length > 0) { selectModule(0); } }); // 从JSON字符串导入数据 function importDataFromString(jsonString) { try { const importedData = JSON.parse(jsonString); // 验证数据结构 if (validateApiConfigStructure(importedData)) { apiConfig = importedData; currentModuleIndex = -1; renderModuleList(); renderApiList(); // 默认选中第一个业务模块 if (apiConfig.moduleList && apiConfig.moduleList.length > 0) { selectModule(0); } console.log('后端API配置数据导入成功'); return true; } else { console.error('导入失败:JSON格式不正确'); return false; } } catch (error) { console.error('导入失败:', error.message); return false; } } // 验证API配置数据结构 function validateApiConfigStructure(data) { return data && typeof data.projectName === 'string' && Array.isArray(data.moduleList); } // 加载配置 async function loadConfig() { try { // 配置数据将通过VS Code扩展的postMessage传递过来 // 这里只是初始化默认配置,等待外部数据传入 console.log('🔧 [后端设计] 等待配置数据传入...'); apiConfig = { "projectName": "后端工程", "moduleList": [ { "moduleEnName": "accountSystemBizModule", "moduleCnNam