作者 陶霁轩

init

  1 +> 1%
  2 +last 2 versions
  3 +not dead
  4 +not ie 11
  1 +#编译模式
  2 +VUE_APP_MODE = development
  3 +
  4 +#中台接口base /dev-web-gateway代理到http://dev-ms.ids111.com:10030/dev-web-gateway
  5 +VUE_APP_MID_REQUEST_BASE_URL = /dev-web-gateway
  6 +
  7 +#业务接口base
  8 +VUE_APP_BUSINESS_REQUEST_BASE_URL = http://kirincub.com:18092/
  9 +
  10 +#上报接口base /report代理到https://jdlog-test.uu.cc
  11 +VUE_APP_TRACKER_BASE_URL = /report
  1 +#编译模式
  2 +VUE_APP_MODE = production
  3 +
  4 +#中台接口base 服务器已将/web-gateway代理
  5 +VUE_APP_MID_REQUEST_BASE_URL = /web-gateway
  6 +
  7 +#业务接口base 服务器已将/精确匹配代理
  8 +VUE_APP_BUSINESS_REQUEST_BASE_URL = /
  9 +
  10 +#上报接口base 服务器已将/report代理到https://jdlog.uu.cc
  11 +VUE_APP_TRACKER_BASE_URL = /report
  1 +#编译模式
  2 +VUE_APP_MODE = testOnline
  3 +
  4 +#中台接口base 服务器已将/web-gateway代理
  5 +VUE_APP_MID_REQUEST_BASE_URL = /web-gateway
  6 +
  7 +#业务接口base 服务器已将/精确匹配代理
  8 +VUE_APP_BUSINESS_REQUEST_BASE_URL = /
  9 +
  10 +#上报接口base 服务器已将/report代理到https://jdlog-test.uu.cc
  11 +VUE_APP_TRACKER_BASE_URL = /report
  1 +module.exports = {
  2 + root: true,
  3 + env: {
  4 + node: true
  5 + },
  6 + 'extends': [
  7 + 'plugin:vue/vue3-essential',
  8 + 'eslint:recommended'
  9 + ],
  10 + parserOptions: {
  11 + parser: '@babel/eslint-parser'
  12 + },
  13 + rules: {
  14 + // 'no-console': process.env.VUE_APP_MODE === 'production' ? 'warn' : 'off',
  15 + 'no-debugger': process.env.VUE_APP_MODE === 'production' ? 'warn' : 'off'
  16 + }
  17 +}
  1 +.DS_Store
  2 +node_modules
  3 +
  4 +
  5 +# local env files
  6 +.env.local
  7 +.env.*.local
  8 +
  9 +# Log files
  10 +npm-debug.log*
  11 +yarn-debug.log*
  12 +yarn-error.log*
  13 +pnpm-debug.log*
  14 +
  15 +# Editor directories and files
  16 +.idea
  17 +.vscode
  18 +*.suo
  19 +*.ntvs*
  20 +*.njsproj
  21 +*.sln
  22 +*.sw?
  1 +{
  2 + "semi": false,
  3 + "singleQuote": true,
  4 + "trailingComma": "none",
  5 + "arrowParens": "avoid",
  6 + "bracketSpacing": true
  7 +}
  1 +# vue3
  2 +
  3 +## Project setup
  4 +
  5 +```
  6 +yarn install
  7 +```
  8 +
  9 +### Compiles and hot-reloads for development
  10 +
  11 +```
  12 +yarn serve
  13 +```
  14 +
  15 +### Compiles and minifies for test
  16 +
  17 +```
  18 +yarn build:test
  19 +```
  20 +
  21 +### Compiles and minifies for production
  22 +
  23 +```
  24 +yarn build
  25 +```
  26 +
  27 +### Lints and fixes files
  28 +
  29 +```
  30 +yarn lint
  31 +```
  32 +
  33 +### 适配相关
  34 +
  35 +开发使用 px 即可,自动转化为 rem
  36 +
  37 +#### public/index.html
  38 +
  39 +最大响应宽度设置
  40 +
  41 +#### vue.config.js
  42 +
  43 +转化尺寸配置
  44 +
  45 +### 配置相关
  46 +
  47 +#### .env 文件
  48 +
  49 +配置各个环境的公共配置,可自由添加
  50 +
  51 +#### scripts/requests
  52 +
  53 +axios 请求封装,包括公共方法,api,上报等
  54 +
  55 +#### scripts/utils
  56 +
  57 +工具函数
  1 +module.exports = {
  2 + presets: [
  3 + '@vue/cli-plugin-babel/preset'
  4 + ]
  5 +}
  1 +{
  2 + "compilerOptions": {
  3 + "target": "es5",
  4 + "module": "esnext",
  5 + "baseUrl": "./",
  6 + "moduleResolution": "node",
  7 + "paths": {
  8 + "@/*": [
  9 + "src/*"
  10 + ]
  11 + },
  12 + "lib": [
  13 + "esnext",
  14 + "dom",
  15 + "dom.iterable",
  16 + "scripthost"
  17 + ]
  18 + }
  19 +}
  1 +{
  2 + "name": "vue",
  3 + "version": "0.1.0",
  4 + "private": true,
  5 + "scripts": {
  6 + "serve": "vue-cli-service serve",
  7 + "build:test": "vue-cli-service build --mode testOnline",
  8 + "build": "vue-cli-service build",
  9 + "lint": "vue-cli-service lint"
  10 + },
  11 + "dependencies": {
  12 + "axios": "^1.4.0",
  13 + "core-js": "^3.8.3",
  14 + "dayjs": "^1.11.9",
  15 + "detect-mobile-device": "^0.0.9",
  16 + "lib-flexible": "^0.3.2",
  17 + "postcss-px2rem": "^0.3.0",
  18 + "qs": "^6.11.2",
  19 + "vant": "^4.5.0",
  20 + "vconsole": "^3.15.1",
  21 + "vue": "^3.2.13",
  22 + "vue-router": "^4.0.3",
  23 + "vuex": "^4.0.0"
  24 + },
  25 + "devDependencies": {
  26 + "@babel/core": "^7.12.16",
  27 + "@babel/eslint-parser": "^7.12.16",
  28 + "@vue/cli-plugin-babel": "~5.0.0",
  29 + "@vue/cli-plugin-eslint": "~5.0.0",
  30 + "@vue/cli-plugin-router": "~5.0.0",
  31 + "@vue/cli-plugin-vuex": "~5.0.0",
  32 + "@vue/cli-service": "~5.0.0",
  33 + "css-loader": "^6.8.1",
  34 + "eslint": "^7.32.0",
  35 + "eslint-plugin-vue": "^8.0.3",
  36 + "postcss-loader": "^7.3.3",
  37 + "sass": "^1.32.7",
  38 + "sass-loader": "^12.0.0",
  39 + "unplugin-vue-components": "^0.25.1"
  40 + }
  41 +}
  1 +<!DOCTYPE html>
  2 +<html lang="zh-cn">
  3 +
  4 +<head>
  5 + <meta charset="utf-8">
  6 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
  7 + <!-- <link rel="icon" href="<%= BASE_URL %>favicon.ico"> -->
  8 + <title>
  9 + <%= htmlWebpackPlugin.options.title %>
  10 + </title>
  11 + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover">
  12 +</head>
  13 +
  14 +<body>
  15 + <noscript>
  16 + <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
  17 + Please enable it to continue.</strong>
  18 + </noscript>
  19 + <div id="app"></div>
  20 + <!-- built files will be auto injected -->
  21 +</body>
  22 +<script>
  23 + ;
  24 + (function (win) {
  25 + var doc = win.document;
  26 + var docEl = doc.documentElement;
  27 + var tid;
  28 + function refreshRem () {
  29 + var width = docEl.getBoundingClientRect().width;
  30 + if (width > 540) { // 最大宽度
  31 + width = 540;
  32 + }
  33 + var rem = width / 10;
  34 + docEl.style.fontSize = rem + 'px';
  35 + }
  36 +
  37 + win.addEventListener('resize', function () {
  38 + clearTimeout(tid);
  39 + tid = setTimeout(refreshRem, 300);
  40 + }, false);
  41 + win.addEventListener('pageshow', function (e) {
  42 + if (e.persisted) {
  43 + clearTimeout(tid);
  44 + tid = setTimeout(refreshRem, 300);
  45 + }
  46 + }, false);
  47 +
  48 + refreshRem();
  49 +
  50 + })(window);
  51 +</script>
  52 +
  53 +</html>
  1 +<template>
  2 + <router-view/>
  3 +</template>
  4 +
  5 +<style lang="scss">
  6 +</style>
  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-popup {
  74 + background: transparent!important;
  75 + overflow-x: hidden;
  76 +}
  77 +.van-toast {
  78 + background: rgba(0,0,0,.7)!important;
  79 +}
  1 +<template>
  2 + <van-popup :show="visible">
  3 + <div class="wrap">
  4 + <a class="close" @click="closeModal('accountModalVisible')" />
  5 + <div class="account-info">
  6 + <div class="username">
  7 + {{ decodeURIComponent(accountInfo['roleName'] || '') }}
  8 + </div>
  9 + <div class="info-item title">等级</div>
  10 + <div class="info-item title">职业</div>
  11 + <div class="info-item title">区服</div>
  12 + <div class="info-item">LV{{ accountInfo['lv'] || 0 }}</div>
  13 + <div class="info-item">
  14 + {{ decodeURIComponent(accountInfo['roleJob'] || '') }}
  15 + </div>
  16 + <div class="info-item">{{ accountInfo['serverName'] }}</div>
  17 + </div>
  18 + <div class="source-info">
  19 + <div class="point-info">
  20 + <div class="title">我的夏日积分:</div>
  21 + <div class="info-item">{{ score || 0 }}</div>
  22 + </div>
  23 + <div class="card-info">
  24 + <div class="title">我的红包券:</div>
  25 + <div class="info-box">
  26 + <div v-for="item in bagList" :key="item.id" class="info-box-item">
  27 + <div class="info-item name">{{ item.bag }}</div>
  28 + <div class="num">{{ item.cardNum || 0 }}张</div>
  29 + </div>
  30 + </div>
  31 + </div>
  32 + </div>
  33 + </div>
  34 + </van-popup>
  35 +</template>
  36 +
  37 +<script>
  38 +export default {
  39 + name: 'AccountModal',
  40 + inject: ['closeModal'],
  41 + props: {
  42 + visible: Boolean,
  43 + score: {
  44 + type: Number,
  45 + required: true
  46 + },
  47 + bagList: {
  48 + type: Object,
  49 + required: true
  50 + },
  51 + accountInfo: {
  52 + type: Object,
  53 + required: true
  54 + }
  55 + },
  56 + data() {
  57 + return {}
  58 + },
  59 + methods: {}
  60 +}
  61 +</script>
  62 +
  63 +<style scoped lang="scss">
  64 +.wrap {
  65 + position: relative;
  66 + width: 599px;
  67 + height: 546px;
  68 + margin: 40px 0;
  69 + padding-top: 138px;
  70 + background: url('@/assets/image/accountModal-bg.png') no-repeat center/100%
  71 + 100%;
  72 +}
  73 +.close {
  74 + position: absolute;
  75 + top: -40px;
  76 + right: 0;
  77 + width: 37px;
  78 + height: 34px;
  79 + background: url('@/assets/image/close.png') no-repeat center/100% 100%;
  80 +}
  81 +.account-info {
  82 + display: flex;
  83 + flex-wrap: wrap;
  84 + width: 452px;
  85 + margin-left: 76px;
  86 + font-size: 28px;
  87 + color: #fff;
  88 + text-align: center;
  89 + .username {
  90 + width: 100%;
  91 + height: 54px;
  92 + line-height: 54px;
  93 + }
  94 + .info-item {
  95 + width: calc(452px / 3);
  96 + height: 42px;
  97 + line-height: 44px;
  98 + &.title {
  99 + color: rgba(255, 255, 255, 0.75);
  100 + }
  101 + }
  102 +}
  103 +.source-info {
  104 + line-height: 56px;
  105 + margin: 20px 0 0 76px;
  106 + font-size: 28px;
  107 + color: rgba(255, 255, 255, 0.75);
  108 + .title {
  109 + width: 200px;
  110 + color: #fff;
  111 + flex-shrink: 0;
  112 + text-align: justify;
  113 + }
  114 + .point-info {
  115 + display: flex;
  116 + }
  117 + .info-item {
  118 + width: 190px;
  119 + flex-shrink: 0;
  120 + }
  121 + .card-info {
  122 + display: flex;
  123 + }
  124 + .info-box-item {
  125 + display: flex;
  126 + }
  127 + .num {
  128 + white-space: nowrap;
  129 + }
  130 +}
  131 +</style>
  1 +<template>
  2 + <van-popup :show="visible">
  3 + <div class="wrap">
  4 + <a class="close" @click="closeModal('exchangeModalVisible')" />
  5 + <div class="content">
  6 + <span>兑换</span>
  7 + <div :class="['countIpt', exchangeData.multiple && 'countIptBg']">
  8 + <input v-if="exchangeData.multiple" type="number" v-model="count" />
  9 + <span v-else v-text="count"></span>
  10 + </div>
  11 + <span>个{{ exchangeData.name }}</span>
  12 + </div>
  13 + <div class="btn-box">
  14 + <a class="btn cancle" @click="closeModal('exchangeModalVisible')" />
  15 + <a class="btn confirm" @click="submit" />
  16 + </div>
  17 + </div>
  18 + </van-popup>
  19 +</template>
  20 +
  21 +<script>
  22 +import { watch, ref } from 'vue'
  23 +export default {
  24 + name: 'ExchangeModal',
  25 + inject: ['closeModal'],
  26 + props: {
  27 + visible: Boolean,
  28 + exchangeData: {
  29 + type: Object,
  30 + required: true
  31 + }
  32 + },
  33 + setup(props) {
  34 + const count = ref(1)
  35 +
  36 + watch(
  37 + () => props.visible,
  38 + newVal => {
  39 + if (newVal) {
  40 + count.value = 1
  41 + }
  42 + }
  43 + )
  44 +
  45 + return {
  46 + count
  47 + }
  48 + },
  49 + methods: {
  50 + submit() {
  51 + this.$emit('submit', {
  52 + ...this.exchangeData,
  53 + count: this.count
  54 + })
  55 + }
  56 + }
  57 +}
  58 +</script>
  59 +
  60 +<style scoped lang="scss">
  61 +.wrap {
  62 + position: relative;
  63 + width: 599px;
  64 + height: 415px;
  65 + margin: 40px 0;
  66 + padding-top: 172px;
  67 + background: url('@/assets/image/exchangeModal-bg.png') no-repeat center/100%
  68 + 100%;
  69 +}
  70 +.close {
  71 + position: absolute;
  72 + top: -40px;
  73 + right: 0;
  74 + width: 37px;
  75 + height: 34px;
  76 + background: url('@/assets/image/close.png') no-repeat center/100% 100%;
  77 +}
  78 +.content {
  79 + height: 60px;
  80 + line-height: 60px;
  81 + font-size: 28px;
  82 + color: rgba(255, 255, 255.75);
  83 + text-align: center;
  84 +}
  85 +.countIpt {
  86 + position: relative;
  87 + display: inline-block;
  88 + input {
  89 + position: relative;
  90 + width: 220px;
  91 + height: 60px;
  92 + margin: 0 6px;
  93 + background: rgba(0, 0, 0, 0.5);
  94 + border: none;
  95 + text-align: center;
  96 + z-index: 2;
  97 + }
  98 + &.countIptBg {
  99 + &::after {
  100 + display: block;
  101 + content: '';
  102 + position: absolute;
  103 + top: 4px;
  104 + left: 10px;
  105 + width: 220px;
  106 + height: 60px;
  107 + border: 1px solid #ff6d26;
  108 + }
  109 + }
  110 +}
  111 +.btn-box {
  112 + display: flex;
  113 + justify-content: space-between;
  114 + width: 506px;
  115 + margin: 60px 0 0 50px;
  116 +}
  117 +.btn {
  118 + display: block;
  119 + width: 238px;
  120 + height: 66px;
  121 + background: no-repeat center/100% 100%;
  122 + &.cancle {
  123 + background-image: url('@/assets/image/cancle.png');
  124 + }
  125 + &.confirm {
  126 + background-image: url('@/assets/image/confirm.png');
  127 + }
  128 +}
  129 +</style>
  1 +<template>
  2 + <van-popup :show="visible">
  3 + <div class="wrap">
  4 + <a class="close" @click="closeModal('ruleModalVisible')" />
  5 + <div class="rule-text">
  6 + 1、在限定活动期间,完成任务即可获得夏日红包抽奖券,抽奖有概率获得夏日积分、现金红包兑换券、实物大奖等奖励。<br />
  7 + 2、夏日积分兑换比例:10夏日积分=1蓝钻/1红钻/1源石,活动周期内,3000蓝钻、5000蓝钻、10000蓝钻分别限定每个角色仅可兑换一次。<br />
  8 + 3、使用夏日积分后,兑换的奖励将直接发送至您的邮箱,兑换过程可能存在5-15分钟的延迟,请您耐心等待。<br />
  9 + 4、现金红包仅支持提现至微信账户,单个账号每日红包使用数量上限为十个,单个账号每日提现额度上限为1000元人民币,请合理安排兑换时间,以免造成损失。<br />
  10 + 5、如您需要兑换实物奖品,请关注官方微信公众号“荣耀全明星手游”,并点击下方菜单栏点击“呼叫网管”,回复“人工客服”联系官方客服人员。<br />
  11 + 6、活动结束后,抽奖券、积分、红包兑换券及实物兑换券将无法使用,请合理安排使用时间,以免造成损失。<br />
  12 + 7、本活动为限时新服活动,非活动期内新服创建的角色将无法参与本活动。<br />
  13 + 8、本页面为《荣耀全明星》用户专属活动页,仅供用户本人进行活动参与,请勿对外分享,以免造成损失。
  14 + </div>
  15 + </div>
  16 + </van-popup>
  17 +</template>
  18 +
  19 +<script>
  20 +export default {
  21 + name: 'RuleModal',
  22 + inject: ['closeModal'],
  23 + props: {
  24 + visible: Boolean
  25 + },
  26 + data() {
  27 + return {}
  28 + },
  29 + methods: {}
  30 +}
  31 +</script>
  32 +
  33 +<style scoped lang="scss">
  34 +.wrap {
  35 + position: relative;
  36 + width: 599px;
  37 + height: 759px;
  38 + margin: 40px 0;
  39 + padding-top: 136px;
  40 + background: url('@/assets/image/ruleModal-bg.png') no-repeat center/100% 100%;
  41 +}
  42 +.close {
  43 + position: absolute;
  44 + top: -40px;
  45 + right: 0;
  46 + width: 37px;
  47 + height: 34px;
  48 + background: url('@/assets/image/close.png') no-repeat center/100% 100%;
  49 +}
  50 +.rule-text {
  51 + width: 580px;
  52 + height: 580px;
  53 + line-height: 36px;
  54 + padding: 0 62px;
  55 + margin: auto;
  56 + font-size: 28px;
  57 + color: #fff;
  58 + overflow-y: auto;
  59 +}
  60 +</style>
  1 +import { createApp } from 'vue'
  2 +import App from './App.vue'
  3 +import router from './router'
  4 +import store from './store'
  5 +import './assets/css/global.css'
  6 +// import 'lib-flexible'
  7 +import { Popup, showToast } from 'vant'
  8 +import 'vant/lib/index.css'
  9 +// import Vconsole from 'vconsole'
  10 +const app = createApp(App);
  11 +
  12 +app.use(store)
  13 + .use(router)
  14 + .use(Popup)
  15 +
  16 +// if (process.env.VUE_APP_MODE !== 'production') {
  17 +// let vConsole = new Vconsole()
  18 +// app.use(vConsole)
  19 +// }
  20 +
  21 +app.config.globalProperties.$toast = showToast
  22 +
  23 +app.mount('#app')
  1 +import { createRouter, createWebHashHistory } from 'vue-router'
  2 +// import { isWeiXin } from 'detect-mobile-device'
  3 +const routes = [
  4 + {
  5 + path: '/',
  6 + name: 'index',
  7 + component: () => import(/* webpackChunkName: "index" */ '../views/index/Index.vue')
  8 + },
  9 +]
  10 +
  11 +const router = createRouter({
  12 + history: createWebHashHistory(),
  13 + routes
  14 +})
  15 +
  16 +// router.beforeEach((to, from, next) => {
  17 +// // 本地开发绕过路由守卫
  18 +// if (process.env.VUE_APP_MODE === 'development') {
  19 +// next()
  20 +// }
  21 +// if (isWeiXin()) {
  22 +// to.name === 'index' ? next() : next('/');
  23 +// } else {
  24 +// to.name === 'guidePage' ? next() : next('/guidePage');
  25 +// }
  26 +// })
  27 +
  28 +export default router
  1 +import URLS from './urls'
  2 +
  3 +
  4 +export { URLS }
  1 +/**
  2 + * @file 常量 - 链接
  3 + */
  4 +export default {
  5 +
  6 +}
  1 +import axios from '../axios'
  2 +import qs from 'qs';
  3 +const midBase = process.env.VUE_APP_MID_REQUEST_BASE_URL
  4 +const businessBase = process.env.VUE_APP_BUSINESS_REQUEST_BASE_URL
  5 +export default {
  6 + // 登录
  7 + login (headers, params) {
  8 + return axios.get(`${midBase}/ms-signin/glory/web-api/login`, {
  9 + headers,
  10 + params
  11 + })
  12 + },
  13 + // 根据token获取用户绑定信息
  14 + getMe (token) {
  15 + return axios.get(`${midBase}/ms-signin/glory/web-api/getMe`, { headers: { token } })
  16 + },
  17 + // 红包提现
  18 + withdraw (data, gameId, token) {
  19 + return axios.post(`${midBase}/ms-signin/glory/web-api/${gameId}/withdraw`, { ...data }, { headers: { token } })
  20 + },
  21 + // 获取积分信息
  22 + cashbackGetScore (data) {
  23 + return axios.post(`${businessBase}cashbackGetScore`, qs.stringify(data), {
  24 + "Content-Type": "application/x-www-form-urlencoded"
  25 + })
  26 + },
  27 + // 兑换钻石
  28 + cashbackExchange (data) {
  29 + return axios.post(`${businessBase}cashbackExchange`, qs.stringify(data), {
  30 + "Content-Type": "application/x-www-form-urlencoded"
  31 + })
  32 + },
  33 +}
  1 +import axios from '../axios'
  2 +const baseUrl = process.env.VUE_APP_TRACKER_BASE_URL
  3 +export default {
  4 + report (data) {
  5 + return axios.post(`${baseUrl}`, [...data])
  6 + }
  7 +}
  1 +/**
  2 + * @file Axios 全局配置
  3 + */
  4 +import axios from 'axios'
  5 +
  6 +const myAxios = axios.create({
  7 + // baseURL: process.env.VUE_APP_MID_REQUEST_BASE_URL,
  8 + // withCredentials: true
  9 +})
  10 +
  11 +myAxios.defaults.timeout = 100000;
  12 +myAxios.interceptors.response.use((res) => {
  13 + if (res.status >= 200 && res.status < 300) {
  14 + return res;
  15 + }
  16 + return Promise.reject(res);
  17 +}, (error) => {
  18 + var err = { message: '网络异常,请刷新重试', err: error, type: 'responseError' };
  19 + return Promise.reject(err);
  20 +});
  21 +
  22 +export default myAxios
  1 +/**
  2 + * @file 请求接口
  3 + */
  4 +import reqPublic from './api/public'
  5 +import Tracker from './api/tracker'
  6 +
  7 +export {
  8 + reqPublic,
  9 + Tracker
  10 +}
  1 +/**
  2 + * @file 工具函数
  3 + * 常用方法,公共方法
  4 + */
  5 +/**
  6 + * 模拟a标签跳转
  7 + * @param url
  8 + * @param target
  9 + * @return {*}
  10 + */
  11 +const ALink = function (url, target = '_blank') {
  12 + const a = document.createElement('a');
  13 + a.href = url;
  14 + a.target = target;
  15 + document.body.appendChild(a);
  16 + a.click();
  17 + document.body.removeChild(a);
  18 +}
  19 +
  20 +/**
  21 + * 获取url指定参数
  22 + * @param {*} name 参数名
  23 + * @param {*} url
  24 + * @returns
  25 + */
  26 +const getParameterByName = function (name, url) {
  27 + if (!url) url = window.location.href;
  28 + name = name.replace(/[[]]/g, '$&');
  29 + var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
  30 + results = regex.exec(url);
  31 + if (!results) return null;
  32 + if (!results[2]) return '';
  33 + return decodeURIComponent(results[2].replace(/\\+/g, ' '));
  34 +}
  35 +
  36 +/**
  37 + * 获取url所有参数
  38 + * @returns
  39 + */
  40 +function getUrlSearchJson () {
  41 + var url = location.search;
  42 + if (!url) {
  43 + return null;
  44 + }
  45 + var newObj = new Object();
  46 + if (url.indexOf("?") != -1) {
  47 + var ops = url.split('?')[1].split("&");
  48 + for (var i = 0; i < ops.length; i++) {
  49 + newObj[ops[i].split("=")[0]] = (ops[i].split("=")[1]) || '';
  50 + }
  51 + }
  52 + return newObj;
  53 +}
  54 +
  55 +function getTimestamp (type = 's') {
  56 + let curDate = new Date().getTime()
  57 + if (type === 's') {
  58 + return Math.floor(curDate / 1000)
  59 + } else {
  60 + return curDate
  61 + }
  62 +}
  63 +
  64 +export { ALink, getParameterByName, getUrlSearchJson, getTimestamp }
  1 +import { createStore } from 'vuex'
  2 +
  3 +export default createStore({
  4 + state: {
  5 + },
  6 + getters: {
  7 + },
  8 + mutations: {
  9 + },
  10 + actions: {
  11 + },
  12 + modules: {
  13 + }
  14 +})
  1 +<template>
  2 + <div class="wrap">
  3 + <!-- KV模块 -->
  4 + <div class="module-kv">
  5 + <div class="top-btn-box">
  6 + <a class="top-btn rule-btn" @click="ruleModalOpen" />
  7 + </div>
  8 + <div class="date">兑换时间:2023年7月13日-9月9日</div>
  9 + </div>
  10 + <!-- 弹窗 -->
  11 + <RuleModal :visible="ruleModalVisible" />
  12 + </div>
  13 +</template>
  14 +
  15 +<script>
  16 +import { reactive } from 'vue'
  17 +import RuleModal from '@/components/RuleModal.vue'
  18 +import { reqPublic, Tracker } from '@/scripts/requests/index.js'
  19 +import { getUrlSearchJson } from '@/scripts/util.js'
  20 +import { isIOS, isMobile } from 'detect-mobile-device'
  21 +import dayjs from 'dayjs'
  22 +export default {
  23 + name: 'IndexPage',
  24 + components: {
  25 + RuleModal
  26 + },
  27 + setup() {
  28 + // 公共上报字段
  29 + const publicReportParams = reactive({
  30 + game_appkey: 'nwDNza2ltADBAcETlnPO',
  31 + game_id: '600025',
  32 + plat_id: !isMobile() ? '4' : isIOS() ? '0' : '1', //上报平台代表的ID,ios 0/android 1/h5 3/pc 4
  33 + client_time: dayjs().format('YYYY-MM-DD HH:mm:ss')
  34 + })
  35 + return {
  36 + publicReportParams
  37 + }
  38 + },
  39 + data() {
  40 + return {
  41 + ruleModalVisible: false //规则弹窗
  42 + }
  43 + },
  44 + computed: {
  45 + /**
  46 + * Url携带参数,游戏中跳转带出
  47 + */
  48 + urlSearch() {
  49 + return getUrlSearchJson()
  50 + }
  51 + },
  52 + provide() {
  53 + return {
  54 + closeModal: this.closeModal
  55 + }
  56 + },
  57 + created() {},
  58 + methods: {
  59 + /**
  60 + * 登录
  61 + * @param {Object} userOps 用户参数
  62 + */
  63 + login(userOps) {
  64 + const { timestamp, gameId, signature, openId, roleId, serverId } = userOps
  65 + reqPublic
  66 + .login({ gameId, timestamp, signature }, { openId, roleId, serverId })
  67 + .then(res => {
  68 + if (process.env.VUE_APP_MODE === 'development') {
  69 + //本地开发处理
  70 + window.location.href =
  71 + 'http://localhost:8080/?' + window.location.href.split('?')[1]
  72 + return
  73 + }
  74 + window.location.href = res.request.responseURL
  75 + })
  76 + .catch(err => {
  77 + console.log('fail', err)
  78 + })
  79 + },
  80 + /**
  81 + * 关闭弹窗
  82 + * @param {*} object 控制开关的变量名称
  83 + */
  84 + closeModal(object) {
  85 + this[object] = false
  86 + },
  87 + /**
  88 + * 打开规则弹窗
  89 + */
  90 + ruleModalOpen() {
  91 + this.ruleModalVisible = true
  92 + },
  93 + /**
  94 + * 页面加载上报(登录成功后)
  95 + */
  96 + onloadReport() {
  97 + let params = [
  98 + {
  99 + ...this.publicReportParams,
  100 + log_type: 'CustomEvent',
  101 + event_id: 'enter_h5'
  102 + }
  103 + ]
  104 + Tracker.report(params)
  105 + }
  106 + }
  107 +}
  108 +</script>
  109 +<style scoped lang="scss">
  110 +@import './index.scss';
  111 +</style>
  1 +.wrap {
  2 + width: 750px;
  3 + height: 3394px;
  4 + margin: auto;
  5 + background: url('@/assets/image/bg.jpg') no-repeat top center/100% auto;
  6 +}
  7 +.gray {
  8 + filter: grayscale(1);
  9 +}
  10 +
  11 +.module-kv {
  12 + height: 1010px;
  13 + padding-top: 70px;
  14 +
  15 + .top-btn-box {
  16 + display: flex;
  17 + justify-content: space-between;
  18 + padding: 0 20px;
  19 + }
  20 +
  21 + .top-btn {
  22 + display: block;
  23 + width: 152px;
  24 + height: 49px;
  25 + background: no-repeat center/100% 100%;
  26 + }
  27 +
  28 + .account-btn {
  29 + background-image: url('@/assets/image/account-btn.png');
  30 + }
  31 +
  32 + .rule-btn {
  33 + background-image: url('@/assets/image/rule-btn.png');
  34 + }
  35 +
  36 + .date {
  37 + margin-top: 820px;
  38 + font-size: 28px;
  39 + color: #fff;
  40 + text-align: center;
  41 + }
  42 +}
  1 +const { defineConfig } = require('@vue/cli-service')
  2 +const px2rem = require('postcss-px2rem')
  3 +
  4 +console.log('---------------构建环境:' + process.env.VUE_APP_MODE + '------------------')
  5 +
  6 +module.exports = defineConfig({
  7 + transpileDependencies: true,
  8 + productionSourceMap: false,
  9 +
  10 + chainWebpack: (config) => {
  11 + config.plugin('html').tap(args => {
  12 + args[0].title = '网页标题'; // 设置网页标题
  13 + args[0].meta = {
  14 + description: 'Your Description', // 设置网页描述
  15 + keywords: 'keyword1, keyword2, keyword3' // 设置关键词
  16 + };
  17 + return args;
  18 + });
  19 +
  20 + // px自动转化rem
  21 + config.module
  22 + .rule('scss')
  23 + .test(/\.scss$/)
  24 + .oneOf('vue')
  25 + .resourceQuery(/\?vue/)
  26 + .use('postcss-loader')
  27 + .loader('postcss-loader')
  28 + .tap((args) => {
  29 + args.postcssOptions = {
  30 + plugins: [
  31 + px2rem({
  32 + // 设计稿尺寸 / 10
  33 + remUnit: 75
  34 + })
  35 + ]
  36 + };
  37 + return args;
  38 + })
  39 + },
  40 +
  41 + devServer: {
  42 + open: true,
  43 + // host: 'localhost',
  44 + port: 8080,
  45 + proxy: {
  46 + "/report": {
  47 + target: 'https://jdlog-test.uu.cc',
  48 + changeOrigin: true,
  49 + pathRewrite: {
  50 + '^/report': ''
  51 + }
  52 + },
  53 + "/dev-web-gateway": {
  54 + target: 'http://dev-ms.ids111.com:10030/',
  55 + changeOrigin: true
  56 + }
  57 + }
  58 + }
  59 +})
此 diff 太大无法显示。