Commit 74f36a89 by crushh

update: 链接

parent df4c1fea
......@@ -41,3 +41,12 @@ export const detailClerkList = params => postJsonRequest('/haoban-manage3-web/hm
//【欢迎语】-- 特殊欢迎语关联详情列表
export const welcomeRelationList = params => getRequest('/haoban-manage3-web/welcome/relation/list', params);
// 【活码链接】-- 新增
export const linkAdd = params => postJsonRequest('/haoban-manage3-web/hm/link/add', params);
// 【活码链接】-- 编辑
export const linkUpdate = params => postJsonRequest('/haoban-manage3-web/hm/link/update', params);
// 【活码链接】-- 详情
export const linkDetail = params => postJsonRequest('/haoban-manage3-web/hm/link/detail', params);
......@@ -64,8 +64,6 @@ Vue.axios.interceptors.request.use(
let haobanSign = sessionStorage.getItem('userInfoBrandId');
haobanSign ? (config.headers.enterpriseId = haobanSign) : '';
}
console.log(config);
return config;
},
err => {
......
......@@ -14,25 +14,24 @@
export default {
/*
* var storeBusinessTime="10:00-22:00" to
*/
* var storeBusinessTime="10:00-22:00" to
*/
timeToDate: function(val) {
var date = new Date()
var date = new Date();
var y = date.getFullYear();
var m = date.getMonth() +1;
var m = date.getMonth() + 1;
var day = date.getDate();
var d = [],newArr = [];
var d = [],
newArr = [];
var dArr = val.split('-');
dArr.forEach(function(ele,index){
newArr.push(ele.split(':'))
})
d = [new Date(y,m,day,newArr[0][0],newArr[0][1]),new Date(y,m,day,newArr[1][0],newArr[1][1])]
dArr.forEach(function(ele, index) {
newArr.push(ele.split(':'));
});
d = [new Date(y, m, day, newArr[0][0], newArr[0][1]), new Date(y, m, day, newArr[1][0], newArr[1][1])];
return d;
},
dateToTime(val) {
// console.log(val)
// (0-9)年月数字的显示
......@@ -40,9 +39,9 @@ export default {
return num > 9 ? '' + num : '0' + num;
}
var t;
var t1 = formatDig(new Date(val[0]).getHours())+':'+formatDig(new Date(val[0]).getMinutes())
var t2 = formatDig(new Date(val[1]).getHours())+':'+formatDig(new Date(val[1]).getMinutes())
t= t1+'-'+t2
var t1 = formatDig(new Date(val[0]).getHours()) + ':' + formatDig(new Date(val[0]).getMinutes());
var t2 = formatDig(new Date(val[1]).getHours()) + ':' + formatDig(new Date(val[1]).getMinutes());
t = t1 + '-' + t2;
return t;
}
}
};
var SIGN_REGEXP = /([yMdhsm])(\1*)/g;
var DEFAULT_PATTERN = 'yyyy-MM-dd';
function padding(s, len) {
var len = len - (s + '').length;
for (var i = 0; i < len; i++) { s = '0' + s; }
return s;
};
var len = len - (s + '').length;
for (var i = 0; i < len; i++) {
s = '0' + s;
}
return s;
}
export default {
getQueryStringByName: function (name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
var context = "";
if (r != null)
context = r[2];
reg = null;
r = null;
return context == null || context == "" || context == "undefined" ? "" : context;
getQueryStringByName: function(name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
var r = window.location.search.substr(1).match(reg);
var context = '';
if (r != null) context = r[2];
reg = null;
r = null;
return context == null || context == '' || context == 'undefined' ? '' : context;
},
formatDate: {
format: function(date, pattern) {
pattern = pattern || DEFAULT_PATTERN;
return pattern.replace(SIGN_REGEXP, function($0) {
switch ($0.charAt(0)) {
case 'y':
return padding(date.getFullYear(), $0.length);
case 'M':
return padding(date.getMonth() + 1, $0.length);
case 'd':
return padding(date.getDate(), $0.length);
case 'w':
return date.getDay() + 1;
case 'h':
return padding(date.getHours(), $0.length);
case 'm':
return padding(date.getMinutes(), $0.length);
case 's':
return padding(date.getSeconds(), $0.length);
}
});
},
formatDate: {
format: function (date, pattern) {
pattern = pattern || DEFAULT_PATTERN;
return pattern.replace(SIGN_REGEXP, function ($0) {
switch ($0.charAt(0)) {
case 'y': return padding(date.getFullYear(), $0.length);
case 'M': return padding(date.getMonth() + 1, $0.length);
case 'd': return padding(date.getDate(), $0.length);
case 'w': return date.getDay() + 1;
case 'h': return padding(date.getHours(), $0.length);
case 'm': return padding(date.getMinutes(), $0.length);
case 's': return padding(date.getSeconds(), $0.length);
}
});
},
parse: function (dateString, pattern) {
var matchs1 = pattern.match(SIGN_REGEXP);
var matchs2 = dateString.match(/(\d)+/g);
if (matchs1.length == matchs2.length) {
var _date = new Date(1970, 0, 1);
for (var i = 0; i < matchs1.length; i++) {
var _int = parseInt(matchs2[i]);
var sign = matchs1[i];
switch (sign.charAt(0)) {
case 'y': _date.setFullYear(_int); break;
case 'M': _date.setMonth(_int - 1); break;
case 'd': _date.setDate(_int); break;
case 'h': _date.setHours(_int); break;
case 'm': _date.setMinutes(_int); break;
case 's': _date.setSeconds(_int); break;
}
}
return _date;
}
return null;
parse: function(dateString, pattern) {
var matchs1 = pattern.match(SIGN_REGEXP);
var matchs2 = dateString.match(/(\d)+/g);
if (matchs1.length == matchs2.length) {
var _date = new Date(1970, 0, 1);
for (var i = 0; i < matchs1.length; i++) {
var _int = parseInt(matchs2[i]);
var sign = matchs1[i];
switch (sign.charAt(0)) {
case 'y':
_date.setFullYear(_int);
break;
case 'M':
_date.setMonth(_int - 1);
break;
case 'd':
_date.setDate(_int);
break;
case 'h':
_date.setHours(_int);
break;
case 'm':
_date.setMinutes(_int);
break;
case 's':
_date.setSeconds(_int);
break;
}
}
return _date;
}
return null;
}
}
};
<template>
<el-popover placement="bottom" style="min-width: 357px" v-model="departmentVisible">
<dm-simple-transfer v-model="checked" :data="data" :item-size="56" :titles="['选择门店', '已选门店']" filterable filter-placeholder="请输入门店名称/code">
<dm-simple-transfer v-model="checked" :props="props" :data="data" :item-size="56" :titles="['选择门店', '已选门店']" filterable filter-placeholder="请输入门店名称/code" @change="change">
<div slot-scope="{ option }">
<p>{{ option.label }}</p>
<p style="font-size: 12px;line-height: 18px">{{ option.key }}</p>
<p style="font-size: 12px;line-height: 18px">{{ option.code }}</p>
</div>
</dm-simple-transfer>
<div class="flex-column item-cell-select inline-block " slot="reference">
<el-input></el-input>
<div class="show-select-num cursor-pointer w-250" slot="reference">
已经选择{{ checked.length }}家门店
<span class="el-input__suffix"
><span class="el-input__suffix-inner"><i :class="['el-select__caret el-input__icon el-icon-arrow-up', departmentVisible ? 'is-reverse' : '']"></i></span
></span>
</div>
</el-popover>
</template>
<script>
import { getRequest } from '@/api/api';
export default {
data() {
return {
departmentVisible: false,
checked: [],
data: []
data: [],
props: {
key: 'storeId',
label: 'storeName'
},
form: {
storeSearchParams: '',
pageSize: 20,
pageNum: 1
}
};
},
mounted() {
this.getList();
},
methods: {
getList() {
getRequest('/haoban-manage3-web/hm/store-list', {}).then(res => {
console.log(res);
const { result } = res.data;
this.data = result || [];
});
},
change(val) {
this.$emit('change', val);
}
}
};
</script>
<style></style>
<style lang="scss" scoped>
.show-select-num {
position: relative;
display: inline-block;
font-size: inherit;
height: 32px;
line-height: 32px;
padding-left: 10px;
-webkit-appearance: none;
background-color: #fff;
background-image: none;
border-radius: 4px;
border: 1px solid #dcdfe6;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: #606266;
.el-select__caret {
color: #c0c4cc;
font-size: 14px;
transition: transform 0.3s;
transform: rotate(180deg);
cursor: pointer;
&.is-reverse {
transform: rotate(0deg);
}
}
}
</style>
......@@ -28,7 +28,7 @@ const attractFlowLinkRouter = [
meta: {
type: 'info'
},
component: _import('salesleads/actCodeManage/attractFlowLink', 'detail')
component: _import('salesleads/actCodeManage/attractFlowLink', 'info')
},
{
path: '/ladingPageList',
......
......@@ -3,32 +3,32 @@
*/
export function isvalidUsername(str) {
const valid_map = ['admin', 'editor']
return valid_map.indexOf(str.trim()) >= 0
const valid_map = ['admin', 'editor'];
return valid_map.indexOf(str.trim()) >= 0;
}
/* 合法uri*/
export function validateURL(textval) {
const urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
return urlregex.test(textval)
const urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;
return urlregex.test(textval);
}
/* 小写字母*/
export function validateLowerCase(str) {
const reg = /^[a-z]+$/
return reg.test(str)
const reg = /^[a-z]+$/;
return reg.test(str);
}
/* 大写字母*/
export function validateUpperCase(str) {
const reg = /^[A-Z]+$/
return reg.test(str)
const reg = /^[A-Z]+$/;
return reg.test(str);
}
/* 大小写字母*/
export function validateAlphabets(str) {
const reg = /^[A-Za-z]+$/
return reg.test(str)
const reg = /^[A-Za-z]+$/;
return reg.test(str);
}
/**
......@@ -37,7 +37,23 @@ export function validateAlphabets(str) {
* @returns {boolean}
*/
export function validateEmail(email) {
const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return re.test(email)
const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
/** 表单校验滚动到第一个错误项
* @param {Object} that vue实例
* this.scrollToError(this);
*/
export const scrollToError = that => {
that.$nextTick(_ => {
const isError = document.getElementsByClassName('is-error');
isError[0].scrollIntoView({
// 滚动到指定节点
// 值有start,center,end,nearest,当前显示在视图区域中间
block: 'center',
// 值有auto、instant,smooth,缓动动画(当前是慢速的)
behavior: 'smooth'
});
});
};
......@@ -2,7 +2,7 @@
<div class="daily-set-wrap">
<div class="daily-set-content border-box">
<div class="salutatory-set-wrap m-t-20">
<el-form label-width="117px" ref="form" :model="form" :rules="rules" refs="form" class="form">
<el-form label-width="117px" ref="form" :model="form" :rules="rules" class="form">
<el-form-item label="欢迎语标题" prop="title">
<el-input show-word-limit placeholder="请输入欢迎语标题" type="text" v-model="form.title" maxlength="20" class="w-384"></el-input>
</el-form-item>
......
......@@ -255,7 +255,7 @@ export default {
console.log(row);
},
goDetail(row) {
console.log(row);
this.$router.push(`attractFlowLinkInfo/${row.linkId}`);
},
goLink(row) {
this.linkUrl = row.linkUrl;
......@@ -265,6 +265,7 @@ export default {
},
goEdit(row) {
console.log(row);
this.$router.push(`attractFlowLinkEdit/${row.linkId}`);
}
}
};
......
<template>
<div class="app-detail-wrap p-20" v-loading="loading">
<div class="flex p-b-40">
<vue-qr id="qrImg" :text="link.linkUrl" :size="200" :margin="5" v-if="link.linkType == 2"></vue-qr>
<div class="m-l-30">
<el-descriptions :title="link.name">
<el-descriptions-item label="ID">{{ link.linkId }}</el-descriptions-item>
<el-descriptions-item label="code">{{ link.linkCode }}</el-descriptions-item>
<el-descriptions-item label="链接类型">
<el-tag size="mini">{{ link.linkType == 1 ? '专用链接' : '通用链接' }}</el-tag></el-descriptions-item
>
<el-descriptions-item label="创建人">{{ link.creatorName }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ link.createTime }}</el-descriptions-item>
<el-descriptions-item label="链接标签">
<el-tag size="mini">{{ link.memberLabelName }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="链接描述">{{ link.remark }}</el-descriptions-item>
</el-descriptions>
<div>
<el-button icon="el-icon-download" plain @click="downloadQR">下载二维码</el-button>
<el-button v-if="link.linkType == 2" v-clipboard:text="link.linkUrl" plain>复制链接</el-button>
<el-button v-if="link.linkType == 2" plain @click="goEdit">修改</el-button>
</div>
</div>
</div>
<div class="fixed-tab" v-if="scrollTop > 300">
<el-tabs v-model="activeName" type="card">
<el-tab-pane label="详情信息" name="first"> <div></div> </el-tab-pane>
<el-tab-pane label="数据统计" name="second">
<div></div>
</el-tab-pane>
</el-tabs>
</div>
<el-tabs v-model="activeName" type="card">
<el-tab-pane label="详情信息" name="first">
<act-code-detail-info type="actLink" :enterprise-id="link.enterpriseId" :welcome-id="link.welcomeId"></act-code-detail-info>
<dm-sub-title type="line">落地页配置</dm-sub-title>
<div>
<div class="flex">
<div class="welcome-left-view">
<el-descriptions :column="1">
<el-descriptions-item label="页面标题">{{ page.pageTitle }}</el-descriptions-item>
<el-descriptions-item label="商户名称">{{ page.merchantName }}</el-descriptions-item>
<el-descriptions-item label="商户电话">{{ page.merchantPhoneNumber }}</el-descriptions-item>
<el-descriptions-item label="商户LOGO">
<img :src="page.merchantLogo" class="merchantLogo" />
</el-descriptions-item>
<el-descriptions-item label="引导语">{{ page.linkCode }}</el-descriptions-item>
</el-descriptions>
</div>
<div class="preview">
<p class="previewTitle">落地页预览</p>
<previewPage :data="page" />
<p class="previewBottom">此二维码只是样式预览效果,请勿直接使用</p>
</div>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="数据统计" name="second"> </el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import { linkDetail } from '@/api/actCode';
import actCodeDetailInfo from '../../components/actCodeDetailInfo.vue';
import previewPage from '@/components/preview-page.vue';
import { _throttle } from '@/common/js/public';
import VueQr from 'vue-qr';
export default {
name: 'actCodeDetail',
components: { actCodeDetailInfo, previewPage, VueQr },
props: {
hmId: {
type: String,
default: ''
}
},
data() {
return {
loading: false,
activeName: 'first',
codeStatusLis: [
{ value: '', style: '' },
{ value: '正常', style: 'success' },
{ value: '已作废', style: 'danger' },
{ value: '待生效', style: 'info' },
{ value: '正常-今日已达上限', style: 'warning' }
],
link: {
linkId: 419648718594129960,
customRuleJson: '{"fw_store":{"open":1,"zs":1,"dz":1,"dy":1},"xg_store":{"open":1,"zs":1,"dz":1,"dy":0}}',
linkType: 2,
memberLabelId: 'fd6b44967aa647bcadfad10706244c56',
name: '活码链接-711',
pageId: 418460224953786370,
remark: '说明',
linkUrl: 'www.baidu.com',
storeList: [
{
storeId: 'ff80808181e0effb0181e26a674c000e',
storeName: '测试有赞商城',
storeCode: '991001'
},
{
storeId: 'ff80808181e0effb0181e128d0b70000',
storeName: '达达店铺',
storeCode: 'DADA'
}
],
storeRuleJson: '{"store_type":2,"open":0,"store":{"dz":0,"dy":1,"ndz":0,"ndy":1}, "city_store":{"open":1,"dz":1,"dy":1}}',
welcomeId: '025867b7a01541979617229a4aca9551',
enterpriseId: 'ff8080815dacd3a2015dacd3ef5c0000',
wxEnterpriseId: 'ca66a01b79474c40b3e7c7f93daf1a3b'
},
page: {},
welcome: {},
scrollTop: 0
};
},
methods: {
downloadQR() {
const qrcode = document.getElementById('qrImg');
console.log(qrcode);
let img = qrcode.getElementsByTagName('img')[0];
let link = document.createElement('a');
let url = img.getAttribute('src');
link.setAttribute('href', url);
link.setAttribute('download', `${this.link.linkId}_${this.link.name}.png`);
link.click();
},
goEdit() {
this.$router.push(`attractFlowLinkEdit/${this.link.linkId}`);
},
async getDetail() {
this.loading = true;
linkDetail({ linkId: this.$route.params.id })
.then(res => {
const { result } = res.data;
if (result) {
const { link, page, welcome } = result;
this.link = link;
this.page = page;
this.welcome = welcome;
}
})
.catch(function(error) {
this.$message.error({
duration: 1000,
message: error.message
});
})
.finally(_ => {
this.loading = false;
});
},
scrollMethod: _throttle(function() {
// 节流会不自然 左右不滑动
this.scrollTop = document.getElementById('hb-layout-pager-one').scrollTop;
}, 100)
},
mounted() {
this.getDetail();
document.getElementById('hb-layout-pager-one').addEventListener('scroll', this.scrollMethod);
},
destroyed() {
document.getElementById('hb-layout-pager-one').removeEventListener('scroll', this.scrollMethod);
}
};
</script>
<style lang="less" scoped>
.app-detail-wrap {
// height: 100%;
background: #fff;
.p-b-40 {
padding-bottom: 40px;
}
}
.img-200 {
width: 200px;
height: 200px;
border-radius: 8px;
padding-right: 30px;
}
.height-22 {
height: 22px;
}
.text-ellipsis-white {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.fixed-tab {
position: absolute;
top: 80px;
z-index: 1;
padding-bottom: 0;
height: 40px;
background: white;
width: 100%;
// left: 50px;
}
.welcome-left-view {
width: 639px;
// margin-right: 120px;
}
.merchantLogo {
width: 120px;
height: 120px;
background: #ffffff;
border-radius: 2px;
border: 1px solid #dcdfe6;
}
.preview {
display: flex;
flex-direction: column;
align-items: center;
margin-left: 40px;
/deep/ .pageTitle {
position: absolute !important;
top: 44px !important;
}
.previewTitle {
font-weight: 500;
color: #303133;
line-height: 20px;
font-size: 14px;
width: 70px;
text-align: center;
margin-bottom: 20px;
}
.previewBottom {
font-size: 12px;
text-align: center;
width: 228px;
color: #909399;
line-height: 17px;
}
}
</style>
<template>
<div>
<div class="daily-set-content">
<el-form label-width="100px" ref="form" :model="form" :rules="rules" refs="form" class="form">
<el-form label-width="100px" ref="form" :model="form" :rules="rules" class="form">
<el-form-item label="模板名称" prop="pageName" required>
<el-input show-word-limit placeholder="请输入模板名称" type="text" v-model="form.pageName" maxlength="20" class="w-340"></el-input>
</el-form-item>
......@@ -41,6 +41,7 @@
import singleUpload from '@/components/single-upload.vue';
import previewPage from '@/components/preview-page.vue';
import { guidePageDetail, guidePageEdit, guidePageSave, wxEnterpriseList } from '@/api/actCode';
export default {
components: {
previewPage,
......@@ -132,11 +133,14 @@ export default {
});
},
save() {
if (this.isEdit) {
this.guidePageEdit();
} else {
this.guidePageSave();
}
this.$refs.form.validate(val => {
if (!val) return;
if (this.isEdit) {
this.guidePageEdit();
} else {
this.guidePageSave();
}
});
}
}
};
......
......@@ -2,7 +2,7 @@
<div class="daily-set-content">
<div class="flex flex-space-between m-b-16">
<div class="flex flex-align-center">
<el-input placeholder="请输入模板ID/名称、创建人" class="w-260" v-model="form.pageSearchText" @keyup.native="value => toInput(value, searchInput)" clearable @clear="getList"> <i slot="prefix" class="el-input__icon el-icon-search"></i> </el-input>
<el-input placeholder="请输入模板ID/名称、创建人" class="w-260" v-model="form.pageSearchText" @keyup.native="toInput" clearable @clear="getList"> <i slot="prefix" class="el-input__icon el-icon-search"></i> </el-input>
<span style="font-size:14px;" class="m-l-10">模板创建时间:</span>
<el-date-picker class="m-l-10 w-256" v-model="form.dateRange" @change="getList" type="daterange" :value-format="'yyyy-MM-dd'" clearable @clear="getList" range-separator="~" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker>
</div>
......
......@@ -56,7 +56,7 @@
</div>
</template>
<script>
import actCodeDetailInfo from './actCodeDetailInfo.vue';
import actCodeDetailInfo from '../../components/actCodeDetailInfo.vue';
import actCodeDetailStatistics from './actCodeDetailStatistics.vue';
import { _throttle } from '@/common/js/public';
import { getRequest, deleteRequest } from '@/api/api';
......
......@@ -31,7 +31,7 @@
<preview-welcome :welcomeContent="welcomeData.welcomeContent" :mediaList="welcomeData.welcomeMediaList"></preview-welcome>
</div>
</div>
<div>
<div v-if="type == 'actCode'">
<div class="title flex">
<div class="blue-block"></div>
<span class="font-w-500 color-303133">使用成员</span>
......@@ -89,6 +89,10 @@ export default {
hmId: {
type: String,
default: ''
},
type: {
type: String,
default: 'actCode'
}
},
data() {
......@@ -183,8 +187,10 @@ export default {
}
},
mounted() {
let that = this;
that.getUseTableList();
if (this.type == 'actCode') {
this.getUseTableList();
}
this.getwelcomeInfo();
},
watch: {
welcomeId: function(newData, oldData) {
......
......@@ -481,6 +481,9 @@ input:focus {
.m-l-16 {
margin-left: 16px;
}
.m-l-30 {
margin-left: 30px;
}
.m-t-6{
margin-top: 6px;
}
......
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