如何在Manufacturing Industry Pro主题下实现用户发票查看编辑删除(无插件)
无需额外插件实现My Account发票管理分步方案
1. 创建自定义数据库表存储发票信息
首先需要创建专属表来保存发票的用户关联信息、元数据和文件路径,避免和WordPress默认数据混淆。将以下代码添加到主题的functions.php文件:
function create_user_invoices_table() { global $wpdb; $table_name = $wpdb->prefix . 'user_invoices'; $charset_collate = $wpdb->get_charset_collate(); // 仅在表不存在时创建 if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) { $sql = "CREATE TABLE $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, user_id mediumint(9) NOT NULL, tax_number varchar(255) NOT NULL, invoice_date date NOT NULL, invoice_number varchar(255) NOT NULL, invoice_amount decimal(10,2) NOT NULL, file_path varchar(255) NOT NULL, created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL, updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL, PRIMARY KEY (id), KEY user_id_idx (user_id) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } } add_action('after_setup_theme', 'create_user_invoices_table');
代码执行一次后可注释,避免重复触发表创建逻辑。
2. 修改Contact Form 7提交逻辑,同步保存数据到数据库
调整CF7的提交钩子,将表单数据和上传文件保存到数据库,同时保留原邮件发送功能。注意替换代码中的表单ID和字段名称为你实际使用的内容:
function save_cf7_invoice_to_db($contact_form) { // 替换为你的CF7表单ID if ($contact_form->id() != 123) return; $submission = WPCF7_Submission::get_instance(); if (!$submission || !is_user_logged_in()) return; $data = $submission->get_posted_data(); $uploaded_files = $submission->uploaded_files(); $user_id = get_current_user_id(); global $wpdb; $table_name = $wpdb->prefix . 'user_invoices'; // 限制用户最多5张发票 $invoice_count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $table_name WHERE user_id = %d", $user_id)); if ($invoice_count >= 5) { $submission->set_response('最多只能上传5张发票'); return; } // 处理文件上传 $file_path = ''; if (!empty($uploaded_files['invoice-file'])) { $temp_file = $uploaded_files['invoice-file']; $upload_dir = wp_upload_dir(); $target_dir = $upload_dir['basedir'] . '/user-invoices/'; // 创建存储目录 if (!file_exists($target_dir)) { mkdir($target_dir, 0755, true); } $file_name = wp_unique_filename($target_dir, basename($temp_file)); $target_path = $target_dir . $file_name; if (move_uploaded_file($temp_file, $target_path)) { $file_path = $upload_dir['baseurl'] . '/user-invoices/' . $file_name; } else { $submission->set_response('文件上传失败,请重试'); return; } } // 写入数据库 $wpdb->insert( $table_name, array( 'user_id' => $user_id, 'tax_number' => sanitize_text_field($data['tax-number']), 'invoice_date' => sanitize_text_field($data['invoice-date']), 'invoice_number' => sanitize_text_field($data['invoice-number']), 'invoice_amount' => floatval($data['invoice-amount']), 'file_path' => $file_path ), array('%d', '%s', '%s', '%s', '%f', '%s') ); } add_action('wpcf7_before_send_mail', 'save_cf7_invoice_to_db');
3. 在My Account页面添加发票管理标签页
通过WooCommerce的钩子添加自定义端点和菜单,让用户能在个人中心访问发票管理页面:
// 添加菜单项到My Account导航 function add_invoices_account_menu($items) { $items['invoices'] = '我的发票'; return $items; } add_filter('woocommerce_account_menu_items', 'add_invoices_account_menu'); // 注册自定义端点 function register_invoices_endpoint() { add_rewrite_endpoint('invoices', EP_ROOT | EP_PAGES); } add_action('init', 'register_invoices_endpoint'); // 刷新重写规则(执行一次后注释) flush_rewrite_rules();
添加代码后,进入WordPress后台「设置→固定链接」点击保存,确保端点生效。
4. 渲染发票列表与操作页面
实现发票列表展示、查看、编辑、删除功能,添加以下代码到functions.php:
function render_invoices_management_page() { if (!is_user_logged_in()) { wp_redirect(wp_login_url()); exit; } $user_id = get_current_user_id(); global $wpdb; $table_name = $wpdb->prefix . 'user_invoices'; $invoices = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE user_id = %d ORDER BY created_at DESC", $user_id)); echo '<div class="woocommerce-MyAccount-content">'; echo '<h2>我的发票</h2>'; // 空状态提示 if (empty($invoices)) { echo '<p>暂无发票记录</p>'; } else { // 发票列表表格 echo '<table class="woocommerce-orders-table shop_table shop_table_responsive account-invoices-table">'; echo '<thead> <tr> <th>发票编号</th> <th>开票日期</th> <th>金额</th> <th>税号</th> <th>操作</th> </tr> </thead>'; echo '<tbody>'; foreach ($invoices as $invoice) { echo '<tr>'; echo '<td data-title="发票编号">' . esc_html($invoice->invoice_number) . '</td>'; echo '<td data-title="开票日期">' . date('Y-m-d', strtotime($invoice->invoice_date)) . '</td>'; echo '<td data-title="金额">' . wc_price($invoice->invoice_amount) . '</td>'; echo '<td data-title="税号">' . esc_html($invoice->tax_number) . '</td>'; echo '<td data-title="操作">'; echo '<a href="' . esc_url($invoice->file_path) . '" target="_blank" class="button button-small">查看</a> '; echo '<a href="' . esc_url(add_query_arg('edit_invoice', $invoice->id, wc_get_account_endpoint_url('invoices'))) . '" class="button button-small">编辑</a> '; echo '<a href="' . esc_url(wp_nonce_url(add_query_arg('delete_invoice', $invoice->id, wc_get_account_endpoint_url('invoices')), 'delete_invoice_' . $invoice->id)) . '" class="button button-small button-danger" onclick="return confirm(\'确定删除该发票?\')">删除</a>'; echo '</td>'; echo '</tr>'; } echo '</tbody></table>'; } // 处理编辑/删除动作 handle_invoice_actions(); echo '</div>'; } add_action('woocommerce_account_invoices_endpoint', 'render_invoices_management_page'); // 处理发票编辑与删除逻辑 function handle_invoice_actions() { if (!is_user_logged_in()) return; $user_id = get_current_user_id(); global $wpdb; $table_name = $wpdb->prefix . 'user_invoices'; // 删除发票 if (isset($_GET['delete_invoice']) && wp_verify_nonce($_GET['_wpnonce'], 'delete_invoice_' . $_GET['delete_invoice'])) { $invoice_id = intval($_GET['delete_invoice']); $invoice = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table_name WHERE id = %d AND user_id = %d", $invoice_id, $user_id)); if ($invoice) { // 删除服务器文件 $local_file_path = str_replace(wp_upload_dir()['baseurl'], wp_upload_dir()['basedir'], $invoice->file_path); if (file_exists($local_file_path)) unlink($local_file_path); // 删除数据库记录 $wpdb->delete($table_name, array('id' => $invoice_id), array('%d')); } wp_redirect(wc_get_account_endpoint_url('invoices')); exit; } // 编辑发票 if (isset($_GET['edit_invoice'])) { $invoice_id = intval($_GET['edit_invoice']); $invoice = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table_name WHERE id = %d AND user_id = %d", $invoice_id, $user_id)); if (!$invoice) { wp_redirect(wc_get_account_endpoint_url('invoices')); exit; } // 处理表单提交 if (isset($_POST['update_invoice']) && wp_verify_nonce($_POST['update_invoice_nonce'], 'update_invoice_' . $invoice_id)) { $update_data = array( 'tax_number' => sanitize_text_field($_POST['tax-number']), 'invoice_date' => sanitize_text_field($_POST['invoice-date']), 'invoice_number' => sanitize_text_field($_POST['invoice-number']), 'invoice_amount' => floatval($_POST['invoice-amount']) ); // 处理文件替换 if (!empty($_FILES['invoice-file']['tmp_name'])) { // 删除旧文件 $old_local_path = str_replace(wp_upload_dir()['baseurl'], wp_upload_dir()['basedir'], $invoice->file_path); if (file_exists($old_local_path)) unlink($old_local_path); // 上传新文件 $upload_dir = wp_upload_dir(); $target_dir = $upload_dir['basedir'] . '/user-invoices/'; $file_name = wp_unique_filename($target_dir, basename($_FILES['invoice-file']['name'])); $target_path = $target_dir . $file_name; if (move_uploaded_file($_FILES['invoice-file']['tmp_name'], $target_path)) { $update_data['file_path'] = $upload_dir['baseurl'] . '/user-invoices/' . $file_name; } } // 更新数据库 $wpdb->update( $table_name, $update_data, array('id' => $invoice_id), array('%s', '%s', '%s', '%f', '%s'), array('%d') ); wp_redirect(wc_get_account_endpoint_url('invoices')); exit; } // 渲染编辑表单 echo '<h3>编辑发票</h3>'; echo '<form method="post" enctype="multipart/form-data" class="woocommerce-form-edit-invoice">'; wp_nonce_field('update_invoice_' . $invoice_id, 'update_invoice_nonce'); echo '<div class="form-row"> <label for="tax-number">税号</label> <input type="text" name="tax-number" id="tax-number" value="' . esc_attr($invoice->tax_number) . '" required> </div>'; echo '<div class="form-row"> <label for="invoice-date">开票日期</label> <input type="date" name="invoice-date" id="invoice-date" value="' . esc_attr($invoice->invoice_date) . '" required> </div>'; echo '<div class="form-row"> <label for="invoice-number">发票编号</label> <input type="text" name="invoice-number" id="invoice-number" value="' . esc_attr($invoice->invoice_number) . '" required> </div>'; echo '<div class="form-row"> <label for="invoice-amount">发票金额</label> <input type="number" step="0.01" name="invoice-amount" id="invoice-amount" value="' . esc_attr($invoice->invoice_amount) . '" required> </div>'; echo '<div class="form-row"> <label for="invoice-file">替换发票文件(可选)</label> <input type="file" name="invoice-file" id="invoice-file" accept=".pdf,.jpg,.jpeg,.png"> <small>当前文件:<a href="' . esc_url($invoice->file_path) . '" target="_blank">查看</a></small> </div>'; echo '<div class="form-row"> <button type="submit" name="update_invoice" class="button">保存修改</button> <a href="' . esc_url(wc_get_account_endpoint_url('invoices')) . '" class="button">取消</a> </div>'; echo '</form>'; } }
5. 样式适配(可选)
添加以下CSS到主题自定义样式中,让发票页面和主题风格统一:
.account-invoices-table { width: 100%; margin: 2em 0; border-collapse: collapse; } .account-invoices-table th, .account-invoices-table td { padding: 12px; border-bottom: 1px solid #eee; } .woocommerce-form-edit-invoice .form-row { margin-bottom: 1.5em; } .woocommerce-form-edit-invoice label { display: block; margin-bottom: 0.5em; font-weight: 600; } .woocommerce-form-edit-invoice input[type="text"], .woocommerce-form-edit-invoice input[type="date"], .woocommerce-form-edit-invoice input[type="number"] { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; } .button-danger { background-color: #dc3232; color: #fff; } .button-danger:hover { background-color: #b92c2c; }
注意事项
- 所有代码建议添加到主题的
functions.php,或创建一个独立的自定义插件(避免主题更新丢失代码)。 - 操作前备份数据库和网站文件。
- 确保服务器目录权限正确(
user-invoices目录需具备写入权限)。 - 可在CF7表单中添加额外验证规则,比如限制文件类型为PDF/图片、金额为正数等。
内容的提问来源于stack exchange,提问作者golnaz mohamadi
相关产品推荐
相关产品推荐

