初始化

This commit is contained in:
谢宇宁
2026-09-15 15:46:36 +07:00
commit da39ab9a2a
125 changed files with 25508 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "app",
components: {},
created() {}
};
</script>
<style>
@media screen and (min-width: 620px) {
/* pc */
html,
body,
#app {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
max-height: 100vh;
overflow: hidden !important;
background-color: black;
}
}
@media screen and (max-width: 620px) {
/* 手机 */
html,
body,
#app {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
max-height: 100vh;
overflow: auto !important;
background-color: black;
}
}
* {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
</style>
+14
View File
@@ -0,0 +1,14 @@
/*
* @Author: 王枫叶
* @Date: 2020-07-20 20:48:00
* @LastEditors: 王枫叶
* @LastEditTime: 2020-10-05 17:23:15
*/
import request from "@/utils/request";
export default data =>
request({
method: "post",
url: "/plm/okn/ijb/vl0gpuBNWklJwcv1",
data
});
+8
View File
@@ -0,0 +1,8 @@
import request from "@/utils/request";
export default data =>
request({
method: "post",
url: "/plm/okn/ijb/fsdfrererdfdf",
data,
});
+8
View File
@@ -0,0 +1,8 @@
import request from "@/utils/request";
export default params =>
request({
method: "get",
url: "https://api.ipify.org/?format=json",
params
});
+14
View File
@@ -0,0 +1,14 @@
/*
* @Author: 王枫叶
* @Date: 2020-08-10 22:55:30
* @LastEditors: 王枫叶
* @LastEditTime: 2020-10-28 22:55:14
*/
import request from "@/utils/request";
export default data =>
request({
method: "post",
url: "/plm/okn/ijb/nuS0EDXSczKgf3Xh",
data
});
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

+129
View File
@@ -0,0 +1,129 @@
/* http://meyerweb.com/eric/tools/css/reset/ */
/* v1.0 | 20080212 */
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
font,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 100%;
vertical-align: baseline;
background: transparent;
}
html{font-size: 625%;}
body {
line-height: 1;
}
ol,
ul {
list-style: none;
}
blockquote,
q {
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: "";
content: none;
}
:focus {
outline: 0;
}
ins {
text-decoration: none;
}
del {
text-decoration: line-through;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
* {
box-sizing: border-box;
font-family: "sans-serif";
-webkit-touch-callout: none; /*系统默认菜单被禁用*/
-webkit-user-select: none; /*webkit浏览器*/
-khtml-user-select: none; /*早期浏览器*/
-moz-user-select: none; /*火狐*/
-ms-user-select: none; /*IE10*/
user-select: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-tap-highlight-color: transparent;
}
input,
textarea {
-webkit-user-select: auto; /*webkit浏览器*/
margin: 0px;
padding: 0px;
outline: none;
}
+11
View File
@@ -0,0 +1,11 @@
/*
Write your variables here. All available variables can be
found in element-ui/packages/theme-chalk/src/common/var.scss.
For example, to overwrite the theme color:
*/
$--color-primary: teal;
/* icon font path, required */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";
+49
View File
@@ -0,0 +1,49 @@
/*
* @Author: 王枫叶
* @Date: 2020-07-20 20:48:00
* @LastEditors: 王枫叶
* @LastEditTime: 2020-10-23 13:54:17
*/
import "@/assets/style/reset.css";
import "@/plugins/flexible.js";
import "@/plugins/scale_no.js";
import "./plugins/element.js";
import Vue from "vue";
import VueClipboard from "vue-clipboard2";
import VueTouch from "vue-touch-hotfix";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import VueAnalytics from "vue-analytics";
import VueAwesomeSwiper from "vue-awesome-swiper";
import { Loading } from "vant";
import { Popup } from "vant";
import "vant/lib/popup/style";
import Vant from "vant";
import "vant/lib/index.css";
Vue.use(Vant);
Vue.use(Loading);
Vue.use(Popup);
Vue.use(VueAwesomeSwiper);
Vue.use(VueTouch, {
name: "v-touch"
}); //触摸插件
// 谷歌统计页面追踪
Vue.use(VueAnalytics, {
id: "UA-165940626-2",
router,
autoTracking: {
pageviewOnLoad: false
}
});
Vue.use(VueClipboard);
Vue.config.productionTip = false;
new Vue({
router,
store,
render: h => h(App),
data: {},
created() {}
}).$mount("#app");
+8
View File
@@ -0,0 +1,8 @@
// eslint-disable-next-line no-unused-vars
import { Button, Tooltip, Message, Dialog } from "element-ui";
import Vue from "vue";
import "../element-variables.scss";
Vue.use(Tooltip);
Vue.use(Button);
Vue.use(Dialog);
+110
View File
@@ -0,0 +1,110 @@
!(function() {
const a =
"@charset \"utf-8\";html{color:#000;background:#fff;overflow-y:scroll;-webkit-text-size-adjust:none;-ms-text-size-adjust:none}html *{outline:0;-webkit-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}html,body{font-family:sans-serif}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td,hr,button,article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{margin:0;padding:0}input,select,textarea{font-size:100%}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}abbr,acronym{border:0;font-variant:normal}del{text-decoration:line-through}address,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:500}ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:500}q:before,q:after{content:''}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}a:hover{text-decoration:underline}ins,a{text-decoration:none}";
const b = document.createElement("style");
if ((document.getElementsByTagName("head")[0].appendChild(b), b.styleSheet))
b.styleSheet.disabled || (b.styleSheet.cssText = a);
else
try {
b.innerHTML = a;
} catch (c) {
b.textContent = a;
}
})();
!(function(a, b) {
function c() {
let b = f.getBoundingClientRect().width;
b / i > 540 && (b = 540 * i);
const c = b / 10;
(f.style.fontSize = c + "px"), (k.rem = a.rem = c);
}
let d;
const e = a.document;
var f = e.documentElement;
let g = e.querySelector('meta[name="viewport"]');
const h = e.querySelector('meta[name="flexible"]');
var i = 0;
let j = 0;
var k = b.flexible || (b.flexible = {});
if (g) {
const l = g.getAttribute("content").match(/initial-scale=([\d.]+)/);
l && ((j = parseFloat(l[1])), (i = parseInt(1 / j)));
} else if (h) {
const m = h.getAttribute("content");
if (m) {
const n = m.match(/initial-dpr=([\d.]+)/);
const o = m.match(/maximum-dpr=([\d.]+)/);
n && ((i = parseFloat(n[1])), (j = parseFloat((1 / i).toFixed(2)))),
o && ((i = parseFloat(o[1])), (j = parseFloat((1 / i).toFixed(2))));
}
}
if (!i && !j) {
const p =
(a.navigator.appVersion.match(/android/gi),
a.navigator.appVersion.match(/iphone/gi));
const q = a.devicePixelRatio;
(i = p
? q >= 3 && (!i || i >= 3)
? 3
: q >= 2 && (!i || i >= 2)
? 2
: 1
: 1),
(j = 1 / i);
}
if ((f.setAttribute("data-dpr", i), !g))
if (
((g = e.createElement("meta")),
g.setAttribute("name", "viewport"),
g.setAttribute(
"content",
"initial-scale=" +
j +
", maximum-scale=" +
j +
", minimum-scale=" +
j +
", user-scalable=no"
),
f.firstElementChild)
)
f.firstElementChild.appendChild(g);
else {
const r = e.createElement("div");
r.appendChild(g), e.write(r.innerHTML);
}
a.addEventListener(
"resize",
function() {
clearTimeout(d), (d = setTimeout(c, 300));
},
!1
),
a.addEventListener(
"pageshow",
function(a) {
a.persisted && (clearTimeout(d), (d = setTimeout(c, 300)));
},
!1
),
e.readyState === "complete"
? (e.body.style.fontSize = 12 * i + "px")
: e.addEventListener(
"DOMContentLoaded",
function() {
e.body.style.fontSize = 12 * i + "px";
},
!1
),
c(),
(k.dpr = a.dpr = i),
(k.refreshRem = c),
(k.rem2px = function(a) {
let b = parseFloat(a) * this.rem;
return typeof a === "string" && a.match(/rem$/) && (b += "px"), b;
}),
(k.px2rem = function(a) {
let b = parseFloat(a) / this.rem;
return typeof a === "string" && a.match(/px$/) && (b += "rem"), b;
});
})(window, window.lib || (window.lib = {}));
+56
View File
@@ -0,0 +1,56 @@
// postcss-px2rem配置之----对html的font-size进行动态设置
window.onload = function() {
document.addEventListener("touchstart", function(event) {
if (event.touches.length > 1) {
event.preventDefault();
}
});
var lastTouchEnd = 0;
document.addEventListener(
"touchend",
function(event) {
var now = new Date().getTime();
if (now - lastTouchEnd <= 300) {
event.preventDefault();
}
lastTouchEnd = now;
},
false
);
document.addEventListener("gesturestart", function(event) {
event.preventDefault();
});
};
(function(win) {
var tid;
function refreshRem() {
// let designSize = 720; // 设计图尺寸
let designSize = 1920; // 设计图尺寸
let html = document.documentElement;
let wW = html.clientWidth; // 窗口宽度
let rem = (wW * 100) / designSize;
document.documentElement.style.fontSize = rem + "px";
}
if (!navigator.userAgent.match(/mobile/i)) {
win.addEventListener(
"resize",
function() {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
},
false
);
win.addEventListener(
"pageshow",
function(e) {
if (e.persisted) {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}
},
false
);
refreshRem();
}
})(window);
+28
View File
@@ -0,0 +1,28 @@
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/land/index.vue";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: Home,
meta: {
title: ""
}
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
router.beforeEach((to, from, next) => {
document.title = to.meta.title;
next();
});
export default router;
+11
View File
@@ -0,0 +1,11 @@
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
modules: {}
});
+187
View File
@@ -0,0 +1,187 @@
const APPID = "JHA-204";
export function getTraceId() {
let str = sessionStorage.getItem(`${APPID}_traceId`);
if (str) return str;
str =
Math.random()
.toString()
.substr(2, 36) + Date.now().toString(36);
sessionStorage.setItem(`${APPID}_traceId`, str);
return str;
}
function getAndroidBrand(model = "") {
const m = model.toLowerCase();
if (!m) return "";
if (/^(sm-|gt-|sch-|sgh-|shv-)/.test(m)) return "Samsung";
if (/^(mix|mi |mi-|mi\d|redmi|m\d{1,2}[a-z]|poco|2\d{3}[a-z0-9]{4,})/.test(m)) return "Xiaomi";
if (/^(pixel)/.test(m)) return "Google";
if (/^(huawei|huawe|ana-|bla-|ele-|lya-|noh-|tas-|vog-|aln-|bra-|clt-|dub-|eml-|frl-|hma-|ine-|jef-|jkm-|jny-|lio-|mar-|mrd-|nam-|oce-|pct-|pot-|sea-|snk-|stk-|tet-|wlz-|yal-)/.test(m)) return "HUAWEI";
if (/^(honor|ali-|bkl-|yal-|nth-|peg-|any-|are-|bkk-|cdy-|cph-|dnn-|fne-|hry-|jsn-|lld-|mov-|rne-|rea-|tfy-|tnr-|crr-|ksa-)/.test(m)) return "HONOR";
if (/^(vivo|v\d|pd\d)/.test(m)) return "vivo";
if (/^(oppo|cph|peh|pht|pgc|pgd|pgf|a\d{3})/.test(m)) return "OPPO";
if (/^(oneplus|hd19|kb20|le21|gm19|cph2\d|de2\d|ne2\d|in2\d|kb2\d|le2\d)/.test(m)) return "OnePlus";
if (/^(realme|rmx)/.test(m)) return "realme";
if (/^(moto|motorola|xt\d)/.test(m)) return "Motorola";
if (/^(iqoo|i2\d|v\d{4}[a-z])/.test(m)) return "iQOO";
if (/^(nokia|ta-\d+)/.test(m)) return "Nokia";
if (/^(sony|xq-|g8\d|xperia)/.test(m)) return "Sony";
if (/^(asus|zs\d|ai\d|rog)/.test(m)) return "ASUS";
if (/^(meizu|m\d+ note)/.test(m)) return "Meizu";
if (/^(nubia|nx\d)/.test(m)) return "nubia";
if (/^(zte|zte-)/.test(m)) return "ZTE";
if (/^(lenovo|tb-|l3\d)/.test(m)) return "Lenovo";
return "";
}
function extractMobileModel(ua = "") {
const sectionMatch = ua.match(
/\(([^)]*(Android|HarmonyOS|OpenHarmony)[^)]*)\)/i
);
if (!sectionMatch || !sectionMatch[1]) return "";
const candidates = sectionMatch[1]
.split(";")
.map(item => item.trim())
.map(item => item.replace(/\s+Build\/.*$/i, "").trim())
.filter(
item =>
item &&
!/^linux$/i.test(item) &&
!/^u$/i.test(item) &&
!/^wv$/i.test(item) &&
!/^android[\d.\s]*$/i.test(item) &&
!/^[a-z]{2}([-_][a-z]{2})?$/i.test(item)
);
return candidates.length ? candidates[candidates.length - 1] : "";
}
function getBrandFromUA(model = "", ua = "") {
const brand = getAndroidBrand(model);
if (brand) return brand;
if (/honor/i.test(ua)) return "HONOR";
if (/(huawei|huaweibrowser)/i.test(ua)) return "HUAWEI";
if (/\bxiaomi\b|miuibrowser/i.test(ua)) return "Xiaomi";
if (/\boppo\b|oppobrowser|heytap/i.test(ua)) return "OPPO";
if (/\bvivo\b|vivobrowser/i.test(ua)) return "vivo";
if (/\bsamsungbrowser\b/i.test(ua)) return "Samsung";
if (/\boneplus\b/i.test(ua)) return "OnePlus";
if (/\brealme\b/i.test(ua)) return "realme";
if (/\bmeizu\b/i.test(ua)) return "Meizu";
if (/\blenovo\b/i.test(ua)) return "Lenovo";
return "";
}
function parseDeviceInfo(ua = "") {
if (!ua) return { device_brand: "", device_model: "" };
if (/iPhone/i.test(ua)) return { device_brand: "Apple", device_model: "iPhone" };
if (/iPad/i.test(ua)) return { device_brand: "Apple", device_model: "iPad" };
if (/iPod/i.test(ua)) return { device_brand: "Apple", device_model: "iPod" };
if (/Android/i.test(ua) || /(harmonyos|openharmony|hongmeng|hmos)/i.test(ua)) {
const model = extractMobileModel(ua);
return { device_brand: getBrandFromUA(model, ua), device_model: model };
}
if (/Macintosh|Mac OS X/i.test(ua)) return { device_brand: "Apple", device_model: "Mac" };
if (/Windows/i.test(ua)) return { device_brand: "Microsoft", device_model: "Windows PC" };
if (/Linux/i.test(ua)) return { device_brand: "Linux", device_model: "Linux PC" };
return { device_brand: "", device_model: "" };
}
export function getSystemType(ua = navigator.userAgent || "") {
if (
/Android/i.test(ua) ||
/(harmonyos|openharmony|hongmeng|hmos)/i.test(ua)
) {
return "android";
}
if (/iPhone|iPad|iPod/i.test(ua)) {
return "ios";
}
return "pc";
}
export function getSystemVersion(ua = navigator.userAgent || "") {
const iosMatch = ua.match(/OS (\d+(?:[_\d]+)?)/i);
if (iosMatch && iosMatch[1]) {
return iosMatch[1].replace(/_/g, ".");
}
const androidMatch = ua.match(/Android\s+([\d.]+)/i);
if (androidMatch && androidMatch[1]) {
return androidMatch[1];
}
return "";
}
export function getDeviceType(ua = navigator.userAgent || "") {
if (/iPhone/i.test(ua)) return "iPhone";
if (/iPad/i.test(ua)) return "iPad";
if (/iPod/i.test(ua)) return "iPod";
if (
/Android/i.test(ua) ||
/(harmonyos|openharmony|hongmeng|hmos)/i.test(ua)
) {
return extractMobileModel(ua);
}
const { device_model } = parseDeviceInfo(ua);
return device_model;
}
let _cachedDeviceInfo = null;
function getDeviceInfo() {
if (!_cachedDeviceInfo) {
_cachedDeviceInfo = parseDeviceInfo(navigator.userAgent || "");
}
return _cachedDeviceInfo;
}
/**
* 上报落地页展示
* vm: 组件 this,必须传(读取 vm.version)
* opts: { landing_page_id }
*/
export function landingPageView(vm, opts = {}) {
const { device_brand, device_model } = getDeviceInfo();
const data = {
event: "landing_page_view",
landing_page_id: opts.landing_page_id || `${APPID}_${vm.version}`,
device_brand,
device_model,
};
return window.tracker(data);
}
/**
* 上报落地页点击
* vm: 组件 this
* opts: { landing_page_id, tab_key, tab_name, click_coordinates_x, click_coordinates_y,
* click_x_percent, click_y_percent, screen_width, screen_height, trace_id }
*/
export function landingPageClick(vm, opts = {}) {
const { device_brand, device_model } = getDeviceInfo();
const screenW = window.screen ? window.screen.width : opts.screen_width || 0;
const screenH = window.screen
? window.screen.height
: opts.screen_height || 0;
const data = {
event: "landing_page_click",
landing_page_id: opts.landing_page_id || `${APPID}_${vm.version}`,
tab_key: opts.tab_key || "",
tab_name: opts.tab_name || "",
click_coordinates_x: opts.click_coordinates_x || 0,
click_coordinates_y: opts.click_coordinates_y || 0,
click_x_percent:
typeof opts.click_x_percent === "number"
? opts.click_x_percent
: Math.round(((opts.click_coordinates_x || 0) / (screenW || 1)) * 100),
click_y_percent:
typeof opts.click_y_percent === "number"
? opts.click_y_percent
: Math.round(((opts.click_coordinates_y || 0) / (screenH || 1)) * 100),
screen_width: screenW,
screen_height: screenH,
trace_id: opts.trace_id || getTraceId(),
device_brand,
device_model,
};
return window.tracker(data);
}
+16
View File
@@ -0,0 +1,16 @@
import hasLocateURLIsYsLive from "./hasLocateURLIsYsLive";
const params = [{ url: "ys.live", query: { dc: "SUNQUAN" } }]; //过滤的url
/**
* 匹配集合内的url 匹配到的则返回对应的query对象,此对象会替换url里参数
*/
export default () => {
for (const iterator of params) {
/**
* 本地URL是否是ys.live
*/
if (hasLocateURLIsYsLive(new RegExp(iterator.url))) {
return JSON.stringify(iterator.query);
}
}
return false;
};
+3
View File
@@ -0,0 +1,3 @@
export default url => {
return url.test(window.location.href);
};
+36
View File
@@ -0,0 +1,36 @@
import axios from "axios";
const sericve = axios.create({
// baseURL: JSON.parse(process.env.VUE_APP_BASE_HOSTS)[0],
baseURL: "/",
timeout: 15000
});
sericve.interceptors.request.use(
function(config) {
return config;
},
function(error) {
return Promise.reject(error);
}
);
sericve.interceptors.response.use(
function(response) {
// 状态码200
if (response.data.code === 200 || response.status === 200) {
return response;
} else {
this.$message.success({
type: "error",
message: "服务器错误"
});
}
},
function(error) {
return Promise.reject(error);
}
);
export default sericve;
+37
View File
@@ -0,0 +1,37 @@
/*
* title: 判断设备类型
* @Author: 王枫叶
* @Date: 2020-10-13 17:47:47
* @LastEditors: 王枫叶
* @LastEditTime: 2020-11-12 11:58:23
*/
export default function(context) {
const userAgent = process.server
? context.req.headers["user-agent"]
: navigator.userAgent;
return (function() {
const ua = userAgent;
const isUc = /(?:UCBrowser)/.test(ua);
const isWindowsPhone = /(?:Windows Phone)/.test(ua) && !isUc;
const isSymbian = /(?:SymbianOS)/.test(ua) || isWindowsPhone;
const isAndroid = /(?:Android)/.test(ua) || isUc;
const isFireFox = /(?:Firefox)/.test(ua);
const isOPPO = /(?:OPPO)/.test(ua);
const isTablet =
/(?:iPad|PlayBook)/.test(ua) ||
(isAndroid && !/(?:Mobile)/.test(ua)) ||
(isFireFox && /(?:Tablet)/.test(ua));
const isPhone = /(?:iPhone)/.test(ua) && !isTablet;
const isWx = /MicroMessenger/.test(ua);
const isPc = !isPhone && !isAndroid && !isSymbian;
return {
userAgent,
isOPPO,
isTablet,
isPhone,
isAndroid,
isPc,
isWx
};
})();
}
@@ -0,0 +1,657 @@
<template>
<van-overlay :show="show" :lock-scroll="false" z-index="999" class="iosGuideOverlay">
<div class="iosGuidePanel" @click.stop @touchmove.stop>
<div class="iosGuideNav">
<div class="backBtn" @click="close">返回</div>
</div>
<div class="iosGuideScroll">
<div class="brandHeader">
<span class="brandName">91porn</span>
<span class="brandSub">轻量版安装引导</span>
</div>
<!-- STEP.1 -->
<div class="stepBlock">
<div class="stepHeader">
<div class="headerRow">
<span class="stepTitle">STEP.1</span>
<span class="stepTag">步骤一</span>
</div>
<div class="stepDeco">
<img class="stepDecoImg" :src="stepDecoImg" alt="" />
</div>
</div>
<div class="stepCard">
<div class="iosDialog">
<div class="dialogBody">
此网站正尝试下载一个配置描述文件。您要允许吗?
</div>
<div class="dialogDivider"></div>
<div class="dialogActions">
<div class="dialogAction">忽略</div>
<div class="dialogActionDivider"></div>
<div class="dialogAction dialogActionBold">允许</div>
</div>
</div>
<p class="stepTip">点击安装91porn轻量版出现安装证书</p>
</div>
</div>
<!-- STEP.2 -->
<div class="stepBlock">
<div class="stepHeader">
<div class="headerRow">
<span class="stepTitle">STEP.2</span>
<span class="stepTag">步骤二</span>
</div>
<div class="stepDeco">
<img class="stepDecoImg" :src="stepDecoImg" alt="" />
</div>
</div>
<div class="stepCard">
<div class="iosScreen">
<div class="iosNav">
<span class="iosNavSide">取消</span>
<span class="iosNavTitle">安装描述文件</span>
<span class="iosNavSide iosNavBold">安装</span>
</div>
<div class="iosList">
<div class="profileHeader">
<div class="appIconPlaceholder">
<img class="cogIcon" :src="cogImg" alt="" />
</div>
<div class="profileInfo">
<p class="profileName">91porn</p>
<p class="profileDesc">亚洲最火成人网站</p>
</div>
</div>
<div class="iosListDivider"></div>
<div class="profileMeta">
<div class="metaRow">
<span class="metaLabel">签署者</span>
<div class="metaValue">
<p>Apple Distribution: Cheng Wang (H3YVBP27D4)</p>
<p class="metaWarn">未验证</p>
</div>
</div>
<div class="metaRow">
<span class="metaLabel">描述</span>
<span class="metaText">91porn</span>
</div>
<div class="metaRow">
<span class="metaLabel">包含</span>
<span class="metaText">Web Clip</span>
</div>
</div>
<div class="iosListDivider"></div>
<div class="moreDetail">
<span>更多详细信息</span>
<span class="moreArrow">›</span>
</div>
</div>
<div class="iosFooterAlert">移除已下载的描述文件</div>
</div>
<p class="stepTip">
点击右上角 <span class="tipHighlight">「安装」</span> 进行下一步
</p>
</div>
</div>
<!-- STEP.3 -->
<div class="stepBlock">
<div class="stepHeader">
<div class="headerRow">
<span class="stepTitle">STEP.3</span>
<span class="stepTag">步骤三</span>
</div>
<div class="stepDeco">
<img class="stepDecoImg" :src="stepDecoImg" alt="" />
</div>
</div>
<div class="stepCard">
<div class="iosScreen">
<div class="iosNav">
<span class="iosNavSide">取消</span>
<span class="iosNavTitle">同意</span>
<span class="iosNavSide iosNavBold">下一步</span>
</div>
<div class="consentBody">
<p class="consentFrom">来自 "91porn" 的消息</p>
<p class="consentText">91porn</p>
</div>
</div>
<p class="stepTip">
点击右上角 <span class="tipHighlight">「下一步」</span>
</p>
</div>
</div>
<!-- STEP.4 -->
<div class="stepBlock">
<div class="stepHeader">
<div class="headerRow">
<span class="stepTitle">STEP.4</span>
<span class="stepTag">步骤四</span>
</div>
<div class="stepDeco">
<img class="stepDecoImg" :src="stepDecoImg" alt="" />
</div>
</div>
<div class="stepCard">
<div class="iosScreen">
<div class="iosNav">
<span class="iosNavSide">取消</span>
<span class="iosNavTitle">警告</span>
<span class="iosNavSide iosNavBold">安装</span>
</div>
<div class="warningBody">
<p class="warningTitle">未验证的描述文件</p>
<p class="warningText">不能验证 "91porn" 的真实性</p>
</div>
</div>
<p class="stepTip stepTipMulti">
点击右上角 <span class="tipHighlight">「安装」</span> 进行下一步<br />
并点击 <span class="tipDone">「完成」</span>
</p>
</div>
</div>
<!-- STEP.5 -->
<div class="stepBlock">
<div class="stepHeader">
<div class="headerRow">
<span class="stepTitle">STEP.5</span>
<span class="stepTag">步骤五</span>
</div>
<div class="stepDeco">
<img class="stepDecoImg" :src="stepDecoImg" alt="" />
</div>
</div>
<div class="stepCard stepCardLast">
<img class="finishIcon" :src="appIconImg" alt="91porn" />
<div class="finishText">
<p class="finishTitle">回到桌面</p>
<p class="stepTip">
重新打开 <span class="tipBrand">[91porn]</span> 即可开始使用
</p>
</div>
</div>
</div>
</div>
</div>
</van-overlay>
</template>
<script>
export default {
name: "IosInstallGuide",
props: {
show: {
type: Boolean,
default: false,
},
},
data() {
return {
stepDecoImg: require("@/assets/images/iosGuide/step-deco.png"),
cogImg: require("@/assets/images/iosGuide/cog.png"),
appIconImg: require("@/assets/images/iosGuide/app-icon.webp"),
};
},
methods: {
close() {
this.$emit("close");
},
},
};
</script>
<style lang="scss" scoped>
.iosGuideOverlay {
display: flex;
align-items: stretch;
justify-content: center;
}
.iosGuidePanel {
width: 100%;
height: 100%;
max-height: 100%;
background: #040910;
display: flex;
flex-direction: column;
overflow: hidden;
position: relative;
}
.iosGuideNav {
flex-shrink: 0;
padding: 20px 20px 10px;
background: #040910;
z-index: 2;
}
.backBtn {
display: inline-flex;
align-items: center;
padding: 4px 12px;
border-radius: 6px;
border: 1px solid rgba(255, 255, 255, 0.15);
background: rgba(255, 255, 255, 0.1);
color: #fff;
font-size: 12px;
font-weight: 500;
line-height: normal;
}
.iosGuideScroll {
flex: 1;
min-height: 0;
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain;
padding: 20px 20px 100px;
display: flex;
flex-direction: column;
gap: 32px;
}
.brandHeader {
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
color: #fff;
font-size: 22px;
line-height: normal;
padding-bottom: 12px;
white-space: nowrap;
.brandName {
font-weight: 800;
}
.brandSub {
font-weight: 700;
}
}
.stepBlock {
display: flex;
flex-direction: column;
gap: 16px;
width: 100%;
}
.stepHeader {
display: flex;
flex-direction: column;
gap: 6px;
}
.headerRow {
display: flex;
align-items: center;
gap: 8px;
}
.stepTitle {
color: #fff;
font-size: 22px;
font-weight: 900;
line-height: normal;
}
.stepTag {
display: inline-flex;
align-items: center;
padding: 2px 8px;
border-radius: 4px;
background: linear-gradient(90deg, #f0b952 0%, #c6822b 100%);
color: #000;
font-size: 11px;
font-weight: 700;
line-height: normal;
}
.stepDeco {
display: flex;
align-items: center;
width: 100%;
}
.stepDecoImg {
display: block;
height: 12px;
width: auto;
}
.stepCard {
width: 100%;
box-sizing: border-box;
padding: 16px;
border-radius: 16px;
border: 1px dashed #192430;
background: #0c121a;
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
.stepCardLast {
gap: 20px;
}
.stepTip {
width: 100%;
margin: 0;
color: #8699a6;
font-size: 14px;
font-weight: 500;
line-height: 1.4;
text-align: center;
}
.stepTipMulti {
line-height: 1.5;
}
.tipHighlight {
color: #2f80ed;
font-weight: 700;
}
.tipDone {
color: #00e676;
font-weight: 700;
}
.tipBrand {
color: #ff366e;
font-weight: 700;
}
.iosDialog {
width: 280px;
border-radius: 14px;
border: 1px solid #3f3f3f;
background: rgba(30, 30, 30, 0.9);
overflow: hidden;
display: flex;
flex-direction: column;
.dialogBody {
padding: 20px 16px;
color: #fff;
font-size: 15px;
font-weight: 600;
line-height: 1.35;
text-align: center;
}
.dialogDivider {
height: 1px;
background: rgba(84, 84, 88, 0.4);
}
.dialogActions {
display: flex;
height: 44px;
}
.dialogAction {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
color: #2f80ed;
font-size: 16px;
font-weight: 400;
}
.dialogActionBold {
font-weight: 600;
}
.dialogActionDivider {
width: 1px;
height: 100%;
background: rgba(84, 84, 88, 0.4);
}
}
.iosScreen {
width: 280px;
border-radius: 12px;
border: 1px solid #1c1c1e;
background: #000;
overflow: hidden;
display: flex;
flex-direction: column;
}
.iosNav {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 12px;
background: #1c1c1e;
font-size: 14px;
line-height: normal;
white-space: nowrap;
.iosNavSide {
color: #2f80ed;
font-weight: 400;
}
.iosNavBold {
font-weight: 600;
}
.iosNavTitle {
color: #fff;
font-weight: 600;
}
}
.iosList {
display: flex;
flex-direction: column;
gap: 12px;
padding: 12px;
}
.profileHeader {
display: flex;
align-items: center;
gap: 12px;
}
.appIconPlaceholder {
width: 40px;
height: 40px;
border-radius: 8px;
background: #2c2c2e;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.cogIcon {
width: 24px;
height: 24px;
display: block;
object-fit: contain;
}
.profileInfo {
flex: 1;
min-width: 0;
.profileName {
margin: 0;
color: #fff;
font-size: 14px;
font-weight: 600;
line-height: normal;
}
.profileDesc {
margin: 2px 0 0;
color: #8699a6;
font-size: 11px;
font-weight: 400;
line-height: normal;
}
}
.iosListDivider {
width: 100%;
height: 1px;
background: #38383a;
}
.profileMeta {
display: flex;
flex-direction: column;
gap: 6px;
width: 100%;
font-size: 11px;
line-height: normal;
}
.metaRow {
display: flex;
align-items: flex-start;
gap: 6px;
width: 100%;
}
.metaLabel {
width: 50px;
flex-shrink: 0;
color: #8699a6;
}
.metaValue {
flex: 1;
min-width: 0;
p {
margin: 0;
color: #fff;
word-break: break-all;
}
.metaWarn {
margin-top: 2px;
color: #ff3b30;
font-weight: 600;
}
}
.metaText {
color: #fff;
}
.moreDetail {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
color: #fff;
font-size: 12px;
line-height: normal;
.moreArrow {
color: #8699a6;
font-size: 14px;
}
}
.iosFooterAlert {
padding: 12px;
background: #1c1c1e;
color: #ff3b30;
font-size: 12px;
line-height: normal;
text-align: center;
}
.consentBody {
display: flex;
flex-direction: column;
gap: 8px;
padding: 16px;
width: 100%;
box-sizing: border-box;
.consentFrom {
margin: 0;
color: #8699a6;
font-size: 11px;
line-height: normal;
}
.consentText {
margin: 0;
color: #fff;
font-size: 13px;
line-height: normal;
}
}
.warningBody {
display: flex;
flex-direction: column;
gap: 8px;
padding: 16px;
width: 100%;
box-sizing: border-box;
.warningTitle {
margin: 0;
color: #8699a6;
font-size: 12px;
font-weight: 600;
line-height: normal;
}
.warningText {
margin: 0;
color: #fff;
font-size: 13px;
line-height: normal;
}
}
.finishIcon {
width: 100px;
height: 100px;
border-radius: 18.75px;
border: 1.563px solid #d73d2d;
object-fit: cover;
display: block;
box-sizing: border-box;
}
.finishText {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
.finishTitle {
margin: 0;
color: #fff;
font-size: 15px;
font-weight: 600;
line-height: normal;
}
}
</style>
+576
View File
@@ -0,0 +1,576 @@
<template>
<div class="mobilePage" @click="pageClick">
<div class="logo"></div>
<swiper :options="swiperOptions">
<swiper-slide v-for="(item, index) in bglist" :key="index">
<div :class="['wrapper', `bg_${item.type}`]">
<div class="figure"></div>
<div class="title-bg"></div>
</div>
</swiper-slide>
<!-- <div class="swiper-pagination" slot="pagination"></div> -->
</swiper>
<div class="floatingBox" v-if="configs && configs.length">
<div class="floatingItem" v-if="cTg" @click="jumpUrl(cTg)">
<div class="telegram"></div>
</div>
<div class="floatingItem" v-if="cPotato" @click="jumpUrl(cPotato)">
<div class="potato"></div>
</div>
<div class="floatingItem" v-if="cBusiness" @click="jumpUrl(cBusiness)">
<div class="business"></div>
</div>
<div class="floatingItem" v-if="cChannel" @click="jumpUrl(cChannel)">
<div class="channel"></div>
</div>
<div class="floatingItem" @click.stop="openOnlineService($event)">
<div class="customer"></div>
</div>
</div>
<div
class="downloadIosAppStore"
@click.stop="getApkInfo('shopIos', $event)"
v-if="switchData.shopIosDownUrl && showIosTip"
>
<div class="close-btn" @click.stop="showIosTip = false"></div>
</div>
<!-- 有ios商店包 -->
<div v-if="os.isPhone" class="bottomBox">
<template v-if="switchData.shopIosDownUrl">
<div class="down-btn" @click.stop="getApkInfo('shopIos', $event)">
立即下载
</div>
<div class="down-btn-spare" @click.stop="getApkInfo(true, $event)">
备用下载
</div>
</template>
<template v-else>
<div class="down-btn" @click.stop="getApkInfo(true, $event)">
立即下载
</div>
</template>
</div>
<div v-else class="bottomBox">
<div class="down-btn" @click.stop="getApkInfo(true, $event)">立即下载</div>
<div
class="down-btn down-btn-spare"
v-if="switchData.androidDownUrl && switchData.channelApkAndDownUrl"
@click.stop="getApkInfo('androidSpare', $event)"
>
备用下载
</div>
</div>
<div class="safari-tip" v-if="os.isPhone">*苹果手机请使用自带Safari浏览器</div>
<!-- 安卓提示框 -->
<van-overlay :show="androidPromptShow" z-index="999" class="androidOverlay">
<div>
<div class="overlayContent" @click.stop>
<div class="confirmBtnBox" @click="androidPromptShow = false"></div>
</div>
</div>
</van-overlay>
<!-- 苹果安装引导 -->
<ios-install-guide :show="iosPromptShow" @close="iosPromptShow = false" />
<van-popup v-model="showTip" class="downTip">
<div class="downTipTitle">温馨提示</div>
<div class="downTipContent">
请使用Safari浏览器进行下载
</div>
<div class="url">{{ currUrl }}</div>
<div class="downTipConfirm" @click.stop="doCopy">复制链接</div>
</van-popup>
</div>
</template>
<script>
import getCustomerServiceUrl from "@/api/getCustomerServiceUrl";
import {
getDeviceType,
getSystemType,
getSystemVersion,
getTraceId,
landingPageClick,
} from "@/utils/eventTracker";
import iosInstallGuide from "./iosInstallGuide";
const APPID = 204;
export default {
components: { iosInstallGuide },
props: ["os", "configs", "switchData"],
data() {
return {
androidPromptShow: false,
iosPromptShow: false,
showTip: false,
currUrl: window.location.href,
cTg: "",
cPotato: "",
cBusiness: "",
cChannel: "",
onlineServiceLoading: false,
recordParam: "",
shopIosDownUrl: "",
showIosTip: true,
swiperOptions: {
direction: "vertical",
loop: true,
autoplay: {
delay: 4000,
disableOnInteraction: false,
},
// pagination: {
// el: ".swiper-pagination",
// clickable: true,
// },
scrollbar: {
el: ".swiper-scrollbar",
hide: true,
},
},
bglist: [
{
type: "01",
},
{
type: "02",
},
],
version: "B",
};
},
watch: {
configs(configs) {
configs.forEach((item) => {
if (item.configType === "tg_group") {
this.cTg = item.link;
} else if (item.configType === "potato_group") {
this.cPotato = item.link;
} else if (item.configType === "sw_cooperate") {
this.cBusiness = item.link;
} else if (item.configType === "qd_cooperate") {
this.cChannel = item.link;
}
});
return configs;
},
},
mounted() {
let ua = this.os.userAgent.toLowerCase();
let isSafari =
ua.indexOf("safari") !== -1 &&
ua.indexOf("browser") === -1 &&
ua.indexOf("android") === -1;
if (!isSafari && this.os.isPhone) {
this.showTip = true;
}
},
methods: {
pageClick(event) {
let click_coordinates_x = event.clientX;
let click_coordinates_y = event.clientY;
landingPageClick(this, {
click_coordinates_x,
click_coordinates_y,
});
},
doCopy() {
this.$copyText(this.currUrl).then(
() => {
console.log("复制成功");
this.showTip = false;
},
() => {
console.log("复制失败");
},
);
},
async showInstallTutorial(type) {
if (type == "ios") {
this.iosPromptShow = true;
} else {
this.androidPromptShow = true;
}
},
async getApkInfo(flag, event) {
let type = "android";
if (this.os.isPhone) {
type = "ios";
if (flag === "shopIos") {
type = "shopIos";
}
} else {
type = "android";
}
if (flag == "androidSpare") {
type = "androidSpare";
}
if (flag && flag !== "shopIos") {
await this.showInstallTutorial(type);
}
this.$emit("recordClick", type);
setTimeout(() => {
this.$emit("getApkInfo", type);
}, 500);
let click_coordinates_x = event.clientX;
let click_coordinates_y = event.clientY;
landingPageClick(this, {
tab_name: "下载按钮",
tab_key: "download",
click_coordinates_x,
click_coordinates_y,
});
},
openMobileCompatibleUrl(url) {
if (!url) {
return;
}
window.location.href = url;
},
async openOnlineService(event) {
const click_coordinates_x = event.clientX;
const click_coordinates_y = event.clientY;
const userAgent = this.os.userAgent || "";
landingPageClick(this, {
tab_name: "在线客服",
tab_key: "customer_service",
click_coordinates_x,
click_coordinates_y,
});
if (this.onlineServiceLoading) {
return;
}
this.onlineServiceLoading = true;
try {
const res = await getCustomerServiceUrl({
uid: this.$route.query.uid || getTraceId(),
appId: APPID,
deviceType: getDeviceType(userAgent),
systemType: getSystemType(userAgent),
systemVersion: getSystemVersion(userAgent),
});
const serviceUrl = res && res.data && res.data.data;
if (serviceUrl) {
this.openMobileCompatibleUrl(serviceUrl);
return;
}
if (this.cChannel) {
this.openMobileCompatibleUrl(this.cChannel);
return;
}
} catch (error) {
if (this.cChannel) {
this.openMobileCompatibleUrl(this.cChannel);
return;
}
console.log("get customer service url error:", error);
} finally {
this.onlineServiceLoading = false;
}
},
jumpUrl(url) {
window.open(url);
},
},
};
</script>
<style lang="scss" scoped>
.mobilePage {
height: 100%;
width: 100%;
.logo {
background: url("../../../assets/images/mobile2/logo.webp") no-repeat;
background-size: 100% 100%;
width: 161px;
height: 58px;
position: absolute;
left: 24px;
top: 63px;
z-index: 100;
}
::v-deep .swiper-container {
width: 100%;
height: 100%;
.swiper-wrapper {
width: 100%;
height: 100%;
}
.swiper-pagination {
right: 10px;
top: 25%;
width: 30px;
height: 124px;
z-index: 11;
position: absolute;
display: flex;
flex-direction: column;
.swiper-pagination-bullet {
width: 12px;
height: 12px;
display: inline-block;
border-radius: 50px;
background: rgba(255, 255, 255, 0.55);
// box-shadow: 0px 0px 5px 0px #fff;
margin-bottom: 10px;
}
.swiper-pagination-bullet-active {
border-radius: 14px;
background: #fff;
height: 73px;
// box-shadow: 0px 0px 8px 0px #fff;
}
}
}
.wrapper {
width: 100%;
height: 100%;
position: relative;
.title-bg {
height: 30%;
aspect-ratio: 142/103;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 14%;
z-index: 20;
}
.figure {
aspect-ratio: 27/64;
height: 70%;
position: absolute;
right: 0px;
bottom: 0px;
z-index: 10;
}
}
.bg_01 {
background: url("../../../assets/images/mobile2/bg01.webp") no-repeat;
background-size: 100% 100%;
.title-bg {
background: url("../../../assets/images/mobile2/title01.webp") no-repeat;
background-size: 100% 100%;
}
.figure {
background: url("../../../assets/images/mobile2/figure01.webp") no-repeat;
background-size: 100% 100%;
}
}
.bg_02 {
background: url("../../../assets/images/mobile2/bg02.webp") no-repeat;
background-size: 100% 100%;
.title-bg {
background: url("../../../assets/images/mobile2/title02.webp") no-repeat;
background-size: 100% 100%;
aspect-ratio: 25/18;
}
.figure {
background: url("../../../assets/images/mobile2/figure02.webp") no-repeat;
background-size: 100% 100%;
aspect-ratio: 97/242;
bottom: 4%;
}
}
.floatingBox {
border-radius: 18px 0 0 18px;
background: rgba(0, 0, 0, 0.6);
width: 36px;
position: fixed;
right: 0;
top: 230px;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
padding: 12px 6px;
z-index: 99;
.floatingItem {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
}
.telegram {
height: 40px;
width: 24px;
background: url("./../../../assets/images/mobile2/telegram.png") no-repeat;
background-size: 100% 100%;
}
.potato {
height: 40px;
width: 24px;
background: url("./../../../assets/images/mobile2/potato.png") no-repeat;
background-size: 100% 100%;
}
.business {
height: 40px;
width: 24px;
background: url("./../../../assets/images/mobile2/business.png") no-repeat;
background-size: 100% 100%;
}
.channel {
height: 40px;
width: 24px;
background: url("./../../../assets/images/mobile2/channel.png") no-repeat;
background-size: 100% 100%;
}
.customer {
height: 40px;
width: 24px;
background: url("./../../../assets/images/mobile2/customer.png") no-repeat;
background-size: 100% 100%;
}
}
.bottomBox {
width: 100%;
position: fixed;
bottom: 6%;
left: 0;
z-index: 101;
display: flex;
align-items: center;
justify-content: center;
.down-btn {
border-radius: 20px;
background: #ff1a80;
width: 144px;
height: 39px;
color: #fff;
font-family: "PingFang MO";
font-size: 16px;
font-weight: 500;
display: flex;
align-items: center;
justify-content: center;
}
.down-btn-spare {
margin-left: 6px;
border-radius: 20px;
background: #ff1a80;
width: 144px;
height: 39px;
color: #fff;
font-family: "PingFang MO";
font-size: 16px;
font-weight: 500;
display: flex;
align-items: center;
justify-content: center;
}
}
.safari-tip {
color: #fff;
text-align: center;
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: normal;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 32px;
}
.downloadIosAppStore {
height: 36px;
width: 284px;
background: url("./../../../assets/images/mobile1/downloadIosAppStore.gif")
no-repeat;
background-size: 100% 100%;
position: fixed;
left: 0;
bottom: 210px;
z-index: 998;
.close-btn {
height: 20px;
width: 20px;
background: url("./../../../assets/images/mobile1/close.png") no-repeat;
background-size: 100% 100%;
position: absolute;
right: -10px;
top: -10px;
}
}
.androidDownBox {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
.androidOverlay {
display: flex;
align-items: center;
justify-content: center;
.overlayContent {
width: 297px;
height: 441px;
background: url("./../../../assets/images/mobile2/android_tip.webp")
no-repeat;
background-size: 100% 100%;
border-radius: 12px;
padding-top: 380px;
.confirmBtnBox {
height: 36px;
width: 140px;
border-radius: 40px;
margin: 0 auto;
}
}
}
}
.downTip {
border-radius: 10px;
padding: 18px;
box-sizing: border-box;
text-align: center;
.downTipTitle {
font-size: 18px;
margin-bottom: 34px;
}
.downTipContent {
white-space: nowrap;
font-size: 15px;
}
.url {
font-size: 15px;
margin-top: 16px;
text-align: left;
}
.downTipConfirm {
font-size: 15px;
width: 160px;
height: 30px;
border-radius: 40px;
margin: 32px auto 0;
color: #fff;
background: #5b92ee;
display: flex;
align-items: center;
justify-content: center;
}
}
</style>
+682
View File
@@ -0,0 +1,682 @@
<template>
<div class="mobilePage" @click="pageClick">
<div class="headerBox">
<div
class="logo"
@click.stop="
getApkInfo(
os.isPhone && switchData.shopIosDownUrl ? 'shopIos' : true,
$event,
)
"
></div>
<div class="headerLinks" v-if="configs && configs.length">
<div class="linkItem" v-if="cTg" @click.stop="jumpUrl(cTg)">
<div class="telegram"></div>
<span>TG</span>
</div>
<div class="linkItem" v-if="cPotato" @click.stop="jumpUrl(cPotato)">
<div class="potato"></div>
<span>土豆</span>
</div>
<div class="linkItem" v-if="cBusiness" @click.stop="jumpUrl(cBusiness)">
<div class="business"></div>
<span>商务</span>
</div>
<div class="linkItem" v-if="cChannel" @click.stop="jumpUrl(cChannel)">
<div class="channel"></div>
<span>渠道</span>
</div>
<div class="linkItem" @click.stop="openOnlineService($event)">
<div class="customer"></div>
<span>客服</span>
</div>
</div>
</div>
<div class="banner-box">
<div
class="banner"
@click.stop="
getApkInfo(
os.isPhone && switchData.shopIosDownUrl ? 'shopIos' : true,
$event,
)
"
></div>
</div>
<div class="ctaBar" @click.stop="getApkInfo(true, $event)">
<div class="ctaText">百万影片 海量成人短剧 免费观看 &gt;&gt;</div>
<div class="ctaBtn" :class="{ ctaBtnIos: os.isPhone }"></div>
</div>
<div
class="main"
@click.stop="
getApkInfo(
os.isPhone && switchData.shopIosDownUrl ? 'shopIos' : true,
$event,
)
"
>
<div class="sectionBox">
<div
class="section"
v-for="item in tabs"
:key="item.value"
:class="{ sectionActive: tabActive === item.value }"
@click="tabActive = item.value"
>
{{ item.label }}
</div>
</div>
<div class="contentBox"></div>
</div>
<div class="bottomBox">
<div
class="downBtnRow"
:class="{ hasShop: os.isPhone && switchData.shopIosDownUrl }"
>
<div
class="downBtn"
v-if="!os.isPhone"
@click.stop="onLiteDownload($event)"
>
<img
class="downIcon"
:src="
os.isPhone
? require('@/assets/images/mobileA/ios-icon.png')
: require('@/assets/images/mobileA/android-icon.png')
"
alt=""
/>
<span>{{ os.isPhone ? "轻量版" : "高速下载" }}</span>
</div>
<div
class="downBtn"
v-if="os.isPhone && switchData.shopIosDownUrl"
@click.stop="getApkInfo('shopIos', $event)"
>
<img
class="downIcon"
:src="require('@/assets/images/mobileA/ios-icon.png')"
alt=""
/>
<span>商店包</span>
</div>
</div>
<div class="downTipText" v-if="!os.isPhone">
安卓安装包爆毒解决方案*下载后开启飞行模式安装*
</div>
<div class="downTipText" v-if="os.isPhone">
*苹果手机请使用自带Safari浏览器
</div>
</div>
<div
class="downloadIosAppStore"
@click.stop="getApkInfo('shopIos', $event)"
v-if="os.isPhone && switchData.shopIosDownUrl && showIosTip"
>
<div class="close-btn" @click.stop="showIosTip = false"></div>
</div>
<!-- 安卓提示框 -->
<van-overlay :show="androidPromptShow" z-index="999" class="androidOverlay">
<div>
<div class="overlayContent" @click.stop>
<div class="confirmBtnBox" @click="androidPromptShow = false"></div>
</div>
</div>
</van-overlay>
<!-- 苹果安装引导 -->
<ios-install-guide :show="iosPromptShow" @close="iosPromptShow = false" />
<van-popup v-model="showTip" class="downTip">
<div class="downTipTitle">温馨提示</div>
<div class="downTipContent">
请使用Safari浏览器进行下载
</div>
<div class="url">{{ currUrl }}</div>
<div class="downTipConfirm" @click.stop="doCopy">复制链接</div>
</van-popup>
</div>
</template>
<script>
import getCustomerServiceUrl from "@/api/getCustomerServiceUrl";
import {
getDeviceType,
getSystemType,
getSystemVersion,
getTraceId,
landingPageClick,
} from "@/utils/eventTracker";
import iosInstallGuide from "./iosInstallGuide";
const APPID = 204;
export default {
components: { iosInstallGuide },
props: ["os", "configs", "switchData"],
data() {
return {
androidPromptShow: false,
iosPromptShow: false,
showTip: false,
currUrl: window.location.href,
tabActive: "hot",
tabs: [
{
label: "热门",
value: "hot",
},
{
label: "短剧",
value: "short_film",
},
{
label: "精选",
value: "featured",
},
{
label: "国产",
value: "domestic",
},
{
label: "乱伦",
value: "darkweb",
},
{
label: "动漫",
value: "cartoon",
},
],
cTg: "",
cPotato: "",
cBusiness: "",
cChannel: "",
onlineServiceLoading: false,
recordParam: "",
shopIosDownUrl: "", // 商店包链接
showIosTip: true,
version: "A",
};
},
watch: {
configs(configs) {
configs.forEach((item) => {
if (item.configType === "tg_group") {
this.cTg = item.link;
} else if (item.configType === "potato_group") {
this.cPotato = item.link;
} else if (item.configType === "sw_cooperate") {
this.cBusiness = item.link;
} else if (item.configType === "qd_cooperate") {
this.cChannel = item.link;
}
});
return configs;
},
},
methods: {
pageClick(event) {
let click_coordinates_x = event.clientX;
let click_coordinates_y = event.clientY;
let tab_name =
this.tabs.find((item) => item.value == this.tabActive)?.label || "";
landingPageClick(this, {
tab_key: this.tabActive,
tab_name,
click_coordinates_x,
click_coordinates_y,
});
},
checkIsSafari() {
const ua = (this.os.userAgent || "").toLowerCase();
return (
ua.indexOf("safari") !== -1 &&
ua.indexOf("browser") === -1 &&
ua.indexOf("android") === -1
);
},
onLiteDownload(event) {
if (this.os.isPhone && !this.checkIsSafari()) {
this.showTip = true;
landingPageClick(this, {
tab_name: "下载按钮",
tab_key: "download",
click_coordinates_x: event.clientX,
click_coordinates_y: event.clientY,
});
return;
}
this.getApkInfo(true, event);
},
// 剪贴板
doCopy() {
this.$copyText(this.currUrl).then(
() => {
console.log("复制成功");
this.showTip = false;
},
() => {
console.log("复制失败");
},
);
},
async showInstallTutorial(type) {
if (type == "ios") {
this.iosPromptShow = true;
} else {
this.androidPromptShow = true;
}
},
async getApkInfo(flag, event) {
let type = "android";
if (this.os.isPhone) {
type = "ios";
if (flag === "shopIos") {
type = "shopIos";
}
} else {
type = "android";
}
if (flag == "androidSpare") {
type = "androidSpare";
}
if (flag && flag !== "shopIos") {
await this.showInstallTutorial(type);
}
this.$emit("recordClick", type);
setTimeout(() => {
this.$emit("getApkInfo", type);
}, 500);
// 上报点击(下载按钮)
let click_coordinates_x = event.clientX;
let click_coordinates_y = event.clientY;
landingPageClick(this, {
tab_name: "下载按钮",
tab_key: "download",
click_coordinates_x,
click_coordinates_y,
});
},
openMobileCompatibleUrl(url) {
if (!url) {
return;
}
window.location.href = url;
},
async openOnlineService(event) {
const click_coordinates_x = event.clientX;
const click_coordinates_y = event.clientY;
const userAgent = this.os.userAgent || "";
landingPageClick(this, {
tab_name: "在线客服",
tab_key: "customer_service",
click_coordinates_x,
click_coordinates_y,
});
if (this.onlineServiceLoading) {
return;
}
this.onlineServiceLoading = true;
try {
const res = await getCustomerServiceUrl({
uid: this.$route.query.uid || getTraceId(),
appId: APPID,
deviceType: getDeviceType(userAgent),
systemType: getSystemType(userAgent),
systemVersion: getSystemVersion(userAgent),
});
const serviceUrl = res && res.data && res.data.data;
if (serviceUrl) {
this.openMobileCompatibleUrl(serviceUrl);
return;
}
if (this.cChannel) {
this.openMobileCompatibleUrl(this.cChannel);
return;
}
} catch (error) {
if (this.cChannel) {
this.openMobileCompatibleUrl(this.cChannel);
return;
}
console.log("get customer service url error:", error);
} finally {
this.onlineServiceLoading = false;
}
},
jumpUrl(url) {
window.open(url);
},
},
};
</script>
<style lang="scss" scoped>
.mobilePage {
height: 100%;
width: 100%;
background-color: #000;
overflow-y: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
.headerBox {
display: flex;
align-items: center;
justify-content: space-between;
height: 70px;
padding: 0 16px;
box-sizing: border-box;
background: #000 url("./../../../assets/images/mobileA/header-bg.webp")
no-repeat center top;
background-size: 100% 100%;
position: relative;
z-index: 1;
width: 100%;
.logo {
width: 140px;
height: 47px;
background: url("./../../../assets/images/mobileA/logo.png") no-repeat;
background-size: 100% 100%;
flex-shrink: 0;
position: relative;
z-index: 1;
}
.headerLinks {
display: flex;
align-items: flex-start;
gap: 17px;
position: relative;
z-index: 1;
.linkItem {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
width: 24px;
span {
color: #fff;
font-size: 10px;
letter-spacing: 0.8px;
line-height: 1;
white-space: nowrap;
}
.telegram,
.potato,
.business,
.channel,
.customer {
width: 24px;
height: 24px;
background-repeat: no-repeat;
background-size: 100% 100%;
}
.telegram {
background-image: url("./../../../assets/images/mobileA/telegram.png");
}
.potato {
background-image: url("./../../../assets/images/mobileA/potato.png");
}
.business {
background-image: url("./../../../assets/images/mobileA/business.png");
}
.channel {
background-image: url("./../../../assets/images/mobileA/channel.png");
}
.customer {
background-image: url("./../../../assets/images/mobileA/customer.png");
}
}
}
}
.banner-box {
margin: 0 auto;
position: relative;
width: 100%;
height: 164px;
}
.banner {
width: 375px;
height: 164px;
background: url("./../../../assets/images/mobileA/banner.webp") no-repeat;
background-size: 100% 100%;
position: absolute;
top: -5px;
left: 50%;
transform: translateX(-50%);
z-index: 0;
}
.ctaBar {
display: flex;
align-items: center;
height: 35px;
padding: 0 16px;
background: linear-gradient(90deg, #fab341 0%, #ff6f2e 100%);
box-sizing: border-box;
position: relative;
.ctaText {
color: #000;
font-size: 15px;
font-weight: 500;
line-height: 23px;
white-space: nowrap;
}
.ctaBtn {
width: 77px;
height: 21px;
margin-left: 20px;
background: url("./../../../assets/images/mobileA/cta-btn.png") no-repeat;
background-size: 100% 100%;
flex-shrink: 0;
}
.ctaBtnIos {
width: 77px;
height: 21px;
margin-left: 0;
background: url("./../../../assets/images/mobileA/cta-btn-ios.png")
no-repeat;
background-size: 100% 100%;
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 12px;
}
}
.main {
padding-bottom: calc(88px + env(safe-area-inset-bottom));
box-sizing: border-box;
.sectionBox {
display: flex;
align-items: center;
justify-content: space-between;
width: 343px;
height: 37px;
margin: 10px auto 0;
padding: 0 5px;
border-radius: 9px;
background: #2d2c2f;
box-sizing: border-box;
.section {
min-width: 49px;
height: 29px;
border-radius: 6px;
color: #fab341;
font-size: 12px;
display: flex;
align-items: center;
justify-content: center;
white-space: nowrap;
}
.sectionActive {
background: #ff6f2e;
color: #fff;
}
}
.contentBox {
width: 343px;
height: 940px;
margin: 8px auto 0;
background: url("./../../../assets/images/mobileA/content.webp") no-repeat;
background-size: 100% 100%;
}
}
.bottomBox {
width: 100%;
min-height: 56px;
margin: 0;
padding: 12px 0 calc(12px + env(safe-area-inset-bottom));
box-sizing: border-box;
background: linear-gradient(90deg, #fab641 0%, #ff6f2e 100%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8px;
position: fixed;
left: 0;
bottom: 0;
z-index: 100;
.downBtnRow {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
&.hasShop {
width: 100%;
padding: 0 53px;
box-sizing: border-box;
// justify-content: space-between;
}
}
.downBtn {
width: 130px;
height: 32px;
border-radius: 5px;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
flex-shrink: 0;
.downIcon {
width: 16px;
height: 16px;
flex-shrink: 0;
display: block;
object-fit: contain;
}
span {
color: #000;
font-size: 12px;
font-weight: 700;
line-height: 1;
}
}
.downTipText {
color: #000;
font-size: 11px;
line-height: 17px;
text-align: center;
white-space: nowrap;
}
}
.downloadIosAppStore {
height: 36px;
width: 284px;
background: url("./../../../assets/images/mobileB/downloadIosAppStore.gif")
no-repeat;
background-size: 100% 100%;
position: fixed;
left: 0;
bottom: 99px;
z-index: 998;
.close-btn {
height: 20px;
width: 20px;
background: url("./../../../assets/images/mobileB/close.png") no-repeat;
background-size: 100% 100%;
position: absolute;
right: -10px;
top: -10px;
}
}
.androidOverlay {
display: flex;
align-items: center;
justify-content: center;
.overlayContent {
width: 297px;
height: 441px;
background: url("./../../../assets/images/mobileA/android_tip.webp")
no-repeat;
background-size: 100% 100%;
border-radius: 12px;
padding-top: 380px;
.confirmBtnBox {
height: 36px;
width: 140px;
border-radius: 40px;
margin: 0 auto;
}
}
}
}
.downTip {
border-radius: 10px;
padding: 18px;
box-sizing: border-box;
text-align: center;
.downTipTitle {
font-size: 18px;
margin-bottom: 34px;
}
.downTipContent {
white-space: nowrap;
font-size: 15px;
}
.url {
font-size: 15px;
margin-top: 16px;
text-align: left;
}
.downTipConfirm {
font-size: 15px;
width: 160px;
height: 30px;
border-radius: 40px;
margin: 32px auto 0;
color: #fff;
background: #5b92ee;
display: flex;
align-items: center;
justify-content: center;
}
}
</style>
+532
View File
@@ -0,0 +1,532 @@
<template>
<div class="mobilePage" @click="pageClick">
<div
class="headerBox"
@click.stop="
getApkInfo(true, $event)
"
>
<div class="header-bg"></div>
</div>
<van-tabs
v-model="tabActive"
title-active-color="#ffffff"
title-inactive-color="#ffffff"
animated
:lazy-render="false"
class="vantTabs"
>
<van-tab
:title="item.label"
:name="item.value"
v-for="item in tabs"
:key="item.value"
>
<div class="main" @click.stop="getApkInfo(os.isPhone && switchData.shopIosDownUrl ? 'shopIos' : true, $event)">
<div class="content0" v-if="item.value == 'short_film'"></div>
<div class="content1" v-if="item.value == 'hot'"></div>
<div class="content2" v-if="item.value == 'darkweb'"></div>
<div class="content3" v-if="item.value == 'cartoon'"></div>
</div>
</van-tab>
</van-tabs>
<div class="floatingBox" v-if="configs && configs.length">
<div class="telegram" v-if="cTg" @click="jumpUrl(cTg)"></div>
<div class="potato" v-if="cPotato" @click="jumpUrl(cPotato)"></div>
<div class="business" v-if="cBusiness" @click="jumpUrl(cBusiness)"></div>
<div class="channel" v-if="cChannel" @click="jumpUrl(cChannel)"></div>
<div class="customer" @click.stop="openOnlineService($event)"></div>
</div>
<div
class="downloadIosAppStore"
@click.stop="getApkInfo('shopIos', $event)"
v-if="os.isPhone && switchData.shopIosDownUrl && showIosTip"
>
<div class="close-btn" @click.stop="showIosTip = false"></div>
</div>
<!-- 有ios商店包 -->
<!-- <div
v-if="os.isPhone && switchData.shopIosDownUrl"
@click.stop="getApkInfo('shopIos', $event)"
class="bottomBox shopIos"
>
<div class="spareBtn" @click.stop="getApkInfo(true, $event)"></div>
</div> -->
<div class="bottomBox" @click.stop="getApkInfo(os.isPhone && switchData.shopIosDownUrl ? 'shopIos' : true, $event)">
<div class="down-btn">立即下载</div>
<div class="down-btn down-btn-spare" v-if="switchData.androidDownUrl && switchData.channelApkAndDownUrl"
@click.stop="getApkInfo('androidSpare', $event)">备用下载</div>
</div>
<!-- 安卓提示框 -->
<van-overlay :show="androidPromptShow" z-index="999" class="androidOverlay">
<div>
<div class="overlayContent" @click.stop>
<div class="confirmBtnBox" @click="androidPromptShow = false"></div>
</div>
</div>
</van-overlay>
<!-- 苹果安装引导 -->
<ios-install-guide :show="iosPromptShow" @close="iosPromptShow = false" />
<van-popup v-model="showTip" class="downTip">
<div class="downTipTitle">温馨提示</div>
<div class="downTipContent">
请使用Safari浏览器进行下载
</div>
<div class="url">{{ currUrl }}</div>
<div class="downTipConfirm" @click.stop="doCopy">复制链接</div>
</van-popup>
</div>
</template>
<script>
import getCustomerServiceUrl from "@/api/getCustomerServiceUrl";
import {
getDeviceType,
getSystemType,
getSystemVersion,
getTraceId,
landingPageClick,
} from "@/utils/eventTracker";
import iosInstallGuide from "./iosInstallGuide";
const APPID = 204;
export default {
components: { iosInstallGuide },
props: ["os", "configs", "switchData"],
data() {
return {
androidPromptShow: false,
iosPromptShow: false,
showTip: false,
currUrl: window.location.href,
tabActive: "short_film",
tabs: [
{
label: "短剧",
value: "short_film",
},
{
label: "热门",
value: "hot",
},
{
label: "乱伦",
value: "darkweb",
},
{
label: "动漫",
value: "cartoon",
},
],
cTg: "",
cPotato: "",
cBusiness: "",
cChannel: "",
onlineServiceLoading: false,
recordParam: "",
shopIosDownUrl: "", // 商店包链接
showIosTip: true,
version: "B",
};
},
watch: {
configs(configs) {
configs.forEach((item) => {
if (item.configType === "tg_group") {
this.cTg = item.link;
} else if (item.configType === "potato_group") {
this.cPotato = item.link;
} else if (item.configType === "sw_cooperate") {
this.cBusiness = item.link;
} else if (item.configType === "qd_cooperate") {
this.cChannel = item.link;
}
});
return configs;
},
},
mounted() {
let ua = this.os.userAgent.toLowerCase();
let isSafari =
ua.indexOf("safari") !== -1 &&
ua.indexOf("browser") === -1 &&
ua.indexOf("android") === -1;
if (!isSafari && this.os.isPhone) {
this.showTip = true;
}
},
methods: {
pageClick(event) {
let click_coordinates_x = event.clientX;
let click_coordinates_y = event.clientY;
let tab_name = this.tabActive == "short_film"
? "短剧"
: this.tabActive == "hot"
? "热门"
: this.tabActive == "darkweb"
? "乱伦"
: "动漫";
landingPageClick(this, {
tab_key: this.tabActive,
tab_name,
click_coordinates_x,
click_coordinates_y,
});
},
// 剪贴板
doCopy() {
this.$copyText(this.currUrl).then(
() => {
console.log("复制成功");
this.showTip = false;
},
() => {
console.log("复制失败");
},
);
},
async showInstallTutorial(type) {
if (type == "ios") {
this.iosPromptShow = true;
} else {
this.androidPromptShow = true;
}
},
async getApkInfo(flag, event) {
let type = "android";
if (this.os.isPhone) {
type = "ios";
if (flag === "shopIos") {
type = "shopIos";
}
} else {
type = "android";
}
if (flag == "androidSpare") {
type = "androidSpare";
}
if (flag && flag !== "shopIos") {
await this.showInstallTutorial(type);
}
this.$emit("recordClick", type);
setTimeout(() => {
this.$emit("getApkInfo", type);
}, 500);
// 上报点击(下载按钮)
let click_coordinates_x = event.clientX;
let click_coordinates_y = event.clientY;
landingPageClick(this, {
tab_name: "下载按钮",
tab_key: "download",
click_coordinates_x,
click_coordinates_y,
});
},
openMobileCompatibleUrl(url) {
if (!url) {
return;
}
window.location.href = url;
},
async openOnlineService(event) {
const click_coordinates_x = event.clientX;
const click_coordinates_y = event.clientY;
const userAgent = this.os.userAgent || "";
landingPageClick(this, {
tab_name: "在线客服",
tab_key: "customer_service",
click_coordinates_x,
click_coordinates_y,
});
if (this.onlineServiceLoading) {
return;
}
this.onlineServiceLoading = true;
try {
const res = await getCustomerServiceUrl({
uid: this.$route.query.uid || getTraceId(),
appId: APPID,
deviceType: getDeviceType(userAgent),
systemType: getSystemType(userAgent),
systemVersion: getSystemVersion(userAgent),
});
const serviceUrl = res && res.data && res.data.data;
if (serviceUrl) {
this.openMobileCompatibleUrl(serviceUrl);
return;
}
if (this.cChannel) {
this.openMobileCompatibleUrl(this.cChannel);
return;
}
} catch (error) {
if (this.cChannel) {
this.openMobileCompatibleUrl(this.cChannel);
return;
}
console.log("get customer service url error:", error);
} finally {
this.onlineServiceLoading = false;
}
},
jumpUrl(url) {
window.open(url);
},
},
};
</script>
<style lang="scss" scoped>
.mobilePage {
height: 100%;
width: 100%;
background-color: #141414;
overflow-y: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
.headerBox {
z-index: 1;
width: 100%;
height: 76px;
background-color: #141414;
.header-bg {
height: 64px;
width: 343px;
background: url("./../../../assets/images/mobileB/logo.png") no-repeat;
background-size: 100% 100%;
margin: 0 auto;
}
}
.vantTabs {
padding: 0 16px 100px;
::v-deep .van-tabs__wrap {
height: 47px;
width: 100%;
background: #141414;
padding-bottom: 10px;
box-sizing: border-box;
.van-tab {
height: 30px;
border-radius: 6px;
}
.van-tab--active {
background: #f68804;
}
.van-tabs__nav {
padding: 0 3.5px;
background: #2d2c2f;
align-items: center;
justify-content: space-between;
border-radius: 8px;
}
.van-tabs__line {
display: none;
}
}
// ::v-deep .van-tabs__content {
// height: 100%;
// .van-tabs__track {
// height: 100%;
// .van-tab__pane-wrapper {
// height: 100%;
// .van-tab__pane {
// height: 100%;
// }
// }
// }
// }
.main {
// height: calc(100% - 190px);
padding: 12px 0 0;
.content0 {
height: 1710px;
width: 343px;
background: url("./../../../assets/images/mobileB/content0.webp")
no-repeat;
background-size: 100% 100%;
}
.content1 {
height: 940px;
width: 343px;
background: url("./../../../assets/images/mobileB/content1.webp")
no-repeat;
background-size: 100% 100%;
}
.content2 {
height: 940px;
width: 343px;
background: url("./../../../assets/images/mobileB/content2.webp")
no-repeat;
background-size: 100% 100%;
}
.content3 {
height: 2571px;
width: 343px;
background: url("./../../../assets/images/mobileB/content3.webp")
no-repeat;
background-size: 100% 100%;
}
}
}
.floatingBox {
border-radius: 18px 0 0 18px;
background: rgba(0, 0, 0, 0.6);
width: 36px;
position: fixed;
right: 0;
top: 187px;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
padding: 12px 0;
.telegram {
height: 40px;
width: 24px;
background: url("./../../../assets/images/mobileB/telegram.png") no-repeat;
background-size: 100% 100%;
}
.potato {
height: 40px;
width: 24px;
background: url("./../../../assets/images/mobileB/potato.png") no-repeat;
background-size: 100% 100%;
}
.business {
height: 40px;
width: 24px;
background: url("./../../../assets/images/mobileB/business.png") no-repeat;
background-size: 100% 100%;
}
.channel {
height: 40px;
width: 24px;
background: url("./../../../assets/images/mobileB/channel.png") no-repeat;
background-size: 100% 100%;
}
.customer {
height: 40px;
width: 24px;
background: url("./../../../assets/images/mobileB/customer.png")
no-repeat;
background-size: 100% 100%;
}
}
.bottomBox {
height: 73px;
width: 343px;
background: url("./../../../assets/images/mobileB/bottomBg.png") no-repeat;
background-size: 100% 100%;
position: fixed;
left: 50%;
bottom: calc(10px + env(safe-area-inset-bottom));
transform: translateX(-50%);
z-index: 100;
.down-btn {
border-radius: 4.052px;
background: #f68804;
width: 57.736px;
height: 17.321px;
color: #fff;
font-family: "PingFang MO";
font-size: 11.09px;
font-weight: 500;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
right: 22px;
bottom: 9.62px;
}
.down-btn-spare {
right: 96px;
}
}
.shopIos {
background: url("./../../../assets/images/mobileB/shopIos.png") no-repeat;
background-size: 100% 100%;
.spareBtn {
position: absolute;
width: 64px;
height: 28px;
border-radius: 14px;
right: 9px;
top: 50%;
transform: translateY(-50%);
}
}
.downloadIosAppStore {
height: 36px;
width: 284px;
background: url("./../../../assets/images/mobileB/downloadIosAppStore.gif")
no-repeat;
background-size: 100% 100%;
position: fixed;
left: 0;
bottom: 110px;
z-index: 998;
.close-btn {
height: 20px;
width: 20px;
background: url("./../../../assets/images/mobileB/close.png") no-repeat;
background-size: 100% 100%;
position: absolute;
right: -10px;
top: -10px;
}
}
.androidOverlay {
display: flex;
align-items: center;
justify-content: center;
.overlayContent {
width: 297px;
height: 441px;
background: url("./../../../assets/images/mobileB/android_tip.webp")
no-repeat;
background-size: 100% 100%;
border-radius: 12px;
padding-top: 380px;
.confirmBtnBox {
height: 36px;
width: 140px;
border-radius: 40px;
margin: 0 auto;
}
}
}
}
.downTip {
border-radius: 10px;
padding: 18px;
box-sizing: border-box;
text-align: center;
.downTipTitle {
font-size: 18px;
margin-bottom: 34px;
}
.downTipContent {
white-space: nowrap;
font-size: 15px;
}
.url {
font-size: 15px;
margin-top: 16px;
text-align: left;
}
.downTipConfirm {
// margin-top: 12px;
font-size: 15px;
width: 160px;
height: 30px;
border-radius: 40px;
margin: 32px auto 0;
color: #fff;
background: #5b92ee;
display: flex;
align-items: center;
justify-content: center;
}
}
</style>
+374
View File
@@ -0,0 +1,374 @@
<template>
<div class="pcm-wrapper" id="pcm-wrapper">
<div class="log"></div>
<div class="contactBox">
<div class="telegram" v-if="cTg" @click="jumpUrl(cTg)"></div>
<div class="potato" v-if="cPotato" @click="jumpUrl(cPotato)"></div>
<div class="business" v-if="cBusiness" @click="jumpUrl(cBusiness)"></div>
<div class="channel" v-if="cChannel" @click="jumpUrl(cChannel)"></div>
<div class="customer" @click="openOnlineService"></div>
</div>
<swiper :options="swiperOptions">
<swiper-slide v-for="(item, index) in bglist" :key="index">
<div :class="['wrapper', `bg_${item.type}`]">
<!-- <div class="title-bg"></div> -->
<!-- <div class="sub-title"></div> -->
<!-- <div class="figure"></div> -->
</div>
</swiper-slide>
<!-- <div class="swiper-pagination" slot="pagination"></div> -->
</swiper>
<div class="er-box">
<div class="downloadBox">
<img class="qrcodeBox" :src="qrImg" alt="" />
</div>
<div class="er-right">
<div class="and-tip">
安卓手机<br />
建议使用UC浏览器扫码
</div>
<div class="common-tip">
安装提示:下载好安装包以后,请断开网络,由于行业原因,本APP会被某些杀毒软件认为病毒,请放心下载使用,本APP有广告和会员收益,安装本APP
不会对您的手机造成任何损害。
</div>
</div>
</div>
</div>
</template>
<script>
import moment from "moment";
import autofit from "autofit.js";
import getCustomerServiceUrl from "@/api/getCustomerServiceUrl";
import {
getDeviceType,
getSystemType,
getSystemVersion,
getTraceId,
} from "@/utils/eventTracker";
const APPID = 204;
autofit.init();
export default {
props: ["qrImg", "configs"],
data() {
return {
cTg: "",
cPotato: "",
cBusiness: "",
cChannel: "",
onlineServiceLoading: false,
swiperOptions: {
direction: "vertical",
loop: true,
autoplay: {
delay: 4000,
disableOnInteraction: false,
},
// pagination: {
// el: ".swiper-pagination",
// clickable: true,
// },
scrollbar: {
el: ".swiper-scrollbar",
hide: true,
},
},
bglist: [
{
type: "01",
},
{
type: "02",
},
// {
// type: "03",
// },
],
};
},
watch: {
configs(configs) {
configs.forEach((item) => {
if (item.configType === "tg_group") {
this.cTg = item.link;
} else if (item.configType === "potato_group") {
this.cPotato = item.link;
} else if (item.configType === "sw_cooperate") {
this.cBusiness = item.link;
} else if (item.configType === "qd_cooperate") {
this.cChannel = item.link;
}
});
return configs;
},
},
mounted() {
autofit.init(
{
dh: 1080,
dw: 1920,
el: "#pcm-wrapper",
resize: true,
},
false
); // 可关闭控制台运行提示输出
},
created() {
setInterval(() => {
this.time = moment().format("HH:mm");
}, 1000);
},
methods: {
async openOnlineService() {
if (this.onlineServiceLoading) {
return;
}
this.onlineServiceLoading = true;
try {
const res = await getCustomerServiceUrl({
uid: this.$route.query.uid || getTraceId(),
appId: APPID,
deviceType: getDeviceType(),
systemType: getSystemType(),
systemVersion: getSystemVersion(),
});
const serviceUrl = res && res.data && res.data.data;
if (serviceUrl) {
window.open(serviceUrl);
return;
}
if (this.cChannel) {
window.open(this.cChannel);
}
} catch (error) {
if (this.cChannel) {
window.open(this.cChannel);
}
console.log("get customer service url error:", error);
} finally {
this.onlineServiceLoading = false;
}
},
jumpUrl(url) {
window.open(url);
},
},
};
</script>
<style lang="scss" scoped>
.pcm-wrapper {
width: 100%;
height: 100%;
cursor: pointer;
position: relative;
.log {
background: url("../../../assets/images/pc/logo.png") no-repeat;
background-size: 100% 100%;
width: 288.5px;
height: 102px;
position: absolute;
left: 104px;
top: 61px;
z-index: 10;
}
.contactBox {
position: absolute;
top: 78px;
right: 105px;
display: flex;
align-items: center;
z-index: 10;
.telegram,
.potato,
.business,
.channel,
.customer {
width: 68px;
height: 68px;
}
.telegram {
background: url("../../../assets/images/pc/telegram.png") no-repeat;
background-size: 100% 100%;
margin-right: 30px;
}
.potato {
background: url("../../../assets/images/pc/potato.png") no-repeat;
background-size: 100% 100%;
margin-right: 30px;
}
.business {
background: url("../../../assets/images/pc/shangwu.png") no-repeat;
background-size: 100% 100%;
margin-right: 30px;
}
.channel {
background: url("../../../assets/images/pc/qudao.png") no-repeat;
background-size: 100% 100%;
margin-right: 30px;
}
.customer {
background: url("../../../assets/images/pc/customer.png") no-repeat;
background-size: 100% 100%;
width: 56px;
height: 56px;
}
}
.er-box {
position: absolute;
left: 150px;
bottom: 210px;
display: flex;
align-items: center;
z-index: 10;
.downloadBox {
width: 210px;
height: 210px;
margin-right: 50px;
display: flex;
align-items: center;
justify-content: center;
background: #d9d9d9;
.qrcodeBox {
background-color: #fff;
width: 208px;
height: 208px;
}
}
.er-right {
.and-tip {
color: #ff6f2e;
font-family: "PingFang SC";
font-size: 30px;
font-style: normal;
font-weight: 500;
line-height: normal;
}
.common-tip {
margin-top: 13px;
width: 531px;
color: #fff;
text-align: justify;
font-family: "PingFang SC";
font-size: 18px;
font-style: normal;
font-weight: 500;
line-height: normal;
}
}
}
::v-deep .swiper-container {
width: 100%;
height: 100%;
.swiper-wrapper {
width: 100%;
height: 100%;
}
.swiper-pagination {
right: 10px;
top: 25%;
width: 30px;
height: 124px;
z-index: 11;
position: absolute;
display: flex;
flex-direction: column;
.swiper-pagination-bullet {
width: 12px;
height: 12px;
display: inline-block;
border-radius: 50px;
background: rgba(255, 255, 255, 0.55);
// box-shadow: 0px 0px 5px 0px #fff;
margin-bottom: 10px;
}
.swiper-pagination-bullet-active {
border-radius: 14px;
background: #fff;
height: 73px;
// box-shadow: 0px 0px 8px 0px #fff;
}
}
}
.wrapper {
width: 100%;
height: 100%;
position: relative;
.title-bg {
width: 768px;
height: 285px;
position: absolute;
left: 107px;
top: 197px;
}
.sub-title {
width: 628px;
height: 49px;
position: absolute;
left: 151px;
top: 513px;
}
.figure {
width: 1021px;
height: 970px;
position: absolute;
right: 0px;
bottom: 0px;
}
}
.bg_01 {
background: url("../../../assets/images/pc/bg01.webp") no-repeat;
background-size: 100% 100%;
.title-bg {
background: url("../../../assets/images/pc/title01.webp") no-repeat;
background-size: 100% 100%;
}
.sub-title {
background: url("../../../assets/images/pc/subTitle.webp") no-repeat;
background-size: 100% 100%;
}
.figure {
background: url("../../../assets/images/pc/figure01.webp") no-repeat;
background-size: 100% 100%;
}
}
.bg_02 {
background: url("../../../assets/images/pc/bg02.webp") no-repeat;
background-size: 100% 100%;
// .wrapper-top {
// background: url("../../../assets/images/pc/header-bg02.webp") no-repeat;
// background-size: 100% 100%;
// }
.title-bg {
background: url("../../../assets/images/pc/title02.webp") no-repeat;
background-size: 100% 100%;
}
.sub-title {
background: url("../../../assets/images/pc/subTitle.webp") no-repeat;
background-size: 100% 100%;
}
.figure {
background: url("../../../assets/images/pc/figure02.webp") no-repeat;
background-size: 100% 100%;
}
}
.bg_03 {
background: url("../../../assets/images/pc/bg01.webp") no-repeat;
background-size: 100% 100%;
.title-bg {
background: url("../../../assets/images/pc/title03.webp") no-repeat;
background-size: 100% 100%;
}
.sub-title {
background: url("../../../assets/images/pc/subTitle.webp") no-repeat;
background-size: 100% 100%;
}
.figure {
background: url("../../../assets/images/pc/figure03.webp") no-repeat;
background-size: 100% 100%;
}
}
}
</style>
+210
View File
@@ -0,0 +1,210 @@
<template>
<div class="pcm-wrapper" id="pcm-wrapper">
<div class="log-box">
<div class="log"></div>
<template v-if="cTg">
<div class="telegram" @click="jumpUrl(cTg)"></div>
<div class="line"></div>
</template>
<template v-if="cChannel">
<div class="channel" @click="jumpUrl(cChannel)"></div>
<div class="line"></div>
</template>
<template v-if="cBusiness">
<div class="business" @click="jumpUrl(cBusiness)"></div>
<div class="line"></div>
</template>
<div class="customer" @click="openOnlineService"></div>
</div>
<div class="er-box">
<div class="downloadBox">
<img class="qrcodeBox" :src="qrImg" alt="" />
</div>
</div>
</div>
</template>
<script>
import moment from "moment";
import autofit from "autofit.js";
import getCustomerServiceUrl from "@/api/getCustomerServiceUrl";
import {
getDeviceType,
getSystemType,
getSystemVersion,
getTraceId,
} from "@/utils/eventTracker";
const APPID = 204;
autofit.init();
export default {
props: ["qrImg", "configs"],
data() {
return {
cTg: "",
cPotato: "",
cBusiness: "",
cChannel: "",
onlineServiceLoading: false,
};
},
watch: {
configs(configs) {
configs.forEach((item) => {
if (item.configType === "tg_group") {
this.cTg = item.link;
} else if (item.configType === "potato_group") {
this.cPotato = item.link;
} else if (item.configType === "sw_cooperate") {
this.cBusiness = item.link;
} else if (item.configType === "qd_cooperate") {
this.cChannel = item.link;
}
});
return configs;
},
},
mounted() {
autofit.init(
{
dh: 1080,
dw: 1920,
el: "#pcm-wrapper",
resize: true,
},
false
); // 可关闭控制台运行提示输出
},
created() {
setInterval(() => {
this.time = moment().format("HH:mm");
}, 1000);
},
methods: {
async openOnlineService() {
if (this.onlineServiceLoading) {
return;
}
this.onlineServiceLoading = true;
try {
const res = await getCustomerServiceUrl({
uid: this.$route.query.uid || getTraceId(),
appId: APPID,
deviceType: getDeviceType(),
systemType: getSystemType(),
systemVersion: getSystemVersion(),
});
const serviceUrl = res && res.data && res.data.data;
if (serviceUrl) {
window.open(serviceUrl);
return;
}
if (this.cChannel) {
window.open(this.cChannel);
}
} catch (error) {
if (this.cChannel) {
window.open(this.cChannel);
}
console.log("get customer service url error:", error);
} finally {
this.onlineServiceLoading = false;
}
},
jumpUrl(url) {
window.open(url);
},
},
};
</script>
<style lang="scss" scoped>
.pcm-wrapper {
width: 100%;
height: 100%;
cursor: pointer;
position: relative;
background: url("../../../assets/images/pc2/bg.webp") no-repeat;
background-size: 100% 100%;
.log-box {
border-radius: 0 0 26.578px 26.578px;
border: 1.661px solid rgba(255, 255, 255, 0.2);
background: rgba(255, 255, 255, 0.12);
backdrop-filter: blur(8.305647850036621px);
display: inline-flex;
height: 106px;
padding: 14px 136.213px 14px 53.156px;
align-items: center;
gap: 93.023px;
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
z-index: 100;
.log {
background: url("../../../assets/images/pc2/logo.png") no-repeat;
background-size: 100% 100%;
width: 187.5px;
height: 64px;
}
.telegram {
background: url("../../../assets/images/pc2/telegram.png") no-repeat;
background-size: 100% 100%;
width: 150px;
height: 36px;
}
.business {
background: url("../../../assets/images/pc2/business.png") no-repeat;
background-size: 100% 100%;
width: 150px;
height: 36px;
}
.channel {
background: url("../../../assets/images/pc2/channel.png") no-repeat;
background-size: 100% 100%;
width: 150px;
height: 36px;
}
.customer {
background: url("../../../assets/images/pc2/customer.png") no-repeat;
background-size: 100% 100%;
width: 150px;
height: 31px;
}
.line {
background: url("../../../assets/images/pc2/line.png") no-repeat;
background-size: 100% 100%;
width: 3.32px;
height: 23.3px;
}
}
.er-box {
position: absolute;
left: 191px;
bottom: 116px;
width: 768px;
height: 250px;
z-index: 10;
background: url("../../../assets/images/pc2/erCode.webp") no-repeat;
background-size: 100% 100%;
.downloadBox {
width: 250px;
height: 250px;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
border-radius: 30px 0 0 30px;
overflow: hidden;
left: 0;
top: 0;
.qrcodeBox {
background-color: #fff;
width: 240px;
height: 240px;
}
}
}
}
</style>
@@ -0,0 +1,111 @@
<template>
<div class="selectLinePopup">
<!-- 选线框 -->
<van-overlay :show="showOverlay" z-index="999" class="selectLineOverlay">
<div class="selectionLineBox">
<div class="titleBox">选择线路</div>
<div class="lineArea">
<div
class="lineBox"
@click.stop="changeLine(item)"
v-for="(item, index) in apiUrls"
:key="item"
>
<div class="selected" v-if="item == currentApi">
<div class="select"></div>
</div>
<div class="unselect" v-else></div>
<div class="line">线路{{ index + 1 }}</div>
</div>
</div>
</div>
</van-overlay>
</div>
</template>
<script>
export default {
props: ["apiUrls", "showOverlay"],
data() {
return {
currentApi: "", // 当前api
};
},
created() {
this.currentApi = this.apiUrls[0];
},
methods: {
changeLine(item) {
this.currentApi = item;
this.$emit("selectLine", item);
},
},
};
</script>
<style scoped lang="scss">
// 选线
.selectLineOverlay {
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
.selectionLineBox {
background-color: white;
border-radius: 8px;
overflow: hidden;
width: 280px;
.titleBox {
color: white;
font-size: 15px;
text-align: center;
height: 38px;
line-height: 38px;
background: linear-gradient(
142deg,
#ffae61 0%,
#ff1101 48%,
#ff00b9 100%
);
}
.lineArea {
padding: 24px 24px;
display: flex;
align-items: center;
justify-content: center;
.lineBox {
white-space: nowrap;
margin: 8px 20px 8px 20px;
display: flex;
align-items: center;
.unselect {
height: 12px;
width: 12px;
border-radius: 50%;
background-color: rgba(238, 238, 238, 1);
}
.selected {
height: 14px;
width: 14px;
border-radius: 50%;
background-color: rgba(238, 238, 238, 1);
display: flex;
align-items: center;
justify-content: center;
.select {
height: 10px;
width: 10px;
border-radius: 50%;
background-color: rgba(221, 0, 27, 1);
}
}
.line {
font-size: 15px;
color: #666;
margin-left: 4px;
flex: 1;
}
}
}
}
}
</style>
+25
View File
@@ -0,0 +1,25 @@
<template>
<div class="wrapper">提示:该应用只支持手机端!</div>
</template>
<script>
export default {
data() {
return {};
},
methods: {},
components: {}
};
</script>
<style scoped>
.wrapper {
width: 100vw;
height: 100vh;
box-sizing: border-box;
position: absolute;
top: 50%;
left: 40%;
font-size: 30px;
}
</style>
+489
View File
@@ -0,0 +1,489 @@
<template>
<div class="container" @click="doCopy()">
<template v-if="version == 'A'">
<mobileA
v-if="!isPC"
class="mobile"
:os="os"
@getApkInfo="handleGetApkInfo"
@recordClick="recordClick"
:ip="ip"
:configs="configs"
:switchData="switchData"
style="height:100%"
ref="mobileRef"
/>
<tips
v-else-if="isPC && page_pc_url === 'https://sisqd.com/?dc=THD2'"
></tips>
<pc
v-else
class="pc"
:qr-img="QRImg"
:os="os"
:configs="configs"
@getApkInfo="handleGetApkInfo"
></pc>
</template>
<template v-else>
<mobileB
v-if="!isPC"
class="mobile"
:os="os"
@getApkInfo="handleGetApkInfo"
@recordClick="recordClick"
:ip="ip"
:configs="configs"
:switchData="switchData"
style="height:100%"
></mobileB>
<tips
v-else-if="isPC && page_pc_url === 'https://sisqd.com/?dc=THD2'"
></tips>
<pc2
v-else
class="pc"
:qr-img="QRImg"
:os="os"
:configs="configs"
@getApkInfo="handleGetApkInfo"
></pc2>
</template>
<!-- loading-->
<div class="loading_box" v-if="loading && !isPC">
<div style="height: 5px"></div>
<div class="lds-roller">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<h3>加载中...</h3>
</div>
<selectLinePopup
:apiUrls="apiUrls"
:showOverlay="showOverlay"
@selectLine="selectLine"
></selectLinePopup>
</div>
</template>
<script>
import getApkInfo from "@/api/getApkInfo";
import getButtonlist from "@/api/getTemplate";
import userAgent from "@/utils/userAgent";
import QRCode from "qrcode";
import axios from "@/utils/request.js";
import mobileB from "./components/mobileB";
import mobileA from "./components/mobileA";
import pc from "./components/pc";
import pc2 from "./components/pc2";
import tips from "./components/tips";
import selectLinePopup from "./components/selectLinePopup";
import { getTraceId, landingPageView } from "@/utils/eventTracker";
const APPID = 204;
export default {
components: {
mobileB,
mobileA,
pc,
pc2,
tips,
selectLinePopup,
},
data() {
return {
type: "",
QRImg: "",
os: "",
param: "",
cutInfo: {}, //替换url参数对象内<key> dc内容;
ip: "",
switchData: {},
page_pc_url: "",
iosDownUrl: "",
androidDownUrl: "",
shopIosDownUrl: "", // 商店包链接
storeAndroidDownUrl: "",
channelApkAndDownUrl: "",
// iosJumpSetUpUrl: "", // 执行完下载链接后需要执行的跳转
loading: true,
currUrl: window.location.href,
apiUrls: JSON.parse(process.env.VUE_APP_BASE_HOSTS), // api数组
showOverlay: false, // 显示选线弹窗
configs: [],
// tgUrl: "",
// potatoUrl: "",
// swUrl: "",
// qdUrl: "",
version: "A",
trace_id: getTraceId(),
};
},
computed: {
isPC() {
return this.os.isPc;
},
},
created() {
// this.version = Math.random() < 0.5 ? "A" : "B";
this.getPcUrl();
this.os = userAgent();
this.functionParam();
this.getButtonlist();
landingPageView(this);
const referrer = document.referrer;
// console.log(referrer, "-----------referrer");
if (referrer) {
sessionStorage.setItem("referrer", referrer);
}
if (this.$route.query.dc) {
sessionStorage.setItem("dc", this.$route.query.dc);
}
// this.getIp();
},
mounted() {
this.getQRImg();
},
methods: {
isDcMatch(value) {
const reg = /^(?:ky(?:(?:0[1-9]|[1-9][0-9]|100))|TLGG(?:(?:0[1-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-6]))|erra(?:(?:0[1-9]|10))|cctl(?:(?:0[1-9]|10))|mijieer[1-5][a-d])$/;
return reg.test(value);
},
getPcUrl() {
this.page_pc_url = window.location.href;
},
//1.判断进来的url地址 替换到需要手动设置的参数 如cd
functionParam() {
this.param =
JSON.stringify(this.$route.query) === "{}"
? "{}"
: JSON.stringify(this.$route.query);
},
//2.获取按钮状态信息
async getButtonlist() {
try {
let param_btn_list = {
appId: APPID,
channel: this.param,
domain: window.location.protocol + "//" + window.location.host,
version: this.version,
};
const res = await getButtonlist(param_btn_list);
this.loading = false;
if (res.data.code === 200) {
this.switchData = res.data.data;
this.configs = res.data.data.configs || [];
this.androidDownUrl = res.data.data.androidDownUrl;
this.storeAndroidDownUrl = res.data.data.storeAndroidDownUrl;
this.channelApkAndDownUrl = res.data.data.channelApkAndDownUrl;
this.iosDownUrl = res.data.data.iosDownUrl;
this.shopIosDownUrl = res.data.data.shopIosDownUrl;
// this.iosJumpSetUpUrl = res.data.data.iosJumpSetUpUrl;
}
} catch (err) {
this.loading = false;
this.showOverlay = true;
console.log(err);
}
},
//3. 获取外网IP地址
getIp() {
axios.get("https://api.ipify.org/?format=json").then((res) => {
this.ip = res.data.ip;
});
},
//4. 点击下载按钮获取apk信息并下载
async handleGetApkInfo(type) {
await this.doCopy();
let terminal;
let packageType;
if (type === "ios") {
terminal = "ios";
packageType = 1;
}else if(type == 'shopIos') {
terminal = "ios";
packageType = 2;
} else if (type == "androidSpare") {
terminal = "androidSpare";
} else {
terminal = "android";
}
if (terminal === "android" || terminal === "androidSpare") {
let dc = this.$route.query.dc;
if (this.storeAndroidDownUrl && this.isDcMatch(dc)) {
let url = this.storeAndroidDownUrl || this.channelApkAndDownUrl;
window.location.href = url;
} else if (terminal === "androidSpare") {
window.location.href = this.androidDownUrl;
} else {
let jumpUrl = this.channelApkAndDownUrl || this.androidDownUrl;
window.location.href = jumpUrl;
}
} else {
let dc = this.$route.query.dc;
let ch = this.$route.query.ch;
let pc = this.$route.query.pc;
let linkUrl = "";
if (dc) {
linkUrl = `${this.iosDownUrl}?dc=${dc}&tid=${this.trace_id}`;
} else if (ch) {
linkUrl = `${this.iosDownUrl}?ch=${ch}&tid=${this.trace_id}`;
} else if (pc) {
linkUrl = `${this.iosDownUrl}?pc=${pc}&tid=${this.trace_id}`;
} else {
linkUrl = `${this.iosDownUrl}?tid=${this.trace_id}`;
}
if (type == 'shopIos') {
window.open(this.shopIosDownUrl);
} else {
window.location.href = linkUrl;
}
// if (this.iosJumpSetUpUrl) {
// setTimeout(() => {
// window.location.href = this.iosJumpSetUpUrl;
// }, 1500);
// }
}
// getApkInfo(param);
},
recordClick(type) {
let terminal;
let packageType;
if (type === "ios") {
terminal = "ios";
packageType = 1;
}else if(type == 'shopIos') {
terminal = "ios";
packageType = 2;
} else {
terminal = "android";
}
const param = {
appId: APPID,
ip: this.ip ? this.ip : "", //获取ip地址
channel: JSON.stringify({
...JSON.parse(this.param),
...this.cutInfo,
}),
domain: window.location.protocol + "//" + window.location.host,
terminal,
packageType,
version: this.version,
};
getApkInfo(param);
},
//5.生成二维码
getQRImg() {
// const referrer = sessionStorage.getItem("referrer");
// const dc = sessionStorage.getItem("dc");
// if (referrer && dc) {
// this.currUrl = referrer + "user.html?dc=" + dc;
// } else {
// if (referrer) {
// this.currUrl = referrer + "user.html";
// } else {
// this.currUrl = window.location.href;
// }
// }
QRCode.toDataURL(this.currUrl, {
width: 170,
margin: 1,
maskPattern: 1,
scale: 1,
color: {
dark: "#000",
light: "rgba()",
},
}).then((url) => {
const regex = /code=/gi;
if (url.indexOf("code=") != -1) {
this.QRImg = url.replace(regex, "pc=");
} else {
this.QRImg = url;
}
});
},
// 6.剪贴板
doCopy() {
let req = JSON.stringify({
...this.$route.query,
tid: this.trace_id,
});
this.$copyText(req).then(
() => {
console.log("复制成功");
},
() => {
console.log("复制失败");
}
);
},
// 选线
selectLine(item) {
axios.defaults.baseURL = item; // 更改apiURL
setTimeout(() => {
this.showOverlay = false;
this.loading = true;
this.getButtonlist(); // 重新请求接口
}, 300);
},
},
};
</script>
<style lang="scss" scoped>
.container {
overflow: hidden;
height: 100%;
.mobile {
height: 100%;
}
}
// @media screen and (min-width: 750px) {
// .mobile {
// display: none;
// }
// .pc {
// overflow: hidden;
// }
// }
// @media screen and (max-width: 750px) {
// .pc {
// display: none;
// }
// }
/* loading */
.loading_box {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 10;
border-radius: 20px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
h3 {
padding-top: 10px;
font-size: 20px;
color: #fff;
}
}
.lds-roller {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
}
.lds-roller div {
animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
transform-origin: 40px 40px;
}
.lds-roller div:after {
content: " ";
display: block;
position: absolute;
width: 7px;
height: 7px;
border-radius: 50%;
background: #fff;
margin: -4px 0 0 -4px;
}
.lds-roller div:nth-child(1) {
animation-delay: -0.036s;
}
.lds-roller div:nth-child(1):after {
top: 63px;
left: 63px;
}
.lds-roller div:nth-child(2) {
animation-delay: -0.072s;
}
.lds-roller div:nth-child(2):after {
top: 68px;
left: 56px;
}
.lds-roller div:nth-child(3) {
animation-delay: -0.108s;
}
.lds-roller div:nth-child(3):after {
top: 71px;
left: 48px;
}
.lds-roller div:nth-child(4) {
animation-delay: -0.144s;
}
.lds-roller div:nth-child(4):after {
top: 72px;
left: 40px;
}
.lds-roller div:nth-child(5) {
animation-delay: -0.18s;
}
.lds-roller div:nth-child(5):after {
top: 71px;
left: 32px;
}
.lds-roller div:nth-child(6) {
animation-delay: -0.216s;
}
.lds-roller div:nth-child(6):after {
top: 68px;
left: 24px;
}
.lds-roller div:nth-child(7) {
animation-delay: -0.252s;
}
.lds-roller div:nth-child(7):after {
top: 63px;
left: 17px;
}
.lds-roller div:nth-child(8) {
animation-delay: -0.288s;
}
.lds-roller div:nth-child(8):after {
top: 56px;
left: 12px;
}
@keyframes lds-roller {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
//loading
</style>