手把手教学:为你的网站添加在线协同代码审查与版本对比功能
引言:为什么网站需要代码审查与版本对比功能?
在当今数字化时代,网站已不仅仅是信息展示平台,更是企业与用户互动的重要窗口。对于技术团队、开发者社区或教育类网站而言,提供代码协作和审查功能可以极大提升用户体验和参与度。想象一下,如果你的WordPress网站能让用户在线协作审查代码、对比不同版本,这不仅能吸引更多开发者用户,还能为现有用户提供强大的实用工具。
传统的代码审查通常需要复杂的开发环境和专业工具,但通过WordPress的灵活性和可扩展性,我们可以将这些专业功能集成到普通网站中。本文将手把手教你如何通过WordPress二次开发,为你的网站添加在线协同代码审查与版本对比功能,无需从头构建复杂系统,利用现有插件和自定义开发实现这一目标。
第一部分:准备工作与环境搭建
1.1 选择合适的WordPress环境
在开始之前,确保你的WordPress环境满足以下要求:
- WordPress 5.0或更高版本
- PHP 7.4或更高版本(推荐PHP 8.0+)
- MySQL 5.6或更高版本
- 至少256MB内存限制
- 支持HTTPS(协同功能需要安全连接)
1.2 必备插件安装
我们将使用一些现有插件作为基础,减少开发工作量:
- Advanced Custom Fields (ACF) - 用于创建自定义字段和元数据
- User Role Editor - 管理用户权限和角色
- WP Code Highlight.js - 代码高亮显示
- Simple History - 记录操作日志
安装这些插件后,激活并确保它们正常运行。
1.3 创建子主题
为了避免主题更新覆盖我们的修改,建议创建子主题:
- 在
wp-content/themes/目录下创建新文件夹,命名为my-code-review-theme -
创建
style.css文件,添加以下内容:/* Theme Name: Code Review Child Theme Template: your-parent-theme-folder-name Version: 1.0 */ @import url("../your-parent-theme-folder-name/style.css"); - 创建
functions.php文件,暂时留空 - 在WordPress后台启用这个子主题
第二部分:数据库设计与数据模型
2.1 设计代码审查数据结构
我们需要创建自定义数据库表来存储代码审查相关数据。在子主题的functions.php中添加以下代码:
// 创建自定义数据库表
function create_code_review_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'code_reviews';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
title varchar(255) NOT NULL,
description text,
code_content longtext NOT NULL,
language varchar(50) DEFAULT 'php',
status varchar(20) DEFAULT 'pending',
author_id bigint(20) NOT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// 创建评论表
$comments_table = $wpdb->prefix . 'code_review_comments';
$sql2 = "CREATE TABLE IF NOT EXISTS $comments_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
review_id mediumint(9) NOT NULL,
user_id bigint(20) NOT NULL,
content text NOT NULL,
line_number int(11),
resolved tinyint(1) DEFAULT 0,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY review_id (review_id)
) $charset_collate;";
dbDelta($sql2);
// 创建版本表
$versions_table = $wpdb->prefix . 'code_review_versions';
$sql3 = "CREATE TABLE IF NOT EXISTS $versions_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
review_id mediumint(9) NOT NULL,
version_number int(11) NOT NULL,
code_content longtext NOT NULL,
author_id bigint(20) NOT NULL,
change_summary text,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY review_id (review_id)
) $charset_collate;";
dbDelta($sql3);
}
add_action('after_setup_theme', 'create_code_review_tables');
2.2 使用ACF创建自定义字段
通过Advanced Custom Fields插件创建代码审查所需的字段组:
- 在WordPress后台进入ACF -> 字段组 -> 新建
-
添加以下字段:
- 代码语言选择器(选择字段)
- 代码内容(文本区域字段,使用Monaco编辑器样式)
- 审查状态(选择字段:待审查、进行中、已完成)
- 允许协作的用户(用户关系字段)
- 将字段组分配给"代码审查"文章类型(我们将在下一节创建)
第三部分:创建代码审查自定义文章类型
3.1 注册自定义文章类型
在子主题的functions.php中添加以下代码:
// 注册代码审查自定义文章类型
function register_code_review_post_type() {
$labels = array(
'name' => '代码审查',
'singular_name' => '代码审查',
'menu_name' => '代码审查',
'add_new' => '添加新审查',
'add_new_item' => '添加新代码审查',
'edit_item' => '编辑代码审查',
'new_item' => '新代码审查',
'view_item' => '查看代码审查',
'search_items' => '搜索代码审查',
'not_found' => '未找到代码审查',
'not_found_in_trash' => '回收站中无代码审查'
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array('slug' => 'code-review'),
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'menu_position' => 5,
'menu_icon' => 'dashicons-editor-code',
'supports' => array('title', 'editor', 'author', 'comments'),
'show_in_rest' => true, // 启用Gutenberg编辑器支持
);
register_post_type('code_review', $args);
}
add_action('init', 'register_code_review_post_type');
3.2 添加自定义分类法
为代码审查添加分类,如编程语言、项目类型等:
// 注册代码审查分类法
function register_code_review_taxonomies() {
// 编程语言分类
$language_labels = array(
'name' => '编程语言',
'singular_name' => '编程语言',
'search_items' => '搜索编程语言',
'all_items' => '所有编程语言',
'parent_item' => '父级编程语言',
'parent_item_colon' => '父级编程语言:',
'edit_item' => '编辑编程语言',
'update_item' => '更新编程语言',
'add_new_item' => '添加新编程语言',
'new_item_name' => '新编程语言名称',
'menu_name' => '编程语言',
);
$language_args = array(
'hierarchical' => true,
'labels' => $language_labels,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array('slug' => 'code-language'),
'show_in_rest' => true,
);
register_taxonomy('code_language', array('code_review'), $language_args);
}
add_action('init', 'register_code_review_taxonomies');
第四部分:前端代码编辑器集成
4.1 集成Monaco代码编辑器
Monaco是VS Code使用的编辑器,功能强大。我们将它集成到WordPress中:
// 添加Monaco编辑器资源
function enqueue_code_editor_assets() {
if (is_singular('code_review') || is_post_type_archive('code_review')) {
// Monaco Editor
wp_enqueue_script('monaco-editor', 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/loader.min.js', array(), '0.34.0', true);
// 自定义编辑器脚本
wp_enqueue_script('code-review-editor', get_stylesheet_directory_uri() . '/js/code-editor.js', array('jquery', 'monaco-editor'), '1.0', true);
// 编辑器样式
wp_enqueue_style('code-review-style', get_stylesheet_directory_uri() . '/css/code-review.css', array(), '1.0');
// 传递数据到JavaScript
wp_localize_script('code-review-editor', 'codeReviewData', array(
'postId' => get_the_ID(),
'userId' => get_current_user_id(),
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('code_review_nonce')
));
}
}
add_action('wp_enqueue_scripts', 'enqueue_code_editor_assets');
4.2 创建编辑器前端界面
创建/js/code-editor.js文件:
(function($) {
'use strict';
// 等待Monaco编辑器加载
require.config({ paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs' } });
$(document).ready(function() {
// 初始化代码编辑器
if ($('#code-editor-container').length) {
initCodeEditor();
}
// 初始化版本对比功能
if ($('#diff-editor-container').length) {
initDiffEditor();
}
});
function initCodeEditor() {
require(['vs/editor/editor.main'], function() {
// 获取代码内容
var initialCode = $('#code-content').val() || '// 在这里输入你的代码nconsole.log("Hello, World!");';
var language = $('#code-language').val() || 'javascript';
// 创建编辑器实例
window.codeEditor = monaco.editor.create(document.getElementById('code-editor-container'), {
value: initialCode,
language: language,
theme: 'vs-dark',
fontSize: 14,
minimap: {
enabled: true
},
scrollBeyondLastLine: false,
automaticLayout: true
});
// 监听内容变化
window.codeEditor.onDidChangeModelContent(function() {
$('#code-content').val(window.codeEditor.getValue());
});
// 语言切换
$('#code-language').on('change', function() {
var language = $(this).val();
monaco.editor.setModelLanguage(window.codeEditor.getModel(), language);
});
});
}
function initDiffEditor() {
require(['vs/editor/editor.main'], function() {
// 获取对比的代码版本
var originalCode = $('#original-code').val() || '';
var modifiedCode = $('#modified-code').val() || '';
var language = $('#diff-language').val() || 'javascript';
// 创建对比编辑器
window.diffEditor = monaco.editor.createDiffEditor(document.getElementById('diff-editor-container'), {
theme: 'vs-dark',
fontSize: 14,
readOnly: true,
automaticLayout: true
});
// 设置对比模型
var originalModel = monaco.editor.createModel(originalCode, language);
var modifiedModel = monaco.editor.createModel(modifiedCode, language);
window.diffEditor.setModel({
original: originalModel,
modified: modifiedModel
});
});
}
// 保存代码版本
window.saveCodeVersion = function() {
var codeContent = window.codeEditor ? window.codeEditor.getValue() : '';
var changeSummary = prompt('请输入本次更改的摘要:', '');
if (changeSummary === null) return;
$.ajax({
url: codeReviewData.ajaxUrl,
type: 'POST',
data: {
action: 'save_code_version',
post_id: codeReviewData.postId,
code_content: codeContent,
change_summary: changeSummary,
nonce: codeReviewData.nonce
},
success: function(response) {
if (response.success) {
alert('版本保存成功!');
location.reload();
} else {
alert('保存失败: ' + response.data);
}
}
});
};
// 添加行内评论
window.addLineComment = function(lineNumber) {
var commentText = prompt('请输入对第 ' + lineNumber + ' 行的评论:', '');
if (commentText === null || commentText.trim() === '') return;
$.ajax({
url: codeReviewData.ajaxUrl,
type: 'POST',
data: {
action: 'add_line_comment',
post_id: codeReviewData.postId,
line_number: lineNumber,
comment: commentText,
nonce: codeReviewData.nonce
},
success: function(response) {
if (response.success) {
alert('评论添加成功!');
location.reload();
} else {
alert('添加失败: ' + response.data);
}
}
});
};
})(jQuery);
第五部分:版本对比功能实现
5.1 创建版本对比界面
在子主题中创建code-review-diff.php模板文件:
<?php
/**
* 代码版本对比模板
*/
get_header(); ?>
<div class="container code-review-container">
<div class="row">
<div class="col-md-12">
<h1 class="page-title">代码版本对比</h1>
<?php
$review_id = isset($_GET['review_id']) ? intval($_GET['review_id']) : 0;
$version1 = isset($_GET['v1']) ? intval($_GET['v1']) : 0;
$version2 = isset($_GET['v2']) ? intval($_GET['v2']) : 0;
if ($review_id && $version1 && $version2) {
global $wpdb;
$versions_table = $wpdb->prefix . 'code_review_versions';
// 获取版本1内容
$version1_data = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM $versions_table WHERE id = %d AND review_id = %d",
$version1, $review_id
));
// 获取版本2内容
$version2_data = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM $versions_table WHERE id = %d AND review_id = %d",
$version2, $review_id
));
if ($version1_data && $version2_data) {
?>
<div class="diff-info">
<h3>对比版本 <?php echo $version1_data->version_number; ?> 与版本 <?php echo $version2_data->version_number; ?></h3>
<p><strong>版本<?php echo $version1_data->version_number; ?>:</strong> <?php echo esc_html($version1_data->change_summary); ?> (<?php echo date('Y-m-d H:i', strtotime($version1_data->created_at)); ?>)</p>
<p><strong>版本<?php echo $version2_data->version_number; ?>:</strong> <?php echo esc_html($version2_data->change_summary); ?> (<?php echo date('Y-m-d H:i', strtotime($version2_data->created_at)); ?>)</p>
</div>
<div class="diff-container">
<div id="diff-editor-container" style="height: 600px; border: 1px solid #ddd;"></div>
<textarea id="original-code" style="display:none;"><?php echo esc_textarea($version1_data->code_content); ?></textarea>
<textarea id="modified-code" style="display:none;"><?php echo esc_textarea($version2_data->code_content); ?></textarea>
<input type="hidden" id="diff-language" value="php">
</div>
<div class="diff-actions mt-3">
<a href="<?php echo get_permalink($review_id); ?>" class="btn btn-secondary">返回代码审查</a>
<button onclick="window.print()" class="btn btn-info">打印对比结果</button>
</div>
<?php
} else {
echo '<div class="alert alert-danger">未找到指定的版本数据。</div>';
}
} else {
echo '<div class="alert alert-warning">请选择要对比的版本。</div>';
}
?>
</div>
</div>
</div>
<?php get_footer(); ?>
5.2 实现版本对比算法
创建/includes/diff-functions.php文件,实现简单的行级对比:
<?php
/**
* 代码对比功能函数
*/
// 简单的行级对比函数
function compare_code_versions($code1, $code2) {
$lines1 = explode("n", $code1);
$lines2 = explode("n", $code2);
$diff = array();
$maxLines = max(count($lines1), count($lines2));
0; $i < $maxLines; $i++) {
$line1 = isset($lines1[$i]) ? $lines1[$i] : '';
$line2 = isset($lines2[$i]) ? $lines2[$i] : '';
if ($line1 !== $line2) {
$diff[] = array(
'line' => $i + 1,
'original' => $line1,
'modified' => $line2,
'type' => $line1 === '' ? 'added' : ($line2 === '' ? 'removed' : 'changed')
);
}
}
return $diff;
}
// 生成对比HTML
function generate_diff_html($code1, $code2, $language = 'php') {
$diff = compare_code_versions($code1, $code2);
if (empty($diff)) {
return '<div class="alert alert-success">两个版本完全相同</div>';
}
$html = '<div class="code-diff-view">';
$html .= '<table class="diff-table table table-bordered">';
$html .= '<thead><tr><th width="5%">行号</th><th width="45%">版本A</th><th width="45%">版本B</th><th width="5%">状态</th></tr></thead>';
$html .= '<tbody>';
foreach ($diff as $change) {
$status_class = '';
$status_text = '';
switch ($change['type']) {
case 'added':
$status_class = 'diff-added';
$status_text = '+';
break;
case 'removed':
$status_class = 'diff-removed';
$status_text = '-';
break;
case 'changed':
$status_class = 'diff-changed';
$status_text = '~';
break;
}
$html .= '<tr class="' . $status_class . '">';
$html .= '<td class="line-number">' . $change['line'] . '</td>';
$html .= '<td class="original-line"><code>' . htmlspecialchars($change['original']) . '</code></td>';
$html .= '<td class="modified-line"><code>' . htmlspecialchars($change['modified']) . '</code></td>';
$html .= '<td class="diff-status">' . $status_text . '</td>';
$html .= '</tr>';
}
$html .= '</tbody></table></div>';
return $html;
}
// 获取版本历史
function get_code_version_history($review_id) {
global $wpdb;
$versions_table = $wpdb->prefix . 'code_review_versions';
$versions = $wpdb->get_results($wpdb->prepare(
"SELECT v.*, u.display_name as author_name
FROM $versions_table v
LEFT JOIN {$wpdb->users} u ON v.author_id = u.ID
WHERE v.review_id = %d
ORDER BY v.version_number DESC",
$review_id
));
return $versions;
}
?>
## 第六部分:协同审查功能实现
### 6.1 实时评论系统
创建实时评论功能,允许用户在特定代码行添加评论:
// 在functions.php中添加AJAX处理函数
add_action('wp_ajax_add_line_comment', 'handle_add_line_comment');
add_action('wp_ajax_nopriv_add_line_comment', 'handle_add_line_comment_no_priv');
function handle_add_line_comment() {
// 验证nonce
if (!wp_verify_nonce($_POST['nonce'], 'code_review_nonce')) {
wp_die('安全验证失败');
}
// 检查用户权限
if (!is_user_logged_in()) {
wp_send_json_error('请先登录');
}
$post_id = intval($_POST['post_id']);
$line_number = intval($_POST['line_number']);
$comment = sanitize_textarea_field($_POST['comment']);
$user_id = get_current_user_id();
// 检查用户是否有权限评论
$allowed_users = get_field('allowed_collaborators', $post_id);
$is_allowed = false;
if ($allowed_users) {
foreach ($allowed_users as $allowed_user) {
if ($allowed_user['ID'] == $user_id) {
$is_allowed = true;
break;
}
}
}
// 如果是作者或管理员,也允许评论
$post = get_post($post_id);
if ($post->post_author == $user_id || current_user_can('manage_options')) {
$is_allowed = true;
}
if (!$is_allowed) {
wp_send_json_error('您没有权限在此代码审查中添加评论');
}
// 保存评论到数据库
global $wpdb;
$comments_table = $wpdb->prefix . 'code_review_comments';
$result = $wpdb->insert(
$comments_table,
array(
'review_id' => $post_id,
'user_id' => $user_id,
'content' => $comment,
'line_number' => $line_number,
'resolved' => 0,
'created_at' => current_time('mysql')
),
array('%d', '%d', '%s', '%d', '%d', '%s')
);
if ($result) {
// 发送通知邮件
send_comment_notification($post_id, $user_id, $comment, $line_number);
wp_send_json_success('评论添加成功');
} else {
wp_send_json_error('评论保存失败');
}
}
function handle_add_line_comment_no_priv() {
wp_send_json_error('请先登录');
}
// 发送评论通知
function send_comment_notification($post_id, $commenter_id, $comment, $line_number) {
$post = get_post($post_id);
$commenter = get_userdata($commenter_id);
$author = get_userdata($post->post_author);
$subject = '您的代码审查有新的评论';
$message = "您好 " . $author->display_name . ",nn";
$message .= $commenter->display_name . " 在您的代码审查中添加了评论:nn";
$message .= "代码行号: " . $line_number . "n";
$message .= "评论内容: " . $comment . "nn";
$message .= "查看详情: " . get_permalink($post_id) . "nn";
$message .= "此邮件由系统自动发送,请勿回复。";
wp_mail($author->user_email, $subject, $message);
}
### 6.2 评论显示与交互界面
创建评论显示模板:
// 在single-code_review.php模板中添加评论显示
function display_code_comments($review_id) {
global $wpdb;
$comments_table = $wpdb->prefix . 'code_review_comments';
$comments = $wpdb->get_results($wpdb->prepare(
"SELECT c.*, u.display_name, u.user_email, u.user_nicename
FROM $comments_table c
LEFT JOIN {$wpdb->users} u ON c.user_id = u.ID
WHERE c.review_id = %d
ORDER BY c.line_number, c.created_at",
$review_id
));
if (empty($comments)) {
return '<div class="no-comments">暂无评论</div>';
}
// 按行号分组
$grouped_comments = array();
foreach ($comments as $comment) {
$line = $comment->line_number ?: 'general';
if (!isset($grouped_comments[$line])) {
$grouped_comments[$line] = array();
}
$grouped_comments[$line][] = $comment;
}
$html = '<div class="code-comments-section">';
$html .= '<h3>代码评论</h3>';
foreach ($grouped_comments as $line_number => $line_comments) {
$line_label = ($line_number === 'general') ? '通用评论' : '第 ' . $line_number . ' 行';
$html .= '<div class="comment-group" data-line="' . $line_number . '">';
$html .= '<h4 class="comment-group-title">' . $line_label . '</h4>';
foreach ($line_comments as $comment) {
$resolved_class = $comment->resolved ? 'resolved' : '';
$avatar = get_avatar($comment->user_email, 32);
$html .= '<div class="comment-item ' . $resolved_class . '" id="comment-' . $comment->id . '">';
$html .= '<div class="comment-header">';
$html .= '<div class="comment-author">' . $avatar . ' <strong>' . $comment->display_name . '</strong></div>';
$html .= '<div class="comment-meta">' . date('Y-m-d H:i', strtotime($comment->created_at)) . '</div>';
$html .= '</div>';
$html .= '<div class="comment-content">' . nl2br(esc_html($comment->content)) . '</div>';
// 评论操作按钮
if (current_user_can('manage_options') || get_current_user_id() == $comment->user_id) {
$html .= '<div class="comment-actions">';
if (!$comment->resolved) {
$html .= '<button class="btn-resolve-comment btn btn-sm btn-success" data-comment-id="' . $comment->id . '">标记为已解决</button>';
} else {
$html .= '<button class="btn-unresolve-comment btn btn-sm btn-warning" data-comment-id="' . $comment->id . '">重新打开</button>';
}
$html .= '<button class="btn-delete-comment btn btn-sm btn-danger" data-comment-id="' . $comment->id . '">删除</button>';
$html .= '</div>';
}
$html .= '</div>';
}
$html .= '</div>';
}
$html .= '</div>';
return $html;
}
## 第七部分:用户权限与协作管理
### 7.1 自定义用户角色与权限
使用User Role Editor插件或代码创建自定义角色:
// 创建代码审查者角色
function create_code_reviewer_role() {
// 复制贡献者角色作为基础
$contributor = get_role('contributor');
// 添加代码审查者角色
add_role('code_reviewer', '代码审查者', $contributor->capabilities);
// 获取代码审查者角色并添加额外权限
$reviewer = get_role('code_reviewer');
// 添加自定义文章类型相关权限
$reviewer->add_cap('edit_code_reviews');
$reviewer->add_cap('edit_others_code_reviews');
$reviewer->add_cap('publish_code_reviews');
$reviewer->add_cap('read_private_code_reviews');
$reviewer->add_cap('delete_code_reviews');
// 添加自定义分类法权限
$reviewer->add_cap('manage_code_languages');
$reviewer->add_cap('edit_code_languages');
$reviewer->add_cap('delete_code_languages');
$reviewer->add_cap('assign_code_languages');
}
add_action('init', 'create_code_reviewer_role');
// 设置默认权限
function set_default_code_review_permissions() {
// 给管理员和编辑者添加权限
$admin = get_role('administrator');
$editor = get_role('editor');
$caps = array(
'edit_code_reviews',
'edit_others_code_reviews',
'publish_code_reviews',
'read_private_code_reviews',
'delete_code_reviews',
'manage_code_languages',
'edit_code_languages',
'delete_code_languages',
'assign_code_languages'
);
foreach ($caps as $cap) {
if ($admin) $admin->add_cap($cap);
if ($editor) $editor->add_cap($cap);
}
}
add_action('admin_init', 'set_default_code_review_permissions');
### 7.2 协作邀请系统
创建用户邀请功能:
// 添加协作邀请功能
function add_collaborator_invitation($review_id, $invitee_email, $inviter_id) {
// 检查用户是否存在
$invitee = get_user_by('email', $invitee_email);
if ($invitee) {
// 用户已存在,直接添加到允许列表
$allowed_users = get_field('allowed_collaborators', $review_id);
if (!$allowed_users) {
$allowed_users = array();
}
// 检查是否已存在
$already_added = false;
foreach ($allowed_users as $user) {
if ($user['ID'] == $invitee->ID) {
$already_added = true;
break;
}
}
if (!$already_added) {
$allowed_users[] = array('ID' => $invitee->ID);
update_field('allowed_collaborators', $allowed_users, $review_id);
// 发送通知
send_invitation_notification($review_id, $invitee->ID, $inviter_id, false);
return array('success' => true, 'message' => '用户已添加到协作列表');
} else {
return array('success' => false, 'message' => '用户已在协作列表中');
}
} else {
// 用户不存在,创建邀请记录
global $wpdb;
$invites_table = $wpdb->prefix . 'code_review_invites';
// 创建表(如果不存在)
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS $invites_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
review_id mediumint(9) NOT NULL,
invitee_email varchar(100) NOT NULL,
inviter_id bigint(20) NOT NULL,
token varchar(64) NOT NULL,
status varchar(20) DEFAULT 'pending',
created_at datetime DEFAULT CURRENT_TIMESTAMP,
expires_at datetime,
PRIMARY KEY (id),
UNIQUE KEY token (token)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// 生成唯一token
$token = wp_generate_password(64, false);
// 设置过期时间(7天后)
$expires = date('Y-m-d H:i:s', strtotime('+7 days'));
// 保存邀请
$wpdb->insert(
$invites_table,
array(
'review_id' => $review_id,
'invitee_email' => $invitee_email,
'inviter_id' => $inviter_id,
'token' => $token,
'expires_at' => $expires
),
array('%d', '%s', '%d', '%s', '%s')
);
// 发送邀请邮件
send_invitation_email($invitee_email, $review_id, $token, $inviter_id);
return array('success' => true, 'message' => '邀请已发送到 ' . $invitee_email);
}
}
// 发送邀请邮件
function send_invitation_email($email, $review_id, $token, $inviter_id) {
$review = get_post($review_id);
$inviter = get_userdata($inviter_id);
$site_name = get_bloginfo('name');
$invite_link = add_query_arg(array(
'action' => 'accept_invite',
'token' => $token,
'review_id' => $review_id
), home_url('/'));
$subject = '您被邀请参与代码审查: ' . $review->post_title;
$message = "您好,nn";
$message .= $inviter->display_name . " 邀请您参与代码审查: " . $review->post_title . "nn";
$message .= "审查描述: " . wp_trim_words($review->post_content, 50) . "nn";
$message .= "点击以下链接接受邀请:n";
$message .= $invite_link . "nn";
$message .= "此链接7天内有效。nn";
$message .= "如果这不是您的邮箱,请忽略此邮件。nn";
$message .= "此邮件由 " . $site_name . " 系统自动发送。";
wp_mail($email, $subject, $message);
}
## 第八部分:前端界面优化与用户体验
### 8.1 响应式设计CSS
创建`/css/code-review.css`文件:
/ 代码审查系统样式 /
/ 主容器 /
.code-review-container {
padding: 20px 0;
max-width: 1200px;
margin: 0 auto;
}
/ 编辑器容器 /
code-editor-container, #diff-editor-container {
border: 1px solid #ddd;
border-radius: 4px;
overflow: hidden;
}
/ 代码行号 /
.code-line-numbers {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 14px;
line-height: 1.5;
color: #999;
text-align: right;
padding-right: 10px;
user-select: none;
}
/ 评论标记 /
.line-comment-marker {
display: inline-block;
width: 20px;
height: 20px;
background-color: #ffc107;
color: #333;
border-radius: 50%;
text-align: center;
line-height: 20
