Merge pull request 'feat(shop): 商品详情/归档壳层 1:1 同家族卡片与内容流' (#74) from worktree-product-shell-1to1 into main
Reviewed-on: CYL/wordpress-theme-aksrt#74
This commit is contained in:
@@ -463,3 +463,29 @@ html.dark .aksrt-product-page__content img {
|
||||
font-size: 13px;
|
||||
color: var(--color-ink-3);
|
||||
}
|
||||
|
||||
|
||||
/* Product detail shell — align with single content stream */
|
||||
.content-shell--product .content-wrap {
|
||||
padding-top: 8px;
|
||||
}
|
||||
.content-shell--product .aksrt-product-page {
|
||||
width: 100%;
|
||||
}
|
||||
.aksrt-product-page__related {
|
||||
margin-top: 28px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
.aksrt-product-page__related-title {
|
||||
margin: 0 0 14px;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: var(--color-ink, #1f2937);
|
||||
}
|
||||
.aksrt-product-page__related-grid.aksrt-product-archive__grid {
|
||||
margin: 0;
|
||||
}
|
||||
.aksrt-product-page__merchant-link {
|
||||
display: inline-block;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
@@ -37,12 +37,15 @@ $author_id = (int) get_post_field('post_author', $product_id);
|
||||
$author = $author_id > 0 ? get_userdata($author_id) : null;
|
||||
?>
|
||||
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<main id="main-content" class="site-main content-shell content-shell--stream content-shell--product" tabindex="-1">
|
||||
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?>
|
||||
|
||||
<?php if (!empty($product)) : ?>
|
||||
<div class="content-wrap container">
|
||||
<div class="content-layout content-layout--no-sidebar">
|
||||
<div class="content-layout__primary">
|
||||
<div
|
||||
class="aksrt-product-page container"
|
||||
class="aksrt-product-page"
|
||||
data-aksrt-product-page
|
||||
data-product-id="<?php echo esc_attr((string) $product_id); ?>"
|
||||
data-options='<?php echo esc_attr(wp_json_encode($options, JSON_UNESCAPED_UNICODE)); ?>'
|
||||
@@ -236,12 +239,16 @@ $author = $author_id > 0 ? get_userdata($author_id) : null;
|
||||
</div>
|
||||
|
||||
<!-- Merchant info -->
|
||||
<?php if ($author) : ?>
|
||||
<?php if ($author) :
|
||||
$store_url = function_exists('aksrt_get_user_home_url')
|
||||
? add_query_arg('tab', 'product', aksrt_get_user_home_url($author_id))
|
||||
: get_author_posts_url($author_id);
|
||||
?>
|
||||
<div class="aksrt-product-page__merchant">
|
||||
<img src="<?php echo esc_url(function_exists('aksrt_get_avatar_url') ? aksrt_get_avatar_url($author_id) : get_avatar_url($author_id)); ?>" alt="" class="aksrt-product-page__merchant-avatar">
|
||||
<div>
|
||||
<strong><?php echo esc_html($author->display_name); ?></strong>
|
||||
<a href="<?php echo esc_url(get_author_posts_url($author_id)); ?>?tab=products" class="aksrt-product-page__merchant-link"><?php esc_html_e('进入店铺', 'aksrt'); ?></a>
|
||||
<a href="<?php echo esc_url($store_url); ?>" class="aksrt-product-page__merchant-link"><?php esc_html_e('进入店铺', 'aksrt'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
@@ -312,11 +319,17 @@ $author = $author_id > 0 ? get_userdata($author_id) : null;
|
||||
|
||||
<!-- Related products -->
|
||||
<?php
|
||||
$related_query = new WP_Query([
|
||||
$related_items = [];
|
||||
if ($shop && method_exists($shop, 'build_product_card_view')) {
|
||||
$related_q = new WP_Query([
|
||||
'post_type' => 'aksrt_product',
|
||||
'posts_per_page' => 6,
|
||||
'post_status' => 'publish',
|
||||
'post__not_in' => [$product_id],
|
||||
'ignore_sticky_posts' => true,
|
||||
'no_found_rows' => true,
|
||||
'update_post_meta_cache' => false,
|
||||
'update_post_term_cache' => false,
|
||||
'tax_query' => !empty($product['categories']) ? [[
|
||||
'taxonomy' => 'aksrt_product_cat',
|
||||
'field' => 'term_id',
|
||||
@@ -324,21 +337,26 @@ $author = $author_id > 0 ? get_userdata($author_id) : null;
|
||||
]] : [],
|
||||
'orderby' => 'rand',
|
||||
]);
|
||||
while ($related_q->have_posts()) {
|
||||
$related_q->the_post();
|
||||
$card = $shop->build_product_card_view((int) get_the_ID());
|
||||
if (!empty($card['id'])) {
|
||||
$related_items[] = $card;
|
||||
}
|
||||
}
|
||||
wp_reset_postdata();
|
||||
}
|
||||
?>
|
||||
<?php if ($related_query->have_posts()) : ?>
|
||||
<?php if (!empty($related_items)) : ?>
|
||||
<section class="aksrt-product-page__related">
|
||||
<h2><?php esc_html_e('相关推荐', 'aksrt'); ?></h2>
|
||||
<div class="aksrt-product-page__related-grid">
|
||||
<?php while ($related_query->have_posts()) : $related_query->the_post(); ?>
|
||||
<a href="<?php echo esc_url(get_permalink()); ?>" class="aksrt-product-page__related-card">
|
||||
<?php $thumb = $shop ? $shop->resolve_main_image(get_the_ID()) : get_the_post_thumbnail_url(get_the_ID(), 'medium'); ?>
|
||||
<?php if ($thumb) : ?>
|
||||
<img src="<?php echo esc_url($thumb); ?>" alt="<?php the_title_attribute(); ?>" loading="lazy">
|
||||
<?php endif; ?>
|
||||
<h3><?php the_title(); ?></h3>
|
||||
<strong>¥<?php echo esc_html(number_format((float) get_post_meta(get_the_ID(), '_aksrt_price', true), 2)); ?></strong>
|
||||
</a>
|
||||
<?php endwhile; wp_reset_postdata(); ?>
|
||||
<h2 class="aksrt-product-page__related-title"><?php esc_html_e('相关推荐', 'aksrt'); ?></h2>
|
||||
<div class="aksrt-product-archive__grid aksrt-product-archive__grid--default aksrt-product-page__related-grid">
|
||||
<?php foreach ($related_items as $related_product) :
|
||||
get_template_part('templates/parts/shop/product', 'card', [
|
||||
'product' => $related_product,
|
||||
'show_sales' => ((int) ($related_product['sales'] ?? 0) > 0),
|
||||
]);
|
||||
endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
@@ -397,6 +415,11 @@ $author = $author_id > 0 ? get_userdata($author_id) : null;
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div><!-- .aksrt-product-page -->
|
||||
</div><!-- .content-layout__primary -->
|
||||
</div><!-- .content-layout -->
|
||||
</div><!-- .content-wrap -->
|
||||
|
||||
<!-- Mobile purchase tabbar -->
|
||||
<div class="aksrt-product-page__mobile-bar" data-aksrt-mobile-purchase>
|
||||
<button type="button" class="aksrt-product-page__mobile-btn" data-aksrt-toggle-fav="<?php echo esc_attr((string) $product_id); ?>">
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Shared product card (archive / related / storefront).
|
||||
*
|
||||
* Expected args:
|
||||
* - product: array from AKSRT_Shop::build_product_card_view()
|
||||
* - show_sales: bool (optional)
|
||||
* - sales_cfg: array (optional; used when show_sales not provided)
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$args = is_array($args ?? null) ? $args : [];
|
||||
$product = is_array($args['product'] ?? null) ? $args['product'] : [];
|
||||
if (empty($product) || empty($product['id'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sales = (int) ($product['sales'] ?? 0);
|
||||
if (array_key_exists('show_sales', $args)) {
|
||||
$show_sales = !empty($args['show_sales']);
|
||||
} else {
|
||||
$sales_cfg = is_array($args['sales_cfg'] ?? null) ? $args['sales_cfg'] : [];
|
||||
$mode = (string) ($sales_cfg['show'] ?? 'show');
|
||||
$min_sales = max(0, (int) ($sales_cfg['show_min'] ?? 0));
|
||||
$show_sales = ($mode === 'show' && $sales > 0) || ($mode === 'threshold' && $sales >= $min_sales);
|
||||
}
|
||||
|
||||
$title = (string) ($product['title'] ?? '');
|
||||
$permalink = (string) ($product['permalink'] ?? '#');
|
||||
$image = (string) ($product['image'] ?? '');
|
||||
$excerpt = (string) ($product['excerpt'] ?? '');
|
||||
$price = (float) ($product['price'] ?? 0);
|
||||
?>
|
||||
<article class="aksrt-product-card">
|
||||
<a href="<?php echo esc_url($permalink !== '' ? $permalink : '#'); ?>" class="aksrt-product-card__link">
|
||||
<?php if ($image !== '') : ?>
|
||||
<div class="aksrt-product-card__image">
|
||||
<img src="<?php echo esc_url($image); ?>" alt="<?php echo esc_attr($title); ?>" loading="lazy">
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-product-card__image aksrt-product-card__image--placeholder"><i class="fas fa-image" aria-hidden="true"></i></div>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-product-card__body">
|
||||
<h3 class="aksrt-product-card__title"><?php echo esc_html($title); ?></h3>
|
||||
<?php if ($excerpt !== '') : ?>
|
||||
<p class="aksrt-product-card__excerpt"><?php echo esc_html(wp_trim_words($excerpt, 15)); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-product-card__footer">
|
||||
<span class="aksrt-product-card__price">¥<?php echo esc_html(number_format($price, 2)); ?></span>
|
||||
<?php if ($show_sales) : ?>
|
||||
<span class="aksrt-product-card__sales"><?php printf(esc_html__('已售 %d', 'aksrt'), $sales); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</article>
|
||||
@@ -145,32 +145,11 @@ extract($args, EXTR_SKIP); // phpcs:ignore WordPress.PHP.DontExtract.extract_ext
|
||||
?>
|
||||
<div class="aksrt-product-archive__grid aksrt-product-archive__grid--default uh-product-grid">
|
||||
<?php foreach ($product_items as $product) :
|
||||
$sales = (int) ($product['sales'] ?? 0);
|
||||
?>
|
||||
<article class="aksrt-product-card">
|
||||
<a href="<?php echo esc_url((string) ($product['permalink'] ?? '#')); ?>" class="aksrt-product-card__link">
|
||||
<?php if (!empty($product['image'])) : ?>
|
||||
<div class="aksrt-product-card__image">
|
||||
<img src="<?php echo esc_url((string) $product['image']); ?>" alt="<?php echo esc_attr((string) ($product['title'] ?? '')); ?>" loading="lazy">
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-product-card__image aksrt-product-card__image--placeholder"><i class="fas fa-image"></i></div>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-product-card__body">
|
||||
<h3 class="aksrt-product-card__title"><?php echo esc_html((string) ($product['title'] ?? '')); ?></h3>
|
||||
<?php if (!empty($product['excerpt'])) : ?>
|
||||
<p class="aksrt-product-card__excerpt"><?php echo esc_html(wp_trim_words((string) $product['excerpt'], 15)); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-product-card__footer">
|
||||
<span class="aksrt-product-card__price">¥<?php echo esc_html(number_format((float) ($product['price'] ?? 0), 2)); ?></span>
|
||||
<?php if ($sales > 0) : ?>
|
||||
<span class="aksrt-product-card__sales"><?php printf(esc_html__('已售 %d', 'aksrt'), $sales); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
get_template_part('templates/parts/shop/product', 'card', [
|
||||
'product' => $product,
|
||||
'show_sales' => ((int) ($product['sales'] ?? 0) > 0),
|
||||
]);
|
||||
endforeach; ?>
|
||||
</div>
|
||||
<?php if ($product_max_pages > 1 && function_exists('aksrt_render_profile_pagination')) : ?>
|
||||
<?php aksrt_render_profile_pagination($product_max_pages, $product_page, 'product_page'); ?>
|
||||
|
||||
@@ -80,35 +80,11 @@ $order_options = [
|
||||
<?php if (!empty($products)) : ?>
|
||||
<div class="aksrt-product-archive__grid aksrt-product-archive__grid--<?php echo esc_attr($style); ?>" id="aksrt-product-grid" data-aksrt-product-grid>
|
||||
<?php foreach ($products as $product) :
|
||||
$sales = (int) ($product['sales'] ?? 0);
|
||||
$mode = (string) ($sales_cfg['show'] ?? 'show');
|
||||
$min_sales = max(0, (int) ($sales_cfg['show_min'] ?? 0));
|
||||
$show_sales = ($mode === 'show' && $sales > 0) || ($mode === 'threshold' && $sales >= $min_sales);
|
||||
?>
|
||||
<article class="aksrt-product-card">
|
||||
<a href="<?php echo esc_url((string) ($product['permalink'] ?? '#')); ?>" class="aksrt-product-card__link">
|
||||
<?php if (!empty($product['image'])) : ?>
|
||||
<div class="aksrt-product-card__image">
|
||||
<img src="<?php echo esc_url((string) $product['image']); ?>" alt="<?php echo esc_attr((string) ($product['title'] ?? '')); ?>" loading="lazy">
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-product-card__image aksrt-product-card__image--placeholder"><i class="fas fa-image"></i></div>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-product-card__body">
|
||||
<h3 class="aksrt-product-card__title"><?php echo esc_html((string) ($product['title'] ?? '')); ?></h3>
|
||||
<?php if (!empty($product['excerpt'])) : ?>
|
||||
<p class="aksrt-product-card__excerpt"><?php echo esc_html(wp_trim_words((string) $product['excerpt'], 15)); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-product-card__footer">
|
||||
<span class="aksrt-product-card__price">¥<?php echo esc_html(number_format((float) ($product['price'] ?? 0), 2)); ?></span>
|
||||
<?php if ($show_sales) : ?>
|
||||
<span class="aksrt-product-card__sales"><?php printf(esc_html__('已售 %d', 'aksrt'), $sales); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
get_template_part('templates/parts/shop/product', 'card', [
|
||||
'product' => $product,
|
||||
'sales_cfg' => $sales_cfg,
|
||||
]);
|
||||
endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($max_pages > 1) : ?>
|
||||
|
||||
@@ -80,35 +80,11 @@ $order_options = [
|
||||
<?php if (!empty($products)) : ?>
|
||||
<div class="aksrt-product-archive__grid aksrt-product-archive__grid--<?php echo esc_attr($style); ?>" id="aksrt-product-grid" data-aksrt-product-grid>
|
||||
<?php foreach ($products as $product) :
|
||||
$sales = (int) ($product['sales'] ?? 0);
|
||||
$mode = (string) ($sales_cfg['show'] ?? 'show');
|
||||
$min_sales = max(0, (int) ($sales_cfg['show_min'] ?? 0));
|
||||
$show_sales = ($mode === 'show' && $sales > 0) || ($mode === 'threshold' && $sales >= $min_sales);
|
||||
?>
|
||||
<article class="aksrt-product-card">
|
||||
<a href="<?php echo esc_url((string) ($product['permalink'] ?? '#')); ?>" class="aksrt-product-card__link">
|
||||
<?php if (!empty($product['image'])) : ?>
|
||||
<div class="aksrt-product-card__image">
|
||||
<img src="<?php echo esc_url((string) $product['image']); ?>" alt="<?php echo esc_attr((string) ($product['title'] ?? '')); ?>" loading="lazy">
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-product-card__image aksrt-product-card__image--placeholder"><i class="fas fa-image"></i></div>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-product-card__body">
|
||||
<h3 class="aksrt-product-card__title"><?php echo esc_html((string) ($product['title'] ?? '')); ?></h3>
|
||||
<?php if (!empty($product['excerpt'])) : ?>
|
||||
<p class="aksrt-product-card__excerpt"><?php echo esc_html(wp_trim_words((string) $product['excerpt'], 15)); ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-product-card__footer">
|
||||
<span class="aksrt-product-card__price">¥<?php echo esc_html(number_format((float) ($product['price'] ?? 0), 2)); ?></span>
|
||||
<?php if ($show_sales) : ?>
|
||||
<span class="aksrt-product-card__sales"><?php printf(esc_html__('已售 %d', 'aksrt'), $sales); ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
get_template_part('templates/parts/shop/product', 'card', [
|
||||
'product' => $product,
|
||||
'sales_cfg' => $sales_cfg,
|
||||
]);
|
||||
endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($max_pages > 1) : ?>
|
||||
|
||||
Reference in New Issue
Block a user