新增新版私域引流

This commit is contained in:
gyq
2025-12-15 16:56:37 +08:00
parent 5007c96116
commit 298cd4775b
6 changed files with 787 additions and 572 deletions

View 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>

View File

@@ -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>

View File

@@ -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>