一.首页界面展示以及项目结构分析
- 首页界面展示
 
    
    
   - 项目结构分析
 
   二.代码展示
- 首页相关模型
首页相关模型如下:
[golang gin框架] 21.Gin 商城项目-导航模块功能
[golang gin框架] 17.Gin 商城项目-商品分类模块, 商品类型模块,商品类型属性模块功能操作
[golang gin框架] 16.Gin 商城项目-商品模块数据表ER图关系分析
[golang gin框架] 15.Gin 商城项目-封装上传图片方法,轮播图的增删改查以及异步修改状态,数量
商品模型Goods.go增加方法GetGoodsByCategory():根据分类id,商品类型获取分类下面的数据
package models
//商品表
type Goods struct {
    Id            int
    Title         string  //商品标题
    SubTitle      string  //附属标题
    GoodsSn       string  //商品编号
    CateId        int     //商品分类id: goods_cate.id
    ClickCount    int     //商品点击数量
    GoodsNumber   int     //商品库存
    Price         float64 //价格
    MarketPrice   float64 //商品市场价(原价)
    RelationGoods string  //关联商品id,如: 1, 23,55 ,商品id以逗号隔开
    GoodsAttr     string  //商品更多属性
    GoodsVersion  string  //商品版本
    GoodsImg      string  //图片
    GoodsGift     string  //商品赠品
    GoodsFitting  string  //商品配件
    GoodsColor    string  //颜色
    GoodsKeywords string  //SEO关键字
    GoodsDesc     string  //SEO商品描述
    GoodsContent  string  //商品详情
    IsDelete      int     //是否删除
    IsHot         int     //是否热销
    IsBest        int     //是否精品
    IsNew         int     //是否新品
    GoodsTypeId   int     //商品类型id,关联GoodsType.Id
    Sort          int     //排序
    Status        int     //状态
    AddTime       int     //添加时间
}
func (Goods) TableName() string {
    return "goods"
}
/**
根据分类id,商品类型获取分类下面的数据
*/
func GetGoodsByCategory(cateId int, goodsType string, limitNum int) []Goods {
    //判断是否顶级分类
    goodsCate := GoodsCate{Id: cateId}
    DB.Find(&goodsCate)
    var tempSlice []int
    if goodsCate.Pid == 0 { // 说明是顶级分类,则需要获取其下面的二级分类
        goodsCateList := []GoodsCate{}
        DB.Where("pid = ?", goodsCate.Id).Find(&goodsCate)
        //把二级分类id存入切片
        for i := 0; i < len(goodsCateList); i++ {
            tempSlice = append(tempSlice, goodsCateList[i].Id)
        }
    }
    tempSlice = append(tempSlice, goodsCate.Id)
    where := "cate_id in ?"
    //通过商品类型,拼接条件
    switch goodsType {
        case "is_best":
            where += " AND is_best = 1"
        case "is_hot":
            where += " AND is_hot = 1"
        case "is_new":
            where += " AND is_new = 1"
        default:
            break
    }
    goodsList := []Goods{}
    DB.Where(where, tempSlice).Order("sort DESC").Select("id, title, price, goods_img, sub_title").Limit(limitNum).Find(&goodsList)
    return goodsList
}2.tools.go工具类代码
增加SubStr截取字符串方法
//SubStr截取字符串
func SubStr(str string, start int, end int) string {
    rs := []rune(str)
    rl := len(rs)
    if start < 0 {
        start = 0
    }
    if start > rl {
        start = 0
    }
    if end < 0 {
        end = rl
    }
    if end > rl {
        end = rl
    }
    if start > end {
        start, end = end, start
    }
    return string(rs[start:end])
}3.main.go注入上面的方法
//自定义模板函数,必须在r.LoadHTMLGlob前面(只调用,不执行, 可以在html 中使用)
    r.SetFuncMap(template.FuncMap{
        "UnixToTime": models.UnixToTime, //注册模板函数
        "Str2Html": models.Str2Html,
        "FormatImg": models.FormatImg,
        "Sub": models.Sub,
        "SubStr": models.SubStr,
    })4.控制器
在controllers/frontend下创建IndexController控制器文件,存放前台首页相关代码
package frontend
//首页
import (
    "github.com/gin-gonic/gin"
    "gorm.io/gorm"
    "goshop/models"
    "net/http"
    "strings"
)
type IndexController struct {
}
func (con IndexController) Index(c *gin.Context) {
    //获取顶部导航列表
    topNavList := []models.Nav{}
    models.DB.Where("status = 1 AND position = 1").Find(&topNavList)
    //获取网站轮播图数据
    focusList := []models.Focus{}
    models.DB.Where("status = 1 AND focus_type = 1").Find(&focusList)
    //获取分类数据
    goodsCateList := []models.GoodsCate{}
    //获取分类列表以及下级分类,并进行排序
    models.DB.Where("pid = ? AND status = ?", 0, 1).Order("sort DESC").Preload("GoodsCateItems", func(db *gorm.DB) *gorm.DB {
        return db.Where("goods_cate.status = 1").Order("goods_cate.sort DESC")
    } ).Find(&goodsCateList)
    //获取中间导航
    middleNavList := []models.Nav{}
    models.DB.Where("status = ? AND position = ? ", 1, 2).Find(&middleNavList)
    //循环,获取中间导航对应的商品数据
    for i:= 0; i < len(middleNavList);i++{
        //获取管理商品
        //替换字符串中的中文逗号strings.ReplaceAll()
        relation := strings.ReplaceAll(middleNavList[i].Relation, ",", ",")
        //把字符串转换成切片
        relationIds := strings.Split(relation, ",")
        //获取对应的商品信息
        goodsList := []models.Goods{}
        models.DB.Where("status = ?", 1).Where("id in ?", relationIds).Select("id, title, goods_img, price").Find(&goodsList)
        middleNavList[i].GoodsItems = goodsList
    }
    //获取手机分类下面的商品
    phoneList := models.GetGoodsByCategory(23, "best", 10)
    c.HTML(http.StatusOK, "frontend/index/index.html", gin.H{
        "topNavList": topNavList,
        "focusList": focusList,
        "goodsCateList": goodsCateList,
        "middleNavList": middleNavList,
        "phoneList": phoneList,
    })
}5.公共的header,footer页面
在templates/frontend/public目录下创建page_header.html(顶部公共html),page_footer.html(底部公共html)
page_header.html
<!-- 相当于给模板定义一个名字, define end 必须成对出现 -->
{{ define "frontend/public/page_header.html" }}
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <meta name="author" content="order by dede58.com"/>
        <title>xxxx</title>
        <link rel="stylesheet" type="text/css" href="/static/frontend/css/style.css">
        <link rel="stylesheet" href="/static/frontend/css/swiper.min.css">
        <script src="/static/frontend/js/jquery-1.10.1.js"></script>
        <script src="/static/frontend/js/swiper.min.js"></script>
        <script src="/static/frontend/js/base.js"> </script>
    </head>
    <body>
    <!-- start header 顶部导航 -->
    <header>
        <div class="top center">
            <div class="left fl">
                <ul>
                    <!--获取长度,并计算,看看是否显示最后的 | 画线-->
                    {{ $temp := .topNavList | len }}
                    {{ $navLen := Sub  $temp 1 }}
                    {{range $key, $value := .topNavList}}
                    <li><a href="{{$value.Link}}"{{if eq $value.IsOpennew 1 }} target="_blank" {{end}} >{{$value.Title}}</a></li>
                    {{if lt $key $navLen}}
                    <li>|</li>
                    {{end}}
                    {{end}}
                    <div class="clear"></div>
                </ul>
            </div>
            <!--登录相关-->
            <div class="right fr">
                <div class="gouwuche fr"><a href="">购物车</a></div>
                <div class="fr">
                    <ul>
                        <li><a href="./login.html" target="_blank">登录</a></li>
                        <li>|</li>
                        <li><a href="./register.html" target="_blank" >注册</a></li>
                        <li>|</li>
                        <li><a href="">消息通知</a></li>
                    </ul>
                </div>
                <div class="clear"></div>
            </div>
            <div class="clear"></div>
        </div>
    </header>
    <!--end header -->
    <!-- start banner_x 中部导航 -->
    <div class="banner_x center">
        <a href="./index.html" target="_blank"><div class="logo fl"></div></a>
        <a href=""><div class="ad_top fl"></div></a>
        <div class="nav fl">
            <ul class="clearfix" id="nav_list">
                {{range $key, $value := .middleNavList }}
                <li>
                    <a href="{{$value.Link}}" target="_blank">{{$value.Title}}</a>
                    <ol class="children-list clearfix">
                        {{range $k, $v := $value.GoodsItems }}
                        <li>
                            <a href="#">
                                <img src="{{$v.GoodsImg | FormatImg }}" />
                                <p>{{$v.Price}}</p>
                            </a>
                        </li>
                        {{end}}
                    </ol>
                </li>
                {{end}}
            </ul>
        </div>
        <!--搜索-->
        <div class="search fr">
            <form action="" method="post">
                <div class="text fl">
                    <input type="text" class="shuru"  placeholder="MIX现货">
                </div>
                <div class="submit fl">
                    <input type="submit" class="sousuo" value="搜索"/>
                </div>
                <div class="clear"></div>
            </form>
            <div class="clear"></div>
        </div>
    </div>
    <!-- end banner_x -->
{{end}}page_footer.html
<!-- 相当于给模板定义一个名字, define end 必须成对出现 -->
{{ define "frontend/public/page_footer.html" }}
    <footer class="mt20 center">
        <div class="mt20">xxx|xxx|xxx|xx书城|xx路由器|视频电话|隐私政策|Select Region</div>
        <div>©xx.com 京ICP证1x07号 京ICP备xxx号 京公网安备xxx号 京网文[2014]0059-xxx9号</div>
        <div>违法和不良信息举报电话:1xx-xxxx-12xx,本网站所列数据,xxxx</div>
    </footer>
{{end}}6.前台首页
{{ define "frontend/index/index.html" }}
    {{template "frontend/public/page_header.html" .}}
    <!-- start banner_y 商品分类 -->
        <div class="banner_y center">
            <div class="nav">
                <ul>
                    {{range $key, $value := .goodsCateList }}
                    <li>
                            <a href="{{$value.Link}}" target="_blank">{{$value.Title}}</a>
                        <div class="pop">
                            <ol class="cate_list clear">
                                {{range $k, $v := $value.GoodsCateItems}}
                                    <li>
                                        <div class="xuangou_left">
                                                <a href="{{$v.Link}}" target="_blank" class="clearfix">
                                                    <div class="img fl"><img src="{{$v.CateImg | FormatImg}}" alt="{{$v.Title}}"></div>
                                                    <span class="fl">{{$v.Title}}</span>
                                                </a>
                                        </div>
                                    </li>
                                {{end}}
                            </ol>
                        </div>
                    </li>
                    {{end}}
                </ul>
            </div>
            <!--轮播图-->
              <div class="swiper-container">
                <div class="swiper-wrapper">
                    {{range $key, $value := .focusList}}
                      <div class="swiper-slide">
                          <a href="{{$value.Link}}" target="_blank">
                            <img src="{{$value.FocusImg | FormatImg}}" alt="{{$value.Title}}" />
                          </a>
                      </div>
                    {{end}}
                </div>
                <!-- Add Arrows -->
                <div class="swiper-button-next"></div>
                <div class="swiper-button-prev"></div>
              </div>
        
        </div>    
    <!-- end banner -->
    <!-- start danpin -->
        <div class="danpin center">
            
            <div class="title center">单品</div>
            <div class="main center">
                <div class="mingxing fl">
                    <div class="sub_mingxing"><a href=""><img src="/static/frontend/image/pinpai2.png" alt=""></a></div>
                    <div class="pinpai"><a href="">xxx</a></div>
                    <div class="youhui">5月9日-10日,下单立减200元</div>
                    <div class="jiage">1999元</div>
                </div>
                ...
                <div class="clear"></div>
            </div>
        </div>
        <!-- 手机 -->
    <!--获取手机分类下面的商品信息 -->
    <div class="category_item w">
        <div class="title center">手机</div>
        <div class="main center">
            <div class="category_item_left">
                <img src="static/itying/image/shouji.jpg" alt="手机">
            </div>
            <div class="category_item_right">
                {{range $key,$value := .phoneList}}
                    <div class="hot fl">
                        <div class="xinpin"><span style="background:#fff"></span></div>
                        <div class="tu"><a href="#"><img src="{{$value.GoodsImg | FormatImg}}"></a></div>
                        <div class="miaoshu"><a href="#">{{$value.Title}}</a></div>
                        <div class="jiage">{{$value.Price}}元</div>
                        <div class="pingjia">372人评价</div>
                        <div class="piao">
                            <a href="">
                                <span>{{SubStr $value.SubTitle 0 4}}</span>
                            </a>
                        </div>
                    </div>
                {{end}}
            </div>
        </div>
    </div>
        <!-- 配件 -->
        <div class="category_item w">
            <div class="title center">配件</div>
            <div class="main center">
                <div class="content">
                    <div class="hot fl"><a href=""><img src="/static/frontend/image/peijian1.jpg"></a>
                    </div>
                    <div class="hot fl">
                        <div class="xinpin"><span>新品</span></div>
                        <div class="tu"><a href=""><img src="/static/frontend/image/peijian2.jpg"></a></div>
                        <div class="miaoshu"><a href="">小米6 硅胶保护套</a></div>
                        <div class="jiage">49元</div>
                        <div class="pingjia">372人评价</div>
                        <div class="piao">
                            <a href="">
                                <span>发货速度很快!很配小米6!</span>
                                <span>来至于mi狼牙的评价</span>
                            </a>
                        </div>
                    </div>
                   
                    <div class="hotlast fr">
                        <div class="hongmi"><a href=""><img src="/static/frontend/image/hongmin4.png" alt=""></a></div>
                        <div class="liulangengduo"><a href=""><img src="/static/frontend/image/liulangengduo.png" alt=""></a></div>                    
                    </div>
                    <div class="clear"></div>
                </div>                
            </div>
        </div>
    {{template "frontend/public/page_footer.html" .}}
    </body>
</html>
{{end}}6.配置路由
在main.go中引入路由文件,在routers/frontendRouters.go下配置路由
main.go
//分组路由文件
routers.AdminRoutersInit(r)
routers.ApiRoutersInit(r)
routers.FrontendRoutersInit(r)frontendRouters.go
package routers
import (
    "goshop/controllers/frontend"
    "github.com/gin-gonic/gin"
)
//设置前端路由
func FrontendRoutersInit(r *gin.Engine) {
    defaultRouters := r.Group("/")
    {
        defaultRouters.GET("/", frontend.IndexController{}.Index)
    }
}[上一节][golang gin框架] 22.Gin 商城项目-商店设置模块,以及通过反射获取系统设置里面的数据


















