前端学习笔记(一)
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 })
};