文章目录[隐藏]
WordPress集成教程:连接航空航班动态API实现实时信息查询
引言:为什么要在WordPress中集成航班动态功能?
在当今数字化时代,网站已不仅仅是信息展示平台,更是功能服务的载体。对于旅游类网站、企业差旅管理平台或航空公司相关网站而言,提供实时航班动态查询功能可以显著提升用户体验和网站实用性。WordPress作为全球最流行的内容管理系统,通过代码二次开发可以轻松集成各类API功能,将专业数据服务转化为网站实用工具。
本教程将详细指导您如何在WordPress中连接航空航班动态API,实现实时航班信息查询功能。我们将从API选择、开发环境搭建、代码实现到前端展示,一步步构建一个完整的航班查询工具。无论您是WordPress开发者、网站管理员还是对Web开发感兴趣的爱好者,都能通过本教程掌握将第三方API集成到WordPress中的核心技能。
第一章:准备工作与环境配置
1.1 选择合适的航空航班动态API
在开始开发前,首先需要选择一个可靠且功能完善的航班动态API服务。目前市场上有多种选择:
- 航空数据API:如FlightAware、FlightStats、AviationStack等专业服务
- 综合性旅行API:如Amadeus、Sabre等提供的航班状态接口
- 免费API选项:部分服务提供有限的免费调用额度,适合小型网站
对于本教程,我们选择使用AviationStack API,因为它提供免费套餐(每月500次请求),且文档清晰、数据准确。您需要前往其官网注册账户并获取API密钥。
1.2 WordPress开发环境搭建
确保您已具备以下环境:
- WordPress安装:建议使用最新版本的WordPress(5.8+)
- 开发主题或子主题:建议创建子主题进行开发,避免主题更新丢失修改
- 代码编辑器:如VS Code、Sublime Text或PHPStorm
- 本地开发环境:可使用XAMPP、MAMP或Local by Flywheel
- 基本PHP和JavaScript知识
1.3 创建插件结构
我们将创建一个独立的WordPress插件来实现航班查询功能,这样可以确保功能独立且易于维护。
在wp-content/plugins/目录下创建新文件夹flight-status-checker,并在其中创建以下文件结构:
flight-status-checker/
├── flight-status-checker.php # 主插件文件
├── includes/
│ ├── class-api-handler.php # API处理类
│ ├── class-shortcode.php # 短代码类
│ └── class-admin-settings.php # 管理设置类
├── assets/
│ ├── css/
│ │ └── frontend.css # 前端样式
│ └── js/
│ └── frontend.js # 前端交互脚本
├── templates/
│ └── flight-form.php # 查询表单模板
└── languages/ # 国际化文件(可选)
第二章:创建WordPress插件框架
2.1 主插件文件配置
打开flight-status-checker.php,添加插件基本信息:
<?php
/**
* Plugin Name: 航班动态查询工具
* Plugin URI: https://yourwebsite.com/flight-status-checker
* Description: 在WordPress网站中集成实时航班动态查询功能
* Version: 1.0.0
* Author: 您的名称
* Author URI: https://yourwebsite.com
* License: GPL v2 or later
* Text Domain: flight-status-checker
* Domain Path: /languages
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('FSC_VERSION', '1.0.0');
define('FSC_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('FSC_PLUGIN_URL', plugin_dir_url(__FILE__));
define('FSC_API_CACHE_TIME', 300); // API缓存时间(秒)
// 检查必要扩展
add_action('admin_init', function() {
if (!extension_loaded('curl')) {
add_action('admin_notices', function() {
echo '<div class="notice notice-error"><p>航班动态查询插件需要cURL扩展支持。请联系您的主机提供商启用cURL。</p></div>';
});
}
});
// 自动加载类文件
spl_autoload_register(function($class_name) {
$prefix = 'FSC_';
$base_dir = FSC_PLUGIN_DIR . 'includes/';
// 检查类是否使用我们的前缀
$len = strlen($prefix);
if (strncmp($prefix, $class_name, $len) !== 0) {
return;
}
$relative_class = substr($class_name, $len);
$file = $base_dir . 'class-' . strtolower(str_replace('_', '-', $relative_class)) . '.php';
if (file_exists($file)) {
require_once $file;
}
});
// 初始化插件
add_action('plugins_loaded', 'fsc_init_plugin');
function fsc_init_plugin() {
// 加载文本域用于国际化
load_plugin_textdomain('flight-status-checker', false, dirname(plugin_basename(__FILE__)) . '/languages');
// 初始化各个组件
if (is_admin()) {
new FSC_Admin_Settings();
}
new FSC_API_Handler();
new FSC_Shortcode();
// 注册激活/停用钩子
register_activation_hook(__FILE__, 'fsc_activate_plugin');
register_deactivation_hook(__FILE__, 'fsc_deactivate_plugin');
}
function fsc_activate_plugin() {
// 创建必要的数据库表或选项
if (!get_option('fsc_settings')) {
$default_settings = array(
'api_key' => '',
'cache_enabled' => true,
'default_airline' => '',
'date_format' => 'Y-m-d',
'time_format' => 'H:i'
);
add_option('fsc_settings', $default_settings);
}
// 设置定时任务清理缓存
if (!wp_next_scheduled('fsc_clear_cache_daily')) {
wp_schedule_event(time(), 'daily', 'fsc_clear_cache_daily');
}
}
function fsc_deactivate_plugin() {
// 清理定时任务
wp_clear_scheduled_hook('fsc_clear_cache_daily');
// 可选:清理缓存数据
// fsc_clear_all_cache();
}
// 添加清理缓存的每日任务
add_action('fsc_clear_cache_daily', 'fsc_clear_old_cache');
function fsc_clear_old_cache() {
global $wpdb;
$table_name = $wpdb->prefix . 'options';
$time = time() - (7 * 24 * 60 * 60); // 删除7天前的缓存
$wpdb->query(
$wpdb->prepare(
"DELETE FROM $table_name WHERE option_name LIKE %s AND option_value < %d",
'_transient_fsc_flight_%',
$time
)
);
}
第三章:API处理类实现
3.1 创建API处理类
在includes/class-api-handler.php中创建API处理核心类:
<?php
class FSC_API_Handler {
private $api_key;
private $api_endpoint = 'http://api.aviationstack.com/v1/';
private $settings;
public function __construct() {
$this->settings = get_option('fsc_settings', array());
$this->api_key = isset($this->settings['api_key']) ? $this->settings['api_key'] : '';
// 注册AJAX处理函数
add_action('wp_ajax_fsc_get_flight_status', array($this, 'ajax_get_flight_status'));
add_action('wp_ajax_nopriv_fsc_get_flight_status', array($this, 'ajax_get_flight_status'));
// 注册REST API端点(可选)
add_action('rest_api_init', array($this, 'register_rest_routes'));
}
/**
* 获取航班状态
*/
public function get_flight_status($params) {
// 参数验证
$flight_number = isset($params['flight_number']) ? sanitize_text_field($params['flight_number']) : '';
$airline_iata = isset($params['airline']) ? sanitize_text_field($params['airline']) : '';
$date = isset($params['date']) ? sanitize_text_field($params['date']) : date('Y-m-d');
if (empty($flight_number)) {
return array(
'success' => false,
'message' => __('请输入航班号', 'flight-status-checker')
);
}
// 检查缓存
$cache_key = 'fsc_flight_' . md5($flight_number . $airline_iata . $date);
$cached_data = get_transient($cache_key);
if ($cached_data !== false && isset($this->settings['cache_enabled']) && $this->settings['cache_enabled']) {
return $cached_data;
}
// 构建API请求参数
$api_params = array(
'access_key' => $this->api_key,
'flight_iata' => $flight_number,
'flight_date' => $date
);
if (!empty($airline_iata)) {
$api_params['airline_iata'] = $airline_iata;
}
// 发送API请求
$response = $this->make_api_request('flights', $api_params);
if ($response['success']) {
// 处理API响应数据
$processed_data = $this->process_flight_data($response['data']);
// 缓存结果
if (isset($this->settings['cache_enabled']) && $this->settings['cache_enabled']) {
set_transient($cache_key, $processed_data, FSC_API_CACHE_TIME);
}
return $processed_data;
} else {
return array(
'success' => false,
'message' => $response['message']
);
}
}
/**
* 发送API请求
*/
private function make_api_request($endpoint, $params) {
if (empty($this->api_key)) {
return array(
'success' => false,
'message' => __('API密钥未配置,请在插件设置中配置API密钥。', 'flight-status-checker')
);
}
$url = $this->api_endpoint . $endpoint . '?' . http_build_query($params);
// 使用WordPress HTTP API
$response = wp_remote_get($url, array(
'timeout' => 15,
'sslverify' => false
));
if (is_wp_error($response)) {
return array(
'success' => false,
'message' => $response->get_error_message()
);
}
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
if (isset($data['error'])) {
return array(
'success' => false,
'message' => isset($data['error']['message']) ? $data['error']['message'] : __('API请求失败', 'flight-status-checker')
);
}
if (isset($data['data']) && is_array($data['data']) && count($data['data']) > 0) {
return array(
'success' => true,
'data' => $data['data']
);
} else {
return array(
'success' => false,
'message' => __('未找到航班信息', 'flight-status-checker')
);
}
}
/**
* 处理航班数据
*/
private function process_flight_data($flight_data) {
if (empty($flight_data) || !is_array($flight_data)) {
return array(
'success' => false,
'message' => __('航班数据格式错误', 'flight-status-checker')
);
}
$flight = $flight_data[0]; // 取第一个结果
// 格式化数据
$formatted_data = array(
'success' => true,
'flight' => array(
'number' => isset($flight['flight']['iata']) ? $flight['flight']['iata'] : '',
'airline' => isset($flight['airline']['name']) ? $flight['airline']['name'] : '',
'status' => isset($flight['flight_status']) ? $this->translate_flight_status($flight['flight_status']) : '',
'departure' => array(
'airport' => isset($flight['departure']['airport']) ? $flight['departure']['airport'] : '',
'iata' => isset($flight['departure']['iata']) ? $flight['departure']['iata'] : '',
'scheduled' => isset($flight['departure']['scheduled']) ? $this->format_datetime($flight['departure']['scheduled']) : '',
'estimated' => isset($flight['departure']['estimated']) ? $this->format_datetime($flight['departure']['estimated']) : '',
'actual' => isset($flight['departure']['actual']) ? $this->format_datetime($flight['departure']['actual']) : '',
'gate' => isset($flight['departure']['gate']) ? $flight['departure']['gate'] : '--',
'terminal' => isset($flight['departure']['terminal']) ? $flight['departure']['terminal'] : '--'
),
'arrival' => array(
'airport' => isset($flight['arrival']['airport']) ? $flight['arrival']['airport'] : '',
'iata' => isset($flight['arrival']['iata']) ? $flight['arrival']['iata'] : '',
'scheduled' => isset($flight['arrival']['scheduled']) ? $this->format_datetime($flight['arrival']['scheduled']) : '',
'estimated' => isset($flight['arrival']['estimated']) ? $this->format_datetime($flight['arrival']['estimated']) : '',
'actual' => isset($flight['arrival']['actual']) ? $this->format_datetime($flight['arrival']['actual']) : '',
'gate' => isset($flight['arrival']['gate']) ? $flight['arrival']['gate'] : '--',
'terminal' => isset($flight['arrival']['terminal']) ? $flight['arrival']['terminal'] : '--'
),
'aircraft' => isset($flight['aircraft']['iata']) ? $flight['aircraft']['iata'] : '--',
'live' => isset($flight['live']) ? $flight['live'] : null
)
);
return $formatted_data;
}
/**
* 翻译航班状态
*/
private function translate_flight_status($status) {
$status_map = array(
'scheduled' => '计划中',
'active' => '飞行中',
'landed' => '已降落',
'cancelled' => '已取消',
'incident' => '异常',
'diverted' => '已改航'
);
return isset($status_map[$status]) ? $status_map[$status] : $status;
}
/**
* 格式化日期时间
*/
private function format_datetime($datetime_string) {
if (empty($datetime_string)) {
return '--';
}
$date_format = isset($this->settings['date_format']) ? $this->settings['date_format'] : 'Y-m-d';
$time_format = isset($this->settings['time_format']) ? $this->settings['time_format'] : 'H:i';
$timestamp = strtotime($datetime_string);
return date($date_format . ' ' . $time_format, $timestamp);
}
/**
* AJAX处理函数
*/
public function ajax_get_flight_status() {
// 验证nonce
if (!check_ajax_referer('fsc_ajax_nonce', 'nonce', false)) {
wp_die(json_encode(array(
'success' => false,
'message' => __('安全验证失败', 'flight-status-checker')
)));
}
$params = array(
'flight_number' => isset($_POST['flight_number']) ? sanitize_text_field($_POST['flight_number']) : '',
'airline' => isset($_POST['airline']) ? sanitize_text_field($_POST['airline']) : '',
'date' => isset($_POST['date']) ? sanitize_text_field($_POST['date']) : date('Y-m-d')
);
$result = $this->get_flight_status($params);
wp_send_json($result);
}
/**
* 注册REST API路由
*/
public function register_rest_routes() {
register_rest_route('flight-status/v1', '/check', array(
'methods' => 'GET',
'callback' => array($this, 'rest_get_flight_status'),
'permission_callback' => '__return_true',
'args' => array(
'flight_number' => array(
'required' => true,
'validate_callback' => function($param) {
return !empty($param);
}
),
'date' => array(
'required' => false,
'default' => date('Y-m-d')
)
)
));
}
public function rest_get_flight_status($request) {
$params = $request->get_params();
$result = $this->get_flight_status($params);
return rest_ensure_response($result);
}
}
第四章:创建短代码和前端界面
4.1 短代码类实现
在includes/class-shortcode.php中创建短代码处理类:
<?php
class FSC_Shortcode {
public function __construct() {
add_shortcode('flight_status_checker', array($this, 'render_shortcode'));
// 注册前端脚本和样式
add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
}
/**
* 渲染短代码
*/
public function render_shortcode($atts) {
// 短代码属性
$atts = shortcode_atts(array(
'title' => '航班动态查询',
'show_airline_field' => 'yes',
'default_date' => '',
'button_text' => '查询航班状态',
'layout' => 'default' // default, compact, detailed
), $atts, 'flight_status_checker');
// 获取模板
ob_start();
include FSC_PLUGIN_DIR . 'templates/flight-form.php';
return ob_get_clean();
}
/**
* 加载前端资源
*/
public function enqueue_frontend_assets() {
// 只在需要时加载
global $post;
if (is_a($post, 'WP_Post') && has_shortcode($post->post_content, 'flight_status_checker')) {
// 加载CSS
wp_enqueue_style(
'fsc-frontend-style',
FSC_PLUGIN_URL . 'assets/css/frontend.css',
array(),
FSC_VERSION
);
// 加载JavaScript
wp_enqueue_script(
'fsc-frontend-script',
FSC_PLUGIN_URL . 'assets/js/frontend.js',
array('jquery'),
FSC_VERSION,
true
);
// 本地化脚本
wp_localize_script('fsc-frontend-script', 'fsc_ajax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('fsc_ajax_nonce'),
'loading_text' => __('查询中...', 'flight-status-checker'),
'error_messages' => array(
'flight_required' => __('请输入航班号', 'flight-status-checker'),
'invalid_format' => __('航班号格式不正确', 'flight-status-checker')
)
));
}
}
}
4.2 创建查询表单模板
在templates/flight-form.php中创建前端表单:
<div class="fsc-flight-checker-wrapper layout-<?php echo esc_attr($atts['layout']); ?>">
<div class="fsc-header">
<h3><?php echo esc_html($atts['title']); ?></h3>
<p class="fsc-description"><?php _e('输入航班号查询实时航班动态信息', 'flight-status-checker'); ?></p>
</div>
<div class="fsc-form-container">
<form id="fsc-flight-form" method="post">
<div class="fsc-form-row">
<div class="fsc-form-group">
<label for="fsc-flight-number">
<i class="fsc-icon fsc-icon-flight"></i>
<?php _e('航班号', 'flight-status-checker'); ?>
</label>
<input
type="text"
id="fsc-flight-number"
name="flight_number"
placeholder="例如:CA123"
required
pattern="[A-Za-z]{2}d{1,4}"
title="<?php _e('请输入正确的航班号格式,如:CA123', 'flight-status-checker'); ?>"
>
<small class="fsc-hint"><?php _e('格式:航空公司代码+数字,如:CA123, MU586', 'flight-status-checker'); ?></small>
</div>
<?php if ($atts['show_airline_field'] === 'yes') : ?>
<div class="fsc-form-group">
<label for="fsc-airline">
<i class="fsc-icon fsc-icon-airline"></i>
<?php _e('航空公司代码(可选)', 'flight-status-checker'); ?>
</label>
<input
type="text"
id="fsc-airline"
name="airline"
placeholder="例如:CA"
pattern="[A-Za-z]{2}"
title="<?php _e('请输入2位航空公司代码', 'flight-status-checker'); ?>"
>
<small class="fsc-hint"><?php _e('2位IATA航空公司代码', 'flight-status-checker'); ?></small>
</div>
<?php endif; ?>
<div class="fsc-form-group">
<label for="fsc-date">
<i class="fsc-icon fsc-icon-calendar"></i>
<?php _e('航班日期', 'flight-status-checker'); ?>
</label>
<input
type="date"
id="fsc-date"
name="date"
value="<?php echo empty($atts['default_date']) ? date('Y-m-d') : esc_attr($atts['default_date']); ?>"
min="<?php echo date('Y-m-d', strtotime('-30 days')); ?>"
max="<?php echo date('Y-m-d', strtotime('+30 days')); ?>"
>
</div>
</div>
<div class="fsc-form-actions">
<button type="submit" class="fsc-submit-btn">
<i class="fsc-icon fsc-icon-search"></i>
<?php echo esc_html($atts['button_text']); ?>
</button>
<button type="button" class="fsc-reset-btn">
<?php _e('重置', 'flight-status-checker'); ?>
</button>
</div>
</form>
</div>
<div class="fsc-results-container" style="display: none;">
<div class="fsc-loading">
<div class="fsc-spinner"></div>
<p><?php _e('正在查询航班信息...', 'flight-status-checker'); ?></p>
</div>
<div class="fsc-results" style="display: none;">
<!-- 结果将通过JavaScript动态填充 -->
</div>
<div class="fsc-error" style="display: none;">
<!-- 错误信息将通过JavaScript动态填充 -->
</div>
</div>
<div class="fsc-footer">
<p class="fsc-disclaimer">
<small>
<i class="fsc-icon fsc-icon-info"></i>
<?php _e('数据来源:AviationStack API,信息仅供参考,请以航空公司官方信息为准。', 'flight-status-checker'); ?>
</small>
</p>
</div>
</div>
4.3 前端样式设计
在assets/css/frontend.css中创建样式:
/* 航班查询工具主样式 */
.fsc-flight-checker-wrapper {
max-width: 800px;
margin: 2rem auto;
padding: 2rem;
background: #ffffff;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
}
.fsc-header {
text-align: center;
margin-bottom: 2rem;
padding-bottom: 1.5rem;
border-bottom: 2px solid #f0f0f0;
}
.fsc-header h3 {
color: #1a237e;
margin: 0 0 0.5rem 0;
font-size: 1.8rem;
font-weight: 600;
}
.fsc-description {
color: #666;
margin: 0;
font-size: 1rem;
}
/* 表单样式 */
.fsc-form-container {
margin-bottom: 2rem;
}
.fsc-form-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
margin-bottom: 1.5rem;
}
.fsc-form-group {
display: flex;
flex-direction: column;
}
.fsc-form-group label {
display: flex;
align-items: center;
margin-bottom: 0.5rem;
color: #333;
font-weight: 500;
font-size: 0.95rem;
}
.fsc-icon {
margin-right: 0.5rem;
font-size: 1.1rem;
color: #1a237e;
}
.fsc-form-group input {
padding: 0.75rem 1rem;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 1rem;
transition: all 0.3s ease;
background: #fafafa;
}
.fsc-form-group input:focus {
outline: none;
border-color: #1a237e;
background: #fff;
box-shadow: 0 0 0 3px rgba(26, 35, 126, 0.1);
}
.fsc-hint {
margin-top: 0.25rem;
color: #666;
font-size: 0.85rem;
line-height: 1.3;
}
/* 按钮样式 */
.fsc-form-actions {
display: flex;
gap: 1rem;
justify-content: center;
margin-top: 1.5rem;
}
.fsc-submit-btn, .fsc-reset-btn {
padding: 0.875rem 2rem;
border: none;
border-radius: 8px;
font-size: 1rem;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.fsc-submit-btn {
background: linear-gradient(135deg, #1a237e 0%, #283593 100%);
color: white;
min-width: 180px;
}
.fsc-submit-btn:hover {
background: linear-gradient(135deg, #283593 0%, #303f9f 100%);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(26, 35, 126, 0.3);
}
.fsc-reset-btn {
background: #f5f5f5;
color: #666;
border: 2px solid #e0e0e0;
}
.fsc-reset-btn:hover {
background: #e0e0e0;
color: #333;
}
/* 加载状态 */
.fsc-loading {
text-align: center;
padding: 3rem;
}
.fsc-spinner {
width: 50px;
height: 50px;
border: 4px solid #f3f3f3;
border-top: 4px solid #1a237e;
border-radius: 50%;
animation: fsc-spin 1s linear infinite;
margin: 0 auto 1rem;
}
@keyframes fsc-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.fsc-loading p {
color: #666;
margin: 0;
}
/* 结果展示 */
.fsc-results {
background: #f8f9ff;
border-radius: 10px;
padding: 2rem;
margin-top: 1.5rem;
border: 1px solid #e0e7ff;
}
.fsc-flight-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 2px solid #e0e7ff;
}
.fsc-flight-number {
font-size: 1.8rem;
font-weight: 700;
color: #1a237e;
margin: 0;
}
.fsc-flight-status {
padding: 0.5rem 1.5rem;
border-radius: 20px;
font-weight: 600;
font-size: 0.9rem;
}
.fsc-status-scheduled { background: #e3f2fd; color: #1565c0; }
.fsc-status-active { background: #e8f5e9; color: #2e7d32; }
.fsc-status-landed { background: #f1f8e9; color: #558b2f; }
.fsc-status-cancelled { background: #ffebee; color: #c62828; }
.fsc-status-delayed { background: #fff3e0; color: #ef6c00; }
.fsc-flight-details {
display: grid;
grid-template-columns: 1fr auto 1fr;
gap: 2rem;
align-items: center;
margin-bottom: 2rem;
}
.fsc-departure, .fsc-arrival {
padding: 1.5rem;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
.fsc-airport-name {
font-size: 1.3rem;
font-weight: 600;
color: #333;
margin: 0 0 0.5rem 0;
}
.fsc-airport-code {
color: #666;
font-size: 0.9rem;
margin-bottom: 1rem;
}
.fsc-time-group {
margin-bottom: 1rem;
}
.fsc-time-label {
display: block;
color: #888;
font-size: 0.85rem;
margin-bottom: 0.25rem;
}
.fsc-time-value {
font-size: 1.1rem;
font-weight: 500;
color: #333;
}
.fsc-terminal-info {
display: flex;
gap: 1rem;
margin-top: 1rem;
padding-top: 1rem;
border-top: 1px solid #eee;
}
.fsc-terminal-info span {
font-size: 0.9rem;
color: #666;
}
.fsc-flight-path {
text-align: center;
position: relative;
}
.fsc-flight-path::before {
content: '';
position: absolute;
top: 50%;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, #1a237e, #283593);
z-index: 1;
}
.fsc-flight-path i {
position: relative;
z-index: 2;
background: white;
padding: 0 1rem;
color: #1a237e;
font-size: 1.5rem;
}
.fsc-flight-meta {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
padding: 1.5rem;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
.fsc-meta-item {
text-align: center;
}
.fsc-meta-label {
display: block;
color: #888;
font-size: 0.85rem;
margin-bottom: 0.25rem;
}
.fsc-meta-value {
font-size: 1.1rem;
font-weight: 500;
color: #333;
}
/* 错误信息 */
.fsc-error {
padding: 2rem;
text-align: center;
background: #ffebee;
border-radius: 8px;
border-left: 4px solid #c62828;
}
.fsc-error-icon {
font-size: 3rem;
color: #c62828;
margin-bottom: 1rem;
}
.fsc-error-title {
color: #c62828;
margin: 0 0 0.5rem 0;
font-size: 1.2rem;
}
.fsc-error-message {
color: #666;
margin: 0;
}
/* 页脚 */
.fsc-footer {
margin-top: 2rem;
padding-top: 1.5rem;
border-top: 1px solid #f0f0f0;
}
.fsc-disclaimer {
color: #888;
font-size: 0.85rem;
line-height: 1.5;
margin: 0;
display: flex;
align-items: flex-start;
gap: 0.5rem;
}
/* 响应式设计 */
@media (max-width: 768px) {
.fsc-flight-checker-wrapper {
padding: 1.5rem;
margin: 1rem auto;
}
.fsc-form-row {
grid-template-columns: 1fr;
gap: 1rem;
}
.fsc-flight-details {
grid-template-columns: 1fr;
gap: 1rem;
}
.fsc-flight-path {
display: none;
}
.fsc-form-actions {
flex-direction: column;
}
.fsc-submit-btn, .fsc-reset-btn {
width: 100%;
}
}
/* 紧凑布局 */
.fsc-flight-checker-wrapper.layout-compact {
max-width: 500px;
padding: 1.5rem;
}
.fsc-flight-checker-wrapper.layout-compact .fsc-form-row {
grid-template-columns: 1fr;
}
.fsc-flight-checker-wrapper.layout-compact .fsc-results {
padding: 1rem;
}
/* 详细布局 */
.fsc-flight-checker-wrapper.layout-detailed .fsc-flight-details {
grid-template-columns: 1fr auto 1fr;
}
.fsc-flight-checker-wrapper.layout-detailed .fsc-flight-meta {
grid-template-columns: repeat(4, 1fr);
}
4.4 前端交互脚本
在`assets
