离开页面给提示

2022-11-08  本文已影响0人  糖醋里脊120625
<template>
  <el-main>
    <el-form :model="form.model" :rules="form.rules" ref="form" style="margin-bottom: 56px" v-loading="form.loading"
             label-width="120px">
      <span>基本信息</span>
      <el-divider></el-divider>

      <el-form-item label="采购类型" required>
        <el-radio-group v-model="form.model.purchaseType" @change="onPurchaseTypeChanged">
          <el-radio label="0">市场自采</el-radio>
          <el-radio label="1">供应商采购</el-radio>
        </el-radio-group>
      </el-form-item>

      <el-form-item v-show="isMarketPurchase" label="采购员" prop="purchaserName">
        <el-col :span="8">
          <el-input v-model="form.model.purchaserName"></el-input>
        </el-col>
      </el-form-item>

      <el-form-item v-show="isSupplierPurchase" label="供应商" prop="supplierName">
        <el-col :span="8">
          <SupplierSearcher @change="onSupplierChanged" style="width: 100%" ref="supplierSearcher"
          />
        </el-col>
      </el-form-item>

      <el-form-item label="交货日期" prop="planSupplyDate" required>
        <el-col :span="8">
          <el-date-picker
            style="width: 100%"
            v-model="form.model.planSupplyDate"
            type="date"
            value-format="yyyy-MM-dd"
            @change="onSupplyDateChanged">
          </el-date-picker>
        </el-col>
      </el-form-item>

      <el-form-item label="采购协议" v-if="purchaseAgreementSelect.options.length>0">
        <el-col :span="8">
          <el-select
            style="width: 100%"
            v-model="form.model.purchaseAgreementId" value-key="id"
            placeholder="请选择"
            @change="onPurchaseAgreementChanged"
            clearable>
            <el-option v-for="item in purchaseAgreementSelect.options" :key="item.id" :label="item.name"
                       :value="item.id"
                       style="height: 56px">
              <span style="float: left;display: block;position: relative">{{ item.name }}</span>
              <span
                style="float:left;display: block;position: absolute;margin-top: 20px; color: #8492a6; font-size: 13px">
                {{ item.beginDate | momentFormat('YYYY-MM-DD') }}至{{ item.endDate | momentFormat('YYYY-MM-DD') }}</span>
            </el-option>
          </el-select>
        </el-col>
      </el-form-item>

      <div class="block-margin"></div>
      <div>商品条目</div>
      <el-divider></el-divider>
      <el-form-item prop="itemList" label-width="0px">
        <el-card shadow="never">
          <div slot="header">
            <el-form :inline="true" :model="itemForm.model" ref="itemForm">
              <el-form-item label="品种" prop="product">
                <PurchaseAgreementProductSearcher v-if="isAgreement"
                                                  ref="productSearcher"
                                                  :onSelected="onProductSelected"
                                                  :agreementId="form.model.purchaseAgreementId"/>
                <ProductSearcher v-else ref="productSearcher" :onSelected="onProductSelected"/>
              </el-form-item>

              <el-form-item label="数量" prop="num">
                <el-input v-model="itemForm.model.num"
                          v-input-number.decimal="{decimal:2,min:0}"
                          ref="numInput"
                          @keyup.enter.native="onItemAddBtnClicked"/>
              </el-form-item>

              <el-form-item label="单价" prop="unitPrice">
                <el-input v-model="itemForm.model.unitPrice"
                          v-input-number.decimal="{decimal:2,min:0}"
                          ref="unitPriceInput"
                          :disabled="isAgreement"
                          @keyup.enter.native="onItemAddBtnClicked"/>
              </el-form-item>

              <el-form-item>
                <el-button type="primary" @click="onItemAddBtnClicked">添加
                </el-button>
              </el-form-item>
            </el-form>
          </div>
          <el-table :data="form.model.itemList"
                    show-summary :summary-method="getSummaries">
            <el-table-column type="index" width="50"></el-table-column>

            <el-table-column label="品种">
              <template slot-scope="scope">
                <GoodsItem :imageSrc="scope.row.product.piImageUrl"
                           :name="scope.row.product.piProductName"
                           :spec="scope.row.product.piSpec"
                           :netContent="scope.row.product.piNetContent"
                           :netContentUnit="scope.row.product.piNetContentUnit"
                           :level="scope.row.product.piLevel"/>
              </template>
            </el-table-column>

            <el-table-column label="数量">
              <template slot-scope="scope">
                <el-input @mousewheel.native.prevent v-model="scope.row.num" size="small"
                          v-input-number.decimal="{decimal:2,min:0}"
                          @change="onItemNumPriceChanged(scope.row,'num')"/>
              </template>
            </el-table-column>

            <el-table-column label="单价">
              <template slot-scope="scope">
                <el-input @mousewheel.native.prevent v-model="scope.row.unitPrice" size="small"
                          v-input-number.decimal="{decimal:2,min:0}"
                          :disabled="isAgreement"
                          @change="onItemNumPriceChanged(scope.row,'unitPrice')"/>
              </template>
            </el-table-column>

            <el-table-column label="小计" prop="amount" align="right">
              <!--              <template slot-scope="scope">-->
              <!--                <el-input @mousewheel.native.prevent v-model="scope.row.amount" size="small"-->
              <!--                          v-input-number.decimal="{decimal:2,min:0}"-->
              <!--                          @change="onItemNumPriceChanged(scope.row,'amount')"/>-->
              <!--              </template>-->
            </el-table-column>

            <el-table-column label="备注">
              <template slot-scope="scope">
                <el-input v-model="scope.row.remark" size="small"/>
              </template>
            </el-table-column>

            <el-table-column label="操作" width="100" align="center">
              <template slot-scope="scope">
                <el-button size="small" type="danger" @click="onItemDeleteClicked(scope.$index)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </el-form-item>

      <el-form-item label-width="0px">
        <el-input type="textarea" v-model="form.model.remark" placeholder="备注"/>
      </el-form-item>

    </el-form>
    <div class="el-main_foot_fixed">
      <el-button @click="back">取消</el-button>
      <el-button type="primary" v-loading="submitLoading" @click="onSubmitBtnClicked">提交</el-button>
      <el-button type="primary" plain @click="onStagingBtnClicked" v-if="!isUpdateStatus">暂存</el-button>
    </div>
  </el-main>
</template>

<script>
import ProductSearcher from "../../components/business/ProductSearcher";
import PurchaseAgreementProductSearcher from "../../components/business/PurchaseAgreementProductSearcher";
import GoodsItem from "../../components/common/GoodsItem";
import SupplierSearcher from "../../components/business/SupplierSearcher";

import purchaseAgreementApi from "../../service/api/purchase-agreement-api";
import selfPurchaseOrderApi from "../../service/api/self-purchase-order-api";

import {centToYuan, yuanToCent} from "../../utils/priceUtil";
import {Decimal} from "decimal.js";

const MODEL_CACHE_KEY = "self-purchase-order/form/model";

export default {
  components: {
    SupplierSearcher,
    PurchaseAgreementProductSearcher,
    ProductSearcher, GoodsItem
  },

  data() {
    return {
      form: {
        model: {
          id: '',
          purchaserName: '',
          purchaseType: '0',
          supplierName: '',
          supplierId: '',
          purchaseAgreementId: '',
          planSupplyDate: '',
          itemList: [],
          remark: '',
        },
        modelBackup: '',
        rules: {
          purchaseType: [
            {required: true, message: "请选择采购类型", trigger: "change"}
          ],
          planSupplyDate: [
            {required: true, message: "请选择交货日期", trigger: "change"}
          ],
          itemList: [
            {required: true, message: "商品条目不可为空"}
          ],
        },
        modelInitialValue: '',
        loading: false
      },
      itemForm: {
        model: {
          product: '',
          unitPrice: '',
          num: '',
        }
      },
      purchaseAgreementSelect: {
        options: []
      },
      submitLoading: false,
      isUpdateStatus: false,
    }
  },

  computed: {
    isAgreement: function () {
      return this.form.model.purchaseAgreementId !== '';
    },

    isMarketPurchase: function () {
      return this.form.model.purchaseType === '0';
    },

    isSupplierPurchase: function () {
      return this.form.model.purchaseType === '1';
    },

    pageHasBeenEdited: function () {
      return this.form.modelInitialValue !== JSON.stringify(this.form.model);
    }
  },

  watch: {
    'form.model.purchaseType'(newValue, oldValue) {
      this.backupFormData('purchaseType', oldValue);
    },

    'form.model.planSupplyDate'(newValue, oldValue) {
      this.backupFormData('planSupplyDate', oldValue);
    },

    'form.model.purchaseAgreementId'(newValue, oldValue) {
      this.backupFormData('purchaseAgreementId', oldValue);
    },
  },

  created() {
    this.id = this.$route.query.id;
  },

  mounted() {
    let id = this.$route.query.id;
    if (id) {
      this.isUpdateStatus = true;
      this.loadDetail(id);
    } else {
      this.restoreTemporaryData();
    }
  },

  methods: {
    loadDetail(id) {
      this.form.loading = true;
      selfPurchaseOrderApi.get(id)
        .then(value => {
          this.setValueToView(value)
        }).finally(() => {
        this.form.loading = false;
      });
    },

    loadPurchaseAgreements(supplierName, supplyDate) {
      // 获取且协议,并判断是否协议的数据源改变了
      purchaseAgreementApi.search({keyword: supplierName, queryDate: supplyDate, pageIndex: 1, pageSize: 20})
        .then(value => {

          // 数据源不包含当前选择的协议的情况弹出确认窗口
          let noCurrentAgreement = this.purchaseAgreementSelect.options.length > 0
            && !value.list.some(item => item.id === this.form.model.purchaseAgreementId);

          if (noCurrentAgreement && this.form.model.itemList.length > 0) {
            this.alertClearConfirm(() => {
              this.purchaseAgreementSelect.options = value.list;
              this.form.model.purchaseAgreementId = '';
            })
          } else {
            this.purchaseAgreementSelect.options = value.list;
          }
        })
    },

    alertClearConfirm(confirm) {
      this.$confirm('协议发生改变,当前商品条目将被清空', '是否继续', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        // 清空商品条目
        this.form.model.itemList = [];
        confirm();
      }).catch(() => {
        this.restoreBackupFormData();
      })
    },

    setValueToView(value) {
      this.form.model = this.$clone(value);
      this.form.model.purchaseType = this.form.model.purchaseType + "";
      this.form.model.itemList = value.itemList.map(el => {
        return {
          product: el.productInfo,
          unitPrice: centToYuan(el.unitPrice),
          num: el.actualPurchaseNum,
          amount: centToYuan(el.amount),
          remark: el.remark,
        };
      });

      if (this.isSupplierPurchase) {
        this.$refs['supplierSearcher'].setValue({
          id: this.form.model.supplierId,
          name: this.form.model.supplierName,
        });

        this.loadPurchaseAgreements(this.form.model.supplierName, this.form.model.planSupplyDate);
      }

      this.initModelInitialValue();
    },

    onSupplierChanged(value) {
      this.backupFormData();
      this.form.model.supplierName = value.name;
      this.form.model.supplierId = value.id;
      this.loadPurchaseAgreements(this.form.model.supplierName, this.form.model.planSupplyDate)
    },

    onPurchaseTypeChanged(val) {
      if (this.isMarketPurchase) {// 切换到市场采购
        let change = () => {
          this.purchaseAgreementSelect.options = [];
          this.form.model.purchaseAgreementId = '';
          this.form.model.supplierId = '';
          this.form.model.supplierName = '';
          this.$refs['supplierSearcher'].setValue({});
        }
        if (JSON.stringify(this.purchaseAgreementSelect.options) !== JSON.stringify([])
          && this.form.model.itemList.length > 0) {
          this.alertClearConfirm(change);
        } else {
          change();
        }
      } else {// 供应商采购
        this.form.model.purchaserName = '';
      }
    },

    onSupplyDateChanged(val) {
      if (this.isSupplierPurchase) {
        this.loadPurchaseAgreements(this.form.model.supplierName, this.form.model.planSupplyDate);
      }
    },

    onProductSelected(item) {
      this.itemForm.model.product = item.obj;

      if (this.isAgreement) {
        this.itemForm.model.unitPrice = item.obj.unitPrice;
      }

      this.$nextTick(() => {
        this.$refs['numInput'].focus();
      })
    },

    onPurchaseAgreementChanged(value) {
      if (this.form.model.itemList.length > 0) {
        this.alertClearConfirm(() => {
          // nothing to do
        });
      }
    },

    onItemAddBtnClicked() {
      let item = this.$clone(this.itemForm.model);
      if (!item.product) {
        this.$message.error("请选择品种");
        return;
      }

      if (!item.num || item.num < 0) {
        this.$message.error("请输入正确数量");
        return;
      }

      if (!item.unitPrice || item.unitPrice < 0) {
        this.$message.error("请输入正确价格");
        return;
      }

      if (this.checkItemExist(item)) {
        this.$message.error("已存在相同品种");
        return;
      }

      item.amount = Decimal.mul(item.num, item.unitPrice).toFixed(2, Decimal.ROUND_DOWN);

      this.form.model.itemList.push(item);
      this.$refs['itemForm'].resetFields();
      this.$refs['unitPriceInput'].blur();
      this.$refs['numInput'].blur();
      this.$refs.productSearcher.clearSelected();
    },

    onItemDeleteClicked(index) {
      this.form.model.itemList.splice(index, 1);
    },

    onItemNumPriceChanged(row, type) {
      switch (type) {
        case 'amount':
          row.unitPrice = Decimal.div(row.amount, row.num).toFixed(2, Decimal.ROUND_DOWN);
          break
        default:
          row.amount = Decimal.mul(row.num, row.unitPrice).toFixed(2, Decimal.ROUND_DOWN);
          break
      }
    },

    checkItemExist(item) {
      if (this.form.model.itemList <= 0) {
        return false;
      }

      return this.form.model.itemList.some(el => {
        return el.product.piId === item.product.piId
      })
    },

    getSummaries(param) {
      const {columns, data} = param;
      const sums = [];
      columns.forEach((column, index) => {
        if (index === 0) {
          sums[index] = "合计";
          return
        }

        if (index === 4) {
          const values = data.map(item => Number(item[column.property]));
          sums[index] = values.reduce((prev, curr) => {
            const value = Number(curr);
            if (!isNaN(value)) {
              return prev + curr;
            } else {
              return prev;
            }
          }, 0);

          sums[index] = sums[index].toFixed(2);
        }
      });
      return sums;
    },

    onStagingBtnClicked() {
      sessionStorage.setItem(MODEL_CACHE_KEY, JSON.stringify(this.form.model));
      this.initModelInitialValue();
      this.$message.success("暂存成功");
    },

    restoreTemporaryData() {
      let value = sessionStorage.getItem(MODEL_CACHE_KEY);
      if (value) {
        this.form.model = JSON.parse(value);

        if (this.isSupplierPurchase) {
          this.$refs['supplierSearcher'].setValue({
            id: this.form.model.supplierId,
            name: this.form.model.supplierName,
          });

          this.loadPurchaseAgreements(this.form.model.supplierName, this.form.model.planSupplyDate);
        }
      }

      this.initModelInitialValue()
    },

    clearTemporaryData() {
      sessionStorage.removeItem(MODEL_CACHE_KEY);
    },

    initModelInitialValue() {
      this.form.modelInitialValue = JSON.stringify(this.form.model);
    },

    back() {
      this.$router.back();
    },

    onSubmitBtnClicked() {
      this.$refs.form.validate((valid) => {
        if (!valid) {
          return false;
        }

        // 转换视图的明细为参数需要的明细
        let items = this.form.model.itemList.map(value => {
          return {
            productId: value.product.piId,
            unitPrice: yuanToCent(value.unitPrice),
            num: value.num,
            remark: value.remark,
          }
        })

        let model = this.$clone(this.form.model);
        model.itemList = items;

        this.submitLoading = true;
        let promise = model.id ? selfPurchaseOrderApi.update(model) : selfPurchaseOrderApi.add(model);
        promise.then(value => {
          this.$message.success("提交成功");
          // 为了跳过离开页面时的验证
          this.initModelInitialValue();

          // 新增成功的情况下清除缓存
          if (model.id === '') {
            this.clearTemporaryData();
          }

          this.back();
        }).finally(() => {
          this.submitLoading = false;
        })
      })
    },

    backupFormData(property, oldValue) {
      let modelClone = this.$clone(this.form.model);
      if (property) {
        modelClone[property] = oldValue;
      }

      this.form.modelBackup = JSON.stringify(modelClone);
    },

    restoreBackupFormData() {
      this.form.model = JSON.parse(this.form.modelBackup);

      let supplierSearcherValue = {
        id: this.form.model.supplierId,
        name: this.form.model.supplierName,
      }

      this.$refs['supplierSearcher'].setValue(supplierSearcherValue);
    },

    alertDataChangeConfirm(confirm, cancel) {
      if (this.pageHasBeenEdited) {
        this.$confirm('数据发生改变,是否离开?', {
          confirmButtonText: '考虑一下',
          cancelButtonText: '直接离开',
          type: 'warning'
        }).then(confirm).catch(cancel);
      } else {
        cancel();
      }
    }
  },

  beforeRouteLeave(to, from, next) {
    next(false);
    setTimeout(() => {
      this.alertDataChangeConfirm(() => {
      }, () => {
        next()
      });
    }, 200);
  }
}
</script>

<style lang="less" scoped>
.el-card {
  .el-form-item {
    margin-bottom: 0;
  }

  .el-card__header {
    background: #F5F7FA;
  }
}

.el-divider--horizontal {
  margin: 10px 0 20px;
}

.block-margin {
  height: 22px;
}

</style>

上一篇下一篇

猜你喜欢

热点阅读