浏览代码

提交源代码

liyunfeng 7 年之前
当前提交
4af7b826f9
共有 100 个文件被更改,包括 4778 次插入0 次删除
  1. 19 0
      .babelrc
  2. 9 0
      .editorconfig
  3. 5 0
      .gitignore
  4. 9 0
      .postcssrc.js
  5. 118 0
      build/.bootstraprc
  6. 35 0
      build/build.js
  7. 45 0
      build/check-versions.js
  8. 45 0
      build/customizations.scss
  9. 9 0
      build/dev-client.js
  10. 89 0
      build/dev-server.js
  11. 71 0
      build/utils.js
  12. 12 0
      build/vue-loader.conf.js
  13. 76 0
      build/webpack.base.conf.js
  14. 35 0
      build/webpack.dev.conf.js
  15. 120 0
      build/webpack.prod.conf.js
  16. 6 0
      config/dev.env.js
  17. 38 0
      config/index.js
  18. 3 0
      config/prod.env.js
  19. 1 0
      dist/index.html
  20. 1 0
      dist/static/css/app.c0a221a4263be2968fc1de35ca54372b.css
  21. 1 0
      dist/static/css/app.c0a221a4263be2968fc1de35ca54372b.css.map
  22. 二进制
      dist/static/fonts/element-icons.b02bdc1.ttf
  23. 二进制
      dist/static/fonts/glyphicons-halflings-regular.448c34a.woff2
  24. 二进制
      dist/static/fonts/glyphicons-halflings-regular.e18bbf6.ttf
  25. 二进制
      dist/static/fonts/glyphicons-halflings-regular.f4769f9.eot
  26. 二进制
      dist/static/fonts/glyphicons-halflings-regular.fa27723.woff
  27. 288 0
      dist/static/img/glyphicons-halflings-regular.8988968.svg
  28. 二进制
      dist/static/img/logo-x2.18951f4.png
  29. 二进制
      dist/static/img/pcenter.d98fa22.png
  30. 二进制
      dist/static/img/qrcode.c1c21c0.png
  31. 2 0
      dist/static/js/app.6691b4d0427d7149a85e.js
  32. 1 0
      dist/static/js/app.6691b4d0427d7149a85e.js.map
  33. 2 0
      dist/static/js/manifest.c81f8109ed0bf39343fc.js
  34. 1 0
      dist/static/js/manifest.c81f8109ed0bf39343fc.js.map
  35. 50 0
      dist/static/js/vendor.f0a8c451559fe42b9056.js
  36. 1 0
      dist/static/js/vendor.f0a8c451559fe42b9056.js.map
  37. 12 0
      index.html
  38. 82 0
      package.json
  39. 133 0
      src/App.vue
  40. 二进制
      src/assets/account.png
  41. 二进制
      src/assets/active-user.png
  42. 二进制
      src/assets/attention.png
  43. 二进制
      src/assets/aword.png
  44. 二进制
      src/assets/baidu.png
  45. 二进制
      src/assets/dynamic.png
  46. 二进制
      src/assets/english.png
  47. 二进制
      src/assets/exit.png
  48. 二进制
      src/assets/follow.png
  49. 二进制
      src/assets/glossary.png
  50. 二进制
      src/assets/google.png
  51. 二进制
      src/assets/headimg-def.png
  52. 二进制
      src/assets/headimg.png
  53. 二进制
      src/assets/home.png
  54. 二进制
      src/assets/idencode.png
  55. 二进制
      src/assets/intro.png
  56. 二进制
      src/assets/invite-code.png
  57. 二进制
      src/assets/japen.png
  58. 二进制
      src/assets/location.png
  59. 二进制
      src/assets/logo-x2.png
  60. 二进制
      src/assets/mission.png
  61. 二进制
      src/assets/msg-none.png
  62. 二进制
      src/assets/msg.png
  63. 二进制
      src/assets/next.png
  64. 二进制
      src/assets/notice.png
  65. 二进制
      src/assets/opt-remove.png
  66. 二进制
      src/assets/password.png
  67. 二进制
      src/assets/pcenter.png
  68. 二进制
      src/assets/phone.png
  69. 二进制
      src/assets/publish-icon.png
  70. 二进制
      src/assets/qie-active.png
  71. 二进制
      src/assets/qie.png
  72. 二进制
      src/assets/qrcode.png
  73. 二进制
      src/assets/rank.png
  74. 二进制
      src/assets/rank1.png
  75. 二进制
      src/assets/rank2.png
  76. 二进制
      src/assets/rank3.png
  77. 二进制
      src/assets/remove.png
  78. 二进制
      src/assets/school.png
  79. 二进制
      src/assets/setting.png
  80. 二进制
      src/assets/switch-close.png
  81. 二进制
      src/assets/switch-open.png
  82. 二进制
      src/assets/trans-list.png
  83. 二进制
      src/assets/transkill.png
  84. 二进制
      src/assets/up-active.png
  85. 二进制
      src/assets/up.png
  86. 二进制
      src/assets/youdao.png
  87. 666 0
      src/components/Calendar.vue
  88. 79 0
      src/components/Follow.vue
  89. 55 0
      src/components/Footer.vue
  90. 105 0
      src/components/Forget.vue
  91. 227 0
      src/components/Header.vue
  92. 941 0
      src/components/Home.vue
  93. 23 0
      src/components/Index.vue
  94. 184 0
      src/components/Letter.vue
  95. 56 0
      src/components/List.vue
  96. 204 0
      src/components/Login.vue
  97. 110 0
      src/components/Message.vue
  98. 355 0
      src/components/Mission.vue
  99. 454 0
      src/components/Person.vue
  100. 0 0
      src/components/Proof.vue

+ 19 - 0
.babelrc

@@ -0,0 +1,19 @@
+{
+  "presets": [
+    ["env"],
+    "stage-2"
+  ],
+  "plugins": ["transform-runtime",["component", [
+      {
+          "libraryName": "element-ui",
+          "styleLibraryName": "theme-default"
+      }
+  ]]],
+  "comments": false,
+  "env": {
+    "test": {
+      "presets": ["env", "stage-2"],
+      "plugins": [ "istanbul" ]
+    }
+  }
+}

+ 9 - 0
.editorconfig

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

+ 5 - 0
.gitignore

@@ -0,0 +1,5 @@
+.DS_Store
+node_modules/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*

+ 9 - 0
.postcssrc.js

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

+ 118 - 0
build/.bootstraprc

@@ -0,0 +1,118 @@
+
+---
+# Output debugging info
+# loglevel: debug
+
+# Major version of Bootstrap: 3 or 4
+bootstrapVersion: 3
+
+# If Bootstrap version 3 is used - turn on/off custom icon font path
+useCustomIconFontPath: false
+
+# Webpack loaders, order matters
+styleLoaders:
+  - style
+  - css
+  - sass
+
+# Extract styles to stand-alone css file
+# Different settings for different environments can be used,
+# It depends on value of NODE_ENV environment variable
+# This param can also be set in webpack config:
+#   entry: 'bootstrap-loader/extractStyles'
+extractStyles: false
+# env:
+#   development:
+#     extractStyles: false
+#   production:
+#     extractStyles: true
+
+
+# Customize Bootstrap variables that get imported before the original Bootstrap variables.
+# Thus, derived Bootstrap variables can depend on values from here.
+# See the Bootstrap _variables.scss file for examples of derived Bootstrap variables.
+#
+# preBootstrapCustomizations: ./path/to/bootstrap/pre-customizations.scss
+preBootstrapCustomizations: ./customizations.scss
+
+
+# This gets loaded after bootstrap/variables is loaded
+# Thus, you may customize Bootstrap variables
+# based on the values established in the Bootstrap _variables.scss file
+#
+# bootstrapCustomizations: ./path/to/bootstrap/customizations.scss
+
+
+# Import your custom styles here
+# Usually this endpoint-file contains list of @imports of your application styles
+#
+# appStyles: ./path/to/your/app/styles/endpoint.scss
+
+
+### Bootstrap styles
+styles:
+
+  # Mixins
+  mixins: true
+
+  # Reset and dependencies
+  normalize: true
+  print: true
+  glyphicons: true
+
+  # Core CSS
+  scaffolding: true
+  type: true
+  code: true
+  grid: true
+  tables: true
+  forms: true
+  buttons: true
+
+  # Components
+  component-animations: true
+  dropdowns: true
+  button-groups: true
+  input-groups: true
+  navs: true
+  navbar: true
+  breadcrumbs: true
+  pagination: true
+  pager: true
+  labels: true
+  badges: true
+  jumbotron: true
+  thumbnails: true
+  alerts: true
+  progress-bars: true
+  media: true
+  list-group: true
+  panels: true
+  wells: true
+  responsive-embed: true
+  close: true
+
+  # Components w/ JavaScript
+  modals: true
+  tooltip: true
+  popovers: true
+  carousel: true
+
+  # Utility classes
+  utilities: true
+  responsive-utilities: true
+
+### Bootstrap scripts
+scripts:
+  transition: true
+  alert: true
+  button: true
+  carousel: true
+  collapse: true
+  dropdown: true
+  modal: true
+  tooltip: true
+  popover: true
+  scrollspy: true
+  tab: true
+  affix: true

+ 35 - 0
build/build.js

@@ -0,0 +1,35 @@
+require('./check-versions')()
+
+process.env.NODE_ENV = 'production'
+
+var ora = require('ora')
+var rm = require('rimraf')
+var path = require('path')
+var chalk = require('chalk')
+var webpack = require('webpack')
+var config = require('../config')
+var webpackConfig = require('./webpack.prod.conf')
+
+var spinner = ora('building for production...')
+spinner.start()
+
+rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
+  if (err) throw err
+  webpack(webpackConfig, function (err, stats) {
+    spinner.stop()
+    if (err) throw err
+    process.stdout.write(stats.toString({
+      colors: true,
+      modules: false,
+      children: false,
+      chunks: false,
+      chunkModules: false
+    }) + '\n\n')
+
+    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'
+    ))
+  })
+})

+ 45 - 0
build/check-versions.js

@@ -0,0 +1,45 @@
+var chalk = require('chalk')
+var semver = require('semver')
+var packageConfig = require('../package.json')
+
+function exec (cmd) {
+  return require('child_process').execSync(cmd).toString().trim()
+}
+
+var versionRequirements = [
+  {
+    name: 'node',
+    currentVersion: semver.clean(process.version),
+    versionRequirement: packageConfig.engines.node
+  },
+  {
+    name: 'npm',
+    currentVersion: exec('npm --version'),
+    versionRequirement: packageConfig.engines.npm
+  }
+]
+
+module.exports = function () {
+  var warnings = []
+  for (var i = 0; i < versionRequirements.length; i++) {
+    var 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 (var i = 0; i < warnings.length; i++) {
+      var warning = warnings[i]
+      console.log('  ' + warning)
+    }
+    console.log()
+    process.exit(1)
+  }
+}

+ 45 - 0
build/customizations.scss

@@ -0,0 +1,45 @@
+$font-family-sans-serif:  Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,SimSun,sans-serif;
+
+$brand-primary:         darken(#fdb92c, 6.5%) !default; // #337ab7
+$brand-success:         #11b471 !default;
+$brand-info:            #5bc0de !default;
+$brand-warning:         #f0ad4e !default;
+$brand-danger:          #fe5e5e !default;
+
+$border-radius-base:        0px !default;
+$border-radius-large:       0px !default;
+$border-radius-small:       0px !default;
+
+//导航链接悬停背景色
+$nav-link-hover-bg: lighten($brand-primary, 30%) !default;
+
+//tab页active背景色和文字颜色
+$nav-tabs-active-link-hover-bg:             $brand-primary !default;
+$nav-tabs-active-link-hover-color:          #fff !default;
+
+$btn-border-radius-base:         17px !default;
+$btn-border-radius-large:        23px !default;
+$btn-border-radius-small:        15px !default;
+
+$input-bg:                       #f7f7f7 !default;
+//** Text color for `<input>`s
+$input-color:                    #000000 !default;
+//** `<input>` border color
+$input-border:                   #d6d6d6 !default;
+//** Default `.form-control` border radius
+// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS.
+$input-border-radius:            17px !default;
+//** Large `.form-control` border radius
+$input-border-radius-large:      23px !default;
+//** Small `.form-control` border radius
+$input-border-radius-small:      15px !default;
+
+//** Border color for inputs on focus
+$input-border-focus:             #fdb92c !default;
+
+//** Placeholder text color
+$input-color-placeholder:        #b8b8b8 !default;
+
+$progress-border-radius:      10px !default;
+
+$grid-gutter-width:         20px !default;

+ 9 - 0
build/dev-client.js

@@ -0,0 +1,9 @@
+/* eslint-disable */
+require('eventsource-polyfill')
+var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
+
+hotClient.subscribe(function (event) {
+  if (event.action === 'reload') {
+    window.location.reload()
+  }
+})

+ 89 - 0
build/dev-server.js

@@ -0,0 +1,89 @@
+require('./check-versions')()
+
+var config = require('../config')
+if (!process.env.NODE_ENV) {
+  process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
+}
+
+var opn = require('opn')
+var path = require('path')
+var express = require('express')
+var webpack = require('webpack')
+var proxyMiddleware = require('http-proxy-middleware')
+var webpackConfig = require('./webpack.dev.conf')
+
+// default port where dev server listens for incoming traffic
+var port = process.env.PORT || config.dev.port
+// automatically open browser, if not set will be false
+var autoOpenBrowser = !!config.dev.autoOpenBrowser
+// Define HTTP proxies to your custom API backend
+// https://github.com/chimurai/http-proxy-middleware
+var proxyTable = config.dev.proxyTable
+
+var app = express()
+var compiler = webpack(webpackConfig)
+
+var devMiddleware = require('webpack-dev-middleware')(compiler, {
+  publicPath: webpackConfig.output.publicPath,
+  quiet: true
+})
+
+var hotMiddleware = require('webpack-hot-middleware')(compiler, {
+  log: () => {}
+})
+// force page reload when html-webpack-plugin template changes
+compiler.plugin('compilation', function (compilation) {
+  compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
+    hotMiddleware.publish({ action: 'reload' })
+    cb()
+  })
+})
+
+// proxy api requests
+Object.keys(proxyTable).forEach(function (context) {
+  var options = proxyTable[context]
+  if (typeof options === 'string') {
+    options = { target: options }
+  }
+  app.use(proxyMiddleware(options.filter || context, options))
+})
+
+// handle fallback for HTML5 history API
+app.use(require('connect-history-api-fallback')())
+
+// serve webpack bundle output
+app.use(devMiddleware)
+
+// enable hot-reload and state-preserving
+// compilation error display
+app.use(hotMiddleware)
+
+// serve pure static assets
+var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
+app.use(staticPath, express.static('./static'))
+
+var uri = 'http://localhost:' + port
+
+var _resolve
+var readyPromise = new Promise(resolve => {
+  _resolve = resolve
+})
+
+console.log('> Starting dev server...')
+devMiddleware.waitUntilValid(() => {
+  console.log('> Listening at ' + uri + '\n')
+  // when env is testing, don't need open it
+  if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
+    opn(uri)
+  }
+  _resolve()
+})
+
+var server = app.listen(port)
+
+module.exports = {
+  ready: readyPromise,
+  close: () => {
+    server.close()
+  }
+}

+ 71 - 0
build/utils.js

@@ -0,0 +1,71 @@
+var path = require('path')
+var config = require('../config')
+var ExtractTextPlugin = require('extract-text-webpack-plugin')
+
+exports.assetsPath = function (_path) {
+  var assetsSubDirectory = process.env.NODE_ENV === 'production'
+    ? config.build.assetsSubDirectory
+    : config.dev.assetsSubDirectory
+  return path.posix.join(assetsSubDirectory, _path)
+}
+
+exports.cssLoaders = function (options) {
+  options = options || {}
+
+  var cssLoader = {
+    loader: 'css-loader',
+    options: {
+      minimize: process.env.NODE_ENV === 'production',
+      sourceMap: options.sourceMap
+    }
+  }
+
+  // generate loader string to be used with extract text plugin
+  function generateLoaders (loader, loaderOptions) {
+    var loaders = [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) {
+  var output = []
+  var loaders = exports.cssLoaders(options)
+  for (var extension in loaders) {
+    var loader = loaders[extension]
+    output.push({
+      test: new RegExp('\\.' + extension + '$'),
+      use: loader
+    })
+  }
+  return output
+}

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

@@ -0,0 +1,12 @@
+var utils = require('./utils')
+var config = require('../config')
+var isProduction = process.env.NODE_ENV === 'production'
+
+module.exports = {
+  loaders: utils.cssLoaders({
+    sourceMap: isProduction
+      ? config.build.productionSourceMap
+      : config.dev.cssSourceMap,
+    extract: isProduction
+  })
+}

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

@@ -0,0 +1,76 @@
+var path = require('path')
+var utils = require('./utils')
+var config = require('../config')
+var vueLoaderConfig = require('./vue-loader.conf')
+var webpack = require('webpack');
+
+function resolve (dir) {
+    return path.join(__dirname, '..', dir)
+}
+
+module.exports = {
+    entry: {
+        app: [`bootstrap-loader/lib/bootstrap.loader?configFilePath=${__dirname}/.bootstraprc!bootstrap-loader/no-op.js`,'./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: {
+            '@': resolve('src')
+        }
+    },
+    module: {
+        rules: [
+            {
+                test: /\.vue$/,
+                loader: 'vue-loader',
+                options: vueLoaderConfig
+            },
+            {
+                test: /\.js$/,
+                loader: 'babel-loader',
+                include: [resolve('src'), resolve('test')]
+            },
+            {
+                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
+                loader: 'url-loader',
+                options: {
+                    limit: 10000,
+                    name: utils.assetsPath('img/[name].[hash:7].[ext]')
+                }
+            },
+            {
+                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
+                loader: 'url-loader',
+                options: {
+                    limit: 10000,
+                    name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
+                }
+            },
+            {
+                test: /bootstrap-sass\/assets\/javascripts\//,
+                loader: 'imports-loader?jQuery=jquery'
+            },
+            {
+                test: /\.svg$/,
+                loader: 'raw-loader',
+                include: [
+                    resolve('src/assets/svg')
+                ]
+            }
+        ]
+    },
+    plugins: [
+        new webpack.ProvidePlugin({
+            $: "jquery",
+            jQuery: "jquery",
+            'window.jQuery':"jquery"
+        })
+    ]
+}

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

@@ -0,0 +1,35 @@
+var utils = require('./utils')
+var webpack = require('webpack')
+var config = require('../config')
+var merge = require('webpack-merge')
+var baseWebpackConfig = require('./webpack.base.conf')
+var HtmlWebpackPlugin = require('html-webpack-plugin')
+var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
+
+// add hot-reload related code to entry chunks
+Object.keys(baseWebpackConfig.entry).forEach(function (name) {
+  baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
+})
+
+module.exports = merge(baseWebpackConfig, {
+  module: {
+    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
+  },
+  // cheap-module-eval-source-map is faster for development
+  devtool: '#cheap-module-eval-source-map',
+  plugins: [
+    new webpack.DefinePlugin({
+      'process.env': config.dev.env
+    }),
+    // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
+    new webpack.HotModuleReplacementPlugin(),
+    new webpack.NoEmitOnErrorsPlugin(),
+    // https://github.com/ampedandwired/html-webpack-plugin
+    new HtmlWebpackPlugin({
+      filename: 'index.html',
+      template: 'index.html',
+      inject: true
+    }),
+    new FriendlyErrorsPlugin()
+  ]
+})

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

@@ -0,0 +1,120 @@
+var path = require('path')
+var utils = require('./utils')
+var webpack = require('webpack')
+var config = require('../config')
+var merge = require('webpack-merge')
+var baseWebpackConfig = require('./webpack.base.conf')
+var CopyWebpackPlugin = require('copy-webpack-plugin')
+var HtmlWebpackPlugin = require('html-webpack-plugin')
+var ExtractTextPlugin = require('extract-text-webpack-plugin')
+var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
+
+var env = config.build.env
+
+var webpackConfig = merge(baseWebpackConfig, {
+  module: {
+    rules: utils.styleLoaders({
+      sourceMap: config.build.productionSourceMap,
+      extract: true
+    })
+  },
+  devtool: config.build.productionSourceMap ? '#source-map' : 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 webpack.optimize.UglifyJsPlugin({
+      compress: {
+        warnings: false
+      },
+      sourceMap: true
+    }),
+    // extract css into its own file
+    new ExtractTextPlugin({
+      filename: utils.assetsPath('css/[name].[contenthash].css')
+    }),
+    // Compress extracted CSS. We are using this plugin so that possible
+    // duplicated CSS from different components can be deduped.
+    new OptimizeCSSPlugin({
+      cssProcessorOptions: {
+        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'
+    }),
+    // split vendor js into its own file
+    new webpack.optimize.CommonsChunkPlugin({
+      name: 'vendor',
+      minChunks: function (module, count) {
+        // 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',
+      chunks: ['vendor']
+    }),
+    // copy custom static assets
+    new CopyWebpackPlugin([
+      {
+        from: path.resolve(__dirname, '../static'),
+        to: config.build.assetsSubDirectory,
+        ignore: ['.*']
+      }
+    ])
+  ]
+})
+
+if (config.build.productionGzip) {
+  var 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) {
+  var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
+  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
+}
+
+module.exports = webpackConfig

+ 6 - 0
config/dev.env.js

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

+ 38 - 0
config/index.js

@@ -0,0 +1,38 @@
+// see http://vuejs-templates.github.io/webpack for documentation.
+var path = require('path')
+
+module.exports = {
+  build: {
+    env: require('./prod.env'),
+    index: path.resolve(__dirname, '../dist/index.html'),
+    assetsRoot: path.resolve(__dirname, '../dist'),
+    assetsSubDirectory: 'static',
+    assetsPublicPath: '/',
+    productionSourceMap: true,
+    // 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
+  },
+  dev: {
+    env: require('./dev.env'),
+    port: 8080,
+    autoOpenBrowser: true,
+    assetsSubDirectory: 'static',
+    assetsPublicPath: '/',
+    proxyTable: {},
+    // CSS Sourcemaps off by default because relative paths are "buggy"
+    // with this option, according to the CSS-Loader README
+    // (https://github.com/webpack/css-loader#sourcemaps)
+    // In our experience, they generally work as expected,
+    // just be aware of this issue when enabling this option.
+    cssSourceMap: false
+  }
+}

+ 3 - 0
config/prod.env.js

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

文件差异内容过多而无法显示
+ 1 - 0
dist/index.html


文件差异内容过多而无法显示
+ 1 - 0
dist/static/css/app.c0a221a4263be2968fc1de35ca54372b.css


文件差异内容过多而无法显示
+ 1 - 0
dist/static/css/app.c0a221a4263be2968fc1de35ca54372b.css.map


二进制
dist/static/fonts/element-icons.b02bdc1.ttf


二进制
dist/static/fonts/glyphicons-halflings-regular.448c34a.woff2


二进制
dist/static/fonts/glyphicons-halflings-regular.e18bbf6.ttf


二进制
dist/static/fonts/glyphicons-halflings-regular.f4769f9.eot


二进制
dist/static/fonts/glyphicons-halflings-regular.fa27723.woff


文件差异内容过多而无法显示
+ 288 - 0
dist/static/img/glyphicons-halflings-regular.8988968.svg


二进制
dist/static/img/logo-x2.18951f4.png


二进制
dist/static/img/pcenter.d98fa22.png


二进制
dist/static/img/qrcode.c1c21c0.png


文件差异内容过多而无法显示
+ 2 - 0
dist/static/js/app.6691b4d0427d7149a85e.js


文件差异内容过多而无法显示
+ 1 - 0
dist/static/js/app.6691b4d0427d7149a85e.js.map


文件差异内容过多而无法显示
+ 2 - 0
dist/static/js/manifest.c81f8109ed0bf39343fc.js


文件差异内容过多而无法显示
+ 1 - 0
dist/static/js/manifest.c81f8109ed0bf39343fc.js.map


文件差异内容过多而无法显示
+ 50 - 0
dist/static/js/vendor.f0a8c451559fe42b9056.js


文件差异内容过多而无法显示
+ 1 - 0
dist/static/js/vendor.f0a8c451559fe42b9056.js.map


+ 12 - 0
index.html

@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>test.yizhiwang.com Test</title>
+      <meta name="viewport" content="width=device-width, initial-scale=1">
+  </head>
+  <body>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+  </body>
+</html>

+ 82 - 0
package.json

@@ -0,0 +1,82 @@
+{
+  "name": "yizhiwang",
+  "version": "1.0.0",
+  "description": "A Vue.js project",
+  "author": "liyunfeng <liyunfeng>",
+  "private": true,
+  "scripts": {
+    "dev": "node build/dev-server.js",
+    "build": "node build/build.js"
+  },
+  "dependencies": {
+    "vue": "^2.2.2",
+    "vue-router": "^2.2.0"
+  },
+  "devDependencies": {
+    "animate.css": "^3.5.2",
+    "autoprefixer": "^6.7.2",
+    "babel-core": "^6.22.1",
+    "babel-loader": "^6.2.10",
+    "babel-plugin-component": "^0.9.1",
+    "babel-plugin-transform-runtime": "^6.22.0",
+    "babel-preset-env": "^1.2.1",
+    "babel-preset-stage-2": "^6.22.0",
+    "babel-register": "^6.22.0",
+    "blueimp-md5": "^2.7.0",
+    "bootstrap-loader": "^2.0.0",
+    "bootstrap-sass": "^3.3.7",
+    "chalk": "^1.1.3",
+    "connect-history-api-fallback": "^1.3.0",
+    "copy-webpack-plugin": "^4.0.1",
+    "css-loader": "^0.26.4",
+    "element-ui": "^1.2.9",
+    "eventsource-polyfill": "^0.9.6",
+    "express": "^4.14.1",
+    "extract-text-webpack-plugin": "^2.0.0",
+    "file-loader": "^0.10.0",
+    "friendly-errors-webpack-plugin": "^1.1.3",
+    "function-bind": "^1.1.0",
+    "html-webpack-plugin": "^2.28.0",
+    "http-proxy-middleware": "^0.17.3",
+    "imports-loader": "^0.7.1",
+    "jquery": "^3.2.1",
+    "jquery-countto": "^1.2.0",
+    "less": "^2.7.2",
+    "less-loader": "^4.0.3",
+    "node-sass": "^4.5.1",
+    "opn": "^4.0.2",
+    "optimize-css-assets-webpack-plugin": "^1.3.0",
+    "ora": "^1.1.0",
+    "postcss-center": "^1.0.0",
+    "raw-loader": "^0.5.1",
+    "resolve-url-loader": "^2.0.2",
+    "rimraf": "^2.6.0",
+    "sass-loader": "^6.0.3",
+    "semver": "^5.3.0",
+    "style-loader": "^0.16.0",
+    "url-loader": "^0.5.7",
+    "v-bar": "^2.0.0",
+    "vee-validate": "^2.0.0-rc.3",
+    "vue-loader": "^11.1.4",
+    "vue-localstorage": "^0.2.0",
+    "vue-resource": "^1.3.1",
+    "vue-style-loader": "^2.0.0",
+    "vue-template-compiler": "^2.2.4",
+    "vuex": "^2.3.1",
+    "waypoints": "^4.0.1",
+    "webpack": "^2.2.1",
+    "webpack-bundle-analyzer": "^2.2.1",
+    "webpack-dev-middleware": "^1.10.0",
+    "webpack-hot-middleware": "^2.16.1",
+    "webpack-merge": "^2.6.1"
+  },
+  "engines": {
+    "node": ">= 4.0.0",
+    "npm": ">= 3.0.0"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not ie <= 8"
+  ]
+}

+ 133 - 0
src/App.vue

@@ -0,0 +1,133 @@
+<template>
+    <div id="app">
+        <router-view style="height:100%;"></router-view>
+    </div>
+</template>
+
+<script>
+    import Vue from 'vue'
+    import md5 from 'blueimp-md5'
+    import * as Const from './const'
+
+    export default {
+        name: 'app',
+        beforeCreate(){
+            Vue.http.options.root = 'http://api.yizhiwang.wang/web';
+            Vue.http.interceptors.push(function(request, next) {
+                var timestamp = Math.round(new Date().getTime()/1000);
+                request.headers.set('AppKey', Const.appkey);
+                request.headers.set('Rest-Auth', md5(timestamp+Const.appkey+Const.secret+request.url));
+                request.headers.set('Rest-Time', timestamp+'');
+                let token = this.$localStorage.get('yzw_token');
+                console.log(token);
+                if(request.url == 'apiv1/auths'){
+                    next();
+                    return;
+                }
+                if(!token){
+                    getToken.call(this,request,next);
+                }else{
+                    request.params.access_token = token;
+                    next(function(res) {
+                        console.log(this);
+                        if(res.body.code && res.body.code != '200'){
+                            this.$notify({
+                                title: '错误',
+                                message: res.body.message,
+                                type:'error'
+                            });
+                        }
+                        if(res.body.code == '1001'){
+                            getToken.call(this,request,next);
+                        }
+                    });
+                }
+            });
+            let token = this.$localStorage.get('yzw_token');
+            if(!token){
+                getToken.call(this,null,null);
+            }
+        }
+    }
+
+    function getToken(request,next){
+        //接口授权
+        this.$http.post('apiv1/auths',{}).then(res => {
+            if(res.body.code == 200){
+                console.log('获取token');
+                this.$localStorage.set('yzw_token',res.body.info.access_token);
+                if(this.$route.path !== '/login' && this.$route.path !== '/reg'){
+                    this.$router.push('/login');
+                    return;
+                }else{
+                    this.$notify({
+                        title: '错误',
+                        message: '接口授权超时,请重新操作',
+                        type:'error'
+                    });
+                    //重发请求
+//                    this.$http[request.method.toLowerCase()](request.url,request.body).then(res => {
+//                        next();
+//                    },res => {
+//                        next();
+//                    });
+                }
+            }else{
+                alert(res.body.message);
+            }
+        },res => {
+            console.log('错误');
+        });
+    }
+</script>
+
+<style>
+
+    html,body{
+        height:100%;
+    }
+
+    body{
+        background-color:#fff;
+    }
+
+    #app{
+        height:100%;
+    }
+
+    .content-box{
+        min-height:100%;
+        padding-top:100px;
+        padding-bottom:120px;
+        box-sizing:border-box;
+    }
+
+    .btn-transparent{
+        background-color:transparent;
+        color:#000;
+        border:2px solid #000;
+        /*font-weight:bold;*/
+        transition:all .3s;
+    }
+
+    .btn-transparent:hover{
+        background-color:#000;
+        color:#fff;
+    }
+
+    .btn:focus,.btn:active:focus{
+        outline:none;
+    }
+
+    input.is-danger{
+        border-color:#ff3860;
+    }
+
+    span.help.is-danger{
+        display:block;
+        color:#ff3860;
+        font-size:12px;
+        margin-top:5px;
+    }
+
+</style>

二进制
src/assets/account.png


二进制
src/assets/active-user.png


二进制
src/assets/attention.png


二进制
src/assets/aword.png


二进制
src/assets/baidu.png


二进制
src/assets/dynamic.png


二进制
src/assets/english.png


二进制
src/assets/exit.png


二进制
src/assets/follow.png


二进制
src/assets/glossary.png


二进制
src/assets/google.png


二进制
src/assets/headimg-def.png


二进制
src/assets/headimg.png


二进制
src/assets/home.png


二进制
src/assets/idencode.png


二进制
src/assets/intro.png


二进制
src/assets/invite-code.png


二进制
src/assets/japen.png


二进制
src/assets/location.png


二进制
src/assets/logo-x2.png


二进制
src/assets/mission.png


二进制
src/assets/msg-none.png


二进制
src/assets/msg.png


二进制
src/assets/next.png


二进制
src/assets/notice.png


二进制
src/assets/opt-remove.png


二进制
src/assets/password.png


二进制
src/assets/pcenter.png


二进制
src/assets/phone.png


二进制
src/assets/publish-icon.png


二进制
src/assets/qie-active.png


二进制
src/assets/qie.png


二进制
src/assets/qrcode.png


二进制
src/assets/rank.png


二进制
src/assets/rank1.png


二进制
src/assets/rank2.png


二进制
src/assets/rank3.png


二进制
src/assets/remove.png


二进制
src/assets/school.png


二进制
src/assets/setting.png


二进制
src/assets/switch-close.png


二进制
src/assets/switch-open.png


二进制
src/assets/trans-list.png


二进制
src/assets/transkill.png


二进制
src/assets/up-active.png


二进制
src/assets/up.png


二进制
src/assets/youdao.png


+ 666 - 0
src/components/Calendar.vue

@@ -0,0 +1,666 @@
+<template>
+    <div class="datepicker">
+        <template v-if="hasInput">
+            <input class="form-control datepicker-input" :class="{'with-reset-button': clearButton}" type="text" :placeholder="placeholder"
+                   :style="{width:width}"
+                   @click="inputClick"
+                   v-model="inputValue"/>
+            <button v-if="clearButton && value" type="button" class="close" @click="inputValue = ''">
+                <span>&times;</span>
+            </button>
+        </template>
+        <div class="datepicker-popup" :style="paneStyle" @mouseover="handleMouseOver" @mouseout="handleMouseOver" v-show="displayDayView">
+            <div class="datepicker-ctrl" v-if="false">
+                <span class="datepicker-preBtn glyphicon glyphicon-chevron-left" aria-hidden="true" @click="preNextMonthClick(0)"></span>
+                <span class="datepicker-nextBtn glyphicon glyphicon-chevron-right" aria-hidden="true" @click="preNextMonthClick(1)"></span>
+            </div>
+            <template v-for="(p, pan) in pane" >
+                <div class="datepicker-inner">
+                    <div class="datepicker-body">
+                        <!--<p @click="switchMonthView">{{stringifyDayHeader(currDate, pan)}}</p>-->
+                        <div class="datepicker-weekRange">
+                            <span v-for="w in text.daysOfWeek">{{w}}</span>
+                        </div>
+                        <div class="datepicker-dateRange">
+              <span v-for="d in dateRange[pan]" class="day-cell" :class="getItemClasses(d)" :data-date="stringify(d.date)" @click="daySelect(d.date, $event)"><div>
+                <template v-if="d.sclass !== 'datepicker-item-gray'">
+                  {{getSpecailDay(d.date) || d.text}}
+                </template>
+                <template v-else>
+                    {{d.text}}
+                </template>
+                <div v-if="d.sclass !== 'datepicker-item-gray'"><slot :name="stringify(d.date)"></slot></div></div>
+              </span>
+                        </div>
+                    </div>
+                </div>
+            </template>
+        </div>
+        <div class="datepicker-popup" :style="paneStyle" v-show="displayMonthView">
+            <div class="datepicker-ctrl">
+                <span class="datepicker-preBtn glyphicon glyphicon-chevron-left" aria-hidden="true" @click="preNextYearClick(0)"></span>
+                <span class="datepicker-nextBtn glyphicon glyphicon-chevron-right" aria-hidden="true" @click="preNextYearClick(1)"></span>
+            </div>
+            <template v-for="(p, pan) in pane" >
+                <div class="datepicker-inner">
+                    <div class="datepicker-body">
+                        <p @click="switchDecadeView">{{stringifyYearHeader(currDate, pan)}}</p>
+                        <div class="datepicker-monthRange">
+                            <template v-for="(m, $index) in text.months">
+                <span :class="{'datepicker-dateRange-item-active':
+                    (text.months[parse(value).getMonth()]  === m) &&
+                    currDate.getFullYear() + pan === parse(value).getFullYear()}"
+                      @click="monthSelect(stringifyYearHeader(currDate, pan), $index)"
+                >{{m.substr(0,3)}}</span>
+                            </template>
+                        </div>
+                    </div>
+                </div>
+            </template>
+        </div>
+        <div class="datepicker-popup" :style="paneStyle" v-show="displayYearView">
+            <div class="datepicker-ctrl">
+                <span class="datepicker-preBtn glyphicon glyphicon-chevron-left" aria-hidden="true" @click="preNextDecadeClick(0)"></span>
+                <span class="datepicker-nextBtn glyphicon glyphicon-chevron-right" aria-hidden="true" @click="preNextDecadeClick(1)"></span>
+            </div>
+            <template v-for="(p, pan) in pane" >
+                <div class="datepicker-inner">
+                    <div class="datepicker-body">
+                        <p>{{stringifyDecadeHeader(currDate, pan)}}</p>
+                        <div class="datepicker-monthRange decadeRange">
+                            <template v-for="decade in decadeRange[pan]">
+                <span :class="{'datepicker-dateRange-item-active':
+                    parse(inputValue).getFullYear() === decade.text}"
+                      @click.stop="yearSelect(decade.text)"
+                >{{decade.text}}</span>
+                            </template>
+                        </div>
+                    </div>
+                </div>
+            </template>
+        </div>
+    </div>
+</template>
+
+<script>
+    export default {
+        name: 'calendar',
+        props: {
+            value: {
+                type: String
+            },
+            format: {
+                default: 'MM/dd/yyyy'
+            },
+            disabledDaysOfWeek: {
+                type: Array,
+                default () {
+                    return []
+                }
+            },
+            width: {
+                type: String,
+                default: '200px'
+            },
+            clearButton: {
+                type: Boolean,
+                default: false
+            },
+            lang: {
+                type: String,
+                default: navigator.language
+            },
+            placeholder: {
+                type: String
+            },
+            hasInput: {
+                type: Boolean,
+                default: true
+            },
+            pane: {
+                type: Number,
+                default: 1
+            },
+            borderWidth: {
+                type: Number,
+                default: 2
+            },
+            onDayClick: {
+                type: Function,
+                default () {}
+            },
+            changePane: {
+                type: Function,
+                default () {}
+            },
+            specialDays: {
+                type: Object,
+                default () {
+                    return {}
+                }
+            },
+            rangeBus: {
+                type: Function,
+                default () {
+                    // return new Vue()
+                }
+            },
+            rangeStatus: {
+                type: Number,
+                default: 0
+            }
+        },
+        mounted () {
+            this._blur = (e) => {
+                if (!this.$el.contains(e.target) && this.hasInput) this.close()
+            }
+            this.$emit('child-created', this)
+            // this.inputValue = this.value
+            // this.dateFormat = this.format
+            this.currDate = this.parse(this.inputValue) || this.parse(new Date())
+            const year = this.currDate.getFullYear()
+            const month = this.currDate.getMonth()
+            this.changePane(year, month, this.pane)
+            if (!this.hasInput) {
+                this.displayDayView = true
+                this.updatePaneStyle()
+            }
+            if (this.rangeStatus) {
+                this.eventbus = this.rangeBus()
+                if (typeof this.eventbus === 'object' && !this.eventbus.$on) {
+                    console.warn('Calendar rangeBus doesn\'t exist')
+                    this.rangeStatus = 0
+                }
+            }
+            if (this.rangeStatus === 2) {
+                this._updateRangeStart = (date) => {
+                    this.rangeStart = date
+                    this.currDate = date
+                    this.inputValue = this.stringify(this.currDate)
+                }
+                this.eventbus.$on('calendar-rangestart', this._updateRangeStart)
+            }
+            document.addEventListener('click', this._blur)
+        },
+        beforeDestroy () {
+            document.removeEventListener('click', this._blur)
+            if (this.rangeStatus === 2) {
+                this.eventbus.$off('calendar-rangestart', this._updateRangeStart)
+            }
+        },
+        data () {
+            return {
+                inputValue: this.value,
+                dateFormat: this.format,
+                currDate: new Date(),
+                dateRange: [],
+                decadeRange: [],
+                paneStyle: {
+                    width: ''
+                },
+                displayDayView: false,
+                displayMonthView: false,
+                displayYearView: false,
+                rangeStart: false,
+                rangeEnd: false
+            }
+        },
+        watch: {
+            currDate () {
+                this.getDateRange()
+            }
+        },
+        computed: {
+            text () {
+                return this.translations(this.lang)
+            }
+        },
+        methods: {
+            handleMouseOver (event) {
+                let target = event.target
+                // this.rangeEnd = false
+                if (!this.rangeStart) {
+                    return true
+                }
+                if (event.type === 'mouseout') {
+                    return true
+                }
+                while (this.$el.contains(target) && !~target.className.indexOf('day-cell')) {
+                    target = target.parentNode
+                }
+                if (~target.className.indexOf('day-cell') && !~target.className.indexOf('datepicker-item-gray')) {
+                    const rangeEnd = target.getAttribute('data-date')
+                    if (this.rangeStart < this.parse(rangeEnd)) {
+                        this.rangeEnd = this.parse(rangeEnd)
+                    }
+                }
+            },
+            getItemClasses (d) {
+                const clazz = []
+                clazz.push(d.sclass)
+                if (this.rangeStart && this.rangeEnd && d.sclass !== 'datepicker-item-gray') {
+                    if (d.date > this.rangeStart && d.date < this.rangeEnd) {
+                        clazz.push('daytoday-range')
+                    }
+                    /* eslint-disable eqeqeq */
+                    if (this.stringify(d.date) == this.stringify(this.rangeStart)) {
+                        clazz.push('daytoday-start')
+                    }
+                    /* eslint-disable eqeqeq */
+                    if (this.stringify(d.date) == this.stringify(this.rangeEnd)) {
+                        clazz.push('daytoday-end')
+                    }
+                }
+                return clazz.join(' ')
+            },
+            translations (lang) {
+                lang = lang || 'en'
+                let text = {
+                    daysOfWeek: ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'],
+                    limit: 'Limit reached ({{limit}} items max).',
+                    loading: 'Loading...',
+                    minLength: 'Min. Length',
+                    months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
+                    notSelected: 'Nothing Selected',
+                    required: 'Required',
+                    search: 'Search'
+                }
+                return window.VueCalendarLang ? window.VueCalendarLang(lang) : text
+            },
+            close () {
+                this.displayDayView = this.displayMonthView = this.displayYearView = false
+            },
+            inputClick () {
+                this.currDate = this.parse(this.inputValue) || this.parse(new Date())
+                if (this.displayMonthView || this.displayYearView) {
+                    this.displayDayView = false
+                } else {
+                    this.displayDayView = !this.displayDayView
+                }
+                this.updatePaneStyle()
+            },
+            updatePaneStyle () {
+                if (!(this.displayMonthView || this.displayYearView)) {
+                    this.$nextTick(function () {
+                        let offsetLeft = this.$el.offsetLeft
+                        let offsetWidth = this.$el.querySelector('.datepicker-inner').offsetWidth
+                        let popWidth = this.pane * offsetWidth + this.borderWidth // add border
+                        this.paneStyle.width = popWidth + 'px'
+                        if (this.hasInput) {
+                            if (popWidth + offsetLeft > document.documentElement.clientWidth) {
+                                this.paneStyle.right = '0px'
+                            }
+                        } else {
+                            this.paneStyle.position = 'initial'
+                        }
+                        this.$forceUpdate()
+                    })
+                }
+            },
+            preNextDecadeClick (flag) {
+                const year = this.currDate.getFullYear()
+                const months = this.currDate.getMonth()
+                const date = this.currDate.getDate()
+                if (flag === 0) {
+                    this.currDate = new Date(year - 10, months, date)
+                } else {
+                    this.currDate = new Date(year + 10, months, date)
+                }
+            },
+            preNextMonthClick (flag) {
+                const year = this.currDate.getFullYear()
+                const month = this.currDate.getMonth()
+                const date = this.currDate.getDate()
+                if (flag === 0) {
+                    const preMonth = this.getYearMonth(year, month - 1)
+                    this.currDate = new Date(preMonth.year, preMonth.month, date)
+                    this.changePane(preMonth.year, preMonth.month, this.pane)
+                } else {
+                    const nextMonth = this.getYearMonth(year, month + 1)
+                    this.currDate = new Date(nextMonth.year, nextMonth.month, date)
+                    this.changePane(nextMonth.year, nextMonth.month, this.pane)
+                }
+            },
+            preNextYearClick (flag) {
+                const year = this.currDate.getFullYear()
+                const months = this.currDate.getMonth()
+                const date = this.currDate.getDate()
+                if (flag === 0) {
+                    this.currDate = new Date(year - 1, months, date)
+                } else {
+                    this.currDate = new Date(year + 1, months, date)
+                }
+            },
+            yearSelect (year) {
+                this.displayYearView = false
+                this.displayMonthView = true
+                this.currDate = new Date(year, this.currDate.getMonth(), this.currDate.getDate())
+            },
+            daySelect (date, event) {
+                let el = event.target
+                if (el.classList[0] === 'datepicker-item-disable') {
+                    return false
+                } else {
+                    if (this.hasInput) {
+                        this.currDate = date
+                        this.inputValue = this.stringify(this.currDate)
+                        this.displayDayView = false
+                        if (this.rangeStatus === 1) {
+                            this.eventbus.$emit('calendar-rangestart', this.currDate)
+                        }
+                    } else {
+                        this.onDayClick(date, this.stringify(date))
+                    }
+                }
+            },
+            switchMonthView () {
+                this.displayDayView = false
+                this.displayMonthView = true
+            },
+            switchDecadeView () {
+                this.displayMonthView = false
+                this.displayYearView = true
+            },
+            monthSelect (year, index) {
+                this.displayMonthView = false
+                this.displayDayView = true
+                this.currDate = new Date(year, index, this.currDate.getDate())
+                this.changePane(year, index, this.pane)
+            },
+            getYearMonth (year, month) {
+                if (month > 11) {
+                    year++
+                    month = 0
+                } else if (month < 0) {
+                    year--
+                    month = 11
+                }
+                return {year: year, month: month}
+            },
+            getSpecailDay (v) {
+                return this.specialDays[this.stringify(v)]
+            },
+            stringifyDecadeHeader (date, pan) {
+                const yearStr = date.getFullYear().toString()
+                const firstYearOfDecade = parseInt(yearStr.substring(0, yearStr.length - 1) + 0, 10) + (pan * 10)
+                const lastYearOfDecade = parseInt(firstYearOfDecade, 10) + 10
+                return firstYearOfDecade + '-' + lastYearOfDecade
+            },
+            siblingsMonth (v, n) {
+                return new Date(v.getFullYear(), v.getMonth() * 1 + n)
+            },
+            stringifyDayHeader (date, month = 0) {
+                const d = this.siblingsMonth(date, month)
+                return this.text.months[d.getMonth()] + ' ' + d.getFullYear()
+            },
+            parseMonth (date) {
+                return this.text.months[date.getMonth()]
+            },
+            stringifyYearHeader (date, year = 0) {
+                return date.getFullYear() + year
+            },
+            stringify (date, format = this.dateFormat) {
+                if (!date) date = this.parse()
+                if (!date) return ''
+                const year = date.getFullYear()
+                const month = date.getMonth() + 1
+                const day = date.getDate()
+                const monthName = this.parseMonth(date)
+                return format
+                    .replace(/yyyy/g, year)
+                    .replace(/MMMM/g, monthName)
+                    .replace(/MMM/g, monthName.substring(0, 3))
+                    .replace(/MM/g, ('0' + month).slice(-2))
+                    .replace(/dd/g, ('0' + day).slice(-2))
+                    .replace(/yy/g, year)
+                    .replace(/M(?!a)/g, month)
+                    .replace(/d/g, day)
+            },
+            parse (str = this.inputValue) {
+                let date
+                if (str.length === 10 && (this.dateFormat === 'dd-MM-yyyy' || this.dateFormat === 'dd/MM/yyyy')) {
+                    date = new Date(str.substring(6, 10), str.substring(3, 5) - 1, str.substring(0, 2))
+                } else {
+                    date = new Date(str)
+                    date.setHours(0, 0, 0)
+                }
+                return isNaN(date.getFullYear()) ? new Date() : date
+            },
+            getDayCount (year, month) {
+                const dict = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+                if (month === 1) {
+                    if ((year % 400 === 0) || (year % 4 === 0 && year % 100 !== 0)) {
+                        return 29
+                    }
+                }
+                return dict[month]
+            },
+            getDateRange () {
+                this.dateRange = []
+                this.decadeRange = []
+                for (let p = 0; p < this.pane; p++) {
+                    let currMonth = this.siblingsMonth(this.currDate, p)
+                    let time = {
+                        year: currMonth.getFullYear(),
+                        month: currMonth.getMonth()
+                    }
+                    let yearStr = time.year.toString()
+                    this.decadeRange[p] = []
+                    let firstYearOfDecade = (yearStr.substring(0, yearStr.length - 1) + 0) - 1
+                    for (let i = 0; i < 12; i++) {
+                        this.decadeRange[p].push({
+                            text: firstYearOfDecade + i + p * 10
+                        })
+                    }
+                    this.dateRange[p] = []
+                    const currMonthFirstDay = new Date(time.year, time.month, 1)
+                    let firstDayWeek = currMonthFirstDay.getDay() + 1
+                    if (firstDayWeek === 0) {
+                        firstDayWeek = 7
+                    }
+                    const dayCount = this.getDayCount(time.year, time.month)
+                    if (firstDayWeek > 1) {
+                        const preMonth = this.getYearMonth(time.year, time.month - 1)
+                        const prevMonthDayCount = this.getDayCount(preMonth.year, preMonth.month)
+                        for (let i = 1; i < firstDayWeek; i++) {
+                            const dayText = prevMonthDayCount - firstDayWeek + i + 1
+                            this.dateRange[p].push({
+                                text: dayText,
+                                date: new Date(preMonth.year, preMonth.month, dayText),
+                                sclass: 'datepicker-item-gray'
+                            })
+                        }
+                    }
+                    for (let i = 1; i <= dayCount; i++) {
+                        const date = new Date(time.year, time.month, i)
+                        const week = date.getDay()
+                        let sclass = ''
+                        this.disabledDaysOfWeek.forEach((el) => {
+                            if (week === parseInt(el, 10)) sclass = 'datepicker-item-disable'
+                        })
+                        if (i === this.currDate.getDate()) {
+                            if (this.inputValue) {
+                                const valueDate = this.parse(this.inputValue)
+                                if (valueDate) {
+                                    if (valueDate.getFullYear() === time.year && valueDate.getMonth() === time.month) {
+                                        sclass = 'datepicker-dateRange-item-active'
+                                    }
+                                }
+                            }
+                        }
+                        this.dateRange[p].push({
+                            text: i,
+                            date: date,
+                            sclass: sclass
+                        })
+                    }
+                    if (this.dateRange[p].length < 42) {
+                        const nextMonthNeed = 42 - this.dateRange[p].length
+                        const nextMonth = this.getYearMonth(time.year, time.month + 1)
+                        for (let i = 1; i <= nextMonthNeed; i++) {
+                            this.dateRange[p].push({
+                                text: i,
+                                date: new Date(nextMonth.year, nextMonth.month, i),
+                                sclass: 'datepicker-item-gray'
+                            })
+                        }
+                    }
+                }
+            }
+        }
+    }
+</script>
+
+<style lang="scss">
+    @mixin clearfix() {
+        &:before,
+        &:after {
+            content: " "; // 1
+            display: table; // 2
+        }
+        &:after {
+            clear: both;
+        }
+    }
+    .datepicker{
+        position: relative;
+        display: block;
+    }
+    input.datepicker-input.with-reset-button {
+        padding-right: 25px;
+    }
+    .datepicker > button.close {
+        position: absolute;
+        top: 0;
+        right: 0;
+        outline: none;
+        z-index: 2;
+        display: block;
+        width: 34px;
+        height: 34px;
+        line-height: 34px;
+        text-align: center;
+    }
+    .datepicker > button.close:focus {
+        opacity: .2;
+    }
+    .datepicker-popup{
+        position: absolute;
+        border: 1px solid #ccc;
+        /*border-radius: 5px;*/
+        background: #e4e4e4;
+        /*margin-top: 2px;*/
+        z-index: 1000;
+        /*box-shadow: 0 6px 12px rgba(0,0,0,0.175);*/
+        @include clearfix;
+    }
+    .datepicker-inner{
+        width: 100%;
+        /*float: left;*/
+    }
+    .datepicker-body{
+        padding: 5px;
+        text-align: center;
+    }
+    .datepicker-ctrl p,
+    .datepicker-ctrl span,
+    .datepicker-body span{
+        display: inline-block;
+        width: 14.2857%;
+        line-height: 24px;
+        height: 28px;
+        // border-radius: 4px;
+        padding:2px;
+
+        div{
+            background-color:#fff;
+        }
+    }
+    .datepicker-ctrl p {
+        width: 65%;
+    }
+    .datepicker-ctrl span {
+        position: absolute;
+    }
+    .datepicker-body span {
+        text-align: center;
+    }
+    .datepicker-monthRange span{
+        width: 48px;
+        height: 50px;
+        line-height: 45px;
+    }
+    .datepicker-item-disable {
+        background-color: white!important;
+        cursor: not-allowed!important;
+    }
+    .decadeRange span:first-child,
+    .decadeRange span:last-child,
+    .datepicker-item-disable,
+    .datepicker-item-gray{
+        color: #999;
+    }
+    .datepicker-dateRange-item-active:hover,
+    .datepicker-dateRange-item-active {
+        background: rgb(50, 118, 177)!important;
+        color: white!important;
+    }
+    .datepicker-monthRange {
+        margin-top: 10px
+    }
+    .datepicker-monthRange span,
+    .datepicker-ctrl span,
+    .datepicker-ctrl p,
+    .datepicker-dateRange span {
+        cursor: pointer;
+    }
+    .datepicker-monthRange span:hover,
+    .datepicker-ctrl p:hover,
+    .datepicker-ctrl i:hover,
+    .datepicker-dateRange span:hover,
+    .datepicker-dateRange-item-hover {
+        background-color : #eeeeee;
+    }
+    .datepicker-dateRange {
+        .daytoday-start,
+        .daytoday-start:hover,
+        .daytoday-end,
+        .daytoday-end:hover{
+            background: rgb(50, 118, 177)!important;
+            color: white!important;
+        }
+    }
+    .datepicker-dateRange .daytoday-range,
+    .datepicker-dateRange .daytoday-range:hover{
+        background-color: #ddd;
+    }
+    .datepicker-weekRange span{
+        font-weight: bold;
+    }
+    .datepicker-label{
+        background-color: #f8f8f8;
+        font-weight: 700;
+        padding: 7px 0;
+        text-align: center;
+    }
+    .datepicker-ctrl{
+        position: relative;
+        /*height: 30px;*/
+        line-height: 30px;
+        font-weight: bold;
+        text-align: center;
+    }
+    .month-btn{
+        font-weight: bold;
+        -webkit-user-select:none;
+        -moz-user-select:none;
+        -ms-user-select:none;
+        user-select:none;
+    }
+    .datepicker-preBtn{
+        left: 2px;
+    }
+    .datepicker-nextBtn{
+        right: 2px;
+    }
+</style>

+ 79 - 0
src/components/Follow.vue

@@ -0,0 +1,79 @@
+<template>
+    <div class="container">
+        <div class="row" style="margin-top:20px;">
+            <div class="col-sm-9" style="padding:0 40px;">
+                <tabs :data="tabs" @click="tabClick"></tabs>
+                <div class="myfollow" v-show="active === 0">
+                    <div class="follow-item" v-for="n in 4">
+                        <img src="../assets/headimg.png">
+                        <span>王大白</span>
+                        <button class="btn btn-primary">取消关注</button>
+                    </div>
+                </div>
+                <div class="fans" v-show="active === 1">
+                    <div class="follow-item" v-for="n in 4">
+                        <img src="../assets/headimg.png">
+                        <span>王大白</span>
+                        <button class="btn btn-primary">关注</button>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <list :data="list" :active="2"></list>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import List from './SideList.vue'
+    import Tabs from './Tabs.vue'
+    import {SIDE_LIST} from '../const'
+
+    export default{
+        components:{
+            List,
+            Tabs
+        },
+        data(){
+            return {
+                list:SIDE_LIST,
+                tabs:[{
+                    title:'我的关注'
+                },{
+                    title:'粉丝'
+                }],
+                active:0
+            }
+        },
+        methods:{
+            tabClick(idx){
+                if(this.active !== idx)this.active = idx;
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    .follow-item{
+        font-size:0;
+        line-height:32px;
+        margin-top:10px;
+    }
+
+    .follow-item img{
+        width:32px;
+        height:32px;
+    }
+
+    .follow-item span{
+        font-size:14px;
+        vertical-align: middle;
+        margin-left:10px;
+    }
+
+    .follow-item button{
+        float:right;
+        width:100px;
+    }
+</style>

+ 55 - 0
src/components/Footer.vue

@@ -0,0 +1,55 @@
+<template>
+    <div class="footer">
+        <div class="item">
+            <a href="javascript:void 0;">帮助中心</a>
+            &nbsp;|&nbsp;
+            <a href="javascript:void 0;">常见问题</a>
+            &nbsp;|&nbsp;
+            <a href="javascript:void 0;">关于我们</a>
+        </div>
+        <div class="item">
+            联系客服-邮箱:xxxxxx@xxx.com
+        </div>
+        <div class="item">
+            XX信息技术有限公司 powered by XXX THX.法律声明 浙ICP备123456789号 浙网公安备123456789号
+        </div>
+    </div>
+</template>
+
+<script>
+
+    export default{
+
+    }
+
+</script>
+
+<style scoped>
+
+    .footer{
+        height:120px;
+        background-color:#f7f7f7;
+        color:#000;
+        width:100%;
+        text-align:center;
+        margin-top:-120px;
+    }
+
+    .copyright{
+        line-height:120px;
+    }
+
+    .footer .item{
+        line-height:1;
+        padding-top:20px;
+    }
+
+    .footer .item a{
+        color:#000;
+    }
+
+    .footer .item:last-child{
+        font-size:12px;
+    }
+
+</style>

+ 105 - 0
src/components/Forget.vue

@@ -0,0 +1,105 @@
+<template>
+    <div>
+        <div class="forget-container">
+            <div class="title">
+                找回密码
+            </div>
+            <div class="body">
+                <div class="form">
+                    <div class="form-item clearfix">
+                        <img class="icon" src="../assets/phone.png">
+                        <input type="text" class="form-control input" placeholder="请输入手机号或邮箱">
+                    </div>
+                    <div class="form-item clearfix">
+                        <img class="icon" src="../assets/idencode.png">
+                        <div class="input-group">
+                            <input type="text" class="form-control" placeholder="请输入验证码">
+                            <span class="input-group-btn">
+                                <button class="btn btn-primary" type="button">获取验证码</button>
+                            </span>
+                        </div>
+                    </div>
+                    <div class="form-item clearfix">
+                        <img class="icon" src="../assets/password.png">
+                        <input type="text" class="form-control input" placeholder="请设置新密码">
+                    </div>
+                    <div class="clearfix operate" style="padding-top:10px;">
+                        <button class="btn btn-danger" style="width:120px">确定</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    export default{
+        data(){
+            return {
+
+            }
+        },
+        methods:{
+
+        }
+    }
+</script>
+
+<style scoped>
+    .forget-container{
+        width:600px;
+        /*height:300px;*/
+        /*background-color:#000;*/
+        top:center;
+        left:center;
+    }
+
+    .title{
+        text-align:center;
+        height:70px;
+        background-color:#fdd32c;
+        line-height:70px;
+        color:#000;
+        font-weight:bold;
+        font-size:24px;
+    }
+
+    .body{
+        border-width:0 2px 2px 2px;
+        border-style:solid;
+        border-color:#d6d6d6;
+        padding:28px 0;
+        text-align:center;
+    }
+
+    .body .form{
+        display:inline-block;
+    }
+
+    .body .form .form-item{
+        margin-bottom:20px;
+    }
+
+    .body .form .icon{
+        float:left;
+        margin-top:2px;
+    }
+    .body .form .input,.body .form .input-group{
+        float:left;
+        width:300px;
+        margin-left:6px;
+    }
+    .body .form .operate button{
+        float:left;
+        margin-left:36px;
+    }
+
+    .body .form .operate a{
+        float:left;
+        display:inline-block;
+        line-height:33px;
+        margin-left:20px;
+        color:#000;
+        /*font-weight:bold;*/
+    }
+</style>

+ 227 - 0
src/components/Header.vue

@@ -0,0 +1,227 @@
+<template>
+    <header class="header">
+        <el-popover style="min-width:120px;"
+            ref="popover1"
+            placement="top"
+            width="150"
+            trigger="hover">
+            <list :data="list" @click="itemClick"></list>
+        </el-popover>
+        <div class="container text-center">
+            <div class="logo" @click="goHome">
+                <img src="../assets/logo-x2.png" height="60px">
+            </div>
+            <!--<div class="title">LOGO</div>-->
+            <template v-if="user">
+                <span style="vertical-align: middle">12:23:00</span>
+                <div class="countdown">
+                    <div class="progress">
+                        <div class="progress-bar progress-bar-danger progress-bar-striped" role="progressbar" aria-valuenow="80" aria-valuemin="0" aria-valuemax="100" style="width: 80%">
+                            <!--<span class="sr-only">80% Complete (danger)</span>-->
+                        </div>
+                    </div>
+                </div>
+                <span style="vertical-align: middle;font-size:15px;">翻译倒计时</span>
+            </template>
+
+            <div class="nav" v-show="!user">
+                <router-link class="btn btn-transparent" style="width:80px;margin-right:20px;" to="/login">登陆</router-link>
+                <router-link class="btn btn-transparent" style="width:80px;" to="/reg">注册</router-link>
+            </div>
+            <div class="icons clearfix" v-show="user">
+                <img class="headimg" src="../assets/headimg.png" v-popover:popover1 height="50px">
+                <img class="msg" src="../assets/msg-none.png" height="50px" @click="goMessage">
+            </div>
+        </div>
+    </header>
+</template>
+
+<script>
+    import List from './List.vue';
+
+    export default{
+        components:{
+            List
+        },
+        data(){
+            return {
+                scrollTop:0,
+                active:0,
+                loged:true,
+                list:[{
+                    img:require('../assets/home.png'),
+                    title:'首页',
+                    path:'/'
+                },{
+                    img:require('../assets/pcenter.png'),
+                    title:'个人中心',
+                    path:'/person'
+                },{
+                    img:require('../assets/follow.png'),
+                    title:'关注',
+                    path:'/follow/0'
+                },{
+                    img:require('../assets/msg.png'),
+                    title:'私信',
+                    path:'/letter/0'
+                },{
+                    img:require('../assets/setting.png'),
+                    title:'设置',
+                    path:'/setting'
+                },{
+                    img:require('../assets/exit.png'),
+                    title:'退出',
+                    path:'/'
+                }]
+            };
+        },
+        computed:{
+            backgroundColor(){
+                if(this.scrollTop >= 200){
+                    return {
+                        backgroundColor:'rgb(32,160,255)'
+                    }
+                }else{
+                    let percent = this.scrollTop / 200;
+                    return {
+                        backgroundColor:`rgba(32,160,255,${percent})`
+                    }
+                }
+            },
+            user(){
+                return this.$store.state.user.user;
+            }
+        },
+        methods:{
+            activeNav(idx){
+                this.active = idx;
+            },
+            itemClick(path){
+                this.$router.push(path);
+            },
+            goMessage(){
+                this.$router.push('/message');
+            },
+            goHome(){
+                this.$router.push('/');
+            }
+        },
+        mounted(){
+            this.scrollTop = $(document).scrollTop();
+            window.onscroll = () => {
+                this.scrollTop = $(document).scrollTop();
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    .header{
+        position:fixed;
+        top:0;
+        left:0;
+        width:100%;
+        height:100px;
+        line-height:100px;
+        z-index:50;
+        background-color:#fdd32c;
+    }
+
+    .title{
+        margin-left:20px;
+        float:left;
+        font-size:28px;
+        font-weight:700;
+        /*color:#fff;*/
+    }
+
+    .logo{
+        display:inline-block;
+        float:left;
+        cursor:pointer;
+    }
+
+    .countdown{
+        display:inline-block;
+        width:600px;
+        vertical-align: middle;
+        margin:0 5px;
+    }
+
+    .countdown .progress{
+        margin-bottom:0;
+    }
+
+    .nav{
+        float:right;
+        margin:0;
+        padding:0;
+    }
+
+    .nav-item{
+        float:left;
+        list-style:none;
+        margin-left:10px;
+    }
+
+    .header .nav-item a{
+        display:block;
+        padding:0 20px;
+        position:relative;
+        text-decoration: none;
+        /*color:#fff;*/
+        opacity:0.8;
+        transition:all 0.3s;
+    }
+
+    .header .nav-item a:after{
+        content:'';
+        position:absolute;
+        bottom:0;
+        left:50%;
+        right:50%;
+        opacity: 0;
+        height:0px;
+        background-color:#99d2fc;
+        transition:all .5s;
+    }
+
+    .header .nav-item a:hover,.header .nav-item a:focus{
+        opacity:1;
+        background-color:transparent;
+    }
+
+    .header .nav-item a:hover:after{
+        left:0;
+        right:0;
+        height:5px;
+        opacity:1;
+    }
+
+    .header .nav-item.active a{
+        opacity:1;
+    }
+
+    .header .nav-item.active a:after{
+        left:0;
+        right:0;
+        height:5px;
+        opacity:1;
+    }
+
+    .icons{
+        float:right;
+        display:inline-block;
+    }
+
+    .icons img{
+        /*float:right;*/
+        /*margin-top:25px;*/
+        cursor:pointer;
+    }
+
+    .icons .headimg{
+        margin-right:20px;
+    }
+
+</style>

+ 941 - 0
src/components/Home.vue

@@ -0,0 +1,941 @@
+<template>
+    <div class="container">
+        <img class="qrcode" src="../assets/qrcode.png">
+        <div class="fixed-container">
+            <div class="header-container clearfix">
+                <div class="exp-container">
+                    <div class="exp clearfix">
+                        <div class="lv">
+                            <img src="../assets/english.png">
+                            Lv {{user ? user.level_info.level_id - 1 : 0}}
+                        </div>
+                        <span>经验值</span>
+                        <div class="progress-container">
+                            <div class="progress">
+                                <div class="progress-bar progress-bar-info" role="progressbar" :aria-valuenow="user ? user.member_experience : 0" aria-valuemin="0" :aria-valuemax="user ? user.level_info.level_end : 1" :style="englishPercent">
+                                    <span class="sr-only">20% Complete</span>
+                                </div>
+                            </div>
+                        </div>
+                        <span>{{user ? user.member_experience : 0}}字 / {{user ? user.level_info.level_end : 1}}字</span>
+                    </div>
+                    <div class="exp clearfix">
+                        <div class="lv">
+                            <img src="../assets/japen.png">
+                            Lv {{user ? user.level_jp_info.level_id - 1 : 0}}
+                        </div>
+                        <span>经验值</span>
+                        <div class="progress-container">
+                            <div class="progress">
+                                <div class="progress-bar progress-bar-danger" role="progressbar" :aria-valuenow="user ? user.member_experience_jp : 0" aria-valuemin="0" :aria-valuemax="user ? user.level_jp_info.level_end : 1" :style="japenPercent">
+                                    <span class="sr-only">20% Complete</span>
+                                </div>
+                            </div>
+                        </div>
+                        <span>{{user ? user.member_experience_jp : 0}}字 / {{user ? user.level_jp_info.level_end : 1}}字</span>
+                    </div>
+                </div>
+                <button class="btn-publish btn btn-danger pull-right" @click="goPublish"><img src="../assets/publish-icon.png" height="16px"> 去发布任务</button>
+            </div>
+            <div class="notice">
+                <img src="../assets/notice.png" height="16px;">
+                公告内容公告内容公告内容公告内容公告内容公告内容公告内容公告内容公告内容公告内容公告内容公告内容公告内容公告内容公告内容公告内容公告内容公告内容
+            </div>
+        </div>
+        <div class="row" style="height:100%;">
+            <div class="col-md-4" style="width:400px;margin-right:40px;height:100%;padding-right:0;">
+                <scrollbar style="height:100%;width:100%">
+                    <div style="padding-right:10px;">
+                        <div class="sel-container">
+                            <div class="row">
+                                <div class="col-md-6">
+                                    <select class="form-control">
+                                        <option value="">请选择领域</option>
+                                    </select>
+                                </div>
+                                <div class="col-md-6">
+                                    <select class="form-control">
+                                        <option value="">请选择任务来源</option>
+                                    </select>
+                                </div>
+                            </div>
+                            <div class="row" style="margin-top:10px;">
+                                <div class="col-md-6">
+                                    <select class="form-control">
+                                        <option value="">请选择翻译人数</option>
+                                    </select>
+                                </div>
+                                <div class="col-md-6">
+                                    <select class="form-control">
+                                        <option value="">请选择翻译语言</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="mission-list">
+                            <div class="mission" v-for="mission in missionList">
+                                <span class="title"><router-link style="color:#000;" :to="'/mission/'+mission.id">{{mission.title}}</router-link></span>
+                                <div class="info">
+                                    任务发布者:
+                                    <span class="auth">{{mission.auth}}</span>
+                                    发布时间:{{mission.publishTime}}
+                                </div>
+                                <div class="row">
+                                    <div class="col-md-4">
+                                        原文{{mission.wordNumber}}字
+                                </div>
+                                    <div class="col-md-8">
+                                        英文限制等级:{{mission.limitLevel}}级
+                                </div>
+                                </div>
+                                <div class="row">
+                                    <div class="col-md-4">
+                                        交稿时间:{{mission.endTime}}
+                                </div>
+                                    <div class="col-md-8">
+                                        稿费:{{mission.money}}
+                                </div>
+                                </div>
+                                <button class="btn btn-primary" @click="receive(mission.id)">领取(2)</button>
+                            </div>
+                        </div>
+                    </div>
+                </scrollbar>
+            </div>
+            <div class="col-md-4" style="width:400px;margin-right:40px;height:100%;padding-right:0;">
+                <scrollbar style="height:100%;width:100%">
+                    <div style="padding-right:10px;">
+                        <div class="dynamic-title">
+                            <div class="title">
+                                <img src="../assets/dynamic.png">
+                                用户动态
+                            </div>
+                            <div class="attention">
+                                我的关注({{attention}}人)
+                            </div>
+                        </div>
+                        <div class="dynamic-list">
+                            <div class="dynamic clearfix" v-for="dynamic in dynamicList">
+                                <div class="avator">
+                                    <a href="javascript:void 0" class="thumbnail" @click="goUser">
+                                        <img :src="dynamic.img" alt="">
+                                    </a>
+                                </div>
+                                <div class="content">
+                                    <div class="info">
+                                        <div class="user">
+                                            <el-popover
+                                                placement="bottom-start"
+                                                width="260"
+                                                trigger="hover"
+                                                >
+                                                <span slot="reference">{{dynamic.user}}</span>
+                                                <div class="card clearfix">
+                                                    <img class="avator" :src="dynamic.img">
+                                                    <div class="content">
+                                                        <div class="info">
+                                                            <div class="name">{{dynamic.user}}</div>
+                                                            <div class="level">LV{{dynamic.lv}}</div>
+                                                        </div>
+                                                        <div class="intro">{{dynamic.intro}}</div>
+                                                    </div>
+                                                </div>
+                                                <div class="card-footer">
+                                                    <div class="ctn">
+                                                        <div class="col">
+                                                            <div>已领取</div>
+                                                            <div>{{dynamic.receive}}</div>
+                                                        </div>
+                                                        <div class="col">
+                                                            <div>关注者</div>
+                                                            <div>{{dynamic.follow}}</div>
+                                                        </div>
+                                                        <div class="col">
+                                                            <a href="javascript:void 0">私信</a>
+                                                        </div>
+                                                        <div class="col">
+                                                            <a href="javascript:void 0">+关注</a>
+                                                        </div>
+                                                    </div>
+                                                </div>
+                                            </el-popover>
+                                        </div>
+                                        <div class="detail">{{dynamic.detail}}</div>
+                                        <div class="time">{{dynamic.time}}</div>
+                                    </div>
+                                    <div class="desc">{{dynamic.desc}}</div>
+                                    <div class="footer">
+                                        <span style="color:#999">字数:</span>
+                                        {{dynamic.wordNumber}}
+                                        <updown style="float:right;"></updown>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </scrollbar>
+            </div>
+            <div class="col-md-4" style="width:280px;height:100%;padding-right:0;">
+                <scrollbar style="height:100%;width:100%">
+                    <div style="padding-right:10px;">
+                        <div class="active-title">
+                            <div class="title">
+                                <img src="../assets/active-user.png">
+                                活跃用户
+                            </div>
+                        </div>
+                        <calendar
+                            value=""
+                            width="280px"
+                            :disabled-days-of-week="[]"
+                            :has-input="false"></calendar>
+                        <div class="sign">
+                            <div>
+                                <button class="btn btn-primary">签到 3月19日</button>
+                            </div>
+                            <p>连续签到11天,有额外奖励哦!</p>
+                        </div>
+                        <div class="active-title">
+                            <div class="title">
+                                <img src="../assets/rank.png">
+                                翻译人气排行榜
+                            </div>
+                        </div>
+                        <div class="row rank">
+                            <div class="col-md-4">
+                                <div class="rank-block">
+                                    <img src="../assets/headimg.png" alt="" class="img-circle img-responsive">
+                                    <img class="medal" src="../assets/rank1.png">
+                                </div>
+                                <div class="name">名称名称</div>
+                            </div>
+                            <div class="col-md-4">
+                                <div class="rank-block">
+                                    <img src="../assets/headimg.png" alt="" class="img-circle img-responsive">
+                                    <img class="medal" src="../assets/rank2.png">
+                                </div>
+                                <div class="name">名称名称</div>
+                            </div>
+                            <div class="col-md-4">
+                                <div class="rank-block">
+                                    <img src="../assets/headimg.png" alt="" class="img-circle img-responsive">
+                                    <img class="medal" src="../assets/rank3.png">
+                                </div>
+                                <div class="name">名称名称</div>
+                            </div>
+                        </div>
+                        <div class="rank-list">
+                            <div class="rank-item">
+                                <img src="../assets/headimg.png" alt="" class="img-circle">
+                                <div class="name">名称名称</div>
+                                <img src="../assets/next.png" class="next">
+                            </div>
+                            <div class="rank-item">
+                                <img src="../assets/headimg.png" alt="" class="img-circle">
+                                <div class="name">名称名称</div>
+                                <img src="../assets/next.png" class="next">
+                            </div>
+                            <div class="rank-item">
+                                <img src="../assets/headimg.png" alt="" class="img-circle">
+                                <div class="name">名称名称</div>
+                                <img src="../assets/next.png" class="next">
+                            </div>
+                        </div>
+                        <div class="about">
+                            <div class="item">
+                                <a href="javascript:void 0;">帮助中心</a>
+                                &nbsp;|&nbsp;
+                                <a href="javascript:void 0;">常见问题</a>
+                                &nbsp;|&nbsp;
+                                <a href="javascript:void 0;">关于我们</a>
+                            </div>
+                            <p>联系客服-邮箱:xxxxxx@xxx.com</p>
+                            <p>XX信息技术有限公司</p>
+                            <p>powered by XXX THX.法律声明</p>
+                            <p>浙ICP备123456789号</p>
+                            <p>浙网公安备123456789号</p>
+                        </div>
+                    </div>
+                </scrollbar>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import Scrollbar from './scrollbar/components/scrollbar.vue'
+    import Calendar from './Calendar.vue'
+    import Updown from './Updown.vue'
+    import * as Types from '../store/mutation-types'
+
+    export default{
+        data(){
+            return {
+                attention:10,
+                missionList:[{
+                    title:'单人翻译',
+                    auth:'大明粉',
+                    publishTime:'2017-02-11',
+                    wordNumber:1000,
+                    limitLevel:5,
+                    endTime:'24h',
+                    money:'200大洋',
+                    id:18
+                },{
+                    title:'多人翻译',
+                    auth:'大明粉',
+                    publishTime:'2017-02-11',
+                    wordNumber:1000,
+                    limitLevel:5,
+                    endTime:'24h',
+                    money:'200大洋',
+                    id:1
+                },{
+                    title:'测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题',
+                    auth:'大明粉',
+                    publishTime:'2017-02-11',
+                    wordNumber:1000,
+                    limitLevel:5,
+                    endTime:'24h',
+                    money:'200大洋'
+                },{
+                    title:'测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题',
+                    auth:'大明粉',
+                    publishTime:'2017-02-11',
+                    wordNumber:1000,
+                    limitLevel:5,
+                    endTime:'24h',
+                    money:'200大洋'
+                },{
+                    title:'测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题',
+                    auth:'大明粉',
+                    publishTime:'2017-02-11',
+                    wordNumber:1000,
+                    limitLevel:5,
+                    endTime:'24h',
+                    money:'200大洋'
+                },{
+                    title:'测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题',
+                    auth:'大明粉',
+                    publishTime:'2017-02-11',
+                    wordNumber:1000,
+                    limitLevel:5,
+                    endTime:'24h',
+                    money:'200大洋'
+                },{
+                    title:'测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题',
+                    auth:'大明粉',
+                    publishTime:'2017-02-11',
+                    wordNumber:1000,
+                    limitLevel:5,
+                    endTime:'24h',
+                    money:'200大洋'
+                },{
+                    title:'测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题',
+                    auth:'大明粉',
+                    publishTime:'2017-02-11',
+                    wordNumber:1000,
+                    limitLevel:5,
+                    endTime:'24h',
+                    money:'200大洋'
+                },{
+                    title:'测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题测试翻译标题',
+                    auth:'大明粉',
+                    publishTime:'2017-02-11',
+                    wordNumber:1000,
+                    limitLevel:5,
+                    endTime:'24h',
+                    money:'200大洋'
+                }],
+                dynamicList:[{
+                    img:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1492546337062&di=51be958e094bb2fba4601a1d596bed92&imgtype=0&src=http%3A%2F%2Fimg.qq745.com%2Fuploads%2Fallimg%2Fd214f9e82320fab30ba54857dbee2f2e.jpg",
+                    user:'王大白',
+                    detail:'领取第x个任务',
+                    time:'1分钟前',
+                    desc:'翻译是你最喜爱的工作,没有之一,为此工作了达数年之久,难道还说不喜爱吗?',
+                    wordNumber:500,
+                    upCount:5,
+                    downCount:0,
+                    lv:2,
+                    intro:'Translation is your favorite job,no one,to work.',
+                    receive:33,
+                    follow:22
+                },{
+                    img:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1492546337062&di=51be958e094bb2fba4601a1d596bed92&imgtype=0&src=http%3A%2F%2Fimg.qq745.com%2Fuploads%2Fallimg%2Fd214f9e82320fab30ba54857dbee2f2e.jpg",
+                    user:'王大白',
+                    detail:'领取第x个任务',
+                    time:'1分钟前',
+                    desc:'翻译是你最喜爱的工作,没有之一,为此工作了达数年之久,难道还说不喜爱吗?',
+                    wordNumber:500,
+                    upCount:5,
+                    downCount:0,
+                    lv:2,
+                    intro:'Translation is your favorite job,no one,to work.',
+                    receive:44,
+                    follow:55
+                },{
+                    img:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1492546337062&di=51be958e094bb2fba4601a1d596bed92&imgtype=0&src=http%3A%2F%2Fimg.qq745.com%2Fuploads%2Fallimg%2Fd214f9e82320fab30ba54857dbee2f2e.jpg",
+                    user:'王大白',
+                    detail:'领取第x个任务',
+                    time:'1分钟前',
+                    desc:'翻译是你最喜爱的工作,没有之一,为此工作了达数年之久,难道还说不喜爱吗?',
+                    wordNumber:500,
+                    upCount:5,
+                    downCount:0,
+                    lv:2,
+                    intro:'Translation is your favorite job,no one,to work.',
+                    receive:44,
+                    follow:55
+                },{
+                    img:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1492546337062&di=51be958e094bb2fba4601a1d596bed92&imgtype=0&src=http%3A%2F%2Fimg.qq745.com%2Fuploads%2Fallimg%2Fd214f9e82320fab30ba54857dbee2f2e.jpg",
+                    user:'王大白',
+                    detail:'领取第x个任务',
+                    time:'1分钟前',
+                    desc:'翻译是你最喜爱的工作,没有之一,为此工作了达数年之久,难道还说不喜爱吗?',
+                    wordNumber:500,
+                    upCount:5,
+                    downCount:0,
+                    lv:2,
+                    intro:'Translation is your favorite job,no one,to work.',
+                    receive:44,
+                    follow:55
+                },{
+                    img:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1492546337062&di=51be958e094bb2fba4601a1d596bed92&imgtype=0&src=http%3A%2F%2Fimg.qq745.com%2Fuploads%2Fallimg%2Fd214f9e82320fab30ba54857dbee2f2e.jpg",
+                    user:'王大白',
+                    detail:'领取第x个任务',
+                    time:'1分钟前',
+                    desc:'翻译是你最喜爱的工作,没有之一,为此工作了达数年之久,难道还说不喜爱吗?',
+                    wordNumber:500,
+                    upCount:5,
+                    downCount:0,
+                    lv:2,
+                    intro:'Translation is your favorite job,no one,to work.',
+                    receive:44,
+                    follow:55
+                },{
+                    img:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1492546337062&di=51be958e094bb2fba4601a1d596bed92&imgtype=0&src=http%3A%2F%2Fimg.qq745.com%2Fuploads%2Fallimg%2Fd214f9e82320fab30ba54857dbee2f2e.jpg",
+                    user:'王大白',
+                    detail:'领取第x个任务',
+                    time:'1分钟前',
+                    desc:'翻译是你最喜爱的工作,没有之一,为此工作了达数年之久,难道还说不喜爱吗?',
+                    wordNumber:500,
+                    upCount:5,
+                    downCount:0,
+                    lv:2,
+                    intro:'Translation is your favorite job,no one,to work.',
+                    receive:44,
+                    follow:55
+                },{
+                    img:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1492546337062&di=51be958e094bb2fba4601a1d596bed92&imgtype=0&src=http%3A%2F%2Fimg.qq745.com%2Fuploads%2Fallimg%2Fd214f9e82320fab30ba54857dbee2f2e.jpg",
+                    user:'王大白',
+                    detail:'领取第x个任务',
+                    time:'1分钟前',
+                    desc:'翻译是你最喜爱的工作,没有之一,为此工作了达数年之久,难道还说不喜爱吗?',
+                    wordNumber:500,
+                    upCount:5,
+                    downCount:0,
+                    lv:2,
+                    intro:'Translation is your favorite job,no one,to work.',
+                    receive:44,
+                    follow:55
+                }]
+            }
+        },
+        components:{
+            Scrollbar,
+            Calendar,
+            Updown
+        },
+        mounted(){
+//            this.$router.push('/login');
+        },
+        created(){
+            console.log('home created');
+            if(!this.user){
+                console.log('get user');
+                //查询用户信息
+                this.$http.get('apiv1/tmembers',{}).then(res => {
+                    if(!res.body.code){
+                        this.$store.commit(Types.SET_USER,res.body);
+                    }
+                },res => {
+
+                });
+            }
+        },
+        methods:{
+            goPublish(){
+                this.$router.push('/publish');
+            },
+            receive(id){
+                this.$router.push('/trans/'+id);
+            },
+            goUser(){
+                this.$router.push('/person/0');
+            }
+        },
+        computed:{
+            user(){
+                return this.$store.state.user.user;
+            },
+            englishPercent(){
+                var width = Math.round(this.user ? this.user.member_experience : 0 / this.user ? this.user.level_info.level_end : 1 * 10000) / 100.00 + "%";
+                return {
+                    width:width
+                }
+            },
+            japenPercent(){
+                var width = Math.round(this.user ? this.user.member_experience_jp : 0 / this.user ? this.user.level_jp_info.level_end : 1 * 10000) / 100.00 + "%";
+                return {
+                    width:width
+                }
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    .container{
+        position:relative;
+        padding-top:222px;
+        padding-bottom:0;
+        height:100%;
+    }
+
+    .qrcode{
+        position:absolute;
+        display:inline-block;
+        width:200px;
+        right:-220px;
+        top:120px;
+    }
+
+    .header-container{
+        padding:20px 0;
+    }
+
+    .fixed-container{
+        padding-bottom:15px;
+        padding-left:15px;
+        padding-right:15px;
+        border-bottom:1px solid #d6d6d6;
+        position:absolute;
+        top:100px;
+        left:0;
+        width:100%;
+    }
+
+    .exp-container{
+        float:left;
+    }
+
+    .exp{
+        line-height:20px;
+    }
+
+    .exp:last-child{
+        margin-top:10px;
+    }
+
+    .btn-publish{
+        width:140px;
+        height:40px;
+        border-radius: 20px;
+    }
+
+    .lv{
+        height:20px;
+        line-height:20px;
+        /*width:70px;*/
+        background-color:#eee;
+        /*border:1px solid #d6d6d6;*/
+        border-radius:10px;
+        padding:0 10px 0 22px;
+        position:relative;
+        float:left;
+    }
+
+    .lv img{
+        position:absolute;
+        top:0;
+        left:0;
+        z-index: 1;
+        display:inline-block;
+        height:20px;
+    }
+
+    .exp{
+        display:table;
+        /*vertical-align: middle;*/
+    }
+
+    .exp span{
+        float:left;
+        font-size:14px;
+        /*line-height:20px;*/
+        /*display:inline-block;*/
+        margin-left:10px;
+    }
+
+    .exp .progress-container{
+        display:table-cell;
+        vertical-align: middle;
+    }
+
+    .exp .progress{
+        /*float:left;*/
+        margin-left:10px;
+        height:15px;
+        margin-bottom:0;
+        width:500px;
+        /*vertical-align: middle;*/
+    }
+
+    .notice{
+        font-size:16px;
+        line-height:1;
+        white-space:nowrap;
+        overflow:hidden;
+        text-overflow:ellipsis;
+    }
+
+    .notice img{
+        float:left;
+        margin-right:5px;
+    }
+
+    .sel-container{
+        padding-top:10px;
+        /*padding-bottom:20px;*/
+    }
+
+    .sel-container .form-control{
+        border-radius:3px;
+    }
+
+    .mission{
+        padding:20px 0;
+        border-bottom:1px solid #d6d6d6;
+        position:relative;
+    }
+
+    .mission .title{
+        display:block;
+        overflow: hidden;
+        white-space:nowrap;
+        text-overflow: ellipsis;
+    }
+
+    .mission .info{
+        margin:10px 0;
+        color:#999;
+        font-size:12px;
+        line-height:1;
+    }
+
+    .mission .info .auth{
+        color:#438eff;
+        margin-right:20px;
+    }
+
+    .mission .row{
+        font-size:12px;
+    }
+
+    .mission .row .col-md-4{
+        padding-right:0;
+    }
+
+    .mission button{
+        width:80px;
+        position:absolute;
+        right:0;
+        bottom:20px;
+    }
+
+    .dynamic-title{
+        padding:15px 0;
+        border-bottom:1px solid #d6d6d6;
+        line-height:1;
+    }
+
+    .dynamic-title .title{
+        font-weight:bold;
+        display:inline-block;
+    }
+
+    .dynamic-title .title img{
+        float:left;
+        display:block;
+        height:14px;
+        margin-right:5px;
+    }
+
+    .dynamic-title .attention{
+        font-size:12px;
+        color:#999;
+        float:right;
+        display:inline-block;
+    }
+
+    .dynamic{
+        padding:15px 0;
+        position:relative;
+        border-bottom:1px solid #d6d6d6;
+    }
+
+    .dynamic .avator{
+        float:left;
+        width:36px;
+        height:36px;
+    }
+
+    .dynamic .avator .thumbnail{
+        margin-bottom:0;
+        padding:0;
+        border-radius:50%;
+        overflow:hidden;
+    }
+
+    .dynamic .content{
+        margin-left:46px;
+    }
+
+    .dynamic .content .info{
+        margin:10px 0;
+        line-height:1;
+        position:relative;
+    }
+
+    .dynamic .content .info > div.user{
+        color:#438eff;
+        margin-right:5px;
+        cursor:pointer;
+    }
+
+    .dynamic .content > .info > div{
+        /*float:left;*/
+        color:#999;
+        display:inline-block;
+    }
+
+    .dynamic .content > .info > div.time{
+        /*float:right;*/
+        font-size:12px;
+        color:#999;
+        position:absolute;
+        right:0;
+    }
+
+    .dynamic .content > .desc{
+        font-size:16px;
+        margin-bottom:10px;
+        white-space: nowrap;
+        text-overflow:ellipsis;
+        overflow:hidden;
+    }
+
+    .dynamic .content > .footer{
+        line-height:33px;
+        font-size:12px;
+    }
+
+    .card{
+        padding-bottom:10px;
+    }
+
+    .card .avator{
+        display:inline-block;
+        width:48px;
+        height:48px;
+        float:left;
+        border-radius:50%;
+    }
+
+    .card .content{
+        margin-left:58px;
+    }
+
+    .card .content > .info{
+        position:relative;
+        line-height:1;
+        margin-top:5px;
+        margin-bottom:10px;
+    }
+
+    .card .content > .info > .name{
+        font-size:18px;
+        /*float:left;*/
+        display:inline-block;
+    }
+
+    .card .content > .info > .level{
+        /*float:right;*/
+        font-size:14px;
+        line-height:18px;
+        position:absolute;
+        display:inline-block;
+        right:0;
+        top:0;
+    }
+
+    .card .content > .intro{
+        font-size:14px;
+        color:#999;
+    }
+
+    .card-footer{
+        height:50px;
+        line-height:50px;
+        background-color:#f7f7f7;
+        border-top:1px solid #d6d6d6;
+        margin:0 -10px -10px -10px;
+        padding:10px 0;
+    }
+
+    .card-footer .ctn{
+        font-size:14px;
+        line-height:30px;
+        height:30px;
+        width:100%;
+    }
+
+    .card-footer .ctn > .col{
+        width:25%;
+        float:left;
+        height:100%;
+        border-right:1px solid #d6d6d6;
+        text-align:center;
+    }
+
+    .card-footer .ctn > .col:last-child{
+        border-right:none;
+    }
+
+    .card-footer .ctn > .col > a{
+        color:#000;
+    }
+
+    .card-footer .ctn > .col > a:hover{
+        text-decoration:none;
+    }
+
+    .card-footer .ctn > .col > div{
+        line-height:15px;
+    }
+
+    .active-title{
+        padding:15px 0;
+        /*border-bottom:1px solid #d6d6d6;*/
+        line-height:1;
+    }
+
+    .active-title .title{
+        font-weight:bold;
+        display:inline-block;
+    }
+
+    .active-title .title img{
+        float: left;
+        display: block;
+        height: 14px;
+        margin-right: 5px;
+    }
+
+    .sign{
+        padding:10px;
+        background-color:#f7f7f7;
+        border:1px solid #d6d6d6;
+        border-top:none;
+        text-align:center;
+    }
+
+    .sign p{
+        margin:0;
+        margin-top:10px;
+    }
+
+    .rank .rank-block{
+        position:relative;
+    }
+
+    .rank .rank-block > .medal{
+        display:inline-block;
+        position:absolute;
+        bottom:-20px;
+        width:20px;
+        left:50%;
+        margin-left:-10px;
+    }
+
+    .rank .name{
+        margin-top:20px;
+        text-align:center;
+        overflow:hidden;
+        text-overflow:ellipsis;
+        white-space:nowrap;
+    }
+
+    .rank-list{
+        margin:20px 0;
+        border-top:1px solid #d6d6d6;
+        border-bottom:1px solid #d6d6d6;
+    }
+
+    .rank-list .rank-item{
+        height:48px;
+        padding:6px 0;
+        line-height:48px;
+        border-bottom:1px solid #d6d6d6;
+        cursor:pointer;
+    }
+
+    .rank-list .rank-item:last-child{
+        border-bottom:none;
+    }
+
+    .rank-list .rank-item > img.img-circle{
+        width:36px;
+        height:36px;
+        display:inline-block;
+        float:left;
+    }
+
+    .rank-list .rank-item > .name{
+        /*display:inline-block;*/
+        line-height:36px;
+        float:left;
+        margin-left:10px;
+    }
+
+    .rank-list .rank-item > img.next{
+        display:inline-block;
+        margin-top:8px;
+        float:right;
+        height:20px;
+    }
+
+    .about{
+        padding:20px;
+        background-color:#f7f7f7;
+        color:#000;
+        text-align:center;
+    }
+
+    .about .item{
+        margin-bottom:10px;
+    }
+
+    .about .item a{
+        color:#000;
+    }
+
+    .about p{
+        font-size:12px;
+    }
+
+    .about p:last-child{
+        margin:0;
+    }
+
+</style>

+ 23 - 0
src/components/Index.vue

@@ -0,0 +1,23 @@
+<template>
+    <div>
+        <Myheader></Myheader>
+        <router-view class="content-box"></router-view>
+        <Myfooter v-if="$route.path !== '/'"></Myfooter>
+    </div>
+</template>
+
+<script>
+    import Myheader from '@/components/Header.vue'
+    import Myfooter from '@/components/Footer.vue'
+
+    export default {
+        components:{
+            Myheader,
+            Myfooter
+        }
+    }
+</script>
+
+<style scoped>
+
+</style>

+ 184 - 0
src/components/Letter.vue

@@ -0,0 +1,184 @@
+<template>
+    <div class="container">
+        <div class="row" style="margin-top:20px;">
+            <div class="col-sm-9" style="padding:0 40px;">
+                <div v-show="tag === 'list'" class="list">
+                    <tabs :data="tabs" @click="tabClick">
+                        <button class="btn btn-primary" style="width:80px;" @click="sendMsg">发私信</button>
+                    </tabs>
+                    <div class="all" v-show="active === 0">
+                        <div class="letter-item" :class="{read:item.readFlag}" v-for="item in letters">
+                            <img :src="item.img">
+                            <span>{{item.username}}</span>
+                            <span @click="lookMsg(item)">给你发了一条私信</span>
+                            <span>{{item.date}}</span>
+                        </div>
+                    </div>
+                    <div class="unread" v-show="active === 1">
+                        <div class="letter-item" v-for="item in unread">
+                            <img :src="item.img">
+                            <span>{{item.username}}</span>
+                            <span @click="lookMsg(item)">给你发了一条私信</span>
+                            <span>{{item.date}}</span>
+                        </div>
+                    </div>
+                    <div class="read" v-show="active === 2">
+                        <div class="letter-item" v-for="item in read">
+                            <img :src="item.img">
+                            <span>{{item.username}}</span>
+                            <span @click="lookMsg(item)">给你发了一条私信</span>
+                            <span>{{item.date}}</span>
+                        </div>
+                    </div>
+                </div>
+                <div v-show="tag === 'send'">
+                    <input type="text" class="form-control" placeholder="@私信谁?">
+                    <textarea class="form-control content" rows="10"></textarea>
+                    <div style="margin-top:20px;">
+                        <button class="btn btn-primary" style="width:80px;" @click="backToList">返回</button>
+                        <button class="btn btn-danger" style="width:80px;margin-left:10px;">发送</button>
+                    </div>
+                </div>
+                <div v-show="tag === 'content'">
+                    <div class="letter-item">
+                        <img :src="msgItem.img">
+                        <span>{{msgItem.username}}</span>
+                        <span>给你发了一条私信</span>
+                        <span>{{msgItem.date}}</span>
+                    </div>
+                    <p style="padding-left:42px;margin-top:10px;">{{msgItem.content}}</p>
+                    <div>
+                        <button class="btn btn-primary" style="width:80px;margin-left:42px;" @click="backToList">返回</button>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <list :data="list" :active="3"></list>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import List from './SideList.vue'
+    import Tabs from './Tabs.vue'
+    import {SIDE_LIST} from '../const'
+
+    export default{
+        components:{
+            List,
+            Tabs
+        },
+        data(){
+            return {
+                tag:'list',
+                msgItem:{},
+                list:SIDE_LIST,
+                tabs:[{
+                    title:'全部消息'
+                },{
+                    title:'未读消息'
+                },{
+                    title:'已读消息'
+                }],
+                letters:[{
+                    img:require('../assets/headimg.png'),
+                    username:'王大白',
+                    readFlag:false,
+                    date:'2017-03-09',
+                    content:'测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容'
+                },{
+                    img:require('../assets/headimg.png'),
+                    username:'王大白',
+                    readFlag:false,
+                    date:'2017-03-09',
+                    content:'测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容'
+                },{
+                    img:require('../assets/headimg.png'),
+                    username:'王大白',
+                    readFlag:true,
+                    date:'2017-03-09',
+                    content:'测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容'
+                },{
+                    img:require('../assets/headimg.png'),
+                    username:'王大白',
+                    readFlag:true,
+                    date:'2017-03-09',
+                    content:'测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容'
+                }],
+                active:0
+            }
+        },
+        computed:{
+            unread(){
+                return this.letters.filter((item) => {
+                    return !item.readFlag;
+                });
+            },
+            read(){
+                return this.letters.filter((item) => {
+                    return item.readFlag;
+                });
+            }
+        },
+        methods:{
+            tabClick(idx){
+                if(this.active !== idx)this.active = idx;
+            },
+            sendMsg(){
+                this.tag = 'send';
+            },
+            backToList(){
+                this.tag = 'list';
+            },
+            lookMsg(item){
+                this.msgItem = item;
+                this.tag = 'content';
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    .letter-item{
+        font-size:0;
+        line-height:32px;
+        margin-top:10px;
+    }
+
+    .letter-item img{
+        width:32px;
+        height:32px;
+    }
+
+    .letter-item span{
+        font-size:14px;
+        vertical-align: middle;
+        margin-left:10px;
+    }
+
+    .letter-item span:last-child{
+        float:right;
+        font-size:12px;
+        color:#999;
+    }
+
+    .letter-item button{
+        float:right;
+        width:100px;
+    }
+
+    .letter-item.read span{
+        color:#999;
+    }
+
+    textarea.content{
+        border-radius:5px;
+        margin-top:10px;
+    }
+
+    .list .letter-item span:nth-child(3){
+        cursor:pointer;
+        text-decoration: underline;
+    }
+</style>

+ 56 - 0
src/components/List.vue

@@ -0,0 +1,56 @@
+<template>
+    <div class="list">
+        <div class="item" v-for="item in data" @click="itemClick(item.path)">
+            <img :src="item.img">
+            <span>{{item.title}}</span>
+        </div>
+    </div>
+</template>
+
+<script>
+    export default{
+        props:{
+            data:{
+                type:Array,
+                default(){
+                    return [];
+                }
+            }
+        },
+        methods:{
+            itemClick(path){
+                this.$emit('click',path);
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    .list{
+        margin:-10px;
+    }
+
+    .item{
+        font-size:0;
+        padding:5px 10px;
+        cursor:pointer;
+    }
+
+    .item:not(:last-child){
+        border-bottom:1px solid #d6d6d6;
+    }
+
+    .item:hover{
+        background-color:#fff294;
+    }
+
+    .item img{
+        width:16px;
+    }
+
+    .item span{
+        font-size:14px;
+        vertical-align: middle;
+        margin-left:5px;
+    }
+</style>

+ 204 - 0
src/components/Login.vue

@@ -0,0 +1,204 @@
+<template>
+    <div>
+        <div class="login-container">
+            <div class="title">
+                <div class="navs">
+                    <a href="javascript:void 0" :class="{active:active === 0}" @click="activeNav(0)">普通登陆</a>
+                    <a href="javascript:void 0" :class="{active:active === 1}" @click="activeNav(1)">快速登陆</a>
+                    <span class="decoration" :style="{left:active === 0 ? '0' : '50%'}"></span>
+                </div>
+            </div>
+            <div class="body">
+                <div class="form">
+                    <div class="form-item clearfix">
+                        <img class="icon" src="../assets/phone.png">
+                        <input type="text" v-validate="'required'" :class="{'is-danger':errors.has('username')}" name="username" class="form-control input" placeholder="请输入手机号或邮箱" v-model="loginData.username">
+                        <span v-show="errors.has('username')" class="help is-danger">请输入手机号或邮箱</span>
+                    </div>
+                    <div class="form-item clearfix" v-show="active === 0">
+                        <img class="icon" src="../assets/password.png">
+                        <input type="password" v-validate="'required'" :class="{'is-danger':errors.has('password')}" name="password" class="form-control input" placeholder="请输入密码" v-model="loginData.password">
+                        <span v-show="errors.has('password')" class="help is-danger">请输入密码</span>
+                    </div>
+                    <div class="form-item clearfix" v-show="active === 1">
+                        <img class="icon" src="../assets/idencode.png">
+                        <div class="input-group">
+                            <input type="text" v-validate="'required'" :class="{'is-danger':errors.has('captche')}" name="captche" class="form-control" placeholder="请输入验证码" v-model="loginData.captche">
+                            <span class="input-group-btn">
+                                <button class="btn btn-primary" type="button">获取验证码</button>
+                            </span>
+                        </div>
+                        <span v-show="errors.has('captche')" class="help is-danger">请输入验证码</span>
+                    </div>
+                    <div class="clearfix operate" style="padding-top:10px;">
+                        <button class="btn btn-danger" style="width:120px" @click="login">登录</button>
+                        <router-link to="/reg">免费注册</router-link>
+                        <router-link to="/forget">忘记密码?</router-link>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import * as Types from '../store/mutation-types'
+
+    export default{
+        data(){
+            return {
+                active:0,
+                loginData:{}
+            }
+        },
+        methods:{
+            activeNav(idx){
+                this.active = idx;
+            },
+            login(){
+                var validObj;
+                if(this.active == 0){
+                    validObj = {
+                        'username':this.loginData.username,
+                        'password':this.loginData.password
+                    }
+                }else{
+                    validObj = {
+                        'username':this.loginData.username,
+                        'captche':this.loginData.captche
+                    }
+                }
+                this.$validator.validateAll(validObj).then(() => {
+                    var form = {};
+//                    form.append('username',this.loginData.username);
+                    var reg = new RegExp("^[0-9]*$");
+                    if(reg.test(this.loginData.username)){
+                        form.mobile = this.loginData.username;
+//                        form.append('mobile',this.loginData.username);
+                    }else{
+                        form.email = this.loginData.username;
+//                        form.append('email',this.loginData.username);
+                    }
+                    if(this.active == 0){
+                        form.password = this.loginData.password;
+                        form.type = 'slow';
+//                        form.append('password',this.loginData.password);
+//                        form.append('type','slow');
+                    }else{
+                        form.captche = this.loginData.captche;
+                        form.type = 'fast';
+//                        form.append('captche',this.loginData.captche);
+//                        form.append('type','fast');
+                    }
+                    this.$http.put('apiv1/tmembers/login',form,{emulateJSON:true}).then(res => {
+                        if(!res.body.code){
+                            this.$store.commit(Types.SET_USER,res.body);
+                            this.$router.push('/');
+                        }
+                    },res => {
+                        console.log('错误');
+                    });
+                }).catch(() => {
+
+                });
+
+            }
+        },
+        beforeCreate(){
+
+        }
+    }
+</script>
+
+<style scoped>
+    .login-container{
+        width:600px;
+        /*height:300px;*/
+        /*background-color:#000;*/
+        top:center;
+        left:center;
+    }
+
+    .title{
+        text-align:center;
+        height:70px;
+        background-color:#fdd32c;
+        line-height:70px;
+    }
+
+    .title .navs{
+        display:inline-block;
+        position:relative;
+    }
+
+    .title .navs a{
+        float:left;
+        display:inline-block;
+        color:#666;
+        font-size:24px;
+        width:144px;
+        margin:0 10px;
+    }
+
+    .title .navs a:hover{
+        color:#000;
+        font-weight:bold;
+        text-decoration: none;
+    }
+
+    .title .navs .decoration{
+        width:144px;
+        margin:0 10px;
+        position:absolute;
+        height:6px;
+        background-color:#000;
+        bottom:0;
+        left:0;
+        transition:left 0.3s;
+    }
+
+    .title .navs a.active{
+        color:#000;
+        font-weight:bold;
+        text-decoration: none;
+    }
+
+    .body{
+        border-width:0 2px 2px 2px;
+        border-style:solid;
+        border-color:#d6d6d6;
+        padding:80px 0;
+        text-align:center;
+    }
+
+    .body .form{
+        display:inline-block;
+    }
+
+    .body .form .form-item{
+        margin-bottom:20px;
+    }
+
+    .body .form .icon{
+        float:left;
+        margin-top:2px;
+    }
+    .body .form .input,.body .form .input-group{
+        float:left;
+        width:300px;
+        margin-left:6px;
+    }
+    .body .form .operate button{
+        float:left;
+        margin-left:36px;
+    }
+
+    .body .form .operate a{
+        float:left;
+        display:inline-block;
+        line-height:33px;
+        margin-left:20px;
+        color:#000;
+        /*font-weight:bold;*/
+    }
+</style>

+ 110 - 0
src/components/Message.vue

@@ -0,0 +1,110 @@
+<template>
+    <div class="container">
+        <div class="row" style="margin-top:20px;">
+            <div class="col-sm-9" style="padding:0 40px;">
+                <div class="title">
+                    消息
+                </div>
+                <div class="message-item" v-for="(item,index) in messages">
+                    <img :src="item.img">
+                    <span>{{item.username}}</span>
+                    <span>{{item.eventMsg}}</span>
+                    <button class="btn btn-primary" style="margin-left:10px;" v-if="item.eventType === '1'">同意</button>
+                    <div class="opt">
+                        <span>{{item.date}}</span>
+                        <img src="../assets/opt-remove.png" @click="deleteMsg(index)">
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-3">
+                <list :data="list" :active="-1"></list>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import List from './SideList.vue'
+    import {SIDE_LIST} from '../const'
+
+    export default{
+        components:{
+            List
+        },
+        data(){
+            return {
+                list:SIDE_LIST,
+                messages:[{
+                    img:require('../assets/headimg.png'),
+                    username:'王大白',
+                    date:'2017-03-09',
+                    eventType:'0',
+                    eventMsg:'评论了你的译文'
+                },{
+                    img:require('../assets/headimg.png'),
+                    username:'王大白',
+                    date:'2017-03-09',
+                    eventType:'0',
+                    eventMsg:'评论了你的译文'
+                },{
+                    img:require('../assets/headimg.png'),
+                    username:'王大白',
+                    date:'2017-03-09',
+                    eventType:'0',
+                    eventMsg:'评论了你的译文'
+                },{
+                    img:require('../assets/headimg.png'),
+                    username:'王大白',
+                    date:'2017-03-09',
+                    eventType:'1',
+                    eventMsg:'给你发了一个翻译校对邀请'
+                }],
+            }
+        },
+        methods:{
+            deleteMsg(idx){
+                this.messages.splice(idx,1);
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    .title{
+        font-size:18px;
+        font-weight:bold;
+        line-height:40px;
+        border-bottom:1px solid #d6d6d6;
+        padding-left:20px;
+    }
+
+    .message-item{
+        font-size:0;
+        line-height:32px;
+        margin-top:10px;
+    }
+
+    .message-item img{
+        width:32px;
+        height:32px;
+    }
+
+    .message-item span{
+        font-size:14px;
+        vertical-align: middle;
+        margin-left:10px;
+    }
+
+    .message-item .opt{
+        float:right;
+        font-size:12px;
+        color:#999;
+    }
+
+    .message-item .opt img{
+        width:16px;
+        height:16px;
+        margin-left:10px;
+        cursor:pointer;
+    }
+</style>

+ 355 - 0
src/components/Mission.vue

@@ -0,0 +1,355 @@
+<template>
+    <div class="container">
+        <div class="row" style="margin-bottom:20px;">
+            <div class="col-sm-6">
+                <div class="user">
+                    <img class="img-circle" :src="task_info.task_member_info.member_header_img ? task_info.task_member_info.member_header_img : defImg">
+                    <span>{{task_info.task_member_info ? task_info.task_member_info.member_nickname ? task_info.task_member_info.member_nickname : task_info.task_member_info.member_username : '无名的旅人'}}</span>
+                </div>
+                <div class="title">{{task_info.task_title}}</div>
+                <p class="content">
+                    {{task_info.task_content}}
+                </p>
+                <div class="row" style="margin-top:12px;">
+                    <div class="col-md-12">
+                        <span class="lb">原文链接:</span>
+                        <div class="input">
+                            <input type="text" class="form-control" :value="task_info.task_url" readonly>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="single" v-if="isSingle">
+                    <div class="header clearfix">
+                        <img class="img-circle" src="../assets/headimg.png">
+                        <span>王大白</span>
+                        <div class="btns">
+                            <button class="btn btn-primary" @click="proof">进行校对</button>
+                            <button class="btn btn-primary">邀请校对</button>
+                            <button class="btn btn-danger">评分</button>
+                        </div>
+                    </div>
+                    <div class="time">
+                        <span>领取时间:2017-01-01 12:00</span><span>完成时间:2017-01-01 12:00</span>
+                    </div>
+                    <div class="translate">
+                        <div class="title">翻译标题翻译标题</div>
+                        <p class="content">1。 高度自律和自黑
+                              为什么不说自信呢?不自信的人,普遍内心比较脆弱。一个自信的人,对自己充满信心,做事往往带着积极向上的力量,并时刻充满激情。所有的盲目自信,和空腹自信,都是自以为是。心中要有真才实学,哪怕在不断的试错,但终究能到达攀登高峰的那一天。
+                              人的自信到底从何而来?以及如何培养自己的自信?高度的自信,从高度的自律而来。自律又是什么?自律就是自己管理自己,自己约束自己。这是一个很重要的能力。先学会克制自己,用严格的日程表来控制生活,才能在这种自律中不断磨练出自信。自信也代表着对事情的控制能力,连最基本的时间都控制不了,谈何自信?
+                              除了自律以外,自黑的能力也相当重要。世界之大,什么鸟都有。等你哪一天稍微做出点成绩,很多认识或不认识的人便在背后,唧唧歪歪的议论是非。从最开始的吐槽,到断章取义的论断甚至无趣的黑你。
+                              自黑就是自己嘲笑自己,自己黑色幽默自己。自黑是一种沟通方式,也是一种境界,更是一种另类的修养。自黑不是等到有人说你时才出现,而是从头到尾都需要有的能力。你必须看透那些无聊恶俗的人,要比他们还会擅长黑自己,待他们自知无趣后,便会羞愧的退场而去。
+                              2。 必须经历绝望
+                              经历绝望的意思,就是已经走过这段岁月。也许你还未曾绝望过,并不意味着你不坚强,但一定没有经历过绝望的人坚强。未绝望过的人生是不完美的人生。绝望可能是情感、事业抑或无法面对的孤独等等。
+                              「必须」 是一个前缀词,一个重要的状态。「必须」并非主动选择,而是做好充分的心理准备。当绝望来临时,坦然无惧的接受它,即使当下极其痛苦,甚至失去了自我。在绝望中寻找希望,才是值得体验的一种人生。
+                              强大的人不是征服什么,而是能承受什么。一些事情,只有经历过了,才能明白其中的道理,和懂得人生的真谛。绝望并不可怕,可怕的是失去勇气和激情。经历绝望,但不要被绝望吞噬。相反你要胜过它,如同战胜黑暗,迎接光明一样。
+                        </p>
+                    </div>
+                    <div class="footer clearfix">
+                        <updown class="updown"></updown>
+                        <Report class="pull-left" style="margin-left:10px;display:block;"></Report>
+                    </div>
+                    <textarea class="form-control" rows="3" style="margin-top:10px;color:#000" placeholder="评论"></textarea>
+                    <div style="margin-top:10px;">
+                        <button class="btn btn-primary pull-right" style="width:80px;">提交</button>
+                    </div>
+                </div>
+
+                <div class="multi" v-else>
+                    <div class="active-title">
+                        <div class="tt">
+                            <img src="../assets/trans-list.png">
+                            译文列表
+                        </div>
+                    </div>
+                    <div class="trans-list">
+                        <div class="item" v-for="n in 3">
+                            <div class="u">
+                                <div class="up">
+                                    5
+                                    <Updown class="updown"></Updown>
+                                </div>
+                                <img class="img-circle" src="../assets/headimg.png">
+                            </div>
+                            <div class="right">
+                                <div class="intro">
+                                    <span>王大白</span>
+                                    <span>翻译了该任务</span>
+                                    <span>领取时间:2017-01-01 12:00</span>
+                                    <span>完成时间:2017-01-01 12:00</span>
+                                </div>
+                                <p>翻译是你最喜爱的工作,没有之一,为此工作了达数年之久,难道还说不喜爱吗?</p>
+                                <div class="btn-block clearfix">
+                                    <button class="btn btn-primary pull-left">查看译文</button>
+                                    <button class="btn btn-primary pull-left" @click="proof">进行校对</button>
+                                    <button class="btn btn-primary pull-left">邀请校对</button>
+                                    <Report class="pull-left report" style="margin-left:10px;"></Report>
+                                    <button class="btn btn-danger pull-right">评分</button>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    import Updown from './Updown.vue'
+    import Report from './Report.vue'
+
+    export default{
+        components:{
+            Updown,
+            Report
+        },
+        data(){
+            return {
+                member_task:{},
+                task_info:{},
+                defImg:require('../assets/headimg-def.png')
+            }
+        },
+        mounted(){
+
+        },
+        methods:{
+            proof(){
+                this.$router.push('/proof/'+0+'/edit');
+            }
+        },
+        computed:{
+            user(){
+                return this.$store.state.user.user ? this.$store.state.user.user : {};
+            },
+            isSingle(){
+                return this.task_info.task_type === 0 ? true :false;
+            }
+        },
+        created(){
+            this.$http.get('apiv1/ttaskinfos/'+this.$route.params.id).then(res => {
+                this.member_task = res.body.member_task;
+                this.task_info = res.body.task_info;
+            },res => {
+
+            });
+        }
+    }
+</script>
+
+<style scoped>
+    .user{
+        margin:20px 0;
+        height:36px;
+        line-height:36px;
+    }
+
+    .user img{
+        display:inline-block;
+        width:36px;
+        height:36px;
+        float:left;
+        margin-right:5px;
+    }
+
+    .user span{
+        color:#438eff;
+        float:left;
+    }
+
+    .title{
+        font-weight:bold;
+        font-size:16px;
+        line-height:1;
+        margin-bottom:10px;
+    }
+
+    .content{
+        color:#666;
+    }
+
+    .lb{
+        position:absolute;
+        left:10px;
+        line-height:34px;
+    }
+
+    .input{
+        padding-left:65px;
+    }
+
+    .header{
+        padding:20px 0 10px 0;
+        line-height:36px;
+        border-bottom:1px solid #d6d6d6;
+    }
+
+    .header img{
+        float:left;
+        display:inline-block;
+        height:36px;
+        width:36px;
+        margin-right:5px;
+    }
+
+    .header span{
+        float:left;
+        color:#438eff;
+    }
+
+    .btns{
+        float:right;
+    }
+
+    .time{
+        margin-top:10px;
+        font-size:12px;
+        color:#b8b8b8;
+        line-height:1;
+    }
+
+    .time span:nth-child(even){
+        margin-left:20px;
+    }
+
+    .translate{
+        background-color:#f7f7f7;
+        padding:15px;
+        margin-top:20px;
+    }
+
+    .translate .content{
+        margin-bottom:0;
+    }
+
+    .footer{
+        margin-top:10px;
+    }
+
+    .footer .updown{
+        float:left;
+    }
+
+    .active-title{
+        padding:30px 0 10px 0;
+        border-bottom:1px solid #d6d6d6;
+        line-height:1;
+    }
+
+    .active-title .tt{
+        font-weight:bold;
+        display:inline-block;
+    }
+
+    .active-title .tt img{
+        float: left;
+        display: block;
+        height: 14px;
+        margin-right: 5px;
+    }
+
+    .trans-list{
+
+    }
+
+    .trans-list > .item{
+        padding:10px 0 20px 0;
+        border-bottom:1px solid #d6d6d6;
+        position:relative;
+    }
+
+    .trans-list > .item > .u{
+        position:absolute;
+        top:10px;
+        left:0;
+        width:80px;
+        line-height:36px;
+    }
+
+    .trans-list > .item > .u > .up{
+        display:inline-block;
+        width:34px;
+        height:34px;
+        text-align:center;
+        border:1px solid #d6d6d6;
+        border-radius:50%;
+        vertical-align: middle;
+        line-height:34px;
+        float:left;
+        margin-top:1px;
+        cursor:pointer;
+        position:relative;
+    }
+
+    .trans-list > .item > .u > .up:hover{
+        background-color:#d6d6d6;
+    }
+
+    .trans-list > .item > .u > .up:hover .updown{
+        display:block;
+    }
+
+    .trans-list > .item > .u > img{
+        display:inline-block;
+        width:36px;
+        height:36px;
+        float:left;
+        margin-left:10px;
+    }
+
+    .trans-list > .item > .right{
+        margin-left:85px;
+    }
+
+    .trans-list > .item > .right > .intro{
+        line-height:36px;
+        margin-bottom:5px;
+    }
+
+    .trans-list > .item > .right > .intro > span:nth-child(1){
+        color:#438eff;
+        margin-left:0;
+        font-size:14px;
+    }
+
+    .trans-list > .item > .right > .intro > span{
+        margin-left:5px;
+        color:#b8b8b8;
+        font-size:12px;
+    }
+
+    .trans-list > .item > .right > p{
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        overflow:hidden;
+        margin-bottom:15px;
+    }
+
+    .trans-list > .item > .right > .btn-block .pull-left:not(:first-child){
+        margin-left:5px;
+    }
+
+    .trans-list > .item > .u > .up > .updown{
+        position:absolute;
+        top:33px;
+        left:0;
+        display:none;
+        text-align:left;
+        line-height:40px;
+    }
+
+    .report{
+        display:none;
+    }
+
+    .trans-list > .item:hover .report{
+        display:block;
+    }
+
+    textarea{
+        border-radius:3px;
+    }
+
+</style>

+ 454 - 0
src/components/Person.vue

@@ -0,0 +1,454 @@
+<template>
+    <div class="container">
+        <div class="row">
+            <div class="col-sm-6">
+                <div class="header">
+                    <img src="../assets/pcenter.png">
+                    <span class="title">个人资料</span>
+                    <div class="exp clearfix">
+                        <div class="lv">
+                            <img src="../assets/english.png">
+                            Lv 10
+                        </div>
+                        <span>经验值:</span>
+                        <span>600字 / 1000字</span>
+                    </div>
+                    <div class="exp clearfix">
+                        <div class="lv">
+                            <img src="../assets/japen.png">
+                            Lv 10
+                        </div>
+                        <span>经验值:</span>
+                        <span>600字 / 1000字</span>
+                    </div>
+                </div>
+                <div class="profile">
+                    <div class="row">
+                        <div class="col-sm-3">
+                            <img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1494004375030&di=9d941b5b1417be938b6262ebdcab9f36&imgtype=0&src=http%3A%2F%2Fpic.cnitblog.com%2Favatar%2F552009%2F20141030013312.png" alt="" class="img-rounded img-responsive">
+                            <div class="nickname">
+                                昵称昵称昵称
+                            </div>
+                            <div class="edit">
+                                <a href="javascript:void 0">编辑个人资料</a>
+                            </div>
+                        </div>
+                        <div class="col-sm-9">
+                            <div class="item">
+                                <img src="../assets/school.png">
+                                <div class="content">
+                                    <div class="word" style="border-radius:16px;">
+                                        测试测试测试
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="item">
+                                <img src="../assets/location.png">
+                                <div class="content">
+                                    <div class="word" style="border-radius:16px;">
+                                        测试测试测试
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="item">
+                                <img src="../assets/aword.png">
+                                <div class="content">
+                                    <div class="word" style="border-radius:5px;">
+                                        测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="item">
+                                <img src="../assets/intro.png">
+                                <div class="content">
+                                    <div class="word" style="border-radius:5px;">
+                                        测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="header">
+                    <img src="../assets/account.png">
+                    <span class="title">个人账户</span>
+                    <div class="recharge">
+                        <a href="javascript:void 0">充值记录</a>
+                        <button class="btn btn-primary">充值</button>
+                    </div>
+                </div>
+                <div class="account">
+                    <div class="row" style="padding-top:20px;">
+                        <div class="col-sm-6" style="border-right:1px solid #d6d6d6;">
+                            <div class="money">
+                                当前金额:<span>1030</span>大洋<a href="javascript:void 0">收支记录</a>
+                            </div>
+                            <div class="alipay">
+                                <span class="title">支付宝账号:</span>
+                                <div class="input">
+                                    <input type="text" class="form-control">
+                                </div>
+                            </div>
+                            <div style="margin-top:30px;">
+                                <button class="btn btn-danger" style="width:100px;">提现</button>
+                            </div>
+                            <p style="margin-top:10px;color:#b8b8b8;">每月1-3号可申请提现,提现金额需大于1000大洋</p>
+                        </div>
+                        <div class="col-sm-6">
+                            <div class="invitation">
+                                <div class="title">
+                                    邀请码购买记录
+                                </div>
+                                <div class="item" :class="{used:item.used}" v-for="item in invCodes">
+                                    邀请码:{{item.code}}
+                                    <span>{{item.state}}</span>
+                                    <span>{{item.date}}</span>
+                                </div>
+                            </div>
+                            <div style="margin-top:10px;">
+                                <button class="btn btn-primary">购买邀请码</button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row" style="margin-top:30px;">
+            <div class="col-sm-6">
+                <div class="header">
+                    <img src="../assets/mission.png">
+                    <span class="title">我领取的任务</span>
+                    <div class="mission-desc">
+                        <span>平均分:</span>
+                        <span>4.5</span>
+                        <span>已翻译数量:</span>
+                        <span>29</span>
+                        <span>领取数:</span>
+                        <span>30</span>
+                        <span>总字数:</span>
+                        <span>12000</span>
+                    </div>
+                </div>
+                <div class="mission">
+                    <div>
+                        <span class="title">小蝌蚪的未来是光明的</span>
+                        <div class="time">
+                            倒计时:
+                            <span>22:23:35</span>
+                        </div>
+                    </div>
+                    <div style="margin-top:20px;">
+                        <button class="btn btn-primary">原文</button>
+                        <button class="btn btn-danger">翻译</button>
+                        <button class="btn btn-danger">校对</button>
+                    </div>
+                </div>
+            </div>
+            <div class="col-sm-6">
+                <div class="header">
+                    <img src="../assets/glossary.png">
+                    <span class="title">生词表</span>
+                </div>
+                <div class="glossary clearfix">
+                    <div class="word" v-for="n in 10">
+                        <span>Boy 男孩</span>
+                        <img src="../assets/remove.png">
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+    export default{
+        data(){
+            return {
+                invCodes:[{
+                    code:'YUE8',
+                    state:'未使用',
+                    date:'2017-01-01',
+                    used:false
+                },{
+                    code:'YUE8',
+                    state:'已使用',
+                    date:'2017-01-01',
+                    used:true
+                },{
+                    code:'YUE8',
+                    state:'已使用',
+                    date:'2017-01-01',
+                    used:true
+                },{
+                    code:'YUE8',
+                    state:'已使用',
+                    date:'2017-01-01',
+                    used:true
+                }]
+            }
+        }
+    }
+</script>
+
+<style scoped>
+    .header{
+        padding-top:25px;
+        padding-bottom:15px;
+        border-bottom:1px solid #d6d6d6;
+        font-size:0;
+    }
+
+    .header > img{
+        width:16px;
+        height:16px;
+    }
+
+    .header > span.title{
+        font-size:16px;
+        vertical-align: middle;
+        margin-left:5px;
+        font-weight:bold;
+    }
+
+    .exp{
+        line-height:20px;
+    }
+
+    .lv{
+        height:20px;
+        line-height:20px;
+        /*width:70px;*/
+        background-color:#eee;
+        /*border:1px solid #d6d6d6;*/
+        border-radius:10px;
+        padding:0 10px 0 22px;
+        position:relative;
+        float:left;
+        font-size:14px;
+    }
+
+    .lv img{
+        position:absolute;
+        top:0;
+        left:0;
+        z-index: 1;
+        display:inline-block;
+        height:20px;
+    }
+
+    .exp{
+        display:inline-table;
+        vertical-align: middle;
+        margin-left:10px;
+    }
+
+    .exp span{
+        float:left;
+        font-size:12px;
+        /*line-height:20px;*/
+        /*display:inline-block;*/
+        margin-left:10px;
+    }
+
+    .profile{
+        padding:20px 0;
+    }
+
+    .profile .img-rounded{
+        border-radius:5px;
+    }
+
+    .profile .item{
+        position:relative;
+    }
+
+    .profile .item:not(:first-child){
+        margin-top:10px;
+    }
+
+    .profile .item img{
+        width:32px;
+        height:32px;
+        position:absolute;
+        top:0;
+        left:0px;
+    }
+
+    .profile .item .content{
+        padding-left:40px;
+    }
+
+    .profile .item .content .word{
+        padding:6px 12px;
+        background-color:#f7f7f7;
+    }
+
+    .nickname{
+        font-size:18px;
+        font-weight:bold;
+        text-align:center;
+        text-overflow:ellipsis;
+        overflow:hidden;
+        white-space:nowrap;
+        margin-top:12px;
+        line-height:1;
+    }
+
+    .edit{
+        text-align:center;
+        margin-top:10px;
+        line-height:1;
+    }
+
+    .edit a{
+        color:#000;
+        font-size:12px;
+        text-decoration: underline;
+    }
+
+    .recharge{
+        float:right;
+        font-size:14px;
+        margin-top:-6px;
+    }
+
+    .recharge a{
+        color:#000;
+        vertical-align: middle;
+        text-decoration: underline;
+    }
+
+    .recharge button{
+        vertical-align: middle;
+        width:80px;
+        margin-left:10px;
+    }
+
+    .account .money{
+        margin-top:20px;
+        color:#666;
+    }
+
+    .account .money span{
+        color:#fe5e5e;
+        font-size:36px;
+    }
+
+    .account .money a{
+        color:#000;
+        margin-left:20px;
+        text-decoration: underline;
+    }
+
+    .alipay .title{
+        position:absolute;
+        left:10px;
+        line-height:34px;
+        color:#666;
+    }
+
+    .alipay .input{
+        padding-left:89px;
+    }
+
+    .invitation{
+        border:1px solid #d6d6d6;
+    }
+
+    .invitation .title{
+        padding:15px 10px;
+        line-height:1;
+        background-color:#d6d6d6;
+        font-weight:bold;
+    }
+
+    .invitation .item{
+        padding:10px;
+        font-size:12px;
+    }
+
+    .invitation .item:nth-child(odd){
+        background-color:#f7f7f7;
+    }
+
+    .invitation .item.used{
+        color:#999;
+    }
+
+    .invitation .item span{
+        margin-left:5px;
+    }
+
+    .header .mission-desc{
+        float:right;
+        font-size:14px;
+        line-height:23px;
+        color:#666;
+    }
+
+    .header .mission-desc span{
+        vertical-align: middle;
+    }
+    .header .mission-desc span:nth-child(odd){
+        margin-left:5px;
+    }
+    .header .mission-desc span:nth-child(even){
+        color:#fe5e5e;
+    }
+
+    .mission,.glossary{
+        margin-top:20px;
+        padding:20px;
+        background-color:#f7f7f7;
+        line-height:1;
+    }
+
+    .mission span.title{
+        font-size:16px;
+    }
+
+    .mission .time{
+        float:right;
+        color:#666;
+    }
+
+    .mission .time span{
+        color:#fe5e5e;
+    }
+
+    .mission button{
+        width:100px;
+    }
+
+    .mission button:not(:first-child){
+        margin-left:10px;
+    }
+
+    .glossary .word{
+        float:left;
+        /*margin-left:10px;*/
+        padding:5px;
+        font-size:0;
+    }
+
+    .glossary .word span{
+        font-size:14px;
+        vertical-align: middle;
+    }
+
+    .glossary .word span:hover{
+        text-decoration: underline;
+    }
+
+    .glossary .word:hover img{
+        display:inline-block;
+    }
+
+    .glossary .word img{
+        width:14px;
+        cursor:pointer;
+        display:none;
+    }
+</style>

+ 0 - 0
src/components/Proof.vue


部分文件因为文件数量过多而无法显示