首页 / 应用软件 / WordPress高级教程,开发集成在线问卷调查与自动报告生成器

WordPress高级教程,开发集成在线问卷调查与自动报告生成器

WordPress高级教程:开发集成在线问卷调查与自动报告生成器

引言:WordPress作为企业级应用开发平台

WordPress早已超越了简单的博客系统范畴,成为全球最受欢迎的内容管理系统(CMS),驱动着超过40%的网站。其强大的插件架构、丰富的API接口和庞大的开发者社区,使得WordPress能够胜任各种复杂的企业级应用开发。本教程将深入探讨如何通过WordPress代码二次开发,实现一个集在线问卷调查与自动报告生成器于一体的高级功能模块。

在当今数据驱动的商业环境中,问卷调查和数据分析工具已成为企业决策的重要支撑。传统上,企业可能需要购买昂贵的专业调查工具或委托定制开发,而通过WordPress二次开发,我们可以以更低的成本、更高的集成度实现这一功能,同时充分利用WordPress的用户管理、权限控制和内容展示能力。

系统架构设计

功能需求分析

在开始开发之前,我们需要明确系统的核心需求:

  1. 问卷调查功能

    • 支持多种题型(单选、多选、文本输入、评分等)
    • 问题逻辑跳转
    • 问卷分页与进度保存
    • 响应式设计,适配移动设备
  2. 报告生成功能

    • 基于问卷结果的自动分析
    • 可视化图表生成
    • 可定制的报告模板
    • 多种格式导出(PDF、Word、HTML)
  3. 管理功能

    • 问卷创建与管理界面
    • 数据收集与统计分析
    • 用户权限与访问控制
    • 报告模板管理

技术架构设计

我们将采用分层架构设计,确保系统的可维护性和扩展性:

  1. 数据层:使用WordPress自定义数据表存储问卷、回答和报告数据
  2. 业务逻辑层:处理问卷逻辑、数据分析和报告生成
  3. 表示层:前端界面和用户交互
  4. 集成层:与WordPress核心功能(用户、权限、主题)的集成

数据库设计与实现

自定义数据表设计

虽然WordPress提供了自定义文章类型(CPT)和元数据存储机制,但对于问卷调查这种结构化数据,我们建议创建专门的数据表以提高查询效率。

-- 问卷主表
CREATE TABLE wp_surveys (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    description TEXT,
    status ENUM('draft', 'published', 'closed') DEFAULT 'draft',
    created_by INT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    settings TEXT, -- JSON格式存储问卷设置
    FOREIGN KEY (created_by) REFERENCES wp_users(ID)
);

-- 问题表
CREATE TABLE wp_survey_questions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    survey_id INT NOT NULL,
    question_text TEXT NOT NULL,
    question_type ENUM('single_choice', 'multiple_choice', 'text', 'rating', 'matrix') NOT NULL,
    options TEXT, -- JSON格式存储选项
    is_required BOOLEAN DEFAULT FALSE,
    sort_order INT DEFAULT 0,
    logic_rules TEXT, -- JSON格式存储逻辑跳转规则
    FOREIGN KEY (survey_id) REFERENCES wp_surveys(id) ON DELETE CASCADE
);

-- 回答表
CREATE TABLE wp_survey_responses (
    id INT AUTO_INCREMENT PRIMARY KEY,
    survey_id INT NOT NULL,
    user_id INT,
    session_id VARCHAR(100),
    started_at DATETIME,
    completed_at DATETIME,
    ip_address VARCHAR(45),
    user_agent TEXT,
    FOREIGN KEY (survey_id) REFERENCES wp_surveys(id),
    FOREIGN KEY (user_id) REFERENCES wp_users(ID)
);

-- 答案详情表
CREATE TABLE wp_survey_answers (
    id INT AUTO_INCREMENT PRIMARY KEY,
    response_id INT NOT NULL,
    question_id INT NOT NULL,
    answer_value TEXT,
    FOREIGN KEY (response_id) REFERENCES wp_survey_responses(id) ON DELETE CASCADE,
    FOREIGN KEY (question_id) REFERENCES wp_survey_questions(id)
);

-- 报告表
CREATE TABLE wp_survey_reports (
    id INT AUTO_INCREMENT PRIMARY KEY,
    survey_id INT NOT NULL,
    title VARCHAR(255) NOT NULL,
    report_type ENUM('summary', 'individual', 'comparative') NOT NULL,
    template_id INT,
    generated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    content LONGTEXT, -- 报告内容,可以是HTML或序列化数据
    file_path VARCHAR(500), -- 导出文件路径
    FOREIGN KEY (survey_id) REFERENCES wp_surveys(id)
);

数据库操作类封装

为了与WordPress数据库操作保持一致,我们创建一个专门的数据库操作类:

<?php
/**
 * 问卷调查数据库操作类
 */
class Survey_DB {
    
    private $wpdb;
    private $charset_collate;
    
    public function __construct() {
        global $wpdb;
        $this->wpdb = $wpdb;
        $this->charset_collate = $wpdb->get_charset_collate();
    }
    
    /**
     * 创建数据表
     */
    public function create_tables() {
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        
        // 问卷主表
        $sql = "CREATE TABLE {$this->wpdb->prefix}surveys (
            id INT AUTO_INCREMENT PRIMARY KEY,
            title VARCHAR(255) NOT NULL,
            description TEXT,
            status ENUM('draft', 'published', 'closed') DEFAULT 'draft',
            created_by INT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            settings TEXT,
            FOREIGN KEY (created_by) REFERENCES {$this->wpdb->prefix}users(ID)
        ) {$this->charset_collate};";
        
        dbDelta($sql);
        
        // 其他表的创建代码类似...
    }
    
    /**
     * 获取问卷列表
     */
    public function get_surveys($args = array()) {
        $defaults = array(
            'status' => 'published',
            'per_page' => 10,
            'page' => 1,
            'orderby' => 'created_at',
            'order' => 'DESC'
        );
        
        $args = wp_parse_args($args, $defaults);
        
        $offset = ($args['page'] - 1) * $args['per_page'];
        
        $sql = $this->wpdb->prepare(
            "SELECT * FROM {$this->wpdb->prefix}surveys 
            WHERE status = %s 
            ORDER BY {$args['orderby']} {$args['order']} 
            LIMIT %d OFFSET %d",
            $args['status'],
            $args['per_page'],
            $offset
        );
        
        return $this->wpdb->get_results($sql);
    }
    
    /**
     * 保存问卷回答
     */
    public function save_response($survey_id, $user_id, $answers) {
        // 开启事务
        $this->wpdb->query('START TRANSACTION');
        
        try {
            // 保存回答主记录
            $response_data = array(
                'survey_id' => $survey_id,
                'user_id' => $user_id,
                'completed_at' => current_time('mysql'),
                'ip_address' => $this->get_client_ip(),
                'user_agent' => $_SERVER['HTTP_USER_AGENT']
            );
            
            $this->wpdb->insert(
                "{$this->wpdb->prefix}survey_responses",
                $response_data
            );
            
            $response_id = $this->wpdb->insert_id;
            
            // 保存每个问题的答案
            foreach ($answers as $question_id => $answer) {
                $answer_data = array(
                    'response_id' => $response_id,
                    'question_id' => $question_id,
                    'answer_value' => is_array($answer) ? json_encode($answer) : $answer
                );
                
                $this->wpdb->insert(
                    "{$this->wpdb->prefix}survey_answers",
                    $answer_data
                );
            }
            
            // 提交事务
            $this->wpdb->query('COMMIT');
            
            return $response_id;
            
        } catch (Exception $e) {
            // 回滚事务
            $this->wpdb->query('ROLLBACK');
            return false;
        }
    }
    
    /**
     * 获取客户端IP
     */
    private function get_client_ip() {
        $ipaddress = '';
        if (isset($_SERVER['HTTP_CLIENT_IP']))
            $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
        else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
            $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
        else if(isset($_SERVER['HTTP_X_FORWARDED']))
            $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
        else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
            $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
        else if(isset($_SERVER['HTTP_FORWARDED']))
            $ipaddress = $_SERVER['HTTP_FORWARDED'];
        else if(isset($_SERVER['REMOTE_ADDR']))
            $ipaddress = $_SERVER['REMOTE_ADDR'];
        else
            $ipaddress = 'UNKNOWN';
        return $ipaddress;
    }
}
?>

问卷创建与管理模块

后台管理界面开发

我们将创建一个完整的后台管理界面,用于问卷的创建、编辑和管理:

<?php
/**
 * 问卷调查管理类
 */
class Survey_Admin {
    
    private $db;
    
    public function __construct() {
        $this->db = new Survey_DB();
        
        // 添加管理菜单
        add_action('admin_menu', array($this, 'add_admin_menu'));
        
        // 注册管理页面脚本
        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
    }
    
    /**
     * 添加管理菜单
     */
    public function add_admin_menu() {
        // 主菜单
        add_menu_page(
            '问卷调查管理',
            '问卷调查',
            'manage_options',
            'survey-manager',
            array($this, 'render_main_page'),
            'dashicons-feedback',
            30
        );
        
        // 子菜单
        add_submenu_page(
            'survey-manager',
            '所有问卷',
            '所有问卷',
            'manage_options',
            'survey-manager',
            array($this, 'render_main_page')
        );
        
        add_submenu_page(
            'survey-manager',
            '新建问卷',
            '新建问卷',
            'manage_options',
            'survey-new',
            array($this, 'render_new_survey_page')
        );
        
        add_submenu_page(
            'survey-manager',
            '报告生成',
            '报告生成',
            'manage_options',
            'survey-reports',
            array($this, 'render_reports_page')
        );
        
        add_submenu_page(
            'survey-manager',
            '设置',
            '设置',
            'manage_options',
            'survey-settings',
            array($this, 'render_settings_page')
        );
    }
    
    /**
     * 渲染主页面
     */
    public function render_main_page() {
        // 获取问卷列表
        $surveys = $this->db->get_surveys();
        
        // 加载模板
        include SURVEY_PLUGIN_DIR . 'templates/admin/survey-list.php';
    }
    
    /**
     * 渲染新建问卷页面
     */
    public function render_new_survey_page() {
        // 处理表单提交
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_survey'])) {
            $this->save_survey($_POST);
        }
        
        // 加载模板
        include SURVEY_PLUGIN_DIR . 'templates/admin/survey-editor.php';
    }
    
    /**
     * 保存问卷
     */
    private function save_survey($data) {
        // 验证和清理数据
        $survey_data = array(
            'title' => sanitize_text_field($data['title']),
            'description' => wp_kses_post($data['description']),
            'status' => sanitize_text_field($data['status']),
            'created_by' => get_current_user_id(),
            'settings' => json_encode(array(
                'require_login' => isset($data['require_login']) ? 1 : 0,
                'limit_responses' => isset($data['limit_responses']) ? intval($data['limit_responses']) : 0,
                'show_progress' => isset($data['show_progress']) ? 1 : 0,
                'randomize_questions' => isset($data['randomize_questions']) ? 1 : 0
            ))
        );
        
        // 保存到数据库
        global $wpdb;
        if (isset($data['survey_id']) && $data['survey_id']) {
            // 更新现有问卷
            $wpdb->update(
                "{$wpdb->prefix}surveys",
                $survey_data,
                array('id' => intval($data['survey_id']))
            );
            $survey_id = $data['survey_id'];
        } else {
            // 创建新问卷
            $wpdb->insert(
                "{$wpdb->prefix}surveys",
                $survey_data
            );
            $survey_id = $wpdb->insert_id;
        }
        
        // 保存问题
        if (isset($data['questions']) && is_array($data['questions'])) {
            $this->save_questions($survey_id, $data['questions']);
        }
        
        // 重定向到编辑页面
        wp_redirect(admin_url('admin.php?page=survey-new&survey_id=' . $survey_id . '&saved=1'));
        exit;
    }
    
    /**
     * 注册管理页面脚本
     */
    public function enqueue_admin_scripts($hook) {
        // 只在我们的管理页面加载脚本
        if (strpos($hook, 'survey-') === false) {
            return;
        }
        
        // 加载Vue.js用于动态界面
        wp_enqueue_script('vue', 'https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js', array(), '2.6.14');
        
        // 加载Element UI组件库
        wp_enqueue_style('element-ui', 'https://unpkg.com/element-ui/lib/theme-chalk/index.css');
        wp_enqueue_script('element-ui', 'https://unpkg.com/element-ui/lib/index.js', array('vue'), '2.15.6');
        
        // 加载自定义脚本
        wp_enqueue_script(
            'survey-admin',
            SURVEY_PLUGIN_URL . 'assets/js/admin.js',
            array('vue', 'element-ui', 'jquery'),
            '1.0.0',
            true
        );
        
        // 加载自定义样式
        wp_enqueue_style(
            'survey-admin',
            SURVEY_PLUGIN_URL . 'assets/css/admin.css',
            array('element-ui'),
            '1.0.0'
        );
        
        // 传递数据到JavaScript
        wp_localize_script('survey-admin', 'survey_admin_data', array(
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('survey_admin_nonce')
        ));
    }
}
?>

问卷编辑器前端实现

使用Vue.js和Element UI创建动态问卷编辑器:

// assets/js/admin.js
(function($) {
    'use strict';
    
    // 创建Vue应用
    new Vue({
        el: '#survey-editor',
        data: {
            survey: {
                title: '',
                description: '',
                status: 'draft',
                settings: {
                    require_login: false,
                    limit_responses: 0,
                    show_progress: true,
                    randomize_questions: false
                }
            },
            questions: [],
            questionTypes: [
                { value: 'single_choice', label: '单选题' },
                { value: 'multiple_choice', label: '多选题' },
                { value: 'text', label: '文本题' },
                { value: 'rating', label: '评分题' },
                { value: 'matrix', label: '矩阵题' }
            ],
            activeQuestionIndex: 0
        },
        methods: {
            // 添加新问题
            addQuestion: function(type) {
                const newQuestion = {
                    id: Date.now(), // 临时ID
                    question_text: '',
                    question_type: type,
                    options: type === 'rating' ? 
                        [{value: 1, label: '1'}, {value: 2, label: '2'}, {value: 3, label: '3'}, {value: 4, label: '4'}, {value: 5, label: '5'}] :
                        type === 'single_choice' || type === 'multiple_choice' ?
                        [{value: 'option1', label: '选项1'}, {value: 'option2', label: '选项2'}] :
                        [],
                    is_required: false,
                    sort_order: this.questions.length,
                    logic_rules: []
                };
                
                this.questions.push(newQuestion);
                this.activeQuestionIndex = this.questions.length - 1;
            },
            
            // 删除问题
            removeQuestion: function(index) {
                this.questions.splice(index, 1);
                if (this.activeQuestionIndex >= index && this.activeQuestionIndex > 0) {
                    this.activeQuestionIndex--;
                }
            },
            
            // 上移问题
            moveQuestionUp: function(index) {
                if (index > 0) {
                    const temp = this.questions[index];
                    this.$set(this.questions, index, this.questions[index - 1]);
                    this.$set(this.questions, index - 1, temp);
                    this.activeQuestionIndex = index - 1;
                }
            },
            
            // 下移问题
            moveQuestionDown: function(index) {
                if (index < this.questions.length - 1) {
                    const temp = this.questions[index];
                    this.$set(this.questions, index, this.questions[index + 1]);
                    this.activeQuestionIndex = index + 1;
                }
            },
            
            // 添加选项
            addOption: function(questionIndex) {
                if (!this.questions[questionIndex].options) {
                    this.$set(this.questions[questionIndex], 'options', []);
                }
                const optionCount = this.questions[questionIndex].options.length + 1;
                this.questions[questionIndex].options.push({
                    value: 'option' + optionCount,
                    label: '选项' + optionCount
                });
            },
            
            // 删除选项
            removeOption: function(questionIndex, optionIndex) {
                this.questions[questionIndex].options.splice(optionIndex, 1);
            },
            
            // 保存问卷
            saveSurvey: function() {
                const formData = new FormData();
                formData.append('action', 'save_survey');
                formData.append('nonce', survey_admin_data.nonce);
                formData.append('survey', JSON.stringify(this.survey));
                formData.append('questions', JSON.stringify(this.questions));
                
                $.ajax({
                    url: survey_admin_data.ajax_url,
                    type: 'POST',
                    data: formData,
                    processData: false,
                    contentType: false,
                    success: function(response) {
                        if (response.success) {
                            this.$message.success('问卷保存成功');
                            if (response.data.redirect) {
                                window.location.href = response.data.redirect;
                            }
                        } else {
                            this.$message.error('保存失败:' + response.data.message);
                        }
                    }.bind(this),
                    error: function() {
                        this.$message.error('网络错误,请重试');
                    }.bind(this)
                });
            },
            
            // 预览问卷
            previewSurvey: function() {
                // 在新窗口打开预览
                const previewUrl = survey_admin_data.site_url + '?survey_preview=' + (this.survey.id || 'new');
                window.open(previewUrl, '_blank');
            }
        },
        mounted: function() {
            // 如果有现有问卷数据,加载它
            if (window.surveyData) {
                this.survey = window.surveyData.survey;
                this.questions = window.surveyData.questions;
            }
        }
    });
})(jQuery);

前端问卷展示与交互

短代码系统实现

为了让用户能够轻松地在文章或页面中插入问卷,我们实现一个短代码系统:

<?php
/**
 * 问卷调查短代码类
 */
class Survey_Shortcode {
    
    private $db;
    
    public function __construct() {
        $this->db = new Survey_DB();
        
        // 注册短代码
        add_shortcode('survey', array($this, 'render_survey'));
        
        // 注册AJAX处理
        add_action('wp_ajax_submit_survey', array($this, 'handle_survey_submission'));
        add_action('wp_ajax_nopriv_submit_survey', array($this, 'handle_survey_submission'));
    }
    
    /**
     * 渲染问卷短代码
     */
    public function render_survey($atts) {
        $atts = shortcode_atts(array(
            'id' => 0,
            'title' => '',
            'width' => '100%',
            'height' => 'auto'
        ), $atts, 'survey');
        
        $survey_id = intval($atts['id']);
        
        if (!$survey_id) {
            return '<div class="survey-error">请指定问卷ID</div>';
        }
        
        // 获取问卷数据
        global $wpdb;
        $survey = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}surveys WHERE id = %d AND status = 'published'",
            $survey_id
        ));
        
        if (!$survey) {
            return '<div class="survey-error">问卷不存在或未发布</div>';
        }
        
        // 检查访问权限
        $settings = json_decode($survey->settings, true);
        if ($settings['require_login'] && !is_user_logged_in()) {
            return '<div class="survey-login-required">请先登录后再填写问卷</div>';
        }
        
        // 检查回答限制
        if ($settings['limit_responses'] > 0) {
            $response_count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->prefix}survey_responses WHERE survey_id = %d",
                $survey_id
            ));
            
            if ($response_count >= $settings['limit_responses']) {
                return '<div class="survey-closed">本问卷已收集足够数据,感谢参与</div>';
            }
        }
        
        // 获取问题列表
        $questions = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}survey_questions 
            WHERE survey_id = %d 
            ORDER BY sort_order ASC",
            $survey_id
        ));
        
        // 解析问题选项
        foreach ($questions as &$question) {
            if ($question->options) {
                $question->options = json_decode($question->options, true);
            }
            if ($question->logic_rules) {
                $question->logic_rules = json_decode($question->logic_rules, true);
            }
        }
        
        // 生成唯一会话ID
        $session_id = $this->generate_session_id();
        
        // 输出问卷HTML
        ob_start();
        include SURVEY_PLUGIN_DIR . 'templates/frontend/survey-form.php';
        return ob_get_clean();
    }
    
    /**
     * 处理问卷提交
     */
    public function handle_survey_submission() {
        // 验证nonce
        if (!check_ajax_referer('survey_submission', 'nonce', false)) {
            wp_die(json_encode(array(
                'success' => false,
                'message' => '安全验证失败'
            )));
        }
        
        $survey_id = intval($_POST['survey_id']);
        $answers = $_POST['answers'];
        $session_id = sanitize_text_field($_POST['session_id']);
        
        // 验证问卷是否存在且开放
        global $wpdb;
        $survey = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}surveys WHERE id = %d AND status = 'published'",
            $survey_id
        ));
        
        if (!$survey) {
            wp_die(json_encode(array(
                'success' => false,
                'message' => '问卷不存在'
            )));
        }
        
        // 检查是否已经提交过
        $settings = json_decode($survey->settings, true);
        if ($settings['prevent_duplicate']) {
            $user_id = get_current_user_id();
            $check_field = $user_id ? 'user_id' : 'session_id';
            $check_value = $user_id ? $user_id : $session_id;
            
            $existing = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$wpdb->prefix}survey_responses 
                WHERE survey_id = %d AND {$check_field} = %s",
                $survey_id,
                $check_value
            ));
            
            if ($existing > 0) {
                wp_die(json_encode(array(
                    'success' => false,
                    'message' => '您已经提交过本问卷'
                )));
            }
        }
        
        // 保存回答
        $user_id = get_current_user_id();
        $response_id = $this->db->save_response($survey_id, $user_id, $answers);
        
        if ($response_id) {
            // 触发完成动作
            do_action('survey_completed', $survey_id, $response_id, $user_id);
            
            wp_die(json_encode(array(
                'success' => true,
                'message' => '提交成功',
                'response_id' => $response_id
            )));
        } else {
            wp_die(json_encode(array(
                'success' => false,
                'message' => '提交失败,请重试'
            )));
        }
    }
    
    /**
     * 生成会话ID
     */
    private function generate_session_id() {
        if (isset($_COOKIE['survey_session_id'])) {
            return $_COOKIE['survey_session_id'];
        }
        
        $session_id = wp_generate_uuid4();
        setcookie('survey_session_id', $session_id, time() + 3600 * 24 * 30, '/');
        
        return $session_id;
    }
}
?>

前端问卷样式与交互

/* assets/css/frontend.css */
.survey-container {
    max-width: 800px;
    margin: 0 auto;
    padding: 30px;
    background: #fff;
    border-radius: 10px;
    box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

.survey-header {
    margin-bottom: 30px;
    padding-bottom: 20px;
    border-bottom: 2px solid #f0f0f0;
}

.survey-title {
    font-size: 28px;
    font-weight: 600;
    color: #333;
    margin-bottom: 10px;
}

.survey-description {
    font-size: 16px;
    color: #666;
    line-height: 1.6;
}

.survey-progress {
    margin-bottom: 30px;
}

.progress-bar {
    height: 8px;
    background: #f0f0f0;
    border-radius: 4px;
    overflow: hidden;
}

.progress-fill {
    height: 100%;
    background: linear-gradient(90deg, #4CAF50, #8BC34A);
    transition: width 0.3s ease;
}

.progress-text {
    text-align: right;
    font-size: 14px;
    color: #666;
    margin-top: 5px;
}

.survey-questions {
    margin-bottom: 40px;
}

.question-item {
    margin-bottom: 30px;
    padding: 25px;
    background: #f9f9f9;
    border-radius: 8px;
    border-left: 4px solid #4CAF50;
    transition: all 0.3s ease;
}

.question-item.required {
    border-left-color: #F44336;
}

.question-item.required .question-text::after {
    content: " *";
    color: #F44336;
}

.question-text {
    font-size: 18px;
    font-weight: 500;
    color: #333;
    margin-bottom: 20px;
    line-height: 1.5;
}

.question-hint {
    font-size: 14px;
    color: #888;
    margin-top: 5px;
    font-style: italic;
}

.options-container {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.option-item {
    display: flex;
    align-items: center;
    padding: 12px 15px;
    background: #fff;
    border: 2px solid #e0e0e0;
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.2s ease;
}

.option-item:hover {
    border-color: #4CAF50;
    background: #f8fff8;
}

.option-item.selected {
    border-color: #4CAF50;
    background: #f0f9f0;
}

.option-radio, .option-checkbox {
    margin-right: 12px;
    width: 20px;
    height: 20px;
}

.option-label {
    font-size: 16px;
    color: #333;
    flex: 1;
}

.text-input {
    width: 100%;
    padding: 12px 15px;
    font-size: 16px;
    border: 2px solid #e0e0e0;
    border-radius: 6px;
    transition: border-color 0.2s ease;
}

.text-input:focus {
    outline: none;
    border-color: #4CAF50;
}

.rating-container {
    display: flex;
    gap: 10px;
    justify-content: center;
}

.rating-star {
    font-size: 32px;
    color: #ddd;
    cursor: pointer;
    transition: color 0.2s ease;
}

.rating-star.active {
    color: #FFC107;
}

.rating-star:hover {
    color: #FFC107;
}

.matrix-table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 10px;
}

.matrix-table th, .matrix-table td {
    padding: 12px;
    text-align: center;
    border: 1px solid #e0e0e0;
}

.matrix-table th {
    background: #f5f5f5;
    font-weight: 500;
}

.matrix-option {
    display: inline-block;
    margin: 0 5px;
}

.survey-navigation {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-top: 30px;
    border-top: 2px solid #f0f0f0;
}

.nav-button {
    padding: 12px 30px;
    font-size: 16px;
    font-weight: 500;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.2s ease;
}

.nav-button.prev {
    background: #f5f5f5;
    color: #666;
}

.nav-button.prev:hover {
    background: #e0e0e0;
}

.nav-button.next {
    background: #4CAF50;
    color: white;
}

.nav-button.next:hover {
    background: #45a049;
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3);
}

.nav-button.submit {
    background: #2196F3;
    color: white;
}

.nav-button.submit:hover {
    background: #1976D2;
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);
}

.survey-footer {
    margin-top: 30px;
    text-align: center;
    font-size: 14px;
    color: #888;
}

/* 响应式设计 */
@media (max-width: 768px) {
    .survey-container {
        padding: 20px;
        margin: 10px;
    }
    
    .survey-title {
        font-size: 24px;
    }
    
    .question-item {
        padding: 20px;
    }
    
    .question-text {
        font-size: 16px;
    }
    
    .nav-button {
        padding: 10px 20px;
        font-size: 14px;
    }
    
    .matrix-table {
        font-size: 14px;
    }
    
    .matrix-table th, .matrix-table td {
        padding: 8px;
    }
}

/* 动画效果 */
@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.question-item {
    animation: fadeIn 0.5s ease forwards;
}

.question-item:nth-child(odd) {
    animation-delay: 0.1s;
}

.question-item:nth-child(even) {
    animation-delay: 0.2s;
}

数据统计与分析模块

数据可视化组件

<?php
/**
 * 数据统计与分析类
 */
class Survey_Analytics {
    
    private $db;
    
    public function __construct() {
        $this->db = new Survey_DB();
        
        // 注册AJAX端点
        add_action('wp_ajax_get_survey_stats', array($this, 'get_survey_statistics'));
    }
    
    /**
     * 获取问卷统计数据
     */
    public function get_survey_statistics($survey_id) {
        global $wpdb;
        
        $stats = array(
            'summary' => array(),
            'questions' => array(),
            'demographics' => array(),
            'timeline' => array()
        );
        
        // 基础统计
        $stats['summary'] = array(
            'total_responses' => $this->get_total_responses($survey_id),
            'completion_rate' => $this->get_completion_rate($survey_id),
            'average_time' => $this->get_average_completion_time($survey_id),
            'daily_average' => $this->get_daily_average($survey_id)
        );
        
        // 问题分析
        $questions = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}survey_questions WHERE survey_id = %d ORDER BY sort_order",
            $survey_id
        ));
        
        foreach ($questions as $question) {
            $question_stats = $this->analyze_question($question->id, $question->question_type);
            $stats['questions'][] = array(
                'id' => $question->id,
                'text' => $question->question_text,
                'type' => $question->question_type,
                'stats' => $question_stats
            );
        }
        
        // 用户画像(如果收集了用户信息)
        $stats['demographics'] = $this->analyze_demographics($survey_id);
        
        // 时间线数据
        $stats['timeline'] = $this->get_response_timeline($survey_id);
        
        return $stats;
    }
    
    /**
     * 分析单个问题
     */
    private function analyze_question($question_id, $question_type) {
        global $wpdb;
        
        $stats = array();
        
        switch ($question_type) {
            case 'single_choice':
            case 'multiple_choice':
                // 获取选项统计
                $answers = $wpdb->get_results($wpdb->prepare(
                    "SELECT answer_value, COUNT(*) as count 
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5222.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

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