> 文章列表 > [golang gin框架] 15.Gin 商城项目-封装上传图片方法,轮播图的增删改查以及异步修改状态,数量

[golang gin框架] 15.Gin 商城项目-封装上传图片方法,轮播图的增删改查以及异步修改状态,数量

[golang gin框架] 15.Gin 商城项目-封装上传图片方法,轮播图的增删改查以及异步修改状态,数量

一.封装上传图片方法

在models/tools.go文件下封装一个上传图片的方法

//图片上传
func UploadImg(c *gin.Context, picName string) (string, error) {//1.获取上传文件file, err := c.FormFile(picName)//判断上传文件上否存在if err != nil { //说明上传文件不存在return "", nil}//2.获取后缀名,判断后缀是否正确: .jpg,.png,.gif,.jpegextName := path.Ext(file.Filename)//设置后缀mapallowExtMap := map[string]bool{".jpg":  true,".png":  true,".gif":  true,".jpeg": true,}//判断后缀是否合法if _, ok := allowExtMap[extName]; !ok {return "", errors.New("文件后缀名不合法")}//3.创建图片保存目录 ./static/upload/20230203//获取日期day := GetDay()//拼接目录dir := "./static/upload/" + day//创建目录:MkdirAll 目录不存在,会一次性创建多层err = os.MkdirAll(dir, 0666)if err != nil {return "", err}//4.生成文件名称和文件保存目录: models.GetUnixNano() 获取时间戳(int64) 纳秒:防止速度过快而上传图片失败; strconv.FormatInt() 把时间戳(int64)转换成字符串filename := strconv.FormatInt(GetUnixNano(), 10) + extName//5.执行上传dst := path.Join(dir, filename)//上传文件到指定目录c.SaveUploadedFile(file, dst)return dst, nil
}//获取年月日
func GetDay() string {template := "20060102"return time.Now().Format(template)
}

二.轮播图的增删改查

  1. 创建轮播图模型

在models目录下创建focus.go轮播图模型

package models//轮播图type Focus struct {Id        intTitle     stringFocusType int  // 1 网站, 2 app, 3 小程序FocusImg  stringLink      stringSort      intStatus    intAddTime   int
}func (Focus) TableName() string {return "focus"
}

2.创建轮播图控制器

在controllers/admin下创建FocusController.go轮播图控制器

package adminimport ("fmt""github.com/gin-gonic/gin""goshop/models""net/http""os""strings"
)type FocusController struct {BaseController
}func (con FocusController) Index(c *gin.Context) {//获取轮播图列表focusList := []models.Focus{}models.DB.Find(&focusList)c.HTML(http.StatusOK, "admin/focus/index.html", gin.H{"focusList": focusList,})
}func (con FocusController) Add(c *gin.Context) {c.HTML(http.StatusOK, "admin/focus/add.html", gin.H{})
}func (con FocusController) DoAdd(c *gin.Context) {//获取请求的表单数据title := strings.Trim(c.PostForm("title"), " ")focusType, err1 := models.Int(c.PostForm("focus_type"))link := strings.Trim(c.PostForm("link"), " ")sort, err2 := models.Int(c.PostForm("sort"))status, err3 := models.Int(c.PostForm("status"))if err1 != nil || err3 != nil {con.Error(c, "非法请求", "/admin/focus/add")return}if err2 != nil {con.Error(c, "请输入正确的排序值", "/admin/focus/add")return}//文件上传操作focusImgSrc, err := models.UploadImg(c, "focus_img")if err != nil {con.Error(c, "图片上传失败", "/admin/focus/add")return}//实例化focus模型focus := models.Focus{Title:     title,FocusType: focusType,FocusImg:  focusImgSrc,Link:      link,Sort:      sort,Status:    status,AddTime:   int(models.GetUnix()),}err = models.DB.Create(&focus).Errorif err != nil {con.Error(c, "增加轮播图失败", "/admin/focus/add")return}con.Success(c, "增加轮播图成功", "/admin/focus")
}func (con FocusController) Edit(c *gin.Context) {//获取要修改的轮播图idid, err := models.Int(c.Query("id"))if err != nil {con.Error(c, "传入数据错误", "/admin/focus")return}focus := models.Focus{Id: id}models.DB.Find(&focus)c.HTML(http.StatusOK, "admin/focus/edit.html", gin.H{"focus": focus,})
}func (con FocusController) DoEdit(c *gin.Context) {//获取请求的表单数据id, err := models.Int(c.PostForm("id"))title := strings.Trim(c.PostForm("title"), " ")focusType, err1 := models.Int(c.PostForm("focus_type"))link := strings.Trim(c.PostForm("link"), " ")sort, err2 := models.Int(c.PostForm("sort"))status, err3 := models.Int(c.PostForm("status"))if err != nil || err1 != nil || err3 != nil {con.Error(c, "非法请求", "/admin/focus")return}if err2 != nil {con.Error(c, "请输入正确的排序值", "/admin/focus/edit?id="+models.String(id))return}//文件上传操作focusImgSrc, err11 := models.UploadImg(c, "focus_img")if err11 != nil {con.Error(c, "图片上传失败", "/admin/focus/edit?id="+models.String(id))return}focus := models.Focus{Id: id}models.DB.Find(&focus)focus.Title = titlefocus.FocusType = focusTypefocus.Status = statusfocus.Sort = sortfocus.Link = linkif focusImgSrc != "" {focus.FocusImg = focusImgSrc}err4 := models.DB.Save(&focus).Errorif err4 != nil {con.Error(c, "修改轮播图失败", "/admin/focus/edit?id="+models.String(id))return}con.Success(c, "修改轮播图成功", "/admin/focus")}//删除
func (con FocusController) Delete(c *gin.Context) {//获取提交的表单数据id, err := models.Int(c.Query("id"))if err != nil {con.Error(c, "传入数据错误", "/admin/focus")return}//查询数据是否存在focus := models.Focus{Id: id}models.DB.Find(&focus)//需要对文件进行删除吗?if focus.FocusImg != "" {fmt.Println(focus.FocusImg)os.Remove(focus.FocusImg)}err = models.DB.Delete(&focus).Errorif err != nil {con.Error(c, "删除数据失败", "/admin/focus")return}con.Success(c, "删除数据成功", "/admin/focus")
}

3.创建轮播图html

在templates/admin/focus下创建轮播图相关html

index.html


{{ define "admin/focus/index.html" }}
{{ template "admin/public/page_header.html" .}}<div class="table-responsive"><table class="table table-bordered"><thead><tr class="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>{{range $key,$value := .focusList}}<tr><td>{{$value.Title}}</td><td>{{if eq $value.FocusType 1}}                    网站{{else if eq $value.FocusType 2}}APP{{else}}小程序{{end}}</td><td>{{if ne $value.FocusImg ""}}<img src="/{{$value.FocusImg}}" width="200"  />{{end}}</td><td>{{$value.Link}}</td><td class="text-center"><span class="chSpanNum"  data-id="{{$value.Id}}" data-table="focus" data-field="sort">{{$value.Sort}}</span></td><td align="center">{{if eq $value.Status 1}}<img class="chStatus" data-id="{{$value.Id}}" data-table="focus" data-field="status" src="/static/admin/images/yes.gif" />{{else}}<img class="chStatus" data-id="{{$value.Id}}" data-table="focus" data-field="status" src="/static/admin/images/no.gif" />{{end}}</td><td class="text-center"><a href="/admin/focus/edit?id={{$value.Id}}" />修改</a><a class="delete" href="/admin/focus/delete?id={{$value.Id}}" />删除</a></td></tr>{{end}}</tbody></table></div>
</body>
</html>
{{end}}

add.html

{{ define "admin/focus/add.html" }}
{{ template "admin/public/page_header.html" .}}<div class="panel panel-default"><div class="panel-heading">增加轮播图</div><div class="panel-body"><div class="table-responsive input-form"><form action="/admin/focus/doAdd" method="post" enctype="multipart/form-data"><ul><li>  名  称: <input type="text" name="title"/></li><li>  类  型: <select name="focus_type" id="type"><option value="1">网站</option><option value="2">APP</option><option value="3">小程序</option></select></li>                   <li>  跳转地址: <input type="text" name="link"/></li><li>  轮 播 图: <input type="file" name="focus_img"/></li>                            <li>  排  序: <input type="text" name="sort" value="100"/></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><br/><button type="submit" class="btn btn-primary">提交</button></li></ul></form></div></div>
</div>
</body>
</html>
{{end}}

edit.html

{{ define "admin/focus/edit.html" }}
{{ template "admin/public/page_header.html" .}}
<div class="panel panel-default"><div class="panel-heading">修改轮播图</div><div class="panel-body"><div class="table-responsive input-form"><form action="/admin/focus/doEdit" method="post" enctype="multipart/form-data"><input type="hidden" name="id" value="{{.focus.Id}}"/><ul><li>  名  称: <input type="text" name="title" value="{{.focus.Title}}"/></li><li>  类  型: <select name="focus_type" id="type"><option {{if eq .focus.FocusType 1}} selected {{end}} value="1">网站</option><option {{if eq .focus.FocusType 2}} selected {{end}} value="2">APP</option><option {{if eq .focus.FocusType 3}} selected {{end}} value="3">小程序</option></select></li>                   <li>  跳转地址: <input type="text" name="link"  value="{{.focus.Link}}"/></li><li>  轮 播 图: <input type="file" name="focus_img" />{{if ne .focus.FocusImg ""}}<img src="/{{.focus.FocusImg}}" width="200" />{{end}}</li>                            <li>  排  序: <input type="text" name="sort" value="{{.focus.Sort}}"/></li><li>  状  态: <input type="radio" name="status" {{if eq .focus.Status 1}} checked {{end}}  value="1" id="a"/> <label for="a">显示</label>    <input type="radio" name="status" {{if eq .focus.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>
</body>
</html>
{{end}}

4.配置路由

在routes/adminRouters.go下配置轮播图路由

package routersimport ("goshop/controllers/admin""goshop/middlewares""github.com/gin-gonic/gin"
)//设置admin后台路由
func AdminRoutersInit(r *gin.Engine) {//路由分组: 配置全局中间件:middlewares.InitMiddlewareadminRouters := r.Group("/admin", middlewares.InitAdminAuthMiddleware){//后台首页adminRouters.GET("/", admin.MainController{}.Index)adminRouters.GET("/welcome", admin.MainController{}.Welcome)//登录页面adminRouters.GET("/login", admin.LoginController{}.Index) // 实例化控制器,并访问其中方法adminRouters.POST("/doLogin", admin.LoginController{}.DoIndex)adminRouters.GET("/loginOut", admin.LoginController{}.LoginOut)//验证码adminRouters.GET("/captcha", admin.LoginController{}.Captcha)//管理员路由adminRouters.GET("/manager", admin.ManagerController{}.Index)adminRouters.GET("/manager/add", admin.ManagerController{}.Add)adminRouters.POST("/manager/doAdd", admin.ManagerController{}.DoAdd)adminRouters.GET("/manager/edit", admin.ManagerController{}.Edit)adminRouters.POST("/manager/doEdit", admin.ManagerController{}.DoEdit)adminRouters.GET("/manager/delete", admin.ManagerController{}.Delete)//轮播图路由adminRouters.GET("/focus", admin.FocusController{}.Index)adminRouters.GET("/focus/add", admin.FocusController{}.Add)adminRouters.POST("/focus/doAdd", admin.FocusController{}.DoAdd)adminRouters.GET("/focus/edit", admin.FocusController{}.Edit)adminRouters.POST("/focus/doEdit", admin.FocusController{}.DoEdit)adminRouters.GET("/focus/delete", admin.FocusController{}.Delete)//角色路由adminRouters.GET("/role", admin.RoleController{}.Index)adminRouters.GET("/role/add", admin.RoleController{}.Add)adminRouters.POST("/role/doAdd", admin.RoleController{}.DoAdd)adminRouters.GET("/role/edit", admin.RoleController{}.Edit)adminRouters.POST("/role/doEdit", admin.RoleController{}.DoEdit)adminRouters.GET("/role/delete", admin.RoleController{}.Delete)adminRouters.GET("/role/auth", admin.RoleController{}.Auth)adminRouters.POST("/role/doAuth", admin.RoleController{}.DoAuth)//权限路由adminRouters.GET("/access", admin.AccessController{}.Index)adminRouters.GET("/access/add", admin.AccessController{}.Add)adminRouters.POST("/access/doAdd", admin.AccessController{}.DoAdd)adminRouters.GET("/access/edit", admin.AccessController{}.Edit)adminRouters.POST("/access/doEdit", admin.AccessController{}.DoEdit)adminRouters.GET("/access/delete", admin.AccessController{}.Delete)}
}

5.界面展示如下

列表

[golang gin框架] 15.Gin 商城项目-封装上传图片方法,轮播图的增删改查以及异步修改状态,数量

新增

[golang gin框架] 15.Gin 商城项目-封装上传图片方法,轮播图的增删改查以及异步修改状态,数量

编辑

[golang gin框架] 15.Gin 商城项目-封装上传图片方法,轮播图的增删改查以及异步修改状态,数量

删除

[golang gin框架] 15.Gin 商城项目-封装上传图片方法,轮播图的增删改查以及异步修改状态,数量

三.封装公共Api接口

封装公共Api接口,实现公共的ajax: 异步修改状态, 异步修改排序
以轮播图为例:
当点击状态图标时,修改状态图标(正常/失效)
当点击排序栏时,生成焦点文本框,输入排序数字,鼠标点击其他地方,失去焦点时,发送请求,修改排序

  1. index.html页面修改排序,状态相关代码


{{ define "admin/focus/index.html" }}
{{ template "admin/public/page_header.html" .}}<div class="table-responsive"><table class="table table-bordered"><thead><tr class="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>{{range $key,$value := .focusList}}<tr><td>{{$value.Title}}</td><td>{{if eq $value.FocusType 1}}                    网站{{else if eq $value.FocusType 2}}APP{{else}}小程序{{end}}</td><td>{{if ne $value.FocusImg ""}}<img src="/{{$value.FocusImg}}" width="200"  />{{end}}</td><td>{{$value.Link}}</td><td class="text-center"><!-- 排序 --><span class="chSpanNum"  data-id="{{$value.Id}}" data-table="focus" data-field="sort">{{$value.Sort}}</span></td><td align="center"><!-- 状态 -->{{if eq $value.Status 1}}<img class="chStatus" data-id="{{$value.Id}}" data-table="focus" data-field="status" src="/static/admin/images/yes.gif" />{{else}}<img class="chStatus" data-id="{{$value.Id}}" data-table="focus" data-field="status" src="/static/admin/images/no.gif" />{{end}}</td><td class="text-center"><a href="/admin/focus/edit?id={{$value.Id}}" />修改</a><a class="delete" href="/admin/focus/delete?id={{$value.Id}}" />删除</a></td></tr>{{end}}</tbody></table></div>
</body>
</html>
{{end}}
  1. static/admin/js/base.js增加修改排序,状态的方法

$(function () {baseApp.init();//当窗口重置时,重新计算窗口高度$(window).resize(function () {baseApp.resizeIframe();})
})var baseApp = {init: function () {this.initAside()this.confirmDelete()this.resizeIframe()this.changeStatus()this.changeNum()},initAside: function () { //左侧菜单栏隐藏显示子栏$(".aside h4").click(function () {$(this).sibling("ul").slideToggle();})},resizeIframe: function() {  // 设置iframe高度$("rightMain").height($(window).height()-80)},confirmDelete: function () { // 删除提示$(".delete").click(function () {var flag = confirm("确定要删除该项?")return flag})},changeStatus: function () { // 改变状态//点击事件$(".chStatus").click(function () {var $this = $(this);var id = $this.attr("data-id");var table = $this.attr("data-table");var field = $this.attr("data-field");console.log(field);$.get("/admin/changeStatus", {id: id, table: table, field: field}, function (res) {if (res.success) {if ($this.attr("src").indexOf("yes") != -1){$this.attr("src", "/static/admin/images/no.gif");} else {$this.attr("src", "/static/admin/images/yes.gif");}} else {alert(res.message);}})})},changeNum: function () {  // 修改排序数字/*1、获取el里面的值  var spanNum=$(this).html()2、创建一个input的dom节点   var input=$("<input value='' />");3、把input放在el里面   $(this).html(input);4、让input获取焦点  给input赋值    $(input).trigger('focus').val(val);5、点击input的时候阻止冒泡$(input).click(function(e){e.stopPropagation();})6、鼠标离开的时候给span赋值,并触发ajax请求$(input).blur(function(){var inputNum=$(this).val();spanEl.html(inputNum);触发ajax请求})*/$(".chSpanNum").click(function () {// 1、获取el 以及el里面的属性值var id = $(this).attr("data-id")var table = $(this).attr("data-table")var field = $(this).attr("data-field")var num = $(this).html().trim()var spanEl = $(this)//2、创建一个input的dom节点   var input=$("<input value='' />");var input = $("<input style='width:60px'  value='' />");// 3、把input放在el里面   $(this).html(input);$(this).html(input);//4、让input获取焦点  给input赋值    $(input).trigger('focus').val(val);$(input).trigger("focus").val(num);//5、点击input的时候阻止冒泡$(input).click(function (e) {e.stopPropagation();})//6、鼠标离开的时候给span赋值,并触发ajax请求$(input).blur(function () {var inputNum = $(this).val()spanEl.html(inputNum)//触发ajax请求$.get("/admin/changeNum", { id: id, table: table, field: field, num: inputNum }, function (response) {if (response.success) {alert(response.message)} else {alert(response.message)}})})})}
}
  1. 封装公共api接口方法

在controllers/MainController.go文件中封装公共方法:改变状态,改变排序

//公共方法:改变表状态的
func (con MainController) ChangeStatus(c *gin.Context) {id, err := models.Int(c.Query("id"))if err != nil {c.JSON(http.StatusOK, gin.H{"success": false,"message": "id参数错误",})return}table := c.Query("table")field := c.Query("field")//修改err1 := models.DB.Exec("update "+ table +" set " + field + " = ABS(" + field + " - 1) where id = ?", id).Errorif err1 != nil {c.JSON(http.StatusOK, gin.H{"success": false,"message": "修改失败,请重试",})return}c.JSON(http.StatusOK, gin.H{"success": true,"message": "操作成功",})
}//公共方法:改变排序数字
func (con MainController) ChangeNum(c *gin.Context) {id, err := models.Int(c.Query("id"))if err != nil {c.JSON(http.StatusOK, gin.H{"success": false,"message": "id参数错误",})return}table := c.Query("table")field := c.Query("field")num := c.Query("num")//修改err1 := models.DB.Exec("update "+ table +" set " + field + " = " + num + " where id = ?", id).Errorif err1 != nil {c.JSON(http.StatusOK, gin.H{"success": false,"message": "修改失败,请重试",})return}c.JSON(http.StatusOK, gin.H{"success": true,"message": "操作成功",})
}

4.配置路由

在routers/adminRouters.go中配置修改状态以及修改排序的路由

adminRouters.GET("/changeStatus", admin.MainController{}.ChangeStatus)
adminRouters.GET("/changeNum", admin.MainController{}.ChangeNum)

[上一节][golang gin框架] 14.Gin 商城项目-RBAC管理