Commit 4a33873b by zhanghaozhe

prettier

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