Python+Flask+Html做一個簡單的測試聯調工具

一、場景:

當與外部聯調或者內部需要走一些固定流程,且重復的事情,往往需要測試經常性的配合且做重復的工作的聯調,這時候需要一些工具作為輔助,或者提供給外部

二、框架:

可以通過Python+Flask+Html做一個簡單的測試聯調工具

三、原理

通過app.py調用我們原有接口進行登錄獲取token并保存后傳給內部接口,并通過Flask框架獲取前端傳值并傳給我們內部接口進行內部接口的調用起到一個web頁面操作進行調用內部接口的作用

四、源碼:

1、框架結構:
  • app.py:后端代碼

  • templates :前端代碼
    在這里插入圖片描述

2、后端代碼:

from flask import Flask, request, session, redirect, url_for, render_template
import requestsapp = Flask(__name__)
app.secret_key = 'your_very_secure_secret_key_2024!'  # 生產環境需使用強密鑰# 基礎配置
app.config.from_mapping(BASE_URL="https://XXXX.com",LOGIN_URL="/login",APP_URL="https://XXXX.com",
)@app.before_first_request
def debug_routes():print("\n=== 已注冊的路由清單 ===")for rule in app.url_map.iter_rules():print(f"端點: {rule.endpoint}, 路徑: {rule.rule}")
def get_api_headers():"""管理端請求頭(使用 Bearer 認證)"""return {"Authorization": f"Bearer {session.get('auth_token', '')}","Content-Type": "application/json"}def get_app_headers():"""APP端動態請求頭(使用 token 字段)"""return {"host": "XXXX.com","clienttype": "WORKER_APP","gxd-client": "WORKER_APP_CLIENT","platformtype": "iOS","token": session.get('auth_token', '')  # 統一使用相同 token}def login_required(f):"""增強版登錄校驗裝飾器"""def wrapper(*args, **kwargs):if not session.get('logged_in'):return redirect(url_for('login'))return f(*args, **kwargs)return wrapper@app.route('/', methods=['GET', 'POST'], endpoint='index')  # 根路徑
@login_required  # 裝飾器在 @app.route 下方
def index():  # 函數名即端點名稱 'index'result = Noneerrors = []if request.method == 'POST':session['last_form'] = request.form.to_dict()action = request.form.get('action')order_no = request.form.get('order_no', '').strip()raise_fee = request.form.get('raise_fee', '0')# 操作映射表action_handlers = {'raise': lambda: add_raise_price(order_no, raise_fee),'query': lambda: get_order_detail(order_no),'complete': lambda: complete_order(order_no),'upload': lambda: upload_location(),'take': lambda: take_order(order_no),'picking': lambda: picking_order(order_no),'pickup': lambda: pickup_order(order_no),'worker_complete': lambda: worker_complete_order(order_no)}if action in action_handlers:handler_result = action_handlers[action]()if 'error' in handler_result:errors.append(handler_result['error'])else:result = handler_resultelse:errors.append("無效的操作類型")return render_template('index.html', errors=errors, result=result)
@app.route('/login', methods=['GET', 'POST'])
def login():if request.method == 'POST':# 獲取登錄憑證username = request.form.get('username')password = request.form.get('password')# 構造登錄請求login_url = f"{app.config['BASE_URL']}{app.config['LOGIN_URL']}"try:response = requests.post(login_url,json={"password": password,"phone": username},timeout=10)login_data = response.json()print(login_data)print(login_data.get('code'))print(login_data["data"]["token"])# 處理登錄響應if login_data.get('code') == 0:  # 根據實際文檔調整# 統一存儲 token 到 auth_tokensession['auth_token'] = login_data["data"]["token"]session['logged_in'] = Truesession.modified = True  # 強制保存 Sessionprint("DEBUG - 當前 Session 內容:", dict(session))  # 輸出 Session 內容return redirect(url_for('index'))else:error_msg = login_data.get('message', '登錄失敗')return render_template('login.html', error=error_msg)except Exception as e:return render_template('login.html', error=str(e))return render_template('login.html')@app.route('/logout')
def logout():session.clear()return redirect(url_for('login'))def handle_api_request(method, url, headers_type='app', payload=None, params=None):"""統一處理 API 請求(增強版)"""try:headers = get_app_headers() if headers_type == 'app' else get_api_headers()response = requests.request(method=method,url=url,headers=headers,json=payload,params=params,timeout=15)# 處理認證失效情況if response.status_code in (401, 403):session.clear()return {"error": "會話已過期,請重新登錄"}response_data = response.json()return response_dataexcept requests.exceptions.RequestException as e:return {"error": f"網絡請求失敗: {str(e)}"}# API 操作函數(統一使用 handle_api_request)
def get_order_detail(order_no):"""查詢訂單(管理端接口)"""url = f"{app.config['BASE_URL']}/admin/XXXXX/{order_no}"return handle_api_request('GET', url, 'api')def add_raise_price(order_no, raise_fee):"""加價接口(管理端接口)"""url = f"{app.config['BASE_URL']}/admin/CCCCCC"payload = {"orderNo": order_no, "raiseFee": float(raise_fee)}return handle_api_request('POST', url, 'api', payload)def upload_location():"""上傳位置信息"""url = f"{app.config['APP_URL']}/api/XXXXXX"payload  = {"location": "113.941204,22.527776"}return handle_api_request('POST', url, 'app',payload)def take_order(order_no):"""騎手搶單"""url = f"{app.config['APP_URL']}/api/XXXXXX"payload = {"signAgreement": 1, "orderNo": order_no, "workerLocation": ""}return handle_api_request('POST', url, 'app', payload)def picking_order(order_no):"""騎手已就位"""url = f"{app.config['APP_URL']}/api/XXXXXXX"payload = {"workerLocation": "113.941204,22.527776", "orderNo": order_no}return handle_api_request('POST', url, 'app', payload)def pickup_order(order_no):"""騎手確認取件"""url = f"{app.config['APP_URL']}/api/XXXXXXX"payload = {"workerLocation": "113.941204,22.527776", "orderNo": order_no}return handle_api_request('POST', url, 'app', payload)def worker_complete_order(order_no):"""騎手完成訂單"""url = f"{app.config['APP_URL']}/api/XXXXXXX"payload = {"workerLocation": "113.941204,22.527776", "orderNo": order_no}return handle_api_request('POST', url, 'app', payload)def complete_order(order_no):"""強制簽收(管理端接口)"""url = f"{app.config['BASE_URL']}/api/XXXXXXX/{order_no}"return handle_api_request('POST', url, 'api')if __name__ == '__main__':# 調試時可啟用詳細日志:app.run(host='0.0.0.0', port=5001, debug=True)
3、前端登錄代碼
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>騎手登錄 | 即時配送系統</title><style>:root {--primary-color: #409EFF;--success-color: #67C23A;--error-color: #F56C6C;--bg-color: #f5f7fa;--text-primary: #303133;--text-secondary: #909399;}* {box-sizing: border-box;margin: 0;padding: 0;}body {font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,"Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB","Microsoft YaHei", sans-serif;background-color: var(--bg-color);display: flex;justify-content: center;align-items: center;min-height: 100vh;}.login-container {background: white;padding: 2.5rem;border-radius: 12px;box-shadow: 0 6px 30px rgba(0, 0, 0, 0.1);width: 100%;max-width: 400px;transition: transform 0.3s ease;}.login-container:hover {transform: translateY(-2px);}h2 {color: var(--text-primary);font-size: 1.8rem;margin-bottom: 2rem;text-align: center;position: relative;}h2::after {content: '';display: block;width: 50px;height: 3px;background: var(--primary-color);margin: 0.8rem auto;border-radius: 2px;}.form-group {margin-bottom: 1.5rem;position: relative;}label {display: block;margin-bottom: 0.8rem;color: var(--text-secondary);font-size: 0.9rem;font-weight: 500;}input {width: 100%;padding: 0.9rem 1.2rem;border: 2px solid #e4e7ed;border-radius: 8px;font-size: 1rem;transition: all 0.3s ease;}input:focus {outline: none;border-color: var(--primary-color);box-shadow: 0 0 0 3px rgba(64, 158, 255, 0.1);}input::placeholder {color: #c0c4cc;}.error {background: #fef0f0;color: var(--error-color);padding: 1rem;border-radius: 8px;margin: 1.5rem 0;display: flex;align-items: center;gap: 0.8rem;border: 1px solid #fbc4c4;}.error::before {content: "!";display: flex;align-items: center;justify-content: center;width: 20px;height: 20px;background: var(--error-color);color: white;border-radius: 50%;font-weight: bold;}button {width: 100%;padding: 1rem;background: var(--primary-color);color: white;border: none;border-radius: 8px;font-size: 1rem;font-weight: 500;cursor: pointer;transition: all 0.3s ease;margin-top: 1rem;}button:hover {background: #66b1ff;box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);}@media (max-width: 480px) {.login-container {margin: 1rem;padding: 1.5rem;}h2 {font-size: 1.5rem;}}</style>
</head>
<body><div class="login-container"><h2>🚴 騎手登錄</h2>{% if error %}<div class="error">{{ error }}</div>{% endif %}<form method="post"><div class="form-group"><label>📱 手機號碼</label><inputtype="text"name="username"requiredplaceholder="請輸入騎手手機號碼"pattern="1[3-9]\d{9}"inputmode="numeric"></div><div class="form-group"><label>🔒 登錄密碼</label><inputtype="password"name="password"requiredplaceholder="請輸入密碼"minlength="6"maxlength="20"></div><button type="submit">騎手登錄 →</button></form></div>
</body>
</html>
4、前端index頁面
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>訂單調試工具</title><style>:root {--primary-color: #409EFF;--success-color: #67C23A;--warning-color: #E6A23C;--danger-color: #F56C6C;--text-primary: #303133;--text-regular: #606266;--border-color: #DCDFE6;--background-base: #f5f7fa;}body {font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;background-color: var(--background-base);color: var(--text-primary);line-height: 1.5;margin: 0;padding: 20px;}.container {max-width: 800px;margin: 0 auto;background: white;border-radius: 8px;box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);padding: 24px;}.header {display: flex;justify-content: flex-end;margin-bottom: 24px;}.header a {color: var(--primary-color);text-decoration: none;padding: 8px 12px;border-radius: 4px;transition: all 0.3s;}.header a:hover {background-color: rgba(64,158,255,.1);}h1 {font-size: 24px;color: var(--text-primary);margin-bottom: 24px;padding-bottom: 16px;border-bottom: 1px solid var(--border-color);}.form-group {margin-bottom: 20px;}label {display: block;margin-bottom: 8px;font-weight: 500;color: var(--text-regular);}select, input {width: 100%;padding: 10px 12px;border: 1px solid var(--border-color);border-radius: 4px;font-size: 14px;transition: border-color 0.3s;}select:focus, input:focus {outline: none;border-color: var(--primary-color);box-shadow: 0 0 0 2px rgba(64,158,255,.2);}button {background-color: var(--primary-color);color: white;border: none;padding: 10px 24px;border-radius: 4px;cursor: pointer;font-size: 14px;transition: all 0.3s;}button:hover {background-color: #66b1ff;transform: translateY(-1px);}.error {background-color: #fef0f0;color: var(--danger-color);padding: 16px;border-radius: 4px;margin: 20px 0;border: 1px solid #fbc4c4;}pre {background: #f8f8f8;padding: 16px;border-radius: 4px;border: 1px solid var(--border-color);overflow-x: auto;font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;}.transition {transition: all 0.3s ease;}.hidden-field {height: 0;opacity: 0;overflow: hidden;margin: 0;padding: 0;border: none;}</style>
</head>
<body><div class="container"><div class="header"><a href="{{ url_for('logout') }}">退出登錄</a></div><h1>📦 訂單調試工具</h1><form method="POST"><div class="form-group"><label>📌 操作類型</label><select name="action" id="actionSelector" required class="transition"><option value="upload" {% if request.form.get('action') == 'upload' %}selected{% endif %}>📍 上傳定位</option><option value="take" {% if request.form.get('action') == 'take' %}selected{% endif %}>🚴 騎手搶單</option><option value="picking" {% if request.form.get('action') == 'picking' %}selected{% endif %}>🛵 騎手已就位</option><option value="pickup" {% if request.form.get('action') == 'pickup' %}selected{% endif %}>📦 騎手確認取件</option><option value="worker_complete" {% if request.form.get('action') == 'worker_complete' %}selected{% endif %}>? 騎手確認送達</option></select></div><div class="form-group transition" id="orderNoField"><label>🔢 訂單號</label><input type="text" name="order_no" id="orderNoInput"value="{{ request.form.get('order_no', '') }}"placeholder="請輸入訂單號(上傳定位不需要)"></div><div class="form-group transition" id="raiseFeeField"><label>💰 加價金額</label><input type="number" step="0.01" name="raise_fee"value="{{ request.form.get('raise_fee', '') }}"placeholder="請輸入大于0的數字"></div><button type="submit" class="transition">🚀 提交操作</button></form>{% if errors %}<div class="error"><h3>? 操作異常</h3><ul>{% for error in errors %}<li>{{ error }}</li>{% endfor %}</ul></div>{% endif %}{% if result %}<div class="result"><h3>📄 接口響應</h3><pre>{{ result|tojson(indent=2,ensure_ascii=False) }}</pre></div>{% endif %}</div><script>// 動態字段控制const actionSelector = document.getElementById('actionSelector');const fields = {orderNo: {element: document.getElementById('orderNoField'),requiredActions: ['take', 'picking', 'pickup', 'worker_complete']},raiseFee: {element: document.getElementById('raiseFeeField'),requiredActions: ['raise']}};function toggleField(field, show) {field.element.style.height = show ? 'auto' : '0';field.element.style.opacity = show ? '1' : '0';field.element.style.margin = show ? '0 0 20px' : '0';const inputs = field.element.querySelectorAll('input');inputs.forEach(input => input.required = show);}function updateForm() {const action = actionSelector.value;// 處理訂單號字段toggleField(fields.orderNo, fields.orderNo.requiredActions.includes(action));// 處理加價字段toggleField(fields.raiseFee, fields.raiseFee.requiredActions.includes(action));}// 初始化updateForm();actionSelector.addEventListener('change', updateForm);// 提交后自動滾動到結果{% if result %}window.scrollTo({top: document.body.scrollHeight,behavior: 'smooth'});{% endif %}</script>
</body>
</html>
5、工具頁面展示:

登錄頁面
在這里插入圖片描述

操作頁面
在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/81653.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/81653.shtml
英文地址,請注明出處:http://en.pswp.cn/web/81653.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Qt5、C++11 獲取wifi列表與wifi連接

一、獲取wifi列表 .h 文件內容 #include <QWidget> #include <QVBoxLayout> #include <QPushButton> #include <QCheckBox> #include <QListWidget>class Setting : public QWidget {Q_OBJECT public:explicit Setting(QWidget *parent nul…

互聯網大廠Java求職面試:AI與大模型應用集成中的架構難題與解決方案-1

互聯網大廠Java求職面試&#xff1a;AI與大模型應用集成中的架構難題與解決方案-1 場景描述 鄭薪苦&#xff0c;一個看似不靠譜但技術潛力巨大的程序員&#xff0c;在一次針對AI與大模型應用集成的面試中&#xff0c;被一位技術總監級別的人物提問。面試官以嚴肅專業的態度&a…

SpringMVC實戰:動態時鐘

引言 在現代 Web 開發中&#xff0c;選擇一個合適的框架對于項目的成功至關重要。Spring MVC 作為 Spring 框架的核心模塊之一&#xff0c;以其清晰的架構、強大的功能和高度的可配置性&#xff0c;成為了 Java Web 開發領域的主流選擇。本文將通過一個“動態時鐘”的實戰項目…

知行之橋如何將消息推送到釘釘群?

在釘釘平臺中&#xff0c;機器人主要分為企業機器人和自定義機器人兩類。本文將重點介紹如何通過自定義機器人&#xff0c;實現將知行之橋 EDI 系統的通知消息高效推送至釘釘群&#xff0c;幫助企業第一時間掌握業務動態。 一、在釘釘群中添加自定義機器人 在需要接收知行之橋…

哈工大計算機系統2024大作業——Hello的程序人生

計算機系統 大作業 題 目 程序人生-Hello’s P2P 專 業 人工智能 學   號 2022112040 班 級 2203601 學 生 郄東昕 指 導 教 師 吳銳 計算機科學與技術學院…

聯軟SDP+安渡:收斂暴露面 從生產網自動取數 安全高效

制造業作為國家經濟的基石&#xff0c;其網絡安全面臨著獨特的挑戰。出于合規和安全考慮&#xff0c;企業內部往往劃分出多個相互隔離的網絡區域&#xff0c;如辦公網、研發網等&#xff0c;以提升整體安全防護能力。然而&#xff0c;網絡隔離在保障安全的同時&#xff0c;也帶…

LeetCode 543 二叉樹的直徑

二叉樹的直徑&#xff1a;樹中任意兩個節點間最長路徑的長度。這個路徑可能經過根節點&#xff0c;也可能不經過。 算法思路 采用深度優先搜索(DFS)的后序遍歷方式&#xff0c;計算每個節點的左右子樹高度&#xff0c;并在過程中更新最大直徑。 代碼解析 var diameterOfBin…

構建安全與合規的Jenkins環境:全周期審計方案詳解

引言 Jenkins作為最流行的CI/CD工具之一&#xff0c;承載著企業核心的自動化構建與交付流程。然而&#xff0c;隨著其復雜性的增加&#xff0c;安全漏洞、權限濫用和合規風險也隨之而來。近期頻發的供應鏈攻擊&#xff08;如通過惡意插件入侵&#xff09;更是敲響警鐘。如何確…

PowerShell Install Sql Server 2025 beta

Sql Server 2025 Download 其它版本和系統自動化腳本下載SQL Server 2025SSMS sql命令行安裝ssms 命令行安裝網盤分享SQL2025 beta

【K8S】K8S基礎概念

一、 K8S組件 1.1 控制平面組件 kube-apiserver&#xff1a;公開 Kubernetes HTTP API 的核心組件服務器。 etcd&#xff1a;具備一致性和高可用性的鍵值存儲&#xff0c;用于所有 API 服務器的數據存儲。 kube-scheduler&#xff1a;查找尚未綁定到節點的 Pod&#xff0c;并將…

【C/C++】設計模式之工廠模式:從簡單到抽象的演進

文章目錄 設計模式之工廠模式&#xff1a;從簡單到抽象的演進1 “工廠”模式分類1.1 簡單工廠&#xff08;Simple Factory&#xff09;1.2 工廠方法&#xff08;Factory Method&#xff09;1.3 抽象工廠&#xff08;Abstract Factory&#xff09; 2 分析3 總結對比 設計模式之工…

HTTP 與 HTTPS 深度解析:原理、實踐與大型項目應用

1. HTTP 與 HTTPS 基礎概念 1.1 HTTP&#xff08;超文本傳輸協議&#xff09; 定義&#xff1a;應用層協議&#xff0c;基于 TCP/IP 通信&#xff0c;默認端口 80 特點&#xff1a; 無狀態協議&#xff08;需 Cookie/Session 維護狀態&#xff09; 明文傳輸&#xff08;易被…

【Excel 擴展正則的能力】工作中賦予處理單元格文本的強大正則表達提取能力

文本提取處理領域&#xff0c;正則表達式是最為強大的存在&#xff0c;工作中Excel 是常用的小型數據采集&#xff0c;處理&#xff0c;分析的工具但本身不具備正則的能力&#xff0c;讓Excel擁有正則的能力無疑是如虎添翼的能力。 方案 讓正則作為函數內容的一部分&#xff0c…

rabbitmq 使用過程中遇到的問題

1. 連接rabbitmq 地址寫法&#xff0c;5672 是連接的端口號&#xff0c;15672是頁面訪問的端口號 2. elasticsearch 的訪問端口是9200&#xff0c; 不是9300&#xff0c;9300 是后臺通信端口號 &#xff0c;這個頁面訪問的端口號是一樣&#xff0c; 3. rabbitmq 的5種交換接…

HTML實戰:響應式個人資料頁面

我將創建一個現代化的響應式個人資料頁面,展示HTML在實際應用中的強大功能。這個頁面將包含多個實戰元素:導航欄、個人簡介、技能展示、作品集和聯系表單。 設計思路 使用Flexbox和Grid布局實現響應式設計 添加CSS過渡效果增強交互體驗 實現深色/淺色模式切換功能 創建懸停動…

工業自動化實戰:基于 VisionPro 與 C# 的機器視覺 PLC 集成方案

一、背景介紹 在智能制造領域&#xff0c;機器視覺檢測與 PLC 控制的無縫集成是實現自動化生產線閉環控制的關鍵。本文將詳細介紹如何使用 C# 開發上位機系統&#xff0c;實現 Cognex VisionPro 視覺系統與西門子 S7 PLC 的數據交互&#xff0c;打造高效、穩定的工業檢測方案。…

如何處理 Python 入門難以進步的現象

Python 初學者難以進步的根本原因在于&#xff1a;缺乏項目實踐、學習路徑不清晰、沒有掌握編程思維、忽略調試與源碼閱讀、缺乏系統性目標驅動。其中&#xff0c;“沒有項目驅動導致學習孤島效應”最為常見且致命。許多初學者只停留在語法知識、刷題階段&#xff0c;無法構建可…

【后端高階面經:緩存篇】37、高并發系統緩存性能優化:從本地到分布式的全鏈路設計

一、緩存性能優化的核心價值與分層架構 (一)緩存的多維價值體系 延遲優化 內存訪問速度(100ns) vs 磁盤數據庫(10ms+),性能提升10萬倍+案例:電商詳情頁通過緩存將響應時間從500ms降至50ms吞吐提升 單機Redis可支撐10萬QPS,分擔數據庫壓力案例:秒殺系統通過緩存攔截9…

windows本地虛擬機上運行docker-compose案例

1、先構建鏡像文件dockerfile&#xff0c;使用docker build -t redis-demo:1.0 -f dockerfile .來構建: FROM openjdk:8-jdk-alpineMAINTAINER qini<nqqq.com>VOLUME /data/upload_filesWORKDIR /usr/local/nqADD ./redis-demo.jar app.jarENV profile prod ENV timezon…

WPF布局基礎

開頭存一個快速排版插件 使用 XAML 格式化工具:XAML Styler - dino.c - 博客園 快捷鍵 在 Visual Studio 2022 中,輸入類似 <Button ... /> 的自閉合 XAML 標簽時,可以通過以下方式快速生成結尾的 />: 方法 1:輸入 / 自動補全 輸入標簽名和屬性: 輸入 <B…