Commit 9439b01d by zhangmeng

feat:文本组件,会员分组组件

parent a90ed774
<!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>GIC后台</title><link rel=stylesheet type=text/css href=static/css/iconfont.css><link rel=stylesheet type=text/css href=static/css/common.css><link href=/marketing/static/css/app.da5671fd371d3d869d900c012cc7ba62.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/marketing/static/js/manifest.0a85049e489e85ac5f0a.js></script><script type=text/javascript src=/marketing/static/js/vendor.b52e32600f8f7c7becf9.js></script><script type=text/javascript src=/marketing/static/js/app.e00bed4283c87a1d185e.js></script></body></html> <!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>GIC后台</title><link rel=stylesheet type=text/css href=static/css/iconfont.css><link rel=stylesheet type=text/css href=static/css/common.css><link href=/marketing/static/css/app.18ea705efab87708353a53def54b4c54.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/marketing/static/js/manifest.0a85049e489e85ac5f0a.js></script><script type=text/javascript src=/marketing/static/js/vendor.b52e32600f8f7c7becf9.js></script><script type=text/javascript src=/marketing/static/js/app.f1c093ce4350cf68fae7.js></script></body></html>
\ No newline at end of file \ 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.
No preview for this file type
This source diff could not be displayed because it is too large. You can view the blob instead.
No preview for this file type
No preview for this file type
<template>
<el-dialog title="添加链接" :visible.sync="show" width="820px" :before-close="close" :append-to-body="true">
<el-form label-width="80px">
<el-form-item label="文本内容">
<dm-input :maxlength="50" v-model="linkText" class="w300"></dm-input>
</el-form-item>
<el-tabs v-model="activeName" type="card">
<el-tab-pane label="H5链接" name="0">
<el-form-item label="链接类型">
<el-radio-group v-model="h5Type">
<el-radio :label="1">内部链接</el-radio>
<el-radio :label="0">网址</el-radio>
</el-radio-group>
</el-form-item>
<p class="pl20 pb20">已选择链接:{{urlInfo.url || '--'}}</p>
<innerUrl class="ml30" v-if="h5Type === 1" @sendRightUrl="getRightUrl" @sendLeftUrl="getLeftUrl" @sendShopData="getShopData"></innerUrl>
<div class="ml30 clearfix" v-if="h5Type === 0" >
<el-input v-model="urlInfo.url" class="w300" @blur="checkUrl" placeholder="请输入网址 http或https开头"></el-input>
</div>
</el-tab-pane>
<el-tab-pane label="小程序链接" name="1">
<p class="pt10 pl20 pb20">已选择链接:{{urlInfo.url || '--'}}</p>
<linktoolspage ref="childlinktoolspage" :isWx="true" :activeName="true" :showType="2" @linkSelect="linkSelect"/>
</el-tab-pane>
</el-tabs>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="close">取 消</el-button>
<el-button type="primary" @click="submit">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
import Vue from 'vue';
import qs from 'qs';
import innerUrl from '@/components/innerUrl/innerUrl';
import linktoolspage from '@/components/linktools/linktoolspage.vue';
/**
* 验证是否为网址
*/
const checkUrl = function (urlString) {
if(urlString!=""){
var reg=/(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/;
if(!reg.test(urlString)){
Vue.prototype.$message({type:"warning",message:"网址不规范,示例:http://www.domain.com"});
return true;
}
}else {
Vue.prototype.$message({type:"warning",message:"网址不规范,示例:http://www.domain.com"});
return true;
}
return false;
}
export default {
components:{
innerUrl,
linktoolspage
},
props: {
show: {
type:Boolean,
default:false
},
obj:{
type:Object,
default() {
return {
name:'',
url:'',
type:1
}
},
},
jumpUrlInfo:{
type:Object,
default() {
return {}
}
},
urlType:{
type:Boolean | String,
default:0
},
appendToBody: {
type:Boolean,
default:false
}
},
watch:{
show(val) {
// urlType: '0: 未选择URL; 1.H5链接; 2.小程序url链接
if(val) {
if (this.urlType == 1) {
this.activeName = '0';
} else if (this.urlType == 2) {
this.activeName = '1';
}
this.linkText = this.jumpUrlInfo.name || '';
this.urlInfo.url = this.jumpUrlInfo.url || '';
}
}
},
data() {
return {
linkText:'',
activeName:'0',
url:'',
h5Type:1,
urlInfo:{name:'',url:'',isWxApp:false,urlType:0},
}
},
methods:{
close() {
this.$emit('update:show',false);
},
async submit() {
// 去除前后空格
this.urlInfo.name = this.linkText.replace(/(^\s*)|(\s*$)/g,"");
if (!this.urlInfo.name) {
this.$tips({type:'warning',message:'链接文本不能为空'});
return;
}
// 判断是否为小程序
this.urlInfo.isWxApp = this.activeName == '1';
// 判断链接类型
this.urlInfo.urlType = this.activeName === '0' ? 1 : 2;
// 如果是H5链接 需要转换
if (this.activeName == '0' && this.h5Type === 1 && this.urlInfo.url.indexOf('https://open.weixin.qq.com/connect/oauth2/authorize') < 0) {
let params = {
url:this.urlInfo.url,
requestProject:'marketing'
}
let res = await this.axios.post('/api-marketing/change-to-WXUrl',qs.stringify(params));
this.urlInfo.url = res.data.response.result;
}
this.$emit('urlInfo',this.urlInfo);
this.close();
},
getRightUrl(data){
console.log(data);
this.urlInfo = data;
},
getLeftUrl(data){
console.log(data);
},
getShopData(data){ // 获取选择的门店id
console.log(data)
this.urlInfo = data;
},
// linktoolspage
linkSelect(val) { // 选择小程序链接的返回值
if (val.url) {
this.urlInfo.url = val.url;
} else {
this.urlInfo.url = 'pages/mall/mall-product-detail/mall-product-detail?proId=' + val.params.proId;
}
},
checkUrl() {
if (this.h5Type === 1 && checkUrl(this.url)) {
this.url = 'http://www.domain.com';
return;
}
}
}
}
</script>
<style lang="scss" scoped>
.w300{
width: 300px;
}
.pb10 {
padding-bottom: 10px;
}
.pl20 {
padding-left: 20px;
}
</style>
<template>
<section class="wx-text">
<div class="wx-text__content">
<div v-html="textarea" @keyup="textInput(textarea,$event)" ref="myTextarea" contenteditable=true @blur="getTextValue"></div>
</div>
<div class="wx-text__opt clearfix">
<a @click="addLink" class="iconfont icon-lianjie" title="添加链接"></a>
<a @click="removeLink" class="iconfont icon-duankailianjie" title="取消链接"></a>
<el-popover placement="top" trigger="hover" width="680" v-if="isSupportVar">
<p>1.支持插入会员信息变量,如下表所示,{数字}为可插入变量,注意变量值长度,一面超过300字文本上限。</p>
<p>2.支持插入H5链接;支持插入小程序链接。</p>
<p>3.支持换行;不支持富文本格式。</p>
<p>会员信息变量表:</p>
<div class="clearfix">
<ul class="fl pr10" v-for="(item,index) in 4" :key="index">
<li v-for="(v,i) in options.slice(index*7,(index+1)*7)" :key="i">{{v.number+v.name}}</li>
</ul>
</div>
<a @click="removeLink" class="iconfont icon-17" title="变量" slot="reference"></a>
</el-popover>
<span class="fr gray fz13">还可以输入{{300-textLength}}字,按下回车键换行</span>
</div>
<my-dialog :show.sync="dialogShow" @urlInfo="getUrlInfo" :urlType.sync="urlType" :jumpUrlInfo.sync="jumpUrlInfo"></my-dialog>
</section>
</template>
<script>
import qs from 'qs';
import myDialog from './dialog';
import strLength from '@/utils/strlen';
const hrefReg = /href=['"]([^"]*)['"].*?/g;
export default {
name:'dm-text',
components:{
'my-dialog':myDialog
},
props:{
value:{
type:String,
default:''
},
appendToBody:{
type:Boolean,
default:false
},
jumpUrlInfo:{
type:Object,
default() {
return {}
}
},
urlType:{
type:Boolean | String,
default:0
},
isSupportVar:{
type:Boolean,
default:false
}
},
watch:{
value:{
handler(val) {
if (val) {
this.textarea = val;
this.computedTextLength();
}
console.log(this.jumpUrlInfo,this.isSupportVar);
},
immediate:true
}
},
data() {
return {
textarea:'',
dialogShow:false,
appid:'',
options:require('./options.js'),
textLength:0
}
},
created() {
this.getAppid();
},
methods:{
// 添加链接
addLink() {
this.dialogShow = true;
},
textInput(v,e){ // 控制微信文本的文字
var textContent = this.$refs.myTextarea.innerText;
textContent = strLength.getByteVal2(e.target.innerText);
// this.textarea = textContent;
this.textNum = strLength.getZhLen(textContent);
this.computedTextLength();
if(this.textNum>=300){
this.$message.error('最多300个字符');
}
},
// 获取内容
getTextValue() {
const reg = /<(?!(a|\/a|div|\/div|br)).*?>/img ; // 只保留a 和 div 标签
let text = this.$refs.myTextarea.innerHTML.replace(reg,"");
text = text.replace(/<\/div>|&nbsp;/g,"").replace(/<((div)).*?>/g,"<br>").split('<br>').filter(v=>v).join('<br>');
// this.hasATag(text,flag => {
// if (flag) {
// var href = text.match(hrefReg)[0];
// text = text.replace(/<((a)).*?>/g,'<a '+href+'">'); // 获取 <a> 并替代
// }
// });
console.log(text)
this.$emit('update:value',text);
},
getUrlInfo(obj) {
console.log(obj)
this.hasATag(this.textarea,flag => {
if (flag) {
if (obj.isWxApp) {
this.textarea += `<a href="${obj.url}" data-miniprogram-appid="${this.appid}" data-miniprogram-path="${obj.url}">${obj.name}</a>`
} else {
this.textarea += '<a href="'+obj.url+'">'+obj.name+'</a>';
}
this.$emit('update:urlType',obj.urlType);
this.$emit('update:jumpUrlInfo',{name:obj.name,url:obj.url});
// this.$nextTick(_ => {
// this.getTextValue();
// })
}
})
},
// 辅助函数 是否有a标签
hasATag(text,cb) {
if(hrefReg.test(text)){
var hrefArr = text.match(hrefReg);
if(hrefArr.length >= 1){
this.$message({type:'warning',message:'只能添加一个链接'});
cb && cb(false);
} else {
cb && cb(true);
}
} else {
cb && cb(true);
}
},
getAppid() {
this.axios.post('/api-marketing/get-enterprise-wechat-appid',qs.stringify({
requestProject:'marketing'
})).then(res => {
this.appid = res.data.result;
console.log(res);
})
},
// 清除a链接
removeLink(){
this.textarea = this.$refs.myTextarea.innerText.replace(/\n/g,'<br>');
this.$emit('update:urlType',0);
this.$emit('update:jumpUrlInfo',{name:'',url:''});
this.$emit('update:value',this.textarea);
},
computedTextLength() {
if (this.$refs.myTextarea) {
this.textLength = this.$refs.myTextarea.innerHTML.length;
} else {
this.textLength = 0;
}
}
}
}
</script>
<style lang="scss" scoped>
.wx-text{
height: 200px;
width: 600px;
border: 1px solid #e7e7eb;
border-radius: 4px;
&__content {
height: 160px;
width: 600px;
& > div {
padding:10px;
height: 140px;
width: 580px;
overflow-x: hidden;
outline:0;
}
}
&__opt {
height: 40px;
line-height: 40px;
padding:0 20px;
border-top:1px solid #e7e7eb;
& > a {
padding-right: 10px;
cursor: pointer;
}
}
}
</style>
module.exports = [
{number:'{1}',name:'{姓名}'},
{number:'{2}',name:'{姓名+先生/女士}'},
{number:'{3}',name:'{生日日期}'},
{number:'{4}',name:'{生日天数}'},
{number:'{5}',name:'{关注日期}'},
{number:'{6}',name:'{关注天数}'},
{number:'{7}',name:'{主门店品牌名称}'},
{number:'{8}',name:'{主门店名称}'},
{number:'{9}',name:'{主门店电话}'},
{number:'{10}',name:'{专属导购姓名}'},
{number:'{11}',name:'{专属导购手机号}'},
{number:'{12}',name:'{开卡日期}'},
{number:'{13}',name:'{开卡天数}'},
{number:'{14}',name:'{开卡门店名称}'},
{number:'{15}',name:'{会员卡号}'},
{number:'{16}',name:'{会员等级名称}'},
{number:'{17}',name:'{主门店地址}'},
{number:'{18}',name:'{会员等级剩余有效天数}'},
{number:'{19}',name:'{积分余额}'},
{number:'{20}',name:'{30天内将过期积分额度}'},
{number:'{21}',name:'{储值余额}'},
{number:'{22}',name:'{消费总额}'},
{number:'{23}',name:'{消费次数}'},
{number:'{24}',name:'{最近消费日期}'},
{number:'{25}',name:'{最近消费间隔}'},
{number:'{26}',name:'{最高单笔消费}'},
{number:'{27}',name:'{最近消费门店名称}'},
{number:'{28}',name:'{最近消费品牌名称}'}]
<template> <template>
<el-dialog title="添加链接" :visible.sync="show" width="820px" :before-close="close"> <el-dialog title="添加链接" :visible.sync="show" width="820px" :before-close="close" :append-to-body="true">
<el-form label-width="80px"> <el-form label-width="80px">
<el-form-item label="文本内容"> <el-form-item label="文本内容">
<dm-input :maxlength="50" v-model="linkText" class="w300"></dm-input> <dm-input :maxlength="50" v-model="linkText" class="w300"></dm-input>
...@@ -12,14 +12,14 @@ ...@@ -12,14 +12,14 @@
<el-radio :label="0">网址</el-radio> <el-radio :label="0">网址</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<p class="pl20 pb20">已选择链接:{{jumpUrlInfo.url || '--'}}</p> <p class="pl20 pb20">已选择链接:{{urlInfo.url || '--'}}</p>
<innerUrl class="ml30" v-if="h5Type === 1" @sendRightUrl="getRightUrl" @sendLeftUrl="getLeftUrl" @sendShopData="getShopData"></innerUrl> <innerUrl class="ml30" v-if="h5Type === 1" @sendRightUrl="getRightUrl" @sendLeftUrl="getLeftUrl" @sendShopData="getShopData"></innerUrl>
<div class="ml30 clearfix" v-if="h5Type === 0" > <div class="ml30 clearfix" v-if="h5Type === 0" >
<el-input v-model="jumpUrlInfo.url" class="w300" @blur="checkUrl" placeholder="请输入网址 http或https开头"></el-input> <el-input v-model="urlInfo.url" class="w300" @blur="checkUrl" placeholder="请输入网址 http或https开头"></el-input>
</div> </div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="小程序链接" name="1"> <el-tab-pane label="小程序链接" name="1">
<p class="pt10 pl20 pb20">已选择链接:{{jumpUrlInfo.url || '--'}}</p> <p class="pt10 pl20 pb20">已选择链接:{{urlInfo.url || '--'}}</p>
<linktoolspage ref="childlinktoolspage" :isWx="true" :activeName="true" :showType="2" @linkSelect="linkSelect"/> <linktoolspage ref="childlinktoolspage" :isWx="true" :activeName="true" :showType="2" @linkSelect="linkSelect"/>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
...@@ -72,13 +72,34 @@ export default { ...@@ -72,13 +72,34 @@ export default {
url:'', url:'',
type:1 type:1
} }
},
},
jumpUrlInfo:{
type:Object,
default() {
return {}
} }
},
urlType:{
type:Boolean | String,
default:0
},
appendToBody: {
type:Boolean,
default:false
} }
}, },
watch:{ watch:{
show(val) { show(val) {
// urlType: '0: 未选择URL; 1.H5链接; 2.小程序url链接
if(val) { if(val) {
if (this.urlType == 1) {
this.activeName = '0';
} else if (this.urlType == 2) {
this.activeName = '1';
}
this.linkText = this.jumpUrlInfo.name || '';
this.urlInfo.url = this.jumpUrlInfo.url || '';
} }
} }
}, },
...@@ -88,40 +109,53 @@ export default { ...@@ -88,40 +109,53 @@ export default {
activeName:'0', activeName:'0',
url:'', url:'',
h5Type:1, h5Type:1,
jumpUrlInfo:{name:'',url:''}, urlInfo:{name:'',url:'',isWxApp:false,urlType:0},
} }
}, },
methods:{ methods:{
close() { close() {
this.$emit('update:show',false); this.$emit('update:show',false);
}, },
submit() { async submit() {
// 去除前后空格
if (this.activeName == '0' && this.h5Type === 1) { this.urlInfo.name = this.linkText.replace(/(^\s*)|(\s*$)/g,"");
this.transfromUrl(); if (!this.urlInfo.name) {
} else { this.$tips({type:'warning',message:'链接文本不能为空'});
this.close(); return;
this.jumpUrlInfo.name = this.linkText;
this.$emit('urlInfo',this.jumpUrlInfo);
} }
// 判断是否为小程序
this.urlInfo.isWxApp = this.activeName == '1';
// 判断链接类型
this.urlInfo.urlType = this.activeName === '0' ? 1 : 2;
// 如果是H5链接 需要转换
if (this.activeName == '0' && this.h5Type === 1 && this.urlInfo.url.indexOf('https://open.weixin.qq.com/connect/oauth2/authorize') < 0) {
let params = {
url:this.urlInfo.url,
requestProject:'marketing'
}
let res = await this.axios.post('/api-marketing/change-to-WXUrl',qs.stringify(params));
this.urlInfo.url = res.data.response.result;
}
this.$emit('urlInfo',this.urlInfo);
this.close();
}, },
getRightUrl(data){ getRightUrl(data){
console.log(data); console.log(data);
this.jumpUrlInfo = data; this.urlInfo = data;
}, },
getLeftUrl(data){ getLeftUrl(data){
console.log(data); console.log(data);
}, },
getShopData(data){ // 获取选择的门店id getShopData(data){ // 获取选择的门店id
console.log(data) console.log(data)
this.jumpUrlInfo = data; this.urlInfo = data;
}, },
// linktoolspage // linktoolspage
linkSelect(val) { // 选择小程序链接的返回值 linkSelect(val) { // 选择小程序链接的返回值
if (val.url) { if (val.url) {
this.jumpUrlInfo.url = val.url; this.urlInfo.url = val.url;
} else { } else {
this.jumpUrlInfo.url = 'pages/mall/mall-product-detail/mall-product-detail?proId=' + val.params.proId; this.urlInfo.url = 'pages/mall/mall-product-detail/mall-product-detail?proId=' + val.params.proId;
} }
}, },
checkUrl() { checkUrl() {
...@@ -129,20 +163,6 @@ export default { ...@@ -129,20 +163,6 @@ export default {
this.url = 'http://www.domain.com'; this.url = 'http://www.domain.com';
return; return;
} }
},
//转换 url 内部链接
transfromUrl(url) {
let params = {
url:this.jumpUrlInfo.url,
requestProject:'marketing'
}
this.axios.post('/api-marketing/change-to-WXUrl',qs.stringify(params)).then(res => {
this.jumpUrlInfo.url = res.data.response.result;
this.jumpUrlInfo.name = this.linkText;
this.$emit('urlInfo',this.jumpUrlInfo);
this.close();
console.log(res);
})
} }
} }
} }
......
<template> <template>
<section class="wx-text"> <section class="wx-text">
<div class="wx-text__content"> <div class="wx-text__content">
<div v-html="textarea" ref="myTextarea" contenteditable=true></div> <div v-html="textarea" @keyup="textInput(textarea,$event)" ref="myTextarea" contenteditable=true @blur="getTextValue"></div>
</div> </div>
<div class="wx-text__opt"> <div class="wx-text__opt clearfix">
<a @click="addLink" class="iconfont icon-lianjie" title="添加链接"></a> <a @click="addLink" class="iconfont icon-lianjie" title="添加链接"></a>
<a @click="removeLink" class="iconfont icon-duankailianjie" title="取消链接"></a> <a @click="removeLink" class="iconfont icon-duankailianjie" title="取消链接"></a>
<el-popover placement="top" trigger="hover" width="680"> <el-popover placement="top" trigger="hover" width="680">
...@@ -12,54 +12,22 @@ ...@@ -12,54 +12,22 @@
<p>3.支持换行;不支持富文本格式。</p> <p>3.支持换行;不支持富文本格式。</p>
<p>会员信息变量表:</p> <p>会员信息变量表:</p>
<div class="clearfix"> <div class="clearfix">
<ul class="fl pr10"> <ul class="fl pr10" v-for="(item,index) in 4" :key="index">
<li>{1}={姓名}</li> <li v-for="(v,i) in options.slice(index*7,(index+1)*7)" :key="i">{{v.number+v.name}}</li>
<li>{2}={姓名+先生/女士}</li>
<li>{3}={生日日期}</li>
<li>{4}={生日天数}</li>
<li>{5}={关注日期}</li>
<li>{6}={关注天数}</li>
<li>{7}={主门店品牌名称}</li>
</ul>
<ul class="fl pr10">
<li>{8}={主门店名称}</li>
<li>{9}={主门店电话}</li>
<li>{10}={专属导购姓名}</li>
<li>{11}={专属导购手机号}</li>
<li>{12}={开卡日期}</li>
<li>{13}={开卡天数}</li>
<li>{14}={开卡门店名称}</li>
</ul>
<ul class="fl pr10">
<li>{15}={会员卡号}</li>
<li>{16}={会员等级名称}</li>
<li>{17}={主门店地址}</li>
<li>{18}={会员等级剩余有效天数}</li>
<li>{19}={积分余额}</li>
<li>{20}={30天内将过期积分额度}</li>
<li>{21}={储值余额}</li>
</ul>
<ul class="fl">
<li>{22}={消费总额}</li>
<li>{23}={消费次数}</li>
<li>{24}={最近消费日期}</li>
<li>{25}={最近消费间隔}</li>
<li>{26}={最高单笔消费}</li>
<li>{27}={最近消费门店名称}</li>
<li>{28}={最近消费品牌名称}</li>
</ul> </ul>
</div> </div>
<a @click="removeLink" class="iconfont icon-17" title="变量" slot="reference"></a> <a @click="removeLink" class="iconfont icon-17" title="变量" slot="reference"></a>
</el-popover> </el-popover>
<span>还可以输入300字,按下回车键换行</span> <span class="fr gray fz13">还可以输入{{300-this.textLength}}字,按下回车键换行</span>
</div> </div>
<my-dialog :show.sync="dialogShow" @urlInfo="getUrlInfo"></my-dialog> <my-dialog :show.sync="dialogShow" @urlInfo="getUrlInfo" :urlType.sync="urlType" :jumpUrlInfo.sync="jumpUrlInfo"></my-dialog>
</section> </section>
</template> </template>
<script> <script>
import qs from 'qs'; import qs from 'qs';
import myDialog from './dialog'; import myDialog from './dialog';
import strLength from '@/utils/strlen';
const hrefReg = /href=['"]([^"]*)['"].*?/g; const hrefReg = /href=['"]([^"]*)['"].*?/g;
export default { export default {
name:'dm-text', name:'dm-text',
...@@ -70,21 +38,46 @@ export default { ...@@ -70,21 +38,46 @@ export default {
value:{ value:{
type:String, type:String,
default:'' default:''
},
appendToBody:{
type:Boolean,
default:false
},
jumpUrlInfo:{
type:Object,
default() {
return {}
}
},
urlType:{
type:Boolean | String,
default:0
} }
}, },
watch:{ watch:{
value:{ value:{
handler(val) { handler(val) {
console.log(this.jumpUrlInfo);
this.textarea = val; this.textarea = val;
}, },
immediate:true immediate:true
},
textarea(val){
console.log(this.$refs.myTextarea)
if (this.$refs.myTextarea) {
this.textLength = this.$refs.myTextarea.innerHTML.length;
} else {
this.textLength = 0;
}
} }
}, },
data() { data() {
return { return {
textarea:'', textarea:'',
dialogShow:false, dialogShow:false,
appid:'' appid:'',
textLength:0,
options:require('./options.js')
} }
}, },
created() { created() {
...@@ -95,9 +88,14 @@ export default { ...@@ -95,9 +88,14 @@ export default {
addLink() { addLink() {
this.dialogShow = true; this.dialogShow = true;
}, },
// 去除链接 textInput(v,e){ // 控制微信文本的文字
removeLink() { var textContent = this.$refs.myTextarea.innerText;
textContent = strLength.getByteVal2(e.target.innerText);
// this.textarea = textContent;
this.textNum = strLength.getZhLen(textContent);
if(this.textNum>=300){
this.$message.error('最多300个字符');
}
}, },
// 获取内容 // 获取内容
getTextValue() { getTextValue() {
...@@ -110,13 +108,25 @@ export default { ...@@ -110,13 +108,25 @@ export default {
// text = text.replace(/<((a)).*?>/g,'<a '+href+'">'); // 获取 <a> 并替代 // text = text.replace(/<((a)).*?>/g,'<a '+href+'">'); // 获取 <a> 并替代
// } // }
// }); // });
console.log(text)
this.$emit('update:value',text); this.$emit('update:value',text);
}, },
getUrlInfo(obj) { getUrlInfo(obj) {
console.log(obj) console.log(obj)
this.hasATag(this.textarea,flag => { this.hasATag(this.textarea,flag => {
if (flag) { if (flag) {
this.textarea += '<a href="'+obj.url+'">'+obj.name+'</a>'; if (obj.isWxApp) {
this.textarea += `<a href="${obj.url}" data-miniprogram-appid="${this.appid}" data-miniprogram-path="${obj.url}">${obj.name}</a>`
} else {
this.textarea += '<a href="'+obj.url+'">'+obj.name+'</a>';
}
this.$emit('update:urlType',obj.urlType);
this.$emit('update:jumpUrlInfo',{name:obj.name,url:obj.url});
// this.$nextTick(_ => { // this.$nextTick(_ => {
// this.getTextValue(); // this.getTextValue();
// }) // })
...@@ -126,7 +136,6 @@ export default { ...@@ -126,7 +136,6 @@ export default {
// 辅助函数 是否有a标签 // 辅助函数 是否有a标签
hasATag(text,cb) { hasATag(text,cb) {
debugger;
if(hrefReg.test(text)){ if(hrefReg.test(text)){
var hrefArr = text.match(hrefReg); var hrefArr = text.match(hrefReg);
if(hrefArr.length >= 1){ if(hrefArr.length >= 1){
...@@ -150,6 +159,8 @@ export default { ...@@ -150,6 +159,8 @@ export default {
// 清除a链接 // 清除a链接
removeLink(){ removeLink(){
this.textarea = this.$refs.myTextarea.innerText.replace(/\n/g,'<br>'); this.textarea = this.$refs.myTextarea.innerText.replace(/\n/g,'<br>');
this.$emit('update:urlType',0);
this.$emit('update:jumpUrlInfo',{name:'',url:''});
this.$emit('update:value',this.textarea); this.$emit('update:value',this.textarea);
}, },
} }
......
module.exports = [
{number:'{1}',name:'{姓名}'},
{number:'{2}',name:'{姓名+先生/女士}'},
{number:'{3}',name:'{生日日期}'},
{number:'{4}',name:'{生日天数}'},
{number:'{5}',name:'{关注日期}'},
{number:'{6}',name:'{关注天数}'},
{number:'{7}',name:'{主门店品牌名称}'},
{number:'{8}',name:'{主门店名称}'},
{number:'{9}',name:'{主门店电话}'},
{number:'{10}',name:'{专属导购姓名}'},
{number:'{11}',name:'{专属导购手机号}'},
{number:'{12}',name:'{开卡日期}'},
{number:'{13}',name:'{开卡天数}'},
{number:'{14}',name:'{开卡门店名称}'},
{number:'{15}',name:'{会员卡号}'},
{number:'{16}',name:'{会员等级名称}'},
{number:'{17}',name:'{主门店地址}'},
{number:'{18}',name:'{会员等级剩余有效天数}'},
{number:'{19}',name:'{积分余额}'},
{number:'{20}',name:'{30天内将过期积分额度}'},
{number:'{21}',name:'{储值余额}'},
{number:'{22}',name:'{消费总额}'},
{number:'{23}',name:'{消费次数}'},
{number:'{24}',name:'{最近消费日期}'},
{number:'{25}',name:'{最近消费间隔}'},
{number:'{26}',name:'{最高单笔消费}'},
{number:'{27}',name:'{最近消费门店名称}'},
{number:'{28}',name:'{最近消费品牌名称}'}]
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
<span class="dm-input_label pr10">选择会员</span> <span class="dm-input_label pr10">选择会员</span>
<el-radio :disabled="isInfo" v-model="form.memberType" :label="0">会员筛选</el-radio> <el-radio :disabled="isInfo" v-model="form.memberType" :label="0">会员筛选</el-radio>
<el-radio :disabled="isInfo" v-model="form.memberType" :label="1">指定会员</el-radio> <el-radio :disabled="isInfo" v-model="form.memberType" :label="1">指定会员</el-radio>
<el-radio :disabled="isInfo" v-model="form.memberType" :label="2">会员分组</el-radio>
</div> </div>
<div v-show="!form.memberType"> <div v-show="!form.memberType">
<vue-gic-people :projectName="projectName" :useId="useId" :hasSearchData="hasSearchData" :sceneValue="sceneValue" ref="peopleFilter" @findFilter="findFilter" @getBackData="getBackData" @editHide= "editHide" @editShow="editShow" @hideBtn="hideBtn"/> <vue-gic-people :projectName="projectName" :useId="useId" :hasSearchData="hasSearchData" :sceneValue="sceneValue" ref="peopleFilter" @findFilter="findFilter" @getBackData="getBackData" @editHide= "editHide" @editShow="editShow" @hideBtn="hideBtn"/>
...@@ -34,11 +35,12 @@ ...@@ -34,11 +35,12 @@
<el-button size="small" @click="cancelFilter">取 消</el-button> <el-button size="small" @click="cancelFilter">取 消</el-button>
</div> </div>
</div> </div>
<vue-gic-confirm-people v-show="form.memberType" idType="memberId" :onlyWxMember="0" @get-data="getConfirmData" :list="memberList"></vue-gic-confirm-people> <vue-gic-confirm-people v-show="form.memberType === 1" idType="memberId" :onlyWxMember="0" @get-data="getConfirmData" :list="memberList"></vue-gic-confirm-people>
<vue-gic-member-group v-if="form.memberType === 2" :defaltSelected="defaltSelected" :height='500' :projectName="projectName" :headerList='headerList' @handleDataTransferred="handleDataTransferred" @handleDataLeft="handleDataLeft"></vue-gic-member-group>
</div> </div>
<!-- 只有存在卡券的情况下出现卡券通知方式 --> <!-- 只有存在卡券的情况下出现卡券通知方式 -->
<section class="dm-form__wrap"> <section class="dm-form__wrap">
<h3 class="dm-title__label">卡券通知方式配置</h3> <h3 class="dm-title__label">卡券通知方式配置</h3>
<el-form-item label="通知方式" class="is-required" prop="noticeType"> <el-form-item label="通知方式" class="is-required" prop="noticeType">
...@@ -175,11 +177,11 @@ export default { ...@@ -175,11 +177,11 @@ export default {
sceneSettingName:'', sceneSettingName:'',
cardId:this.$route.params.id, cardId:this.$route.params.id,
cardName:this.$route.params.name, cardName:this.$route.params.name,
noticeType:1, noticeType:1,
templateNoticeFlag:0, templateNoticeFlag:0,
// 判断模板消息能否使用 // 判断模板消息能否使用
templateUseEnable:1, templateUseEnable:1,
memberGroupIds:''
}, },
rules:{ rules:{
putOnName:{required:true,message:'活动名称不能为空',trigger:'blur'} putOnName:{required:true,message:'活动名称不能为空',trigger:'blur'}
...@@ -208,6 +210,9 @@ export default { ...@@ -208,6 +210,9 @@ export default {
isEdit:this.$route.meta.type === 'edit', isEdit:this.$route.meta.type === 'edit',
isInfo:this.$route.meta.type === 'info', isInfo:this.$route.meta.type === 'info',
isAdd:this.$route.meta.type === 'send', isAdd:this.$route.meta.type === 'send',
defaltSelected:[],
projectName:'marketing',
headerList: [ 'effectiveStatus'] // 表头配置,默认全部,分组名称默认显示不可配置
} }
}, },
computed: { computed: {
...@@ -276,18 +281,19 @@ export default { ...@@ -276,18 +281,19 @@ export default {
this.form.putOnTime = form.putOnTime; this.form.putOnTime = form.putOnTime;
this.form.cardName = res.result.card.cardName; this.form.cardName = res.result.card.cardName;
/** '0-不通知 1-微信对话框 2-模板消息' **/ /** '0-不通知 1-微信对话框 2-模板消息' **/
this.form.noticeType = form.noticeType || 0; this.form.noticeType = form.noticeType || 0;
// 会员设置回显
if (res.result.searchId) { if (this.form.memberType === 0) {
this.useId = res.result.searchId this.useId = res.result.searchId
this.hasSearchData = form.searchParams; this.hasSearchData = form.searchParams;
} this.form.memberSearchDTO = form.searchParams
if (this.form.memberType) { } else if (this.form.memberType === 1) {
this.memberList = res.result.memberList; this.memberList = res.result.memberList;
} else if (this.form.memberType === 2) {
this.defaltSelected = res.result.tagGroupList || [];
} }
// 如果是编辑或者详情,从该接口获取卡券详情 // 如果是编辑或者详情,从该接口获取卡券详情
const card = res.result.card; const card = res.result.card;
this.cardInfo = { this.cardInfo = {
...@@ -419,10 +425,14 @@ export default { ...@@ -419,10 +425,14 @@ export default {
// 保存校验 // 保存校验
submit(formName) { submit(formName) {
if (!this.form.memberType && this.toggleTag && !this.getSaveData ) { if (this.form.memberType === 0 && this.toggleTag && !this.getSaveData ) {
this.$tips({type:'warning',message:'人群筛选未保存条件'}) this.$tips({type:'warning',message:'人群筛选未保存条件'})
return; return;
} }
if (this.form.memberType === 2 && !this.form.memberGroupIds) {
this.$tips({type:'warning',message:'会员分组不能为空'});
return;
}
this.$refs[formName].validate((valid) => { this.$refs[formName].validate((valid) => {
if (valid) { if (valid) {
this.$confirm('是否群发卡券?', '提示', { this.$confirm('是否群发卡券?', '提示', {
...@@ -443,7 +453,8 @@ export default { ...@@ -443,7 +453,8 @@ export default {
// 计算发送多少人 // 计算发送多少人
async sendCard() { async sendCard() {
let params = { let params = {
memberSearchDTO:this.form.memberSearchDTO, // memberSearchDTO:this.form.memberSearchDTO,
memberSearchDTO:this.form.memberType ? this.form.memberGroupIds : this.form.memberSearchDTO,
memberType:this.form.memberType, memberType:this.form.memberType,
memberIds:this.form.openIds, memberIds:this.form.openIds,
cardId:this.form.cardId, cardId:this.form.cardId,
...@@ -452,11 +463,6 @@ export default { ...@@ -452,11 +463,6 @@ export default {
if (res.errorCode === 0) { if (res.errorCode === 0) {
var sumPerson = res.result.totalSendCount; var sumPerson = res.result.totalSendCount;
var reducePerson = res.result.repeatMemberIds.length; var reducePerson = res.result.repeatMemberIds.length;
// if(sumPerson-reducePerson>1000){
// this.$tips({type:'warning',message:'投放人数不能大于1000'});
// return ;
// }
this.$confirm(`合计发送${sumPerson}人,是否发送?`, '提示', { this.$confirm(`合计发送${sumPerson}人,是否发送?`, '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelBUttonText: '取消', cancelBUttonText: '取消',
...@@ -478,11 +484,10 @@ export default { ...@@ -478,11 +484,10 @@ export default {
cardId:this.form.cardId, // 2.投放卡券,卡券主键ID cardId:this.form.cardId, // 2.投放卡券,卡券主键ID
sceneSettingId:this.form.sceneSettingId, // 3.营销场景 sceneSettingId:this.form.sceneSettingId, // 3.营销场景
memberType:this.form.memberType, // 4.选择会员类型: 会员筛选: 0; 指定会员: 1 memberType:this.form.memberType, // 4.选择会员类型: 会员筛选: 0; 指定会员: 1
memberSearchDTO:this.form.memberSearchDTO, // JSON.Stringify 人群筛选器 // memberSearchDTO:this.form.memberSearchDTO, // JSON.Stringify 人群筛选器
memberSearchDTO:this.form.memberType ? this.form.memberGroupIds : this.form.memberSearchDTO,
putOnType:this.form.putOnType, // 发送时间, 0:立即发送; 1:定时发送(定时必须选择时间) putOnType:this.form.putOnType, // 发送时间, 0:立即发送; 1:定时发送(定时必须选择时间)
searchJson:this.getSaveData, searchJson:this.getSaveData,
noticeType:this.form.noticeType noticeType:this.form.noticeType
} }
...@@ -525,7 +530,7 @@ export default { ...@@ -525,7 +530,7 @@ export default {
} }
if (this.form.memberType) { if (this.form.memberType === 1) {
params.memberIds = this.form.openIds; // 指定会员:memberType = 1, 多个会员memberId用逗号拼接 params.memberIds = this.form.openIds; // 指定会员:memberType = 1, 多个会员memberId用逗号拼接
} }
if (this.form.putOnType) { if (this.form.putOnType) {
...@@ -595,6 +600,16 @@ export default { ...@@ -595,6 +600,16 @@ export default {
getConfirmData(val) { getConfirmData(val) {
this.form.openIds = val; this.form.openIds = val;
}, },
// 会员分组方法
handleDataTransferred(data) {
// 会员分组 情况下 memberSearchDTO 传数组字符串
if (this.form.memberType === 2) {
this.form.memberGroupIds = data.map(v => v.memberTagGroupId).filter(v => v).join(',');
}
},
handleDataLeft(selectedData, selectionToRemove) {
console.log(selectedData, selectionToRemove)
}
}, },
filters:{ filters:{
filterDate(val) { filterDate(val) {
......
...@@ -133,7 +133,7 @@ ...@@ -133,7 +133,7 @@
<!-- 营销事件 --> <!-- 营销事件 -->
<section class="dm-form__wrap"> <section class="dm-form__wrap">
<h3 class="dm-title__label">营销事件</h3> <h3 class="dm-title__label">营销事件</h3>
<marketing-event ref="marketingEvent" @has-card="hasCard" v-if="ecmPlanId" :ecmPlanId="ecmPlanId" :code="code" :enabledMessageState="enabledMessageState"></marketing-event> <marketing-event ref="marketingEvent" @has-card="hasCard" v-if="ecmPlanId" :ecmPlanId="ecmPlanId" :isSupportVar="form.effectType === 0" :code="code" :enabledMessageState="enabledMessageState"></marketing-event>
</section> </section>
<!-- 只有存在卡券的情况下出现卡券通知方式 --> <!-- 只有存在卡券的情况下出现卡券通知方式 -->
<section class="dm-form__wrap" v-if="currentCard.comName"> <section class="dm-form__wrap" v-if="currentCard.comName">
......
module.exports = [
{number:'{1}',name:'{姓名}'},
{number:'{2}',name:'{姓名+先生/女士}'},
{number:'{3}',name:'{生日日期}'},
{number:'{4}',name:'{生日天数}'},
{number:'{5}',name:'{关注日期}'},
{number:'{6}',name:'{关注天数}'},
{number:'{7}',name:'{主门店品牌名称}'},
{number:'{8}',name:'{主门店名称}'},
{number:'{9}',name:'{主门店电话}'},
{number:'{10}',name:'{专属导购姓名}'},
{number:'{11}',name:'{专属导购手机号}'},
{number:'{12}',name:'{开卡日期}'},
{number:'{13}',name:'{开卡天数}'},
{number:'{14}',name:'{开卡门店名称}'},
{number:'{15}',name:'{会员卡号}'},
{number:'{16}',name:'{会员等级名称}'},
{number:'{17}',name:'{主门店地址}'},
{number:'{18}',name:'{会员等级剩余有效天数}'},
{number:'{19}',name:'{积分余额}'},
{number:'{20}',name:'{30天内将过期积分额度}'},
{number:'{21}',name:'{储值余额}'},
{number:'{22}',name:'{消费总额}'},
{number:'{23}',name:'{消费次数}'},
{number:'{24}',name:'{最近消费日期}'},
{number:'{25}',name:'{最近消费间隔}'},
{number:'{26}',name:'{最高单笔消费}'},
{number:'{27}',name:'{最近消费门店名称}'},
{number:'{28}',name:'{最近消费品牌名称}'}]
<template> <template>
<!-- <span class="dm-text__wrap ellipsis-l2 inline-block" v-html="item.content"></span> --> <!-- <span class="dm-text__wrap ellipsis-l2 inline-block" v-html="item.content"></span> -->
<span class="dm-text__wrap inline-block" v-html="item.content"></span> <span class="dm-text__wrap inline-block" v-html="transfContent"></span>
</template> </template>
<script> <script>
import options from '../assets/options.js';
export default { export default {
name: 'item-text', name: 'item-text',
props: { props: {
...@@ -11,6 +12,41 @@ export default { ...@@ -11,6 +12,41 @@ export default {
default() { default() {
return {} return {}
} }
},
isSupportVar:{
type:Boolean,
default:false
}
},
computed: {
transfContent() {
// 替换{数字}为文本
console.log(this.item)
let val = this.item.content;
if (this.isSupportVar) {
val = val.replace(/\{(?:[1-9]|(1[0-9])?|2[0-8])\}/g,(...argument) => {
let str = '';
let arg = argument[0];
console.log(arg)
options.map(v => {
if (v.number === arg) {
str = v.name;
}
})
return str;
});
}
if (this.item.urlType === 2) {
val = val.replace(/\<.*\>(.*)\<.*\>/g,(...argument) => {
let str = '';
let arg = argument[0];
str = '<i class="iconfont icon-xiaochengxu blue"></i>'+arg;
console.log(arg)
return str;
});
}
console.log(val)
return val;
} }
} }
} }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
<!-- 组件 区域 --> <!-- 组件 区域 -->
<div class="dm-marketing__content__item" v-for="(v,i) in list" :key="i"> <div class="dm-marketing__content__item" v-for="(v,i) in list" :key="i">
<i class="dm-marketing__content--index">{{i+1}}</i> <i class="dm-marketing__content--index">{{i+1}}</i>
<component :is="v.comName" :item="v.item"></component> <component :is="v.comName" :item="v.item" :isSupportVar="isSupportVar"></component>
<i class="el-icon-edit dm-marketing__opt--icon" v-if="v.comName === 'item-teltask' || v.comName === 'item-text' || v.comName === 'item-wxa'" @click="editItem(v)"></i> <i class="el-icon-edit dm-marketing__opt--icon" v-if="v.comName === 'item-teltask' || v.comName === 'item-text' || v.comName === 'item-wxa'" @click="editItem(v)"></i>
<dm-delete @confirm="delItem(v)"> <dm-delete @confirm="delItem(v)">
<i class="el-icon-delete dm-marketing__opt--icon"></i> <i class="el-icon-delete dm-marketing__opt--icon"></i>
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
</transition> </transition>
</div> </div>
<!-- 弹窗组件 --> <!-- 弹窗组件 -->
<component :is="dialogCom" @sendItem="saveToList" :item="currentItem" :show.sync="dialogShow"></component> <component :is="dialogCom" @sendItem="saveToList" :item="currentItem" :show.sync="dialogShow" :isSupportVar="isSupportVar"></component>
</section> </section>
</template> </template>
...@@ -103,6 +103,10 @@ export default { ...@@ -103,6 +103,10 @@ export default {
enabledMessageState: { enabledMessageState: {
type:Number, type:Number,
default:1 default:1
},
isSupportVar:{
type:Boolean,
default:false
} }
}, },
data() { data() {
...@@ -258,8 +262,11 @@ export default { ...@@ -258,8 +262,11 @@ export default {
// 2.文本 // 2.文本
if (val.comName === 'text') { if (val.comName === 'text') {
params.title = val.content; params.title = val.content;
params.text = {// ecm话务对象 // 如果有链接,需要判断链接类型
content:val.content params.text = {
content:val.content,
jumpUrlInfo:val.jumpUrlInfo && JSON.stringify(val.jumpUrlInfo),
urlType:val.urlType,
} }
} }
// 3.小程序 // 3.小程序
......
...@@ -51,7 +51,8 @@ ...@@ -51,7 +51,8 @@
</div> </div>
<dm-img-box v-show="info.contentType === 2" :mediaId="info.mediaId" @get-data="getImgData"></dm-img-box> <dm-img-box v-show="info.contentType === 2" :mediaId="info.mediaId" @get-data="getImgData"></dm-img-box>
<div v-show="info.contentType === 1"> <div v-show="info.contentType === 1">
<wxText :msgText="info.content" @listenWxText="getWxText"></wxText> <!-- <wxText :msgText="info.content" @listenWxText="getWxText"></wxText> -->
<wx-text :appendToBody="true" :value.sync="info.content" :urlType.sync="info.urlType" :jumpUrlInfo.sync="info.jumpUrlInfo" :isSupportVar="false" ref="wxText"></wx-text>
</div> </div>
</div> </div>
</section> </section>
...@@ -87,14 +88,16 @@ import {formateDateTimeByType} from '@/utils/index.js' ...@@ -87,14 +88,16 @@ import {formateDateTimeByType} from '@/utils/index.js'
import {checkMessageSendCount} from '@/service/api/messageApi.js'; import {checkMessageSendCount} from '@/service/api/messageApi.js';
import {sceneSettingList,sendRecordSaveService,wechatImageTextEdit,getWechatMarketingDetail} from '@/service/api/wechatApi.js'; import {sceneSettingList,sendRecordSaveService,wechatImageTextEdit,getWechatMarketingDetail} from '@/service/api/wechatApi.js';
import config from '@/config' import config from '@/config'
import wxText from '@/components/wxText/wxText' // import wxText from '@/components/wxText/wxText'
import wxText from '@/components/wx-text/index.vue';
export default { export default {
name: 'add-record', name: 'add-record',
components:{ components:{
dmImgText, dmImgText,
dmImgBox, dmImgBox,
wxText 'wx-text':wxText
}, },
computed: { computed: {
asideShow() { asideShow() {
...@@ -141,6 +144,8 @@ export default { ...@@ -141,6 +144,8 @@ export default {
content:'', content:'',
textNum:0, textNum:0,
mediaId:'', mediaId:'',
urlType:0,
jumpUrlInfo:{name:'',url:''}
}, },
memberList:[], memberList:[],
isEdit:this.$route.meta.type === 'edit', isEdit:this.$route.meta.type === 'edit',
...@@ -191,6 +196,8 @@ export default { ...@@ -191,6 +196,8 @@ export default {
this.info.wechatTextId = result.wechatTextId || ''; this.info.wechatTextId = result.wechatTextId || '';
this.info.content = result.content || ''; this.info.content = result.content || '';
this.info.mediaId = result.mediaId || ''; this.info.mediaId = result.mediaId || '';
this.info.urlType = result.urlType || 0;
this.info.jumpUrlInfo = (result.jumpUrlInfo && JSON.parse(result.jumpUrlInfo)) || {name:'',url:''};
if (res.result.searchId) { if (res.result.searchId) {
this.useId = res.result.searchId this.useId = res.result.searchId
this.hasSearchData = result.searchParams; this.hasSearchData = result.searchParams;
......
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