购物项目实战学习记录(1)——整体设计及首页代码设计

This is my study notes from MOOC.

表设计

表需求

前台

  • 商品分类
  • 商品售卖地区
  • 用户信息
  • 商品列表
  • 商品详情
  • 购物车
  • 订单表
  • 个人中心:消息、收藏、收货地址、个人信息

后台

  • 商品管理
  • 订单管理
  • 安全权限:独立模块,菜单、角色、用户表。
  • 地区管理
  • 商家管理

结构ER图

前台

  • deal:商品
  • deal_category:商品分类
  • area:商品地区,虽然是同一个商品,但是为了简单区分,把同一商品不同的售卖地区标定为不同的商品。
  • deal_detail:商品详情,详情页才使用,使用频率不同。
  • image_info:商品图片
  • cart:购物车
  • order_basic:订单基本信息,订单编号、收件人、下单时间、支付方式、状态等。
  • order_detail:订单详细信息,包含的商品信息、单价、数量、总价等。
  • user:用户
  • user_basic_info:用户基本信息
  • address:用户的收货地址
  • favorite:用户的收藏
  • message:用户消息(站内信)
    在这里插入图片描述

后台

  • admin_user:用户
  • admin_user_role:用户角色
  • admin_role:角色
  • admin_function:菜单
  • admin_role_function:角色<->菜单的关联表。
    在这里插入图片描述

首页代码(后台)

在这里插入图片描述
主要代码是左侧分类+下方4大+4小的商品信息

IndexController(首页Controller)

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

@Controller
public class IndexController extends BaseSiteController {

	@Autowired private DealService dealService;
	@Autowired private DealCategoryService categoryService;

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String index(Model model, HttpServletRequest request) {
		//1.分类
		//2.首页商品
		//3.每个大分类下显示8个商品

		List<DealCategory> categories = categoryService.getCategories();
		model.addAttribute("categories", categories);

		//根据IP确定
		Long areaId = getAreaId(request);


		//1.构造一个结构体存放每个分类的8个商品
		//2.页面循环结构体的集合
		//3.结构体包含8个商品,1个分类
		//4.8个商品分两组

		List<IndexCategoryDealDTO> indexCategoryDealDTOs = new ArrayList<>();
		categories.forEach(category -> {
			List<Deal> deals = dealService.getDealsForIndex(areaId, category.getSelfAndChildrenIds());
			indexCategoryDealDTOs.add(new IndexCategoryDealDTO(category, deals));
		});

		model.addAttribute("indexCategoryDealDTOs", indexCategoryDealDTOs);
		return "index";
	}
}

注:
(1)index方法配置RequestMapping注解,关联的URL为/,且方法为GET
(2)首页左侧为商品分类,下方为商品分类的商品(四大图+四小图),故代码要获取分类信息,以及每一个分类信息的商品信息(获取到4+4的辅助类后,构造一个基于分类的辅助类列表,传到前台显示)。
(3)还要根据Request获取访问者的IP,确定售卖地区。
(4)跳转到index页面,由SpringMVC进行页面解析。

DealCategoryService(商品分类的Service)

// 涉及的主要方法
    public List<DealCategory> getCategories() {

        List<DealCategory> dealCategories = getAllWithoutDeleted();//从缓存或数据库中查询全部

        //JDK8的stream处理,把根分类区分出来
        List<DealCategory> roots = dealCategories.stream().filter(dealCategory -> (dealCategory.getParentId() == 0)).collect(Collectors.toList());

        //对跟分类进行排序
        roots.sort(new Comparator<DealCategory>() {
            @Override
            public int compare(DealCategory o1, DealCategory o2) {
                return o1.getOrderNum() > o2.getOrderNum() ? 1 : -1;
            }
        });

        //把非根分类区分出来
        List<DealCategory> subs = dealCategories.stream().filter(dealCategory -> (dealCategory.getParentId() != 0)).collect(Collectors.toList());

        //递归构建结构化的分类信息
        roots.forEach(root -> buildSubs(root, subs));
        return roots;
    }
   /**
     * 查询所有未删除的商品类别
     *
     * @return
     */
    private List<DealCategory> getAllWithoutDeleted() {
        List<DealCategory> allCategories = dealCategoryCacheOperator.getAllDealCategories();
//        CacheUtil.getAllEntities(DealCategory.class);
        if (allCategories == null || allCategories.size() == 0) {
            allCategories = dealCategoryDAO.getAllWithoutDeleted();
            for (DealCategory dealCategory : allCategories) {
                dealCategoryCacheOperator.putDealCategory(dealCategory);
//                CacheUtil.putEntity("DealCategory." + dealCategory.getId(), dealCategory);
//                CacheUtil.putEntity(dealCategory);
            }
        }
        return allCategories;
    }

注:
(1)从缓存或数据库中读取全部的分类信息
(2)找到根分类信息,以及找到非根分类。
(3)将其分类信息构建成链表(父子关系)的结构,返回给方法调用者。
(4)若缓存中不存在,则查找数据库并放在缓存中。

IndexCategoryDealDTO

因为首页每个分类要显示四大图+四小图的形式,构建一个辅助类帮助存放这8个商品。

public class IndexCategoryDealDTO {

    @Getter @Setter private DealCategory category;
    @Getter @Setter private List<Deal> first;
    @Getter @Setter private List<Deal> second;


    public IndexCategoryDealDTO(DealCategory category, List<Deal> deals) {
        this.category = category;

        //1.从deals截取出前4个赋值给first
        //2.再4个赋值给second
        //3.不够怎么办?不够4个与不够8个
        //4.多了怎么办?
        if (CollectionUtils.isEmpty(deals)) {
            this.first = new ArrayList<>();
            this.second = new ArrayList<>();
        } else if (deals.size() > 4) {
            this.first = deals.subList(0, 4);
            if (deals.size() > 8) {
                this.second = deals.subList(4, 8);
            } else {
                this.second = deals.subList(4, deals.size());
            }
        } else {
            this.first = new ArrayList<>(deals);
            this.second = new ArrayList<>();
        }
    }
}

注:
(1)构造函数,传入所有的商品信息,帮助构建4+4的商品列表。

前台(freemarker)

基于freemarker模板,文件后缀为.ftl

index.ftl

<#import "macro/common.ftl" as common>
<html>
	<head>
		<title>首页</title>
	</head>
	<body>
		<div class="banner comWidth clearfix">
			<div class="banner_bar banner_big">
				<ul class="imgBox">
					<li><a href="#"><img src="${ctx}/images/banner/banner_01.jpg" alt="banner"></a></li>
					<li><a href="#"><img src="${ctx}/images/banner/banner_02.jpg" alt="banner"></a></li>
				</ul>
				<div class="imgNum">
					<a href="#" class="active"></a><a href="#"></a><a href="#"></a><a href="#"></a>
				</div>
			</div>
		</div>

		<#if indexCategoryDealDTOs??>
			<#list indexCategoryDealDTOs as dto>
				<div class="shopTit comWidth">
					<span class="icon"></span><h3>${dto.category.name}</h3>
					<a href="${ctx}/category/${dto.category.urlName}" class="more">更多&gt;&gt;</a>
				</div>
				<div class="shopList comWidth clearfix">
					<div class="leftArea">
						<div class="banner_bar banner_sm">
							<ul class="imgBox">
								<li><a href="#"><img src="images/banner/banner_sm_01.jpg" alt="banner"></a></li>
								<li><a href="#"><img src="images/banner/banner_sm_02.jpg" alt="banner"></a></li>
							</ul>
							<div class="imgNum">
								<a href="#" class="active"></a><a href="#"></a><a href="#"></a><a href="#"></a>
							</div>
						</div>
					</div>
					<div class="rightArea">
						<#if dto.first?exists>
							<div class="shopList_top clearfix">
								<#list dto.first as deal>
									<div class="shop_item">
										<div class="shop_img">
											<a href="${ctx}/item/${deal.skuId}"><img src="${helper.getDealImageUrlForIndexDeal1List(deal)}" alt=""></a>
										</div>
										<h3>${deal.dealTitle}</h3>
										<p><@common.formatPrice deal.dealPrice/></p>
                                        <#--<p>${deal.dealPrice}</p>-->
									</div>
								</#list>
							</div>
						</#if>
						<#if dto.second?exists>
							<div class="shopList_sm clearfix">
								<#list dto.second as deal>
									<div class="shopItem_sm">
										<div class="shopItem_smImg">
											<a href="${ctx}/item/${deal.skuId}"><img src="${helper.getDealImageUrlForIndexDeal2List(deal)}" alt=""></a>
										</div>
										<div class="shopItem_text">
											<p>${deal.dealTitle}</p>
											<h3><@common.formatPrice deal.dealPrice/></h3>
										</div>
									</div>
								</#list>
							</div>
						</#if>
					</div>
				</div>
			</#list>
		</#if>
	</body>
</html>

注:
(1)注意首部的import,包括了一些freemarker的(定义一些工具)。
(2)<#if> 标签,进行判断。
(3)<#list ** as **>标签,进行循环。
(4)剩下的大概的意思,应该都会懂,取循环变量的字段去做显示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值