文章目录[隐藏]
实现小批量快速打样的WordPress集成插件教程
概述
在当今快速发展的电商环境中,小批量快速打样已成为产品开发的关键环节。本教程将指导您创建一个WordPress插件,帮助用户高效管理小批量打样流程。这个插件将包含产品提交、打样状态跟踪和团队协作功能,适合初创企业和小型设计团队使用。
插件架构设计
1. 插件基础结构
首先,我们创建插件的基本文件结构:
<?php
/**
* 插件名称: 小批量快速打样管理系统
* 版本: 1.0.0
* 描述: 用于管理小批量产品打样流程的WordPress插件
* 作者: 您的姓名
* 文本域: rapid-prototyping
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('RP_PLUGIN_VERSION', '1.0.0');
define('RP_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('RP_PLUGIN_URL', plugin_dir_url(__FILE__));
// 初始化插件
class RapidPrototypingPlugin {
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() {
// 激活/停用钩子
register_activation_hook(__FILE__, array($this, 'activate'));
register_deactivation_hook(__FILE__, array($this, 'deactivate'));
// 初始化
add_action('init', array($this, 'init'));
// 管理菜单
add_action('admin_menu', array($this, 'add_admin_menu'));
// 加载脚本和样式
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_scripts'));
}
public function activate() {
$this->create_database_tables();
$this->create_default_options();
}
public function deactivate() {
// 清理临时数据
$this->cleanup_temporary_data();
}
public function init() {
// 加载文本域
load_plugin_textdomain('rapid-prototyping', false, dirname(plugin_basename(__FILE__)) . '/languages');
// 注册自定义文章类型
$this->register_custom_post_types();
}
// 其他方法将在下面实现
}
// 启动插件
RapidPrototypingPlugin::get_instance();
?>
2. 数据库表设计
创建必要的数据库表来存储打样项目数据:
<?php
// 在RapidPrototypingPlugin类中添加以下方法
private function create_database_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'rapid_prototyping_projects';
// 项目表
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
project_name varchar(255) NOT NULL,
description text,
designer_id bigint(20) NOT NULL,
status varchar(50) DEFAULT 'draft',
priority tinyint(1) DEFAULT 1,
materials text,
quantity int(11) DEFAULT 1,
due_date datetime,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY designer_id (designer_id),
KEY status (status)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// 打样版本表
$versions_table = $wpdb->prefix . 'rapid_prototyping_versions';
$sql = "CREATE TABLE IF NOT EXISTS $versions_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
project_id mediumint(9) NOT NULL,
version_number varchar(20) NOT NULL,
file_url varchar(500),
notes text,
feedback text,
approved_by bigint(20),
approved_at datetime,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY project_id (project_id),
FOREIGN KEY (project_id) REFERENCES $table_name(id) ON DELETE CASCADE
) $charset_collate;";
dbDelta($sql);
// 团队成员表
$team_table = $wpdb->prefix . 'rapid_prototyping_team';
$sql = "CREATE TABLE IF NOT EXISTS $team_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
project_id mediumint(9) NOT NULL,
user_id bigint(20) NOT NULL,
role varchar(50) NOT NULL,
added_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY project_user (project_id, user_id),
FOREIGN KEY (project_id) REFERENCES $table_name(id) ON DELETE CASCADE
) $charset_collate;";
dbDelta($sql);
}
?>
3. 管理界面实现
创建插件管理页面和功能:
<?php
// 在RapidPrototypingPlugin类中添加以下方法
public function add_admin_menu() {
// 主菜单
add_menu_page(
__('快速打样管理', 'rapid-prototyping'),
__('快速打样', 'rapid-prototyping'),
'manage_options',
'rapid-prototyping',
array($this, 'render_dashboard_page'),
'dashicons-hammer',
30
);
// 子菜单
add_submenu_page(
'rapid-prototyping',
__('所有项目', 'rapid-prototyping'),
__('所有项目', 'rapid-prototyping'),
'manage_options',
'rp-projects',
array($this, 'render_projects_page')
);
add_submenu_page(
'rapid-prototyping',
__('添加新项目', 'rapid-prototyping'),
__('添加新项目', 'rapid-prototyping'),
'manage_options',
'rp-add-project',
array($this, 'render_add_project_page')
);
add_submenu_page(
'rapid-prototyping',
__('设置', 'rapid-prototyping'),
__('设置', 'rapid-prototyping'),
'manage_options',
'rp-settings',
array($this, 'render_settings_page')
);
}
public function render_dashboard_page() {
?>
<div class="wrap rp-dashboard">
<h1><?php _e('快速打样仪表板', 'rapid-prototyping'); ?></h1>
<div class="rp-stats-container">
<?php $this->display_statistics(); ?>
</div>
<div class="rp-recent-projects">
<h2><?php _e('最近项目', 'rapid-prototyping'); ?></h2>
<?php $this->display_recent_projects(); ?>
</div>
</div>
<?php
}
private function display_statistics() {
global $wpdb;
$table_name = $wpdb->prefix . 'rapid_prototyping_projects';
// 获取统计数据
$total_projects = $wpdb->get_var("SELECT COUNT(*) FROM $table_name");
$active_projects = $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE status IN ('in_progress', 'review')");
$completed_projects = $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE status = 'completed'");
?>
<div class="rp-stats-grid">
<div class="rp-stat-card">
<h3><?php echo esc_html($total_projects); ?></h3>
<p><?php _e('总项目数', 'rapid-prototyping'); ?></p>
</div>
<div class="rp-stat-card">
<h3><?php echo esc_html($active_projects); ?></h3>
<p><?php _e('进行中项目', 'rapid-prototyping'); ?></p>
</div>
<div class="rp-stat-card">
<h3><?php echo esc_html($completed_projects); ?></h3>
<p><?php _e('已完成项目', 'rapid-prototyping'); ?></p>
</div>
</div>
<?php
}
?>
4. 前端提交表单
创建用户提交打样请求的前端表单:
<?php
// 创建短码处理类
class RP_Shortcodes {
public static function init() {
add_shortcode('rp_submission_form', array(__CLASS__, 'render_submission_form'));
add_shortcode('rp_project_status', array(__CLASS__, 'render_project_status'));
}
public static function render_submission_form($atts) {
// 检查用户是否登录
if (!is_user_logged_in()) {
return '<p>' . __('请登录后提交打样请求。', 'rapid-prototyping') . '</p>';
}
ob_start();
?>
<div class="rp-submission-form-container">
<h2><?php _e('提交打样请求', 'rapid-prototyping'); ?></h2>
<form id="rp-submission-form" method="post" enctype="multipart/form-data">
<?php wp_nonce_field('rp_submit_project', 'rp_nonce'); ?>
<div class="rp-form-group">
<label for="project_name"><?php _e('项目名称', 'rapid-prototyping'); ?> *</label>
<input type="text" id="project_name" name="project_name" required>
</div>
<div class="rp-form-group">
<label for="description"><?php _e('项目描述', 'rapid-prototyping'); ?></label>
<textarea id="description" name="description" rows="4"></textarea>
</div>
<div class="rp-form-row">
<div class="rp-form-group">
<label for="quantity"><?php _e('打样数量', 'rapid-prototyping'); ?></label>
<input type="number" id="quantity" name="quantity" min="1" max="100" value="1">
</div>
<div class="rp-form-group">
<label for="priority"><?php _e('优先级', 'rapid-prototyping'); ?></label>
<select id="priority" name="priority">
<option value="1"><?php _e('低', 'rapid-prototyping'); ?></option>
<option value="2" selected><?php _e('中', 'rapid-prototyping'); ?></option>
<option value="3"><?php _e('高', 'rapid-prototyping'); ?></option>
</select>
</div>
</div>
<div class="rp-form-group">
<label for="materials"><?php _e('使用材料', 'rapid-prototyping'); ?></label>
<textarea id="materials" name="materials" rows="3"
placeholder="<?php esc_attr_e('请详细描述所需材料...', 'rapid-prototyping'); ?>"></textarea>
</div>
<div class="rp-form-group">
<label for="due_date"><?php _e('期望完成日期', 'rapid-prototyping'); ?></label>
<input type="date" id="due_date" name="due_date">
</div>
<div class="rp-form-group">
<label for="design_files"><?php _e('设计文件', 'rapid-prototyping'); ?></label>
<input type="file" id="design_files" name="design_files[]" multiple accept=".jpg,.png,.pdf,.stl,.obj">
<p class="rp-help-text"><?php _e('支持JPG, PNG, PDF, STL, OBJ格式,最多5个文件', 'rapid-prototyping'); ?></p>
</div>
<div class="rp-form-group">
<label for="additional_notes"><?php _e('附加说明', 'rapid-prototyping'); ?></label>
<textarea id="additional_notes" name="additional_notes" rows="3"></textarea>
</div>
<button type="submit" class="rp-submit-button">
<?php _e('提交打样请求', 'rapid-prototyping'); ?>
</button>
<div id="rp-form-message"></div>
</form>
</div>
<script>
jQuery(document).ready(function($) {
$('#rp-submission-form').on('submit', function(e) {
e.preventDefault();
var formData = new FormData(this);
formData.append('action', 'rp_submit_project');
$.ajax({
url: '<?php echo admin_url("admin-ajax.php"); ?>',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
if (response.success) {
$('#rp-form-message').html(
'<div class="rp-success">' + response.data.message + '</div>'
);
$('#rp-submission-form')[0].reset();
} else {
$('#rp-form-message').html(
'<div class="rp-error">' + response.data.message + '</div>'
);
}
}
});
});
});
</script>
<?php
return ob_get_clean();
}
}
// 在插件初始化时注册短码
add_action('init', array('RP_Shortcodes', 'init'));
?>
5. AJAX处理与数据验证
处理表单提交的AJAX请求:
<?php
// 在RapidPrototypingPlugin类中添加AJAX处理方法
private function init_ajax_handlers() {
add_action('wp_ajax_rp_submit_project', array($this, 'handle_project_submission'));
add_action('wp_ajax_nopriv_rp_submit_project', array($this, 'handle_no_privilege'));
add_action('wp_ajax_rp_get_project_status', array($this, 'get_project_status'));
}
public function handle_project_submission() {
// 验证nonce
if (!wp_verify_nonce($_POST['rp_nonce'], 'rp_submit_project')) {
wp_die(__('安全验证失败', 'rapid-prototyping'));
}
// 验证用户权限
if (!is_user_logged_in()) {
wp_send_json_error(array(
'message' => __('请先登录', 'rapid-prototyping')
));
}
// 验证必填字段
$required_fields = array('project_name');
foreach ($required_fields as $field) {
if (empty($_POST[$field])) {
wp_send_json_error(array(
'message' => sprintf(__('%s为必填字段', 'rapid-prototyping'), $field)
));
}
}
global $wpdb;
$table_name = $wpdb->prefix . 'rapid_prototyping_projects';
// 准备数据
$project_data = array(
'project_name' => sanitize_text_field($_POST['project_name']),
'description' => sanitize_textarea_field($_POST['description']),
'designer_id' => get_current_user_id(),
'status' => 'draft',
'priority' => intval($_POST['priority']),
'materials' => sanitize_textarea_field($_POST['materials']),
'quantity' => intval($_POST['quantity']),
'due_date' => !empty($_POST['due_date']) ? sanitize_text_field($_POST['due_date']) : null,
'created_at' => current_time('mysql')
);
// 插入数据库
$result = $wpdb->insert($table_name, $project_data);
if ($result) {
$project_id = $wpdb->insert_id;
// 处理文件上传
$this->handle_file_uploads($project_id);
// 发送通知邮件
$this->send_notification_email($project_id);
wp_send_json_success(array(
'message' => __('打样请求提交成功!', 'rapid-prototyping'),
'project_id' => $project_id
));
} else {
wp_send_json_error(array(
'message' => __('提交失败,请重试', 'rapid-prototyping')
));
}
}
private function handle_file_uploads($project_id) {
if (!empty($_FILES['design_files'])) {
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');
$files = $_FILES['design_files'];
$upload_dir = wp_upload_dir();
$rp_dir = $upload_dir['basedir'] . '/rapid-prototyping/' . $project_id;
// 创建目录
if (!file_exists($rp_dir)) {
wp_mkdir_p($rp_dir);
}
// 处理多个文件
foreach ($files['name'] as $key => $value) {
if ($files['name'][$key]) {
$file = array(
'name' => $files['name'][$key],
'type' => $files['type'][$key],
'tmp_name' => $files['tmp_name'][$key],
'error' => $files['error'][$key],
'size' => $files['size'][$key]
);
$upload_overrides = array('test_form' => false);
$movefile = wp_handle_upload($file, $upload_overrides);
if ($movefile && !isset($movefile['error'])) {
// 保存文件信息到数据库
$this->save_file_info($project_id, $movefile['url'], $file['name']);
}
}
}
}
}
?>
6. 样式与脚本优化
6. 样式与脚本优化
为插件添加专业的前端样式和交互功能:
<?php
// 在RapidPrototypingPlugin类中添加以下方法
public function enqueue_admin_scripts($hook) {
// 只在插件页面加载
if (strpos($hook, 'rapid-prototyping') === false) {
return;
}
// 加载CSS样式
wp_enqueue_style(
'rp-admin-style',
RP_PLUGIN_URL . 'assets/css/admin.css',
array(),
RP_PLUGIN_VERSION
);
// 加载JavaScript
wp_enqueue_script(
'rp-admin-script',
RP_PLUGIN_URL . 'assets/js/admin.js',
array('jquery', 'jquery-ui-sortable', 'jquery-ui-datepicker'),
RP_PLUGIN_VERSION,
true
);
// 加载日期选择器样式
wp_enqueue_style(
'jquery-ui-style',
'https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css'
);
// 本地化脚本
wp_localize_script('rp-admin-script', 'rp_admin', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('rp_admin_nonce'),
'confirm_delete' => __('确定要删除这个项目吗?', 'rapid-prototyping'),
'saving' => __('保存中...', 'rapid-prototyping'),
'saved' => __('已保存', 'rapid-prototyping')
));
}
public function enqueue_frontend_scripts() {
// 只在需要的地方加载
if (has_shortcode(get_post()->post_content, 'rp_submission_form') ||
has_shortcode(get_post()->post_content, 'rp_project_status')) {
// 前端CSS
wp_enqueue_style(
'rp-frontend-style',
RP_PLUGIN_URL . 'assets/css/frontend.css',
array(),
RP_PLUGIN_VERSION
);
// 前端JavaScript
wp_enqueue_script(
'rp-frontend-script',
RP_PLUGIN_URL . 'assets/js/frontend.js',
array('jquery'),
RP_PLUGIN_VERSION,
true
);
// 本地化脚本
wp_localize_script('rp-frontend-script', 'rp_frontend', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('rp_frontend_nonce'),
'uploading' => __('上传中...', 'rapid-prototyping'),
'max_files' => __('最多只能上传5个文件', 'rapid-prototyping'),
'invalid_file' => __('文件格式不支持', 'rapid-prototyping')
));
}
}
?>
<!-- assets/css/admin.css -->
<style>
/* 管理界面样式 */
.rp-dashboard {
padding: 20px;
}
.rp-stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin: 20px 0;
}
.rp-stat-card {
background: #fff;
border: 1px solid #ccd0d4;
border-radius: 4px;
padding: 20px;
text-align: center;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.rp-stat-card h3 {
font-size: 2em;
margin: 0 0 10px;
color: #2271b1;
}
.rp-projects-table {
background: #fff;
border: 1px solid #ccd0d4;
border-radius: 4px;
overflow: hidden;
}
.rp-projects-table table {
width: 100%;
border-collapse: collapse;
}
.rp-projects-table th {
background: #f6f7f7;
padding: 12px;
text-align: left;
border-bottom: 2px solid #ccd0d4;
}
.rp-projects-table td {
padding: 12px;
border-bottom: 1px solid #f0f0f0;
}
.rp-status-badge {
display: inline-block;
padding: 4px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
}
.rp-status-draft { background: #f0f0f0; color: #666; }
.rp-status-in_progress { background: #e1f5fe; color: #0277bd; }
.rp-status-review { background: #fff3e0; color: #ef6c00; }
.rp-status-completed { background: #e8f5e9; color: #2e7d32; }
.rp-status-cancelled { background: #ffebee; color: #c62828; }
.rp-action-buttons {
display: flex;
gap: 5px;
}
.rp-btn {
padding: 6px 12px;
border: none;
border-radius: 3px;
cursor: pointer;
font-size: 13px;
text-decoration: none;
display: inline-block;
}
.rp-btn-primary {
background: #2271b1;
color: white;
}
.rp-btn-secondary {
background: #f6f7f7;
color: #2271b1;
border: 1px solid #2271b1;
}
.rp-btn-danger {
background: #d63638;
color: white;
}
.rp-form-container {
background: #fff;
padding: 20px;
border: 1px solid #ccd0d4;
border-radius: 4px;
max-width: 800px;
}
.rp-form-group {
margin-bottom: 20px;
}
.rp-form-group label {
display: block;
margin-bottom: 5px;
font-weight: 600;
}
.rp-form-group input[type="text"],
.rp-form-group input[type="number"],
.rp-form-group input[type="date"],
.rp-form-group select,
.rp-form-group textarea {
width: 100%;
padding: 8px;
border: 1px solid #8c8f94;
border-radius: 4px;
box-sizing: border-box;
}
.rp-form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.rp-help-text {
font-size: 12px;
color: #666;
margin-top: 5px;
}
</style>
<!-- assets/js/admin.js -->
<script>
jQuery(document).ready(function($) {
// 项目状态快速编辑
$('.rp-status-select').on('change', function() {
var projectId = $(this).data('project-id');
var newStatus = $(this).val();
$.ajax({
url: rp_admin.ajax_url,
type: 'POST',
data: {
action: 'rp_update_status',
project_id: projectId,
status: newStatus,
nonce: rp_admin.nonce
},
beforeSend: function() {
$(this).prop('disabled', true);
},
success: function(response) {
if (response.success) {
// 更新状态徽章
var badge = $('.rp-status-badge[data-project-id="' + projectId + '"]');
badge.removeClass().addClass('rp-status-badge rp-status-' + newStatus)
.text(response.data.status_label);
// 显示成功消息
showMessage(response.data.message, 'success');
} else {
showMessage(response.data.message, 'error');
}
},
complete: function() {
$(this).prop('disabled', false);
}
});
});
// 批量操作
$('#rp-bulk-action').on('click', function() {
var action = $('#bulk-action-selector').val();
var selectedProjects = $('.rp-project-checkbox:checked').map(function() {
return $(this).val();
}).get();
if (selectedProjects.length === 0) {
alert('请至少选择一个项目');
return;
}
if (confirm('确定要执行此操作吗?')) {
$.ajax({
url: rp_admin.ajax_url,
type: 'POST',
data: {
action: 'rp_bulk_action',
projects: selectedProjects,
bulk_action: action,
nonce: rp_admin.nonce
},
success: function(response) {
if (response.success) {
location.reload();
} else {
showMessage(response.data.message, 'error');
}
}
});
}
});
// 日期选择器
$('.rp-datepicker').datepicker({
dateFormat: 'yy-mm-dd',
minDate: 0
});
// 文件上传预览
$('.rp-file-upload').on('change', function(e) {
var files = e.target.files;
var previewContainer = $(this).siblings('.rp-file-preview');
previewContainer.empty();
for (var i = 0; i < files.length; i++) {
var file = files[i];
var reader = new FileReader();
reader.onload = function(e) {
var preview = $('<div class="rp-file-preview-item"></div>');
if (file.type.startsWith('image/')) {
preview.append('<img src="' + e.target.result + '" alt="' + file.name + '">');
}
preview.append('<span>' + file.name + '</span>');
previewContainer.append(preview);
}
reader.readAsDataURL(file);
}
});
function showMessage(message, type) {
var messageDiv = $('<div class="rp-message rp-message-' + type + '"></div>')
.text(message)
.hide()
.appendTo('.wrap');
messageDiv.fadeIn().delay(3000).fadeOut(function() {
$(this).remove();
});
}
});
</script>
7. 项目状态跟踪系统
实现完整的项目状态跟踪和工作流管理:
<?php
// 在RapidPrototypingPlugin类中添加状态管理方法
class RP_Workflow_Manager {
private static $statuses = array(
'draft' => array(
'label' => '草稿',
'color' => '#666',
'next_steps' => array('in_progress', 'cancelled')
),
'in_progress' => array(
'label' => '进行中',
'color' => '#0277bd',
'next_steps' => array('review', 'cancelled')
),
'review' => array(
'label' => '审核中',
'color' => '#ef6c00',
'next_steps' => array('in_progress', 'completed', 'cancelled')
),
'completed' => array(
'label' => '已完成',
'color' => '#2e7d32',
'next_steps' => array()
),
'cancelled' => array(
'label' => '已取消',
'color' => '#c62828',
'next_steps' => array()
)
);
public static function get_statuses() {
return apply_filters('rp_workflow_statuses', self::$statuses);
}
public static function get_status_label($status) {
$statuses = self::get_statuses();
return isset($statuses[$status]) ? $statuses[$status]['label'] : $status;
}
public static function get_next_possible_statuses($current_status) {
$statuses = self::get_statuses();
return isset($statuses[$current_status]) ? $statuses[$current_status]['next_steps'] : array();
}
public static function can_transition($from_status, $to_status) {
$next_steps = self::get_next_possible_statuses($from_status);
return in_array($to_status, $next_steps);
}
public static function update_project_status($project_id, $new_status, $user_id = null) {
global $wpdb;
$table_name = $wpdb->prefix . 'rapid_prototyping_projects';
// 获取当前状态
$current_status = $wpdb->get_var($wpdb->prepare(
"SELECT status FROM $table_name WHERE id = %d",
$project_id
));
// 检查状态转换是否允许
if (!self::can_transition($current_status, $new_status)) {
return new WP_Error('invalid_transition',
sprintf(__('无法从"%s"状态转换到"%s"状态', 'rapid-prototyping'),
self::get_status_label($current_status),
self::get_status_label($new_status)
)
);
}
// 更新状态
$result = $wpdb->update(
$table_name,
array('status' => $new_status, 'updated_at' => current_time('mysql')),
array('id' => $project_id)
);
if ($result !== false) {
// 记录状态变更历史
self::log_status_change($project_id, $current_status, $new_status, $user_id);
// 发送通知
self::send_status_notification($project_id, $current_status, $new_status);
return true;
}
return false;
}
private static function log_status_change($project_id, $old_status, $new_status, $user_id = null) {
global $wpdb;
$log_table = $wpdb->prefix . 'rapid_prototyping_status_log';
$wpdb->insert($log_table, array(
'project_id' => $project_id,
'old_status' => $old_status,
'new_status' => $new_status,
'changed_by' => $user_id ?: get_current_user_id(),
'changed_at' => current_time('mysql')
));
}
private static function send_status_notification($project_id, $old_status, $new_status) {
global $wpdb;
$project_table = $wpdb->prefix . 'rapid_prototyping_projects';
$team_table = $wpdb->prefix . 'rapid_prototyping_team';
// 获取项目信息
$project = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM $project_table WHERE id = %d",
$project_id
));
// 获取团队成员
$team_members = $wpdb->get_results($wpdb->prepare(
"SELECT user_id FROM $team_table WHERE project_id = %d",
$project_id
));
// 收集所有需要通知的用户
$recipients = array($project->designer_id);
foreach ($team_members as $member) {
$recipients[] = $member->user_id;
}
$recipients = array_unique($recipients);
// 发送邮件给每个用户
foreach ($recipients as $user_id) {
$user = get_user_by('id', $user_id);
if ($user) {
$subject = sprintf(__('项目状态更新: %s', 'rapid-prototyping'), $project->project_name);
$message = sprintf(__(
'您好 %s,
您的项目"%s"状态已更新:
从: %s
到: %s
项目详情: %s
感谢您使用快速打样系统。
', 'rapid-prototyping'),
$user->display_name,
$project->project_name,
self::get_status_label($old_status),
self::get_status_label($new_status),
admin_url('admin.php?page=rp-projects&action=view&id=' . $project_id)
);
wp_mail($user->user_email, $subject, $message);
}
}
}
public static function get_status_timeline($project_id) {
global $wpdb;
$log_table = $wpdb->prefix . 'rapid_prototyping_status_log';
$logs = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM $log_table
WHERE project_id = %d
ORDER BY changed_at DESC",
$project_id
));
$timeline = array();
foreach ($logs as $log) {
$user = get_user_by('id', $log->changed_by);
$timeline[] = array(
'timestamp' => $log->changed_at,
'old_status' => self::get_status_label($log->old_status),
'new_status' => self::get_status_label($log->new_status),
'changed_by' => $user ? $user->display_name : __('系统', 'rapid-prototyping'),
'avatar' => $user ? get_avatar_url($user->ID, array('size' => 32)) : ''
);
}
return $timeline;
}
}
?>
8. 团队协作功能
实现团队成员管理和协作功能:
<?php
// 团队管理类
class RP_Team_Manager {
public static function add_team_member($project_id, $user_id, $role = 'collaborator') {
global $wpdb;
$table_name = $wpdb->prefix . 'rapid_prototyping_team';
// 检查是否已是团队成员
$existing = $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM $table_name
WHERE project_id = %d AND user_id = %d",
$project_id, $user_id
));
if ($existing > 0) {
return new WP_Error('already_member',
__('该用户已是团队成员', 'rapid-prototyping'));
}
// 添加团队成员
$result = $wpdb->insert($table_name, array(
'project_id' => $project_id,


