2025-07-04 19:07:35 +08:00

187 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
主页面视图
"""
from flask import Blueprint, render_template, session, current_app, request, redirect, url_for
from app.models.user import User
from app.models.product import Product, Category
from sqlalchemy import func
main_bp = Blueprint('main', __name__)
@main_bp.route('/')
def index():
"""首页"""
user = None
if 'user_id' in session:
try:
user = User.query.get(session['user_id'])
if user and user.status != 1:
# 用户被禁用清除session
session.pop('user_id', None)
user = None
except Exception as e:
current_app.logger.error(f"获取用户信息失败: {str(e)}")
session.pop('user_id', None)
user = None
# 获取热门商品按销量排序取前8个
hot_products = Product.query.filter_by(status=1)\
.order_by(Product.sales_count.desc())\
.limit(8).all()
# 获取最新商品按创建时间排序取前8个
new_products = Product.query.filter_by(status=1)\
.order_by(Product.created_at.desc())\
.limit(8).all()
# 获取活跃的顶级分类(用于导航)
top_categories = Category.query.filter_by(is_active=1, parent_id=0)\
.order_by(Category.sort_order)\
.limit(6).all()
return render_template('index.html',
user=user,
hot_products=hot_products,
new_products=new_products,
top_categories=top_categories)
@main_bp.route('/products')
def product_list():
"""商品列表页面"""
page = request.args.get('page', 1, type=int)
per_page = 20
# 基础查询:只显示上架商品
query = Product.query.filter_by(status=1)
# 分类筛选
category_id = request.args.get('category_id', type=int)
if category_id:
# 获取该分类及其所有子分类的商品
category = Category.query.get_or_404(category_id)
if category.level == 1: # 一级分类,查找所有子分类
subcategory_ids = [c.id for c in Category.query.filter_by(parent_id=category_id).all()]
subcategory_ids.append(category_id)
query = query.filter(Product.category_id.in_(subcategory_ids))
else:
query = query.filter_by(category_id=category_id)
# 搜索功能
search = request.args.get('search', '').strip()
if search:
query = query.filter(Product.name.like(f'%{search}%'))
# 价格筛选
min_price = request.args.get('min_price', type=float)
max_price = request.args.get('max_price', type=float)
if min_price is not None:
query = query.filter(Product.price >= min_price)
if max_price is not None:
query = query.filter(Product.price <= max_price)
# 排序
sort = request.args.get('sort', 'default')
if sort == 'price_asc':
query = query.order_by(Product.price.asc())
elif sort == 'price_desc':
query = query.order_by(Product.price.desc())
elif sort == 'sales':
query = query.order_by(Product.sales_count.desc())
elif sort == 'newest':
query = query.order_by(Product.created_at.desc())
else: # default
query = query.order_by(Product.created_at.desc())
# 分页
products = query.paginate(page=page, per_page=per_page, error_out=False)
# 获取所有分类用于侧边栏
categories = Category.query.filter_by(is_active=1, parent_id=0)\
.order_by(Category.sort_order).all()
# 当前分类信息
current_category = None
if category_id:
current_category = Category.query.get(category_id)
return render_template('product/list.html',
products=products,
categories=categories,
current_category=current_category,
search=search,
category_id=category_id,
sort=sort,
min_price=min_price,
max_price=max_price)
@main_bp.route('/products/<int:product_id>')
def product_detail(product_id):
"""商品详情页面"""
product = Product.query.filter_by(id=product_id, status=1).first_or_404()
# 增加浏览量
try:
product.view_count += 1
from config.database import db
db.session.commit()
except Exception as e:
current_app.logger.error(f"更新浏览量失败: {str(e)}")
# 获取商品图片(按排序)
images = product.images
if images:
images = sorted(images, key=lambda x: x.sort_order)
# 获取商品库存信息并转换为字典
inventory_list = product.inventory
inventory_data = []
if inventory_list:
for inventory in inventory_list:
inventory_data.append({
'id': inventory.id,
'sku_code': inventory.sku_code,
'spec_combination': inventory.spec_combination,
'price_adjustment': float(inventory.price_adjustment) if inventory.price_adjustment else 0,
'stock': inventory.stock,
'warning_stock': inventory.warning_stock,
'is_default': inventory.is_default,
'status': inventory.status,
'final_price': inventory.get_final_price()
})
# 获取推荐商品(同分类的其他商品)
recommended_products = Product.query.filter(
Product.category_id == product.category_id,
Product.id != product.id,
Product.status == 1
).order_by(Product.sales_count.desc()).limit(4).all()
return render_template('product/detail.html',
product=product,
images=images,
inventory_list=inventory_list,
inventory_data=inventory_data,
recommended_products=recommended_products)
@main_bp.route('/category/<int:category_id>')
def category_products(category_id):
"""分类商品页面(重定向到商品列表)"""
return redirect(url_for('main.product_list', category_id=category_id))
@main_bp.route('/search')
def search():
"""搜索页面(重定向到商品列表)"""
search_query = request.args.get('q', '').strip()
return redirect(url_for('main.product_list', search=search_query))
@main_bp.route('/about')
def about():
"""关于我们"""
return render_template('about.html')