feat:重构c端代码

This commit is contained in:
wwxin 2024-07-25 14:58:42 +08:00
commit 06049cb3fd
53 changed files with 11065 additions and 0 deletions

15
.env.development Normal file
View File

@ -0,0 +1,15 @@
# 页面标题
VITE_APP_TITLE = 'aaaa'
# 开发环境配置
VITE_APP_ENV = 'development'
# 若依管理系统/开发环境
VITE_APP_BASE_API = '/api'
# local dev
VITE_APP_LOCAL_PORT = '8087'
# server info
VITE_APP_SERVER_HOST = 'http://200.12.111.111'
VITE_APP_SERVER_PORT = '80'

25
.env.production Normal file
View File

@ -0,0 +1,25 @@
###
# @Author: wwxin 2463926940@qq.com
# @Date: 2024-01-04 09:57:02
# @LastEditors: wwxin 2463926940@qq.com
# @LastEditTime: 2024-07-20 10:23:10
# @FilePath: /a-vue3 2/.env.production
# @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
###
# 页面标题
VITE_APP_TITLE = 111
# 生产环境配置
VITE_APP_ENV = 'production'
# 若依管理系统/生产环境
VITE_APP_BASE_API = ''
# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip
# local dev
VITE_APP_LOCAL_PORT = '3000'
# server info
VITE_APP_SERVER_HOST = 'http://111.111.111.111'

26
.eslintrc.js Normal file
View File

@ -0,0 +1,26 @@
module.exports = {
root: true,
env: {
node: true
},
extends: ['plugin:vue/recommended'],
rules: {
"comma-dangle": ["error", "never"]
},
parserOptions: {
parser: '@typescript-eslint/parser'
},
overrides: [
{
files: ['**/__tests__/*.{j,t}s?(x)'],
env: {
jest: true
}
}
]
}

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
.history
.local
.idea

36
README.en.md Normal file
View File

@ -0,0 +1,36 @@
# vip-server-new
#### Description
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

39
README.md Normal file
View File

@ -0,0 +1,39 @@
# vip-server-new
#### 介绍
{**以下是 Gitee 平台说明,您可以替换此简介**
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN。专为开发者提供稳定、高效、安全的云端软件开发协作平台
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

3
babel.config.json.bak Normal file
View File

@ -0,0 +1,3 @@
{
"plugins": ["@vue/babel-plugin-jsx"]
}

19
components.d.ts vendored Normal file
View File

@ -0,0 +1,19 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
declare module 'vue' {
export interface GlobalComponents {
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SvgIcon: typeof import('./src/components/SvgIcon/index.vue')['default']
VanLoading: typeof import('vant/es')['Loading']
VanNoticeBar: typeof import('vant/es')['NoticeBar']
VanOverlay: typeof import('vant/es')['Overlay']
VanSwipe: typeof import('vant/es')['Swipe']
VanSwipeItem: typeof import('vant/es')['SwipeItem']
}
}

25
index.html Normal file
View File

@ -0,0 +1,25 @@
<!--
* @Author: wwxin
* @Date: 2024-06-20 16:55:56
* @LastEditors: 嘻嘻听我说 2463926940@qq.com
* @LastEditTime: 2024-06-21 16:33:50
* @FilePath: /a-vue3 2/index.html
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<!-- <link rel="stylesheet" type="text/css" href="https://prom-cdn.xtl10.fun/resources/css/indexAll.css"> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

1
jest.config.js Normal file
View File

@ -0,0 +1 @@
module.exports = { preset: '@vue/cli-plugin-unit-jest' };

10
jsconfig.json Normal file
View File

@ -0,0 +1,10 @@
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
},
"jsx":"preserve"
},
"exclude": ["node_modules", "dist"]
}

5204
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

42
package.json Normal file
View File

@ -0,0 +1,42 @@
{
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
},
"dependencies": {
"@element-plus/icons-vue": "2.0.10",
"@vue-macros/reactivity-transform": "^0.4.6",
"@vueuse/core": "9.5.0",
"axios": "0.27.2",
"cz-conventional-changelog": "^3.3.0",
"element-plus": "^2.3.4",
"js-md5": "^0.8.3",
"lodash": "^4.17.21",
"pinia": "^2.1.7",
"uuid": "^8.3.0",
"vant": "^4.9.1",
"vue": "3.3.4",
"vue-router": "4.1.4"
},
"devDependencies": {
"@vant/auto-import-resolver": "^1.2.1",
"@vitejs/plugin-vue": "^5.0.4",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/compiler-sfc": "3.2.45",
"sass": "^1.64.2",
"sass-loader": "^10.1.1",
"unplugin-auto-import": "^0.11.4",
"unplugin-vue-components": "^0.26.0",
"unplugin-vue-setup-extend-plus": "0.4.9",
"vite": "^5.0.7",
"vite-plugin-compression": "0.5.1",
"vite-plugin-svg-icons": "2.0.1"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
11

30
src/App.vue Normal file
View File

@ -0,0 +1,30 @@
<!--
* @Author: 嘻嘻听我说 2463926940@qq.com
* @Date: 2024-06-20 15:13:44
* @LastEditors: wwxin 2463926940@qq.com
* @LastEditTime: 2024-07-03 11:23:29
* @FilePath: /a-vue3 2/src/App.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<router-view></router-view>
</template>
<script setup>
</script>
<style>
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
#app{
width: 100%;
overflow: scroll;
}
</style>

46
src/api/request.js Normal file
View File

@ -0,0 +1,46 @@
/*
* @Author: wwxin 2463926940@qq.com
* @Date: 2024-06-20 15:10:50
* @LastEditors: wwxin 2463926940@qq.com
* @LastEditTime: 2024-07-22 11:02:27
* @FilePath: /vip-server-new/src/api/request.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import axios from 'axios';
const getHttp = () => {
const domainName = window.location.hostname;
if (domainName.indexOf("prom-cdn.xtl10.fun") > -1) {
return "http://zong.xtl10.fun";
} else {
return "http://zong.xtl10.fun";
}
};
const http = axios.create({
baseURL: getHttp(), // baseURL
withCredentials: false, // 跨域请求时是否需要使用凭证
});
// request 拦截器
http.interceptors.request.use(
config => {
return config;
},
error => {
return Promise.reject(error);
}
);
// response 拦截器
http.interceptors.response.use(
response => {
// 响应成功
return Promise.resolve(response);
},
error => {
// 响应失败
return Promise.reject(error);
}
);
export default http;

72
src/api/urls.js Normal file
View File

@ -0,0 +1,72 @@
/*
* @Author: wwxin 2463926940@qq.com
* @Date: 2024-06-20 15:11:40
* @LastEditors: wwxin 2463926940@qq.com
* @LastEditTime: 2024-07-25 09:37:47
* @FilePath: /vip-server-new/src/api/urls.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import request from './request';
//推广位的基础信息
export function resourceInfo(params) {
return request({
url: `/api/c/common/resource/info/${params.promotionCode}`,
method: 'get',
params,
});
}
//推广位-所有协议
export function resourceAgree(params) {
return request({
url: `/api/c/common/resource/agreement/${params.promotionId}/${params.typesparmes}`,
method: 'get',
});
}
//推广位-普通类型
export function resourceArea(params) {
return request({
url: `/api/a/area/tel`,
method: 'get',
params
});
}
//普通推广位-创建订单
export function proOrder(data) {
return request({
url: `/api/order`,
method: 'post',
data
});
}
//推广位-普通类型
export function resourceAreaDj(params) {
return request({
url: `/api/a/area/dj`,
method: 'get',
params
});
}
//推广位-埋点
export function resourceAreaAv(params) {
return request({
url: `/api/a/area/av`,
method: 'get',
params
});
}
//联合推广位-创建订单
export function creatUnion(data) {
return request({
url: `/api/order/union`,
method: 'post',
data
});
}
//推广位类型-运营商基本信息
export function yingnuoInfo(params) {
return request({
url: `/api/yingnuo/promotion/${params.promotionCode}`,
method: 'get',
params,
});
}

25
src/assets/rem.js Normal file
View File

@ -0,0 +1,25 @@
/*
* @Author: wwxin 2463926940@qq.com
* @Date: 2024-07-03 09:57:48
* @LastEditors: wwxin 2463926940@qq.com
* @LastEditTime: 2024-07-03 11:19:09
* @FilePath: /a-vue3 2/src/assets/rem.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// rem等比适配配置文件
// 基准大小
// export const baseSize =54;
// // 设置 rem 函数
// function setRem() {
// const scale = document.documentElement.clientWidth / 1920;
// // const scale = 1;
// // 设置页面根节点字体大小“Math.min(scale, 2)” 指最高放大比例为2可根据实际业务需求调整
// document.documentElement.style.fontSize =
// baseSize * Math.min(scale, 2) + "px";
// }
// // 初始化
// setRem();
// // 改变窗口大小时重新设置 rem
// window.onresize = function () {
// setRem();
// };

View File

@ -0,0 +1,53 @@
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName" :fill="color" />
</svg>
</template>
<script>
export default defineComponent({
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
},
color: {
type: String,
default: ''
},
},
setup(props) {
return {
iconName: computed(() => `#icon-${props.iconClass}`),
svgClass: computed(() => {
if (props.className) {
return `svg-icon ${props.className}`
}
return 'svg-icon'
})
}
}
})
</script>
<style scope lang="scss">
.sub-el-icon,
.nav-icon {
display: inline-block;
font-size: 15px;
margin-right: 12px;
position: relative;
}
.svg-icon {
width: 1em;
height: 1em;
position: relative;
fill: currentColor;
vertical-align: -2px;
}
</style>

View File

@ -0,0 +1,10 @@
import * as components from '@element-plus/icons-vue'
export default {
install: (app) => {
for (const key in components) {
const componentConfig = components[key];
app.component(componentConfig.name, componentConfig);
}
},
};

View File

@ -0,0 +1,42 @@
import { checkType } from '@/utils';
import { formatTime as fmtTime } from '@/utils/time-utils';
import i18n from '@/lang';
export function formatTime(time, format) {
if (!time) return;
if (checkType(time) === 'number' && (time + '').length === 10) {
time = +time * 1000;
}
return fmtTime(time, format);
}
export function formatTimeFromNow(time, format) {
if (!time) return;
if (checkType(time) === 'number' && (time + '').length === 10) {
time = +time * 1000;
}
const d = new Date(time);
const now = Date.now();
const diff = (now - d) / 1000;
if (diff < 60) {
return i18n.t('unit["刚刚"]');
} else if (diff < 3600) {
// less 1 hour
return Math.floor(diff / 60) + i18n.t('unit["分钟前"]');
} else if (diff < 3600 * 24) {
return Math.floor(diff / 3600) + i18n.t('unit["小时前"]');
} else if (diff < 3600 * 24 * 7) {
return Math.floor(diff / (3600 * 24)) + i18n.t('unit["天前"]');
} else if (diff < 3600 * 24 * 7 * 5) {
return Math.floor(diff / (3600 * 24 * 7)) + i18n.t('unit["周前"]');
} else if (diff < 3600 * 24 * 30 * 13) {
return Math.floor(diff / (3600 * 24 * 30)) + i18n.t('unit["个月前"]');
}
return fmtTime(time, format);
}

1
src/filters/index.js Normal file
View File

@ -0,0 +1 @@
export * from './functions/formatTime';

9
src/icons/index.js Normal file
View File

@ -0,0 +1,9 @@
import Vue from 'vue';
import SvgIcon from '@/components/SvgIcon';// svg component
// register globally
Vue.component('svg-icon', SvgIcon);
const req = require.context('./svg', false, /\.svg$/u);
const requireAll = requireContext => requireContext.keys().map(requireContext);
requireAll(req);

14
src/icons/svg/upload.svg Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
<style type="text/css">
.st0{fill:#DEE2E6;}
</style>
<path class="st0" d="M156.5,163.2c-14.5-0.3-26.1-12.3-25.9-26.8s12.3-26.1,26.8-25.9c14.4,0.3,25.9,12,25.9,26.3
C183.2,151.6,171.2,163.4,156.5,163.2z M156.5,121.4l-13.8,15h9.2v18h9.2v-18h9.2L156.5,121.4z M156.3,136.5v0.4H156L156.3,136.5z
M163.6,104.9V44.5h-147c-0.1-4.2,3.2-7.7,7.4-7.8c0.2,0,0.4,0,0.5,0h139c0,0,8.2,0.6,8.2,7.8V108c-0.4-0.2-0.8-0.4-1.2-0.6
C168.4,106.3,166.1,105.5,163.6,104.9L163.6,104.9z M132.8,59.9c0,0,15.7-0.2,15.7,15.1c0,0,1.4,14.7-15.7,15.1
c0,0-15.3,0.3-15.2-15.1C117.8,66.7,124.5,60,132.8,59.9z M24.6,136l6.9-0.2L62.7,90l31.7,38.4l23.2-23l11.9,11.8
c-9.5,12.5-8.6,30,2.1,41.4h-107c-4.3,0-7.8-3.5-7.9-7.8V44.5h7.8L24.6,136z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

22
src/icons/svgo.yml Normal file
View File

@ -0,0 +1,22 @@
# replace default config
# multipass: true
# full: true
plugins:
# - name
#
# or:
# - name: false
# - name: true
#
# or:
# - name:
# param1: 1
# param2: 2
- removeAttrs:
attrs:
- 'fill'
- 'fill-rule'

41
src/main.js Normal file
View File

@ -0,0 +1,41 @@
/*
* @Author: wwxin 2463926940@qq.com
* @Date: 2024-06-20 16:13:54
* @LastEditors: wwxin 2463926940@qq.com
* @LastEditTime: 2024-07-03 18:23:00
* @FilePath: /a-vue3 2/src/main.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { createApp } from "vue";
import App from "./App.vue";
import store from './store'
import router from './router'
import './styles/index.scss'; // global css
/* svg */
import 'virtual:svg-icons-register'
import SvgIcon from '@/components/SvgIcon'
import ElementPlus from "element-plus";
import 'element-plus/dist/index.css';
import './styles/element.scss';
import _ from 'lodash';
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import "./assets/rem";
import { Dialog } from 'vant';
import 'vant/lib/index.css';
const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(Dialog);
app.use(store)
app.use(ElementPlus)
// 全局注册 'src/schema/custom/' 目录下的表单自定义组件
app.use(router)
app.config.globalProperties._ = _;
window._ = _;
app.component('svg-icon', SvgIcon)
app.mount("#app");

104
src/router/index.js Normal file
View File

@ -0,0 +1,104 @@
/*
* @Author: wwxin 2463926940@qq.com
* @Date: 2024-06-20 16:54:22
* @LastEditors: wwxin 2463926940@qq.com
* @LastEditTime: 2024-07-25 10:02:14
* @FilePath: /a-vue3 2/src/router/index.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { createWebHistory, createRouter } from 'vue-router'
import _ from 'lodash'
/* Layout */
// 公共路由
export const constantRoutes = [
{
path: '/promotion',
name: 'Promotion',
hidden: true,
component: () => import('@/views/promotion/promotion'),
},
{
path: '/promotionat',
name: 'Promotionat',
hidden: true,
component: () => import('@/views/promotion/promotionat'),
},
{
path: '/agree',
name: 'agree',
hidden: true,
component: () => import('@/views/promotion/agree'),
},
{
path: '/upromotion',
name: 'upromotion',
hidden: true,
component: () => import('@/views/promotion/upromotion'),
},
{
path: '/wxpromotion',
name: 'wxpromotion',
hidden: true,
component: () => import('@/views/promotion/wxpromotion'),
},
{
path: '/wxpromotionx',
name: 'wxpromotionx',
hidden: true,
component: () => import('@/views/promotion/wxpromotionx'),
},
{
path: '/middlePage',
name: 'middlePage',
hidden: true,
component: () => import('@/views/promotion/middlePage'),
},
]
export const asyncRoutes = [
]
// 路由映射表
export const RouteMap = {};
/**
* 初始化路由映射表
* @param {object} route 路由信息
* @param {string} parentPath 父节点的完整路由地址
*/
function initRouteMap(route, parentPath = '') {
const routeName = route.name;
const currentPath = (parentPath + '/' + route.path)
.replace(/\/\//gu, '/')
.replace(/\/$/u, '');
if (routeName) {
RouteMap[routeName] = currentPath;
}
if (!_.isEmpty(route.children)) {
route.children.forEach(item => {
initRouteMap(item, currentPath);
});
}
}
asyncRoutes.forEach(item => initRouteMap(item));
const router = createRouter({
history: createWebHistory(),
routes: constantRoutes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
},
});
export function resetRouter() {
const newRouter = createRouter({
// 路由配置
})
router.matcher = newRouter.matcher
}
export default router;

3
src/store/index.js Normal file
View File

@ -0,0 +1,3 @@
const store = createPinia()
export default store

46
src/store/modules/app.js Normal file
View File

@ -0,0 +1,46 @@
const useAppStore=defineStore('app',{
state:()=>({
sidebar: {
opened: localStorage.getItem('sidebarStatus') ? !!+localStorage.getItem('sidebarStatus') : true,
withoutAnimation: false
},
device: 'desktop',
personCoolDown: []
}),
actions:{
TOGGLE_SIDEBAR() {
this.sidebar.opened = !this.sidebar.opened;
this.sidebar.withoutAnimation = false;
if (this.sidebar.opened) {
localStorage.setItem('sidebarStatus', 1);
} else {
localStorage.setItem('sidebarStatus', 0);
}
},
CLOSE_SIDEBAR( withoutAnimation) {
localStorage.setItem('sidebarStatus', 0);
this.sidebar.opened = false;
this.sidebar.withoutAnimation = withoutAnimation;
},
TOGGLE_DEVICE( device) {
this.device = device;
},
SET_PERSON_COOL_DOWN(list) {
this.personCoolDown = list;
},
toggleSideBar() {
this.TOGGLE_SIDEBAR()
},
closeSideBar({ withoutAnimation }) {
this.CLOSE_SIDEBAR(withoutAnimation)
},
toggleDevice(device) {
this.TOGGLE_DEVICE(device)
}
}
})
export default useAppStore

159
src/styles/common.scss Normal file
View File

@ -0,0 +1,159 @@
$--color-primary: teal;
$--color-success: #0fd2be;
$--color-info: #909399;
$--color-warning: #ff6600;
$--color-error: #ff274b;
html {
overflow: hidden;
height: 100vh;
width: 100vw;
font-size: 54px;
}
body {
font-family: "微软雅黑" !important;
width: 10rem;
}
html,body{
margin: 0 auto !important;
}
button:focus {
outline: none !important;
}
button{
background: transparent;
}
/**
* 修复 dialog双对话框打开 body元素会有个padding-right样式造成页面横向挤压
*/
.el-popup-parent--hidden {
padding-right: 0 !important;
}
.common__wrapper {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
flex: 1;
position: relative;
overflow: visible;
.pagination {
transform: translate(0, 35px);
border-radius: 4px;
}
.common-main__header {
position: absolute;
height: 52px;
width: 100%;
top: 0px;
right: 34px;
display: flex;
justify-content: flex-end;
align-items: center;
z-index: 1;
}
.common-main__main {
position: absolute;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
padding-left: 16px;
padding-right: 32px;
overflow: auto;
}
}
.toolbar {
padding-top: .5rem;
padding-bottom: .5rem;
// background-color: #edf4ff;
flex: 0 1 auto;
flex-direction: column;
align-items: center;
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 10%), 0 1px 2px 0 rgb(0 0 0 / 6%);
border-radius: 4px 4px 0 0;
}
.task-detail__wrapper {
width: 380px;
margin-right: 19px;
}
.title__wrapper {
height: 40px;
width: 100%;
display: flex;
align-items: center;
background-color: #f4f7fe;
&:first-child {
padding-left: 11px;
font-family: SourceHanSansSC-Regular;
font-size: 14px;
font-weight: normal;
font-stretch: normal;
letter-spacing: 0px;
color: #3569e7;
}
}
//定义一个支持公共card-list自适应的todo-list 默认宽度为340 请自行覆盖宽度
.yq-card-list__wrapper {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}
.yq-card-list__item {
width: 320px;
margin: 0 auto;
}
.x-padding-50px {
padding-left: 50px;
padding-right: 50px;
}
.ml16{
margin-left: 16px;
width: calc(100% - 16px) !important;
}
// 类prepend形式的select
.like-prepend-left {
.el-input.is-focus .el-input__inner {
border: none;
}
}
.el-link+.el-link,
.el-link+.el-dropdown {
margin-left: 5px;
}
.el-dropdown .menu-arrow {
transition: all .2s linear;
&.is-active {
transform: rotate(180deg);
}
}
.ellipsis-span {
text-overflow: ellipsis;
white-space: nowrap;
display: block;
max-width: 100%;
overflow: hidden;
}
%no-warp {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

286
src/styles/element-ui.scss Normal file
View File

@ -0,0 +1,286 @@
// cover some element-ui styles
.el-icon-warning {
color: #ff6600;
}
.el-breadcrumb__inner,
.el-breadcrumb__inner a {
font-weight: 400 !important;
}
.el-upload {
input[type="file"] {
display: none !important;
}
}
.el-upload__input {
display: none;
}
// to fixed https://github.com/ElemeFE/element/issues/2461
.el-dialog {
transform: none;
left: 0;
position: relative;
margin: 0 auto;
border-radius: 10px;
.el-dialog__header {
height: 70px;
border-bottom: 1px solid rgba($color: #13325a, $alpha: 0.3);
&::before {
content: '';
display: inline-block;
width: 3px;
height: 34px;
background-color: #3569e7;
position: absolute;
left: 0;
top: 18px;
}
.el-dialog__headerbtn {
font-size: 18px;
top: 25px;
}
}
}
.el-message-box {
border: none !important;
border-radius: 10px;
.el-message-box__header {
height: 70px;
border-bottom: 1px solid rgba($color: #13325a, $alpha: 0.3);
display: flex;
align-items: center;
justify-content: space-between;
&::before {
content: '';
display: inline-block;
width: 3px;
height: 34px;
background-color: #3569e7;
position: absolute;
left: 0;
top: 18px;
}
.el-message-box__headerbtn {
font-size: 18px;
top: 25px;
}
}
.el-message-box__content {
padding-top: 20px;
padding-bottom: 20px;
}
.el-message-box__btns {
.el-button {
border-radius: 16px;
}
}
}
// refine element ui upload
.upload-container {
.el-upload {
width: 100%;
.el-upload-dragger {
width: 100%;
height: 200px;
}
}
}
// dropdown
.el-dropdown-menu {
a {
display: block;
}
}
// to fix el-date-picker css style
.el-range-separator {
box-sizing: content-box;
}
.el-timeline-item__wrapper {
margin-top: 6rem;
}
.el-timeline-item {
max-height: 180px;
box-sizing: border-box;
}
.el-timeline-item__tail {
border-left: 2px solid #2a3a78 !important;
}
.el-timeline-item__node {
top: 6.5rem;
}
.el-timeline .el-timeline-item:last-child .el-timeline-item__tail {
display: block !important;
}
.el-timeline-item__timestamp.is-bottom {
left: -4rem !important;
position: absolute;
margin-top: -5.6rem !important;
}
.el-button {
outline: none !important;
}
.el-button :focus {
outline: none !important;
}
.el-loading-mask svg {
display: inline-block;
}
.el-table {
.el-table__header-wrapper {
thead {
background-color: #ffffff !important;
color: #333333 !important;
}
}
th {
background-color: #f6f8fa !important;
}
.cell {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
}
.el-table__body-wrapper {
background-color: #f7fbff;
}
.el-form .el-form-item__label {
position: relative;
z-index: 1;
}
.el-select {
width: 100%;
}
.el-select .el-select__tags span.el-tag {
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}
.el-select-dropdown {
max-width: 0;
}
.el-table {
td {
border-top: 1px solid transparent;
border-bottom: 1px solid #d3e1ef;
}
.el-table__row {
background-color: #f1f5f9;
}
.el-table__row--striped {
background-color: #f7fbff;
}
.el-table__header-wrapper {
height: 52px;
background-color: #fbfdff;
box-shadow: 0px 0px 4px 0px rgba(190, 211, 235, 0.6);
border-radius: 6px 6px 0px 0px;
tr {
height: 52px;
background-color: #fbfdff;
box-shadow: 0px 0px 4px 0px rgba(190, 211, 235, 0.6);
border-radius: 6px 6px 0px 0px;
}
th {
background-color: #fbfdff !important;
}
}
tr.el-table__row:hover {
background: #e6f1ff;
border-top: 1px solid #8cacf2;
border-bottom: 1px solid #8cacf2;
box-sizing: border-box;
td {
background: #e6f1ff;
border-top: 1px solid #8cacf2;
border-bottom: 1px solid #8cacf2;
box-sizing: border-box;
}
}
&.el-table--striped .el-table__body tr.el-table__row--striped.current-row td,
.el-table__body tr.current-row>td {
background: #e6f1ff;
border-top: 1px solid #8cacf2;
border-bottom: 1px solid #8cacf2;
box-sizing: border-box;
}
}
.el-input__inner {
background-color: #fafcff;
border-radius: 8px;
border: solid 1px #c2d0e2;
}
.el-checkbox__inner {
width: 16px;
height: 16px;
border-radius: 4px;
}
.el-input-number__decrease {
border-radius: 8px 0 0 8px;
}
.el-input-number__increase {
border-radius: 0 8px 8px 0;
}
.el-input-number.is-controls-right .el-input-number__decrease {
border-radius: 0 0 8px 0;
}
.el-input-number.is-controls-right .el-input-number__increase {
border-radius: 0 8px 0 0;
}
.el-range-input,
.el-cascader__search-input {
background-color: #fafcff;
}

28
src/styles/element.scss Normal file
View File

@ -0,0 +1,28 @@
// styles/element/index.scss
/* 只需要重写你需要的即可 */
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
$colors: (
'primary': (
'base': #3569e7
),
'success': (
'base': #0fd2be
),
'warning': (
'base': #ff6600
),
'danger': (
'base': #ff274b
),
'error': (
'base': #ff274b
),
'info': (
'base': #909399
)
),
);
// 如果只是按需导入则可以忽略以下内容
// 如果你想导入所有样式:
@use "element-plus/theme-chalk/src/index.scss" as *;

118
src/styles/index.scss Normal file
View File

@ -0,0 +1,118 @@
@import './common.scss';
@import "./mixin";
@import "./element-ui";
@import "./scroll-bar";
body {
height: 100%;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB,
Microsoft YaHei, Arial, sans-serif;
font-size: 14px;
background-color: #f4f7fe;
line-height: 1.5;
max-width: 100% !important;
}
label {
font-weight: 700;
}
.href-item {
color: #4fd1c5;
text-align: right;
}
html {
height: 100%;
box-sizing: border-box;
}
#app {
height: 102%;
width: 100%;
}
*,
*:before,
*:after {
box-sizing: inherit;
list-style: none;
}
fieldset, ol, ul {
margin: 0;
padding: 0;
}
blockquote, dd, dl, figure, h1, h2, h3, h4, h5, h6, hr, p, pre {
margin: 0;
}
a:focus,
a:active {
outline: none;
}
a,
a:focus,
a:hover {
cursor: pointer;
color: inherit;
text-decoration: none;
}
div:focus {
outline: none;
}
.clearfix {
&:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
}
// main-container global css
.app-container {
padding: 20px;
}
.__object-form-item {
padding: 0 !important;
border: none !important;
.v-layout {
border: none !important;
padding: 8px !important;
.v-layout {
border: none !important;
background-color: #f4f4f5;
border-radius: 4px;
.v-layout {
padding: 0 !important;
.el-form-item {
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
}
}
}
}
}
.el-input-number {
width: 100% !important;
}
}
div[role="tooltip"] {
max-width: 500px;
white-space: pre-wrap;
overflow-wrap: break-word;
}
.flex-1 {
flex: 1 1 0%;
}

28
src/styles/mixin.scss Normal file
View File

@ -0,0 +1,28 @@
@mixin clearfix {
&:after {
content: "";
display: table;
clear: both;
}
}
@mixin scrollBar {
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
@mixin relative {
position: relative;
width: 100%;
height: 100%;
}

View File

@ -0,0 +1,31 @@
@mixin utils-ellipsis($rowCount: 1) {
@if $rowCount <= 1 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} @else {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
word-break: break-all;
-webkit-line-clamp: $rowCount;
-webkit-box-orient: vertical;
}
}
/**
* 自适应的栅格布局通过widthheight 设定内部元素的宽高
* colGap 设定内部元素块的最小列间距
* rowGap 设定内部元素块的最小行间距
*/
@mixin gird-auto($width, $height, $colGap, $rowGap){
display: grid;
grid-template-columns: repeat(auto-fill, $width);
grid-auto-columns: $width;
grid-template-rows: $height;
grid-auto-rows: $height;
grid-column-gap: $colGap;
grid-row-gap: $rowGap;
justify-content: space-between;
}

View File

@ -0,0 +1,17 @@
::-webkit-scrollbar {
width: 2px;
height: 0.25rem;
background-color: transparent;
}
::-webkit-scrollbar-track {
border-radius: 0;
}
::-webkit-scrollbar-thumb {
border-radius: 0;
background-color: #bed0e2;
transition: all 0.2s;
border-radius: 0.25rem;
}
::-webkit-scrollbar-thumb:hover {
background-color: rgba(95, 95, 95, 0.7);
}

View File

@ -0,0 +1,44 @@
import axios from 'axios';
/**
* 根据请求/响应体 生成对应key
* @param {Object} config
*/
function _getKey({ method, url, params = undefined, data = undefined }) {
const formatParam = params ? (typeof params === 'object' ? JSON.stringify(params) : params) : '';
const formatData = data ? (typeof data === 'object' ? JSON.stringify(data) : data) : '';
return `${method}${url}${formatParam}${formatData}`;
}
// 添加请求拦截器
export function filterRepeatRequest(config, httpStore) {
const source = axios.CancelToken.source();
config.cancelToken = source.token;
const useCurrentHttp = typeof config.useCurrentHttp === 'boolean' ? config.useCurrentHttp : true; // 默认取消老的请求
const key = _getKey(config);
// 有重复的请求
if (httpStore.has(key)) {
if (useCurrentHttp) {
// 取消老的请求
httpStore.get(key).cancel();
httpStore.delete(key);
} else {
// 取消当前的请求
source.cancel();
}
} else {
// 没有重复的请求
httpStore.set(key, source);
}
return config;
}
export function filterRepeatResponse(response, httpStore) {
const { config } = response;
const key = _getKey(config);
if (httpStore.has(key)) {
httpStore.delete(key);
}
return response;
}

60
src/utils/tools.js Normal file
View File

@ -0,0 +1,60 @@
/*
* @Author: wwxin 2463926940@qq.com
* @Date: 2023-08-29 14:22:42
* @LastEditors: wwxin 2463926940@qq.com
* @LastEditTime: 2024-07-25 10:09:39
* @FilePath: /vip-server-new/src/utils/tools.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
export function isMobile(value) {
return /^1[3|4|5|6|7|8|9][0-9]\d{8}$/.test(value);
}
export function isIOS() {
return /iPhone|iPad|iPod/i.test(navigator.userAgent);
}
export const showTel = () => {
const telArr = getRandomTel();
const membershipTypes = [
"已领取爱奇艺月卡会员",
"已领取优酷VIP月卡会员",
"已领取芒果TV月卡会员",
"已领取喜马拉雅VIP月卡会员",
"已领取青桔单车月卡会员",
"已领取饿了么月卡会员",
"已领取QQ绿钻月卡会员"
];
return telArr.map((tel, index) => `${tel} ${membershipTypes[index % 7]}`);
};
//联合的
export const showlhTel = () => {
const telArr = getRandomTel();
return telArr.map(tel => `${tel}已领取会员`);
};
export const getRandomTel = () => {
const numArray = [
"139", "138", "137", "136", "135", "134", "159", "158", "157", "150",
"151", "152", "188", "187", "182", "183", "184", "178", "130", "131",
"132", "156", "155", "186", "185", "176", "133", "153", "189", "180",
"181", "177"
];
const numList = [];
const arraryLength = numArray.length;
for (let n = 0; n < 120; n++) {
const prefix = numArray[Math.floor(Math.random() * arraryLength)];
let num = prefix;
for (let j = 0; j < 8; j++) {
num += Math.floor(Math.random() * 10);
}
const maskedNum = `${num.slice(0, 3)}****${num.slice(7)}`;
numList.push(maskedNum);
}
return numList;
};

View File

@ -0,0 +1,90 @@
<!--
* @Author: wwxin 2463926940@qq.com
* @Date: 2024-07-03 13:47:13
* @LastEditors: wwxin 2463926940@qq.com
* @LastEditTime: 2024-07-24 14:01:42
* @FilePath: /a-vue3 2/src/views/promotion/agree.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div>
<div class="nav-header">
<div class="back" @click="$router.go(-1)">返回</div>
<div class="nav-title">{{ titleText }}</div>
</div>
<div v-html="textcontent">
</div>
</div>
</template>
<script setup>
import {resourceAgree} from '@/api/urls'
import { useRouter } from "vue-router";
const $router = useRouter();
const route = useRoute()
let textcontent = $ref("");
let titleText = $ref("");
const showTitleText=()=>{
const promotionId=route.query.promotionId
const specialPromotionIds = ['1780145474481205250', '1779410650476883969'];
const isSpecialPromotion = specialPromotionIds.includes(promotionId);
let type=route.query.type
const titleMap = {
1: {
special: '《蜻蜓FM超级会员自动续费服务协议》',
normal: '《活动规则》'
},
2: {
special: '《蜻蜓FM隐私政策》',
normal: '《隐私政策》'
},
3: {
special: '《蜻蜓FM超级会员服务协议》',
normal: '《会员服务及自动续费协议》'
},
4: {
special: '《蜻蜓FM超级会员自动续费服务协议》',
normal: '《蜻蜓FM超级会员自动续费服务协议》'
}
};
titleText = titleMap[type] ? (isSpecialPromotion ? titleMap[type].special : titleMap[type].normal) : '';
}
onMounted(()=>{
let promotionId=route.query.promotionId
let typesparmes=route.query.type
resourceAgree({promotionId,typesparmes}).then((resp) => {
textcontent=resp.data.result
});
showTitleText()
})
</script>
<style lang="scss" scoped>
.nav-header {
display: flex;
border-bottom: 1px solid #000;
height: 40px;
line-height: 40px;
align-items: center;
justify-content: center;
position: relative;
color: #000;
.nav-title {
font-weight: 600;
font-size: 20px;
margin-left: 15px;
}
.back{
position: absolute;
left: 2%;
text-decoration: underline;
cursor: pointer;
font-size: 16px;
}
}
</style>

View File

@ -0,0 +1,71 @@
<!--
* @Author: wwxin 2463926940@qq.com
* @Date: 2024-07-09 14:51:23
* @LastEditors: wwxin 2463926940@qq.com
* @LastEditTime: 2024-07-25 10:18:10
* @FilePath: /a-vue3 2/src/views/promotion/middlePage.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div class="main">
<div class="btns" @click="openAlipay">点击打开支付宝</div>
</div>
</template>
<script setup>
import { useRouter } from "vue-router";
const $router = useRouter();
const route = useRoute();
const getHttp = () => {
const domainName = window.location.hostname;
if (domainName.indexOf("prom-cdn.xtl10.fun") > -1) {
return "http://47.109.21.59:888";
} else {
return "http://47.109.21.59:889";
}
};
const openAlipay = () => {
let url = getQueryVariable("url");
let scheme = "alipays://platformapi/startapp?appId=20000067&url=" + url;
window.location.href=scheme
};
const getQueryVariable = (variable) => {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
return false;
};
onMounted(() => {});
</script>
<style lang="scss" scoped>
.main {
width: 120%;
height: 100vh;
background: #3875f2;
position: relative;
text-align: center;
.btns {
position: absolute;
border-radius: 0.1rem;
margin: 0 auto;
background: #fff;
width: 80%;
height: 1.2rem;
color: #3d7ceb;
top: 50%;
left: 2%;
text-align: center;
font-weight: bolder;
line-height: 1.2rem;
cursor: pointer;
}
}
</style>

View File

@ -0,0 +1,687 @@
<template>
<div v-if="!htmlLoadFinish" class="whitccc"></div>
<div
v-if="htmlLoadFinish"
class="index-page"
:style="{ backgroundImage: 'url(' + coverImgUrl + ')' }"
>
<div ref="myImg">
<img :src="img1" alt="" class="header-img" />
<img :src="img2" alt="" class="item" />
<van-notice-bar scrollable left-icon="volume-o" v-if="showNoticeBar">
{{ ntext.join("" + longSpace) }}
</van-notice-bar>
</div>
<div class="transaction-view" ref="myTransactionView">
<div class="ipt-view">
<input
placeholder="请输入手机号码"
type="tel"
class="ipt"
maxlength="11"
ref="myInput"
v-model="mobile"
@input="phoneBlur"
v-on:focus="onInputFocus"
/>
</div>
<button
class="trasition-btns"
:style="{ backgroundImage: 'url(' + coverBtnImgUrl + ')' }"
type="button"
@click="submitOrder"
></button>
<div class="agreement-view" style="padding: 0 30px">
<div class="view">
<van-checkbox v-model="isCheck" checked-color="red"
>我已阅读并同意
<a
v-if="agreementOne == 1"
class="agreement"
id="hd"
@click="toAgreePages('hdRule')"
>活动规则</a
>
<a
v-if="agreementTwo == 1"
class="agreement"
id="ys"
@click="toAgreePages('ysRule')"
>隐私政策</a
>
</van-checkbox>
</div>
<div>
<a
v-if="agreementThree == 1"
class="agreement"
id="hy2"
@click="toAgreePages('hyService')"
>会员服务及自动续费协议</a
>
<span v-if="promotionCode != 'RZpJsF'"
>{{ accTxt }}业务资费:<a>{{ price }}</a
>/{{ priceTxt }}</span
>
</div>
</div>
</div>
<img :src="img3" alt="" class="item" />
<div class="rule-content">
<img :src="img4" alt="" class="rule-info" />
</div>
</div>
<van-overlay :show="overlayShow">
<div class="wrapper-div"><van-loading color="#1989fa" size="80" /></div>
</van-overlay>
<van-dialog
v-model:show="showDialogs"
v-if="showDialogs"
:title="dialogTitle"
show-confirm-button
>
<template #default>
<div v-html="richcontent" class="rich-content"></div>
</template>
</van-dialog>
<van-dialog
title="用户协议及隐私保护"
style="width: 85%"
:show-confirm-button="false"
v-model:show="tipsShow"
>
<template #default>
<div class="tip-dialog">
<div class="agreement-view" style="padding: 0 30px">
<div class="view">
我已阅读并同意
<a
v-if="agreementOne == 1"
class="agreement"
id="hd"
@click="toAgreePages('hdRule')"
>活动规则</a
>
<a
v-if="agreementTwo == 1"
class="agreement"
id="ys"
@click="toAgreePages('ysRule')"
>隐私政策</a
>
<a
v-if="agreementThree == 1"
class="agreement"
id="hy2"
@click="toAgreePages('hyService')"
>会员服务及自动续费协议</a
>
<span v-if="promotionCode != 'RZpJsF'"
>{{ accTxt }}业务资费:<a>{{ price }}</a
>/{{ priceTxt }}</span
>
</div>
</div>
<div class="btn-list">
<van-button type="primary" @click="handleAgree('agree')"
>同意并继续</van-button
>
<div class="no-agree" @click="handleAgree('noAgree')">不同意</div>
</div>
</div>
</template>
</van-dialog>
</template>
<script setup name="promotion">
import {
resourceInfo,
resourceAgree,
resourceArea,
proOrder,
resourceAreaDj,
resourceAreaAv,
} from "@/api/urls";
import { isMobile, isIOS, showTel } from "@/utils/tools";
import md5 from "js-md5";
import { showDialog } from "vant";
import { useRouter } from "vue-router";
const longSpace = "\xa0".repeat(10);
let $router = useRouter();
let htmlLoadFinish = ref(false);
let tipsShow = ref(false);
let richcontent = ref("");
let ntext = reactive([]);
let showDialogs = ref(false);
let dialogTitle = ref("");
const promotionCode = ref("");
let img1 = ref("");
let img2 = ref("");
let img3 = ref("");
let img4 = ref("");
let price = ref("14");
let promotionId = ref("");
let priceTxt = ref("月");
let accTxt = ref("开通严选会员,") ;
let delayDay = ref("");
let payMethod = ref("");
let periodPayDays = ref("");
let confirmSwitch = ref("0");
let autoSelect = ref("1");
let callbackUrl = ref("");
let agreementOne = ref("");
let agreementTwo = ref("");
let agreementThree = ref("");
let mobile = ref("");
let isCheck = ref(false);
let overlayShow = ref(false);
let coverImgUrl = ref("");
let coverBtnImgUrl = ref("");
let isTelOrder = ref(false);
let showNoticeBar = ref(true);
//
const handleAgree = (type) => {
if (type === "agree") {
isCheck.value = true;
tipsShow.value = false;
if (isMobile(mobile)) {
resourceArea({ promotionCode: promotionCode.value, tel: mobile }).then(
(resp) => {}
);
submitOrder();
}
} else {
tipsShow.value = false;
}
};
//
const phoneBlur = () => {
if (isMobile(mobile) && autoSelect.value == "1") {
if (isCheck.value == false) {
tipsShow.value = true;
} else {
isCheck.value = true;
resourceArea({ promotionCode: promotionCode.value, tel: mobile }).then(
(resp) => {}
);
submitOrder();
}
}
};
const getUrlParam = () => {
let url = document.location.toString();
let arrObj = url.split("?");
let params = Object.create(null);
if (arrObj.length > 1) {
arrObj = arrObj[1].split("&");
arrObj.forEach((item) => {
item = item.split("=");
params[item[0]] = item[1];
});
}
return params;
};
//agree
const toAgreePages = (types) => {
let typesparmes = types === "hdRule" ? 1 : types === "ysRule" ? 2 : 3;
if (promotionCode.value == "KXYBZU") {
resourceAgree({promotionId:promotionId.value, typesparmes}).then((resp) => {
richcontent.value = resp.data.result;
showDialogs.value = true;
dialogTitle.value =
types === "hdRule"
? "活动规则"
: types === "ysRule"
? "隐私政策"
: "会员服务";
});
return;
}
$router.push(`/agree?promotionId=${promotionId.value}&type=${typesparmes}`);
};
const shouye = () => {
let param = getUrlParam();
resourceInfo({promotionCode:promotionCode.value,...param}).then((resp) => {
if (resp.data.code == "S00000") {
const result = resp.data.result;
document.title = result.name;
const cdnBaseUrl = "https://prom-cdn.xtl10.fun/";
//
coverImgUrl.value = cdnBaseUrl + result.backImg;
img1.value = cdnBaseUrl + result.logoImg;
img2.value = cdnBaseUrl + result.imgOne;
img3.value = cdnBaseUrl + result.imgTwo;
img4.value = cdnBaseUrl + result.imgThree;
coverBtnImgUrl.value = cdnBaseUrl + result.imgXxBtn;
//
payMethod.value = result.payMethod;
price.value = result.price;
delayDay.value = result.delayDay;
periodPayDays.value = result.periodPayDays;
confirmSwitch.value = result.confirmSwitch;
autoSelect.value = result.autoSelect;
callbackUrl.value = result.callbackUrl;
agreementOne.value = result.agreementOne;
agreementTwo.value = result.agreementTwo;
agreementThree.value = result.agreementThree;
promotionId.value= result.promotionId;
mobile.value = result.tepn;
priceTxt.value = result.periodPayDays + "天";
accTxt.value = result.agreementTxt;
if (
promotionCode.value === "afSKPj" ||
promotionCode.value === "MadlRh" ||
promotionCode.value === "oVkHuA"
) {
accTxt.value = "开通VIP会员";
}
let isRend = true;
if (getQueryVariable("phnumber")) {
const mobile = getQueryVariable("phnumber");
if (mobile && mobile.length > 0) {
if (isMobile(mobile)) {
isCheck.value = true;
isTelOrder.value = true;
submitData();
isRend = false;
}
}
}
if (isRend) {
const keyImages = [
{ id: "coverImg", url: coverImgUrl.value },
{ id: "img1", url: img1.value },
{ id: "img2", url: img2.value },
];
const otherImages = [
{ id: "img3", url: img3.value },
{ id: "img4", url: img4.value },
];
const loadImages = (images) => {
return images.map((image) => {
return new Promise((resolve, reject) => {
const imgElement = document.getElementById(image.id);
if (imgElement && image.url) {
const img = new Image();
img.src = image.url;
img.onload = () => {
imgElement.src = image.url;
resolve(image.url);
};
img.onerror = () =>
reject(new Error(`${image.url} load error`));
} else {
resolve(); // imgElement url resolve
}
});
});
};
//
Promise.all(loadImages(keyImages))
.then(() => {
htmlLoadFinish.value = true; //
//
return Promise.all(loadImages(otherImages));
})
.catch((error) => {
console.error(error); //
});
}
}
});
};
//
const maidian = () => {
shouye();
const fpPromise = import(
"https://prom-cdn.xtl10.fun/resources/js/fingerprintjs.js"
).then((FingerprintJS) => FingerprintJS.load());
fpPromise
.then((fp) => fp.get())
.then((result) => {
const visitorId = result.visitorId;
resourceAreaAv({ id: visitorId, promotionCode: promotionCode.value }).then(
(resp) => {}
);
});
};
const getQueryVariable = (variable) => {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
return false;
};
const submitOrder = () => {
if (isCheck.value) {
submitData();
} else {
tipsShow.value = true;
// showToast("");
}
};
/*
* changeURLStatic 修改地址栏URL参数 不跳转
* @param name 参数名
* @param value 参数值
*
* */
const changeURLStatic = (name, value) => {
let url = location.href;
let url2 = "";
let reg = eval("/([?|&]" + name + "=)[^&]*/gi");
value = value.toString().replace(/(^\s*)|(\s*$)/g, ""); //
if (!value) {
url2 = url.replace(reg, ""); //
} else {
if (url.match(reg)) {
url2 = url.replace(reg, "$1" + value); //
} else {
url2 = url + (url.indexOf("?") > -1 ? "&" : "?") + name + "=" + value; //
}
}
history.replaceState(null, null, url2); //
};
const submitData = async () => {
if (!isMobile(mobile.value)) {
showToast("请输入正确的手机号码");
return;
}
let ua = navigator.userAgent.toLowerCase();
try {
$refs.myInput.blur();
} catch {}
let xiayou = getQueryVariable("param");
let extra = getQueryVariable("extra");
//sim
if (extra != "" && xiayou != "") {
xiayou = '{"url" : "' + xiayou + '" , "id" : "' + extra + '"}';
}
if (callbackUrl.value == "Tammy") {
xiayou = window.location.search.substring(1);
}
if (callbackUrl.value == "jietingche") {
xiayou = getQueryVariable("jtcAdRequestId");
}
if (callbackUrl.value == "pp") {
xiayou = getQueryVariable("push_id");
}
let text = `mobile=${ mobile.value}promotionCode=${promotionCode.value}`
if (!isTelOrder.value) {
overlayShow.value = true;
}
let param = {
mobile: mobile.value,
promotionCode: promotionCode.value,
sign: md5(text),
extra: xiayou,
traceId: "323",
};
resourceAreaDj({promotionCode:promotionCode.value}).then((resp) => {});
proOrder(param)
.then((resp) => {
if (resp.data.code == "S00000") {
let jumpp = resp.data.result.payUrl;
if (ua.match(/MicroMessenger/i) == "micromessenger") {
if (payMethod.value == "0" && isIOS()) {
//
jumpp = jumpp.replaceAll(
"https://openapi.alipay.com/gateway.do?",
""
);
}
if (confirmSwitch.value == "1") {
let msgg =
`签约会员自动续费,开通成功后,下一笔扣款预计发生在${ delayDay.value},商户每隔${ periodPayDays.value}天,自动从你的支付宝账户扣款${price.value}`
showDialog({
title: "提示",
message: msgg,
})
.then(() => {
let P = jumpp;
changeURLStatic("phnumber", mobile.value);
hrefurl(P, payMethod.value, isIOS());
})
.catch(() => {});
} else {
changeURLStatic("phnumber", mobile.value);
let P = jumpp;
hrefurl(P, payMethod.value, isIOS());
}
} else {
window.location.href = jumpp;
}
} else {
showDialog({
title: "提示",
message: resp.data.message,
});
}
})
.finally(() => {
setTimeout(function () {
overlayShow.value = false;
}, 1500);
});
};
//
const hrefurl = (p, payMethod, ios) => {
if (ios) {
if (payMethod == "0") {
window.location.href =
"https://ulink.alipay.com/?scheme=" +
encodeURIComponent(
`alipays://platformapi/startapp?appId=60000157&appClearTop=false&startMultApp=YES&sign_params=${encodeURIComponent(
p
)}`
);
} else {
window.location.href =
"https://ulink.alipay.com/?scheme=" +
encodeURIComponent(
`alipays://platformapi/startapp?appId=20000067&url=${encodeURIComponent(
p
)}`
);
}
} else {
let traceId = localStorage.getItem("traceId");
var link = document.createElement("a");
link.href = `${
location.protocol + "//" + location.host
}/static/wechatUrls.txt?payMethod=${payMethod}&url=${encodeURIComponent(
p
)}&promotionCode=${promotionCode.value}`;
link.textContent = "点击这里下载PDF文件";
link.download = "wechatUrls.txt";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
return;
}
};
onMounted(() => {
promotionCode.value = getQueryVariable("promotionCode");
if (promotionCode.value != "RZpJsF") {
ntext = showTel();
} else {
showNoticeBar.value = false;
}
maidian();
});
</script>
<style lang="scss" scoped>
.tip-dialog {
margin: 20px 10px;
padding: 10px 0;
.van-button {
width: 90%;
border-radius: 28px;
height: 65px;
margin: 8px 0;
font-size: 26px;
}
.btn-list {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
.no-agree {
color: #000;
opacity: 0.4;
margin-top: 14px;
font-size: 13px;
}
}
.agreement-view {
align-items: center;
color: #666;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
font-size: 14px;
.agreement {
color: rgb(207, 126, 126);
}
.view {
display: flex;
flex-wrap: wrap;
line-height: 30px;
}
}
}
.rich-content {
padding: 20px;
max-height: 600px;
overflow-y: auto;
}
@keyframes scaleBtn {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
25% {
/* -webkit-transform: scale(.8); */
transform: scale(0.8);
}
50% {
-webkit-transform: scale(1);
transform: scale(1);
}
75% {
-webkit-transform: scale(0.8);
transform: scale(0.8);
}
}
.index-page {
.rule-content {
width: 100%;
.rule-info {
width: 100%;
}
}
.header-img {
width: 100%;
display: block;
}
.item {
width: 100%;
display: block;
}
.transaction-view {
display: flex;
align-items: center;
flex-direction: column;
.ipt-view {
background-color: #fff;
border: 1px solid #ffe1cc;
border-radius: 65px;
display: -ms-flexbox;
display: flex;
height: 54px ;
margin: 15px 0px;
width: 85%;
.ipt {
border: none;
color: #000;
font-size: 22px;
width: 100%;
font-weight: 900;
border-radius: 50%;
padding-left: 20px;
}
}
.trasition-btns {
-webkit-animation: scaleBtn 2s ease-in-out infinite;
animation: scaleBtn 2s ease-in-out infinite;
background-repeat: no-repeat;
background-size: 100% 100%;
display: block;
height: 1.2rem;
margin-bottom: 0.32407rem;
width: 6rem;
border: none;
}
.agreement-view {
align-items: center;
color: #fff;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
font-size: 12px;
::v-deep .van-checkbox__label {
color: #fff !important;
}
.agreement {
color: #fdd599;
}
.view {
display: flex;
align-items: center;
}
}
}
}
.van-toast .van-toast__text {
font-size: 0.37037rem;
padding: 0.27778rem 0;
min-width: 7.40741rem;
}
.notice-p {
display: inline-block;
margin-right: 40px;
}
.wrapper {
display: flex;
align-items: flex-start;
justify-content: flex-end;
height: 100%;
}
.whitccc {
height: 100vh;
width: 100vw;
background-color: #fff;
}
.wrapper-div {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
</style>

View File

@ -0,0 +1,660 @@
<template>
<div v-if="!htmlLoadFinish" class="whitccc"></div>
<div
v-if="htmlLoadFinish"
class="index-page"
:style="{ backgroundImage: 'url(' + coverImgUrl + ')' }"
>
<div ref="myImg">
<img :src="img1" alt="" class="header-img" />
<img :src="img2" alt="" class="item" />
<van-notice-bar scrollable left-icon="volume-o" v-if="showNoticeBar">
{{ ntext.join("" + longSpace) }}
</van-notice-bar>
</div>
<div class="transaction-view" ref="myTransactionView">
<!-- <div class="ipt-view">
<input
placeholder="请输入手机号码"
type="tel"
class="ipt"
maxlength="11"
ref="myInput"
v-model="mobile"
@input="phoneBlur"
v-on:focus="onInputFocus"
/>
</div> -->
<button
class="trasition-btns"
:style="{ backgroundImage: 'url(' + coverBtnImgUrl + ')' }"
type="button"
@click="submitOrder"
></button>
<div class="agreement-view" style="padding: 0 30px">
<div class="view">
<van-checkbox v-model="isCheck" checked-color="red"
>我已阅读并同意
<a
v-if="agreementOne == 1"
class="agreement"
id="hd"
@click="toAgreePages('hdRule')"
>活动规则</a
>
<a
v-if="agreementTwo == 1"
class="agreement"
id="ys"
@click="toAgreePages('ysRule')"
>隐私政策</a
>
</van-checkbox>
</div>
<div>
<a
v-if="agreementThree == 1"
class="agreement"
id="hy2"
@click="toAgreePages('hyService')"
>会员服务及自动续费协议</a
>
<span v-if="promotionCode != 'RZpJsF'"
>{{ accTxt }}业务资费:<a>{{ price }}</a
>/{{ priceTxt }}</span
>
</div>
</div>
</div>
<img :src="img3" alt="" class="item" />
<div class="rule-content">
<img :src="img4" alt="" class="rule-info" />
</div>
</div>
<van-overlay :show="overlayShow">
<div class="wrapper-div"><van-loading color="#1989fa" size="80" /></div>
</van-overlay>
<van-dialog
v-model:show="showDialogs"
v-if="showDialogs"
:title="dialogTitle"
show-confirm-button
>
<template #default>
<div v-html="richcontent" class="rich-content"></div>
</template>
</van-dialog>
<van-dialog
title="用户协议及隐私保护"
style="width: 85%"
:show-confirm-button="false"
v-model:show="tipsShow"
>
<template #default>
<div class="tip-dialog">
<div class="agreement-view" style="padding: 0 30px">
<div class="view">
我已阅读并同意
<a
v-if="agreementOne == 1"
class="agreement"
id="hd"
@click="toAgreePages('hdRule')"
>活动规则</a
>
<a
v-if="agreementTwo == 1"
class="agreement"
id="ys"
@click="toAgreePages('ysRule')"
>隐私政策</a
>
<a
v-if="agreementThree == 1"
class="agreement"
id="hy2"
@click="toAgreePages('hyService')"
>会员服务及自动续费协议</a
>
<span v-if="promotionCode != 'RZpJsF'"
>{{ accTxt }}业务资费:<a>{{ price }}</a
>/{{ priceTxt }}</span
>
</div>
</div>
<div class="btn-list">
<van-button type="primary" @click="handleAgree('agree')"
>同意并继续</van-button
>
<div class="no-agree" @click="handleAgree('noAgree')">不同意</div>
</div>
</div>
</template>
</van-dialog>
</template>
<script setup name="promotion">
import {
resourceInfo,
resourceAgree,
resourceArea,
proOrder,
resourceAreaDj,
resourceAreaAv,
} from "@/api/urls";
import { isMobile, isIOS, showTel } from "@/utils/tools";
import md5 from "js-md5";
import { showDialog } from "vant";
import { useRouter } from "vue-router";
const longSpace = "\xa0".repeat(10);
let $router = useRouter();
let htmlLoadFinish = ref(false);
let tipsShow = ref(false);
let richcontent = ref("");
let ntext = reactive([]);
let showDialogs = ref(false);
let dialogTitle = ref("");
let promotionCode = ref("");
let img1 = ref("");
let img2 = ref("");
let img3 = ref("");
let img4 = ref("");
let price = ref("14");
let promotionId = ref("");
let priceTxt = ref("月");
let accTxt = "开通严选会员,";
let delayDay = ref("");
let payMethod = ref("");
let periodPayDays = ref("");
let confirmSwitch = ref("0");
let callbackUrl = ref("");
let agreementOne = ref("");
let agreementTwo = ref("");
let agreementThree = ref("");
let mobile = ref("19999999999");
let isCheck = ref(false);
let overlayShow = ref(false);
let coverImgUrl = ref("");
let coverBtnImgUrl = ref("");
let isTelOrder = ref(false);
let showNoticeBar = ref(true);
//
const handleAgree = (type) => {
if (type === "agree") {
isCheck.value = true;
tipsShow.value = false;
if (isMobile(mobile.value)) {
resourceArea({ promotionCode: promotionCode.value, tel: mobile.value }).then(
(resp) => {}
);
submitOrder();
}
} else {
tipsShow.value = false;
}
};
const getUrlParam = () => {
let url = document.location.toString();
let arrObj = url.split("?");
let params = Object.create(null);
if (arrObj.length > 1) {
arrObj = arrObj[1].split("&");
arrObj.forEach((item) => {
item = item.split("=");
params[item[0]] = item[1];
});
}
return params;
};
//agree
const toAgreePages = (types) => {
let typesparmes = types === "hdRule" ? 1 : types === "ysRule" ? 2 : 3;
$router.push(`/agree?promotionId=${promotionId.value}&type=${typesparmes}`);
};
const shouye = () => {
let param = getUrlParam();
resourceInfo({promotionCode:promotionCode.value,...param}).then((resp) => {
if (resp.data.code == "S00000") {
const result = resp.data.result;
document.title = result.name;
const cdnBaseUrl = "https://prom-cdn.xtl10.fun/";
//
coverImgUrl.value = cdnBaseUrl + result.twoBackImg;
img1.value = cdnBaseUrl + result.twoLogoImg;
img2.value = cdnBaseUrl + result.twoImgOne;
img3.value = cdnBaseUrl + result.twoImgTwo;
img4.value = cdnBaseUrl + result.twoImgThree;
coverBtnImgUrl.value = cdnBaseUrl + result.twoImgXxBtn;
//
payMethod.value = result.payMethod;
price.value = result.price;
delayDay.value = result.delayDay;
periodPayDays.value = result.periodPayDays;
confirmSwitch.value = result.confirmSwitch;
callbackUrl.value= result.callbackUrl;
agreementOne.value = result.agreementOne;
agreementTwo.value = result.agreementTwo;
agreementThree.value = result.agreementThree;
promotionId.value = result.promotionId;
mobile.value = result.tepn ||'19999999999';
priceTxt.value = result.periodPayDays + "天";
accTxt = result.agreementTxt;
if (
promotionCode.value === "afSKPj" ||
promotionCode.value === "MadlRh" ||
promotionCode.value === "oVkHuA"
) {
accTxt = "VIP";
}
let isRend = true;
if (getQueryVariable("phnumber")) {
mobile = getQueryVariable("phnumber");
if (mobile && mobile.length > 0) {
if (isMobile(mobile)) {
isCheck.value = true;
isTelOrder.value = true;
submitData();
isRend = false;
}
}
}
if (isRend) {
const keyImages = [
{ id: "coverImg", url: coverImgUrl.value },
{ id: "img1", url: img1.value },
{ id: "img2", url: img2.value },
];
const otherImages = [
{ id: "img3", url: img3.value },
{ id: "img4", url: img4.value },
];
const loadImages = (images) => {
return images.map((image) => {
return new Promise((resolve, reject) => {
const imgElement = document.getElementById(image.id);
if (imgElement && image.url) {
const img = new Image();
img.src = image.url;
img.onload = () => {
imgElement.src = image.url;
resolve(image.url);
};
img.onerror = () =>
reject(new Error(`${image.url} load error`));
} else {
resolve(); // imgElement url resolve
}
});
});
};
//
Promise.all(loadImages(keyImages))
.then(() => {
htmlLoadFinish.value = true; //
//
return Promise.all(loadImages(otherImages));
})
.catch((error) => {
console.error(error); //
});
}
}
});
};
//
const maidian = () => {
shouye();
const fpPromise = import(
"https://prom-cdn.xtl10.fun/resources/js/fingerprintjs.js"
).then((FingerprintJS) => FingerprintJS.load());
fpPromise
.then((fp) => fp.get())
.then((result) => {
const visitorId = result.visitorId;
resourceAreaAv({ id: visitorId, promotionCode: promotionCode.value }).then(
(resp) => {}
);
});
};
const getQueryVariable = (variable) => {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
return false;
};
const submitOrder = () => {
if (isCheck.value) {
submitData();
} else {
tipsShow.value = true;
// showToast("");
}
};
/*
* changeURLStatic 修改地址栏URL参数 不跳转
* @param name 参数名
* @param value 参数值
*
* */
const changeURLStatic = (name, value) => {
let url = location.href;
let url2 = "";
let reg = eval("/([?|&]" + name + "=)[^&]*/gi");
value = value.toString().replace(/(^\s*)|(\s*$)/g, ""); //
if (!value) {
url2 = url.replace(reg, ""); //
} else {
if (url.match(reg)) {
url2 = url.replace(reg, "$1" + value); //
} else {
url2 = url + (url.indexOf("?") > -1 ? "&" : "?") + name + "=" + value; //
}
}
history.replaceState(null, null, url2); //
};
const submitData = async () => {
let mobiles = mobile.value;
if (!isMobile(mobiles)) {
showToast("请输入正确的手机号码");
return;
}
let ua = navigator.userAgent.toLowerCase();
try {
$refs.myInput.blur();
} catch {}
let xiayou = getQueryVariable("param");
let extra = getQueryVariable("extra");
//sim
if (extra != "" && xiayou != "") {
xiayou = '{"url" : "' + xiayou + '" , "id" : "' + extra + '"}';
}
if (callbackUrl.value == "Tammy") {
xiayou = window.location.search.substring(1);
}
if (callbackUrl.value == "jietingche") {
xiayou = getQueryVariable("jtcAdRequestId");
}
if (callbackUrl.value == "pp") {
xiayou = getQueryVariable("push_id");
}
let text =`mobile=${mobiles}promotionCode=${promotionCode.value}`
if (!isTelOrder.value) {
overlayShow.value = true;
}
let param = {
mobile: mobiles,
promotionCode: promotionCode.value,
sign: md5(text),
extra: xiayou,
traceId: "323",
};
resourceAreaDj({promotionCode:promotionCode.value}).then((resp) => {});
proOrder(param)
.then((resp) => {
if (resp.data.code == "S00000") {
let jumpp = resp.data.result.payUrl;
if (ua.match(/MicroMessenger/i) == "micromessenger") {
if (payMethod.value == "0" && isIOS()) {
//
jumpp = jumpp.replaceAll(
"https://openapi.alipay.com/gateway.do?",
""
);
}
if (confirmSwitch.value == "1") {
let msgg =
`签约会员自动续费,开通成功后,下一笔扣款预计发生在${delayDay.value},商户将每隔${periodPayDays.value}天,自动从你的支付宝账户扣款${price.value}`
showDialog({
title: "提示",
message: msgg,
})
.then(() => {
let P = jumpp;
changeURLStatic("phnumber", mobiles);
hrefurl(P, payMethod.value, isIOS());
})
.catch(() => {});
} else {
changeURLStatic("phnumber", mobiles);
let P = jumpp;
hrefurl(P, payMethod.value, isIOS());
}
} else {
window.location.href = jumpp;
}
} else {
showDialog({
title: "提示",
message: resp.data.message,
});
}
})
.finally(() => {
setTimeout(function () {
overlayShow.value = false;
}, 1500);
});
};
//
const hrefurl = (p, payMethod, ios) => {
if (ios) {
if (payMethod == "0") {
window.location.href =
"https://ulink.alipay.com/?scheme=" +
encodeURIComponent(
`alipays://platformapi/startapp?appId=60000157&appClearTop=false&startMultApp=YES&sign_params=${encodeURIComponent(
p
)}`
);
} else {
window.location.href =
"https://ulink.alipay.com/?scheme=" +
encodeURIComponent(
`alipays://platformapi/startapp?appId=20000067&url=${encodeURIComponent(
p
)}`
);
}
} else {
let traceId = localStorage.getItem("traceId");
var link = document.createElement("a");
link.href = `${
location.protocol + "//" + location.host
}/static/wechatUrls.txt?payMethod=${payMethod.value}&url=${encodeURIComponent(
p
)}&promotionCode=${promotionCode.value}`;
link.textContent = "点击这里下载PDF文件";
link.download = "wechatUrls.txt";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
return;
}
};
onMounted(() => {
promotionCode.value = getQueryVariable("promotionCode");
if (promotionCode.value != "RZpJsF") {
ntext = showTel();
} else {
showNoticeBar.value = false;
}
maidian();
});
</script>
<style lang="scss" scoped>
.tip-dialog {
margin: 20px 10px;
padding: 10px 0;
.van-button {
width: 90%;
border-radius: 28px;
height: 65px;
margin: 8px 0;
font-size: 26px;
}
.btn-list {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
.no-agree {
color: #000;
opacity: 0.4;
margin-top: 14px;
font-size: 13px;
}
}
.agreement-view {
align-items: center;
color: #666;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
font-size: 14px;
.agreement {
color: rgb(207, 126, 126);
}
.view {
display: flex;
flex-wrap: wrap;
line-height: 30px;
}
}
}
.rich-content {
padding: 20px;
max-height: 600px;
overflow-y: auto;
}
@keyframes scaleBtn {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
25% {
/* -webkit-transform: scale(.8); */
transform: scale(0.8);
}
50% {
-webkit-transform: scale(1);
transform: scale(1);
}
75% {
-webkit-transform: scale(0.8);
transform: scale(0.8);
}
}
.index-page {
.rule-content {
width: 100%;
.rule-info {
width: 100%;
}
}
.header-img {
width: 100%;
display: block;
}
.item {
width: 100%;
display: block;
}
.transaction-view {
display: flex;
align-items: center;
flex-direction: column;
.ipt-view {
background-color: #fff;
border: 1px solid #ffe1cc;
border-radius: 65px;
display: -ms-flexbox;
display: flex;
height: 54px ;
margin: 15px 0px;
width: 85%;
.ipt {
border: none;
color: #000;
font-size: 22px;
width: 100%;
font-weight: 900;
border-radius: 50%;
padding-left: 20px;
}
}
.trasition-btns {
-webkit-animation: scaleBtn 2s ease-in-out infinite;
animation: scaleBtn 2s ease-in-out infinite;
background-repeat: no-repeat;
background-size: 100% 100%;
display: block;
height: 1.2rem;
margin-bottom: 0.32407rem;
width: 6rem;
border: none;
}
.agreement-view {
align-items: center;
color: #fff;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
font-size: 12px;
::v-deep .van-checkbox__label {
color: #fff !important;
}
.agreement {
color: #fdd599;
}
.view {
display: flex;
align-items: center;
}
}
}
}
.van-toast .van-toast__text {
font-size: 0.37037rem;
padding: 0.27778rem 0;
min-width: 7.40741rem;
}
.notice-p {
display: inline-block;
margin-right: 40px;
}
.wrapper {
display: flex;
align-items: flex-start;
justify-content: flex-end;
height: 100%;
}
.whitccc {
height: 100vh;
width: 100vw;
background-color: #fff;
}
.wrapper-div {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
</style>

View File

@ -0,0 +1,611 @@
<template>
<div
class="index-page"
:style="{ backgroundImage: 'url(' + coverImgUrl + ')' }"
>
<div class="hdgz" v-if="agreementOne == 1" @click="toAgreePages('hdRule')">
活动规则
</div>
<div ref="myImg">
<img :src="img1" alt="" class="header-img" />
<img :src="img2" alt="" class="item" />
<van-notice-bar scrollable left-icon="volume-o" v-if="showNoticeBar">
{{ ntext.join("" + longSpace) }}
</van-notice-bar>
</div>
<div class="transaction-view" ref="myTransactionView">
<div class="ipt-view">
<input
placeholder="请输入手机号码"
type="tel"
class="ipt"
maxlength="11"
ref="myInput"
v-model="mobile"
@input="phoneBlur"
/>
</div>
<button
class="trasition-btns"
:style="{ backgroundImage: 'url(' + coverBtnImgUrl + ')' }"
type="button"
@click="submitOrder"
></button>
<div class="agreement-view" style="padding: 0 30px">
<div class="view">
<van-checkbox v-model="isCheck" checked-color="red"
>我已阅读并同意
<a
v-if="agreementTwo == 1"
class="agreement"
id="ys"
@click="toAgreePages('ysRule')"
>隐私政策</a
>
<a
v-if="agreementThree == 1"
class="agreement"
@click="toAgreePages('hyService')"
id="hy"
>会员服务协议</a
>
<a
v-if="agreementFour == 1"
class="agreement"
id="hd"
@click="toAgreePages('zdxfService')"
>自动续费协议</a
>并同意购买自动续费商品
</van-checkbox>
</div>
<span v-if="promotionCode != 'RZpJsF'"
>{{ accTxt }}业务资费:<a>{{ price }}</a
>/{{ priceTxt }}</span
>
<div v-if="promotionCode == 'RZpJsF'">首月19.9元次月29.9元</div>
</div>
</div>
<img :src="img3" alt="" class="item" />
<div class="rule-content">
<img :src="img4" alt="" class="rule-info" />
</div>
</div>
<van-overlay :show="overlayShow">
<div class="wrapper-div"><van-loading color="#1989fa" size="80" /></div>
</van-overlay>
<van-dialog
title="用户协议及隐私保护"
style="width: 85%"
:show-confirm-button="false"
v-model:show="tipsShow"
>
<template #default>
<div class="tip-dialog">
<div class="agreement-view" style="padding: 0 30px">
<div class="view">
我已阅读并同意
<a
v-if="agreementTwo == 1"
class="agreement"
id="ys"
@click="toAgreePages('ysRule')"
>隐私政策</a
>
<a
v-if="agreementThree == 1"
class="agreement"
@click="toAgreePages('hyService')"
id="hy"
>会员服务协议</a
>
<a
v-if="agreementFour == 1"
class="agreement"
id="hd"
@click="toAgreePages('zdxfService')"
>自动续费协议</a
>并同意购买自动续费商品
</div>
</div>
<div class="btn-list">
<van-button type="primary" @click="handleAgree('agree')"
>同意并继续</van-button
>
<div class="no-agree" @click="handleAgree('noAgree')">不同意</div>
</div>
</div>
</template>
</van-dialog>
</template>
<script setup name="promotion">
import { showlhTel, isIOS, isMobile } from "@/utils/tools";
import {
resourceInfo,
resourceArea,
resourceAreaDj,
resourceAreaAv,
creatUnion,
} from "@/api/urls";
import md5 from "js-md5";
import { useRouter } from "vue-router";
const longSpace = "\xa0".repeat(10);
let $router = useRouter();
import { showDialog } from "vant";
let ntext = $ref([]);
let tipsShow = $ref(false);
let promotionCode = ref("");
let img1 = ref("");
let img2 = ref("");
let img3 = ref("");
let img4 = ref("");
let price = ref("14");
let priceTxt = ref("月");
let accTxt = ref("开通严选会员,");
let delayDay = ref("");
let payMethod = ref("0");
let periodPayDays = ref("");
let confirmSwitch = ref("0");
let autoSelect = ref("1");
let agreementOne = ref("");
let agreementTwo = ref("");
let agreementThree = ref("");
let agreementFour = ref("");
let mobile = ref("");
let isCheck = ref(false);
let overlayShow = ref(false);
let coverImgUrl = ref("");
let showNoticeBar = ref(true);
let coverBtnImgUrl = ref("");
let traceId = $ref("");
let unionType = ref("");
let promotionId = ref("");
const phoneBlur = () => {
if (isMobile(mobile.value)) {
if (isCheck.value == false) {
tipsShow = true;
} else {
isCheck.value = true;
resourceArea({
union: 1,
promotionCode: promotionCode.value,
tel: mobile.value,
}).then((resp) => {});
submitOrder();
}
}
};
//
const handleAgree = (type) => {
if (type === "agree") {
isCheck.value = true;
tipsShow = false;
if (isMobile(mobile.value)) {
resourceArea({
union: 1,
promotionCode: promotionCode.value,
tel: mobile.value,
}).then((resp) => {});
submitOrder();
}
} else {
tipsShow = false;
}
};
//agree
const toAgreePages = (types) => {
let typesparmes =
types === "hdRule"
? 1
: types === "ysRule"
? 2
: types === "hyService"
? 3
: 4;
$router.push(`/agree?promotionId=${promotionId.value}&type=${typesparmes}`);
};
const shouye = () => {
resourceInfo({promotionCode:promotionCode.value}).then((resp) => {
if (resp.data.code == "S00000") {
const result = resp.data.result;
document.title = result.name;
const cdnBaseUrl = "https://prom-cdn.xtl10.fun/";
//
coverImgUrl.value = cdnBaseUrl + result.backImg;
img1.value = cdnBaseUrl + result.logoImg;
img2.value = cdnBaseUrl + result.imgOne;
img3.value = cdnBaseUrl + result.imgTwo;
img4.value = cdnBaseUrl + result.imgThree;
coverBtnImgUrl.value = cdnBaseUrl + result.imgXxBtn;
//
payMethod.value = result.payMethod || "0";
price.value = result.price;
delayDay.value = result.delayDay;
periodPayDays.value = result.periodPayDays;
confirmSwitch.value = result.confirmSwitch;
autoSelect.value = result.autoSelect;
agreementOne.value = result.agreementOne;
agreementTwo.value = result.agreementTwo;
agreementThree.value = result.agreementThree;
agreementFour.value = result.agreementFour;
promotionId.value = result.promotionId;
//广-
unionType.value = result.unionType;
if (result.periodPayDays) {
priceTxt.value =`${result.periodPayDays}`
}
accTxt.value = result.agreementTxt;
if (
promotionCode.value == "afSKPj" ||
promotionCode.value == "MadlRh" ||
promotionCode.value == "oVkHuA"
) {
accTxt.value = "VIP";
}
if (getQueryVariable("phnumber")) {
const mobile1 = getQueryVariable("phnumber");
if (isMobile(mobile1) && autoSelect.value == "1") {
isCheck.value = true;
submitData();
}
}
}
});
};
const maidian = () => {
shouye();
const fpPromise = import(
"https://prom-cdn.xtl10.fun/resources/js/fingerprintjs.js"
).then((FingerprintJS) => FingerprintJS.load());
fpPromise
.then((fp) => fp.get())
.then((result) => {
const visitorId = result.visitorId;
resourceAreaAv({ id: visitorId, promotionCode: promotionCode.value }).then(
(resp) => {}
);
});
};
const getQueryVariable = (variable) => {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
return false;
};
const submitOrder = () => {
if (isCheck.value) {
submitData();
} else {
tipsShow = true;
//showToast("");
}
};
/*
* changeURLStatic 修改地址栏URL参数 不跳转
* @param name 参数名
* @param value 参数值
*
* */
const changeURLStatic = (name, value) => {
let url = location.href;
let url2 = "";
let reg = eval("/([?|&]" + name + "=)[^&]*/gi");
value = value.toString().replace(/(^\s*)|(\s*$)/g, ""); //
if (!value) {
url2 = url.replace(reg, ""); //
} else {
if (url.match(reg)) {
url2 = url.replace(reg, "$1" + value); //
} else {
url2 = url + (url.indexOf("?") > -1 ? "&" : "?") + name + "=" + value; //
}
}
history.replaceState(null, null, url2); //
};
const submitData = async () => {
let mobiles = mobile.value;
if (!isMobile(mobiles)) {
showToast("请输入正确的手机号码");
return;
}
let ua = navigator.userAgent.toLowerCase();
let xiayou = getQueryVariable("param");
let text = `mobile=${mobiles}promotionCode=${promotionCode.value}`
overlayShow.value = true;
let param = {
mobile: mobiles,
promotionCode: promotionCode.value,
sign: md5(text),
extra: xiayou,
};
resourceAreaDj({ union: 1, promotionCode: promotionCode.value }).then((resp) => {});
creatUnion(param)
.then((resp) => {
if (resp.data.code == "S00000") {
let jumpp = resp.data.result.payUrl;
let youkuurl = resp.data.result.jumpUrl;
if (ua.match(/MicroMessenger/i) == "micromessenger") {
//
// if (unionType == 2) {
// window.location.href = youkuurl;
// return;
// }
if (payMethod.value == "0") {
jumpp = jumpp.replaceAll(
"https://openapi.alipay.com/gateway.do?",
""
);
}
if (confirmSwitch.value == "1") {
let msgg =
`签约会员自动续费,开通成功后,下一笔扣款预计发生在${delayDay.value},商户将每隔${periodPayDays.value}天,自动从你的支付宝账户扣款${price.value}`
showDialog({
title: "提示",
message: msgg,
})
.then(() => {
let P = jumpp;
changeURLStatic("phnumber", mobiles);
hrefurl(P, payMethod.value, isIOS());
})
.catch(() => {});
} else {
changeURLStatic("phnumber", mobiles);
let P = jumpp;
hrefurl(P, payMethod.value, isIOS());
}
} else {
//
if (unionType.value == 2) {
window.location.href = youkuurl;
return;
}
window.location.href = jumpp;
}
getBurialPoint(1100);
} else {
showToast(resp.data.message);
}
})
.finally(() => {
setTimeout(function () {
overlayShow.value = false;
}, 1500);
});
};
const hrefurl = (p, payMethod, ios) => {
if (ios) {
if (payMethod == "0") {
window.location.href =
"https://ulink.alipay.com/?scheme=" +
encodeURIComponent(
`alipays://platformapi/startapp?appId=60000157&appClearTop=false&startMultApp=YES&sign_params=${encodeURIComponent(
p
)}`
);
} else {
window.location.href =
"https://ulink.alipay.com/?scheme=" +
encodeURIComponent(
`alipays://platformapi/startapp?appId=20000067&url=${encodeURIComponent(
p
)}`
);
}
} else {
let traceId = localStorage.getItem("traceId");
var link = document.createElement("a");
link.href = `${
location.protocol + "//" + location.host
}/static/wechatUrls.txt?payMethod=${payMethod}&url=${encodeURIComponent(
p
)}&promotionCode=${promotionCode.value}`;
link.textContent = "点击这里下载PDF文件";
link.download = "wechatUrls.txt";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
return;
}
};
onMounted(() => {
promotionCode.value = getQueryVariable("promotionCode");
if (promotionCode.value != "RZpJsF") {
ntext = showlhTel();
} else {
showNoticeBar.value = false;
}
maidian();
});
</script>
<style lang="scss" scoped>
.tip-dialog {
margin: 20px 10px;
padding: 10px 0;
.van-button {
width: 90%;
border-radius: 28px;
height: 65px;
margin: 8px 0;
font-size: 26px;
}
.btn-list {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
.no-agree {
color: #000;
opacity: 0.4;
margin-top: 14px;
font-size: 13px;
}
}
.agreement-view {
align-items: center;
color: #666;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
font-size: 14px;
.agreement {
color: rgb(207, 126, 126);
}
.view {
line-height: 30px;
}
}
}
.rich-content {
padding: 20px;
max-height: 600px;
overflow-y: auto;
}
@keyframes scaleBtn {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
25% {
/* -webkit-transform: scale(.8); */
transform: scale(0.8);
}
50% {
-webkit-transform: scale(1);
transform: scale(1);
}
75% {
-webkit-transform: scale(0.8);
transform: scale(0.8);
}
}
.index-page {
position: relative;
.hdgz {
writing-mode: vertical-rl;
text-orientation: upright;
width: 40px;
height: 120px;
background: rgba(51, 51, 51, 0.6);
border-radius: 6px;
font-size: 24px;
color: #fff;
line-height: 26px;
text-align: center;
position: absolute;
top: 60px;
right: 12px;
padding: 6px;
}
.rule-content {
width: 100%;
.rule-info {
width: 100%;
}
}
.header-img {
width: 100%;
display: block;
}
.item {
width: 100%;
display: block;
}
.transaction-view {
display: flex;
align-items: center;
flex-direction: column;
.ipt-view {
background-color: #fff;
border: 1px solid #ffe1cc;
border-radius: 65px;
display: -ms-flexbox;
display: flex;
height: 54px;
margin: 15px 0px;
width: 85%;
.ipt {
border: none;
color: #000;
font-size: 24px;
width: 100%;
font-weight: 900;
border-radius: 50%;
padding-left: 20px;
}
}
.trasition-btns {
-webkit-animation: scaleBtn 2s ease-in-out infinite;
animation: scaleBtn 2s ease-in-out infinite;
background-repeat: no-repeat;
background-size: 100% 100%;
display: block;
height: 1.2rem;
margin-bottom: 0.32407rem;
width: 6rem;
border: none;
}
.agreement-view {
align-items: center;
color: #fff;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
font-size: 12px;
::v-deep .van-checkbox__label {
color: #fff !important;
}
.agreement {
color: #fdd599;
}
.view {
display: flex;
align-items: center;
}
}
}
}
.van-toast .van-toast__text {
font-size: 0.37037rem;
padding: 0.27778rem 0;
min-width: 7.40741rem;
}
.notice-p {
display: inline-block;
margin-right: 40px;
}
.wrapper {
display: flex;
align-items: flex-start;
justify-content: flex-end;
height: 100%;
}
.whitccc {
height: 100vh;
width: 100vw;
background-color: #fff;
}
.wrapper-div {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
</style>

View File

@ -0,0 +1,683 @@
<template>
<div v-if="!htmlLoadFinish" class="whitccc"></div>
<div
v-if="htmlLoadFinish"
class="index-page"
:style="{ backgroundImage: 'url(' + coverImgUrl + ')' }"
>
<div ref="myImg">
<img :src="img1" alt="" class="header-img" />
<img :src="img2" alt="" class="item" />
<van-notice-bar scrollable left-icon="volume-o">
{{ ntext.join("" + longSpace) }}
</van-notice-bar>
</div>
<div class="transaction-view" ref="myTransactionView">
<div class="ipt-view">
<input
placeholder="请输入手机号码"
type="tel"
class="ipt"
maxlength="11"
ref="myInput"
v-model="mobile"
@input="phoneBlur"
v-on:focus="onInputFocus"
/>
</div>
<button
class="trasition-btns"
:style="{ backgroundImage: 'url(' + coverBtnImgUrl + ')' }"
type="button"
@click="submitOrder"
></button>
<div class="agreement-view" style="padding: 0 30px">
<div class="view">
<van-checkbox v-model="isCheck" checked-color="red"
>我已阅读并同意
<a
v-if="agreementOne == 1"
class="agreement"
id="hd"
@click="toAgreePages('hdRule')"
>活动规则</a
>
<a
v-if="agreementTwo == 1"
class="agreement"
id="ys"
@click="toAgreePages('ysRule')"
>隐私政策</a
>
</van-checkbox>
</div>
<div>
<a
v-if="agreementThree == 1"
class="agreement"
id="hy2"
@click="toAgreePages('hyService')"
>会员服务及自动续费协议</a
>
协议
<span v-if="promotionCode != 'RZpJsF'"
>{{ accTxt }}业务资费:<a>{{ price }}</a
>/{{ priceTxt }}</span
>
</div>
</div>
</div>
<img :src="img3" alt="" class="item" />
<div class="rule-content">
<img :src="img4" alt="" class="rule-info" />
</div>
</div>
<van-overlay :show="overlayShow">
<div class="wrapper-div"><van-loading color="#1989fa" size="80" /></div>
</van-overlay>
<van-dialog
v-model:show="showDialogs"
v-if="showDialogs"
:title="dialogTitle"
show-confirm-button
>
<template #default>
<div v-html="richcontent" class="rich-content"></div>
</template>
</van-dialog>
<van-dialog
title="用户协议及隐私保护"
style="width: 85%"
:show-confirm-button="false"
v-model:show="tipsShow"
>
<template #default>
<div class="tip-dialog">
<div class="agreement-view" style="padding: 0 30px">
<div class="view">
我已阅读并同意
<a
v-if="agreementOne == 1"
class="agreement"
id="hd"
@click="toAgreePages('hdRule')"
>活动规则</a
>
<a
v-if="agreementTwo == 1"
class="agreement"
id="ys"
@click="toAgreePages('ysRule')"
>隐私政策</a
>
<a
v-if="agreementThree == 1"
class="agreement"
id="hy2"
@click="toAgreePages('hyService')"
>会员服务及自动续费协议</a
>
<span v-if="promotionCode != 'RZpJsF'"
>{{ accTxt }}业务资费:<a>{{ price }}</a
>/{{ priceTxt }}</span
>
</div>
</div>
<div class="btn-list">
<van-button type="primary" @click="handleAgree('agree')"
>同意并继续</van-button
>
<div class="no-agree" @click="handleAgree('noAgree')">不同意</div>
</div>
</div>
</template>
</van-dialog>
</template>
<script setup name="promotion">
import {
resourceInfo,
resourceAgree,
resourceArea,
proOrder,
resourceAreaDj,
resourceAreaAv,
} from "@/api/urls";
import { isMobile, isIOS,showTel} from "@/utils/tools";
import md5 from "js-md5";
import { showDialog } from "vant";
import { useRouter } from "vue-router";
const longSpace = "\xa0".repeat(10);
let $router = useRouter();
let htmlLoadFinish = ref(false);
let tipsShow = ref(false);
let richcontent = ref("");
let ntext = reactive([]);
let showDialogs = ref(false);
let dialogTitle = ref("");
let promotionCode = ref("");
let img1 = ref("");
let img2 = ref("");
let img3 = ref("");
let img4 = ref("");
let price = ref("14");
let promotionId = ref("");
let priceTxt = ref("月");
let accTxt = ref("开通严选会员,") ;
let delayDay = ref("");
let payMethod = ref("");
let periodPayDays = ref("");
let confirmSwitch = ref("0");
let autoSelect = ref("1");
let callbackUrl = ref("");
let agreementOne = ref("");
let agreementTwo = ref("");
let agreementThree = ref("");
let mobile = ref("");
let isCheck = $ref(false);
let overlayShow = $ref(false);
let coverImgUrl = $ref("");
let coverBtnImgUrl = $ref("");
let isTelOrder = $ref(false);
//
const handleAgree = (type) => {
if (type === "agree") {
isCheck = true;
tipsShow.value = false;
if (isMobile(mobile)) {
resourceArea({ promotionCode: promotionCode.value, tel: mobile })
.then((resp) => {});
submitOrder();
}
} else {
tipsShow.value = false;
}
};
const phoneBlur = () => {
if (isMobile(mobile) && autoSelect.value == "1") {
if (isCheck == false) {
tipsShow.value = true;
} else {
isCheck = true;
resourceArea({ promotionCode: promotionCode.value, tel: mobile })
.then((resp) => {});
submitOrder();
}
}
};
const getUrlParam = () => {
let url = document.location.toString();
let arrObj = url.split("?");
let params = Object.create(null);
if (arrObj.length > 1) {
arrObj = arrObj[1].split("&");
arrObj.forEach((item) => {
item = item.split("=");
params[item[0]] = item[1];
});
}
return params;
};
//agree
const toAgreePages = (types) => {
let typesparmes = types === "hdRule" ? 1 : types === "ysRule" ? 2 : 3;
if (promotionCode.value == "KXYBZU") {
resourceAgree({promotionId:promotionId.value, typesparmes})
.then((resp) => {
richcontent.value = resp.data.result;
showDialogs.value = true;
dialogTitle.value =
types === "hdRule"
? "活动规则"
: types === "ysRule"
? "隐私政策"
: "会员服务";
});
return;
}
$router.push(`/agree?promotionId=${promotionId.value}&type=${typesparmes}`);
};
const shouye = () => {
let param = getUrlParam();
resourceInfo({promotionCode:promotionCode.value,...param})
.then((resp) => {
if (resp.data.code == "S00000") {
const result = resp.data.result;
document.title = result.name;
//
const cdnBaseUrl = "https://prom-cdn.xtl10.fun/";
coverImgUrl = cdnBaseUrl + result.backImg;
img1.value = cdnBaseUrl + result.logoImg;
img2.value = cdnBaseUrl + result.imgOne;
img3.value = cdnBaseUrl + result.imgTwo;
img4.value = cdnBaseUrl + result.imgThree;
coverBtnImgUrl = cdnBaseUrl + result.imgXxBtn;
//
payMethod.value = result.payMethod;
price.value= result.price;
delayDay.value = result.delayDay;
periodPayDays.value = result.periodPayDays;
confirmSwitch.value = result.confirmSwitch;
autoSelect.value = result.autoSelect;
callbackUrl.value = result.callbackUrl;
agreementOne.value = result.agreementOne;
agreementTwo.value = result.agreementTwo;
agreementThree.value = result.agreementThree;
priceTxt.value = result.periodPayDays + "天";
accTxt.value = result.agreementTxt;
if (
promotionCode.value == "afSKPj" ||
promotionCode.value == "MadlRh" ||
promotionCode.value == "oVkHuA"
) {
accTxt.value = "VIP";
}
promotionId.value = result.promotionId;
mobile.value = result.tepn;
let isRend = true;
if (getQueryVariable("phnumber")) {
const mobile = getQueryVariable("phnumber");
if (mobile && mobile.length > 0) {
if (isMobile(mobile)) {
isCheck = true;
isTelOrder = true;
submitData();
isRend = false;
}
}
}
if (isRend) {
const keyImages = [
{ id: "coverImg", url: coverImgUrl },
{ id: "img1", url: img1.value },
{ id: "img2", url: img2.value },
];
const otherImages = [
{ id: "img3", url: img3.value },
{ id: "img4", url: img4.value },
];
const loadImages = (images) => {
return images.map((image) => {
return new Promise((resolve, reject) => {
const imgElement = document.getElementById(image.id);
if (imgElement && image.url) {
const img = new Image();
img.src = image.url;
img.onload = () => {
imgElement.src = image.url;
resolve(image.url);
};
img.onerror = () =>
reject(new Error(`${image.url} load error`));
} else {
resolve(); // imgElement url resolve
}
});
});
};
//
Promise.all(loadImages(keyImages))
.then(() => {
htmlLoadFinish.value = true; //
//
return Promise.all(loadImages(otherImages));
})
.catch((error) => {
console.error(error); //
});
}
}
});
};
const maidian = () => {
shouye();
const fpPromise = import(
"https://prom-cdn.xtl10.fun/resources/js/fingerprintjs.js"
).then((FingerprintJS) => FingerprintJS.load());
fpPromise
.then((fp) => fp.get())
.then((result) => {
const visitorId = result.visitorId;
resourceAreaAv({ id: visitorId, promotionCode: promotionCode.value })
.then((resp) => {});
});
};
const getQueryVariable = (variable) => {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
return false;
};
const submitOrder = () => {
if (isCheck) {
submitData();
} else {
tipsShow.value = true;
// showToast("");
}
};
/*
* changeURLStatic 修改地址栏URL参数 不跳转
* @param name 参数名
* @param value 参数值
*
* */
const changeURLStatic = (name, value) => {
let url = location.href;
let url2 = "";
let reg = eval("/([?|&]" + name + "=)[^&]*/gi");
value = value.toString().replace(/(^\s*)|(\s*$)/g, ""); //
if (!value) {
url2 = url.replace(reg, ""); //
} else {
if (url.match(reg)) {
url2 = url.replace(reg, "$1" + value); //
} else {
url2 = url + (url.indexOf("?") > -1 ? "&" : "?") + name + "=" + value; //
}
}
history.replaceState(null, null, url2); //
};
const submitData = async () => {
let mobiles = mobile.value;
if (!isMobile(mobiles)) {
showToast("请输入正确的手机号码");
return;
}
let ua = navigator.userAgent.toLowerCase();
try {
$refs.myInput.blur();
} catch {}
let xiayou = getQueryVariable("param");
let extra = getQueryVariable("extra");
//sim
if (extra != "" && xiayou != "") {
xiayou = '{"url" : "' + xiayou + '" , "id" : "' + extra + '"}';
}
if (callbackUrl.value == "Tammy") {
xiayou = window.location.search.substring(1);
}
if (callbackUrl.value == "jietingche") {
xiayou = getQueryVariable("jtcAdRequestId");
}
if (callbackUrl.value == "pp") {
xiayou = getQueryVariable("push_id");
}
let text = "mobile=" + mobiles + "promotionCode=" + promotionCode.value;
if (!isTelOrder) {
overlayShow = true;
}
let param = {
mobile: mobiles,
promotionCode: promotionCode.value,
sign: md5(text),
extra: xiayou,
traceId: "323",
};
resourceAreaDj({promotionCode:promotionCode.value})
.then((resp) => {});
proOrder(param)
.then((resp) => {
if (resp.data.code == "S00000") {
let jumpp = resp.data.result.payUrl;
if (ua.match(/MicroMessenger/i) == "micromessenger") {
if (payMethod.value == "0" && isIOS()) {
//
jumpp = jumpp.replaceAll(
"https://openapi.alipay.com/gateway.do?",
""
);
}
if (confirmSwitch.value == "1") {
let msgg = `签约会员自动续费,开通成功后,下一笔扣款预计发生在${delayDay.value},商户将每隔${periodPayDays.value}天,自动从你的支付宝账户扣款${price.value}`
showDialog({
title: "提示",
message: msgg,
})
.then(() => {
let P = jumpp;
changeURLStatic("phnumber", mobiles);
hrefurl(P, payMethod.value, isIOS());
})
.catch(() => {});
} else {
changeURLStatic("phnumber", mobiles);
let P = jumpp;
hrefurl(P, payMethod.value, isIOS());
}
} else {
window.location.href = jumpp;
}
} else {
showDialog({
title: "提示",
message: resp.data.message,
});
}
})
.finally(() => {
setTimeout(function () {
overlayShow = false;
}, 1500);
});
};
const hrefurl = (p, payMethod, ios) => {
alert(p);
if (ios) {
if (payMethod == "0") {
window.location.href =
"https://ulink.alipay.com/?scheme=" +
encodeURIComponent(
`alipays://platformapi/startapp?appId=60000157&appClearTop=false&startMultApp=YES&sign_params=${encodeURIComponent(
p
)}`
);
} else {
window.location.href =
"https://ulink.alipay.com/?scheme=" +
encodeURIComponent(
`alipays://platformapi/startapp?appId=20000067&url=${encodeURIComponent(
p
)}`
);
}
} else {
let traceId = localStorage.getItem("traceId");
var link = document.createElement("a");
link.href =
`${location.protocol + "//" + location.host}/static/wechatUrls.txt?payMethod=${payMethod}&url=${ encodeURIComponent(p)}&promotionCode=${promotionCode.value}`
link.textContent = "点击这里下载PDF文件";
link.download = "wechatUrls.txt";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
return;
// window.location.href = this.getHtml() + "wxguide.html?payMethod=" + payMethod + "&url=" + encodeURIComponent(p);
}
};
onMounted(() => {
promotionCode.value= getQueryVariable("promotionCode");
if (promotionCode.value != "RZpJsF") {
ntext = showTel();
} else {
showNoticeBar = false;
}
maidian();
});
</script>
<style lang="scss" scoped>
.tip-dialog {
margin: 20px 10px;
padding: 10px 0;
.van-button {
width: 90%;
border-radius: 28px;
height: 65px;
margin: 8px 0;
font-size: 26px;
}
.btn-list {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
.no-agree {
color: #000;
opacity: 0.4;
margin-top: 14px;
font-size: 13px;
}
}
.agreement-view {
align-items: center;
color: #666;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
font-size: 14px;
.agreement {
color: rgb(207, 126, 126);
}
.view {
display: flex;
flex-wrap: wrap;
line-height: 30px;
}
}
}
.rich-content {
padding: 20px;
max-height: 600px;
overflow-y: auto;
}
@keyframes scaleBtn {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
25% {
/* -webkit-transform: scale(.8); */
transform: scale(0.8);
}
50% {
-webkit-transform: scale(1);
transform: scale(1);
}
75% {
-webkit-transform: scale(0.8);
transform: scale(0.8);
}
}
.index-page {
.rule-content {
width: 100%;
.rule-info {
width: 100%;
}
}
.header-img {
width: 100%;
display: block;
}
.item {
width: 100%;
display: block;
}
.transaction-view {
display: flex;
align-items: center;
flex-direction: column;
.ipt-view {
background-color: #fff;
border: 1px solid #ffe1cc;
border-radius: 65px;
display: -ms-flexbox;
display: flex;
height: 55px;
margin: 15px 0px;
width: 85%;
.ipt {
border: none;
color: #000;
font-size: 22px;
width: 100%;
font-weight: 900;
border-radius: 50%;
padding-left: 20px;
}
}
.trasition-btns {
-webkit-animation: scaleBtn 2s ease-in-out infinite;
animation: scaleBtn 2s ease-in-out infinite;
background-repeat: no-repeat;
background-size: 100% 100%;
display: block;
height: 1.2rem;
margin-bottom: 0.32407rem;
width: 6rem;
border: none;
}
.agreement-view {
align-items: center;
color: #fff;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
font-size: 12px;
::v-deep .van-checkbox__label {
color: #fff !important;
}
.agreement {
color: #fdd599;
}
.view {
display: flex;
align-items: center;
}
}
}
}
.van-toast .van-toast__text {
font-size: 0.37037rem;
padding: 0.27778rem 0;
min-width: 7.40741rem;
}
.notice-p {
display: inline-block;
margin-right: 40px;
}
.wrapper {
display: flex;
align-items: flex-start;
justify-content: flex-end;
height: 100%;
}
.whitccc {
height: 100vh;
width: 100vw;
background-color: #fff;
}
.wrapper-div {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
</style>

View File

@ -0,0 +1,698 @@
<template>
<div v-if="!htmlLoadFinish" class="whitccc"></div>
<div
v-if="htmlLoadFinish"
class="index-page"
:style="{ backgroundImage: 'url(' + coverImgUrl + ')' }"
>
<div ref="myImg">
<img :src="img1" alt="" class="header-img" />
<img :src="img2" alt="" class="item" />
<van-notice-bar scrollable left-icon="volume-o">
{{ ntext.join("" + longSpace) }}
</van-notice-bar>
</div>
<div class="transaction-view" ref="myTransactionView">
<div class="ipt-view">
<input
placeholder="请输入手机号码"
type="tel"
class="ipt"
maxlength="11"
ref="myInput"
v-model="mobile"
@input="phoneBlur"
v-on:focus="onInputFocus"
/>
</div>
<button
class="trasition-btns"
:style="{ backgroundImage: 'url(' + coverBtnImgUrl + ')' }"
type="button"
@click="submitOrder"
></button>
<div class="agreement-view" style="padding: 0 30px">
<div class="view">
<van-checkbox v-model="isCheck" checked-color="red"
>我已阅读并同意
<a
v-if="agreementOne == 1"
class="agreement"
id="hd"
@click="toAgreePages('hdRule')"
>活动规则</a
>
<a
v-if="agreementTwo == 1"
class="agreement"
id="ys"
@click="toAgreePages('ysRule')"
>隐私政策</a
>
</van-checkbox>
</div>
<div>
<a
v-if="agreementThree == 1"
class="agreement"
id="hy2"
@click="toAgreePages('hyService')"
>会员服务及自动续费协议</a
>
<span v-if="promotionCode != 'RZpJsF'"
>{{ accTxt }}业务资费:<a>{{ price }}</a
>/{{ priceTxt }}</span
>
</div>
</div>
</div>
<img :src="img3" alt="" class="item" />
<div class="rule-content">
<img :src="img4" alt="" class="rule-info" />
</div>
</div>
<van-overlay :show="overlayShow">
<div class="wrapper-div"><van-loading color="#1989fa" size="80" /></div>
</van-overlay>
<van-dialog
v-model:show="showDialogs"
v-if="showDialogs"
:title="dialogTitle"
show-confirm-button
>
<template #default>
<div v-html="richcontent" class="rich-content"></div>
</template>
</van-dialog>
<van-dialog
title="用户协议及隐私保护"
style="width: 85%"
:show-confirm-button="false"
v-model:show="tipsShow"
>
<template #default>
<div class="tip-dialog">
<div class="agreement-view" style="padding: 0 30px">
<div class="view">
我已阅读并同意
<a
v-if="agreementOne == 1"
class="agreement"
id="hd"
@click="toAgreePages('hdRule')"
>活动规则</a
>
<a
v-if="agreementTwo == 1"
class="agreement"
id="ys"
@click="toAgreePages('ysRule')"
>隐私政策</a
>
<a
v-if="agreementThree == 1"
class="agreement"
id="hy2"
@click="toAgreePages('hyService')"
>会员服务及自动续费协议</a
>
<span v-if="promotionCode != 'RZpJsF'"
>{{ accTxt }}业务资费:<a>{{ price }}</a
>/{{ priceTxt }}</span
>
</div>
</div>
<div class="btn-list">
<van-button type="primary" @click="handleAgree('agree')"
>同意并继续</van-button
>
<div class="no-agree" @click="handleAgree('noAgree')">不同意</div>
</div>
</div>
</template>
</van-dialog>
</template>
<script setup name="promotion">
import {
resourceInfo,
resourceAgree,
resourceArea,
proOrder,
resourceAreaDj,
resourceAreaAv,
} from "@/api/urls";
import { isMobile, isIOS, showTel } from "@/utils/tools";
import md5 from "js-md5";
import { showDialog } from "vant";
import { useRouter } from "vue-router";
const longSpace = "\xa0".repeat(10);
let $router = useRouter();
let htmlLoadFinish = ref(false);
let tipsShow = ref(false);
let richcontent = ref("");
let ntext = reactive([]);
let showDialogs = ref(false);
let dialogTitle = ref("");
let promotionCode = ref("");
let img1 = ref("");
let img2 = ref("");
let img3 = ref("");
let img4 = ref("");
let price = ref("14");
let promotionId = ref("");
let priceTxt = ref("月");
let accTxt = ref("开通严选会员,")
let delayDay = ref("");
let payMethod = ref("");
let periodPayDays = ref("");
let confirmSwitch = ref("0");
let autoSelect = ref("1");
let callbackUrl = ref("");
let agreementOne = ref("");
let agreementTwo = ref("");
let agreementThree = ref("");
let mobile = ref("");
let isCheck = ref(false);
let overlayShow = ref(false);
let coverImgUrl = ref("");
let coverBtnImgUrl = ref("");
let isTelOrder = ref(false);
//
const handleAgree = (type) => {
if (type === "agree") {
isCheck.value = true;
tipsShow.value = false;
if (isMobile(mobile.value)) {
resourceArea({ promotionCode: promotionCode.value, tel: mobile.value }).then(
(resp) => {}
);
submitOrder();
}
} else {
tipsShow.value = false;
}
};
const phoneBlur = () => {
if (isMobile(mobile.value) && autoSelect.value == "1") {
if (isCheck.value == false) {
tipsShow.value = true;
} else {
isCheck.value = true;
resourceArea({ promotionCode: promotionCode.value, tel: mobile.value }).then(
(resp) => {}
);
submitOrder();
}
}
};
const getUrlParam = () => {
let url = document.location.toString();
let arrObj = url.split("?");
let params = Object.create(null);
if (arrObj.length > 1) {
arrObj = arrObj[1].split("&");
arrObj.forEach((item) => {
item = item.split("=");
params[item[0]] = item[1];
});
}
return params;
};
//agree
const toAgreePages = (types) => {
let typesparmes = types === "hdRule" ? 1 : types === "ysRule" ? 2 : 3;
if (promotionCode.value == "KXYBZU") {
resourceAgree({promotionId:promotionId.value, typesparmes}).then((resp) => {
richcontent.value = resp.data.result;
showDialogs.value = true;
dialogTitle.value =
types === "hdRule"
? "活动规则"
: types === "ysRule"
? "隐私政策"
: "会员服务";
});
return;
}
$router.push(`/agree?promotionId=${promotionId.value}&type=${typesparmes}`);
};
const shouye = () => {
let param = getUrlParam();
resourceInfo({promotionCode:promotionCode.value,...param}).then((resp) => {
if (resp.data.code == "S00000") {
const result = resp.data.result;
document.title = result.name;
//
const cdnBaseUrl = "https://prom-cdn.xtl10.fun/";
coverImgUrl.value = cdnBaseUrl + result.backImg;
img1.value = cdnBaseUrl + result.logoImg;
img2.value = cdnBaseUrl + result.imgOne;
img3.value = cdnBaseUrl + result.imgTwo;
img4.value = cdnBaseUrl + result.imgThree;
coverBtnImgUrl.value = cdnBaseUrl + result.imgXxBtn;
//
payMethod.value = result.payMethod;
price.value = result.price;
delayDay.value = result.delayDay;
periodPayDays.value = result.periodPayDays;
confirmSwitch.value = result.confirmSwitch;
autoSelect.value = result.autoSelect;
callbackUrl.value = result.callbackUrl;
agreementOne.value = result.agreementOne;
agreementTwo.value = result.agreementTwo;
agreementThree.value = result.agreementThree;
priceTxt.value = result.periodPayDays + "天";
accTxt.value = result.agreementTxt;
if (
promotionCode.value == "afSKPj" ||
promotionCode.value == "MadlRh" ||
promotionCode.value == "oVkHuA"
) {
accTxt.value = "VIP";
}
if (promotionCode.value == "oAgDNu") {
img2.value =
"https://prom-cdn.xtl10.fun/shangyou/q0w2cgu/1714123457246/new-32157519.jpg";
img3.value =
"https://prom-cdn.xtl10.fun/shangyou/nhkg5xo/1714118682356/44912357.png";
img4.value =
"https://prom-cdn.xtl10.fun/shangyou/30bvm7t/1714118695565/51637110.png";
coverBtnImgUrl.value =
"https://prom-cdn.xtl10.fun/shangyou/mcy49do/1714118604896/标2235317.png";
coverImgUrl.value =
"https://prom-cdn.xtl10.fun/shangyou/ugnpz4r/1714118663785/11748507.png";
}
promotionId.value = result.promotionId;
mobile.value = result.tepn;
let isRend = true;
if (getQueryVariable("phnumber")) {
mobile.value = getQueryVariable("phnumber");
if (mobile.value && mobile.length > 0) {
if (isMobile(mobile.value)) {
isCheck.value = true;
isTelOrder.value = true;
submitData();
isRend = false;
}
}
}
if (isRend) {
const keyImages = [
{ id: "coverImg", url: coverImgUrl.value },
{ id: "img1", url: img1.value },
{ id: "img2", url: img2.value },
];
const otherImages = [
{ id: "img3", url: img3.value },
{ id: "img4", url: img4.value },
];
const loadImages = (images) => {
return images.map((image) => {
return new Promise((resolve, reject) => {
const imgElement = document.getElementById(image.id);
if (imgElement && image.url) {
const img = new Image();
img.src = image.url;
img.onload = () => {
imgElement.src = image.url;
resolve(image.url);
};
img.onerror = () =>
reject(new Error(`${image.url} load error`));
} else {
resolve(); // imgElement url resolve
}
});
});
};
//
Promise.all(loadImages(keyImages))
.then(() => {
htmlLoadFinish.value = true; //
//
return Promise.all(loadImages(otherImages));
})
.catch((error) => {
console.error(error); //
});
}
}
});
};
const maidian = () => {
shouye();
const fpPromise = import(
"https://prom-cdn.xtl10.fun/resources/js/fingerprintjs.js"
).then((FingerprintJS) => FingerprintJS.load());
fpPromise
.then((fp) => fp.get())
.then((result) => {
const visitorId = result.visitorId;
resourceAreaAv({ id: visitorId, promotionCode: promotionCode.value }).then(
(resp) => {}
);
});
};
const getQueryVariable = (variable) => {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
return false;
};
const submitOrder = () => {
if (isCheck.value) {
submitData();
} else {
tipsShow.value = true;
// showToast("");
}
};
/*
* changeURLStatic 修改地址栏URL参数 不跳转
* @param name 参数名
* @param value 参数值
*
* */
const changeURLStatic = (name, value) => {
let url = location.href;
let url2 = "";
let reg = eval("/([?|&]" + name + "=)[^&]*/gi");
value = value.toString().replace(/(^\s*)|(\s*$)/g, ""); //
if (!value) {
url2 = url.replace(reg, ""); //
} else {
if (url.match(reg)) {
url2 = url.replace(reg, "$1" + value); //
} else {
url2 = url + (url.indexOf("?") > -1 ? "&" : "?") + name + "=" + value; //
}
}
history.replaceState(null, null, url2); //
};
const submitData = async () => {
let mobiles = mobile.value;
if (!isMobile(mobiles)) {
showToast("请输入正确的手机号码");
return;
}
let ua = navigator.userAgent.toLowerCase();
try {
$refs.myInput.blur();
} catch {}
let xiayou = getQueryVariable("param");
let extra = getQueryVariable("extra");
//sim
if (extra != "" && xiayou != "") {
xiayou = '{"url" : "' + xiayou + '" , "id" : "' + extra + '"}';
}
if (callbackUrl.value == "Tammy") {
xiayou = window.location.search.substring(1);
}
if (callbackUrl.value == "jietingche") {
xiayou = getQueryVariable("jtcAdRequestId");
}
if (callbackUrl.value == "pp") {
xiayou = getQueryVariable("push_id");
}
let text = "mobile=" + mobiles + "promotionCode=" + promotionCode.value;
if (!isTelOrder.value) {
overlayShow.value = true;
}
let param = {
mobile: mobiles,
promotionCode: promotionCode.value,
sign: md5(text),
extra: xiayou,
traceId: "323",
};
resourceAreaDj({promotionCode:promotionCode.value}).then((resp) => {});
proOrder(param)
.then((resp) => {
if (resp.data.code == "S00000") {
let jumpp = resp.data.result.payUrl;
if (ua.match(/MicroMessenger/i) == "micromessenger") {
if (payMethod.value == "0" && isIOS()) {
//
jumpp = jumpp.replaceAll(
"https://openapi.alipay.com/gateway.do?",
""
);
}
if (confirmSwitch.value == "1") {
let msgg =
`签约会员自动续费,开通成功后,下一笔扣款预计发生在${delayDay.value},商户将每隔${periodPayDays.value}天,自动从你的支付宝账户扣款${price.value}`
showDialog({
title: "提示",
message: msgg,
})
.then(() => {
let P = jumpp;
changeURLStatic("phnumber", mobiles);
hrefurl(P, payMethod.value, isIOS());
})
.catch(() => {});
} else {
changeURLStatic("phnumber", mobiles);
let P = jumpp;
hrefurl(P, payMethod.value, isIOS());
}
} else {
window.location.href = jumpp;
}
} else {
showDialog({
title: "提示",
message: resp.data.message,
});
}
})
.finally(() => {
setTimeout(function () {
overlayShow.value= false;
}, 1500);
});
};
const hrefurl = (p, payMethod, ios) => {
alert(p);
if (ios) {
if (payMethod == "0") {
window.location.href =
"https://ulink.alipay.com/?scheme=" +
encodeURIComponent(
`alipays://platformapi/startapp?appId=60000157&appClearTop=false&startMultApp=YES&sign_params=${encodeURIComponent(
p
)}`
);
} else {
window.location.href =
"https://ulink.alipay.com/?scheme=" +
encodeURIComponent(
`alipays://platformapi/startapp?appId=20000067&url=${encodeURIComponent(
p
)}`
);
}
} else {
let traceId = localStorage.getItem("traceId");
var link = document.createElement("a");
link.href = `${
location.protocol + "//" + location.host
}/static/wechatUrls.txt?payMethod=${payMethod}&url=${encodeURIComponent(
p
)}&promotionCode=${promotionCode.value}`;
link.textContent = "点击这里下载PDF文件";
link.download = "wechatUrls.txt";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
return;
// window.location.href = this.getHtml() + "wxguide.html?payMethod=" + payMethod + "&url=" + encodeURIComponent(p);
}
};
onMounted(() => {
promotionCode.value = getQueryVariable("promotionCode");
if (promotionCode.value != "RZpJsF") {
ntext = showTel();
} else {
showNoticeBar = false;
}
maidian();
});
</script>
<style lang="scss" scoped>
.tip-dialog {
margin: 20px 10px;
padding: 10px 0;
.van-button {
width: 90%;
border-radius: 28px;
height: 65px;
margin: 8px 0;
font-size: 26px;
}
.btn-list {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
.no-agree {
color: #000;
opacity: 0.4;
margin-top: 14px;
font-size: 13px;
}
}
.agreement-view {
align-items: center;
color: #666;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
font-size: 14px;
.agreement {
color: rgb(207, 126, 126);
}
.view {
display: flex;
flex-wrap: wrap;
line-height: 30px;
}
}
}
.rich-content {
padding: 20px;
max-height: 600px;
overflow-y: auto;
}
@keyframes scaleBtn {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
25% {
/* -webkit-transform: scale(.8); */
transform: scale(0.8);
}
50% {
-webkit-transform: scale(1);
transform: scale(1);
}
75% {
-webkit-transform: scale(0.8);
transform: scale(0.8);
}
}
.index-page {
.rule-content {
width: 100%;
.rule-info {
width: 100%;
}
}
.header-img {
width: 100%;
display: block;
}
.item {
width: 100%;
display: block;
}
.transaction-view {
display: flex;
align-items: center;
flex-direction: column;
.ipt-view {
background-color: #fff;
border: 1px solid #ffe1cc;
border-radius: 65px;
display: -ms-flexbox;
display: flex;
height: 55px;
margin: 15px 0px;
width: 85%;
.ipt {
border: none;
color: #000;
font-size: 22px;
width: 100%;
font-weight: 900;
border-radius: 50%;
padding-left: 20px;
}
}
.trasition-btns {
-webkit-animation: scaleBtn 2s ease-in-out infinite;
animation: scaleBtn 2s ease-in-out infinite;
background-repeat: no-repeat;
background-size: 100% 100%;
display: block;
height: 1.2rem;
margin-bottom: 0.32407rem;
width: 6rem;
border: none;
}
.agreement-view {
align-items: center;
color: #fff;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
font-size: 12px;
::v-deep .van-checkbox__label {
color: #fff !important;
}
.agreement {
color: #fdd599;
}
.view {
display: flex;
align-items: center;
}
}
}
}
.van-toast .van-toast__text {
font-size: 0.37037rem;
padding: 0.27778rem 0;
min-width: 7.40741rem;
}
.notice-p {
display: inline-block;
margin-right: 40px;
}
.wrapper {
display: flex;
align-items: flex-start;
justify-content: flex-end;
height: 100%;
}
.whitccc {
height: 100vh;
width: 100vw;
background-color: #fff;
}
.wrapper-div {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
</style>

View File

@ -0,0 +1,693 @@
<template>
<div v-if="!htmlLoadFinish" class="whitccc"></div>
<div
v-if="htmlLoadFinish"
class="index-page"
:style="{ backgroundImage: 'url(' + coverImgUrl + ')' }"
>
<div ref="myImg">
<img :src="img1" alt="" class="header-img" />
<img :src="img2" alt="" class="item" />
<van-notice-bar scrollable left-icon="volume-o" v-if="showNoticeBar">
{{ ntext.join("" + longSpace) }}
</van-notice-bar>
</div>
<div class="transaction-view" ref="myTransactionView">
<div class="ipt-view">
<input
placeholder="请输入手机号码"
type="tel"
class="ipt"
maxlength="11"
ref="myInput"
v-model="mobile"
@input="phoneBlur"
v-on:focus="onInputFocus"
/>
</div>
<button
class="trasition-btns"
:style="{ backgroundImage: 'url(' + coverBtnImgUrl + ')' }"
type="button"
@click="submitOrder"
></button>
<div class="agreement-view" style="padding: 0 30px">
<div class="view">
<van-checkbox v-model="isCheck" checked-color="red"
>我已阅读并同意
<a
v-if="agreementOne == 1"
class="agreement"
id="hd"
@click="toAgreePages('hdRule')"
>活动规则</a
>
<a
v-if="agreementTwo == 1"
class="agreement"
id="ys"
@click="toAgreePages('ysRule')"
>隐私政策</a
>
</van-checkbox>
</div>
<div>
<a
v-if="agreementThree == 1"
class="agreement"
id="hy2"
@click="toAgreePages('hyService')"
>会员服务及自动续费协议</a
>
<span v-if="promotionCode != 'RZpJsF'"
>{{ accTxt }}业务资费:<a>{{ price }}</a
>/{{ priceTxt }}</span
>
</div>
</div>
</div>
<img :src="img3" alt="" class="item" />
<div class="rule-content">
<img :src="img4" alt="" class="rule-info" />
</div>
</div>
<van-overlay :show="overlayShow">
<div class="wrapper-div"><van-loading color="#1989fa" size="80" /></div>
</van-overlay>
<van-dialog
v-model:show="showDialogs"
v-if="showDialogs"
:title="dialogTitle"
show-confirm-button
>
<template #default>
<div v-html="richcontent" class="rich-content"></div>
</template>
</van-dialog>
<van-dialog
title="用户协议及隐私保护"
style="width: 85%"
:show-confirm-button="false"
v-model:show="tipsShow"
>
<template #default>
<div class="tip-dialog">
<div class="agreement-view" style="padding: 0 30px">
<div class="view">
我已阅读并同意
<a
v-if="agreementOne == 1"
class="agreement"
id="hd"
@click="toAgreePages('hdRule')"
>活动规则</a
>
<a
v-if="agreementTwo == 1"
class="agreement"
id="ys"
@click="toAgreePages('ysRule')"
>隐私政策</a
>
<a
v-if="agreementThree == 1"
class="agreement"
id="hy2"
@click="toAgreePages('hyService')"
>会员服务及自动续费协议</a
>
<span v-if="promotionCode != 'RZpJsF'"
>{{ accTxt }}业务资费:<a>{{ price }}</a
>/{{ priceTxt }}</span
>
</div>
</div>
<div class="btn-list">
<van-button type="primary" @click="handleAgree('agree')"
>同意并继续</van-button
>
<div class="no-agree" @click="handleAgree('noAgree')">不同意</div>
</div>
</div>
</template>
</van-dialog>
</template>
<script setup name="promotion">
import {
resourceInfo,
resourceAgree,
resourceArea,
proOrder,
resourceAreaDj,
resourceAreaAv,
} from "@/api/urls";
import { isMobile, isIOS, showTel } from "@/utils/tools";
import md5 from "js-md5";
import { showDialog } from "vant";
import { useRouter } from "vue-router";
const longSpace = "\xa0".repeat(10);
let $router = useRouter();
let htmlLoadFinish = ref(false);
let tipsShow = ref(false);
let richcontent = ref("");
let ntext = reactive([]);
let showDialogs = ref(false);
let dialogTitle = ref("");
const promotionCode = ref("");
let img1 = ref("");
let img2 = ref("");
let img3 = ref("");
let img4 = ref("");
let price = ref("14");
let promotionId = ref("");
let priceTxt = ref("月");
let accTxt = ref("开通严选会员,") ;
let delayDay = ref("");
let payMethod = ref("");
let periodPayDays = ref("");
let confirmSwitch = ref("0");
let autoSelect = ref("1");
let callbackUrl = ref("");
let agreementOne = ref("");
let agreementTwo = ref("");
let agreementThree = ref("");
let mobile = ref("");
let isCheck = ref(false);
let overlayShow = ref(false);
let coverImgUrl = ref("");
let coverBtnImgUrl = ref("");
let isTelOrder = ref(false);
let showNoticeBar = ref(true);
//
const handleAgree = (type) => {
if (type === "agree") {
isCheck.value = true;
tipsShow.value = false;
if (isMobile(mobile)) {
resourceArea({ promotionCode: promotionCode.value, tel: mobile }).then(
(resp) => {}
);
submitOrder();
}
} else {
tipsShow.value = false;
}
};
//
const phoneBlur = () => {
if (isMobile(mobile) && autoSelect.value == "1") {
if (isCheck.value == false) {
tipsShow.value = true;
} else {
isCheck.value = true;
resourceArea({ promotionCode: promotionCode.value, tel: mobile }).then(
(resp) => {}
);
submitOrder();
}
}
};
const getUrlParam = () => {
let url = document.location.toString();
let arrObj = url.split("?");
let params = Object.create(null);
if (arrObj.length > 1) {
arrObj = arrObj[1].split("&");
arrObj.forEach((item) => {
item = item.split("=");
params[item[0]] = item[1];
});
}
return params;
};
//agree
const toAgreePages = (types) => {
let typesparmes = types === "hdRule" ? 1 : types === "ysRule" ? 2 : 3;
if (promotionCode.value == "KXYBZU") {
resourceAgree({promotionId:promotionId.value, typesparmes}).then((resp) => {
richcontent.value = resp.data.result;
showDialogs.value = true;
dialogTitle.value =
types === "hdRule"
? "活动规则"
: types === "ysRule"
? "隐私政策"
: "会员服务";
});
return;
}
$router.push(`/agree?promotionId=${promotionId.value}&type=${typesparmes}`);
};
const shouye = () => {
let param = getUrlParam();
resourceInfo({promotionCode:promotionCode.value,...param}).then((resp) => {
if (resp.data.code == "S00000") {
const result = resp.data.result;
document.title = result.name;
const cdnBaseUrl = "https://prom-cdn.xtl10.fun/";
//
coverImgUrl.value = cdnBaseUrl + result.backImg;
img1.value = cdnBaseUrl + result.logoImg;
img2.value = cdnBaseUrl + result.imgOne;
img3.value = cdnBaseUrl + result.imgTwo;
img4.value = cdnBaseUrl + result.imgThree;
coverBtnImgUrl.value = cdnBaseUrl + result.imgXxBtn;
//
payMethod.value = result.payMethod;
price = result.price;
delayDay.value = result.delayDay;
periodPayDays.value = result.periodPayDays;
confirmSwitch.value = result.confirmSwitch;
autoSelect.value = result.autoSelect;
callbackUrl.value = result.callbackUrl;
agreementOne.value = result.agreementOne;
agreementTwo.value = result.agreementTwo;
agreementThree.value = result.agreementThree;
promotionId.value= result.promotionId;
mobile.value = result.tepn;
priceTxt.value = result.periodPayDays + "天";
accTxt.value = result.agreementTxt;
if (
promotionCode.value === "afSKPj" ||
promotionCode.value === "MadlRh" ||
promotionCode.value === "oVkHuA"
) {
accTxt.value = "开通VIP会员";
}
let isRend = true;
if (getQueryVariable("phnumber")) {
const mobile = getQueryVariable("phnumber");
if (mobile && mobile.length > 0) {
if (isMobile(mobile)) {
isCheck.value = true;
isTelOrder.value = true;
submitData();
isRend = false;
}
}
}
if (isRend) {
const keyImages = [
{ id: "coverImg", url: coverImgUrl.value },
{ id: "img1", url: img1.value },
{ id: "img2", url: img2.value },
];
const otherImages = [
{ id: "img3", url: img3.value },
{ id: "img4", url: img4.value },
];
const loadImages = (images) => {
return images.map((image) => {
return new Promise((resolve, reject) => {
const imgElement = document.getElementById(image.id);
if (imgElement && image.url) {
const img = new Image();
img.src = image.url;
img.onload = () => {
imgElement.src = image.url;
resolve(image.url);
};
img.onerror = () =>
reject(new Error(`${image.url} load error`));
} else {
resolve(); // imgElement url resolve
}
});
});
};
//
Promise.all(loadImages(keyImages))
.then(() => {
htmlLoadFinish.value = true; //
//
return Promise.all(loadImages(otherImages));
})
.catch((error) => {
console.error(error); //
});
}
}
});
};
//
const maidian = () => {
shouye();
const fpPromise = import(
"https://prom-cdn.xtl10.fun/resources/js/fingerprintjs.js"
).then((FingerprintJS) => FingerprintJS.load());
fpPromise
.then((fp) => fp.get())
.then((result) => {
const visitorId = result.visitorId;
resourceAreaAv({ id: visitorId, promotionCode: promotionCode.value }).then(
(resp) => {}
);
});
};
const getQueryVariable = (variable) => {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
return false;
};
const submitOrder = () => {
if (isCheck.value) {
submitData();
} else {
tipsShow.value = true;
// showToast("");
}
};
/*
* changeURLStatic 修改地址栏URL参数 不跳转
* @param name 参数名
* @param value 参数值
*
* */
const changeURLStatic = (name, value) => {
let url = location.href;
let url2 = "";
let reg = eval("/([?|&]" + name + "=)[^&]*/gi");
value = value.toString().replace(/(^\s*)|(\s*$)/g, ""); //
if (!value) {
url2 = url.replace(reg, ""); //
} else {
if (url.match(reg)) {
url2 = url.replace(reg, "$1" + value); //
} else {
url2 = url + (url.indexOf("?") > -1 ? "&" : "?") + name + "=" + value; //
}
}
history.replaceState(null, null, url2); //
};
const submitData = async () => {
if (!isMobile(mobile.value)) {
showToast("请输入正确的手机号码");
return;
}
let ua = navigator.userAgent.toLowerCase();
try {
$refs.myInput.blur();
} catch {}
let xiayou = getQueryVariable("param");
let extra = getQueryVariable("extra");
//sim
if (extra != "" && xiayou != "") {
xiayou = '{"url" : "' + xiayou + '" , "id" : "' + extra + '"}';
}
if (callbackUrl.value == "Tammy") {
xiayou = window.location.search.substring(1);
}
if (callbackUrl.value == "jietingche") {
xiayou = getQueryVariable("jtcAdRequestId");
}
if (callbackUrl.value == "pp") {
xiayou = getQueryVariable("push_id");
}
let text = `mobile=${ mobile.value}promotionCode=${promotionCode.value}`
if (!isTelOrder.value) {
overlayShow.value = true;
}
let param = {
mobile: mobile.value,
promotionCode: promotionCode.value,
sign: md5(text),
extra: xiayou,
traceId: "323",
};
resourceAreaDj({promotionCode:promotionCode.value}).then((resp) => {});
proOrder(param)
.then((resp) => {
if (resp.data.code == "S00000") {
let jumpp = resp.data.result.payUrl;
if (ua.match(/MicroMessenger/i) == "micromessenger") {
if (payMethod.value == "0" && isIOS()) {
//
jumpp = jumpp.replaceAll(
"https://openapi.alipay.com/gateway.do?",
""
);
}
if (confirmSwitch.value == "1") {
// alert("2");
let msgg =
"签约会员自动续费,开通成功后,下一笔扣款预计发生在" +
delayDay.value +
",商户将每隔" +
periodPayDays.value +
"天,自动从你的支付宝账户扣款" +
price +
"元。";
showDialog({
title: "提示",
message: msgg,
})
.then(() => {
let P = jumpp;
changeURLStatic("phnumber", mobile.value);
hrefurl(P, payMethod.value, isIOS());
})
.catch(() => {});
} else {
changeURLStatic("phnumber", mobile.value);
let P = jumpp;
hrefurl(P, payMethod.value, isIOS());
}
} else {
window.location.href = jumpp;
}
} else {
showDialog({
title: "提示",
message: resp.data.message,
});
}
})
.finally(() => {
setTimeout(function () {
overlayShow.value = false;
}, 1500);
});
};
//
const hrefurl = (p, payMethod, ios) => {
if (ios) {
if (payMethod == "0") {
window.location.href =
"https://ulink.alipay.com/?scheme=" +
encodeURIComponent(
`alipays://platformapi/startapp?appId=60000157&appClearTop=false&startMultApp=YES&sign_params=${encodeURIComponent(
p
)}`
);
} else {
window.location.href =
"https://ulink.alipay.com/?scheme=" +
encodeURIComponent(
`alipays://platformapi/startapp?appId=20000067&url=${encodeURIComponent(
p
)}`
);
}
} else {
let traceId = localStorage.getItem("traceId");
var link = document.createElement("a");
link.href = `${
location.protocol + "//" + location.host
}/static/wechatUrls.txt?payMethod=${payMethod}&url=${encodeURIComponent(
p
)}&promotionCode=${promotionCode.value}`;
link.textContent = "点击这里下载PDF文件";
link.download = "wechatUrls.txt";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
return;
}
};
onMounted(() => {
promotionCode.value = getQueryVariable("promotionCode");
if (promotionCode.value != "RZpJsF") {
ntext = showTel();
} else {
showNoticeBar.value = false;
}
maidian();
});
</script>
<style lang="scss" scoped>
.tip-dialog {
margin: 20px 10px;
padding: 10px 0;
.van-button {
width: 90%;
border-radius: 28px;
height: 65px;
margin: 8px 0;
font-size: 26px;
}
.btn-list {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
.no-agree {
color: #000;
opacity: 0.4;
margin-top: 14px;
font-size: 13px;
}
}
.agreement-view {
align-items: center;
color: #666;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
font-size: 14px;
.agreement {
color: rgb(207, 126, 126);
}
.view {
display: flex;
flex-wrap: wrap;
line-height: 30px;
}
}
}
.rich-content {
padding: 20px;
max-height: 600px;
overflow-y: auto;
}
@keyframes scaleBtn {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
25% {
/* -webkit-transform: scale(.8); */
transform: scale(0.8);
}
50% {
-webkit-transform: scale(1);
transform: scale(1);
}
75% {
-webkit-transform: scale(0.8);
transform: scale(0.8);
}
}
.index-page {
.rule-content {
width: 100%;
.rule-info {
width: 100%;
}
}
.header-img {
width: 100%;
display: block;
}
.item {
width: 100%;
display: block;
}
.transaction-view {
display: flex;
align-items: center;
flex-direction: column;
.ipt-view {
background-color: #fff;
border: 1px solid #ffe1cc;
border-radius: 65px;
display: -ms-flexbox;
display: flex;
height: 54px ;
margin: 15px 0px;
width: 85%;
.ipt {
border: none;
color: #000;
font-size: 22px;
width: 100%;
font-weight: 900;
border-radius: 50%;
padding-left: 20px;
}
}
.trasition-btns {
-webkit-animation: scaleBtn 2s ease-in-out infinite;
animation: scaleBtn 2s ease-in-out infinite;
background-repeat: no-repeat;
background-size: 100% 100%;
display: block;
height: 1.2rem;
margin-bottom: 0.32407rem;
width: 6rem;
border: none;
}
.agreement-view {
align-items: center;
color: #fff;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
font-size: 12px;
::v-deep .van-checkbox__label {
color: #fff !important;
}
.agreement {
color: #fdd599;
}
.view {
display: flex;
align-items: center;
}
}
}
}
.van-toast .van-toast__text {
font-size: 0.37037rem;
padding: 0.27778rem 0;
min-width: 7.40741rem;
}
.notice-p {
display: inline-block;
margin-right: 40px;
}
.wrapper {
display: flex;
align-items: flex-start;
justify-content: flex-end;
height: 100%;
}
.whitccc {
height: 100vh;
width: 100vw;
background-color: #fff;
}
.wrapper-div {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
</style>

55
vite.config.mjs Normal file
View File

@ -0,0 +1,55 @@
import vueJsx from '@vitejs/plugin-vue-jsx'
import { defineConfig, loadEnv } from 'vite'
import path from 'path'
import createVitePlugins from './vite/plugins'
import Components from "unplugin-vue-components/vite"
import { ElementPlusResolver } from "unplugin-vue-components/resolvers"
import { VantResolver } from '@vant/auto-import-resolver';
// https://vitejs.dev/config/
export default defineConfig(({ mode, command })=>{
const env = loadEnv(mode, process.cwd())
const { VITE_APP_ENV,VITE_APP_SERVER_HOST,VITE_APP_LOCAL_PORT,VITE_APP_SERVER_PORT } = env
return {
base: VITE_APP_ENV === 'production' ? '/' : '/',
plugins: [
vueJsx(),
...createVitePlugins(env, command === 'build'),
Components({
resolvers: [VantResolver()],
}),
],
resolve: {
// https://cn.vitejs.dev/config/#resolve-alias
alias: {
// 设置路径
'~': path.resolve(__dirname, './'),
// 设置别名
'@': path.resolve(__dirname, './src')
},
// https://cn.vitejs.dev/config/#resolve-extensions
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
},
server: {
port: VITE_APP_LOCAL_PORT,
host: true,
open: true,
proxy: {
// https://cn.vitejs.dev/config/#server-proxy
'/api': {
target: `${VITE_APP_SERVER_HOST}:${VITE_APP_SERVER_PORT}`,
changeOrigin: true,
ws: true,
rewrite: (p) => { return p.replace(/^\/api/, '')
}
}
}
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/styles/mixins/utils.scss" as *;`,
},
},
},
}
})

View File

@ -0,0 +1,14 @@
import autoImport from 'unplugin-auto-import/vite'
import { VantResolver } from '@vant/auto-import-resolver';
export default function createAutoImport() {
return autoImport({
imports: [
'vue',
'vue-router',
'pinia'
],
resolvers: [VantResolver()],
dts: false
})
}

View File

@ -0,0 +1,28 @@
import compression from 'vite-plugin-compression'
export default function createCompression(env) {
const { VITE_BUILD_COMPRESS } = env
const plugin = []
if (VITE_BUILD_COMPRESS) {
const compressList = VITE_BUILD_COMPRESS.split(',')
if (compressList.includes('gzip')) {
// http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
plugin.push(
compression({
ext: '.gz',
deleteOriginFile: false
})
)
}
if (compressList.includes('brotli')) {
plugin.push(
compression({
ext: '.br',
algorithm: 'brotliCompress',
deleteOriginFile: false
})
)
}
}
return plugin
}

17
vite/plugins/index.js Normal file
View File

@ -0,0 +1,17 @@
import vue from '@vitejs/plugin-vue'
import ReactivityTransform from '@vue-macros/reactivity-transform/vite';
import createAutoImport from './auto-import'
import createSvgIcon from './svg-icon'
import createCompression from './compression'
import createSetupExtend from './setup-extend'
export default function createVitePlugins(viteEnv, isBuild = false) {
const vitePlugins = [vue({ refTransform: true })]
vitePlugins.push(ReactivityTransform())
vitePlugins.push(createAutoImport())
vitePlugins.push(createSetupExtend())
vitePlugins.push(createSvgIcon(isBuild))
isBuild && vitePlugins.push(...createCompression(viteEnv))
return vitePlugins
}

View File

@ -0,0 +1,5 @@
import setupExtend from 'unplugin-vue-setup-extend-plus/vite'
export default function createSetupExtend() {
return setupExtend({})
}

10
vite/plugins/svg-icon.js Normal file
View File

@ -0,0 +1,10 @@
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'
export default function createSvgIcon(isBuild) {
return createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/icons/svg')],
symbolId: 'icon-[dir]-[name]',
svgoOptions: isBuild
})
}