Commit 55eee6ca by crushh

udpate: dist

parent 084ced0a
...@@ -416,4 +416,4 @@ ...@@ -416,4 +416,4 @@
} }
} }
} }
} }
\ No newline at end of file
...@@ -21,7 +21,7 @@ export default { ...@@ -21,7 +21,7 @@ export default {
case 4: case 4:
str = '客户复购'; str = '客户复购';
break; break;
case 5: case 0:
str = '其它场景'; str = '其它场景';
break; break;
} }
......
import { requests } from './index'; import { requests } from './index';
const PREFIX = 'api-marketing/ai/'; const PREFIX = 'api-marketing/ai/';
//活动分页查询-统计 //活动分页查询-统计
export const pageStatistics = params => requests(PREFIX + 'page-statistics', params, true); export const pageStatistics = params => requests(PREFIX + 'page-statistics', params, true);
...@@ -43,11 +44,12 @@ export const getLogs = params => requests('/api-marketing/page-activity-event-ex ...@@ -43,11 +44,12 @@ export const getLogs = params => requests('/api-marketing/page-activity-event-ex
// 获取AI数据统计详情 // 获取AI数据统计详情
export const getCustomDetail = params => requests('/api-marketing/statistics/page-data-statistics-custom-detail', params, true, false, 'get'); export const getCustomDetail = params => requests('/api-marketing/statistics/page-data-statistics-custom-detail', params, true, false, 'get');
//标签库-分页列表数据 //标签库-标签值列表
export const platformTagPageListV2 = params => requests('/gic-member-tag-web/memberTag/platformTagPageListV2', params, true, false, 'get'); export const pageMemberTagDetail = params => requests('/gic-member-tag-web/memberTag/pageMemberTagDetail', params, true, false, 'get');
//标签库-标签层级 //标签库-标签层级
export const platformHomePageV2 = params => requests('/gic-member-tag-web/memberTag/platformHomePageV2', params, true, false, 'get'); export const platformHomePageV2 = params => requests('/gic-member-tag-web/memberTag/platformHomePageByAI', params, true, false, 'get');
// 获取AI数据统计活动信息 // 获取AI数据统计活动信息
export const getActivityInfo = params => requests('/api-marketing/statistics/get-activity-info', params, true, false, 'get'); export const getActivityInfo = params => requests('/api-marketing/statistics/get-activity-info', params, true, false, 'get');
......
...@@ -8,6 +8,11 @@ import router from '../../router/index'; ...@@ -8,6 +8,11 @@ import router from '../../router/index';
import store from '../../store/index'; import store from '../../store/index';
import Vue from 'vue'; import Vue from 'vue';
/**
* 兼容 errorCode:0 || code:'0' 为正确返回的接口
*
*/
// 加载最小时间 // 加载最小时间
const MINI_TIME = 300; const MINI_TIME = 300;
// 超时时间 // 超时时间
...@@ -133,6 +138,8 @@ const requests = (url, data = {}, contentTypeIsJSON = false, isSilence = false, ...@@ -133,6 +138,8 @@ const requests = (url, data = {}, contentTypeIsJSON = false, isSilence = false,
.then(res => { .then(res => {
clearTimeout(_timer); clearTimeout(_timer);
popRequest(_random); popRequest(_random);
resolve(res.data);
return;
if (res.data.errorCode !== 0 && res.data.code != 0) { if (res.data.errorCode !== 0 && res.data.code != 0) {
reject(res); reject(res);
if (res.data.message.indexOf('抱歉') >= 0) { if (res.data.message.indexOf('抱歉') >= 0) {
......
import axios from 'axios';
import qs from 'qs';
import { Message } from 'element-ui';
/**
* 兼容 errorCode:1 || code:'0' 为正确返回的接口
*
*/
let __DEVELOPMENT = process.env.NODE_ENV === 'development';
let __PRODUCTION = process.env.NODE_ENV === 'production';
const service = axios.create();
service.defaults.timeout = 30000;
if (__DEVELOPMENT) {
service.defaults.withCredentials = true;
}
service.interceptors.request.use(
config => {
return config;
},
err => {
if (__DEVELOPMENT) {
console.log('>>>>>>>>>> request error >>>>>>>>>>');
}
return Promise.reject(err);
}
);
service.interceptors.response.use(
response => {
const { data, config } = response;
let err;
const { errorCode, code } = data;
switch (errorCode) {
case 1:
return data;
case 401:
Message({
message: '登录失效',
type: 'error'
});
__PRODUCTION && (window.location.href = '/gic-web/#/login');
break;
case undefined:
break;
default:
Message({
message: data.message,
type: 'error'
});
err = new Error(`${data.message}: ${config.url}`);
if (__DEVELOPMENT) {
console.log('>>>>>>>>>> response data error >>>>>>>>>>');
}
return Promise.reject(err);
}
switch (code) {
case '0':
return data.result;
case '401':
Message({
message: '登录失效',
type: 'error'
});
__PRODUCTION && (window.location.href = '/gic-web/#/login');
break;
default:
Message({
message: data.message,
type: 'error'
});
err = new Error(`${data.message}: ${config.url}`);
if (__DEVELOPMENT) {
console.log('>>>>>>>>>> response data error >>>>>>>>>>');
}
return Promise.reject(err);
}
},
err => {
const status = err.response.status;
switch (status) {
case 400:
err.message = '请求错误';
break;
case 401:
err.message = '未授权,请登录';
__PRODUCTION && (window.location.href = '/gic-web/#/login');
break;
case 403:
err.message = '拒绝访问';
break;
case 404:
err.message = `请求地址出错: ${err.response.config.url}`;
break;
case 408:
err.message = '请求超时';
break;
case 500:
err.message = '服务器内部错误';
break;
case 501:
err.message = '服务未实现';
break;
case 502:
err.message = '网关错误';
break;
case 503:
err.message = '服务不可用';
break;
case 504:
err.message = '网关超时';
break;
case 505:
err.message = 'HTTP版本不受支持';
break;
default:
break;
}
if (__DEVELOPMENT) {
console.log('>>>>>>>>>> response error >>>>>>>>>>');
}
Message({
message: '系统异常',
type: 'error'
});
return Promise.reject(err);
}
);
export function request(config, options = {}) {
const defaultConfig = {
headers: {
'Content-Type': 'application/json',
sign: localStorage.getItem('sign') || ''
},
params: {},
data: {}
};
config = Object.assign(defaultConfig, config);
if (config.url.match(/requestProject/) === null) {
config.url = config.url + '?requestProject=marketing';
}
// if (config.useName) {
// if (config.method.toLowerCase() === 'post') {
// config.data.requestProject = 'marketing';
// } else if (config.method.toLowerCase() === 'get') {
// config.params.requestProject = 'marketing';
// }
// }
if (config.useForm) {
config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
config.data = qs.stringify(config.data);
}
return service(config);
}
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
</el-form-item> </el-form-item>
</el-radio> </el-radio>
</el-form-item> </el-form-item>
<el-form-item label="生日范围" prop="birthDate1" v-show="form.birth_type == 1 || form.birth_type == 3"> <el-form-item label="生日范围" prop="birthDate1" v-show="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" :picker-options="pickerOptions" type="daterange" placeholder="请选择生日范围" range-separator="~" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker>
</el-form-item> </el-form-item>
<el-form-item label="生日范围" prop="birthDate2" v-show="form.birth_type == 2"> <el-form-item label="生日范围" prop="birthDate2" v-show="form.birth_type == 2">
...@@ -42,9 +42,9 @@ let maxTimeMonth = null; ...@@ -42,9 +42,9 @@ let maxTimeMonth = null;
export default { export default {
data() { data() {
const birthDateValidtor = (rule, value, callback) => { const birthDateValidtor = (rule, value, callback) => {
if ((this.form.birth_type == 1 || this.form.birth_type == 3) && !this.form.birthDate1.length) { if ((this.form.birth_type == 1 || this.form.birth_type == 3) && !this.form.birthDate1) {
return callback(new Error('生日范围不能为空')); return callback(new Error('生日范围不能为空'));
} else if (this.form.birth_type == 2 && !this.form.birthDate2.length) { } else if (this.form.birth_type == 2 && !this.form.birthDate2) {
return callback(new Error('生日范围不能为空')); return callback(new Error('生日范围不能为空'));
} }
callback(); callback();
...@@ -125,11 +125,11 @@ export default { ...@@ -125,11 +125,11 @@ export default {
computed: { computed: {
activeTime() { activeTime() {
let str = ''; let str = '';
if (this.form.birth_type == 1 && this.form.birthDate1.length) { if (this.form.birth_type == 1 && this.form.birthDate1 && this.form.birthDate1.length) {
str = formatDateTimeByType(this.form.birthDate1[0], 'yyyy-MM-dd') + ' 至 ' + formatDateTimeByType(this.form.birthDate1[1], 'yyyy-MM-dd'); str = formatDateTimeByType(this.form.birthDate1[0], 'yyyy-MM-dd') + ' 至 ' + formatDateTimeByType(this.form.birthDate1[1], 'yyyy-MM-dd');
} else if (this.form.birth_type == 2 && this.form.birthDate2.length) { } else if (this.form.birth_type == 2 && this.form.birthDate2 && this.form.birthDate2.length) {
str = formatDateTimeByType(this.form.birthDate2[0], 'yyyy-MM-dd') + ' 至 ' + formatDateTimeByType(this.form.birthDate2[1], 'yyyy-MM-dd'); str = formatDateTimeByType(this.form.birthDate2[0], 'yyyy-MM-dd') + ' 至 ' + formatDateTimeByType(this.form.birthDate2[1], 'yyyy-MM-dd');
} else if (this.form.birth_type == 3 && this.form.birthDate1.length) { } else if (this.form.birth_type == 3 && this.form.birthDate1 && this.form.birthDate1.length) {
let start = this.form.birthDate1[0] - this.form.birth_days * 24 * 60 * 60 * 1000; let start = this.form.birthDate1[0] - this.form.birth_days * 24 * 60 * 60 * 1000;
let end = this.form.birthDate1[1] - this.form.birth_days * 24 * 60 * 60 * 1000; let end = this.form.birthDate1[1] - this.form.birth_days * 24 * 60 * 60 * 1000;
str = formatDateTimeByType(start, 'yyyy-MM-dd') + ' 至 ' + formatDateTimeByType(end, 'yyyy-MM-dd'); str = formatDateTimeByType(start, 'yyyy-MM-dd') + ' 至 ' + formatDateTimeByType(end, 'yyyy-MM-dd');
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
<div class="section"> <div class="section">
<birthSense ref="activeTime1" :data="birthTimeData" v-show="form.scene == 1" /> <birthSense ref="activeTime1" :data="birthTimeData" v-show="form.scene == 1" />
<holidaySense ref="activeTime2" :data="holidayTimeData" v-show="form.scene == 2" /> <holidaySense ref="activeTime2" :data="holidayTimeData" v-show="form.scene == 2" />
<activeTime ref="activeTime" :data="activeTimeData" v-show="form.scene == 3 || form.scene == 4 || form.scene == 5" /> <activeTime ref="activeTime" :data="activeTimeData" v-show="form.scene == 3 || form.scene == 4 || form.scene == 0" />
</div> </div>
<dm-sub-title line>人群规则<span class="tips">针对选择的客户仅会执行一次外呼任务。</span></dm-sub-title> <dm-sub-title line>人群规则<span class="tips">针对选择的客户仅会执行一次外呼任务。</span></dm-sub-title>
<div class="section"> <div class="section">
...@@ -29,13 +29,13 @@ ...@@ -29,13 +29,13 @@
<el-radio v-model="form.memberType" :label="1">客户分组</el-radio> <el-radio v-model="form.memberType" :label="1">客户分组</el-radio>
<div> <div>
<div class="tips" style="margin:0 0 12px 0;">默认为权限范围内的全部客户</div> <div class="tips" style="margin:0 0 12px 0;">默认为权限范围内的全部客户</div>
<el-button v-if="form.memberType == 0 && !memberCrowdWidgetId && form.scene != 4" size="small" @click="ruleVisible = true">添加其他条件</el-button> <el-button v-if="form.memberType == 0 && !memberCrowdWidgetId && form.scene != 0" size="small" @click="ruleVisible = true">添加其他条件</el-button>
<ruleFilter v-show="form.memberType == 0 && form.scene != 4" :visiable.sync="ruleVisible" @save="handleRuleFilterSave" :memberCrowdWidgetId="memberCrowdWidgetId" /> <ruleFilter v-show="form.memberType == 0 && form.scene != 0" :visiable.sync="ruleVisible" @save="handleRuleFilterSave" :memberCrowdWidgetId="memberCrowdWidgetId" />
<el-button v-if="form.memberType == 1 && !selectedGroup.length" size="small" @click="groupVisible = true">添加分组</el-button> <el-button v-if="form.memberType == 1 && !selectedGroup.length" size="small" @click="groupVisible = true">添加分组</el-button>
<gic-new-member-group v-show="form.memberType == 1" :visiable.sync="groupVisible" :defaltSelected="selectedGroup" @change="confirmGroupDialog" /> <gic-new-member-group v-show="form.memberType == 1" :visiable.sync="groupVisible" :defaltSelected="selectedGroup" @change="confirmGroupDialog" />
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="消费条件" v-if="form.scene == 4"> <el-form-item label="消费条件" v-if="form.scene == 0">
<div class="consumeLine"> <div class="consumeLine">
<el-checkbox v-model="form.consume_days_flag" :true-label="1" :false-label="0" :disabled="disabledCheck" @change="handleLastconsume('days')">最近消费间隔</el-checkbox> <el-checkbox v-model="form.consume_days_flag" :true-label="1" :false-label="0" :disabled="disabledCheck" @change="handleLastconsume('days')">最近消费间隔</el-checkbox>
<el-input-number v-model="form.consume_days" controls-position="right" :max="730" :min="30" size="small" style="margin:0 10px;" /> <el-input-number v-model="form.consume_days" controls-position="right" :max="730" :min="30" size="small" style="margin:0 10px;" />
...@@ -48,8 +48,8 @@ ...@@ -48,8 +48,8 @@
<el-checkbox v-model="form.consume_amount_flag" :true-label="1" :false-label="0" :disabled="disabledCheck" @change="handleLastconsume('amount')">累计消费金额</el-checkbox> <el-checkbox v-model="form.consume_amount_flag" :true-label="1" :false-label="0" :disabled="disabledCheck" @change="handleLastconsume('amount')">累计消费金额</el-checkbox>
<el-input-number v-model="form.consume_amount" controls-position="right" :max="100000" :min="1" size="small" style="margin:0 10px;" /> <el-input-number v-model="form.consume_amount" controls-position="right" :max="100000" :min="1" size="small" style="margin:0 10px;" />
</div> </div>
<el-button size="small" @click="ruleVisible2 = true" v-if="!memberCrowdWidgetId">添加其它条件</el-button> <el-button size="small" @click="ruleVisible2 = true" v-if="form.memberType == 0 && !memberCrowdWidgetId">添加其它条件</el-button>
<ruleFilter :visiable.sync="ruleVisible2" @save="handleRuleFilterSave" :memberCrowdWidgetId="memberCrowdWidgetId" :hideId="hideId" /> <ruleFilter v-show="form.memberType == 0" :visiable.sync="ruleVisible2" @save="handleRuleFilterSave" :memberCrowdWidgetId="memberCrowdWidgetId" :hideId="hideId" />
<span class="tips">勾选消费条件后,添加规则不支持选择【金字塔分层】</span> <span class="tips">勾选消费条件后,添加规则不支持选择【金字塔分层】</span>
</el-form-item> </el-form-item>
<el-form-item label="预计覆盖人数"> <el-form-item label="预计覆盖人数">
...@@ -224,7 +224,7 @@ ...@@ -224,7 +224,7 @@
</dm-form-bottom> </dm-form-bottom>
</el-form> </el-form>
<lib-message v-if="smsDialogVisible" :show.sync="smsDialogVisible" :useByEcm="false" @sendItem="handleSendItem"></lib-message> <lib-message v-if="smsDialogVisible" :show.sync="smsDialogVisible" :useByEcm="false" @sendItem="handleSendItem"></lib-message>
<tagPop :visiable.sync="tagsDialogVisible" /> <tagPop :visiable.sync="tagsDialogVisible" @save="saveTagPop" />
<el-dialog :title="tipsDialogContent.title" :visible="tipsDialogContent.visible" width="700px" @close="tipsDialogContent.visible = false"> <el-dialog :title="tipsDialogContent.title" :visible="tipsDialogContent.visible" width="700px" @close="tipsDialogContent.visible = false">
<div class="gradeContent"> <div class="gradeContent">
<div class="tips"> <div class="tips">
...@@ -323,8 +323,8 @@ export default { ...@@ -323,8 +323,8 @@ export default {
// 打标签列表 // 打标签列表
{ {
options: [], options: [],
id: 'fd6b44967aa647bcadfad10706244c56', id: '',
name: '区间' name: ''
} }
], ],
smsList: [ smsList: [
...@@ -560,8 +560,9 @@ export default { ...@@ -560,8 +560,9 @@ export default {
async getMemberCount() { async getMemberCount() {
const activeTimeData = await this.$refs[`activeTime${[1, 2].includes(this.form.scene) ? this.form.scene : ''}`].submit(); const activeTimeData = await this.$refs[`activeTime${[1, 2].includes(this.form.scene) ? this.form.scene : ''}`].submit();
const { startDate, endDate, birth_type, birth_days, holiday_date, holiday_type, holiday_name } = activeTimeData; const { startDate, endDate, birth_type, birth_days, holiday_date, holiday_type, holiday_name } = activeTimeData;
const { scene, consume_days_flag, consume_days, consume_times_flag, consume_times, consume_amount_flag, consume_amount, memberType, filterJson } = this.form; const { scene, consume_days_flag, consume_days, consume_times_flag, consume_times, consume_amount_flag, consume_amount, memberType } = this.form;
let sceneJson = JSON.stringify({}); let sceneJson = JSON.stringify({});
let filterJson = '';
if (scene == 1) { if (scene == 1) {
sceneJson = JSON.stringify({ sceneJson = JSON.stringify({
birth_type, birth_type,
...@@ -583,6 +584,11 @@ export default { ...@@ -583,6 +584,11 @@ export default {
consume_amount consume_amount
}); });
} }
if (memberType == 0) {
filterJson = this.memberCrowdWidgetId;
} else if (memberType == 1) {
filterJson = this.selectedGroupIds;
}
const data = { const data = {
memberType, memberType,
sceneJson, sceneJson,
...@@ -606,12 +612,13 @@ export default { ...@@ -606,12 +612,13 @@ export default {
handleRuleFilterSave(id, data) { handleRuleFilterSave(id, data) {
this.memberCrowdWidgetId = id; this.memberCrowdWidgetId = id;
this.filterFrontShow = data ? JSON.parse(data.filterFrontShow) : []; this.filterFrontShow = data ? JSON.parse(data.filterFrontShow) : [];
console.log(data); this.getMemberCount();
}, },
/**客户分组 */ /**客户分组 */
confirmGroupDialog(arr, idStr) { confirmGroupDialog(arr, idStr) {
this.selectedGroup = arr; this.selectedGroup = arr;
this.selectedGroupIds = idStr; this.selectedGroupIds = idStr;
this.getMemberCount();
console.log(arr); console.log(arr);
console.log(idStr); console.log(idStr);
}, },
...@@ -664,10 +671,14 @@ export default { ...@@ -664,10 +671,14 @@ export default {
}, },
/** 根据客户意向打标签 */ /** 根据客户意向打标签 */
openTagsDialog(index) { openTagsDialog(index) {
this.currentIndex = index;
this.tagsDialogVisible = true; this.tagsDialogVisible = true;
}, },
confirmTagsDialog() { saveTagPop(data) {
this.tagsDialogVisible = false; const { tagItemId, tagItemName } = data;
this.tagMatchList[this.currentIndex].id = tagItemId;
this.tagMatchList[this.currentIndex].name = tagItemName;
this.tagMatchList = this.tagMatchList.splice(0);
}, },
handleTagClose(item) { handleTagClose(item) {
const obj = this.tagMatchList.find(val => val.id == item.id); const obj = this.tagMatchList.find(val => val.id == item.id);
......
...@@ -123,7 +123,7 @@ export default { ...@@ -123,7 +123,7 @@ export default {
form: { form: {
activityName: '', //活动名称 activityName: '', //活动名称
activityId: '', //活动id activityId: '', //活动id
scene: '', //活动场景 「1 客户生日」、「2 节日活动邀约」、「3 加企微好友」、「4 客户复购」、「5 其它场景」 scene: '', //活动场景 「1 客户生日」、「2 节日活动邀约」、「3 加企微好友」、「4 客户复购」、「0 其它场景」
aiTemplateId: '', //话术模板id aiTemplateId: '', //话术模板id
memberType: 0, // 会员类型(0:会员筛选,1:会员分组) memberType: 0, // 会员类型(0:会员筛选,1:会员分组)
filterJson: '{"list":[{"type":"or","list":[{"type":"data","data":{"key":"city","compute":"in","value":"330100"}}]},{"type":"or","list":[{"type":"data","data":{"key":"mainStoreId","compute":"in","value":"e8fdc210a59411ecb9cb9f7ed8d63716","dealKey":"storeWidget"}}]}],"type":"and"}', filterJson: '{"list":[{"type":"or","list":[{"type":"data","data":{"key":"city","compute":"in","value":"330100"}}]},{"type":"or","list":[{"type":"data","data":{"key":"mainStoreId","compute":"in","value":"e8fdc210a59411ecb9cb9f7ed8d63716","dealKey":"storeWidget"}}]}],"type":"and"}',
......
<template>
<el-dialog :visible.sync="showPop" :title="options.popTitle" width="600px" @close="closePop" destroy-on-close>
<div class="manualTagEdit-wrap">
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px">
<el-form-item label="标签名称:" prop="tagName">
<el-input class="w-full" placeholder="请输入内容" v-model="ruleForm.tagName" :maxlength="15"></el-input>
<label class="input-label">{{ ruleForm.tagName.length }}/15</label>
</el-form-item>
<el-form-item label="所属分类:" prop="tagLevel">
<div class="tagLevel">
<el-form-item prop="tagTwoLevelGroupId" class="fl">
<el-select class="w-225" placeholder="请选择" v-model="ruleForm.tagTwoLevelGroupId" @change="changeTwo">
<el-option v-for="item in optionsTwo" :key="item.tagLevelGroupId" :label="item.levelName" :value="item.tagLevelGroupId"> </el-option>
</el-select>
</el-form-item>
<el-form-item prop="tagLevelGroupId" class="fl">
<el-select class="w-225 ml10" placeholder="请选择" v-model="ruleForm.tagLevelGroupId">
<el-option v-for="item in optionsThree" :key="item.tagLevelGroupId" :label="item.levelName" :value="item.tagLevelGroupId"> </el-option>
</el-select>
</el-form-item>
</div>
</el-form-item>
<el-form-item label="标签值:" prop="tagValue">
<div class="tag-list">
<tag-value-item v-for="item in ruleForm.tagValue" :current-length="ruleForm.tagValue.length" :key="item.id" :item="item" class="w-full" @add="onAddTagVal" @del="onDelTagVal" />
</div>
</el-form-item>
<el-form-item label="标签描述:" prop="tagDescribe">
<el-input class="w-full" type="textarea" v-model="ruleForm.tagDescribe" :maxlength="100" show-word-limit placeholder="请输入标签描述,最多100字"></el-input>
</el-form-item>
</el-form>
<div class="manualTagEdit-btns">
<el-button @click="$emit('update:showPop', false)">取消</el-button>
<el-button type="primary" @click="confirmSave">保存</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
const validateTagValue = (rule, value, cb) => {
if (value.some(el => !el.tagItemName)) {
return cb(new Error('请完善标签值'));
}
cb();
};
const GenNonDuplicateID = () => {
return Math.random().toString();
};
import tagValueItem from './tag-value-item.vue';
export default {
name: 'manualTagEdit',
props: {
showPop: Boolean,
options: Object
},
data() {
return {
// 编辑标签的时候,获取标签的 id
// tagId: '',
// 标签基本信息模块的表单
ruleForm: {
tagName: '',
tagLevel: 'test',
tagTwoLevelGroupId: '',
tagLevelGroupId: '',
tagDescribe: '',
pending: false,
tagSort: null,
tagType: 0,
tagValue: [{ id: GenNonDuplicateID(), deleteFlag: false, tagItemName: '' }]
},
// 标签基本信息模块的表单验证
rules: {
tagName: [{ required: true, message: '请输入标签名称', trigger: 'blur' }],
tagLevel: [{ required: true, message: '' }],
tagLevelGroupId: [{ required: true, message: '请选择所属分类', trigger: 'blur' }],
tagTwoLevelGroupId: [{ required: true, message: '请选择所属分类', trigger: 'blur' }],
tagType: [{ required: true, trigger: 'blur' }],
tagValue: [{ required: true, trigger: 'blur', validator: validateTagValue }]
},
// 标签所属分类的下拉列表数据
optionsTwo: [],
optionsThree: [],
// 标签值列表的数据
tagValTableData: [],
preSyncWmStatus: 0,
deleteList: [],
isEdit: false
};
},
watch: {
options: {
deep: true,
immediate: true,
handler(newVal) {
this.ruleForm.tagTwoLevelGroupId = newVal.tagTwoLevelGroupId;
this.ruleForm.tagLevelGroupId = newVal.tagLevelGroupId;
if (newVal.tagId) {
this.isEdit = true;
this.getTagData(newVal.tagId);
} else {
this.isEdit = false;
this.ruleForm.tagName = '';
this.ruleForm.tagDescribe = '';
this.ruleForm.tagSort = null;
this.ruleForm.tagType = 0;
this.ruleForm.tagTwoLevelGroupId = '';
this.ruleForm.tagLevelGroupId = '';
// 刷新tagValue
this.ruleForm.tagValue = [{ id: GenNonDuplicateID(), deleteFlag: false, tagItemName: '' }];
// this.getOptionsThree(newVal.tagTwoLevelGroupId);
}
// 获取初始化分类是否同步至微盟的状态
const initData = this.optionsThree.find(el => el.tagLevelGroupId == this.ruleForm.tagLevelGroupId);
if (initData) this.preSyncWmStatus = initData.syncWmFlag;
this.getOptionsTwo();
}
}
},
components: {
tagValueItem
},
methods: {
closePop() {
this.$refs.ruleForm.resetFields();
this.$emit('update:showPop', false);
},
// 保存标签基本信息
confirmSave() {
if (this.ruleForm.pending) return;
this.ruleForm.pending = true;
this.$refs.ruleForm.validate(valid => {
if (valid) {
const isSyncWm = this.optionsThree.find(el => el.tagLevelGroupId == this.ruleForm.tagLevelGroupId).syncWmFlag;
const isAutoSync = this.options.isSync;
// 开启手动同步且移动前已同步至微盟,移动后未同步至微盟
if (!isAutoSync && this.preSyncWmStatus && !isSyncWm) {
this.$confirm('该分类未开启微盟标签同步,修改后标签将不会再同步至微盟,并且已同步至微盟侧的会员标签将从微盟侧删除,是否继续保存?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
this.saveApi();
})
.catch(() => (this.ruleForm.pending = false));
} else {
this.saveApi();
}
} else {
this.ruleForm.pending = false;
}
});
},
// 保存标签基本信息
saveApi() {
const tagItemList = this.ruleForm.tagValue.concat(this.deleteList).map(el => {
delete el.id;
return el;
});
const data = {
tagId: this.options.tagId,
tagName: this.ruleForm.tagName,
tagDescribe: this.ruleForm.tagDescribe,
tagLevelGroupId: this.ruleForm.tagLevelGroupId,
tagItemList,
isMultiple: this.ruleForm.tagType,
tagType: 2 // 2 活动标签 1 手工
};
this.axios
.post('/gic-member-tag-web/memberTag/saveHandMemberTag?requestProject=marketing', data)
.then(res => {
const { errorCode, message } = res.data;
this.ruleForm.pending = false;
if (errorCode !== 1) {
this.$message.error({
duration: 1000,
message: message
});
return;
}
this.$message.success('保存成功', 'success');
this.$emit('save');
this.closePop();
})
.catch(error => {
this.ruleForm.pending = false;
this.$message.error({
duration: 1000,
message: error.message
});
});
},
// 获取二级分类列表
getOptionsTwo() {
const params = { tagLevelType: 2 };
console.log(params);
this.axios
.get('/gic-member-tag-web/tagLevel/handSecondLevel?requestProject=marketing&tagLevelType=2')
.then(res => {
const { errorCode, result } = res.data;
if (errorCode === 1) {
this.optionsTwo = result;
}
})
.catch(error => {
this.$message.error({
duration: 1000,
message: error.message
});
});
},
// 点击二级分类获取三级分类列表
changeTwo(value) {
this.ruleForm.tagLevelGroupId = '';
this.getOptionsThree(value);
},
// 获取三级分类列表
getOptionsThree(tagLevelGroupId) {
this.axios
.get(`/gic-member-tag-web/tagLevel/handThirdLevel?requestProject=marketing&tagLevelGroupId=${tagLevelGroupId}`)
.then(res => {
const { errorCode, result } = res.data;
if (errorCode === 1) {
this.optionsThree = result;
}
})
.catch(error => {
this.$message.error({
duration: 1000,
message: error.message
});
});
},
// 编辑时获取当前标签数据
getTagData(tagId) {
this.axios
.get(`/gic-member-tag-web/memberTag/getTagById?requestProject=marketing&tagId=${tagId}`)
.then(res => {
const { errorCode, result } = res.data;
if (errorCode === 1) {
this.ruleForm.tagName = result.tagName;
this.ruleForm.tagLevelGroupId = result.tagLevelGroupId;
this.ruleForm.tagTwoLevelGroupId = result.tagTwoLevelGroupId;
this.ruleForm.tagDescribe = result.tagDescribe;
this.ruleForm.tagSort = result.sort;
this.ruleForm.tagType = result.isMultiple;
this.ruleForm.tagValue = result.itemList || [];
if (result.itemList.length) {
this.ruleForm.tagValue = result.itemList.map(el => {
el.id = GenNonDuplicateID();
el.deleteFlag = false;
return el;
});
} else {
this.ruleForm.tagValue = [{ id: GenNonDuplicateID(), deleteFlag: false, tagItemName: '' }];
}
// 根据已选二级 id 获取三级列表
if (result.tagTwoLevelGroupId) {
this.getOptionsThree(result.tagTwoLevelGroupId);
}
}
})
.catch(err => {
console.log(err);
});
},
onAddTagVal(id) {
const index = this.ruleForm.tagValue.findIndex(el => el.id == id);
const obj = { id: GenNonDuplicateID(), deleteFlag: false, tagItemName: '' };
this.ruleForm.tagValue.splice(index + 1, 0, obj);
},
onDelTagVal(id) {
const index = this.ruleForm.tagValue.findIndex(el => el.id == id);
if (this.ruleForm.tagValue[index].tagItemId) {
// 编辑数据删除的维护到list中,修改deletFlag= true在合并到请求数据中
const deleteData = this.ruleForm.tagValue.splice(index, 1)[0];
deleteData.deleteFlag = true;
this.deleteList.push(deleteData);
} else {
this.ruleForm.tagValue.splice(index, 1);
}
}
}
};
</script>
<style lang="scss" scoped>
/deep/ .el-dialog-title {
font-size: 16px;
font-weight: bold;
}
.input-label {
position: absolute;
top: 2px;
right: 45px;
z-index: 1;
font-size: 12px;
color: #c0c4cc;
}
.textarea-label {
.input-label {
top: 92px;
right: 45px;
}
}
.manualTagEdit-btns {
padding: 10px 0;
text-align: right;
}
.w-447 {
width: 447px;
}
.w-560 {
width: 560px;
}
.icon {
font-size: 14px;
color: #606266;
margin-left: 1px;
position: relative;
top: 1px;
}
.w-full {
width: 100%;
}
.w-225 {
width: 225px;
}
.ml10 {
margin-left: 10px;
}
footer {
margin-bottom: 4px;
}
.tag-list {
max-height: 100px;
overflow-y: auto;
}
.manual-dialog .el-dialog__footer {
margin-top: 15px;
border-top: 1px solid #dcdfe6;
}
.uploading .uploading-progress .el-progress__text {
font-size: 12px !important;
color: #909399;
}
.manualTagEdit-wrap .el-form-item__label {
color: #606266;
}
.manualTagEdit-wrap .el-textarea__inner {
height: 96px;
resize: none;
box-sizing: border-box;
}
.tag-value-wrapper .tag-cell {
height: 56px;
}
.tag-value-wrapper .tag-head {
height: 23px;
}
.fl {
float: left;
}
.tagLevel {
display: flex;
}
</style>
<template>
<div class="flex">
<el-input v-model="item.tagItemName" placeholder="请输入标签值" class="w-380" maxlength="15" show-word-limit @change="onChange" />
<template>
<i v-if="currentLength < 50" class="iconfont plus icon margin icon-PlusOutlined" @click="add" />
<i v-else class="icon margin" />
</template>
<i v-if="currentLength > 1" class="iconfont delete icon icon-delete" @click="del" />
</div>
</template>
<script>
export default {
name: 'TagValueItem',
props: {
item: Object,
currentLength: Number
},
data() {
return {
tagValue: ''
};
},
methods: {
add() {
this.$emit('add', this.item.id);
},
del() {
this.$emit('del', this.item.id);
}
}
};
</script>
<style scoped lang="scss">
@mixin flex($justify, $alignItems) {
display: flex;
justify-content: $justify;
align-items: $alignItems;
}
.flex {
@include flex(initial, center);
&:not(:last-of-type) {
margin-bottom: 20px;
}
}
.w-380 {
width: 380px;
}
.icon {
display: inline-block;
width: 24px;
height: 24px;
border-radius: 2px;
text-align: center;
line-height: 24px;
cursor: pointer;
}
.margin {
margin: 0 7px 0 16px;
}
.plus {
color: #2f54eb;
&:hover {
background: rgba(47, 84, 235, 0.1);
}
}
.delete {
color: #f5222d;
&:hover {
background: rgba(245, 34, 45, 0.1);
}
}
</style>
<template> <template>
<el-dialog title="选择标签" :visible.sync="visiable" width="900px" :before-close="close"> <div>
<div class="container"> <el-dialog title="选择标签" :visible.sync="visiable" width="900px" :before-close="close">
<el-tabs tab-position="left" @tab-click="onTabsClick" v-model="activeName"> <div class="container">
<el-tab-pane :label="item.levelName" v-for="item in tabList" :key="item.id" :name="item.id" v-loading="tabPaneLoading"> <el-tabs tab-position="left" @tab-click="onTabsClick" v-model="activeName">
<div class="rightContent"> <el-tab-pane :label="item.levelName" v-for="item in tabList" :key="item.id" :name="item.id" v-loading="tabPaneLoading">
<div class="searchWrap"> <div class="rightContent">
<div><el-input prefix-icon="el-icon-search" v-model="search" placeholder="请输入标签名称" @keyup.enter.native="getList" clearable @clear="getList"></el-input></div> <div class="searchWrap">
<div class="btn"><el-button size="small" type="primary" @click="addGroup">新增标签</el-button></div> <div><el-input prefix-icon="el-icon-search" v-model="search" placeholder="请输入标签名称" @keyup.enter.native="getList" clearable @clear="getList"></el-input></div>
<div class="btn"><el-button size="small" type="primary" @click="showPopVisible = true">新增标签</el-button></div>
</div>
<div class="radioContainer">
<div v-for="item in valueList" :key="item.tagId" class="radioLine">
<div class="lineTitle">{{ item.tagName }}</div>
<el-radio v-for="value in item.itemList" :key="value.tagItemId" :label="value" v-model="selectedTag">{{ value.tagItemName }}</el-radio>
</div>
</div>
<el-pagination class="fr" layout="prev, pager, next" v-if="totalCount" :total="totalCount" :page-size="pageSize" :current-page.sync="currentPage" @current-change="getGroupList"> </el-pagination>
</div> </div>
<div class="radioContainer"> </el-tab-pane>
<el-radio v-for="item in value" :key="item.tagId" :label="item.tagId">{{ item.tagName }}</el-radio> </el-tabs>
</div> </div>
<el-pagination layout="prev, pager, next" v-if="totalCount" :total="totalCount" :page-size="pageSize" :current-page.sync="currentPage" @current-change="getGroupList"> </el-pagination>
</div> <div slot="footer" class="dialog-footer">
</el-tab-pane> <el-button @click="close">取消</el-button>
</el-tabs> <el-button type="primary" @click="confirm">确定</el-button>
</div> </div>
<div slot="footer" class="dialog-footer"> </el-dialog>
<el-button @click="close">取消</el-button> <manual-tag-edit :options="manualTagPop" :showPop.sync="showPopVisible" @save="addNewTag"></manual-tag-edit>
<el-button type="primary" @click="confirm">确定</el-button> </div>
</div>
</el-dialog>
</template> </template>
<script> <script>
import { platformTagPageListV2, platformHomePageV2 } from '@/service/api/aiApi.js'; import { pageMemberTagDetail, platformHomePageV2 } from '@/service/api/aiApi.js';
import ManualTagEdit from './manualTagEdit';
export default { export default {
data() { data() {
return { return {
activeName: '', activeName: '',
search: '', search: '',
tabList: [], tabList: [],
value: [], valueList: [],
tabPaneLoading: false, tabPaneLoading: false,
totalCount: 0, totalCount: 0,
currentPage: 1, currentPage: 1,
pageSize: 40 pageSize: 5,
showPopVisible: false,
manualTagPop: {
show: false,
popTitle: '',
tagId: '',
tagLevelGroupId: '',
tagTwoLevelGroupId: '',
isSync: false
},
selectedTag: ''
}; };
}, },
props: { props: {
...@@ -47,32 +65,48 @@ export default { ...@@ -47,32 +65,48 @@ export default {
mounted() { mounted() {
this.getPlatformHomePageV2(); this.getPlatformHomePageV2();
}, },
components: {
ManualTagEdit
},
methods: { methods: {
confirm() {
if (!this.selectedTag) {
this.$message.waring('请选择标签');
return;
}
this.$emit('save', this.selectedTag);
this.close();
},
addNewTag() {
this.activeName = this.tabList[0].id;
this.currentPage = 1;
this.getPageMemberTagDetail();
},
getList() { getList() {
this.currentPage = 1; this.currentPage = 1;
this.getPlatformTagPageListV2(); this.getPageMemberTagDetail();
}, },
onTabsClick(val) { onTabsClick(val) {
const { name } = val; const { name } = val;
console.log(name); console.log(name);
this.getPlatformTagPageListV2(); this.getPageMemberTagDetail();
this.currentPage = 1; this.currentPage = 1;
}, },
close() { close() {
this.selectedTag = '';
this.$emit('update:visiable', false); this.$emit('update:visiable', false);
}, },
async getPlatformTagPageListV2() { async getPageMemberTagDetail() {
const param = { const param = {
search: this.search, search: this.search,
tagLevelGroupId: this.activeName != 2 ? this.activeName : 0, tagLevelGroupId: this.activeName,
// tagType: 2,
pageNum: this.currentPage, pageNum: this.currentPage,
pageSize: this.pageSize pageSize: this.pageSize
}; };
const { result } = await platformTagPageListV2(param); const { result } = await pageMemberTagDetail(param);
if (result) { if (result) {
this.totalCount = result.totalCount; this.totalCount = result.totalCount;
this.value = result.result; this.valueList = result.result;
} }
}, },
async getPlatformHomePageV2() { async getPlatformHomePageV2() {
...@@ -81,11 +115,12 @@ export default { ...@@ -81,11 +115,12 @@ export default {
}; };
const { result } = await platformHomePageV2(param); const { result } = await platformHomePageV2(param);
if (result) { if (result) {
this.tabList = [{ levelName: '所有活动标签', id: 2 }, ...result[0].children]; this.tabList = [{ levelName: '所有活动标签', id: result[0].tagLevelGroupId }, ...result[0].children];
} }
if (this.tabList.length) { if (this.tabList.length) {
this.activeName = this.tabList[0].id; this.activeName = this.tabList[0].id;
this.getPlatformTagPageListV2(); this.currentPage = 1;
this.getPageMemberTagDetail();
} }
} }
} }
...@@ -108,12 +143,25 @@ export default { ...@@ -108,12 +143,25 @@ export default {
border: 1px solid #dcdfe6; border: 1px solid #dcdfe6;
} }
.radioContainer { .radioContainer {
display: flex;
flex-wrap: wrap;
gap: 10px;
height: 400px; height: 400px;
overflow-y: auto;
.el-radio + .el-radio { .el-radio + .el-radio {
margin: 0; margin: 0;
} }
} }
.radioLine {
.lineTitle {
font-weight: bolder;
margin-bottom: 12px;
width: 100%;
}
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 24px;
}
.fr {
float: right;
}
</style> </style>
...@@ -89,7 +89,7 @@ ...@@ -89,7 +89,7 @@
</template> </template>
<script> <script>
import { page, rechargeCenter, stopActivityPlan, startActivityPlan } from '@/service/api/aiApi.js'; import { page, rechargeCenter, stopActivityPlan, startActivityPlan, pageStatistics } from '@/service/api/aiApi.js';
import { formatDateTimeByType } from '@/utils/index.js'; import { formatDateTimeByType } from '@/utils/index.js';
import filterAvater from '@/mixins/filterAvater.js'; import filterAvater from '@/mixins/filterAvater.js';
import dmDropdown from '@/components/dm-drop-down/dm-drop-down'; import dmDropdown from '@/components/dm-drop-down/dm-drop-down';
...@@ -162,7 +162,7 @@ export default { ...@@ -162,7 +162,7 @@ export default {
limitCode: '' limitCode: ''
}, },
visible: row => { visible: row => {
return row.log_flag === 1; return row.logFlag === 1;
}, },
handler: row => handler: row =>
this.$router.push({ this.$router.push({
...@@ -180,7 +180,7 @@ export default { ...@@ -180,7 +180,7 @@ export default {
limitCode: '' limitCode: ''
}, },
visible: row => { visible: row => {
return row.log_flag === 1; return row.logFlag === 1;
}, },
handler: row => { handler: row => {
this.$router.push({ this.$router.push({
...@@ -219,7 +219,7 @@ export default { ...@@ -219,7 +219,7 @@ export default {
}, },
{ {
title: '其它场景', title: '其它场景',
scene: 5, scene: 0,
iconName: 'icon-qitachangjing', iconName: 'icon-qitachangjing',
content: '自定义营销场景' content: '自定义营销场景'
} }
...@@ -238,7 +238,7 @@ export default { ...@@ -238,7 +238,7 @@ export default {
label: '客户复购' label: '客户复购'
}, },
{ {
value: 5, value: 0,
label: '其它场景' label: '其它场景'
} }
], ],
...@@ -355,10 +355,32 @@ export default { ...@@ -355,10 +355,32 @@ export default {
params.endTime = formatDateTimeByType(params.time[1]).replace('00:00:00', '23:59:59'); params.endTime = formatDateTimeByType(params.time[1]).replace('00:00:00', '23:59:59');
} }
delete params.time; delete params.time;
const { result } = await page(params).finally(() => (this.loading = false)); const { result } = await page(params);
this.tableData = result.list || []; if (result) {
this.total = result.total; this.tableData = result.list || [];
console.log(this.tableData); const ids = this.tableData.map(item => item.activityId).join(',');
this.total = result.total;
console.log(this.tableData);
this.pageStatistics(ids);
} else {
this.loading = false;
}
},
async pageStatistics(ids) {
const { result } = await pageStatistics({ ids }).finally(() => (this.loading = false));
if (result) {
result.forEach(element => {
let obj = this.tableData.find(item => item.activityId == element.activityId);
const { marketingNumber, outboundNumber, totalConnectionNumber, telephoneConnectionRate, connectionIntentionRate } = element;
obj.marketingNumber = marketingNumber;
obj.outboundNumber = outboundNumber;
obj.totalConnectionNumber = totalConnectionNumber;
obj.telephoneConnectionRate = telephoneConnectionRate;
obj.connectionIntentionRate = connectionIntentionRate;
});
}
this.tableData = this.tableData.splice(0);
}, },
stopTask(row) { stopTask(row) {
this.$confirm('任务终止后未外呼的客户将停止外呼任务,终止后不可重新启用任务,是否继续终止任务?', '提示', { this.$confirm('任务终止后未外呼的客户将停止外呼任务,终止后不可重新启用任务,是否继续终止任务?', '提示', {
......
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