编辑新增等功能
使用ant-design的组件,关于引入和使用就不说了,把UserList.vue完整的代码放出来供大家参考,一些必要的地方也已经写好了注释,大部分代码都是重复的。和之前的有些许改变。后台也可以按照自己喜欢的风格来做。
<template>
<div>
<a-card>
<a-row :gutter="20">
<a-col :span="6">
<a-input-search
v-model="queryParam.username"
allowClear placeholder="请输入用户名"
enter-button
@search="getUserList" />
</a-col>
<a-col :span="4">
<a-button type="primary" @click="AddUserVisible = true">新增</a-button>
</a-col>
</a-row>
<a-table
:columns='columns'
rowKey='ID'
:pagination="pagination"
:dataSource="userlist"
bordered
@change="handleTableChange"
>
<span slot="role" slot-scope="role">{{role == 1 ? "管理员":"订阅者"}}</span>
<template slot="action" slot-scope="data">
<div class="actionSlot">
<a-button type="info" icon="info" style="margin-right:15px" @click="ChangePassword(data.ID)">修改密码</a-button>
<a-button type="primary" icon="edit" style="margin-right:15px" @click="editUser(data.ID)">编辑</a-button>
<a-popconfirm title="确认删除?删除后无法恢复" ok-text="确认" cancel-text="取消" @confirm="delUser(data.ID)">
<a-button icon="delete" type="danger">删除</a-button>
</a-popconfirm>
</div>
</template>
</a-table>
</a-card>
<!-- 新增用户对话框 -->
<a-modal
title="新增用户"
:visible="AddUserVisible"
@ok="AddUserOk"
@cancel="addUserCanal"
closable
>
<a-form-model :model="userinfo" :rules="userRules" ref="addUserRef">
<a-form-model-item label="用户名" prop="username">
<a-input v-model="userinfo.username"></a-input>
</a-form-model-item>
<a-form-model-item label="密码" prop="password">
<a-input-password v-model="userinfo.password">
</a-input-password>
</a-form-model-item>
<a-form-model-item label="确认密码" prop="checkpass">
<a-input-password v-model="userinfo.checkpass">
</a-input-password>
</a-form-model-item>
</a-form-model>
</a-modal>
<!-- 编辑用户 -->
<a-modal
title="编辑用户"
:visible="editUserVisible"
@ok="editUserOk"
width="60%"
@cancel="editUserCanal"
closable
>
<a-form-model :model="userinfo" :rules="userRules" ref="addUserRef">
<a-form-model-item label="用户名" prop="username">
<a-input v-model="userinfo.username"></a-input>
</a-form-model-item>
<a-form-model-item label="是否为管理员">
<a-switch
:checked="IsAdmin"
checked-children="是"
un-checked-children="否"
@change="adminChange"
/>
</a-form-model-item>
</a-form-model>
</a-modal>
<!-- 编辑密码 -->
<a-modal
closable
title="修改密码"
:visible="changePasswordVisible"
width="60%"
@ok="changePasswordOk"
@cancel="changePasswordCancel"
destroyOnClose
>
<a-form-model :model="userinfo" :rules="userRules" ref="addUserRef">
<a-form-model-item has-feedback label="密码" prop="password">
<a-input-password v-model="userinfo.password"></a-input-password>
</a-form-model-item>
<a-form-model-item has-feedback label="确认密码" prop="checkpass">
<a-input-password v-model="userinfo.checkpass"></a-input-password>
</a-form-model-item>
</a-form-model>
</a-modal>
</div>
</template>
<script>
const columns = [
{
title: 'ID',
dataIndex: 'ID',
key: 'id',
width: '10%',
align:'center'
},
{
title: '用户名',
dataIndex: 'username',
key: 'username',
width: '20%',
align:'center'
},
{
title: '角色',
dataIndex: 'role',
key: 'role',
width: '20%',
scopedSlots:{customRender:'role'},
align:'center'
},
{
title: '操作',
key: 'action',
width: '30%',
scopedSlots:{customRender:'action'},
align:'center'
},
]
export default {
data(){
return{
columns,
changePasswordVisible: false,
// 分页
pagination: {
pageSizeOptions: ['5', '10', '20'],
pageSize: 5,
total: 0,
showSizeChanger: true,
showTotal: (total) => `共${total}条`,
},
queryParam: {
username:'',
pagesize: 5,
pagenum: 1,
},
userlist:[],
AddUserVisible:false,
editUserVisible:false,
userinfo:{
id:0,
username:'',
password:'',
checkpass:'',
role:2
},
userRules:{
username: [
{
validator: (rule, value, callback) => {
if (this.userinfo.username == '') {
callback(new Error('请输入用户名'))
}
if ([...this.userinfo.username].length < 4 || [...this.userinfo.username].length > 12) {
callback(new Error('用户名应当在4到12个字符之间'))
} else {
callback()
}
},
trigger: 'blur',
},
],
password: [
{
validator: (rule, value, callback) => {
if (this.userinfo.password == '') {
callback(new Error('请输入密码'))
}
if ([...this.userinfo.password].length < 6 || [...this.userinfo.password].length > 20) {
callback(new Error('密码应当在6到20位之间'))
} else {
callback()
}
},
trigger: 'blur',
},
],
checkpass: [
{
validator: (rule, value, callback) => {
if (this.userinfo.checkpass == '') {
callback(new Error('请输入密码'))
}
if (this.userinfo.password !== this.userinfo.checkpass) {
callback(new Error('密码不一致,请重新输入'))
} else {
callback()
}
},
trigger: 'blur',
},
],
},
}
},
created(){
this.getUserList()
},
computed: {
// 加载前布尔判断
IsAdmin: function () {
if (this.userinfo.role === 1) {
return true
} else {
return false
}
}
},
methods:{
// 查询用户
async getUserList(){
const { data:res } = await this.$http.get('api/v1/user/', {
params:{
username: this.queryParam.username,
size: this.queryParam.pagesize,
page: this.queryParam.pagenum,
},
})
if(res.code != 200)return this.$message.error(res.msg)
this.userlist = res.data
this.pagination.total = res.total
},
// 分页
handleTableChange(pagination, filters, sorter) {
var pager = { ...this.pagination }
pager.current = pagination.current
pager.pageSize = pagination.pageSize
this.queryParam.pagesize = pagination.pageSize
this.queryParam.pagenum = pagination.current
if (pagination.pageSize !== this.pagination.pageSize) {
this.queryParam.pagenum = 1
pager.current = 1
}
this.pagination = pager
this.getUserList()
},
// 删除用户
async delUser(id){
const { data: res } = await this.$http.delete(`api/admin/user/${id}/`)
if(res.code != 200)return this.$message.error(res.msg)
this.queryParam.pagenum = 1
this.$message.success('删除成功')
this.getUserList()
},
AddUserOk(){
this.$refs.addUserRef.validate(async (vaild)=>{
if(!vaild)return this.$message.error("格式不正确")
const { data: res } = await this.$http.post("api/v1/user/",{
"username":this.userinfo.username,
"password":this.userinfo.password,
"role": this.userinfo.role,
})
if (res.code != 200) return this.$message.error(res.msg)
// 清空搜索框
this.$refs.addUserRef.resetFields()
// 关闭弹窗
this.AddUserVisible = false
this.$message.success('添加用户成功')
this.getUserList()
})
},
// role布尔值判断
adminChange(checked){
if (checked) {
this.userinfo.role = 1
} else {
this.userinfo.role = 2
}
},
// 取消的方法
addUserCanal(){
this.$refs.addUserRef.resetFields()
this.AddUserVisible = false
},
// 编辑框获取用户信息
async editUser(id){
this.editUserVisible = true
const {data: res } = await this.$http.get(`/api/v1/user/${id}/`)
this.userinfo = res.data
this.userinfo.id = id
},
// 编辑用户
editUserOk(){
this.$refs.addUserRef.validate(async (vaild)=>{
if(!vaild)return this.$message.error("格式不正确")
const { data: res } = await this.$http.put(`/api/admin/user/${this.userinfo.id}/`,{
"username":this.userinfo.username,
"role": this.userinfo.role,
})
if (res.code != 200) return this.$message.error(res.msg)
// 清空搜索框
this.$refs.addUserRef.resetFields()
// 关闭弹窗
this.editUserVisible = false
this.$message.success('编辑用户成功')
this.getUserList()
})
},
// 取消编辑销毁数据
editUserCanal(){
this.$refs.addUserRef.resetFields()
this.editUserVisible = false
},
// 修改密码获取信息
ChangePassword(id){
this.changePasswordVisible = true
this.userinfo.id = id
},
// 修改密码
changePasswordOk() {
this.$refs.addUserRef.validate(async (valid) => {
if (!valid) return this.$message.error('参数不符合要求,请重新输入')
const { data: res } = await this.$http.put(`/api/admin/editpass/${this.userinfo.id}/`,{
"password":this.userinfo.password
})
if (res.code != 200) return this.$message.error(res.msg)
this.changePasswordVisible = false
this.$message.success('修改密码成功')
this.getUserList()
})
},
// 修改密码取消
changePasswordCancel() {
this.$refs.addUserRef.resetFields()
this.changePasswordVisible = false
this.$message.info('已取消')
},
}
}
</script>
<style>
.actionSlot{
display: flex;
justify-content: center;
}
</style>
分类和文章列表页
CV大法好,只是在后端新增了一个搜索文章的功能。和搜索用户也是一样的啦。
model/Article.go
// SearchArticle 搜索文章标题
func SearchArticle(title string, pageSize int, pageNum int) ([]Article, int, int64) {
var articleList []Article
var err error
var total int64
err = Db.Select("article.id,title, img, created_at, updated_at, `desc`, comment_count, read_count, category.name").Limit(pageSize).Offset((pageNum-1)*pageSize).Order("Created_At DESC").Joins("Category").Where("title LIKE ?",
title+"%",
).Find(&articleList).Error
// 单独计数
Db.Model(&articleList).Count(&total)
if err != nil {
return nil, errmsg.ERROR, 0
}
return articleList, errmsg.SUCCSE, total
}
/api/v1/article.go
// 查询文章列表
func GetArticles(c *gin.Context) {
// 字符串转int
Size,_ := strconv.Atoi(c.DefaultQuery("size","3"))
Page,_ := strconv.Atoi(c.DefaultQuery("page","1"))
title := c.Query("title")
if len(title) == 0 {
data, code, total := model.GetArticles(Size, Page)
c.JSON(http.StatusOK, gin.H{
"code": code,
"msg": errmsg.GetErrorMsg(code),
"data": data,
"total": total,
})
return
}
data, code, total := model.SearchArticle(title,Size,Page)
c.JSON(http.StatusOK, gin.H{
"code": code,
"data": data,
"total": total,
"msg": errmsg.GetErrorMsg(code),
})
}
前端页面也放一下代码,闭着眼复制就可以了。
components/article/ArtList.vue
<template>
<div>
<a-card>
<a-row :gutter="20">
<a-col :span="6">
<a-input-search
v-model="queryParam.title"
placeholder="输入文章名查找"
enter-button
allowClear
@search="getArtList"
/>
</a-col>
<a-col :span="4">
<a-button type="primary" @click="$router.push('addart')">新增</a-button>
</a-col>
<a-col :span="3">
<a-select placeholder="请选择分类" style="width: 200px" @change="CateChange">
<a-select-option
v-for="item in Catelist"
:key="item.id"
:value="item.id"
>{{ item.name }}</a-select-option>
</a-select>
</a-col>
<a-col :span="1">
<a-button type="info" @click="getArtList()">显示全部</a-button>
</a-col>
</a-row>
<a-table
rowKey="ID"
:columns="columns"
:pagination="pagination"
:dataSource="Artlist"
bordered
@change="handleTableChange"
>
<span class="ArtImg" slot="img" slot-scope="img">
<img :src="img" />
</span>
<template slot="action" slot-scope="data">
<div class="actionSlot">
<a-button
size="small"
type="primary"
icon="edit"
style="margin-right: 15px"
@click="$router.push(`addart/${data.ID}`)"
>编辑</a-button>
<a-popconfirm title="确认删除?删除后无法恢复" ok-text="确认" cancel-text="取消" @confirm="deleteArt(data.ID)">
<a-button icon="delete" size="small" type="danger">删除</a-button>
</a-popconfirm>
</div>
</template>
</a-table>
</a-card>
</div>
</template>
<script>
import day from 'dayjs'
const columns = [
{
title: 'ID',
dataIndex: 'ID',
width: '5%',
key: 'id',
align: 'center',
},
{
title: '更新日期',
dataIndex: 'UpdatedAt',
width: '10%',
key: 'UpdatedAt',
align: 'center',
customRender: (val) => {
return val ? day(val).format('YYYY年MM月DD日 HH:mm') : '暂无'
},
},
{
title: '分类',
dataIndex: 'Category.name',
width: '5%',
key: 'name',
align: 'center',
},
{
title: '文章标题',
dataIndex: 'title',
width: '15%',
key: 'title',
align: 'center',
},
{
title: '文章描述',
dataIndex: 'desc',
width: '20%',
key: 'desc',
align: 'center',
},
{
title: '缩略图',
dataIndex: 'img',
width: '20%',
key: 'img',
align: 'center',
scopedSlots: { customRender: 'img' },
},
{
title: '操作',
width: '15%',
key: 'action',
align: 'center',
scopedSlots: { customRender: 'action' },
},
]
export default {
data() {
return {
pagination: {
pageSizeOptions: ['5', '10', '20'],
pageSize: 5,
total: 0,
showSizeChanger: true,
showTotal: (total) => `共${total}条`,
},
Artlist: [],
Catelist: [],
columns,
queryParam: {
title: '',
pagesize: 5,
pagenum: 1,
},
}
},
created() {
this.getCateList()
this.getArtList()
},
methods: {
// 获取文章列表
async getArtList() {
const { data: res } = await this.$http.get('api/v1/article/', {
params: {
title: this.queryParam.title,
size: this.queryParam.pagesize,
page: this.queryParam.pagenum,
},
})
if (res.code !== 200) {
if (res.code === 1004 || 1005 || 1006 || 1007) {
window.sessionStorage.clear()
this.$router.push('/login')
}
this.$message.error(res.message)
}
this.Artlist = res.data
this.pagination.total = res.total
},
// 获取分类
async getCateList() {
const { data: res } = await this.$http.get('api/v1/category/',{params: {
size: 100,
page: 1,
},})
if (res.code !== 200) return this.$message.error(res.msg)
this.Catelist = res.data
this.pagination.total = res.total
},
// 更改分页
handleTableChange(pagination, filters, sorter) {
var pager = { ...this.pagination }
pager.current = pagination.current
pager.pageSize = pagination.pageSize
this.queryParam.pagesize = pagination.pageSize
this.queryParam.pagenum = pagination.current
if (pagination.pageSize !== this.pagination.pageSize) {
this.queryParam.pagenum = 1
pager.current = 1
}
this.pagination = pager
this.getArtList()
},
// 删除文章
async deleteArt(id) {
const { data: res } = await this.$http.delete(`api/admin/article/${id}/`)
if (res.code != 200) return this.$message.error(res.msg)
this.$message.success('删除成功')
this.queryParam.pagenum = 1
this.getArtList()
},
// 查询分类下的文章
CateChange(value) {
this.getCateArt(value)
},
async getCateArt(id) {
const { data: res } = await this.$http.get(`api/v1/catelist/${id}/`, {
params: { size: this.queryParam.pagesize, page: this.queryParam.pagenum },
})
if (res.code !== 200) return this.$message.error(res.msg)
this.Artlist = res.data
this.pagination.total = res.total
},
},
}
</script>
<style scoped>
.actionSlot {
display: flex;
justify-content: center;
}
.ArtImg {
height: 100%;
width: 100%;
}
.ArtImg img {
width: 100px;
height: 80px;
}
</style>
components/category/CateList.vue
<template>
<div>
<a-card>
<a-row :gutter="20">
<a-col :span="4">
<a-button type="primary" @click="AddcateVisible = true">新增分类</a-button>
</a-col>
</a-row>
<a-table
:columns='columns'
rowKey='id'
:pagination="pagination"
:dataSource="catelist"
bordered
@change="handleTableChange"
>
<template slot="action" slot-scope="data">
<div class="actionSlot">
<a-button type="primary" icon="edit" style="margin-right:15px" @click="editcate(data.id)">编辑</a-button>
<a-popconfirm title="确认删除?删除后无法恢复" ok-text="确认" cancel-text="取消" @confirm="delcate(data.id)">
<a-button icon="delete" type="danger">删除</a-button>
</a-popconfirm>
</div>
</template>
</a-table>
</a-card>
<!-- 新增分类对话框 -->
<a-modal
title="新增分类"
:visible="AddcateVisible"
@ok="AddcateOk"
@cancel="addcateCanal"
closable
>
<a-form-model :model="cateinfo" ref="addcateRef">
<a-form-model-item label="分类名" prop="name">
<a-input v-model="cateinfo.name"></a-input>
</a-form-model-item>
</a-form-model>
</a-modal>
<!-- 编辑分类 -->
<a-modal
title="编辑分类"
:visible="editcateVisible"
@ok="editcateOk"
width="60%"
@cancel="editcateCanal"
closable
>
<a-form-model :model="cateinfo" ref="addcateRef">
<a-form-model-item label="分类名" prop="name">
<a-input v-model="cateinfo.name"></a-input>
</a-form-model-item>
</a-form-model>
</a-modal>
</div>
</template>
<script>
const columns = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: '10%',
align:'center'
},
{
title: '分类名',
dataIndex: 'name',
key: 'name',
width: '20%',
align:'center'
},
{
title: '操作',
key: 'action',
width: '30%',
scopedSlots:{customRender:'action'},
align:'center'
},
]
export default {
data(){
return{
columns,
changePasswordVisible: false,
// 分页
pagination: {
pageSizeOptions: ['5', '10', '20'],
pageSize: 5,
total: 0,
showSizeChanger: true,
showTotal: (total) => `共${total}条`,
},
queryParam: {
name:'',
pagesize: 5,
pagenum: 1,
},
catelist:[],
AddcateVisible:false,
editcateVisible:false,
cateinfo:{
id:0,
name:'',
},
}
},
created(){
this.getcateList()
},
methods:{
// 查询分类
async getcateList(){
const { data:res } = await this.$http.get('api/v1/category/', {
params:{
size: this.queryParam.pagesize,
page: this.queryParam.pagenum,
},
})
if(res.code != 200)return this.$message.error(res.msg)
this.catelist = res.data
this.pagination.total = res.total
},
// 分页
handleTableChange(pagination, filters, sorter) {
var pager = { ...this.pagination }
pager.current = pagination.current
pager.pageSize = pagination.pageSize
this.queryParam.pagesize = pagination.pageSize
this.queryParam.pagenum = pagination.current
if (pagination.pageSize !== this.pagination.pageSize) {
this.queryParam.pagenum = 1
pager.current = 1
}
this.pagination = pager
this.getcateList()
},
// 删除分类
async delcate(id){
const { data: res } = await this.$http.delete(`api/admin/category/${id}/`)
if(res.code != 200)return this.$message.error(res.msg)
this.$message.success('删除成功')
this.queryParam.pagenum = 1
this.getcateList()
},
async AddcateOk(){
const { data: res } = await this.$http.post("api/admin/category/",{
"name":this.cateinfo.name,
})
if (res.code != 200) return this.$message.error(res.msg)
// 清空搜索框
this.$refs.addcateRef.resetFields()
// 关闭弹窗
this.AddcateVisible = false
this.$message.success('添加成功')
this.getcateList()
},
// 取消的方法
addcateCanal(){
this.$refs.addcateRef.resetFields()
this.AddcateVisible = false
},
// 编辑框获取分类信息
async editcate(id){
this.editcateVisible = true
const {data: res } = await this.$http.get(`/api/v1/category/${id}/`)
this.cateinfo = res.data
this.cateinfo.id = id
},
// 编辑分类
async editcateOk(){
const { data: res } = await this.$http.put(`/api/admin/category/${this.cateinfo.id}/`,{
"name":this.cateinfo.name,
})
if (res.code != 200) return this.$message.error(res.msg)
// 清空搜索框
this.$refs.addcateRef.resetFields()
// 关闭弹窗
this.editcateVisible = false
this.$message.success('编辑成功')
this.getcateList()
},
// 取消编辑销毁数据
editcateCanal(){
this.$refs.addcateRef.resetFields()
this.editcateVisible = false
},
}
}
</script>
<style>
.actionSlot{
display: flex;
justify-content: center;
}
</style>
- Post link: https://www.godhearing.cn/gin-vue-da-jian-ge-ren-bo-ke-8/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.