vue3+elmentPlus 后台系统数据增删改查模板

451 阅读3分钟

vue3+elmentPlus 后台系统数据增删改查模板

列表页面

/index.vue

<template>
  <div v-loading.fullscreen.lock="loading">
    <div class="app-container">
      <el-form :model="searchFrom">
        <el-row :gutter="20">
          <el-col :span="8">
                <el-form-item label="名称" prop="name">
                    <el-input v-model="searchFrom.name" />
                </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="类型:">
              <el-select v-model="searchFrom.iType" clearable filterable>
                <el-option v-for="item in typeOptions" :key="item.value" :label="item.name" :value="item.value"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="状态:">
              <el-select v-model="searchFrom.status" clearable filterable>
                <el-option v-for="item in statusOptions" :key="item.value" :label="item.name" :value="item.value"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row style="margin-bottom: 20px">
          <el-col :span="24" class="text-center">
            <el-button @click="handleReset">重置</el-button>
            <el-button type="primary" @click="handleSearch">查询</el-button>
            <el-button type="success" @click="handleAdd">新建</el-button>
          </el-col>
        </el-row>
      </el-form>
      <div class="page-main">
        <el-table
          :data="tableData"
          border
          style="width: 100%"
          @select="selectChangeEvent"
          @select-all="selectAllChangeEvent"
        >
          <el-table-column type="selection" width="60" label="全选" align="center" />
          <el-table-column prop="name" label="名称" align="center"></el-table-column>
          <el-table-column prop="iType" label="类型" align="center">
            <template #default="scope">{{ formatterType(scope.row.iType) }}</template>
          </el-table-column>
          <el-table-column prop="course" label="课程" align="center">
            <template #default="scope">{{ scope.row.course.text }}</template>
          </el-table-column>
          <el-table-column prop="status" label="状态" align="center">
            <template #default="scope">{{ formatterStatus(scope.row.status) }}</template>
          </el-table-column>
          <el-table-column label="操作" align="center">
            <template #default="scope">
              <el-button size="small" type="primary" @click="handleEdit(scope.row)">修改</el-button>
              <el-button size="small" type="primary" @click="seeDetails(scope.row)">详情</el-button>
            </template>
          </el-table-column>
         </el-table> 
         <div class="pagination">
          <el-pagination
            v-model:currentPage="currentPage"
            v-model:page-size="pageSize"
            :page-sizes="[10, 20, 30, 40]"
            :background="true"
            layout="total, sizes, prev, pager, next, jumper"
            :total="total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          >
          </el-pagination>
        </div>
      </div>
      <!-- 新建 修改 详情-->
      <Edit
        v-if="showDialog"
        ref="RefSelectPolicies"
        v-model:show="showDialog"
        :permission="permission"
        :row="currentRow"
        @flushed="handleSearch"
      >
      </Edit>
    </div>
  </div>
</template>
  
<script setup lang="ts">
import { onMounted, onUpdated, reactive, ref, watch, watchEffect } from "vue";
import { funcResetObj } from "/@/utils/index";
import Edit from "./edit.vue";
import { useRequest } from "@xus/vue-reuse";
import { ElMessage } from "element-plus";
import { confirmMessage, errorMessage, successMessage } from "/@/utils/message";
import { nextTick } from "process";
import deepcopy from 'deepcopy'

// 列表查询
const searchFrom = reactive({
  name: "",
  iType: "",
  course: "",
  status: "",
});
const currentPage = ref<number>(1);
const pageSize = ref<number>(10);
const total = ref<number>(0);
const tableData = ref([]);
const currentRow = ref();
const loading = ref(false)
const relationshipOptions = ref([])

// 假数据
const tableData1 = [
  {
    name: "1",
    iType: "2",
    course: {text:'c',code:'3'},
    status: 0,
  },
]
const tableData2 = [
  {
    name: "11",
    iType: "22",
    course: {text:'cc',code:'33'},
    status: 1,
  },
]
const tableData3 = [
  {
    name: "111",
    iType: "222",
    course: {text:'ccc',code:'333'},
    status: 0,
  },
]

// 数据格式化,字典
const typeOptions = [
  {
    name:'类型1',
    value:'1'
  },
  {
    name:'类型2',
    value:'2'
  },
]
const statusOptions = [
  {
    name:'开启',
    value:0
  },
  {
    name:'关闭',
    value:1
  },
]
const formatterType = (val)=>{
  console.log('formatterType',val);
  return val+'!'
}
const formatterStatus = (val)=>{
  console.log('formatterStatus',val);
  return statusOptions.filter(item=>item.value===val)[0].name
}

// 勾选
const selectChangeEvent = (row)=>{
  console.log('selectChangeEvent',row);
  
}
const selectAllChangeEvent = (all)=>{
  console.log('selectAllChangeEvent',all);
}

// 请求数据 
const getList = () => {
  const req = {
    ...searchFrom,
    pageNum: currentPage.value,
    pageSize: pageSize.value,
  };
  // 请求接口,获取数据
  total.value = 35
  if(currentPage.value===1){
    tableData.value = tableData1
  }else if(currentPage.value===2){
    tableData.value = tableData2
  }else if(currentPage.value===3){
    tableData.value = tableData3
  }
};

// 查询
const handleSearch = () => {
  currentPage.value = 1;
  getList();
};

//重置按钮
const handleReset = () => {
  funcResetObj(searchFrom);
  currentPage.value = 1;
  getList();
};

// 改变条数
const handleSizeChange = (val: number) => {
  pageSize.value = val
  getList();
};

// 改变页数
const handleCurrentChange = (val: number) => {
  currentPage.value = val;
  getList();
};

const permission = ref('')
const showDialog = ref(false)
// 新建 
const handleAdd = ()=>{
  permission.value = 'add'
  showDialog.value = true;
}
// 修改
const handleEdit = async(obj) => {
  currentRow.value = obj
  permission.value = 'edit'
  showDialog.value = true;
};
// 详情
const seeDetails = async(obj) => {
  currentRow.value = obj
  permission.value = 'look'
  showDialog.value = true;
};

onMounted(() => {
  getList();
});

</script>
  
<style lang="scss" scoped>
.app-container{
  margin: 10px;
  padding: 20px;
  font-size: 14px;
  background-color: #fff;
  border-radius: 5px;
  .page-main{
    margin-top:30px;
  }
  .text-center {
    text-align: center;
  }
  .pagination {
    display: flex;
    justify-content: right;
    margin-top: 30px;
  }
}
</style>
  

新增/修改/详情页面

/add.vue

<template>
  <el-dialog
    v-model="props.show"
    :title="title"
    width="60%"
    :before-close="close"
  >
    <el-form :model="form" :disabled="disabled" ref="formRef" :rules="rules" class="container" label-width="100px">
      <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="名称:" prop="name">
              <el-input v-model="form.name" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="类型:" prop="iType">
              <el-select v-model="form.iType" clearable filterable>
                <el-option v-for="item in typeOptions" :key="item.value" :label="item.name" :value="item.value"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
      </el-row>
      <el-row style="margin-bottom: 20px" v-if="permission!=='look'">
        <el-col :span="24" class="text-center">
          <el-button @click="cancel">取消</el-button>
          <el-button type="primary" @click="confirm">提交</el-button>
        </el-col>
      </el-row>
    </el-form>
  </el-dialog>
</template>
  
<script lang="ts" setup>
import { reactive, watch, ref } from "vue";
import { useRequest } from "@xus/vue-reuse";
import { ElMessage, FormInstance, FormRules } from "element-plus";
const props = defineProps({
  show: {
    type: Boolean,
    default: false,
  },
  row: {
    type: Object,
    default: null,
  },
  permission:{
    type: String,
    default:''
  },
});
const emit = defineEmits(["update:show",'flushed']);
console.log("props", props);
// 弹框设置
const disabled = ref(true)
const title = ref('详情')
if(props.permission!=='look'){
    disabled.value = false
    if(props.permission==='add'){
        title.value='新建'
    }else{
        title.value='修改'
    }
}
// 表单设置
const form = reactive({
  id:null,
  name: "",
  iType:""
});
const formRef = ref<FormInstance>()
const rules = reactive<FormRules>({
  name: [
    { required: true, message: '请输入名字', trigger: 'blur' },
  ],
  iType: [
    { required: true, message: '请选择类型', trigger: 'change' },
  ],
})
// 字典
interface IOption{
  name:string
  value:string
}
const typeOptions = ref([] as IOption[]);
typeOptions.value = [
  {
    name:'类型1',
    value:'1'
  },
  {
    name:'类型2',
    value:'2'
  },
]

// 修改/详情 数据反显
if (props.permission!=='add') {
  form.name = props.row.name;
  form.iType = props.row.iType;
  console.log("form", form);
}
// 取消
const cancel = () => {
  console.log("cancel");
  emit("update:show");
};
// 确认
const confirm = () => {
  console.log("confirm", form);
  formRef.value?.validate().then(()=>{
    //   const data = { 
    //   };
    //   if(props.permission=='add'){
    //   }else{
    //     data.id = props.row.id
    //     runPolicyEsimEdit(data)
    //   }  
    emit("update:show");
  })
  
};
const close = () => {
  console.log("close");
  emit("update:show");
};
</script>
  
<style scoped>
.container{
  margin: 0 20px;
}
.text-center {
  text-align: center;
}
</style>
  

通用弹框组件

当弹框内容较多,或者弹框内逻辑比较复杂时,可以将弹框及弹框中的内容封装为一个组件,降低主页面的复杂度

/index.vue 中使用组件

    <operateDialog v-if="showEditDialog" v-model:show="showEditDialog" :row="curRow" :title="dialogTitle" @refresh="refreshList"/>

/operateDialog.vue 弹框组件

<template>
    <el-dialog
        v-model="show"
        :title="title"
        width="30%"
        :before-close="handleClose"
    >
        <span>xxx</span>
        <template #footer>
            <span class="dialog-footer">
                <el-button @click="handleClose">取消</el-button>
                <el-button type="primary" @click="confirm"> 确定 </el-button>
            </span>
        </template>
    </el-dialog>
</template>

<script lang='ts' setup>
const props = defineProps({
    show:{
        type:Boolean,
        default:false
    },
    title:{
        type:String,
        default:''
    },
    row: {
        type: Object,
        default: null,
    },
})
const emits = defineEmits(['update:show','refresh'])
const handleClose = ()=>{
    emits('update:show')
}
const confirm = ()=>{
    emits('update:show')
    // 操作成功 刷新列表
    emits('refresh')
}
</script>

<style scoped>

</style>