Commit d8da88f3 by crushh

update: dist

parents a9e6c250 726029b9
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><link rel="shortcut icon" href=./static/img/favicon.ico><title></title><link rel=stylesheet type=text/css href=static/css/common.css><link rel=stylesheet href=//at.alicdn.com/t/font_688955_2dxzdzrb3a7.css><script src=//at.alicdn.com/t/font_688955_2dxzdzrb3a7.js></script><link rel=stylesheet href=//at.alicdn.com/t/font_3229694_f4zx0uhc8y.css><script src=//at.alicdn.com/t/font_3229694_f4zx0uhc8y.js></script><link src=//at.alicdn.com/t/font_2859043_udehp133w1.css><script src=//at.alicdn.com/t/font_2859043_udehp133w1.js></script><link rel=stylesheet href=//at.alicdn.com/t/font_2996579_dv9vctk5vdt.css><script src=//at.alicdn.com/t/font_2996579_dv9vctk5vdt.js></script><link href=/marketing/static/css/main.dd3ee59138a403db2b2df40befbf51dc.css rel=stylesheet></head><body><div id=app><div class=el-loading-spinner style="width: 98%;"><svg viewBox="25 25 50 50" class=circular><circle cx=50 cy=50 r=20 fill=none class=path></circle></svg></div></div><script>(function() {
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><link rel="shortcut icon" href=./static/img/favicon.ico><title></title><link rel=stylesheet type=text/css href=static/css/common.css><link rel=stylesheet href=//at.alicdn.com/t/font_688955_2dxzdzrb3a7.css><script src=//at.alicdn.com/t/font_688955_2dxzdzrb3a7.js></script><link rel=stylesheet href=//at.alicdn.com/t/font_3229694_f4zx0uhc8y.css><script src=//at.alicdn.com/t/font_3229694_f4zx0uhc8y.js></script><link src=//at.alicdn.com/t/font_2859043_udehp133w1.css><script src=//at.alicdn.com/t/font_2859043_udehp133w1.js></script><link rel=stylesheet href=//at.alicdn.com/t/font_2996579_dv9vctk5vdt.css><script src=//at.alicdn.com/t/font_2996579_dv9vctk5vdt.js></script><link href=/marketing/static/css/main.187f68f8eac900c8faa5c1fee1b0f026.css rel=stylesheet></head><body><div id=app><div class=el-loading-spinner style="width: 98%;"><svg viewBox="25 25 50 50" class=circular><circle cx=50 cy=50 r=20 fill=none class=path></circle></svg></div></div><script>(function() {
var src = '/component/static/import-component.js?timestrap=' + new Date().getTime();
var host = window.location.host;
host = host.indexOf('localhost') > -1 || host.indexOf('192.168') > -1 ? 'gicdev.demogic.com' : host;
document.write('<script src="//' + host + src + '"><\/script>');
})();</script><script src=//web-1251519181.file.myqcloud.com/components/pagination.1.0.8.js></script><script src=//web-1251519181.file.myqcloud.com/components/track.1.0.4.js></script><script src=//web-1251519181.file.myqcloud.com/components/upload-file.1.0.10.js></script><script type=text/javascript src=/marketing/static/js/manifest.b8f7a74aeebb1a4dc254.js></script><script type=text/javascript src=/marketing/static/js/vendor.e0ebad0c4fec1c8f90bf.js></script><script type=text/javascript src=/marketing/static/js/main.49efa4669cdd190b2269.js></script></body></html>
\ No newline at end of file
})();</script><script src=//web-1251519181.file.myqcloud.com/components/pagination.1.0.8.js></script><script src=//web-1251519181.file.myqcloud.com/components/track.1.0.4.js></script><script src=//web-1251519181.file.myqcloud.com/components/upload-file.1.0.10.js></script><script type=text/javascript src=/marketing/static/js/manifest.7e35f053e02d60dba1f0.js></script><script type=text/javascript src=/marketing/static/js/vendor.e0ebad0c4fec1c8f90bf.js></script><script type=text/javascript src=/marketing/static/js/main.ff5713dd087f9e7d3ef5.js></script></body></html>
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
!function(e){var a=window.webpackJsonp;window.webpackJsonp=function(n,t,o){for(var f,d,i,b=0,u=[];b<n.length;b++)d=n[b],c[d]&&u.push(c[d][0]),c[d]=0;for(f in t)Object.prototype.hasOwnProperty.call(t,f)&&(e[f]=t[f]);for(a&&a(n,t,o);u.length;)u.shift()();if(o)for(b=0;b<o.length;b++)i=r(r.s=o[b]);return i};var n={},c={25:0};function r(a){if(n[a])return n[a].exports;var c=n[a]={i:a,l:!1,exports:{}};return e[a].call(c.exports,c,c.exports,r),c.l=!0,c.exports}r.e=function(e){var a=c[e];if(0===a)return new Promise(function(e){e()});if(a)return a[2];var n=new Promise(function(n,r){a=c[e]=[n,r]});a[2]=n;var t=document.getElementsByTagName("head")[0],o=document.createElement("script");o.type="text/javascript",o.charset="utf-8",o.async=!0,o.timeout=12e4,r.nc&&o.setAttribute("nonce",r.nc),o.src=r.p+"static/js/"+({0:"card",1:"game",2:"wechat",3:"ecm",4:"message",5:"ewash",6:"scan",7:"recharge",8:"activity",9:"signIn",10:"evaluation",11:"cdKey",12:"popup",13:"msg",15:"calllog"}[e]||e)+"."+{0:"41c7631aa9e73c180155",1:"f181ab6eebcbd72190fd",2:"7382607b308fad8e75fc",3:"56696a760b6434ee3776",4:"1aaefaafc2a94a86663f",5:"feb0ffd2cfb795f0d746",6:"2aca5fad371384a0ba3b",7:"fed72fe4c42bb8d8d839",8:"8d4c40ff420c756774b8",9:"e6f1eb3edd0d67e0733b",10:"1a27de8282c8acca16a9",11:"b3c01b56cf6bb230b455",12:"2cc9afcdab04796a1278",13:"0da42538485540d84757",14:"89303590323322a2c37e",15:"d9311e9aefc4261c6843",16:"bea1e19a292b8b599704",17:"cc12e35ea94e31a7caa8",18:"fdc377d2e375560439b8",19:"8c5e16e70f68ed6b292b",20:"bc68fb59d5a3191a267b",21:"3b70c426e7cb5384d238",22:"67ff09408b92aef14903"}[e]+".js";var f=setTimeout(d,12e4);function d(){o.onerror=o.onload=null,clearTimeout(f);var a=c[e];0!==a&&(a&&a[1](new Error("Loading chunk "+e+" failed.")),c[e]=void 0)}return o.onerror=o.onload=d,t.appendChild(o),n},r.m=e,r.c=n,r.d=function(e,a,n){r.o(e,a)||Object.defineProperty(e,a,{configurable:!1,enumerable:!0,get:n})},r.n=function(e){var a=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(a,"a",a),a},r.o=function(e,a){return Object.prototype.hasOwnProperty.call(e,a)},r.p="/marketing/",r.oe=function(e){throw console.error(e),e}}([]);
\ No newline at end of file
!function(e){var c=window.webpackJsonp;window.webpackJsonp=function(a,t,o){for(var f,d,i,u=0,b=[];u<a.length;u++)d=a[u],n[d]&&b.push(n[d][0]),n[d]=0;for(f in t)Object.prototype.hasOwnProperty.call(t,f)&&(e[f]=t[f]);for(c&&c(a,t,o);b.length;)b.shift()();if(o)for(u=0;u<o.length;u++)i=r(r.s=o[u]);return i};var a={},n={25:0};function r(c){if(a[c])return a[c].exports;var n=a[c]={i:c,l:!1,exports:{}};return e[c].call(n.exports,n,n.exports,r),n.l=!0,n.exports}r.e=function(e){var c=n[e];if(0===c)return new Promise(function(e){e()});if(c)return c[2];var a=new Promise(function(a,r){c=n[e]=[a,r]});c[2]=a;var t=document.getElementsByTagName("head")[0],o=document.createElement("script");o.type="text/javascript",o.charset="utf-8",o.async=!0,o.timeout=12e4,r.nc&&o.setAttribute("nonce",r.nc),o.src=r.p+"static/js/"+({0:"card",1:"game",2:"wechat",3:"ecm",4:"message",5:"ewash",6:"scan",7:"recharge",8:"activity",9:"signIn",10:"evaluation",11:"cdKey",12:"popup",13:"msg",15:"calllog"}[e]||e)+"."+{0:"80d1936ea4de2804dfbc",1:"5a1bfcbdae922c5cb3f1",2:"837762799f9de67f9ff7",3:"75ea62c50b0f84572356",4:"a579e0d4d8aa6f6f6302",5:"203e4f6e985e67df6514",6:"683faea022b925c5c899",7:"fed72fe4c42bb8d8d839",8:"8d4c40ff420c756774b8",9:"936efa151c0c10b84dea",10:"1a27de8282c8acca16a9",11:"b3c01b56cf6bb230b455",12:"2cc9afcdab04796a1278",13:"c7783f06c3125f466186",14:"bd7ce76031c31aada8c0",15:"d9311e9aefc4261c6843",16:"063cbd36444acf6c7b76",17:"8f7c8ec7e22388b2a591",18:"2af26558d70ad004e039",19:"480cefdabd2e30b85ede",20:"f88ddb7978003e576787",21:"3b70c426e7cb5384d238",22:"67ff09408b92aef14903"}[e]+".js";var f=setTimeout(d,12e4);function d(){o.onerror=o.onload=null,clearTimeout(f);var c=n[e];0!==c&&(c&&c[1](new Error("Loading chunk "+e+" failed.")),n[e]=void 0)}return o.onerror=o.onload=d,t.appendChild(o),a},r.m=e,r.c=a,r.d=function(e,c,a){r.o(e,c)||Object.defineProperty(e,c,{configurable:!1,enumerable:!0,get:a})},r.n=function(e){var c=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(c,"a",c),c},r.o=function(e,c){return Object.prototype.hasOwnProperty.call(e,c)},r.p="/marketing/",r.oe=function(e){throw console.error(e),e}}([]);
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
<template>
<div>
<el-button v-for="item in notDropdownList" :disabled="typeof item.disabled === 'function' ? item.disabled(scopeData) : item.disabled" v-bind="{ type: 'text', ...item.props }" :key="item.text" @click="handleCommand(item)">{{ item.text }}</el-button>
<el-dropdown v-if="buttonArray.length > max" v-bind="{ type: 'text', ...dropdownProps }" @click="() => emitEventHandler('click')" @command="handleCommand" @visible-change="bool => emitEventHandler('visible-change', bool)">
<span class="el-dropdown-link">
<i class="iconfont icon-more"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="item in dropdownList" :class="{ 'item-disabled': typeof item.disabled === 'function' ? item.disabled(scopeData) : item.disabled }" :command="item" :key="item.text">
<el-button :disabled="typeof item.disabled === 'function' ? item.disabled(scopeData) : item.disabled" v-bind="{ type: 'text', ...item.props }">{{ item.text }}</el-button>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<script>
export default {
name: 'dm-dropdown',
components: {},
props: {
dropdownProps: {
//Dropdown Attributes
type: Object,
default: () => {}
},
configs: {
type: Array,
default: () => []
},
max: {
type: [Number, String],
default: 3
},
scopeData: Object
},
methods: {
emitEventHandler(event) {
this.$emit(event, ...Array.from(arguments).slice(1));
},
handleCommand(config) {
if (typeof config.disabled == 'function' ? config.disabled(this.scopeData) : config.disabled) return;
config.handler && config.handler(this.scopeData);
this.emitEventHandler('command', { config, data: this.scopeData });
}
},
computed: {
buttonArray() {
return this.configs.filter(item => {
let visible = item.visible;
if (typeof visible === 'boolean') {
return item.visible;
} else if (typeof visible === 'function') {
return item.visible(this.scopeData);
} else {
return true;
}
});
},
notDropdownList() {
return this.buttonArray.length > this.max ? this.buttonArray.slice(0, this.max - 1) : this.buttonArray;
},
dropdownList() {
return this.buttonArray.length > this.max ? this.buttonArray.slice(this.max - 1) : [];
}
}
};
</script>
<style lang="scss" scoped>
.el-dropdown-link {
cursor: pointer;
color: #2f54eb;
}
.el-button--text + .el-dropdown {
margin-left: 8px;
}
.item-disabled {
cursor: not-allowed;
}
</style>
## 示例
```
<el-table-column
fixed="right"
label="操作"
>
<template slot-scope="scope">
<dm-dropdown :scope-data="scope.row" :configs="btnArr" @command="onCommand"/>
</template>
</el-table-column>
export default {
name: 'btn',
data() {
return {
dropdownAttr: {
// splitButton: true
},
btnArr: [
{
text: '查看',
visible: (row)=>row.status === 2, // 不写visible属性默认为true
handler: (row) =>{
console.log(row)
console.log('查看')
},
},
{
text: '编辑',
handler: (row) =>{
console.log(row)
console.log('编辑')
},
},
{
text: '删除',
handler: (row) =>{
console.log(row)
console.log('删除')
}
},
{
text: '复制',
handler: (row) =>{
console.log(row)
console.log('复制')
},
},
{
text: '禁用',
handler: (row) =>{
console.log(row)
console.log('禁用')
},
}
],
}
},
methods: {
onCommand(item) {
console.log(item)
},
}
}
```
### props
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 是否必传 |
| ------------ | ------------ | ------------ | ------------ | ------------ | ------------ |
| scopeData | - | Object | -- | -- | 否 |
| configs | 按钮数组 | Array | [{text:string(必传), visible: boolean \| function, handler: function,props:按钮属性配置(非必传)}] | -- | 是 |
| dropdownProps | el-dropDown的属性 | Object | -- | -- | 否 |
| max | 最多展示几个按钮 | String/Number | -- | 3 | 否 |
#### events
| 事件名称 | 说明 | 参数 |
| ------------ | ------------ | ------------ |
| command | 按钮触发事件 | {config, data} |
### 更新日志:
- v1.0.0 cr by 黄冷<br>
......@@ -120,3 +120,6 @@ export const aiOutboundStoreGroupSplit = params => requests('/api-marketing/stat
// 活动转换门店分组数据
export const aiTransformStoreGroupSplit = params => requests('/api-marketing/statistics/ai-transform-store-group-split', params, true, false, 'get');
// 客户明细导出
export const exportAiCustomDetail = '/api-marketing/statistics/export-ai-custom-detail';
......@@ -72,3 +72,9 @@ export const downloadOImportSmsTemp = config.api + PREFIX + 'download-import-sms
// 卡券营销--导入短信群发--导出发送人群
export const exportSmsImportPlanLog = config.api + PREFIX + 'export-sms-import-plan-log';
//ecm查看筛选人数
export const checkEcmSendCount = params => requests(PREFIX + 'check-ecm-send-count', params);
// 短信群发-删除前查询是否关联活动
export const queryBusiCommonCheck = params => requests('/api-plug/query-busi-common-check', params, true, false, 'get');
......@@ -13,4 +13,7 @@ export const saveStoreSignSetting = params => requests(PREFIX + 'save', params);
// 门店签到配置查询
export const getStoreSignDetail = params => requests(PREFIX + 'get-detail', params);
// 门店签到计划删除
export const delSignPlan = params => requests(PREFIX + 'del-sign-plan', params);
\ No newline at end of file
export const delSignPlan = params => requests(PREFIX + 'del-sign-plan', params);
// 门店签到导出
export const exportStoreSign = config.api + PREFIX + 'export-store-sign';
\ No newline at end of file
......@@ -2,6 +2,7 @@
<div class="data-detail">
<div v-if="analyseFlag" class="page-tip">活动转化金额每天更新 1 次</div>
<el-input v-model="search.search" @change="handleCurrentChange(1)" type="text" placeholder="请输入姓名/昵称/手机号/会员卡号" prefix-icon="el-icon-search" clearable class="search-bar"></el-input>
<el-button class="fr" type="primary" icon="iconfont fz14 icon-cp-xiazai" v-if="$getButtonLimit($buttonCode.marketingAiDetailExport)" :limit-code="$buttonCode.marketingAiDetailExport" @click="exportExcel" size="small" :disabled="!total"> 查询结果导出</el-button>
<el-table :data="tableData" v-loading="loading">
<el-table-column label="基本信息" min-width="200px" show-overflow-tooltip fixed="left">
<div slot-scope="{ row }" class="member-info">
......@@ -42,13 +43,14 @@
</div>
</el-table-column>
</el-table>
<vue-gic-export-excel :dialogVisible.sync="dialogVisible" :dataArr="tableData" :type="2" :excelUrl="excelUrl" :params="params" :projectName="projectName"></vue-gic-export-excel>
<dm-pagination v-if="total > 0" background @size-change="handleSizeChange" @current-change="handleCurrentChange" :total="total" :current-page="search.pageNum" :page-size="search.pageSize" :page-sizes="[20, 40, 60, 80]" layout="total, sizes, prev, pager, next"></dm-pagination>
</div>
</template>
<script>
import { formatDateTimeByType } from '@/utils/index.js';
import { getCustomDetail } from '@/service/api/aiApi.js';
import { getCustomDetail, exportAiCustomDetail } from '@/service/api/aiApi.js';
export default {
name: 'AiDataDetail',
......@@ -65,7 +67,10 @@ export default {
},
tableData: [],
total: 0,
loading: false
loading: false,
dialogVisible: false,
excelUrl: '', // 下载数据的地址
params: {} // 传递的参数
};
},
created() {
......@@ -76,6 +81,16 @@ export default {
console.log('mounted3');
},
methods: {
exportExcel() {
this.params = {
search: this.search.search,
analyseFlag: this.analyseFlag ? 1 : 0,
smsFlag: this.showSendTime ? 1 : 0,
activityId: this.search.activityId
};
this.dialogVisible = true;
this.excelUrl = exportAiCustomDetail;
},
getData() {
this.loading = true;
getCustomDetail(this.search)
......
......@@ -39,12 +39,11 @@
<script>
import { formatDateTimeByType } from '@/utils/index.js';
import { getActivityInfo } from '@/service/api/aiApi.js';
import gicNewMemberGroup from '@/components/dm-new-member-group/index.vue';
import ruleFilter from '@/components/dm-new-rule/ruleFilter.vue';
export default {
name: 'ActivityInfo',
components: { gicNewMemberGroup, ruleFilter },
components: { ruleFilter },
data() {
return {
activityInfo: {}
......
......@@ -352,10 +352,10 @@ export default {
}
const originData = res.result[0];
this.talkTimeData = [
{ label: '<10秒', color: '#2d4dd1', count: originData['less_than_10'], percent: originData['10_proportion'] },
{ label: '10-59秒', color: '#D6B38C', count: originData['10_to_59'], percent: originData['10_to_59_proportion'] },
{ label: '60-119秒', color: '#14C9C9', count: originData['60_to_119'], percent: originData['60_to_119_proportion'] },
{ label: '>120秒', color: '#05B770', count: originData['greater_than_120'], percent: originData['120_proportion'] }
{ label: '≤10秒', color: '#2d4dd1', count: originData['firstInterval'], percent: originData['firstProportion'] },
{ label: '11-30秒', color: '#D6B38C', count: originData['secondInterval'], percent: originData['secondProportion'] },
{ label: '31-60秒', color: '#14C9C9', count: originData['thirdInterval'], percent: originData['thirdProportion'] },
{ label: '>60秒', color: '#05B770', count: originData['fourthInterval'], percent: originData['fourthProportion'] }
];
const data = [
this.talkTimeData.reduce(
......
<template>
<div class="defineTime">
<p class="tips">自定义时段不少于4个小时</p>
<p class="tips">自定义时段不少于2个小时</p>
<el-form :model="form" ref="defineTime">
<div class="flex" v-for="(v, i) in form.timeRangeList" :key="i">
<el-form-item class="mt10" :prop="'timeRangeList.' + i + '.startTime'" :rules="[{ validator: validateTime(i) }, { validator: validateStarTime(v, i) }]">
......@@ -134,8 +134,9 @@ export default {
let start = new Date(new Date().toLocaleDateString() + ' ' + item.startTime).getTime();
minutes = (end - start) / 60000 + minutes;
});
if (minutes < 240) {
this.$message.error('自定义时段不少于4个小时');
if (minutes < 120) {
this.$message.error('自定义时段不少于2个小时');
return false;
} else {
return true;
......
......@@ -284,10 +284,8 @@ import birthSense from '@/views/ai/task/components/birthActiveTime.vue';
import holidaySense from '@/views/ai/task/components/holidayActiveTime.vue';
import LibMessage from '@/views/ecm/marketing-event/components/lib-message.vue';
import activeTime from '@/views/ai/task/components/activeTime.vue';
import tagPop from '@/views/ai/task/tagPop.vue';
import { formatDateTimeByType, _debounce } from '@/utils/index';
import gicNewMemberGroup from '@/components/dm-new-member-group/index.vue';
import ruleFilter from '@/components/dm-new-rule/ruleFilter.vue';
export default {
mixins: [filterAvater],
......@@ -489,9 +487,7 @@ export default {
holidaySense,
activeTime,
LibMessage,
gicNewMemberGroup,
ruleFilter,
tagPop
ruleFilter
},
methods: {
async getActivityDetail(activityId) {
......
......@@ -139,7 +139,6 @@
<script>
import ruleFilter from '@/components/dm-new-rule/ruleFilter.vue';
import gicNewMemberGroup from '@/components/dm-new-member-group/index.vue';
import filterAvater from '@/mixins/filterAvater.js';
import { formatDateTimeByType } from '@/utils/index.js';
import { getActivityDetail, aiDictList, templateList, getSmsTemplateEcho } from '@/service/api/aiApi.js';
......@@ -192,8 +191,7 @@ export default {
this.getActivityDetail(this.$route.params.id);
},
components: {
ruleFilter,
gicNewMemberGroup
ruleFilter
},
filters: {
birthTypeFilter(val) {
......
<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>
<div>
<el-dialog title="选择标签" :visible.sync="visiable" width="900px" :before-close="close">
<div class="container">
<el-tabs tab-position="left" @tab-click="onTabsClick" v-model="activeName">
<el-tab-pane :label="item.levelName" v-for="item in tabList" :key="item.id" :name="item.id" v-loading="tabPaneLoading">
<div class="rightContent">
<div class="searchWrap">
<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" v-if="valueList.length">
<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="selectVal" @change="val => handleChange(item.tagName, val)">{{ value.tagItemName }}</el-radio>
</div>
</div>
<div class="nonData" v-else>
暂无数据
</div>
<dm-pagination class="fr" layout="prev, pager, next" v-if="totalCount" :total="totalCount" :page-size="pageSize" :current-page.sync="currentPage" @current-change="getPageMemberTagDetail"> </dm-pagination>
</div>
</el-tab-pane>
</el-tabs>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
</div>
</el-dialog>
<manual-tag-edit :options="manualTagPop" :showPop.sync="showPopVisible" @save="addNewTag"></manual-tag-edit>
</div>
</template>
<script>
import { pageMemberTagDetail, platformHomePageV2 } from '@/service/api/aiApi.js';
import ManualTagEdit from './manualTagEdit';
export default {
data() {
return {
activeName: '',
search: '',
tabList: [],
valueList: [],
tabPaneLoading: false,
totalCount: 0,
currentPage: 1,
pageSize: 20,
showPopVisible: false,
manualTagPop: {
show: false,
popTitle: '',
tagId: '',
tagLevelGroupId: '',
tagTwoLevelGroupId: '',
isSync: false
},
selectVal: '',
selectedTag: ''
};
},
props: {
visiable: {
type: Boolean,
default: false
}
},
mounted() {
this.getPlatformHomePageV2();
},
components: {
ManualTagEdit
},
methods: {
handleChange(val, label) {
this.selectedTag = JSON.parse(JSON.stringify(label));
this.selectedTag.tagItemName = val + '-' + this.selectedTag.tagItemName;
},
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() {
this.currentPage = 1;
this.getPageMemberTagDetail();
},
onTabsClick(val) {
const { name } = val;
console.log(name);
this.currentPage = 1;
this.getPageMemberTagDetail();
},
close() {
this.selectedTag = '';
this.$emit('update:visiable', false);
},
async getPageMemberTagDetail() {
const param = {
search: this.search,
tagLevelGroupId: this.activeName,
pageNum: this.currentPage,
pageSize: this.pageSize
};
const { result } = await pageMemberTagDetail(param);
if (result) {
this.totalCount = result.totalCount;
this.valueList = result.result;
}
},
async getPlatformHomePageV2() {
const param = {
tagLevelType: 2
};
const { result } = await platformHomePageV2(param);
if (result) {
this.tabList = [{ levelName: '所有活动标签', id: result[0].tagLevelGroupId }, ...result[0].children[0].children];
}
if (this.tabList.length) {
this.activeName = this.tabList[0].id;
this.getPageMemberTagDetail();
}
}
}
};
</script>
<style lang="scss" scoped>
.rightContent {
padding: 4px 0 0 16px;
box-sizing: border-box;
}
.searchWrap {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.container {
height: 521px;
border-radius: 4px;
border: 1px solid #dcdfe6;
padding: 11px 17px 0 0;
}
.radioContainer {
height: 430px;
overflow-y: auto;
.el-radio + .el-radio {
margin-left: 0;
}
}
.nonData {
height: 430px;
display: flex;
justify-content: center;
align-items: center;
}
.radioLine {
.lineTitle {
font-weight: bolder;
margin-bottom: 16px;
width: 100%;
color: #303030;
}
display: flex;
flex-wrap: wrap;
margin-bottom: 24px;
}
.fr {
float: right;
margin: 0;
}
</style>
......@@ -93,7 +93,7 @@
import { page, rechargeCenter, stopActivityPlan, startActivityPlan, pageStatistics, aiAccountCheck } from '@/service/api/aiApi.js';
import { formatDateTimeByType } from '@/utils/index.js';
import filterAvater from '@/mixins/filterAvater.js';
import dmDropdown from '@/components/dm-drop-down/dm-drop-down';
const maxTimeRange = 365 * 24 * 60 * 60 * 1000; // 12个月
export default {
mixins: [filterAvater],
......@@ -326,9 +326,6 @@ export default {
}
next();
},
components: {
dmDropdown
},
filters: {
activePlanStatusFilter(val) {
let str = '- -';
......@@ -416,43 +413,42 @@ export default {
params.endTime = formatDateTimeByType(params.time[1], 'yyyy-MM-dd');
}
delete params.time;
const { result } = await page(params);
if (!result) return;
this.tableData = result.list || [];
const ids = this.tableData.map(item => item.activityId).join(',');
this.total = result.total;
this.pageStatistics(ids);
},
async pageStatistics(ids) {
try {
const { result } = await pageStatistics({ ids });
const { result } = await page(params);
if (!result) return;
let obj = {};
result.forEach(element => {
obj[element.activityId] = element;
});
this.tableData.forEach(item => {
if (obj[item.activityId]) {
const { marketingNumber, outboundNumber, totalConnectionNumber, telephoneConnectionRate, connectionIntentionRate } = obj[item.activityId];
item.marketingNumber = marketingNumber;
item.outboundNumber = outboundNumber;
item.totalConnectionNumber = totalConnectionNumber;
item.telephoneConnectionRate = telephoneConnectionRate;
item.connectionIntentionRate = connectionIntentionRate;
} else {
item.marketingNumber = '- -';
item.outboundNumber = '- -';
item.totalConnectionNumber = '- -';
item.telephoneConnectionRate = '- -';
item.connectionIntentionRate = '- -';
}
});
this.tableData = this.tableData.splice(0);
this.tableData = result.list || [];
const ids = this.tableData.map(item => item.activityId).join(',');
this.total = result.total;
this.pageStatistics(ids);
} finally {
this.loading = false;
}
},
async pageStatistics(ids) {
const { result } = await pageStatistics({ ids });
if (!result) return;
let obj = {};
result.forEach(element => {
obj[element.activityId] = element;
});
this.tableData.forEach(item => {
if (obj[item.activityId]) {
const { marketingNumber, outboundNumber, totalConnectionNumber, telephoneConnectionRate, connectionIntentionRate } = obj[item.activityId];
item.marketingNumber = marketingNumber;
item.outboundNumber = outboundNumber;
item.totalConnectionNumber = totalConnectionNumber;
item.telephoneConnectionRate = telephoneConnectionRate;
item.connectionIntentionRate = connectionIntentionRate;
} else {
item.marketingNumber = '- -';
item.outboundNumber = '- -';
item.totalConnectionNumber = '- -';
item.telephoneConnectionRate = '- -';
item.connectionIntentionRate = '- -';
}
});
this.tableData = this.tableData.splice(0);
},
stopTask(row) {
this.$confirm('任务终止后未外呼的客户将停止外呼任务,终止后不可重新启用任务,是否继续终止任务?', '提示', {
confirmButtonText: '终止',
......
<template>
<section class="card-record-get" v-loading="recordLoading">
<div class="page-tip">当天的卡券领取记录数据可在隔天下载完整内容</div>
<div class="page-tip">当天的卡券领取记录数据可在隔天下载完整内容<br />导出数据只支持近两年数据</div>
<!-- 条件筛选区 -->
<div class="pb20">
<el-input clearable v-model="listParams.search" style="width:240px" placeholder="请输入会员信息/卡券代码" @change="refresh"><i slot="prefix" class="el-input__icon el-icon-search"></i></el-input>
......@@ -18,7 +18,9 @@
<el-select class="dm-select pl10" v-model="listParams.cardStatus" placeholder="选择卡券状态" @change="refresh">
<el-option v-for="(item, index) in cardStatusOptions" :key="index" :label="item.label" :value="item.value"></el-option>
</el-select>
<span class="vertical-middle">领取时间:</span><el-date-picker v-model="dateTime" :clearable="false" @change="changeTime" class="w250" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker> <span class="vertical-middle">核销时间:</span><el-date-picker v-model="dateTime2" @change="refresh" class="w250" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
<span class="vertical-middle">领取时间:</span>
<el-date-picker v-model="dateTime" :clearable="false" @change="changeTime" :picker-options="pickerOptionsGet" class="w250" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
<span class="vertical-middle">核销时间:</span><el-date-picker v-model="dateTime2" @change="refresh" class="w250" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</div>
<!-- 列表 -->
<el-table tooltipEffect="light" :data="recordList" style="width: 100%" @sort-change="sortList">
......@@ -112,7 +114,7 @@
</div>
<div class="ml20">
<el-radio v-model="confirm.radio" :label="1">所有卡券领取时期段导出</el-radio>
<el-date-picker clearable v-model="confirm.dateTime" class="block mt10 mb10" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
<el-date-picker clearable v-model="confirm.dateTime" value-format="timestamp" :picker-options="pickerOptions" class="block mt10 mb10" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="confirmClose">取 消</el-button>
......@@ -124,11 +126,23 @@
<script>
import { formatDateTimeByType } from '@/utils/index.js';
import cardSelectFilter from '@/components/card-select/filterable';
import { cardRecordPage, coupcardDestroy, exportReceivedRecordExcel } from '@/service/api/cardApi.js';
import { coupcardDestroy, exportReceivedRecordExcel } from '@/service/api/cardApi.js';
import { axios } from '@/service/api/index';
import qs from 'qs';
import cardOrder from './card-order';
import tableMethods from '@/mixins/tableMethods.js';
import filterAvater from '@/mixins/filterAvater.js';
let maxTime = null;
let minTime = null;
const daysFun = () => {
let y = new Date().getFullYear() - 1;
let isLeap = (0 === y % 4 && 0 === y % 100) || 0 === y % 400;
let days = isLeap ? 366 : 365;
let preY = new Date().getFullYear() - 2;
let preYisLeap = (0 === preY % 4 && 0 === preY % 100) || 0 === preY % 400;
let prevDays = preYisLeap ? 366 : 365;
return { days, prevDays };
};
export default {
name: 'record-get',
mixins: [tableMethods, filterAvater],
......@@ -141,6 +155,7 @@ export default {
formatDateTimeByType,
dateTime: [],
dateTimeCopy: [],
daysFun,
dateTime2: ['', ''],
// limit: false, // 限制筛选时间前后七天
cardStatusOptions: [
......@@ -182,7 +197,31 @@ export default {
dialogVisible: false,
excelUrl: '', // 下载数据的地址
params: {}, // 传递的参数
dataArr: []
dataArr: [],
pickerOptions: {
disabledDate: time => {
const { days, prevDays } = daysFun();
// let monthDayNum = new Date().getDate() + 1;
return time.getTime() < Date.now() - (days * 8.64e7 + prevDays * 8.64e7) || time.getTime() >= new Date().getTime();
}
},
pickerOptionsGet: {
onPick(time) {
if (!time.maxDate) {
const minTimeRange = 7 * 24 * 60 * 60 * 1000; // 7day
minTime = time.minDate.getTime() - minTimeRange;
maxTime = time.minDate.getTime() + minTimeRange < new Date().getTime() ? time.minDate.getTime() + minTimeRange : new Date().getTime();
}
},
disabledDate: time => {
if (minTime && maxTime && this.listParams.allCouponFlag == 1) {
return time.getTime() < minTime || time.getTime() > maxTime;
} else {
const { days, prevDays } = daysFun();
return time.getTime() < Date.now() - (days * 8.64e7 + prevDays * 8.64e7) || time.getTime() > new Date().getTime();
}
}
}
};
},
computed: {
......@@ -320,11 +359,24 @@ export default {
this.listParams.writeOffBeginTime = '';
this.listParams.writeOffEndTime = '';
}
const params = { ...this.listParams };
let res = await cardRecordPage(params);
this.recordList = res.result.result;
this.total = res.result.totalCount;
this.recordLoading = false;
let data = { ...this.listParams };
data = qs.stringify(Object.assign({ requestProject: 'gic-web' }, data));
// let res = await cardRecordPage(data); 60000
axios
.post('/api-marketing/card-record-page', data, { timeout: 60000 })
.then(res => {
if (res.data.errorCode == 0) {
const { result } = res.data;
this.recordList = result.result;
this.total = result.totalCount;
}
})
.catch(_ => {
this.$message.error('查询量过大');
})
.finally(_ => {
this.recordLoading = false;
});
},
// 发送记录操作: 删除
delData(row) {
......
<template>
<section class="card-record-send">
<div class="page-tip">投放记录详情次日更新</div>
<div class="pb22">
<el-select class="vertical-middle w150" v-model="listParams.putonType" placeholder="投放状态" @change="handleStatusChange">
<el-option label="投放成功" :value="1"></el-option>
......
import { _debounce } from '@/utils/index';
import { checkMessageSendCount } from '@/service/api/messageApi.js';
import { checkEcmSendCount } from '@/service/api/messageApi.js';
import { getEcmInfo, saveEcmInfo, getUseStoredFalg, getXsxsFalg, gicPaymentList } from '@/service/api/ecmApi.js';
import { getCardManualSetting } from '@/service/api/cardApi.js';
import { listTemplateVariables } from '@/service/api/msgApi.js';
......@@ -61,6 +61,7 @@ export default {
describe: '',
lateDays: '',
brithday_day: '',
brithday_dayval: -1,
brithday_type: 1,
attention_day: '',
lastCost_day: '',
......@@ -209,10 +210,10 @@ export default {
checked(val) {
switch (val[0]) {
case 'brithday_day':
if (!this.form.brithday_day) {
this.form.brithday_type = 1;
this.form.brithday_day = 1;
}
// if (!this.form.brithday_day) {
// this.form.brithday_type = 1;
// this.form.brithday_day = 1;
// }
this.form.attention_day = 0;
this.form.lastCost_day = 0;
break;
......@@ -345,18 +346,12 @@ export default {
filterWord(prop) {
this.copyTemplate[prop] = this.copyTemplate[prop].replace(/[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF][\u200D|\uFE0F]|[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF]|[0-9|*|#]\uFE0F\u20E3|[0-9|#]\u20E3|[\u203C-\u3299]\uFE0F\u200D|[\u203C-\u3299]\uFE0F|[\u2122-\u2B55]|\u303D|[\A9|\AE]\u3030|\uA9|\uAE|\u3030/g, '');
},
checkMessageSendCount() {
checkEcmSendCount(params) {
return new Promise(async (resolve, reject) => {
let events = this.$refs.marketingEvent.list.map(el => el.name);
events = Array.from(new Set(events));
const params = {
memberSearchDTO: this.form.memberType ? this.form.memberGroupIds : this.form.memberSearchDTO,
marketingType: 0,
// 区分人员筛选和会员分组,需要传这个flag
groupType: this.form.memberType
};
this.loading = true;
const res = await checkMessageSendCount(params).finally(() => (this.loading = false));
const res = await checkEcmSendCount(params).finally(() => (this.loading = false));
if (res && res.errorCode === 0) {
this.$confirm(
`<div>
......@@ -495,11 +490,15 @@ export default {
this.hasSearchData = result.filterJson || '{}';
}
if (this.form.effectType === 1) {
if (commonScene.brithday_day != 0) {
commonScene.brithday_day == -1 ? (this.form.brithday_dayval = -1) : (this.form.brithday_dayval = 1);
}
this.form.brithday_day = commonScene.brithday_day;
this.form.brithday_type = commonScene.brithday_type || 1;
this.form.attention_day = commonScene.attention_day;
this.form.lastCost_day = commonScene.lastCost_day;
if (this.form.brithday_day) {
if (this.form.brithday_day != 0) {
this.checked = ['brithday_day'];
} else if (this.form.attention_day) {
this.checked = ['attention_day'];
......@@ -767,6 +766,12 @@ export default {
return;
}
}
// 时效为触点时:'图文', '文本', '小程序', '图片' 添加事件大于3条时无法创建;时效为重复,单次时:小程序 大于3无法创建
if (this.$refs.marketingEvent.hasEventOverTime()) {
let str = this.form.effectType == 0 ? '受微信客服接口1分钟内最多只支持3次调用影响,图文/文本/小程序/图片事件单次计划最多3条' : '受微信客服接口1分钟内最多只支持3次调用影响,小程序事件单次计划最多3条';
this.$message({ type: 'warning', message: str });
return;
}
if (this.form.effectType == 2) {
// 单次
......@@ -945,7 +950,6 @@ export default {
expireType: this.form.expireType,
beginDate: this.form.expireType ? formatDateTimeByType(this.form.beginDate, 'yyyy-MM-dd-HH-mm-ss') : '',
endDate: this.form.expireType ? formatDateTimeByType(this.form.endDate, 'yyyy-MM-dd-HH-mm-ss') : '',
brithday_day: this.form.effectType == 1 ? this.form.brithday_day : undefined,
brithday_type: this.form.effectType == 1 ? this.form.brithday_type : undefined,
attention_day: this.form.effectType == 1 ? this.form.attention_day : undefined,
lastCost_day: this.form.effectType == 1 ? this.form.lastCost_day : undefined,
......@@ -959,7 +963,15 @@ export default {
execDateType: this.form.effectType == 1 ? this.form.execDateType : undefined, // 重复执行频率(1:天; 2:周 3:月)
execDate: this.form.effectType == 1 ? (this.form.execDate ? this.form.execDate.join() : '') : undefined // '周/月(1,2,3,4,5,6,7,)'
};
if (this.form.effectType == 1) {
if (this.checked[0] == 'brithday_day') {
this.form.brithday_dayval == -1 ? (params.brithday_day = -1) : (params.brithday_day = this.form.brithday_day);
} else {
params.brithday_day = 0;
}
} else {
params.brithday_day = undefined;
}
if (this.form.effectType == 1) {
// 重复
params.effectTime = Number(this.form.effectTime.split(':')[0]);
......@@ -1101,7 +1113,7 @@ export default {
return false;
}
if (this.form.effectType != 0) {
let count = await this.checkMessageSendCount();
let count = await this.checkEcmSendCount(params);
params.forecastMemberCount = count;
}
this.loading = true;
......
......@@ -69,13 +69,21 @@
<div class="fz12 gray">选填,勾选后生效</div>
<el-checkbox-group v-model="checked" :max="1">
<div class="pb10" style="display:flex;">
<el-checkbox :disabled="!isAdd" class="w150" label="brithday_day">会员生日前 </el-checkbox>
<el-checkbox :disabled="!isAdd" class="w150" label="brithday_day" style="margin-right:0">会员生日</el-checkbox>
<el-select class="w100" :disabled="!isAdd" v-model="form.brithday_type" placeholder="请选择生日类型" @change="effectActionChange">
<el-option label="阳历生日" :value="1"></el-option>
<el-option label="阴历生日" :value="2"></el-option>
</el-select>
<el-input-number controls-position="right" :min="checked[0] === 'brithday_day' ? 1 : 0" style="width:244px;" :disabled="checked[0] !== 'brithday_day' || isEdit" v-model="form.brithday_day"></el-input-number>
<el-radio style="margin-left:10px" :disabled="checked[0] !== 'brithday_day' || isEdit" v-model="form.brithday_dayval" :label="-1">
<span style="line-height:32px">当天</span>
</el-radio>
<el-radio :disabled="checked[0] !== 'brithday_day' || isEdit" v-model="form.brithday_dayval" :label="1">
之前
<el-input-number controls-position="right" :min="1" :max="366" style="width:115px;" :disabled="checked[0] !== 'brithday_day' || isEdit" v-model="form.brithday_day"></el-input-number>
</el-radio>
</div>
<div class="pb10">
<el-checkbox :disabled="!isAdd" class="w150" label="attention_day">关注时长超过 </el-checkbox>
<el-input-number controls-position="right" :min="checked[0] === 'attention_day' ? 1 : 0" :max="100000" style="width:344px;" :disabled="checked[0] !== 'attention_day' || isEdit" v-model="form.attention_day"></el-input-number>
......
......@@ -413,7 +413,6 @@
/* teltask message */
.dm-message__item__wrap,.dm-teltask__item__wrap{
width: 870px;
height: 94px;
margin:0 10px;
border: 1px solid rgba(228,231,237,1);
border-radius: 4px;
......@@ -437,17 +436,11 @@
-webkit-box-orient: vertical;
}
.dm-message__item--content,.dm-teltask__item--content {
.dm-message__item--content,.dm-teltask__item--content{
font-size: 14px;
color: #606266;
max-height: 30px;
line-height: 30px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
line-height: 30px;
}
.dm-integral__item__wrap {
width: 250px;
......
......@@ -245,7 +245,7 @@ export default {
}
});
}
return this.options.filter(item => item.show == true);
if (this.list) return this.options.filter(item => item.show == true);
}
},
watch: {
......@@ -495,6 +495,21 @@ export default {
this.$message({ type: 'warning', message: `最多只能添加${this.maxEventCount}个营销事件` });
return;
}
console.log(this.effectType);
if (this.effectType == 0) {
let arr = ['图文', '文本', '小程序', '图片'];
if (this.isOverThreeTime(v, arr)) {
this.$message({ type: 'warning', message: `受微信客服接口1分钟内最多只支持3次调用影响,图文/文本/小程序/图片事件单次计划最多3条` });
return;
}
} else {
let arr = ['小程序'];
if (this.isOverThreeTime(v, arr)) {
this.$message({ type: 'warning', message: `受微信客服接口1分钟内最多只支持3次调用影响,小程序事件单次计划最多3条` });
return;
}
}
// if (v.value === 'grade' && this.list.some(item => item.comName === 'item-grade')) {
// this.$message({ type: 'warning', message: `已添加会员卡升级营销事件` });
// return;
......@@ -600,6 +615,20 @@ export default {
isOverMaxCount() {
return this.list.length >= this.maxEventCount;
},
// 营销事件为“图文/文本/小程序/图片时,添加内容大于3条时无法创建
isOverThreeTime(v, arr) {
let i = 0;
this.list.forEach(item => {
if (arr.includes(item.name)) {
i++;
}
});
if (i >= 3 && arr.includes(v.name)) {
return true;
}
return false;
},
//判断营销列表里是否有短信 提供给父级使用
hasMessageInList() {
return this.list.some(v => v.comName === 'item-message' && v.item.type === 1);
......@@ -608,6 +637,36 @@ export default {
hasIntegralMultiple() {
return this.list.some(v => v.comName === 'item-integral' && v.item.integralType === 2);
},
// 时效为触点时:'图文', '文本', '小程序', '图片' 添加事件大于3条时无法创建;时效为重复,单次时:小程序 大于3无法创建
hasEventOverTime() {
let obj = {};
this.list.forEach(item => {
if (obj[item.name]) {
obj[item.name] = ++obj[item.name];
} else {
obj[item.name] = 1;
}
});
if (this.effectType == 0) {
let arr = ['图文', '文本', '小程序', '图片'];
let i = 0;
arr.forEach(key => {
if (obj[key]) {
i = obj[key] + i;
}
});
return i > 3;
} else {
let arr = ['小程序'];
let i = 0;
arr.forEach(key => {
if (obj[key]) {
i = obj[key] + i;
}
});
return i > 3;
}
},
//判断营销列表里是否有卡券 提供给父级使用
hasReturnCard() {
let item = {};
......
......@@ -6,7 +6,7 @@
渠道分析
<el-date-picker v-model="dateTime2" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" @change="cardChannelAnalysis"></el-date-picker>
</dm-sub-title>
<el-table tooltipEffect="light" :data="tableList" style="width:100%" v-loading="loading">
<el-table tooltipEffect="light" :data="tableList" style="width: 100%" v-loading="loading">
<el-table-column v-for="(v, i) in tableHeader" :key="i" :align="v.align" :width="v.width" :min-width="v.minWidth" :prop="v.prop" :label="v.label" :formatter="v.formatter"></el-table-column>
</el-table>
</div>
......@@ -50,7 +50,11 @@ export default {
listParams: {
type: ''
},
kpiNameOptions: [{ label: '领取次数', value: 'card-puton1' }, { label: '使用次数', value: 'card-puton2' }, { label: '销售额', value: 'card-puton3' }], // eslint-disable-line
kpiNameOptions: [
{ label: '领取次数', value: 'card-puton1' },
{ label: '使用次数', value: 'card-puton2' },
{ label: '销售额', value: 'card-puton3' }
], // eslint-disable-line
tableHeader: [
{ label: '渠道名称', prop: 'receiveName', align: 'left', minWidth: '200' },
{
......@@ -105,7 +109,11 @@ export default {
beginTime: '',
endTime: ''
};
this.kpiNameOptions = [{ label: '领取次数', value: 'shelf-cards1' }, { label: '使用次数', value: 'shelf-cards2' }, { label: '销售额', value: 'shelf-cards3' }]; // eslint-disable-line
this.kpiNameOptions = [
{ label: '领取次数', value: 'shelf-cards1' },
{ label: '使用次数', value: 'shelf-cards2' },
{ label: '销售额', value: 'shelf-cards3' }
]; // eslint-disable-line
this.cardTrendEchart();
} else {
this.chartParams = {
......@@ -115,7 +123,12 @@ export default {
endTime: '',
day: 1
};
(this.kpiNameOptions = [{ label: '领取次数', value: 'card-puton1' }, { label: '使用次数', value: 'card-puton2' }, { label: '销售额', value: 'card-puton3' }]), this.cardChannelAnalysis(); // eslint-disable-line
(this.kpiNameOptions = [
{ label: '领取次数', value: 'card-puton1' },
{ label: '使用次数', value: 'card-puton2' },
{ label: '销售额', value: 'card-puton3' }
]),
this.cardChannelAnalysis(); // eslint-disable-line
this.cardTrendEchart();
}
},
......
......@@ -93,11 +93,9 @@ import { cmhPage, stopGame, pageStatistics } from '@/service/api/gameApi.js';
import links from '../common/links';
import { formatDateTimeByType } from '@/utils/index.js';
import img from '@/assets/img/template1/mould_share_page.png';
import dmDropdown from '@/components/dm-drop-down/dm-drop-down';
export default {
components: {
dmDropdown,
links
},
data() {
......
......@@ -177,8 +177,6 @@
<script>
import { formatDateTimeByType } from '@/utils/index.js';
import gicNewMemberGroup from '@/components/dm-new-member-group/index.vue';
const music = new Audio();
export default {
props: {
......@@ -223,9 +221,7 @@ export default {
this.desW = 300;
}
},
components: {
gicNewMemberGroup
},
computed: {
storeParams() {
return !this.isAdd ? { creatorId: this.form.creatorId } : {};
......
......@@ -135,7 +135,6 @@
<script>
import { getPageLink } from '@/service/api/gameApi.js';
import Linktools from '@/components/linktools-fulls/index.vue';
import gicNewMemberGroup from '@/components/dm-new-member-group/index.vue';
export default {
data() {
const filterJsonVal = (rule, value, callback) => {
......@@ -307,8 +306,7 @@ export default {
}
},
components: {
Linktools,
gicNewMemberGroup
Linktools
},
computed: {
storeParams() {
......
<template>
<el-dialog title="提示" width="520px" top="30vh" custom-class="cre-dialog" :modal-append-to-body="false" :visible.sync="dialogVisible" :before-close="close">
<div v-loading="loading" class="flex">
<div class="el-message-box__status el-icon-warning position-ab"></div>
<div class="batch-content">
<p class="batch-txt">{{ tips }}</p>
<ul class="batch-ul">
<li v-for="item in list" :key="item.id" class="batch-li" @click="handleClickItem(item)">
<span class="relationName"> {{ item.busiObjRelationType | activeType }}--{{ item.busiObjRelationName }}</span>
<span class="relationCreater">{{ item.busiObjRelationCreater }}</span>
</li>
</ul>
</div>
</div>
<!-- <span class="footer" slot="footer">
<el-button type="primary" @click="close">关闭</el-button>
</span> -->
</el-dialog>
</template>
<script>
const routeMap = {
//1, "短信群发"2, "智能营销"3, "ai营销"4, "导入群发"5, "扫码营销"
1: '/message/record', //活动名maxlength10
2: '/ecm/list', //活动名maxlength30
3: '/ai/list', //活动名maxlength30
4: '/message/import-send', //活动名maxlength10
5: '/scan/list' //活动名maxlength9
};
export default {
props: {
dialogVisible: {
type: Boolean,
default: false
},
tips: {
type: String,
default: '当前短信模板已被以下活动引用,删除后引用该模板的活动短信将无法发送,慎重操作!如需删除模板,需要先暂停引用活动,才可删除'
},
list: {
type: Array,
default: () => []
},
loading: false
},
filters: {
activeType(val) {
const obj = {
1: '短信群发',
2: '智能营销',
3: 'AI营销',
4: '导入群发',
5: '扫码营销'
};
return obj[val];
}
},
methods: {
close() {
this.$emit('update:dialogVisible', false);
},
handleClickItem(item) {
if (item.permissionFlag) {
this.localtionChange(item);
} else {
this.$message.warning('当前活动无权限查看,请联系创建人修改活动状态');
}
},
localtionChange(item) {
const path = routeMap[item.busiObjRelationType];
this.$router.push(`${path}`);
}
}
};
</script>
<style lang="scss" scoped>
.cre-dialog {
.position-ab {
top: 95px;
}
.batch-content {
margin-left: 38px;
.batch-txt {
font-size: 14px;
color: #303133;
line-height: 20px;
}
.batch-ul {
margin-top: 16px;
li {
display: flex;
justify-content: flex-start;
margin-bottom: 10px;
}
.relationName,
.relationCreater {
font-size: 14px;
color: #303133;
line-height: 20px;
text-align: left;
}
.relationName {
width: 288px;
color: #2f54eb;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.relationCreater {
margin-left: 10px;
width: 145px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
.footer {
display: flex;
justify-content: center;
}
}
</style>
......@@ -47,12 +47,14 @@
<img class="block block-center pt100" width="60" height="60" src="../../assets/img/no-data_icon.png" alt="" />
<el-button class="block block-center mt10" type="text" @click="$router.push('/message/temp/add')">新建短信模板</el-button>
</div>
<del-dialog :dialogVisible.sync="dialogVisible" :list="delList" />
<dm-pagination v-show="smsTempList.length" background class="dm-pagination" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listParams.currentPage" :page-sizes="[20, 40, 60, 80]" :page-size="listParams.pageSize" layout="total, sizes, prev, pager, next" :total="total"></dm-pagination>
</section>
</template>
<script>
import { formatDateTimeByType } from '@/utils/index.js';
import { LoadLibList, delTempService } from '@/service/api/messageApi.js';
import { LoadLibList, delTempService, queryBusiCommonCheck } from '@/service/api/messageApi.js';
import delDialog from './delDialog.vue';
export default {
name: 'sms-lib',
data() {
......@@ -76,23 +78,37 @@ export default {
total: 0,
allUsableCount: 0,
usedCount: 0,
dateTime: []
dateTime: [],
dialogVisible: false,
delList: []
};
},
created() {
this.LoadLibList();
},
components: {
delDialog
},
methods: {
onDeleteData(v) {
this.$confirm('确认删除该模板?删除后,所有引用此模板的短信都会停止发送。', '提示', {
confirmButtonText: '确认',
cancelBUttonText: '取消',
type: 'warning'
})
.then(() => {
this.delData(v);
})
.catch(() => {});
queryBusiCommonCheck({ busiObjId: v.gicSmsTemplateId, busiType: 1 }).then(res => {
const { result } = res;
if (!result.candele) {
this.delList = result.list;
this.dialogVisible = true;
} else {
this.$confirm('确认删除该模板,删除后无法恢复短信模板', '提示', {
confirmButtonText: '确认',
cancelBUttonText: '取消',
type: 'warning'
})
.then(() => {
this.delData(v);
})
.catch(() => {});
}
});
},
search() {
this.listParams.currentPage = 1;
......
......@@ -38,7 +38,7 @@
</el-form-item>
<el-form-item :label="v.keyName" v-for="(v, i) in templateKeyDataList" :key="i">
<div v-if="v.keyName !== '使用渠道:'">
<span class="vertical-middle">显示接收人{{ v.keyName }}</span>
<span class="vertical-middle">显示接收人{{ v.keyName | keyNameFilter }}</span>
<el-color-picker class="ml10 vertical-middle" v-model="v.color"></el-color-picker>
</div>
<div v-else>
......@@ -67,12 +67,12 @@
<p class="pre-header" :style="'color:' + info.headerColor + ';'">{{ info.headerText }}</p>
<p class="pre-keyName" v-for="(v, i) in templateKeyDataList" :key="i">
{{ v.keyName }}
<span :style="`color:${v.color}`">示例文字</span>
<span :style="`color:${v.color}`">{{ v.keyName | exampleNameFilter }}</span>
</p>
<p class="pre-remark" :style="'color:' + info.remarkColor + ';'">{{ info.remarkText }}</p>
<div class="pre-foot clearfix">
<span class="fz13 fl ">详情</span>
<span class="fz13 fl">详情</span>
<i class="el-icon-arrow-right fr"></i>
</div>
</div>
......@@ -85,7 +85,9 @@
<span class="gray fz13 pl10">同时选择跳转小程序和H5页面,优先跳转小程序页面</span>
</dm-sub-title>
<div class="msg-edit__url">
<p class="pb20"><el-checkbox v-model="checked2">跳转小程序</el-checkbox></p>
<p class="pb20">
<el-checkbox v-model="checked2">跳转小程序</el-checkbox>
</p>
<div v-if="checked2">
<div class="pl20 pb20">
<el-radio v-model="radio2" :label="1">小程序链接</el-radio>
......@@ -96,7 +98,9 @@
<linktoolspage ref="childlinktoolspage" :isWx="true" :showType="2" @linkSelect="linkSelect" />
</div>
</div>
<p class="pt20 pb20"><el-checkbox v-model="checked1">跳转H5页面</el-checkbox></p>
<p class="pt20 pb20">
<el-checkbox v-model="checked1">跳转H5页面</el-checkbox>
</p>
<div v-if="checked1">
<div class="pl20 pb20">
<el-radio v-model="radio1" :label="1" @change="info.h5 = ''">内部链接</el-radio>
......@@ -118,7 +122,7 @@
<span class="gray fz13"> 22点至次日9点为防骚扰时段,通知将在结束后发送</span>
</div>
</dm-sub-title>
<el-form-item label="积分即将过期前" label-width="120px"> <el-input-number :precision="0" controls-position="right" v-model="info.remindDay" :min="1" :max="31"></el-input-number> 天发送该模板消息提醒。 </el-form-item>
<el-form-item label="积分即将过期前" label-width="120px"> <el-input-number :precision="0" controls-position="right" v-model="info.remindDay" :min="1" :max="31"> </el-input-number> 天发送该模板消息提醒。 </el-form-item>
<!-- <el-form-item label="发送时间设置" label-width="120px">
<el-select v-model="info.sendTime" class="w300">
<el-option v-for="(v, i) in dayOptions" :key="i" :value="v.value" :label="v.label"></el-option>
......@@ -529,6 +533,20 @@ export default {
} else {
return '未知时间';
}
},
keyNameFilter(val) {
if (val == '变更类型:') {
val = '变更类型+积分分值:';
}
return val;
},
exampleNameFilter(val) {
if (val != '变更类型:') {
val = '示例文字';
} else {
val = '线上签到增加5积分';
}
return val;
}
}
};
......@@ -540,23 +558,28 @@ export default {
/deep/ .el-col {
padding: 10px 0;
}
padding: 20px 0;
// border-bottom:1px solid #DCDFE6;
}
&__content {
width: 1100px;
}
&__left {
display: inline-block;
vertical-align: top;
width: 613px;
background: #f0f2f5;
overflow: hidden;
&--inner {
background: #fff;
width: 565px;
margin: 15px auto;
padding: 10px;
/deep/ .input-suffix {
width: 448px;
height: 40px;
......@@ -565,11 +588,13 @@ export default {
border-top: none;
border-radius: 0 0 4px 4px;
}
/deep/ .el-textarea__inner {
color: inherit;
}
}
}
&__right {
position: relative;
display: inline-block;
......@@ -579,6 +604,7 @@ export default {
background: url(../../assets/img/msg-preview.png) no-repeat center;
background-size: cover;
vertical-align: top;
&--inner {
border: 1px solid #dcdfe6;
border-radius: 4px;
......@@ -594,28 +620,34 @@ export default {
font-size: 17px;
font-weight: 700;
}
.pre-updateTime {
font-size: 14px;
line-height: 1.5;
}
.pre-header {
font-size: 15px;
margin: 10px 0;
}
.pre-keyName {
font-size: 14px;
line-height: 1.5;
}
.pre-remark {
font-size: 15px;
margin: 20px 0 10px 0;
}
.pre-foot {
border-top: 1px solid #dcdfe6;
padding-top: 5px;
}
}
}
&__url {
&--inner {
padding-bottom: 40px;
......
......@@ -4,7 +4,9 @@
<el-date-picker class="w250" v-model="pageParams.time" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" @change="refresh"></el-date-picker>
<el-input v-model="pageParams.storeName" class="w300" placeholder="请输入门店名称或门店code" clearable @change="refresh"><i slot="prefix" class="el-input__icon el-icon-search"></i></el-input>
<el-input v-model="pageParams.memberInfo" class="w300" placeholder="会员姓名/手机号/签到计划" clearable @change="refresh"><i slot="prefix" class="el-input__icon el-icon-search"></i></el-input>
<el-button class="fr" type="primary" icon="iconfont fz14 icon-cp-xiazai" v-if="$getButtonLimit($buttonCode.marketingExportSign)" :limit-code="$buttonCode.marketingExportSign" @click="exportExcel" size="small" :disabled="!total"> 查询结果导出</el-button>
</div>
<el-table tooltipEffect="light" :data="tableList" style="width: 100%">
<el-table-column :show-overflow-tooltip="true" align="left" prop="createTime" label="签到时间">
<template slot-scope="scope">
......@@ -32,12 +34,13 @@
</el-table-column>
<el-table-column :show-overflow-tooltip="true" align="left" prop="prizeTxt" label="签到福利"></el-table-column>
</el-table>
<vue-gic-export-excel :dialogVisible.sync="dialogVisible" :dataArr="tableList" :type="2" :excelUrl="excelUrl" :params="params" :projectName="projectName"></vue-gic-export-excel>
<dm-pagination v-show="tableList.length" background class="dm-pagination" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageParams.currentPage" :page-sizes="[20, 40, 60, 80]" :page-size="pageParams.pageSize" layout="total, sizes, prev, pager, next" :total="total"></dm-pagination>
</section>
</template>
<script>
import { getPageSignLog } from '@/service/api/storeSign.js';
import { getPageSignLog, exportStoreSign } from '@/service/api/storeSign.js';
import { formatDateTimeByType } from '@/utils/index.js';
export default {
name: 'sign-record',
......@@ -54,7 +57,10 @@ export default {
tableList: [],
// 门店单选
storeName: '',
storeDialog: false
storeDialog: false,
dialogVisible: false,
excelUrl: '', // 下载数据的地址
params: {} // 传递的参数
};
},
created() {
......@@ -85,6 +91,17 @@ export default {
this.loading = false;
}
},
exportExcel() {
const params = { storeName: this.pageParams.storeName, memberInfo: this.pageParams.memberInfo };
if (this.pageParams.time) {
params.startTime = formatDateTimeByType(this.pageParams.time[0], 'yyyy-MM-dd');
params.endTime = formatDateTimeByType(this.pageParams.time[1], 'yyyy-MM-dd');
delete params.time;
}
this.params = params;
this.dialogVisible = true;
this.excelUrl = exportStoreSign;
},
refresh() {
this.pageParams.currentPage = '1';
this.fetch();
......
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