作者 陶霁轩

init

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