当前位置: 首页 > article >正文

后台数据管理系统 - 项目架构设计-Vue3+axios+Element-plus(0926)

十四、文章分类添加编辑 [element-plus 弹层]

Git仓库:https://gitee.com/msyycn/vue3-hei-ma.git

点击显示弹层

  1. 准备弹层
const dialogVisible = ref(false)

<el-dialog v-model="dialogVisible" title="添加弹层" width="30%">
  <div>我是内容部分</div>
  <template #footer>
    <span class="dialog-footer">
      <el-button @click="dialogVisible = false">取消</el-button>
      <el-button type="primary"> 确认 </el-button>
    </span>
  </template>
</el-dialog>
  1. 点击事件
<template #extra><el-button type="primary" @click="onAddChannel">添加分类</el-button></template>

const onAddChannel = () => {
  dialogVisible.value = true
}

封装弹层组件 ChannelEdit

添加 和 编辑,可以共用一个弹层,所以可以将弹层封装成一个组件

组件对外暴露一个方法 open, 基于 open 的参数,初始化表单数据,并判断区分是添加 还是 编辑

  1. open({ }) => 添加操作,添加表单初始化无数据
  2. open({ id: xx, … }) => 编辑操作,编辑表单初始化需回显

具体实现:

  1. 封装组件 article/components/ChannelEdit.vue
<script setup>
import { ref } from 'vue'
const dialogVisible = ref(false)

const open = async (row) => {
  dialogVisible.value = true
  console.log(row)
}

defineExpose({
  open
})
</script>

<template>
  <el-dialog v-model="dialogVisible" title="添加弹层" width="30%">
    <div>我是内容部分</div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary"> 确认 </el-button>
      </span>
    </template>
  </el-dialog>
</template>
  1. 通过 ref 绑定
const dialog = ref()

<!-- 弹窗 -->
<channel-edit ref="dialog"></channel-edit>
  1. 点击调用方法显示弹窗
const onAddChannel = () => {
  dialog.value.open({})
}
const onEditChannel = (row) => {
  dialog.value.open(row)
}

ChannelEdit.vue(封装的组件)

<script setup>
import {ref} from 'vue'

const dialogVisible = ref(false) //弹层状态

 

// 组件对外暴露一个方法,open ,基于open 传来的参数,区分添加还是编辑
// open ({}) => 表单无需渲染,说明是添加分
// open ({id, name}) => 表单需要渲染,说明是编辑分类
// open调用后,可以打开弹窗
const open = (row) =>{
  console.log(row)
  dialogVisible.value = true
  
}
// 向外暴露一个方法,close,关闭弹窗
defineExpose({
  open
})
</script>

<template>
 
 //弹层
    <el-dialog
    v-model="dialogVisible"
    title="添加弹层"
    width="500"
    :before-close="handleClose"
  >
  <div>渲染表单</div>
    <span>我是内容部分  </span>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="dialogVisible = false">
          确认
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

 

ArticleChannel.vue

<script setup>
import { artGetChannelsService } from '@/api/article'
import { Delete,Edit } from   '@element-plus/icons-vue'
 
import {ref} from 'vue'
import ChannelEdit from './components/ChannelEdit.vue'
const channelList = ref([]) // 文章分类列表
const loading = ref(false) //加载状态
 const dialog = ref()
// 获取文章分类列表
const getChannelList = async () => {
  // 发请求之前先将loading设置为true
  loading.value = true
  // 调用接口
  const res = await artGetChannelsService()
  channelList.value = res.data.data
  // channelList.value = []
  // 发完请求,关闭loading
  loading.value = false
  // console.log('文章分类列表',channelList.value);
  
}

// 调用获取文章分类列表
getChannelList()


// 编辑文章分类
const onEditChannel =(row) =>{
// console.log(row,$index)
dialog.value.open({row})
}       

// 删除文章分类
const onDelChannel =(row,$index)=>{
  console.log(row,$index)

}
const onAddChannel = () => {
  dialog.value.open({})
}
 
</script>

<template>
  <div>
    <!-- 按需引入 -->
    <page-container title="文章分类"> 
    <!-- 右侧按钮 - 添加文章 - 具名插槽 -->
      <template #extra>
        <el-button @click="onAddChannel">添加分类</el-button>
      </template>
      <!-- 主体部分--表格 -->
      <el-table :data="channelList" style="width: 100%" v-loading="loading">
          <el-table-column   label="序号"    type="index"  width="100" ></el-table-column>
          <el-table-column   label="分类名称" prop="cate_name" ></el-table-column>
          <el-table-column   label="分类别名" prop="cate_alias" ></el-table-column>
          <el-table-column   label="操作"      width="100">
          <template #default="{row,$index}">
             <el-button  @click="onEditChannel(row,$index)" plain :icon="Edit" circle type="primary" ></el-button>
             <el-button  @click="onDelChannel(row,$index)" plain :icon="Delete" circle type="danger" ></el-button>
          </template>
          </el-table-column>
         <!-- 没有数据 -->
         <template #empty>
      <el-empty description="暂无数据"></el-empty>
      </template>
      </el-table>
    
    <!-- 添加分类弹窗 -->
    <channel-edit ref="dialog"> </channel-edit>
 
    </page-container>
    
  </div>
</template>

<style lang="scss" scoped>
</style>

预览视图

请添加图片描述

准备弹层表单

  1. 准备数据 和 校验规则
const formModel = ref({
  cate_name: '',
  cate_alias: ''
})
const rules = {
  cate_name: [
    { required: true, message: '请输入分类名称', trigger: 'blur' },
    {
      pattern: /^\S{1,10}$/,
      message: '分类名必须是1-10位的非空字符',
      trigger: 'blur'
    }
  ],
  cate_alias: [
    { required: true, message: '请输入分类别名', trigger: 'blur' },
    {
      pattern: /^[a-zA-Z0-9]{1,15}$/,
      message: '分类别名必须是1-15位的字母数字',
      trigger: 'blur'
    }
  ]
}
  1. 准备表单
<el-form
  :model="formModel"
  :rules="rules"
  label-width="100px"
  style="padding-right: 30px"
>
  <el-form-item label="分类名称" prop="cate_name">
    <el-input
      v-model="formModel.cate_name"
      minlength="1"
      maxlength="10"
    ></el-input>
  </el-form-item>
  <el-form-item label="分类别名" prop="cate_alias">
    <el-input
      v-model="formModel.cate_alias"
      minlength="1"
      maxlength="15"
    ></el-input>
  </el-form-item>
</el-form>
  1. 编辑需要回显,表单数据需要初始化
const open = async (row) => {
  dialogVisible.value = true
  formModel.value = { ...row }
    //不回显的话,需要修改为
   // formModel.value = {...row.row} 即可
}
  1. 基于传过来的表单数据,进行标题控制,有 id 的是编辑
:title="formModel.id ? '编辑分类' : '添加分类'"

确认提交

  1. api/article.js 封装请求 API
// 添加文章分类
export const artAddChannelService = (data) => request.post('/my/cate/add', data)
// 编辑文章分类
export const artEditChannelService = (data) =>
  request.put('/my/cate/info', data)
  1. 页面中校验,判断,提交请求
<el-form ref="formRef">
const formRef = ref()
const onSubmit = async () => {
  await formRef.value.validate()
  formModel.value.id
    ? await artEditChannelService(formModel.value)
    : await artAddChannelService(formModel.value)
  ElMessage({
    type: 'success',
    message: formModel.value.id ? '编辑成功' : '添加成功'
  })
  dialogVisible.value = false
}
  1. 通知父组件进行回显
const emit = defineEmits(['success'])

const onSubmit = async () => {
  ...
  emit('success')
}
  1. 父组件监听 success 事件,进行调用回显
<channel-edit ref="dialog" @success="onSuccess"></channel-edit>

const onSuccess = () => {
  getChannelList()
}

源码

ChannelEdit.vue

<script setup>
import {ref} from 'vue'

const dialogVisible = ref(false) //弹层状态

 

// 组件对外暴露一个方法,open ,基于open 传来的参数,区分添加还是编辑
// open ({}) => 表单无需渲染,说明是添加分
// open ({id, name}) => 表单需要渲染,说明是编辑分类
// open调用后,可以打开弹窗
const open = async (row) =>{
  // console.log(row)
  dialogVisible.value = true
  formModel.value = {...row.row} //添加 =》 重置了表单内容,编辑-> 存储了需要回显的数据
console.log('formModel:',formModel.value)
console.log(formModel.value.row.cate_name)
 
}

 
// 向外暴露一个方法,close,关闭弹窗
defineExpose({
  open
})



const formModel = ref({
  cate_name:'',
  cate_alias:'' //别名
})


// 表单校验规则
const rules ={
  cate_name:[
    {required:true,message:'请输入分类名称',trigger:'blur'},
    {pattern:/^\S{1,10}$/,message:'分类名称长度在1-10个字符之间',trigger:'blur'}
  ],
  cate_alias:[
    {required:true,message:'请输入分类别名',trigger:'blur'},
    {pattern:/^[a-zA-Z0-9]{1,15}$/,message:'分类名称长度在1-15个字母或数字之间',trigger:'blur'}
  ]

}


// 表单提交
import { artEditChannelService,artAddChannelService } from '@/api/article'
// import { ElMessage } from 'element-plus';
const formRef = ref()
const emit = defineEmits(['success'])
const onSubmit = async () => {
  await formRef.value.validate()
  const isEdit = formModel.value.id
  if(isEdit){
    // 编辑
    await artEditChannelService(formModel.value)
    ElMessage.success('编辑成功') 
  }
  else {
    // 添加
    await artAddChannelService(formModel.value)
    ElMessage.success('添加成功')
  }
  // 无论编辑成功还是添加成功都需要关闭弹窗
  dialogVisible.value = false
  emit('success',isEdit) // 触发父组件的success事件


}
</script>

<template>
 

    <el-dialog 
    v-model="dialogVisible"
    :title="formModel.id ? '编辑分类' : '添加分类'"
    width="500"
    :before-close="handleClose"
  >
  <!-- 渲染表单 -->
  <el-form   ref="formRef" :model="formModel" :rules="rules" label-width="100px" style="padding-right:30px ;">
      <el-form-item label="分类名称" prop="cate_name" ><el-input v-model="formModel.cate_name" placeholder="请输入分类名称"></el-input></el-form-item>
      <el-form-item label="分类别名" prop="cate_alias" ><el-input v-model="formModel.cate_alias" placeholder="请输入分类别名"></el-input></el-form-item>
  </el-form>
 
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="onSubmit"> 确认 </el-button>
      </div>
    </template>
  </el-dialog>
</template>

 

ArticleChannel.vue

<script setup>
import { artGetChannelsService } from '@/api/article'
import { Delete,Edit } from   '@element-plus/icons-vue'
 
import {ref} from 'vue'
import ChannelEdit from './components/ChannelEdit.vue'
const channelList = ref([]) // 文章分类列表
const loading = ref(false) //加载状态
 const dialog = ref()
// 获取文章分类列表
const getChannelList = async () => {
  // 发请求之前先将loading设置为true
  loading.value = true
  // 调用接口
  const res = await artGetChannelsService()
  channelList.value = res.data.data
  // channelList.value = []
  // 发完请求,关闭loading
  loading.value = false
  // console.log('文章分类列表',channelList.value);
  
}

// 调用获取文章分类列表
getChannelList()


// 编辑文章分类
const onEditChannel =(row) =>{
// console.log(row,$index)
dialog.value.open({row})
}       

// 删除文章分类
const onDelChannel =(row,$index)=>{
  console.log(row,$index)

}
const onAddChannel = () => {
  dialog.value.open({})
}

const onSuccess =()=>{
  // 刷新文章分类列表
  getChannelList()
}
 
</script>

<template>
  <div>
    <!-- 按需引入 -->
    <page-container title="文章分类"> 
    <!-- 右侧按钮 - 添加文章 - 具名插槽 -->
      <template #extra>
        <el-button @click="onAddChannel">添加分类</el-button>
      </template>
      <!-- 主体部分--表格 -->
      <el-table :data="channelList" style="width: 100%" v-loading="loading">
          <el-table-column   label="序号"    type="index"  width="100" ></el-table-column>
          <el-table-column   label="分类名称" prop="cate_name" ></el-table-column>
          <el-table-column   label="分类别名" prop="cate_alias" ></el-table-column>
          <el-table-column   label="操作"      width="100">
          <template #default="{row,$index}">
             <el-button  @click="onEditChannel(row,$index)" plain :icon="Edit" circle type="primary" ></el-button>
             <el-button  @click="onDelChannel(row,$index)" plain :icon="Delete" circle type="danger" ></el-button>
          </template>
          </el-table-column>
         <!-- 没有数据 -->
         <template #empty>
      <el-empty description="暂无数据"></el-empty>
      </template>
      </el-table>
    
    <!-- 添加分类弹窗 -->
    <channel-edit ref="dialog" @success="onSuccess"> </channel-edit>
 
    </page-container>
    
  </div>
</template>

<style lang="scss" scoped>
</style>

预览视图
请添加图片描述

文章分类删除

  1. api/article.js封装接口 api
// 删除文章分类
export const artDelChannelService = (id) =>
  request.delete('/my/cate/del', {
    params: { id }
  })
  1. 页面中添加确认框,调用接口进行提示(ArticleChannel.vue)
const onDelChannel = async (row) => {
  await ElMessageBox.confirm('你确认删除该分类信息吗?', '温馨提示', {
    type: 'warning',
    confirmButtonText: '确认',
    cancelButtonText: '取消'
  })
  await artDelChannelService(row.id)
  ElMessage({ type: 'success', message: '删除成功' })
  getChannelList()
}

预览视图

请添加图片描述
文章分类模块完结,撒花儿~~***


http://www.kler.cn/a/327023.html

相关文章:

  • Linux中的软硬链接文件详解
  • 练习LabVIEW第三十八题
  • Ghidra无头模式(自动化批处理执行重复性任务)
  • 全面解析Flutter中的Stream用法及实际应用
  • Oracle OCP认证考试考点详解082系列11
  • 深入探讨 Jenkins 中 HTML 格式无法正常显示的现象及解决方案
  • leetcode刷题day27|贪心算法Part01(455.分发饼干、376. 摆动序列、53. 最大子序和)
  • 两个向量所在平面的法线,外积,叉积,行列式
  • GIT安装及集成到IDEA中操作步骤
  • Linux基础命令mount,umount详解
  • jmeter进行性能测试实践
  • 查看 .so 库(共享对象库)的依赖
  • linux驱动编程——等待队列
  • 显示器放大后,大漠识图识色坐标偏移解决方法
  • 【leetcode】122. 买卖股票的最佳时机 II
  • Linux下路由信息探测traceroute
  • UE4_Niagara基础实例—5、骨架网格体表面生成粒子及过滤骨骼位置生成粒子
  • 不同领域神经网络一般选择什么模型作为baseline(基准模型)
  • 【如何在Linux系统本地快速部署Leanote蚂蚁笔记】
  • SQL第9课——汇总数据
  • 命令模式
  • PCL 索引空间采样
  • golang fmt.Sprintf 引用前述变量
  • java将word转pdf
  • python 实现lstm prediction预测算法
  • 【C++】unordered_map(set)