Commit 4b3933ef authored by wildfirecode13's avatar wildfirecode13

1

parent 7475b79d
File added
const apiCfg = {
getRule:`projectRule.query`,
doJoin: {
uri: `join.do`,
method: "post"
},
}
export default apiCfg;
import apiCfg from './apicfg';
import {getPxToken} from "@spark/projectx";
import {callApi} from '@spark/api-base'
import {Toast} from '@spark/ui'
import {isFromShare, newUser} from 'duiba-utils';
let mergeData = {
user_type: newUser ? '0' : '1',
is_from_share: isFromShare ? '0' : '1',
}
const apiList = {
...apiCfg
}
const API = generateAPI(apiList);
export default API;
function getRequestParams(value) {
if (typeof value === 'string') {
return {
uri: value,
method: 'get'
}
} else if (typeof value === 'object') {
const {uri, method = 'get', headers, withToken, secret, secretKey, contentType = 'form'} = value;
return {
uri,
method,
headers,
withToken,
secret,
secretKey,
contentType,
}
} else {
console.error('getRequestParams: 传参有误');
}
}
function generateAPI(apiList) {
const api = {};
for (let key in apiList) {
let value = apiList[key];
const {method, uri, headers: mHeaders, withToken, secret, secretKey, contentType} = getRequestParams(value);
api[key] = async (params = {}, headers) => {
let token;
if (withToken) {
try {
token = await getPxToken();
} catch (e) {
Toast('星速台token获取失败,***请补全该处理逻辑***');
return;
}
}
let mergedHeaders = {...mHeaders, ...headers}
if (withToken && token) {
params.token = token;
}
params = {...params, ...mergeData};
const result = await callApi(uri, params, method, mergedHeaders, false, secret, secretKey, contentType)
.catch(e => {
//捕获网络异常
Toast((e.message || '网络异常') + ' ***请补全该处理逻辑***');
});
if (result) {
//判断接口错误
if (!result.success) {
Toast((result.message || '接口错误') + ' ***请补全该处理逻辑***');
}
//返回整个结果
return result;
}
}
}
return api;
}
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./app.less";
import Modal from './modal/modal';
import MD from '../MD';
MD();
import "../monitor.js"; //前端错误监控
//此处为spark-cli动态生成
class App extends Component {
render() {
return (
<div>
<div>请在app.jsx中指定首页</div>
<Modal />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
* {
margin: 0;
padding: 0;
}
html,
body {
font-size: 24px;
width: 100%;
height: 100%;
-webkit-text-size-adjust: 100% !important;
text-size-adjust: 100% !important;
-moz-text-size-adjust: 100% !important;
}
import React, { Component } from "react";
import './modal.less';
import { observer } from 'mobx-react';
import modalStore from '../store/modal';
import { toJS } from 'mobx';
export const cfg = {
};
@observer
class Modal extends Component {
constructor(props) {
super(props);
}
componentDidMount() { }
render() {
const list = toJS(modalStore.popList);
if (!list.length) return <section></section>;
let PopUp, popData, PopUpMulti, popUpMultiData;
if (list.length > 1 && list[list.length - 1].isMulti == true) {
const popObj2 = list[list.length - 1];
PopUpMulti = cfg[popObj2.key];
popUpMultiData = popObj2.data;
}
const popObj = list[0];
PopUp = cfg[popObj.key];
popData = popObj.data;
const _div = document.getElementById("root");
let _top = window.scrollY;
if (_div && PopUp) {
_div.style.position = "fixed";
} else {
_div && (_div.style.position = "static");
window.scrollTo(0, _top);
}
return <section className="modal-hoc-bg" style={{
zIndex: !!modalStore.popList.length ? 1000 : -1,
display: !!modalStore.popList.length ? 'block' : 'none'
}}>
{PopUp && <PopUp popData={popData} />}
{PopUpMulti && <section className="modal-hoc-bg" style={{
zIndex: !!modalStore.popList.length ? 1000 : -1,
display: !!modalStore.popList.length ? 'block' : 'none'
}}><PopUpMulti popData={popUpMultiData} />
</section>}
</section>;
}
}
export default Modal;
\ No newline at end of file
.modal-hoc-bg {
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.8);
z-index: 1000;
}
\ No newline at end of file
import { makeAutoObservable } from 'mobx';
import API from '../api/index';
const store = makeAutoObservable({
ruleInfo: '',
setRule(ruleInfo) {
this.ruleInfo = ruleInfo
},
async initRule() {
// 模拟获取远程的数据
const { data } = await API.getRule();
this.setRule(data)
}
})
export default store;
\ No newline at end of file
import { makeAutoObservable,toJS } from 'mobx';
//此处配置页面的优先级,越大优先级越高
// PopIndex:11
const modalIndex = {
}
const modalStore = makeAutoObservable({
popList: [],
/**
*
* @param {*} key 弹窗名,一般是类名的字符串
* @param {*} data 需要传递的数据,弹窗中使用 const {popData} = props; 获取
* @param {*} isMulti 是否是二级弹窗,在不关闭已有弹窗的基础上,弹出当前弹窗。注意,如果是二级弹窗,关闭时必须传key
*/
pushPop(key, data,isMulti=false) {
if (this.popList.length) {
let cacheList = this.popList.slice();
cacheList.push({ key, data,isMulti });
cacheList = cacheList.sort((a, b) => ((modalIndex[b.key] ? modalIndex[b.key] : 10) - (modalIndex[a.key] ? modalIndex[a.key] : 10)))
this.popList.clear();
this.popList.push(...cacheList);
} else {
this.popList.push({ key, data,isMulti });
}
// console.log("this.popList:::",toJS(this.popList));
},
closePop(key) {
if (key) {
let cacheList = this.popList.slice();
cacheList = cacheList.filter(obj => (obj.key != key));
this.popList.clear();
this.popList.push(...cacheList);
} else {
this.popList.shift();
}
},
closePopAll() {
this.popList.clear();
}
});
export default modalStore;
.DS_Store
node_modules/
___cache/
__cache/
coverage/
dist/
npm-debug.log
selenium-debug.log
.idea
.builds
.project
.vscode
yarn-error.log
.yarn
.package-lock
yarn.lock
.cache
packages/**/package-lock.json
released
output.js
output.js.map
.psd
.psb
#src/assets/
\ No newline at end of file
import MD from 'spark-utils/out/md/index.js';
let appId = CFG.appID;
const dcm = '202.' + CFG.projectId + '.0.0';
const domain = '//embedlog.duiba.com.cn';
let MDList = [
{
ele: `.test-md1`,
data: {
dpm: `${appId}.110.5.1`,
dcm,
domain,
appId
},
once: false
}
];
export default () =>
MD({
show: MDList, // 曝光
click: MDList // 点击
});
# spark-template
烽火台app3.0中的静态模板配置
\ No newline at end of file
const { assets } = require("spark-assets");
const args = process.argv.splice(2);
let argsObj = {
imgmin: false,
imgup: false
}
if (args.length == 1) {
argsObj.imgmin = 'imgmin' == args[0];
argsObj.imgup = 'imgup' == args[0];
} else if (args.length == 2) {
argsObj.imgmin = 'imgmin' == args[0];
argsObj.imgup = 'imgup' == args[1];
}
assets(argsObj)
\ No newline at end of file
exports.SPARK_CONFIG_DIR_KEY = ['OUTPUT_DIR', 'SOURCE_DIR', 'TEMP_DIR', 'ENTRY', 'TEMPLATE']
exports.SPARK_CONFIG = 'sparkrc.js'
//对应项目在线素材存储的cdn配置,用于迭代开发从线上拉取素材到本地
exports.SPARK_CDN_RES_CFG='sparkrescfg.json'
\ No newline at end of file
const loaderUtils = require('loader-utils');
module.exports = function (source) {
const options = loaderUtils.getOptions(this);
let result = source;
if (options.arr) {
options.arr.map(op => {
result = result.replace(op.replaceFrom, op.replaceTo);
})
} else {
result = source.replace(options.replaceFrom, options.replaceTo);
}
return result
};
const babel = require('@babel/core');
const HtmlWebpackPlugin = require("html-webpack-plugin");
class HtmlJsToES5Plugin {
process(htmlPluginData) {
return new Promise(function (resolve) {
const scriptRegExp = /<script>(.|\n)*?<\/script>/gi;
htmlPluginData.html = htmlPluginData.html.replace(scriptRegExp, function (match) {
const code = match.replace("<script>", "").replace("</script>", "");
const es5Code = babel.transform(code, { 'presets': ['@babel/preset-env'] }).code;
return `<script>${es5Code}</script>`;
});
resolve();
});
};
apply(compiler){
compiler.hooks.compilation.tap('HtmlJsToES5Plugin', (compilation) => {
HtmlWebpackPlugin.getHooks(compilation).afterTemplateExecution.tapAsync(
"HtmlJsToES5Plugin",
async (html, cb) => {
await this.process(html);
cb(null, html);
}
);
});
}
}
// exports.default = HtmlJsToES5Plugin;
module.exports = HtmlJsToES5Plugin;
// 端口是否被占用
exports.getProcessIdOnPort=function(port) {
try {
const execOptions = {
encoding: 'utf8',
stdio: [
'pipe',
'pipe',
'ignore',
],
};
return execSync('lsof -i:' + port + ' -P -t -sTCP:LISTEN', execOptions)
.split('\n')[0]
.trim();
} catch (e) {
return null;
}
}
const childProcessSync=async function(cmd, params, cwd, printLog = true) {
return new Promise((resolve, reject) => {
let proc = childProcess(cmd, params, cwd, printLog);
proc.on('close', (code) => {
if (code === 0) {
resolve(proc['logContent']);
} else {
reject(code);
}
});
});
}
const getGitBranch=async function(cwd) {
try {
const result = await childProcessSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], cwd, false);
if (!result.startsWith('fatal:')) {
return result.trim();
}
} catch (e) {
return undefined;
}
}
const getProjectNameByPackage=function() {
return require(`${process.cwd()}/package.json`).name
}
/**
* 理论上每个项目独一无二的文件夹名字-默认取分支名
* 如果当前未创建分支,取包名+日期
* (实际很多情况是直接clone老项目,包名相同,以防资源被替换,所以用日期加一下)
*/
exports.getCdnFolderName=async function() {
const branch = await getGitBranch(process.cwd());
const date = Date.now();
if (branch) {
return branch + "/" + date;
}
let foldername = getProjectNameByPackage() + "/" + date;
return foldername;
}
\ No newline at end of file
const path = require('path');
const fs = require("fs");
const { SPARK_CONFIG_DIR_KEY, SPARK_CONFIG } = require('./scripts/constant');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const ProgressBarPlugin = require("progress-bar-webpack-plugin");
module.exports = function (isProd) {
const appPath = process.cwd();
const sparkConfig = require(path.join(appPath, SPARK_CONFIG));
const isEslint = fs.existsSync(`${appPath}/.eslintrc.js`);
const cssReg = /\.(css|less)$/;
// 处理相对路径
SPARK_CONFIG_DIR_KEY.map((key) => {
sparkConfig[key] = path.resolve(appPath, sparkConfig[key]);
});
const stylePlugins = [
require("autoprefixer")({
overrideBrowserslist: ["> 1%", "last 2 versions", "not ie <= 8"],
})
];
if (sparkConfig.PX2REM) {
stylePlugins.push(
require("postcss-px2rem-exclude")({
remUnit: 100, // 注意算法,这是750设计稿,html的font-size按照750比例
exclude: /node_modules/i,
})
);
}
const styleLoader = (cssOptions = {}) => {
return [
{
loader: "style-loader",
},
isProd && {
loader: MiniCssExtractPlugin.loader,
options: {
esModule: false,
},
},
{
loader: "css-loader",
options: {
...cssOptions,
importLoaders: 2, // 如果遇到css里面的 @import 执行后面两个loader。 不然如果import了less,css-loader是解析不了
},
},
{
loader: "postcss-loader",
options: {
sourceMap: isProd,
plugins: stylePlugins,
},
},
{
loader: require.resolve("less-loader"),
options: {
sourceMap: isProd,
},
},
].filter(Boolean);
};
return {
entry: sparkConfig.ENTRY,
mode: isProd ? 'production' : 'development',
devtool: "source-map",
output: {
path: path.resolve(__dirname, sparkConfig.OUTPUT_DIR),
filename: "js/[name].js",
},
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
"@src": path.resolve(__dirname, sparkConfig.SOURCE_DIR),
},
},
module: {
rules: [
// 提前进行eslint, 默认从下往上,通过enforce pre提前
isEslint && {
test: /\.js|jsx/,
enforce: "pre",
loader: "eslint-loader",
options: {
cache: true,
formatter: require("eslint-friendly-formatter"),
fix: true,
failOnError: true,
configFile: `${appPath}/.eslintrc.js`,
},
include: sparkConfig.SOURCE_DIR,
},
{
test: cssReg,
use: styleLoader(),
include: sparkConfig.SOURCE_DIR,
},
{
test: /\.(js|jsx)$/,
loader: require.resolve("babel-loader"),
exclude: [path.resolve("node_modules")],
options: {
presets: [
require("@babel/preset-env").default,
require("@babel/preset-react").default
],
plugins: [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose": false }],
require("@babel/plugin-transform-runtime").default,
],
sourceType: 'unambiguous'
},
},
{
test: [/\.(jpg|jpeg|png|svg|bmp)$/, /\.(eot|woff2?|ttf|svg)$/],
loader: require.resolve("url-loader"),
options: {
name: "[path][name].[ext]", // name默认是加上hash值。这里做了更改,不让加
outputPath: "images",
limit: 10240, // url-loader处理图片默认是转成base64, 这里配置如果小于10kb转base64,否则使用file-loader打包到images文件夹下
},
},
].filter(Boolean),
},
plugins: [
isProd &&
new MiniCssExtractPlugin({
filename: "styles/[name].[hash].css",
}),
new HtmlWebpackPlugin({
template: sparkConfig.TEMPLATE,
minify: !sparkConfig.UNMINIFY_INDEX && isProd,
}),
new CleanWebpackPlugin({
// cleanOnceBeforeBuildPatterns:['**/*', 'dist'] // 这里不用写 是默认的。 路径会根据output 输出的路径去清除
}),
new ProgressBarPlugin(),
].filter(Boolean),
optimization: {
minimize: isProd,
minimizer: [
// 替换的js压缩 因为uglifyjs不支持es6语法,
new TerserPlugin({
cache: true,
sourceMap: isProd,
extractComments: false, // 提取注释
parallel: true, // 多线程
terserOptions: {
compress: {
pure_funcs: ["console.log"],
},
},
}),
// 压缩css
new OptimizeCSSAssetsPlugin({
assetNameRegExp: /\.optimize\.css$/g,
cssProcessor: require("cssnano"),
cssProcessorPluginOptions: {
preset: ["default", { discardComments: { removeAll: true } }],
},
canPrint: true,
}),
],
// 修改文件的ids的形成方式,避免单文件修改,会导致其他文件的hash值变化,影响缓存
moduleIds: "hashed",
splitChunks: {
chunks: "all",
minSize: 30000, //小于这个限制的会打包进Main.js
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10, // 优先级权重,层级 相当于z-index。 谁值越大权会按照谁的规则打包
name: "vendors",
},
},
},
// chunks 映射关系的 list单独从 app.js里提取出来
runtimeChunk: {
name: (entrypoint) => `runtime-${entrypoint.name}`,
},
},
};
}
\ No newline at end of file
const { SPARK_CONFIG } = require("./scripts/constant");
const Webpack = require("webpack");
const webpackBaseConfig = require("./webpack.common.config");
const WebpackMerge = require("webpack-merge");
const WebpackDevServer = require("webpack-dev-server");
const opn = require("opn");
const apiMocker = require('mocker-api');
const path = require('path');
const { getProcessIdOnPort } = require("./scripts/utils");
const sparkConfig = require(path.resolve(SPARK_CONFIG));
const webpackDevConfig = function () {
return {
devServer: {
useLocalIp: true,
open: false,
hot: true,
host: "0.0.0.0",
// hotOnly: true
before(app) {
if (sparkConfig.API_MOCK) {
apiMocker(app, path.resolve('./mock/index.js'), {
changeHost: true,
})
}
}
},
plugins: [
// new Webpack.WatchIgnorePlugin([/[\\/]mock[\\/]/]),
new Webpack.HotModuleReplacementPlugin()
]
};
};
const buildDev = async function (config) {
let { port } = config;
return new Promise((resolve, reject) => {
const config = WebpackMerge(webpackBaseConfig(false), webpackDevConfig());
const compiler = Webpack(config);
const devServerOptions = Object.assign({}, config.devServer);
console.log('devServerOptions', devServerOptions);
const server = new WebpackDevServer(compiler, devServerOptions);
if (getProcessIdOnPort(port)) {
reject(`端口 ${port} 已被使用`);
return;
} else {
server.listen(
port || 8088,
"0.0.0.0",
() => {
console.log(`Starting server on http://localhost:${port}`);
opn(`http://localhost:${port || 8088}`);
resolve();
},
(err) => {
if (err) console.error("server linsten err--", err);
reject();
}
);
}
});
};
const args = process.argv.splice(2);
const port = args[0] || 8088
buildDev({
port: Number(port)
})
const path = require("path");
const chalk = require("chalk");
const fs = require('fs-extra');
const Webpack = require("webpack");
const WebpackMerge = require("webpack-merge");
const webpackBaseConfig = require("./webpack.common.config");
const { uploadFiles } = require("spark-assets");
const isProd = true;
const { getCdnFolderName } = require("./scripts/utils");
const { SPARK_CONFIG } = require("./scripts/constant");
const HtmlJsToES5Plugin = require("./scripts/plugins/HtmlJsToES5Plugin");
const { DepReporter } =require('spark-log-event');
const sparkConfig = require('../sparkrc');
const webpackProdConfig = function (cdnFolderName, resPathProd) {
return {
output: {
publicPath: `//yun.duiba.com.cn/spark/v2/${cdnFolderName}/`,
filename: isProd ? "js/[name].[contenthash:8].js" : "js/[name].[contenthash:4].js",
},
resolveLoader: {
modules: ['node_modules', path.resolve(__dirname, './scripts/loaders')]
},
module: {
rules: [
{
test: /sparkrc\.js$/,
exclude: [path.resolve("node_modules")],
use: [
{
loader: 'replaceLoader',
options: {
arr: [
{
replaceFrom: /(MOCK_STATUS: true)|(MOCK_STATUS:true)|("MOCK_STATUS": true)|("MOCK_STATUS":true)/,
replaceTo: '"MOCK_STATUS": false'
},
{
replaceFrom: /(RES_PATH:'\/src\/assets\/')|(RES_PATH: '\/src\/assets\/')|("RES_PATH":"\/src\/assets\/")|("RES_PATH": "\/src\/assets\/")/,
replaceTo: `"RES_PATH":"${resPathProd}/"`
}
]
}
}
]
}
]
},
plugins: [
new Webpack.IgnorePlugin(/[\\/]mock[\\/]/),
new HtmlJsToES5Plugin(),
new DepReporter()
],
node: {
crypto: 'empty'
}
};
};
const buildProd = async function () {
const cdnFolderName = await getCdnFolderName();
const appPath = process.cwd();
const sparkConfig = require(path.join(appPath, SPARK_CONFIG));
const _webpackProdConfig = await webpackProdConfig(cdnFolderName, sparkConfig.RES_PATH_PROD || '');
//新增 JS_PATH_PROD 用作
let newSparkCfg = Object.assign({}, sparkConfig);
newSparkCfg['JS_PATH_PROD'] = `//yun.duiba.com.cn/spark/v2/${cdnFolderName}/js`;
const str = `module.exports =${JSON.stringify(newSparkCfg, null, 2)}`;
fs.writeFileSync(path.join(appPath, SPARK_CONFIG), str);
return new Promise((resolve, reject) => {
const config = WebpackMerge(webpackBaseConfig(isProd), _webpackProdConfig);
const compiler = Webpack(config);
compiler.run(async (error, stats) => {
if (error) {
return reject(error);
}
console.log(
stats.toString({
chunks: false, // 使构建过程更静默无输出
colors: true, // 在控制台展示颜色
})
);
console.log(`${chalk.yellow("打包成功, 等待上传")}\n`);
// await uploadFiles(config.output.path, '', cdnFolderName);
await uploadFiles(config.output.path, '', cdnFolderName, /.map$/);
resolve();
});
});
};
buildProd();
\ No newline at end of file
{
"compilerOptions": {
"experimentalDecorators": true,
"baseUrl": "./",
"paths": {
"@src/*": ["src/*"]
}
},
"exclude": [
"node_modules"
]
}
\ No newline at end of file
module.exports = {
"data": 3,
"success": true
}
\ No newline at end of file
module.exports = {
"data": "<p>以下是游戏规则:手速要快,点击红包雨。。333。。。。。。。。。。。。。。。。。。。。11111111111111sadasdadadsad5555555557777777777799999999999911111111111111111111111222222222222222222222222222222222222222222222222222222222222222333333333333333333333333333333333333333333333333333333333333311111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222233333333333333333333333333333333333333333333333333333333333331111111111111111111111111111111111111111111111111111111111111112222222222222222222222222222222222222222222222222222222222222223333333333333333333333333333333333333333333333333333333333333</p>",
"success": true
}
\ No newline at end of file
const rule = require("./common/rule");
const drawNum = require("./common/drawNum");
const proxy = {
"GET /projectRule.query": rule,
"GET /drawNum.query": drawNum
};
module.exports = proxy;
import { SentryInit } from '@spark/monitor-sdk';
if (CFG && CFG.MONITOR) {
SentryInit({
projectId: CFG.projectId,
name: CFG.projectName, // 线上正式项目的名称
sourcemapVersion:CFG.SOURCEVERSION,
users: [
'15068753667',
'17609348390',
'17692710437'
] // 前端开发者的钉钉手机号,字符串类型,可多个, 例如 ['176xxxx', '151xxxx']
});
}
\ No newline at end of file
This diff is collapsed.
{
"name": "temp_base",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "cross-env NODE_ENV=development node ./config/webpack.dev.config.js",
"imgmin": "node ./config/scripts/assets/index.js imgmin",
"imgup": "node ./config/scripts/assets/index.js imgup",
"imgminup": "node ./config/scripts/assets/index.js imgmin imgup",
"prod": "cross-env NODE_ENV=production node ./config/webpack.prod.config.js",
"build": "cross-env NODE_ENV=production node ./config/scripts/assets/index.js imgmin imgup && node ./config/webpack.prod.config.js"
},
"dependencies": {
"@spark/api-base": "^2.0.29",
"@spark/monitor-sdk": "^1.1.3",
"@spark/projectx": "^2.0.13",
"@spark/ui": "^2.0.36",
"@spark/utils": "^2.0.41",
"axios": "^0.19.2",
"css-loader": "^3.6.0",
"duiba-utils": "^1.0.2",
"history": "^4.10.1",
"mobx": "^6.2.0",
"mobx-react": "^7.1.0",
"postcss-loader": "^3.0.0",
"prettier": "^2.0.5",
"qs": "^6.9.4",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-redux": "^5.0.7",
"react-router-dom": "^5.2.0",
"redux": "^4.0.0",
"redux-thunk": "^2.3.0",
"spark-utils": "^0.0.12",
"style-loader": "^1.2.1",
"@spark/api-common": "^2.0.15",
"@spark/share": "^2.0.81",
"@spark/nbxiaoxiaole": "^1.0.83",
"@spark/red_pack_rain": "^0.0.11",
"@spark/chop_hands_com": "^1.0.3",
"@spark/animation": "^2.0.44",
"@spark/jump_high": "^0.0.5",
"@spark/hitplanet": "^1.1.9",
"@spark/api-checkin": "^1.0.39",
"@spark/preset-tmrAward": "^1.0.37",
"@spark/preset-timing": "^1.0.4"
},
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/plugin-proposal-decorators": "^7.13.15",
"@babel/plugin-transform-runtime": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10",
"autoprefixer": "^9.8.6",
"babel-loader": "^8.2.2",
"chalk": "^4.1.0",
"clean-webpack-plugin": "^3.0.0",
"cross-env": "^7.0.3",
"eslint-loader": "^4.0.2",
"fs-extra": "^9.0.1",
"html-webpack-plugin": "^4.5.1",
"less": "^4.1.0",
"less-loader": "^7.2.1",
"mini-css-extract-plugin": "^1.3.4",
"mocker-api": "^2.7.5",
"mockjs": "^1.1.0",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"postcss-px2rem-exclude": "0.0.6",
"progress-bar-webpack-plugin": "^2.1.0",
"spark-assets": "^1.1.5",
"spark-log-event": "^1.0.2",
"url-loader": "^4.1.1",
"webpack": "^4.43.0",
"webpack-cli": "^4.3.1",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "^4.2.2"
}
}
{"testId":"","devId":"","prodId":"pa9431864"}
<!DOCTYPE html>
<html lang="zh">
<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">
<title>活动标题</title>
<script src="//yun.duiba.com.cn/spark/v2/spark.base.fz.wxpollyfill.js"></script>
<script src="//yun.duiba.com.cn/js-libs/rem/1.1.3/rem.min.js"></script>
<script src="//yun.duiba.com.cn/h5/lib/zepto.min.js"></script>
<script>
function getApp() {
return {
cloud: {},
cloudName: "clientTemplate2C",
requestType: "mock"
}
}
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 id="sparkAutoCode">
//此处为烽火台自动生成,请勿自行添加其他逻辑;
var CFG = CFG || {};
CFG.projectName = `重庆中信银行拆盲盒(2)`;
CFG.MONITOR = `true`;
CFG.SOURCEVERSION = `pdf58f5ba_f32cc84a8`;
CFG.projectName = `重庆中信银行拆盲盒(2)`;
CFG.MONITOR = `true`;
CFG.SOURCEVERSION = `pdf58f5ba_f32cc84a8`;
</script></head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
module.exports ={
"OUTPUT_DIR": "dist",
"SOURCE_DIR": "src",
"TEMP_DIR": "./.temp",
"ENTRY": "src/app.jsx",
"TEMPLATE": "./public/index.html",
"API_MOCK": true,
"PX2REM": true,
"IMAGE_Q1": 0.6,
"IMAGE_Q2": 0.8,
"RES_PATH": "/src/assets/",
"RES_PATH_PROD": "//yun.duiba.com.cn/spark/v2/temp_base/1625106287829",
"JS_PATH_PROD": "//yun.duiba.com.cn/spark/v2/temp_base/1625115704656/js"
}
\ No newline at end of file
{"assetsPathArr":["//yun.duiba.com.cn/spark/v2/temp_base/1625106287829/index/index_bg.png","//yun.duiba.com.cn/spark/v2/temp_base/1625106287829/index/index_loading.png","//yun.duiba.com.cn/spark/v2/temp_base/1625106287829/index/index_progressbg.png","//yun.duiba.com.cn/spark/v2/temp_base/1625106287829/index/index_progressfront.png","//yun.duiba.com.cn/spark/v2/temp_base/1625106287829/index/index_title.png"]}
\ No newline at end of file
const apiCfg = {
getRule:`projectRule.query`,
doJoin: {
uri: `join.do`,
method: "post"
},
}
export default apiCfg;
import apiCfg from './apicfg';
import {getPxToken} from "@spark/projectx";
import {callApi} from '@spark/api-base'
import {Toast} from '@spark/ui'
import {isFromShare, newUser} from 'duiba-utils';
let mergeData = {
user_type: newUser ? '0' : '1',
is_from_share: isFromShare ? '0' : '1',
}
const apiList = {
...apiCfg
}
const API = generateAPI(apiList);
export default API;
function getRequestParams(value) {
if (typeof value === 'string') {
return {
uri: value,
method: 'get'
}
} else if (typeof value === 'object') {
const {uri, method = 'get', headers, withToken, secret, secretKey, contentType = 'form'} = value;
return {
uri,
method,
headers,
withToken,
secret,
secretKey,
contentType,
}
} else {
console.error('getRequestParams: 传参有误');
}
}
function generateAPI(apiList) {
const api = {};
for (let key in apiList) {
let value = apiList[key];
const {method, uri, headers: mHeaders, withToken, secret, secretKey, contentType} = getRequestParams(value);
api[key] = async (params = {}, headers) => {
let token;
if (withToken) {
try {
token = await getPxToken();
} catch (e) {
Toast('星速台token获取失败,***请补全该处理逻辑***');
return;
}
}
let mergedHeaders = {...mHeaders, ...headers}
if (withToken && token) {
params.token = token;
}
params = {...params, ...mergeData};
const result = await callApi(uri, params, method, mergedHeaders, false, secret, secretKey, contentType)
.catch(e => {
//捕获网络异常
Toast((e.message || '网络异常') + ' ***请补全该处理逻辑***');
});
if (result) {
//判断接口错误
if (!result.success) {
Toast((result.message || '接口错误') + ' ***请补全该处理逻辑***');
}
//返回整个结果
return result;
}
}
}
return api;
}
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./app.less";
import Modal from './modal/modal';
import MD from '../MD';
MD();
import "../monitor.js"; //前端错误监控
import Index from "./components/index/index.jsx";
//此处为spark-cli动态生成
class App extends Component {
render() {
return (
<div>
<Index>
</Index>
<Modal />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
* {
margin: 0;
padding: 0;
}
html,
body {
font-size: 24px;
width: 100%;
height: 100%;
-webkit-text-size-adjust: 100% !important;
text-size-adjust: 100% !important;
-moz-text-size-adjust: 100% !important;
}
'use strict';
import React, { Component } from 'react';
import { RES_PATH } from '../../../sparkrc.js';
import { observer } from 'mobx-react';
import store from '../../store/index';
import modalStore from '../../store/modal';
import './index.less';
@observer
class Index extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
setTimeout(() => {
console.log('你好,我是test0701');
window.foo.bar();
}, 1000);
}
render() {
return (
<div className="index ">
<span
className="index_bg "
style={{ background: `url("${RES_PATH + 'index/index_bg.png'}") no-repeat 0 0 / 100% 100%` }}
/>
<span
className="index_title "
style={{ background: `url("${RES_PATH + 'index/index_title.png'}") no-repeat 0 0 / 100% 100%` }}
/>
<span
className="index_loading "
style={{ background: `url("${RES_PATH + 'index/index_loading.png'}") no-repeat 0 0 / 100% 100%` }}
/>
<div className="index_progress ">
<span
className="index_progressbg "
style={{ background: `url("${RES_PATH + 'index/index_progressbg.png'}") no-repeat 0 0 / 100% 100%` }}
/>
<span
className="index_progressfront "
style={{ background: `url("${RES_PATH + 'index/index_progressfront.png'}") no-repeat 0 0 / 100% 100%` }}
/>
</div>
</div>
);
}
}
export default Index;
.index {
.index_bg {
width: 750px;
height: 1624px;
top: 0px;
left: 0px;
position: absolute;
}
.index_title {
width: 633px;
height: 244px;
top: 253px;
left: 64px;
position: absolute;
}
.index_loading {
width: 163px;
height: 31px;
top: 1076px;
left: 299px;
position: absolute;
}
.index_progress {
width: 578px;
height: 31px;
top: 1028px;
left: 91px;
position: absolute;
.index_progressbg {
width: 578px;
height: 31px;
top: 0px;
left: 0px;
position: absolute;
}
.index_progressfront {
width: 563px;
height: 23px;
top: 4px;
left: 8px;
position: absolute;
}
}
}
import React, { Component } from "react";
import Index from "../components/index/index";
import './modal.less';
import { observer } from 'mobx-react';
import modalStore from '../store/modal';
import { toJS } from 'mobx';
export const cfg = {
Index: Index
};
@observer
class Modal extends Component {
constructor(props) {
super(props);
}
componentDidMount() {}
render() {
const list = toJS(modalStore.popList);
if (!list.length) return <section></section>;
let PopUp, popData, PopUpMulti, popUpMultiData;
if (list.length > 1 && list[list.length - 1].isMulti == true) {
const popObj2 = list[list.length - 1];
PopUpMulti = cfg[popObj2.key];
popUpMultiData = popObj2.data;
}
const popObj = list[0];
PopUp = cfg[popObj.key];
popData = popObj.data;
const _div = document.getElementById("root");
let _top = window.scrollY;
if (_div && PopUp) {
_div.style.position = "fixed";
} else {
_div && (_div.style.position = "static");
window.scrollTo(0, _top);
}
return <section className="modal-hoc-bg" style={{
zIndex: !!modalStore.popList.length ? 1000 : -1,
display: !!modalStore.popList.length ? 'block' : 'none'
}}>
{PopUp && <PopUp popData={popData} />}
{PopUpMulti && <section className="modal-hoc-bg" style={{
zIndex: !!modalStore.popList.length ? 1000 : -1,
display: !!modalStore.popList.length ? 'block' : 'none'
}}><PopUpMulti popData={popUpMultiData} />
</section>}
</section>;
}
}
export default Modal;
\ No newline at end of file
.modal-hoc-bg {
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.8);
z-index: 1000;
}
\ No newline at end of file
import { makeAutoObservable } from 'mobx';
import API from '../api/index';
const store = makeAutoObservable({
ruleInfo: '',
setRule(ruleInfo) {
this.ruleInfo = ruleInfo
},
async initRule() {
// 模拟获取远程的数据
const { data } = await API.getRule();
this.setRule(data)
}
})
export default store;
\ No newline at end of file
import { makeAutoObservable,toJS } from 'mobx';
//此处配置页面的优先级,越大优先级越高
// PopIndex:11
const modalIndex = {
}
const modalStore = makeAutoObservable({
popList: [],
/**
*
* @param {*} key 弹窗名,一般是类名的字符串
* @param {*} data 需要传递的数据,弹窗中使用 const {popData} = props; 获取
* @param {*} isMulti 是否是二级弹窗,在不关闭已有弹窗的基础上,弹出当前弹窗。注意,如果是二级弹窗,关闭时必须传key
*/
pushPop(key, data,isMulti=false) {
if (this.popList.length) {
let cacheList = this.popList.slice();
cacheList.push({ key, data,isMulti });
cacheList = cacheList.sort((a, b) => ((modalIndex[b.key] ? modalIndex[b.key] : 10) - (modalIndex[a.key] ? modalIndex[a.key] : 10)))
this.popList.clear();
this.popList.push(...cacheList);
} else {
this.popList.push({ key, data,isMulti });
}
// console.log("this.popList:::",toJS(this.popList));
},
closePop(key) {
if (key) {
let cacheList = this.popList.slice();
cacheList = cacheList.filter(obj => (obj.key != key));
this.popList.clear();
this.popList.push(...cacheList);
} else {
this.popList.shift();
}
},
closePopAll() {
this.popList.clear();
}
});
export default modalStore;
{"proName":"test0701","proDesc":"","proPath":"/Users/wanghongyuan/test0701","createTime":1625105683638}
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