新增新版私域引流
This commit is contained in:
230
components/attract-popup.vue
Normal file
230
components/attract-popup.vue
Normal file
@@ -0,0 +1,230 @@
|
||||
<!-- 私域引流 -->
|
||||
<template>
|
||||
<u-popup :show="show" mode="center" :safeAreaInsetBottom="false">
|
||||
<view class="new_preview">
|
||||
<view class="header">{{ shopInfo.shopName }}</view>
|
||||
<view class="content">
|
||||
<view class="title">{{ form.title }}</view>
|
||||
<view class="img_wrap">
|
||||
<image class="img" :src="form.qrCode"></image>
|
||||
</view>
|
||||
<view class="intro">
|
||||
{{ form.content }}
|
||||
</view>
|
||||
<view class="foot">
|
||||
{{ form.note }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="close" @click="closeHandle">
|
||||
<u-icon name="close" color="#fff" size="14"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import dayjs from 'dayjs';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { config } from '@/common/api/market/drainageConfig.js';
|
||||
import { checkArrayElementsExist } from '@/utils/util.js';
|
||||
|
||||
const shopInfo = ref('');
|
||||
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: 'home' // 调用的位置 home首页 order支付成功后
|
||||
}
|
||||
});
|
||||
|
||||
const show = ref(false);
|
||||
const form = ref({});
|
||||
const drainageHomeKey = 'drainageHome';
|
||||
function closeHandle() {
|
||||
switch (props.type) {
|
||||
case 'home':
|
||||
// 在首页关闭
|
||||
switch (form.value.homeType) {
|
||||
case 'only':
|
||||
// 仅显示1次
|
||||
uni.cache.set(drainageHomeKey, {
|
||||
value: form.value.homeType
|
||||
});
|
||||
break;
|
||||
case 'day':
|
||||
// 每天显示1次
|
||||
uni.cache.set(drainageHomeKey, {
|
||||
value: form.value.homeType,
|
||||
time: dayjs().format('YYYY-MM-DD')
|
||||
});
|
||||
break;
|
||||
case 'every':
|
||||
// 每次onload都显示
|
||||
uni.cache.set(drainageHomeKey, {
|
||||
value: form.value.homeType
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'order':
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
show.value = false;
|
||||
}
|
||||
|
||||
// 显示逻辑
|
||||
function showHandle() {
|
||||
switch (props.type) {
|
||||
case 'home':
|
||||
// 首页
|
||||
if (form.value.homeEnable == 0) return;
|
||||
let drainage = uni.cache.get(drainageHomeKey);
|
||||
|
||||
console.log('drainage', drainage);
|
||||
|
||||
if (!drainage || form.value.homeType != drainage.value) {
|
||||
uni.cache.set(drainageHomeKey, '');
|
||||
show.value = true;
|
||||
} else {
|
||||
switch (drainage.value) {
|
||||
case 'only':
|
||||
// 存在则证明已经显示过一次,则不在显示
|
||||
break;
|
||||
case 'day':
|
||||
// 判断是不是用一天,同一天不显示,不是同一天则显示
|
||||
let localDay = drainage.time;
|
||||
let currentDay = dayjs().format('YYYY-MM-DD');
|
||||
if (localDay != currentDay) {
|
||||
show.value = true;
|
||||
}
|
||||
break;
|
||||
case 'every':
|
||||
// 页面每次onload会触发显示
|
||||
show.value = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'order':
|
||||
// 订单 只要包含用餐类型就显示
|
||||
let shopMode = shopInfo.value.eatModel.split(',');
|
||||
if (checkArrayElementsExist(shopMode, form.value.orderType)) {
|
||||
show.value = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取私域引流配置
|
||||
async function configAjax() {
|
||||
try {
|
||||
const shopId = uni.cache.get('shopId');
|
||||
const res = await config({ shopId: shopId });
|
||||
form.value = res;
|
||||
showHandle();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
configAjax
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
shopInfo.value = uni.cache.get('shopInfo');
|
||||
if (props.type == 'home') {
|
||||
configAjax();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.new_preview {
|
||||
--bg: #3f3b37;
|
||||
--color: #f6dfc4;
|
||||
--borderColor: #f6dfc45b;
|
||||
width: 90vw;
|
||||
background-color: var(--bg);
|
||||
border-radius: 4px;
|
||||
position: relative;
|
||||
.close {
|
||||
--size: 70upx;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
border-radius: 50%;
|
||||
background-color: var(--bg);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
bottom: calc(var(--size) * -1 - 20upx);
|
||||
left: 50%;
|
||||
margin-left: calc(var(--size) / 2 * -1);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
color: var(--color);
|
||||
height: 50px;
|
||||
border-bottom: 1px dashed var(--borderColor);
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-bottom: 14px;
|
||||
|
||||
.title {
|
||||
font-size: 14px;
|
||||
color: var(--color);
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.img_wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.img {
|
||||
--size: 220px;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.intro {
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
color: var(--color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
.foot {
|
||||
height: 40px;
|
||||
color: var(--borderColor);
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 14px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,114 +1,93 @@
|
||||
<template>
|
||||
<view>
|
||||
<!-- 私域引流 -->
|
||||
<up-popup
|
||||
:show="show"
|
||||
mode="center"
|
||||
round="16rpx"
|
||||
closeOnClickOverlay
|
||||
@close="close"
|
||||
:safeAreaInsetBottom="false"
|
||||
>
|
||||
<view class="preview-box">
|
||||
<view class="u-flex" style="align-items: stretch">
|
||||
<view
|
||||
class="u-flex-1 u-p-r-24 u-flex u-flex-col"
|
||||
style="align-items: start; justify-content: space-between"
|
||||
>
|
||||
<view>
|
||||
<view class="font-14 font-bold color-333">{{
|
||||
drainageConfig.title
|
||||
}}</view>
|
||||
<view class="u-m-t-16 font-12 color-666">{{
|
||||
drainageConfig.content
|
||||
}}</view>
|
||||
</view>
|
||||
<view>
|
||||
<!-- 私域引流 -->
|
||||
<up-popup :show="show" mode="center" round="16rpx" closeOnClickOverlay @close="close" :safeAreaInsetBottom="false">
|
||||
<view class="preview-box">
|
||||
<view class="u-flex" style="align-items: stretch">
|
||||
<view class="u-flex-1 u-p-r-24 u-flex u-flex-col" style="align-items: start; justify-content: space-between">
|
||||
<view>
|
||||
<view class="font-14 font-bold color-333">{{ drainageConfig.title }}</view>
|
||||
<view class="u-m-t-16 font-12 color-666">{{ drainageConfig.content }}</view>
|
||||
</view>
|
||||
|
||||
<view class="color-999 font-12 u-m-t-16">{{
|
||||
drainageConfig.note
|
||||
}}</view>
|
||||
</view>
|
||||
<view class="color-999 font-12 u-m-t-16">{{ drainageConfig.note }}</view>
|
||||
</view>
|
||||
|
||||
<image
|
||||
:show-menu-by-longpress="true"
|
||||
:src="drainageConfig.qrCode"
|
||||
style="width: 240rpx; height: 240rpx"
|
||||
mode="aspectFit"
|
||||
></image>
|
||||
</view>
|
||||
<image :show-menu-by-longpress="true" :src="drainageConfig.qrCode" style="width: 240rpx; height: 240rpx" mode="aspectFit"></image>
|
||||
</view>
|
||||
|
||||
<view class="close" @click="close">
|
||||
<up-icon name="close-circle" size="34" color="#fff"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
</up-popup>
|
||||
</view>
|
||||
<view class="close" @click="close">
|
||||
<up-icon name="close-circle" size="34" color="#fff"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
</up-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import * as drainageConfigApi from "@/common/api/market/drainageConfig.js";
|
||||
import { ref, reactive, computed, watch, onMounted } from "vue";
|
||||
import * as drainageConfigApi from '@/common/api/market/drainageConfig.js';
|
||||
import { ref, reactive, computed, watch, onMounted } from 'vue';
|
||||
|
||||
const showPreview = defineModel({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
type: Boolean,
|
||||
default: false
|
||||
});
|
||||
|
||||
const show=ref(false);
|
||||
const emit = defineEmits(["close"]);
|
||||
const show = ref(false);
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
function close() {
|
||||
show.value = false;
|
||||
emit("close");
|
||||
show.value = false;
|
||||
emit('close');
|
||||
}
|
||||
const drainageConfig = ref({});
|
||||
async function getDrainageConfig() {
|
||||
const shopId = uni.cache.get("shopId");
|
||||
const drainageConfigRes = await drainageConfigApi.config({
|
||||
shopId: shopId,
|
||||
});
|
||||
drainageConfig.value = drainageConfigRes;
|
||||
if (drainageConfig.value.isEnable) {
|
||||
show.value = true;
|
||||
} else {
|
||||
close();
|
||||
}
|
||||
const shopId = uni.cache.get('shopId');
|
||||
const drainageConfigRes = await drainageConfigApi.config({
|
||||
shopId: shopId
|
||||
});
|
||||
drainageConfig.value = drainageConfigRes;
|
||||
if (drainageConfig.value.isEnable) {
|
||||
show.value = true;
|
||||
} else {
|
||||
close();
|
||||
}
|
||||
}
|
||||
// onMounted(() => {
|
||||
// getDrainageConfig();
|
||||
// });
|
||||
watch(
|
||||
() => showPreview.value,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
getDrainageConfig();
|
||||
}
|
||||
}
|
||||
() => showPreview.value,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
getDrainageConfig();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.u-flex-col {
|
||||
flex-direction: column;
|
||||
flex-direction: column;
|
||||
}
|
||||
.preview {
|
||||
padding: 8rpx 32rpx;
|
||||
border-radius: 12rpx;
|
||||
background: $my-main-color;
|
||||
color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
line-height: 40rpx;
|
||||
padding: 8rpx 32rpx;
|
||||
border-radius: 12rpx;
|
||||
background: $my-main-color;
|
||||
color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
.preview-box {
|
||||
width: 700rpx;
|
||||
padding: 32rpx 28rpx;
|
||||
position: relative;
|
||||
.close {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: -100rpx;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
width: 700rpx;
|
||||
padding: 32rpx 28rpx;
|
||||
position: relative;
|
||||
.close {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: -100rpx;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,43 +1,49 @@
|
||||
<template>
|
||||
<view>
|
||||
<!-- 生成公众号二维码 -->
|
||||
<we-qrcode @generate="(e) => qrcodeResult(e)"></we-qrcode>
|
||||
<view>
|
||||
<!-- 生成公众号二维码 -->
|
||||
<we-qrcode @generate="(e) => qrcodeResult(e)"></we-qrcode>
|
||||
|
||||
<officialAccount
|
||||
followIndex="order"
|
||||
:wechatAcQrcode="wechatAcQrcode"
|
||||
v-if="showOfficialAccount"
|
||||
@close="modelClose($event, 'officialAccount')"
|
||||
/>
|
||||
<Drainage v-model="showDrainage" @close="modelClose($event, 'drainage')" />
|
||||
</view>
|
||||
<officialAccount followIndex="order" :wechatAcQrcode="wechatAcQrcode" v-if="showOfficialAccount" @close="modelClose($event, 'officialAccount')" />
|
||||
<!-- <Drainage v-model="showDrainage" @close="modelClose($event, 'drainage')" /> -->
|
||||
<attractPopup type="order" ref="attractPopupRef" />
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import weQrcode from "@/components/wechat-ac-qrcode.vue";
|
||||
<script setup>
|
||||
import weQrcode from '@/components/wechat-ac-qrcode.vue';
|
||||
|
||||
import { ref, watch, computed, reactive, toRaw } from "vue";
|
||||
import officialAccount from "@/components/official-account.vue";
|
||||
import Drainage from "@/components/drainage.vue";
|
||||
import attractPopup from '@/components/attract-popup.vue';
|
||||
import { ref, watch, computed, reactive, toRaw } from 'vue';
|
||||
import officialAccount from '@/components/official-account.vue';
|
||||
import Drainage from '@/components/drainage.vue';
|
||||
|
||||
const attractPopupRef = ref(null);
|
||||
|
||||
const showDrainage = defineModel({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
type: Boolean,
|
||||
default: false
|
||||
});
|
||||
|
||||
watch(showDrainage, (newVal, oldVal) => {
|
||||
console.log('modelValue 变化:', { newVal, oldVal });
|
||||
if (newVal == true) {
|
||||
attractPopupRef.value.configAjax();
|
||||
}
|
||||
});
|
||||
|
||||
const showOfficialAccount = ref(false);
|
||||
|
||||
function modelClose(e, type) {
|
||||
console.log("modelClose", type);
|
||||
if (type == "drainage") {
|
||||
showOfficialAccount.value = true;
|
||||
return;
|
||||
}
|
||||
console.log('modelClose', type);
|
||||
if (type == 'drainage') {
|
||||
showOfficialAccount.value = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
const wechatAcQrcode = ref("");
|
||||
const userinfo = uni.cache.get("userInfo") || {};
|
||||
const codeVal = ref(userinfo.wechatAcQrcode || "");
|
||||
console.log("codeVal", codeVal.value);
|
||||
const wechatAcQrcode = ref('');
|
||||
const userinfo = uni.cache.get('userInfo') || {};
|
||||
const codeVal = ref(userinfo.wechatAcQrcode || '');
|
||||
console.log('codeVal', codeVal.value);
|
||||
function qrcodeResult(e) {
|
||||
wechatAcQrcode.value = e;
|
||||
wechatAcQrcode.value = e;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user