首页 / 教程文章 / WordPress小批量定制插件支持AR预览功能的集成教程

WordPress小批量定制插件支持AR预览功能的集成教程

WordPress小批量定制插件支持AR预览功能的集成教程

一、AR预览功能概述与准备工作

增强现实(AR)技术正在改变用户与数字内容的交互方式。在WordPress电商或展示类网站中,集成AR预览功能可以让用户通过手机摄像头查看产品在真实环境中的效果,显著提升用户体验和转化率。本教程将指导您开发一个支持AR预览的WordPress定制插件。

准备工作

  1. 环境要求

    • WordPress 5.0+
    • PHP 7.4+
    • 支持HTTPS的服务器(AR功能需要安全连接)
  2. 技术选型

    • 使用WebXR API进行AR功能开发
    • Three.js作为3D渲染引擎
    • Model-Viewer组件用于快速集成
  3. 插件基础结构

    wp-ar-preview/
    ├── wp-ar-preview.php          # 主插件文件
    ├── includes/
    │   ├── class-ar-model.php     # AR模型处理类
    │   ├── class-shortcode.php    # 短码处理类
    │   └── class-admin.php        # 后台管理类
    ├── assets/
    │   ├── js/
    │   ├── css/
    │   └── models/                # 3D模型存储目录
    ├── templates/                 # 前端模板
    └── uninstall.php              # 卸载脚本

二、创建插件主文件与基础配置

首先创建插件的主文件,这是插件的入口点:

<?php
/**
 * Plugin Name: WordPress AR预览插件
 * Plugin URI: https://yourwebsite.com/
 * Description: 为WordPress产品添加AR预览功能
 * Version: 1.0.0
 * Author: 您的名称
 * License: GPL v2 or later
 * Text Domain: wp-ar-preview
 */

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

// 定义插件常量
define('WP_AR_PREVIEW_VERSION', '1.0.0');
define('WP_AR_PREVIEW_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('WP_AR_PREVIEW_PLUGIN_URL', plugin_dir_url(__FILE__));
define('WP_AR_PREVIEW_MODEL_DIR', WP_AR_PREVIEW_PLUGIN_DIR . 'assets/models/');

// 自动加载类文件
spl_autoload_register(function ($class_name) {
    $prefix = 'WP_AR_Preview_';
    $base_dir = WP_AR_PREVIEW_PLUGIN_DIR . 'includes/';
    
    $len = strlen($prefix);
    if (strncmp($prefix, $class_name, $len) !== 0) {
        return;
    }
    
    $relative_class = substr($class_name, $len);
    $file = $base_dir . 'class-' . str_replace('_', '-', strtolower($relative_class)) . '.php';
    
    if (file_exists($file)) {
        require_once $file;
    }
});

// 初始化插件
function wp_ar_preview_init() {
    // 检查WordPress版本
    if (version_compare(get_bloginfo('version'), '5.0', '<')) {
        add_action('admin_notices', function() {
            echo '<div class="notice notice-error"><p>';
            echo __('AR预览插件需要WordPress 5.0或更高版本', 'wp-ar-preview');
            echo '</p></div>';
        });
        return;
    }
    
    // 初始化各个组件
    WP_AR_Preview_Admin::get_instance();
    WP_AR_Preview_Shortcode::get_instance();
    WP_AR_Preview_Model::get_instance();
}
add_action('plugins_loaded', 'wp_ar_preview_init');

// 激活插件时的操作
register_activation_hook(__FILE__, function() {
    // 创建必要的目录
    if (!file_exists(WP_AR_PREVIEW_MODEL_DIR)) {
        wp_mkdir_p(WP_AR_PREVIEW_MODEL_DIR);
    }
    
    // 添加默认选项
    add_option('wp_ar_preview_settings', array(
        'enable_ar' => '1',
        'default_model_scale' => '1',
        'ar_button_text' => '在您的空间中查看',
        'supported_formats' => array('glb', 'gltf')
    ));
});

// 停用插件时的清理操作
register_deactivation_hook(__FILE__, function() {
    // 清理临时数据
    delete_transient('wp_ar_preview_cache');
});

三、AR模型处理类实现

创建AR模型处理类,负责处理3D模型的上传、验证和存储:

<?php
/**
 * AR模型处理类
 * 负责处理3D模型文件的上传、验证和管理
 */

class WP_AR_Preview_Model {
    private static $instance = null;
    private $allowed_types = array('glb', 'gltf');
    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        add_action('wp_ajax_upload_ar_model', array($this, 'handle_model_upload'));
        add_action('wp_ajax_nopriv_upload_ar_model', array($this, 'handle_model_upload'));
    }
    
    /**
     * 处理模型上传
     */
    public function handle_model_upload() {
        // 验证nonce
        if (!wp_verify_nonce($_POST['nonce'], 'wp_ar_preview_upload')) {
            wp_die('安全验证失败');
        }
        
        // 检查文件上传
        if (!isset($_FILES['model_file'])) {
            wp_send_json_error('没有上传文件');
        }
        
        $file = $_FILES['model_file'];
        
        // 验证文件类型
        $file_ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        if (!in_array($file_ext, $this->allowed_types)) {
            wp_send_json_error('不支持的文件格式。请上传GLB或GLTF文件。');
        }
        
        // 验证文件大小(限制为50MB)
        $max_size = 50 * 1024 * 1024;
        if ($file['size'] > $max_size) {
            wp_send_json_error('文件太大。最大允许50MB。');
        }
        
        // 生成唯一文件名
        $filename = uniqid('model_') . '.' . $file_ext;
        $destination = WP_AR_PREVIEW_MODEL_DIR . $filename;
        
        // 移动上传的文件
        if (move_uploaded_file($file['tmp_name'], $destination)) {
            // 保存到数据库
            $model_id = $this->save_model_to_db(array(
                'filename' => $filename,
                'original_name' => $file['name'],
                'file_size' => $file['size'],
                'upload_date' => current_time('mysql')
            ));
            
            wp_send_json_success(array(
                'model_id' => $model_id,
                'filename' => $filename,
                'url' => WP_AR_PREVIEW_PLUGIN_URL . 'assets/models/' . $filename
            ));
        } else {
            wp_send_json_error('文件上传失败');
        }
    }
    
    /**
     * 保存模型信息到数据库
     */
    private function save_model_to_db($data) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'ar_models';
        
        // 创建表(如果不存在)
        $this->create_models_table();
        
        $wpdb->insert($table_name, $data);
        return $wpdb->insert_id;
    }
    
    /**
     * 创建模型表
     */
    private function create_models_table() {
        global $wpdb;
        $table_name = $wpdb->prefix . 'ar_models';
        $charset_collate = $wpdb->get_charset_collate();
        
        $sql = "CREATE TABLE IF NOT EXISTS $table_name (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            filename varchar(255) NOT NULL,
            original_name varchar(255) NOT NULL,
            file_size bigint(20) NOT NULL,
            upload_date datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
            PRIMARY KEY (id)
        ) $charset_collate;";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);
    }
    
    /**
     * 获取模型URL
     */
    public function get_model_url($model_id) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'ar_models';
        
        $filename = $wpdb->get_var($wpdb->prepare(
            "SELECT filename FROM $table_name WHERE id = %d",
            $model_id
        ));
        
        if ($filename) {
            return WP_AR_PREVIEW_PLUGIN_URL . 'assets/models/' . $filename;
        }
        
        return false;
    }
}

四、前端AR预览组件开发

创建前端AR预览组件,使用WebXR和Three.js实现AR功能:

/**
 * AR预览组件 - 前端JavaScript实现
 * 使用WebXR API和Three.js实现AR预览功能
 */

class ARPreview {
    constructor(containerId, modelUrl, options = {}) {
        this.container = document.getElementById(containerId);
        this.modelUrl = modelUrl;
        this.options = Object.assign({
            scale: 1.0,
            autoRotate: true,
            arScale: 'fixed',
            cameraControls: true
        }, options);
        
        this.scene = null;
        this.camera = null;
        this.renderer = null;
        this.model = null;
        this.xrSession = null;
        
        this.init();
    }
    
    /**
     * 初始化AR场景
     */
    async init() {
        // 检查WebXR支持
        if (!navigator.xr) {
            this.showError('您的浏览器不支持WebXR。请使用最新版的Chrome或Edge。');
            return;
        }
        
        // 创建Three.js场景
        this.scene = new THREE.Scene();
        this.scene.background = new THREE.Color(0xffffff);
        
        // 创建相机
        this.camera = new THREE.PerspectiveCamera(
            60, 
            this.container.clientWidth / this.container.clientHeight, 
            0.1, 
            1000
        );
        
        // 创建渲染器
        this.renderer = new THREE.WebGLRenderer({ 
            antialias: true,
            alpha: true 
        });
        this.renderer.setSize(
            this.container.clientWidth, 
            this.container.clientHeight
        );
        this.renderer.xr.enabled = true;
        this.container.appendChild(this.renderer.domElement);
        
        // 添加光源
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.8);
        this.scene.add(ambientLight);
        
        const directionalLight = new THREE.DirectionalLight(0xffffff, 0.6);
        directionalLight.position.set(1, 1, 1);
        this.scene.add(directionalLight);
        
        // 加载3D模型
        await this.loadModel();
        
        // 添加AR按钮
        this.createARButton();
        
        // 开始渲染循环
        this.renderer.setAnimationLoop(() => {
            this.render();
        });
        
        // 处理窗口大小变化
        window.addEventListener('resize', () => this.onWindowResize());
    }
    
    /**
     * 加载3D模型
     */
    async loadModel() {
        return new Promise((resolve, reject) => {
            const loader = new THREE.GLTFLoader();
            
            loader.load(
                this.modelUrl,
                (gltf) => {
                    this.model = gltf.scene;
                    this.model.scale.set(
                        this.options.scale,
                        this.options.scale,
                        this.options.scale
                    );
                    
                    // 居中模型
                    const box = new THREE.Box3().setFromObject(this.model);
                    const center = box.getCenter(new THREE.Vector3());
                    this.model.position.sub(center);
                    
                    this.scene.add(this.model);
                    resolve();
                },
                (progress) => {
                    // 加载进度回调
                    console.log(`模型加载进度: ${(progress.loaded / progress.total * 100).toFixed(2)}%`);
                },
                (error) => {
                    console.error('模型加载失败:', error);
                    reject(error);
                }
            );
        });
    }
    
    /**
     * 创建AR按钮
     */
    createARButton() {
        const button = document.createElement('button');
        button.id = 'ar-button';
        button.textContent = '👁️ AR预览';
        button.style.cssText = `
            position: absolute;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            padding: 12px 24px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            border-radius: 30px;
            font-size: 16px;
            cursor: pointer;
            z-index: 1000;
            box-shadow: 0 4px 15px rgba(0,0,0,0.2);
        `;
        
        button.addEventListener('click', () => this.enterAR());
        this.container.appendChild(button);
    }
    
    /**
     * 进入AR模式
     */
    async enterAR() {
        try {
            // 请求AR会话
            const session = await navigator.xr.requestSession('immersive-ar', {
                requiredFeatures: ['hit-test'],
                optionalFeatures: ['dom-overlay'],
                domOverlay: { root: this.container }
            });
            
            this.xrSession = session;
            this.renderer.xr.setSession(session);
            
            // 创建AR控制器
            this.controller = this.renderer.xr.getController(0);
            this.scene.add(this.controller);
            
            // 添加点击事件放置模型
            this.controller.addEventListener('select', () => this.placeModel());
            
            // 会话结束事件
            session.addEventListener('end', () => {
                this.xrSession = null;
            });
            
        } catch (error) {
            console.error('无法启动AR会话:', error);
            this.showError('无法启动AR功能。请确保设备支持AR并已授予相机权限。');
        }
    }
    
    /**
     * 放置模型到AR空间
     */
    placeModel() {
        if (!this.model || !this.controller) return;
        
        // 创建模型副本
        const modelClone = this.model.clone();
        
        // 使用控制器位置
        modelClone.position.copy(this.controller.position);
        
        // 随机旋转
        modelClone.rotation.y = Math.random() * Math.PI * 2;
        
        this.scene.add(modelClone);
    }
    
    /**
     * 渲染循环
     */
    render() {
        if (this.model && this.options.autoRotate && !this.xrSession) {
            this.model.rotation.y += 0.005;
        }
        
        this.renderer.render(this.scene, this.camera);
    }
    
    /**
     * 窗口大小变化处理
     */
    onWindowResize() {
        this.camera.aspect = this.container.clientWidth / this.container.clientHeight;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(
            this.container.clientWidth, 
            this.container.clientHeight
        );
    }
    
    /**
     * 显示错误信息
     */
    showError(message) {
        const errorDiv = document.createElement('div');
        errorDiv.style.cssText = `
            padding: 20px;
            background: #fee;
            border: 1px solid #f99;
            border-radius: 5px;
            margin: 10px 0;
            color: #c00;
        `;
        errorDiv.textContent = message;
        this.container.appendChild(errorDiv);
    }
}

// 导出到全局作用域
window.ARPreview = ARPreview;

五、短码系统与后台管理

创建短码系统和后台管理界面:

<?php
/**
 * 短码处理类
 * 提供[ar_preview]短码用于在文章和页面中插入AR预览
 */

class WP_AR_Preview_Shortcode {
    private static $instance = null;
    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        add_shortcode('ar_preview', array($this, 'render_shortcode'));
        add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
    }
    
    /**
     * 渲染AR预览短码
     */
    public function render_shortcode($atts) {
        $atts = shortcode_atts(array(
            'model_id' => 0,
            'width' => '100%',
            'height' => '500px',
            'scale' => '1',
            'auto_rotate' => 'true',
            'title' => 'AR预览'
        ), $atts, 'ar_preview');
        
        // 验证模型ID
        $model_id = intval($atts['model_id']);
        if ($model_id <= 0) {
            return '<div class="ar-error">请提供有效的模型ID</div>';
        }
        
        // 获取模型URL
        $model_manager = WP_AR_Preview_Model::get_instance();
        $model_url = $model_manager->get_model_url($model_id);
        
        if (!$model_url) {
            return '<div class="ar-error">找不到指定的3D模型</div>';
        }
        
        // 生成唯一容器ID
        $container_id = 'ar-container-' . uniqid();
        
        // 输出HTML结构
        ob_start();
        ?>
        <div class="ar-preview-wrapper">
            <h3 class="ar-title"><?php echo esc_html($atts['title']); ?></h3>
            <div id="<?php echo esc_attr($container_id); ?>" 
                 class="ar-viewer" 
                 style="width: <?php echo esc_attr($atts['width']); ?>; 

height: <?php echo esc_attr($atts['height']); ?>;

                    position: relative; 
                    border-radius: 8px; 
                    overflow: hidden; 
                    background: #f5f5f5;">
        </div>
        <div class="ar-instructions" style="margin-top: 10px; font-size: 14px; color: #666;">
            <p>💡 提示:点击"AR预览"按钮,使用手机摄像头在真实环境中查看模型</p>
        </div>
    </div>
    
    <script type="module">
        document.addEventListener('DOMContentLoaded', function() {
            // 等待Three.js和相关依赖加载完成
            if (typeof THREE !== 'undefined' && typeof ARPreview !== 'undefined') {
                new ARPreview('<?php echo esc_js($container_id); ?>', '<?php echo esc_js($model_url); ?>', {
                    scale: <?php echo floatval($atts['scale']); ?>,
                    autoRotate: <?php echo $atts['auto_rotate'] === 'true' ? 'true' : 'false'; ?>,
                    arScale: 'fixed'
                });
            } else {
                console.error('AR预览组件依赖未正确加载');
            }
        });
    </script>
    <?php
    return ob_get_clean();
}

/**
 * 加载前端脚本和样式
 */
public function enqueue_scripts() {
    // 只在需要时加载
    if (!has_shortcode(get_post()->post_content, 'ar_preview')) {
        return;
    }
    
    // 加载Three.js
    wp_enqueue_script(
        'three-js',
        'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js',
        array(),
        'r128',
        true
    );
    
    // 加载GLTFLoader
    wp_enqueue_script(
        'three-gltf-loader',
        WP_AR_PREVIEW_PLUGIN_URL . 'assets/js/GLTFLoader.js',
        array('three-js'),
        '1.0.0',
        true
    );
    
    // 加载WebXR polyfill(如果需要)
    wp_enqueue_script(
        'webxr-polyfill',
        'https://cdn.jsdelivr.net/npm/webxr-polyfill@latest/build/webxr-polyfill.js',
        array(),
        '1.0.0',
        true
    );
    
    // 加载主AR脚本
    wp_enqueue_script(
        'wp-ar-preview-frontend',
        WP_AR_PREVIEW_PLUGIN_URL . 'assets/js/ar-preview.js',
        array('three-js', 'three-gltf-loader'),
        WP_AR_PREVIEW_VERSION,
        true
    );
    
    // 加载样式
    wp_enqueue_style(
        'wp-ar-preview-style',
        WP_AR_PREVIEW_PLUGIN_URL . 'assets/css/ar-style.css',
        array(),
        WP_AR_PREVIEW_VERSION
    );
}

}


## 六、后台管理界面开发

创建后台管理界面,允许用户上传和管理3D模型:

<?php
/**

  • 后台管理类
  • 提供插件设置页面和模型管理功能
    */

class WP_AR_Preview_Admin {

private static $instance = null;

public static function get_instance() {
    if (null === self::$instance) {
        self::$instance = new self();
    }
    return self::$instance;
}

private function __construct() {
    add_action('admin_menu', array($this, 'add_admin_menu'));
    add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
    add_action('wp_ajax_get_models_list', array($this, 'ajax_get_models_list'));
}

/**
 * 添加管理菜单
 */
public function add_admin_menu() {
    add_menu_page(
        'AR预览设置',
        'AR预览',
        'manage_options',
        'wp-ar-preview',
        array($this, 'render_admin_page'),
        'dashicons-visibility',
        30
    );
    
    add_submenu_page(
        'wp-ar-preview',
        '模型管理',
        '模型管理',
        'manage_options',
        'wp-ar-models',
        array($this, 'render_models_page')
    );
}

/**
 * 渲染设置页面
 */
public function render_admin_page() {
    $settings = get_option('wp_ar_preview_settings', array());
    ?>
    <div class="wrap">
        <h1>AR预览插件设置</h1>
        
        <form method="post" action="options.php">
            <?php settings_fields('wp_ar_preview_settings_group'); ?>
            
            <table class="form-table">
                <tr>
                    <th scope="row">启用AR功能</th>
                    <td>
                        <label>
                            <input type="checkbox" name="wp_ar_preview_settings[enable_ar]" 
                                value="1" <?php checked(1, $settings['enable_ar'] ?? 1); ?>>
                            启用增强现实预览功能
                        </label>
                    </td>
                </tr>
                
                <tr>
                    <th scope="row">默认模型缩放</th>
                    <td>
                        <input type="number" name="wp_ar_preview_settings[default_model_scale]" 
                            value="<?php echo esc_attr($settings['default_model_scale'] ?? 1); ?>" 
                            step="0.1" min="0.1" max="10">
                        <p class="description">设置3D模型的默认显示大小</p>
                    </td>
                </tr>
                
                <tr>
                    <th scope="row">AR按钮文字</th>
                    <td>
                        <input type="text" name="wp_ar_preview_settings[ar_button_text]" 
                            value="<?php echo esc_attr($settings['ar_button_text'] ?? '在您的空间中查看'); ?>"
                            class="regular-text">
                    </td>
                </tr>
                
                <tr>
                    <th scope="row">支持的格式</th>
                    <td>
                        <label>
                            <input type="checkbox" name="wp_ar_preview_settings[supported_formats][]" 
                                value="glb" <?php echo in_array('glb', $settings['supported_formats'] ?? ['glb', 'gltf']) ? 'checked' : ''; ?>>
                            .glb (二进制GLTF)
                        </label><br>
                        <label>
                            <input type="checkbox" name="wp_ar_preview_settings[supported_formats][]" 
                                value="gltf" <?php echo in_array('gltf', $settings['supported_formats'] ?? ['glb', 'gltf']) ? 'checked' : ''; ?>>
                            .gltf (JSON格式)
                        </label>
                    </td>
                </tr>
            </table>
            
            <?php submit_button(); ?>
        </form>
        
        <div class="card">
            <h2>使用说明</h2>
            <ol>
                <li>在"模型管理"页面上传3D模型文件(支持.glb和.gltf格式)</li>
                <li>在文章或页面中使用短码:[ar_preview model_id="1"]</li>
                <li>短码参数说明:
                    <ul>
                        <li><code>model_id</code>: 模型ID(必填)</li>
                        <li><code>width</code>: 预览区宽度,默认100%</li>
                        <li><code>height</code>: 预览区高度,默认500px</li>
                        <li><code>scale</code>: 模型缩放比例,默认1</li>
                        <li><code>title</code>: 预览标题</li>
                    </ul>
                </li>
            </ol>
        </div>
    </div>
    <?php
}

/**
 * 渲染模型管理页面
 */
public function render_models_page() {
    // 处理模型上传
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['ar_model'])) {
        $this->handle_model_upload();
    }
    
    // 处理模型删除
    if (isset($_GET['delete_model'])) {
        $this->handle_model_delete(intval($_GET['delete_model']));
    }
    ?>
    <div class="wrap">
        <h1>3D模型管理</h1>
        
        <!-- 上传表单 -->
        <div class="card" style="margin-bottom: 20px;">
            <h2>上传新模型</h2>
            <form method="post" enctype="multipart/form-data">
                <?php wp_nonce_field('wp_ar_preview_upload', 'ar_upload_nonce'); ?>
                
                <table class="form-table">
                    <tr>
                        <th scope="row">选择模型文件</th>
                        <td>
                            <input type="file" name="ar_model" accept=".glb,.gltf" required>
                            <p class="description">支持GLB和GLTF格式,最大50MB</p>
                        </td>
                    </tr>
                    
                    <tr>
                        <th scope="row">模型名称</th>
                        <td>
                            <input type="text" name="model_name" class="regular-text" 
                                placeholder="例如:沙发模型" required>
                        </td>
                    </tr>
                    
                    <tr>
                        <th scope="row">模型描述</th>
                        <td>
                            <textarea name="model_description" rows="3" class="large-text"></textarea>
                        </td>
                    </tr>
                </table>
                
                <?php submit_button('上传模型'); ?>
            </form>
        </div>
        
        <!-- 模型列表 -->
        <div class="card">
            <h2>已上传的模型</h2>
            <?php $this->render_models_table(); ?>
        </div>
    </div>
    <?php
}

/**
 * 渲染模型表格
 */
private function render_models_table() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'ar_models';
    
    $models = $wpdb->get_results("SELECT * FROM $table_name ORDER BY upload_date DESC");
    
    if (empty($models)) {
        echo '<p>暂无模型,请先上传。</p>';
        return;
    }
    ?>
    <table class="wp-list-table widefat fixed striped">
        <thead>
            <tr>
                <th>ID</th>
                <th>文件名</th>
                <th>原始名称</th>
                <th>文件大小</th>
                <th>上传时间</th>
                <th>短码</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($models as $model): ?>
            <tr>
                <td><?php echo $model->id; ?></td>
                <td><?php echo esc_html($model->filename); ?></td>
                <td><?php echo esc_html($model->original_name); ?></td>
                <td><?php echo size_format($model->file_size); ?></td>
                <td><?php echo date('Y-m-d H:i', strtotime($model->upload_date)); ?></td>
                <td>
                    <code>[ar_preview model_id="<?php echo $model->id; ?>"]</code>
                    <button type="button" class="button button-small copy-shortcode" 
                        data-shortcode='[ar_preview model_id="<?php echo $model->id; ?>"]'>
                        复制
                    </button>
                </td>
                <td>
                    <a href="<?php echo WP_AR_PREVIEW_PLUGIN_URL . 'assets/models/' . $model->filename; ?>" 
                       class="button" download>下载</a>
                    <a href="?page=wp-ar-models&delete_model=<?php echo $model->id; ?>" 
                       class="button button-link-delete" 
                       onclick="return confirm('确定要删除这个模型吗?')">删除</a>
                </td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
    
    <script>
    jQuery(document).ready(function($) {
        $('.copy-shortcode').click(function() {
            var shortcode = $(this).data('shortcode');
            navigator.clipboard.writeText(shortcode).then(function() {
                alert('短码已复制到剪贴板!');
            });
        });
    });
    </script>
    <?php
}

/**
 * 处理模型上传
 */
private function handle_model_upload() {
    if (!wp_verify_nonce($_POST['ar_upload_nonce'], 'wp_ar_preview_upload')) {
        wp_die('安全验证失败');
    }
    
    if (!current_user_can('upload_files')) {
        wp_die('您没有上传文件的权限');
    }
    
    $model_manager = WP_AR_Preview_Model::get_instance();
    
    // 模拟$_FILES结构
    $file = array(
        'name' => $_FILES['ar_model']['name'],
        'type' => $_FILES['ar_model']['type'],
        'tmp_name' => $_FILES['ar_model']['tmp_name'],
        'error' => $_FILES['ar_model']['error'],
        'size' => $_FILES['ar_model']['size']
    );
    
    $_FILES['model_file'] = $file;
    
    // 调用模型处理类的上传方法
    $model_manager->handle_model_upload();
}

/**
 * 处理模型删除
 */
private function handle_model_delete($model_id) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'ar_models';
    
    // 获取文件名
    $filename = $wpdb->get_var($wpdb->prepare(
        "SELECT filename FROM $table_name WHERE id = %d",
        $model_id
    ));
    
    if ($filename) {
        // 删除文件
        $file_path = WP_AR_PREVIEW_MODEL_DIR . $filename;
        if (file_exists($file_path)) {
            unlink($file_path);
        }
        
        // 删除数据库记录
        $wpdb->delete($table_name, array('id' => $model_id));
        
        echo '<div class="notice notice-success"><p>模型已删除</p></div>';
    }
}

/**
 * 加载后台脚本
 */
public function enqueue_admin_scripts($hook) {
    if (strpos($hook, 'wp-ar-preview') === false) {
        return;
    }
    
    wp_enqueue_script(
        'wp-ar-preview-admin',
        WP_AR_PREVIEW_PLUGIN_URL . 'assets/js/admin.js',
        array('jquery'),
        WP_AR_PREVIEW_VERSION,
        true
    );
    
    wp_enqueue_style(
        'wp-ar-preview-admin-style',
        WP_AR_PREVIEW_PLUGIN_URL . 'assets/css/admin.css',
        array(),
        WP_AR_PREVIEW_VERSION
    );
}

}


## 七、CSS样式文件

创建前端样式文件,美化AR预览界面:

/ assets/css/ar-style.css /

/ AR预览容器样式 /
.ar-preview-wrapper {

margin: 20px 0;
border: 1px solid #e0e0e0;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
background: white;

}

.ar-title {

padding: 15px 20px;
margin: 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
font-size: 18px;
font-weight: 600;

}

.ar-viewer {

position: relative;
min-height: 400px;

}

/ 加载状态 /
.ar-loading {

position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
color: #666;

}

.ar-loading-spinner {

display: inline-block;
width: 40px;
height: 40px;
border: 3px solid #f3f3f3;
border-top: 3px solid #667eea;
border-radius: 50%;
animation: ar-spin 1s linear infinite;
margin-bottom: 10px;

}

@keyframes ar-spin {

0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }

}

/ AR按钮样式 /

ar-button {

transition: all 0.3s ease;

}

ar-button:hover {

transform: translateX(-50%) scale(1.05);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);

}

ar-button:active {

transform: translateX(-50%) scale(0.95);

}

/ 错误提示 /
.ar-error {

padding: 20px;
background: #fff5f5;
border: 1px solid #feb2b2;
border-radius: 8px;
color: #c53030;
text-align: center;

}

/ 响应式设计 /
@media (max-width: 768px) {

.ar-preview-wrapper {
    margin: 10px 0;
    border-radius: 8px;
}

.ar-title {
    padding: 12px 15px;
    font-size: 16px;
}

.ar-viewer {
    min-height: 300px;
}

}

/ 模型控制面板 /
.ar-controls {

position: absolute;
bottom: 70px;
left: 20px;
display: flex;
gap: 10px;
z-index: 100;

}

.control-button {

width: 40px;
height: 40px;
border-radius: 50%;
background: white;
border: none;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/6237.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

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