init_hooks(); } /** * 初始化钩子 */ private function init_hooks() { // 管理菜单 add_action('admin_menu', array($this, 'add_admin_menu')); // 产品数据面板 add_filter('woocommerce_product_data_tabs', array($this, 'add_product_data_tabs')); add_action('woocommerce_product_data_panels', array($this, 'add_product_data_panels')); add_action('woocommerce_process_product_meta', array($this, 'save_product_data')); // 产品类型 add_filter('product_type_selector', array($this, 'add_product_types')); // 订单管理 add_action('add_meta_boxes', array($this, 'add_order_meta_boxes')); add_action('woocommerce_admin_order_data_after_billing_address', array($this, 'display_order_subscription_info')); // 脚本和样式 add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts')); // AJAX 处理 add_action('wp_ajax_yoone_search_products', array($this, 'ajax_search_products')); add_action('wp_ajax_yoone_get_bundle_items', array($this, 'ajax_get_bundle_items')); add_action('wp_ajax_yoone_save_bundle_items', array($this, 'ajax_save_bundle_items')); // 列表页面自定义列 add_filter('manage_product_posts_columns', array($this, 'add_product_columns')); add_action('manage_product_posts_custom_column', array($this, 'display_product_columns'), 10, 2); } /** * 加载管理脚本 */ public function enqueue_admin_scripts($hook) { global $post_type; if ($post_type === 'product' || strpos($hook, 'yoone-subscriptions') !== false) { wp_enqueue_script( 'yoone-admin', YOONE_SUBSCRIPTIONS_PLUGIN_URL . 'assets/js/admin.js', array('jquery', 'jquery-ui-sortable'), YOONE_SUBSCRIPTIONS_VERSION, true ); wp_enqueue_style( 'yoone-admin', YOONE_SUBSCRIPTIONS_PLUGIN_URL . 'assets/css/admin.css', array(), YOONE_SUBSCRIPTIONS_VERSION ); wp_localize_script('yoone-admin', 'yoone_admin_params', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('yoone_admin_nonce'), 'i18n' => array( 'loading' => __('加载中...', 'yoone-subscriptions'), 'error' => __('发生错误', 'yoone-subscriptions'), 'confirm_delete' => __('确定要删除吗?', 'yoone-subscriptions'), 'select_product' => __('选择产品', 'yoone-subscriptions'), 'add_item' => __('添加项目', 'yoone-subscriptions'), 'remove_item' => __('移除项目', 'yoone-subscriptions'), ) )); } } /* |-------------------------------------------------------------------------- | 管理菜单 |-------------------------------------------------------------------------- */ /** * 添加管理菜单 */ public function add_admin_menu() { add_menu_page( __('Yoone 订阅', 'yoone-subscriptions'), __('Yoone 订阅', 'yoone-subscriptions'), 'manage_woocommerce', 'yoone-subscriptions', array($this, 'subscriptions_page'), 'dashicons-update', 56 ); add_submenu_page( 'yoone-subscriptions', __('所有订阅', 'yoone-subscriptions'), __('所有订阅', 'yoone-subscriptions'), 'manage_woocommerce', 'yoone-subscriptions', array($this, 'subscriptions_page') ); add_submenu_page( 'yoone-subscriptions', __('套装管理', 'yoone-subscriptions'), __('套装管理', 'yoone-subscriptions'), 'manage_woocommerce', 'yoone-bundles', array($this, 'bundles_page') ); add_submenu_page( 'yoone-subscriptions', __('支付设置', 'yoone-subscriptions'), __('支付设置', 'yoone-subscriptions'), 'manage_woocommerce', 'yoone-payment-settings', array($this, 'payment_settings_page') ); add_submenu_page( 'yoone-subscriptions', __('报告', 'yoone-subscriptions'), __('报告', 'yoone-subscriptions'), 'manage_woocommerce', 'yoone-reports', array($this, 'reports_page') ); } /** * 订阅管理页面 */ public function subscriptions_page() { $list_table = new Yoone_Subscriptions_List_Table(); $list_table->prepare_items(); echo '
'; echo '

' . __('订阅管理', 'yoone-subscriptions') . '

'; $list_table->display(); echo '
'; } /** * 套装管理页面 */ public function bundles_page() { $action = isset($_GET['action']) ? $_GET['action'] : 'list'; switch ($action) { case 'edit': case 'add': $this->bundle_edit_page(); break; default: $this->bundle_list_page(); break; } } /** * 套装列表页面 */ private function bundle_list_page() { $list_table = new Yoone_Bundles_List_Table(); $list_table->prepare_items(); echo '
'; echo '

' . __('套装管理', 'yoone-subscriptions'); echo '' . __('添加套装', 'yoone-subscriptions') . ''; echo '

'; $list_table->display(); echo '
'; } /** * 套装编辑页面 */ private function bundle_edit_page() { $bundle_id = isset($_GET['id']) ? intval($_GET['id']) : 0; $bundle = new Yoone_Bundle($bundle_id); if (isset($_POST['save_bundle'])) { $this->save_bundle_data($bundle); } include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'includes/admin/views/bundle-edit.php'; } /** * 支付设置页面 */ public function payment_settings_page() { if (isset($_POST['save_settings'])) { $this->save_payment_settings(); } include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'includes/admin/views/payment-settings.php'; } /** * 报告页面 */ public function reports_page() { include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'includes/admin/views/reports.php'; } /* |-------------------------------------------------------------------------- | 产品数据面板 |-------------------------------------------------------------------------- */ /** * 添加产品数据标签 */ public function add_product_data_tabs($tabs) { $tabs['yoone_bundle'] = array( 'label' => __('套装设置', 'yoone-subscriptions'), 'target' => 'yoone_bundle_product_data', 'class' => array('show_if_yoone_bundle'), 'priority' => 25, ); $tabs['yoone_subscription'] = array( 'label' => __('订阅设置', 'yoone-subscriptions'), 'target' => 'yoone_subscription_product_data', 'class' => array(), 'priority' => 26, ); return $tabs; } /** * 添加产品数据面板 */ public function add_product_data_panels() { global $post; // 套装设置面板 echo '
'; woocommerce_wp_select(array( 'id' => '_yoone_bundle_discount_type', 'label' => __('折扣类型', 'yoone-subscriptions'), 'options' => array( '' => __('无折扣', 'yoone-subscriptions'), 'percentage' => __('百分比折扣', 'yoone-subscriptions'), 'fixed' => __('固定金额折扣', 'yoone-subscriptions'), ), )); woocommerce_wp_text_input(array( 'id' => '_yoone_bundle_discount_value', 'label' => __('折扣值', 'yoone-subscriptions'), 'description' => __('输入折扣值(百分比或固定金额)', 'yoone-subscriptions'), 'type' => 'number', 'custom_attributes' => array( 'step' => '0.01', 'min' => '0', ), )); woocommerce_wp_text_input(array( 'id' => '_yoone_bundle_min_quantity', 'label' => __('最小数量', 'yoone-subscriptions'), 'description' => __('套装中产品的最小总数量', 'yoone-subscriptions'), 'type' => 'number', 'custom_attributes' => array( 'min' => '0', ), )); woocommerce_wp_text_input(array( 'id' => '_yoone_bundle_max_quantity', 'label' => __('最大数量', 'yoone-subscriptions'), 'description' => __('套装中产品的最大总数量(0表示无限制)', 'yoone-subscriptions'), 'type' => 'number', 'custom_attributes' => array( 'min' => '0', ), )); echo '
'; echo '

' . __('套装产品', 'yoone-subscriptions') . '

'; echo '
'; echo '
'; echo ''; echo '
'; echo '
'; echo '
'; // 订阅设置面板 echo '
'; woocommerce_wp_checkbox(array( 'id' => '_yoone_subscription_enabled', 'label' => __('启用订阅', 'yoone-subscriptions'), 'description' => __('将此产品设为订阅产品', 'yoone-subscriptions'), )); woocommerce_wp_select(array( 'id' => '_yoone_subscription_period', 'label' => __('订阅周期', 'yoone-subscriptions'), 'options' => array( 'day' => __('天', 'yoone-subscriptions'), 'week' => __('周', 'yoone-subscriptions'), 'month' => __('月', 'yoone-subscriptions'), 'year' => __('年', 'yoone-subscriptions'), ), 'value' => get_post_meta($post->ID, '_yoone_subscription_period', true) ?: 'month', )); woocommerce_wp_text_input(array( 'id' => '_yoone_subscription_interval', 'label' => __('订阅间隔', 'yoone-subscriptions'), 'description' => __('每隔多少个周期收费一次', 'yoone-subscriptions'), 'type' => 'number', 'value' => get_post_meta($post->ID, '_yoone_subscription_interval', true) ?: '1', 'custom_attributes' => array( 'min' => '1', ), )); woocommerce_wp_text_input(array( 'id' => '_yoone_subscription_length', 'label' => __('订阅长度', 'yoone-subscriptions'), 'description' => __('订阅持续多少个周期(0表示永久)', 'yoone-subscriptions'), 'type' => 'number', 'value' => get_post_meta($post->ID, '_yoone_subscription_length', true) ?: '0', 'custom_attributes' => array( 'min' => '0', ), )); woocommerce_wp_text_input(array( 'id' => '_yoone_subscription_trial_length', 'label' => __('试用期长度', 'yoone-subscriptions'), 'description' => __('免费试用期天数(0表示无试用期)', 'yoone-subscriptions'), 'type' => 'number', 'value' => get_post_meta($post->ID, '_yoone_subscription_trial_length', true) ?: '0', 'custom_attributes' => array( 'min' => '0', ), )); woocommerce_wp_text_input(array( 'id' => '_yoone_subscription_signup_fee', 'label' => __('注册费', 'yoone-subscriptions'), 'description' => __('一次性注册费用', 'yoone-subscriptions'), 'type' => 'number', 'value' => get_post_meta($post->ID, '_yoone_subscription_signup_fee', true) ?: '0', 'custom_attributes' => array( 'step' => '0.01', 'min' => '0', ), )); echo '
'; } /** * 保存产品数据 */ public function save_product_data($post_id) { // 套装设置 $bundle_fields = array( '_yoone_bundle_discount_type', '_yoone_bundle_discount_value', '_yoone_bundle_min_quantity', '_yoone_bundle_max_quantity', ); foreach ($bundle_fields as $field) { if (isset($_POST[$field])) { update_post_meta($post_id, $field, sanitize_text_field($_POST[$field])); } } // 订阅设置 $subscription_fields = array( '_yoone_subscription_enabled', '_yoone_subscription_period', '_yoone_subscription_interval', '_yoone_subscription_length', '_yoone_subscription_trial_length', '_yoone_subscription_signup_fee', ); foreach ($subscription_fields as $field) { if (isset($_POST[$field])) { update_post_meta($post_id, $field, sanitize_text_field($_POST[$field])); } else { delete_post_meta($post_id, $field); } } // 如果是套装产品,创建或更新套装记录 if (isset($_POST['product-type']) && $_POST['product-type'] === 'yoone_bundle') { $this->save_bundle_product_data($post_id); } } /** * 添加产品类型 */ public function add_product_types($types) { $types['yoone_bundle'] = __('套装产品', 'yoone-subscriptions'); return $types; } /* |-------------------------------------------------------------------------- | 订单管理 |-------------------------------------------------------------------------- */ /** * 添加订单元框 */ public function add_order_meta_boxes() { add_meta_box( 'yoone-order-subscriptions', __('相关订阅', 'yoone-subscriptions'), array($this, 'order_subscriptions_meta_box'), 'shop_order', 'normal', 'default' ); } /** * 订单订阅元框 */ public function order_subscriptions_meta_box($post) { global $wpdb; $subscriptions = $wpdb->get_results($wpdb->prepare(" SELECT * FROM {$wpdb->prefix}yoone_subscriptions WHERE parent_order_id = %d ", $post->ID)); if (empty($subscriptions)) { echo '

' . __('此订单没有相关订阅', 'yoone-subscriptions') . '

'; return; } echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; foreach ($subscriptions as $subscription) { echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; } echo ''; echo '
' . __('订阅ID', 'yoone-subscriptions') . '' . __('状态', 'yoone-subscriptions') . '' . __('金额', 'yoone-subscriptions') . '' . __('下次付款', 'yoone-subscriptions') . '' . __('操作', 'yoone-subscriptions') . '
#' . $subscription->id . '' . ucfirst($subscription->status) . '' . wc_price($subscription->total) . '' . ($subscription->next_payment_date ? date('Y-m-d', strtotime($subscription->next_payment_date)) : '-') . ''; echo '' . __('查看', 'yoone-subscriptions') . ''; echo '
'; } /** * 显示订单订阅信息 */ public function display_order_subscription_info($order) { $has_subscription = false; foreach ($order->get_items() as $item) { $product = $item->get_product(); if ($product && $product->get_meta('_yoone_subscription_enabled') === 'yes') { $has_subscription = true; break; } } if ($has_subscription) { echo '
'; echo '

' . __('此订单包含订阅产品', 'yoone-subscriptions') . '

'; echo '
'; } } /* |-------------------------------------------------------------------------- | 产品列表自定义列 |-------------------------------------------------------------------------- */ /** * 添加产品列 */ public function add_product_columns($columns) { $new_columns = array(); foreach ($columns as $key => $column) { $new_columns[$key] = $column; if ($key === 'product_type') { $new_columns['yoone_subscription'] = __('订阅', 'yoone-subscriptions'); $new_columns['yoone_bundle'] = __('套装', 'yoone-subscriptions'); } } return $new_columns; } /** * 显示产品列内容 */ public function display_product_columns($column, $post_id) { switch ($column) { case 'yoone_subscription': $enabled = get_post_meta($post_id, '_yoone_subscription_enabled', true); if ($enabled === 'yes') { echo ''; } else { echo ''; } break; case 'yoone_bundle': $product = wc_get_product($post_id); if ($product && $product->get_type() === 'yoone_bundle') { echo ''; } else { echo ''; } break; } } /* |-------------------------------------------------------------------------- | AJAX 处理 |-------------------------------------------------------------------------- */ /** * AJAX 搜索产品 */ public function ajax_search_products() { check_ajax_referer('yoone_admin_nonce', 'nonce'); $term = sanitize_text_field($_POST['term']); $products = wc_get_products(array( 'limit' => 20, 'status' => 'publish', 's' => $term, )); $results = array(); foreach ($products as $product) { $results[] = array( 'id' => $product->get_id(), 'text' => $product->get_name() . ' (#' . $product->get_id() . ')', 'price' => $product->get_price(), ); } wp_send_json($results); } /** * AJAX 获取套装项目 */ public function ajax_get_bundle_items() { check_ajax_referer('yoone_admin_nonce', 'nonce'); $product_id = intval($_POST['product_id']); $bundle = new Yoone_Bundle(); $bundle_data = $bundle->get_bundle_by_product_id($product_id); if ($bundle_data) { $items = $bundle->get_bundle_items($bundle_data['id']); wp_send_json_success($items); } else { wp_send_json_success(array()); } } /** * AJAX 保存套装项目 */ public function ajax_save_bundle_items() { check_ajax_referer('yoone_admin_nonce', 'nonce'); $product_id = intval($_POST['product_id']); $items = isset($_POST['items']) ? $_POST['items'] : array(); if (!$product_id) { wp_send_json_error(__('无效的产品ID', 'yoone-subscriptions')); } // 获取或创建套装 $bundle = new Yoone_Bundle(); $bundle_data = $bundle->get_bundle_by_product_id($product_id); if ($bundle_data) { $bundle = new Yoone_Bundle($bundle_data['id']); } else { $bundle->set_product_id($product_id); $bundle->set_name(get_the_title($product_id)); $bundle->set_status('active'); $bundle->save(); } // 清除现有项目 $bundle->clear_items(); // 添加新项目 foreach ($items as $index => $item) { $bundle->add_item( intval($item['product_id']), intval($item['quantity']), floatval($item['discount']), $index ); } wp_send_json_success(__('套装项目已保存', 'yoone-subscriptions')); } /* |-------------------------------------------------------------------------- | 辅助方法 |-------------------------------------------------------------------------- */ /** * 保存套装产品数据 */ private function save_bundle_product_data($product_id) { $bundle = new Yoone_Bundle(); $bundle_data = $bundle->get_bundle_by_product_id($product_id); if ($bundle_data) { $bundle = new Yoone_Bundle($bundle_data['id']); } else { $bundle->set_product_id($product_id); $bundle->set_name(get_the_title($product_id)); } // 更新套装设置 $bundle->set_discount_type(sanitize_text_field($_POST['_yoone_bundle_discount_type'] ?? '')); $bundle->set_discount_value(floatval($_POST['_yoone_bundle_discount_value'] ?? 0)); $bundle->set_min_quantity(intval($_POST['_yoone_bundle_min_quantity'] ?? 0)); $bundle->set_max_quantity(intval($_POST['_yoone_bundle_max_quantity'] ?? 0)); $bundle->set_status('active'); $bundle->save(); } /** * 保存套装数据 */ private function save_bundle_data($bundle) { if (!wp_verify_nonce($_POST['yoone_bundle_nonce'], 'save_bundle')) { return; } $bundle->set_name(sanitize_text_field($_POST['bundle_name'])); $bundle->set_description(sanitize_textarea_field($_POST['bundle_description'])); $bundle->set_discount_type(sanitize_text_field($_POST['discount_type'])); $bundle->set_discount_value(floatval($_POST['discount_value'])); $bundle->set_min_quantity(intval($_POST['min_quantity'])); $bundle->set_max_quantity(intval($_POST['max_quantity'])); $bundle->set_status(sanitize_text_field($_POST['status'])); $bundle->save(); // 保存套装项目 if (isset($_POST['bundle_items'])) { $bundle->clear_items(); foreach ($_POST['bundle_items'] as $index => $item) { $bundle->add_item( intval($item['product_id']), intval($item['quantity']), floatval($item['discount']), $index ); } } wp_redirect(admin_url('admin.php?page=yoone-bundles&message=saved')); exit; } /** * 保存支付设置 */ private function save_payment_settings() { if (!wp_verify_nonce($_POST['yoone_payment_nonce'], 'save_payment_settings')) { return; } $settings = array( 'moneris_enabled' => sanitize_text_field($_POST['moneris_enabled'] ?? ''), 'moneris_testmode' => sanitize_text_field($_POST['moneris_testmode'] ?? ''), 'moneris_store_id' => sanitize_text_field($_POST['moneris_store_id'] ?? ''), 'moneris_api_token' => sanitize_text_field($_POST['moneris_api_token'] ?? ''), 'moneris_country' => sanitize_text_field($_POST['moneris_country'] ?? 'CA'), ); foreach ($settings as $key => $value) { update_option('yoone_' . $key, $value); } wp_redirect(admin_url('admin.php?page=yoone-payment-settings&message=saved')); exit; } }