commit 30727f4f6541ef10f4ad14fccf9cb73d8ecb9395 Author: Andy Leong Date: Tue Jul 26 18:26:27 2022 +0800 脚手架搭建 diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..8c1f1e4 --- /dev/null +++ b/.babelrc @@ -0,0 +1,13 @@ +{ + "plugins": [ + [ + "import", + { + "libraryName": "vant", + "libraryDirectory": "es", + "style": true + } + ] + ] + } + \ No newline at end of file diff --git a/.env.dev b/.env.dev new file mode 100644 index 0000000..b5932ad --- /dev/null +++ b/.env.dev @@ -0,0 +1,3 @@ +NODE_ENV = 'dev' +VUE_APP_BASE_URL = 'http://localhost:8080/pars-training' +VUE_APP_CDN = 'https://cdn.xglpa.com/tcubic/wx/' \ No newline at end of file diff --git a/.env.prod b/.env.prod new file mode 100644 index 0000000..1725c6c --- /dev/null +++ b/.env.prod @@ -0,0 +1,6 @@ +NODE_ENV = 'production' +VUE_APP_BASE_URL = 'https://cdn.xglpa.com/tcubic/pdf/' +VUE_APP_API = 'https://cdn.xglpa.com/tcubic/pdf/' +VUE_APP_CDN = 'https://cdn.xglpa.com/tcubic/pdf/' +VUE_APP_APPID = '1aeedce2a31340e591a5d64080d6105b' +VUE_APP_ACTIVITYID = '20220510563146' \ No newline at end of file diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..7993c1d --- /dev/null +++ b/.env.test @@ -0,0 +1,6 @@ +NODE_ENV = 'test' +VUE_APP_BASE_URL = 'https://hd.xglpa.com/zszq-celebration/activity/' +VUE_APP_API = 'https://test.szxgl.cn/zszq-celebration' +VUE_APP_CDN = 'https://test.szxgl.cn/zszq-celebration/activity/' +VUE_APP_APPID = '1aeedce2a31340e591a5d64080d6105b' +VUE_APP_ACTIVITYID = '20220510563146' \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..403adbc --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +.DS_Store +node_modules +/dist + + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/README.md b/README.md new file mode 100644 index 0000000..c814ddc --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# 招商证券88司庆活动 + diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..e84fb41 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,8 @@ +module.exports = { + presets: [ + // '@vue/cli-plugin-babel/preset' + ['@vue/app', { + useBuiltIns: 'entry' + }] + ] +} diff --git a/bash/autoUploadTest.sh b/bash/autoUploadTest.sh new file mode 100644 index 0000000..e74ab0e --- /dev/null +++ b/bash/autoUploadTest.sh @@ -0,0 +1,3 @@ +#!/bin/sh +# 自动允许上传至测试服务器 +echo yes | deploy-cli-service deploy --mode test \ No newline at end of file diff --git a/deploy.config.js b/deploy.config.js new file mode 100644 index 0000000..8e679bc --- /dev/null +++ b/deploy.config.js @@ -0,0 +1,31 @@ +module.exports = { + projectName: 'my-cli', // 项目名称 + // privateKey: '/Users/rucky/.ssh/id_rsa', + passphrase: '', + // 测试环境部署 + test: { + // 环境对象 + name: 'szxgl测试环境', // 环境名称 + script: 'npm run build:test', // 打包命令 + host: '39.108.110.167', // 服务器地址 + port: 22, // 服务器端口号 + username: 'root', // 服务器登录用户名 + password: 'XfhdTest123', // 服务器登录密码 + distPath: 'dist', // 本地打包生成目录 + webDir: "/mnt/services/tomcat-8090-test/webapps/zszq-celebration/activity", // test替换自己实际项目目录 服务器部署路径(不可为空或'/') + isRemoveRemoteFile: true // 是否删除远程文件(默认true) + }, + // 生产环境部署 + prod: { + // 环境对象 + name: 'xglpa生产环境', // 环境名称 + script: 'npm run build:prod', // 打包命令 + host: '39.108.248.30', // 服务器地址 + port: 22, // 服务器端口号 + username: 'liangzejun', // 服务器登录用户名 + password: 'lzj.xfhd99', // 服务器登录密码 + distPath: 'dist', // 本地打包生成目录 + webDir: "/home/services/tomcats/public-webapps/xxx/front", // xxx替换自己实际项目目录 服务器部署路径(不可为空或'/') + isRemoveRemoteFile: true // 是否删除远程文件(默认true) + } +} \ No newline at end of file diff --git a/dist.zip b/dist.zip new file mode 100644 index 0000000..acf5eff Binary files /dev/null and b/dist.zip differ diff --git a/package.json b/package.json new file mode 100644 index 0000000..8a3c538 --- /dev/null +++ b/package.json @@ -0,0 +1,92 @@ +{ + "name": "hello-world", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "vue-cli-service serve --mode dev", + "test": "vue-cli-service serve --mode test", + "build:test": "vue-cli-service build --mode test", + "build:prod": "vue-cli-service build --mode prod", + "lint": "vue-cli-service lint", + "deploy:test": "bash ./bash/autoUploadTest.sh", + "deploy:prod": "deploy-cli-service deploy --mode prod" + }, + "dependencies": { + "@upload-io/vue-uploader": "^1.5.5", + "amfe-flexible": "^2.2.1", + "autoprefixer": "^9.8.8", + "axios": "^0.24.0", + "babel-polyfill": "^6.26.0", + "compression-webpack-plugin": "^5.0.1", + "core-js": "^3.6.5", + "deploy-cli-service": "^1.3.0", + "element-plus": "^2.1.9", + "es6-promise": "^4.2.8", + "gsap": "^3.9.1", + "hammerjs": "^2.0.8", + "html2canvas": "^1.0.0-rc.4", + "image-frame-player": "^1.0.2", + "node-sass": "^4.14.1", + "pdfh5": "^1.4.2", + "pixi.js": "^6.3.2", + "postcss": "^7.0.39", + "postcss-px2rem": "^0.3.0", + "qs": "^6.10.3", + "sass-loader": "^7.3.1", + "socket.io-client": "^4.5.0", + "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.17", + "uploader": "^1.45.14", + "vant": "^3.4.7", + "vconsole": "^3.11.0", + "vue": "^3.0.0", + "vue-canvas-poster": "^1.2.1", + "vue-cropper": "^1.0.3", + "vue-router": "^4.0.12", + "vue-socket.io": "^3.0.10", + "vue-video-player": "^5.0.2", + "vuex": "^4.0.2", + "weixin-js-sdk": "^1.6.0", + "xgplayer": "^2.31.6", + "xgplayer-hls.js": "^2.6.1" + }, + "devDependencies": { + "@vue/cli-plugin-babel": "~4.5.0", + "@vue/cli-plugin-eslint": "~4.5.0", + "@vue/cli-service": "~4.5.0", + "@vue/compiler-sfc": "^3.0.0", + "babel-eslint": "^10.1.0", + "babel-plugin-import": "^1.13.3", + "babel-plugin-transform-remove-console": "^6.9.4", + "eslint": "^6.7.2", + "eslint-plugin-vue": "^7.0.0", + "mini-css-extract-plugin": "^2.4.6", + "sass": "^1.47.0", + "uglifyjs-webpack-plugin": "^2.2.0", + "unplugin-auto-import": "^0.7.0", + "unplugin-element-plus": "^0.3.4", + "unplugin-vue-components": "^0.19.2", + "vue-loader": "^15.9.8", + "vue-loader-v16": "^16.0.0-beta.5.4" + }, + "eslintConfig": { + "root": true, + "env": { + "node": true + }, + "extends": [ + "plugin:vue/vue3-essential", + "eslint:recommended" + ], + "parserOptions": { + "parser": "babel-eslint" + }, + "rules": { + "no-unused-vars": "off" + } + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not dead" + ] +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..3242573 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,11 @@ +const AutoPrefixer = require("autoprefixer"); +const px2rem = require("postcss-px2rem"); +module.exports = ({ file }) => { + let remUnit; // 判断条件 请自行调整 我使用的是 mand-mobile ui 没有对vant引入进行测试 + if (file && file.dirname && file.dirname.indexOf("vant") > -1) { remUnit = 37.5; } else { remUnit = 75; } + return { + plugins: [ + px2rem({ remUnit: remUnit, }), + AutoPrefixer({ overrideBrowserslist: ["last 20 versions", "android >= 4.0"] })] + }; +} \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..df36fcf Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..d94dee8 --- /dev/null +++ b/public/index.html @@ -0,0 +1,26 @@ + + + + + + + + + + + <%= htmlWebpackPlugin.options.title %> + + + + + + +
+ + + + \ No newline at end of file diff --git a/public/share.html b/public/share.html new file mode 100644 index 0000000..9dad9d7 --- /dev/null +++ b/public/share.html @@ -0,0 +1,23 @@ + + + + + + + + + <%= htmlWebpackPlugin.options.title %> + + + + + +
+ + + + \ No newline at end of file diff --git a/src/api/httpServe.js b/src/api/httpServe.js new file mode 100644 index 0000000..7d410e7 --- /dev/null +++ b/src/api/httpServe.js @@ -0,0 +1,40 @@ +import axios from 'axios' +import QS from 'qs'; + +// 创建axios +const service = axios.create({ + // baseURL: 'https://hd.xglpa.com/pars-training', //生产环境 + // baseURL: 'http://test.szxgl.cn/pars-training', //测试环境 + // withCredentials: true, + baseURL: process.env.VUE_APP_API, + // responseType: 'json', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, +}); + + +// 添加请求拦截器 +service.interceptors.request.use(function (config) { + // 在发送请求之前做些什么 + console.log("开始请求"); + config + return config; +}, function (error) { + // 对请求错误做些什么 + return Promise.reject(error); +}); + +// 添加响应拦截器 +service.interceptors.response.use(function (response) { + + + // 对响应数据做点什么 + // console.log(response.data); + return response; +}, function (error) { + // 对响应错误做点什么 + return Promise.reject(error); +}); + +export default service; \ No newline at end of file diff --git a/src/assets/img/pdf.pdf b/src/assets/img/pdf.pdf new file mode 100644 index 0000000..8b7d7bd Binary files /dev/null and b/src/assets/img/pdf.pdf differ diff --git a/src/assets/img/share.jpg b/src/assets/img/share.jpg new file mode 100644 index 0000000..e8acfbe Binary files /dev/null and b/src/assets/img/share.jpg differ diff --git a/src/assets/logo.png b/src/assets/logo.png new file mode 100644 index 0000000..f3d2503 Binary files /dev/null and b/src/assets/logo.png differ diff --git a/src/assets/media/bgm.mp3 b/src/assets/media/bgm.mp3 new file mode 100644 index 0000000..bafe07d Binary files /dev/null and b/src/assets/media/bgm.mp3 differ diff --git a/src/assets/media/video.mp4 b/src/assets/media/video.mp4 new file mode 100644 index 0000000..355c206 Binary files /dev/null and b/src/assets/media/video.mp4 differ diff --git a/src/assets/style/global.scss b/src/assets/style/global.scss new file mode 100644 index 0000000..9ee2ec5 --- /dev/null +++ b/src/assets/style/global.scss @@ -0,0 +1,42 @@ +@charset "utf-8"; +$red:red; +$green:green; + +// DIV宽高 +@mixin box ($width,$height){ + width: $width; + height: $height; +} +// DIV宽高定位 +@mixin pos ($width,$height,$left,$top){ + width: $width; + height: $height; + position: absolute; + left: $left; + top:$top; +} + +// DIV背景 +@mixin bg_pos ($src){ + background: url($src) no-repeat; + background-size: 100% 100%; +} + +// flex居中定位 +@mixin flex (){ + display: flex; + justify-content: center; + align-items: center; +} + + +// 全屏样式 +@mixin fixed (){ + width: 100%; + height: 100%; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; +} diff --git a/src/components/Index.vue b/src/components/Index.vue new file mode 100644 index 0000000..5a75699 --- /dev/null +++ b/src/components/Index.vue @@ -0,0 +1,63 @@ + + + + + \ No newline at end of file diff --git a/src/data/imgList.js b/src/data/imgList.js new file mode 100644 index 0000000..e998de1 --- /dev/null +++ b/src/data/imgList.js @@ -0,0 +1,4 @@ +export default [ + + +]; \ No newline at end of file diff --git a/src/page/Home/Home.vue b/src/page/Home/Home.vue new file mode 100644 index 0000000..16a9f1d --- /dev/null +++ b/src/page/Home/Home.vue @@ -0,0 +1,50 @@ + + + + + \ No newline at end of file diff --git a/src/page/Home/main.js b/src/page/Home/main.js new file mode 100644 index 0000000..e406460 --- /dev/null +++ b/src/page/Home/main.js @@ -0,0 +1,24 @@ + +import "babel-polyfill" +import { createApp } from 'vue' +import App from './Home.vue' +import Vue from 'vue' +import store from '@/store' +import "amfe-flexible" + + +import VConsole from 'vconsole' +const vConsole = new VConsole(); + + +// 注册全局方法 +const app = createApp(App); + +// app.use(router) +app.use(store) +app.mount('#app') + + + + + diff --git a/src/page/Share/Share.vue b/src/page/Share/Share.vue new file mode 100644 index 0000000..08fe41e --- /dev/null +++ b/src/page/Share/Share.vue @@ -0,0 +1,34 @@ + + + + + \ No newline at end of file diff --git a/src/page/Share/main.js b/src/page/Share/main.js new file mode 100644 index 0000000..a3b8990 --- /dev/null +++ b/src/page/Share/main.js @@ -0,0 +1,30 @@ + +import { createApp } from 'vue' +import App from './Share.vue' +import Vue from 'vue' +import store from '@/store' +import "amfe-flexible" +import h5plugin from "../../utils/plugin" +import VConsole from 'vconsole' +const vConsole = new VConsole(); + + + +// if (process.env.NODE_ENV != 'production') { +// // 非正式环境都打开debug模式 +// const vConsole = new VConsole(); +// } + + +// 注册全局方法 +const app = createApp(App); +// app.config.globalProperties.$h5plugin = h5plugin; + +// app.use(router) +app.use(store) +app.mount('#share') + + + + + diff --git a/src/plugins/elementPlus.js b/src/plugins/elementPlus.js new file mode 100644 index 0000000..6e3b222 --- /dev/null +++ b/src/plugins/elementPlus.js @@ -0,0 +1,14 @@ +// // 完整引入 +import ElementPlus from 'element-plus' +import 'element-plus/dist/index.css' + + +// 按需引入 +// import { ElButton } from "element3"; +// import 'element3/lib/theme-chalk/button.css' + +export default function (app) { + // 完整插件 + app.use(ElementPlus) + // app.use(ElButton) +} \ No newline at end of file diff --git a/src/plugins/vantUI.js b/src/plugins/vantUI.js new file mode 100644 index 0000000..e69de29 diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..a5eb080 --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,10 @@ +import { createRouter, createWebHashHistory } from 'vue-router'; + +const router = createRouter({ + history: createWebHashHistory(), + routes: [ + { path: '/', component: () => import('@/views/Home.vue') } + ] +}); + +export default router diff --git a/src/store/index.js b/src/store/index.js new file mode 100644 index 0000000..b0edb39 --- /dev/null +++ b/src/store/index.js @@ -0,0 +1,38 @@ +import { createStore } from 'vuex'; +import h5plugin from "@/utils/plugin.js" + +export default createStore({ + state: { + userProgress: { + pass1IsComplete: 0, //第一题完成情况 + pass2IsComplete: 0, //第二题完成情况 + pass3IsComplete: 0, //第三题完成情况 + pass1IsDraw: 0, //第一题抽奖情况 + pass2IsDraw: 0, //第二题抽奖情况 + pass3IsDraw: 0, //第三题抽奖情况 + pass1Prize: '', //第一题抽奖结果 + pass2Prize: '', //第二题抽奖结果 + pass3Prize: '', //第三题抽奖结果 + }, //用户进度 + openId: '', //用户openid + openToken: '', //用户openToken + pass1IsComplete: '', //第一题完成情况 + pass1IsDraw: '', //第一题抽奖情况 + pass1Prize: '', //第一题抽奖结果 + pass2IsComplete: '', //第二题完成情况 + pass2IsDraw: '', //第二题抽奖情况 + pass2Prize: '', //第二题抽奖结果 + pass3IsComplete: '', //第三题完成情况 + pass3IsDraw: '', //第三题抽奖情况 + pass3Prize: '', //第三题抽奖结果 + }, + // 改变方法 + mutations: { + updateOpenid(state) { + // state.openid = changVal + // console.log(state.openid); + } + }, + actions: {}, + modules: {}, +}) \ No newline at end of file diff --git a/src/utils/imgPreloader.js b/src/utils/imgPreloader.js new file mode 100644 index 0000000..00511ad --- /dev/null +++ b/src/utils/imgPreloader.js @@ -0,0 +1,22 @@ +const imgPreloader = url => { + return new Promise((resolve, reject) => { + let image = new Image(); + image.src = url; + image.onload = () => { + resolve(); + // console.log(image.src); + }; + image.onerror = () => { + reject(); + }; + }); +}; +export const imgsPreloader = imgs => { + let promiseArr = []; + imgs.forEach(element => { + promiseArr.push(imgPreloader(element)); + // console.log(element); + }); + console.log("图片资源数量:", promiseArr.length); + return Promise.all(promiseArr); +}; \ No newline at end of file diff --git a/src/utils/io.js b/src/utils/io.js new file mode 100644 index 0000000..0fda81a --- /dev/null +++ b/src/utils/io.js @@ -0,0 +1,39 @@ +const getSocket = (url, params, callback) => { + let socket; + + if (typeof (WebSocket) === 'undefined') { + console.log('您的浏览器不支持WebSocket'); + } else { + console.log('您的浏览器支持WebSocket'); + + // 初始化 WebSocket 对象,指定要连接的服务器地址与端口建立连接 + socket = new WebSocket(url); + + // 打开事件 + socket.onopen = function () { + console.log('Socket 已打开'); + socket.send(params); + }; + + // 获得消息事件 + socket.onmessage = function (msg) { + // 发现消息进入, 开始处理前端触发逻辑 + callback(msg, socket); + }; + + // 关闭事件 + socket.onclose = function () { + console.log('Socket 已关闭'); + }; + + // 发生了错误事件 + socket.onerror = function () { + console.log('Socket 发生了错误,请刷新页面'); + // 此时可以尝试刷新页面 + }; + } +} + +export { + getSocket +} diff --git a/src/utils/plugin.js b/src/utils/plugin.js new file mode 100644 index 0000000..6e28225 --- /dev/null +++ b/src/utils/plugin.js @@ -0,0 +1,265 @@ +import store from '../store' + +const h5plugin = { + //是否在微信环境 + isWX() { + var ua = window.navigator.userAgent.toLowerCase(); + if (ua.match(/MicroMessenger/i) == 'micromessenger') { + console.log("微信环境"); + return true; + } else { + console.log("非微信环境"); + return false; + } + }, + // 判断微博环境 + isWeibo() { + var ua = window.navigator.userAgent.toLowerCase(); + if (ua.match(/WeiBo/i) == "weibo") { + console.log("微博环境"); + return true; + } else { + console.log("非微博环境"); + return false; + } + + }, + + // 判断Safari环境 + isSafari() { + var ua = window.navigator.userAgent.toLowerCase(); + if ((/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent))) { + console.log("Safari环境"); + return true; + } else { + console.log("非Safari环境"); + return false; + } + + }, + + //是否为安卓 + isAndriod() { + var naviga = navigator.userAgent; + if (naviga.indexOf('Android') > -1 || naviga.indexOf('Adr') > -1) { + console.log("Andriod环境"); + return true; + } else { + console.log("非Andriod环境"); + + return false; + + } + }, + //路径获取关键字 + getQueryString(name) { + //截取页面传递字符串 + var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); + var r = window.location.search.substr(1).match(reg); + if (r != null) return unescape(r[2]); + return null; + }, + + // 判断全面屏和非全面屏 + judgeBigScreen() { //,这里根据返回值 true 或false ,返回true的话 则为全面屏 + let result = false; + const rate = window.screen.height / window.screen.width; + let limit = window.screen.height == window.screen.availHeight ? 1.8 : 1.65; // 临界判断值 + // window.screen.height为屏幕高度 + // window.screen.availHeight 为浏览器 可用高度 + if (rate > limit) { + // console.log("全面屏"); + + result = true; + return result; + } + // console.log("非面屏"); + return result; + }, + + // 获取url html名称 + getUrlHtml() { + //获取url地址 + var ts_href = window.location.href; + var ts_mainText = ""; + //获取地址最后一个“/”的下标 + var ts_indexof = ts_href.lastIndexOf("/"); + //获取地址“/”之后的的内容 + var ts_indexText = ts_href.substring(ts_indexof + 1); + //获取地址“.html”的下标 + var ts_htmlBeforeText = ts_indexText.indexOf(".html"); + //获取 “/”到".html"之间的内容 + ts_mainText = ts_indexText.substring(0, ts_htmlBeforeText); + + console.log("当前入口:", ts_mainText); + return ts_mainText; + + }, + + // 获取cookie中的值 + getSetCookie(name, value, options) { + if (typeof value != 'undefined') { + options = options || {}; + + if (value === null) { + value = ''; + options = this._extend({}, options, true); + options.expires = -1; + } + + var expires = ''; + + if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { + var date; + + if (typeof options.expires == 'number') { + date = new Date(); + date.setTime(date.getTime() + options.expires * 24 * 60 * 60 * 1000); + } else { + date = options.expires; + } + + expires = '; expires=' + date.toUTCString(); + } + + var path = options.path ? '; path=' + options.path : ''; + var domain = options.domain ? '; domain=' + options.domain : ''; + var secure = options.secure ? '; secure' : ''; + document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join(''); + } else { + var cookieValue = null; + + if (document.cookie && document.cookie != '') { + var cookies = document.cookie.split(';'); + + for (var i = 0; i < cookies.length; i++) { + // var cookie = $.trim(cookies[i]); + var cookie = cookies[i].trim(); + + if (cookie.substring(0, name.length + 1) == name + '=') { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + + return cookieValue; + } + }, + + // 安卓机型自动播放音乐 + BGMAutoPlayMgr(url) { + this.audioContext = new (window.AudioContext || window.webkitAudioContext || window.mozAudioContext)(); + this.sourceNode = null; + this.buffer = null; + this.isPlayingBGM = false; + this.toggleBGM = function () { + if (typeof this.sourceNode == 'object') { + if (this.isPlayingBGM) { + this.sourceNode.stop(); + this.isPlayingBGM = false; + } else this._playSourceNode(); + } + } + this._playSourceNode = function () { + const audioContext = this.audioContext; + audioContext.resume(); + const _sourceNode = audioContext.createBufferSource(); + _sourceNode.buffer = this.buffer; + _sourceNode.loop = true; + _sourceNode.connect(audioContext.destination); + _sourceNode.start(0); + this.sourceNode = _sourceNode; + this.isPlayingBGM = true; + } + let loadAndAutoPlay = (audioUrl) => { + const audioContext = this.audioContext; + const xhr = new XMLHttpRequest(); + xhr.open('GET', audioUrl, true); + xhr.responseType = 'arraybuffer'; + xhr.onreadystatechange = () => { + if (xhr.status < 400 && xhr.status >= 200 && xhr.readyState === 4) { + audioContext.decodeAudioData(xhr.response, buffer => { + this.buffer = buffer; + WeixinJSBridge.invoke("getNetworkType", {}, () => this._playSourceNode()); + }); + } + } + xhr.send(); + } + loadAndAutoPlay(url); + loadAndAutoPlay = null; + }, + + // 金管家获取openid及openToken + getJGJId() { + return new Promise(resolve => { + // 获取openid + PALifeOpen.getOpenId( + { + appId: '1aeedce2a31340e591a5d64080d6105b' // 商户编号,区分⽣产和测试环境商户编号 + }, + rsp => { + // 调⽤接⼝成功后的回调函数 + console.log('success', rsp.data); + store.state.openId = rsp.data.openId + store.state.openToken = rsp.data.openToken + if (rsp.ret == 0) { + store.state.openId = rsp.data.openId + store.state.openToken = rsp.data.openToken + const data = { + id: store.state.openId, + token: store.state.openToken + }; + resolve(data); + // console.log(`获取到金管家openid时间:${Math.abs(s_t - new Date().getTime())}`); + } + if (rsp.ret == -1) { + console.log(JSON.stringify(rsp)); + } + }, + e => { + // 调⽤接⼝异常的回调函数 + console.log('failed', e); + } + ) + }) + }, + + // 金管家内部埋点 + addPoint(page, spage, des = {}) { + const activityId = process.env.VUE_APP_ACTIVITYID; + PALifeOpen.invoke( + "device", + "addRecord", + { + eventId: `499${page}-${activityId}`, //必填,根据需求 + labelId: `499${page}${spage}-${activityId}`, //必填,根据需求 + // 扩展参数 + parameters: { + ext: JSON.stringify(des) + } + }, + // 调用接口成功后的回调函数 // alert(JSON.stringify(rsp)) + rsp => console.debug("success ", rsp), + // 调用接口异常的回调函数 + e => console.debug("failed ", e), + { + timeout: 86400000 + } + ); + return this; + }, + + // 百度统计埋点 + addPointByBd(des) { + _hmt && _hmt.push(["_trackEvent", `${des}`, `${des} success`]); + return this; + }, + + + + +} + +export default h5plugin; \ No newline at end of file diff --git a/src/utils/websocket.min.js b/src/utils/websocket.min.js new file mode 100644 index 0000000..0cbc023 --- /dev/null +++ b/src/utils/websocket.min.js @@ -0,0 +1,4 @@ +/*reconnecting-websocket.min.js*/ + +!function(a,b){"function"==typeof define&&define.amd?define([],b):"undefined"!=typeof module&&module.exports?module.exports=b():a.ReconnectingWebSocket=b()}(this,function(){function a(b,c,d){function l(a,b){var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,!1,!1,b),c}var e={debug:!1,automaticOpen:!0,reconnectInterval:1e3,maxReconnectInterval:3e4,reconnectDecay:1.5,timeoutInterval:2e3};d||(d={});for(var f in e)this[f]="undefined"!=typeof d[f]?d[f]:e[f];this.url=b,this.reconnectAttempts=0,this.readyState=WebSocket.CONNECTING,this.protocol=null;var h,g=this,i=!1,j=!1,k=document.createElement("div");k.addEventListener("open",function(a){g.onopen(a)}),k.addEventListener("close",function(a){g.onclose(a)}),k.addEventListener("connecting",function(a){g.onconnecting(a)}),k.addEventListener("message",function(a){g.onmessage(a)}),k.addEventListener("error",function(a){g.onerror(a)}),this.addEventListener=k.addEventListener.bind(k),this.removeEventListener=k.removeEventListener.bind(k),this.dispatchEvent=k.dispatchEvent.bind(k),this.open=function(b){h=new WebSocket(g.url,c||[]),b||k.dispatchEvent(l("connecting")),(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","attempt-connect",g.url);var d=h,e=setTimeout(function(){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","connection-timeout",g.url),j=!0,d.close(),j=!1},g.timeoutInterval);h.onopen=function(){clearTimeout(e),(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onopen",g.url),g.protocol=h.protocol,g.readyState=WebSocket.OPEN,g.reconnectAttempts=0;var d=l("open");d.isReconnect=b,b=!1,k.dispatchEvent(d)},h.onclose=function(c){if(clearTimeout(e),h=null,i)g.readyState=WebSocket.CLOSED,k.dispatchEvent(l("close"));else{g.readyState=WebSocket.CONNECTING;var d=l("connecting");d.code=c.code,d.reason=c.reason,d.wasClean=c.wasClean,k.dispatchEvent(d),b||j||((g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onclose",g.url),k.dispatchEvent(l("close")));var e=g.reconnectInterval*Math.pow(g.reconnectDecay,g.reconnectAttempts);setTimeout(function(){g.reconnectAttempts++,g.open(!0)},e>g.maxReconnectInterval?g.maxReconnectInterval:e)}},h.onmessage=function(b){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onmessage",g.url,b.data);var c=l("message");c.data=b.data,k.dispatchEvent(c)},h.onerror=function(b){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onerror",g.url,b),k.dispatchEvent(l("error"))}},1==this.automaticOpen&&this.open(!1),this.send=function(b){if(h)return(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","send",g.url,b),h.send(b);throw"INVALID_STATE_ERR : Pausing to reconnect websocket"},this.close=function(a,b){"undefined"==typeof a&&(a=1e3),i=!0,h&&h.close(a,b)},this.refresh=function(){h&&h.close()}}return a.prototype.onopen=function(){},a.prototype.onclose=function(){},a.prototype.onconnecting=function(){},a.prototype.onmessage=function(){},a.prototype.onerror=function(){},a.debugAll=!1,a.CONNECTING=WebSocket.CONNECTING,a.OPEN=WebSocket.OPEN,a.CLOSING=WebSocket.CLOSING,a.CLOSED=WebSocket.CLOSED,a}); + diff --git a/src/utils/wxshare.js b/src/utils/wxshare.js new file mode 100644 index 0000000..087ae27 --- /dev/null +++ b/src/utils/wxshare.js @@ -0,0 +1,61 @@ +import wx from 'weixin-js-sdk'; +import axios from "axios"; + +export function wxShare(option) { + let url = location.href.split('#')[0]; + // qiween: https://www.qiween.com/wxapi/api/jsconfig + // 信蜂: https://wx.xfhd.net/wxapi/api/jsconfig?appid=wx41d80a1bb01f658d + axios.get('https://wx.xfhd.net/wxapi/api/jsconfig?appid=wx41d80a1bb01f658d', { + params: { url } + }) + .then((res) => { + let data = res.data; + wx.config({ + debug: false, // 开启调试模式 + appId: data.appId, // 必填,公众号的唯一标识 + timestamp: data.timestamp, // 必填,生成签名的时间戳 + nonceStr: data.nonceStr, // 必填,生成签名的随机串 + signature: data.signature, // 必填,签名,见附录1 + jsApiList: [ + 'checkJsApi', + 'updateTimelineShareData', + 'updateAppMessageShareData', + ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 + }) + wx.ready(function () { + wx.updateTimelineShareData({ + title: option.title, // 分享标题 + link: option.link, // 分享链接 + imgUrl: option.imgUrl, // 分享图标 + desc: option.desc, // 分享描述 + success() {// 用户成功分享后执行的回调函数 + console.log("成功!"); + _hmt.push(['_trackEvent', '微信分享', '分享好友成功',]) + }, + cancel() {// 用户取消分享后执行的回调函数 + + console.log("取消!"); + + } + }); + wx.updateAppMessageShareData({ + title: option.title, // 分享标题 + desc: option.desc, // 分享描述 + link: option.link, // 分享链接 + imgUrl: option.imgUrl, // 分享图标 + success() {// 用户成功分享后执行的回调函数 + console.log("成功!"); + _hmt.push(['_trackEvent', '微信分享', '分享朋友圈成功',]) + + + }, + cancel() {// 用户取消分享后执行的回调函数 + console.log("取消!"); + + } + }) + }) + }) + .catch(() => { + }); +} \ No newline at end of file diff --git a/vue.config.js b/vue.config.js new file mode 100644 index 0000000..e504c0f --- /dev/null +++ b/vue.config.js @@ -0,0 +1,112 @@ +const path = require('path'); +const resolve = (dir) => path.join(__dirname, '.', dir); +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); +const isProduction = process.env.NODE_ENV === 'production' +const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV); +const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i; +const CompressionWebpackPlugin = require("compression-webpack-plugin"); + + +module.exports = { + // 多页面配置 + pages: { + index: { + entry: 'src/page/Home/main.js', + template: 'public/index.html', + filename: 'index.html', + title: '招商证券88司庆活动', + }, + share: { + entry: 'src/page/Share/main.js', + template: 'public/share.html', + filename: 'share.html', + title: '分享页', + } + }, + + // 打包路径配置 + productionSourceMap: false, + publicPath: process.env.NODE_ENV == "production" ? process.env.VUE_APP_CDN : './', // CDN路径 + // publicPath: process.env.VUE_APP_CDN, // CDN路径 + outputDir: 'dist', //打包后生成的目录名称 + assetsDir: 'static', //静态资源名称 + indexPath: 'index.html', //html的输出路径 + + + // css相关配置 + css: { + // 引入scss公共样式 + loaderOptions: { + sass: { + data: `@import "@/assets/style/global.scss";` + } + }, + extract: true // 是否使用css分离插件 ExtractTextPlugin + }, + + // filenameHashing: false, //去掉打包后的hash值 + + // 开启gzip压缩 + configureWebpack: config => { + const plugins = []; + if (IS_PROD) { + plugins.push( + new CompressionWebpackPlugin({ + filename: "[path].gz[query]", + algorithm: "gzip", + test: productionGzipExtensions, + threshold: 10240, + minRatio: 0.8 + }) + ); + + } + config.plugins = [...config.plugins, ...plugins]; + }, + + chainWebpack: config => { + // 别名配置 + config.resolve.alias + .set("@", resolve("src")) + .set("@assets", resolve("src/assets")) + .set("@views", resolve("src/views")) + + // 标题配置 + // config + // .plugin('html') + // .tap(args => { + // args[0].title = '双优精英' + // return args + // }) + + // babel-polyfill配置 + config.entry('main').add('babel-polyfill') + + devtool: 'inline-source-map' + }, + + // 关闭eslint校验 + lintOnSave: false, + devServer: { + overlay: { + warning: false, + errors: false + }, + + // proxy: { + // // wss跨域配置 + // '/wsq': { + // //需要访问的服务器地址 + // target: 'wss://h5.qiween.cn/jlg520/websocket', + // //后面空格替换前面,确保服务器有这个地址 + // pathRewrite: { '^/wsq': '' }, + // //false时,以原域名访问服务器;true时,原域名变成服务器域名访问 + // changeOrigin: true + // } + // } + + }, + + productionSourceMap: false, // 生产环境是否生成 sourceMap 文件 + +}; \ No newline at end of file