Commit 256115d0 by crushh

Merge branch 'feature/3月迭代' into dev

parents 96292cac b5074fc6
......@@ -104,27 +104,17 @@ export default {
},
watch: {
tableData(val) {
if (val.length) {
this.$nextTick(() => {
console.log(this.selected);
if (this.selected.length) {
this.selected.forEach(item => {
val.forEach(row => {
if (item.memberTagGroupId == row.memberTagGroupId) {
// 必须要传入从this.tableData里查询到的对象才能出现被勾选样式
this.$refs.table.toggleRowSelection(
this.tableData.find(row => {
return row.memberTagGroupId == item.memberTagGroupId;
})
);
}
});
});
} else {
this.$refs.table.clearSelection();
}
if (!val.length) return;
this.$nextTick(() => {
if (!this.selected.length) return;
const obj = {};
val.forEach(item => {
obj[item.memberTagGroupId] = item;
});
}
this.selected.forEach(item => {
obj[item.memberTagGroupId] && this.$refs.table.toggleRowSelection(obj[item.memberTagGroupId]);
});
});
},
activeName: {
handler(val) {
......@@ -143,13 +133,7 @@ export default {
},
methods: {
selectable(row) {
if (this.readonly) {
return false;
} else if (!this.realTimeType.includes(row.isRealTime)) {
return false;
} else {
return true;
}
return !this.readonly && this.realTimeType.includes(row.isRealTime);
},
addGroup() {
window.open('http://gicdev.demogic.com/member-tag/#/memberGroupEdit?refresh', '_blank');
......
......@@ -74,41 +74,5 @@ const transform = (data, scenes) => {
result.filterFrontShow = JSON.stringify(filterFrontShow);
return { data: result, bool: filterFrontShow.length > 0 };
};
/**
* @description 处理回显数据
* @param {Object} data 选择好的筛选条件数据
* @chainNodeName {String} 节点名字如:会员等级
* @selectValue {String} 选择条件的文案
* @esScreeningWidgetChainId {String} 节点Id
*/
// const handleEchoData = data => {
// let arr = [];
// data.forEach(item => {
// if (item.selectValue && item.selectValue.length) {
// let selectValue = [];
// if (item.templateCode == 'com026') {
// let myMap = new Map();
// item.selectList.forEach(item => {
// item.data.forEach(val => {
// myMap.set(val.key, val.value);
// });
// });
// item.selectValue.forEach(key => {
// selectValue.push(myMap.get(key));
// });
// selectValue = selectValue.join(',');
// } else if (item.templateCode == 'tag001') {
// item.selectList.forEach(obj => {
// if (item.selectValue.includes(obj.key)) {
// selectValue.push(obj.value);
// }
// });
// selectValue = selectValue.join(',');
// }
// arr.push({ chainNodeName: item.chainNodeName, selectValue, esScreeningWidgetChainId: item.esScreeningWidgetChainId });
// }
// });
// return arr;
// };
export default transform;
......@@ -107,19 +107,18 @@ export default {
type: Boolean,
default: false
}
// echoWidth: {
// type: String,
// default: '400px'
// }
},
mounted() {
this.getDataList();
},
watch: {
memberCrowdWidgetId(val) {
if (val) {
this.echoFlag = true;
this.getEchoData();
memberCrowdWidgetId: {
immediate: true,
handler(val) {
if (val) {
this.echoFlag = true;
this.getEchoData();
}
}
},
hideId(val) {
......@@ -153,9 +152,6 @@ export default {
}
});
this.echoData = this.handleEchoData(filterFrontShow);
// console.log(this.echoData);
// console.log(filterFrontShow);
// console.log(this.conditionTypeList);
}
});
},
......
......@@ -36,6 +36,14 @@ export default {
}
},
{
path: 'copy/:id',
name: '复制活动',
component: () => import('../../views/ai/task/form.vue'),
meta: {
type: 'copy'
}
},
{
path: 'logs/:id',
name: '提交日志',
component: () => import('../../views/ai/logs.vue')
......
......@@ -53,11 +53,15 @@ export const platformHomePageV2 = params => requests('/gic-member-tag-web/member
// 获取AI数据统计活动信息
export const getActivityInfo = params => requests('/api-marketing/statistics/get-activity-info', params, true, false, 'get');
// 获取短信模板内容
export const getSmsTemplateEcho = params => requests('/api-marketing/get-sms-template-echo', params, true, false, 'get');
// 获取AI数据统计外呼数据
export const getOutBound = params => requests('/api-marketing/statistics/out-bound', params, true, false, 'get');
export const getIntentionLabel = params => requests('/api-marketing/statistics/intention-label', params, true, false, 'get');
export const getBillAnalysis = params => requests('/api-marketing/statistics/bill-quality-analysis', params, true, false, 'get');
export const getCallDuration = params => requests('/api-marketing/statistics/call-duration', params, true, false, 'get');
export const getComparativeData = params => requests('/api-marketing/statistics/comparative-statistics', params, true, false, 'get');
// 人群规则回显
export const getMemberCrowd = params => requests('/api-plug/query-member-crowd-new', params, true);
......
......@@ -375,7 +375,9 @@ export const getTimesByReq = (str, type = 1) => {
*/
export const numFormat = function(num) {
if (typeof num != 'number') {
console.error('numFormat Arguments TypeError: Arguments type is not number');
// if (process.env.NODE_ENV == 'development') {
// console.error('numFormat Arguments TypeError: Arguments type is not number');
// }
return '--';
}
return num.toString().replace(/\d+/, n => {
......
......@@ -2,38 +2,50 @@
<div class="ai-data-report">
<div class="report-module">
<dm-sub-title>活动信息</dm-sub-title>
<activity-info @flag="getFlag"></activity-info>
<activity-info @flag="getFlag" @filterJson="getFilterJson"></activity-info>
</div>
<div class="report-module">
<dm-sub-title> AI外呼数据<span class="title-tip">数据实时更新</span> </dm-sub-title>
<ai-data :ai-data-show="aiDataShow"></ai-data>
<ai-data :ai-data-show="flags"></ai-data>
</div>
<div class="report-module">
<div class="report-module" v-if="flags.analyseFlag == 1">
<dm-sub-title> 活动转化数据<span class="title-tip">数据每天更新 1 次</span> </dm-sub-title>
<conversion></conversion>
<conversion :member-type="flags.memberType" :filter-json="filterJson"></conversion>
</div>
</div>
</template>
<script>
// import G2 from '@antv/g2';
import ActivityInfo from './ai-data-report/activity-info.vue';
import AiData from './ai-data-report/ai-data.vue';
import Conversion from './ai-data-report/conversion.vue';
// 开启活动分析时,活动信息中展示分析天数
// 开启活动分析时,AI外呼数据中展示活动费用
// 发送挂机短信时,AI外呼数据中展示短信发送总数
// 开启活动分析时,展示活动转化数据
// 会员类型为0时,活动分析中对比项支持会员类型、会员等级、金字塔会员分层
// 会员类型为1时,活动分析对比项支持客户分组
export default {
name: 'AiDataReport',
components: { ActivityInfo, AiData, Conversion },
data() {
return {
aiDataShow: {
analyseFlag: 0,
smsFlag: 0
}
flags: {
memberType: 0, // 0会员筛选1会员分组
analyseFlag: 0, // 活动分析 1开启0关闭
smsFlag: 0 // 发送挂机短信 1是0否
},
filterJson: '' // 人群规则选择器id
};
},
methods: {
getFlag(flag) {
this.aiDataShow = flag;
this.flags = flag;
},
getFilterJson(filterJson) {
this.filterJson = filterJson;
}
}
};
......
......@@ -30,14 +30,14 @@
</div>
<div class="member-rule">
<div class="member-rule-title">人群规则:</div>
<div class="member-rule-list" v-if="activityInfo.memberType == 0">
<div class="member-rule-item">{{ memberRule || '--' }}</div>
</div>
<ruleFilter class="member-rule-list" v-if="activityInfo.memberType == 0" :memberCrowdWidgetId="activityInfo.filterJson" />
<!-- <gic-new-member-group :visible="true" :defalt-selected="memberRule.selectValue"></gic-new-member-group> -->
<div class="member-rule-list" v-if="activityInfo.memberType == 1">
<div class="member-rule-item">生日范围:3月1日-3月31日</div>
{{ memberRule }}
<!-- <div class="member-rule-item">生日范围:3月1日-3月31日</div>
<div class="member-rule-item">会员等级:银卡、金卡</div>
<div class="member-rule-item">金字塔会员分层:核心会员31-90天、潜力会员31-90天</div>
<div class="member-rule-item">会员服务门店:会员分组(华南直营、华北直营)</div>
<div class="member-rule-item">会员服务门店:会员分组(华南直营、华北直营)</div> -->
</div>
</div>
</div>
......@@ -45,13 +45,14 @@
<script>
import { formatDateTimeByType } from '@/utils/index.js';
import { getActivityInfo, getMemberCrowd, getGroupByIds } from '@/service/api/aiApi.js';
import { getActivityInfo, getGroupByIds } from '@/service/api/aiApi.js';
import gicNewMemberGroup from '@/components/dm-new-member-group/index.vue';
import ruleFilter from '@/components/dm-new-rule/ruleFilter.vue';
// TODO 回显人群规则
export default {
name: 'ActivityInfo',
components: { gicNewMemberGroup },
components: { gicNewMemberGroup, ruleFilter },
data() {
return {
activityInfo: {},
......@@ -84,17 +85,14 @@ export default {
analyseFlag: this.activityInfo.analyseFlag, //1开0关 开启活动分析开关
smsFlag: this.activityInfo.smsFlag //挂机短信1是0否
});
this.$emit('filterJson', this.activityInfo.filterJson);
this.getMemberCrowd();
});
},
getMemberCrowd() {
const { memberType, filterJson, sceneJson } = this.activityInfo;
if (memberType == 0) {
getMemberCrowd({ memberCrowdWidgetId: filterJson }).then(res => {
this.memberRule = res.result.filterFrontShow;
});
} else if (memberType == 1) {
getGroupByIds({ memberTagGroupIds: sceneJson }).then(res => {
const { memberType, filterJson } = this.activityInfo;
if (memberType == 1) {
getGroupByIds({ memberTagGroupIds: filterJson }).then(res => {
this.memberRule = res.result.filterFrontShow;
});
}
......@@ -132,18 +130,24 @@ export default {
}
.member-rule-list {
margin-top: 10px;
padding: 16px;
background: #f7f8fa;
border-radius: 4px;
.member-rule-item {
font-size: 14px;
font-weight: 400;
color: #303133;
line-height: 20px;
+ .member-rule-item {
margin-top: 10px;
/deep/ .echo-member-group {
padding: 15px;
.subTitle {
display: none;
}
}
// padding: 16px;
// background: #f7f8fa;
// border-radius: 4px;
// .member-rule-item {
// font-size: 14px;
// font-weight: 400;
// color: #303133;
// line-height: 20px;
// + .member-rule-item {
// margin-top: 10px;
// }
// }
}
}
</style>
......@@ -25,7 +25,11 @@
<el-col :span="8">
<div class="chart-title">通话时长</div>
<div class="chart-box">
<div id="chart-duration"></div>
<div id="chart-duration">
<svg aria-hidden="true" class="no-data-icon">
<use xlink:href="#icon-cp-no-data"></use>
</svg>
</div>
<div v-if="talkTimeData.length > 0">
<div class="talk-legend" v-for="el in talkTimeData" :key="el.color">
<i class="talk-legend-icon" :style="{ background: el.color }"></i>
......@@ -34,9 +38,6 @@
<span class="talk-legend-percent">{{ el.percent }}</span>
</div>
</div>
<svg v-else aria-hidden="true" class="no-data-icon">
<use xlink:href="#icon-cp-no-data"></use>
</svg>
</div>
</el-col>
</el-row>
......@@ -179,7 +180,7 @@ export default {
const value = this.targetData[item.key];
switch (item.type) {
case 'number':
item.value = typeof value == 'number' ? numFormat(value) : '--';
item.value = numFormat(value);
break;
case 'time':
item.value = '--';
......@@ -191,7 +192,7 @@ export default {
}
break;
case 'amount':
item.value = typeof value == 'number' ? numFormat(value) : '--';
item.value = numFormat(value);
break;
case 'rate':
item.value = value == null ? '--' : value;
......@@ -233,6 +234,7 @@ export default {
percent: originData[el + '_proportion']
};
});
document.getElementById('chart-tag').innerHTML = '';
const chart = new G2.Chart({
container: 'chart-tag',
forceFit: true,
......@@ -283,6 +285,7 @@ export default {
{ label: '线路问题', count: originData['count_4'], percent: originData['4_proportion'] },
{ label: '被叫问题', count: originData['count_5'], percent: originData['5_proportion'] }
];
document.getElementById('chart-record').innerHTML = '';
const chart = new G2.Chart({
container: 'chart-record',
forceFit: true,
......@@ -354,7 +357,7 @@ export default {
value: '通话数量', // value字段
retains: ['type'] // 保留字段集,默认为除fields以外的所有字段
});
document.getElementById('chart-duration').innerHTML = '';
const chart = new G2.Chart({
container: 'chart-duration',
forceFit: true,
......
......@@ -9,7 +9,7 @@
<defineTime v-show="form.callFlag == 1" ref="defineTime" :data="form.callTime" />
</el-form-item>
<el-form-item label="活动有效期" required>
<el-date-picker value-format="timestamp" format="MM-dd" v-model="form.activeTime" @change="handleDateChange" type="daterange" placeholder="请选择生日范围" range-separator="~" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker>
<el-date-picker value-format="timestamp" format="yyyy-MM-dd" :picker-options="pickerOptions" @blur="minTime = maxTime = null" v-model="form.activeTime" @change="handleDateChange" type="daterange" placeholder="请选择生日范围" range-separator="~" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker>
</el-form-item>
</el-form>
</template>
......@@ -17,7 +17,8 @@
<script>
import defineTime from './defineTime.vue';
import { formatDateTimeByType } from '@/utils/index';
let minTime = null;
let maxTime = null;
export default {
data() {
return {
......@@ -27,6 +28,26 @@ export default {
callFlag: 0, //外呼时段 0 默认 1 自定义
callTime: [{}] // 自定义时段
},
pickerOptions: {
onPick(time) {
// 起始时间:仅半年范围内 && 结束时间:跨度最多3个月,即所选起始时间往后+90天为上限;
if (!time.maxDate) {
const minTimeRange = 90 * 24 * 60 * 60 * 1000; // 3个月
const maxTimeRange = 180 * 24 * 60 * 60 * 1000; // 6个月
minTime = time.minDate.getTime() - minTimeRange > new Date(new Date().toLocaleDateString()).getTime() ? time.minDate.getTime() - minTimeRange : new Date(new Date().toLocaleDateString()).getTime();
maxTime = time.minDate.getTime() + minTimeRange < new Date().getTime() + maxTimeRange ? time.minDate.getTime() + minTimeRange : new Date().getTime() + maxTimeRange;
}
},
disabledDate: time => {
const maxTimeRange = 180 * 24 * 60 * 60 * 1000; // 6个月
if (minTime && maxTime) {
return time.getTime() < minTime || time.getTime() > maxTime;
} else {
return time.getTime() < new Date(new Date().toLocaleDateString()).getTime() || time.getTime() > new Date().getTime() + maxTimeRange;
}
}
},
rules: {}
};
},
......@@ -82,6 +103,11 @@ export default {
}
});
});
},
handleDateChange(val) {
if (!val) {
minTime = maxTime = null;
}
}
}
};
......
......@@ -12,10 +12,10 @@
</el-radio>
</el-form-item>
<el-form-item label="生日范围" prop="birthDate1" v-if="form.birth_type == 1 || form.birth_type == 3" required>
<el-date-picker value-format="timestamp" format="MM-dd" v-model="form.birthDate1" @change="handleDateChange" :picker-options="pickerOptions" type="daterange" placeholder="请选择生日范围" range-separator="~" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker>
<el-date-picker value-format="timestamp" format="MM-dd" v-model="form.birthDate1" @change="handleDateChange" @blur="minTime = maxTime = null" :picker-options="pickerOptions" type="daterange" placeholder="请选择生日范围" range-separator="~" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker>
</el-form-item>
<el-form-item label="生日范围" prop="birthDate2" v-if="form.birth_type == 2">
<el-date-picker type="monthrange" value-format="timestamp" format="MM月" v-model="form.birthDate2" @change="handleDateMonthChange" :picker-options="pickerOptionsMonth" placeholder="请选择生日范围" range-separator="~" start-placeholder="开始月份" end-placeholder="结束月份"> </el-date-picker>
<el-date-picker type="monthrange" value-format="timestamp" format="MM月" v-model="form.birthDate2" @change="handleDateMonthChange" @blur="minTimeMonth = maxTimeMonth = null" :picker-options="pickerOptionsMonth" placeholder="请选择生日范围" range-separator="~" start-placeholder="开始月份" end-placeholder="结束月份"> </el-date-picker>
</el-form-item>
<el-form-item label="外呼时段" required>
<el-radio v-model="form.callFlag" :label="0">默认时段</el-radio>
......@@ -35,11 +35,10 @@
<script>
import defineTime from './defineTime.vue';
import { formatDateTimeByType } from '@/utils/index';
let minTime = null;
let maxTime = null;
let minTime = null;
let minTimeMonth = null;
let maxTimeMonth = null;
export default {
data() {
const birthDateValidtor = (rule, value, callback) => {
......@@ -84,17 +83,19 @@ export default {
onPick(time) {
// 起始时间:仅半年范围内 && 结束时间:跨度最多3个月,即所选起始时间往后+90天为上限;
if (!time.maxDate) {
const timeRange = 90 * 24 * 60 * 60 * 1000; // 3个月
minTime = time.minDate.getTime(); // 最小时间
maxTime = time.minDate.getTime() + timeRange; // 最大时间
const minTimeRange = 90 * 24 * 60 * 60 * 1000; // 3个月
const maxTimeRange = 180 * 24 * 60 * 60 * 1000; // 6个月
minTime = time.minDate.getTime() - minTimeRange > new Date(new Date().toLocaleDateString()).getTime() ? time.minDate.getTime() - minTimeRange : new Date(new Date().toLocaleDateString()).getTime();
maxTime = time.minDate.getTime() + minTimeRange < new Date().getTime() + maxTimeRange ? time.minDate.getTime() + minTimeRange : new Date().getTime() + maxTimeRange;
}
},
disabledDate: time => {
const timeRange = 30 * 24 * 60 * 60 * 1000; // 3个月
const maxTimeRange = 180 * 24 * 60 * 60 * 1000; // 6个月
if (minTime && maxTime) {
return time.getTime() < minTime || time.getTime() > maxTime;
} else {
return time.getTime() < new Date().getTime() - 24 * 60 * 60 * 1000 || time.getTime() > new Date().getTime() + timeRange;
return time.getTime() < new Date(new Date().toLocaleDateString()).getTime() || time.getTime() > new Date().getTime() + maxTimeRange;
}
}
},
......@@ -102,21 +103,22 @@ export default {
onPick(time) {
// 起始时间:仅半年范围内 && 结束时间:跨度最多3个月,即所选起始时间往后+90天为上限;
if (!time.maxDate) {
const timeRange = 90 * 24 * 60 * 60 * 1000; // 3个月
minTimeMonth = time.minDate.getTime(); // 最小时间
maxTimeMonth = time.minDate.getTime() + timeRange; // 最大时间
const minTimeRange = 90 * 24 * 60 * 60 * 1000; // 3个月
const maxTimeRange = 180 * 24 * 60 * 60 * 1000; // 6个月
minTimeMonth = time.minDate.getTime() - minTimeRange > new Date(new Date().toLocaleDateString()).getTime() ? time.minDate.getTime() - minTimeRange : new Date(new Date().toLocaleDateString()).getTime();
maxTimeMonth = time.minDate.getTime() + minTimeRange < new Date().getTime() + maxTimeRange ? time.minDate.getTime() + minTimeRange : new Date().getTime() + maxTimeRange;
}
},
disabledDate: time => {
const timeRange = 180 * 24 * 60 * 60 * 1000; // 3个月
if (minTimeMonth && maxTimeMonth) {
const maxTimeRange = 180 * 24 * 60 * 60 * 1000; // 6个月
if (maxTimeMonth) {
return time.getTime() < minTimeMonth || time.getTime() > maxTimeMonth;
} else {
return time.getTime() < new Date().getTime() || time.getTime() > new Date().getTime() + timeRange;
return time.getTime() < new Date(new Date().getFullYear(), new Date().getMonth(), 1).getTime() || time.getTime() > new Date().getTime() + maxTimeRange;
}
}
},
currentTime: new Date(new Date().toLocaleDateString()).getTime()
currentTime: new Date(new Date().toLocaleDateString()).getTime() // 当天零点时间戳
};
},
props: {
......@@ -177,7 +179,7 @@ export default {
obj.startDate = birthDate1[0] - birth_days * 24 * 60 * 60 * 1000;
obj.endDate = birthDate1[1] - birth_days * 24 * 60 * 60 * 1000;
} else if (birth_type == 2) {
obj.startDate = birthDate2[0];
obj.startDate = this.currentTime;
obj.endDate = birthDate2[1];
} else {
obj.startDate = birthDate1[0];
......
......@@ -44,9 +44,9 @@
仅支持选择节日日期为最近1-60天内的节日
</div>
<div class="holiday" v-for="item in holidayData" :key="item.id">
<dm-sub-title>{{ item.id }}</dm-sub-title>
<dm-sub-title>{{ item.name }}</dm-sub-title>
<div class="radioLine">
<el-radio v-model="selectedData" :label="val" v-for="val in item.holidaysList" :key="val.id">{{ val.name }}</el-radio>
<el-radio v-model="selectedData" :disabled="val.disabled" :label="val" v-for="val in item.holidaysList" :key="val.id">{{ val.name }}</el-radio>
</div>
</div>
<span slot="footer">
......@@ -159,15 +159,14 @@ export default {
visible: false,
pickerOptions: {
onPick(time) {
// 起始时间:仅半年范围内 && 结束时间:跨度最多3个月,即所选起始时间往后+90天为上限;
if (!time.maxDate) {
const timeRange = 60 * 24 * 60 * 60 * 1000; // 3个月
const timeRange = 60 * 24 * 60 * 60 * 1000;
minTime = time.minDate.getTime(); // 最小时间
maxTime = time.minDate.getTime() + timeRange; // 最大时间
}
},
disabledDate: time => {
const timeRange = 60 * 24 * 60 * 60 * 1000; // 3个月
const timeRange = 60 * 24 * 60 * 60 * 1000;
if (minTime && maxTime) {
return time.getTime() < minTime || time.getTime() > maxTime;
} else {
......@@ -230,10 +229,17 @@ export default {
},
async getListAllHolidays() {
const { result } = await listAllHolidays();
console.log(result);
if (result) {
this.holidayData = result;
}
if (!result) return;
result.forEach(item => {
if (item.holidaysList && item.holidaysList.length) {
item.holidaysList.forEach(val => {
if (getTimesByReq(val.date) <= this.currentTime || this.currentTime + 60 * 24 * 60 * 60 * 1000 < getTimesByReq(val.date)) {
val.disabled = true;
}
});
}
});
this.holidayData = result;
},
addItem() {
if (!this.selectedData) {
......
......@@ -153,7 +153,7 @@ export default {
limitCode: ''
},
handler: row => {
console.log('复制');
this.$router.push('/ai/copy/' + row.activityId);
}
},
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment