Files
huangguo_landpage/src/pages/mobile2/index.vue
T
2026-09-15 18:00:56 +07:00

896 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="mobile" id="mobile" v-if="showContent">
<div class="bg">
<picture>
<source type="image/webp" :srcset="bg1W" />
<img :src="bg1" alt="" />
</picture>
</div>
<!-- 顶部 -->
<div class="top1">
<div class="left">
<picture>
<source type="image/webp" :srcset="headW" />
<img :src="head" alt="" />
</picture>
</div>
<div class="right" @click.stop="downBtn(1)">
<picture>
<source type="image/webp" :srcset="icon2W" />
<img :src="icon2" alt="download" />
</picture>
</div>
</div>
<div class="content1">
<!-- tab -->
<div class="top3">
<div @click="activeItem = item" class="top3Item" :class="item.id == activeItem.id && 'activeClass'"
v-for="(item, index) in tabList" :key="index">
{{ item.name }}
</div>
</div>
<!-- 图片内容 -->
<div class="top4">
<picture>
<source type="image/webp" :srcset="activeItem.imgW" />
<img :src="activeItem.img" alt="" />
</picture>
</div>
</div>
<div class="top5">
<div class="top5-box">
<picture>
<source type="image/webp" :srcset="icon8W" />
<img :src="icon8" alt="" />
</picture>
<div class="btn-js" @click="downBtn(0)">
<picture>
<source type="image/webp" :srcset="btn2W" />
<img :src="btn2" alt="download" />
</picture>
</div>
<div class="btn-by" @click="downBtn(1)">
<picture>
<source type="image/webp" :srcset="btn5W" />
<img :src="btn5" alt="download" />
</picture>
</div>
</div>
</div>
<!-- <div class="fixdTitle" v-if="!isIos">
<div class="fixdTitleContent">
<div class="logo">
<picture>
<source type="image/webp" :srcset="logoW" />
<img :src="logo" alt="" />
</picture>
</div>
<div class="topFont">
<picture>
<source type="image/webp" :srcset="topFontW" />
<img :src="topFont" alt="" />
</picture>
</div>
</div>
<div class="btn2" @click="downBtn(1)">
<img src="../../assets/image/mebile-index/btn2.png" alt="" />
</div>
</div>
<div class="fixdTitle" v-else>
<div class="fixdTitleContent">
<div class="logo">
<picture>
<source type="image/webp" :srcset="logoW" />
<img :src="logo" alt="" />
</picture>
</div>
<div class="topFont">
<picture>
<source type="image/webp" :srcset="topFontW" />
<img :src="topFont" alt="" />
</picture>
</div>
</div>
<div class="btn2" @click="downBtn(1)">
<img src="../../assets/image/mebile-index/btn2.png" alt="" />
</div>
</div> -->
<div class="rightFixed" :class="{ hide: !isOpen }">
<div class="icon" @click="isOpenFn">
<picture v-if="!isOpen">
<source type="image/webp" :srcset="icon9W" />
<img :src="icon9" alt="" />
</picture>
<!-- ------------++++++ -->
<picture v-else>
<source type="image/webp" :srcset="icon3W" />
<img :src="icon3" alt="" />
</picture>
</div>
<div class="list">
<!-- 官方群组 -->
<div class="item">
<picture>
<source type="image/webp" :srcset="fj_iconW" />
<img :src="fj_icon" alt="" @click="links('https://t.me/bilitv12')" />
</picture>
<span>福利群组</span>
</div>
<!-- 商务渠道 -->
<div class="item">
<picture>
<source type="image/webp" :srcset="qz_iconW" />
<img :src="qz_icon" alt="" @click="links('https://t1t1.com/')" />
</picture>
<span>广告商务</span>
</div>
<!-- 在线客服 -->
<div class="item">
<picture>
<source type="image/webp" :srcset="kf_iconW" />
<img :src="kf_icon" alt="" @click="openCustomerService" />
</picture>
<span>在线客服</span>
</div>
</div>
</div>
<!-- <div class="content">
<div class="mobileTitle">
<picture>
<source type="image/webp" :srcset="mobileTitleW" />
<img :src="mobileTitle" alt="" />
</picture>
</div>
<div class="peopBg">
<div class="peopBgContent">
<picture>
<source type="image/webp" :srcset="peopLabelW" />
<img :src="peopLabel" alt="" />
</picture>
</div>
<picture>
<source type="image/webp" :srcset="peopBgW" />
<img :src="peopBg" alt="" />
</picture>
</div>
<div class="tipBtm">
<div class="tipBtmContent" @click="downBtn(0)">
立即下载
</div>
<div class="bottomText">
<picture>
<source type="image/webp" :srcset="bottomTextW" />
<img :src="bottomText" alt="" />
</picture>
</div>
</div>
</div> -->
<!-- <div
class="iosStore"
v-if="buttonList?.shopIosDownUrl && isIos"
@click="downBtn(0)"
>
<picture>
<source type="image/webp" :srcset="downloadBtnW" />
<img :src="downloadBtn" alt="" />
</picture>
</div> -->
</div>
</template>
<script lang="ts" setup>
import fj_icon from '~/assets/image/mebile-index/fj_icon.png'
import qz_icon from '~/assets/image/mebile-index/qz_icon.png'
import kf_icon from '~/assets/image/mebile-index/kf_icon.png'
import head from '~/assets/image/mebile-index2/head.png'
import headW from '~/assets/image/mebile-index2/head.webp'
import bg1 from '~/assets/image/mebile-index2/bg1.png'
import icon2 from '~/assets/image/mebile-index2/icon2.png'
import icon3 from '~/assets/image/mebile-index2/icon3.png'
import icon5 from '~/assets/image/mebile-index2/icon5.jpeg'
import icon6 from '~/assets/image/mebile-index2/icon6.jpeg'
import icon7 from '~/assets/image/mebile-index2/icon7.jpeg'
import icon8 from '~/assets/image/mebile-index2/icon8.png'
import icon9 from '~/assets/image/mebile-index2/icon9.png'
import btn2 from '~/assets/image/mebile-index/btn2.png'
import btn5 from '~/assets/image/mebile-index/btn5.png'
import btn2W from '~/assets/image/mebile-index/btn2.webp'
import btn5W from '~/assets/image/mebile-index/btn5.webp'
import fj_iconW from '~/assets/image/mebile-index/fj_icon.webp'
import qz_iconW from '~/assets/image/mebile-index/qz_icon.webp'
import kf_iconW from '~/assets/image/mebile-index/kf_icon.webp'
import bg1W from '~/assets/image/mebile-index2/bg1.webp'
import icon2W from '~/assets/image/mebile-index2/icon2.webp'
import icon3W from '~/assets/image/mebile-index2/icon3.webp'
import icon5W from '~/assets/image/mebile-index2/icon5.webp'
import icon6W from '~/assets/image/mebile-index2/icon6.webp'
import icon7W from '~/assets/image/mebile-index2/icon7.webp'
import icon8W from '~/assets/image/mebile-index2/icon8.webp'
import icon9W from '~/assets/image/mebile-index2/icon9.webp'
import { bottonclick, getButtonList, downloadH5, getCustomerServiceUrl } from '~/api/btn'
import type { donwloadParam, channel, H5param } from '~/api/interface'
import { onMounted, ref, reactive, version } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { getSessionTraceId, renewSessionTraceId } from '~/utils/traceId'
import { copyToClipboard } from '~/utils/clipboard'
const props = defineProps({
version: {
type: String,
default() {
return ''
}
}
})
const showContent = ref(false)
const isOpen = ref(true)
const activeTab = ref('热门')
const route = useRoute()
const router = useRouter()
const uDonwloadParam = ref<donwloadParam>({})
function isIOS() {
const userAgent = navigator.userAgent.toLowerCase()
return /iphone|ipad|ipod/.test(userAgent)
}
const isIos = isIOS()
const ip = ref('')
const buttonList = ref()
const onlineServiceLoading = ref(false)
const isOpenFn = () => {
console.log(isOpen.value)
isOpen.value = !isOpen.value
}
const tabList = [
{ name: '热门', id: 0, img: icon5, imgW: icon5W },
{ name: '原创', id: 1, img: icon6, imgW: icon6W },
{ name: '动漫', id: 2, img: icon7, imgW: icon7W },
]
const activeItem = ref(tabList[0])
const getIP = async () => {
try {
const response = await fetch('https://api.ipify.org?format=json')
const data = await response.json()
ip.value = data.ip
} catch (err) {
console.log('获取外部IP失败' + err)
}
}
const getlist = async () => {
try {
const { data } = await getButtonList({
appId: 126,
domain: window.location.protocol + '//' + window.location.host,
channel: JSON.stringify(route.query),
version: props.version,
tid: getSessionTraceId(),
})
buttonList.value = data
} catch (err) {
console.log('获取按钮列表失败' + err)
}
}
onMounted(async () => {
try {
await getIP()
} catch (e) {
console.log(e)
}
await getlist()
showContent.value = true
})
function downBtn(index?: number) {
const trace_id = renewSessionTraceId()
copyToClipboard(JSON.stringify({ ...route.query, trace_id }))
const param = reactive<donwloadParam>({
appId: 126,
ip: ip.value,
channel: JSON.stringify(route.query),
domain: window.location.host || '',
terminal: isIos ? 'ios' : 'android',
version: props.version
})
if (isIos) {
let type = 'iosH5'
// 只有商店包跟轻量版
console.log(buttonList.value.iosDownUrl)
if (buttonList.value?.shopIosDownUrl && index === 0) {
type = 'iosStore'
} else {
type = 'iosH5'
}
downLoadIos(param, type)
} else {
// 下载android应用
downLoadAndroid(param, index)
}
}
//TODO:IOS下载
async function downLoadIos(param: donwloadParam, type: any) {
switch (type) {
case 'iosStore':
param.packageType = 2
try {
window.location.href = buttonList.value.shopIosDownUrl
} catch (error) {
console.log(error)
}
await bottonclick(param)
break
case 'iosH5':
param.packageType = 1
uDonwloadParam.value = param
if (buttonList.value?.iosDownUrl) {
const appVersion = navigator.appVersion
const IOSversion = appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/)
console.log(appVersion, IOSversion)
// if (IOSversion.length > 0 && parseInt(IOSversion[1]) >= 17) {
// alert(
// '当前设备系统版本过高,请手动打开 系统配置->通用->VPN与设备管理,手动安装描述文件'
// )
// router.push({
// path: '/h5-install',
// query: { url: buttonList.value.iosDownUrl }
// })
// setTimeout(() => {
// window.location.href = buttonList.value.iosDownUrl
// }, 300)
// } else {
// router.push({
// path: '/h5-install',
// query: { url: buttonList.value.iosDownUrl }
// })
// setTimeout(() => {
// window.location.href = buttonList.value.iosDownUrl
// }, 300)
// setTimeout(() => {
// window.location.href =
// 'https://df6.gepqjpb.cc/js/embedded.mobileprovision?v=1'
// }, 5000)
// }
alert(
'当前设备系统版本过高,请手动打开 系统配置->通用->VPN与设备管理,手动安装描述文件'
)
router.push({
path: '/h5-install',
query: { url: buttonList.value.iosDownUrl }
})
setTimeout(() => {
window.location.href = buttonList.value.iosDownUrl
}, 300)
} else if (buttonList.value.storeIosDownUrl) {
window.location.href = buttonList.value.storeIosDownUrl
} else {
const paramData: H5param = {
appId: 126,
dc: (uDonwloadParam.value.channel as channel).dc,
pc: (uDonwloadParam.value.channel as channel).pc
}
await downloadH5(paramData).then((res) => {
const file = new File(
[res.data.value as unknown as BlobPart],
'descriptionFile.mobileconfig',
{
type: 'application/x-apple-aspen-config'
}
)
// 方法3:
const objectUrl = URL.createObjectURL(file)
const eleLink = document.createElement('a')
eleLink.href = objectUrl
eleLink.download = 'descriptionFile.mobileconfig'
eleLink.click()
})
}
await bottonclick(param)
break
}
}
const isDcMatch = (value) => {
// ky01-ky100
const kyReg = /^ky(0?[1-9]|[1-9][0-9]|100)$/i;
// TLGG01-TLGG56
const tlggReg = /^TLGG(0?[1-9]|[1-4][0-9]|5[0-6])$/i;
// erra01-erra10
const erraReg = /^erra(0?[1-9]|10)$/i;
return kyReg.test(value) || tlggReg.test(value) || erraReg.test(value);
};
// 特殊渠道号 cctl01-cctl10
const isCctlDc = (dc: any) => {
return /^cctl(0[1-9]|10)$/i.test(dc);
};
//TODOandroid下载
async function downLoadAndroid(param: donwloadParam, index: number) {
try {
if(isCctlDc(route.query.dc)){
window.location.href = 'https://mdapkkk.zwk9.com/blxv_260202_2.0.1+19.apk';
return
}
// 特殊渠道号处理
if(isDcMatch(route.query.dc) && buttonList.value.hkAndroidDownUrl){
window.location.href = buttonList.value.hkAndroidDownUrl;
}else{
// 有渠道链接就走渠道链接
if(index === 0 && buttonList.value.channelApkAndDownUrl){
window.location.href = buttonList.value.channelApkAndDownUrl;
}else{
if (index === 0 && buttonList.value.androidDownUrl) {
window.location.href = buttonList.value.androidDownUrl;
} else {
window.location.href = buttonList.value.storeAndroidDownUrl;
}
}
}
await bottonclick(param);
} catch (error) {
console.log(error)
}
}
function links(url: string) {
window.location.href = url
}
function getDeviceType(userAgent: string) {
return /android/i.test(userAgent) ? 'Android' : 'iOS'
}
function getSystemType(userAgent: string) {
return /android/i.test(userAgent) ? 'Android' : 'iOS'
}
function getSystemVersion(userAgent: string) {
const androidVersion = userAgent.match(/Android\s([\d.]+)/i)
if (androidVersion?.[1]) {
return androidVersion[1]
}
const iosVersion = userAgent.match(/OS (\d+[_\d]*)/i)
if (iosVersion?.[1]) {
return iosVersion[1].replace(/_/g, '.')
}
return ''
}
async function openCustomerService() {
if (onlineServiceLoading.value) {
return
}
onlineServiceLoading.value = true
try {
const userAgent = navigator.userAgent || ''
const res = await getCustomerServiceUrl({
uid: String(route.query.uid || getSessionTraceId()),
appId: 126,
deviceType: getDeviceType(userAgent),
systemType: getSystemType(userAgent),
systemVersion: getSystemVersion(userAgent)
})
const serviceUrl = res && res.data
if (serviceUrl) {
window.location.href = serviceUrl as unknown as string
return
}
} catch (error) {
console.log('get customer service url error:', error)
} finally {
onlineServiceLoading.value = false
}
}
</script>
<style lang="scss" scoped>
.mobile {
width: 7.5rem;
height: 100%;
overflow: hidden;
position: relative;
.bg {
width: 7.5rem;
height: auto;
position: fixed;
top: 0;
left: 0;
z-index: -1;
img {
width: 100%;
height: auto;
}
}
.top1 {
width: 6.86rem;
position: fixed;
left: 0.32rem;
top: 0.2rem;
display: flex;
align-items: center;
justify-content: space-between;
.left {
width: 100%;
img {
width: 100%;
}
}
.right {
width: 1.7rem;
position: absolute;
right: 10px;
img {
width: 100%;
}
}
}
.content1 {
position: fixed;
left: 0.32rem;
top: 1.7rem;
width: 6.86rem;
.top2 {
height: 4.44rem;
width: 100%;
img {
width: 100%;
height: 100%;
}
}
.top3 {
width: 100%;
height: 0.6rem;
border-radius: 8px;
margin-top: 0.3rem;
background: #303030;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
.top3Item {
height: 0.6rem;
border-radius: 8px;
line-height: 0.6rem;
text-align: center;
font-size: 0.32rem;
}
.activeClass {
background: #FF3F7C;
}
}
.top4 {
margin-top: 0.3rem;
width: 100%;
// height: 400px;
height: calc(100dvh - 4.38rem);
overflow-y: auto;
img {
width: 100%;
}
}
}
.top5 {
width: 7.5rem;
height: 1.14rem;
position: fixed;
padding: 0 12px;
left: 0;
bottom: 10px;
z-index: 10;
img {
width: 100%;
height: 100%;
}
}
.bglog {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.9);
color: #fff;
text-align: center;
line-height: 5rem;
z-index: 10;
.copy {
width: 5rem;
height: 1rem;
margin: 0 auto;
line-height: 1rem;
}
}
.iosStore {
position: fixed;
bottom: 5rem;
left: 0;
right: 0;
z-index: 10;
img {
height: 0.66rem;
width: 5.5rem;
}
}
.fixdTitle {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 10;
padding: 0 0.32rem;
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
height: 1.2rem;
background: url('~/assets/image/mebile-index/downloadBtn.png') no-repeat;
background-size: 100%;
.fixdTitleContent {
display: flex;
align-items: center;
justify-content: center;
gap: 0.2rem;
.logo {
img {
width: 0.6rem;
height: 0.6rem;
}
}
.topFont {
img {
width: 2.86rem;
height: 0.6rem;
}
}
}
.btn2 {
display: flex;
align-items: center;
img {
height: 0.72rem;
}
}
.btn1-txt {
width: 100%;
height: 100%;
background: linear-gradient(90.63deg, #003cc9 43.99%, #058be5 97.99%);
border-radius: 0.32rem;
padding: 0.04rem 0.16rem;
font-size: 0.28rem;
font-weight: 600;
span {
color: rgb(255, 221, 56);
}
}
}
.rightFixed {
position: fixed;
transition: transform 0.5s;
top: 4.2rem;
right: 0.22rem;
z-index: 100;
&.hide {
transform: translateX(1.38rem);
}
.icon {
position: absolute;
height: 0.56rem;
width: 0.32rem;
top: 50%;
transform: translateY(-50%);
right: 1.16rem;
img {
width: 100%;
}
}
.list {
width: 1.16rem;
height: 4.04rem;
border-radius: 1rem;
border: 0.01rem solid #fff;
background: rgba(45, 44, 47, 0.7);
display: flex;
flex-direction: column;
justify-content: space-around;
.item {
display: flex;
flex-wrap: wrap;
justify-content: center;
span {
font-size: 0.21rem;
}
img {
width: 0.5rem;
}
}
}
}
.content {
position: relative;
z-index: 9;
text-align: center;
height: 100%;
padding-bottom: 2.3rem;
overflow: auto;
padding-top: 1.6rem;
display: flex;
flex-direction: column;
align-items: center;
.mz {
width: 6.86rem;
}
.downloadBtn {
align-items: center;
display: flex;
justify-content: space-around;
width: 100%;
padding: 0 0.5rem;
img {
width: 2.8rem;
}
}
.mobileTitle {
img {
width: 6.86rem;
}
}
.tipBtm {
position: fixed;
bottom: 0rem;
left: 50%;
transform: translateX(-50%);
width: 6.54rem;
margin: 0.4rem auto;
border-radius: 0.16rem;
.tipBtmContent {
background: linear-gradient(90deg, #EA5B80 0%, #E60C49 100%);
width: 3.16rem;
height: 0.8rem;
margin: 0.4rem auto;
border-radius: 0.52rem;
padding-top: 6.17px;
padding-right: 9.25px;
padding-bottom: 6.17px;
padding-left: 9.25px;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.32rem;
font-weight: 640;
color: #fff;
cursor: pointer;
}
}
.peopBg {
position: relative;
img {
width: 100%;
}
}
.bottomText {
img {
width: 6.54rem;
}
}
.peopBgContent {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
margin: 0 auto;
img {
width: 6.54rem;
}
}
}
}
.fade-in-enter-active,
.fade-in-leave-active {
transition: opacity 0.2s ease-in-out;
}
.fade-in-enter-from,
.fade-in-leave-to {
opacity: 0;
}
@supports (-webkit-touch-callout: none) {
.page {
height: -webkit-fill-available;
}
}
.btn-js {
position: absolute;
right: 2rem;
top: 0.3rem;
width: 1.6rem;
height: 30px;
img {
width: 100%;
height: 100%;
}
}
.btn-by {
position: absolute;
right: 10px;
top: 0.3rem;
width: 1.6rem;
height: 30px;
img {
width: 100%;
height: 100%;
}
}
.top5-box {
position: relative;
width: 100%;
height: 100%;
}
</style>