[golang gin框架] 17.Gin 商城项目-商品分类模块, 商品类型模块,商品类型属性模块功能操作
一.商品分类的增、删、改、查,以及商品分类的自关联
1.界面展示以及操作说明
列表
商品分类列表展示说明:
(1).增加商品分类按钮
(2).商品分类,以及子分类相关数据列表展示
(3).排序,状态,修改,删除操作处理

新增

编辑

删除

修改状态,排序

2.创建商品分类模型
在controllers/admin下创建GoodsCate.go商品分类控制器
package models//商品分类type GoodsCate struct {Id intTitle string // 标题CateImg string // 分类图片Link string // 跳转地址Template string // 加载的模板: 为空的话加载默认模板, 不为空的话加载自定义模板Pid int // 上级id: 为0的话则是顶级分类SubTitle string // SEO标题Keywords string // SEO关键字Description string // SEO描述Sort int // 排序Status int // 状态: 1 显示, 0 隐藏AddTime int // 添加时间GoodsCateItems []GoodsCate `gorm:"foreignKey:pid;references:Id"` // 关联自身,下级分类
}func (GoodsCate) TableName() string {return "goods_cate"
}
3.创建商品分类色控制器
在controllers/admin下创建GoodsCateController.go商品分类控制器
上传图片操作代码见:[golang gin框架] 15.Gin 商城项目-封装上传图片方法,轮播图的增删改查以及异步修改状态,数量
package admin//商品分类import ("github.com/gin-gonic/gin""goshop/models""net/http""strings"
)type GoodsCateController struct {BaseController
}func (con GoodsCateController) Index(c *gin.Context) {//定义一个切片goodsCateList := []models.GoodsCate{}//获取分类列表以及下级分类models.DB.Where("pid = ?", 0).Preload("GoodsCateItems").Find(&goodsCateList)c.HTML(http.StatusOK, "admin/goodsCate/index.html", gin.H{"goodsCateList": goodsCateList,})
}//新增
func (con GoodsCateController) Add(c *gin.Context) {//获取商品分类顶级分类goodsCateList := []models.GoodsCate{}models.DB.Where("pid = ?", 0).Find(&goodsCateList)c.HTML(http.StatusOK, "admin/goodsCate/add.html", gin.H{"goodsCateList": goodsCateList,})
}//新增:提交
func (con GoodsCateController) DoAdd(c *gin.Context) {//获取请求的表单数据title := strings.Trim(c.PostForm("title"), " ")link := strings.Trim(c.PostForm("link"), " ")template := strings.Trim(c.PostForm("template"), " ")pid, err1 := models.Int(c.PostForm("pid"))subTitle := strings.Trim(c.PostForm("subTitle"), " ")keywords := strings.Trim(c.PostForm("keywords"), " ")description := strings.Trim(c.PostForm("description"), " ")sort, err2 := models.Int(c.PostForm("sort"))status, err3 := models.Int(c.PostForm("status"))if err1 != nil || err3 != nil {con.Error(c, "非法请求", "/admin/goodsCate/add")return}if err2 != nil {con.Error(c, "请输入正确的排序值", "/admin/goodsCate/add")return}//文件上传操作imgSrc, err := models.UploadImg(c, "cate_img")if err != nil {con.Error(c, "图片上传失败", "/admin/goodsCate/add")return}//实例化GoodsCate模型goodsCate := models.GoodsCate{Title: title,Link: link,Sort: sort,Status: status,CateImg: imgSrc,Template: template,Pid: pid,SubTitle: subTitle,Keywords: keywords,Description: description,AddTime: int(models.GetUnix()),}err = models.DB.Create(&goodsCate).Errorif err != nil {con.Error(c, "增加商品失败", "/admin/goodsCate/add")return}con.Success(c, "增加商品成功", "/admin/goodsCate")
}//编辑
func (con GoodsCateController) Edit(c *gin.Context) {//获取角色idid, err := models.Int(c.Query("id"))if err != nil {con.Error(c, "传入数据错误", "/admin/goodsCate")return}//获取商品分类顶级分类goodsCateList := []models.GoodsCate{}models.DB.Where("pid = ?", 0).Find(&goodsCateList)//获取商品goodsCate := models.GoodsCate{Id: id}models.DB.Find(&goodsCate)c.HTML(http.StatusOK, "admin/goodsCate/edit.html", gin.H{"goodsCate": goodsCate,"goodsCateList": goodsCateList,})
}//编辑:提交
func (con GoodsCateController) DoEdit(c *gin.Context) {//获取提交的表单数据id, err := models.Int(c.PostForm("id"))if err != nil {con.Error(c, "传入数据错误", "/admin/goodsCate")return}//获取请求的表单数据title := strings.Trim(c.PostForm("title"), " ")link := strings.Trim(c.PostForm("link"), " ")template := strings.Trim(c.PostForm("template"), " ")pid, err1 := models.Int(c.PostForm("pid"))subTitle := strings.Trim(c.PostForm("subTitle"), " ")keywords := strings.Trim(c.PostForm("keywords"), " ")description := strings.Trim(c.PostForm("description"), " ")sort, err2 := models.Int(c.PostForm("sort"))status, err3 := models.Int(c.PostForm("status"))if err1 != nil || err3 != nil {con.Error(c, "非法请求", "/admin/goodsCate/add")return}if err2 != nil {con.Error(c, "请输入正确的排序值", "/admin/goodsCate/add")return}//文件上传操作imgSrc, err := models.UploadImg(c, "cate_img")if err != nil {con.Error(c, "图片上传失败", "/admin/goodsCate/add")return}//查询分类是否存在goodsCate := models.GoodsCate{Id: id}models.DB.Find(&goodsCate)if imgSrc != "" {goodsCate.CateImg = imgSrc}goodsCate.Title = titlegoodsCate.Link = linkgoodsCate.Sort = sortgoodsCate.Status = statusgoodsCate.Template = templategoodsCate.Pid = pidgoodsCate.SubTitle = subTitlegoodsCate.Keywords = keywordsgoodsCate.Description = descriptionerr = models.DB.Save(&goodsCate).Errorif err != nil {con.Error(c, "修改数据失败", "/admin/goodsCate/edit?id="+models.String(id))return}con.Success(c, "修改数据成功", "/admin/goodsCate")
}//删除
func (con GoodsCateController) Delete(c *gin.Context) {//获取提交的表单数据id, err := models.Int(c.Query("id"))if err != nil {con.Error(c, "传入数据错误", "/admin/goodsCate")return}//查询数据是否存在goodsCate := models.GoodsCate{Id: id}if goodsCate.Pid == 0 { // 顶级分类goodsCateList := []models.GoodsCate{}models.DB.Where("pid = ? ", goodsCate.Id).Find(&goodsCateList)if len(goodsCateList) > 0 {con.Error(c, "当前分类下存在子分类,请先删除子分类后再来删除这个数据", "/admin/goodsCate")return}}err = models.DB.Delete(&goodsCate).Errorif err != nil {con.Error(c, "删除数据失败", "/admin/goodsCate")return}con.Success(c, "删除数据成功", "/admin/goodsCate")
}
4.创建商品分类html以及js
在templates/admin/goodsCate下创建商品分类相关html
修改状态以及排序操作代码见:[golang gin框架] 15.Gin 商城项目-封装上传图片方法,轮播图的增删改查以及异步修改状态,数量
index.html
{{ define "admin/goodsCate/index.html" }}
{{ template "admin/public/page_header.html" .}}<div class="container-fluid"><div class="row"><div class="panel panel-default"><div class="panel-heading"><a href="/admin/goodsCate/add" class="btn btn-primary">增加商品分类</a></div><!--列表展示--><div class="table-responsive"><table class="table table-bordered"><thead><tr class="th"><th>分类名称</th><th>分类图片</th><th class="text-center">排序</th><th class="text-center">状态</th><th class="text-center">操作</th></tr></thead><tbody>{{range $key,$value := .goodsCateList}} <tr><td>{{$value.Title}}</td><td></td><td><span class="chSpanNum" data-id="{{$value.Id}}" data-table="goods_cate" data-field="sort">{{$value.Sort}}</span></td><td class="text-center">{{if eq $value.Status 1}} <img src="/static/admin/images/yes.gif" class="chStatus" data-id="{{$value.Id}}" data-table="goods_cate" data-field="status" />{{else}}<img src="/static/admin/images/no.gif" class="chStatus" data-id="{{$value.Id}}" data-table="goods_cate" data-field="status" />{{end}}</td> <td class="text-center"> <a href="/admin/goodsCate/edit?id={{$value.Id}}" />修改</a> <a class="delete" href="/admin/goodsCate/delete?id={{$value.Id}}" />删除</a></td></tr>{{range $k,$v := $value.GoodsCateItems}} <tr><td> ----{{$v.Title}}</td><td><img src="/{{$v.CateImg}}" width="80" /></td><td class="text-center"><span class="chSpanNum" data-id="{{$v.Id}}" data-table="goods_cate" data-field="sort" data-num="{{$v.Sort}}">{{$v.Sort}}</span></td><td class="text-center">{{if eq $v.Status 1}} <img src="/static/admin/images/yes.gif" class="chStatus" data-id="{{$v.Id}}" data-table="goods_cate" data-field="status" />{{else}}<img src="/static/admin/images/no.gif" class="chStatus" data-id="{{$v.Id}}" data-table="goods_cate" data-field="status" />{{end}}</td><td class="text-center"> <a href="/admin/goodsCate/edit?id={{$v.Id}}" />修改</a> <a class="delete" href="/admin/goodsCate/delete?id={{$v.Id}}" />删除</a></td></tr>{{end}}{{end}}</tbody></table></div></div></div>
</div>
</body>
</html>
{{end}}
add.html
{{ define "admin/goodsCate/add.html" }}
{{ template "admin/public/page_header.html" .}}
<div class="container-fluid"><div class="row"><div class="panel panel-default"><div class="panel-heading">增加分类</div><div class="panel-body"><div class="table-responsive input-form"><form action="/admin/goodsCate/doAdd" method="post" enctype="multipart/form-data"><ul><li> <span>分类名称:</span> <input type="text" name="title" class="input" /></li><li> <span>上级分类:</span><select name="pid" id="pid"><option value="0">顶级分类</option>{{range $key,$value := .goodsCateList}}<option value="{{$value.Id}}">{{$value.Title}}</option>{{end}}</select></li> <li> <span>分类图片:</span> <input type="file" name="cate_img"/></li> <li> <span>跳转地址:</span> <input type="text" name="link" class="input"/></li> <li> <span>分类模板:</span> <input type="text" name="template" class="input"/><span>空表示默认模板</span></li><li> <span>Seo标题:</span> <input type="text" name="sub_title" class="input"/></li><li> <span>Seo关键词: </span><input type="text" name="keywords" class="input"/></li><li> <span>Seo描述:</span> <textarea name="description" id="description" cols="84" rows="4"></textarea></li> <li> <span>排 序:</span> <input type="text" name="sort" value="10"/></li> <li> <span>状 态:</span> <input type="radio" name="status" checked value="1" id="a"/> <label for="a">显示</label> <input type="radio" name="status" value="0" id="b"/><label for="b">隐藏</label> </li><li><br/><button type="submit" class="btn btn-primary">提交</button></li></ul></form></div></div></div></div>
</div>
</body>
</html>
{{end}}
edit.html
{{ define "admin/goodsCate/edit.html" }}
{{ template "admin/public/page_header.html" .}}
<div class="container-fluid"><div class="row"><div class="panel panel-default"><div class="panel-heading">修改分类</div><div class="panel-body"><div class="table-responsive input-form"><form action="/admin/goodsCate/doEdit" method="post" enctype="multipart/form-data"><ul><input type="hidden" name="id" value="{{.goodsCate.Id}}"><li> <span>分类名称:</span> <input type="text" name="title" class="input" value="{{.goodsCate.Title}}" /></li><li> <span>上级分类:</span>{{$pid := .goodsCate.Pid}}<select name="pid" id="pid"><option value="0">顶级分类</option>{{range $key,$value := .goodsCateList}} {{if eq $pid $value.Id}} <option selected value="{{$value.Id}}">{{$value.Title}}</option>{{else}}<option value="{{$value.Id}}">{{$value.Title}}</option>{{end}}{{end}}</select></li> <li> <span>分类图片:</span> <input type="file" name="cate_img"/></li> {{if ne .goodsCate.CateImg ""}}<img src="/{{.goodsCate.CateImg}}" width="100px" size="60" />{{end}}<li> <span>跳转地址:</span> <input type="text" name="link" class="input" value="{{.goodsCate.Link}}"/></li> <li> <span>分类模板:</span> <input type="text" name="template" class="input" value="{{.goodsCate.Template}}"/><span>空表示默认模板</span></li><li> <span>Seo标题:</span> <input type="text" name="sub_title" class="input" value="{{.goodsCate.SubTitle}}"/></li><li> <span>Seo关键词: </span><input type="text" name="keywords" class="input" value="{{.goodsCate.Keywords}}"/></li><li> <span>Seo描述:</span> <textarea name="description" id="description" cols="84" rows="4">{{.goodsCate.Description}}</textarea></li> <li> <span>排 序:</span> <input type="text" name="sort" value="{{.goodsCate.Sort}}"/></li> <li> <span>状 态:</span> <input type="radio" name="status" {{if eq .goodsCate.Status 1}}checked{{end}} value="1" id="a"/> <label for="a">显示</label> <input type="radio" name="status" {{if eq .goodsCate.Status 0}}checked{{end}} value="0" id="b"/><label for="b">隐藏</label> </li><li><br/><button type="submit" class="btn btn-primary">提交</button></li></ul></form></div></div></div></div>
</div>
</body>
</html>{{end}}
5.配置路由
在routes/adminRouters.go下增加商品分类路由
//商品分类路由
adminRouters.GET("/goodsCate", admin.GoodsCateController{}.Index)
adminRouters.GET("/goodsCate/add", admin.GoodsCateController{}.Add)
adminRouters.POST("/goodsCate/doAdd", admin.GoodsCateController{}.DoAdd)
adminRouters.GET("/goodsCate/edit", admin.GoodsCateController{}.Edit)
adminRouters.POST("/goodsCate/doEdit", admin.GoodsCateController{}.DoEdit)
adminRouters.GET("/goodsCate/delete", admin.GoodsCateController{}.Delete)
二.商品类型的增、删、改、查
1.界面展示以及操作说明
列表
商品类型列表展示说明:
(1).增加商品类型按钮
(2).商品类型,相关数据列表展示
(3).状态,修改,删除,类型属性操作处理

新增

编辑

删除

修改状态

2.创建商品类型模型
在controllers/admin下创建GoodsType.go商品类型控制器
package models//商品类型type GoodsType struct {Id intTitle string // 类型名称Description string // 介绍Status int // 状态AddTime int // 添加时间
}func (GoodsType) TableName() string {return "goods_type"
}
3.创建商品类型控制器
在controllers/admin下创建GoodsTypeController.go商品类型控制器
package adminimport ("goshop/models""net/http""strings""github.com/gin-gonic/gin"
)type GoodsTypeController struct {BaseController
}func (con GoodsTypeController) Index(c *gin.Context) {goodsTypeList := []models.GoodsType{}models.DB.Find(&goodsTypeList)c.HTML(http.StatusOK, "admin/goodsType/index.html", gin.H{"goodsTypeList": goodsTypeList,})}
func (con GoodsTypeController) Add(c *gin.Context) {c.HTML(http.StatusOK, "admin/goodsType/add.html", gin.H{})
}func (con GoodsTypeController) DoAdd(c *gin.Context) {title := strings.Trim(c.PostForm("title"), " ")description := strings.Trim(c.PostForm("description"), " ")status, err1 := models.Int(c.PostForm("status"))if err1 != nil {con.Error(c, "传入的参数不正确", "/admin/goodsType/add")return}if title == "" {con.Error(c, "标题不能为空", "/admin/goodsType/add")return}goodsType := models.GoodsType{Title: title,Description: description,Status: status,AddTime: int(models.GetUnix()),}err := models.DB.Create(&goodsType).Errorif err != nil {con.Error(c, "增加商品类型失败 请重试", "/admin/goodsType/add")} else {con.Success(c, "增加商品类型成功", "/admin/goodsType")}}
func (con GoodsTypeController) Edit(c *gin.Context) {id, err := models.Int(c.Query("id"))if err != nil {con.Error(c, "传入数据错误", "/admin/goodsType")} else {goodsType := models.GoodsType{Id: id}models.DB.Find(&goodsType)c.HTML(http.StatusOK, "admin/goodsType/edit.html", gin.H{"goodsType": goodsType,})}}
func (con GoodsTypeController) DoEdit(c *gin.Context) {id, err1 := models.Int(c.PostForm("id"))title := strings.Trim(c.PostForm("title"), " ")description := strings.Trim(c.PostForm("description"), " ")status, err2 := models.Int(c.PostForm("status"))if err1 != nil || err2 != nil {con.Error(c, "传入数据错误", "/admin/goodsType")return}if title == "" {con.Error(c, "商品类型的标题不能为空", "/admin/goodsType/edit?id="+models.String(id))}goodsType := models.GoodsType{Id: id}models.DB.Find(&goodsType)goodsType.Title = titlegoodsType.Description = descriptiongoodsType.Status = statuserr3 := models.DB.Save(&goodsType).Errorif err3 != nil {con.Error(c, "修改数据失败", "/admin/goodsType/edit?id="+models.String(id))} else {con.Success(c, "修改数据成功", "/admin/goodsType")}
}
func (con GoodsTypeController) Delete(c *gin.Context) {id, err := models.Int(c.Query("id"))if err != nil {con.Error(c, "传入数据错误", "/admin/goodsType")} else {goodsType := models.GoodsType{Id: id}models.DB.Delete(&goodsType)con.Success(c, "删除数据成功", "/admin/goodsType")}
}
4.创建商品类型html以及js
在templates/admin/goodsType下创建商品类型相关html
修改状态操作代码见:[golang gin框架] 15.Gin 商城项目-封装上传图片方法,轮播图的增删改查以及异步修改状态,数量
index.html
{{ define "admin/goodsType/index.html" }}
{{ template "admin/public/page_header.html" .}}
<div class="container-fluid"><div class="row"><div class="panel panel-default"><div class="panel-heading"><div class="pagination" id="pa"></div><a href="/admin/goodsType/add" class="btn btn-primary">增加商品类型</a></div><!--列表展示--><div class="table-responsive"><table class="table table-bordered"><thead><tr class="th"><th>商品类型名称</th><th>商品类型描述</th><th class="text-center">状态</th><th class="text-center">操作</th></tr></thead><tbody>{{range $key,$value := .goodsTypeList}}<tr><td>{{$value.Title}}</td><td>{{$value.Description}}</td><td class="text-center">{{if eq $value.Status 1}} <img src="/static/admin/images/yes.gif" class="chStatus" data-id="{{$value.Id}}" data-table="goods_type" data-field="status" />{{else}}<img src="/static/admin/images/no.gif" class="chStatus" data-id="{{$value.Id}}" data-table="goods_type" data-field="status" />{{end}}</td><td class="text-center"><a href="/admin/goodsTypeAttribute?id={{$value.Id}}">类型属性</a><a href="/admin/goodsType/edit?id={{$value.Id}}">修改</a> <a class="delete"href="/admin/goodsType/delete?id={{$value.Id}}">删除</a></td></tr>{{end}}</tbody></table></div></div></div>
</div>
</body>
</html>
{{end}}
add.html
{{ define "admin/goodsType/add.html" }}
{{ template "admin/public/page_header.html" .}}
<div class="container-fluid"><div class="row"><div class="panel panel-default"> <div class="panel-heading">增加商品类型</div><div class="panel-body"><div class="table-responsive input-form"><form action="/admin/goodsType/doAdd" method="post"><ul><li>类型名称: <input type="text" name="title"/></li><li>类型描述:<textarea name="description" cols="60" rows="8"></textarea></li><li> 状 态: <input type="radio" name="status" checked value="1" id="a"/> <label for="a">显示</label> <input type="radio" name="status" value="0" id="b"/><label for="b">隐藏</label> </li><li><li><br/><button type="submit" class="btn btn-default">提交</button></li></ul></form></div></div></div></div>
</div>
</body>
</html>
{{end}}
edit.html
{{ define "admin/goodsType/edit.html" }}
{{ template "admin/public/page_header.html" .}}
<div class="container-fluid"><div class="row"><div class="panel panel-default"> <div class="panel-heading">修改商品类型</div><div class="panel-body"><div class="table-responsive input-form"><form action="/admin/goodsType/doEdit" method="post"><ul><input type="hidden" name="id" value="{{.goodsType.Id}}" /><li>类型名称: <input type="text" name="title" value="{{.goodsType.Title}}"/></li><li>类型描述:<textarea name="description" id="" cols="60" rows="8">{{.goodsType.Description}}</textarea></li><li> 状 态: <input type="radio" name="status" {{if eq .goodsType.Status 1}}checked{{end}} value="1" id="a"/> <label for="a">显示</label> <input type="radio" name="status" {{if eq .goodsType.Status 0}}checked{{end}} value="0" id="b"/><label for="b">隐藏</label> </li><li><li><br/><button type="submit" class="btn btn-default">提交</button></li></ul></form></div></div></div></div>
</div>
</body>
</html>
{{end}}
5.配置路由
在routes/adminRouters.go下配置商品类型路由
//商品类型路由
adminRouters.GET("/goodsType", admin.GoodsTypeController{}.Index)
adminRouters.GET("/goodsType/add", admin.GoodsTypeController{}.Add)
adminRouters.POST("/goodsType/doAdd", admin.GoodsTypeController{}.DoAdd)
adminRouters.GET("/goodsType/edit", admin.GoodsTypeController{}.Edit)
adminRouters.POST("/goodsType/doEdit", admin.GoodsTypeController{}.DoEdit)
adminRouters.GET("/goodsType/delete", admin.GoodsTypeController{}.Delete)
三.商品类型属性的增、删、改、查
1.界面展示以及操作说明
列表
点击商品类型列表中,对应商品类型的类型属性,跳转到商品类型属性列表页面,以电脑类型为例,展示说明:
(1).增加商品类型属性按钮
(2).商品类型属性,相关数据列表展示
(3).排序,状态,修改,删除,操作处理

新增
选择商品类型,以及录入方式 (可以自行增加很多录入方式,具体根据具体业务分析),进行添加

编辑


删除

修改状态

2.创建商品类型属性模型
在controllers/admin下创建GoodsTypeAttribute.go商品类型属性控制器
package models// 商品类型属性设置type GoodsTypeAttribute struct {Id int `json:"id"` // HTML页面使用名称CateId int `json:"cate_id"` //商品类型id:商品类型表goods_type.idTitle string `json:"title"` // 属性名称AttrType int `json:"attr_type"` //属性录入方式: 1 单行文本框, 2 多行文本框, 3 从下面列表中选择(一行代表一个可选值)AttrValue string `json:"attr_value"` //可选值列表Status int `json:"status"` // 状态Sort int `json:"sort"` //排序AddTime int `json:"add_time"` //增加时间
}func (GoodsTypeAttribute) TableName() string {return "goods_type_attribute"
}
3.创建商品类型属性控制器
在controllers/admin下创建GoodsTypeAttributeController.go商品类型属性控制器
package adminimport ("goshop/models""net/http""strings""github.com/gin-gonic/gin"
)type GoodsTypeAttributeController struct {BaseController
}func (con GoodsTypeAttributeController) Index(c *gin.Context) {cateId, err := models.Int(c.Query("id"))if err != nil {con.Error(c, "传入的参数不正确", "/admin/goodsType")return}//获取商品类型属性goodsTypeAttributeList := []models.GoodsTypeAttribute{}models.DB.Where("cate_id=?", cateId).Find(&goodsTypeAttributeList)//获取商品类型属性对应的类型goodsType := models.GoodsType{}models.DB.Where("id=?", cateId).Find(&goodsType)c.HTML(http.StatusOK, "admin/goodsTypeAttribute/index.html", gin.H{"cateId": cateId,"goodsTypeAttributeList": goodsTypeAttributeList,"goodsType": goodsType,})}
func (con GoodsTypeAttributeController) Add(c *gin.Context) {//获取当前商品类型属性对应的类型idcateId, err := models.Int(c.Query("cate_id"))if err != nil {con.Error(c, "传入的参数不正确", "/admin/goodsType")return}//获取所有的商品类型goodsTypeList := []models.GoodsType{}models.DB.Find(&goodsTypeList)c.HTML(http.StatusOK, "admin/goodsTypeAttribute/add.html", gin.H{"goodsTypeList": goodsTypeList,"cateId": cateId,})
}func (con GoodsTypeAttributeController) DoAdd(c *gin.Context) {title := strings.Trim(c.PostForm("title"), " ")cateId, err1 := models.Int(c.PostForm("cate_id"))attrType, err2 := models.Int(c.PostForm("attr_type"))attrValue := c.PostForm("attr_value")sort, err3 := models.Int(c.PostForm("sort"))if err1 != nil || err2 != nil {con.Error(c, "非法请求", "/admin/goodsType")return}if title == "" {con.Error(c, "商品类型属性名称不能为空", "/admin/goodsTypeAttribute/add?cate_id="+models.String(cateId))return}if err3 != nil {con.Error(c, "排序值不对", "/admin/goodsTypeAttribute/add?cate_id="+models.String(cateId))return}goodsTypeAttr := models.GoodsTypeAttribute{Title: title,CateId: cateId,AttrType: attrType,AttrValue: attrValue,Status: 1,Sort: sort,AddTime: int(models.GetUnix()),}err := models.DB.Create(&goodsTypeAttr).Errorif err != nil {con.Error(c, "增加商品类型属性失败 请重试", "/admin/goodsTypeAttribute/add?cate_id="+models.String(cateId))return}con.Success(c, "增加商品类型属性成功", "/admin/goodsTypeAttribute?id="+models.String(cateId))
}func (con GoodsTypeAttributeController) Edit(c *gin.Context) {//获取当前要修改数据的idid, err := models.Int(c.Query("id"))if err != nil {con.Error(c, "传入的参数不正确", "/admin/goodsType")return}//获取当前id对应的商品类型属性goodsTypeAttribute := models.GoodsTypeAttribute{Id: id}models.DB.Find(&goodsTypeAttribute)//获取所有的商品类型goodsTypeList := []models.GoodsType{}models.DB.Find(&goodsTypeList)c.HTML(http.StatusOK, "admin/goodsTypeAttribute/edit.html", gin.H{"goodsTypeAttribute": goodsTypeAttribute,"goodsTypeList": goodsTypeList,})
}func (con GoodsTypeAttributeController) DoEdit(c *gin.Context) {id, err1 := models.Int(c.PostForm("id"))title := strings.Trim(c.PostForm("title"), " ")cateId, err2 := models.Int(c.PostForm("cate_id"))attrType, err3 := models.Int(c.PostForm("attr_type"))attrValue := c.PostForm("attr_value")sort, err4 := models.Int(c.PostForm("sort"))if err1 != nil || err2 != nil || err3 != nil {con.Error(c, "非法请求", "/admin/goodsType")return}if title == "" {con.Error(c, "商品类型属性名称不能为空", "/admin/goodsTypeAttribute/edit?id="+models.String(id))return}if err4 != nil {con.Error(c, "排序值不对", "/admin/goodsTypeAttribute/edit?id="+models.String(id))return}goodsTypeAttr := models.GoodsTypeAttribute{Id: id}models.DB.Find(&goodsTypeAttr)goodsTypeAttr.Title = titlegoodsTypeAttr.CateId = cateIdgoodsTypeAttr.AttrType = attrTypegoodsTypeAttr.AttrValue = attrValuegoodsTypeAttr.Sort = sorterr := models.DB.Save(&goodsTypeAttr).Errorif err != nil {con.Error(c, "修改数据失败", "/admin/goodsTypeAttribute/edit?id="+models.String(id))return}con.Success(c, "需改数据成功", "/admin/goodsTypeAttribute?id="+models.String(cateId))
}func (con GoodsTypeAttributeController) Delete(c *gin.Context) {id, err1 := models.Int(c.Query("id"))cateId, err2 := models.Int(c.Query("cate_id"))if err1 != nil || err2 != nil {con.Error(c, "传入参数错误", "/admin/goodsType")return}goodsTypeAttr := models.GoodsTypeAttribute{Id: id}models.DB.Delete(&goodsTypeAttr)con.Success(c, "删除数据成功", "/admin/goodsTypeAttribute?id="+models.String(cateId))
}
4.创建商品类型属性html以及js
在templates/admin/goodsTypeAttribute下创建商品类型属性相关html
修改状态以及排序操作代码见:[golang gin框架] 15.Gin 商城项目-封装上传图片方法,轮播图的增删改查以及异步修改状态,数量
index.html
{{ define "admin/goodsTypeAttribute/index.html" }}
{{ template "admin/public/page_header.html" .}}<div class="container-fluid"><div class="row"><div class="panel panel-default"><div class="panel-heading">{{.goodsType.Title}} <a href="/admin/goodsTypeAttribute/add?cate_id={{.cateId}}" class="btn btn-primary">增加类型属性</a></div><!--列表展示--><div class="table-responsive"><table class="table table-bordered"><thead><tr class="th"><th>属性名称</th><th>商品类型</th><th>属性值的录入方式</th><th>可选值列表</th><th>增加时间</th><th class="text-center">排序</th><th class="text-center">状态</th><th class="text-center">操作</th></tr></thead><tbody>{{$cateTitle := .goodsType.Title}}{{range $key,$value := .goodsTypeAttributeList}}<tr><td>{{$value.Title}}</td><td>{{$cateTitle}}</td><td>{{if eq $value.AttrType 1}}单行文本框{{else if eq $value.AttrType 2}}多行文本框{{else if eq $value.AttrType 3}}select下拉框{{end}}</td><td>{{$value.AttrValue}}</td><td>{{UnixToTime $value.AddTime}}</td><td><span class="chSpanNum" data-id="{{$value.Id}}" data-table="goods_type_attribute" data-field="sort">{{$value.Sort}}</span></td><td class="text-center">{{if eq $value.Status 1}}<img src="/static/admin/images/yes.gif" class="chStatus" data-id="{{$value.Id}}"data-table="goods_type_attribute" data-field="status" />{{else}}<img src="/static/admin/images/no.gif" class="chStatus" data-id="{{$value.Id}}"data-table="goods_type_attribute" data-field="status" />{{end}}</td><td class="text-center"><ahref="/admin/goodsTypeAttribute/edit?id={{$value.Id}}" >修改</a><a class="delete"href="/admin/goodsTypeAttribute/delete?id={{$value.Id}}&cate_id={{$value.CateId}}" >删除</a></td></tr>{{end}}</tbody></table></div></div></div>
</div></body>
</html>
{{end}}
add.html
{{ define "admin/goodsTypeAttribute/add.html" }}
{{ template "admin/public/page_header.html" .}}<div class="container-fluid"><div class="row"><div class="panel panel-default"><div class="panel-heading">增加商品类型属性</div><div class="panel-body"><div class="table-responsive input-form"><form action="/admin/goodsTypeAttribute/doAdd" method="post"><ul><li> 属性名称: <input type="text" name="title" /></li><li> 所属类型:{{$cateId := .cateId}}<select name="cate_id" id="cate_id">{{range $key,$value := .goodsTypeList}}<option {{if eq $cateId $value.Id}} selected {{end}} value="{{$value.Id}}">{{$value.Title}}</option> {{end}}</select></li><li> 录入方式:<input type="radio" name="attr_type" value="1" checked="true" id="text" /><labelfor="text">单行文本框</label> <input type="radio" name="attr_type" value="2" id="textarea" /><labelfor="textarea">多行文本框</label> <input type="radio" name="attr_type" value="3" id="select" /><labelfor="select">从下面的列表中选择(一行代表一个可选值)</label> </li><li>可选值列表:<textarea name="attr_value" id="attr_value" cols="60" rows="8" disabled="disabled"></textarea></li><li> <span>排 序:</span> <input type="text" name="sort" value="10" /></li><li><br /><button type="submit" class="btn btn-primary">提交</button></li></ul></form></div></div></div></div>
</div>
<script>$(function(){ $("input[name='attr_type").change(function(){// alert($(this).val())if($(this).val()==3){$("#attr_value").attr("disabled",false)}else{$("#attr_value").attr("disabled",true)}})
})
</script>
</body>
</html>{{end}}
edit.html
{{ define "admin/goodsTypeAttribute/edit.html" }}
{{ template "admin/public/page_header.html" .}}<div class="container-fluid"><div class="row"><div class="panel panel-default"><div class="panel-heading">修改商品类型属性</div><div class="panel-body"><div class="table-responsive input-form"><form action="/admin/goodsTypeAttribute/doEdit" method="post"><input type="hidden" name="id" value="{{.goodsTypeAttribute.Id}}" /><ul><li> 属性名称: <input type="text" name="title" value="{{.goodsTypeAttribute.Title}}" /></li><li> 所属类型:{{$cateId := .goodsTypeAttribute.CateId}}<select name="cate_id" id="cate_id">{{range $key,$value := .goodsTypeList}}<option {{if eq $cateId $value.Id}} selected {{end}} value="{{$value.Id}}">{{$value.Title}}</option> {{end}}</select></li><li> 录入方式:<input type="radio" name="attr_type" value="1" {{if eq .goodsTypeAttribute.AttrType 1}} checked="true" {{end}} id="text" /><labelfor="text">单行文本框</label> <input type="radio" name="attr_type" value="2" {{if eq .goodsTypeAttribute.AttrType 2}} checked="true" {{end}} id="textarea" /><labelfor="textarea">多行文本框</label> <input type="radio" name="attr_type" value="3" {{if eq .goodsTypeAttribute.AttrType 3}} checked="true" {{end}} id="select" /><labelfor="select">从下面的列表中选择(一行代表一个可选值)</label> </li><li>可选值列表:<textarea name="attr_value" id="attr_value" cols="60" rows="8" {{if ne .goodsTypeAttribute.AttrType 3}} disabled="disabled" {{end}}>{{.goodsTypeAttribute.AttrValue}}</textarea></li><li> <span>排 序:</span> <input type="text" name="sort" value="{{.goodsTypeAttribute.Sort}}" /></li><li><br /><button type="submit" class="btn btn-primary">提交</button></li></ul></form></div></div></div></div>
</div>
<script>$(function(){ $("input[name='attr_type").change(function(){// alert($(this).val())if($(this).val()==3){$("#attr_value").attr("disabled",false)}else{$("#attr_value").attr("disabled",true)}})
})
</script>
</body>
</html>{{end}}
5.配置路由
在routes/adminRouters.go下配置商品类型路由
//商品类型属性路由adminRouters.GET("/goodsTypeAttribute", admin.GoodsTypeAttributeController{}.Index)adminRouters.GET("/goodsTypeAttribute/add", admin.GoodsTypeAttributeController{}.Add)adminRouters.POST("/goodsTypeAttribute/doAdd", admin.GoodsTypeAttributeController{}.DoAdd)adminRouters.GET("/goodsTypeAttribute/edit", admin.GoodsTypeAttributeController{}.Edit)adminRouters.POST("/goodsTypeAttribute/doEdit", admin.GoodsTypeAttributeController{}.DoEdit)adminRouters.GET("/goodsTypeAttribute/delete", admin.GoodsTypeAttributeController{}.Delete)
[上一节][golang gin框架] 16.Gin 商城项目-商品模块数据表ER图关系分析
[下一节][golang gin框架] 18.GoLang 图像处理,剪切图片,生成图片二维码
相关文章:

[golang gin框架] 17.Gin 商城项目-商品分类模块, 商品类型模块,商品类型属性模块功能操作
一.商品分类的增、删、改、查,以及商品分类的自关联1.界面展示以及操作说明列表商品分类列表展示说明:(1).增加商品分类按钮(2).商品分类,以及子分类相关数据列表展示(3).排序,状态,修改,删除操作处理 新增编辑删除修改状态,排序2.创建商品分类模型在controllers/admin下创建Go…...
Redis安装-使用包管理安装Redis
这种在Linux上使用apt-get包管理器安装Redis的方式称为“包管理安装”。这种安装方式使用操作系统的官方软件库来获取和安装软件包,可以自动处理软件包的依赖关系,并确保软件包与系统其他部分兼容。这是一种安全、可靠且方便的安装方式,适用于…...

HTML属性的概念和使用
通过前面的学习,我们已经对 HTML标签 有了简单的认识,知道可以在标签中可以添加一些属性,这些属性包含了标签的额外信息,例如: href 属性可以为 <a> 标签提供链接地址;src 属性可以为 <img> 标…...

ChatGPT基础知识系列之一文说透ChatGPT
ChatGPT基础知识系列之一文说透ChatGPT OpenAI近期发布聊天机器人模型ChatGPT,迅速出圈全网。它以对话方式进行交互。以更贴近人的对话方式与使用者互动,可以回答问题、承认错误、挑战不正确的前提、拒绝不适当的请求。高质量的回答、上瘾式的交互体验,圈内外都纷纷惊呼。 …...

‘go install‘ requires a version when current directory is not in a module
背景 安装好环境之后,跑个helloworld看看 目录结构 workspacepathsrchellohelloworld.go代码: package mainimport "fmt"func main() { fmt.Println("Hello World") }1.使用 go run 命令 - 在命令提示符旁,输入 go …...

蓝桥杯嵌入式第十三届(第二套客观题)
文章目录 前言一、题目1二、题目2三、题目3四、题目4五、题目5六、题目6七、题目7八、题目8九、题目9十、题目10总结前言 本篇文章继续讲解客观题。 一、题目1 这个其实属于送分题,了解嵌入式或者以后想要入行嵌入式的同学应该都对嵌入式特点有所了解。 A. 采用专用微控制…...
FFmpeg进阶:各种输入输出设备
文章目录查看设备列表输入设备介绍输出设备介绍查看设备列表 我们可以通过ffmpeg自带的工具查看系统支持的设备列表信息, 对应的指令如下所示: ffmpeg -devices输入设备介绍 通过配置ffmpeg的输入设备,我们可以访问系统中的某个多媒体设备的数据。下面详细介绍一下各个系统中…...
使用Shell笔记总结
一、变量 1、定义变量不加$符号,使用变量要用$;等号两边不能直接接空格符;通常大写字符为系统默认变量,自行设定变量可以使用小写字符。 2、双引号内的特殊字符如 $ 等,可以保有其符号代表的特性,即可以有…...

反常积分的审敛法
目录 无穷先的反常积分的审敛法 定理1:比较判别法 例题: 比较判别法的极限形式: 例题: 定理3:绝对收敛准则 例题: 无界函数的反常积分收敛法 例题: 无穷先的反常积分的审敛法 定理1&#x…...
python实战应用讲解-【numpy专题篇】numpy常见函数使用示例(十三)(附python示例代码)
目录 Python numpy.ma.mask_or()函数 Python numpy.ma.notmasked_contiguous函数 Python numpy.ma.notmasked_edges()函数 Python numpy.ma.where()函数 Python Numpy MaskedArray.all()函数 Python Numpy MaskedArray.anom()函数 Python Numpy MaskedArray.any()函数 …...
Java设计模式(十九)—— 桥接模式
桥接模式定义如下:将抽象部分与它的实现部分分离,使它们都可以独立地变化。 适合桥接模式的情景如下: 不希望抽象和某些重要的实现代码是绑定关系,可运行时动态决定抽象和实现者都可以继承的方式独立的扩充,程序在运行…...
多线程并发安全问题
文章目录并发安全问题线程安全性死锁定义实现一个死锁查看死锁解决死锁其他线程安全问题单例模式并发安全问题 线程安全性 线程安全是指我们所写的代码在并发情况下使用时,总是能表现出正确的行为;反之,未实现线程安全的代码,表…...
P1005 [NOIP2007 提高组] 矩阵取数游戏
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的 ��nm 的矩阵,矩阵中的每个元素 ��,�ai,j 均为非负整数。游戏规则如下: 每次取数时须从每行各取走一个元素ÿ…...

百度云【人脸识别】
目录 1:百度云【人脸识别云服务】 2:Java-SDK文档 3:项目中测试 1:百度云【人脸识别云服务】 人脸识别云服务 包含实名认证、人脸对比、人脸搜索、活体检测等能力。灵活应用于金融、泛安防等行业场景,满足身份核验…...
强化模板模块
一、非类型模板参数 模板参数分为 类型模板参数(C模板的零基础讲解)和非类型模板参数。 看下面的代码 #define N 10 //T就是类型模板参数 template<class T> class Array { private:T a[N]; }; int main() {Array<int> a1;Array<double> a2;return 0; }上面…...
Vue.js学习详细课程系列--共32节(6 / 6)
Vue.js学习课程(6 / 6)29. 组件:参数验证知识点组件的数据综合例30. 组件:事件传递知识点v-on$emit综合例31. 组件:slot插槽知识点slot综合例32. 组件:组合slot知识点slot命名综合例29. 组件:参…...

【TFT屏幕】1.44寸彩屏
文章目录一.硬件层——引脚配置的移植二.应用层——显示函数的移植1. 移植显示一个字符函数2. 移植显示数字函数3.叠加方式选择一.硬件层——引脚配置的移植 宏定义的方式,直接修改引脚,实测可直接更改,非常方便移植 /*******************…...

vue3组合式api
文章目录组合式API介绍什么是组合式 API?为什么要有组合式 API?更好的逻辑复用更灵活的代码组织Option ApiOption Api的缺陷Composition Api更好的类型推导更小的生产包体积与选项式 API 的关系取舍组合式 API 是否覆盖了所有场景?可以同时使…...

Maven高级-私服
Maven高级-私服6,私服6.1 私服简介6.2 私服安装步骤1:下载解压步骤2:启动Nexus步骤3:浏览器访问步骤4:首次登录重置密码6.3 私服仓库分类6.4 本地仓库访问私服配置步骤1:私服上配置仓库步骤2:配置本地Maven对私服的访问权限步骤3:配置私服的访问路径6.5 私服资源上传…...
网络优化小结
网络基础知识 OSI七层网络架构 OSI简称Open System Intercnnect,开放式系统互联,是一个国际互联网标准制定的一个组织 应用层 实际应用场景,比如 浏览器、文件传输、电子邮件、文件服务、虚拟终端等; http、FTP、ssh等 表示层…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
Yii2项目自动向GitLab上报Bug
Yii2 项目自动上报Bug 原理 yii2在程序报错时, 会执行指定action, 通过重写ErrorAction, 实现Bug自动提交至GitLab的issue 步骤 配置SiteController中的actions方法 public function actions(){return [error > [class > app\helpers\web\ErrorAction,],];}重写Error…...

Centos 7 服务器部署多网站
一、准备工作 安装 Apache bash sudo yum install httpd -y sudo systemctl start httpd sudo systemctl enable httpd创建网站目录 假设部署 2 个网站,目录结构如下: bash sudo mkdir -p /var/www/site1/html sudo mkdir -p /var/www/site2/html添加测试…...