一.首页界面展示以及项目结构分析
首页界面展示



项目结构分析

二.代码展示
首页相关模型
首页相关模型如下:
[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 商城项目-商店设置模块,以及通过反射获取系统设置里面的数据