ts+vue3 elementUI表单提交编辑

需求:

因为有些有唯一性校验的字段,如果没被编辑并且传了;后端更新时会失败;所以只传需要变更的字段。
在提交表单使用http的put请求进行数据更新时,只提交表单中被修改的数据,而不是提交整个表单

分析:

获取表单数据时clone一份作为原始数据rawData

在提交表单前将表单数据 formData 和 rawData 的数据进行比较

将差异存放到新的对象 diffData 中,在提交表单时提交就行了

`Object.getOwnPropertyNames()`
 Object.getOwnPropertyNames(rData).forEach((val: string, idx: number) => {
 JSON.parse(JSON.stringify(row));
 Reflect.ownKeys(JSON.parse(JSON.stringify(row)));

<!-- 编辑模态框 -->
  <el-dialog
        title="社区信息"
        v-model="dialogEditVisible"
        width="540px"
        :before-close="handleClose">
        <!-- <span>这是一段信息</span> -->
        <el-form
        :model="data.rowObject"
        ref="dataForm"
        label-position="left"
        label-width="90px"
        style="width: 400px; margin-left:50px;"
        >
            <div class="demo-input-suffix">
                <el-row style="margin-top: 0px">
                    <el-col :span="5" :offset="1" style="text-align: center;height: 32px;line-height: 32px;color:#000;">
                        <span style="color:red;">*</span>社区名称
                    </el-col>
                    <el-col :span="14" :offset="0">
                        <el-input
                            placeholder="请输入内容"
                            v-model="data.rowObject.name"
                            size="small">
                        </el-input>
                    </el-col>
                </el-row>
                <el-row style="margin-top: 20px">
                    <el-col :span="5" :offset="1" style="text-align: center;height: 32px;line-height: 32px;color:#000;">
                        关联APP-ID
                    </el-col>
                    <el-col :span="14" :offset="0">
                        <el-input
                            placeholder="请输入内容"
                            v-model="data.rowObject.relateAppId"
                            :disabled="true"
                            size="small">
                        </el-input>
                    </el-col>
                </el-row>
                <el-row style="margin-top: 20px">
                    <el-col :span="5" :offset="1" style="text-align: center;height: 32px;line-height: 32px;color:#000;">
                        <span style="color:red;">*</span>社区ICON
                    </el-col>
                    <el-col :span="14" :offset="0">
                        <el-button size="small" @click="clickAppId(data.rowObject.relateAppId)">通过APP-ID拉取</el-button>
                        <!-- <el-button size="medium" @click="mupload">上传</el-button> -->
                        <el-upload
                            class="upload-demo"
                            :ref="myUpload"
                            action="https://jsonplaceholder.typicode.com/posts/"
                            accept="image/jpeg,image/png,image/jpg"
                            :on-change="handleChangePic"
                            :on-preview="handlePreview"
                            :on-remove="handleRemove"
                            :on-error="handleErrorPic"
                            :file-list="fileList"
                            list-type="picture"
                            :limit="1"
                            :on-exceed="handleExceed">
                            <el-button size="small" type="primary" :disabled="data.disableUploadFlag">点击上传</el-button>
                            <template #tip>
                                <div class="el-upload__tip">
                                只能上传 jpg/png/jepg 文件,且不超过 300kb
                                </div>
                            </template>
                        </el-upload>
                    </el-col>
                </el-row>
                <el-row style="margin-top: 20px">
                    <el-col :span="5" :offset="1" style="text-align: center;height: 32px;line-height: 32px;color:#000;">
                        社区基数
                    </el-col>
                    <el-col :span="14" :offset="0" class="sq_jishu">
                        <div class="sq_js_div">
                            <el-col :span="10" :offset="2" style="margin-top:5px">
                                基础用户量
                            </el-col>
                            <el-col :span="10" :offset="1">
                                <el-input
                                    placeholder="请输入内容"
                                    v-model="data.rowObject.baseUserNum"
                                    size="small">
                                </el-input>
                            </el-col>
                        </div>
                        <div class="sq_js_div">
                            <el-col :span="10" :offset="3" style="margin-top: 5px;margin-right: 4px!important;">
                                基础热度
                            </el-col>
                            <el-col :span="10" :offset="1">
                                <el-input
                                    placeholder="请输入内容"
                                    v-model="data.rowObject.baseHotNum"
                                    size="small">
                                </el-input>
                            </el-col>
                        </div>
                    </el-col>
                </el-row>
                <el-row style="margin-top: 20px">
                    <el-col :span="9" :offset="0"
                    style="text-align: center;height: 32px;line-height: 32px;color:#000;margin-left: -49px;">
                        <span style="color:red;">*</span>非管理员用户关联
                    </el-col>
                    <el-col :span="12" :offset="0">
                        <!-- <el-button type="" icon="el-icon-plus" size="small">添加</el-button> -->
                            <el-button type="" @click="innerVisible = true" size="small">添加</el-button>
                    </el-col>
                    <el-col :span="14" :offset="6" class="sq_jishu" style="margin-top:10px">
                        <div class="sq_jishu_div">
                            <div class="sq_jishu_div_role">
                                厂商
                            </div>
                            <div  class="sq_jishu_div_tagAll">
                                <!-- <el-tag>标签一标签一</el-tag>
                                <el-tag>标签一标签一</el-tag> -->
                                <el-tag
                                    :key="tag"
                                    v-for="tag in dynamicTags"
                                    closable
                                    :disable-transitions="false"
                                    @close="handleTagClose(tag)">
                                    {
   
   {tag}}
                                </el-tag>
                                <el-tag
                                    v-if="tagAddVisible"
                                    closable
                                    v-model="inputUserValue"
                                    :disable-transitions="false"
                                    @close="handleTagClose(tag)">
                                    {
   
   {data.tag1}}
                                </el-tag>
                            </div>
                        </div>
                    </el-col>
                </el-row>
            </div>
        </el-form>
        <template #footer>
            <span class="dialog-footer">
            <el-button @click="dialogEditVisible = false">取 消</el-button>
            <!-- <el-button type="primary" @click="dialogEditVisible = false">确 定</el-button> -->
            <el-button type="primary" @click="clickEdit">确 定</el-button>
            </span>
        </template>
    </el-dialog>

<script lang="ts">
import {
    
     defineComponent, reactive, ref, toRefs, onMounted, watchEffect, nextTick } from 'vue';
import {
    
     getCommunitTable, deleteTableDataApi, getAppIdApi, changeStatusApi, getCommunitSearchList, editCommunitApi } from '../../reactivity/getCommunityData';
import {
    
     ElMessage } from 'element-plus';
import {
    
     AnyObject } from 'element-plus/lib/el-table/src/table.type';

export default defineComponent({
    
    
  setup() {
    
    
    // const { pageInfo, tableList } = getCommunitTable({
    
    
    // currentPage: data.pageInfo.currentPage, pageSize: data.pageInfo.pageSize });
    // 定义翻页-初始化
    const pageInfoInit = reactive({
    
    
      currentPage: 1,
      pageSize: 5,
    });
    const {
    
     pageInfo, tableList } = getCommunitTable({
    
     ...pageInfoInit });
    console.log('aaaaaaaaaaaaaaaaaaaaa', pageInfo);
    console.log('bbbbbbbbbbbbbbbbbbbbb', tableList);
    // const collapse = ref(false);
    const tagsList = reactive([]);
    const data = reactive({
    
    
      pageInfo,
      tableList,
      value1: '',
      options: [ // 下拉框选项内容
        {
    
    
          value: '选项1',
          label: '上线中',
        },
        {
    
    
          value: '选项2',
          label: '下线中',
        },
      ],
      value: '', // 下拉框
      activeNames: ['1'],
      userRole: true, // false
      isZhankai: true,
      currentPage2: 1,
      dialogEditVisible: false, // 编辑dialog展示
      editInputcId: '',
      rowObject: {
    
    }, // 模拟一个row一行数据信息  编辑模态框绑定数据
      rawData: {
    
    },	// 获取表单时clone的原始数据————编辑copy
      objT: {
    
     a: 1, b: 2, c: 3 },
      diffData: {
    
    },	// 差异——编辑提交的内容
      CommunityID: '', // 搜索id
      searchInfo: {
    
     // 搜索里所有可填的信息
        CommunityID: '', // 搜索条件ID
        CommunityName: '', // 搜索条件昵称
        communityTime: [], // [], // 搜索 创建时间到结束时间
        connectUserQQ: '', // 搜索关联用户qq
        cState: '', // 搜索 上线下线状态
      },
      delRowId: 0, // 查找到要删除的一行的id
      delIndex: 0, // 当前一行要删除的索引index
      //   upOrDownRowId: 0, // 查找到要操作上下线的一行的id
      upOrDownRowStatus: 0, // 操作上下线 + 删除操作  ——————————1-下线,2-上线,3-删除
      dialogDelVisible: false, // 删除模态框初始化隐藏
      editForm: {
    
     // 编辑模态框 -数据来源于一行的数据  ---暂时不使用
        CommunityID: '', // 搜索条件ID
        // 关联APP-ID 暂时空缺
        CommunityName: '', // 搜索条件昵称
        CommunityIcon: '', // 社区icon可以上传,可以通过关联appid 获取
        editTime: '', // 编辑操作时间需要 前台记录当时时间
        connectUserQQ: '', // 搜索关联用户qq ------非管理员用户关联 (可删除)
        value: '', // 搜索 上线下线状态
        // 关联用户 模态框还需要补充的内容 ----- 内嵌表格
        userRole: '', // 用户类型
        fileList: [{
    
    
          name: '1.jpg',
          url: 'files/1.jpg',
        }, {
    
    
          name: 'food2.jpeg',
          url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
        }],
        // fileList: ['https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'],
        // my_upload: ref(null),  // 上传绑定----便于清除
      },
      dialogUpOrDownVisible: false, // 操作状态----模态框初始化隐藏
      innerVisible: false, // 内嵌 添加社区的关联用户
      form: {
    
     // 内嵌 添加社区的关联用户  表单信息
        name: '',
        region: '',
        date1: '',
        date2: '',
        delivery: false,
        type: [],
        resource: '',
        desc: '',
      },
      formLabelWidth: '80px',
      dialogAddVisible: false, // 创建社区模态框
      gridData: [{
    
    
        id: '123456',
        name: '王小虎',
        role: '版主',
      }, {
    
    
        id: '456123',
        name: '王小',
        role: '厂商',
      }, {
    
    
        id: '145623',
        name: '小王',
        role: '厂商',
      },  {
    
    
        id: '123456',
        name: '小虎',
        role: '写手',
      }, {
    
    
        id: '456123',
        name: '王小',
        role: '厂商',
      }],
      dynamicTags: ['标签一', '标签二', '标签三'], // 模拟添加关联社区 -- 用户标签
      inputUserValue: '', // 输入的modle
      disableUploadFlag: false, // 上传按钮是否置灰
      addUser: {
    
     // 创建用户表单信息
        id: 0,
        name: '',
        relateAppId: 0,
        icon: '',
        baseUserNum: 0,
        baseHotNum: 0,
        backgroundImg: '',
        relateUser: '',
        status: 0,
        creatorId: 0,
        createTime: 0,
        operateTime: 0,
        operatorId: 0,
        iconSource: 0,
        url: '', // 数据库 社区链接
        createTimestamp: 0, // 创建时间
        operateTimestamp: 0, // 更新 时间
      },
      tagAddVisible: false, // 动态添加关联tag
      tag1: '', // 内模态框点击按钮- 获取的用户名称添加到社区信息中:非管理员用户关联tag里
    });
    const refData = toRefs(data);
    console.log('refData:', refData);
    const handleChange = () => {
    
    
      data.isZhankai = !data.isZhankai;
    //   console.log('val', val);
    //   console.log('data.isZhankai:', data.isZhankai);
    };
    const handleEdit = (index: number, row: unknown) => {
    
    
      console.log('当前索引index:', index, '当前行数row:', row);
      data.dialogEditVisible = true;
      //   data.rowObject = row;
      data.rowObject = JSON.parse(JSON.stringify(row)); // 解决element-ui中,在表单中修改数据,表格的数据也跟着修改的问题
      //   data.rawData = Reflect.ownKeys(JSON.parse(JSON.stringify(row))); // 编辑copy数据
      data.rawData = JSON.parse(JSON.stringify(row));
      console.log('data.rowObject:', data.rowObject, 'data.rawData:', data.rawData);
      //   console.log('data.rowObject:', Object.keys(data.rowObject), 'data.rawData:', Object.keys(data.rawData));
    };
    // 比较编辑差异的方法
    const diffFormData  = () => {
    
    
      const rData: AnyObject = data.rawData;
      const dData: AnyObject = data.diffData;
      const formO: AnyObject = data.rowObject;
      console.log('rData:', rData); // copy数据
      Object.getOwnPropertyNames(rData).forEach((val: string, idx: number) => {
    
    
        console.log(`${
      
      val} -> ${
      
      rData[val]}`);
        console.log('idx:', idx);
        if (rData[val] !== formO[val]) {
    
    
          if (!data.diffData) {
    
     // 未修改
            data.diffData = {
    
    };
          }
          dData[val] = formO[val];
          console.log('dData[val]:', dData[val]);
        }
        console.log('dData:', dData);
      });
      editCommunitApi({
    
     ...dData })
        .then((res) => {
    
    
          console.log('res:', res);
          if (res && !res.ret) {
    
    
            ElMessage.success({
    
    
              message: '编辑成功成功',
              type: 'success',
            });
            fetchData(data.pageInfo.pageNum, data.pageInfo.pageSize);
          }
        })
        .finally(() => {
    
    
          data.dialogEditVisible = false;
          // return true;
        });
    };
    // edit模态框提交修改内容 按钮
    const clickEdit = () => {
    
    
      diffFormData();
      data.dialogEditVisible = false;
      console.log('data.rowObject:', data.rowObject);
    };
    const handleDelete = (index: number, row: {
    
     id: number; status: number;}) => {
    
     // 删除模态框展示
      console.log(index, row);
      data.delRowId = row.id;
      data.delIndex = index;
      data.upOrDownRowStatus = 3;
      console.log('data.delRowId:', data.delRowId, 'data.upOrDownRowStatus:', data.upOrDownRowStatus);
      data.dialogDelVisible = true;
    };
    const fetchData = async (pageN: number|unknown, pageS: number|unknown) => {
    
     // 分页请求
    //   getCommunitTable({ pageNum: pageN, pageSize: pageS });
      getCommunitSearchList({
    
     pageNum: pageN, pageSize: pageS })
        .then((res) => {
    
    
          console.log('res:', res);
        });
    };
    // 编辑 上传upload图片 --- 手动删除
    const handleRemove = (file: {
    
     raw: {
    
     type: string; size: number; }; }, fileList: unknown) => {
    
    
      console.log(file, fileList);
    };
    // 编辑 上传upload图片 点击上传按钮
    const handlePreview = (file: unknown) => {
    
    
      console.log('file:', file);
    //   handleChangePic(file, FileList);
    };
    // 限制上传文件个数
    const handleExceed = (file: unknown, fileList: unknown) => {
    
    
      console.log('file:', file, 'fileList:', fileList);
      //   this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
      ElMessage.warning({
    
    
        message: '当前限制选择 1 个图片文件文件',
        type: 'warning',
        duration: 2000,
      });
    };
    // 限制上传文件格式为图片资源
    const handleChangePic = (file: {
    
     raw: {
    
     type: string; size: number; }; }, fileList: unknown) => {
    
    
      console.log('file:', file, 'fileList:', fileList);
      const isTypeTrue = /^image\/(jpeg|png|jpg)$/.test(file.raw.type);
      //   console.log('this.refs', this.refs);
      //   eslint-disable-next-line no-mixed-spaces-and-tabs
	  const isLt300K = file.raw.size / 1024 < 300;
      if (!isLt300K) {
    
    
        ElMessage.error({
    
    
          message: '上传图片大小不能超过300K!',
          type: 'error',
          duration: 2000,
        });
        handleRemove(file, fileList);
        // data.my_upload.clearFiles(); // 清除文件对象
        // this.$refs.upload.clearFiles();
        // nextTick((el) => {
    
    
        //   console.log('myUpload:', el);
        //   // console.log('myUpload.clearFiles:', el.clearFiles);
        //   const el1 = { ...el };
        //   console.log('el:', el1);
        //   el1.clearFiles();
        // });
      }
      if (!isTypeTrue) {
    
    
        ElMessage.error({
    
    
          message: '上传图片格式不对',
          type: 'error',
          duration: 2000,
        });
    };
    const clickAppId = (appid: number) => {
    
    
      console.log('appid:', appid);
      // handleChangePic()
      getAppIdApi({
    
     appId: appid })
        .then((res) => {
    
    
          console.log('res111111111111:', res);
          if (res && !res.ret) {
    
    
            ElMessage.success({
    
    
              message: '拉取成功',
              type: 'success',
            });
            data.disableUploadFlag = true; // 上传按钮置灰
          }
        })
        .finally(() => {
    
    
          data.dialogDelVisible = false;
          // return true;
        });
    };
    // 文件上传失败出发的钩子 类型function(err, file, fileList)
    const handleErrorPic = (error: unknown, file: unknown, fileList: unknown) => {
    
    
      console.log('error:', error, 'file:', file, 'fileList:', fileList);
    };
    // handleUpOrDown_ 操作上线-线下点击事件
    const handleUpOrDown = (index: number, row: {
    
     id: number; status: number; }) => {
    
     // 操作上线模态框展示
      console.log(index, row);
      data.delRowId = row.id;
      // eslint-disable-next-line eqeqeq
      if (row.status == 1) {
    
     // 当前1为下线
        data.upOrDownRowStatus = 2;
      // eslint-disable-next-line eqeqeq
      } else if (row.status == 2) {
    
     // 当前2为上线
        data.upOrDownRowStatus = 1;
      }
      console.log('data.delRowId:', data.delRowId, 'data.upOrDownRowStatus:', data.upOrDownRowStatus);
      data.dialogUpOrDownVisible = true;
    };
    onMounted(() => {
    
    
    //   fetchData(data.pageInfo.pageSize);
      watchEffect(() => {
    
    
        // fetchData(data.pageInfo.pageSize);
      });
      handlesearch();
    });
    return {
    
    
      ...refData,      tagsList,
      pageInfo,
      data,
      handleEdit, // 编辑
      handleRemove, // 编辑------上传图片 X取消按钮
      handlePreview, // 编辑------上传upload图片 点击上传按钮
      handleExceed, // 限制上传文件个数
      handleChangePic, // 限制上传文件格式为图片资源
      handleErrorPic, //
      myUpload,
      diffFormData, //  比较差异的方法
      clickEdit, // 编辑模态框 确认按钮
      clickAppId, // appid拉取的图片
      fetchData, // 刷新查询数据信息
    };
  },
  methods: {
    
    
  },
});
</script>

展示效果:
在这里插入图片描述

修改部分内容之后:

在这里插入图片描述
点击【确定】按钮提交表单,
在这里插入图片描述
改变的信息:
在这里插入图片描述
在这里插入图片描述
只提交了修改的表单信息


import {
    
     request } from '@/services';
import {
    
     onMounted, Ref, ref } from 'vue';
import {
    
     AxiosRequestConfig } from 'axios';
import {
    
     AnyObject } from 'element-plus/lib/el-table/src/table.type';

interface pageInfo{
    
    
  // pageNum当前第几页 pageSize每页记录数  total列表总条数  totalPage列表总页数
  pageNum?: number
  //   currentPage?: number
  pageSize?: number
  total?: number
  totalPage?: number
}
interface tableItem{
    
    
  cId?: number
  cName?: string
  cTime?: string
  cIcon?: string
  cStatus?: boolean
  cBuilder?: string
  connectUser?: string
  operator?: string
  operatorTime?: string
}
// 添加用户列表信息
interface userItem{
    
    
  userId?: number
  nickName?: string
  roleId?: number // 检索条件3(非必填):用户类型 2-厂商 3-版主 4-写手
}
interface communitInterface  {
    
    
  pageInfo?: pageInfo
  //   tableList?: Array<tableItem>
  communities?: Array<tableItem>
}
interface userInterface  {
    
    
  pageInfo?: pageInfo
  //   tableList?: Array<tableItem>
  users?: Array<userItem>
}
interface resultInterface<T> {
    
    
  ret: number;
  msg: string;
  data: T;
}
// 获取社区列表
export function getCommunitTable(req: AnyObject): {
    
     pageInfo: Ref<pageInfo>, tableList: Ref<Array<tableItem>> } {
    
    
  const pi = ref<pageInfo>({
    
    });
  const ti = ref<Array<tableItem>>([]);
  onMounted(async () => {
    
    
    const {
    
     data } = await request<AxiosRequestConfig, resultInterface<communitInterface>>({
    
    
    //   url: '/api/community/get_community_list',
      url: '/api/manage/community/batch',
      method: 'get',
      params: {
    
    
        // pageNum: 10,
        // pageSize: 5,
        ...req,
      },
    });
    // pi.value = data?.data.pageInfo || {};
    // ti.value = data?.data.tableList || [];
    pi.value = data?.data.pageInfo || {
    
    };
    ti.value = data?.data.communities || [];
    console.log('communitytList data:', data);
  });
  return {
    
     pageInfo: pi, tableList: ti };
}
// 搜索
export function getCommunitSearchList(req: AnyObject): Promise<unknown> {
    
    
  return request<AxiosRequestConfig, resultInterface<communitInterface>>({
    
    
    url: '/api/manage/community/batch',
    method: 'get',
    params: {
    
    
      ...req,
    },
  });
}
// 删除
export function deleteTableDataApi(req: AnyObject): Promise<resultInterface<communitInterface> | AnyObject> {
    
    
  return request<AxiosRequestConfig, resultInterface<communitInterface>>({
    
    
    url: '/api/manage/community/status',
    method: 'put',
    params: {
    
    
      ...req,
    },
  });
}
// 通过appid拉取图片
interface appInfo{
    
    
  appId?: number
  appName?: string
  icon?: string
}
interface appInfoInterface  {
    
    
  appInfo?: appInfo
}
// 通过appid拉取图片
export function getAppIdApi(req: AnyObject): Promise<resultInterface<appInfoInterface> | AnyObject> {
    
    
  return request<AxiosRequestConfig, resultInterface<appInfoInterface>>({
    
    
    url: '/api/manage/community/appinfo',
    method: 'get',
    params: {
    
    
      ...req,
    },
  });
}

// 社区状态变更 社区删除
// "status": number 社区状态:1-下线,2-上线,3-删除
export function changeStatusApi(req: AnyObject): Promise<resultInterface<communitInterface> | AnyObject> {
    
    
  return request<AxiosRequestConfig, resultInterface<communitInterface>>({
    
    
    url: '/api/manage/community/status',
    method: 'put',
    params: {
    
    
      ...req,
    },
  });
}

//   保存社区接口 ---社区创建、社区编辑
// id为0为创建,id!=0为社区编辑
// "iconSource": number 图标来源、用于前端显示:1-应用图标,2-上传
export function editCommunitApi(req: AnyObject): Promise<resultInterface<communitInterface> | AnyObject> {
    
    
  return request<AxiosRequestConfig, resultInterface<communitInterface>>({
    
    
    url: '/api/manage/community',
    method: 'post',
    params: {
    
    
      ...req,
    },
  });
}
// 查询单个社区信息
export function getOneCommunitApi(req: AnyObject): Promise<resultInterface<tableItem> | AnyObject> {
    
    
  return request<AxiosRequestConfig, resultInterface<tableItem>>({
    
    
    url: '/api/manage/community/',
    method: 'get',
    params: {
    
    
      ...req,
    },
  });
}

// 获取非管理员用户列表-过滤掉C端用户(可条件检索,条件空即检索所有非管理员用户) :创建社区-关联非管理员用户时用
export function getUserListApi(req: AnyObject): Promise<resultInterface<userInterface> | AnyObject> {
    
    
  return request<AxiosRequestConfig, resultInterface<userInterface>>({
    
    
    url: '/api/manage/user/query_non_administrator_list',
    method: 'post',
    params: {
    
    
      ...req,
    },
  });
}

猜你喜欢

转载自blog.csdn.net/weixin_41056807/article/details/114272657