wgt-node-utils 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -0
- package/dist/bundle.js +2 -1
- package/dist/bundle.js.LICENSE.txt +1 -0
- package/package.json +7 -3
- package/src/index.js +461 -8
- package/webpack.config.js +10 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wgt-node-utils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "WGT工具类包",
|
|
5
5
|
"main": "dist/bundle.js",
|
|
6
6
|
"scripts": {
|
|
@@ -14,18 +14,22 @@
|
|
|
14
14
|
"author": "rookie",
|
|
15
15
|
"license": "ISC",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"axios": "^1.7.7"
|
|
18
|
-
"babel-loader": "^9.2.1"
|
|
17
|
+
"axios": "^1.7.7"
|
|
19
18
|
},
|
|
20
19
|
"devDependencies": {
|
|
21
20
|
"@babel/core": "^7.25.8",
|
|
22
21
|
"@babel/preset-env": "^7.25.8",
|
|
23
22
|
"@eslint/js": "^9.12.0",
|
|
23
|
+
"@larksuiteoapi/node-sdk": "^1.37.2",
|
|
24
24
|
"babel-cli": "^6.26.0",
|
|
25
|
+
"babel-loader": "^9.2.1",
|
|
25
26
|
"cross-env": "^7.0.3",
|
|
27
|
+
"crypto-browserify": "^3.12.0",
|
|
26
28
|
"eslint": "^9.12.0",
|
|
27
29
|
"eslint-plugin-react": "^7.37.1",
|
|
30
|
+
"fs": "0.0.1-security",
|
|
28
31
|
"globals": "^15.11.0",
|
|
32
|
+
"path": "^0.12.7",
|
|
29
33
|
"typescript-eslint": "^8.9.0",
|
|
30
34
|
"webpack": "^5.95.0",
|
|
31
35
|
"webpack-cli": "^5.1.4"
|
package/src/index.js
CHANGED
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
const axios = require('axios');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const lark = require('@larksuiteoapi/node-sdk');
|
|
2
5
|
class wgtNodeUtils {
|
|
3
|
-
constructor() {
|
|
6
|
+
constructor(appId, appSecret) {
|
|
4
7
|
// 存储domain 对象
|
|
5
8
|
this.domainMap = {};
|
|
6
9
|
// 存储文件内容对象
|
|
7
10
|
this.fileContents = {};
|
|
11
|
+
// 飞书发送工具
|
|
12
|
+
this.client = null;
|
|
13
|
+
// 存储游戏原始链接对象
|
|
14
|
+
this.gameResourcesMap = {};
|
|
15
|
+
// 是否發送错误信息开关
|
|
16
|
+
this.filesErrorSendStatus = false;
|
|
17
|
+
|
|
18
|
+
// 初始化Lark客户端
|
|
19
|
+
if (appId && appSecret) {
|
|
20
|
+
this.initClient(appId, appSecret);
|
|
21
|
+
} else {
|
|
22
|
+
console.error('Lark客户端初始化失败:未提供appId或appSecret');
|
|
23
|
+
}
|
|
8
24
|
}
|
|
9
25
|
|
|
10
26
|
// 获取系统信息
|
|
@@ -13,12 +29,6 @@ class wgtNodeUtils {
|
|
|
13
29
|
*
|
|
14
30
|
*/
|
|
15
31
|
getSystem = (userAgent) => {
|
|
16
|
-
// 调试时获取到的数据:
|
|
17
|
-
// 'user-agent': 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36'
|
|
18
|
-
// 'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1',
|
|
19
|
-
// 'user-agent': 'Mozilla/5.0 (iPad; CPU OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1',
|
|
20
|
-
// 'user-agent': 'Mozilla/5.0 (iPad; CPU OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1',
|
|
21
|
-
// 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36',
|
|
22
32
|
const ua = userAgent;
|
|
23
33
|
const isWindowsPhone = /(?:Windows Phone)/.test(ua);
|
|
24
34
|
const isSymbian = /(?:SymbianOS)/.test(ua) || isWindowsPhone;
|
|
@@ -34,7 +44,10 @@ class wgtNodeUtils {
|
|
|
34
44
|
};
|
|
35
45
|
}
|
|
36
46
|
|
|
37
|
-
|
|
47
|
+
/***
|
|
48
|
+
* @headers 设备header 信息
|
|
49
|
+
*
|
|
50
|
+
*/
|
|
38
51
|
getCloudFrontDevice = (headers) => {
|
|
39
52
|
// cloud front逻辑
|
|
40
53
|
const cfDesktop = headers['cloudfront-is-desktop-viewer'];
|
|
@@ -79,7 +92,447 @@ class wgtNodeUtils {
|
|
|
79
92
|
}
|
|
80
93
|
return device;
|
|
81
94
|
}
|
|
95
|
+
// 获取cloud front传回的设备信息
|
|
96
|
+
getCloudFrontSystem = (device) => {
|
|
97
|
+
const system = {
|
|
98
|
+
isAndroid: device === 'Android',
|
|
99
|
+
isPhone: device === 'IOS',
|
|
100
|
+
isTablet: device === 'Pad'
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// 其它设备均为空的情况下,默认当前设置为pc
|
|
104
|
+
if (!system.isAndroid && !system.isPhone && !system.isTablet) {
|
|
105
|
+
system.isPC = true;
|
|
106
|
+
}
|
|
107
|
+
return system;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/***
|
|
111
|
+
* 通用头信息添加
|
|
112
|
+
* @res node端 返回头
|
|
113
|
+
*
|
|
114
|
+
*/
|
|
115
|
+
addCommonHeadersInfo = res => {
|
|
116
|
+
// 增加头信息Content-Type, 在开启gzip时会用到
|
|
117
|
+
res.setHeader('Content-Type','text/html; charset=utf-8');
|
|
118
|
+
|
|
119
|
+
// 指定被允许iframe的域名
|
|
120
|
+
res.setHeader('Content-Security-Policy','frame-ancestors https://*.enjoy4fun.com https://*.beesads.com');
|
|
121
|
+
|
|
122
|
+
// 通知浏览器应该只通过 HTTPS 访问该站点,并且以后使用 HTTP 访问该站点的所有尝试都应自动重定向到 HTTPS
|
|
123
|
+
res.setHeader('Strict-Transport-Security','max-age=63072000; includeSubDomains; preload');
|
|
124
|
+
|
|
125
|
+
// 指定客户端一定要遵循在 Content-Type 首部中对 MIME 类型 的设定
|
|
126
|
+
res.setHeader('X-Content-Type-Options','nosniff');
|
|
127
|
+
|
|
128
|
+
// 针对版本 8 及以上的 Internet Explorer,指示浏览器不要直接在浏览器中打开下载
|
|
129
|
+
res.setHeader('X-Download-Options','noopen');
|
|
130
|
+
|
|
131
|
+
// 当前页的主题标记为观察对象
|
|
132
|
+
// Topics API 的目的是为调用者(包括运行脚本的页面上的第三方广告技术或广告提供商)提供页面访问者当前可能感兴趣的粗粒度广告主题。
|
|
133
|
+
// 这些主题将补充上下文来自当前页面的信号可以组合起来以帮助为访问者找到合适的广告。
|
|
134
|
+
res.setHeader('Observe-Browsing-Topics','?1');
|
|
135
|
+
}
|
|
136
|
+
/***
|
|
137
|
+
* 获取siteId 通过hostname
|
|
138
|
+
* @url node端 返回头
|
|
139
|
+
* @hostname 网站 hostname
|
|
140
|
+
* @defaultSiteId 网站模版默认使用ID
|
|
141
|
+
*/
|
|
142
|
+
async getSiteByHostname(url, hostname, defaultSiteId) {
|
|
143
|
+
return new Promise((resolve) => {
|
|
144
|
+
let siteId = this.domainMap[hostname];
|
|
145
|
+
// 内存中存在, 使用缓存的原因是siteId与domain不会变化,而zoneMap却因为会变而不能存储
|
|
146
|
+
if (siteId) {
|
|
147
|
+
return resolve(siteId);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
axios.get(url, { params: { domain: hostname } }).then((res) => {
|
|
151
|
+
let siteData = res.data.data;
|
|
152
|
+
// 如果未获取到数据,使用enjoy4fun.com做为默认数据
|
|
153
|
+
if (!siteData) {
|
|
154
|
+
siteId = defaultSiteId;
|
|
155
|
+
console.log(new Date(), `获取site失败: domain=${hostname}`);
|
|
156
|
+
} else {
|
|
157
|
+
siteId = siteData.siteId;
|
|
158
|
+
domainMap[hostname] = siteId;
|
|
159
|
+
console.log(new Date(), 'domainMap缓存更新', siteId, domainMap);
|
|
160
|
+
}
|
|
161
|
+
resolve(siteId);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
/***
|
|
166
|
+
* 获取 site相关配置
|
|
167
|
+
* @isMobile 是否为移动端
|
|
168
|
+
* @url 请求后端接口
|
|
169
|
+
* @hostname 网站 hostname
|
|
170
|
+
* @imgDomain 图片地址
|
|
171
|
+
* @creativeId widget creative Id
|
|
172
|
+
*/
|
|
173
|
+
// TODO 还未开发完成
|
|
174
|
+
async getSiteConfigByHostname(isMobile, url, hostname, imgDomain, creativeId, buildName) {
|
|
175
|
+
const params = {
|
|
176
|
+
domain: hostname,
|
|
177
|
+
creative_id: creativeId
|
|
178
|
+
}
|
|
179
|
+
return new Promise((resolve) => {
|
|
180
|
+
axios.get(url, { params }).then(res => {
|
|
181
|
+
let siteData = res.data.data;
|
|
182
|
+
// 如果未获取到数据,使用enjoy4fun.com做为默认数据
|
|
183
|
+
if (!siteData) {
|
|
184
|
+
siteData = {
|
|
185
|
+
siteId: "site_12",
|
|
186
|
+
zoneMap: {
|
|
187
|
+
'pad_bottom_300_250': "45330",
|
|
188
|
+
'pad_bottom_336_280': "45326",
|
|
189
|
+
'pc_bottom_728_90': "45320",
|
|
190
|
+
'pc_right_300_250': "45321",
|
|
191
|
+
'pc_right_300_600': "45322",
|
|
192
|
+
'pc_right_300_250_2': "45324",
|
|
193
|
+
'pc_left_160_600': "45323",
|
|
194
|
+
'mobile_300_250_top': "45327",
|
|
195
|
+
'mobile_300_250_mid': "45328",
|
|
196
|
+
'mobile_300_600_bottom': "45329",
|
|
197
|
+
'interstitial_pc': "45334",
|
|
198
|
+
'interstitial_mobile': "45335",
|
|
199
|
+
'pc_bottom_160_90': "45325",
|
|
200
|
+
'pc_pad_walkthrough_336_280': "45319",
|
|
201
|
+
'mobile_game': "45331",
|
|
202
|
+
'pc_game': "45333",
|
|
203
|
+
'pad_game': "45332",
|
|
204
|
+
'sidewall': "47185"
|
|
205
|
+
},
|
|
206
|
+
theme: {
|
|
207
|
+
icon: '',
|
|
208
|
+
logo: '',
|
|
209
|
+
title: '',
|
|
210
|
+
bgLeftImg: '',
|
|
211
|
+
bgRightImg: '',
|
|
212
|
+
bgBottomImg: '',
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// 通过设备清洗zoneKeyMap
|
|
218
|
+
const zoneKeyList = isMobile ? mobileZoneKeyList : pcZoneKeyList;
|
|
219
|
+
let zoneMapForDevice = {};
|
|
220
|
+
const zoneMap = siteData.zoneMap || {};
|
|
221
|
+
zoneKeyList.forEach(zoneKey => {
|
|
222
|
+
if (zoneMap[zoneKey]) {
|
|
223
|
+
zoneMapForDevice[zoneKey] = zoneMap[zoneKey];
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
siteData.zoneMap = zoneMapForDevice;
|
|
82
227
|
|
|
228
|
+
// 处理皮肤字段
|
|
229
|
+
const { icon, logo, title, bgLeftImg, bgRightImg, bgBottomImg, ...otherTheme } = siteData.theme || {};
|
|
230
|
+
siteData.theme = {
|
|
231
|
+
icon: icon ? `${imgDomain}/site_icon/${icon}` : `/${buildName}/favicon.ico`,
|
|
232
|
+
logo: logo ? `${imgDomain}/site_logo/${logo}` : `/${buildName}/assets/logo-small.svg`,
|
|
233
|
+
title: title || 'Enjoy4fun',
|
|
234
|
+
bgLeftImg: bgLeftImg ? `${imgDomain}/theme/${bgLeftImg}` : '/gamebridge-web/assets/bg-left-winter.png',
|
|
235
|
+
bgRightImg: bgRightImg ? `${imgDomain}/theme/${bgRightImg}` : '/gamebridge-web/assets/bg-right-winter.png',
|
|
236
|
+
bgBottomImg: bgBottomImg ? `${imgDomain}/theme/${bgBottomImg}` : '/gamebridge-web/assets/bg-bottom-winter.png',
|
|
237
|
+
...otherTheme
|
|
238
|
+
}
|
|
239
|
+
resolve(siteData);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/***
|
|
245
|
+
* node启动时将静态资源读取到内存中
|
|
246
|
+
* @buildName 打包名称
|
|
247
|
+
* @version 打包版本号
|
|
248
|
+
*
|
|
249
|
+
*/
|
|
250
|
+
readF2eFiles = (buildName, version) => {
|
|
251
|
+
console.log('静态资源:开始读取');
|
|
252
|
+
return new Promise((resolve, reject) => {
|
|
253
|
+
try {
|
|
254
|
+
// 指定目录路径
|
|
255
|
+
const directoryPath = path.join(__dirname, `../${buildName}/${version}`);
|
|
83
256
|
|
|
257
|
+
// 读取目录下的所有文件
|
|
258
|
+
const files = fs.readdirSync(directoryPath);
|
|
259
|
+
files.forEach(file => {
|
|
260
|
+
// 构建文件的完整路径
|
|
261
|
+
const filePath = path.join(directoryPath, file);
|
|
262
|
+
|
|
263
|
+
// 检查是否为文件
|
|
264
|
+
if (fs.statSync(filePath).isFile()) {
|
|
265
|
+
// 读取文件内容并存储到对象中
|
|
266
|
+
this.fileContents[file] = fs.readFileSync(filePath, 'utf8');
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
// 增加react依赖
|
|
270
|
+
this.fileContents['react.production.min.js'] = fs.readFileSync(path.join(__dirname, `../${buildName}/dist/react.production.min.js`),'utf8');
|
|
271
|
+
this.fileContents['react-dom.production.min.js'] = fs.readFileSync(path.join(__dirname, `../${buildName}/dist/react-dom.production.min.js`),'utf8');
|
|
272
|
+
this.fileContents['react-router-dom.min.js'] = fs.readFileSync(path.join(__dirname, `../${buildName}/dist/react-router-dom.min.js`),'utf8');
|
|
273
|
+
|
|
274
|
+
console.log('静态资源列表:');
|
|
275
|
+
const f2eFileLoadStatus = Object.keys(fileContents).every((item) => {
|
|
276
|
+
const file = this.fileContents[item];
|
|
277
|
+
console.log(item, ':', file ? file.length : 'null');
|
|
278
|
+
return file && file.length > 0;
|
|
279
|
+
});
|
|
280
|
+
if (f2eFileLoadStatus) {
|
|
281
|
+
resolve();
|
|
282
|
+
} else {
|
|
283
|
+
reject();
|
|
284
|
+
}
|
|
285
|
+
} catch (e) {
|
|
286
|
+
reject();
|
|
287
|
+
}
|
|
288
|
+
console.log('静态资源:读取结束');
|
|
289
|
+
});
|
|
290
|
+
};
|
|
291
|
+
/***
|
|
292
|
+
* node启动时将静态资源读取到内存中
|
|
293
|
+
* @appId 打包名称
|
|
294
|
+
* @appSecret 打包版本号
|
|
295
|
+
*
|
|
296
|
+
*/
|
|
297
|
+
initClient = (appId, appSecret) => {
|
|
298
|
+
if (!this.client) {
|
|
299
|
+
this.client = new lark.Client({
|
|
300
|
+
appId: appId,
|
|
301
|
+
appSecret: appSecret,
|
|
302
|
+
disableTokenCache: false
|
|
303
|
+
});
|
|
304
|
+
console.log('Lark客户端初始化成功');
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/***
|
|
308
|
+
* node启动时将静态资源读取到内存中
|
|
309
|
+
* @appId 打包名称
|
|
310
|
+
* @appSecret 打包版本号
|
|
311
|
+
* @message 发送信息值
|
|
312
|
+
* @receive_id client 所使用的receive_id
|
|
313
|
+
*/
|
|
314
|
+
sendFeiShu = (message, appId, appSecret, receive_id) => {
|
|
315
|
+
if (!this.client) {
|
|
316
|
+
if (!appId || !appSecret) {
|
|
317
|
+
console.error('Lark客户端未初始化,且未提供appId和appSecret,无法发送消息');
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
this.initClient(appId, appSecret);
|
|
321
|
+
}
|
|
322
|
+
// 发送消息
|
|
323
|
+
this.client.im.message.create({
|
|
324
|
+
params: {
|
|
325
|
+
receive_id_type: 'chat_id',
|
|
326
|
+
},
|
|
327
|
+
data: {
|
|
328
|
+
receive_id: 'oc_aba13955509035daa7a799f30b1b3341',
|
|
329
|
+
msg_type: 'text',
|
|
330
|
+
content: `{"text":"<b>前端容器node报错</b>\\ncomponents: ${components}\\nenv: ${process.env.ENV}\\nmesssage: ${message}"}`,
|
|
331
|
+
uuid: '',
|
|
332
|
+
},
|
|
333
|
+
}).then(res => {
|
|
334
|
+
console.log('消息发送成功:', res);
|
|
335
|
+
}).catch(err => {
|
|
336
|
+
console.error('消息发送失败:', err);
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
/***
|
|
340
|
+
* node 端发送日志
|
|
341
|
+
* @text 发送文本
|
|
342
|
+
* @err 发送信息类型
|
|
343
|
+
*/
|
|
344
|
+
appendLog = (title, err) => {
|
|
345
|
+
try {
|
|
346
|
+
if (!err) {
|
|
347
|
+
console.warn(`============${new Date().toLocaleString()}===========`);
|
|
348
|
+
console.warn(title);
|
|
349
|
+
}
|
|
350
|
+
else if (err.config) {
|
|
351
|
+
console.error(`============${new Date().toLocaleString()}===========`);
|
|
352
|
+
console.error(`${title} [${err.config.method}]: ${err.config.url}`);
|
|
353
|
+
console.error(`request: {params: ${JSON.stringify(err.config.params)}, data: ${JSON.stringify(err.config.data)}}`);
|
|
354
|
+
console.error(`response: ${JSON.stringify(err.response)}`);
|
|
355
|
+
this.sendFeiShu(`${title} [${err.config.method}]: ${err.config.url}`);
|
|
356
|
+
} else {
|
|
357
|
+
console.error(`============${new Date().toLocaleString()}===========`);
|
|
358
|
+
console.error(`${title} ${err}`);
|
|
359
|
+
this.sendFeiShu(`${title} ${err}`);
|
|
360
|
+
}
|
|
361
|
+
} catch (e) {
|
|
362
|
+
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
/**
|
|
366
|
+
* 验证是否为空对像
|
|
367
|
+
* @param v 对象
|
|
368
|
+
*/
|
|
369
|
+
isEmptyObj = (v) => {
|
|
370
|
+
return (
|
|
371
|
+
v === undefined ||
|
|
372
|
+
v === null ||
|
|
373
|
+
(typeof v === 'string' && v.trim() === '') ||
|
|
374
|
+
(Object.prototype.toString.apply(v) === '[object Object]' && JSON.stringify(v) === '{}') ||
|
|
375
|
+
(Array.isArray(v) && v.every(item => isEmpty(item)))
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* 用于渲染游戏卡列表,清理无用字段
|
|
380
|
+
* @param list 清理数组
|
|
381
|
+
*/
|
|
382
|
+
clearGameCardListData = (list) => {
|
|
383
|
+
// 游戏卡片使用到的字段
|
|
384
|
+
return list.map((item = {}) => {
|
|
385
|
+
return {
|
|
386
|
+
id: item.game_id,
|
|
387
|
+
icon: item.base_icon,
|
|
388
|
+
path: item.game_path,
|
|
389
|
+
name: item.game_name,
|
|
390
|
+
icon_video: item.icon_video,
|
|
391
|
+
new: item.new ? true : undefined // 将false转换为undefined, 用于节省ssr生成的文本长度
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* 用于渲染类型卡片列表,清理无用字段
|
|
397
|
+
* @param list 清理数组
|
|
398
|
+
*/
|
|
399
|
+
clearCategoryListData = list => {
|
|
400
|
+
return list.map((item = {}) => {
|
|
401
|
+
return {
|
|
402
|
+
id: item.id,
|
|
403
|
+
path: item.path,
|
|
404
|
+
icon: item.base_icon,
|
|
405
|
+
name: item.name
|
|
406
|
+
};
|
|
407
|
+
})
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* 用于渲染演练视频卡片的数据,清理无用字段
|
|
411
|
+
* @param list 清理数组
|
|
412
|
+
*/
|
|
413
|
+
clearWalkThroughVideoListData = list => {
|
|
414
|
+
return list.map((item = {}) => {
|
|
415
|
+
return {
|
|
416
|
+
game_name: item.game_name,
|
|
417
|
+
game_path: item.game_path,
|
|
418
|
+
thumbnail: item.thumbnail,
|
|
419
|
+
video_id: item.video_id,
|
|
420
|
+
duration: item.duration
|
|
421
|
+
};
|
|
422
|
+
})
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* 拉去语言信息
|
|
426
|
+
* @param url 请求语言信息链接
|
|
427
|
+
*/
|
|
428
|
+
getLanguageList = (url) => {
|
|
429
|
+
// 默认值
|
|
430
|
+
// 默认值
|
|
431
|
+
const defaultLanList = [{
|
|
432
|
+
code: 'en',
|
|
433
|
+
name: 'English',
|
|
434
|
+
icon: 'cfgv1bursfevmln3akj0.webp'
|
|
435
|
+
}]
|
|
436
|
+
return new Promise((resolve) => {
|
|
437
|
+
axios.get(url).then(res => {
|
|
438
|
+
let list = res.data.data || [];
|
|
439
|
+
// 清理无用字段
|
|
440
|
+
list = list.map(item => {
|
|
441
|
+
return {
|
|
442
|
+
code: item.lan,
|
|
443
|
+
name: item.lan_name,
|
|
444
|
+
icon: item.icon
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
resolve(list || defaultLanList);
|
|
448
|
+
}).catch(() => {
|
|
449
|
+
this.appendLog('语言读取', '语言接口调用失败');
|
|
450
|
+
// 调用失败时,返回en
|
|
451
|
+
resolve(defaultLanList);
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* 游戏详情页面, 游戏资源链接替换
|
|
457
|
+
* @link 原始游戏链接
|
|
458
|
+
* @hostName 当前域名
|
|
459
|
+
* @ENV 当前环境
|
|
460
|
+
*/
|
|
461
|
+
ReplaceGameResources = async (link, hostName, ENV) => {
|
|
462
|
+
|
|
463
|
+
let gameLink = '';
|
|
464
|
+
const GAME_DEFAULT_DOMAIN = 'https://game.enjoy4fun.com';
|
|
465
|
+
try {
|
|
466
|
+
let domainArr = hostName.split('.');
|
|
467
|
+
let domain = domainArr.slice(-2).join('.');
|
|
468
|
+
let gameDomain = this.gameResourcesMap[domain];
|
|
469
|
+
|
|
470
|
+
// 当前没有map 中没有存储新的 domain,创建新的map
|
|
471
|
+
if (!gameDomain) {
|
|
472
|
+
gameDomain = `https://game.${domain}`;
|
|
473
|
+
const isAvailable = await checkDomainAvailability(gameDomain);
|
|
474
|
+
if (isAvailable) {
|
|
475
|
+
console.log('gameDomain可用,使用新的域名')
|
|
476
|
+
this.gameResourcesMap[domain] = gameDomain;
|
|
477
|
+
} else {
|
|
478
|
+
console.log('gameDomain不可用,使用默认域名')
|
|
479
|
+
this.gameResourcesMap[domain] = GAME_DEFAULT_DOMAIN;
|
|
480
|
+
gameDomain = GAME_DEFAULT_DOMAIN;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// 当前游戏domain 为默认游戏域名
|
|
485
|
+
if (gameDomain === GAME_DEFAULT_DOMAIN) {
|
|
486
|
+
console.log(new Date(), 'gameResourcesMap:存在且等于默认游戏名使用默认link', this.gameResourcesMap,'link', link);
|
|
487
|
+
return link;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// 替换游戏链接
|
|
491
|
+
if (ENV.includes('prod') || ENV.includes('qa')) {
|
|
492
|
+
gameLink = link.replace(GAME_DEFAULT_DOMAIN, gameDomain);
|
|
493
|
+
}
|
|
494
|
+
console.log(new Date(), 'gameResourcesMap:存在使用替换新的域名', this.gameResourcesMap, 'gameDomain', gameDomain, 'gameLink', gameLink);
|
|
495
|
+
return gameLink;
|
|
496
|
+
} catch (error) {
|
|
497
|
+
gameLink = link;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return gameLink;
|
|
501
|
+
};
|
|
502
|
+
/**
|
|
503
|
+
* 获取前端静态资源
|
|
504
|
+
* @pageName 页面名称
|
|
505
|
+
* @isMobile 是否为移动端
|
|
506
|
+
*/
|
|
507
|
+
getModelF2eFiles = (pageName, isMobile) => {
|
|
508
|
+
let jsName = `${pageName}.entry.js`;
|
|
509
|
+
let cssName = `${pageName}.entry.css`;
|
|
510
|
+
// 带设备信息的静态资源
|
|
511
|
+
if (typeof isMobile === 'boolean') {
|
|
512
|
+
const device = isMobile ? 'mobile' : 'pc';
|
|
513
|
+
jsName = `${pageName}-${device}.entry.js`;
|
|
514
|
+
cssName = `${pageName}-${device}.entry.css`;
|
|
515
|
+
}
|
|
516
|
+
const f2eFiles = {
|
|
517
|
+
jsStr: fileContents[jsName],
|
|
518
|
+
cssStr: fileContents[cssName],
|
|
519
|
+
reactStr: fileContents['react.production.min.js'],
|
|
520
|
+
reactDomStr: fileContents['react-dom.production.min.js'],
|
|
521
|
+
reactRouterStr: fileContents['react-router-dom.min.js'],
|
|
522
|
+
};
|
|
523
|
+
// 每次启动服务后仅对第一次失败进行验证
|
|
524
|
+
if (!this.filesErrorSendStatus) {
|
|
525
|
+
const fileStatus = Object.keys(f2eFiles).every(item => {
|
|
526
|
+
let file = f2eFiles[item];
|
|
527
|
+
if (file && file.length > 0) {
|
|
528
|
+
return true;
|
|
529
|
+
}
|
|
530
|
+
this.appendLog(`${pageName}[${item}]`, '文件加载失败');
|
|
531
|
+
return false;
|
|
532
|
+
});
|
|
533
|
+
this.filesErrorSendStatus = !fileStatus;
|
|
534
|
+
}
|
|
535
|
+
return f2eFiles;
|
|
536
|
+
}
|
|
84
537
|
}
|
|
85
538
|
module.exports = new wgtNodeUtils();
|
package/webpack.config.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// webpack.config.js
|
|
2
2
|
const path = require('path');
|
|
3
|
-
|
|
3
|
+
const webpack = require('webpack');
|
|
4
4
|
module.exports = {
|
|
5
5
|
entry: './src/index.js', // 入口文件
|
|
6
6
|
output: {
|
|
7
7
|
path: path.resolve(__dirname, 'dist'),
|
|
8
8
|
filename: 'bundle.js', // 输出的文件名
|
|
9
|
-
library: '
|
|
9
|
+
library: 'wgtNodeUtils', // 暴露库名
|
|
10
10
|
libraryTarget: 'umd', // 使用 UMD 规范
|
|
11
11
|
globalObject: 'this'
|
|
12
12
|
},
|
|
@@ -21,5 +21,12 @@ module.exports = {
|
|
|
21
21
|
}
|
|
22
22
|
]
|
|
23
23
|
},
|
|
24
|
-
mode: 'production' // 生产模式,优化打包
|
|
24
|
+
mode: 'production', // 生产模式,优化打包
|
|
25
|
+
resolve: {
|
|
26
|
+
fallback: {
|
|
27
|
+
fs: false, // 告诉 Webpack 不需要处理 fs 模块
|
|
28
|
+
crypto: false,
|
|
29
|
+
querystring: false
|
|
30
|
+
},
|
|
31
|
+
},
|
|
25
32
|
};
|