文章目录[隐藏]
实战教学:为你的网站添加在线团队投票与决策辅助工具
引言:为什么网站需要团队协作工具?
在当今数字化工作环境中,团队协作效率直接影响项目成败。无论是小型创业团队、远程工作小组,还是企业内部部门,都需要高效的工具来收集意见、做出决策。然而,许多团队仍然依赖分散的沟通渠道——微信群讨论、邮件投票、Excel表格统计——这种方式效率低下且容易造成信息丢失。
通过为你的WordPress网站添加在线投票与决策辅助工具,你可以创建一个集中的协作平台,让团队成员能够实时参与决策过程,记录讨论结果,并追踪决策历史。这不仅提高了团队效率,还创造了透明、可追溯的决策文化。
本教程将带你一步步实现这一功能,无需购买昂贵的第三方服务,通过代码二次开发即可拥有完全可控的团队协作工具。
第一部分:准备工作与环境搭建
1.1 开发环境要求
在开始之前,请确保你拥有以下环境:
- WordPress 5.0及以上版本
- PHP 7.2及以上版本(推荐7.4+)
- MySQL 5.6及以上版本
- 一个代码编辑器(如VS Code、Sublime Text等)
- 基础的HTML、CSS、JavaScript和PHP知识
1.2 创建开发用的子主题
为了避免主题更新导致代码丢失,我们首先创建一个子主题:
- 在WordPress的
wp-content/themes/目录下创建新文件夹team-vote-theme - 在该文件夹中创建
style.css文件,添加以下内容:
/*
Theme Name: Team Vote Theme
Template: 你的父主题名称
Version: 1.0
Description: 用于团队投票功能的子主题
*/
/* 导入父主题样式 */
@import url("../父主题名称/style.css");
- 创建
functions.php文件,添加以下代码:
<?php
// 子主题初始化
function team_vote_theme_setup() {
// 加载父主题样式
add_action('wp_enqueue_scripts', 'enqueue_parent_styles');
}
add_action('after_setup_theme', 'team_vote_theme_setup');
function enqueue_parent_styles() {
wp_enqueue_style('parent-style', get_template_directory_uri().'/style.css');
}
// 在这里添加我们的自定义功能
?>
- 在WordPress后台启用这个子主题
1.3 创建插件还是主题功能?
对于这种功能,我们有三种实现方式:
- 作为主题的一部分(适合特定主题)
- 创建独立插件(适合多站点或主题无关场景)
- 使用功能插件(Functions Plugin)模式
本教程将采用功能插件模式,这样即使更换主题,功能也能保留。在wp-content/plugins/目录下创建team-vote-tool文件夹,并创建主文件team-vote-tool.php:
<?php
/**
* Plugin Name: 团队投票与决策辅助工具
* Plugin URI: https://yourwebsite.com/
* Description: 为WordPress网站添加在线团队投票与决策辅助功能
* Version: 1.0.0
* Author: 你的名字
* License: GPL v2 or later
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('TEAM_VOTE_VERSION', '1.0.0');
define('TEAM_VOTE_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('TEAM_VOTE_PLUGIN_URL', plugin_dir_url(__FILE__));
// 初始化插件
require_once TEAM_VOTE_PLUGIN_DIR . 'includes/init.php';
?>
第二部分:数据库设计与数据模型
2.1 创建自定义数据库表
团队投票系统需要存储投票活动、选项、用户投票记录等信息。我们在插件激活时创建必要的数据库表:
在插件目录下创建includes/activate.php:
<?php
function team_vote_activate_plugin() {
// 检查必要的WordPress函数
if (!function_exists('dbDelta')) {
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
}
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
// 投票活动表
$table_name = $wpdb->prefix . 'team_votes';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
title varchar(255) NOT NULL,
description text,
creator_id bigint(20) NOT NULL,
status varchar(20) DEFAULT 'active',
vote_type varchar(50) DEFAULT 'single',
max_choices mediumint(9) DEFAULT 1,
start_date datetime DEFAULT NULL,
end_date datetime DEFAULT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
dbDelta($sql);
// 投票选项表
$table_name = $wpdb->prefix . 'team_vote_options';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
vote_id mediumint(9) NOT NULL,
option_text varchar(500) NOT NULL,
description text,
image_url varchar(500),
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY vote_id (vote_id)
) $charset_collate;";
dbDelta($sql);
// 投票记录表
$table_name = $wpdb->prefix . 'team_vote_records';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
vote_id mediumint(9) NOT NULL,
option_id mediumint(9) NOT NULL,
user_id bigint(20) NOT NULL,
comment text,
voted_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY user_vote_unique (vote_id, user_id, option_id),
KEY vote_id (vote_id),
KEY user_id (user_id)
) $charset_collate;";
dbDelta($sql);
// 决策讨论表
$table_name = $wpdb->prefix . 'team_decisions';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
title varchar(255) NOT NULL,
description text,
creator_id bigint(20) NOT NULL,
status varchar(20) DEFAULT 'discussion',
final_decision text,
deadline datetime DEFAULT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
dbDelta($sql);
// 决策评论表
$table_name = $wpdb->prefix . 'team_decision_comments';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
decision_id mediumint(9) NOT NULL,
user_id bigint(20) NOT NULL,
comment text NOT NULL,
sentiment varchar(20) DEFAULT 'neutral',
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY decision_id (decision_id),
KEY user_id (user_id)
) $charset_collate;";
dbDelta($sql);
// 存储插件版本,便于后续更新
add_option('team_vote_db_version', TEAM_VOTE_VERSION);
}
register_activation_hook(__FILE__, 'team_vote_activate_plugin');
?>
2.2 创建数据模型类
为了更方便地操作数据,我们创建模型类。在includes/models/目录下创建Vote.php:
<?php
class TeamVoteModel {
private $wpdb;
private $table_votes;
private $table_options;
private $table_records;
public function __construct() {
global $wpdb;
$this->wpdb = $wpdb;
$this->table_votes = $wpdb->prefix . 'team_votes';
$this->table_options = $wpdb->prefix . 'team_vote_options';
$this->table_records = $wpdb->prefix . 'team_vote_records';
}
// 创建新投票
public function create_vote($data) {
$defaults = array(
'status' => 'active',
'vote_type' => 'single',
'max_choices' => 1,
'created_at' => current_time('mysql')
);
$data = wp_parse_args($data, $defaults);
$result = $this->wpdb->insert(
$this->table_votes,
$data
);
if ($result) {
return $this->wpdb->insert_id;
}
return false;
}
// 获取投票详情
public function get_vote($vote_id) {
$query = $this->wpdb->prepare(
"SELECT * FROM $this->table_votes WHERE id = %d",
$vote_id
);
return $this->wpdb->get_row($query);
}
// 获取用户的所有投票
public function get_user_votes($user_id, $status = null) {
$where = "WHERE creator_id = %d";
$params = array($user_id);
if ($status) {
$where .= " AND status = %s";
$params[] = $status;
}
$query = $this->wpdb->prepare(
"SELECT * FROM $this->table_votes $where ORDER BY created_at DESC",
$params
);
return $this->wpdb->get_results($query);
}
// 添加投票选项
public function add_option($vote_id, $option_text, $description = '', $image_url = '') {
return $this->wpdb->insert(
$this->table_options,
array(
'vote_id' => $vote_id,
'option_text' => $option_text,
'description' => $description,
'image_url' => $image_url
)
);
}
// 获取投票的所有选项
public function get_options($vote_id) {
$query = $this->wpdb->prepare(
"SELECT * FROM $this->table_options WHERE vote_id = %d ORDER BY id ASC",
$vote_id
);
return $this->wpdb->get_results($query);
}
// 记录用户投票
public function record_vote($vote_id, $option_id, $user_id, $comment = '') {
// 检查是否已经投过票(对于单选投票)
$vote = $this->get_vote($vote_id);
if ($vote->vote_type === 'single') {
$existing = $this->wpdb->get_var($this->wpdb->prepare(
"SELECT COUNT(*) FROM $this->table_records
WHERE vote_id = %d AND user_id = %d",
$vote_id, $user_id
));
if ($existing > 0) {
return new WP_Error('already_voted', '您已经投过票了');
}
}
// 检查多选投票是否超过最大选择数
if ($vote->vote_type === 'multiple') {
$current_choices = $this->wpdb->get_var($this->wpdb->prepare(
"SELECT COUNT(*) FROM $this->table_records
WHERE vote_id = %d AND user_id = %d",
$vote_id, $user_id
));
if ($current_choices >= $vote->max_choices) {
return new WP_Error('max_choices', '已达到最大选择数量');
}
}
return $this->wpdb->insert(
$this->table_records,
array(
'vote_id' => $vote_id,
'option_id' => $option_id,
'user_id' => $user_id,
'comment' => $comment
)
);
}
// 获取投票结果
public function get_results($vote_id) {
$query = $this->wpdb->prepare(
"SELECT o.id, o.option_text, o.description, o.image_url,
COUNT(r.id) as vote_count
FROM $this->table_options o
LEFT JOIN $this->table_records r ON o.id = r.option_id
WHERE o.vote_id = %d
GROUP BY o.id
ORDER BY vote_count DESC",
$vote_id
);
return $this->wpdb->get_results($query);
}
// 检查用户是否已投票
public function has_user_voted($vote_id, $user_id) {
$count = $this->wpdb->get_var($this->wpdb->prepare(
"SELECT COUNT(*) FROM $this->table_records
WHERE vote_id = %d AND user_id = %d",
$vote_id, $user_id
));
return $count > 0;
}
// 获取用户的投票选择
public function get_user_vote($vote_id, $user_id) {
$query = $this->wpdb->prepare(
"SELECT r.*, o.option_text
FROM $this->table_records r
JOIN $this->table_options o ON r.option_id = o.id
WHERE r.vote_id = %d AND r.user_id = %d",
$vote_id, $user_id
);
return $this->wpdb->get_results($query);
}
}
?>
同样地,创建决策模型类Decision.php,由于篇幅限制,这里不展开详细代码。
第三部分:前端界面设计与实现
3.1 创建投票创建表单
在templates/目录下创建create-vote.php:
<?php
/**
* 创建投票表单模板
*/
if (!defined('ABSPATH')) {
exit;
}
// 检查用户是否登录
if (!is_user_logged_in()) {
echo '<div class="team-vote-message">请先登录以创建投票</div>';
return;
}
// 处理表单提交
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['create_vote'])) {
// 这里添加表单处理逻辑,将在后面实现
}
// 获取当前用户ID
$current_user_id = get_current_user_id();
?>
<div class="team-vote-container">
<h2>创建新投票</h2>
<form id="create-vote-form" method="POST" action="">
<?php wp_nonce_field('create_vote_action', 'create_vote_nonce'); ?>
<div class="form-group">
<label for="vote_title">投票标题 *</label>
<input type="text" id="vote_title" name="vote_title" required
placeholder="例如:选择团队下次团建地点">
</div>
<div class="form-group">
<label for="vote_description">投票描述</label>
<textarea id="vote_description" name="vote_description" rows="3"
placeholder="详细描述投票的背景和目的"></textarea>
</div>
<div class="form-row">
<div class="form-group">
<label for="vote_type">投票类型</label>
<select id="vote_type" name="vote_type">
<option value="single">单选</option>
<option value="multiple">多选</option>
</select>
</div>
<div class="form-group" id="max-choices-container" style="display:none;">
<label for="max_choices">最多可选数量</label>
<input type="number" id="max_choices" name="max_choices"
min="2" max="10" value="3">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="start_date">开始时间</label>
<input type="datetime-local" id="start_date" name="start_date">
</div>
<div class="form-group">
<label for="end_date">结束时间</label>
<input type="datetime-local" id="end_date" name="end_date">
</div>
</div>
<div class="form-group">
<label>投票选项 *</label>
<div id="vote-options-container">
<div class="option-item">
<input type="text" name="options[]" placeholder="选项内容" required>
<textarea name="option_descriptions[]" placeholder="选项描述(可选)"></textarea>
<input type="text" name="option_images[]" placeholder="图片URL(可选)">
<button type="button" class="remove-option">删除</button>
</div>
<div class="option-item">
<input type="text" name="options[]" placeholder="选项内容" required>
<textarea name="option_descriptions[]" placeholder="选项描述(可选)"></textarea>
<input type="text" name="option_images[]" placeholder="图片URL(可选)">
<button type="button" class="remove-option">删除</button>
</div>
</div>
<button type="button" id="add-option" class="button-secondary">添加选项</button>
</div>
<div class="form-submit">
<input type="submit" name="create_vote" value="创建投票" class="button-primary">
</div>
</form>
</div>
<script>
jQuery(document).ready(function($) {
// 显示/隐藏多选数量设置
$('#vote_type').change(function() {
if ($(this).val() === 'multiple') {
$('#max-choices-container').show();
} else {
$('#max-choices-container').hide();
}
});
// 添加选项
$('#add-option').click(function() {
var optionHtml = `
<div class="option-item">
选项内容" required>
<textarea name="option_descriptions[]" placeholder="选项描述(可选)"></textarea>
<input type="text" name="option_images[]" placeholder="图片URL(可选)">
<button type="button" class="remove-option">删除</button>
</div>`;
$('#vote-options-container').append(optionHtml);
});
// 删除选项
$(document).on('click', '.remove-option', function() {
if ($('.option-item').length > 2) {
$(this).closest('.option-item').remove();
} else {
alert('投票至少需要两个选项');
}
});
});
</script>
### 3.2 创建投票展示与参与界面
在`templates/`目录下创建`vote-display.php`:
<?php
/**
- 投票展示与参与模板
*/
if (!defined('ABSPATH')) {
exit;
}
// 获取投票ID
$vote_id = isset($_GET['vote_id']) ? intval($_GET['vote_id']) : 0;
if (!$vote_id) {
echo '<div class="team-vote-message">未指定投票</div>';
return;
}
// 获取投票信息
$vote_model = new TeamVoteModel();
$vote = $vote_model->get_vote($vote_id);
if (!$vote) {
echo '<div class="team-vote-message">投票不存在</div>';
return;
}
// 获取投票选项
$options = $vote_model->get_options($vote_id);
if (empty($options)) {
echo '<div class="team-vote-message">投票选项未设置</div>';
return;
}
// 检查投票状态
$current_time = current_time('mysql');
$is_active = true;
if ($vote->start_date && $vote->start_date > $current_time) {
$is_active = false;
$status_message = '投票尚未开始';
} elseif ($vote->end_date && $vote->end_date < $current_time) {
$is_active = false;
$status_message = '投票已结束';
} elseif ($vote->status !== 'active') {
$is_active = false;
$status_message = '投票已关闭';
}
// 获取当前用户信息
$current_user_id = get_current_user_id();
$has_voted = $vote_model->has_user_voted($vote_id, $current_user_id);
$user_votes = $has_voted ? $vote_model->get_user_vote($vote_id, $current_user_id) : array();
// 获取投票结果
$results = $vote_model->get_results($vote_id);
$total_votes = 0;
foreach ($results as $result) {
$total_votes += $result->vote_count;
}
// 处理投票提交
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit_vote']) && $is_active && !$has_voted) {
// 这里添加投票处理逻辑
}
?>
<div class="team-vote-container">
<div class="vote-header">
<h2><?php echo esc_html($vote->title); ?></h2>
<div class="vote-meta">
<span class="vote-creator">创建者: <?php echo get_userdata($vote->creator_id)->display_name; ?></span>
<span class="vote-date">创建时间: <?php echo date('Y-m-d H:i', strtotime($vote->created_at)); ?></span>
<?php if ($vote->end_date): ?>
<span class="vote-deadline">截止时间: <?php echo date('Y-m-d H:i', strtotime($vote->end_date)); ?></span>
<?php endif; ?>
</div>
<?php if ($vote->description): ?>
<div class="vote-description">
<?php echo wpautop(esc_html($vote->description)); ?>
</div>
<?php endif; ?>
<div class="vote-status">
<?php if ($is_active): ?>
<span class="status-active">● 进行中</span>
<?php else: ?>
<span class="status-inactive">● <?php echo $status_message; ?></span>
<?php endif; ?>
<span class="total-votes">总投票数: <?php echo $total_votes; ?></span>
</div>
</div>
<?php if ($is_active && !$has_voted): ?>
<form id="vote-form" method="POST" action="">
<?php wp_nonce_field('vote_action_' . $vote_id, 'vote_nonce'); ?>
<input type="hidden" name="vote_id" value="<?php echo $vote_id; ?>">
<div class="vote-options">
<h3>请选择<?php echo $vote->vote_type === 'multiple' ? '(可多选)' : '(单选)'; ?></h3>
<?php foreach ($options as $index => $option): ?>
<div class="vote-option">
<label class="option-label">
<?php if ($vote->vote_type === 'multiple'): ?>
<input type="checkbox" name="selected_options[]"
value="<?php echo $option->id; ?>"
class="option-checkbox">
<?php else: ?>
<input type="radio" name="selected_options"
value="<?php echo $option->id; ?>"
class="option-radio" required>
<?php endif; ?>
<div class="option-content">
<div class="option-text"><?php echo esc_html($option->option_text); ?></div>
<?php if ($option->description): ?>
<div class="option-description">
<?php echo esc_html($option->description); ?>
</div>
<?php endif; ?>
<?php if ($option->image_url): ?>
<div class="option-image">
<img src="<?php echo esc_url($option->image_url); ?>"
alt="<?php echo esc_attr($option->option_text); ?>">
</div>
<?php endif; ?>
</div>
</label>
</div>
<?php endforeach; ?>
</div>
<div class="vote-comment">
<label for="vote_comment">投票备注(可选)</label>
<textarea id="vote_comment" name="vote_comment"
placeholder="请说明您选择此选项的理由..."></textarea>
</div>
<div class="vote-submit">
<button type="submit" name="submit_vote" class="button-primary">
提交投票
</button>
</div>
</form>
<?php elseif ($has_voted): ?>
<div class="already-voted">
<h3>您已参与本次投票</h3>
<p>您选择了以下选项:</p>
<ul class="user-selections">
<?php foreach ($user_votes as $user_vote): ?>
<li><?php echo esc_html($user_vote->option_text); ?></li>
<?php endforeach; ?>
</ul>
<?php if (!empty($user_votes[0]->comment)): ?>
<div class="user-comment">
<strong>您的备注:</strong>
<p><?php echo esc_html($user_votes[0]->comment); ?></p>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
<!-- 投票结果展示 -->
<div class="vote-results">
<h3>投票结果</h3>
<?php if ($total_votes > 0): ?>
<div class="results-summary">
<p>总参与人数: <strong><?php echo $total_votes; ?></strong></p>
</div>
<div class="results-chart">
<?php foreach ($results as $result):
$percentage = $total_votes > 0 ? round(($result->vote_count / $total_votes) * 100, 1) : 0;
?>
<div class="result-item">
<div class="result-header">
<span class="option-text"><?php echo esc_html($result->option_text); ?></span>
<span class="vote-count"><?php echo $result->vote_count; ?> 票 (<?php echo $percentage; ?>%)</span>
</div>
<div class="result-bar-container">
<div class="result-bar" style="width: <?php echo $percentage; ?>%;"></div>
</div>
<?php if ($result->description): ?>
<div class="result-description">
<?php echo esc_html($result->description); ?>
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php else: ?>
<p class="no-results">暂无投票结果</p>
<?php endif; ?>
</div>
</div>
<?php if ($is_active && !$has_voted): ?>
<script>
jQuery(document).ready(function($) {
// 多选投票的最大选择限制
<?php if ($vote->vote_type === 'multiple' && $vote->max_choices > 0): ?>
var maxChoices = <?php echo $vote->max_choices; ?>;
$('.option-checkbox').change(function() {
var checkedCount = $('.option-checkbox:checked').length;
if (checkedCount > maxChoices) {
$(this).prop('checked', false);
alert('最多只能选择 ' + maxChoices + ' 个选项');
}
});
<?php endif; ?>
// 表单提交验证
$('#vote-form').submit(function(e) {
var selectedCount = $('.option-checkbox:checked').length +
($('.option-radio:checked').length ? 1 : 0);
if (selectedCount === 0) {
e.preventDefault();
alert('请至少选择一个选项');
return false;
}
<?php if ($vote->vote_type === 'multiple'): ?>
if (selectedCount > maxChoices) {
e.preventDefault();
alert('最多只能选择 ' + maxChoices + ' 个选项');
return false;
}
<?php endif; ?>
});
});
</script>
<?php endif; ?>
### 3.3 创建决策讨论板界面
在`templates/`目录下创建`decision-board.php`:
<?php
/**
- 决策讨论板模板
*/
if (!defined('ABSPATH')) {
exit;
}
// 获取决策ID
$decision_id = isset($_GET['decision_id']) ? intval($_GET['decision_id']) : 0;
if (!$decision_id) {
echo '<div class="team-vote-message">未指定决策讨论</div>';
return;
}
// 获取决策信息
$decision_model = new TeamDecisionModel();
$decision = $decision_model->get_decision($decision_id);
if (!$decision) {
echo '<div class="team-vote-message">决策讨论不存在</div>';
return;
}
// 获取讨论评论
$comments = $decision_model->get_comments($decision_id);
// 获取当前用户信息
$current_user_id = get_current_user_id();
$current_user = wp_get_current_user();
// 处理评论提交
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit_comment'])) {
// 这里添加评论处理逻辑
}
?>
<div class="decision-container">
<div class="decision-header">
<h2><?php echo esc_html($decision->title); ?></h2>
<div class="decision-meta">
<span class="decision-creator">发起人: <?php echo get_userdata($decision->creator_id)->display_name; ?></span>
<span class="decision-date">创建时间: <?php echo date('Y-m-d H:i', strtotime($decision->created_at)); ?></span>
<?php if ($decision->deadline): ?>
<span class="decision-deadline">截止时间: <?php echo date('Y-m-d H:i', strtotime($decision->deadline)); ?></span>
<?php endif; ?>
<span class="decision-status status-<?php echo $decision->status; ?>">
<?php
$status_labels = array(
'discussion' => '讨论中',
'voting' => '投票中',
'decided' => '已决定',
'closed' => '已关闭'
);
echo $status_labels[$decision->status] ?? $decision->status;
?>
</span>
</div>
<?php if ($decision->description): ?>
<div class="decision-description">
<h3>决策背景</h3>
<?php echo wpautop(esc_html($decision->description)); ?>
</div>
<?php endif; ?>
<?php if ($decision->final_decision && $decision->status === 'decided'): ?>
<div class="final-decision">
<h3>最终决定</h3>
<div class="decision-content">
<?php echo wpautop(esc_html($decision->final_decision)); ?>
</div>
<div class="decision-meta">
决定时间: <?php echo date('Y-m-d H:i', strtotime($decision->updated_at)); ?>
</div>
</div>
<?php endif; ?>
</div>
<!-- 讨论区 -->
<div class="discussion-section">
<h3>讨论区 (<?php echo count($comments); ?> 条评论)</h3>
<?php if ($decision->status === 'discussion' || $decision->status === 'voting'): ?>
<div class="comment-form">
<form method="POST" action="">
<?php wp_nonce_field('comment_action_' . $decision_id, 'comment_nonce'); ?>
<div class="form-group">
<label for="comment_content">发表您的观点</label>
<textarea id="comment_content" name="comment_content"
rows="4" required
placeholder="请详细阐述您的观点和建议..."></textarea>
</div>
<div class="form-group">
<label for="comment_sentiment">观点倾向</label>
<select id="comment_sentiment" name="comment_sentiment">
<option value="support">支持</option>
<option value="neutral" selected>中立</option>
<option value="oppose">反对</option>
<option value="question">疑问</option>
<option value="suggestion">建议</option>
</select>
</div>
<div class="form-submit">
<button type="submit" name="submit_comment" class="button-primary">
发表评论
</button>
</div>
</form>
</div>
<?php endif; ?>
<div class="comments-list">
<?php if (empty($comments)): ?>
<p class="no-comments">暂无讨论,快来发表第一个观点吧!</p>
<?php else: ?>
<?php foreach ($comments as $comment):
$comment_user = get_userdata($comment->user_id);
$sentiment_classes = array(
'support' => 'sentiment-support',
'oppose' => 'sentiment-oppose',
'question' => 'sentiment-question',
'suggestion' => 'sentiment-suggestion',
'neutral' => 'sentiment-neutral'
);
$sentiment_labels = array(
'support' => '支持',
'oppose' => '反对',
'question' => '疑问',
'suggestion' => '建议',
'neutral' => '中立'
);
?>
<div class="comment-item <?php echo $sentiment_classes[$comment->sentiment] ?? ''; ?>">
<div class="comment-header">
<div class="comment-author">
<span class="author-avatar">
<?php echo get_avatar($comment->user_id, 40); ?>
</span>
<span class="author-name"><?php echo $comment_user->display_name; ?></span>
<span class="comment-sentiment">
<?php echo $sentiment_labels[$comment->sentiment] ?? $comment->sentiment; ?>
</span>
</div>
<div class="comment-date">
<?php echo date('Y-m-d H:i', strtotime($comment->created_at)); ?>
</div>
</div>
<div class="comment-content">
<?php echo wpautop(esc_html($comment->comment)); ?>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<!-- 相关投票(如果存在) -->
<?php
// 获取与决策相关的投票
$related_votes = $decision_model->get_related_votes($decision_id);
if (!empty($related_votes)):
?>
<div class="related-votes">
<h3>相关投票</h3>
<div class="votes-list">
<?php foreach ($related_votes as $vote): ?>
<div class="vote-summary">
<h4><?php echo esc_html($vote->title); ?></h4>
<p><?php echo esc_html(wp_trim_words($vote->description, 20)); ?></p>
<a href="?page=team_vote&vote_id=<?php echo $vote->id; ?>" class="button-small">
查看投票
</a>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
</div>
<style>
.sentiment-support {
border-left: 4px solid #4CAF50;
}
.sentiment-oppose {
border-left: 4px solid #F44336;
}
.sentiment-question {
border-left: 4px solid #FF9800;
}
.sentiment-suggestion {
border-left: 4px solid #2196F3;
}
.sentiment-neutral {
border-left: 4px solid #9E9E9E;
}
</style>
## 第四部分:后端逻辑与AJAX处理
### 4.1 表单处理与数据验证
