前端学习笔记(一)

前端学习笔记(一)

1. 输入框限制

<template>
  <el-form-item label="周数">
     <el-input
	  placeholder="请输入周数"
	  // 限制输入框条件:如果输入一位数只能输入1-9,其他情况可以输入任意正整数
	  oninput="if(this.value.length==1){this.value=this.value.replace(/[^1-9]/g,'')}else{this.value=this.value.replace(/\D/g,'')}"
	  clearable   // 清除按钮
	  v-model="params.weekNum"
	  type="number" // 显示调整增减标签
	  min="1" // 调整增减标签最小值为1
	  ></el-input>
  </el-form-item>
</template>

2、通过v-if判断组件是否显示,true为显示

<template>
  <el-form-item v-if="is_sales_director">
    <el-radio-group v-model="radioInput" class="radio-style">
	  <el-radio label="PERSONAL">个人</el-radio>
	  <el-radio label="SUBORDINATE">下属</el-radio>
	</el-radio-group>
  </el-form-item>
</template>

<script>
export default {
  data() {
	 return {
	   is_sales_director: false,  // 定义初始化为false
	 }
  }
}
</script>

3、选择框内默认选本年年份

<el-form-item label="年份">
   <el-date-picker v-model="params.year" type="year" placeholder="选择年份">
   </el-date-picker>
</el-form-item>

<script>
export default {
  methods() {
	 initInput {
	   const nowDate = new Date(); // 获取当前日期
       const nowYear = nowDate.getFullYear(); // 获取当前年份
       this.params.year = nowYear + ''; // 加上''才显示当前年份,否则为1970
	 }
  }
}
</script>

4、添加watch监听

<script>
export default {
  watch: {
    /** 监听项目预算,如果项目预算发生改变,将软件预算和硬件预算置空 */
    'forms.prjInfo.budget': {
      handler: function() {
        this.forms.prjInfo.hardwareBudget = '';
        this.forms.prjInfo.softwareBudget = '';
      }
    },
    /** 监听软件预算,如果软件预算发生改变,硬件预算也修改 */
    'forms.prjInfo.softwareBudget': {
      handler: function(softwareBudget) {
        this.forms.prjInfo.hardwareBudget = this.forms.prjInfo.budget - softwareBudget;
      }
    },
  }
}
</script>

5、通过@change或@input监听实现方法

<template>
	<el-form-item label="软件预算" prop="softwareBudget">
	   <el-input
	    :disabled="is_editable"
	    type="number"
	    @change="countBudget(slotProps.tabs)"  // 传入slotProps.tabs表单
	    //@input="countBudget(slotProps.tabs)" 使用change响应点击输入框才会变更数据,如果使用input方法则输入框中数据会实时变更(一修改别的对话框立马变更)
	    placeholder="软件预算"
	    v-model.number="slotProps.tabs.softwareBudget" // 为slotProps.tabs表单下的softwareBudget属性
	    >
	    <template slot="append">万元</template>
	   </el-input>
	</el-form-item>
</template>

<script>
export default {
  methods: {
  // 当软件预算输入框输入数据的时候,传入的val表单下softwareBudget属性和hardwareBudget 属性都初始化
  changeBudget(val) {
      val.softwareBudget = '';
      val.hardwareBudget = '';
    },
  }
}
</script>

6、通过computed监视点击是“编辑”还是“查看”,点击编辑可以进行修改,查看无法修改

(1)子页面代码:
<el-row>
   <el-col :span="24">
      <el-form-item label="本周总结" prop="workSummary">
        <el-input
          type="textarea"
          maxlength="256"
          :autosize="{ minRows: 3, maxRows: 4 }"
          placeholder="本周总结"
          v-model="forms.week.workSummary"
          :disabled="is_edit" // 5.引用方法名为is_edit的方法
        ></el-input>
      </el-form-item>
   </el-col>
</el-row>

<script>
export default {
  name: 'popup-customer', // *@AAAAA*
  components: { [TableWeekdtl.name]: TableWeekdtl },
  props: {
  // 3.从父页面中拿到这个整个包括各种属性的对象,用customer_info命名去调属性
    customer_info: {  
      type: Object,
      default: () => {}
    }
  },
  
computed: {  // 监视
    // 是否为查看
    is_edit() {
    // 4.通过获取customer_info对象调showPage属性,点击编辑传入'edit',点击查看传入'show'
      console.log(this.customer_info.showPage); 
      return this.customer_info.showPage === 'show'; 
    }
  },
</script>
(2)父页面代码
<template>
  <div class="layout vflex" v-loading="loading" v-keydown:search="'enter'">
    <el-dialog
      :visible.sync="is_show_addDialog"
      :title="dialogTitle"
      class="send-dialog"
      v-dialogDrag
      :before-close="close"
      :close-on-click-modal="false"
      custom-class="min-form-dialog fit "
      width="95%"
      top="15px"
    >
    // 引入子组件中的*@AAAAA* popup-customer
      <popup-customer v-if="is_show_addDialog" :popup_type="popupType" :customer_info="popupParam" @close="close" @refresh="search" />
    </el-dialog>
  </div>
</template>

<script>
// 引入依赖
import IMTable from '@/components/imTable/imTable.vue';
import PopupCustomer from './components/popup-customer-tabs.vue';

export default {
  name: 'my-client',
  components: {
    'im-table': IMTable,
    'popup-customer': PopupCustomer // 引入
  },
  data() {
    return {
      // 省略代码
      popupParam: {},
      popupType: '',
      showType: 'show', // 1.A、点击查看调用show方法
      editType: 'edit', // 1.B、点击编辑调用edit方法
      radioInput: 'PERSONAL'
    };
  },
  mounted() {
    this.initInput();
    this.initTable();
  },
  methods: {
    initInput() {},
    initTable() {
      this.tableHeader = [];
      this.btnOperate = [
        {
          name: '编辑',
          code: 'edit',
          show: 'true'
        },
        {
          name: '删除',
          code: 'delete',
          show: 'true'
        },
        {
          name: '查看',
          code: 'show',
          show: 'true'
        }
      ];
    // 编辑
    edit(e, param) {
      this.dialogTitle = '编辑';
      this.popupType = 'edit';
      this.popupParam = param;
      // 2.B、调用上面editType,将popupParam的showPage属性设置为 'edit'
      this.popupParam.showPage = this.editType; 
      this.is_show_addDialog = true;
    },
    // 父子组件参数同步
    setPopupParam(param) {
      this.popupParam = param;
    },
    // 查看
    show(e, param) {
      this.dialogTitle = '查看';
      this.popupType = 'show';
      this.popupParam = param;
      // 2.A 调用上面showType,将popupParam的showPage属性设置为 'show'
      this.popupParam.showPage = this.showType;
      this.is_show_addDialog = true;
//☆此时,去子页面computed中的is_edit方法中调传过去的属性数据
    },
    // 点击表给选中的操作,实现按钮功能
    tableOperateClick(data) {
      switch (data.type) {
        case 'edit': 
          this.edit(null, data.param);
          break;
        case 'delete':
          this.batchDelete(null, data.param);
          break;
        case 'show':
          this.show(null, data.param);
          break;
        default:
          break;
      }
    }
  };
</script>

7、如何使用im-table拿到参数并在列表中显示

(1)子页面(从父页面中获取参数)
<template>
  // 一、引入im-table组件
  <im-table style="width: 100%; height: 400px;"  // 样式,如果用class可能导致数据无法显示在列表中
    ref="im_table"  // 获取数据 跳转至this.$refs.im_table
    api="/im-gateway/im-sales/PrjSaleWeekly/list/prj"  // 引用后台数据的api,对应后台controller层配置的地址
    http_method="get"  //http的get请求
    :table_header="tableHeader"  // 表头
    >
  </im-table>
</template>

<script>
// 二、导入im-table组件依赖
import IMTable from '@/components/imTable/imTable.vue';
export default {
  name: 'table-weekdtl',
  components: {
    // 重命名
    'im-table': IMTable
  },
  props: {
    /** 项目列表 */
    prjList: { type: Array, default: () => [] },
    /** 周报表单 */
    // 四、从父页面拿过来的集合参数,下方getData()方法中this.weekDtl调用的就是此处的表单
    weekDtl: { type: Array, default: () => {} }
  },
  created() {
    // 六、显示表头数据
    this.initTable();
  },
  mounted() {
    // ☆七、调用getData()方法,获取数据
    this.getData();
  },
  computed: {
    result() {
      // 省略
    }
  },
  methods: {
    getData() {
      // 五、从四props中拿到参数,将weekDtl集合赋值给$refs中的im_table的tableData
      this.$refs.im_table.tableData = this.weekDtl;
    },
    initTable() {
      // 表头数据,即要显示哪些内容,拿到的集合往表中根据prop字段来添加数据
      this.tableHeader = [
        {
          prop: 'startEndTime',
          label: '年份',
          show: true
        }
      ];
    }
  }
};
</script>
(2)父页面(主要传参)
<template>
  <fieldset>
    <legend>周报列表</legend>
    // 三、传参
    <table-weekdtl 
      :prjList="prjList"
      :weekDtl="forms.weekDtl"
      @delete="deleteWeekDtl"
    ></table-weekdtl>
  </fieldset>
</template>

<script>
import TableWeekdtl from './table-weekdtl.vue';

export default {
  data() {
    return {
      // 主子表表单 
      forms: {
        week: {},
        weekDtl: []  // 此处声明
      },

8、当需要通过watch监视根据A=B+C自动计算时在这里插入图片描述

  • 项目预算 = 软件预算 + 硬件预算
  • 当输入项目预算和软件预算时自动计算硬件预算
  • 当输入项目预算和硬件预算时自动计算软件预算
  • 当项目预算发生改变时,软件预算和硬件预算都置空
难点:通过watch方法监视时,始终所有方法都在执行,处理不好会导致修改项目预算时其他不变或者修改项目预算,软件预算为0,硬件预算等于软件预算
<template>
  <el-col :span="6">
    <el-form-item label="项目预算">
      <number-input placeholder="项目预算" unit="万元" v-model="forms.prjInfo.budget"></number-input>
    </el-form-item>
  </el-col>
  <el-col :span="6">
    <el-form-item label="软件预算">
      <number-input placeholder="软件预算" unit="万元" v-model="forms.prjInfo.softwareBudget" />
      </el-form-item>
    </el-col>
  <el-col :span="6">
    <el-form-item label="硬件预算">
      <number-input placeholder="硬件预算" unit="万元" v-model="forms.prjInfo.hardwareBudget" />
    </el-form-item>
  </el-col>
</template>

<script>
export default {
  watch: {
    /** 监听项目预算,如果项目预算不等于硬件加软件,将软件预算和硬件预算置空 */
    'forms.prjInfo.budget': {
      handler: function(budget) {
      // 如果:硬件 + 软件 ≠ 项目,说明是项目发生改变,所以置空硬件、软件
        if (this.forms.prjInfo.softwareBudget + this.forms.prjInfo.hardwareBudget !== budget) {
          this.forms.prjInfo.softwareBudget = '';
          this.forms.prjInfo.hardwareBudget = '';
        }
      }
    },
    
    /** 监听软件预算,如果软件预算发生改变,硬件预算也修改,项目预算不变 */
    'forms.prjInfo.softwareBudget': {
      handler: function(softwareBudget) {
       // 如果:项目 ≠ 空串 且 硬件 ≠ 项目,则执行
        if (this.forms.prjInfo.budget !== '' && this.forms.prjInfo.hardwareBudget !== this.forms.prjInfo.budget) {
          // 如果:硬件 ≠ 空串,则执行计算硬件
          if (this.forms.prjInfo.softwareBudget !== '') {
            this.forms.prjInfo.hardwareBudget = this.forms.prjInfo.budget - softwareBudget;
          } else {
            return '';
          }
        }
      }
    },
    
    /** 监听硬件预算,如果硬件预算发生改变,软件预算也修改,项目预算不变 */
    'forms.prjInfo.hardwareBudget': {
      handler: function(hardwareBudget) {
        // 如果:项目 ≠ 空串 且 软件 ≠ 空串,则执行计算软件
        if (this.forms.prjInfo.budget !== '' && this.forms.prjInfo.softwareBudget !== '') {
          this.forms.prjInfo.softwareBudget = this.forms.prjInfo.budget - hardwareBudget;
        }
      }
    },
  }
}
</script>

9、validate数据校验

效果:输入不满足条件的数据时无法保存表单并标红
在这里插入图片描述

<template>
  <div class="dialog-body" v-loading="loading">
    <!-- 项目表单 -->
    <el-form
      ref="form"
      :model="forms.prjInfo"
      :rules="rules.prjInfo"   // 三、引入rules
      class="insideForm add-ticket"
      size="mini"
      label-position="right"
      label-width="90px"
      :show-message="true"
      :inline-message="true"
    >
      <fieldset>
        <legend>项目详情</legend>
        <el-row>
          <el-col :span="6">
            // 四、在(二)中根据prop对应
            <el-form-item label="项目预算" prop="budget">
              <number-input :disabled="is_info" placeholder="项目预算" unit="万元" v-model="forms.prjInfo.budget" min="0"></number-input>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="软件预算" prop="softwareBudget">
              <number-input :disabled="is_info" placeholder="软件预算" unit="万元" v-model="forms.prjInfo.softwareBudget" min="0" />
            </el-form-item>
          </el-col>
        </el-row>
      </fieldset>
    </el-form>
  </div>
</template>

<script>
export default {
  data() {
    // 一、定义变量
    const validateBudget = (rule, value, callback) => {
      if (value < 0) {
        callback(new Error('预算金额不能小于0'));
      }
      callback();
    };
    const validateSoftWareBudget = (rule, value, callback) => {
      if (value < 0) {
        callback(new Error('软件预算金额不能小于0'));
      } else if (value > this.forms.prjInfo.budget) {
        callback(new Error('软件预算金额不能超过项目预算'));
      }
      callback();
    };

    return {
    // 表单校验
      rules: {
        prjInfo: {
          // 二、在rules中添加(一)中定义的变量
          budget: [{ validator: validateBudget, trigger: 'blur' }],
          softwareBudget: [{ validator: validateSoftWareBudget, trigger: 'blur' }],
        }
      },
    }
  }

10、通过前端api查找后端方法

我的项目-编辑项目-新增项目-下方子表项目周报,周报按周数降序排序

1.找到api 在这里插入图片描述
2.找到controller层在这里插入图片描述
3.在controller中找到service层的方法
/**
     * 根据项目分页查询
     *
     * @param page    分页
     * @param prjCode 项目编码
     */
    public IPage<PrjSaleWeekly> pageQuery(Page<PrjSaleWeekly> page, String prjCode) {
        List<PrjSaleWeeklyDtl> list = prjSaleWeeklyDtlService.queryByPrj(prjCode);
        List<Long> ids = list.stream().map(PrjSaleWeeklyDtl::getWeeklyId).collect(Collectors.toList());
        if (ids.size() == 0) {
            return new Page<>();
        }
        return this.baseMapper.selectPage(page, new QueryWrapper<PrjSaleWeekly>().lambda()
                .in(PrjSaleWeekly::getWeeklyId, ids).orderByDesc(PrjSaleWeekly::getWeekNum));
                // 找到方法,在最后添加orderByDesc方法,根据周数降序排序
    }

11.添加表单验证

<template>
  <el-form
    ref="form"
    :model="forms.prjInfo"
    :rules="rules.prjInfo" // 引入rules
    class="insideForm add-ticket"
    size="mini"
    label-position="right"
    label-width="90px"
    :show-message="true"
    :inline-message="true"
  ></el-form>
</template>

<script>
export default{
  data() {
    const validateDeal = (rule, value, callback) => {
      if (value < 0) {
        callback(new Error('成交金额不能小于0'));
      }
      callback();
    };
    
    /** 表单校验规则 */
      rules: {
        prjInfo: {
          customerCode: [{ required: true, message: '请选择客户', trigger: 'blur' }], // 检测是否为空的
          deal: [{ validator: validateDeal, trigger: 'blur' }]  // 根据定义对象进行验证
        }
      },
</script>

12.Vue父子组件传值

1.父页面代码 index.vue
<template>
  <template>
    // 点击按钮传入一行的所有数据 row
    <el-link type="primary" @click="track(row, 'edit')">客户跟进</el-link>
  </template>
  <el-dialog
    :visible.sync="is_show_trackLineDialog"
    :title="dialogTitle"
    width="70%"
    class="send-dialog"
    v-dialogDrag
    :before-close="close"
    :close-on-click-modal="false"
    custom-class="min-form-dialog fit "
    >
    // cust-track-timeline
    <cust-track-timeline
      v-if="is_show_trackLineDialog"
      :track_param="trackParam"
      // 六、将cstmPrjCode传给子页面的props中的 cstm_prj_code
      :cstm_prj_code="cstmPrjCode"
    />
  </el-dialog>
</template>

<script>
// 一、引入子页面依赖
import CustTrackLine from './components/cust-track-timeline.vue';

export default {
  components: {
    'cust-track-timeline': CustTrackLine
  },
  methods: {
    // 二、点击按钮调用此方法,接收一个param数组,包含表单的全部数据
    track(param) {
      // 三、param的code属性赋给cstmPrjCode
      this.cstmPrjCode = param.customerCode;
    }
  }
2.子表单,接收和赋值
<template>
  <el-form-item label="客户编号" prop="cstmPrjCode">
    // AA.v-model对应数据
    <el-input placeholder="客户编号" :disabled="true" v-model="formData.cstmPrjCode">
    </el-input>
  </el-form-item>
</template>

<script>
export default {
  name: 'cust-track-timeline',
  props: {
    // 四、父页面客户编号带入
    cstm_prj_code: {
      type: String,
      required: false,
      default: ''
    }
  },
  
  methods: {
    addTrack() {
      this.is_show_line = true;
      // 五、对应AA中的v-model赋值
      this.formData.cstmPrjCode = this.cstm_prj_code;
    }
  }

13.前后端交互:MybatisPlus + Vue

一、后端

1.Service层

// 目的:根据编码,时间段,类型查询数据
public List<PrjTrack> getList(String cstmPrjCode,String startTime,String endTime,String trackType) {
    // 时间选择器有时间时,根据时间段查询
    if(startTime != "" && endTime != "" ){
        Date begin = DateUtil.parseDate(startTime);
        Date end = DateUtil.parseDate(endTime);
        return this.baseMapper.selectList(new QueryWrapper<PrjTrack>().lambda().between(PrjTrack::getVisitTime, begin, end).eq(PrjTrack::getCstmPrjCode, cstmPrjCode).eq(PrjTrack::getTrackTyp,trackType));
        }
    // 时间选择器中未选择时间的情况,默认查询本月初到当天
    Date today = DateUtil.date();
    Date begin = DateUtil.beginOfMonth(DateUtil.offsetMonth(today,0));
    Date end = DateUtil.endOfMonth(DateUtil.offsetMonth(today,0));
    return this.baseMapper.selectList(new QueryWrapper<PrjTrack>().lambda().between(PrjTrack::getVisitTime, begin, end).eq(PrjTrack::getCstmPrjCode, cstmPrjCode).eq(PrjTrack::getTrackTyp, trackType));
    }

2.Controller层

@Api(value = "PrjTrackController", tags = {"PrjTrack接口"})
@RequestMapping("/PrjTrack")
@RestController
public class PrjTrackController extends BaseController {
    private static final Logger LOG = LoggerFactory.getLogger(PrjTrackController.class);
    @Autowired
    private PrjTrackService prjTrackService;

	// 保存表单进数据库方法
    @ApiOperation("保存")
    @PostMapping(value = "/saveTrack")
    public ResponseData<Object> save(@RequestBody PrjTrack prjTrack) {
        prjTrackService.saveOrUpdate(prjTrack);
        return ResponseData.SUCCESS_NO_DATA;
    }
    
    @ApiOperation("根据项目编号及时间范围查询某项目所有的数据")
    @GetMapping(value = "/listTrack")
    public ResponseData<Object> getTrackList(String cstmPrjCode, String startTime, String endTime, String trackType){
        return  ResponseData.success(prjTrackService.getTrackList(cstmPrjCode,startTime,endTime,trackType));
    }
}
二、前端

效果:在这里插入图片描述
点击新增后:
在这里插入图片描述
1.组件Vue(负责显示表单和显示值)

<template>
  <div class="layout vflex" v-loading="loading">
    <el-row :gutter="20" class="shrink0">
      <el-col :span="24">
        <el-form class="sBar bg font_medium" :inline="true" size="small">
          // 时间区间选择器,默认传的是一个String型数组,在方法中进行拆分成开始和结束时间
          <el-form-item label="选择时间">
            <el-date-picker
              v-model="params.date"
              value-format="yyyy-MM-dd"
              type="daterange"
              :picker-options="pickerOptions"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              @change="chooseTimeRange"
            >
            </el-date-picker>
          </el-form-item>
          <el-form-item>
            <el-button @click="getTimeLine" class="line">查询</el-button>
          </el-form-item>
          <el-form-item v-if="!is_add">
            <div v-if="!is_show_line">
              <el-button @click="addTrack" type="primary">新增</el-button>
            </div>
          </el-form-item>
        </el-form>
      </el-col>
    </el-row>

    <el-form
      ref="form"
      :model="formData"
      :rules="rules.track"
      class="insideForm com_dict"
      size="medium"
      label-position="right"
      label-width="100px"
      :show-message="true"
      :inline-message="true"
    >
      // 显示新增表单
      <fieldset v-if="is_show_line">
        <legend>客户跟进</legend>
        <el-row>
          <el-col :span="8">
            <el-form-item label="客户名称" prop="customerName">
              <el-input :disabled="true" placeholder="客户名称" v-model="formData.customerName"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="客户编号" prop="cstmPrjCode">
              <el-input placeholder="客户编号" :disabled="true" v-model="formData.cstmPrjCode"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="拜访方式" prop="visitMode">
              <el-select v-model="formData.visitMode" clearable placeholder="请选择">
                <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>

        <el-row>
          // 拜访对象:从客户联系人中选取,使用v-for循环使下拉框动态绑定数值
          <el-col :span="8">
            <el-form-item label="拜访对象" prop="visitors">
              <el-select v-model="formData.visitors" clearable placeholder="请选择">
                <el-option v-for="item in custContacts" :key="item.contactsId" :label="item.contactsName" :value="item.contactsId"> </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="拜访时间" prop="visitTime">
              <el-date-picker
                type="date"
                :picker-options="pickerOptions"
                :isShowShortcuts="false"
                placeholder="拜访时间"
                v-model="formData.visitTime"
              ></el-date-picker>
            </el-form-item>
          </el-col>
        </el-row>

        <el-row>
          <el-col :span="24">
            <el-form-item label="拜访内容" prop="visitContents">
              <el-input
                placeholder="拜访内容"
                v-model="formData.visitContents"
                type="textarea"
                maxlength="256"
                show-word-limit
                :autosize="{ minRows: 3, maxRows: 4 }"
              />
            </el-form-item>
          </el-col>
        </el-row>

        <el-row>
          <el-col :span="24">
            <el-form-item label="备注" prop="rmk">
              <el-input placeholder="备注" v-model="formData.rmk" type="textarea" maxlength="256" show-word-limit :autosize="{ minRows: 3, maxRows: 4 }" />
            </el-form-item>
          </el-col>
        </el-row>

        <div class="footbutton">
          <el-button @click="cancel">取消</el-button>
          <el-button @click="saveData" type="primary" plain>保存</el-button>
        </div>
      </fieldset>
    </el-form>

    // ☆☆☆ 时间线表单
    <fieldset>
      <legend>时间线</legend>
      <div class="block">
        <div class="radio">
          排序:
          <el-radio-group v-model="reverse">
            <el-radio :label="false">正序</el-radio>
            <el-radio :label="true">逆序</el-radio>
          </el-radio-group>
        </div>

        <el-row>
          <el-timeline :reverse="reverse">
            // v-for循环在组件中显示时间线
            <el-timeline-item v-for="(activity, index) in activities" :key="index" :timestamp="activity.timestamp">
              {{ activity.content }}
            </el-timeline-item>
          </el-timeline>
        </el-row>
      </div>
    </fieldset>
  </div>
</template>

<script>
import moment from 'moment';
import customerApi from '@/api/business/project/prjCustomer';

// ☆核心:调用js中的方法,js中的方法是和后端交互起来的
import saveTrackApi from '@/api/business/sales/track.js';

export default {
  name: 'cust-track-timeline',
  props: {
    // 个人/下属判断
    track_param: {
      type: String,
      required: false,
      default: ''
    },

    // 客户编号带入,从index.vue带入,点击该行的操作按钮时整一行数据带入,进行选择,通过props绑定
    cstm_prj_code: {
      type: String,
      required: false,
      default: ''
    },

    // 客户名称带入
    customer_name: {
      type: String,
      required: false,
      default: ''
    }
  },

  components: {},

  data() {
    return {
      // 加载中
      loading: false,
      // 初始化formData
      formData: {
        customerName: '',
        cstmPrjCode: '',
        visitMode: '',
        visitors: '',
        visitTime: '',
        trackTyp: '',
        visitContents: '',
        rmk: '',
        dateInput: '',
        contactsCode: '',

        // 联系人变量
        custContacts: []
      },
      // 拆分日期区间
      params: {
        startTime: '',
        endTime: '',
        date: ''
      },
      // 限制表单日期选择区间
      pickerOptions: {
        disabledDate(time) {
          return time.getTime() > Date.now() - 8.64e6;
        }
      },
      // 初始化活动表单
      activities: [],
      
      // 初始不显示填写的表单
      is_show_line: false,
      reverse: true,

      /**默认显示时间 */
      defaultst: '',
      defaultet: '',

      /** 表单校验规则 */
      rules: {
        track: {
          visitMode: [{ required: true, message: '请选择拜访方式', trigger: 'blur' }],
          visitors: [{ required: true, message: '请选择拜访对象', trigger: 'blur' }],
          visitTime: [{ required: true, message: '请选择拜访时间', trigger: 'blur' }],
          visitContents: [{ required: true, message: '请输入拜访内容', trigger: 'blur' }]
        }
      },

      // 下拉框选定内容
      options: [
        {
          label: '电话联系',
          value: 'telphone'
        },
        {
          label: '面谈交流',
          value: 'interview'
        }
      ],

	  // 下拉框选定内容
      trackTyp: [
        {
          label: '客户跟进',
          value: 'cstm'
        },
        {
          label: '项目跟进',
          value: 'prj'
        }
      ]
    };
  },


  computed: {
    // 从index.vue接收来的数据判断是个人还是下属(个人为edit,方法返回false,显示新增按钮可以新增;下属为show,方法返回true,不显示按钮不可新增)
    is_add() {
      return this.track_param === 'show';
    }
  },
  created() {
    this.getContactListByCustomer();
  },
  mounted() {
    // 通过moment转格式
    this.getTimeLine();
    this.defaultst = moment(moment().startOf('month')).format('YYYY-MM-DD');
    console.log(this.defaultst);
    this.params.date = [this.defaultst, moment(new Date()).format('YYYY-MM-DD')];
  },

  methods: {
    // 客户跟进,点击新增按钮时,表单显示
    addTrack() {
      this.is_show_line = true;
      // 从index.vue点击获取该行所有数据,选择带入的编码和姓名,赋值给表单中的属性
      this.formData.cstmPrjCode = this.cstm_prj_code;
      this.formData.customerName = this.customer_name;
    },

    cancel() {
      // 点击取消按钮,隐藏表单
      this.is_show_line = false;
    },

    // 获取日期区间
    chooseTimeRange(time) {
      this.params.startTime = time[0];
      this.params.endTime = time[1];
    },

    // 点击保存按钮,调用提交表单方法
    saveData() {
      this.submitForm('form');
    },
    // 表单为空验证
    submitForm(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          this.postForm();
        } else {
          console.log('保存错误!');
          return false;
        }
      });
    },
    
    // 表单发送给后端数据库
    postForm() {
      // 从此客户跟进页面 点击新增的必定默认是客户跟进方式,编码cstm
      this.formData.trackTyp = 'cstm';
      const param = {
        //将右边表单填写的数据 赋值给 左边实体类中的属性,对应数据库数据
        cstmPrjCode: this.formData.cstmPrjCode,
        visitMode: this.formData.visitMode,
        visitors: this.formData.visitors,
        visitTime: this.formData.visitTime,
        visitContents: this.formData.visitContents,
        trackTyp: this.formData.trackTyp,
        rmk: this.formData.rmk
      };

      this.loading = true;
      // 核心:调用api中的后端方法(api.方法名(参数)),把上面的param塞进方法里
      saveTrackApi.saveTrack(param).then(
        res => {
          if (res.success === true) {
            this.is_show_line = false;
            this.loading = false;
            this.$message.success('保存成功');
            this.getTimeLine();
            // 初始化类型
            this.formData.trackTyp = '';
            this.formData = [];

          } else {
            this.loading = false;
            this.$message.error('保存失败' + res.content);
          }
        },
        err => {
          this.loading = false;
          this.$message.error(err.message);
        }
      );
    },

    /** 根据客户编码获取项目联系人列表 */
    getContactListByCustomer() {
      if (!this.cstm_prj_code) {
        return false;
      }
      customerApi
        .getCustomerContacts({ customerCode: this.cstm_prj_code })
        .then(res => {
          if (res.success) {
            this.custContacts = res.data;
          } else {
            this.$message.error('获取联系人失败');
          }
        })
        .finally(() => {});
    },

    // ☆核心:显示本月时间线数据,往activity中装数据,然后显示在表单中
    getTimeLine() {
      var start = this.params.startTime;
      var end = this.params.endTime;
      var trackType = 'cstm';
      // 如果没有选择时间区间
      if (this.params.startTime == null && this.params.startTime.length == 0) {
        start = null;
        end = null;
      }
      getAllApi.getAll(this.cstm_prj_code, start, end, trackType).then(res => {
        // 初始化activity数据,至关重要,否则每次点一次查询就会重复显示一次
        this.activities = [];
        for (var i = 0; i < res.data.length; i++) {
          // 往activity中放数据,右边的赋值给左边
          this.activities.push({
            content: '联系人:' + res.data[i].visitors + ',拜访内容:' + res.data[i].visitContents + ',备注:' + res.data[i].rmk,
            timestamp: res.data[i].visitTime
          });
        }
      });
    }
  }
};
</script>

2.custTrack.js

import http from '@/utils/serviceHttp';

export default {
  /** 保存跟进表单 */
  saveTrack: prjTrack => http.sales.post('/PrjTrack/save', prjTrack),
  /** 显示本月数据 */
  // 方法名: (参数1, 参数2, 参数3, 参数4) =>
  //   http.服务名.请求方式('后端对应方法地址值', { 参数名1: 参数值1, 参数名2: 参数值2,})
  getTrackList: (cstmPrjCode, startTime, endTime, trackType) =>
    http.sales.get('/PrjTrack/list', { cstmPrjCode: cstmPrjCode, startTime: startTime, endTime: endTime, trackType: trackType })
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值