作者 陶霁轩

init

  1 +.vscode/
  2 +.idea/
  3 +node_modules
  4 +npm-debug.log
  1 +registry = https://registry.npm.taobao.org/
  1 +{
  2 + "semi": false,
  3 + "singleQuote": true,
  4 + "trailingComma": "none",
  5 + "arrowParens": "avoid",
  6 + "bracketSpacing": true
  7 +}
  1 +## 项目名称
  2 +
  3 +> vue2-mo
  4 +
  5 +## 运行说明
  6 +
  7 +- 安装依赖
  8 +
  9 + ```
  10 + npm i
  11 + ```
  12 +
  13 +- 本地运行(测试接口)
  14 +
  15 + ```
  16 + npm start
  17 + ```
  18 +
  19 +- 本地运行(正式接口)
  20 +
  21 + ```
  22 + npm test
  23 + ```
  24 +
  25 +- 构建(测试接口)
  26 +
  27 + ```
  28 + npm run build:test
  29 + ```
  30 +
  31 +- 构建(正式接口)
  32 + ```
  33 + npm run build
  34 + ```
  35 +
  36 +## 适配相关
  37 +
  38 +开发使用 px 即可,自动转化为 rem
  39 +
  40 +### **modules/index.html**
  41 +
  42 +最大响应宽度设置
  43 +
  44 +### **postcss.config**
  45 +
  46 +转化尺寸配置
  47 +
  48 +## 配置相关
  49 +
  50 +### **src/constants **
  51 +
  52 +配置各个环境的常量,可自由添加
  53 +
  54 +### **scripts/requests**
  55 +
  56 +axios 请求封装,包括公共方法,api,上报等
  57 +
  58 +### **scripts/utils**
  59 +
  60 +工具函数
  61 +
  62 +### **scripts/filters**
  63 +
  64 +过滤器
  1 +/**
  2 + * @file babel 配置文件
  3 + */
  4 +module.exports = {
  5 + plugins: ['@babel/plugin-syntax-dynamic-import'],
  6 + presets: [
  7 + [
  8 + '@babel/preset-env', {
  9 + 'modules': false,
  10 + 'useBuiltIns': 'usage'
  11 + }
  12 + ]
  13 + ]
  14 +}
  1 +Chrome >= 33
  2 +iOS >= 8
  1 +/**
  2 + * @file webpack 配置文件
  3 + */
  4 +const path = require('path')
  5 +
  6 +const CleanWebpackPlugin = require('clean-webpack-plugin')
  7 +const HtmlWebpackPlugin = require('html-webpack-plugin')
  8 +const MiniCssExtractPlugin = require('mini-css-extract-plugin')
  9 +const { VueLoaderPlugin } = require('vue-loader')
  10 +const hashDigestLength = 6 // 文件名末尾 hash 值长度
  11 +/**
  12 + * webpack 配置项
  13 + * @param {Object} env - 环境对象
  14 + * @param {Object} argv - 命令行参数选项
  15 + * @param {String} argv.mode - 模式
  16 + */
  17 +module.exports = function (env = {}, argv) {
  18 + let productionEnv = (!argv.host && argv.mode == 'production'); //生产环境下打包情况不一样,先清除旧的dist,部分文件的publicPath也不一样
  19 + let config = {
  20 + devtool: productionEnv ? '' : 'source-map',
  21 +
  22 + resolve: {
  23 + alias: {
  24 + '@': path.resolve(__dirname, '../src'),
  25 + components: path.resolve(__dirname, '../src/components'),
  26 + images: path.resolve(__dirname, '../src/images'),
  27 + modules: path.resolve(__dirname, '../src/modules'),
  28 + scripts: path.resolve(__dirname, '../src/scripts'),
  29 + styles: path.resolve(__dirname, '../src/styles'),
  30 + }
  31 + },
  32 +
  33 + entry: {
  34 + app: './src/scripts',
  35 + },
  36 +
  37 + output: {
  38 + // filename: 'scripts/[name]_[chunkhash].js',
  39 + filename: 'scripts/[name].js',
  40 + hashDigestLength,
  41 + // path: path.resolve(__dirname, productionEnv ? '../../dist/m/' : '../dist/'),
  42 + path: path.resolve(__dirname, productionEnv ? '../dist/' : '../dist/'),
  43 + },
  44 +
  45 + module: {
  46 + rules: [{
  47 + test: /\.(jpg|png|svg|gif)$/,
  48 + use: [{
  49 + loader: 'file-loader',
  50 + options: {
  51 + // name: `[name]_[hash:${hashDigestLength}].[ext]`,
  52 + name: `[name].[ext]`,
  53 + outputPath: 'images',
  54 + publicPath: productionEnv ? '/images/' : '/images/',
  55 + //https://inside.wx.luckyxp.com.cn/webup/data/User/wxtest/home/project/lls-m/dist/images/
  56 + }
  57 + }]
  58 + }, {
  59 + test: /\.(woff|ttf|woff2|eot)$/,
  60 + use: [
  61 + {
  62 + loader: 'file-loader',
  63 + options: {
  64 + outputPath: 'styles',
  65 + publicPath: './'
  66 + }
  67 + }
  68 + ]
  69 + }, {
  70 + test: /\.(css|postcss)$/,
  71 + use: [{
  72 + loader: MiniCssExtractPlugin.loader
  73 + }, {
  74 + loader: 'css-loader',
  75 + options: {
  76 + importLoaders: 1
  77 + }
  78 + }, {
  79 + loader: 'postcss-loader',
  80 + }]
  81 + }, {
  82 + test: /\.js$/,
  83 + exclude: /node_modules/,
  84 + use: [{
  85 + loader: 'babel-loader'
  86 + }]
  87 + }, {
  88 + test: /\.vue$/,
  89 + use: [{
  90 + loader: 'vue-loader',
  91 + options: {
  92 + compilerOptions: {
  93 + preserveWhitespace: false
  94 + }
  95 + }
  96 + }]
  97 + }]
  98 + },
  99 +
  100 + plugins: [
  101 + new VueLoaderPlugin(),
  102 + new MiniCssExtractPlugin({
  103 + filename: 'styles/[name]_[chunkhash].css'
  104 + // filename: 'styles/[name].css'
  105 + }),
  106 + new HtmlWebpackPlugin({
  107 + title: 'AFK Journey',
  108 + template: './src/index.html',
  109 + })
  110 + ],
  111 +
  112 + optimization: {
  113 + runtimeChunk: {
  114 + name: 'manifest'
  115 + },
  116 + splitChunks: {
  117 + chunks: 'all',
  118 + minChunks: 2
  119 + }
  120 + },
  121 +
  122 + performance: {
  123 + hints: false
  124 + },
  125 +
  126 + devServer: {
  127 + contentBase: path.join(__dirname, '../'),
  128 + disableHostCheck: true,
  129 + open: true,
  130 + host: 'localhost',
  131 + // host: '192.168.17.6',
  132 + // host: 'inside.wx.luckyxp.com.cn',
  133 + port: 8001,
  134 + proxy: {
  135 + }
  136 + }
  137 + }
  138 +
  139 + config.plugins = config.plugins.concat([
  140 + // new CleanWebpackPlugin([productionEnv ? 'm' : 'dist'], {
  141 + // root: path.join(__dirname, productionEnv ? '../../dist/' : '../')
  142 + // }),
  143 + new CleanWebpackPlugin(['dist'], {
  144 + root: path.join(__dirname, '../')
  145 + }),
  146 + ])
  147 +
  148 + return config
  149 +}
此 diff 太大无法显示。
  1 +{
  2 + "name": "igame",
  3 + "version": "1.0.0",
  4 + "description": "igame",
  5 + "main": "index.js",
  6 + "scripts": {
  7 + "start": "webpack-dev-server --config build/webpack.config.js --mode=development --progress",
  8 + "test": "webpack-dev-server --config build/webpack.config.js --mode=production --progress",
  9 + "build:test": "webpack --config build/webpack.config.js --mode=development --progress",
  10 + "build": "webpack --config build/webpack.config.js --mode=production --progress"
  11 + },
  12 + "repository": {
  13 + "type": "git",
  14 + "url": ""
  15 + },
  16 + "author": "taojixuan",
  17 + "devDependencies": {
  18 + "@babel/core": "^7.3.4",
  19 + "@babel/plugin-syntax-dynamic-import": "^7.2.0",
  20 + "@babel/preset-env": "^7.3.4",
  21 + "autoprefixer": "^9.4.9",
  22 + "axios": "^0.18.0",
  23 + "babel-loader": "^8.0.5",
  24 + "clean-webpack-plugin": "^1.0.1",
  25 + "css-loader": "^2.1.0",
  26 + "cssnano": "^4.1.10",
  27 + "file-loader": "^3.0.1",
  28 + "html-webpack-plugin": "^3.2.0",
  29 + "mini-css-extract-plugin": "^0.5.0",
  30 + "node-sass": "^7.0.1",
  31 + "postcss-import": "^12.0.1",
  32 + "postcss-loader": "^3.0.0",
  33 + "postcss-nested": "^4.1.2",
  34 + "sass-loader": "^13.0.2",
  35 + "style-loader": "^3.3.1",
  36 + "vue": "^2.6.10",
  37 + "vue-color": "^2.7.0",
  38 + "vue-loader": "^15.6.4",
  39 + "vue-router": "^3.0.2",
  40 + "vue-template-compiler": "^2.6.10",
  41 + "vuex": "^3.1.0",
  42 + "webpack": "^4.29.5",
  43 + "webpack-cli": "^3.2.3",
  44 + "webpack-dev-server": "^3.2.1"
  45 + },
  46 + "dependencies": {
  47 + "clipboard": "^2.0.11",
  48 + "core-js": "^2.5.7",
  49 + "postcss-px2rem": "^0.3.0",
  50 + "vant": "^2.12.50"
  51 + }
  52 +}
  1 +module.exports = {
  2 + plugins: [
  3 + require('postcss-import'),
  4 + require('postcss-nested'),
  5 + require('postcss-px2rem')({
  6 + 'remUnit': 75
  7 + }),
  8 + require('autoprefixer'),
  9 + require('cssnano')({
  10 + preset: ['default', {
  11 + mergeLonghand: false,
  12 + }]
  13 + }),
  14 + ]
  15 +}
  1 +<!DOCTYPE html>
  2 +<html lang="zh-Hans">
  3 +
  4 +<head>
  5 + <meta charset="UTF-8">
  6 + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover">
  7 + <title>
  8 + <%= htmlWebpackPlugin.options.title %>
  9 + </title>
  10 + <meta name="keywords"
  11 + content="afk journey,AFK,AFK2,RPG,RPGGAMES,MMORPG,FREEGAME,FARLIGHT,IDLE RPG,Strategy RPG,Gacha,Journey,Open World" />
  12 + <link rel="icon"
  13 + href="https://oss-resource.farlightgames.com/p/SDK/200000/0/100000/2023-04-23/D:/img/f92c62a9048640b522cdb0fd00eb379b.ico">
  14 +</head>
  15 +
  16 +<body>
  17 + <div id="app"></div>
  18 +</body>
  19 +<style>
  20 + .grecaptcha-badge {
  21 + display: none !important;
  22 + opacity: 0;
  23 + }
  24 +</style>
  25 +<script>
  26 + (function (win) {
  27 + var doc = win.document;
  28 + var docEl = doc.documentElement;
  29 + var tid;
  30 + function refreshRem () {
  31 + var width = docEl.getBoundingClientRect().width;
  32 + if (width > 600) { // 最大宽度
  33 + width = 600;
  34 + }
  35 + var rem = width / 10;
  36 + docEl.style.fontSize = rem + 'px';
  37 + }
  38 +
  39 + win.addEventListener('resize', function () {
  40 + clearTimeout(tid);
  41 + tid = setTimeout(refreshRem, 300);
  42 + }, false);
  43 + win.addEventListener('pageshow', function (e) {
  44 + if (e.persisted) {
  45 + clearTimeout(tid);
  46 + tid = setTimeout(refreshRem, 300);
  47 + }
  48 + }, false);
  49 +
  50 + refreshRem();
  51 +
  52 + })(window);
  53 +</script>
  54 +
  55 +</html>
  56 +
  57 +</html>
  1 +<template>
  2 + <router-view></router-view>
  3 +</template>
  4 +
  5 +<script>
  6 +export default {
  7 + data() {
  8 + return {
  9 + };
  10 + },
  11 + methods: {
  12 + },
  13 + created() {
  14 + },
  15 + mounted() {
  16 + },
  17 + computed: {},
  18 +};
  19 +</script>
  20 +
  21 +<style lang="postcss">
  22 +
  23 +</style>
  1 +<template>
  2 + <div>not found</div>
  3 +</template>
  1 +.container {
  2 + width: 750px;
  3 + height: 4288px;
  4 + margin: auto;
  5 + background: url(../../images/bg.jpg) no-repeat top center/100% auto;
  6 +}
  1 +<template>
  2 + <div class="container">首页</div>
  3 +</template>
  4 +
  5 +<script>
  6 +import Tracker from '@/scripts/tracker'
  7 +import { reqPublic } from 'scripts/requests/index.js'
  8 +import Clipboard from 'clipboard'
  9 +import { ALink, getParameterByName, getUrlSearchJson } from 'scripts/util'
  10 +import { URLS, ENV } from 'scripts/constants/index'
  11 +export default {
  12 + components: {},
  13 + data() {
  14 + return {}
  15 + },
  16 + computed: {},
  17 + methods: {},
  18 + created() {},
  19 + mounted() {},
  20 + watch: {},
  21 +}
  22 +</script>
  23 +
  24 +<style lang="postcss" scoped>
  25 +@import './index.postcss';
  26 +</style>
  1 +<template>
  2 + <div class="root">
  3 + <transition name="el-fade-in" mode="out-in">
  4 + <router-view></router-view>
  5 + </transition>
  6 + </div>
  7 +</template>
  8 +
  9 +<script>
  10 +export default {
  11 + data() {
  12 + return {}
  13 + },
  14 + methods: {
  15 + initMenu() {},
  16 + },
  17 + created() {},
  18 + mounted() {},
  19 + computed: {},
  20 +}
  21 +</script>
  22 +
  23 +<style lang="postcss"></style>
  1 +/**
  2 + * @file 常量 - 环境
  3 + */
  4 + const ENV = process.env.NODE_ENV === 'production' ? 'prod' : 'dev';
  5 + const HOSTNAME = process.env.NODE_ENV === 'production' ? 'https://game-reserve-api.farlightgames.com' : 'https://game-reserve-api-test.farlightgames.com';
  6 + const IOS_APPID = process.env.NODE_ENV === "production" ? "1628970855" : "1131944535";
  7 + const ANDROID_APPID = process.env.NODE_ENV === "production" ? "com.farlightgames.igame.gp" : "com.lilithgame.sgame.android.cn";
  8 + const IOS_LILITH_APPID = process.env.NODE_ENV === "production" ? "10013832" : "8876096";
  9 + const ANDROID_LILITH_APPID = process.env.NODE_ENV === "production" ? "10013832" : "5660453";
  10 + const FILTER_ID = process.env.NODE_ENV === "production" ? 85252 : 89032;
  11 + export default {
  12 + ENV,
  13 + HOSTNAME,
  14 + IOS_APPID,
  15 + ANDROID_APPID,
  16 + IOS_LILITH_APPID,
  17 + ANDROID_LILITH_APPID,
  18 + FILTER_ID
  19 + }
  1 +import ENV from './env'
  2 +import URLS from './urls'
  3 +
  4 +export { ENV,URLS }
  1 +const kvUrl = 'https://oss-resource.farlightgames.com/p/SDK/200000/0/100000/2023-04-23/D:/video/7f42f378ea8a098ede28586170c4c056.mp4'
  2 +const videoUrl = 'https://oss-resource.farlightgames.com/p/SDK/200000/0/100000/2023-04-23/D:/video/b5f951cc9b914e98ea25dab668cfd1c6.mp4'
  3 +const mLink = process.env.NODE_ENV === 'production' ? 'https://afkjourney.farlightgames.com/m/index.html' : 'https://inside.wx.luckyxp.com.cn/webup/data/User/wxtest/home/project/lls-m/dist/index.html'
  4 +const pcLink = process.env.NODE_ENV === 'production' ? 'https://afkjourney.farlightgames.com/index.html' : 'https://inside.wx.luckyxp.com.cn/webup/data/User/wxtest/home/project/lls-pc/dist/index.html'
  5 +export default {
  6 + kvUrl,
  7 + videoUrl,
  8 + mLink,
  9 + pcLink
  10 +}
  1 +/**
  2 + * @file vue 全局过滤器
  3 + */
  4 +import Vue from 'vue'
  5 +
  6 +/**
  7 + * 时间格式化
  8 + * @param {Number|String} time - 时间戳或字符串
  9 + * @param {String} format - 时间格式:'YYYY-MM-DD hh:mm:ss'(默认值)
  10 + * @param {Boolean} simplify - 是否简化时间格式
  11 + */
  12 +Vue.filter('adFormatTime', function (time, format = 'YYYY-MM-DD hh:mm:ss', simplify) {
  13 + if (typeof time == 'string' && time.indexOf('T') === -1) { //排除格林威治时间
  14 + time = time.replace(/-/g, '/')
  15 + }
  16 + if (String(time).length < 11) {
  17 + time += '000';
  18 + }
  19 + let date = new Date(Number(time));
  20 +
  21 + // #region 简化时间格式,最多 7 天
  22 + if (simplify) {
  23 + let result = ''
  24 + let difference = Date.now() - date.getTime()
  25 + if (difference < 60000) {
  26 + result = '刚刚'
  27 + } else if (difference < 3600000) {
  28 + result = parseInt(difference / 60000) + ' 分钟前'
  29 + } else if (difference < 86400000) {
  30 + result = parseInt(difference / 3600000) + ' 小时前'
  31 + } else if (difference < 604800000) {
  32 + result = parseInt(difference / 86400000) + ' 天前'
  33 + }
  34 + if (result) {
  35 + return result
  36 + }
  37 + }
  38 + // #endregion
  39 +
  40 + const patterns = {
  41 + 'M+': date.getMonth() + 1,
  42 + 'D+': date.getDate(),
  43 + 'h+': date.getHours(),
  44 + 'm+': date.getMinutes(),
  45 + 's+': date.getSeconds()
  46 + }
  47 + if (/Y+/.test(format)) {
  48 + format = format.replace(RegExp.lastMatch, (date.getFullYear() + '').slice(4 - RegExp.lastMatch.length))
  49 + }
  50 + for (let p in patterns) {
  51 + if (new RegExp('(' + p + ')').test(format)) {
  52 + format = format.replace(RegExp.lastMatch, RegExp.lastMatch.length == 1 ? patterns[p] : String(patterns[p]).padStart(2, '0'))
  53 + }
  54 + }
  55 + return format
  56 +})
  57 +
  58 +/**
  59 + * 数字格式化
  60 + * @param {Number} num - 待格式化的数字
  61 + */
  62 +Vue.filter('adFormatNumber', function (num) {
  63 + if (typeof num == 'undefined') {
  64 + return ''
  65 + }
  66 + let result = num.toString()
  67 + if (num > 100000000) {
  68 + result = (num / 100000000).toFixed(1) + '亿'
  69 + } else if (num > 10000) {
  70 + result = (num / 10000).toFixed(1) + '万'
  71 + }
  72 + return result
  73 +})
  1 +/**
  2 + * @file 项目入口文件
  3 + */
  4 +import Vue from 'vue'
  5 +import VueRouter from 'vue-router'
  6 +import Vuex from 'vuex'
  7 +import routes from './routes'
  8 +import store from './store'
  9 +import App from 'modules/app/index.vue'
  10 +import './landscape.js'
  11 +import './ipadLandscape.js'
  12 +import './common'
  13 +import './filters'
  14 +import 'styles/common.css'
  15 +import 'styles/commonStyle.css'
  16 +
  17 +Vue.use(VueRouter)
  18 +Vue.use(Vuex)
  19 +import 'vant/es/toast/style';
  20 +import { Toast, Popup } from "vant";
  21 +Vue.use(Toast);
  22 +Vue.use(Popup);
  23 +
  24 +// 配置发送请求拦截器,实现路由切换后取消之前的请求
  25 +let axiosPromiseArr = [];
  26 +import axios from 'axios'
  27 +axios.interceptors.request.use(config => {
  28 + config.cancelToken = new axios.CancelToken(cancel => {
  29 + axiosPromiseArr.push({ cancel });
  30 + })
  31 + return config;
  32 +}, err => {
  33 + var error = { message: '网络异常,请刷新重试', err: err, type: 'requestError' };
  34 + console.log(error);
  35 + return Promise.reject(error);
  36 +})
  37 +
  38 +var Router = new VueRouter({ routes });
  39 +
  40 +Router.beforeEach((to, from, next) => {
  41 + axiosPromiseArr.forEach((ele, index) => {
  42 + ele.cancel();
  43 + delete axiosPromiseArr[index];
  44 + })
  45 + next()
  46 +})
  47 +
  48 +new Vue({
  49 + el: '#app',
  50 + render: h => h(App),
  51 + router: Router,
  52 + store: new Vuex.Store(store),
  53 +})
  54 +
  1 +var supportsOrientationChange = "onorientationchange" in window,
  2 + orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";
  3 +// 监听事件
  4 +window.addEventListener(orientationEvent, function () {
  5 + var ua = navigator.userAgent;
  6 + var deviceType = "";
  7 + //判断设备类型
  8 + if (ua.indexOf("iPad") > 0) {
  9 + deviceType = "isIpad";
  10 + } else if (ua.indexOf("Android") > 0) {
  11 + deviceType = "isAndroid";
  12 + } else {
  13 + // console.log("既不是ipad,也不是安卓!");
  14 + return;
  15 + }
  16 + let ipadId = document.getElementById('orientLayer')
  17 + // 判断横竖屏
  18 + if ("isIpad" == deviceType) {
  19 + if (Math.abs(window.orientation) == 90) {
  20 + ipadId.style.display = 'block'
  21 + // console.log("我是ipad的横屏",ipadId.style.display = 'block');
  22 + } else {
  23 + // console.log("我是ipad的竖屏");
  24 + ipadId.style.display = 'none'
  25 + }
  26 + }
  27 +}, false);
  1 +/* 横竖提示处理
  2 + * isVertical:不传默认为false,即显示竖屏提示,(false: 提示用户横屏, true:提示用户竖屏)
  3 + */
  4 +(function landscape(config) {
  5 + var isVertical =true;
  6 + var showWay = isVertical ? "@media screen and (min-aspect-ratio: 12/7){#orientLayer{display:block;} }" :
  7 + "@media all and (orientation : portrait){#orientLayer{display: block;} }";
  8 + var color = config && config.color ? config.color : "#000",
  9 + txt = isVertical ? "Screen Auto-Rotate" : " ",
  10 + images = config && config.images ? config.images :
  11 + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIYAAADaCAMAAABU68ovAAAAXVBMVEUAAAD29vb////x8fH////////x8fH5+fn29vby8vL////5+fn39/f6+vr////x8fH////////+/v7////09PT////x8fH39/f////////////////////x8fH///+WLTLGAAAAHXRSTlMAIpML+gb4ZhHWn1c2gvHBvq1uKJcC6k8b187lQ9yhhboAAAQYSURBVHja7d3blpowFIDhTUIAOchZDkre/zE7ycySrbUUpsRN2/1fzO18KzEqxEVgTiZNfgmmtxRc8iaR8HNe8x4BtjQePKayYCIoyBSgvNNE1AkNSHqZyLqk97EgUCCHBzZ5mkg7ScvIJuIyOyXBRFxgpqWZyGsAZLB1KjsJi8nutHU4JCRbFRH8tmirI9k8Jx2sqNs8K/m0LQkrktO2crgcgXGB4AiTEsB0hJfo9MGgX7CGcYiYwQxmMOOvZwRhBG8tCoMXjBDeXvWCEcHbi14wgCBmMIMZzGAGM5jxETNwzMAxA8cMHDNwzMAxA8cMHDNwzMAxA8cMHDNwzMAxY6E2rUQxnH2tz9cirlJFwFBJedaPnUv0M7++egPDE8iAJcIDmxwH5wwv9vUviw2kLbVO3TJU5uul/EyB0FoLp4x60PdGUd3qPurrWyjGGTc05u+1dcgI7/+tCCPARWGhH7o5Y7RCf+bH9ctXLp6v2BVDxfqz0oPXeSVaNtINo/1SXDv4dck8IIkbhtC2ol+iouEonTBCbYvVMnXOjxww6s/RFrBUpXHh/gw1rHj5d/qhYn9Gpk2FWh6xRBRX5Oj3Znh2Sq49/L6+y8pB26q9GbE2dbA2mVbx6I+7MfBglLCttm73ZQi7AD3iL4HqjFYJHSPRppqaUaJ3ATpGa+ckpGak2hRRMyqjGMkvl+xyFeSMwjAqcsZgGDdyhl0oNTnDN4yenJGZFGxNChP5/Y3efh6SM2rDOJMzboYxkDMqwyjIGcIw6F+io2FU1IxIm1JqRmgXSkvNKNCXeTpGrU0JNSO2c6LIGPgCS8AuDHz9ta0SXWDtxoDRH+MqlbC2Dt2G2JFRadtQZt2qq/orGowdGb2euxYiqWEpVWhTBnszoNAPdStuQwxqf0aocdWKW4Z+DfszIh8pxJqbuCE4YAC+4bm0evtipjpgJHeFnyyt1Ku2xa0bhjxr27p75rECNwyI9ZwvXkHq+7aTaMEV44YYy/spfgjgjNHaWW+GeUhGEX7tLlVinIFDDSgnOwhi1V6bU0b6tVS9eAERe863g4dRrtiHdc6o+nn5vtyVVgR79Cqt4uL6gfHPQyGqtP2vf7HADGbcYwaOGThm4JiBYwaOGThm4JiBYwaOGThm4JiBYwaOGThm4JiBYwaOGThm4JjhtOM+J/AgT008yDMkN/dPP9hzS8zAMQN3OEYeekp5YU7KOKXwVXqiY+QS7smcinGKABWdiBgpPJTSMHJ4KidhhPBUSMLw4CmPhKHgKUXCkHsygum71ftNSgCX6bsl8FQyfbcL5EdYsDk0R3j7aiA5wpt5AjKg/2gLJEBD/0Hf2OOf/vRrj6z/7GtP4B3nMKyjHA12kIPSjnJs3FEO0TvKkYJHOWCR+rjJH0Vn6fI5PjNbAAAAAElFTkSuQmCC";
  12 + // style
  13 + var nodeStyle = document.createElement('style');
  14 + nodeStyle.setAttribute('type', 'text/css');
  15 + nodeStyle.innerHTML =
  16 + '@-webkit-keyframes rotation{10%{transform: rotate(90deg); -webkit-transform: rotate(90deg)} 50%, 60%{transform: rotate(0deg); -webkit-transform: rotate(0deg)} 90%{transform: rotate(90deg); -webkit-transform: rotate(90deg)} 100%{transform: rotate(90deg); -webkit-transform: rotate(90deg)} } @keyframes rotation{10%{transform: rotate(90deg); -webkit-transform: rotate(90deg)} 50%, 60%{transform: rotate(0deg); -webkit-transform: rotate(0deg)} 90%{transform: rotate(90deg); -webkit-transform: rotate(90deg)} 100%{transform: rotate(90deg); -webkit-transform: rotate(90deg)} } #orientLayer{display: none; z-index: 999999;} ' +
  17 + showWay +
  18 + ' .mod-orient-layer{display: none; position: fixed; height: 100%; width: 100%; left: 0; top: 0; right: 0; bottom: 0; background: ' +
  19 + color +
  20 + '; z-index: 9997} .mod-orient-layer__content{position: absolute; width: 100%; top: 45%; margin-top: -75px; text-align: center} .mod-orient-layer__icon-orient{background-image: url(' +
  21 + images +
  22 + '); display: inline-block; width: 67px; height: 109px; transform: rotate(90deg); -webkit-transform: rotate(90deg); -webkit-animation: rotation infinite 1.5s ease-in-out; animation: rotation infinite 1.5s ease-in-out; -webkit-background-size: 67px; background-size: 67px} .mod-orient-layer__desc{margin-top: 20px; font-size: 15px; color: #fff}'
  23 + document.getElementsByTagName('body')[0].appendChild(nodeStyle);
  24 + // dom
  25 + var nodeDom = document.createElement('div');
  26 + nodeDom.setAttribute('id', 'orientLayer');
  27 + nodeDom.setAttribute('class', 'mod-orient-layer');
  28 + nodeDom.innerHTML =
  29 + '<div class="mod-orient-layer__content"> <i class="icon mod-orient-layer__icon-orient"></i> <div class="mod-orient-layer__desc">' +
  30 + txt + '</div> </div>';
  31 + document.getElementsByTagName('body')[0].appendChild(nodeDom);
  32 +}())
  1 +import axios from '../axios'
  2 +import { ENV } from 'scripts/constants/index'
  3 +// import { Message } from 'element-ui';
  4 +
  5 +export default {
  6 + // 新增预约
  7 + appointment(data){
  8 + let params = {
  9 + ...data
  10 + }
  11 + return axios
  12 + .post(`/gear/reserve/v2/nocode-add`, { ...params })
  13 + .then((res) => {
  14 + return res.data
  15 + })
  16 + .catch((err) => {
  17 + // Message.error(err, 2)
  18 + })
  19 + }
  20 +}
  1 +/**
  2 + * @file Axios 全局配置
  3 + */
  4 +import axios from 'axios'
  5 +import { ENV } from '../constants/index'
  6 +
  7 +
  8 +const myAxios = axios.create({
  9 + baseURL: ENV.HOSTNAME,
  10 + // withCredentials: true
  11 +})
  12 +
  13 +myAxios.defaults.timeout = 10000;
  14 +myAxios.interceptors.response.use((res) => {
  15 + if (res.status >= 200 && res.status < 300) {
  16 + return res;
  17 + }
  18 + return Promise.reject(res);
  19 +}, (error) => {
  20 + // 网络异常
  21 + if (axios.isCancel(error)) {
  22 + var err = { message: '路由切换,网络请求已取消', err: error, type: 'cancel' };
  23 + console.log(err);
  24 + return Promise.reject(err);
  25 + } else {
  26 + var err = { message: '网络异常,请刷新重试', err: error, type: 'responseError' };
  27 + console.log(err);
  28 + return Promise.reject(err);
  29 + }
  30 +});
  31 +
  32 +export default myAxios
  1 +/**
  2 + * @file 请求接口
  3 + */
  4 +import reqPublic from './api/public'
  5 +
  6 +export {
  7 + reqPublic,
  8 +}
  1 +/**
  2 + * @file 路由信息
  3 + */
  4 +
  5 +export default [{
  6 + path: '/',
  7 + redirect: '/index',
  8 + component: () => import(/* webpackChunkName: 'entry' */ '../modules/app/index.vue')
  9 +}, {
  10 + path: '/index',
  11 + component: () => import(/* webpackChunkName: 'index' */ '../modules/layout/index.vue'),
  12 + children: [
  13 + {
  14 + path: '/index',
  15 + component: () => import(/* webpackChunkName: 'index' */ '../modules/index/index.vue'),
  16 + meta: {
  17 + name: '首页'
  18 + }
  19 + }
  20 + ]
  21 +}, {
  22 + path: '*',
  23 + name: '404',
  24 + component: () => import(/* webpackChunkName: '404' */ '../modules/errorPages/my404.vue'),
  25 + meta: {
  26 + name: '404'
  27 + }
  28 +}]
  1 +/**
  2 + * @file 状态管理
  3 + */
  4 +// import { reqPublic } from "scripts/requests/index.js";
  5 +export default {
  6 + state: {
  7 + },
  8 + mutations: {
  9 + },
  10 + actions: {
  11 + },
  12 + getters: {
  13 + }
  14 +}
  1 +/**
  2 + * 发送自定义上报时间
  3 + * @param {*} eventName 事件名称
  4 + * @param {*} eventParams 自定义参数
  5 + */
  6 +let send = function (eventName, eventParams = {}) {
  7 + gtag('event', eventName, {
  8 + ...eventParams
  9 + })
  10 +}
  11 +const Tracker = {
  12 + /**
  13 + * 点击预约按钮
  14 + */
  15 + start_index: function () {
  16 + send('start_appointment_index')
  17 + },
  18 +}
  19 +
  20 +
  21 +export default Tracker
  1 +/**
  2 + * @file 工具函数
  3 + * 常用方法,公共方法
  4 + */
  5 +
  6 +/**
  7 + * @name GetLabelFormValue 对象数组中根据一个字段获取对象
  8 + * @param {Array[Object]} array - 对象数组
  9 + * @param {String} key - 字段名
  10 + * @param {any} value - 该字段的预设值
  11 + * @param {String} label - 可选,无匹配对象的空值字段
  12 + */
  13 + const GetObjFormKey = function (array, key = 'value', value = '', label) {
  14 + if (!array) return {}
  15 +
  16 + for (var item of array) {
  17 + if (String(item[key]) === String(value)) {
  18 + return item
  19 + }
  20 + }
  21 + if (label) {
  22 + var result = {}
  23 + result[label] = ''
  24 + return result
  25 + } else {
  26 + return {}
  27 + }
  28 +}
  29 +
  30 +/**
  31 + * 模拟a标签跳转
  32 + * @param url
  33 + * @param target
  34 + * @return {*}
  35 + */
  36 + const ALink = function(url, target = '_blank') {
  37 + const a = document.createElement('a');
  38 + a.href = url;
  39 + a.target = target;
  40 + document.body.appendChild(a);
  41 + a.click();
  42 + document.body.removeChild(a);
  43 +}
  44 +/**
  45 + * 获取url参数
  46 + * @param {*} name 参数名
  47 + * @param {*} url
  48 + * @returns
  49 + */
  50 + const getParameterByName = function (name, url) {
  51 + if (!url) url = window.location.href;
  52 + name = name.replace(/[[]]/g, '$&');
  53 + var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
  54 + results = regex.exec(url);
  55 + if (!results) return null;
  56 + if (!results[2]) return '';
  57 + return decodeURIComponent(results[2].replace(/\\+/g, ' '));
  58 +}
  59 +
  60 +function getUrlSearchJson() {
  61 + var url = location.search;
  62 + if(!url) {
  63 + return null;
  64 + }
  65 + var newObj = new Object();
  66 + if (url.indexOf("?") != -1) {
  67 + var strs = url.split('?')[1].split("&");
  68 + for (var i = 0; i < strs.length; i++) {
  69 + newObj[strs[i].split("=")[0]] = (strs[i].split("=")[1]) || '';
  70 + }
  71 + }
  72 + return newObj;
  73 +}
  74 +
  75 +export { GetObjFormKey, ALink, getParameterByName, getUrlSearchJson }
  1 +/**
  2 + * @file 公共样式
  3 + */
  4 +html,body{
  5 +/* we don't want to allow users to select text everywhere,
  6 + you can enable it on the places you think appropriate */
  7 + user-select: none;
  8 + -webkit-overflow-scrolling: touch;
  9 + font-family: -apple-system, "Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB", "Source Han Sans", "Microsoft YaHei", sans-serif;
  10 + height: 100%;
  11 + scroll-behavior: smooth;
  12 +}
  13 +*, *:before, *:after {
  14 + /* suppressing the tap highlight */
  15 + -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  16 + box-sizing: border-box;
  17 + vertical-align: top;
  18 + padding: 0;
  19 + margin: 0;
  20 + -webkit-font-smoothing: antialiased;
  21 +}
  22 +
  23 +*:focus {
  24 + /* the default outline doesn't play well with a mobile application,
  25 + I usually start without it,
  26 + but don't forget to research further to make your mobile app accessible. */
  27 + outline: 0;
  28 +}
  29 +
  30 +a {
  31 + background: transparent;
  32 + text-decoration: none;
  33 + outline: none;
  34 + transition: all .1s linear;
  35 +}
  36 +
  37 +a:active {
  38 + filter: brightness(1.1);
  39 +}
  40 +
  41 +.clickBtn:active {
  42 + filter: brightness(1.1);
  43 + transform: scale(0.98);
  44 +}
  45 +
  46 +
  47 +*[contenteditable] {
  48 + user-select: auto !important;
  49 + -webkit-user-select: auto !important;
  50 +}
  51 +/**
  52 + * 有强迫症的同学总会觉得输入框文本位置整体偏上,感觉未居中心里就痒痒的。桌面端浏览器里声明line-height等于height就能解决,但移动端浏览器里还是未能解决,需将line-height声明为normal才行。
  53 + */
  54 +input {
  55 + line-height: normal;
  56 +}
  57 +
  58 +::-webkit-scrollbar {
  59 + width: 8px;
  60 + height: 8px;
  61 + background-color: transparent;
  62 +}
  63 +
  64 +::-webkit-scrollbar-track {
  65 + background-color: transparent;
  66 +}
  67 +
  68 +::-webkit-scrollbar-thumb {
  69 + border-radius: 3px;
  70 + background-color: #5d5d5d;
  71 +}
  72 +
  73 +.van-toast {
  74 + min-width: 1.6rem!important;
  75 + border-radius: 0.08rem!important;
  76 + font-size: 0.38rem!important;
  77 + padding: 0.24rem 0.4rem!important;
  78 + line-height: 1.5!important;
  79 +}
  80 +
  81 +.van-popup {
  82 + background-color: transparent!important;
  83 + width: 100%;
  84 + height: 100%;
  85 +}
  86 +
  87 +.van-overlay{
  88 + background-color: rgba(0,0,0,.4)!important;
  89 +}
  90 +
  91 +.van-overflow-hidden{
  92 + overflow: auto!important;
  93 +}
  94 +
  95 +button {
  96 + border: none;
  97 +}
  98 +
  99 +
  100 +