TODO清单小项目
后端部分
main.go
package main
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type Info struct {
ID uint `gorm:"primarykey" json:"id" `
Content string `form:"content" json:"content" binding:"required" `
OK bool `form:"ok" json:"ok" gorm:"default:true"`
}
var DB *gorm.DB
func initDB() {
dsn := "root:123456@tcp(127.0.0.1:3306)/go7?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn))
if err != nil {
panic(err)
}
DB = db
DB.AutoMigrate(&Info{})
}
func main() {
initDB()
ct := gin.Default()
ct.LoadHTMLFiles("./index.tmpl", "./404.html")
ct.GET("/index", func(c *gin.Context) {
var list []Info
DB.Find(&list)
c.HTML(http.StatusOK, "index.tmpl", gin.H{
"list": list,
})
})
ct.POST("/index", func(c *gin.Context) {
var newinfo Info
if err := c.ShouldBind(&newinfo); err != nil {
c.Redirect(http.StatusFound, "/index")
return
}
DB.Create(&newinfo)
c.Redirect(http.StatusFound, "/index")
})
ct.PUT("/index/:id", func(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var info Info
DB.Where("id=?", id).Find(&info)
info.OK = !info.OK
DB.Save(&info)
c.JSON(http.StatusOK, gin.H{
"status": "ok",
})
})
ct.DELETE("/index/:id", func(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
DB.Delete(&Info{}, id)
c.JSON(http.StatusOK, gin.H{
"status": "ok",
})
})
ct.NoRoute(func(c *gin.Context) {
c.HTML(http.StatusNotFound, "404.html", nil)
})
ct.Run()
}
前端部分
<!DOCTYPE html>
<html>
<head>
<title>Todo小项目</title>
</head>
<body>
<h1>Todo清单</h1>
<ul>
{{range .list}}
<li>
<span>{{.Content}}</span>
<span>{{.OK}}</span>
<button onclick="change({{.ID}})">切换</button>
<button onclick="del({{.ID}})">删除</button>
</li>
{{end}}
</ul>
<hr>
<form action="/index" method="post">
<label for ="todo">要做的事情:</label>
<input type="text" id="todo" name="content" required>
<button type ="submit">提交</button>
</form>
</body>
</html>
<script>
async function change(id) {
try {
const response = await fetch(`/index/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json"
}
});
if (response.ok) {
window.location.reload();
} else {
alert("切换失败,服务器返回错误");
}
} catch (error) {
console.error("请求发生错误:", error);
alert("网络连接失败");
}
}
async function del(id){
try{
const response = await fetch(`/index/${id}`, {
method: "DELETE",
headers: {
"Content-Type": "application/json"
}
});
if (response.ok) {
window.location.reload();
} else {
alert("切换失败,服务器返回错误");
}
}catch(error){
alert("网络连接失败");
}
}
</script>
结果:
![[/images/e16878cc3af2d99f2e3bb606b62e731b.png]]
- 模型定义: 每一个待办事情都有一个独立的id,内容,判断是否做完的变量
- GET: 发送查看待办事项列表的请求,查询数据库并通过template返回给前端
- POST: 通过form表单形式得到待办事项内容,插入数据库,并重定向至GET页面
- PUT: 通过button调用异步函数change(id),后端根据前端的fetch(/index/${id})请求拿到id并修改,返回给前端状态码,前端刷新页面
- DELETE: 与PUT原理相同