modal-create-coupon.vue 9.73 KB
<template>
  <i-modal v-model="visiable" :loading="posting" :title="readonly ? '查看优惠券' : '创建/编辑优惠券'" @on-ok="onOk" width="600">
    <i-spin v-if="loading"></i-spin>
    <i-form v-else ref="formCoupon" :rules="ruleValidate" :model="formData" :label-width="80">
      <i-form-item class="form-group" label="基本信息"></i-form-item>
      <i-form-item label="Token" v-if="couponToken">
        {{couponToken}}
      </i-form-item>
      <i-form-item label="名称" prop="couponName">
        <i-input placeholder="名称建议30字以内" v-model="formData.couponName" :disabled="readonly" style="width: 200px"></i-input>
      </i-form-item>
      <i-form-item label="数量" prop="couponNum">
        <i-input-number placeholder="数量" v-model="formData.couponNum" :disabled="readonly" style="width: 100px;"></i-input-number>
      </i-form-item>
      <i-form-item label="使用次数" prop="useNum">
        <i-input placeholder="使用次数" v-model="formData.useNum" disabled style="width: 100px;"></i-input>
      </i-form-item>
      <i-form-item label="使用期限" prop="time">
        <i-date-picker type="datetimerange" v-model="formData.time" :disabled="readonly" placeholder="使用期限" format="yyyy-MM-dd HH:mm" style="width: 250px"></i-date-picker>
      </i-form-item>
      <i-form-item label="优惠券说明" prop="remark">
        <i-input type="textarea" placeholder="优惠券使用条件简介" :disabled="readonly" v-model="formData.remark"></i-input>
      </i-form-item>
      <i-form-item class="form-group" label="使用条件"></i-form-item>
      <i-form-item label="优惠条件" prop="useLimitType" style="display: inline-block; width: 100%">
        <i-select style="width: 100px" :disabled="readonly" v-model="formData.useLimitType">
          <i-option :value="0">无限制</i-option>
          <i-option :value="2">金额</i-option>
        </i-select>
        <div style="display: inline-block" v-if="formData.useLimitType === 2">
          &nbsp;
          金额满:
          <i-input-number style="width: 100px" :disabled="readonly" placeholder="限制金额" v-model="formData.useLimitValue">
          </i-input-number>
        </div>
      </i-form-item>
      <i-form-item label="优惠金额" prop="couponAmount">
        <i-input-number placeholder="优惠金额" :disabled="readonly" v-model="formData.couponAmount" style="width: 100px">
        </i-input-number>
      </i-form-item>
      <i-form-item label="适用范围(指定商品)" prop="productLimitValue">
        <i-input type="textarea" :disabled="readonly" placeholder="填写商品编码,多个商品编码用英文逗号分隔" v-model="formData.productLimitValue"></i-input>
        <i-poptip trigger="hover">
          <div slot="content">
            <p>1.上传文件必须是xlsx文件</p>
            <p>2.第一行标题栏:商品编码</p>
            <p>3.<a href="javascript:;" @click="onExample">下载样例</a></p>
          </div>
          <i-upload action="" :format="['xlsx']" :max-size="1024" :before-upload="onBeforeUpload">
            <i-button type="success" size="small" :disabled="readonly">导入</i-button>
            <p>{{uploadTxt}}</p>
          </i-upload>
        </i-poptip>
        
      </i-form-item>
    </i-form>
  </i-modal>
</template>

<script>
import Api from 'api/api';
import dayjs from 'dayjs';
import xlsx from 'xlsx';

const api = new Api();

export default {
  name: 'ModalCreateCoupon',
  data() {
    return {
      readonly: false,
      visiable: false,
      loading: false,
      posting: true,
      uploadTxt: '',
      couponToken: '',
      formData: {
        id: 0,
        couponName: '',
        couponNum: 0,
        useNum: 1,
        couponAmount: 0,
        useLimitType: 0,
        remark: '',
        productLimitValue: '',
        useLimitValue: 0,
        time: ['', '']
      },
      ruleValidate: {
        couponName: {required: true, max: 30, message: '请输入名称'},
        couponNum: {type: 'number', required: true, min: 1, message: '请输入数量'},
        couponAmount: {type: 'number', required: true, min: 1, message: '请输入优惠金额'},
        time: {required: true, validator: (rule, value, callback) => {
          if (value.some(v => !v)) {
            callback(new Error('请选择使用期限'));
          } else {
            callback();
          }
        }},
        remark: {required: true, message: '请输入优惠券说明'},
        useLimitType: {required: true, validator: (rule, value, callback) => {
          if (value >= 0) {
            if (value === 2) {
              if (parseInt(this.formData.useLimitValue) > 0) {
                callback();
              } else {
                callback(new Error('请输入限制金额'));
              }
            } else {
              callback();
            }
          } else {
            callback(new Error('请选择优惠条件'));
          }
        }},
        productLimitValue: {required: true, validator: (rule, value, callback) => {
          const ids = (value || '').split(',');

          if (!value || !ids.length) {
            callback(new Error('请输入适用范围'));
          } else if(ids.some(id => id ? !parseInt(id) : false)) {
            callback(new Error('适用范围格式错误'));
          } else {
            callback();
          }
        }},
      }
    };
  },
  methods: {
    async show(id, readonly) {
      this.readonly = readonly;
      this.posting = this.visiable = true;
      this.$refs.formCoupon.resetFields();
      let initData = {
        id: 0,
        couponName: '',
        couponNum: 0,
        useNum: 1,
        couponAmount: 0,
        useLimitType: 0,
        remark: '',
        productLimitValue: '',
        useLimitValue: 0,
        time: ['', '']
      };

      if (id) {
        this.loading = true;
        const result = await api._get('/ufoPlatform/coupon/getCouponInfo', {
          id
        });
        this.loading = false;

        if (result.code === 200) {
          const coupon = result.data.coupon;

          this.couponToken = coupon.couponToken;
          initData = {
            id,
            couponName: coupon.couponName,
            couponNum: coupon.couponNum,
            useNum: coupon.useNum,
            couponAmount: coupon.couponAmount,
            useLimitType: coupon.useLimitType,
            remark: coupon.remark,
            productLimitValue: coupon.productLimitValue,
            useLimitValue: coupon.useLimitValue,
            time: [dayjs.unix(coupon.startTime).format('YYYY-MM-DD HH:mm:ss'), dayjs.unix(coupon.endTime).format('YYYY-MM-DD HH:mm:ss')]
          };
        } else {
          result.message && this.$Message.warning(result.message);
        }
      }
      this.formData = initData;
    },
    onOk() {
      this.$refs.formCoupon.validate(valid => {
        if (!valid) {
          this.posting = false;
          this.$nextTick(() => {
            this.posting = true;
          });
        } else {
          this.saveData(this.formData);
        }
      });
    },
    async saveData(params) {
      if (this.readonly) {
        this.visiable = false;
        return;
      }
      const result = await api._post('/ufoPlatform/coupon/saveOrUpdateCoupon', {
        id: params.id || void 0,
        couponName: params.couponName,
        couponAmount: params.couponAmount,
        couponNum: params.couponNum,
        useNum: params.useNum,
        useLimitValue: params.useLimitValue,
        productLimitValue: params.productLimitValue,
        remark: params.remark,
        useLimitType: parseInt(params.useLimitType) >= 0 ? params.useLimitType : void 0,
        startTime: params.time[0] ? dayjs(params.time[0]).unix() : void 0,
        endTime: params.time[1] ? dayjs(params.time[1]).unix() : void 0,
      });

      if (result.code === 200) {
        this.$Message.success('保存成功');
        this.visiable = false;
        this.$emit('on-created');
      } else {
        result.message && this.$Message.warning(result.message);
        this.posting = false;
        this.$nextTick(() => {
          this.posting = true;
        });
      }
    },
    onBeforeUpload(file) {
      const fileExt = file.name.split('.').pop().toLocaleLowerCase();
      if (fileExt !== 'xlsx') {
        this.$Message.warning('文件格式错误');
        return false;
      }
      if (file.size > 1024 * 1024) {
        this.$Message.warning('文件大小超过1M');
        return false;
      }
      const reader = new FileReader();

      reader.readAsArrayBuffer(file);
      reader.onloadstart = () => {
        this.uploadTxt = '开始读取';
      };
      reader.onprogress = e => {
        this.uploadTxt = `进度:${Math.round(e.loaded / e.total * 100)}...`;
      };
      reader.onerror = () => {
        this.uploadTxt = '文件读取出错';
      };
      reader.onload = e => {
        this.uploadTxt = '';
        try {
          const data = e.target.result;
          const workbook = xlsx.read(data, { type: 'array' });
          const firstSheetName = workbook.SheetNames[0];
          const worksheet = workbook.Sheets[firstSheetName];
          const results = xlsx.utils.sheet_to_json(worksheet);

          this.formData.productLimitValue = results.map(r => r['商品编码']).filter(r => r).join(',');

        } catch (error) {
          this.uploadTxt = '文件解析失败,请按照格式上传';
        }
        

      };
      return false;
    },
    onExample() {
      const wb = xlsx.utils.book_new();
      const ws = xlsx.utils.json_to_sheet([{
        '商品编码': '123456'
      }]);
      xlsx.utils.book_append_sheet(wb, ws, '优惠券适用范围示例');
      xlsx.writeFile(wb, '优惠券适用范围示例.xlsx');
    }
  }
};
</script>

<style lang="scss" scoped>
.form-group {
  width: 100%;
  height: 30px;
  background-color: #f5f7f9;
}
</style>