Commit 9d9d0c72 authored by haiyoucuv's avatar haiyoucuv

new 模板

parent 7e904621
UPLOAD_DIR=TNGD_GAMES/B_Client UPLOAD_DIR=db_games/spark/v3
\ No newline at end of file \ No newline at end of file
# .env.production # .env.production
CDN_DOMAIN=//gamification-sbx.tngdigital.com.my CDN_DOMAIN=//yun.duiba.com.cn
OSS_REGION=oss-ap-southeast-3 OSS_REGION=oss-cn-hangzhou
OSS_BUCKET=sbx-gamification-tngd OSS_BUCKET=duiba
OSS_ACCESS_KEY_ID=LTAI5tApBGwYWaj6zLmKUaTJ OSS_ACCESS_KEY_ID=LTAI5tPUSSxgkEmKPAfVXUQQ
OSS_ACCESS_SECRET=W3OvCDpbE3ywMaQnTNWzySnhPRK1We OSS_ACCESS_SECRET=6sk3EDd1BYrXlAUoh8maMuN7hOMkh1
\ No newline at end of file \ No newline at end of file
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="dns-prefetch" href="//yun.duiba.com.cn" />
<link rel="preconnect" href="//embedlog.duiba.com.cn">
<title>活动标题</title>
<script type="text/javascript">
if (localStorage && localStorage.isWebp) {
document
.getElementsByTagName('html')[0]
.setAttribute('duiba-webp', 'true');
}
</script>
<script src="//yun.duiba.com.cn/js-libs/rem/1.1.3/rem.min.js"></script>
<script>
var CFG = CFG || {};
CFG.projectId = location.pathname.split('/')[2] || '1';
function getUrlParam(name) {
var search = window.location.search;
var matched = search
.slice(1)
.match(new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i'));
return search.length ? matched && matched[2] : null;
}
CFG.appID = '${APPID}';
if (!getUrlParam("appID")) {
// alert("【警告】检测到活动url中没有appID参数\n缺少该参数会导致埋点、分享、app信息获取错误。")
}
</script>
<script type="module" crossorigin src="//yun.duiba.com.cn/db_games/spark/v3/1729238505291/assets/index-6Aqtw07R.js"></script>
<link rel="stylesheet" crossorigin href="//yun.duiba.com.cn/db_games/spark/v3/1729238505291/assets/index-B2EZ7m-P.css">
<script type="module">import.meta.url;import("_").catch(()=>1);(async function*(){})().next();if(location.protocol!="file:"){window.__vite_is_modern_browser=true}</script>
<script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
</head>
<body>
<div id="root"></div>
<script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
<script nomodule crossorigin id="vite-legacy-polyfill" src="//yun.duiba.com.cn/db_games/spark/v3/1729238505291/assets/polyfills-legacy-DPMTo3qc.js"></script>
<script nomodule crossorigin id="vite-legacy-entry" data-src="//yun.duiba.com.cn/db_games/spark/v3/1729238505291/assets/index-legacy-BjxNED3H.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
</body>
</html>
...@@ -16,12 +16,8 @@ ...@@ -16,12 +16,8 @@
"@spark/svgaplayer": "^2.0.5", "@spark/svgaplayer": "^2.0.5",
"@spark/ui": "^2.1.28", "@spark/ui": "^2.1.28",
"@spark/utils": "^2.0.88", "@spark/utils": "^2.0.88",
"@types/crypto-js": "^4.2.2",
"@types/node": "^22.5.1",
"ali-oss": "^6.21.0",
"chalk": "^5.3.0", "chalk": "^5.3.0",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"dotenv": "^16.4.5",
"duiba-utils": "^2.0.2", "duiba-utils": "^2.0.2",
"less": "^4.2.0", "less": "^4.2.0",
"mobx": "^6.13.1", "mobx": "^6.13.1",
...@@ -35,20 +31,23 @@ ...@@ -35,20 +31,23 @@
"@babel/plugin-proposal-decorators": "^7.24.7", "@babel/plugin-proposal-decorators": "^7.24.7",
"@eslint/js": "^9.9.0", "@eslint/js": "^9.9.0",
"@types/ali-oss": "^6.16.11", "@types/ali-oss": "^6.16.11",
"@types/crypto-js": "^4.2.2",
"@types/postcss-pxtorem": "^6.0.3", "@types/postcss-pxtorem": "^6.0.3",
"@types/progress": "^2.0.7", "@types/progress": "^2.0.7",
"@types/react": "^18.3.3", "@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"@vitejs/plugin-legacy": "^5.4.2", "@vitejs/plugin-legacy": "^5.4.2",
"@vitejs/plugin-react": "^4.3.1", "@vitejs/plugin-react": "^4.3.1",
"ali-oss": "^6.21.0",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"dotenv": "^16.4.5",
"eslint": "^9.9.0", "eslint": "^9.9.0",
"eslint-plugin-react-hooks": "^5.1.0-rc.0", "eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.9", "eslint-plugin-react-refresh": "^0.4.9",
"globals": "^15.9.0", "globals": "^15.9.0",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"postcss-pxtorem": "^6.1.0", "postcss-pxtorem": "^6.1.0",
"terser": "^5.31.6", "terser": "^5.36.0",
"typescript": "5.5.4", "typescript": "5.5.4",
"typescript-eslint": "^8.0.1", "typescript-eslint": "^8.0.1",
"vite": "5.4.2", "vite": "5.4.2",
......
...@@ -23,8 +23,6 @@ class App extends Component { ...@@ -23,8 +23,6 @@ class App extends Component {
async componentDidMount() { async componentDidMount() {
await store.getFrontVariable(); await store.getFrontVariable();
console.log(import.meta.glob("./assets/**/*"));
} }
render() { render() {
......
@import "../../res.less"; @import "../../res.less";
.homeDemo {}
.homeDemo {
position: absolute;
.homeImg {
position: absolute;
left: 100px;
top: 400px;
width: 200px;
height: 200px;
.webpBg("LoadingPage/loadingIp.png");
}
.svga {
position: absolute;
left: 0;
top: 0;
width: 400px;
height: 400px;
}
}
import React from 'react'; import React from 'react';
import {observer} from 'mobx-react'; import { observer } from 'mobx-react';
import './HomeDemo.less'; import './HomeDemo.less';
import { SvgaPlayer } from "@spark/svgaplayer";
import svga from "../../assets/LoadingPage/1红色标题.svga";
import png from "../../assets/LoadingPage/loadingIp.png";
@observer @observer
class HomeDemo extends React.Component { class HomeDemo extends React.Component {
render() { componentDidMount() {
return <div className="homeDemo">
当前为活动首页 }
</div>;
} render() {
return <div className="homeDemo">
<div className="homeImg" />
<img src={png} />
当前为活动首页
<SvgaPlayer className="svga" src={svga} />
</div>;
}
} }
export default HomeDemo; export default HomeDemo;
...@@ -7,12 +7,7 @@ ...@@ -7,12 +7,7 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
//background: linear-gradient(152deg, #AEE7FF 6%, #F1DEFC 43%, #F3E7FB 73%);
.webpBg("LoadingPage/loadingBg.jpg"); .webpBg("LoadingPage/loadingBg.jpg");
//background-image: url("../../assets/LoadingPage/loadingBg.jpg");
background-size: 750px 1624px;
.loading-ip { .loading-ip {
position: absolute; position: absolute;
......
import React from "react"; import React from "react";
import {observer} from "mobx-react"; import { observer } from "mobx-react";
import "./LoadingDemo.less"; import { PAGE_MAP } from "../../utils/constants";
// import {preloadAsset} from "../../utils/preload1.3";
import {PAGE_MAP} from "../../utils/constants";
import store from "../../store/store"; import store from "../../store/store";
import { preload } from "../../utils/preload.ts";
import "./LoadingDemo.less";
@observer @observer
class LoadingDemo extends React.Component { class LoadingDemo extends React.Component {
state = { state = {
curPercentage: 0 curPercentage: 0
} }
curPercentage = 0; curPercentage = 0;
intervalId: number = 0; intervalId: number = 0;
isEvenLoad = true; // 是否匀速加载进度条
componentDidMount() {
componentDidMount() { this.preloadAssetInit();
this.preloadAssetInit();
// this.jump();
// this.jump(); }
}
/**
/** * 资源预加载
* 资源预加载 */
*/ preloadAssetInit = async () => {
preloadAssetInit = async () => {
// const imageList = []; const files = import.meta.glob("../../assets/**/*", {
// preloadAsset( import: "default",
// imageList, eager: true,
// 3, });
// this.onLoadingProgress,
// ).then(() => { const urls = Object.values(files) as string[];
// // 预加载资源完成
// // 异步加载默认关闭 await preload(urls, (progress, loaded, total) => {
// // setTimeout(() => { const percentage = Math.floor(progress * 100);
// // // 异步加载资源开始 this.setEvenProgress(percentage);
// // const asyncImageList = assetList.asyncLoadImg; });
// // preloadAsset(asyncImageList, 1) };
// // }, 5000);
// }); jump = () => {
}; setTimeout(() => {
store.changePage(PAGE_MAP.HOME_PAGE); // 跳转页面
jump = () => { }, 100);
setTimeout(() => { };
store.changePage(PAGE_MAP.HOME_PAGE); // 跳转页面
}, 100);
}; /**
* 以1%匀速加载进度
* @param {*} percentage
/** */
* 资源加载进度回调 setEvenProgress = (percentage) => {
* @param {*} progress this.intervalId && clearInterval(this.intervalId);
*/ let curPercentage = this.curPercentage;
onLoadingProgress = (progress) => { this.intervalId = setInterval(() => {
const percentage = Math.floor(progress * 100); if (curPercentage >= percentage) {
console.log("progress", percentage); clearInterval(this.intervalId);
if (this.isEvenLoad) { this.jump();
this.setEvenProgress(percentage); return;
} else { }
if (percentage == 100) { curPercentage += 1;
this.jump(); this.curPercentage = curPercentage;
} this.setState({
curPercentage,
});
}, 10);
};
render() {
const { curPercentage } = this.state;
return <div className="loading">
<div className="loading-ip" />
<div className="progressBarBg" />
<div className="progressBar">
<div className="progressBarFill" style={{
transform: `translateX(${curPercentage - 100}%)`
}} />
</div>
<span className="progressTxt">金豆正在路上...... {curPercentage}%</span>
</div>;
} }
};
/**
* 以1%匀速加载进度
* @param {*} percentage
*/
setEvenProgress = (percentage) => {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
this.intervalId && clearInterval(this.intervalId);
let curPercentage = this.curPercentage;
// @ts-ignore
this.intervalId = setInterval(() => {
if (curPercentage >= percentage) {
clearInterval(this.intervalId);
this.jump();
return;
}
curPercentage += 1;
this.curPercentage = curPercentage;
this.setState({
curPercentage,
});
}, 10);
};
render() {
const {curPercentage} = this.state;
return <div className="loading">
<div className="loading-ip"/>
<div className="progressBarBg"/>
<div className="progressBar">
<div className="progressBarFill" style={{
transform: `translateX(${curPercentage - 100}%)`
}}/>
</div>
<span className="progressTxt">金豆正在路上...... {curPercentage}%</span>
</div>;
}
} }
export default LoadingDemo; export default LoadingDemo;
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
background-image: var(--p); background-image: var(--p);
[duiba-webp='true'] & { [duiba-webp='true'] & {
--p: url("@{RES_PATH}@{value}@{webp}");
background-image: var(--p); background-image: var(--p);
} }
} }
......
...@@ -18,8 +18,8 @@ class Store { ...@@ -18,8 +18,8 @@ class Store {
Did1NDA0NDc: "sharePage", Did1NDA0NDc: "sharePage",
myPrize: "myPrize", // TODO 举例子 新宿台奖品页 myPrize: "myPrize", // TODO 举例子 新宿台奖品页
index: PAGE_MAP.LOADING_PAGE, index: PAGE_MAP.HOME_PAGE,
}[skinId] || PAGE_MAP.HOME_PAGE; }[skinId] || PAGE_MAP.LOADING_PAGE;
pageData = {}; pageData = {};
......
...@@ -5,29 +5,36 @@ ...@@ -5,29 +5,36 @@
*/ */
(function () { (function () {
let lowAdr = false; let lowAdr = false;
const ua = navigator.userAgent.toLowerCase() const ua = navigator.userAgent.toLowerCase()
const isAndroid = ua.indexOf('android') > -1 || ua.indexOf('adr') > -1; const isAndroid = ua.indexOf('android') > -1 || ua.indexOf('adr') > -1;
if (isAndroid) { if (isAndroid) {
const ver = parseFloat(ua.substr(ua.indexOf('android') + 8, 3)); const ver = parseFloat(ua.substr(ua.indexOf('android') + 8, 3));
lowAdr = ver < 4.4; lowAdr = ver < 4.4;
}
if (lowAdr && localStorage) {
delete localStorage.isWebp;
}
if (localStorage && !localStorage.isWebp) {
const img = new Image()
img.onload = function () {
if (img.width === 1 && !lowAdr) {
localStorage.isWebp = true;
document.getElementsByTagName('html')[0].setAttribute('duiba-webp', 'true')
} else {
localStorage.isWebp = '';
}
} }
img.onerror = function () { if (lowAdr && localStorage) {
localStorage.isWebp = '' delete localStorage.isWebp;
} }
img.src = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA=' if (localStorage && !localStorage.isWebp) {
} const img = new Image()
})() img.onload = function () {
if (img.width === 1 && !lowAdr) {
localStorage.isWebp = true;
document.getElementsByTagName('html')[0].setAttribute('duiba-webp', 'true')
} else {
localStorage.isWebp = '';
}
}
img.onerror = function () {
localStorage.isWebp = ''
}
img.src = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA='
}
})();
export const webpQuery = "?x-oss-process=image/format,webp";
export function supportWebp() {
return !!localStorage?.isWebp;
}
\ No newline at end of file
import { supportWebp, webpQuery } from "./checkwebp.ts";
export const svgaRegex = (/\.(svga)$/);
export const jpgRegex = (/\.(jpe?g)$/);
export const pngRegex = (/\.(png)$/);
export const webpRegex = (/\.(webp)$/);
export const gifRegex = (/\.(gif)$/);
export const imgRegex = (/\.(png|jpe?g|webp|gif)$/);
const typeRegex = (/\.([^.]+)$/);
const loaders = {
".jpg": loadImg,
".jpeg": loadImg,
".png": loadImg,
".webp": loadImg,
".gif": loadImg,
'.svga': loadSvga,
}
export async function preload(
urls: string[],
onProcess?: (progress: number, loaded: number, total: number) => void,
onComplete?: () => void
) {
const ps = [];
let loaded = 0;
const total = urls.length;
// 获取文件类型
urls.forEach((url) => {
const type = url.match(typeRegex)?.[0];
const loadFunc = loaders[type] || loadUnknown;
const p = loadFunc(url).then(() => {
loaded++;
const progress = loaded / total;
onProcess && onProcess(progress, loaded, total);
if (loaded >= total) {
onComplete && onComplete();
}
});
ps.push(p);
});
}
/**
* 加载一张图片
* @param {string} url 地址
*/
export function loadImg(url: string) {
return new Promise((resolve) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = err => {
console.warn('load', url, err);
resolve(null);
};
img.crossOrigin = 'anonymous';
img.src = url + (supportWebp() ? webpQuery : '');
});
}
export function loadSvga(url: string) {
return Promise.resolve();
}
export function loadUnknown(url: string) {
console.warn(`load unknown: ${url}`);
return Promise.resolve();
}
\ No newline at end of file
/// <reference types="vite/client" /> /// <reference types="vite/client" />
declare module "*.svga" {
const src: string;
export default src;
}
\ No newline at end of file
...@@ -20,7 +20,8 @@ ...@@ -20,7 +20,8 @@
"noImplicitAny": false, "noImplicitAny": false,
"noUnusedLocals": false, "noUnusedLocals": false,
"noUnusedParameters": false, "noUnusedParameters": false,
"noFallthroughCasesInSwitch": true "noFallthroughCasesInSwitch": true,
"types": ["node_modules/@types/node"]
}, },
"include": ["src"] "include": ["src"],
} }
...@@ -5,91 +5,91 @@ import autoprefixer from "autoprefixer" ...@@ -5,91 +5,91 @@ import autoprefixer from "autoprefixer"
import postcsspxtorem from "postcss-pxtorem" import postcsspxtorem from "postcss-pxtorem"
import { viteMockServe } from "vite-plugin-mock"; import { viteMockServe } from "vite-plugin-mock";
import DuibaPublish from "./config/DuibaPublish/DuibaPublish.ts"; import DuibaPublish from "./config/DuibaPublish/DuibaPublish.ts";
import dotenv from 'dotenv'; import dotenv from 'dotenv';
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig(({mode}) => { export default defineConfig(({ mode }) => {
dotenv.config({path: [`./config/.env.global`, `./config/.env.${mode}`]}); dotenv.config({ path: [`./config/.env.global`, `./config/.env.${mode}`] });
const { const {
NODE_ENV, NODE_ENV,
UPLOAD_DIR, CDN_DOMAIN, UPLOAD_DIR, CDN_DOMAIN,
OSS_REGION, OSS_BUCKET, OSS_REGION, OSS_BUCKET,
OSS_ACCESS_KEY_ID, OSS_ACCESS_SECRET, OSS_ACCESS_KEY_ID, OSS_ACCESS_SECRET,
} = process.env; } = process.env;
console.log(UPLOAD_DIR, NODE_ENV, CDN_DOMAIN, OSS_REGION, OSS_BUCKET, OSS_ACCESS_KEY_ID, OSS_ACCESS_SECRET) // console.log(UPLOAD_DIR, NODE_ENV, CDN_DOMAIN, OSS_REGION, OSS_BUCKET, OSS_ACCESS_KEY_ID, OSS_ACCESS_SECRET)
const isDev = NODE_ENV == "development"; const isDev = NODE_ENV == "development";
const versionStamp = Date.now(); const versionStamp = Date.now();
const prodBase = `${CDN_DOMAIN}/${UPLOAD_DIR}/${versionStamp}/`; const prodBase = `${CDN_DOMAIN}/${UPLOAD_DIR}/${versionStamp}/`;
return { return {
base: !isDev ? prodBase : "", base: !isDev ? prodBase : "",
server: { server: {
// port: 3001 // port: 3001
}, open: true,
plugins: [
react({
babel: {
plugins: [
["@babel/plugin-proposal-decorators", {legacy: true}],
["@babel/plugin-proposal-class-properties", {loose: true}],
],
}, },
}), assetsInclude: [/\.(svga)$/],
legacy({
targets: ['defaults', 'not IE 11'],
}),
viteMockServe({
// default
mockPath: 'mock',
enable: true,
}),
!isDev && DuibaPublish({
buildVersion: versionStamp,
uploadDir: UPLOAD_DIR,
region: OSS_REGION,
bucket: OSS_BUCKET,
accessKeyId: OSS_ACCESS_KEY_ID,
accessKeySecret: OSS_ACCESS_SECRET,
}),
],
css: {
postcss: {
plugins: [ plugins: [
autoprefixer({ react({
overrideBrowserslist: [ babel: {
"Android 4.1", plugins: [
"iOS 7.1", ["@babel/plugin-proposal-decorators", { legacy: true }],
"Chrome > 31", ["@babel/plugin-proposal-class-properties", { loose: true }],
"ff > 31", ],
"ie >= 8", },
"last 10 versions", // 所有主流浏览器最近10版本用 }),
], legacy({
grid: true targets: ['defaults', 'not IE 11'],
}), }),
postcsspxtorem({ viteMockServe({
rootValue: 100, // default
// propList: ["*", "!border"], // 除 border 外所有px 转 rem mockPath: 'mock',
selectorBlackList: [".noRem-"], // 过滤掉.noRem-开头的class,不进行rem转换 enable: true,
}), }),
!isDev && DuibaPublish({
buildVersion: versionStamp,
uploadDir: UPLOAD_DIR,
region: OSS_REGION,
bucket: OSS_BUCKET,
accessKeyId: OSS_ACCESS_KEY_ID,
accessKeySecret: OSS_ACCESS_SECRET,
}),
], ],
}, css: {
preprocessorOptions: { postcss: {
less: { plugins: [
javascriptEnabled: true, autoprefixer({
}, overrideBrowserslist: [
}, "Android 4.1",
modules: { "iOS 7.1",
localsConvention: 'camelCase' "Chrome > 31",
} "ff > 31",
"ie >= 8",
"last 10 versions", // 所有主流浏览器最近10版本用
],
grid: true
}),
postcsspxtorem({
rootValue: 100,
propList: ["*", "!border"], // 除 border 外所有px 转 rem
selectorBlackList: [".noRem-"], // 过滤掉.noRem-开头的class,不进行rem转换
}),
],
},
preprocessorOptions: {
less: {
javascriptEnabled: true,
},
},
modules: {
localsConvention: 'camelCase'
}
}
} }
}
} }
) )
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment