基于HTML、JS、Flask与MySQL的多步骤问卷实现求助
多步骤问卷优化:前端控流程+单次后端查询方案
问题概况
我正在开发一款3步骤的企业匹配问卷:
- 步骤1:单选企业类别(radio按钮)
- 步骤2:多选所需功能(checkbox)
- 步骤3:单选集成需求(radio按钮)
用户完成问卷后,系统需从MySQL数据库中筛选符合所选条件的企业名称返回。当前实现尝试用每一步的用户输入生成SQL查询,以此动态加载下一步选项,但存在两个核心问题:
- 必须提交完整问卷才会触发后续查询,流程割裂
- 数据库响应延迟时,后续步骤的选项无法正常加载
希望改用JavaScript控制多步骤逻辑,最后仅执行一次数据库查询,求具体实现方案,附当前App.py和index.html代码。
实现方案
1. 前端:用JS接管步骤切换,统一收集参数后提交
核心思路是把所有步骤的DOM元素放在页面中,通过JS控制显示/隐藏,全程不向后端提交中间数据,最后一次性发送完整参数。
前端代码修改(index.html)
<!-- 步骤容器 --> <div class="step-container"> <div class="step active" id="step1"> <h3>选择企业类别</h3> <label><input type="radio" name="category" value="SaaS"> SaaS</label> <label><input type="radio" name="category" value="OnPrem"> 本地部署</label> <button onclick="switchStep(2)">下一步</button> </div> <div class="step" id="step2"> <h3>选择所需功能</h3> <label><input type="checkbox" name="features" value="CRM"> CRM</label> <label><input type="checkbox" name="features" value="Analytics"> 数据分析</label> <button onclick="switchStep(1)">上一步</button> <button onclick="switchStep(3)">下一步</button> </div> <div class="step" id="step3"> <h3>选择集成需求</h3> <label><input type="radio" name="integration" value="API"> API集成</label> <label><input type="radio" name="integration" value="NoIntegration"> 无需集成</label> <button onclick="switchStep(2)">上一步</button> <button onclick="submitQuery()">提交查询</button> </div> </div> <!-- 结果展示区 --> <div id="result"></div> <style> .step { display: none; } .step.active { display: block; } </style> <script> function switchStep(targetStep) { // 切换步骤显示状态 document.querySelectorAll('.step').forEach(step => step.classList.remove('active')); document.getElementById(`step${targetStep}`).classList.add('active'); } function submitQuery() { // 收集所有选中的参数 const selectedCategory = document.querySelector('input[name="category"]:checked')?.value; const selectedFeatures = Array.from(document.querySelectorAll('input[name="features"]:checked')).map(el => el.value); const selectedIntegration = document.querySelector('input[name="integration"]:checked')?.value; // 参数校验(可选,避免空提交) if (!selectedCategory || selectedFeatures.length === 0 || !selectedIntegration) { alert('请完成所有步骤的选择'); return; } // 显示加载状态 const resultDiv = document.getElementById('result'); resultDiv.innerHTML = '<p>正在查询...</p>'; // 发送AJAX请求到后端 fetch('/submit-query', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ category: selectedCategory, features: selectedFeatures, integration: selectedIntegration }) }) .then(res => res.json()) .then(data => { // 渲染查询结果 if (data.companies.length === 0) { resultDiv.innerHTML = '<p>未找到匹配的企业</p>'; } else { resultDiv.innerHTML = ` <h3>匹配的企业</h3> <ul>${data.companies.map(company => `<li>${company}</li>`).join('')}</ul> `; } }) .catch(err => { resultDiv.innerHTML = '<p>查询失败,请稍后重试</p>'; console.error(err); }); } </script>
2. 后端:接收完整参数,执行单次SQL查询
后端只需提供一个接收POST请求的接口,拿到所有参数后执行一次筛选查询,返回结果即可。
后端代码修改(App.py)
from flask import Flask, request, jsonify import mysql.connector app = Flask(__name__) # 数据库配置(替换为你的实际配置) DB_CONFIG = { 'user': 'your_db_user', 'password': 'your_db_pwd', 'host': 'localhost', 'database': 'your_db_name' } @app.route('/submit-query', methods=['POST']) def submit_query(): try: # 获取前端发送的参数 req_data = request.get_json() category = req_data.get('category') features = req_data.get('features', []) integration = req_data.get('integration') # 构建参数化SQL查询(避免SQL注入) query = """ SELECT company_name FROM companies WHERE category = %s AND integration_requirement = %s AND feature IN ({}) """.format(', '.join(['%s'] * len(features))) # 执行查询 conn = mysql.connector.connect(**DB_CONFIG) cursor = conn.cursor() cursor.execute(query, [category, integration] + features) companies = [row[0] for row in cursor.fetchall()] cursor.close() conn.close() return jsonify({'companies': companies}) except Exception as e: print(f"查询错误: {e}") return jsonify({'error': '查询失败'}), 500 if __name__ == '__main__': app.run(debug=True)
核心注意事项
- SQL注入防护:必须使用参数化查询,绝对不能直接拼接用户输入到SQL语句中
- 前端体验优化:添加步骤切换动画、提交时的加载状态,以及错误提示,提升用户体验
- 参数校验:前端和后端都要做参数校验,避免空值或非法参数导致查询出错
内容的提问来源于stack exchange,提问作者h1917
相关产品推荐
相关产品推荐

