You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
customAgent/src/components/notice-bar.vue

389 lines
10 KiB

<template>
<div class="notice-box opacity" v-if="dataList.length > 0" :class="elder ? 'elder-wrapper' : ''">
<van-notice-bar
left-icon="volume-o"
mode="link"
:scrollable="false"
:color="fontColor"
:background="bgColor"
@click.stop="selectedPopup($event)"
>
<van-swipe
vertical
class="notice-swipe"
:autoplay="3000"
:scrollable="false"
:show-indicators="false"
@change="onChange"
>
<van-swipe-item class="van-ellipsis" v-for="(item, index) in dataList" :key="index">{{
item.noticeTitle
}}</van-swipe-item>
</van-swipe>
</van-notice-bar>
<!-- popup弹窗内容(全屏) -->
<van-popup
class="notice-popup"
v-model:show="noticeShow"
position="bottom"
:duration="0.3"
:close-on-click-overlay="true"
:style="{ height: '100%', 'background-color': contentBg }"
>
<div class="notice-box-main">
<div class="notice-header">
<van-nav-bar
class="notice-bar-box"
:class="{ 'notice-title': !isWX }"
:title="title"
@click-left="handleHide"
>
<template #left><van-icon name="cross" /></template>
</van-nav-bar>
</div>
<div
style="
margin-top: 10px;
margin-right: 0.4rem;
display: flex;
align-items: center;
justify-content: flex-end;
"
v-if="Tips"
>
<van-checkbox
v-model="checked"
:icon-size="elder ? '20px' : '17px'"
:shape="elder ? 'round' : 'square'"
style="color: #000"
>
<span :class="elder ? 'tip' : ''" style="color: #000; font-weight: 500"
>本周不再提示</span
>
</van-checkbox>
</div>
<div class="notice-content" v-if="content" v-html="content"></div>
</div>
</van-popup>
<!-- popup弹窗内容(半屏) -->
<van-popup
class="notice-popup"
v-model:show="noticeShowban"
overlay-class="noticeBg"
position="center"
:duration="0.6"
:close-on-click-overlay="true"
:style="{ background: 'none' }"
>
<div class="notice-box-main" style="width: 300px">
<div
:class="elder ? 'notice-box-main-icon' : ''"
style="margin-bottom: 10px; text-align: right"
>
<van-icon
:name="elder ? 'cross' : 'close'"
:size="elder ? 16 : 20"
:color="elder ? '#979797' : '#fff'"
@click="handleHide"
/>
</div>
<div
class="notice-content"
style="
background: #fff;
border-radius: 10px;
width: 300px;
height: 300px;
box-sizing: border-box;
padding: 15px;
"
v-if="content"
v-html="content"
></div>
<div
style="margin-top: 10px; display: flex; align-items: center; justify-content: center"
v-if="Tips"
>
<van-checkbox
v-model="checked"
:icon-size="elder ? '20px' : '17px'"
:shape="elder ? 'round' : 'square'"
style="color: #fff"
>
<span :class="elder ? 'tip' : ''" style="color: #fff; font-weight: 500"
>本周不再提示</span
>
</van-checkbox>
</div>
</div>
</van-popup>
</div>
</template>
<script setup>
import { ref, inject, onMounted, nextTick } from 'vue'
import { showToast } from 'vant'
import { Post } from '@/utils/https'
import imageService from '@/utils/imageService'
const props = defineProps({ isWX: { type: Boolean, default: false } })
const emit = defineEmits(['isNoticeHandle'])
const store = inject('appStore', null)
const source = inject('source', ref(''))
const isLostMessage = inject('isLostMessage', ref(null))
const hotUser = inject('hotUser', ref(false))
const elder = inject('elder', false)
const current = ref(0)
const fontColor = ref('#ed6a0c')
const bgColor = ref('#fffbe8')
const contentBg = ref('#fff')
const noticeShow = ref(false)
const noticeShowban = ref(false)
const content = ref('')
const title = ref('')
const dataList = ref([])
const checked = ref(false)
const Tips = ref(false)
function handleHide() {
noticeShow.value = false
noticeShowban.value = false
if (checked.value) localStorage['liccsAds'] = new Date().getTime()
}
async function replaceDomainDev(txt) {
if (window.location.href.indexOf('localhost') !== -1) {
txt = txt.replace('../', '//ssp-dev.trace.com.cn/')
}
const imgRegex = /<img[^>]+src=["']([^"']+)["'][^>]*>/gi
const matches = []
let match
const originalTxt = txt
while ((match = imgRegex.exec(originalTxt)) !== null) {
matches.push({ fullTag: match[0], src: match[1], index: match.index })
}
if (matches.length === 0) return txt
const results = await Promise.all(
matches.map(async (item) => {
try {
let fileKey = item.src
if (fileKey.startsWith('..')) fileKey = fileKey.substring(2)
if (
!fileKey.includes('/') ||
fileKey.startsWith('http://') ||
fileKey.startsWith('https://') ||
fileKey.startsWith('data:')
)
return null
const imageUrl = await imageService.getImageByKey(fileKey, {
useCache: true,
timeout: 10000,
})
return { originalTag: item.fullTag, originalSrc: item.src, newUrl: imageUrl }
} catch {
return null
}
})
)
let processedTxt = txt
results.forEach((result) => {
if (result?.newUrl) {
const escapedSrc = result.originalSrc.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
processedTxt = processedTxt.replace(
new RegExp(`src=["']${escapedSrc}["']`, 'g'),
`src="${result.newUrl}"`
)
}
})
return processedTxt
}
async function selectedPopup() {
Tips.value = false
checked.value = false
const index = current.value
const item = dataList.value[index]
if (item?.noticeDesc) {
content.value = await replaceDomainDev(item.noticeDesc)
if (source.value === '95290000') title.value = item.noticeTitle
if (item.screenType === 1) noticeShow.value = true
else noticeShowban.value = true
}
store?.dispatch?.('userBehavior', { eventType: '9', eventMsg: '点击通知栏' }).catch(console.log)
}
function onChange(index) {
current.value = index
}
async function getDataList() {
Tips.value = true
const param = { source: source.value || source }
Post('message/info', param)
.then(async (res) => {
if (res.code && res.code !== 0) {
emit('isNoticeHandle', false)
showToast(res.msg)
return
}
fontColor.value = res.data.fontColor
bgColor.value = res.data.bgColor
dataList.value = res.data.list || []
if (dataList.value.length > 0) {
emit('isNoticeHandle', true)
if (source.value === '95290000') title.value = dataList.value[0].noticeTitle
const lostMsg = isLostMessage.value || isLostMessage
if ((lostMsg === 2 || lostMsg === 3) && !hotUser.value) {
if (res.data.isPop === 1) {
content.value = await replaceDomainDev(dataList.value[0].noticeDesc)
if (adsIsWeek(dataList.value[0].id)) {
setTimeout(() => {
if (dataList.value[0].screenType === 1) noticeShow.value = true
else noticeShowban.value = true
}, 500)
}
}
}
} else {
emit('isNoticeHandle', false)
}
})
.catch((error) => {
emit('isNoticeHandle', false)
console.log(error)
})
}
function adsIsWeek(id) {
const oldtime = localStorage['liccsAds']
const nowData = new Date(new Date().toLocaleDateString())
let currentDay = nowData.getDay()
if (currentDay === 0) currentDay = 7
const monDayTime = nowData.getTime() - (currentDay - 1) * 24 * 60 * 60 * 1000
const sunDayTime =
nowData.getTime() + (7 - currentDay) * 24 * 60 * 60 * 1000 + 24 * 60 * 60 * 1000 - 1
return !(oldtime && monDayTime <= oldtime && sunDayTime >= oldtime)
}
onMounted(() => {
nextTick(() => getDataList())
})
</script>
<style scoped>
.notice-box {
height: 40px;
overflow: hidden;
text-align: left;
}
.notice-swipe {
height: 40px;
line-height: 40px;
}
.notice-box-main {
position: relative;
display: flex;
flex-direction: column;
align-items: stretch;
overflow-y: visible;
height: 100%;
border-radius: 20px 20px 0 0;
}
.notice-header {
height: 43px;
flex-shrink: 0;
}
.notice-content {
padding: 15px 15px 30px 15px;
font-size: 14px;
flex: 1 1 auto;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
.notice-content :deep(p) {
padding: 6px 0;
}
.notice-content :deep(em),
.notice-content :deep(i) {
font-style: italic;
}
.notice-content :deep(table tr th),
.notice-content :deep(table tr td) {
border: 1px solid #ddd;
padding: 5px;
}
.notice-title {
height: 100%;
background: #0074e1;
}
.notice-bar-box.van-nav-bar :deep(.van-icon) {
font-size: 22px;
line-height: 40px;
color: #1989fa;
}
.notice-bar-box.van-nav-bar :deep(.van-nav-bar__text) {
line-height: 40px;
}
.notice-title.van-nav-bar :deep(.van-icon),
.notice-title.van-nav-bar :deep(.van-nav-bar__text),
.notice-title.van-nav-bar :deep(.van-nav-bar__title) {
color: #fff;
}
.notice-content :deep(h1) {
font-size: 36px !important;
}
.notice-content :deep(h2) {
font-size: 24px !important;
}
.notice-content :deep(h3) {
font-size: 21px !important;
}
.notice-content :deep(h4) {
font-size: 18px !important;
}
.notice-content :deep(h5) {
font-size: 16px !important;
}
.notice-content :deep(h6) {
font-size: 14px !important;
}
.notice-content :deep(h1),
.notice-content :deep(h2),
.notice-content :deep(h3),
.notice-content :deep(h4),
.notice-content :deep(h5),
.notice-content :deep(h6) {
font-weight: bold !important;
}
.notice-content :deep(img) {
width: auto;
max-width: 100%;
}
.notice-content :deep(img:not([class='eleImg'])) {
margin: 20px 0;
}
</style>