在 WooCommerce 订单详情中添加历史订单时间线
在 WooCommerce 的订单详情页面中,只能查看当前订单的情况,而不能直接查看用户的所有订单情况,为了解决这个痛点,我写了一段代码, 可以实现显示当前客户的所有订单的时间线和订单汇总情况。
效果展示
- 顶部表格汇总了不同状态的订单数量和订单金额
- 按时间降序的方式展示了所有订单的总额与状态
- 点击订单号可以新窗口打开该订单的编辑页面
- 当前订单在时间线上显示为彩色阴影
代码展示
将以下代码添加到子主题的 functions.php
内即可
function order_timeline_display_meta_box($post)
{
if (get_post_meta($post->ID, '_customer_user', true) == 0) {
echo '<p>This is a guest order.</p>';
return;
}
$customer_id = get_post_meta($post->ID, '_customer_user', true);
$orders = wc_get_orders(array(
'customer' => $customer_id,
'limit' => -1,
));
if (count($orders) > 1) {
$order_status_count = array();
$order_status_total = array();
foreach ($orders as $order) {
$order_status = $order->get_status();
if (isset($order_status_count[$order_status])) {
$order_status_count[$order_status] += 1;
$order_status_total[$order_status] += $order->get_total();
} else {
$order_status_count[$order_status] = 1;
$order_status_total[$order_status] = $order->get_total();
}
}
echo '<table class="order-total-table">';
echo '<tr><th>Status</th><th>Cnt</th><th>Total</th></tr>';
foreach ($order_status_count as $status => $count) {
$status_color = '';
echo '<tr><td>' . ucfirst($status) . '</td><td>' . $count . '</td><td>' . wc_price($order_status_total[$status]) . '</td></tr>';
}
echo '</table>';
}
echo '<ul class="order-timeline-timeline">';
foreach ($orders as $order) {
$order_id = $order->get_id();
$order_date = $order->get_date_created()->format('F j, Y');
$order_total = $order->get_total();
$order_status = $order->get_status();
$currency_symbol = get_woocommerce_currency_symbol();
$status_color = '';
switch ($order_status) {
case 'completed':
$status_color = '#8bc34a';
break;
case 'processing':
$status_color = '#ffc107';
break;
case 'pending':
$status_color = '#03a9f4';
break;
case 'on-hold':
$status_color = '#e91e63';
break;
case 'cancelled':
$status_color = '#9e9e9e';
break;
case 'refunded':
$status_color = '#ff5722';
break;
case 'failed':
$status_color = '#f44336';
break;
default:
$status_color = '#9e9e9e';
}
$class_current_order = '';
if ($order_id == $post->ID) {
$class_current_order = 'current-order';
}
echo '<li class="' . $class_current_order . '">';
echo '<div class="order-timeline-timeline-card">';
$order_edit_link = get_edit_post_link($order_id);
echo '<div class="order-timeline-timeline-head"><div class="order-timeline-timeline-order-number">' . '<a href="' . $order_edit_link . '" target="_blank">#' . $order_id . '</a>' . '</div><div class="order-timeline-timeline-date">' . $order_date . '</div></div>';
echo '<div class="order-timeline-timeline-bottom"><div class="order-timeline-timeline-status" style="background-color: ' . $status_color . ';">' . ucfirst($order_status) . '</div><div class="order-timeline-timeline-total">' . $currency_symbol . $order_total . '</div>';
echo '</div>';
echo '</li>';
}
echo '</ul>';
?>
<style>
.order-total-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 10px;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3);
border-radius: 5px;
}
.order-total-table th {
background-color: #f1f1f1;
}
.order-total-table tr:nth-child(odd) {
background-color: #f1f1f1;
}
.order-total-table th,
.order-total-table td {
text-align: center;
padding: 8px;
}
ul.order-timeline-timeline {
list-style: none;
margin: 0;
padding: 0;
position: relative;
}
ul.order-timeline-timeline li {
position: relative;
padding-left: 20px;
}
ul.order-timeline-timeline li::before {
content: "";
width: 12px;
height: 12px;
background-color: #ccc;
border-radius: 50%;
position: absolute;
left: 1px;
z-index: 1;
transform: translateX(-50%);
}
ul.order-timeline-timeline li::after {
content: "";
position: absolute;
width: 2px;
height: calc(100% + 10px);
background-color: #ccc;
top: 8px;
left: 0;
}
ul.order-timeline-timeline li .order-timeline-timeline-card {
padding: 10px;
box-sizing: border-box;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3);
border-radius: 5px;
}
ul.order-timeline-timeline li.current-order .order-timeline-timeline-card {
box-shadow: 0 2px 2px 2px #2271b1a3;
}
ul.order-timeline-timeline li.current-order::before{
background-color: #2271b1;
}
ul.order-timeline-timeline li .order-timeline-timeline-bottom,
ul.order-timeline-timeline li .order-timeline-timeline-head {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
align-items: flex-end;
}
ul.order-timeline-timeline li .order-timeline-timeline-order-number {
font-weight: bold;
}
ul.order-timeline-timeline li .order-timeline-timeline-status {
display: inline-block;
color: #fff;
font-weight: bold;
padding: 4px 8px;
border-radius: 5px;
}
ul.order-timeline-timeline li .order-timeline-timeline-total {
font-weight: bold;
}
</style>
<?php
}
function order_timeline_plugin_add_meta_box()
{
add_meta_box(
'order-timeline-order-timeline',
'Order Timeline',
'order_timeline_display_meta_box',
'shop_order',
'side',
'high'
);
}
add_action('add_meta_boxes', 'order_timeline_plugin_add_meta_box');
概要
上述代码还可通过 Code Snippets
插件添加到网站后台中。
如果 WooCommerce 设置了 Guest 可直接下单,则可能出现订单未绑定客户的情况,不会展示客户的订单时间线。
第二版更新
更新内容
- 修复创建订单页面报错问题
完整代码
function order_timeline_display_meta_box($post)
{
if ($post->post_status == 'auto-draft') {
echo '<p>Timeline shows on the created orders.</p>';
return;
}
if (get_post_meta($post->ID, '_customer_user', true) == 0) {
echo '<p>This is a guest order.</p>';
return;
}
$customer_id = get_post_meta($post->ID, '_customer_user', true);
$orders = wc_get_orders(array(
'customer' => $customer_id,
'limit' => -1,
));
if (count($orders) > 1) {
$order_status_count = array();
$order_status_total = array();
foreach ($orders as $order) {
$order_status = $order->get_status();
if (isset($order_status_count[$order_status])) {
$order_status_count[$order_status] += 1;
$order_status_total[$order_status] += $order->get_total();
} else {
$order_status_count[$order_status] = 1;
$order_status_total[$order_status] = $order->get_total();
}
}
echo '<table class="order-total-table">';
echo '<tr><th>Status</th><th>Cnt</th><th>Total</th></tr>';
foreach ($order_status_count as $status => $count) {
$status_color = '';
echo '<tr><td>' . ucfirst($status) . '</td><td>' . $count . '</td><td>' . wc_price($order_status_total[$status]) . '</td></tr>';
}
echo '</table>';
}
echo '<ul class="order-timeline-timeline">';
foreach ($orders as $order) {
$order_id = $order->get_id();
$order_date = $order->get_date_created()->format('F j, Y');
$order_total = $order->get_total();
$order_status = $order->get_status();
$currency_symbol = get_woocommerce_currency_symbol();
$status_color = '';
switch ($order_status) {
case 'completed':
$status_color = '#8bc34a';
break;
case 'processing':
$status_color = '#ffc107';
break;
case 'pending':
$status_color = '#03a9f4';
break;
case 'on-hold':
$status_color = '#e91e63';
break;
case 'cancelled':
$status_color = '#9e9e9e';
break;
case 'refunded':
$status_color = '#ff5722';
break;
case 'failed':
$status_color = '#f44336';
break;
default:
$status_color = '#9e9e9e';
}
$class_current_order = '';
if ($order_id == $post->ID) {
$class_current_order = 'current-order';
}
echo '<li class="' . $class_current_order . '">';
echo '<div class="order-timeline-timeline-card">';
$order_edit_link = get_edit_post_link($order_id);
echo '<div class="order-timeline-timeline-head"><div class="order-timeline-timeline-order-number">' . '<a href="' . $order_edit_link . '" target="_blank">#' . $order_id . '</a>' . '</div><div class="order-timeline-timeline-date">' . $order_date . '</div></div>';
echo '<div class="order-timeline-timeline-bottom"><div class="order-timeline-timeline-status" style="background-color: ' . $status_color . ';">' . ucfirst($order_status) . '</div><div class="order-timeline-timeline-total">' . $currency_symbol . $order_total . '</div>';
echo '</div>';
echo '</li>';
}
echo '</ul>';
?>
<style>
.order-total-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 10px;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3);
border-radius: 5px;
}
.order-total-table th {
background-color: #f1f1f1;
}
.order-total-table tr:nth-child(odd) {
background-color: #f1f1f1;
}
.order-total-table th,
.order-total-table td {
text-align: center;
padding: 8px;
}
ul.order-timeline-timeline {
list-style: none;
margin: 0;
padding: 0;
position: relative;
}
ul.order-timeline-timeline li {
position: relative;
padding-left: 20px;
}
ul.order-timeline-timeline li::before {
content: "";
width: 12px;
height: 12px;
background-color: #ccc;
border-radius: 50%;
position: absolute;
left: 1px;
z-index: 1;
transform: translateX(-50%);
}
ul.order-timeline-timeline li::after {
content: "";
position: absolute;
width: 2px;
height: calc(100% + 10px);
background-color: #ccc;
top: 8px;
left: 0;
}
ul.order-timeline-timeline li .order-timeline-timeline-card {
padding: 10px;
box-sizing: border-box;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3);
border-radius: 5px;
}
ul.order-timeline-timeline li.current-order .order-timeline-timeline-card {
box-shadow: 0 2px 2px 2px #2271b1a3;
}
ul.order-timeline-timeline li.current-order::before{
background-color: #2271b1;
}
ul.order-timeline-timeline li .order-timeline-timeline-bottom,
ul.order-timeline-timeline li .order-timeline-timeline-head {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
align-items: flex-end;
}
ul.order-timeline-timeline li .order-timeline-timeline-order-number {
font-weight: bold;
}
ul.order-timeline-timeline li .order-timeline-timeline-status {
display: inline-block;
color: #fff;
font-weight: bold;
padding: 4px 8px;
border-radius: 5px;
}
ul.order-timeline-timeline li .order-timeline-timeline-total {
font-weight: bold;
}
</style>
<?php
}
function order_timeline_plugin_add_meta_box()
{
add_meta_box(
'order-timeline-order-timeline',
'Order Timeline',
'order_timeline_display_meta_box',
'shop_order',
'side',
'high'
);
}
add_action('add_meta_boxes', 'order_timeline_plugin_add_meta_box');