Commit 4a33873b by zhanghaozhe

prettier

parent 212a67b6
build
node_modules
public
\ No newline at end of file
const postcssNormalize = require('postcss-normalize')
const path = require('path')
const postcssNormalize = require("postcss-normalize")
const path = require("path")
module.exports = {
stories: ['../src/common/**/*.stories.tsx'],
stories: ["../src/common/**/*.stories.tsx"],
addons: [
{
name: '@storybook/preset-typescript',
name: "@storybook/preset-typescript",
options: {
tsLoaderOptions: {
configFile: path.resolve(__dirname, '../tsconfig.json'),
configFile: path.resolve(__dirname, "../tsconfig.json"),
},
},
},
'@storybook/addon-actions',
'@storybook/addon-links',
'@storybook/addon-knobs',
"@storybook/addon-actions",
"@storybook/addon-links",
"@storybook/addon-knobs",
],
webpackFinal: async config => {
webpackFinal: async (config) => {
config.module.rules.push({
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
"style-loader",
"css-loader",
{
loader: require.resolve('postcss-loader'),
loader: require.resolve("postcss-loader"),
options: {
ident: 'postcss',
ident: "postcss",
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
require("postcss-flexbugs-fixes"),
require("postcss-preset-env")({
autoprefixer: {
flexbox: 'no-2009',
flexbox: "no-2009",
},
stage: 3,
}),
......@@ -45,10 +45,10 @@ module.exports = {
},
},
{
loader: 'sass-loader',
loader: "sass-loader",
},
],
})
return config;
return config
},
};
}
import './style.scss'
import '../src/assets/font/iconfont.css'
import '@csstools/normalize.css/normalize.css'
\ No newline at end of file
import "./style.scss"
import "../src/assets/font/iconfont.css"
import "@csstools/normalize.css/normalize.css"
新m端前端项目
\ No newline at end of file
新 m 端前端项目
'use strict';
"use strict"
const fs = require('fs');
const path = require('path');
const paths = require('./paths');
const fs = require("fs")
const path = require("path")
const paths = require("./paths")
// Make sure that including paths.js after env.js will read .env variables.
delete require.cache[require.resolve('./paths')];
delete require.cache[require.resolve("./paths")]
const NODE_ENV = process.env.NODE_ENV;
const NODE_ENV = process.env.NODE_ENV
if (!NODE_ENV) {
throw new Error(
'The NODE_ENV environment variable is required but was not specified.'
);
"The NODE_ENV environment variable is required but was not specified."
)
}
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
......@@ -21,24 +21,24 @@ const dotenvFiles = [
// Don't include `.env.local` for `test` environment
// since normally you expect tests to produce the same
// results for everyone
NODE_ENV !== 'test' && `${paths.dotenv}.local`,
NODE_ENV !== "test" && `${paths.dotenv}.local`,
paths.dotenv,
].filter(Boolean);
].filter(Boolean)
// Load environment variables from .env* files. Suppress warnings using silent
// if this file is missing. dotenv will never modify any environment variables
// that have already been set. Variable expansion is supported in .env files.
// https://github.com/motdotla/dotenv
// https://github.com/motdotla/dotenv-expand
dotenvFiles.forEach(dotenvFile => {
dotenvFiles.forEach((dotenvFile) => {
if (fs.existsSync(dotenvFile)) {
require('dotenv-expand')(
require('dotenv').config({
require("dotenv-expand")(
require("dotenv").config({
path: dotenvFile,
})
);
)
}
});
})
// We support resolving modules according to `NODE_PATH`.
// This lets you use absolute paths in imports inside large monorepos:
......@@ -49,29 +49,29 @@ dotenvFiles.forEach(dotenvFile => {
// Otherwise, we risk importing Node.js core modules into an app instead of webpack shims.
// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421
// We also resolve them to make sure all tools using them work consistently.
const appDirectory = fs.realpathSync(process.cwd());
process.env.NODE_PATH = (process.env.NODE_PATH || '')
const appDirectory = fs.realpathSync(process.cwd())
process.env.NODE_PATH = (process.env.NODE_PATH || "")
.split(path.delimiter)
.filter(folder => folder && !path.isAbsolute(folder))
.map(folder => path.resolve(appDirectory, folder))
.join(path.delimiter);
.filter((folder) => folder && !path.isAbsolute(folder))
.map((folder) => path.resolve(appDirectory, folder))
.join(path.delimiter)
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
// injected into the application via DefinePlugin in webpack configuration.
const REACT_APP = /^REACT_APP_/i;
const REACT_APP = /^REACT_APP_/i
function getClientEnvironment(publicUrl) {
const raw = Object.keys(process.env)
.filter(key => REACT_APP.test(key))
.filter((key) => REACT_APP.test(key))
.reduce(
(env, key) => {
env[key] = process.env[key];
return env;
env[key] = process.env[key]
return env
},
{
// Useful for determining whether we’re running in production mode.
// Most importantly, it switches React into the correct mode.
NODE_ENV: process.env.NODE_ENV || 'development',
NODE_ENV: process.env.NODE_ENV || "development",
// Useful for resolving the correct path to static assets in `public`.
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
// This should only be used as an escape hatch. Normally you would put
......@@ -86,16 +86,16 @@ function getClientEnvironment(publicUrl) {
WDS_SOCKET_PATH: process.env.WDS_SOCKET_PATH,
WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT,
}
);
)
// Stringify all values so we can feed into webpack DefinePlugin
const stringified = {
'process.env': Object.keys(raw).reduce((env, key) => {
env[key] = JSON.stringify(raw[key]);
return env;
"process.env": Object.keys(raw).reduce((env, key) => {
env[key] = JSON.stringify(raw[key])
return env
}, {}),
};
}
return { raw, stringified };
return { raw, stringified }
}
module.exports = getClientEnvironment;
module.exports = getClientEnvironment
'use strict';
"use strict"
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const chalk = require('react-dev-utils/chalk');
const paths = require('./paths');
const fs = require("fs")
const path = require("path")
const crypto = require("crypto")
const chalk = require("react-dev-utils/chalk")
const paths = require("./paths")
// Ensure the certificate and key provided are valid and if not
// throw an easy to debug error
function validateKeyAndCerts({ cert, key, keyFile, crtFile }) {
let encrypted;
let encrypted
try {
// publicEncrypt will throw an error with an invalid cert
encrypted = crypto.publicEncrypt(cert, Buffer.from('test'));
encrypted = crypto.publicEncrypt(cert, Buffer.from("test"))
} catch (err) {
throw new Error(
`The certificate "${chalk.yellow(crtFile)}" is invalid.\n${err.message}`
);
)
}
try {
// privateDecrypt will throw an error with an invalid key
crypto.privateDecrypt(key, encrypted);
crypto.privateDecrypt(key, encrypted)
} catch (err) {
throw new Error(
`The certificate key "${chalk.yellow(keyFile)}" is invalid.\n${
err.message
}`
);
)
}
}
......@@ -38,29 +38,29 @@ function readEnvFile(file, type) {
`You specified ${chalk.cyan(
type
)} in your env, but the file "${chalk.yellow(file)}" can't be found.`
);
)
}
return fs.readFileSync(file);
return fs.readFileSync(file)
}
// Get the https config
// Return cert files if provided in env, otherwise just true or false
function getHttpsConfig() {
const { SSL_CRT_FILE, SSL_KEY_FILE, HTTPS } = process.env;
const isHttps = HTTPS === 'true';
const { SSL_CRT_FILE, SSL_KEY_FILE, HTTPS } = process.env
const isHttps = HTTPS === "true"
if (isHttps && SSL_CRT_FILE && SSL_KEY_FILE) {
const crtFile = path.resolve(paths.appPath, SSL_CRT_FILE);
const keyFile = path.resolve(paths.appPath, SSL_KEY_FILE);
const crtFile = path.resolve(paths.appPath, SSL_CRT_FILE)
const keyFile = path.resolve(paths.appPath, SSL_KEY_FILE)
const config = {
cert: readEnvFile(crtFile, 'SSL_CRT_FILE'),
key: readEnvFile(keyFile, 'SSL_KEY_FILE'),
};
cert: readEnvFile(crtFile, "SSL_CRT_FILE"),
key: readEnvFile(keyFile, "SSL_KEY_FILE"),
}
validateKeyAndCerts({ ...config, keyFile, crtFile });
return config;
validateKeyAndCerts({ ...config, keyFile, crtFile })
return config
}
return isHttps;
return isHttps
}
module.exports = getHttpsConfig;
module.exports = getHttpsConfig
'use strict';
"use strict"
// This is a custom Jest transformer turning style imports into empty objects.
// http://facebook.github.io/jest/docs/en/webpack.html
module.exports = {
process() {
return 'module.exports = {};';
return "module.exports = {};"
},
getCacheKey() {
// The output is always the same.
return 'cssTransform';
return "cssTransform"
},
};
}
'use strict';
"use strict"
const path = require('path');
const camelcase = require('camelcase');
const path = require("path")
const camelcase = require("camelcase")
// This is a custom Jest transformer turning file imports into filenames.
// http://facebook.github.io/jest/docs/en/webpack.html
module.exports = {
process(src, filename) {
const assetFilename = JSON.stringify(path.basename(filename));
const assetFilename = JSON.stringify(path.basename(filename))
if (filename.match(/\.svg$/)) {
// Based on how SVGR generates a component name:
// https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6
const pascalCaseFilename = camelcase(path.parse(filename).name, {
pascalCase: true,
});
const componentName = `Svg${pascalCaseFilename}`;
})
const componentName = `Svg${pascalCaseFilename}`
return `const React = require('react');
module.exports = {
__esModule: true,
......@@ -32,9 +32,9 @@ module.exports = {
})
};
}),
};`;
};`
}
return `module.exports = ${assetFilename};`;
return `module.exports = ${assetFilename};`
},
};
}
'use strict';
"use strict"
const fs = require('fs');
const path = require('path');
const paths = require('./paths');
const chalk = require('react-dev-utils/chalk');
const resolve = require('resolve');
const fs = require("fs")
const path = require("path")
const paths = require("./paths")
const chalk = require("react-dev-utils/chalk")
const resolve = require("resolve")
/**
* Get additional module paths based on the baseUrl of a compilerOptions object.
......@@ -12,7 +12,7 @@ const resolve = require('resolve');
* @param {Object} options
*/
function getAdditionalModulePaths(options = {}) {
const baseUrl = options.baseUrl;
const baseUrl = options.baseUrl
// We need to explicitly check for null and undefined (and not a falsy value) because
// TypeScript treats an empty string as `.`.
......@@ -21,21 +21,21 @@ function getAdditionalModulePaths(options = {}) {
// Note that NODE_PATH is deprecated and will be removed
// in the next major release of create-react-app.
const nodePath = process.env.NODE_PATH || '';
return nodePath.split(path.delimiter).filter(Boolean);
const nodePath = process.env.NODE_PATH || ""
return nodePath.split(path.delimiter).filter(Boolean)
}
const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
const baseUrlResolved = path.resolve(paths.appPath, baseUrl)
// We don't need to do anything if `baseUrl` is set to `node_modules`. This is
// the default behavior.
if (path.relative(paths.appNodeModules, baseUrlResolved) === '') {
return null;
if (path.relative(paths.appNodeModules, baseUrlResolved) === "") {
return null
}
// Allow the user set the `baseUrl` to `appSrc`.
if (path.relative(paths.appSrc, baseUrlResolved) === '') {
return [paths.appSrc];
if (path.relative(paths.appSrc, baseUrlResolved) === "") {
return [paths.appSrc]
}
// If the path is equal to the root directory we ignore it here.
......@@ -43,17 +43,17 @@ function getAdditionalModulePaths(options = {}) {
// not transpiled outside of `src`. We do allow importing them with the
// absolute path (e.g. `src/Components/Button.js`) but we set that up with
// an alias.
if (path.relative(paths.appPath, baseUrlResolved) === '') {
return null;
if (path.relative(paths.appPath, baseUrlResolved) === "") {
return null
}
// Otherwise, throw an error.
throw new Error(
chalk.red.bold(
"Your project's `baseUrl` can only be set to `src` or `node_modules`." +
' Create React App does not support other values at this time.'
" Create React App does not support other values at this time."
)
)
);
}
/**
......@@ -62,18 +62,18 @@ function getAdditionalModulePaths(options = {}) {
* @param {*} options
*/
function getWebpackAliases(options = {}) {
const baseUrl = options.baseUrl;
const baseUrl = options.baseUrl
if (!baseUrl) {
return {};
return {}
}
const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
const baseUrlResolved = path.resolve(paths.appPath, baseUrl)
if (path.relative(paths.appPath, baseUrlResolved) === '') {
if (path.relative(paths.appPath, baseUrlResolved) === "") {
return {
src: paths.appSrc,
};
}
}
}
......@@ -83,59 +83,59 @@ function getWebpackAliases(options = {}) {
* @param {*} options
*/
function getJestAliases(options = {}) {
const baseUrl = options.baseUrl;
const baseUrl = options.baseUrl
if (!baseUrl) {
return {};
return {}
}
const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
const baseUrlResolved = path.resolve(paths.appPath, baseUrl)
if (path.relative(paths.appPath, baseUrlResolved) === '') {
if (path.relative(paths.appPath, baseUrlResolved) === "") {
return {
'^src/(.*)$': '<rootDir>/src/$1',
};
"^src/(.*)$": "<rootDir>/src/$1",
}
}
}
function getModules() {
// Check if TypeScript is setup
const hasTsConfig = fs.existsSync(paths.appTsConfig);
const hasJsConfig = fs.existsSync(paths.appJsConfig);
const hasTsConfig = fs.existsSync(paths.appTsConfig)
const hasJsConfig = fs.existsSync(paths.appJsConfig)
if (hasTsConfig && hasJsConfig) {
throw new Error(
'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.'
);
"You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file."
)
}
let config;
let config
// If there's a tsconfig.json we assume it's a
// TypeScript project and set up the config
// based on tsconfig.json
if (hasTsConfig) {
const ts = require(resolve.sync('typescript', {
const ts = require(resolve.sync("typescript", {
basedir: paths.appNodeModules,
}));
config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config;
}))
config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config
// Otherwise we'll check if there is jsconfig.json
// for non TS projects.
} else if (hasJsConfig) {
config = require(paths.appJsConfig);
config = require(paths.appJsConfig)
}
config = config || {};
const options = config.compilerOptions || {};
config = config || {}
const options = config.compilerOptions || {}
const additionalModulePaths = getAdditionalModulePaths(options);
const additionalModulePaths = getAdditionalModulePaths(options)
return {
additionalModulePaths: additionalModulePaths,
webpackAliases: getWebpackAliases(options),
jestAliases: getJestAliases(options),
hasTsConfig,
};
}
}
module.exports = getModules();
module.exports = getModules()
'use strict';
"use strict"
const path = require('path');
const fs = require('fs');
const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath');
const path = require("path")
const fs = require("fs")
const getPublicUrlOrPath = require("react-dev-utils/getPublicUrlOrPath")
// Make sure any symlinks in the project folder are resolved:
// https://github.com/facebook/create-react-app/issues/637
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
const appDirectory = fs.realpathSync(process.cwd())
const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath)
// We use `PUBLIC_URL` environment variable or "homepage" field to infer
// "public path" at which the app is served.
......@@ -16,57 +16,55 @@ const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
// We can't use a relative path in HTML because we don't want to load something
// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
const publicUrlOrPath = getPublicUrlOrPath(
process.env.NODE_ENV === 'development',
require(resolveApp('package.json')).homepage,
process.env.NODE_ENV === "development",
require(resolveApp("package.json")).homepage,
process.env.PUBLIC_URL
);
)
const moduleFileExtensions = [
'web.mjs',
'mjs',
'web.js',
'js',
'web.ts',
'ts',
'web.tsx',
'tsx',
'json',
'web.jsx',
'jsx',
];
"web.mjs",
"mjs",
"web.js",
"js",
"web.ts",
"ts",
"web.tsx",
"tsx",
"json",
"web.jsx",
"jsx",
]
// Resolve file paths in the same order as webpack
const resolveModule = (resolveFn, filePath) => {
const extension = moduleFileExtensions.find(extension =>
const extension = moduleFileExtensions.find((extension) =>
fs.existsSync(resolveFn(`${filePath}.${extension}`))
);
)
if (extension) {
return resolveFn(`${filePath}.${extension}`);
return resolveFn(`${filePath}.${extension}`)
}
return resolveFn(`${filePath}.js`);
};
return resolveFn(`${filePath}.js`)
}
// config after eject: we're in ./config/
module.exports = {
dotenv: resolveApp('.env'),
appPath: resolveApp('.'),
appBuild: resolveApp('build'),
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
appIndexJs: resolveModule(resolveApp, 'src/index'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
appTsConfig: resolveApp('tsconfig.json'),
appJsConfig: resolveApp('jsconfig.json'),
yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveModule(resolveApp, 'src/setupTests'),
proxySetup: resolveApp('src/setupProxy.js'),
appNodeModules: resolveApp('node_modules'),
dotenv: resolveApp(".env"),
appPath: resolveApp("."),
appBuild: resolveApp("build"),
appPublic: resolveApp("public"),
appHtml: resolveApp("public/index.html"),
appIndexJs: resolveModule(resolveApp, "src/index"),
appPackageJson: resolveApp("package.json"),
appSrc: resolveApp("src"),
appTsConfig: resolveApp("tsconfig.json"),
appJsConfig: resolveApp("jsconfig.json"),
yarnLockFile: resolveApp("yarn.lock"),
testsSetup: resolveModule(resolveApp, "src/setupTests"),
proxySetup: resolveApp("src/setupProxy.js"),
appNodeModules: resolveApp("node_modules"),
publicUrlOrPath,
};
}
module.exports.moduleFileExtensions = moduleFileExtensions;
module.exports.moduleFileExtensions = moduleFileExtensions
'use strict';
"use strict"
const { resolveModuleName } = require('ts-pnp');
const { resolveModuleName } = require("ts-pnp")
exports.resolveModuleName = (
typescript,
......@@ -15,8 +15,8 @@ exports.resolveModuleName = (
compilerOptions,
resolutionHost,
typescript.resolveModuleName
);
};
)
}
exports.resolveTypeReferenceDirective = (
typescript,
......@@ -31,5 +31,5 @@ exports.resolveTypeReferenceDirective = (
compilerOptions,
resolutionHost,
typescript.resolveTypeReferenceDirective
);
};
)
}
'use strict';
"use strict"
const fs = require('fs');
const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
const ignoredFiles = require('react-dev-utils/ignoredFiles');
const redirectServedPath = require('react-dev-utils/redirectServedPathMiddleware');
const paths = require('./paths');
const getHttpsConfig = require('./getHttpsConfig');
const fs = require("fs")
const errorOverlayMiddleware = require("react-dev-utils/errorOverlayMiddleware")
const evalSourceMapMiddleware = require("react-dev-utils/evalSourceMapMiddleware")
const noopServiceWorkerMiddleware = require("react-dev-utils/noopServiceWorkerMiddleware")
const ignoredFiles = require("react-dev-utils/ignoredFiles")
const redirectServedPath = require("react-dev-utils/redirectServedPathMiddleware")
const paths = require("./paths")
const getHttpsConfig = require("./getHttpsConfig")
const host = process.env.HOST || '0.0.0.0';
const sockHost = process.env.WDS_SOCKET_HOST;
const sockPath = process.env.WDS_SOCKET_PATH; // default: '/sockjs-node'
const sockPort = process.env.WDS_SOCKET_PORT;
const host = process.env.HOST || "0.0.0.0"
const sockHost = process.env.WDS_SOCKET_HOST
const sockPath = process.env.WDS_SOCKET_PATH // default: '/sockjs-node'
const sockPort = process.env.WDS_SOCKET_PORT
module.exports = function(proxy, allowedHost) {
module.exports = function (proxy, allowedHost) {
return {
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote
// websites from potentially accessing local content through DNS rebinding:
......@@ -33,12 +33,12 @@ module.exports = function(proxy, allowedHost) {
// specified the `proxy` setting. Finally, we let you override it if you
// really know what you're doing with a special environment variable.
disableHostCheck:
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === "true",
// Enable gzip compression of generated files.
compress: true,
// Silence WebpackDevServer's own logs since they're generally not useful.
// It will still show compile warnings and errors with this setting.
clientLogLevel: 'none',
clientLogLevel: "none",
// By default WebpackDevServer serves physical files from current directory
// in addition to all the virtual build products that it serves from memory.
// This is confusing because those files won’t automatically be available in
......@@ -65,7 +65,7 @@ module.exports = function(proxy, allowedHost) {
hot: true,
// Use 'ws' instead of 'sockjs-node' on server since we're using native
// websockets in `webpackHotDevClient`.
transportMode: 'ws',
transportMode: "ws",
// Prevent a WS client from getting injected as we're already including
// `webpackHotDevClient`.
injectClient: false,
......@@ -106,25 +106,25 @@ module.exports = function(proxy, allowedHost) {
// Keep `evalSourceMapMiddleware` and `errorOverlayMiddleware`
// middlewares before `redirectServedPath` otherwise will not have any effect
// This lets us fetch source contents from webpack for the error overlay
app.use(evalSourceMapMiddleware(server));
app.use(evalSourceMapMiddleware(server))
// This lets us open files from the runtime error overlay.
app.use(errorOverlayMiddleware());
app.use(errorOverlayMiddleware())
if (fs.existsSync(paths.proxySetup)) {
// This registers user provided middleware for proxy reasons
require(paths.proxySetup)(app);
require(paths.proxySetup)(app)
}
},
after(app) {
// Redirect to `PUBLIC_URL` or `homepage` from `package.json` if url not match
app.use(redirectServedPath(paths.publicUrlOrPath));
app.use(redirectServedPath(paths.publicUrlOrPath))
// This service worker file is effectively a 'no-op' that will reset any
// previous service worker registered for the same host:port combination.
// We do this in development to avoid hitting the production cache if
// it used the same host and port.
// https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
app.use(noopServiceWorkerMiddleware(paths.publicUrlOrPath));
app.use(noopServiceWorkerMiddleware(paths.publicUrlOrPath))
},
};
};
}
}
'use strict';
"use strict"
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'development';
process.env.NODE_ENV = 'development';
process.env.REACT_APP_BUILD_ENV = 'development';
process.env.BABEL_ENV = "development"
process.env.NODE_ENV = "development"
process.env.REACT_APP_BUILD_ENV = "development"
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', err => {
throw err;
});
process.on("unhandledRejection", (err) => {
throw err
})
// Ensure environment variables are read.
require('../config/env');
require("../config/env")
const fs = require('fs');
const chalk = require('react-dev-utils/chalk');
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const clearConsole = require('react-dev-utils/clearConsole');
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
const fs = require("fs")
const chalk = require("react-dev-utils/chalk")
const webpack = require("webpack")
const WebpackDevServer = require("webpack-dev-server")
const clearConsole = require("react-dev-utils/clearConsole")
const checkRequiredFiles = require("react-dev-utils/checkRequiredFiles")
const {
choosePort,
createCompiler,
prepareProxy,
prepareUrls,
} = require('react-dev-utils/WebpackDevServerUtils');
const openBrowser = require('react-dev-utils/openBrowser');
const paths = require('../config/paths');
const configFactory = require('../config/webpack.config');
const createDevServerConfig = require('../config/webpackDevServer.config');
} = require("react-dev-utils/WebpackDevServerUtils")
const openBrowser = require("react-dev-utils/openBrowser")
const paths = require("../config/paths")
const configFactory = require("../config/webpack.config")
const createDevServerConfig = require("../config/webpackDevServer.config")
const useYarn = fs.existsSync(paths.yarnLockFile);
const isInteractive = process.stdout.isTTY;
const useYarn = fs.existsSync(paths.yarnLockFile)
const isInteractive = process.stdout.isTTY
// Warn and crash if required files are missing
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
process.exit(1);
process.exit(1)
}
// Tools like Cloud9 rely on this.
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
const HOST = process.env.HOST || '0.0.0.0';
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000
const HOST = process.env.HOST || "0.0.0.0"
if (process.env.HOST) {
console.log(
......@@ -52,41 +51,41 @@ if (process.env.HOST) {
chalk.bold(process.env.HOST)
)}`
)
);
)
console.log(
`If this was unintentional, check that you haven't mistakenly set it in your shell.`
);
)
console.log(
`Learn more here: ${chalk.yellow('https://bit.ly/CRA-advanced-config')}`
);
console.log();
`Learn more here: ${chalk.yellow("https://bit.ly/CRA-advanced-config")}`
)
console.log()
}
// We require that you explictly set browsers and do not fall back to
// browserslist defaults.
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
const { checkBrowsers } = require("react-dev-utils/browsersHelper")
checkBrowsers(paths.appPath, isInteractive)
.then(() => {
// We attempt to use the default port but if it is busy, we offer the user to
// run on a different port. `choosePort()` Promise resolves to the next free port.
return choosePort(HOST, DEFAULT_PORT);
return choosePort(HOST, DEFAULT_PORT)
})
.then(port => {
.then((port) => {
if (port == null) {
// We have not found a port.
return;
return
}
const config = configFactory('development');
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const appName = require(paths.appPackageJson).name;
const useTypeScript = fs.existsSync(paths.appTsConfig);
const urls = prepareUrls(protocol, HOST, port);
const config = configFactory("development")
const protocol = process.env.HTTPS === "true" ? "https" : "http"
const appName = require(paths.appPackageJson).name
const useTypeScript = fs.existsSync(paths.appTsConfig)
const urls = prepareUrls(protocol, HOST, port)
const devSocket = {
warnings: warnings =>
devServer.sockWrite(devServer.sockets, 'warnings', warnings),
errors: errors =>
devServer.sockWrite(devServer.sockets, 'errors', errors),
};
warnings: (warnings) =>
devServer.sockWrite(devServer.sockets, "warnings", warnings),
errors: (errors) =>
devServer.sockWrite(devServer.sockets, "errors", errors),
}
// Create a webpack compiler that is configured with custom messages.
const compiler = createCompiler({
appName,
......@@ -96,38 +95,38 @@ checkBrowsers(paths.appPath, isInteractive)
useYarn,
useTypeScript,
webpack,
});
})
// Load proxy config
const proxySetting = require(paths.appPackageJson).proxy;
const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
const proxySetting = require(paths.appPackageJson).proxy
const proxyConfig = prepareProxy(proxySetting, paths.appPublic)
// Serve webpack assets generated by the compiler over a web server.
const serverConfig = createDevServerConfig(
proxyConfig,
urls.lanUrlForConfig
);
const devServer = new WebpackDevServer(compiler, serverConfig);
)
const devServer = new WebpackDevServer(compiler, serverConfig)
// Launch WebpackDevServer.
devServer.listen(port, HOST, err => {
devServer.listen(port, HOST, (err) => {
if (err) {
return console.log(err);
return console.log(err)
}
if (isInteractive) {
clearConsole();
clearConsole()
}
console.log(chalk.cyan('Starting the development server...\n'));
openBrowser(urls.localUrlForBrowser);
});
console.log(chalk.cyan("Starting the development server...\n"))
openBrowser(urls.localUrlForBrowser)
})
['SIGINT', 'SIGTERM'].forEach(function(sig) {
process.on(sig, function() {
devServer.close();
process.exit();
});
});
;["SIGINT", "SIGTERM"].forEach(function (sig) {
process.on(sig, function () {
devServer.close()
process.exit()
})
})
.catch(err => {
})
.catch((err) => {
if (err && err.message) {
console.log(err.message);
console.log(err.message)
}
process.exit(1);
});
process.exit(1)
})
'use strict';
"use strict"
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'test';
process.env.NODE_ENV = 'test';
process.env.PUBLIC_URL = '';
process.env.BABEL_ENV = "test"
process.env.NODE_ENV = "test"
process.env.PUBLIC_URL = ""
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', err => {
throw err;
});
process.on("unhandledRejection", (err) => {
throw err
})
// Ensure environment variables are read.
require('../config/env');
require("../config/env")
const jest = require('jest');
const execSync = require('child_process').execSync;
let argv = process.argv.slice(2);
const jest = require("jest")
const execSync = require("child_process").execSync
let argv = process.argv.slice(2)
function isInGitRepository() {
try {
execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
return true;
execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" })
return true
} catch (e) {
return false;
return false
}
}
function isInMercurialRepository() {
try {
execSync('hg --cwd . root', { stdio: 'ignore' });
return true;
execSync("hg --cwd . root", { stdio: "ignore" })
return true
} catch (e) {
return false;
return false
}
}
......@@ -42,19 +41,18 @@ function isInMercurialRepository() {
// or explicitly running all tests
if (
!process.env.CI &&
argv.indexOf('--coverage') === -1 &&
argv.indexOf('--no-watch') === -1 &&
argv.indexOf('--watchAll') === -1
argv.indexOf("--coverage") === -1 &&
argv.indexOf("--no-watch") === -1 &&
argv.indexOf("--watchAll") === -1
) {
// https://github.com/facebook/create-react-app/issues/5210
const hasSourceControl = isInGitRepository() || isInMercurialRepository();
argv.push(hasSourceControl ? '--watch' : '--watchAll');
const hasSourceControl = isInGitRepository() || isInMercurialRepository()
argv.push(hasSourceControl ? "--watch" : "--watchAll")
}
// Jest doesn't have this option so we'll remove it
if (argv.indexOf('--no-watch') !== -1) {
argv = argv.filter(arg => arg !== '--no-watch');
if (argv.indexOf("--no-watch") !== -1) {
argv = argv.filter((arg) => arg !== "--no-watch")
}
jest.run(argv);
jest.run(argv)
import React, { PureComponent } from 'react';
import React, { PureComponent } from "react"
function setSize() {
document.body.style.height = `${window.innerHeight}px`
document.getElementById('root').style.height = `${window.innerHeight}px`
document.getElementById("root").style.height = `${window.innerHeight}px`
document.documentElement.style.height = `${window.innerHeight}px`
}
export default function (WrappedComponent) {
return class extends PureComponent {
componentDidMount() {
setSize()
window.addEventListener('resize', setSize)
window.addEventListener("resize", setSize)
}
componentWillUnmount() {
document.body.style.height = `auto`
document.getElementById('root').style.height = `auto`
document.documentElement.style.height = 'auto'
window.removeEventListener('resize', setSize)
document.getElementById("root").style.height = `auto`
document.documentElement.style.height = "auto"
window.removeEventListener("resize", setSize)
}
render() {
return (
<WrappedComponent {...this.props}/>
);
return <WrappedComponent {...this.props} />
}
}
}
import React, { PureComponent } from 'react'
import NavBar from 'src/common/NavBar'
import React, { PureComponent } from "react"
import NavBar from "src/common/NavBar"
export default function WithTab(WrappedComponent) {
return class extends PureComponent {
render() {
return (
<>
<WrappedComponent {...this.props}/>
<NavBar/>
<WrappedComponent {...this.props} />
<NavBar />
</>
)
}
......
export {default as WithTab} from './WithTab'
export {default as WithFullSize} from './WithFullSize'
\ No newline at end of file
export { default as WithTab } from "./WithTab"
export { default as WithFullSize } from "./WithFullSize"
......@@ -11,7 +11,7 @@ $main-color: #09f; // 主体颜色
// 字体
$font-family-zh: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;
$font-family-en: Arial, sans-serif !default;
// 盒子模型
......@@ -131,7 +131,7 @@ body {
padding-bottom: constant(safe-area-inset-bottom);
}
img{
img {
max-width: 100%;
}
......@@ -328,13 +328,13 @@ input[type="radio"]:checked:before {
height: 48px;
box-shadow: 0 0 3px #9a9a9a;
.label, .track, .button {
.label,
.track,
.button {
height: 48px;
}
}
}
}
.close {
......
......@@ -4,7 +4,7 @@
// 行内元素也可以使用 flex 布局
// .box-example { display: inline-flex; }
// 以下6个属性设置在容器上
// 以下 6 个属性设置在容器上
// 1. flex-direction --> 子项目排列的方向
// row 默认,水平从左到右
......@@ -31,7 +31,7 @@
// flex-end 交叉轴的终点对齐
// center 交叉轴的中点对齐
// baseline 子项目的第一行文字的基线对齐
// stretch 默认值,如果子项目未设置高度或设为auto,将占满整个容器的高度
// stretch 默认值,如果子项目未设置高度或设为 auto,将占满整个容器的高度
// 6. align-content 定义了多根轴线的对齐方式,如果子项目只有一根轴线,则该属性无效。
// flex-start 与交叉轴的起点对齐。
......@@ -41,28 +41,28 @@
// space-around 每根轴线两侧的间隔都相等,所以轴线之间的间隔比轴线与边框的间隔大一倍
// stretch 默认值,轴线占满整个交叉轴
// 以下6个属性设置在子项目上。
// 以下 6 个属性设置在子项目上。
// 1. order 定义子项目的排列顺序,数值越小,排位越靠前。默认值为0.
// 1. order 定义子项目的排列顺序,数值越小,排位越靠前。默认值为 0.
// 2. flex-grow 定义子项目放大比例,默认为0,即如果存在剩余空间,也不放大。
// 如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。
// 如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍
// 2. flex-grow 定义子项目放大比例,默认为 0,即如果存在剩余空间,也不放大。
// 如果所有项目的 flex-grow 属性都为 1,则它们将等分剩余空间(如果有的话)。
// 如果一个项目的 flex-grow 属性为 2,其他项目都为 1,则前者占据的剩余空间将比其他项多一倍
// 3. flex-shrink 定义了子项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
// 如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。
// 如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。
// 3. flex-shrink 定义了子项目的缩小比例,默认为 1,即如果空间不足,该项目将缩小。
// 如果所有项目的 flex-shrink 属性都为 1,当空间不足时,都将等比例缩小。
// 如果一个项目的 flex-shrink 属性为 0,其他项目都为 1,则空间不足时,前者不缩小。
// 4. flex-basis 属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。
// 浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
// 它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。
// 浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为 auto,即项目的本来大小。
// 它可以设为跟 width 或 height 属性一样的值(比如 350px),则项目将占据固定空间。
// 5. flex 该属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
// 5. flex 该属性是 flex-grow, flex-shrink 和 flex-basis 的简写,默认值为 0 1 auto。后两个属性可选。
// 该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)
// 建议优先使用这个 flex 属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
// align-self 允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。
// 默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch
// 该属性可能取6个值,除了 auto ,其他都与 align-items 属性完全一致。
// 该属性可能取 6 个值,除了 auto ,其他都与 align-items 属性完全一致。
// ------------------------------------------------------------
@mixin fontFamily($font){
font-family: $font, "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;;
@mixin fontFamily($font) {
font-family: $font, "Helvetica Neue", Helvetica, "PingFang SC",
"Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
}
......@@ -4,7 +4,7 @@
$active: #09f;
$white: #fff;
$black: #000;
$red: #FF2121;
$red: #ff2121;
$redprice: #ff3131;
$color_333: #333;
$color_555: #555;
......@@ -12,14 +12,13 @@ $color_666: #666;
$color_888: #888;
$color_999: #999;
$color_606: #606060;
$color_bbb: #BBB;
$color_bbb: #bbb;
$color_202426: #202426;
$color_4B4B4B: #4B4B4B;
$color_FE2F2F: #FE2F2F;
$color_FF4000: #FF4000;
$color_FF0000: #FF0000;
$color_525B65: #525B65;
$color_4B4B4B: #4b4b4b;
$color_FE2F2F: #fe2f2f;
$color_FF4000: #ff4000;
$color_FF0000: #ff0000;
$color_525B65: #525b65;
/*
* @ 文字大小
......@@ -35,48 +34,46 @@ $font_16: 16px;
$font_14: 14px;
$font_12: 12px;
/*
* @ 背景颜色
*/
$bg_active: #09f;
$bg_0078FF: #0078FF;
$bg_0080FF: #0080FF;
$bg_0078FF: #0078ff;
$bg_0080FF: #0080ff;
$bg_fff: #fff;
$bg_000: #000;
$bg_f4f4f4: #f4f4f4;
$bg_f5f5f5: #f5f5f5;
$bg_f7f9fc: #f7f9fc;
$bg_EBEFF5: #EBEFF5;
$bg_EBEFF5: #ebeff5;
$bg_ccc: #ccc;
$bg_333: #333;
$bg_666: #666;
$bg_999: #999;
$bg_82BBFB: #82BBFB;
$bg_EBC05A: #EBC05A;
$bg_EBA216: #EBA216;
$bg_82BBFB: #82bbfb;
$bg_EBC05A: #ebc05a;
$bg_EBA216: #eba216;
$bg_ff9898: #ff9898;
$bg_ff3131: #ff3131;
$bg_FFF8EB: #FFF8EB;
$bg_FFE400: #FFE400;
$bg_FFA200: #FFA200;
$bg_FE2F2F: #FE2F2F;
$bg_FADD29: #FADD29;
$bg_E7E7E7: #E7E7E7;
$bg_18B4ED: #18B4ED;
$bg_FF4000: #FF4000;
$bg_FD7700: #FD7700;
$bg_FCCD05: #FCCD05;
$bg_FF9500: #FF9500;
$bg_077FD0: #077FD0;
$bg_0198FE: #0198FE;
$bg_F4AAA7: #F4AAA7;
$bg_E02E24: #E02E24;
$bg_007FD0: #007FD0;
$bg_FF0000: #FF0000;
$bg_FFF4CE: #FFF4CE;
$bg_FAFAFA: #FAFAFA;
$bg_FFF8EB: #fff8eb;
$bg_FFE400: #ffe400;
$bg_FFA200: #ffa200;
$bg_FE2F2F: #fe2f2f;
$bg_FADD29: #fadd29;
$bg_E7E7E7: #e7e7e7;
$bg_18B4ED: #18b4ed;
$bg_FF4000: #ff4000;
$bg_FD7700: #fd7700;
$bg_FCCD05: #fccd05;
$bg_FF9500: #ff9500;
$bg_077FD0: #077fd0;
$bg_0198FE: #0198fe;
$bg_F4AAA7: #f4aaa7;
$bg_E02E24: #e02e24;
$bg_007FD0: #007fd0;
$bg_FF0000: #ff0000;
$bg_FFF4CE: #fff4ce;
$bg_FAFAFA: #fafafa;
/*
* @ 分割线颜色
......@@ -84,17 +81,15 @@ $bg_FAFAFA: #FAFAFA;
$sp_ddd: #ddd;
$sp_e7eaf1: #e7eaf1;
/*
* @ 边框颜色
*/
$border_ddd: #ddd;
$border_e7eaf1: #E7EAF1;
$border_e7eaf1: #e7eaf1;
$border_f31: #f31;
$border_ccc: #ccc;
/*
* @ 标签颜色
*/
$E0B97B: #E0B97B;
\ No newline at end of file
$E0B97B: #e0b97b;
This source diff could not be displayed because it is too large. You can view the blob instead.
module.exports = function() {
module.exports = function () {
return {
"@brand-primary": 'green',
"@color-text-base": '#333'
"@brand-primary": "green",
"@color-text-base": "#333",
}
}
import React, { Component } from 'react';
import CallApp from 'callapp-lib'
import React, { Component } from "react"
import CallApp from "callapp-lib"
const options = {
scheme: {
protocol: 'julyedu',
host: '',
port: ''
protocol: "julyedu",
host: "",
port: "",
},
intent: {
package: "com.julyapp.julyonline",
scheme: "julyedu",
action: 'julyapp.julyedu',
category: 'category_julyedu'
action: "julyapp.julyedu",
category: "category_julyedu",
},
universal: {
host: "api.julyedu.com/action",
pathKey: 'page'
pathKey: "page",
},
appstore: "https://itunes.apple.com/cn/app/id1102275343?mt=8",
yingyongbao: "http://android.myapp.com/myapp/detail.htm?apkName=com.julyapp.julyonline",
fallback: "http://android.myapp.com/myapp/detail.htm?apkName=com.julyapp.julyonline"
yingyongbao:
"http://android.myapp.com/myapp/detail.htm?apkName=com.julyapp.julyonline",
fallback:
"http://android.myapp.com/myapp/detail.htm?apkName=com.julyapp.julyonline",
}
class OpenApp extends Component {
callApp = new CallApp(options)
// callApp = null
static defaultProps = {
text: '在APP打开'
text: "在APP打开",
}
handleClick = () => {
this.callApp.open({
path: '',
param: {
},
path: "",
param: {},
callback: () => {
window.location.href = "http://android.myapp.com/myapp/detail.htm?apkName=com.julyapp.julyonline";
}
});
window.location.href =
"http://android.myapp.com/myapp/detail.htm?apkName=com.julyapp.julyonline"
},
})
}
render() {
return (
<div className={this.props.className} onClick={this.handleClick}>{this.props.text}</div>
);
<div className={this.props.className} onClick={this.handleClick}>
{this.props.text}
</div>
)
}
}
export default OpenApp;
export default OpenApp
import React, { Component } from 'react';
import './index.scss'
import React, { Component } from "react"
import "./index.scss"
import { initCaptchaNC } from "src/utils"
const appkey = 'FFFF0N000000000090FC'
const scene = 'nc_login_h5'
const appkey = "FFFF0N000000000090FC"
const scene = "nc_login_h5"
class CaptchaAli extends Component {
nc = null
el = null
state = {
isLoaded: false
isLoaded: false,
}
componentDidMount() {
const _this = this
this.el && initCaptchaNC(() => {
const nc_token = [appkey, (new Date()).getTime(), Math.random()].join(':');
this.el &&
initCaptchaNC(() => {
const nc_token = [appkey, new Date().getTime(), Math.random()].join(":")
this.nc = NoCaptcha.init({
renderTo: '#nc',
renderTo: "#nc",
appkey,
scene,
token: nc_token,
elementID: ['tel'],
elementID: ["tel"],
bannerHidden: false,
callback(data) {
_this.props.onVerify({
......@@ -29,27 +30,27 @@ class CaptchaAli extends Component {
scene,
token: nc_token,
session_id: data.csessionid,
sig: data.sig
sig: data.sig,
})
},
error(s) {
console.log(s)
}
},
})
NoCaptcha.setEnabled(true);
NoCaptcha.setEnabled(true)
this.nc.reset()
this.props.getInstance(this.nc)
})
}
render() {
const {mb = 30} = this.props
const { mb = 30 } = this.props
return (
<div id={'captcha'} style={{marginBottom: `${mb}px`}}>
<div id="nc" ref={el => this.el = el}></div>
<div id={"captcha"} style={{ marginBottom: `${mb}px` }}>
<div id="nc" ref={(el) => (this.el = el)}></div>
</div>
);
)
}
}
export default CaptchaAli;
\ No newline at end of file
export default CaptchaAli
import React, { Component } from 'react';
import { initCaptcha } from 'src/utils';
import { BarLoader } from 'react-spinners';
import './index.scss';
const CAPTCHAID = '6b0f5f6c8f334f3693ee754ba5692e36'
import React, { Component } from "react"
import { initCaptcha } from "src/utils"
import { BarLoader } from "react-spinners"
import "./index.scss"
const CAPTCHAID = "6b0f5f6c8f334f3693ee754ba5692e36"
class Captcha extends Component {
state = {
isReady: false
isReady: false,
}
componentDidMount() {
const {getInstance, handleError, onVerify} = this.props;
const _this = this;
const el = document.getElementById('captcha');
el && initCaptcha(function () {
initNECaptcha({
const { getInstance, handleError, onVerify } = this.props
const _this = this
const el = document.getElementById("captcha")
el &&
initCaptcha(function () {
initNECaptcha(
{
element: el,
captchaId: CAPTCHAID,
mode: 'float',
width: 'auto',
mode: "float",
width: "auto",
onReady: function (instance) {
// 验证码一切准备就绪,此时可正常使用验证码的相关功能
_this.setState({
isReady: true
});
isReady: true,
})
},
onVerify: function (err, data) {
onVerify(err,data)
}
onVerify(err, data)
},
instance => {
},
(instance) => {
getInstance && getInstance(instance)
},
err => {
(err) => {
handleError && handleError(err)
}
)
......@@ -47,24 +47,23 @@ class Captcha extends Component {
<div
className="captcha-container"
style={{
'marginBottom': this.props.mrBtm
marginBottom: this.props.mrBtm,
}}
>
{
!this.state.isReady &&
{!this.state.isReady && (
<div className="captcha-animation">
<BarLoader />
</div>
}
)}
<div
id={'captcha'}
id={"captcha"}
style={{
'marginBottom': this.props.mrBtm
marginBottom: this.props.mrBtm,
}}
/>
</div>
);
)
}
}
export default Captcha;
\ No newline at end of file
export default Captcha
import React from 'react'
import './index.scss'
import React from "react"
import "./index.scss"
const Tag = (props) => {
return (
<span className={`state ${props.className}`}>
{props.children}
</span>
)
return <span className={`state ${props.className}`}>{props.children}</span>
}
export default Tag
import React, { Component } from 'react';
import './clearable-input.scss'
import classnames from 'classnames'
import React, { Component } from "react"
import "./clearable-input.scss"
import classnames from "classnames"
class ClearableInput extends Component {
render() {
let {
value,
name,
wrapperClass,
inputClass,
type = 'text',
type = "text",
icon,
setFieldValue,
...rest
} = this.props
let clearIconStyle = {
display: value && value.length ? 'block' : 'none'
display: value && value.length ? "block" : "none",
}
return (
<div className={classnames('clearable-input-wrapper', wrapperClass)}>
<div className={classnames("clearable-input-wrapper", wrapperClass)}>
<input
type={type}
value={value}
......@@ -29,15 +28,15 @@ class ClearableInput extends Component {
/>
{icon}
<i
className={'iconfont icondanseshixintubiao-3 clear'}
className={"iconfont icondanseshixintubiao-3 clear"}
onClick={() => {
setFieldValue(name,'')
setFieldValue(name, "")
}}
style={clearIconStyle}
/>
</div>
);
)
}
}
export default ClearableInput;
\ No newline at end of file
export default ClearableInput
......@@ -11,7 +11,7 @@
border-radius: 4px;
vertical-align: bottom;
}
.course-status{
.course-status {
width: 100%;
height: 24px;
position: absolute;
......@@ -21,8 +21,8 @@
line-height: 24px;
color: $white;
font-size: 13px;
background-color: #E02E24;
opacity: .6;
background-color: #e02e24;
opacity: 0.6;
}
.course-title {
......
import React from 'react'
import './course.scss'
import {Link} from "react-router-dom"
import React from "react"
import "./course.scss"
import { Link } from "react-router-dom"
const Course = (props) => {
return (
......@@ -8,15 +8,14 @@ const Course = (props) => {
{props.top}
<a onClick={() => props.toDetail(props.id)}>
{/* <Link to={`/detail?id=${props.id}`}> */}
<img src={props.img} alt=""/>
<img src={props.img} alt="" />
{props.status}
<p className={`course-title ${props.className}`}>{props.title}</p>
{/* </Link> */}
</a>
{props.bottom}
</li>
);
};
export default Course;
)
}
export default Course
import React, {Component} from 'react'
import './index.scss';
import {withRouter} from 'react-router-dom'
import {browser,getParam} from "src/utils";
import React, { Component } from "react"
import "./index.scss"
import { withRouter } from "react-router-dom"
import { browser, getParam } from "src/utils"
class HeaderBar extends Component {
constructor(props) {
super(props);
super(props)
}
goBack = () => {
const {state, hash} = this.props.location
if(hash.includes('goback')){
const { state, hash } = this.props.location
if (hash.includes("goback")) {
return window.history.go(-1)
}
if(browser.isWeixin && getParam('code') && getParam('state')){
if (browser.isWeixin && getParam("code") && getParam("state")) {
window.history.go(-2)
}
if(state.records && state.records.length > 1){
window.history.go(-1);
}else if(state.from && state.from.pathname) {
if (state.records && state.records.length > 1) {
window.history.go(-1)
} else if (state.from && state.from.pathname) {
location.replace(`${state.from.pathname}${state.from.search}`)
}else{
} else {
window.location.href = window.location.origin
}
}
toLink = () => {
const { toHref } = this.props;
const { toHref } = this.props
// console.log(toHref);
location.replace(toHref)
}
goShop = () => {
this.props.history.push('/shopcart')
this.props.history.push("/shopcart")
}
render() {
const { toHref, home } = this.props;
const { toHref, home } = this.props
return (
<div className="detail-header" style={{...this.props.style}}>
{
!toHref && this.props.arrow &&
<i className='iconfont iconiconfront-68' onClick={this.props.goBack || this.goBack}></i>
}
{
toHref && typeof toHref === 'function' &&
<i className='iconfont iconiconfront-68' onClick={toHref}></i>
}
{
toHref && typeof toHref === 'string' &&
<i className='iconfont iconiconfront-68' onClick={this.toLink}></i>
}
<span className='herder'>{this.props.title}</span>
{
this.props.cart &&
<i className='iconfont icongouwuche-xianxing' onClick={this.goShop}></i>
}
{
this.props.delete &&
<i className='iconfont iconiconfront-56' onClick={this.props.toDelete}></i>
}
{
home &&
<i className="iconfont iconshouye-xianxing"></i>
}
<div className="detail-header" style={{ ...this.props.style }}>
{!toHref && this.props.arrow && (
<i
className="iconfont iconiconfront-68"
onClick={this.props.goBack || this.goBack}
></i>
)}
{toHref && typeof toHref === "function" && (
<i className="iconfont iconiconfront-68" onClick={toHref}></i>
)}
{toHref && typeof toHref === "string" && (
<i className="iconfont iconiconfront-68" onClick={this.toLink}></i>
)}
<span className="herder">{this.props.title}</span>
{this.props.cart && (
<i
className="iconfont icongouwuche-xianxing"
onClick={this.goShop}
></i>
)}
{this.props.delete && (
<i
className="iconfont iconiconfront-56"
onClick={this.props.toDelete}
></i>
)}
{home && <i className="iconfont iconshouye-xianxing"></i>}
</div>
);
)
}
};
}
export default withRouter(HeaderBar);
export default withRouter(HeaderBar)
......@@ -18,7 +18,6 @@
float: right;
}
.herder {
font-size: 16px;
color: $color_202426;
......
import React, {Component} from 'react'
import {SearchBar} from 'antd-mobile'
import './index.scss'
import React, { Component } from "react"
import { SearchBar } from "antd-mobile"
import "./index.scss"
class HeaderBar extends Component {
toSearch() {
window.location.href = '/search';
window.location.href = "/search"
}
return() {
window.location.href = '/';
window.location.href = "/"
}
goShop = () => {
const { isLogin = false } = this.props;
let url = isLogin? '/shopcart' : '/passport';
window.location.replace(url);
const { isLogin = false } = this.props
let url = isLogin ? "/shopcart" : "/passport"
window.location.replace(url)
}
render() {
return (
<div className='preferential'>
<div className="preferential">
<div className="search-nav">
{
!this.props.toHref &&
{!this.props.toHref && (
<i
className={'iconfont iconiconfront-68 return'}
className={"iconfont iconiconfront-68 return"}
onClick={this.return.bind(this)}
/>
}
{
this.props.toHref &&
)}
{this.props.toHref && (
<i
className={'iconfont iconiconfront-68 return'}
className={"iconfont iconiconfront-68 return"}
onClick={this.props.toHref}
/>
}
)}
<SearchBar
placeholder="搜索课程"
cancelText={" "}
......@@ -42,14 +40,13 @@ class HeaderBar extends Component {
showCancelButton={false}
/>
<i
className={'iconfont icongouwuche-xianxing shopping-cart'}
className={"iconfont icongouwuche-xianxing shopping-cart"}
onClick={this.goShop}
/>
</div>
</div>
)
}
}
export default HeaderBar;
export default HeaderBar
......@@ -12,7 +12,9 @@
background-color: $bg_f7f9fc;
}
.am-search-input, .am-search-synthetic-ph, .am-search-value {
.am-search-input,
.am-search-synthetic-ph,
.am-search-value {
text-align: left;
padding-left: 15px;
height: 26px;
......@@ -24,7 +26,8 @@
border-radius: 13px;
}
.shopping-cart, .return {
.shopping-cart,
.return {
font-size: 20px;
}
}
import React, { Component } from 'react';
import ReactDOM from 'react-dom'
import { HashLoader } from "react-spinners";
import './loading.scss'
import React, { Component } from "react"
import ReactDOM from "react-dom"
import { HashLoader } from "react-spinners"
import "./loading.scss"
const container = document.body
class Loading extends Component {
static defaultProps = {
text: '加载中',
fake: 0
text: "加载中",
fake: 0,
}
state = {
isLoading: true
isLoading: true,
}
componentDidMount() {
if(!this.props.isLoading){
if (!this.props.isLoading) {
this.setState({
isLoading: false
isLoading: false,
})
}
}
componentDidUpdate(prevProps) {
let {isLoading, fake} = this.props
let { isLoading, fake } = this.props
if (!isLoading) {
if(fake){
if (fake) {
setTimeout(() => {
this.setState({
isLoading
isLoading,
})
}, fake)
}else {
if(prevProps.isLoading) {
this.setState(()=>({
isLoading: false
} else {
if (prevProps.isLoading) {
this.setState(() => ({
isLoading: false,
}))
}
}
}else{
if(prevProps.isLoading !== isLoading) {
this.setState(()=>({
isLoading: true
} else {
if (prevProps.isLoading !== isLoading) {
this.setState(() => ({
isLoading: true,
}))
}
}
}
render() {
const innerLoading =
const innerLoading = (
<div className="loading">
<div className="loading-wrapper">
<HashLoader
css={{
display: 'block',
marginTop: '-100px'
display: "block",
marginTop: "-100px",
}}
size={50}
color={'#09f'}
color={"#09f"}
/>
<p>{this.props.text}</p>
</div>
</div>
)
return (
this.state.isLoading ? ReactDOM.createPortal(innerLoading, container) : this.props.children
);
return this.state.isLoading
? ReactDOM.createPortal(innerLoading, container)
: this.props.children
}
}
export default Loading;
\ No newline at end of file
export default Loading
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import classnames from 'classnames';
import './index.scss';
import React, { Component } from "react"
import ReactDOM from "react-dom"
import classnames from "classnames"
import "./index.scss"
const Root = document.querySelector('body');
const events = ['touchmove', 'mousewheel'];
const Root = document.querySelector("body")
const events = ["touchmove", "mousewheel"]
class Mask extends Component {
constructor(props) {
super(props);
if(!this.el) {
this.el = document.createElement('div');
super(props)
if (!this.el) {
this.el = document.createElement("div")
}
}
componentDidMount() {
events.forEach(item => {
events.forEach((item) => {
this.el.addEventListener(item, this.preventEvent, {
passive: false
passive: false,
})
})
Root.appendChild(this.el);
Root.appendChild(this.el)
}
componentWillUnmount() {
Root.removeChild(this.el);
Root.removeChild(this.el)
}
preventEvent = e => {
e.preventDefault();
preventEvent = (e) => {
e.preventDefault()
}
render() {
const { visible, handleToHide, className } = this.props;
if(visible) {
const { visible, handleToHide, className } = this.props
if (visible) {
return ReactDOM.createPortal(
(
<div className="mask">
<div className={classnames("mask-content", className)}>
{this.props.children}
......@@ -44,14 +42,13 @@ class Mask extends Component {
<div className="mask-footer">
<i className="mask-button__close" onClick={handleToHide}></i>
</div>
</div>
),
</div>,
this.el
);
}else {
return null;
)
} else {
return null
}
}
}
export default Mask;
\ No newline at end of file
export default Mask
......@@ -8,8 +8,8 @@
left: 0;
width: 100%;
height: 100%;
color:#fff;
background-color: rgba(0, 0, 0, .5);
color: #fff;
background-color: rgba(0, 0, 0, 0.5);
z-index: 999;
}
......@@ -31,5 +31,5 @@
width: 33px;
height: 33px;
background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/close-btn.png');
background-image: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/close-btn.png");
}
import React from 'react';
import { NavLink, withRouter } from 'react-router-dom'
import './index.scss'
import React from "react"
import { NavLink, withRouter } from "react-router-dom"
import "./index.scss"
const navLinkConfig = [
{
to: '/',
to: "/",
exact: true,
icon: 'index-icon',
activeIcon: 'index-icon-active',
text: '首页'
icon: "index-icon",
activeIcon: "index-icon-active",
text: "首页",
},
{
to: '/classify',
to: "/classify",
exact: false,
icon: 'classify-icon',
activeIcon: 'classify-icon-active',
text: '分类'
icon: "classify-icon",
activeIcon: "classify-icon-active",
text: "分类",
},
{
to: '/study',
to: "/study",
exact: false,
icon: 'study-icon',
activeIcon: 'study-icon-active',
text: '学习'
icon: "study-icon",
activeIcon: "study-icon-active",
text: "学习",
},
{
to: '/my',
to: "/my",
exact: false,
icon: 'my-icon',
activeIcon: 'my-icon-active',
text: '我的'
}
icon: "my-icon",
activeIcon: "my-icon-active",
text: "我的",
},
]
const NavBar = React.memo(({location}) => {
const NavBar = React.memo(({ location }) => {
return (
<div className="nav-bar">
{
navLinkConfig.map(item => {
let {icon, text, activeIcon, ...rest} = item
{navLinkConfig.map((item) => {
let { icon, text, activeIcon, ...rest } = item
return (
<NavLink
activeClassName={'active'}
className={'nav-item'}
activeClassName={"active"}
className={"nav-item"}
key={icon}
{...rest}
>
<i className={`icon ${item.to.length > 1 ? location.pathname.startsWith(item.to) ? activeIcon : icon : location.pathname === item.to ? activeIcon : icon}`}/>
<i
className={`icon ${
item.to.length > 1
? location.pathname.startsWith(item.to)
? activeIcon
: icon
: location.pathname === item.to
? activeIcon
: icon
}`}
/>
<span>{text}</span>
</NavLink>
)
})
}
<div className={'click-able'}></div>
})}
<div className={"click-able"}></div>
</div>
)
})
......
......@@ -78,7 +78,3 @@
background-image: linear-gradient(0deg, #ddd 50%, transparent 50%);
}
}
import React from 'react';
import './orderlist.scss';
import {Link} from "react-router-dom";
import React from "react"
import "./orderlist.scss"
import { Link } from "react-router-dom"
/**
* @OrderList 组件内容
......@@ -13,30 +12,33 @@ import {Link} from "react-router-dom";
* @constructor
*/
const OrderItem = ({ info, tab, children, src,id, isaist, toDetail, ...restProps }) => {
const OrderItem = ({
info,
tab,
children,
src,
id,
isaist,
toDetail,
...restProps
}) => {
return (
<div className='public-list-item'>
<div className="public-list-item">
<div className="public-content">
{tab}
<div className="public-cover" >
<div className="public-cover">
{/* <Link to={`/detail?id=${id}`}> */}
<img src={src} alt="" onClick={() => toDetail(id)} />
{/* </Link> */}
{
(isaist &&
<span className='return_cash'></span>
)
}
{isaist && <span className="return_cash"></span>}
</div>
{info}
</div>
{React.Children.map(
children,
child => (child ? React.cloneElement(child, {}) : child)
{React.Children.map(children, (child) =>
child ? React.cloneElement(child, {}) : child
)}
</div>
)
}
export default OrderItem;
\ No newline at end of file
export default OrderItem
......@@ -38,7 +38,6 @@
background: url("./image/return.icon.png") no-repeat;
background-size: 100% 100%;
}
}
.order-info {
......
import React, { PureComponent } from 'react'
import './tag.scss'
import React, { PureComponent } from "react"
import "./tag.scss"
export default class Tag extends PureComponent {
render() {
return (
......
.tagLately, .tagHot {
.tagLately,
.tagHot {
display: block;
max-width: 100%;
overflow: hidden;
......@@ -8,7 +9,7 @@
padding: 4px 10px;
border-radius: 14px;
float: left;
background-color: #F5F5F5;
background-color: #f5f5f5;
line-height: 20px;
color: #666;
}
......
import React, {Component} from 'react'
import './index.scss'
import {http} from 'src/utils'
import React, { Component } from "react"
import "./index.scss"
import { http } from "src/utils"
class UserGift extends Component {
state = {
user_gift: ''
user_gift: "",
}
componentDidMount() {
http.get(`${API['base-api']}/web/home/popup`).then((res) => {
const {errno, data} = res.data
http.get(`${API["base-api"]}/web/home/popup`).then((res) => {
const { errno, data } = res.data
if (errno === 200) {
this.setState({
user_gift: data.new_user_gift.prize_img
user_gift: data.new_user_gift.prize_img,
})
}
})
......@@ -26,14 +26,17 @@ class UserGift extends Component {
}
render() {
const {user_gift} = this.state
const { user_gift } = this.state
return (
<div className={'user-gift-popup'}>
<div className={'user-gift-bgimg'}>
<img onClick={this.get_newerModal} src={user_gift} alt=""/>
<img className={'close_gift_box'}
<div className={"user-gift-popup"}>
<div className={"user-gift-bgimg"}>
<img onClick={this.get_newerModal} src={user_gift} alt="" />
<img
className={"close_gift_box"}
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/tinypng-common/close_icon.png"
onClick={this.close} alt=""/>
onClick={this.close}
alt=""
/>
</div>
</div>
)
......
.user-gift-popup {
background: rgba(0, 0, 0, .3);
background: rgba(0, 0, 0, 0.3);
position: fixed;
left: 0;
top: 0;
......
import React from 'react';
import './index.scss'
import React from "react"
import "./index.scss"
const VList = (props) => {
return (
<li
className='v-list-item'
className="v-list-item"
onClick={() => {
typeof props.toDetail === 'function' && props.toDetail(props.id)
typeof props.toDetail === "function" && props.toDetail(props.id)
}}
>
<div className="content">
<div className="cover">
{props.status}
{props.courseExpire}
{props.toDetail
? (<img src={props.img} alt=""/>)
: (<img src={props.img} alt=""/>)
}
{props.toDetail ? (
<img src={props.img} alt="" />
) : (
<img src={props.img} alt="" />
)}
</div>
{props.info}
</div>
{props.tab}
</li>
);
};
)
}
export default VList;
\ No newline at end of file
export default VList
......@@ -31,7 +31,5 @@
color: $white;
font-size: 13px;
}
}
}
import React, {Component} from 'react'
import './index.scss'
import React, { Component } from "react"
import "./index.scss"
class WxLogin extends Component {
constructor(props) {
......@@ -9,14 +9,17 @@ class WxLogin extends Component {
// 提示微信登录还是账号登录,微信授权登录不需要绑定手机号
wxLogin = () => {
let url = window.location.href
if (url.includes('code=') && url.includes('state=STATE')) {
let index = url.lastIndexOf('code=')
if (url.includes("code=") && url.includes("state=STATE")) {
let index = url.lastIndexOf("code=")
url = url.substr(0, index - 1)
}
window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx23dac6775ac82877&redirect_uri=" + encodeURIComponent(url + "&aa=bb").toLowerCase() + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"
window.location.href =
"https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx23dac6775ac82877&redirect_uri=" +
encodeURIComponent(url + "&aa=bb").toLowerCase() +
"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"
}
zhLogin = () => {
this.props.history.push('/passport')
this.props.history.push("/passport")
}
render() {
......@@ -24,11 +27,17 @@ class WxLogin extends Component {
<div className="change-login-type">
<div className="login-type-content">
<div className="wx-login" onClick={this.wxLogin}>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/mlCourse/m/wx-icon.png" alt=""/>
<img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/mlCourse/m/wx-icon.png"
alt=""
/>
<span>微信登录</span>
</div>
<div className="zh-login" onClick={this.zhLogin}>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/mlCourse/m/zh-icon.png" alt=""/>
<img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/mlCourse/m/zh-icon.png"
alt=""
/>
<span>账号登录</span>
</div>
</div>
......
.change-login-type {
background: rgba(0, 0, 0, .5);
background: rgba(0, 0, 0, 0.5);
position: fixed;
left: 0;
top: 0;
......@@ -22,7 +22,8 @@
justify-content: space-between;
}
.wx-login, .zh-login {
.wx-login,
.zh-login {
text-align: center;
img {
width: 34px;
......@@ -31,7 +32,7 @@
span {
display: block;
color: #525C65;
color: #525c65;
font-size: 14px;
margin-top: 3px;
}
......
import React from 'react'
import Address from "./index";
import {text, boolean, withKnobs} from '@storybook/addon-knobs'
import {action} from '@storybook/addon-actions'
import React from "react"
import Address from "./index"
import { text, boolean, withKnobs } from "@storybook/addon-knobs"
import { action } from "@storybook/addon-actions"
export default {
title: 'address',
title: "address",
component: Address,
decorators: [withKnobs]
decorators: [withKnobs],
}
let visible = true,
title = '收货地址',
subtitle = '获奖用户(以最终榜单为准)请及时填写收货信息',
address = '金域国际中心',
phone = '1331234123',
name = '某某某'
title = "收货地址",
subtitle = "获奖用户(以最终榜单为准)请及时填写收货信息",
address = "金域国际中心",
phone = "1331234123",
name = "某某某"
export const Default = () => {
visible = boolean('visible', visible)
name = text('name', name)
phone = text('phone', phone)
address = text('address', address)
title = text('title(optional)', title)
subtitle = text('subtitle(optional)', subtitle)
visible = boolean("visible", visible)
name = text("name", name)
phone = text("phone", phone)
address = text("address", address)
title = text("title(optional)", title)
subtitle = text("subtitle(optional)", subtitle)
return <Address visible={visible}
return (
<Address
visible={visible}
subtitle={subtitle}
title={title}
name={name}
phone={phone}
address={address}
onClose={action('onClose')}
validate={() => ({name: '姓名'})}
onClose={action("onClose")}
validate={() => ({ name: "姓名" })}
onError={(errors) => {
console.log(errors);}}
console.log(errors)
}}
onSubmit={(values, formikHelpers) => {
console.log(formikHelpers);
console.log(formikHelpers)
}}
/>
)
}
......@@ -12,14 +12,14 @@
.title {
margin-bottom: 8px;
color: #525C65;
color: #525c65;
font-size: 16px;
}
.subtitle {
margin-bottom: 15px;
font-size: 13px;
color: #ED6A1D;
color: #ed6a1d;
text-align: left;
}
......@@ -27,13 +27,13 @@
width: 250px;
height: 40px;
line-height: 40px;
border: 1px solid #DDD;
border: 1px solid #ddd;
font-size: 13px;
color: #999;
outline: 0;
-webkit-appearance: none;
&:nth-child(n+2) {
&:nth-child(n + 2) {
margin-top: 10px;
}
......@@ -55,7 +55,7 @@
border: 0;
}
.close{
.close {
position: absolute;
left: 50%;
bottom: -56px;
......
import React, {Component} from 'react'
import './index.scss'
import MaskCover from "../cover";
import {Formik, Form, Field, FormikHelpers, FormikErrors} from "formik";
import React, { Component } from "react"
import "./index.scss"
import MaskCover from "../cover"
import { Formik, Form, Field, FormikHelpers, FormikErrors } from "formik"
interface PersonalInfo {
name: string
......@@ -15,46 +15,61 @@ interface Props extends PersonalInfo {
onClose: () => void
visible: boolean
validate: () => void
onSubmit: (values: PersonalInfo, formikHelpers: FormikHelpers<PersonalInfo>) => void
onSubmit: (
values: PersonalInfo,
formikHelpers: FormikHelpers<PersonalInfo>
) => void
onError: (errors: FormikErrors<PersonalInfo>) => void
}
const Address: React.FC<Props> = ({name, phone, address, title, subtitle, visible, onClose, validate, onSubmit, onError}) => {
return (
visible ?
const Address: React.FC<Props> = ({
name,
phone,
address,
title,
subtitle,
visible,
onClose,
validate,
onSubmit,
onError,
}) => {
return visible ? (
<MaskCover>
<div className="common-address-container">
<div className="title">{title}</div>
<div className="subtitle">{subtitle}</div>
<Formik initialValues={{name, phone, address}}
<Formik
initialValues={{ name, phone, address }}
enableReinitialize={true}
onSubmit={onSubmit}
validate={validate}
>
{
(props) => {
{(props) => {
if (props.errors) {
onError(props.errors)
}
return <Form className={'form'}>
<Field placeholder={'姓名'} name='name'></Field>
<Field placeholder={'手机号'} name='phone'></Field>
<Field placeholder={'地址'} name='address'></Field>
<button type={'submit'} className={'submit'}>提交</button>
return (
<Form className={"form"}>
<Field placeholder={"姓名"} name="name"></Field>
<Field placeholder={"手机号"} name="phone"></Field>
<Field placeholder={"地址"} name="address"></Field>
<button type={"submit"} className={"submit"}>
提交
</button>
</Form>
}
}
)
}}
</Formik>
<i className={'iconfont iconiconfront-2 close'} onClick={onClose}></i>
<i className={"iconfont iconiconfront-2 close"} onClick={onClose}></i>
</div>
</MaskCover>
: null
)
) : null
}
Address.defaultProps = {
title: '收货信息',
subtitle: '获奖用户(以最终榜单为准)请及时填写收货信息'
title: "收货信息",
subtitle: "获奖用户(以最终榜单为准)请及时填写收货信息",
}
export default Address
import React, { Component } from 'react';
import { http } from 'src/utils';
import { Formik, Form, Field } from 'formik';
import { Toast } from "antd-mobile";
import './index.scss';
import React, { Component } from "react"
import { http } from "src/utils"
import { Formik, Form, Field } from "formik"
import { Toast } from "antd-mobile"
import "./index.scss"
class AddressPopup extends Component {
constructor(props) {
......@@ -10,22 +10,22 @@ class AddressPopup extends Component {
this.state = {
isLoading: false,
addressInfo: {
name: '',
phone: '',
address: '',
name: "",
phone: "",
address: "",
},
}
}
componentDidMount() {
this.fetchUserAddress();
this.fetchUserAddress()
}
// 获取收货信息
fetchUserAddress = () => {
const {addressInfo} = this.state;
http.get(`${API.home}/sys/user_address_info`).then(res => {
const {code, data, msg} = res.data;
const { addressInfo } = this.state
http.get(`${API.home}/sys/user_address_info`).then((res) => {
const { code, data, msg } = res.data
if (code === 200) {
this.setState({
addressInfo: Object.assign({}, addressInfo, {
......@@ -34,77 +34,78 @@ class AddressPopup extends Component {
address: data.address,
}),
isLoading: true,
});
})
}
});
})
}
handleToSubmit = (params = {}) => {
const {successBindAddress} = this.props;
http.post(`${API.home}/sys/update_address`, {
act_type: 'treasure',
const { successBindAddress } = this.props
http
.post(`${API.home}/sys/update_address`, {
act_type: "treasure",
...params,
}).then(res => {
const {code, msg} = res.data;
})
.then((res) => {
const { code, msg } = res.data
if (code === 200) {
successBindAddress();
successBindAddress()
} else {
Toast.info(msg, 2, null, false);
Toast.info(msg, 2, null, false)
}
});
})
}
render() {
const {isLoading, addressInfo} = this.state;
const {tip, prize, skip = 'default'} = this.props;
const { isLoading, addressInfo } = this.state
const { tip, prize, skip = "default" } = this.props
return (
<>
{
isLoading &&
{isLoading && (
<Formik
initialValues={{
...addressInfo,
}}
validate={({name, phone, address}) => {
const errors = {};
validate={({ name, phone, address }) => {
const errors = {}
if (!name) {
errors.name = '请输入收件人';
errors.name = "请输入收件人"
}
if (!/^1[3-9]\d{9}$/.test(phone)) {
errors.phone = '请填写正确格式的手机号';
errors.phone = "请填写正确格式的手机号"
}
if (!address) {
errors.address = '请输入收货地址';
errors.address = "请输入收货地址"
}
return errors;
return errors
}}
validateOnBlur={false}
validateOnChange={false}
onSubmit={(values) => {
this.handleToSubmit(values);
this.handleToSubmit(values)
}}
>
{
({errors}) => (
{({ errors }) => (
<Form className="address-form" data-skip={skip}>
<h2 className="address-form__title">收货信息</h2>
{
prize ? (
<p className='address__prize'>
{prize ? (
<p className="address__prize">
您抽中了
<span style={{'color': '#FF4000'}}>{prize}</span>
<span style={{ color: "#FF4000" }}>{prize}</span>
</p>
) : (null)
}
{
tip ? (<div className="address-form__subtitle">{tip}</div>) : (
<p className="address-form__desc">请及时填写收货信息,获得实物奖品后将第一时间为您邮寄</p>)
}
) : null}
{tip ? (
<div className="address-form__subtitle">{tip}</div>
) : (
<p className="address-form__desc">
请及时填写收货信息,获得实物奖品后将第一时间为您邮寄
</p>
)}
<Field
name="name"
render={({field}) => (
render={({ field }) => (
<div className="address-form__item">
<input
{...field}
......@@ -112,16 +113,15 @@ class AddressPopup extends Component {
type="text"
placeholder="收件人"
/>
{
errors.name &&
{errors.name && (
<p className="address-form__tip">{errors.name}</p>
}
)}
</div>
)}
/>
<Field
name="phone"
render={({field}) => (
render={({ field }) => (
<div className="address-form__item">
<input
{...field}
......@@ -129,16 +129,15 @@ class AddressPopup extends Component {
type="text"
placeholder="联系方式"
/>
{
errors.phone &&
{errors.phone && (
<p className="address-form__tip">{errors.phone}</p>
}
)}
</div>
)}
/>
<Field
name="address"
render={({field}) => (
render={({ field }) => (
<div className="address-form__item">
<input
{...field}
......@@ -146,10 +145,9 @@ class AddressPopup extends Component {
type="text"
placeholder="收货地址"
/>
{
errors.address &&
{errors.address && (
<p className="address-form__tip">{errors.address}</p>
}
)}
</div>
)}
/>
......@@ -157,16 +155,16 @@ class AddressPopup extends Component {
className="address-form__submit"
data-status="do"
type="submit"
>提交
>
提交
</button>
</Form>
)
}
)}
</Formik>
}
)}
</>
);
)
}
}
export default AddressPopup;
\ No newline at end of file
export default AddressPopup
// 地址弹窗
[data-skip="default"] {
.address-form__item {
width: 250px;
}
......@@ -15,13 +14,12 @@
background-color: rgba(82, 92, 101, 0.3);
&[data-status="do"] {
background-color: #0099FF;
background-color: #0099ff;
}
}
}
[data-skip="year"] {
.address-form__title {
margin: 10px 0 0;
font-size: 18px;
......@@ -50,7 +48,7 @@
border: 1px solid #090909;
border-radius: 5px;
color: #090909;
background-color: #FFE319;
background-color: #ffe319;
}
}
......
......@@ -14,7 +14,7 @@
}
.popup-form__button--num {
border: 1px solid #99D6FF;
border: 1px solid #99d6ff;
border-right-style: none;
border-radius: 6px 0 0 6px;
}
......@@ -31,7 +31,7 @@
}
.popup-form__ipt {
border: 1px solid #99D6FF;
border: 1px solid #99d6ff;
border-radius: 6px;
&[data-type="tel"] {
......@@ -56,7 +56,7 @@
}
.popup-form__button--num {
border: 1px solid #CDCDCD;
border: 1px solid #cdcdcd;
border-right-style: none;
border-radius: 3px 0 0 3px;
}
......@@ -74,7 +74,7 @@
}
.popup-form__ipt {
border: 1px solid #CDCDCD;
border: 1px solid #cdcdcd;
border-radius: 3px;
&[data-type="tel"] {
......@@ -117,11 +117,11 @@
.button {
width: 40px;
height: 40px;
.icon{
.icon {
left: 5px;
}
}
.bg-green{
.bg-green {
height: 40px;
line-height: 40px;
}
......@@ -162,7 +162,7 @@
&::after {
display: block;
content: '';
content: "";
position: absolute;
top: 0;
right: 0;
......@@ -170,7 +170,7 @@
width: 1px;
height: 14px;
margin: auto 0;
background-color: #AAAAAA;
background-color: #aaaaaa;
}
.iconfont {
......@@ -196,11 +196,11 @@
.popup-form__tip {
margin: 0;
font-size: 12px;
color: #FF3131;
color: #ff3131;
.iconfont {
font-size: 15px;
color: #FF3131;
color: #ff3131;
}
}
......@@ -208,7 +208,7 @@
width: 110px;
height: 36px;
padding: 0;
border: 1px solid #E5E5E5;
border: 1px solid #e5e5e5;
box-sizing: border-box;
font-size: 13px;
color: #999;
......@@ -216,9 +216,9 @@
line-height: 36px;
background-color: transparent;
&[data-status='do'] {
border-color: #0099FF;
color: #0099FF;
&[data-status="do"] {
border-color: #0099ff;
color: #0099ff;
}
}
......@@ -227,17 +227,17 @@
padding: 0;
margin: 0 auto;
border-style: none;
color: #2B2B2B;
background-color: #F9DB4A;
color: #2b2b2b;
background-color: #f9db4a;
cursor: pointer;
&[data-status="done"] {
color: #fff;
background-color: #ABABAB;
background-color: #ababab;
}
&[data-status='do'] {
&[data-status="do"] {
color: #fff;
background-color: #0099FF;
background-color: #0099ff;
}
}
......@@ -19,7 +19,7 @@
.title {
font-size: 16px;
color: #525C65;
color: #525c65;
text-align: center;
}
......
import React from 'react'
import ReactDOM from 'react-dom'
import './index.scss'
import classnames from 'classnames'
import React from "react"
import ReactDOM from "react-dom"
import "./index.scss"
import classnames from "classnames"
const re = /(https?|ftp):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/
......@@ -22,17 +22,12 @@ function ClosablePopup({
content,
className,
closable = true,
close = function () {
},
close = function () {},
clickMaskClose = true,
closeIcon = 'iconiconfront-2',
afterClose = function () {
},
remove = function () {
}
closeIcon = "iconiconfront-2",
afterClose = function () {},
remove = function () {},
}: Props) {
function unmountComponent() {
ReactDOM.unmountComponentAtNode(div)
if (div && div.parentNode) {
......@@ -64,30 +59,32 @@ function ClosablePopup({
}
const closablePopup = (
<div className={'closable-popup-mask'} onClick={clickMask}>
<div className={classnames(['popup-container', className])}>
<div className={"closable-popup-mask"} onClick={clickMask}>
<div className={classnames(["popup-container", className])}>
<div className="title">{title}</div>
<div className="content">
{content}
</div>
{
closable &&
(re.test(closeIcon)
? <img src={closeIcon} alt="" className={'close-icon'} onClick={_close} />
: <i className={`close iconfont ${closeIcon}`} onClick={_close} />)
}
<div className="content">{content}</div>
{closable &&
(re.test(closeIcon) ? (
<img
src={closeIcon}
alt=""
className={"close-icon"}
onClick={_close}
/>
) : (
<i className={`close iconfont ${closeIcon}`} onClick={_close} />
))}
</div>
</div>
)
const div = document.createElement('div')
const div = document.createElement("div")
document.body.appendChild(div)
ReactDOM.render(closablePopup, div)
return {
close: _close,
remove: unmountComponent
remove: unmountComponent,
}
}
......
import React, { Component } from 'react';
import { Toast } from 'antd-mobile';
import { http } from 'src/utils';
import './index.scss';
import React, { Component } from "react"
import { Toast } from "antd-mobile"
import { http } from "src/utils"
import "./index.scss"
class ConfirmPhone extends Component {
continueBindPhone = () => {
const { data, successBindPhone } = this.props;
http.post(
`${API.home}/sys/v2/user/bindMobile`,
{
const { data, successBindPhone } = this.props
http
.post(`${API.home}/sys/v2/user/bindMobile`, {
...data,
type: 1, // 1:绑定,2:修改绑定
is_valid: 0, // is_valid 是否验证 1:验证(默认),0不验证
})
.then((res) => {
const { code, msg } = res.data
if (code === 200) {
successBindPhone()
} else {
Toast.info(msg, 2, null, false)
}
).then(res => {
const { code, msg } = res.data;
if(code === 200 ) {
successBindPhone();
}else {
Toast.info(msg, 2, null, false);
}
});
})
}
render() {
const {
bindInfo = { },
desc,
skip = 'year',
handleToCancle
} = this.props;
const { bindInfo = {}, desc, skip = "year", handleToCancle } = this.props
return (
<div className="popup-bind" data-skip={skip}>
<h2 className="popup-bind__title">绑定手机号</h2>
{
desc
? <div className="popup-bind__desc">{desc}</div>
: <p className="popup-bind__desc">该手机号已绑定到以下账号,继续绑定将解除以下绑定状态</p>
}
{desc ? (
<div className="popup-bind__desc">{desc}</div>
) : (
<p className="popup-bind__desc">
该手机号已绑定到以下账号,继续绑定将解除以下绑定状态
</p>
)}
<ul className="popup-bind__list">
{
bindInfo['email'] &&
{bindInfo["email"] && (
<li className="popup-bind__account">
{/* 邮箱 */}
<i className="popup-bind__icon" data-plat="mail"></i>
<p className="popup-bind__account--name">{bindInfo['email']}</p>
<p className="popup-bind__account--name">{bindInfo["email"]}</p>
</li>
}
{
bindInfo['wechat_nickname'] &&
)}
{bindInfo["wechat_nickname"] && (
<li className="popup-bind__account">
{/* wechat */}
<i className="popup-bind__icon" data-plat="wachat"></i>
<p className="popup-bind__account--name">{bindInfo['wechat_nickname']}</p>
<p className="popup-bind__account--name">
{bindInfo["wechat_nickname"]}
</p>
</li>
}
{
bindInfo['qq_nickname'] &&
)}
{bindInfo["qq_nickname"] && (
<li className="popup-bind__account">
{/* qq */}
<i className="popup-bind__icon" data-plat="qq"></i>
<p className="popup-bind__account--name">{bindInfo['qq_nickname']}</p>
<p className="popup-bind__account--name">
{bindInfo["qq_nickname"]}
</p>
</li>
}
{
bindInfo['sina_nickname'] &&
)}
{bindInfo["sina_nickname"] && (
<li className="popup-bind__account">
{/* 微博 */}
<i className="popup-bind__icon" data-plat="sina"></i>
<p className="popup-bind__account--name">{bindInfo['sina_nickname']}</p>
<p className="popup-bind__account--name">
{bindInfo["sina_nickname"]}
</p>
</li>
}
)}
</ul>
<div className="popup-bind__footer">
<button
className="popup-bind__button popup-bind__button--cancle"
onClick={handleToCancle}>取消</button>
onClick={handleToCancle}
>
取消
</button>
<button
className="popup-bind__button popup-bind__button--confirm"
onClick={this.continueBindPhone}>继续绑定</button>
onClick={this.continueBindPhone}
>
继续绑定
</button>
</div>
</div>
)
}
}
export default ConfirmPhone;
\ No newline at end of file
export default ConfirmPhone
......@@ -33,14 +33,14 @@
}
.popup-bind__button--cancle {
border: 1px solid #0099FF;
color: #0099FF;
border: 1px solid #0099ff;
color: #0099ff;
}
.popup-bind__button--confirm {
border-style: none;
color: #fff;
background-color: #0099FF;
background-color: #0099ff;
}
}
......@@ -56,7 +56,7 @@
.popup-bind__desc {
width: 269px;
font-size: 12px;
color: #FF2121;
color: #ff2121;
line-height: 18px;
}
......@@ -95,11 +95,10 @@
.popup-bind__button--confirm {
border: 1px solid #090909;
color: #090909;
background-color: #FFE319;
background-color: #ffe319;
}
}
.popup-bind {
text-align: center;
}
......@@ -119,8 +118,8 @@
margin: 0 52px;
text-align: left;
&:nth-child(n+2) {
border-top: 1px solid #E5E5E5;
&:nth-child(n + 2) {
border-top: 1px solid #e5e5e5;
}
}
......@@ -135,19 +134,19 @@
background-position: center;
&[data-plat="mail"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/icon-mail.png');
background-image: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/icon-mail.png");
}
&[data-plat="sina"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/icon-sina.png');
background-image: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/icon-sina.png");
}
&[data-plat="qq"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/icon-qq.png');
background-image: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/icon-qq.png");
}
&[data-plat="wachat"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/icon-wechat.png');
background-image: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/icon-wechat.png");
}
}
......
import React from 'react'
import './course-base.scss'
import React from "react"
import "./course-base.scss"
const Course = (props) => {
return (
<li className={`course-base-item ${props.className}`} onClick={props.handleClick.bind(this, props.id)}>
<li
className={`course-base-item ${props.className}`}
onClick={props.handleClick.bind(this, props.id)}
>
{props.top}
<img src={props.img} alt=""/>
<img src={props.img} alt="" />
<p className="course-title">{props.title}</p>
{props.bottom}
</li>
);
};
export default Course;
)
}
export default Course
import React, {ReactNode, ReactElement} from 'react';
import {handleNavigation, Navigation} from "../index";
import {RequireAtLeastOne} from 'src/utils/types'
import {History} from "history";
import './index.scss'
import React, { ReactNode, ReactElement } from "react"
import { handleNavigation, Navigation } from "../index"
import { RequireAtLeastOne } from "src/utils/types"
import { History } from "history"
import "./index.scss"
export interface CoursePropsBasic {
image: string
......@@ -19,34 +17,47 @@ export interface CoursePropsBasic {
marketing?: string
}
export type CourseProps = RequireAtLeastOne<CoursePropsBasic, 'history' | 'navigate'>
const CourseCardH: React.FC<CourseProps> = ({image, title, subtitle, status, navigate, courseId, tag, history, marketing}) => {
export type CourseProps = RequireAtLeastOne<
CoursePropsBasic,
"history" | "navigate"
>
const CourseCardH: React.FC<CourseProps> = ({
image,
title,
subtitle,
status,
navigate,
courseId,
tag,
history,
marketing,
}) => {
return (
<div className={'course-card course-card-h'} onClick={(e) => {
<div
className={"course-card course-card-h"}
onClick={(e) => {
if (navigate) {
handleNavigation({e, courseId, navigate})
handleNavigation({ e, courseId, navigate })
} else {
handleNavigation({e, courseId, history} as Navigation)
handleNavigation({ e, courseId, history } as Navigation)
}
}}>
}}
>
<div className="show">
<img src={image} alt={title}/>
<img src={image} alt={title} />
{marketing && <div className="marketing">{marketing}</div>}
{tag}
</div>
<div className="info">
<div className="title">{title}</div>
{subtitle && <div className="subtitle">{subtitle}</div>}
<div className="status">
{status}
<div className="status">{status}</div>
</div>
</div>
</div>
);
)
}
CourseCardH.displayName = 'CourseCardH'
CourseCardH.displayName = "CourseCardH"
export default CourseCardH;
\ No newline at end of file
export default CourseCardH
......@@ -20,11 +20,11 @@
.title {
margin-bottom: 30px;
font-size: 15px;
color: #525C65;
color: #525c65;
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
-webkit-line-clamp: 2;
@include fontFamily('PingFangSC-Regular');
@include fontFamily("PingFangSC-Regular");
}
}
import React from 'react'
import {CourseProps} from '../course-card-h'
import {handleNavigation, Navigation} from "../index";
import React from "react"
import { CourseProps } from "../course-card-h"
import { handleNavigation, Navigation } from "../index"
import './index.scss'
import "./index.scss"
const CourseCardV: React.FC<CourseProps> = ({title, image, courseId, status, tag, navigate, history, marketing}) => {
return <div className={'course-card-v'} onClick={(e) => {
navigate ? handleNavigation({e, courseId, navigate})
: handleNavigation({e, courseId, history} as Navigation)
}}>
const CourseCardV: React.FC<CourseProps> = ({
title,
image,
courseId,
status,
tag,
navigate,
history,
marketing,
}) => {
return (
<div
className={"course-card-v"}
onClick={(e) => {
navigate
? handleNavigation({ e, courseId, navigate })
: handleNavigation({ e, courseId, history } as Navigation)
}}
>
<div className="show">
<img src={image} alt={title}/>
<img src={image} alt={title} />
{marketing && <div className="marketing">{marketing}</div>}
{tag}
</div>
<div className="title">{title}</div>
<div className="status">{status}</div>
</div>
)
}
export default CourseCardV
import React from "react";
import {withKnobs, number, text} from "@storybook/addon-knobs";
import {action} from "@storybook/addon-actions";
import React from "react"
import { withKnobs, number, text } from "@storybook/addon-knobs"
import { action } from "@storybook/addon-actions"
import CourseCardH from "./course-card-h";
import CourseCardV from "./course-card-v";
import CourseCardH from "./course-card-h"
import CourseCardV from "./course-card-v"
export const courseData = {
courseId: 140,
title: '三月面试求职班',
subtitle: '搞定算法 直通BAT',
image: 'https://julyedu-img-public.oss-cn-beijing.aliyuncs.com/Public/Image/20a86c1353.jpg',
marketing: '拼团减100元'
title: "三月面试求职班",
subtitle: "搞定算法 直通BAT",
image:
"https://julyedu-img-public.oss-cn-beijing.aliyuncs.com/Public/Image/20a86c1353.jpg",
marketing: "拼团减100元",
}
export default {
title: 'course-card',
title: "course-card",
component: CourseCardH,
decorators: [withKnobs, (story: () => React.ReactElement) => <div className={'shadow'}>{story()}</div>],
excludeStories: /.*Data$/
decorators: [
withKnobs,
(story: () => React.ReactElement) => (
<div className={"shadow"}>{story()}</div>
),
],
excludeStories: /.*Data$/,
}
let {title, courseId, image, subtitle, marketing} = courseData
let { title, courseId, image, subtitle, marketing } = courseData
let navigate = action(`navigate to /detail?id=${courseId}`)
const status = <button className={'purchase'}>立即购买</button>
const status = <button className={"purchase"}>立即购买</button>
export const Default = () => {
title = text('title', title)
subtitle = text('subtitle', subtitle)
image = text('image', image)
courseId = number('courseId', courseId)
marketing = text('marketing', marketing)
return <CourseCardH title={title} status={status} courseId={courseId} subtitle={subtitle} image={image}
navigate={navigate} marketing={marketing}></CourseCardH>
title = text("title", title)
subtitle = text("subtitle", subtitle)
image = text("image", image)
courseId = number("courseId", courseId)
marketing = text("marketing", marketing)
return (
<CourseCardH
title={title}
status={status}
courseId={courseId}
subtitle={subtitle}
image={image}
navigate={navigate}
marketing={marketing}
></CourseCardH>
)
}
export const V = () => {
title = text('title', title)
image = text('image', image)
courseId = number('courseId', courseId)
return <CourseCardV image={image} courseId={courseId} status={status} title={title}
navigate={navigate} marketing={marketing}></CourseCardV>
title = text("title", title)
image = text("image", image)
courseId = number("courseId", courseId)
return (
<CourseCardV
image={image}
courseId={courseId}
status={status}
title={title}
navigate={navigate}
marketing={marketing}
></CourseCardV>
)
}
......@@ -6,7 +6,7 @@
height: 24px;
color: #fff;
font-size: 13px;
background: rgba(224, 46, 36, .6);
background: rgba(224, 46, 36, 0.6);
text-align: center;
line-height: 24px;
}
import React from "react";
import { History } from "history";
import { RequireAtLeastOne } from 'src/utils/types'
import CourseCardV from "./course-card-v";
import CourseCardH from "./course-card-h";
import React from "react"
import { History } from "history"
import { RequireAtLeastOne } from "src/utils/types"
import CourseCardV from "./course-card-v"
import CourseCardH from "./course-card-h"
interface BaseNavigation {
e: React.MouseEvent
......@@ -13,14 +12,24 @@ interface BaseNavigation {
history?: History
}
export type Navigation = RequireAtLeastOne<BaseNavigation, 'history' | 'navigate'>
export type Navigation = RequireAtLeastOne<
BaseNavigation,
"history" | "navigate"
>
export const handleNavigation: (navigationArgs: Navigation) => void = ({ e, courseId, navigate, history }) => {
const _n = navigate || function (courseId: number) {
export const handleNavigation: (navigationArgs: Navigation) => void = ({
e,
courseId,
navigate,
history,
}) => {
const _n =
navigate ||
function (courseId: number) {
history!.push(`/detail?id=${courseId}`)
}
let nodeName = (e.target as HTMLElement).nodeName.toLowerCase()
if (nodeName === 'a' || nodeName === 'button') {
if (nodeName === "a" || nodeName === "button") {
return
}
_n(courseId)
......
......@@ -4,6 +4,6 @@
right: 0;
bottom: 0;
left: 0;
background: rgba(0, 0, 0, .6);
background: rgba(0, 0, 0, 0.6);
z-index: 999;
}
import React from 'react';
import './index.scss'
import React from "react"
import "./index.scss"
const MaskCover:React.FC = ({children}) => {
return (
<div className={'mask-cover'}>
{children}
</div>
);
};
const MaskCover: React.FC = ({ children }) => {
return <div className={"mask-cover"}>{children}</div>
}
export default MaskCover;
\ No newline at end of file
export default MaskCover
import React from 'react'
import { Modal } from 'antd-mobile'
import './index.scss'
import React from "react"
import { Modal } from "antd-mobile"
import "./index.scss"
export default function ({
amount,
limit_amount,
onCancel = () => {
},
onConfirm
}) {
onCancel = () => {},
onConfirm,
}) {
const content = (
<>
<div className="end-expansion-alert-ques">
......@@ -20,8 +19,8 @@ export default function ({
</div>
</>
)
Modal.alert('温馨提示', content, [
{text: '再考虑下', onPress: onCancel, style: {color: '#333'}},
{text: '确定结束膨胀', onPress: onConfirm}
Modal.alert("温馨提示", content, [
{ text: "再考虑下", onPress: onCancel, style: { color: "#333" } },
{ text: "确定结束膨胀", onPress: onConfirm },
])
}
export { default as VList } from './VList'
export { default as Course } from './Course' // 课程状态(试听 正在直播)+封面+标题+ 详情
export { default as Tag } from './CategoryTag'
export { default as OrderItem } from './OrderList'
export { default as HeaderBar } from './HeaderBar'
export { default as CallApp } from './CallApp'
export { default as Captcha } from './Captcha'
export { default as CaptchaAli } from './Captcha-ali'
export { default as VList } from "./VList"
export { default as Course } from "./Course" // 课程状态(试听 正在直播)+封面+标题+ 详情
export { default as Tag } from "./CategoryTag"
export { default as OrderItem } from "./OrderList"
export { default as HeaderBar } from "./HeaderBar"
export { default as CallApp } from "./CallApp"
export { default as Captcha } from "./Captcha"
export { default as CaptchaAli } from "./Captcha-ali"
export { default as ClearableInput } from "./ClearableInput"
export { default as Loading } from './Loading'
export { default as RenderTabBar } from './renderTabBar'
export { default as Popup } from './closable-popup'
export { default as WxLogin } from './WxLogin'
export { default as UserGift } from './UserGift'
export { default as Loading } from "./Loading"
export { default as RenderTabBar } from "./renderTabBar"
export { default as Popup } from "./closable-popup"
export { default as WxLogin } from "./WxLogin"
export { default as UserGift } from "./UserGift"
$red: #FF2121;
$red: #ff2121;
$gray: #999;
.prices {
display: flex;
......
import React from "react";
import './index.scss'
import React from "react"
import "./index.scss"
interface Props {
current: number | string
origin: number | string
}
const Prices: React.FC<Props> = ({current, origin}) => {
return <div className="prices">
<span className="current"><span className={'sign'}>¥</span>{current}</span>
<span className='origin'>¥{origin}</span>
const Prices: React.FC<Props> = ({ current, origin }) => {
return (
<div className="prices">
<span className="current">
<span className={"sign"}>¥</span>
{current}
</span>
<span className="origin">¥{origin}</span>
</div>
)
}
export default Prices
import React from 'react'
import Prices from './index'
import {withKnobs, number} from '@storybook/addon-knobs'
import React from "react"
import Prices from "./index"
import { withKnobs, number } from "@storybook/addon-knobs"
export default {
title: 'prices',
title: "prices",
component: Prices,
decorators: [withKnobs, (story: () => React.ReactNode) => <div className={'shadow'} style={{width: '100px', padding: '10px'}}>{story()}</div>]
decorators: [
withKnobs,
(story: () => React.ReactNode) => (
<div className={"shadow"} style={{ width: "100px", padding: "10px" }}>
{story()}
</div>
),
],
}
export const Default = () => {
const current = number('current', 100)
const origin = number('origin', 1000)
const current = number("current", 100)
const origin = number("origin", 1000)
return <Prices current={current} origin={origin}></Prices>
}
import { Sticky } from 'react-sticky'
import { Sticky } from "react-sticky"
import { Tabs } from "antd-mobile"
import React from "react"
export default function RenderTabBar({topOffset = 0,zIndex = 1, ...rest}) {
export default function RenderTabBar({ topOffset = 0, zIndex = 1, ...rest }) {
return (
<Sticky topOffset={topOffset}>
{({style}) => <div style={{...style, zIndex}}>
<Tabs.DefaultTabBar {...rest}/>
</div>}
{({ style }) => (
<div style={{ ...style, zIndex }}>
<Tabs.DefaultTabBar {...rest} />
</div>
)}
</Sticky>
)
}
import React from 'react';
import './index.scss'
import React from "react"
import "./index.scss"
const VList = (props) => {
return (
<li className='v-list-base-item' onClick={props.handleClick.bind(this, props.id, props.item)}>
<li
className="v-list-base-item"
onClick={props.handleClick.bind(this, props.id, props.item)}
>
<div className="content">
<div className="cover">
{props.status}
<img src={props.img} alt=""/>
<img src={props.img} alt="" />
</div>
{props.info}
</div>
{props.tab}
</li>
);
};
)
}
export default VList;
export default VList
......@@ -31,7 +31,5 @@
color: $white;
font-size: 13px;
}
}
}
import React, { Component } from 'react';
import Swiper from 'swiper'
import './index.scss'
import 'swiper/dist/css/swiper.min.css'
import { Link } from "react-router-dom";
import React, { Component } from "react"
import Swiper from "swiper"
import "./index.scss"
import "swiper/dist/css/swiper.min.css"
import { Link } from "react-router-dom"
class Index extends Component {
container = null
......@@ -11,12 +10,12 @@ class Index extends Component {
componentDidMount() {
if (this.props.bannerList.length > 1) {
this.swiper = new Swiper('.swiper-container', {
direction: 'horizontal',
this.swiper = new Swiper(".swiper-container", {
direction: "horizontal",
loop: true,
spaceBetween: 12,
centeredSlides: true,
slidesPerView: 'auto',
slidesPerView: "auto",
loopedSlides: 3,
autoplay: true,
})
......@@ -27,45 +26,40 @@ class Index extends Component {
this.swiper && this.swiper.destroy()
}
render() {
const {bannerList} = this.props
const { bannerList } = this.props
return (
<div className={'index-banner-swiper'}>
<div className={'swiper-container'} ref={el => this.container = el}>
<div className={"index-banner-swiper"}>
<div className={"swiper-container"} ref={(el) => (this.container = el)}>
<ul className="swiper-wrapper">
{
bannerList && bannerList.length > 0 && bannerList.map((item, index) => {
{bannerList &&
bannerList.length > 0 &&
bannerList.map((item, index) => {
return (
<li className={'swiper-slide'} key={index}>
{
Number.isNaN(parseInt(item.jump_url)) ?
<li className={"swiper-slide"} key={index}>
{Number.isNaN(parseInt(item.jump_url)) ? (
<a href={item.jump_url} key={index}>
<img className="item" src={item.name} alt=""/>
</a> :
<img className="item" src={item.name} alt="" />
</a>
) : (
<Link
to={{
pathname: '/detail',
pathname: "/detail",
search: `?id=${item.jump_url}`,
}}
key={index}
>
<img
className="item"
src={item.name}
alt=""
/>
<img className="item" src={item.name} alt="" />
</Link>
}
)}
</li>
)
})
}
})}
</ul>
</div>
</div>
);
)
}
}
export default Index;
\ No newline at end of file
export default Index
.index-banner-swiper{
.index-banner-swiper {
.swiper {
&-container {
padding: 0 20px !important;
......@@ -8,7 +8,7 @@
width: 335px !important;
height: 168px !important;
transform: scale3d(1, 0.9, 1);
transition: transform .4s;
transition: transform 0.4s;
img {
width: 100% !important;
......
import React from 'react'
import { Link } from "react-router-dom";
import './index.scss'
import React from "react"
import { Link } from "react-router-dom"
import "./index.scss"
const AllCourseNavigation = React.memo(() => {
return <div className="all-course">
<Link to='/classify'>
return (
<div className="all-course">
<Link to="/classify">
<p>查看全部课程 &gt;&gt;</p>
<span>数学基础、数学结构、大数据实战、Python...</span>
</Link>
</div>
)
})
export default AllCourseNavigation
Object.defineProperty(exports, "__esModule", {
value: true
});
var DEFAULT = exports.DEFAULT = 'DEFAULT';
var ROLL = exports.ROLL = 'ROLL';
var CARD = exports.CARD = 'CARD';
console.log(DEFAULT,ROLL,CARD)
\ No newline at end of file
value: true,
})
var DEFAULT = (exports.DEFAULT = "DEFAULT")
var ROLL = (exports.ROLL = "ROLL")
var CARD = (exports.CARD = "CARD")
console.log(DEFAULT, ROLL, CARD)
import React from 'react'
import { Link, withRouter } from "react-router-dom";
import React from "react"
import { Link, withRouter } from "react-router-dom"
import { Course } from "src/common/index"
import './index.scss'
import "./index.scss"
// 课程模块儿公共组件
// 课程数量是奇数第一个课程需要横着展示沾满一行,课程数量是偶数一行显示两个
const HomeCourseList = function ({modules, history}) {
const toDetail = id => {
const HomeCourseList = function ({ modules, history }) {
const toDetail = (id) => {
history.push(`/detail?id=${id}`)
}
return modules.length > 0 && modules.map((module, i) => {
return <div key={i}>
<Module module={module}
toDetail={toDetail}
/>
<p className="borderTop"/>
return (
modules.length > 0 &&
modules.map((module, i) => {
return (
<div key={i}>
<Module module={module} toDetail={toDetail} />
<p className="borderTop" />
</div>
)
})
)
}
const Module = function CourseList({module, toDetail}) {
const Module = function CourseList({ module, toDetail }) {
let filterList = []
let isOdd = module.list.length % 2 === 0
if (module.name === '限时免费') {
if (module.name === "限时免费") {
filterList = module.list
} else {
// 数量为奇数时,第一个课程显示大图(如后台未上传,前台显示小图),课程数量为偶数时,均显示小图
......@@ -36,61 +36,72 @@ const Module = function CourseList({module, toDetail}) {
if (isOdd) {
filterList = module.list
} else {
filterList = module.list[0].course_img === module.list[0].course_img_small ? module.list : module.list.slice(1)
filterList =
module.list[0].course_img === module.list[0].course_img_small
? module.list
: module.list.slice(1)
}
}
return <div className='category home-course-list'>
return (
<div className="category home-course-list">
<h2 className="title">
{module.name}
{
module.name === '限时免费' && <span className={'hot'}>hot</span>
}
{module.name === "限时免费" && <span className={"hot"}>hot</span>}
</h2>
{
module.show_more === 1 &&
<Link className="more" to='/classify'>查看更多 &gt;</Link>
}
{
module.show_more === 2 ?
module.name === '限时免费'
? <Link className="more" to={'/free'}>查看更多 &gt;</Link>
: <Link className="more" to={module.more_page}>查看更多 &gt;</Link>
: null
}
{module.show_more === 1 && (
<Link className="more" to="/classify">
查看更多 &gt;
</Link>
)}
{module.show_more === 2 ? (
module.name === "限时免费" ? (
<Link className="more" to={"/free"}>
查看更多 &gt;
</Link>
) : (
<Link className="more" to={module.more_page}>
查看更多 &gt;
</Link>
)
) : null}
{/* <LazyLoad offset={50}> */}
<ul className='index-course-detail'>
{
module.name !== '限时免费' && !isOdd && module.list[0].course_img !== module.list[0].course_img_small &&
<div className="category-vip" onClick={() => toDetail(module.list[0].course_id)}>
<img src={module.list[0].course_img} alt=""/>
<ul className="index-course-detail">
{module.name !== "限时免费" &&
!isOdd &&
module.list[0].course_img !== module.list[0].course_img_small && (
<div
className="category-vip"
onClick={() => toDetail(module.list[0].course_id)}
>
<img src={module.list[0].course_img} alt="" />
</div>
}
{
filterList.map((item, index) => {
)}
{filterList.map((item, index) => {
const top = item.is_limit_free ? null : (
<div>
{item.is_audition === true &&
<span className='audition'><i className={'iconfont iconerji'}></i>试听</span>
}
{item.is_aist &&
<span className='return_bash'></span>
}
{item.is_audition === true && (
<span className="audition">
<i className={"iconfont iconerji"}></i>试
</span>
)}
{item.is_aist && <span className="return_bash"></span>}
</div>
)
const bottom = <Bottom course={item}/>
const bottom = <Bottom course={item} />
const status = item.is_limit_free ? null : <div>
{item.is_bargain &&
<p className='course-status'>砍价减{item.bargain_price}</p>
}
{item.is_groupon &&
<p className='course-status'>拼团价{item.groupon_price}</p>
}
const status = item.is_limit_free ? null : (
<div>
{item.is_bargain && (
<p className="course-status">砍价减{item.bargain_price}</p>
)}
{item.is_groupon && (
<p className="course-status">拼团价{item.groupon_price}</p>
)}
</div>
)
return (
<Course
key={index}
......@@ -102,18 +113,18 @@ const Module = function CourseList({module, toDetail}) {
title={item.course_title}
id={item.course_id}
toDetail={toDetail}
className='text-overflow-2'
className="text-overflow-2"
/>
)
})
}
})}
</ul>
{/* </LazyLoad> */}
</div>
)
}
//限时免费
function LimitFree({course}) {
function LimitFree({ course }) {
/*
*
* limit_free_status: 0-未领取 1-已领取 2-已过期
......@@ -121,37 +132,43 @@ function LimitFree({course}) {
* */
switch (course.limit_free_status) {
case 0:
return <Link to={`/detail?id=${course.course_id}`}>
<p className={'course-price'}>
<span className={'free'}>免费领取</span>
<span className={'old'}>¥{course.price}</span>
return (
<Link to={`/detail?id=${course.course_id}`}>
<p className={"course-price"}>
<span className={"free"}>免费领取</span>
<span className={"old"}>¥{course.price}</span>
</p>
</Link>
)
case 1:
return <div className={'isbuy'}>已领取</div>
return <div className={"isbuy"}>已领取</div>
default:
return <p className="course-price">
return (
<p className="course-price">
<span className="new">¥{course.discounts_price}</span>
<span className="old">¥{course.price}</span>
</p>
)
}
}
//课程底部
function Bottom({course}) {
function Bottom({ course }) {
if (course.is_buy) {
if (course.is_limit_free && course.limit_free_status === 1) {
return <div class={'isbuy'}>已领取</div>
return <div class={"isbuy"}>已领取</div>
} else {
return <div className={'isbuy'}>已购买</div>
return <div className={"isbuy"}>已购买</div>
}
} else {
return course.is_limit_free
? <LimitFree course={course}/>
: <p className="course-price">
return course.is_limit_free ? (
<LimitFree course={course} />
) : (
<p className="course-price">
<span className="new">¥{course.discounts_price}</span>
<span className="old">¥{course.price}</span>
</p>
)
}
}
......
......@@ -27,7 +27,7 @@
}
.more {
color:rgba(81,91,101,.8);
color: rgba(81, 91, 101, 0.8);
font-size: 12px;
float: right;
}
......@@ -69,7 +69,6 @@
background-size: 100% 100%;
}
.course-price {
margin-top: 10px;
......@@ -118,7 +117,6 @@
}
}
.limit-free {
padding: 0 15px;
color: #333;
......@@ -176,13 +174,15 @@
}
}
$red: #FF2121;
$red: #ff2121;
.bottom span:nth-child(1), .bottom button:nth-child(1) {
.bottom span:nth-child(1),
.bottom button:nth-child(1) {
margin-right: 6px;
}
.current-price, .free {
.current-price,
.free {
color: $red;
font-size: 15px;
}
......@@ -200,11 +200,9 @@
border: 0;
}
}
}
.borderTop {
width: 100%;
height: 8px;
background-color: #F3F4F8;
background-color: #f3f4f8;
}
Object.defineProperty(exports, "__esModule", {
value: true
});
value: true,
})
var _animateTypes = require('./animateTypes');
var _animateTypes = require("./animateTypes")
var animateTypess = _interopRequireWildcard(_animateTypes);
var animateTypess = _interopRequireWildcard(_animateTypes)
var clientWidth = exports.clientWidth = document.documentElement.clientWidth || document.body.clientWidth;
var clientWidth = (exports.clientWidth =
document.documentElement.clientWidth || document.body.clientWidth)
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj
} else {
var newObj = {}
if (obj != null) {
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key))
newObj[key] = obj[key]
}
}
newObj.default = obj
return newObj
}
}
exports.default = function (animateTypes, stage, progress, duration) {
switch (animateTypes) {
case animateTypess.CARD:
switch (stage) {
case 'pre':
case "pre":
return {
width: '90%',
left: '20px',
transform: 'translateX(' + -(clientWidth * 0.92 + progress) + 'px) scaleY(' + (0.92 + Math.abs(progress / (clientWidth * 0.92) * 0.2)) + ')',
transitionDuration: duration + 's',
zIndex: 2
};
case 'active':
width: "90%",
left: "20px",
transform:
"translateX(" +
-(clientWidth * 0.92 + progress) +
"px) scaleY(" +
(0.92 + Math.abs((progress / (clientWidth * 0.92)) * 0.2)) +
")",
transitionDuration: duration + "s",
zIndex: 2,
}
case "active":
return {
width: '90%',
left: '20px',
transform: 'translateX(' + -progress + 'px) scaleY(' + (1 - Math.abs(progress / (clientWidth * 0.85) * 0.2)) + ')',
transitionDuration: duration + 's',
zIndex: 3
};
case 'next':
width: "90%",
left: "20px",
transform:
"translateX(" +
-progress +
"px) scaleY(" +
(1 - Math.abs((progress / (clientWidth * 0.85)) * 0.2)) +
")",
transitionDuration: duration + "s",
zIndex: 3,
}
case "next":
return {
width: '90%',
left: '20px',
transform: 'translateX(' + (clientWidth * 0.92 - progress) + 'px) scaleY(' + (0.92 + Math.abs(progress / (clientWidth * 0.92) * 0.2)) + ')',
width: "90%",
left: "20px",
transform:
"translateX(" +
(clientWidth * 0.92 - progress) +
"px) scaleY(" +
(0.92 + Math.abs((progress / (clientWidth * 0.92)) * 0.2)) +
")",
transitionDuration: duration + "s",
zIndex: 1
};
case 'prePro':
zIndex: 1,
}
case "prePro":
return {
width: '90%',
left: '20px',
transform: 'translateX(' + (-(clientWidth * 1.7) - progress) + 'px) scaleY(' + (1 - Math.abs(progress / (clientWidth * 0.92) * 0.2)) + ')',
width: "90%",
left: "20px",
transform:
"translateX(" +
(-(clientWidth * 1.7) - progress) +
"px) scaleY(" +
(1 - Math.abs((progress / (clientWidth * 0.92)) * 0.2)) +
")",
transitionDuration: duration + "s",
zIndex: 1
};
case 'nextPro':
zIndex: 1,
}
case "nextPro":
return {
width: '90%',
left: '20px',
transform: 'translateX(' + (clientWidth * 1.7 - progress) + 'px) scaleY(' + (1 - Math.abs(progress / (clientWidth * 0.92) * 0.2)) + ')',
width: "90%",
left: "20px",
transform:
"translateX(" +
(clientWidth * 1.7 - progress) +
"px) scaleY(" +
(1 - Math.abs((progress / (clientWidth * 0.92)) * 0.2)) +
")",
transitionDuration: duration + "s",
zIndex: 1
};
default: break;
zIndex: 1,
}
default:
break
}
break;
default: break;
break
default:
break
}
};
\ No newline at end of file
}
import React, {Component} from 'react'
import './index.scss'
import {http} from 'src/utils'
import React, { Component } from "react"
import "./index.scss"
import { http } from "src/utils"
import { Link } from "react-router-dom"
import {Toast} from "antd-mobile";
import { Toast } from "antd-mobile"
class ExpandActiveToast extends Component {
constructor(props) {
super(props);
super(props)
this.state = {
expandLength: 0,
isShowExpand:true
isShowExpand: true,
}
}
componentDidMount() {
http.get(`${API['base-api']}/sys/deposit/notice`).then((res) => {
http.get(`${API["base-api"]}/sys/deposit/notice`).then((res) => {
if (res.data.errno == 200) {
const {data} = res.data
const { data } = res.data
this.setState({
expandLength: data.num
expandLength: data.num,
})
} else {
Toast.info(res.data.msg, 2)
}
})
}
cleseExpand = () => {
this.setState({isShowExpand: false})
this.setState({ isShowExpand: false })
}
render() {
return (
<div>
{
this.state.expandLength > 0 && this.state.isShowExpand &&
{this.state.expandLength > 0 && this.state.isShowExpand && (
<div className="expand-active-toast">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/guanggao.png" alt=''/>
<img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/guanggao.png"
alt=""
/>
<div className="expand-toast-swiper">
<p>您有<span className="red">{this.state.expandLength}</span>待支付尾款的课程 再不支付就要过期了!</p>
<p>
您有<span className="red">{this.state.expandLength}</span>
待支付尾款的课程 再不支付就要过期了!
</p>
</div>
<Link to='/final-deposit-order?source=1'>查看</Link>
<Link to="/final-deposit-order?source=1">查看</Link>
<img
onClick={e => this.cleseExpand()}
onClick={(e) => this.cleseExpand()}
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/guanbi.png"
alt=''
alt=""
/>
</div>
}
)}
</div>
);
)
}
}
export default ExpandActiveToast
......@@ -43,7 +43,6 @@
text-align: center;
}
@-webkit-keyframes scollLeft {
from {
right: -100%;
......
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