首页 / 应用软件 / 实战教程,在WordPress中集成天气与地图显示插件

实战教程,在WordPress中集成天气与地图显示插件

实战教程:在WordPress中集成天气与地图显示插件

引言:为什么WordPress需要集成天气与地图功能?

在当今数字化时代,网站的功能丰富性直接关系到用户体验和网站价值。对于许多类型的WordPress网站来说,集成天气和地图功能可以显著提升实用性和用户粘性。旅游博客需要展示目的地天气,本地商家网站需要显示店铺位置,活动策划网站需要提供场地地图和天气信息——这些场景都说明了集成这些功能的必要性。

传统的解决方案是使用第三方小工具或iframe嵌入,但这些方法往往存在加载速度慢、样式不统一、功能受限等问题。通过WordPress代码二次开发实现这些功能,不仅可以获得更好的性能和控制权,还能确保与网站主题完美融合,提供一致的用户体验。

本教程将引导您完成在WordPress中集成天气与地图显示功能的完整过程,从API选择到代码实现,再到前端展示,为您提供一个完整的解决方案。

第一部分:准备工作与环境配置

1.1 选择合适的天气和地图API

在开始编码之前,我们需要选择合适的数据源。对于天气数据,有几个流行的API可供选择:

  1. OpenWeatherMap:提供免费层级的API调用,包含当前天气、预报和历史数据
  2. WeatherAPI:简单易用,免费套餐包含300万次调用/月
  3. AccuWeather:数据准确但免费层级限制较多

对于地图功能,主流选择包括:

  1. Google Maps API:功能强大但需要绑定信用卡(有免费额度)
  2. Mapbox:提供美观的地图样式和灵活的定制选项
  3. Leaflet + OpenStreetMap:完全开源免费的解决方案

考虑到成本和易用性,本教程将使用:

  • 天气数据:OpenWeatherMap API(免费版)
  • 地图显示:Leaflet + OpenStreetMap(完全免费)

1.2 注册API密钥

OpenWeatherMap注册步骤:

  1. 访问 OpenWeatherMap官网
  2. 点击"Sign Up"创建账户
  3. 登录后进入API Keys页面
  4. 生成新的API密钥并保存

Leaflet无需API密钥,可以直接使用。

1.3 WordPress开发环境准备

确保您具备以下环境:

  1. 本地或线上的WordPress安装(建议5.0以上版本)
  2. 代码编辑器(VS Code、Sublime Text等)
  3. FTP客户端或文件管理器(用于上传代码)
  4. 基本的PHP、JavaScript和HTML/CSS知识

1.4 创建自定义插件目录

为了避免主题更新导致代码丢失,我们将创建一个独立插件:

  1. 在WordPress的wp-content/plugins/目录下创建新文件夹weather-map-integration
  2. 在该文件夹中创建主插件文件weather-map-integration.php

第二部分:创建基础插件结构

2.1 插件头部信息

打开weather-map-integration.php,添加以下插件声明:

<?php
/**
 * Plugin Name: Weather & Map Integration
 * Plugin URI: https://yourwebsite.com/
 * Description: 在WordPress中集成天气与地图显示功能
 * Version: 1.0.0
 * Author: 您的名称
 * Author URI: https://yourwebsite.com/
 * License: GPL v2 or later
 * Text Domain: weather-map-integration
 */

// 防止直接访问
if (!defined('ABSPATH')) {
    exit;
}

2.2 定义插件常量

在插件头部信息后添加以下常量定义:

// 定义插件路径和URL常量
define('WMI_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('WMI_PLUGIN_URL', plugin_dir_url(__FILE__));

// 定义API密钥常量(在实际使用中应从设置页面获取)
define('WMI_OPENWEATHER_API_KEY', 'your_openweather_api_key_here');

// 插件版本
define('WMI_VERSION', '1.0.0');

2.3 创建插件主类

使用面向对象的方式组织插件代码:

class Weather_Map_Integration {
    
    private static $instance = null;
    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        $this->init_hooks();
    }
    
    private function init_hooks() {
        // 初始化钩子
        add_action('init', array($this, 'init'));
        add_action('admin_menu', array($this, 'add_admin_menu'));
        add_action('admin_init', array($this, 'register_settings'));
        add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_scripts'));
        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
        
        // 注册短代码
        add_shortcode('weather_display', array($this, 'weather_shortcode'));
        add_shortcode('map_display', array($this, 'map_shortcode'));
        add_shortcode('weather_map_combo', array($this, 'weather_map_combo_shortcode'));
    }
    
    public function init() {
        // 初始化代码
        load_plugin_textdomain('weather-map-integration', false, dirname(plugin_basename(__FILE__)) . '/languages');
    }
    
    // 其他方法将在后续部分添加
}

// 初始化插件
Weather_Map_Integration::get_instance();

第三部分:创建管理设置页面

3.1 添加管理菜单

在插件类中添加以下方法:

public function add_admin_menu() {
    add_menu_page(
        '天气与地图设置',
        '天气地图',
        'manage_options',
        'weather-map-settings',
        array($this, 'settings_page'),
        'dashicons-location-alt',
        80
    );
    
    add_submenu_page(
        'weather-map-settings',
        'API设置',
        'API设置',
        'manage_options',
        'weather-map-api-settings',
        array($this, 'api_settings_page')
    );
    
    add_submenu_page(
        'weather-map-settings',
        '显示设置',
        '显示设置',
        'manage_options',
        'weather-map-display-settings',
        array($this, 'display_settings_page')
    );
}

3.2 注册设置选项

public function register_settings() {
    // API设置
    register_setting('wmi_api_settings', 'wmi_openweather_api_key');
    register_setting('wmi_api_settings', 'wmi_default_city');
    register_setting('wmi_api_settings', 'wmi_default_country');
    
    // 显示设置
    register_setting('wmi_display_settings', 'wmi_temperature_unit');
    register_setting('wmi_display_settings', 'wmi_map_height');
    register_setting('wmi_display_settings', 'wmi_map_width');
    register_setting('wmi_display_settings', 'wmi_default_zoom');
    register_setting('wmi_display_settings', 'wmi_show_attribution');
    
    // API设置部分
    add_settings_section(
        'wmi_api_section',
        'API配置',
        array($this, 'api_section_callback'),
        'weather-map-api-settings'
    );
    
    add_settings_field(
        'wmi_openweather_api_key',
        'OpenWeatherMap API密钥',
        array($this, 'api_key_field_callback'),
        'weather-map-api-settings',
        'wmi_api_section'
    );
    
    add_settings_field(
        'wmi_default_city',
        '默认城市',
        array($this, 'default_city_field_callback'),
        'weather-map-api-settings',
        'wmi_api_section'
    );
    
    // 显示设置部分
    add_settings_section(
        'wmi_display_section',
        '显示设置',
        array($this, 'display_section_callback'),
        'weather-map-display-settings'
    );
    
    add_settings_field(
        'wmi_temperature_unit',
        '温度单位',
        array($this, 'temperature_unit_field_callback'),
        'weather-map-display-settings',
        'wmi_display_section'
    );
    
    // 更多设置字段...
}

public function api_section_callback() {
    echo '<p>配置天气和地图API的相关设置。请确保您已注册相应的API服务。</p>';
}

public function api_key_field_callback() {
    $api_key = get_option('wmi_openweather_api_key', '');
    echo '<input type="text" id="wmi_openweather_api_key" name="wmi_openweather_api_key" value="' . esc_attr($api_key) . '" class="regular-text" />';
    echo '<p class="description">请输入您的OpenWeatherMap API密钥。如果没有,请访问<a href="https://openweathermap.org/api" target="_blank">OpenWeatherMap官网</a>注册获取。</p>';
}

// 其他字段回调函数...

3.3 创建设置页面模板

public function api_settings_page() {
    if (!current_user_can('manage_options')) {
        return;
    }
    
    ?>
    <div class="wrap">
        <h1><?php echo esc_html(get_admin_page_title()); ?></h1>
        <form action="options.php" method="post">
            <?php
            settings_fields('wmi_api_settings');
            do_settings_sections('weather-map-api-settings');
            submit_button('保存设置');
            ?>
        </form>
    </div>
    <?php
}

public function display_settings_page() {
    if (!current_user_can('manage_options')) {
        return;
    }
    
    ?>
    <div class="wrap">
        <h1><?php echo esc_html(get_admin_page_title()); ?></h1>
        <form action="options.php" method="post">
            <?php
            settings_fields('wmi_display_settings');
            do_settings_sections('weather-map-display-settings');
            submit_button('保存设置');
            ?>
        </form>
    </div>
    <?php
}

第四部分:天气功能实现

4.1 创建天气数据获取类

在插件目录下创建includes/class-weather-data.php

<?php
if (!defined('ABSPATH')) {
    exit;
}

class WMI_Weather_Data {
    
    private $api_key;
    private $base_url = 'https://api.openweathermap.org/data/2.5/';
    
    public function __construct($api_key = '') {
        $this->api_key = $api_key ?: get_option('wmi_openweather_api_key', '');
    }
    
    /**
     * 获取当前天气数据
     */
    public function get_current_weather($city, $country = '', $units = 'metric') {
        $location = $city;
        if (!empty($country)) {
            $location .= ',' . $country;
        }
        
        $transient_key = 'wmi_current_weather_' . md5($location . $units);
        $cached_data = get_transient($transient_key);
        
        if ($cached_data !== false) {
            return $cached_data;
        }
        
        $url = $this->base_url . 'weather';
        $args = array(
            'q' => $location,
            'appid' => $this->api_key,
            'units' => $units,
            'lang' => $this->get_language_code()
        );
        
        $response = wp_remote_get(add_query_arg($args, $url));
        
        if (is_wp_error($response)) {
            return array('error' => $response->get_error_message());
        }
        
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        if (isset($data['cod']) && $data['cod'] != 200) {
            return array('error' => $data['message'] ?? '未知错误');
        }
        
        // 缓存数据10分钟
        set_transient($transient_key, $data, 10 * MINUTE_IN_SECONDS);
        
        return $data;
    }
    
    /**
     * 获取天气预报数据
     */
    public function get_forecast($city, $country = '', $units = 'metric', $days = 5) {
        $location = $city;
        if (!empty($country)) {
            $location .= ',' . $country;
        }
        
        $transient_key = 'wmi_forecast_' . md5($location . $units . $days);
        $cached_data = get_transient($transient_key);
        
        if ($cached_data !== false) {
            return $cached_data;
        }
        
        $url = $this->base_url . 'forecast';
        $args = array(
            'q' => $location,
            'appid' => $this->api_key,
            'units' => $units,
            'cnt' => $days * 8, // 每3小时一个数据点
            'lang' => $this->get_language_code()
        );
        
        $response = wp_remote_get(add_query_arg($args, $url));
        
        if (is_wp_error($response)) {
            return array('error' => $response->get_error_message());
        }
        
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        if (isset($data['cod']) && $data['cod'] != 200) {
            return array('error' => $data['message'] ?? '未知错误');
        }
        
        // 缓存数据30分钟
        set_transient($transient_key, $data, 30 * MINUTE_IN_SECONDS);
        
        return $data;
    }
    
    /**
     * 根据IP获取位置信息
     */
    public function get_location_by_ip() {
        $transient_key = 'wmi_location_ip_' . $_SERVER['REMOTE_ADDR'];
        $cached_data = get_transient($transient_key);
        
        if ($cached_data !== false) {
            return $cached_data;
        }
        
        // 使用ipapi.co服务(免费)
        $response = wp_remote_get('https://ipapi.co/json/');
        
        if (is_wp_error($response)) {
            return array('city' => 'Beijing', 'country' => 'CN');
        }
        
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        $location = array(
            'city' => $data['city'] ?? 'Beijing',
            'country' => $data['country'] ?? 'CN'
        );
        
        // 缓存24小时
        set_transient($transient_key, $location, 24 * HOUR_IN_SECONDS);
        
        return $location;
    }
    
    /**
     * 获取语言代码
     */
    private function get_language_code() {
        $locale = get_locale();
        $lang_map = array(
            'zh_CN' => 'zh_cn',
            'zh_TW' => 'zh_tw',
            'en_US' => 'en',
            'en_GB' => 'en',
            'es_ES' => 'es',
            'fr_FR' => 'fr',
            'de_DE' => 'de',
            'ja' => 'ja',
            'ko_KR' => 'kr'
        );
        
        return $lang_map[$locale] ?? 'en';
    }
    
    /**
     * 处理天气数据为前端可用格式
     */
    public function process_weather_data($weather_data) {
        if (isset($weather_data['error'])) {
            return $weather_data;
        }
        
        $processed = array(
            'location' => $weather_data['name'] . ', ' . ($weather_data['sys']['country'] ?? ''),
            'temperature' => round($weather_data['main']['temp']),
            'feels_like' => round($weather_data['main']['feels_like']),
            'description' => $weather_data['weather'][0]['description'],
            'icon' => $weather_data['weather'][0]['icon'],
            'humidity' => $weather_data['main']['humidity'],
            'pressure' => $weather_data['main']['pressure'],
            'wind_speed' => $weather_data['wind']['speed'],
            'wind_deg' => $weather_data['wind']['deg'],
            'sunrise' => date('H:i', $weather_data['sys']['sunrise']),
            'sunset' => date('H:i', $weather_data['sys']['sunset']),
            'timestamp' => time()
        );
        
        return $processed;
    }
}

4.2 创建天气显示短代码

在主插件类中添加天气短代码方法:

public function weather_shortcode($atts) {
    $atts = shortcode_atts(array(
        'city' => '',
        'country' => '',
        'units' => get_option('wmi_temperature_unit', 'metric'),
        'show_forecast' => 'false',
        'forecast_days' => 3,
        'layout' => 'compact', // compact, detailed, card
        'title' => '当前天气'
    ), $atts, 'weather_display');
    
    // 如果没有指定城市,尝试根据IP获取
    if (empty($atts['city'])) {
        $weather_data = new WMI_Weather_Data();
        $location = $weather_data->get_location_by_ip();
        $atts['city'] = $location['city'];
        $atts['country'] = $location['country'];
    }
    
    // 获取天气数据
    $weather_api = new WMI_Weather_Data();
    $current_weather = $weather_api->get_current_weather($atts['city'], $atts['country'], $atts['units']);
    
    if (isset($current_weather['error'])) {
        return '<div class="wmi-error">无法获取天气数据: ' . esc_html($current_weather['error']) . '</div>';
    }
    
    $processed_weather = $weather_api->process_weather_data($current_weather);
    
    // 获取天气预报(如果需要)
    $forecast_data = array();
    if ($atts['show_forecast'] === 'true') {
        $forecast = $weather_api->get_forecast($atts['city'], $atts['country'], $atts['units'], $atts['forecast_days']);

if (!isset($forecast['error'])) {

        $forecast_data = $this->process_forecast_data($forecast);
    }
}

// 生成输出HTML
ob_start();
?>
<div class="wmi-weather-container wmi-layout-<?php echo esc_attr($atts['layout']); ?>" 
     data-city="<?php echo esc_attr($atts['city']); ?>"
     data-country="<?php echo esc_attr($atts['country']); ?>"
     data-units="<?php echo esc_attr($atts['units']); ?>">
    
    <div class="wmi-weather-header">
        <h3 class="wmi-weather-title"><?php echo esc_html($atts['title']); ?></h3>
        <div class="wmi-location"><?php echo esc_html($processed_weather['location']); ?></div>
    </div>
    
    <div class="wmi-current-weather">
        <div class="wmi-weather-main">
            <div class="wmi-temperature">
                <span class="wmi-temp-value"><?php echo esc_html($processed_weather['temperature']); ?></span>
                <span class="wmi-temp-unit">°<?php echo $atts['units'] === 'metric' ? 'C' : 'F'; ?></span>
            </div>
            <div class="wmi-weather-icon">
                <img src="https://openweathermap.org/img/wn/<?php echo esc_attr($processed_weather['icon']); ?>@2x.png" 
                     alt="<?php echo esc_attr($processed_weather['description']); ?>">
            </div>
        </div>
        
        <div class="wmi-weather-details">
            <div class="wmi-weather-desc"><?php echo esc_html($processed_weather['description']); ?></div>
            <div class="wmi-weather-meta">
                <span class="wmi-feels-like">体感温度: <?php echo esc_html($processed_weather['feels_like']); ?>°</span>
                <span class="wmi-humidity">湿度: <?php echo esc_html($processed_weather['humidity']); ?>%</span>
                <span class="wmi-wind">风速: <?php echo esc_html($processed_weather['wind_speed']); ?> m/s</span>
            </div>
        </div>
    </div>
    
    <?php if (!empty($forecast_data)): ?>
    <div class="wmi-forecast">
        <h4 class="wmi-forecast-title"><?php echo esc_html($atts['forecast_days']); ?>天预报</h4>
        <div class="wmi-forecast-days">
            <?php foreach ($forecast_data as $day): ?>
            <div class="wmi-forecast-day">
                <div class="wmi-forecast-date"><?php echo esc_html($day['date']); ?></div>
                <div class="wmi-forecast-icon">
                    <img src="https://openweathermap.org/img/wn/<?php echo esc_attr($day['icon']); ?>.png" 
                         alt="<?php echo esc_attr($day['description']); ?>">
                </div>
                <div class="wmi-forecast-temp">
                    <span class="wmi-forecast-temp-max"><?php echo esc_html($day['temp_max']); ?>°</span>
                    <span class="wmi-forecast-temp-min"><?php echo esc_html($day['temp_min']); ?>°</span>
                </div>
            </div>
            <?php endforeach; ?>
        </div>
    </div>
    <?php endif; ?>
    
    <div class="wmi-weather-footer">
        <div class="wmi-sun-times">
            <span class="wmi-sunrise">日出: <?php echo esc_html($processed_weather['sunrise']); ?></span>
            <span class="wmi-sunset">日落: <?php echo esc_html($processed_weather['sunset']); ?></span>
        </div>
        <div class="wmi-update-time">
            更新时间: <?php echo date('H:i', $processed_weather['timestamp']); ?>
        </div>
    </div>
</div>
<?php

return ob_get_clean();

}

private function process_forecast_data($forecast_data) {

$daily_data = array();
$grouped_by_day = array();

// 按日期分组
foreach ($forecast_data['list'] as $item) {
    $date = date('Y-m-d', $item['dt']);
    if (!isset($grouped_by_day[$date])) {
        $grouped_by_day[$date] = array();
    }
    $grouped_by_day[$date][] = $item;
}

// 处理每天的数据
$count = 0;
foreach ($grouped_by_day as $date => $day_items) {
    if ($count >= 5) break; // 最多显示5天
    
    $temps = array();
    $icons = array();
    $descriptions = array();
    
    foreach ($day_items as $item) {
        $temps[] = $item['main']['temp'];
        $icons[] = $item['weather'][0]['icon'];
        $descriptions[] = $item['weather'][0]['description'];
    }
    
    // 获取最常见的图标和描述
    $icon_counts = array_count_values($icons);
    arsort($icon_counts);
    $most_common_icon = key($icon_counts);
    
    $desc_counts = array_count_values($descriptions);
    arsort($desc_counts);
    $most_common_desc = key($desc_counts);
    
    $daily_data[] = array(
        'date' => date('m/d', strtotime($date)),
        'day' => date('D', strtotime($date)),
        'temp_max' => round(max($temps)),
        'temp_min' => round(min($temps)),
        'icon' => $most_common_icon,
        'description' => $most_common_desc
    );
    
    $count++;
}

return $daily_data;

}


## 第五部分:地图功能实现

### 5.1 创建地图数据类

在插件目录下创建`includes/class-map-data.php`:

<?php
if (!defined('ABSPATH')) {

exit;

}

class WMI_Map_Data {


/**
 * 获取位置坐标
 */
public function get_coordinates($location) {
    $transient_key = 'wmi_coordinates_' . md5($location);
    $cached_data = get_transient($transient_key);
    
    if ($cached_data !== false) {
        return $cached_data;
    }
    
    // 使用Nominatim(OpenStreetMap的搜索服务)
    $url = 'https://nominatim.openstreetmap.org/search';
    $args = array(
        'q' => $location,
        'format' => 'json',
        'limit' => 1,
        'addressdetails' => 1
    );
    
    $response = wp_remote_get(add_query_arg($args, $url), array(
        'headers' => array(
            'User-Agent' => 'WordPress Weather Map Integration/1.0'
        )
    ));
    
    if (is_wp_error($response)) {
        return array('error' => $response->get_error_message());
    }
    
    $body = wp_remote_retrieve_body($response);
    $data = json_decode($body, true);
    
    if (empty($data)) {
        return array('error' => '未找到位置信息');
    }
    
    $coordinates = array(
        'lat' => $data[0]['lat'],
        'lon' => $data[0]['lon'],
        'display_name' => $data[0]['display_name'],
        'address' => $data[0]['address']
    );
    
    // 缓存30天
    set_transient($transient_key, $coordinates, 30 * DAY_IN_SECONDS);
    
    return $coordinates;
}

/**
 * 获取多个标记点
 */
public function get_multiple_markers($locations) {
    $markers = array();
    
    foreach ($locations as $location) {
        if (is_array($location) && isset($location['lat'], $location['lng'])) {
            $markers[] = array(
                'lat' => $location['lat'],
                'lng' => $location['lng'],
                'title' => $location['title'] ?? '',
                'description' => $location['description'] ?? ''
            );
        } else {
            $coords = $this->get_coordinates($location);
            if (!isset($coords['error'])) {
                $markers[] = array(
                    'lat' => $coords['lat'],
                    'lng' => $coords['lon'],
                    'title' => is_array($location) ? ($location['title'] ?? '') : $location,
                    'description' => $coords['display_name']
                );
            }
        }
    }
    
    return $markers;
}

/**
 * 计算地图边界
 */
public function calculate_bounds($markers) {
    if (empty($markers)) {
        return array(
            'south' => 0,
            'west' => 0,
            'north' => 0,
            'east' => 0
        );
    }
    
    $lats = array_column($markers, 'lat');
    $lngs = array_column($markers, 'lng');
    
    return array(
        'south' => min($lats),
        'west' => min($lngs),
        'north' => max($lats),
        'east' => max($lngs)
    );
}

}


### 5.2 创建地图显示短代码

在主插件类中添加地图短代码方法:

public function map_shortcode($atts) {

$atts = shortcode_atts(array(
    'location' => '',
    'lat' => '',
    'lng' => '',
    'zoom' => get_option('wmi_default_zoom', 13),
    'height' => get_option('wmi_map_height', '400px'),
    'width' => get_option('wmi_map_width', '100%'),
    'markers' => '', // JSON格式或逗号分隔
    'show_search' => 'false',
    'show_controls' => 'true',
    'map_style' => 'streets', // streets, satellite, terrain
    'title' => '位置地图'
), $atts, 'map_display');

// 生成唯一ID
$map_id = 'wmi-map-' . uniqid();

// 处理位置数据
$locations = array();

if (!empty($atts['markers'])) {
    // 尝试解析JSON
    $markers_json = json_decode($atts['markers'], true);
    if (json_last_error() === JSON_ERROR_NONE) {
        $locations = $markers_json;
    } else {
        // 逗号分隔的字符串
        $marker_list = explode(',', $atts['markers']);
        foreach ($marker_list as $marker) {
            $locations[] = trim($marker);
        }
    }
} elseif (!empty($atts['location'])) {
    $locations[] = $atts['location'];
} elseif (!empty($atts['lat']) && !empty($atts['lng'])) {
    $locations[] = array(
        'lat' => $atts['lat'],
        'lng' => $atts['lng'],
        'title' => $atts['title']
    );
} else {
    // 默认位置
    $weather_data = new WMI_Weather_Data();
    $default_location = $weather_data->get_location_by_ip();
    $locations[] = $default_location['city'] . ', ' . $default_location['country'];
}

// 获取坐标
$map_api = new WMI_Map_Data();
$markers = $map_api->get_multiple_markers($locations);

// 计算地图边界
$bounds = $map_api->calculate_bounds($markers);

ob_start();
?>
<div class="wmi-map-container" id="<?php echo esc_attr($map_id); ?>-container">
    <?php if (!empty($atts['title'])): ?>
    <h3 class="wmi-map-title"><?php echo esc_html($atts['title']); ?></h3>
    <?php endif; ?>
    
    <?php if ($atts['show_search'] === 'true'): ?>
    <div class="wmi-map-search">
        <input type="text" id="<?php echo esc_attr($map_id); ?>-search" 
               placeholder="搜索地点..." class="wmi-map-search-input">
        <button type="button" class="wmi-map-search-button">搜索</button>
    </div>
    <?php endif; ?>
    
    <div class="wmi-map" 
         id="<?php echo esc_attr($map_id); ?>"
         style="height: <?php echo esc_attr($atts['height']); ?>; 
                width: <?php echo esc_attr($atts['width']); ?>;">
    </div>
    
    <div class="wmi-map-info">
        <?php if (!empty($markers) && count($markers) === 1): ?>
        <div class="wmi-location-info">
            <strong><?php echo esc_html($markers[0]['title'] ?: '位置'); ?>:</strong>
            <span><?php echo esc_html($markers[0]['description']); ?></span>
        </div>
        <?php endif; ?>
    </div>
</div>

<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
    if (typeof L !== 'undefined') {
        initWmiMap('<?php echo esc_js($map_id); ?>', {
            markers: <?php echo json_encode($markers); ?>,
            bounds: <?php echo json_encode($bounds); ?>,
            zoom: <?php echo intval($atts['zoom']); ?>,
            showControls: <?php echo $atts['show_controls'] === 'true' ? 'true' : 'false'; ?>,
            mapStyle: '<?php echo esc_js($atts['map_style']); ?>'
        });
    }
});
</script>
<?php

return ob_get_clean();

}


### 5.3 创建组合短代码

public function weather_map_combo_shortcode($atts) {

$atts = shortcode_atts(array(
    'location' => '',
    'city' => '',
    'country' => '',
    'layout' => 'side-by-side', // side-by-side, map-above, weather-above
    'height' => '500px',
    'show_forecast' => 'true',
    'show_search' => 'true',
    'title' => '天气与位置'
), $atts, 'weather_map_combo');

// 确定位置
if (!empty($atts['location'])) {
    $location_parts = explode(',', $atts['location']);
    $atts['city'] = trim($location_parts[0]);
    if (isset($location_parts[1])) {
        $atts['country'] = trim($location_parts[1]);
    }
}

ob_start();
?>
<div class="wmi-combo-container wmi-layout-<?php echo esc_attr($atts['layout']); ?>">
    <h2 class="wmi-combo-title"><?php echo esc_html($atts['title']); ?></h2>
    
    <div class="wmi-combo-content">
        <div class="wmi-combo-weather">
            <?php 
            echo $this->weather_shortcode(array(
                'city' => $atts['city'],
                'country' => $atts['country'],
                'show_forecast' => $atts['show_forecast'],
                'layout' => 'detailed',
                'title' => ''
            ));
            ?>
        </div>
        
        <div class="wmi-combo-map">
            <?php
            $location_str = !empty($atts['country']) ? 
                $atts['city'] . ', ' . $atts['country'] : 
                $atts['city'];
            
            echo $this->map_shortcode(array(
                'location' => $location_str,
                'height' => $atts['height'],
                'show_search' => $atts['show_search'],
                'title' => ''
            ));
            ?>
        </div>
    </div>
</div>
<?php

return ob_get_clean();

}


## 第六部分:前端资源加载与样式

### 6.1 注册和加载脚本样式

在主插件类中添加以下方法:

public function enqueue_frontend_scripts() {

// 加载Leaflet地图库
wp_enqueue_style('leaflet-css', 'https://unpkg.com/leaflet@1.7.1/dist/leaflet.css', array(), '1.7.1');
wp_enqueue_script('leaflet-js', 'https://unpkg.com/leaflet@1.7.1/dist/leaflet.js', array(), '1.7.1', true);

// 加载插件样式
wp_enqueue_style('wmi-frontend-style', WMI_PLUGIN_URL . 'assets/css/frontend.css', array(), WMI_VERSION);

// 加载插件脚本
wp_enqueue_script('wmi-frontend-script', WMI_PLUGIN_URL . 'assets/js/frontend.js', array('jquery', 'leaflet-js'), WMI_VERSION, true);

// 本地化脚本
wp_localize_script('wmi-frontend-script', 'wmi_ajax', array(
    'ajax_url' => admin_url('admin-ajax.php'),
    'nonce' => wp_create_nonce('wmi_ajax_nonce'),
    'default_location' => $this->get_default_location(),
    'strings' => array(
        'loading' => __('加载中...', 'weather-map-integration'),
        'error' => __('发生错误', 'weather-map-integration'),
        'search_placeholder' => __('输入地点
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5074.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

工作时间:周一至周五,9:00-17:30,节假日休息
返回顶部