「这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战」
前言
前一篇文章做了一个根据分类筛选导航域名详情的列表展示,今天难度进一步加大,做一个可以分类下域名详情的删改查,重点是要在Element-UI的Dialog 对话框中加上一个选择框。
前端部分
今天前端和后端代码都一样多,代码太多了只展示添加的部分,不展示整个页面了。首先是需要在列表页增加更仔细的信息:
增加table列
分类和url,需要增加两个
el-table-column,lable就是列的名字,前面几篇就说过插槽了,这里不复述了。
<el-table-column label="分类ID">
<template slot-scope="scope">
{{ scope.row.TypeID }}
</template>
</el-table-column>
<el-table-column label="Url">
<template slot-scope="scope">
{{ scope.row.URL }}
</template>
</el-table-column>
增加两个对话框
<!-- 添加导航网址 -->
<el-dialog title="添加导航url" :visible.sync="formAddVisible" width="450px" center>
<el-form ref="addform" :inline="true">
<el-form-item label="选择分类">
<el-select v-model="add_type" placeholder="请选择类型" style="max-width:140px">
<el-option v-for="item in typelist" :key="item.ID" :value="item.ID" :label="item.Name" />
</el-select>
</el-form-item>
<el-form-item label="输入名称">
<el-input v-model="addForm.name" placeholder="请输入导航名称" />
</el-form-item>
<el-form-item label="输入域名">
<el-input v-model="addForm.url" placeholder="请输入导航url" />
</el-form-item>
</el-form>
<el-button native-type="primary" @click="onSubmitAdd">确认添加</el-button>
</el-dialog>
<!-- 修改导航url -->
<el-dialog title="编辑导航url" :visible.sync="formEditVisible" width="450px" center>
<el-form ref="addform" :inline="true">
<el-form-item label="选择分类">
<el-select v-model="edit_type" placeholder="请选择类型" style="max-width:140px">
<el-option v-for="item in typelist" :key="item.ID" :value="item.ID" :label="item.Name" />
</el-select>
</el-form-item>
<el-form-item label="输入名称">
<el-input v-model="editForm.name" placeholder="请输入导航名称" />
</el-form-item>
<el-form-item label="输入域名">
<el-input v-model="editForm.url" placeholder="请输入导航url" />
</el-form-item>
</el-form>
<el-button native-type="primary" @click="onSubmitEdit">确认修改</el-button>
</el-dialog>
效果如图:
原生的还是挺好看的。我在每个对话框中的
el-form中增加了一个:inline="true"属性,使input和它的说明的label显示在了同一行,但是提交的button为了不让它跟最后一个表格输入框在一行我把它 放在了form的外面。
然后使用了双向绑定,点击编辑的时候会把点击的那一列的数据渲染在对话框中:
bindEdit(data) {
this.editForm.id = data.ID
this.editForm.name = data.Name
this.editForm.url = data.URL
this.editForm.type_id = data.TypeID
this.edit_type = data.TypeID
this.formEditVisible = true
},
最重要的使会把那一列数据的type_id记下来去回显到单选框。而且跟另外一个单选框独立,更改数据时的分类单选框和添加分类单选框互相独立,添加分类单选框打开永远是全部,全部传递给后端的type_id就是0然后会报错,直到选择了有值的分类id。这里需要注意的是所有使用到了变量数据都需要在vue对象中data属性中定义,所以为了实现这些功能在data中定义了很多变量:
data() {
return {
add_type: '全部',
edit_type: '',
typelist: [],
list: [],
type: 0,
formAddVisible: false,
formEditVisible: false,
addForm: {
type_id: 0,
name: '',
url: ''
},
editForm: {
id: 0,
type_id: 0,
name: '',
url: ''
}
}
},
数据监听
watch: {
type(val) {
this.fetchData()
},
add_type(val) {
this.addForm.type_id = val
}
},
监听了两个变量,第一个是上篇文章的根据单选框选择重新渲染带条件的列表。第二个实现的是添加详情数据时选择分类更改type_id提供给提交表单时使用,所以这里在添加数据方法的时候获取的type_id是从数据监听这里获取的,并没有从单选框获取:
onSubmitEdit() {
editUrl({
id: this.editForm.id,
type_id: this.edit_type,
name: this.editForm.name,
url: this.editForm.url
}).then(res => {
this.$message({
type: 'success',
message: '修改成功'
})
this.fetchData()
this.formEditVisible = false
})
}
后端
简单讲一讲,不亮出全部的代码了,路由器添加了3行代码,分别是删除详情,增加详情,修改详情
admin.POST("/DelUrl", controller.DelUrl)
admin.POST("/AddUrl", controller.AddUrl)
admin.POST("/EditUrl", controller.EditUrl)
验证器这里都需要传值,而且字段都是必须的:
type DelUrlRequest struct {
Id int `form:"id" json:"id" binding:"required"`
}
type AddUrlRequest struct {
Name string `form:"name" json:"name" binding:"required"`
TypeID int `form:"type_id" json:"type_id" binding:"required"`
Url string `form:"url" json:"url" binding:"required"`
}
type EditUrlRequest struct {
Id int `form:"id" json:"id" binding:"required"`
Name string `form:"name" json:"name" binding:"required"`
TypeID int `form:"type_id" json:"type_id" binding:"required"`
Url string `form:"url" json:"url" binding:"required"`
}
控制器加了三个方法,使用的验证器删除的验证器可以使用删除分类的验证器,但是为了规范还是没有偷懒:
func DelUrl(c *gin.Context) {
var json request.DelUrlRequest
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result := global.NewResult(c)
err := service.DelUrl(json)
if err != nil {
result.Error(5201, err.Error(), "删除失败")
return
}
result.Success("删除成功")
}
func AddUrl(c *gin.Context) {
var json request.AddUrlRequest
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result := global.NewResult(c)
id, err := service.AddUrl(json)
if err != nil {
result.Error(5201, err.Error(), "域名获取失败")
return
}
result.Success(id)
}
func EditUrl(c *gin.Context) {
var json request.EditUrlRequest
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result := global.NewResult(c)
err := service.EditUrl(json)
if err != nil {
result.Error(5201, err.Error(), "域名修改失败")
return
}
result.Success("域名修改成功")
}
服务方法,需要根据ORM方法需要的数据按照顺序传入,不然就会混乱,而且需要根据控制器曾需要的内容返回,有的传新增数据的ID,有的只需要传是否报错:
func DelUrl(json request.DelUrlRequest) (err error) {
nil := model.DelUrl(json.Id)
return nil
}
func AddUrl(json request.AddUrlRequest) (id int, err error) {
id, nil := model.AddUrl(json.Name, json.Url, json.TypeID)
return id, nil
}
func EditUrl(json request.EditUrlRequest) (err error) {
nil := model.EditUrl(json.Id, json.TypeID, json.Name, json.Url)
return nil
}
最后model层,注意替换模型对象和字段内容,删除是最简单的:
//删除一个详情
func DelUrl(id int) error {
return db.Delete(&UrlList{}, id).Error
}
//增加一个详情
func AddUrl(name string, url string, type_id int) (id int, err error) {
ListData := UrlList{
Name: name,
TypeID: type_id,
URL: url,
}
err = db.Debug().Create(&ListData).Error
return int(ListData.ID), err
}
//修改一个详情
func EditUrl(id int, type_id int, name string, url string) error {
return db.Debug().Model(&UrlList{}).Where("id = ?", id).Updates(map[string]interface{}{
"TypeID": type_id,
"Name": name,
"Url": url,
}).Error
}
总结
今天这篇文章我认为重难点就是单选框的数据回显控制,最开始是让两个对话框中的单选框互相影响了,感觉体验很差,最后多定义了一些变量,加上变量监控才解决了这个问题。还是小小的绕了一个弯,在其中还是感觉到了VUE的强大之处,所有的数据都是放在Vue对象中,是真实存在并随时都可以调用操作的,非常方便,在jQuery中对一些概念封装很模糊,通常都是写很多方法操作数据,然后要实现一些稍微复杂的功能导致方法会写的很长,最终导致逻辑混乱,不知道哪里操作了数据~
下篇准备完善用户登录,让它更像完整的商业项目。