panhui 6 tahun lalu
induk
melakukan
a7328d0fa6
50 mengubah file dengan 3202 tambahan dan 0 penghapusan
  1. 12 0
      .babelrc
  2. 9 0
      .editorconfig
  3. 14 0
      .gitignore
  4. 10 0
      .postcssrc.js
  5. 41 0
      build/build.js
  6. 54 0
      build/check-versions.js
  7. TEMPAT SAMPAH
      build/logo.png
  8. 101 0
      build/utils.js
  9. 22 0
      build/vue-loader.conf.js
  10. 82 0
      build/webpack.base.conf.js
  11. 95 0
      build/webpack.dev.conf.js
  12. 145 0
      build/webpack.prod.conf.js
  13. 7 0
      config/dev.env.js
  14. 69 0
      config/index.js
  15. 4 0
      config/prod.env.js
  16. 15 0
      index.html
  17. 69 0
      package.json
  18. 141 0
      src/App.vue
  19. TEMPAT SAMPAH
      src/assets/home_icon_jifen.png
  20. TEMPAT SAMPAH
      src/assets/icon_choujiang.png
  21. TEMPAT SAMPAH
      src/assets/icon_dibuchoujiang.png
  22. TEMPAT SAMPAH
      src/assets/icon_renwu.png
  23. TEMPAT SAMPAH
      src/assets/icon_success.png
  24. TEMPAT SAMPAH
      src/assets/icon_warning.png
  25. TEMPAT SAMPAH
      src/assets/icon_wode.png
  26. TEMPAT SAMPAH
      src/assets/img_choujiaozhuanpan.png
  27. 5 0
      src/assets/去除文件名中.bat
  28. 36 0
      src/components/Modal/index.js
  29. 137 0
      src/components/Modal/main.vue
  30. 58 0
      src/components/progressbar.vue
  31. 6 0
      src/main.css
  32. 129 0
      src/main.js
  33. 27 0
      src/pages/Home.vue
  34. 104 0
      src/pages/Index.vue
  35. 48 0
      src/router/index.js
  36. 3 0
      src/styles/base/mobile.less
  37. 37 0
      src/styles/base/setArrow.less
  38. 21 0
      src/styles/base/setChecked.less
  39. 51 0
      src/styles/base/setOnepx.less
  40. 24 0
      src/styles/base/text.less
  41. 1150 0
      src/styles/component.css
  42. 54 0
      src/styles/data-table.less
  43. 266 0
      src/styles/default.css
  44. 7 0
      src/styles/fn.less
  45. 1 0
      src/styles/normalize.css
  46. 52 0
      src/styles/reset.less
  47. 21 0
      src/styles/sub-tab.less
  48. 43 0
      src/styles/tab.less
  49. 32 0
      src/vuex/index.js
  50. 0 0
      static/.gitkeep

+ 12 - 0
.babelrc

@@ -0,0 +1,12 @@
+{
+  "presets": [
+    ["env", {
+      "modules": false,
+      "targets": {
+        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
+      }
+    }],
+    "stage-2"
+  ],
+  "plugins": ["transform-vue-jsx", "transform-runtime"]
+}

+ 9 - 0
.editorconfig

@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true

+ 14 - 0
.gitignore

@@ -0,0 +1,14 @@
+.DS_Store
+node_modules/
+/dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln

+ 10 - 0
.postcssrc.js

@@ -0,0 +1,10 @@
+// https://github.com/michael-ciniawsky/postcss-load-config
+
+module.exports = {
+  "plugins": {
+    "postcss-import": {},
+    "postcss-url": {},
+    // to edit target browsers: use "browserslist" field in package.json
+    "autoprefixer": {}
+  }
+}

+ 41 - 0
build/build.js

@@ -0,0 +1,41 @@
+'use strict'
+require('./check-versions')()
+
+process.env.NODE_ENV = 'production'
+
+const ora = require('ora')
+const rm = require('rimraf')
+const path = require('path')
+const chalk = require('chalk')
+const webpack = require('webpack')
+const config = require('../config')
+const webpackConfig = require('./webpack.prod.conf')
+
+const spinner = ora('building for production...')
+spinner.start()
+
+rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
+  if (err) throw err
+  webpack(webpackConfig, (err, stats) => {
+    spinner.stop()
+    if (err) throw err
+    process.stdout.write(stats.toString({
+      colors: true,
+      modules: false,
+      children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
+      chunks: false,
+      chunkModules: false
+    }) + '\n\n')
+
+    if (stats.hasErrors()) {
+      console.log(chalk.red('  Build failed with errors.\n'))
+      process.exit(1)
+    }
+
+    console.log(chalk.cyan('  Build complete.\n'))
+    console.log(chalk.yellow(
+      '  Tip: built files are meant to be served over an HTTP server.\n' +
+      '  Opening index.html over file:// won\'t work.\n'
+    ))
+  })
+})

+ 54 - 0
build/check-versions.js

@@ -0,0 +1,54 @@
+'use strict'
+const chalk = require('chalk')
+const semver = require('semver')
+const packageConfig = require('../package.json')
+const shell = require('shelljs')
+
+function exec (cmd) {
+  return require('child_process').execSync(cmd).toString().trim()
+}
+
+const versionRequirements = [
+  {
+    name: 'node',
+    currentVersion: semver.clean(process.version),
+    versionRequirement: packageConfig.engines.node
+  }
+]
+
+if (shell.which('npm')) {
+  versionRequirements.push({
+    name: 'npm',
+    currentVersion: exec('npm --version'),
+    versionRequirement: packageConfig.engines.npm
+  })
+}
+
+module.exports = function () {
+  const warnings = []
+
+  for (let i = 0; i < versionRequirements.length; i++) {
+    const mod = versionRequirements[i]
+
+    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
+      warnings.push(mod.name + ': ' +
+        chalk.red(mod.currentVersion) + ' should be ' +
+        chalk.green(mod.versionRequirement)
+      )
+    }
+  }
+
+  if (warnings.length) {
+    console.log('')
+    console.log(chalk.yellow('To use this template, you must update following to modules:'))
+    console.log()
+
+    for (let i = 0; i < warnings.length; i++) {
+      const warning = warnings[i]
+      console.log('  ' + warning)
+    }
+
+    console.log()
+    process.exit(1)
+  }
+}

TEMPAT SAMPAH
build/logo.png


+ 101 - 0
build/utils.js

@@ -0,0 +1,101 @@
+'use strict'
+const path = require('path')
+const config = require('../config')
+const ExtractTextPlugin = require('extract-text-webpack-plugin')
+const packageConfig = require('../package.json')
+
+exports.assetsPath = function (_path) {
+  const assetsSubDirectory = process.env.NODE_ENV === 'production'
+    ? config.build.assetsSubDirectory
+    : config.dev.assetsSubDirectory
+
+  return path.posix.join(assetsSubDirectory, _path)
+}
+
+exports.cssLoaders = function (options) {
+  options = options || {}
+
+  const cssLoader = {
+    loader: 'css-loader',
+    options: {
+      sourceMap: options.sourceMap
+    }
+  }
+
+  const postcssLoader = {
+    loader: 'postcss-loader',
+    options: {
+      sourceMap: options.sourceMap
+    }
+  }
+
+  // generate loader string to be used with extract text plugin
+  function generateLoaders (loader, loaderOptions) {
+    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
+
+    if (loader) {
+      loaders.push({
+        loader: loader + '-loader',
+        options: Object.assign({}, loaderOptions, {
+          sourceMap: options.sourceMap
+        })
+      })
+    }
+
+    // Extract CSS when that option is specified
+    // (which is the case during production build)
+    if (options.extract) {
+      return ExtractTextPlugin.extract({
+        use: loaders,
+        fallback: 'vue-style-loader'
+      })
+    } else {
+      return ['vue-style-loader'].concat(loaders)
+    }
+  }
+
+  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
+  return {
+    css: generateLoaders(),
+    postcss: generateLoaders(),
+    less: generateLoaders('less'),
+    sass: generateLoaders('sass', { indentedSyntax: true }),
+    scss: generateLoaders('sass'),
+    stylus: generateLoaders('stylus'),
+    styl: generateLoaders('stylus')
+  }
+}
+
+// Generate loaders for standalone style files (outside of .vue)
+exports.styleLoaders = function (options) {
+  const output = []
+  const loaders = exports.cssLoaders(options)
+
+  for (const extension in loaders) {
+    const loader = loaders[extension]
+    output.push({
+      test: new RegExp('\\.' + extension + '$'),
+      use: loader
+    })
+  }
+
+  return output
+}
+
+exports.createNotifierCallback = () => {
+  const notifier = require('node-notifier')
+
+  return (severity, errors) => {
+    if (severity !== 'error') return
+
+    const error = errors[0]
+    const filename = error.file && error.file.split('!').pop()
+
+    notifier.notify({
+      title: packageConfig.name,
+      message: severity + ': ' + error.name,
+      subtitle: filename || '',
+      icon: path.join(__dirname, 'logo.png')
+    })
+  }
+}

+ 22 - 0
build/vue-loader.conf.js

@@ -0,0 +1,22 @@
+'use strict'
+const utils = require('./utils')
+const config = require('../config')
+const isProduction = process.env.NODE_ENV === 'production'
+const sourceMapEnabled = isProduction
+  ? config.build.productionSourceMap
+  : config.dev.cssSourceMap
+
+module.exports = {
+  loaders: utils.cssLoaders({
+    sourceMap: sourceMapEnabled,
+    extract: isProduction
+  }),
+  cssSourceMap: sourceMapEnabled,
+  cacheBusting: config.dev.cacheBusting,
+  transformToRequire: {
+    video: ['src', 'poster'],
+    source: 'src',
+    img: 'src',
+    image: 'xlink:href'
+  }
+}

+ 82 - 0
build/webpack.base.conf.js

@@ -0,0 +1,82 @@
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const config = require('../config')
+const vueLoaderConfig = require('./vue-loader.conf')
+
+function resolve (dir) {
+  return path.join(__dirname, '..', dir)
+}
+
+
+
+module.exports = {
+  context: path.resolve(__dirname, '../'),
+  entry: {
+    app: './src/main.js'
+  },
+  output: {
+    path: config.build.assetsRoot,
+    filename: '[name].js',
+    publicPath: process.env.NODE_ENV === 'production'
+      ? config.build.assetsPublicPath
+      : config.dev.assetsPublicPath
+  },
+  resolve: {
+    extensions: ['.js', '.vue', '.json'],
+    alias: {
+      'vue$': 'vue/dist/vue.esm.js',
+      '@': resolve('src'),
+    }
+  },
+  module: {
+    rules: [
+      {
+        test: /\.vue$/,
+        loader: 'vue-loader',
+        options: vueLoaderConfig
+      },
+      {
+        test: /\.js$/,
+        loader: 'babel-loader',
+        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
+      },
+      {
+        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: utils.assetsPath('img/[name].[hash:7].[ext]')
+        }
+      },
+      {
+        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: utils.assetsPath('media/[name].[hash:7].[ext]')
+        }
+      },
+      {
+        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
+        }
+      }
+    ]
+  },
+  node: {
+    // prevent webpack from injecting useless setImmediate polyfill because Vue
+    // source contains it (although only uses it if it's native).
+    setImmediate: false,
+    // prevent webpack from injecting mocks to Node native modules
+    // that does not make sense for the client
+    dgram: 'empty',
+    fs: 'empty',
+    net: 'empty',
+    tls: 'empty',
+    child_process: 'empty'
+  }
+}

+ 95 - 0
build/webpack.dev.conf.js

@@ -0,0 +1,95 @@
+'use strict'
+const utils = require('./utils')
+const webpack = require('webpack')
+const config = require('../config')
+const merge = require('webpack-merge')
+const path = require('path')
+const baseWebpackConfig = require('./webpack.base.conf')
+const CopyWebpackPlugin = require('copy-webpack-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
+const portfinder = require('portfinder')
+
+const HOST = process.env.HOST
+const PORT = process.env.PORT && Number(process.env.PORT)
+
+const devWebpackConfig = merge(baseWebpackConfig, {
+  module: {
+    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
+  },
+  // cheap-module-eval-source-map is faster for development
+  devtool: config.dev.devtool,
+
+  // these devServer options should be customized in /config/index.js
+  devServer: {
+    clientLogLevel: 'warning',
+    historyApiFallback: {
+      rewrites: [
+        { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
+      ],
+    },
+    hot: true,
+    contentBase: false, // since we use CopyWebpackPlugin.
+    compress: true,
+    host: HOST || config.dev.host,
+    port: PORT || config.dev.port,
+    open: config.dev.autoOpenBrowser,
+    overlay: config.dev.errorOverlay
+      ? { warnings: false, errors: true }
+      : false,
+    publicPath: config.dev.assetsPublicPath,
+    proxy: config.dev.proxyTable,
+    quiet: true, // necessary for FriendlyErrorsPlugin
+    watchOptions: {
+      poll: config.dev.poll,
+    }
+  },
+  plugins: [
+    new webpack.DefinePlugin({
+      'process.env': require('../config/dev.env')
+    }),
+    new webpack.HotModuleReplacementPlugin(),
+    new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
+    new webpack.NoEmitOnErrorsPlugin(),
+    // https://github.com/ampedandwired/html-webpack-plugin
+    new HtmlWebpackPlugin({
+      filename: 'index.html',
+      template: 'index.html',
+      inject: true
+    }),
+    // copy custom static assets
+    new CopyWebpackPlugin([
+      {
+        from: path.resolve(__dirname, '../static'),
+        to: config.dev.assetsSubDirectory,
+        ignore: ['.*']
+      }
+    ])
+  ]
+})
+
+module.exports = new Promise((resolve, reject) => {
+  portfinder.basePort = process.env.PORT || config.dev.port
+  portfinder.getPort((err, port) => {
+    if (err) {
+      reject(err)
+    } else {
+      // publish the new Port, necessary for e2e tests
+      process.env.PORT = port
+      // add port to devServer config
+      devWebpackConfig.devServer.port = port
+
+      // Add FriendlyErrorsPlugin
+      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
+        compilationSuccessInfo: {
+          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
+        },
+        onErrors: config.dev.notifyOnErrors
+        ? utils.createNotifierCallback()
+        : undefined
+      }))
+
+      resolve(devWebpackConfig)
+    }
+  })
+})

+ 145 - 0
build/webpack.prod.conf.js

@@ -0,0 +1,145 @@
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const webpack = require('webpack')
+const config = require('../config')
+const merge = require('webpack-merge')
+const baseWebpackConfig = require('./webpack.base.conf')
+const CopyWebpackPlugin = require('copy-webpack-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const ExtractTextPlugin = require('extract-text-webpack-plugin')
+const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
+const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
+
+const env = require('../config/prod.env')
+
+const webpackConfig = merge(baseWebpackConfig, {
+  module: {
+    rules: utils.styleLoaders({
+      sourceMap: config.build.productionSourceMap,
+      extract: true,
+      usePostCSS: true
+    })
+  },
+  devtool: config.build.productionSourceMap ? config.build.devtool : false,
+  output: {
+    path: config.build.assetsRoot,
+    filename: utils.assetsPath('js/[name].[chunkhash].js'),
+    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
+  },
+  plugins: [
+    // http://vuejs.github.io/vue-loader/en/workflow/production.html
+    new webpack.DefinePlugin({
+      'process.env': env
+    }),
+    new UglifyJsPlugin({
+      uglifyOptions: {
+        compress: {
+          warnings: false
+        }
+      },
+      sourceMap: config.build.productionSourceMap,
+      parallel: true
+    }),
+    // extract css into its own file
+    new ExtractTextPlugin({
+      filename: utils.assetsPath('css/[name].[contenthash].css'),
+      // Setting the following option to `false` will not extract CSS from codesplit chunks.
+      // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
+      // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 
+      // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
+      allChunks: true,
+    }),
+    // Compress extracted CSS. We are using this plugin so that possible
+    // duplicated CSS from different components can be deduped.
+    new OptimizeCSSPlugin({
+      cssProcessorOptions: config.build.productionSourceMap
+        ? { safe: true, map: { inline: false } }
+        : { safe: true }
+    }),
+    // generate dist index.html with correct asset hash for caching.
+    // you can customize output by editing /index.html
+    // see https://github.com/ampedandwired/html-webpack-plugin
+    new HtmlWebpackPlugin({
+      filename: config.build.index,
+      template: 'index.html',
+      inject: true,
+      minify: {
+        removeComments: true,
+        collapseWhitespace: true,
+        removeAttributeQuotes: true
+        // more options:
+        // https://github.com/kangax/html-minifier#options-quick-reference
+      },
+      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
+      chunksSortMode: 'dependency'
+    }),
+    // keep module.id stable when vendor modules does not change
+    new webpack.HashedModuleIdsPlugin(),
+    // enable scope hoisting
+    new webpack.optimize.ModuleConcatenationPlugin(),
+    // split vendor js into its own file
+    new webpack.optimize.CommonsChunkPlugin({
+      name: 'vendor',
+      minChunks (module) {
+        // any required modules inside node_modules are extracted to vendor
+        return (
+          module.resource &&
+          /\.js$/.test(module.resource) &&
+          module.resource.indexOf(
+            path.join(__dirname, '../node_modules')
+          ) === 0
+        )
+      }
+    }),
+    // extract webpack runtime and module manifest to its own file in order to
+    // prevent vendor hash from being updated whenever app bundle is updated
+    new webpack.optimize.CommonsChunkPlugin({
+      name: 'manifest',
+      minChunks: Infinity
+    }),
+    // This instance extracts shared chunks from code splitted chunks and bundles them
+    // in a separate chunk, similar to the vendor chunk
+    // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
+    new webpack.optimize.CommonsChunkPlugin({
+      name: 'app',
+      async: 'vendor-async',
+      children: true,
+      minChunks: 3
+    }),
+
+    // copy custom static assets
+    new CopyWebpackPlugin([
+      {
+        from: path.resolve(__dirname, '../static'),
+        to: config.build.assetsSubDirectory,
+        ignore: ['.*']
+      }
+    ])
+  ]
+})
+
+if (config.build.productionGzip) {
+  const CompressionWebpackPlugin = require('compression-webpack-plugin')
+
+  webpackConfig.plugins.push(
+    new CompressionWebpackPlugin({
+      asset: '[path].gz[query]',
+      algorithm: 'gzip',
+      test: new RegExp(
+        '\\.(' +
+        config.build.productionGzipExtensions.join('|') +
+        ')$'
+      ),
+      threshold: 10240,
+      minRatio: 0.8
+    })
+  )
+}
+
+if (config.build.bundleAnalyzerReport) {
+  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
+  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
+}
+
+module.exports = webpackConfig

+ 7 - 0
config/dev.env.js

@@ -0,0 +1,7 @@
+'use strict'
+const merge = require('webpack-merge')
+const prodEnv = require('./prod.env')
+
+module.exports = merge(prodEnv, {
+  NODE_ENV: '"development"'
+})

+ 69 - 0
config/index.js

@@ -0,0 +1,69 @@
+'use strict'
+// Template version: 1.3.1
+// see http://vuejs-templates.github.io/webpack for documentation.
+
+const path = require('path')
+
+module.exports = {
+  dev: {
+
+    // Paths
+    assetsSubDirectory: 'static',
+    assetsPublicPath: '/',
+    proxyTable: {},
+
+    // Various Dev Server settings
+    host: 'localhost', // can be overwritten by process.env.HOST
+    port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
+    autoOpenBrowser: false,
+    errorOverlay: true,
+    notifyOnErrors: true,
+    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
+
+    
+    /**
+     * Source Maps
+     */
+
+    // https://webpack.js.org/configuration/devtool/#development
+    devtool: 'cheap-module-eval-source-map',
+
+    // If you have problems debugging vue-files in devtools,
+    // set this to false - it *may* help
+    // https://vue-loader.vuejs.org/en/options.html#cachebusting
+    cacheBusting: true,
+
+    cssSourceMap: true
+  },
+
+  build: {
+    // Template for index.html
+    index: path.resolve(__dirname, '../dist/index.html'),
+
+    // Paths
+    assetsRoot: path.resolve(__dirname, '../dist'),
+    assetsSubDirectory: 'static',
+    assetsPublicPath: '/',
+
+    /**
+     * Source Maps
+     */
+
+    productionSourceMap: true,
+    // https://webpack.js.org/configuration/devtool/#production
+    devtool: '#source-map',
+
+    // Gzip off by default as many popular static hosts such as
+    // Surge or Netlify already gzip all static assets for you.
+    // Before setting to `true`, make sure to:
+    // npm install --save-dev compression-webpack-plugin
+    productionGzip: false,
+    productionGzipExtensions: ['js', 'css'],
+
+    // Run the build command with an extra argument to
+    // View the bundle analyzer report after build finishes:
+    // `npm run build --report`
+    // Set to `true` or `false` to always turn it on or off
+    bundleAnalyzerReport: process.env.npm_config_report
+  }
+}

+ 4 - 0
config/prod.env.js

@@ -0,0 +1,4 @@
+'use strict'
+module.exports = {
+  NODE_ENV: '"production"'
+}

+ 15 - 0
index.html

@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+    <title>脉乐</title>
+</head>
+
+<body>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+</body>
+
+</html>

+ 69 - 0
package.json

@@ -0,0 +1,69 @@
+{
+  "name": "maile",
+  "version": "1.0.0",
+  "description": "A Vue.js project",
+  "author": "panhui <1529378564@qq.com>",
+  "private": true,
+  "scripts": {
+    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
+    "start": "npm run dev",
+    "build": "node build/build.js"
+  },
+  "dependencies": {
+    "axios": "^0.18.0",
+    "less": "^3.0.4",
+    "less-loader": "^4.1.0",
+    "moment": "^2.24.0",
+    "vconsole": "^3.3.0",
+    "vue": "^2.5.2",
+    "vue-axios": "^2.1.1",
+    "vue-router": "^3.0.1",
+    "vuex": "^3.0.1"
+  },
+  "devDependencies": {
+    "autoprefixer": "^7.1.2",
+    "babel-core": "^6.22.1",
+    "babel-helper-vue-jsx-merge-props": "^2.0.3",
+    "babel-loader": "^7.1.1",
+    "babel-plugin-syntax-jsx": "^6.18.0",
+    "babel-plugin-transform-runtime": "^6.22.0",
+    "babel-plugin-transform-vue-jsx": "^3.5.0",
+    "babel-preset-env": "^1.3.2",
+    "babel-preset-stage-2": "^6.22.0",
+    "chalk": "^2.0.1",
+    "copy-webpack-plugin": "^4.0.1",
+    "css-loader": "^0.28.0",
+    "extract-text-webpack-plugin": "^3.0.0",
+    "file-loader": "^1.1.4",
+    "friendly-errors-webpack-plugin": "^1.6.1",
+    "html-webpack-plugin": "^2.30.1",
+    "node-notifier": "^5.1.2",
+    "optimize-css-assets-webpack-plugin": "^3.2.0",
+    "ora": "^1.2.0",
+    "portfinder": "^1.0.13",
+    "postcss-import": "^11.0.0",
+    "postcss-loader": "^2.0.8",
+    "postcss-url": "^7.2.1",
+    "rimraf": "^2.6.0",
+    "semver": "^5.3.0",
+    "shelljs": "^0.7.6",
+    "uglifyjs-webpack-plugin": "^1.1.1",
+    "url-loader": "^0.5.8",
+    "vue-loader": "^13.3.0",
+    "vue-style-loader": "^3.0.1",
+    "vue-template-compiler": "^2.5.2",
+    "webpack": "^3.6.0",
+    "webpack-bundle-analyzer": "^2.9.0",
+    "webpack-dev-server": "^2.9.1",
+    "webpack-merge": "^4.1.0"
+  },
+  "engines": {
+    "node": ">= 6.0.0",
+    "npm": ">= 3.0.0"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not ie <= 8"
+  ]
+}

+ 141 - 0
src/App.vue

@@ -0,0 +1,141 @@
+<template>
+  <div class="appRoot">
+    <transition :name="'vux-pop-' + (direction === 'forward' ? 'in' : 'out')">
+      <router-view class="router-view"></router-view>
+    </transition>
+  </div>
+</template>
+<script>
+import { mapState } from 'vuex'
+export default {
+  name: 'app',
+  data() {
+    return {
+    }
+  },
+  mounted() {
+  },
+  computed: {
+    ...mapState(['isChinese', 'direction']),
+  },
+}
+
+</script>
+<style lang="less" scoped>
+.appRoot {
+  position: relative;
+  height: 100%;
+}
+</style>
+<style lang="less">
+@import "styles/reset.less";
+
+.appRoot {
+  background-color: #fff;
+}
+
+.router-view {
+  box-sizing: border-box;
+  width: 100%;
+  height: 100%;
+  animation-duration: 0.3s;
+  animation-fill-mode: both;
+  backface-visibility: hidden;
+  overflow: hidden;
+  transform: translate3d(0, 0, 0);
+  position: absolute;
+  top: 0;
+  left: 0;
+  overflow: auto;
+  -webkit-overflow-scrolling: touch;
+}
+
+.fade-enter-active,
+.fade-leave-active {
+  transition: opacity 0.3s;
+}
+
+.fade-enter,
+.fade-leave-active {
+  opacity: 0;
+}
+
+.vux-pop-out-enter-active,
+.vux-pop-out-leave-active,
+.vux-pop-in-enter-active,
+.vux-pop-in-leave-active {
+  will-change: transform;
+  height: 100%;
+  position: absolute;
+  left: 0;
+}
+
+.vux-pop-out-enter-active {
+  animation-name: popInLeft;
+}
+
+.vux-pop-out-leave-active {
+  animation-name: popOutRight;
+}
+
+.vux-pop-in-enter-active {
+  perspective: 1000;
+  animation-name: popInRight;
+}
+
+.vux-pop-in-leave-active {
+  animation-name: popOutLeft;
+}
+
+.black_zhaozi {
+  width: 100%;
+  height: 100%;
+  position: fixed;
+  top: 0;
+  left: 0;
+  background: rgba(0, 0, 0, 0.5);
+  z-index: 990;
+}
+
+@keyframes popInLeft {
+  from {
+    opacity: 0;
+    transform: translate3d(-100%, 0, 0);
+  }
+  to {
+    opacity: 1;
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+@keyframes popOutLeft {
+  from {
+    opacity: 1;
+  }
+  to {
+    opacity: 0;
+    transform: translate3d(-100%, 0, 0);
+  }
+}
+
+@keyframes popInRight {
+  from {
+    opacity: 0;
+    transform: translate3d(100%, 0, 0);
+  }
+  to {
+    opacity: 1;
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+@keyframes popOutRight {
+  from {
+    opacity: 1;
+  }
+  to {
+    opacity: 0;
+    transform: translate3d(100%, 0, 0);
+  }
+}
+</style>

TEMPAT SAMPAH
src/assets/home_icon_jifen.png


TEMPAT SAMPAH
src/assets/icon_choujiang.png


TEMPAT SAMPAH
src/assets/icon_dibuchoujiang.png


TEMPAT SAMPAH
src/assets/icon_renwu.png


TEMPAT SAMPAH
src/assets/icon_success.png


TEMPAT SAMPAH
src/assets/icon_warning.png


TEMPAT SAMPAH
src/assets/icon_wode.png


TEMPAT SAMPAH
src/assets/img_choujiaozhuanpan.png


+ 5 - 0
src/assets/去除文件名中.bat

@@ -0,0 +1,5 @@
+@echo off& setlocal enabledelayedexpansion
+
+for /f "delims=" %%1 in ('dir /a /b') do (set wind=%%1
+
+ren "%%~1" "!wind:@3x=!")

+ 36 - 0
src/components/Modal/index.js

@@ -0,0 +1,36 @@
+import Vue from 'vue'
+import Main from './main.vue'
+let ModalConstructor = Vue.extend(Main)
+let instance = null
+var Modal = function(data) {
+    if (typeof data !== 'object') {
+        data = { msg: '' + data }
+    }
+    if (instance && instance.visible) {
+        Object.keys(data).forEach(function(key) {
+            instance[key] = data[key]
+        })
+        instance.restartTimer()
+    } else {
+        instance = new ModalConstructor({
+            data: data
+        })
+        instance.vm = instance.$mount()
+        document.body.appendChild(instance.vm.$el)
+    }
+    return instance.vm
+};
+['success', 'warning', 'info', 'loading'].forEach(type => {
+    Modal[type] = data => {
+        if (typeof data !== 'object') {
+            data = { msg: '' + data }
+        }
+        data.type = type
+        return Modal(data)
+    }
+})
+
+Modal.close = function() {
+    instance && instance.close()
+}
+export default Modal

+ 137 - 0
src/components/Modal/main.vue

@@ -0,0 +1,137 @@
+<template>
+  <transition name="fade" v-on:after-leave="afterLeave">
+    <div class="modal-container" @touchstart.stop.prevent v-show="visible">
+      <div class="modalInfo" v-if="icon === 'info'">
+        <div class="msg">{{msg}}</div>
+      </div>
+      <div class="modal" v-else :class="{nobg:type=='noBg'}">
+        <!-- <img class="icon" src="../../assets/icon_info.png" v-if="icon === 'info'"> -->
+        <img class="icon" src="../../assets/icon_success.png" v-if="icon === 'success'">
+        <progressbar v-else-if="icon === 'loading'" style="margin-bottom:12px"></progressbar>
+        <div class="msg">{{msg}}</div>
+      </div>
+    </div>
+  </transition>
+</template>
+<script>
+import progressbar from '../progressbar'
+export default {
+  name: 'progress-dialog',
+  created() { },
+  mounted() {
+    this.visible = true
+    this.startTimer()
+  },
+  data() {
+    return {
+      msg: '',
+      type: 'info',
+      timer: null,
+      duration: 2000,
+      visible: false,
+      type: ''
+    }
+  },
+  computed: {
+    icon() {
+      if (['info', 'success', 'warning', 'loading'].indexOf(this.type) !== - 1) {
+        return this.type
+      } else {
+        return 'info'
+      }
+    }
+  },
+  methods: {
+    startTimer() {
+      if (this.duration > 0) {
+        this.timer = setTimeout(() => {
+          this.close()
+        }, this.duration)
+      }
+    },
+    restartTimer() {
+      clearTimeout(this.timer)
+      this.startTimer()
+    },
+    close() {
+      this.visible = false
+      // this.$el.addEventListener('transitionend', this.destroyView)
+    },
+    destroyView() {
+      this.$destroy(true)
+      this.$el.parentNode.removeChild(this.$el)
+    },
+    afterLeave(el) {
+      this.destroyView()
+    },
+  },
+  components: {
+    progressbar
+  }
+}
+
+</script>
+<style lang="less" scoped>
+.modal-container {
+  position: fixed;
+  width: 100%;
+  height: 100%;
+  left: 0;
+  top: 0;
+  z-index: 700;
+}
+.modalInfo {
+  position: fixed;
+  top: 45%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  background: rgba(0, 0, 0, 0.7);
+  border-radius: 4px;
+  padding: 8px 20px;
+  .msg {
+    width: 100%;
+    line-height: 20px;
+  }
+  z-index: 550;
+}
+.modal {
+  width: 120px;
+  height: 120px;
+  position: fixed;
+  left: 0;
+  top: 0;
+  right: 0;
+  bottom: 1.6rem;
+  margin: auto;
+  background: rgba(0, 0, 0, 0.7);
+  border-radius: 10px;
+  display: flex;
+  align-items: center;
+  flex-direction: column;
+  justify-content: center;
+  .icon {
+    width: 60px;
+  }
+
+  &.nobg {
+    background: transparent;
+  }
+}
+
+.msg {
+  color: #fff;
+  font-size: 14px;
+  width: 80%;
+  text-align: center;
+}
+
+.fade-enter,
+.fade-leave-active {
+  opacity: 0;
+}
+
+.fade-enter-active,
+.fade-leave-active {
+  transition: all 0.5s;
+}
+</style>

+ 58 - 0
src/components/progressbar.vue

@@ -0,0 +1,58 @@
+<template>
+    <svg class="loading-icon" xmlns="http://www.w3.org/2000/svg" :width="size" :height="size" viewBox="0 0 100 100">
+        <path fill="none" d="M0 0h100v100H0z" />
+        <rect width="7" height="20" x="46.5" y="40" fill="#E9E9E9" rx="4" ry="4" transform="translate(0 -30)" />
+        <rect width="7" height="20" x="46.5" y="40" fill="#989697" rx="4" ry="4" transform="rotate(30 105.98 65)" />
+        <rect width="7" height="20" x="46.5" y="40" fill="#9B999A" rx="4" ry="4" transform="rotate(60 75.98 65)" />
+        <rect width="7" height="20" x="46.5" y="40" fill="#A3A1A2" rx="4" ry="4" transform="rotate(90 65 65)" />
+        <rect width="7" height="20" x="46.5" y="40" fill="#ABA9AA" rx="4" ry="4" transform="rotate(120 58.66 65)" />
+        <rect width="7" height="20" x="46.5" y="40" fill="#B2B2B2" rx="4" ry="4" transform="rotate(150 54.02 65)" />
+        <rect width="7" height="20" x="46.5" y="40" fill="#BAB8B9" rx="4" ry="4" transform="rotate(180 50 65)" />
+        <rect width="7" height="20" x="46.5" y="40" fill="#C2C0C1" rx="4" ry="4" transform="rotate(-150 45.98 65)" />
+        <rect width="7" height="20" x="46.5" y="40" fill="#CBCBCB" rx="4" ry="4" transform="rotate(-120 41.34 65)" />
+        <rect width="7" height="20" x="46.5" y="40" fill="#D2D2D2" rx="4" ry="4" transform="rotate(-90 35 65)" />
+        <rect width="7" height="20" x="46.5" y="40" fill="#DADADA" rx="4" ry="4" transform="rotate(-60 24.02 65)" />
+        <rect width="7" height="20" x="46.5" y="40" fill="#E2E2E2" rx="4" ry="4" transform="rotate(-30 -5.98 65)" />
+    </svg>
+</template>
+<script>
+export default {
+    name: 'progressbar',
+    props: {
+        size: {
+            default: 38
+        },
+        color: {
+            default: '#999'
+        }
+    }
+}
+</script>
+<style lang="less" scoped>
+.loading-icon {
+    -webkit-animation: weuiLoading 1s steps(12, end) infinite;
+    animation: weuiLoading 1s steps(12, end) infinite;
+}
+
+@-webkit-keyframes weuiLoading {
+    0% {
+        -webkit-transform: rotate3d(0, 0, 1, 0deg);
+        transform: rotate3d(0, 0, 1, 0deg);
+    }
+    100% {
+        -webkit-transform: rotate3d(0, 0, 1, 360deg);
+        transform: rotate3d(0, 0, 1, 360deg);
+    }
+}
+
+@keyframes weuiLoading {
+    0% {
+        -webkit-transform: rotate3d(0, 0, 1, 0deg);
+        transform: rotate3d(0, 0, 1, 0deg);
+    }
+    100% {
+        -webkit-transform: rotate3d(0, 0, 1, 360deg);
+        transform: rotate3d(0, 0, 1, 360deg);
+    }
+}
+</style>

+ 6 - 0
src/main.css

@@ -0,0 +1,6 @@
+.bg {
+    background-position: center center;
+    background-size: cover;
+    background-repeat: no-repeat;
+    border-radius: 6px;
+}

+ 129 - 0
src/main.js

@@ -0,0 +1,129 @@
+import Vue from 'vue'
+import App from './App'
+import router from './router'
+import store from './vuex'
+import axios from 'axios'
+import Modal from './components/Modal'
+import './main.css'
+
+
+// import Vconsole from 'vconsole';
+// new Vconsole();
+
+
+Vue.prototype.$modal = Modal;
+var scale = (window.screen.width / 375).toFixed(2)
+var meta = document.createElement('meta')
+meta.name = 'viewport'
+meta.content = 'width=375,initial-scale=' + scale + ',user-scalable=no'
+document.head.appendChild(meta)
+
+
+Vue.config.productionTip = false
+const baseUrl = process.env.NODE_ENV === 'production' ? '../' : `http://${location.hostname}:8080`;
+Vue.prototype.$baseUrl = baseUrl;
+// const baseUrl = 'http://www.xiangjuwu.com'
+axios.defaults.withCredentials = true;
+axios.defaults.baseURL = baseUrl;
+
+
+Vue.prototype.$http = {
+    get(params) {
+        return new Promise((resolve, reject) => {
+            if (params instanceof String) {
+                params = { url: params };
+            } else if (!params instanceof Object) {
+                reject('params error');
+                return;
+            }
+            if (!params.url) {
+                reject('url error');
+                return;
+            } else if (!params.url instanceof String) {
+                reject('url error');
+                return;
+            } else if (params.url.length === 0) {
+                reject('url error');
+                return;
+            }
+            // if (!/^(http:\/\/)|(https:\/\/)/.test(params.url)) {
+            //     params.url = baseUrl + params.url;
+            // }
+            store.commit('updateFetchingData', true);
+            axios.get(params.url, {
+                params: params.data
+            }, { withCredentials: true }).then(res => {
+                store.commit('updateFetchingData', false);
+                if (res.status === 200) {
+                    resolve(res.data);
+                } else {
+                    reject(res);
+                }
+
+            }).catch(e => {
+                store.commit('updateFetchingData', false);
+                reject(e);
+            });
+        });
+    },
+    post(params) {
+        if (params instanceof String) {
+            params = { url: params };
+        } else if (!params instanceof Object) {
+            reject('params error');
+            return;
+        }
+        if (!params.url) {
+            reject('url error');
+            return;
+        } else if (!params.url instanceof String) {
+            reject('url error');
+            return;
+        } else if (params.url.length === 0) {
+            reject('url error');
+            return;
+        }
+        // if (!/^(http:\/\/)|(https:\/\/)/.test(params.url)) {
+        //     params.url = baseUrl + params.url;
+        // }
+        let data = new FormData();
+        if (params.data) {
+            for (let key in params.data) {
+                if (params.data.hasOwnProperty(key)) {
+                    if (params.data[key] instanceof Array) {
+                        data.append(key, params.data[key].join());
+                    } else if (!(params.data[key] instanceof Object)) {
+                        data.append(key, params.data[key]);
+                    }
+                }
+            }
+        }
+        return new Promise((resolve, reject) => {
+            store.commit('updateFetchingData', true);
+            axios.post(params.url, data, { withCredentials: true }).then(res => {
+                store.commit('updateFetchingData', false);
+                if (res.status === 200) {
+                    resolve(res.data);
+                } else {
+                    reject(res);
+                }
+
+            }).catch(e => {
+                store.commit('updateFetchingData', false);
+                reject(e);
+            });
+        });
+    }
+};
+
+
+
+
+/* eslint-disable no-new */
+new Vue({
+    el: '#app',
+    router,
+    store,
+    components: { App },
+    template: '<App/>'
+})

+ 27 - 0
src/pages/Home.vue

@@ -0,0 +1,27 @@
+<template>
+  <div class="container">
+    
+  </div>
+</template>
+<script>
+
+
+
+
+
+import { mapState } from 'vuex'
+export default {
+  name: 'draw',
+  data() {
+    return {
+    }
+  },
+  computed: {
+    ...mapState([]),
+
+  }
+}
+
+</script>
+<style lang="less" scoped>
+</style>

+ 104 - 0
src/pages/Index.vue

@@ -0,0 +1,104 @@
+<template>
+  <div class="container">
+    <transition :name="'vux-pop-' + (direction === 'forward' ? 'in' : 'out')">
+      <router-view class="tab-page"></router-view>
+    </transition>
+    <div class="tab-bottom">
+      <div class="tab-item" :class="{active:item.isActive}" v-for="item in tabList">
+        <img :src="item.icon" alt>
+        <div>{{item.name}}</div>
+      </div>
+
+      <img src="../assets/icon_dibuchoujiang.png" alt="">
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+import moment from 'moment'
+export default {
+  name: 'index',
+  data() {
+    return {
+      tabInfoList: [{
+        name: '任务',
+        icon: require('../assets/icon_renwu.png'),
+        preIcon: require('../assets/icon_renwu.png'),
+        path: 'task'
+      }, {
+        name: '我的',
+        icon: require('../assets/icon_wode.png'),
+        preIcon: require('../assets/icon_wode.png'),
+        path: 'user'
+      }]
+    }
+  },
+  created() {
+
+  },
+  computed: {
+    ...mapState(['direction', 'userInfo']),
+    tabList() {
+      var list = [];
+      this.tabInfoList.forEach(item => {
+        var jsonp = {
+          icon: item.icon,
+          name: item.name,
+          isActive: false
+        }
+        if (item.path == this.$route.query.name) {
+          jsonp.icon = item.preIcon;
+          jsonp.isActive = true;
+        }
+        list.push(jsonp)
+      })
+      return list;
+    }
+  },
+  methods: {
+
+  }
+}
+
+</script>
+
+<style lang="less" scoped>
+.container {
+  display: flex;
+  flex-direction: column;
+  height: 100vh;
+  overflow: hidden;
+  background: linear-gradient(
+    180deg,
+    rgba(251, 210, 73, 1) 0%,
+    rgba(245, 166, 35, 1) 100%
+  );
+
+  .tab-bottom {
+    min-height: 49px;
+    display: flex;
+    background-color: #fff;
+    display: flex;
+    .tab-item {
+      flex-grow: 1;
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      img {
+        width: 20px;
+        height: 20px;
+      }
+
+      div {
+        height: 14px;
+        font-size: 10px;
+        color: rgba(153, 153, 153, 1);
+        line-height: 14px;
+        margin-top: 3px;
+      }
+    }
+  }
+}
+</style>

+ 48 - 0
src/router/index.js

@@ -0,0 +1,48 @@
+import Vue from 'vue'
+import Router from 'vue-router'
+import store from '../vuex'
+import Index from "../pages/index";
+
+Vue.use(Router)
+const router = new Router({
+    routes: [{
+        path: '/',
+        redirect: 'home'
+    }, {
+        path: "/",
+        name: "index",
+        component: Index,
+        children: [{
+            path: '/home',
+            name: 'home',
+            meta: {
+                title: '抽奖'
+            },
+            component: resolve => require(['../pages/Home'], resolve)
+        }]
+    }]
+})
+
+router.beforeEach((to, from, next) => {
+    store.commit('updateIsChinese', store.state.isChinese);
+    if (to.params.isNext) {
+        store.commit('updateDirection', 'forward')
+    } else {
+        store.commit('updateDirection', 'reverse')
+    }
+
+    if (to.meta.title) {
+        document.title = to.meta.title
+    } else {
+        document.title = '脉乐'
+    }
+
+    if (/\/http/.test(to.path)) {
+        let url = to.path.split("http")[1];
+        window.location.href = `http${url}`;
+    } else {
+        next();
+    }
+});
+
+export default router;

+ 3 - 0
src/styles/base/mobile.less

@@ -0,0 +1,3 @@
+.setTapColor(@c:rgba(0,0,0,0)) {
+    -webkit-tap-highlight-color: @c;
+}

+ 37 - 0
src/styles/base/setArrow.less

@@ -0,0 +1,37 @@
+._setArrow(@arrowsize, @borderColor, @borderWidth){
+    display: inline-block;
+    height: @arrowsize;
+    width: @arrowsize;
+    border-width: @borderWidth @borderWidth 0 0;
+    border-color: @borderColor;
+    border-style: solid;
+}
+
+.setArrow(@direction, @arrowsize, @borderColor, @borderWidth) when (@direction = top) {
+    ._setArrow(@arrowsize, @borderColor, @borderWidth);
+    transform: matrix(0.71,-0.71,0.71,0.71,0,0); // rotate(-45deg)
+}
+
+.setArrow(@direction, @arrowsize, @borderColor,@borderWidth) when (@direction = right) {
+    ._setArrow(@arrowsize, @borderColor, @borderWidth);
+    transform: matrix(0.71,0.71,-0.71,0.71,0,0); // rotate(45deg);
+
+    position: relative;
+    top: -2px;
+}
+
+.setArrow(@direction, @arrowsize, @borderColor,@borderWidth) when (@direction = down) {
+    ._setArrow(@arrowsize, @borderColor, @borderWidth);
+    transform: matrix(-0.71,0.71,-0.71,-0.71,0,0); // rotate(135deg);
+
+    position: relative;
+    top: -3px;
+}
+
+.setArrow(@direction, @arrowsize, @borderColor,@borderWidth) when (@direction = left) {
+    ._setArrow(@arrowsize, @borderColor, @borderWidth);
+    transform: matrix(-0.71,-0.71,0.71,-0.71,0,0); // rotate(-135deg);
+
+    position: relative;
+    top: -2px;
+}

+ 21 - 0
src/styles/base/setChecked.less

@@ -0,0 +1,21 @@
+.setChecked(@c:#FFFFFF) {
+    display: inline-block;
+    content: '';
+    width: 4px;
+    height: 8px;
+    border-bottom: 2px solid @c;
+    border-right: 2px solid @c;
+    transform: translate(0, 0) rotate(45deg);
+}
+
+.setCheckedAbs(@c:#FFFFFF) {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    content: '';
+    width: 4px;
+    height: 8px;
+    border-bottom: 2px solid @c;
+    border-right: 2px solid @c;
+    transform: translate(-50%, -65%) rotate(45deg);
+}

+ 51 - 0
src/styles/base/setOnepx.less

@@ -0,0 +1,51 @@
+.setTopLine(@c: #ebebeb) {
+    content: " ";
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    height: 1px;
+    border-top: 1px solid @c;
+    color: @c;
+    transform-origin: 0 0;
+    transform: scaleY(0.5);
+}
+
+.setBottomLine(@c: #ebebeb) {
+    content: " ";
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    right: 0;
+    height: 1px;
+    border-bottom: 1px solid @c;
+    color: @c;
+    transform-origin: 0 100%;
+    transform: scaleY(0.5);
+}
+
+.setLeftLine(@c: #ebebeb) {
+    content: " ";
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 1px;
+    bottom: 0;
+    border-left: 1px solid @c;
+    color: @c;
+    transform-origin: 0 0;
+    transform: scaleX(0.5);
+}
+
+.setRightLine(@c: #ebebeb) {
+    content: " ";
+    position: absolute;
+    right: 0;
+    top: 0;
+    width: 1px;
+    bottom: 0;
+    border-right: 1px solid @c;
+    color: @c;
+    transform-origin: 100% 0;
+    transform: scaleX(0.5);
+}

+ 24 - 0
src/styles/base/text.less

@@ -0,0 +1,24 @@
+.ellipsis(@w:auto) {
+    width: @w;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    word-wrap: normal;
+}
+
+.ellipsisLn(@line) {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    -webkit-line-clamp: @line;
+}
+.text_wrap() {
+    word-wrap:break-word;
+    word-break:break-all;
+}
+.hyphens() {
+    word-wrap:break-word;
+    -webkit-hyphens:auto;
+    hyphens:auto;
+}

+ 1150 - 0
src/styles/component.css

@@ -0,0 +1,1150 @@
+.stack {
+	margin: 0 auto;
+	position: relative;
+	z-index: 1000;
+	width: 320px;
+	height: 320px;
+	padding: 0;
+	list-style: none;
+    pointer-events: none;
+}
+
+.stack__item {
+	background: #fff;
+	height: 100%;
+	width: 100%;
+	border-radius: 4px;
+	text-align: center;
+	overflow: hidden;
+	position: absolute;
+	opacity: 0;
+	display: -webkit-flex;
+	display: flex;
+	-webkit-flex-direction: column;
+	flex-direction: column;
+	-webkit-touch-callout: none;
+	-webkit-user-select: none;
+	-khtml-user-select: none;
+	-moz-user-select: none;
+	-ms-user-select: none;
+	user-select: none;
+	pointer-events: auto;
+}
+
+.stack__item img {
+	width: 100%;
+	display: block;
+	pointer-events: none;
+}
+
+.controls {
+	position: relative;
+	width: 200px;
+	text-align: center;
+	margin: 3em 0 0 0;
+}
+
+.button {
+	border: none;
+	background: none;
+	position: relative;
+	display: inline-block;
+	padding: 0.25em;
+	margin: 0 0.5em;
+	cursor: pointer;
+	font-size: 1.5em;
+	width: 50px;
+	height: 50px;
+	z-index: 100;
+	-webkit-tap-highlight-color:rgba(0,0,0,0);
+}
+
+.button .fa {
+	pointer-events: none;
+}
+
+.button--default {
+	background: #333;
+	border-radius: 3px;
+	color: #fff;
+	font-size: 0.95em;
+	font-weight: bold;
+	padding: 0.65em 2em;
+	width: auto;
+	height: auto;
+}
+
+.button--sonar {
+	border-radius: 50%;
+	background: #fff;
+}
+
+.button--sonar::before {
+	position: absolute;
+	top: 50%;
+	left: 50%;
+	border-radius: 50%;
+	content: '';
+	opacity: 0;
+	pointer-events: none;
+	border: 4px solid rgba(255,255,255,0.5);
+	margin: -35px 0 0 -35px;
+	width: 70px;
+	height: 70px;
+}
+
+.button--sonar.button--active::before {
+	-webkit-animation: anim-effect-sonar 0.3s ease-out forwards;
+	animation: anim-effect-sonar 0.3s ease-out forwards;
+}
+
+@-webkit-keyframes anim-effect-sonar {
+	0% {
+		opacity: 1;
+		-webkit-transform: scale3d(0.9, 0.9, 1);
+		transform: scale3d(0.9, 0.9, 1);
+	}
+	to {
+		opacity: 0;
+		-webkit-transform: scale3d(1.4, 1.4, 1);
+		transform: scale3d(1.4, 1.4, 1);
+	}
+}
+
+@keyframes anim-effect-sonar {
+	0% {
+		opacity: 1;
+		-webkit-transform: scale3d(0.9, 0.9, 1);
+		transform: scale3d(0.9, 0.9, 1);
+	}
+	to {
+		opacity: 0;
+		-webkit-transform: scale3d(1.4, 1.4, 1);
+		transform: scale3d(1.4, 1.4, 1);
+	}
+}
+
+.material-circle {
+	width: 150vh;
+	height: 150vh;
+	margin: -75vh 0 0 -75vh;
+	z-index: 0;
+	border-radius: 50%;
+	pointer-events: none;
+	opacity: 0;
+	position: absolute;
+	z-index: 0;
+	-webkit-transform: scale3d(0, 0, 1);
+	transform: scale3d(0, 0, 1);
+}
+
+.material-circle--accept.material-circle--active {
+	background: #81d47d;
+}
+
+.material-circle--reject.material-circle--active {
+	background: #e66868;
+}
+
+.material-circle--active {
+	-webkit-animation: anim-effect-material 0.6s ease-out forwards;
+	animation: anim-effect-material 0.6s ease-out forwards;
+}
+
+@-webkit-keyframes anim-effect-material {
+	0% {
+		opacity: 1;
+		-webkit-transform: scale3d(0, 0, 1);
+		transform: scale3d(0, 0, 1);
+	}
+	70% {
+		opacity: 1;
+		-webkit-transform: scale3d(1.4, 1.4, 1);
+		transform: scale3d(1.4, 1.4, 1);
+	}
+	100% {
+		opacity: 0;
+		-webkit-transform: scale3d(1.4, 1.4, 1);
+		transform: scale3d(1.4, 1.4, 1);
+	}
+}
+
+@keyframes anim-effect-material {
+	0% {
+		opacity: 1;
+		-webkit-transform: scale3d(0, 0, 1);
+		transform: scale3d(0, 0, 1);
+	}
+	70% {
+		opacity: 1;
+		-webkit-transform: scale3d(1.4, 1.4, 1);
+		transform: scale3d(1.4, 1.4, 1);
+	}
+	100% {
+		opacity: 0;
+		-webkit-transform: scale3d(1.4, 1.4, 1);
+		transform: scale3d(1.4, 1.4, 1);
+	}
+}
+
+.button:focus {
+	outline: none;
+}
+
+.button--accept {
+	color: #81d47d;
+}
+
+.button--reject {
+	color: #e66868;
+}
+
+.text-hidden {
+	position: absolute;
+	overflow: hidden;
+	width: 0;
+	height: 0;
+	color: transparent;
+	display: block;
+}
+
+/* Animations */
+.stack__item--reject,
+.stack__item--accept {
+	pointer-events: none;
+}
+
+/***********************************************/
+/******************** yuda *********************/
+/***********************************************/
+
+.stack--yuda .stack__item--reject {
+	-webkit-animation: yudaReject 0.5s forwards;
+	animation: yudaReject 0.5s forwards;
+}
+
+@-webkit-keyframes yudaReject {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(0,200px,0);
+		transform: translate3d(0,200px,0);
+	}
+}
+
+@keyframes yudaReject {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(0,200px,0);
+		transform: translate3d(0,200px,0);
+	}
+}
+
+.stack--yuda .stack__item--accept {
+	-webkit-animation: yudaAccept 0.5s forwards;
+	animation: yudaAccept 0.5s forwards;
+	-webkit-transform-origin: 50% 300%;
+	transform-origin: 50% 300%;
+}
+
+@-webkit-keyframes yudaAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: rotate3d(0,0,1,20deg);
+		transform: rotate3d(0,0,1,20deg);
+	}
+}
+
+@keyframes yudaAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: rotate3d(0,0,1,20deg);
+		transform: rotate3d(0,0,1,20deg);
+	}
+}
+
+
+/***********************************************/
+/******************** krisna *******************/
+/***********************************************/
+
+
+.stack--krisna .stack__item--reject {
+	-webkit-animation: krisnaReject 0.5s forwards;
+	animation: krisnaReject 0.5s forwards;
+}
+
+@-webkit-keyframes krisnaReject {
+	to {
+		-webkit-transform: translate3d(-25vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+		transform: translate3d(-25vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+	}
+}
+
+@keyframes krisnaReject {
+	to {
+		-webkit-transform: translate3d(-25vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+		transform: translate3d(-25vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+	}
+}
+
+.stack--krisna .stack__item--accept {
+	-webkit-animation: krisnaAccept 0.5s forwards;
+	animation: krisnaAccept 0.5s forwards;
+}
+
+@-webkit-keyframes krisnaAccept {
+	to {
+		-webkit-transform: translate3d(25vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+		transform: translate3d(25vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+	}
+}
+
+@keyframes krisnaAccept {
+	to {
+		-webkit-transform: translate3d(25vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+		transform: translate3d(25vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+	}
+}
+
+/* ...when content has 100% viewport width */
+@media screen and (max-width: 60em) {
+	@-webkit-keyframes krisnaReject {
+		to {
+			-webkit-transform: translate3d(-50vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+			transform: translate3d(-50vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+		}
+	}
+
+	@keyframes krisnaReject {
+		to {
+			-webkit-transform: translate3d(-50vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+			transform: translate3d(-50vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+		}
+	}
+
+	@-webkit-keyframes krisnaAccept {
+		to {
+			-webkit-transform: translate3d(50vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+			transform: translate3d(50vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+		}
+	}
+
+	@keyframes krisnaAccept {
+		to {
+			-webkit-transform: translate3d(50vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+			transform: translate3d(50vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+		}
+	}
+}
+
+
+/***********************************************/
+/******************** wangi *********************/
+/***********************************************/
+
+.stack--wangi .stack__item--reject {
+	-webkit-animation: wangiReject 0.5s forwards;
+	animation: wangiReject 0.5s forwards;
+	-webkit-transform-origin: 0% 0%;
+	transform-origin: 0% 0%;
+}
+
+@-webkit-keyframes wangiReject {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(0, 400px,0) rotate3d(0,0,1,40deg);
+		transform: translate3d(0, 400px,0) rotate3d(0,0,1,40deg);
+	}
+}
+
+@keyframes wangiReject {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(0, 400px,0) rotate3d(0,0,1,40deg);
+		transform: translate3d(0, 400px,0) rotate3d(0,0,1,40deg);
+	}
+}
+
+.stack--wangi .stack__item--accept {
+	-webkit-animation: wangiAccept 0.5s forwards;
+	animation: wangiAccept 0.5s forwards;
+	-webkit-transform-origin: 100% 0%;
+	transform-origin: 100% 0%;
+}
+
+@-webkit-keyframes wangiAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(0, 400px,0) rotate3d(0,0,1,-40deg);
+		transform: translate3d(0, 400px,0) rotate3d(0,0,1,-40deg);
+	}
+}
+
+@keyframes wangiAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(0, 400px,0) rotate3d(0,0,1,-40deg);
+		transform: translate3d(0, 400px,0) rotate3d(0,0,1,-40deg);
+	}
+}
+
+
+/***********************************************/
+/********************* wira ********************/
+/***********************************************/
+
+
+.stack--wira .stack__item--reject {
+	-webkit-animation: wiraReject 0.5s forwards;
+	animation: wiraReject 0.5s forwards;
+	-webkit-animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+	animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+	-webkit-transform-origin: -150% 50%;
+	transform-origin: -150% 50%;
+}
+
+@-webkit-keyframes wiraReject {
+	to {
+		opacity: 0;
+		-webkit-transform: rotate3d(0,0,1,-60deg);
+		transform: rotate3d(0,0,1,-60deg);
+	}
+}
+
+@keyframes wiraReject {
+	to {
+		opacity: 0;
+		-webkit-transform: rotate3d(0,0,1,-60deg);
+		transform: rotate3d(0,0,1,-60deg);
+	}
+}
+
+.stack--wira .stack__item--accept {
+	-webkit-animation: wiraAccept 0.5s forwards;
+	animation: wiraAccept 0.5s forwards;
+	-webkit-animation-timing-function: cubic-bezier(0.3,1,0.3,1);
+	animation-timing-function: cubic-bezier(0.3,1,0.3,1);
+	-webkit-transform-origin: 250% 50%;
+	transform-origin: 250% 50%;
+}
+
+@-webkit-keyframes wiraAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: rotate3d(0,0,1,60deg);
+		transform: rotate3d(0,0,1,60deg);
+	}
+}
+
+@keyframes wiraAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: rotate3d(0,0,1,60deg);
+		transform: rotate3d(0,0,1,60deg);
+	}
+}
+
+
+/***********************************************/
+/******************** utari ********************/
+/***********************************************/
+
+.stack--utari .stack__item--reject {
+	-webkit-animation: utariReject 0.6s forwards;
+	animation: utariReject 0.6s forwards;
+	-webkit-animation-timing-function: ease-in;
+	animation-timing-function: ease-in;
+	-webkit-transform-origin: 50% 100%;
+	transform-origin: 50% 100%;
+}
+
+@-webkit-keyframes utariReject {
+	40% {
+		opacity: 1;
+		-webkit-animation-timing-function: ease-out;
+		animation-timing-function: ease-out;
+		-webkit-transform: translate3d(0,-20%,30px);
+		transform: translate3d(0,-20%,30px);
+	}
+	100% {
+		opacity: 0;
+		-webkit-transform: translate3d(0,150%,-300px) rotate3d(1,0,0,-40deg);
+		transform: translate3d(0,150%,-300px) rotate3d(1,0,0,-40deg);
+	}
+}
+
+@keyframes utariReject {
+	40% {
+		opacity: 1;
+		-webkit-animation-timing-function: ease-out;
+		animation-timing-function: ease-out;
+		-webkit-transform: translate3d(0,-20%,30px);
+		transform: translate3d(0,-20%,30px);
+	}
+	100% {
+		opacity: 0;
+		-webkit-transform: translate3d(0,150%,-300px) rotate3d(1,0,0,-40deg);
+		transform: translate3d(0,150%,-300px) rotate3d(1,0,0,-40deg);
+	}
+}
+
+.stack--utari .stack__item--accept {
+	-webkit-animation: utariAccept 0.6s forwards;
+	animation: utariAccept 0.6s forwards;
+	-webkit-animation-timing-function: ease-in;
+	animation-timing-function: ease-in;
+}
+
+@-webkit-keyframes utariAccept {
+	40% {
+		-webkit-animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+		animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+		-webkit-transform: translate3d(-40%,0,0) scale3d(1.1,1.1,1);
+		transform: translate3d(-40%,0,0) scale3d(1.1,1.1,1);
+	}
+	100% {
+		opacity: 0;
+		-webkit-transform: translate3d(25vw,0,0) translate3d(10%,0,0) scale3d(0.1,0.1,1);
+		transform: translate3d(25vw,0,0) translate3d(10%,0,0) scale3d(0.1,0.1,1);
+	}
+}
+
+@keyframes utariAccept {
+	40% {
+		-webkit-animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+		animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+		-webkit-transform: translate3d(-40%,0,0) scale3d(1.1,1.1,1);
+		transform: translate3d(-40%,0,0) scale3d(1.1,1.1,1);
+	}
+	100% {
+		opacity: 0;
+		-webkit-transform: translate3d(25vw,0,0) translate3d(10%,0,0) scale3d(0.1,0.1,1);
+		transform: translate3d(25vw,0,0) translate3d(10%,0,0) scale3d(0.1,0.1,1);
+	}
+}
+
+/* ...when content has 100% viewport width */
+@media screen and (max-width: 60em) {
+	@-webkit-keyframes utariAccept {
+		40% {
+			-webkit-animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+			animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+			-webkit-transform: translate3d(-40%,0,0) scale3d(1.1,1.1,1);
+			transform: translate3d(-40%,0,0) scale3d(1.1,1.1,1);
+		}
+		100% {
+			opacity: 0;
+			-webkit-transform: translate3d(50vw,0,0) translate3d(10%,0,0) scale3d(0.1,0.1,1);
+			transform: translate3d(50vw,0,0) translate3d(10%,0,0) scale3d(0.1,0.1,1);
+		}
+	}
+
+	@keyframes utariAccept {
+		40% {
+			-webkit-animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+			animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+			-webkit-transform: translate3d(-40%,0,0) scale3d(1.1,1.1,1);
+			transform: translate3d(-40%,0,0) scale3d(1.1,1.1,1);
+		}
+		100% {
+			opacity: 0;
+			-webkit-transform: translate3d(50vw,0,0) translate3d(10%,0,0) scale3d(0.1,0.1,1);
+			transform: translate3d(50vw,0,0) translate3d(10%,0,0) scale3d(0.1,0.1,1);
+		}
+	}	
+}
+
+/***********************************************/
+/******************* slamet ********************/
+/***********************************************/
+
+.counter {
+	position: absolute;
+	left: 50%;
+	top: 30px;
+	width: 40px;
+	margin-left: -20px;
+}
+
+.counter svg {
+	display: block;
+	margin: 14px auto 0;
+	fill: #58785A;
+}
+
+.counter__number {
+	text-align: center;
+	position: absolute;
+	background: #e66868;
+	font-size: 10px;
+	font-weight: bold;
+	color: #fff;
+	width: 20px;
+	height: 20px;
+	line-height: 20px;
+	border-radius: 50%;
+	bottom: -5px;
+	right: -5px;
+}
+
+.stack--slamet .stack__item--reject {
+	-webkit-animation: slametReject 0.5s forwards;
+	animation: slametReject 0.5s forwards;
+	-webkit-transform-origin: 50% 100%;
+	transform-origin: 50% 100%;
+}
+
+@-webkit-keyframes slametReject {
+	to {
+		opacity: 0;
+		-webkit-transform: rotate3d(1,0,0,-90deg);
+		transform: rotate3d(1,0,0,-90deg);
+	}
+}
+
+@keyframes slametReject {
+	to {
+		opacity: 0;
+		-webkit-transform: rotate3d(1,0,0,-90deg);
+		transform: rotate3d(1,0,0,-90deg);
+	}
+}
+
+.stack--slamet .stack__item--accept {
+	-webkit-animation: slametAccept 0.6s forwards;
+	animation: slametAccept 0.6s forwards;
+	-webkit-animation-timing-function: ease-in;
+	animation-timing-function: ease-in;
+}
+
+@-webkit-keyframes slametAccept {
+	40% {
+		-webkit-animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+		animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+		-webkit-transform: translate3d(0,20%,0) scale3d(1.1,1.1,1);
+		transform: translate3d(0,20%,0) scale3d(1.1,1.1,1);
+	}
+	80% {
+		opacity: 1;
+		-webkit-transform: translate3d(0,-280px,0) scale3d(0.1,0.1,1);
+		transform: translate3d(0,-280px,0) scale3d(0.1,0.1,1);
+	}
+	100% {
+		opacity: 0;
+		-webkit-transform: translate3d(0,-250px,0) scale3d(0.05,0.05,1);
+		transform: translate3d(0,-250px,0) scale3d(0.05,0.05,1);
+	}
+}
+
+@keyframes slametAccept {
+	40% {
+		-webkit-animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+		animation-timing-function: cubic-bezier(0.4,1,0.3,1);
+		-webkit-transform: translate3d(0,20%,0) scale3d(1.1,1.1,1);
+		transform: translate3d(0,20%,0) scale3d(1.1,1.1,1);
+	}
+	80% {
+		opacity: 1;
+		-webkit-transform: translate3d(0,-280px,0) scale3d(0.1,0.1,1);
+		transform: translate3d(0,-280px,0) scale3d(0.1,0.1,1);
+	}
+	100% {
+		opacity: 0;
+		-webkit-transform: translate3d(0,-250px,0) scale3d(0.05,0.05,1);
+		transform: translate3d(0,-250px,0) scale3d(0.05,0.05,1);
+	}
+}
+
+
+/***********************************************/
+/******************** eka **********************/
+/***********************************************/
+
+
+.stack--eka .stack__item--reject {
+	-webkit-animation: ekaReject 0.5s forwards;
+	animation: ekaReject 0.5s forwards;
+	-webkit-transform-origin: 100% 50%;
+	transform-origin: 100% 50%;
+}
+
+@-webkit-keyframes ekaReject {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(-150%,150%,0) rotate3d(0,0,1,-20deg);
+		transform: translate3d(-150%,150%,0) rotate3d(0,0,1,-20deg);
+	}
+}
+
+@keyframes ekaReject {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(-150%,150%,0) rotate3d(0,0,1,-20deg);
+		transform: translate3d(-150%,150%,0) rotate3d(0,0,1,-20deg);
+	}
+}
+
+.stack--eka .stack__item--accept {
+	-webkit-animation: ekaAccept 0.5s forwards;
+	animation: ekaAccept 0.5s forwards;
+	-webkit-transform-origin: -100% 50%;
+	transform-origin: -100% 50%;
+}
+
+@-webkit-keyframes ekaAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(150%,-150%,0) rotate3d(0,0,1,20deg);
+		transform: translate3d(150%,-150%,0) rotate3d(0,0,1,20deg);
+	}
+}
+
+@keyframes ekaAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(150%,-150%,0) rotate3d(0,0,1,20deg);
+		transform: translate3d(150%,-150%,0) rotate3d(0,0,1,20deg);
+	}
+}
+
+
+/***********************************************/
+/******************** dian *********************/
+/***********************************************/
+
+
+.stack--dian .stack__item--reject {
+	-webkit-animation: dianReject 0.5s forwards;
+	animation: dianReject 0.5s forwards;
+	-webkit-transform-origin: 50% -300%;
+	transform-origin: 50% -300%;
+}
+
+@-webkit-keyframes dianReject {
+	to {
+		opacity: 0;
+		-webkit-transform: rotate3d(0,0,1,20deg);
+		transform: rotate3d(0,0,1,20deg);
+	}
+}
+
+@keyframes dianReject {
+	to {
+		opacity: 0;
+		-webkit-transform: rotate3d(0,0,1,20deg);
+		transform: rotate3d(0,0,1,20deg);
+	}
+}
+
+.stack--dian .stack__item--accept {
+	-webkit-animation: dianAccept 0.5s forwards;
+	animation: dianAccept 0.5s forwards;
+	-webkit-transform-origin: 50% -300%;
+	transform-origin: 50% -300%;
+}
+
+@-webkit-keyframes dianAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: rotate3d(0,0,1,-20deg);
+		transform: rotate3d(0,0,1,-20deg);
+	}
+}
+
+@keyframes dianAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: rotate3d(0,0,1,-20deg);
+		transform: rotate3d(0,0,1,-20deg);
+	}
+}
+
+
+/***********************************************/
+/******************** iman *********************/
+/***********************************************/
+
+
+.stack--iman .stack__item--reject {
+	-webkit-animation: imanReject 0.5s forwards;
+	animation: imanReject 0.5s forwards;
+}
+
+@-webkit-keyframes imanReject {
+	to {
+		-webkit-transform: translate3d(-25vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+		transform: translate3d(-25vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+	}
+}
+
+@keyframes imanReject {
+	to {
+		-webkit-transform: translate3d(-25vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+		transform: translate3d(-25vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+	}
+}
+
+.stack--iman .stack__item--accept {
+	-webkit-animation: imanAccept 0.5s forwards;
+	animation: imanAccept 0.5s forwards;
+}
+
+@-webkit-keyframes imanAccept {
+	to {
+		-webkit-transform: translate3d(25vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+		transform: translate3d(25vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+	}
+}
+
+@keyframes imanAccept {
+	to {
+		-webkit-transform: translate3d(25vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+		transform: translate3d(25vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+	}
+}
+
+/* ...when content has 100% viewport width */
+@media screen and (max-width: 60em) {
+
+	@-webkit-keyframes imanReject {
+		to {
+			-webkit-transform: translate3d(-50vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+			transform: translate3d(-50vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+		}
+	}
+
+	@keyframes imanReject {
+		to {
+			-webkit-transform: translate3d(-50vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+			transform: translate3d(-50vw,0,0) translate3d(-60%,0,0) rotate3d(0,0,1,-5deg);
+		}
+	}
+
+	@-webkit-keyframes imanAccept {
+		to {
+			-webkit-transform: translate3d(50vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+			transform: translate3d(50vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+		}
+	}
+
+	@keyframes imanAccept {
+		to {
+			-webkit-transform: translate3d(50vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+			transform: translate3d(50vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+		}
+	}
+
+}
+
+/***********************************************/
+/****************** iskandar *******************/
+/***********************************************/
+
+
+.stack--iskandar .stack__item--reject {
+	-webkit-animation: iskandarReject 0.5s forwards;
+	animation: iskandarReject 0.5s forwards;
+	-webkit-transform-origin: 50% 0%;
+	transform-origin: 50% 0%;
+}
+
+@-webkit-keyframes iskandarReject {
+	50% {
+		opacity: 1;
+	}
+	100% {
+		opacity: 0;
+		-webkit-transform: translate3d(0,-100px,20px) rotate3d(1,0,0,90deg);
+		transform: translate3d(0,-100px,20px) rotate3d(1,0,0,90deg);
+	}
+}
+
+@keyframes iskandarReject {
+	50% {
+		opacity: 1;
+	}
+	100% {
+		opacity: 0;
+		-webkit-transform: translate3d(0,-100px,20px) rotate3d(1,0,0,90deg);
+		transform: translate3d(0,-100px,20px) rotate3d(1,0,0,90deg);
+	}
+}
+
+.stack--iskandar .stack__item--accept {
+	-webkit-animation: iskandarAccept 0.5s forwards;
+	animation: iskandarAccept 0.5s forwards;
+}
+
+@-webkit-keyframes iskandarAccept {
+	to {
+		-webkit-transform: translate3d(25vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+		transform: translate3d(25vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+	}
+}
+
+@keyframes iskandarAccept {
+	to {
+		-webkit-transform: translate3d(25vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+		transform: translate3d(25vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+	}
+}
+
+/* ...when content has 100% viewport width */
+@media screen and (max-width: 60em) {
+
+	@-webkit-keyframes iskandarAccept {
+		to {
+			-webkit-transform: translate3d(50vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+			transform: translate3d(50vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+		}
+	}
+
+	@keyframes iskandarAccept {
+		to {
+			-webkit-transform: translate3d(50vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+			transform: translate3d(50vw,0,0) translate3d(60%,0,0) rotate3d(0,0,1,5deg);
+		}
+	}
+
+}
+
+/***********************************************/
+/******************** kasih ********************/
+/***********************************************/
+
+
+.stack--kasih .stack__item--reject {
+	-webkit-animation: kasihReject 0.4s ease-in forwards;
+	animation: kasihReject 0.4s ease-in forwards;
+}
+
+@-webkit-keyframes kasihReject {
+	to {
+		-webkit-transform: translate3d(-25vw,0,0) translate3d(-60%,0,0);
+		transform: translate3d(-25vw,0,0) translate3d(-60%,0,0);
+	}
+}
+
+@keyframes kasihReject {
+	to {
+		-webkit-transform: translate3d(-25vw,0,0) translate3d(-60%,0,0);
+		transform: translate3d(-25vw,0,0) translate3d(-60%,0,0);
+	}
+}
+
+.stack--kasih .stack__item--accept {
+	-webkit-animation: kasihAccept 0.4s ease-in forwards;
+	animation: kasihAccept 0.4s ease-in forwards;
+}
+
+@-webkit-keyframes kasihAccept {
+	to {
+		-webkit-transform: translate3d(25vw,0,0) translate3d(60%,0,0);
+		transform: translate3d(25vw,0,0) translate3d(60%,0,0);
+	}
+}
+
+@keyframes kasihAccept {
+	to {
+		-webkit-transform: translate3d(25vw,0,0) translate3d(60%,0,0);
+		transform: translate3d(25vw,0,0) translate3d(60%,0,0);
+	}
+}
+
+/* ...when content has 100% vieport width */
+@media screen and (max-width: 60em) {
+	@-webkit-keyframes kasihReject {
+		to {
+			-webkit-transform: translate3d(-50vw,0,0) translate3d(-60%,0,0);
+			transform: translate3d(-50vw,0,0) translate3d(-60%,0,0);
+		}
+	}
+
+	@keyframes kasihReject {
+		to {
+			-webkit-transform: translate3d(-50vw,0,0) translate3d(-60%,0,0);
+			transform: translate3d(-50vw,0,0) translate3d(-60%,0,0);
+		}
+	}
+
+	@-webkit-keyframes kasihAccept {
+		to {
+			-webkit-transform: translate3d(50vw,0,0) translate3d(60%,0,0);
+			transform: translate3d(50vw,0,0) translate3d(60%,0,0);
+		}
+	}
+
+	@keyframes kasihAccept {
+		to {
+			-webkit-transform: translate3d(50vw,0,0) translate3d(60%,0,0);
+			transform: translate3d(50vw,0,0) translate3d(60%,0,0);
+		}
+	}
+}
+
+/***********************************************/
+/******************* buana ********************/
+/***********************************************/
+
+
+.stack--buana .stack__item--reject {
+	-webkit-animation: buanaReject 0.5s forwards;
+	animation: buanaReject 0.5s forwards;
+}
+
+@-webkit-keyframes buanaReject {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(-25%,200%,0) rotate3d(0,0,1,25deg);
+		transform: translate3d(-25%,200%,0) rotate3d(0,0,1,215deg);
+	}
+}
+
+@keyframes buanaReject {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(-25%,200%,0) rotate3d(0,0,1,25deg);
+		transform: translate3d(-25%,200%,0) rotate3d(0,0,1,25deg);
+	}
+}
+
+.stack--buana .stack__item--accept {
+	-webkit-animation: buanaAccept 0.5s forwards;
+	animation: buanaAccept 0.5s forwards;
+}
+
+@-webkit-keyframes buanaAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(25%,200%,0) rotate3d(0,0,1,-25deg);
+		transform: translate3d(25%,200%,0) rotate3d(0,0,1,-25deg);
+	}
+}
+
+@keyframes buanaAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(25%,200%,0) rotate3d(0,0,1,-25deg);
+		transform: translate3d(25%,200%,0) rotate3d(0,0,1,-25deg);
+	}
+}
+
+/***********************************************/
+/******************** mawar *********************/
+/***********************************************/
+
+.stack--mawar .stack__item--reject {
+	-webkit-animation: mawarReject 0.5s forwards;
+	animation: mawarReject 0.5s forwards;
+}
+
+@-webkit-keyframes mawarReject {
+	to {
+		-webkit-transform: translate3d(-25vw,0,0) translate3d(-60%,0,0);
+		transform: translate3d(-25vw,0,0) translate3d(-60%,0,0);
+	}
+}
+
+@keyframes mawarReject {
+	to {
+		-webkit-transform: translate3d(-25vw,0,0) translate3d(-60%,0,0);
+		transform: translate3d(-25vw,0,0) translate3d(-60%,0,0);
+	}
+}
+
+.stack--mawar .stack__item--accept {
+	-webkit-animation: mawarAccept 0.5s forwards;
+	animation: mawarAccept 0.5s forwards;
+	-webkit-transform-origin: 100% 50%;
+	transform-origin: 100% 50%;
+}
+
+@-webkit-keyframes mawarAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(150px,0,0) scale3d(0.7,0.7,1) rotate3d(0,1,0,90deg);
+		transform: translate3d(150px,0,0) scale3d(0.7,0.7,1) rotate3d(0,1,0,90deg);
+	}
+}
+
+@keyframes mawarAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(150px,0,0) scale3d(0.7,0.7,1) rotate3d(0,1,0,90deg);
+		transform: translate3d(150px,0,0) scale3d(0.7,0.7,1) rotate3d(0,1,0,90deg);
+	}
+}
+
+/* ...when content has 100% vieport width */
+@media screen and (max-width: 60em) {
+	
+	@-webkit-keyframes mawarReject {
+		to {
+			-webkit-transform: translate3d(-50vw,0,0) translate3d(-60%,0,0);
+			transform: translate3d(-50vw,0,0) translate3d(-60%,0,0);
+		}
+	}
+
+	@keyframes mawarReject {
+		to {
+			-webkit-transform: translate3d(-50vw,0,0) translate3d(-60%,0,0);
+			transform: translate3d(-50vw,0,0) translate3d(-60%,0,0);
+		}
+	}
+
+}
+
+
+/***********************************************/
+/******************** cinta **********************/
+/***********************************************/
+
+
+.stack--cinta .stack__item--reject {
+	-webkit-animation: cintaReject 0.5s forwards;
+	animation: cintaReject 0.5s forwards;
+}
+
+@-webkit-keyframes cintaReject {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(25vw,0,0) translate3d(60%,0,0);
+		transform: translate3d(25vw,0,0) translate3d(60%,0,0);
+	}
+}
+
+@keyframes cintaReject {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(25vw,0,0) translate3d(60%,0,0);
+		transform: translate3d(25vw,0,0) translate3d(60%,0,0);
+	}
+}
+
+.stack--cinta .stack__item--accept {
+	-webkit-animation: cintaAccept 0.5s forwards;
+	animation: cintaAccept 0.5s forwards;
+}
+
+@-webkit-keyframes cintaAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(0,0,1000px);
+		transform: translate3d(0,0,1000px);
+	}
+}
+
+@keyframes cintaAccept {
+	to {
+		opacity: 0;
+		-webkit-transform: translate3d(0,0,1000px);
+		transform: translate3d(0,0,1000px);
+	}
+}
+
+@media screen and (max-width: 60em) {
+	.stack {
+		width: 260px;
+		height: 260px;
+	}
+}

+ 54 - 0
src/styles/data-table.less

@@ -0,0 +1,54 @@
+  @import './base/setOnepx';
+ .head {
+        height: 36px;
+        display: flex;
+        align-items: center;
+        margin-left: 14px;
+    }
+
+.column1 {
+    flex-grow: 1;
+    display: flex;
+    align-items: center;
+    font-size: 12px;
+    color: #FFFFFF;
+    .num {
+        width: 18px;
+        height: 16px;
+        background: #666666;
+        border-radius: 2px;
+        line-height: 16px;
+        text-align: center;
+        margin-right: 10px;
+    }
+    .cover {
+        width: 24px;
+        height: 24px;
+        border-radius: 50%;
+        margin-right: 10px;
+    }
+    .name {
+        font-size: 13px;
+        color: #FFFFFF;
+    }
+}
+
+.column2 {
+    width: 50px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    font-size: 12px;
+    color: #FFFFFF;
+}
+
+.item {
+    display: flex;
+    height: 36px;
+    background: #1C2B3B;
+    margin-left: 14px;
+    position: relative;
+    &:after {
+        .setTopLine(rgba(241, 83, 53, 0.60));
+    }
+}

+ 266 - 0
src/styles/default.css

@@ -0,0 +1,266 @@
+@import url(http://fonts.useso.com/css?family=Raleway:200,500,700,800);
+@font-face {
+	font-family: 'icomoon';
+	src:url('../fonts/icomoon.eot?rretjt');
+	src:url('../fonts/icomoon.eot?#iefixrretjt') format('embedded-opentype'),
+		url('../fonts/icomoon.woff?rretjt') format('woff'),
+		url('../fonts/icomoon.ttf?rretjt') format('truetype'),
+		url('../fonts/icomoon.svg?rretjt#icomoon') format('svg');
+	font-weight: normal;
+	font-style: normal;
+}
+
+[class^="icon-"], [class*=" icon-"] {
+	font-family: 'icomoon';
+	speak: none;
+	font-style: normal;
+	font-weight: normal;
+	font-variant: normal;
+	text-transform: none;
+	line-height: 1;
+
+	/* Better Font Rendering =========== */
+	-webkit-font-smoothing: antialiased;
+	-moz-osx-font-smoothing: grayscale;
+}
+
+*, *:after, *:before { -webkit-box-sizing: border-box; box-sizing: border-box; }
+.clearfix:before, .clearfix:after {display: table;  content: ''; }
+.clearfix:after { clear: both; }
+
+body {
+	/* font-family: Avenir, 'Helvetica Neue', 'Lato', 'Segoe UI', Helvetica, Arial, sans-serif; */
+	color: #444;
+	background: #fff;
+	-webkit-font-smoothing: antialiased;
+	-moz-osx-font-smoothing: grayscale;
+}
+
+a {
+	outline: none;
+	color: #03a9f4;
+	text-decoration: none;
+}
+
+a:hover, a:focus {
+	color: #fff;
+}
+
+button:focus {
+	outline: none;
+}
+
+.container {
+	display: -webkit-flex;
+	display: flex;
+	-webkit-justify-content: center;
+	justify-content: center;
+	-webkit-align-items: center;
+	align-items: center;
+	-webkit-flex-wrap: wrap;
+	flex-wrap: wrap;
+}
+.bgcolor-1 { background: #f0efee; }
+.bgcolor-2 { background: #f9f9f9; }
+.bgcolor-3 { background: #e8e8e8; }/*light grey*/
+.bgcolor-4 { background: #2f3238; color: #fff; }/*Dark grey*/
+.bgcolor-5 { background: #df6659; color: #521e18; }/*pink1*/
+.bgcolor-6 { background: #2fa8ec; }/*sky blue*/
+.bgcolor-7 { background: #d0d6d6; }/*White tea*/
+.bgcolor-8 { background: #3d4444; color: #fff; }/*Dark grey2*/
+.bgcolor-9 { background: #ef3f52; color: #fff;}/*pink2*/
+.bgcolor-10{ background: #64448f; color: #fff;}/*Violet*/
+.bgcolor-11{ background: #3755ad; color: #fff;}/*dark blue*/
+.bgcolor-12{ background: #3498DB; color: #fff;}/*light blue*/
+.bgcolor-20{ background: #494A5F;color: #D5D6E2;}
+/* Header */
+.htmleaf-header{
+	width: 100%;
+	padding: 2em 1em 4em;
+	text-align: center;
+	color: #fff;
+	background: #66677c;
+}
+.htmleaf-header h1 {
+	color: #D5D6E2;
+	font-weight: 600;
+	font-size: 2em;
+	line-height: 1;
+	margin-bottom: 0;
+	/* font-family: "Microsoft YaHei","宋体","Segoe UI", "Lucida Grande", Helvetica, Arial,sans-serif, FreeSans, Arimo; */
+}
+.htmleaf-header h1 span {
+	/* font-family: "Microsoft YaHei","宋体","Segoe UI", "Lucida Grande", Helvetica, Arial,sans-serif, FreeSans, Arimo; */
+	display: block;
+	font-size: 60%;
+	font-weight: 400;
+	padding: 0.8em 0 0.5em 0;
+	color: #c3c8cd;
+}
+/*nav*/
+.htmleaf-demo a{color: #1d7db1;text-decoration: none;}
+.htmleaf-demo{width: 100%;padding-bottom: 1.2em;}
+.htmleaf-demo a{display: inline-block;margin: 0.5em;padding: 0.6em 1em;border: 3px solid #1d7db1;font-weight: 700;}
+.htmleaf-demo a:hover{opacity: 0.6;}
+.htmleaf-demo a.current{background:#1d7db1;color: #fff; }
+/* Top Navigation Style */
+.htmleaf-links {
+	position: relative;
+	display: inline-block;
+	white-space: nowrap;
+	font-size: 1.5em;
+	text-align: center;
+}
+
+.htmleaf-links::after {
+	position: absolute;
+	top: 0;
+	left: 50%;
+	margin-left: -1px;
+	width: 2px;
+	height: 100%;
+	background: #dbdbdb;
+	content: '';
+	-webkit-transform: rotate3d(0,0,1,22.5deg);
+	transform: rotate3d(0,0,1,22.5deg);
+}
+
+.htmleaf-icon {
+	display: inline-block;
+	margin: 0.5em;
+	padding: 0em 0;
+	width: 1.5em;
+	text-decoration: none;
+}
+
+.htmleaf-icon span {
+	display: none;
+}
+
+.htmleaf-icon:before {
+	margin: 0 5px;
+	text-transform: none;
+	font-weight: normal;
+	font-style: normal;
+	font-variant: normal;
+	font-family: 'icomoon';
+	line-height: 1;
+	speak: none;
+	-webkit-font-smoothing: antialiased;
+}
+/* Content */
+.content {
+	-webkit-align-self: stretch;
+	align-self: stretch;
+	overflow: hidden;
+	padding: 2em 2em 6em;
+	width: 50%;
+	position: relative;
+	display: -webkit-flex;
+	display: flex;
+	-webkit-justify-content: center;
+	justify-content: center;
+	-webkit-align-items: center;
+	align-items: center;
+	-webkit-flex-direction: column;
+	flex-direction: column;
+}
+
+.content:nth-child(even):last-child {
+	width: 100%;
+}
+
+.content__title {
+	margin: 0 auto 6em 0;
+	font-size: 1em;
+	z-index: 100;
+	position: relative;
+	color: rgba(0,0,0,0.25);
+}
+
+.color-0 { background: #3f51b5; }
+.color-1 { background: #5cc2f1; }
+.color-2 { background: #fff59d; }
+.color-3 { background: #9993c1; }
+.color-4 { background: #e88a63; }
+.color-5 { background: #91c794; }
+.color-6 { background: #565f77; }
+.color-7 { background: #9d62c5; }
+.color-8 { background: #EA9292; }
+.color-9 { background: #7c79ce; }
+/* footer */
+.htmleaf-footer{width: 100%;padding-top: 10px;}
+.htmleaf-small{font-size: 0.8em;}
+.center{text-align: center;}
+
+.related {
+	width: 100%;
+	color: #fff;
+	background: #494A5F;
+	text-align: center;
+	font-size: 1.25em;
+	padding: 0.5em 0;
+	overflow: hidden;
+}
+
+.related > a {
+	vertical-align: top;
+	width: calc(100% - 20px);
+	max-width: 340px;
+	display: inline-block;
+	text-align: center;
+	margin: 20px 10px;
+	padding: 25px;
+	/* font-family: "Microsoft YaHei","宋体","Segoe UI", "Lucida Grande", Helvetica, Arial,sans-serif, FreeSans, Arimo; */
+}
+.related a {
+	display: inline-block;
+	text-align: left;
+	margin: 20px auto;
+	padding: 10px 20px;
+	opacity: 0.8;
+	-webkit-transition: opacity 0.3s;
+	transition: opacity 0.3s;
+	-webkit-backface-visibility: hidden;
+}
+
+.related a:hover,
+.related a:active {
+	opacity: 1;
+}
+
+.related a img {
+	max-width: 100%;
+	opacity: 0.8;
+	border-radius: 4px;
+}
+.related a:hover img,
+.related a:active img {
+	opacity: 1;
+}
+.related h3{font-family: "Microsoft YaHei", sans-serif;}
+.related a h3 {
+	font-weight: 300;
+	margin-top: 0.15em;
+	color: #fff;
+}
+/* icomoon */
+.icon-htmleaf-home-outline:before {
+	content: "\e5000";
+}
+
+.icon-htmleaf-arrow-forward-outline:before {
+	content: "\e5001";
+}
+
+@media screen and (max-width: 60em) {
+	.htmleaf-header h1 {
+		font-size: 3em;
+	}
+	.content {
+		width: 100%;
+	}
+	.related {
+		font-size: 0.9em;
+	}
+}

+ 7 - 0
src/styles/fn.less

@@ -0,0 +1,7 @@
+// mixin
+@import "./base/mobile";
+@import "./base/setOnepx";
+@import "./base/setArrow";
+@import "./base/text";
+
+

+ 1 - 0
src/styles/normalize.css

@@ -0,0 +1 @@
+article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}audio,canvas,video{display:inline-block;}audio:not([controls]){display:none;height:0;}[hidden]{display:none;}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}body{margin:0;}a:focus{outline:thin dotted;}a:active,a:hover{outline:0;}h1{font-size:2em;margin:0.67em 0;}abbr[title]{border-bottom:1px dotted;}b,strong{font-weight:bold;}dfn{font-style:italic;}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}mark{background:#ff0;color:#000;}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em;}pre{white-space:pre-wrap;}q{quotes:"\201C" "\201D" "\2018" "\2019";}small{font-size:80%;}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}sup{top:-0.5em;}sub{bottom:-0.25em;}img{border:0;}svg:not(:root){overflow:hidden;}figure{margin:0;}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}legend{border:0;padding:0;}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}button,input{line-height:normal;}button,select{text-transform:none;}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}button[disabled],html input[disabled]{cursor:default;}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}textarea{overflow:auto;vertical-align:top;}table{border-collapse:collapse;border-spacing:0;}

+ 52 - 0
src/styles/reset.less

@@ -0,0 +1,52 @@
+@import "fn.less";
+
+html {
+    -ms-text-size-adjust: 100%;
+    -webkit-text-size-adjust: 100%;
+    height: 100%;
+    width: 100%;
+    overflow : hidden;
+    background: #F3F4F5;
+}
+
+body {
+    line-height: 1.6;
+    font-family: -apple-system-font,"Helvetica Neue",sans-serif;
+    height: 100%;
+    width: 100%;
+    overflow-x: hidden;
+    overflow-y: scroll;
+    background: #F3F4F5;
+}
+
+pre {
+     font-family: -apple-system-font,"Helvetica Neue",sans-serif;
+}
+
+* {
+    margin: 0;
+    padding: 0;
+}
+
+a img {
+    border: 0;
+}
+
+a {
+    text-decoration: none;
+    .setTapColor();
+}
+
+input,textarea,button{
+    border: none;
+    outline: none;
+	background: none;
+    appearance: none;
+}
+
+ul,li{
+    appearance: none;
+    margin: 0;
+    padding: 0;
+    list-style-type:none;
+}

+ 21 - 0
src/styles/sub-tab.less

@@ -0,0 +1,21 @@
+.subTabs {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    height: 36px;
+    background: #2B3B4C;
+}
+
+.subTabs .subTab {
+    flex-basis: 0;
+    flex-grow: 1;
+    font-size: 12px;
+    color: rgba(255, 255, 255, 0.60);
+    height: 36px;
+    line-height: 36px;
+    text-align: center;
+}
+
+.subTabs .subTab.active {
+    color: #F15436;
+}

+ 43 - 0
src/styles/tab.less

@@ -0,0 +1,43 @@
+.tabs {
+    display: flex;
+    align-items: center;
+    background: rgba(0, 0, 0, 0.60);
+    width: 100%;
+    position: absolute;
+    bottom: 0;
+    height: 42px;
+}
+
+.tabs .tab {
+    font-size: 12px;
+    color: #FFFFFF;
+    flex-basis: 0;
+    flex-grow: 1;
+    text-align: center;
+    height: 42px;
+    line-height: 42px;
+    position: relative;
+    box-sizing: border-box;
+    padding-bottom: 2px;
+}
+
+.tabs .tab.active {
+    color: #F15436;
+    border-bottom: 2px solid #F15436;
+}
+
+.tabs .tab::after {
+    content: ' ';
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    right: 0;
+    width: 1px;
+    height: 12px;
+    background: #fff;
+    margin: auto;
+}
+
+.tabs .tab:last-child::after {
+    content: none;
+}

+ 32 - 0
src/vuex/index.js

@@ -0,0 +1,32 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+
+Vue.use(Vuex);
+
+export default new Vuex.Store({
+    state: {
+        tableHeight: 0,
+        fetchingData: false,
+        userInfo: null,
+        clientWidth: 0,
+        isChinese: true,
+        direction: true,
+    },
+    mutations: {
+        updateTableHeight(state, height) {
+            state.tableHeight = height;
+        },
+        updateFetchingData(state, fetchingData) {
+            state.fetchingData = fetchingData
+        },
+        updateClientWidth(state, width) {
+            state.clientWidth = width
+        },
+        updateIsChinese(state, isChinese) {
+            state.isChinese = isChinese
+        },
+        updateDirection(state, direction) {
+            state.direction = direction
+        }
+    }
+})

+ 0 - 0
static/.gitkeep