vue组件化开发之清单的增删改查

191 阅读1分钟

一,父组件-清单列表页(说明:这里的清单列表页也是一个子组件,可以请看示例图)

<template>
  <div id="engineeringList">
    <transition name="screening-box">
      <div class="screening-box" v-show="options.isShow" @click.stop="setShow">
        <!--  -->
        <div
          class="screening-box"
          v-show="options.isShow"
          @click.stop="setShow"
        >
          <transition name="screening">
            <div class="screening" v-if="options.isShow" @click.stop>
              <!-- 头部 -->
              <div class="screening-header">
                {{
                  options.editMode == "edit" ? "工程量编辑" : "工程量清单查看"
                }}
                <i
                  class="ifca-iconfont ifca-icon-gengduo-left"
                  @click="setShow"
                ></i>
              </div>
              <div class="box-content">
                <!-- 中间内容 -->
                <div
                  class="content-class"
                  v-for="(item, i) in options.dataSource"
                  :key="i"
                  @click.stop="editClick(item, i)"
                >
                  <div
                    class="projectlist"
                    v-if="item.dataRowState != 'Deleted'"
                  >
                    <div class="projectTitle">
                      <div class="left">工程量清单{{ i + 1 }}</div>
                      <i
                        v-if="options.editMode != 'view'"
                        class="right iconfont icon-lajixiang"
                        @click.stop="deleteClick(item, i)"
                      ></i>
                    </div>
                    <div class="projectContent">
                      <div class="contentOne">
                        <span class="titleColor">内容:</span>
                        <span>{{ item.content }}</span>
                      </div>
                      <div class="contentTwo">
                        <div class="subtitle">
                          <span class="titleColor">单位:</span>
                          <span>{{ item.unitOfMeasurement }}</span>
                        </div>
                        <div class="subtitle">
                          <span class="titleColor">工程量:</span>
                          <span>{{ item.quantities }}</span>
                        </div>
                      </div>
                      <div class="contentTwo">
                        <div class="subtitle">
                          <span class="titleColor">单价:</span>
                          <span>{{ item.comprehensiveAmt }}</span>
                        </div>
                        <div class="subtitle">
                          <span class="titleColor">总价:</span>
                          <span>{{ item.sumComprehensiveAmt }}</span>
                        </div>
                      </div>
                      <div class="contentTwo">
                        <div class="subtitle">
                          <span class="titleColor">税率:</span>
                          <span>{{ item.taxTotalAmtName.key }}</span>
                        </div>
                        <div class="subtitle">
                          <span class="titleColor">税额:</span>
                          <span>{{ item.taxRate }}</span>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
                <!-- 添加清单 -->
                <div
                  class="addJect"
                  @click="addClick"
                  v-if="options.editMode != 'view'"
                >
                  <span class="icon">+</span>
                  <span>添加工程量清单</span>
                </div>
              </div>

              <!-- 底部按钮 -->
              <div class="button-box">
                <div
                  class="buttonClass defaultButtonClass"
                  @click="buttonClick('cancel')"
                >
                  关闭
                </div>
                <div
                  class="buttonClass primaryButtonClass"
                  @click="buttonClick('save')"
                  v-if="options.editMode != 'view'"
                >
                  保存
                </div>
              </div>
            </div>
          </transition>
        </div>
      </div>
    </transition>

    <!-- 工程清单新增底部滑块 -->
    <engineeringEdit
      v-if="engineeringEditOptions.isShow"
      :options="engineeringEditOptions"
      @callBack="formCallBack"
    ></engineeringEdit>
  </div>
</template>

<script>
import engineeringEdit from "./engineeringEdit";
export default {
  components: {
    engineeringEdit,
  },
  props: {
    // 接受父组件传过来的值
    options: {
      type: Object,
      default: {
        isShow: false,
        // 注意: editMode属性有两个值:
        // "view"不能新增修改删除只有查看功能  
        // "edit"可以新增修改删除
        editMode: "view",
        // dataSource后台给到的清单列表数据
        dataSource: [],
      },
    },
  },
  data() {
    return {
      // 传给子组件的数据
      engineeringEditOptions: {
        isShow: false,
        item: {},
      },
      engineeringEditIndex: -1,
      listData: []
    };
  },
  created() {
     // 深拷贝数据给到listData
    this.listData = JSON.parse(JSON.stringify(this.options.dataSource))
  },
  methods: {
    setShow() {
      this.options.isShow = !this.options.isShow;
    },

    /**
     * 按钮点击事件
     * type :   取消 cancel ; 保存  save
     */
    buttonClick(type) {
      if (type == "save") {
        this.$emit("callBack", JSON.stringify(this.listData));
      }
      this.setShow();
    },
    /**
     * 点击新增工程清单事件
     */
    addClick() {
      //重置下标
      this.engineeringEditIndex = -1;
      //格式化数据
      this.engineeringEditOptions.item = {
        // dataRowState默认是新增数据
        dataRowState: "Added",
        content: "",
        unitOfMeasurement: "",
        quantities: "",
        comprehensiveAmt: "",
        sumComprehensiveAmt: 0,
        taxTotalAmt: 0,
        taxTotalAmtName: {},
        taxRate: 0,
      };
      this.engineeringEditOptions.isShow = true;
    },
    // 新增回调(这里新增保存和修改保存是一个回调,根据engineeringEditIndex来判断)
    formCallBack(formData) {
      let dataList = JSON.parse(formData);
      // 只要engineeringEditIndex不是-1 它就是修改数据!
      // 然后把子组件传过来的dataList替换掉options.dataSource中的那条数据!!
      // 否则就是新增数据,直接push到options.dataSource中
      if (this.engineeringEditIndex > -1) {
        this.listData[this.engineeringEditIndex] = dataList;
      } else {
        this.listData.push(dataList);
      }
    },
    // 删除
    deleteClick(item, index) {
      // 如果是新增数据直接可以删除
      if (item.dataRowState == "Added")
        this.listData.splice(index, 1);
      else {
        item.dataRowState = "Deleted";
      }
    },
    // 编辑
    editClick(item, i) {
      //记录当前编辑数据的下标,以便编辑完后,直接替换原数据
      this.engineeringEditIndex = i;
      // 如果dataRowState == "Unchanged"则把dataRowState改为修改状态
      if (item.dataRowState == "Unchanged") item.dataRowState = "Modified";
      this.engineeringEditOptions.item = item;
      this.engineeringEditOptions.isShow = true;
    },
  },
};
</script>

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

二,子组件(添加和修改页面)

<template>
  <div id="engineeringEdit">
    <ifca-popup-balck
      v-model="options.isShow"
      @on-show="onShow"
      @on-hide="onHide"
      maxHeight="90%"
      :headerShow="true"
      head-title="新增工程量清单"
      @on-click-left="show = false"
    >
      <div class="formContent">
        <!-- 表单 -->
        <ifca-form @submit="submit" :formItem="formItem">
          <ifca-form-cell
            title="内容:"
            v-model="formData.content"
            :required="true"
            :input="true"
            :activeOff="true"
            :autofocus="true"
            :isLink="false"
          ></ifca-form-cell>
          <ifca-form-cell
            title="单位:"
            v-model="formData.unitOfMeasurement"
            :required="true"
            :input="true"
            :activeOff="true"
            :autofocus="true"
            :isLink="false"
          ></ifca-form-cell>
          <ifca-form-cell
            title="工程量:"
            v-model="formData.quantities"
            :required="true"
            inputType="number"
            :input="true"
            :activeOff="true"
            :autofocus="true"
            :isLink="false"
            name="myUnit"
            @on-change="numberChange"
          ></ifca-form-cell>
          <ifca-form-cell
            title="单价:"
            v-model="formData.comprehensiveAmt"
            :required="true"
            inputType="number"
            :input="true"
            :activeOff="true"
            :autofocus="true"
            :isLink="false"
            name="myUnit"
            @on-change="numberChange"
          ></ifca-form-cell>
          <ifca-form-cell
            title="总价:"
            v-model="formData.sumComprehensiveAmt"
            inputType="number"
            :input="false"
            :activeOff="true"
            :autofocus="true"
            :isLink="false"
            name="myUnit"
          ></ifca-form-cell>
          <ifca-form-radio
            title="税率:"
            v-model="formData.taxTotalAmtName"
            name="税率"
            :required="true"
            placeholder="请选择税率"
            :list="taxRateList"
            @on-change="taxRateChange"
          ></ifca-form-radio>
          <ifca-form-cell
            title="税额:"
            v-model="formData.taxRate"
            :input="false"
            :activeOff="true"
            :autofocus="true"
            :isLink="false"
            name="myUnit"
          ></ifca-form-cell>
        </ifca-form>
        <!-- 按钮信息 -->
        <div class="button-box">
          <div class="buttonClass defaultButtonClass" @click="closelClick()">
            关闭
          </div>
          <div class="buttonClass primaryButtonClass" @click="confirmClick()">
            确认
          </div>
        </div>
      </div>
    </ifca-popup-balck>
  </div>
</template>

<script>
import { calculationAmt } from "@/assets/js/formatData.js";
export default {
  props: {
    // 接受父组件传过来的值
    options: {
      type: Object,
      default: {
        isShow: false,
        editMode: "view",
        item: {
          dataRowState: "Added",
          content: "",
          unitOfMeasurement: "",
          quantities: "",
          comprehensiveAmt: "",
          sumComprehensiveAmt: 0,
          taxTotalAmt: 0,
          taxTotalAmtName: {},
          taxRate: 0,
        },
      },
    },
  },
  data() {
    return {
      // 税率
      taxRateList: [],
      //表单数据
      formData: {},
    };
  },

  created() {
    this.getTaxData();
    // 注意!!!这里当组件打开时会把options.item数据给到formData中,让它显示!
    this.formData = JSON.parse(JSON.stringify(this.options.item));
  },
  methods: {
    onShow() {},
    onHide() {},
    // 关闭
    closelClick() {
      this.options.isShow = false;
    },
    // 确认
    confirmClick() {
      if (!this.checkData()) {
        return;
      }
      console.log(1111, this.formData);
      this.options.isShow = false;
      // 传值给父组件
      this.$emit("callBack", JSON.stringify(this.formData));
    },
    // 表单校验
    checkData() {
      if (!this.formData.content) {
        this.messageAlert("内容不能为空");
        return false;
      }
      if (!this.formData.unitOfMeasurement) {
        this.messageAlert("单位不能为空");
        return false;
      }
      if (!this.formData.quantities) {
        this.messageAlert("工程量不能为空");
        return false;
      }
      if (!this.formData.comprehensiveAmt) {
        this.messageAlert("单价不能为空");
        return false;
      }
      if (!this.formData.taxTotalAmtName.value) {
        this.messageAlert("请选择税率");
        return false;
      }
      return true;
    },
    messageAlert(content) {
      $ifcaPopup.tips({ content: content, time: 1500 });
    },
  },
};
</script>

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

三,说明:前端这边每次操作(新增,修改,删除)都会给数据添加对应的状态,这样做会告诉后台这个列表里哪些数据是新增或修改或删除的!!!

四,示例图

微信图片_20210321133759.png

微信图片_20210321133835.png

微信图片_20210321133950.png