最近搜索

vue3 小案例 复杂的增删改查,可以查看修改记录 主要知识点 slot

浏览:6
管理员 2025-07-17 08:40



常量

export  const levelMap = {
    1:"全平台投放",
    2:"首页投放",
    3:"区域投放",
    4:"内部投放",
}




index

<template>

  <div style="padding: 15px; width: 800px;" >
    <p>复杂的增删改查,可以查看修改记录</p>
    <div><el-button @click="add">新建</el-button></div>


    <el-table :data="list">

      <el-table-column label="项目名" prop="name">
      </el-table-column>

      <el-table-column  label="级别">
        <template #default="scope">
          <div>{{  levelMap[scope.row.level] }}</div>
        </template>
      </el-table-column>

      <el-table-column  label="是否第三方">
        <template #default="scope">
          <div>{{scope.row.other==1?"是":"否"}}</div>
        </template>
      </el-table-column>

      <el-table-column  label="目标人群">
        <template #default="scope">
          <div>{{formatPeople(scope.row.peopleList)}}</div>
        </template>
      </el-table-column>

      <el-table-column  label="操作">
        <template #default="scope">
          <el-button size="small" type="primary"   @click="clickView(scope.row.id)" >详情</el-button>
          <el-button size="small"   type="success" @click="clickEdit(scope.row.id)">编辑</el-button>
          <el-popconfirm   title="您确定要删除这条记录吗?" @confirm="clickDelete(scope.row.id)">
            <template #reference>
              <el-button   size="small" type="danger"  >删除</el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>

    </el-table>

  </div>
</template>


<script setup>
import requestUtil from "@/util/request";
import  store from '@/store'
import  {ref, computed  , onMounted,nextTick , reactive,onBeforeMount, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted} from 'vue'
import  {ElMessage} from 'element-plus'
import  router from '@/router'
import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/util/jsencrypt";
import {Check,  Delete,  Edit,   Message,  Search,   Star,} from '@element-plus/icons-vue'
import {levelMap} from "@/util/constant";

const list = ref([]);

function  formatPeople(people){
 const arr =  people.map((item)=>{
    return item.name
  })
  return arr.join(",");
}

const queryForm=ref({
  query:'',
  pageNum:1,
  pageSize:100
})

const initList =async()=>{
  console.log(queryForm.value);
  const res=await requestUtil.post("api/project/list",queryForm.value);
  list.value=res.data.projectList;
}


initList();

function add(){
    router.push("/test/demo1/detail?type=create");
}

function clickView(id){
  router.push("/test/demo1/detail?type=view&id="+id);
}

function clickEdit(id){
  router.push("/test/demo1/detail?type=edit&id="+id);
}

const clickDelete=async (id)=>{
  var ids = []
  ids.push(id)
  const res=await requestUtil.post("api/project/delete",ids)
  if(res.data.code==200){
    ElMessage({
      type: 'success',
      message: '执行成功!'
    })
    initList();
  }else{
    ElMessage({
      type: 'error',
      message: res.data.msg,
    })
  }

}
</script>

<style scoped>
h2{
  font-size: 30px;
  padding: 10px 0px;
  font-weight: bold;
}
</style>



detail 



<script setup>
import requestUtil from "@/util/request";
import  store from '@/store'
import  {ref, computed  , onMounted,nextTick , reactive,onBeforeMount, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted} from 'vue'
import  {ElMessage} from 'element-plus'
import  router from '@/router'
import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/util/jsencrypt";
import {Check,  Delete,  Edit,   Message,  Search,   Star,} from '@element-plus/icons-vue'
import {levelMap} from "@/util/constant";
import  {useRoute} from 'vue-router'

import detailCom  from './detailCom'

const {query}  = useRoute();
const type = query.type;
const id = query.id;

//这个暂时 手工设置 。随后 可以后台获取 。
const oldInfoData = ref({
  id:-1,
  name:"old-name-123",
  level:1,
  other:1,
  peopleList:[
    { "id": 11, "name": "1111211", "size": "1", "touDate": "2024-12-30", "projectId": 10 },
    { "id": 11, "name": "23", "size": "1", "touDate": "2024-12-01", "projectId": 10 },
  ]
});

const num1 = ref(1);
const num2 = ref(22);

const numsum = computed(() => {
  return num1.value + num2.value ;//不相等 返回true isDiff是true  有差异  这是针对字符串的判断
});

function fun1(){
  num1.value = 34;
  num2.value = 34;
}

const formRef=ref(null)
const form=ref({
  id:-1,
  name:"",
  level:1,
  other:1,
  peopleList:[

  ]
})

const rules=ref({
  reason:[
    { required: true, message: '请填写原因分析'}
  ]
})
const isDataLoaded = ref(false);

const  init = async()=>{
  if(type==='create'){
    //isDataLoaded.value = true;  //
  }else{
    //请求数据
    const res=await requestUtil.get("api/project/"+id);
    form.value=res.data.project;
    isDataLoaded.value = true;  // 数据加载完成后设置状态
  }
}
init();

function  add_row(){
  form.value.peopleList.push({
    name:"",
    touDate:"",
    size:""
  });
}

const  save = async()=> {
  if(type==='create'){
    let result=await requestUtil.post("api/project/save",form.value);
    let data=result.data;
    if(data.code==200){
      ElMessage.success("执行成功!")
    }else{
      ElMessage.error(data.msg);
    }
  }else if(type==='edit'){
    let result=await requestUtil.post("api/project/edit",form.value);
    let data=result.data;
    if(data.code==200){
      ElMessage.success("执行成功!")
    }else{
      ElMessage.error(data.msg);
    }
  }
}
</script>

<style scoped>
h2{
  font-size: 20px;
  padding: 10px 0px;
  font-weight: bold;
}
</style>

<template>

  <div style="padding: 15px; width: 450px;">

    <el-form
        label-width="auto"
        ref="formRef"
        :model="form"
        :rules="rules"
        style="  border-radius: 8px; padding-top: 15px;"
    >

      <el-form-item label="项目名称" prop="name"   >
        <detailCom :type="type" :nowValue="form.name" :oldValue="oldInfoData.name"   >
          <el-input v-model="form.name" />
        </detailCom>
      </el-form-item>

      <el-form-item label="项目级别"  prop="level"  >
        <detailCom :type="type" :nowValue="levelMap[form.level]" :oldValue="levelMap[oldInfoData.level]">
          <el-select  filterable   v-model="form.level" placeholder="请选择项目级别"  >
            <template v-for="item in Object.keys(levelMap)" :key="item">
              <el-option :label="levelMap[item]" :value="parseInt(item)"></el-option>
            </template>
          </el-select>
        </detailCom>
      </el-form-item>

      <el-form-item label="是否有第三方"  prop="other"  >
        <detailCom :type="type" :nowValue="form.other===1?'是':'否'" :oldValue="oldInfoData.other===1?'是':'否'" >
          <el-radio-group v-model="form.other">
            <el-radio :value="1">是</el-radio>
            <el-radio :value="2">否</el-radio>
          </el-radio-group>
        </detailCom>
      </el-form-item>

      <h2>人群</h2>
      <el-table :data="form.peopleList">

        <el-table-column width="150" label="人群名称">
            <template #default="scope">
              <detailCom :type="type" :nowValue="scope.row.name"  :oldValue="oldInfoData.peopleList[scope.$index]?.name"     >
                    <el-input v-model="scope.row.name" />
              </detailCom>
            </template>
        </el-table-column>

        <el-table-column width="90"  label="投放量级">
          <template #default="scope">
            <detailCom :type="type"  :nowValue="scope.row.size"  :oldValue="oldInfoData.peopleList[scope.$index]?.size"   >
              <el-input v-model="scope.row.size" />
            </detailCom>
          </template>
        </el-table-column>
        <el-table-column     label="投放时间">
          <template #default="scope">
            <detailCom :type="type"  :nowValue="scope.row.touDate"  :oldValue="oldInfoData.peopleList[scope.$index]?.touDate"   >
              <el-date-picker
                  v-model="scope.row.touDate"
                  type="date"
                  value-format="YYYY-MM-DD"
                  placeholder="请选择日期时间"   />
            </detailCom>
          </template>
        </el-table-column>

      </el-table>

      <div style="text-align: center;">
        <el-button    @click="add_row">
          添加一行
        </el-button>
      </div>

      <el-form-item style="padding-top: 45px;">
        <el-button  type="primary" @click="save">
          提交
        </el-button>
      </el-form-item>

    </el-form>

  </div>
</template>




detail-com


<script setup>
import {ref, reactive, computed } from 'vue';
const props=defineProps(
    {
      type:{
        required:true
      },
      nowValue:{
        required:true
      },
      oldValue:{
        required:true
      },
      index:{
        required:true
      }

    }
)
const isDiff = computed(() => {
  console.log("计算属性", "nowValue:"+props.nowValue,"oldValue:"+props.oldValue);
  console.log("index:", props.index);

  if(props.oldValue === undefined || props.oldValue ==='' ){
    //如果是undefined就是没有修改。   或者是空字符串。
    return  false;
  }
  if(props.nowValue instanceof Array && props.oldValue instanceof  Array ){
    return props.nowValue.length !== props.oldValue.length;//不相等 返回true isDiff是true  有差异  这是针对字符串的判断
  }
  return props.nowValue !== props.oldValue ;//不相等 返回true isDiff是true  有差异  这是针对字符串的判断
});
</script>
<style scoped>
.diffColor{
  background-color: red;
}
</style>


<template>
  <slot  v-if="type==='create'||type==='edit'"></slot>
<!--  这里写name=view  就是让他不是默认插槽 如果不写name=view  下面的el-tooltip-div不会显示的, 会显示传来的html 覆盖下面的el-tooltip-div
<detailCom :type="type" :nowValue="form.name" :oldValue="oldInfoData.name"   >
          <el-input v-model="form.name" />
        </detailCom>
        会显示传来的input
        name=view 下面的内容相当于是默认值。
-->
  <slot v-if="type==='view'" name="view" :value="{nowValue,oldValue}">
    <el-tooltip :disabled="!isDiff" :content="`修改前:${oldValue}`">
      <div :class="{diffColor:isDiff}">{{nowValue}}</div>
    </el-tooltip>
  </slot>
</template>




总结

主要就是slot  插槽。



联系站长

站长微信:xiaomao0055

站长QQ:14496453