diff --git a/main/CSS/record.css b/main/CSS/record.css index 2b8e710..4d46d72 100644 --- a/main/CSS/record.css +++ b/main/CSS/record.css @@ -7,4 +7,131 @@ .btn-playback { background-color: #2196f3; color: white; +} + +/* 轨迹管理区域样式 */ +.path-management { + margin-top: 30px; + padding: 20px; + background: linear-gradient(145deg, #e6e6e6, #ffffff); + border-radius: 15px; + box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.1), -10px -10px 20px rgba(255, 255, 255, 0.7); + width: 100%; + max-width: 600px; +} + +.path-management h3 { + margin-top: 0; + color: #333; + text-align: center; +} + +.path-input { + display: flex; + gap: 10px; + margin-bottom: 20px; + justify-content: center; +} + +.path-input input { + padding: 10px; + border: none; + border-radius: 10px; + background: #f5f5f5; + box-shadow: inset 5px 5px 10px rgba(0, 0, 0, 0.1), inset -5px -5px 10px rgba(255, 255, 255, 0.7); + width: 200px; + font-size: 16px; +} + +.btn-save { + background: linear-gradient(145deg, #4CAF50, #45a049); + color: white; + border: none; + border-radius: 10px; + padding: 10px 20px; + font-size: 16px; + font-weight: bold; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.1), -5px -5px 10px rgba(255, 255, 255, 0.7); +} + +.btn-save:hover { + transform: translateY(-2px); + box-shadow: 7px 7px 14px rgba(0, 0, 0, 0.15), -7px -7px 14px rgba(255, 255, 255, 0.8); +} + +.btn-save:active { + transform: translateY(0); + box-shadow: 3px 3px 6px rgba(0, 0, 0, 0.1), -3px -3px 6px rgba(255, 255, 255, 0.7); +} + +.path-list h4 { + margin-top: 0; + color: #555; + text-align: center; +} + +#pathList { + list-style: none; + padding: 0; + max-height: 200px; + overflow-y: auto; +} + +#pathList li { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px; + margin: 5px 0; + background: #f5f5f5; + border-radius: 10px; + box-shadow: 3px 3px 6px rgba(0, 0, 0, 0.1), -3px -3px 6px rgba(255, 255, 255, 0.7); +} + +#pathList li button { + background: linear-gradient(145deg, #f44336, #da190b); + color: white; + border: none; + border-radius: 5px; + padding: 5px 10px; + font-size: 12px; + cursor: pointer; + transition: all 0.3s ease; +} + +#pathList li button:hover { + background: linear-gradient(145deg, #e53935, #c62828); +} + +#pathList li button.load-btn { + background: linear-gradient(145deg, #2196F3, #1976D2); + margin-right: 5px; +} + +#pathList li button.load-btn:hover { + background: linear-gradient(145deg, #1E88E5, #1565C0); +} + +/* 响应式设计 - 轨迹管理 */ +@media (max-width: 650px) { + .path-input { + flex-direction: column; + align-items: center; + } + + .path-input input { + width: 100%; + max-width: 300px; + } + + .btn-save { + width: 100%; + max-width: 300px; + } + + .path-management { + padding: 15px; + } } \ No newline at end of file diff --git a/main/Javascript/record.js b/main/Javascript/record.js index 9203d91..ffdf4a5 100644 --- a/main/Javascript/record.js +++ b/main/Javascript/record.js @@ -12,12 +12,153 @@ window.addEventListener('DOMContentLoaded', function() { const recordBtn = document.getElementById('recordBtn'); const playbackBtn = document.getElementById('playbackBtn'); const status = document.getElementById('status'); + + // 获取轨迹管理相关元素 + const pathNameInput = document.getElementById('pathName'); + const savePathBtn = document.getElementById('savePathBtn'); + const pathList = document.getElementById('pathList'); // 调试信息 console.log('Record.js loaded'); console.log('recordBtn:', recordBtn); console.log('playbackBtn:', playbackBtn); console.log('status:', status); + console.log('pathNameInput:', pathNameInput); + console.log('savePathBtn:', savePathBtn); + console.log('pathList:', pathList); + + // 列出已保存的轨迹 + function listPaths() { + fetch('/list_paths') + .then(response => response.json()) + .then(data => { + if (data.status === 'success') { + // 清空路径列表 + pathList.innerHTML = ''; + + // 添加路径到列表 + data.paths.forEach(path => { + const li = document.createElement('li'); + li.innerHTML = ` + ${path} +
错误: ${data.message}
`; + } + }) + .catch(error => { + status.innerHTML = `通信错误: ${error.message}
`; + }); + } + + // 保存轨迹 + function savePath() { + const pathName = pathNameInput.value.trim(); + if (!pathName) { + status.innerHTML = '请输入轨迹名称
'; + return; + } + + if (window.recordedActions.length === 0) { + status.innerHTML = '没有可保存的轨迹
'; + return; + } + + fetch('/save_path', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ name: pathName, actions: window.recordedActions }) + }) + .then(response => response.json()) + .then(data => { + if (data.status === 'success') { + status.innerHTML = `${data.message}
`; + // 清空输入框 + pathNameInput.value = ''; + // 更新轨迹列表 + listPaths(); + } else { + status.innerHTML = `错误: ${data.message}
`; + } + }) + .catch(error => { + status.innerHTML = `通信错误: ${error.message}
`; + }); + } + + // 加载轨迹 + function loadPath(pathName) { + fetch(`/load_path?name=${pathName}`) + .then(response => response.json()) + .then(data => { + if (data.status === 'success') { + window.recordedActions = data.data.actions; + status.innerHTML = `轨迹 ${pathName} 加载成功,共 ${window.recordedActions.length} 个操作
`; + } else { + status.innerHTML = `错误: ${data.message}
`; + } + }) + .catch(error => { + status.innerHTML = `通信错误: ${error.message}
`; + }); + } + + // 删除轨迹 + function deletePath(pathName) { + if (confirm(`确定要删除轨迹 ${pathName} 吗?`)) { + fetch('/delete_path', { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ name: pathName }) + }) + .then(response => response.json()) + .then(data => { + if (data.status === 'success') { + status.innerHTML = `${data.message}
`; + // 更新轨迹列表 + listPaths(); + } else { + status.innerHTML = `错误: ${data.message}
`; + } + }) + .catch(error => { + status.innerHTML = `通信错误: ${error.message}
`; + }); + } + } + + // 保存轨迹按钮点击事件 + if (savePathBtn) { + savePathBtn.addEventListener('click', savePath); + } + + // 页面加载时列出已保存的轨迹 + listPaths(); // 录制按钮点击事件 - 支持鼠标和触摸事件 function toggleRecording() { diff --git a/main/index.html b/main/index.html index 13e8a7b..f2a6732 100644 --- a/main/index.html +++ b/main/index.html @@ -47,6 +47,19 @@ + +就绪
diff --git a/main/server.py b/main/server.py index ffd4ffb..8c5bcca 100644 --- a/main/server.py +++ b/main/server.py @@ -2,6 +2,7 @@ from flask import Flask, send_file, request, jsonify, send_from_directory import motor import time import os +import json app = Flask(__name__) @@ -87,5 +88,85 @@ def control(): print(f"控制出错: {e}") return jsonify({'status': 'error', 'message': f'控制出错: {e}'}) +# 保存轨迹路由 +@app.route('/save_path', methods=['POST']) +def save_path(): + data = request.get_json() + path_name = data.get('name') + recorded_actions = data.get('actions') + + if not path_name or not recorded_actions: + return jsonify({'status': 'error', 'message': '路径名称和轨迹数据不能为空'}) + + try: + # 确保Path目录存在 + os.makedirs('Path', exist_ok=True) + + # 保存为JSON文件 + file_path = os.path.join('Path', f'{path_name}.json') + with open(file_path, 'w', encoding='utf-8') as f: + json.dump({'name': path_name, 'actions': recorded_actions}, f, ensure_ascii=False, indent=2) + + return jsonify({'status': 'success', 'message': '轨迹保存成功'}) + except Exception as e: + print(f"保存轨迹出错: {e}") + return jsonify({'status': 'error', 'message': f'保存轨迹出错: {e}'}) + +# 列出轨迹路由 +@app.route('/list_paths', methods=['GET']) +def list_paths(): + try: + # 确保Path目录存在 + os.makedirs('Path', exist_ok=True) + + # 列出所有轨迹文件 + path_files = [f.replace('.json', '') for f in os.listdir('Path') if f.endswith('.json')] + + return jsonify({'status': 'success', 'paths': path_files}) + except Exception as e: + print(f"列出轨迹出错: {e}") + return jsonify({'status': 'error', 'message': f'列出轨迹出错: {e}'}) + +# 加载轨迹路由 +@app.route('/load_path', methods=['GET']) +def load_path(): + path_name = request.args.get('name') + + if not path_name: + return jsonify({'status': 'error', 'message': '路径名称不能为空'}) + + try: + file_path = os.path.join('Path', f'{path_name}.json') + if not os.path.exists(file_path): + return jsonify({'status': 'error', 'message': '轨迹文件不存在'}) + + with open(file_path, 'r', encoding='utf-8') as f: + data = json.load(f) + + return jsonify({'status': 'success', 'data': data}) + except Exception as e: + print(f"加载轨迹出错: {e}") + return jsonify({'status': 'error', 'message': f'加载轨迹出错: {e}'}) + +# 删除轨迹路由 +@app.route('/delete_path', methods=['DELETE']) +def delete_path(): + data = request.get_json() + path_name = data.get('name') + + if not path_name: + return jsonify({'status': 'error', 'message': '路径名称不能为空'}) + + try: + file_path = os.path.join('Path', f'{path_name}.json') + if not os.path.exists(file_path): + return jsonify({'status': 'error', 'message': '轨迹文件不存在'}) + + os.remove(file_path) + return jsonify({'status': 'success', 'message': '轨迹删除成功'}) + except Exception as e: + print(f"删除轨迹出错: {e}") + return jsonify({'status': 'error', 'message': f'删除轨迹出错: {e}'}) + if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True)