yuantianjiao 6 years ago
parent
commit
f6886bb09a
77 changed files with 13916 additions and 0 deletions
  1. 12
    0
      .babelrc
  2. 9
    0
      .editorconfig
  3. 4
    0
      .eslintignore
  4. 29
    0
      .eslintrc.js
  5. 14
    0
      .gitignore
  6. 10
    0
      .postcssrc.js
  7. 0
    0
      `${k}
  8. 41
    0
      build/build.js
  9. 54
    0
      build/check-versions.js
  10. BIN
      build/logo.png
  11. 101
    0
      build/utils.js
  12. 22
    0
      build/vue-loader.conf.js
  13. 92
    0
      build/webpack.base.conf.js
  14. 95
    0
      build/webpack.dev.conf.js
  15. 145
    0
      build/webpack.prod.conf.js
  16. 7
    0
      config/dev.env.js
  17. 83
    0
      config/index.js
  18. 4
    0
      config/prod.env.js
  19. 12
    0
      index.html
  20. 11772
    0
      package-lock.json
  21. 77
    0
      package.json
  22. 24
    0
      src/App.vue
  23. BIN
      src/assets/bg.png
  24. BIN
      src/assets/bolang.png
  25. BIN
      src/assets/bottomMsg.png
  26. BIN
      src/assets/dialog.png
  27. BIN
      src/assets/down.png
  28. BIN
      src/assets/font/hkhb.ttf
  29. BIN
      src/assets/heixing.png
  30. BIN
      src/assets/huxian.png
  31. BIN
      src/assets/jiantou.png
  32. BIN
      src/assets/juxing.png
  33. BIN
      src/assets/line1.png
  34. BIN
      src/assets/line2.png
  35. BIN
      src/assets/line3.png
  36. BIN
      src/assets/line4.png
  37. BIN
      src/assets/line5.png
  38. BIN
      src/assets/line6.png
  39. BIN
      src/assets/line7.png
  40. BIN
      src/assets/line8.png
  41. BIN
      src/assets/line9.png
  42. BIN
      src/assets/linjiang.png
  43. BIN
      src/assets/lq.png
  44. BIN
      src/assets/qrCode.jpg
  45. BIN
      src/assets/quan.png
  46. BIN
      src/assets/shuangyuan.png
  47. BIN
      src/assets/tanchuang.png
  48. BIN
      src/assets/touxiang.png
  49. BIN
      src/assets/xiaoniao.png
  50. BIN
      src/assets/xiaosenlin.png
  51. BIN
      src/assets/yinfu1.png
  52. BIN
      src/assets/yinfu2.png
  53. BIN
      src/assets/yinfu3.png
  54. BIN
      src/assets/yinfu4.png
  55. BIN
      src/assets/yinfu5.png
  56. BIN
      src/assets/zhi.png
  57. BIN
      src/assets/zhizhen.png
  58. BIN
      src/assets/zhuanpan.png
  59. 65
    0
      src/components/qrCodeCard/qrCodeCard.vue
  60. 7
    0
      src/config/index.js
  61. 27
    0
      src/main.js
  62. 280
    0
      src/page/index/index.vue
  63. 331
    0
      src/page/index/page.scss
  64. 52
    0
      src/page/lotteryDetail/index.vue
  65. 16
    0
      src/page/lotteryDetail/page.scss
  66. 57
    0
      src/page/lotteryList/index.vue
  67. 23
    0
      src/page/lotteryList/page.scss
  68. 30
    0
      src/router/index.js
  69. 130
    0
      src/store/app.js
  70. 26
    0
      src/store/index.js
  71. 69
    0
      src/store/prize.js
  72. 72
    0
      src/style/main.css
  73. 60
    0
      src/util/ajax.js
  74. 39
    0
      src/util/api.js
  75. 25
    0
      src/util/util.js
  76. 0
    0
      static/.gitkeep
  77. 0
    0
      {

+ 12
- 0
.babelrc View File

1
+{
2
+  "presets": [
3
+    ["env", {
4
+      "modules": false,
5
+      "targets": {
6
+        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7
+      }
8
+    }],
9
+    "stage-2"
10
+  ],
11
+  "plugins": ["transform-vue-jsx", "transform-runtime"]
12
+}

+ 9
- 0
.editorconfig View File

1
+root = true
2
+
3
+[*]
4
+charset = utf-8
5
+indent_style = space
6
+indent_size = 2
7
+end_of_line = lf
8
+insert_final_newline = true
9
+trim_trailing_whitespace = true

+ 4
- 0
.eslintignore View File

1
+/build/
2
+/config/
3
+/dist/
4
+/*.js

+ 29
- 0
.eslintrc.js View File

1
+// https://eslint.org/docs/user-guide/configuring
2
+
3
+module.exports = {
4
+  root: true,
5
+  parserOptions: {
6
+    parser: 'babel-eslint'
7
+  },
8
+  env: {
9
+    browser: true,
10
+  },
11
+  extends: [
12
+    // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
13
+    // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
14
+    'plugin:vue/essential', 
15
+    // https://github.com/standard/standard/blob/master/docs/RULES-en.md
16
+    'standard'
17
+  ],
18
+  // required to lint *.vue files
19
+  plugins: [
20
+    'vue'
21
+  ],
22
+  // add your custom rules here
23
+  rules: {
24
+    // allow async-await
25
+    'generator-star-spacing': 'off',
26
+    // allow debugger during development
27
+    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
28
+  }
29
+}

+ 14
- 0
.gitignore View File

1
+.DS_Store
2
+node_modules/
3
+/dist/
4
+npm-debug.log*
5
+yarn-debug.log*
6
+yarn-error.log*
7
+
8
+# Editor directories and files
9
+.idea
10
+.vscode
11
+*.suo
12
+*.ntvs*
13
+*.njsproj
14
+*.sln

+ 10
- 0
.postcssrc.js View File

1
+// https://github.com/michael-ciniawsky/postcss-load-config
2
+
3
+module.exports = {
4
+  "plugins": {
5
+    "postcss-import": {},
6
+    "postcss-url": {},
7
+    // to edit target browsers: use "browserslist" field in package.json
8
+    "autoprefixer": {}
9
+  }
10
+}

+ 0
- 0
`${k} View File


+ 41
- 0
build/build.js View File

1
+'use strict'
2
+require('./check-versions')()
3
+
4
+process.env.NODE_ENV = 'production'
5
+
6
+const ora = require('ora')
7
+const rm = require('rimraf')
8
+const path = require('path')
9
+const chalk = require('chalk')
10
+const webpack = require('webpack')
11
+const config = require('../config')
12
+const webpackConfig = require('./webpack.prod.conf')
13
+
14
+const spinner = ora('building for production...')
15
+spinner.start()
16
+
17
+rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18
+  if (err) throw err
19
+  webpack(webpackConfig, (err, stats) => {
20
+    spinner.stop()
21
+    if (err) throw err
22
+    process.stdout.write(stats.toString({
23
+      colors: true,
24
+      modules: false,
25
+      children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26
+      chunks: false,
27
+      chunkModules: false
28
+    }) + '\n\n')
29
+
30
+    if (stats.hasErrors()) {
31
+      console.log(chalk.red('  Build failed with errors.\n'))
32
+      process.exit(1)
33
+    }
34
+
35
+    console.log(chalk.cyan('  Build complete.\n'))
36
+    console.log(chalk.yellow(
37
+      '  Tip: built files are meant to be served over an HTTP server.\n' +
38
+      '  Opening index.html over file:// won\'t work.\n'
39
+    ))
40
+  })
41
+})

+ 54
- 0
build/check-versions.js View File

1
+'use strict'
2
+const chalk = require('chalk')
3
+const semver = require('semver')
4
+const packageConfig = require('../package.json')
5
+const shell = require('shelljs')
6
+
7
+function exec (cmd) {
8
+  return require('child_process').execSync(cmd).toString().trim()
9
+}
10
+
11
+const versionRequirements = [
12
+  {
13
+    name: 'node',
14
+    currentVersion: semver.clean(process.version),
15
+    versionRequirement: packageConfig.engines.node
16
+  }
17
+]
18
+
19
+if (shell.which('npm')) {
20
+  versionRequirements.push({
21
+    name: 'npm',
22
+    currentVersion: exec('npm --version'),
23
+    versionRequirement: packageConfig.engines.npm
24
+  })
25
+}
26
+
27
+module.exports = function () {
28
+  const warnings = []
29
+
30
+  for (let i = 0; i < versionRequirements.length; i++) {
31
+    const mod = versionRequirements[i]
32
+
33
+    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34
+      warnings.push(mod.name + ': ' +
35
+        chalk.red(mod.currentVersion) + ' should be ' +
36
+        chalk.green(mod.versionRequirement)
37
+      )
38
+    }
39
+  }
40
+
41
+  if (warnings.length) {
42
+    console.log('')
43
+    console.log(chalk.yellow('To use this template, you must update following to modules:'))
44
+    console.log()
45
+
46
+    for (let i = 0; i < warnings.length; i++) {
47
+      const warning = warnings[i]
48
+      console.log('  ' + warning)
49
+    }
50
+
51
+    console.log()
52
+    process.exit(1)
53
+  }
54
+}

BIN
build/logo.png View File


+ 101
- 0
build/utils.js View File

1
+'use strict'
2
+const path = require('path')
3
+const config = require('../config')
4
+const ExtractTextPlugin = require('extract-text-webpack-plugin')
5
+const packageConfig = require('../package.json')
6
+
7
+exports.assetsPath = function (_path) {
8
+  const assetsSubDirectory = process.env.NODE_ENV === 'production'
9
+    ? config.build.assetsSubDirectory
10
+    : config.dev.assetsSubDirectory
11
+
12
+  return path.posix.join(assetsSubDirectory, _path)
13
+}
14
+
15
+exports.cssLoaders = function (options) {
16
+  options = options || {}
17
+
18
+  const cssLoader = {
19
+    loader: 'css-loader',
20
+    options: {
21
+      sourceMap: options.sourceMap
22
+    }
23
+  }
24
+
25
+  const postcssLoader = {
26
+    loader: 'postcss-loader',
27
+    options: {
28
+      sourceMap: options.sourceMap
29
+    }
30
+  }
31
+
32
+  // generate loader string to be used with extract text plugin
33
+  function generateLoaders (loader, loaderOptions) {
34
+    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
35
+
36
+    if (loader) {
37
+      loaders.push({
38
+        loader: loader + '-loader',
39
+        options: Object.assign({}, loaderOptions, {
40
+          sourceMap: options.sourceMap
41
+        })
42
+      })
43
+    }
44
+
45
+    // Extract CSS when that option is specified
46
+    // (which is the case during production build)
47
+    if (options.extract) {
48
+      return ExtractTextPlugin.extract({
49
+        use: loaders,
50
+        fallback: 'vue-style-loader'
51
+      })
52
+    } else {
53
+      return ['vue-style-loader'].concat(loaders)
54
+    }
55
+  }
56
+
57
+  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
58
+  return {
59
+    css: generateLoaders(),
60
+    postcss: generateLoaders(),
61
+    less: generateLoaders('less'),
62
+    sass: generateLoaders('sass', { indentedSyntax: true }),
63
+    scss: generateLoaders('sass'),
64
+    stylus: generateLoaders('stylus'),
65
+    styl: generateLoaders('stylus')
66
+  }
67
+}
68
+
69
+// Generate loaders for standalone style files (outside of .vue)
70
+exports.styleLoaders = function (options) {
71
+  const output = []
72
+  const loaders = exports.cssLoaders(options)
73
+
74
+  for (const extension in loaders) {
75
+    const loader = loaders[extension]
76
+    output.push({
77
+      test: new RegExp('\\.' + extension + '$'),
78
+      use: loader
79
+    })
80
+  }
81
+
82
+  return output
83
+}
84
+
85
+exports.createNotifierCallback = () => {
86
+  const notifier = require('node-notifier')
87
+
88
+  return (severity, errors) => {
89
+    if (severity !== 'error') return
90
+
91
+    const error = errors[0]
92
+    const filename = error.file && error.file.split('!').pop()
93
+
94
+    notifier.notify({
95
+      title: packageConfig.name,
96
+      message: severity + ': ' + error.name,
97
+      subtitle: filename || '',
98
+      icon: path.join(__dirname, 'logo.png')
99
+    })
100
+  }
101
+}

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

1
+'use strict'
2
+const utils = require('./utils')
3
+const config = require('../config')
4
+const isProduction = process.env.NODE_ENV === 'production'
5
+const sourceMapEnabled = isProduction
6
+  ? config.build.productionSourceMap
7
+  : config.dev.cssSourceMap
8
+
9
+module.exports = {
10
+  loaders: utils.cssLoaders({
11
+    sourceMap: sourceMapEnabled,
12
+    extract: isProduction
13
+  }),
14
+  cssSourceMap: sourceMapEnabled,
15
+  cacheBusting: config.dev.cacheBusting,
16
+  transformToRequire: {
17
+    video: ['src', 'poster'],
18
+    source: 'src',
19
+    img: 'src',
20
+    image: 'xlink:href'
21
+  }
22
+}

+ 92
- 0
build/webpack.base.conf.js View File

1
+'use strict'
2
+const path = require('path')
3
+const utils = require('./utils')
4
+const config = require('../config')
5
+const vueLoaderConfig = require('./vue-loader.conf')
6
+
7
+function resolve (dir) {
8
+  return path.join(__dirname, '..', dir)
9
+}
10
+
11
+const createLintingRule = () => ({
12
+  test: /\.(js|vue)$/,
13
+  loader: 'eslint-loader',
14
+  enforce: 'pre',
15
+  include: [resolve('src'), resolve('test')],
16
+  options: {
17
+    formatter: require('eslint-friendly-formatter'),
18
+    emitWarning: !config.dev.showEslintErrorsInOverlay
19
+  }
20
+})
21
+
22
+module.exports = {
23
+  context: path.resolve(__dirname, '../'),
24
+  entry: {
25
+    app: './src/main.js'
26
+  },
27
+  output: {
28
+    path: config.build.assetsRoot,
29
+    filename: '[name].js',
30
+    publicPath: process.env.NODE_ENV === 'production'
31
+      ? config.build.assetsPublicPath
32
+      : config.dev.assetsPublicPath
33
+  },
34
+  resolve: {
35
+    extensions: ['.js', '.vue', '.json'],
36
+    alias: {
37
+      'vue$': 'vue/dist/vue.esm.js',
38
+      '@': resolve('src'),
39
+    }
40
+  },
41
+  module: {
42
+    rules: [
43
+      ...(config.dev.useEslint ? [createLintingRule()] : []),
44
+      {
45
+        test: /\.vue$/,
46
+        loader: 'vue-loader',
47
+        options: vueLoaderConfig
48
+      },
49
+      {
50
+        test: /\.js$/,
51
+        loader: 'babel-loader',
52
+        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
53
+      },
54
+      {
55
+        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
56
+        loader: 'url-loader',
57
+        options: {
58
+          limit: 10000,
59
+          name: utils.assetsPath('img/[name].[hash:7].[ext]')
60
+        }
61
+      },
62
+      {
63
+        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
64
+        loader: 'url-loader',
65
+        options: {
66
+          limit: 10000,
67
+          name: utils.assetsPath('media/[name].[hash:7].[ext]')
68
+        }
69
+      },
70
+      {
71
+        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
72
+        loader: 'url-loader',
73
+        options: {
74
+          limit: 10000,
75
+          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
76
+        }
77
+      }
78
+    ]
79
+  },
80
+  node: {
81
+    // prevent webpack from injecting useless setImmediate polyfill because Vue
82
+    // source contains it (although only uses it if it's native).
83
+    setImmediate: false,
84
+    // prevent webpack from injecting mocks to Node native modules
85
+    // that does not make sense for the client
86
+    dgram: 'empty',
87
+    fs: 'empty',
88
+    net: 'empty',
89
+    tls: 'empty',
90
+    child_process: 'empty'
91
+  }
92
+}

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

1
+'use strict'
2
+const utils = require('./utils')
3
+const webpack = require('webpack')
4
+const config = require('../config')
5
+const merge = require('webpack-merge')
6
+const path = require('path')
7
+const baseWebpackConfig = require('./webpack.base.conf')
8
+const CopyWebpackPlugin = require('copy-webpack-plugin')
9
+const HtmlWebpackPlugin = require('html-webpack-plugin')
10
+const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
11
+const portfinder = require('portfinder')
12
+
13
+const HOST = process.env.HOST
14
+const PORT = process.env.PORT && Number(process.env.PORT)
15
+
16
+const devWebpackConfig = merge(baseWebpackConfig, {
17
+  module: {
18
+    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
19
+  },
20
+  // cheap-module-eval-source-map is faster for development
21
+  devtool: config.dev.devtool,
22
+
23
+  // these devServer options should be customized in /config/index.js
24
+  devServer: {
25
+    clientLogLevel: 'warning',
26
+    historyApiFallback: {
27
+      rewrites: [
28
+        { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
29
+      ],
30
+    },
31
+    hot: true,
32
+    contentBase: false, // since we use CopyWebpackPlugin.
33
+    compress: true,
34
+    host: HOST || config.dev.host,
35
+    port: PORT || config.dev.port,
36
+    open: config.dev.autoOpenBrowser,
37
+    overlay: config.dev.errorOverlay
38
+      ? { warnings: false, errors: true }
39
+      : false,
40
+    publicPath: config.dev.assetsPublicPath,
41
+    proxy: config.dev.proxyTable,
42
+    quiet: true, // necessary for FriendlyErrorsPlugin
43
+    watchOptions: {
44
+      poll: config.dev.poll,
45
+    }
46
+  },
47
+  plugins: [
48
+    new webpack.DefinePlugin({
49
+      'process.env': require('../config/dev.env')
50
+    }),
51
+    new webpack.HotModuleReplacementPlugin(),
52
+    new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
53
+    new webpack.NoEmitOnErrorsPlugin(),
54
+    // https://github.com/ampedandwired/html-webpack-plugin
55
+    new HtmlWebpackPlugin({
56
+      filename: 'index.html',
57
+      template: 'index.html',
58
+      inject: true
59
+    }),
60
+    // copy custom static assets
61
+    new CopyWebpackPlugin([
62
+      {
63
+        from: path.resolve(__dirname, '../static'),
64
+        to: config.dev.assetsSubDirectory,
65
+        ignore: ['.*']
66
+      }
67
+    ])
68
+  ]
69
+})
70
+
71
+module.exports = new Promise((resolve, reject) => {
72
+  portfinder.basePort = process.env.PORT || config.dev.port
73
+  portfinder.getPort((err, port) => {
74
+    if (err) {
75
+      reject(err)
76
+    } else {
77
+      // publish the new Port, necessary for e2e tests
78
+      process.env.PORT = port
79
+      // add port to devServer config
80
+      devWebpackConfig.devServer.port = port
81
+
82
+      // Add FriendlyErrorsPlugin
83
+      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
84
+        compilationSuccessInfo: {
85
+          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
86
+        },
87
+        onErrors: config.dev.notifyOnErrors
88
+        ? utils.createNotifierCallback()
89
+        : undefined
90
+      }))
91
+
92
+      resolve(devWebpackConfig)
93
+    }
94
+  })
95
+})

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

1
+'use strict'
2
+const path = require('path')
3
+const utils = require('./utils')
4
+const webpack = require('webpack')
5
+const config = require('../config')
6
+const merge = require('webpack-merge')
7
+const baseWebpackConfig = require('./webpack.base.conf')
8
+const CopyWebpackPlugin = require('copy-webpack-plugin')
9
+const HtmlWebpackPlugin = require('html-webpack-plugin')
10
+const ExtractTextPlugin = require('extract-text-webpack-plugin')
11
+const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12
+const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
13
+
14
+const env = require('../config/prod.env')
15
+
16
+const webpackConfig = merge(baseWebpackConfig, {
17
+  module: {
18
+    rules: utils.styleLoaders({
19
+      sourceMap: config.build.productionSourceMap,
20
+      extract: true,
21
+      usePostCSS: true
22
+    })
23
+  },
24
+  devtool: config.build.productionSourceMap ? config.build.devtool : false,
25
+  output: {
26
+    path: config.build.assetsRoot,
27
+    filename: utils.assetsPath('js/[name].[chunkhash].js'),
28
+    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
29
+  },
30
+  plugins: [
31
+    // http://vuejs.github.io/vue-loader/en/workflow/production.html
32
+    new webpack.DefinePlugin({
33
+      'process.env': env
34
+    }),
35
+    new UglifyJsPlugin({
36
+      uglifyOptions: {
37
+        compress: {
38
+          warnings: false
39
+        }
40
+      },
41
+      sourceMap: config.build.productionSourceMap,
42
+      parallel: true
43
+    }),
44
+    // extract css into its own file
45
+    new ExtractTextPlugin({
46
+      filename: utils.assetsPath('css/[name].[contenthash].css'),
47
+      // Setting the following option to `false` will not extract CSS from codesplit chunks.
48
+      // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
49
+      // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 
50
+      // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
51
+      allChunks: true,
52
+    }),
53
+    // Compress extracted CSS. We are using this plugin so that possible
54
+    // duplicated CSS from different components can be deduped.
55
+    new OptimizeCSSPlugin({
56
+      cssProcessorOptions: config.build.productionSourceMap
57
+        ? { safe: true, map: { inline: false } }
58
+        : { safe: true }
59
+    }),
60
+    // generate dist index.html with correct asset hash for caching.
61
+    // you can customize output by editing /index.html
62
+    // see https://github.com/ampedandwired/html-webpack-plugin
63
+    new HtmlWebpackPlugin({
64
+      filename: config.build.index,
65
+      template: 'index.html',
66
+      inject: true,
67
+      minify: {
68
+        removeComments: true,
69
+        collapseWhitespace: true,
70
+        removeAttributeQuotes: true
71
+        // more options:
72
+        // https://github.com/kangax/html-minifier#options-quick-reference
73
+      },
74
+      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
75
+      chunksSortMode: 'dependency'
76
+    }),
77
+    // keep module.id stable when vendor modules does not change
78
+    new webpack.HashedModuleIdsPlugin(),
79
+    // enable scope hoisting
80
+    new webpack.optimize.ModuleConcatenationPlugin(),
81
+    // split vendor js into its own file
82
+    new webpack.optimize.CommonsChunkPlugin({
83
+      name: 'vendor',
84
+      minChunks (module) {
85
+        // any required modules inside node_modules are extracted to vendor
86
+        return (
87
+          module.resource &&
88
+          /\.js$/.test(module.resource) &&
89
+          module.resource.indexOf(
90
+            path.join(__dirname, '../node_modules')
91
+          ) === 0
92
+        )
93
+      }
94
+    }),
95
+    // extract webpack runtime and module manifest to its own file in order to
96
+    // prevent vendor hash from being updated whenever app bundle is updated
97
+    new webpack.optimize.CommonsChunkPlugin({
98
+      name: 'manifest',
99
+      minChunks: Infinity
100
+    }),
101
+    // This instance extracts shared chunks from code splitted chunks and bundles them
102
+    // in a separate chunk, similar to the vendor chunk
103
+    // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
104
+    new webpack.optimize.CommonsChunkPlugin({
105
+      name: 'app',
106
+      async: 'vendor-async',
107
+      children: true,
108
+      minChunks: 3
109
+    }),
110
+
111
+    // copy custom static assets
112
+    new CopyWebpackPlugin([
113
+      {
114
+        from: path.resolve(__dirname, '../static'),
115
+        to: config.build.assetsSubDirectory,
116
+        ignore: ['.*']
117
+      }
118
+    ])
119
+  ]
120
+})
121
+
122
+if (config.build.productionGzip) {
123
+  const CompressionWebpackPlugin = require('compression-webpack-plugin')
124
+
125
+  webpackConfig.plugins.push(
126
+    new CompressionWebpackPlugin({
127
+      asset: '[path].gz[query]',
128
+      algorithm: 'gzip',
129
+      test: new RegExp(
130
+        '\\.(' +
131
+        config.build.productionGzipExtensions.join('|') +
132
+        ')$'
133
+      ),
134
+      threshold: 10240,
135
+      minRatio: 0.8
136
+    })
137
+  )
138
+}
139
+
140
+if (config.build.bundleAnalyzerReport) {
141
+  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
142
+  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
143
+}
144
+
145
+module.exports = webpackConfig

+ 7
- 0
config/dev.env.js View File

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

+ 83
- 0
config/index.js View File

1
+'use strict'
2
+// Template version: 1.3.1
3
+// see http://vuejs-templates.github.io/webpack for documentation.
4
+
5
+const path = require('path')
6
+
7
+module.exports = {
8
+  dev: {
9
+    // Paths
10
+    assetsSubDirectory: 'static',
11
+    assetsPublicPath: '/',
12
+    proxyTable: {
13
+      '/api': {
14
+        // target: 'https://dp.huiju360.com.cn/hj_operations',
15
+        target: 'http://192.168.0.62:8788', //wf
16
+        // target: 'http://192.168.0.11:8088', //zys
17
+        changeOrigin: true, // 如果接口跨域,需要进行这个参数配置
18
+        // pathRewrite: {
19
+        //   '^/api': 'api'
20
+        // },
21
+      },
22
+    },
23
+    // Various Dev Server settings
24
+    host: '0.0.0.0', // can be overwritten by process.env.HOST
25
+    port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
26
+    autoOpenBrowser: false,
27
+    errorOverlay: true,
28
+    notifyOnErrors: true,
29
+    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
30
+
31
+    // Use Eslint Loader?
32
+    // If true, your code will be linted during bundling and
33
+    // linting errors and warnings will be shown in the console.
34
+    useEslint: true,
35
+    // If true, eslint errors and warnings will also be shown in the error overlay
36
+    // in the browser.
37
+    showEslintErrorsInOverlay: false,
38
+
39
+    /**
40
+     * Source Maps
41
+     */
42
+
43
+    // https://webpack.js.org/configuration/devtool/#development
44
+    devtool: 'cheap-module-eval-source-map',
45
+
46
+    // If you have problems debugging vue-files in devtools,
47
+    // set this to false - it *may* help
48
+    // https://vue-loader.vuejs.org/en/options.html#cachebusting
49
+    cacheBusting: true,
50
+    cssSourceMap: true
51
+  },
52
+
53
+  build: {
54
+    // Template for index.html
55
+    index: path.resolve(__dirname, '../dist/index.html'),
56
+
57
+    // Paths
58
+    assetsRoot: path.resolve(__dirname, '../dist'),
59
+    assetsSubDirectory: 'static',
60
+    assetsPublicPath: './',
61
+
62
+    /**
63
+     * Source Maps
64
+     */
65
+
66
+    productionSourceMap: true,
67
+    // https://webpack.js.org/configuration/devtool/#production
68
+    devtool: '#source-map',
69
+
70
+    // Gzip off by default as many popular static hosts such as
71
+    // Surge or Netlify already gzip all static assets for you.
72
+    // Before setting to `true`, make sure to:
73
+    // npm install --save-dev compression-webpack-plugin
74
+    productionGzip: false,
75
+    productionGzipExtensions: ['js', 'css'],
76
+
77
+    // Run the build command with an extra argument to
78
+    // View the bundle analyzer report after build finishes:
79
+    // `npm run build --report`
80
+    // Set to `true` or `false` to always turn it on or off
81
+    bundleAnalyzerReport: process.env.npm_config_report
82
+  }
83
+}

+ 4
- 0
config/prod.env.js View File

1
+'use strict'
2
+module.exports = {
3
+  NODE_ENV: '"production"'
4
+}

+ 12
- 0
index.html View File

1
+<!DOCTYPE html>
2
+<html>
3
+  <head>
4
+    <meta charset="utf-8">
5
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
6
+    <title>lottery</title>
7
+  </head>
8
+  <body>
9
+    <div id="app"></div>
10
+    <!-- built files will be auto injected -->
11
+  </body>
12
+</html>

+ 11772
- 0
package-lock.json
File diff suppressed because it is too large
View File


+ 77
- 0
package.json View File

1
+{
2
+  "name": "lottery",
3
+  "version": "1.0.0",
4
+  "description": "A Vue.js project",
5
+  "author": "aoaoyqh",
6
+  "private": true,
7
+  "scripts": {
8
+    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
9
+    "start": "npm run dev",
10
+    "lint": "eslint --ext .js,.vue src",
11
+    "build": "node build/build.js"
12
+  },
13
+  "dependencies": {
14
+    "axios": "^0.18.0",
15
+    "qrcodejs2": "^0.0.2",
16
+    "vant": "^1.2.1",
17
+    "vue": "^2.5.2",
18
+    "vue-router": "^3.0.1",
19
+    "vuex": "^3.0.1"
20
+  },
21
+  "devDependencies": {
22
+    "autoprefixer": "^7.1.2",
23
+    "babel-core": "^6.22.1",
24
+    "babel-eslint": "^8.2.1",
25
+    "babel-helper-vue-jsx-merge-props": "^2.0.3",
26
+    "babel-loader": "^7.1.1",
27
+    "babel-plugin-syntax-jsx": "^6.18.0",
28
+    "babel-plugin-transform-runtime": "^6.22.0",
29
+    "babel-plugin-transform-vue-jsx": "^3.5.0",
30
+    "babel-preset-env": "^1.3.2",
31
+    "babel-preset-stage-2": "^6.22.0",
32
+    "chalk": "^2.0.1",
33
+    "copy-webpack-plugin": "^4.0.1",
34
+    "css-loader": "^0.28.0",
35
+    "eslint": "^4.15.0",
36
+    "eslint-config-standard": "^10.2.1",
37
+    "eslint-friendly-formatter": "^3.0.0",
38
+    "eslint-loader": "^1.7.1",
39
+    "eslint-plugin-import": "^2.7.0",
40
+    "eslint-plugin-node": "^5.2.0",
41
+    "eslint-plugin-promise": "^3.4.0",
42
+    "eslint-plugin-standard": "^3.0.1",
43
+    "eslint-plugin-vue": "^4.0.0",
44
+    "extract-text-webpack-plugin": "^3.0.0",
45
+    "file-loader": "^1.1.4",
46
+    "friendly-errors-webpack-plugin": "^1.6.1",
47
+    "html-webpack-plugin": "^2.30.1",
48
+    "node-notifier": "^5.1.2",
49
+    "optimize-css-assets-webpack-plugin": "^3.2.0",
50
+    "ora": "^1.2.0",
51
+    "portfinder": "^1.0.13",
52
+    "postcss-import": "^11.0.0",
53
+    "postcss-loader": "^2.0.8",
54
+    "postcss-url": "^7.2.1",
55
+    "rimraf": "^2.6.0",
56
+    "semver": "^5.3.0",
57
+    "shelljs": "^0.7.6",
58
+    "uglifyjs-webpack-plugin": "^1.1.1",
59
+    "url-loader": "^0.5.8",
60
+    "vue-loader": "^13.3.0",
61
+    "vue-style-loader": "^3.0.1",
62
+    "vue-template-compiler": "^2.5.2",
63
+    "webpack": "^3.6.0",
64
+    "webpack-bundle-analyzer": "^2.9.0",
65
+    "webpack-dev-server": "^2.9.1",
66
+    "webpack-merge": "^4.1.0"
67
+  },
68
+  "engines": {
69
+    "node": ">= 6.0.0",
70
+    "npm": ">= 3.0.0"
71
+  },
72
+  "browserslist": [
73
+    "> 1%",
74
+    "last 2 versions",
75
+    "not ie <= 8"
76
+  ]
77
+}

+ 24
- 0
src/App.vue View File

1
+<template>
2
+  <div id="app">
3
+    <router-view/>
4
+  </div>
5
+</template>
6
+
7
+<script>
8
+export default {
9
+  name: 'App'
10
+}
11
+</script>
12
+
13
+<style>
14
+#app {
15
+  font-family: 'Avenir', Helvetica, Arial, sans-serif;
16
+  -webkit-font-smoothing: antialiased;
17
+  -moz-osx-font-smoothing: grayscale;
18
+  text-align: center;
19
+  color: #2c3e50;
20
+}
21
+::-webkit-scrollbar {
22
+    display: none;
23
+}
24
+</style>

BIN
src/assets/bg.png View File


BIN
src/assets/bolang.png View File


BIN
src/assets/bottomMsg.png View File


BIN
src/assets/dialog.png View File


BIN
src/assets/down.png View File


BIN
src/assets/font/hkhb.ttf View File


BIN
src/assets/heixing.png View File


BIN
src/assets/huxian.png View File


BIN
src/assets/jiantou.png View File


BIN
src/assets/juxing.png View File


BIN
src/assets/line1.png View File


BIN
src/assets/line2.png View File


BIN
src/assets/line3.png View File


BIN
src/assets/line4.png View File


BIN
src/assets/line5.png View File


BIN
src/assets/line6.png View File


BIN
src/assets/line7.png View File


BIN
src/assets/line8.png View File


BIN
src/assets/line9.png View File


BIN
src/assets/linjiang.png View File


BIN
src/assets/lq.png View File


BIN
src/assets/qrCode.jpg View File


BIN
src/assets/quan.png View File


BIN
src/assets/shuangyuan.png View File


BIN
src/assets/tanchuang.png View File


BIN
src/assets/touxiang.png View File


BIN
src/assets/xiaoniao.png View File


BIN
src/assets/xiaosenlin.png View File


BIN
src/assets/yinfu1.png View File


BIN
src/assets/yinfu2.png View File


BIN
src/assets/yinfu3.png View File


BIN
src/assets/yinfu4.png View File


BIN
src/assets/yinfu5.png View File


BIN
src/assets/zhi.png View File


BIN
src/assets/zhizhen.png View File


BIN
src/assets/zhuanpan.png View File


+ 65
- 0
src/components/qrCodeCard/qrCodeCard.vue View File

1
+<template>
2
+  <div class="codeLayout">
3
+    <div id="QRcode"></div>
4
+  </div>
5
+</template>
6
+
7
+<script>
8
+import QRCode from 'qrcodejs2'
9
+export default {
10
+  name: 'qrCodeCard',
11
+  props: {
12
+    msg: {
13
+      type: Object,
14
+      default: () => {}
15
+    }
16
+  },
17
+  data () {
18
+    return {
19
+      lessonType: {
20
+        800: '1012-',
21
+        801: '1012-',
22
+        802: '1011-',
23
+        803: '1010-',
24
+        804: '1013-'
25
+      }
26
+    }
27
+  },
28
+  methods: {
29
+    InitCodeRules (info) {
30
+      let codeText
31
+      for (var Key in this.lessonType
32
+      ) {
33
+        if (parseInt(Key) === this.msg.course_type) {
34
+          codeText = this.lessonType[Key] + '-1'
35
+        }
36
+      }
37
+      const ele = document.querySelector('#QRcode')
38
+      this.qrCode = new QRCode(ele, {
39
+        text: codeText,
40
+        width: '100',
41
+        height: '100',
42
+        colorDark: '#000000',
43
+        colorLight: '#ffffff',
44
+        correctLevel: QRCode.CorrectLevel.H
45
+      })
46
+    }
47
+  },
48
+  components: {
49
+    QRCode
50
+  },
51
+  mounted () {
52
+    this.InitCodeRules()
53
+  }
54
+}
55
+</script>
56
+
57
+<style lang="scss" scoped>
58
+.codeLayout{
59
+  display: flex;
60
+  flex-flow: column nowrap;
61
+  justify-content: center;
62
+  align-items: center;
63
+  padding-bottom: .1rem;
64
+}
65
+</style>

+ 7
- 0
src/config/index.js View File

1
+export default {
2
+  appid: 'wx7320287e057bbeee',
3
+  redirect_uri: encodeURIComponent(window.location.href),
4
+  response_type: 'code',
5
+  scope: 'snsapi_userinfo',
6
+  state: '12313'
7
+}

+ 27
- 0
src/main.js View File

1
+// The Vue build version to load with the `import` command
2
+// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3
+import Vue from 'vue'
4
+import App from './App'
5
+import Vuex from 'vuex'
6
+import './style/main.css'
7
+import router from './router'
8
+import Ajax from './util/ajax'
9
+import api from './util/api'
10
+import toolClass from './util/util'
11
+import store from './store'
12
+import Vant from 'vant'
13
+import 'vant/lib/vant-css/index.css'
14
+Vue.use(Vant)
15
+Vue.use(Vuex)
16
+Vue.config.productionTip = false
17
+Vue.prototype.$api = api
18
+Vue.prototype.$ajax = Ajax
19
+Vue.prototype.toolClass = toolClass
20
+/* eslint-disable no-new */
21
+new Vue({
22
+  el: '#app',
23
+  router,
24
+  store,
25
+  components: { App },
26
+  template: '<App/>'
27
+})

+ 280
- 0
src/page/index/index.vue View File

1
+<template>
2
+  <div class="bg mainPage">
3
+    <img class="bg-img" :src="bg" alt="" width="100%">
4
+    <transition name="fade">
5
+      <div class="dialog" v-if="showDialog" @click="close">
6
+        <div class="box" @click.stop='stop'>
7
+          <img class='dialog-bg' @click.stop="close" :src="dialog" alt="">
8
+          <div class='dialog-title'>恭喜你!<span>成功获得</span></div>
9
+          <div class="dialog-name">{{winning}}</div>
10
+          <img class="qrCode" :src="qrCode" alt="">
11
+          <div v-if="showBtn" @click="get">
12
+            <img class="lq" :src="lq" alt="">
13
+          </div>
14
+          <div v-else @click="get">
15
+            <img class="lq" :src="lq" alt="">
16
+          </div>
17
+          <div class="desc">长按二维码“城的空间”,进入会员中心查看奖品吧</div>
18
+        </div>
19
+      </div>
20
+    </transition>
21
+    <div class="turntable">
22
+      <div :class='{ "round": round }' class="turntable-body">
23
+        <div v-for='(item, index) in data.prizeList' :key='index' :class='item.class'>
24
+          <img :src="item.img" alt="">
25
+          <span :class='item.font'>{{item.PrizeName}}</span>
26
+        </div>
27
+        <img :src="turntable" alt="" width="100%" height="100%">
28
+      </div>
29
+      <img class="pointer"  @click="run" :src="pointer" alt="">
30
+      <img class="down" :src="down" alt="">
31
+      <img class="yf1" :src="yf1" alt="">
32
+      <img class="yf2" :src="yf2" alt="">
33
+      <img class="yf3" :src="yf3" alt="">
34
+      <img class="yf4" :src="yf4" alt="">
35
+      <img class="yf5" :src="yf3" alt="">
36
+      <img class="yf6" :src="yf4" alt="">
37
+      <img class="hx" :src="blackStar" alt="">
38
+      <img class="hux" :src="xian" alt="">
39
+      <img class="sl" :src="sl" alt="">
40
+      <img class="sl2" :src="sl" alt="">
41
+      <img class="jx" :src="jx" alt="">
42
+    </div>
43
+    <div class="paper">
44
+      <img :src="paper" alt="" width="100%">
45
+      <div class="winningList">
46
+        <div class="title">
47
+          <img :src="blackStar" alt="">
48
+          <span>中奖名单</span>
49
+          <img :src="jt" alt="">
50
+        </div>
51
+        <div class="list">
52
+          <div v-for='(item, index) in  data.list' :key='index'>
53
+            <img :src="item.UserHeadImg" alt="">
54
+            <span>{{item.PrizeName}}</span>
55
+            <span>{{item.UserName}}</span>
56
+          </div>
57
+        </div>
58
+      </div>
59
+      <div class="rule">
60
+        <div class="title">
61
+          <img :src="sy" alt="">
62
+          <span>活动规则</span>
63
+          <img :src="jt" alt="">
64
+        </div>
65
+        <div class="content">
66
+          <pre style="white-space:pre-line; text-align: left;">{{data.prize.LuckdrawRule}}</pre>
67
+          <!-- <div class="mb">抽奖活动</div>
68
+          <div v-for="(item,index) in data.prizeList" :key='index'>
69
+            <span>{{item.PrizeName}}</span>
70
+            <span>{{item.Probability}}%几率</span>
71
+          </div>
72
+          <div class="mb mt">抽奖方式:通过分享链接,点击立即抽奖按钮,每个活动每人仅可参加一次</div>
73
+          <div class="mb">领取方式:线下出示奖品二维码即可扫码核销</div>
74
+          <div>领取地点:悦见山G99</div> -->
75
+        </div>
76
+      </div>
77
+      <img class="bird" :src="bird" alt="">
78
+      <img class="quan1" :src="quan" alt="">
79
+      <img class="quan2" :src="quan" alt="">
80
+      <img class="bl1" :src="bl" alt="">
81
+      <img class="bl2" :src="bl" alt="">
82
+      <img class="jx2" :src="jx" alt="">
83
+    </div>
84
+  </div>
85
+</template>
86
+
87
+<script>
88
+import bg from '@/assets/bg.png'
89
+import turntable from '@/assets/zhuanpan.png'
90
+import pointer from '@/assets/zhizhen.png'
91
+import paper from '@/assets/zhi.png'
92
+import blackStar from '@/assets/heixing.png'
93
+import jt from '@/assets/jiantou.png'
94
+import tx from '@/assets/touxiang.png'
95
+import sy from '@/assets/shuangyuan.png'
96
+import bird from '@/assets/xiaoniao.png'
97
+import yf1 from '@/assets/yinfu1.png'
98
+import yf2 from '@/assets/yinfu2.png'
99
+import yf3 from '@/assets/yinfu3.png'
100
+import yf4 from '@/assets/yinfu4.png'
101
+import xian from '@/assets/huxian.png'
102
+import sl from '@/assets/xiaosenlin.png'
103
+import jx from '@/assets/juxing.png'
104
+import quan from '@/assets/quan.png'
105
+import bl from '@/assets/bolang.png'
106
+import down from '@/assets/down.png'
107
+import dialog from '@/assets/dialog.png'
108
+import lq from '@/assets/lq.png'
109
+import qrCode from '@/assets/qrCode.jpg'
110
+import line1 from '@/assets/line4.png'
111
+import line2 from '@/assets/line5.png'
112
+import line3 from '@/assets/line6.png'
113
+import line4 from '@/assets/line7.png'
114
+import line5 from '@/assets/line8.png'
115
+import line6 from '@/assets/line9.png'
116
+import line7 from '@/assets/line1.png'
117
+import line8 from '@/assets/line2.png'
118
+import line9 from '@/assets/line3.png'
119
+import { mapState, createNamespacedHelpers } from 'vuex'
120
+const { mapActions: mapAppActions } = createNamespacedHelpers('app')
121
+export default {
122
+  data () {
123
+    return {
124
+      bg,
125
+      turntable,
126
+      pointer,
127
+      paper,
128
+      blackStar,
129
+      jt,
130
+      sl,
131
+      jx,
132
+      tx,
133
+      sy,
134
+      yf1,
135
+      yf2,
136
+      yf3,
137
+      yf4,
138
+      xian,
139
+      bird,
140
+      quan,
141
+      bl,
142
+      down,
143
+      dialog,
144
+      qrCode,
145
+      lq,
146
+      line1,
147
+      line2,
148
+      line3,
149
+      line4,
150
+      line5,
151
+      line6,
152
+      line7,
153
+      line8,
154
+      line9,
155
+      isRun: false,
156
+      round: false,
157
+      showDialog: false,
158
+      data: {
159
+        userInfo: {},
160
+        prize: {},
161
+        prizeList: [],
162
+        list: []
163
+      },
164
+      winning: '',
165
+      showBtn: false,
166
+      jump: ''
167
+    }
168
+  },
169
+  created () {
170
+    this.getUserInfo({ luckdrawid: this.lotteryId }).then((res) => {
171
+      this.data.userInfo = this.userInfo
172
+      console.log(this.data.userInfo)
173
+      if (this.data.userInfo.record) {
174
+        this.winning = this.data.userInfo.record.PrizeName
175
+        this.showDialog = true
176
+        if (this.data.userInfo.detail) {
177
+          if (this.data.userInfo.detail.Url) {
178
+            this.showBtn = 1
179
+            this.jump = this.data.userInfo.detail.Url
180
+          }
181
+        }
182
+      }
183
+      this.getPrize({ id: this.lotteryId }).then((res) => {
184
+        this.data.prize = this.prize
185
+        this.data.prizeList = this.data.prize.Prizes
186
+        this.init()
187
+      })
188
+      this.getRecord({ id: this.lotteryId }).then((res) => {
189
+        if (this.list.length >= 10) {
190
+          this.data.list = this.list.slice(0, 10)
191
+        } else {
192
+          this.data.list = this.list
193
+        }
194
+      })
195
+    })
196
+  },
197
+  computed: {
198
+    ...mapState({
199
+      userInfo: x => x.app.userInfo,
200
+      prize: x => x.app.prize,
201
+      list: x => x.app.record,
202
+      lotteryId: x => x.app.lotteryId
203
+    })
204
+  },
205
+  methods: {
206
+    ...mapAppActions(['getUserInfo', 'getPrize', 'setPrize', 'getRecord']),
207
+    init () {
208
+      let lineList = [this.line1, this.line2, this.line3, this.line4, this.line5, this.line6, this.line7, this.line8, this.line9]
209
+      if (Math.ceil(this.data.prizeList.length / lineList.length) > 1) {
210
+        let length = Math.ceil(this.data.prizeList.length / lineList.length)
211
+        for (let i = 1; i < length; i++) {
212
+          lineList = lineList.concat(lineList)
213
+        }
214
+      }
215
+      let deg = 360 / this.data.prizeList.length
216
+      let rule = ''
217
+      for (let i = 0; i < this.data.prizeList.length; i++) {
218
+        this.data.prizeList[i].class = 'prize' + i
219
+        this.data.prizeList[i].font = 'font' + i
220
+        this.data.prizeList[i].img = lineList[i]
221
+        console.log(deg * (i + 1))
222
+        rule += `.prize${i}{transform: rotate(${deg * (i + 1)}deg);transform-origin:0 0;} .font${i}{transform: rotate(${(deg / 2)}deg);transform-origin:0 0;}`
223
+      }
224
+      let style = document.createElement('style')
225
+      style.type = 'text/css'
226
+      style.innerHTML = rule
227
+      document.getElementsByTagName('head')[0].appendChild(style)
228
+      this.stylesheet = document.styleSheets[document.styleSheets.length - 1]
229
+    },
230
+    start () {
231
+      return new Promise((resolve, reject) => {
232
+        if (this.isRun) {
233
+        } else {
234
+          this.isRun = true
235
+          let dynamicValue = -3690
236
+          this.setPrize({ id: this.lotteryId, openId: this.data.userInfo.user.OpenId }).then((res) => {
237
+            for (let i = 0; i < this.data.prizeList.length; i++) {
238
+              if (this.data.prizeList[i].Id === res.prize.Id) {
239
+                dynamicValue -= ((360 / this.data.prizeList.length * (i + 1)) + 360 / this.data.prizeList.length / 2)
240
+              }
241
+            }
242
+            let rule = `@keyframes round {0% {transform: rotate(0deg);}100% {transform: rotate(${dynamicValue}deg);}}`
243
+            let style = document.createElement('style')
244
+            style.type = 'text/css'
245
+            style.innerHTML = rule
246
+            document.getElementsByTagName('head')[0].appendChild(style)
247
+            this.stylesheet = document.styleSheets[document.styleSheets.length - 1]
248
+            this.round = true
249
+            resolve(res)
250
+          })
251
+        }
252
+      })
253
+    },
254
+    get () {
255
+      console.log('去领取')
256
+      window.location.href = this.jump
257
+    },
258
+    close (data) {
259
+      this.showDialog = false
260
+    },
261
+    run () {
262
+      this.start().then((res) => {
263
+        this.winning = res.prize.PrizeName
264
+        this.showBtn = res.detail.Url ? 1 : 0
265
+        this.jump = res.detail.Url
266
+        setTimeout(() => {
267
+          this.showDialog = true
268
+        }, 10000)
269
+      })
270
+    },
271
+    stop () {
272
+      console.log('stop')
273
+    }
274
+  }
275
+}
276
+</script>
277
+
278
+<style lang="scss" scoped>
279
+@import "page.scss";
280
+</style>

+ 331
- 0
src/page/index/page.scss View File

1
+@font-face {
2
+  font-family: myFont;
3
+  src: url("../../assets/font/hkhb.ttf")
4
+}
5
+body * {
6
+  font-family: myFont;
7
+}
8
+
9
+.bg {
10
+  position: relative;
11
+  width: 100%;
12
+  .turntable {
13
+    position: absolute;
14
+    top: 2.2rem;
15
+    width: 100%;
16
+    height: 3rem;
17
+    display: flex;
18
+    justify-content: center;
19
+    align-items: center;
20
+    > img {
21
+      position: absolute;
22
+      z-index: 10;
23
+    }
24
+    .yf1 {
25
+      bottom: -0.25rem;
26
+      right: 0.05rem;
27
+      width: 0.2rem;
28
+    }
29
+    .yf2 {
30
+      bottom: 0;
31
+      right: 0.8rem;
32
+      width: 0.1rem;
33
+    }
34
+    .yf3 {
35
+      bottom: -0.41rem;
36
+      right: 0.45rem;
37
+      width: 0.25rem;
38
+    }
39
+    .yf4 {
40
+      bottom: -0.3rem;
41
+      right: 1.3rem;
42
+      width: 0.25rem;
43
+    }
44
+    .yf5 {
45
+      bottom: 0.15rem;
46
+      left: 0.65rem;
47
+      width: 0.25rem;
48
+      transform: rotate(25deg);
49
+    }
50
+    .yf6 {
51
+      top: 0.3rem;
52
+      left: 0.4rem;
53
+      width: 0.25rem;
54
+      transform: rotate(-60deg);
55
+    }
56
+    .hx {
57
+      top: 0.1rem;
58
+      right: 0.7rem;
59
+      width: 0.3rem;
60
+    }
61
+    .hux {
62
+      top: 0.45rem;
63
+      right: 0.3rem;
64
+      width: 0.4rem;
65
+    }
66
+    .sl {
67
+      top: 0.15rem;
68
+      right: 0;
69
+      width: 1rem;
70
+      height: 0.5rem;
71
+      z-index: 1;
72
+    }
73
+    .sl2 {
74
+      bottom: -0.4rem;
75
+      left: 0;
76
+      width: 0.95rem;
77
+      height: 0.5rem;
78
+      z-index: 1;
79
+    }
80
+    .jx {
81
+      bottom: 0.3rem;
82
+      right: 0.02rem;
83
+      width: 0.5rem;
84
+      height: 0.06rem;
85
+      z-index: 1;
86
+      transform: rotate(180deg);
87
+    }
88
+    .down {
89
+      top: -0.3rem;
90
+      left: 50%;
91
+      transform: translateX(-50%);
92
+      width: 0.3rem;
93
+      z-index: 1;
94
+    }
95
+    .turntable-body {
96
+      width: 3rem;
97
+      height: 3rem;
98
+      position: relative;
99
+      z-index: 9;
100
+      div {
101
+        position: absolute;
102
+        width: 1.5rem;
103
+        height: 1.5rem;
104
+        line-height: 0.18rem;
105
+        right: 0;
106
+        bottom: 0;
107
+        img{
108
+          width: 93%;
109
+          position: absolute;
110
+          top: -0.04rem;
111
+          left: 0;
112
+        }
113
+        span{
114
+          overflow : hidden;
115
+          text-overflow: ellipsis;
116
+          display: -webkit-box;
117
+          -webkit-line-clamp: 2;
118
+          -webkit-box-orient: vertical;
119
+          width: .7rem;
120
+          margin: 0 auto;
121
+          position: absolute;
122
+          top: 0rem;
123
+          left: 0rem;
124
+          width: 100%;
125
+          text-align: right;
126
+          padding: 0 .3rem 0 .4rem;
127
+          box-sizing: border-box;
128
+        }
129
+      }
130
+    }
131
+    .round {
132
+      animation: round 10s ease;
133
+      animation-fill-mode: forwards;
134
+    }
135
+    .pointer {
136
+      position: absolute;
137
+      top: 50%;
138
+      left: 50%;
139
+      transform: translate(-50%, -60%);
140
+      width: 0.8rem;
141
+    }
142
+  }
143
+  .dialog {
144
+    width: 100%;
145
+    height: 100%;
146
+    background: rgba(0, 0, 0, 0.5);
147
+    position: fixed;
148
+    top: 0;
149
+    left: 0;
150
+    z-index: 999;
151
+    display: flex;
152
+    justify-content: center;
153
+    align-items: center;
154
+    .box {
155
+      width: 3.1rem;
156
+      height: 2.35rem;
157
+      position: relative;
158
+      display: flex;
159
+      flex-flow: column nowrap;
160
+      justify-content: center;
161
+      align-items: center;
162
+      .dialog-bg {
163
+        position: absolute;
164
+        top: -0.3rem;
165
+        width: 100%;
166
+        left: -0.05rem;
167
+        z-index: -10;
168
+      }
169
+      .dialog-title {
170
+        font-size: 0.18rem;
171
+        span {
172
+          font-family: Arial, Helvetica, sans-serif;
173
+        }
174
+      }
175
+      .dialog-name {
176
+        font-size: 0.18rem;
177
+        margin: 0.1rem 0;
178
+      }
179
+      .qrCode {
180
+        width: 0.8rem;
181
+        display: block;
182
+      }
183
+      .lq {
184
+        width: 1rem;
185
+        margin: 0.1rem 0 0.05rem;
186
+      }
187
+      .desc {
188
+        font-size: 0.12rem;
189
+        font-family: Arial, Helvetica, sans-serif;
190
+        color: rgba(160, 160, 160, 1);
191
+      }
192
+    }
193
+  }
194
+  .paper {
195
+    width: 100%;
196
+    position: absolute;
197
+    top: 5.6rem;
198
+    left: 0;
199
+    .winningList {
200
+      width: 2.8rem;
201
+      height: 2.8rem;
202
+      position: absolute;
203
+      top: 0.8rem;
204
+      left: 50%;
205
+      transform: translateX(-50%);
206
+      .title {
207
+        display: flex;
208
+        align-items: center;
209
+        justify-content: center;
210
+        img:nth-of-type(1) {
211
+          width: 0.25rem;
212
+        }
213
+        img:nth-of-type(2) {
214
+          width: 0.14rem;
215
+        }
216
+        span {
217
+          font-size: 0.14rem;
218
+          padding: 0 0.1rem;
219
+        }
220
+      }
221
+      .list {
222
+        overflow-x: hidden;
223
+        overflow-y: scroll;
224
+        height: 2.6rem;
225
+        div {
226
+          display: flex;
227
+          align-items: center;
228
+          justify-content: space-between;
229
+          img {
230
+            width: 0.18rem;
231
+            height: 0.18rem;
232
+          }
233
+          span:nth-of-type(1) {
234
+            flex: 1;
235
+            text-align: left;
236
+            margin: 0.1rem 0.1rem;
237
+          }
238
+          span:nth-of-type(2) {
239
+            text-align: right;
240
+          }
241
+        }
242
+      }
243
+    }
244
+    .rule {
245
+      width: 2.8rem;
246
+      height: 2.4rem;
247
+      position: absolute;
248
+      top: 3.8rem;
249
+      left: 50%;
250
+      transform: translateX(-50%);
251
+      .title {
252
+        display: flex;
253
+        align-items: center;
254
+        justify-content: center;
255
+        margin-bottom: 0.2rem;
256
+        img:nth-of-type(1) {
257
+          width: 0.25rem;
258
+        }
259
+        img:nth-of-type(2) {
260
+          width: 0.14rem;
261
+        }
262
+        span {
263
+          font-size: 0.14rem;
264
+          padding: 0 0.1rem;
265
+        }
266
+      }
267
+      .content {
268
+        .mb {
269
+          margin-bottom: 0.1rem;
270
+        }
271
+        .mt {
272
+          margin-top: 0.1rem;
273
+        }
274
+        div {
275
+          display: flex;
276
+          justify-content: space-between;
277
+          align-items: center;
278
+          margin-bottom: 0.05rem;
279
+          text-align: left;
280
+        }
281
+      }
282
+    }
283
+    .bird {
284
+      position: absolute;
285
+      bottom: 0.55rem;
286
+      left: 50%;
287
+      transform: translateX(-50%);
288
+      width: 1.2rem;
289
+    }
290
+    .quan1 {
291
+      position: absolute;
292
+      top: 1.1rem;
293
+      left: 0;
294
+      width: 0.28rem;
295
+    }
296
+    .quan2 {
297
+      position: absolute;
298
+      bottom: 4rem;
299
+      right: -0.1rem;
300
+      width: 0.28rem;
301
+    }
302
+    .bl1 {
303
+      position: absolute;
304
+      bottom: 2rem;
305
+      right: 0rem;
306
+      width: 0.5rem;
307
+      height: 0.16rem;
308
+    }
309
+    .bl2 {
310
+      position: absolute;
311
+      bottom: 3.6rem;
312
+      left: -0.1rem;
313
+      width: 0.5rem;
314
+      height: 0.16rem;
315
+    }
316
+    .jx2 {
317
+      position: absolute;
318
+      bottom: 0.3rem;
319
+      left: 0;
320
+      width: 0.8rem;
321
+      z-index: 1;
322
+    }
323
+  }
324
+}
325
+
326
+.fade-enter-active, .fade-leave-active {
327
+  transition: opacity .5s;
328
+}
329
+.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
330
+  opacity: 0;
331
+}

+ 52
- 0
src/page/lotteryDetail/index.vue View File

1
+<template>
2
+  <div class="mainPage">
3
+    <div>核销时间:2018-08-22 ~ 2018-10-03</div>
4
+    <div class="name">核销地点:江北新区白马路10号悦见山</div>
5
+    <div>
6
+      <qrCode :msg='msg' v-if='data.detail.Status === 0'></qrCode>
7
+      <div v-else class="bottomMsg">
8
+        <img :src="bottomMsg" alt="">
9
+      </div>
10
+    </div>
11
+  </div>
12
+</template>
13
+
14
+<script>
15
+import qrCode from '@/components/qrCodeCard/qrCodeCard'
16
+import bottomMsg from '@/assets/bottomMsg.png'
17
+import { mapState, createNamespacedHelpers } from 'vuex'
18
+const { mapActions: mapPrizeActions } = createNamespacedHelpers('prize')
19
+export default {
20
+  data () {
21
+    return {
22
+      data: {
23
+        detail: {}
24
+      },
25
+      msg: {
26
+        course_type: 800
27
+      },
28
+      bottomMsg
29
+    }
30
+  },
31
+  components: {
32
+    qrCode
33
+  },
34
+  computed: {
35
+    ...mapState({
36
+      detail: x => x.prize.detail
37
+    })
38
+  },
39
+  created () {
40
+    this.getLotteryDetail({ id: this.$route.query.id }).then((res) => {
41
+      this.data.detail = this.detail
42
+    })
43
+  },
44
+  methods: {
45
+    ...mapPrizeActions(['getLotteryDetail'])
46
+  }
47
+}
48
+</script>
49
+
50
+<style lang="scss" scoped>
51
+@import "page.scss";
52
+</style>

+ 16
- 0
src/page/lotteryDetail/page.scss View File

1
+.mainPage{
2
+  padding: 1.5rem .3rem 0;
3
+  box-sizing: border-box;
4
+  display: flex;
5
+  justify-content: center;
6
+  align-items: center;
7
+  flex-flow: column nowrap;
8
+  .name{
9
+    margin: .4rem 0;
10
+  }
11
+  .bottomMsg{
12
+    img{
13
+      width: 3rem;
14
+    }
15
+  }
16
+}

+ 57
- 0
src/page/lotteryList/index.vue View File

1
+<template>
2
+  <div class="mainPage">
3
+    <div class="list title">
4
+      <span>奖品</span>
5
+      <span>领取时间</span>
6
+    </div>
7
+    <div class="list" v-for='(item,index) in data.list' :key='index' @click="toDetail(item)">
8
+      <span>{{item.PrizeName}}</span>
9
+      <span>{{toolClass.dateFormat(item.CreateDate)}}</span>
10
+    </div>
11
+  </div>
12
+</template>
13
+
14
+<script>
15
+import { mapState, createNamespacedHelpers } from 'vuex'
16
+const { mapActions: mapPrizeActions } = createNamespacedHelpers('prize')
17
+const { mapActions: mapAppActions } = createNamespacedHelpers('app')
18
+export default {
19
+  data () {
20
+    return {
21
+      data: {
22
+        list: []
23
+      }
24
+    }
25
+  },
26
+  computed: {
27
+    ...mapState({
28
+      list: x => x.prize.list,
29
+      lotteryId: x => x.app.lotteryId,
30
+      userInfo: x => x.app.userInfo
31
+    })
32
+  },
33
+  created () {
34
+    this.getUserInfo({ luckdrawid: this.lotteryId }).then((res) => {
35
+      this.data.userInfo = this.userInfo
36
+      this.getLotteryList({ userid: this.data.userInfo.user.Id }).then((res) => {
37
+        this.data.list = this.list
38
+      })
39
+    })
40
+  },
41
+  methods: {
42
+    ...mapPrizeActions(['getLotteryList']),
43
+    ...mapAppActions(['getUserInfo']),
44
+    toDetail (item) {
45
+      if (item.Url) {
46
+        window.location.href = item.Url
47
+      } else {
48
+        this.$router.push({ name: 'lotteryDetail', query: { id: item.Id } })
49
+      }
50
+    }
51
+  }
52
+}
53
+</script>
54
+
55
+<style lang="scss" scoped>
56
+@import "page.scss";
57
+</style>

+ 23
- 0
src/page/lotteryList/page.scss View File

1
+.list{
2
+  display: flex;
3
+  justify-content: space-between;
4
+  align-items: center;
5
+  padding: .1rem .3rem;
6
+  border-bottom: 1px solid rgba(238,238,238,1);
7
+  span{
8
+    color: rgba(108,108,108,1);
9
+    display: block;
10
+    width: 60%;
11
+    text-align: center;
12
+  }
13
+  span:nth-of-type(1){
14
+    width: 40%;
15
+  }
16
+}
17
+.title{
18
+  background-color: rgba(242,242,242,1);
19
+  span{
20
+    color: #000;
21
+    font-weight: bold;
22
+  }
23
+}

+ 30
- 0
src/router/index.js View File

1
+import Vue from 'vue'
2
+import Router from 'vue-router'
3
+import index from '@/page/index'
4
+import lotteryList from '@/page/lotteryList'
5
+import lotteryDetail from '@/page/lotteryDetail'
6
+
7
+Vue.use(Router)
8
+
9
+export default new Router({
10
+  routes: [
11
+    {
12
+      path: '/',
13
+      name: 'index',
14
+      component: index,
15
+      meta: {
16
+        id: '1'
17
+      }
18
+    },
19
+    {
20
+      path: '/lotteryList',
21
+      name: 'lotteryList',
22
+      component: lotteryList
23
+    },
24
+    {
25
+      path: '/lotteryDetail',
26
+      name: 'lotteryDetail',
27
+      component: lotteryDetail
28
+    }
29
+  ]
30
+})

+ 130
- 0
src/store/app.js View File

1
+import Ajax from '../util/ajax'
2
+import api from '../util/api'
3
+const http = {}
4
+
5
+// 请求数据
6
+http.getUserInfo = (data) => {
7
+  return new Promise((resolve, reject) => {
8
+    Ajax(api.system.getCode.url, {
9
+      method: api.system.getCode.method
10
+    }).then((result) => {
11
+      Ajax(api.lottery.userInfo.url, {
12
+        method: api.lottery.userInfo.method,
13
+        queryData: {
14
+          code: result.code,
15
+          luckdrawid: data.luckdrawid
16
+        }
17
+      }).then(res => {
18
+        resolve(res)
19
+      }).catch((err) => {
20
+        reject(err)
21
+      })
22
+    })
23
+  })
24
+}
25
+
26
+http.getPrize = (data) => {
27
+  return new Promise((resolve, reject) => {
28
+    Ajax(api.lottery.getPrize.url, {
29
+      method: api.lottery.getPrize.method,
30
+      urlData: {
31
+        id: data.id
32
+      }
33
+    }).then(res => {
34
+      resolve(res)
35
+    }).catch((err) => {
36
+      reject(err)
37
+    })
38
+  })
39
+}
40
+
41
+http.setPrize = (data) => {
42
+  return new Promise((resolve, reject) => {
43
+    Ajax(api.lottery.setPrize.url, {
44
+      method: api.lottery.setPrize.method,
45
+      urlData: {
46
+        id: data.id
47
+      },
48
+      data: {
49
+        openid: data.openId
50
+        // openid: 'oMOpz0hNdM4vvxI6CghCSUWiRsJA'
51
+      }
52
+    }).then(res => {
53
+      resolve(res)
54
+    }).catch((err) => {
55
+      reject(err)
56
+    })
57
+  })
58
+}
59
+
60
+http.getRecord = (data) => {
61
+  return new Promise((resolve, reject) => {
62
+    Ajax(api.lottery.getRecord.url, {
63
+      method: api.lottery.getRecord.method,
64
+      queryData: {
65
+        id: data.id
66
+      }
67
+    }).then(res => {
68
+      resolve(res)
69
+    }).catch((err) => {
70
+      reject(err)
71
+    })
72
+  })
73
+}
74
+
75
+export default {
76
+  namespaced: true,
77
+  state: {
78
+    lotteryId: '1',
79
+    userInfo: {}, // 用户信息
80
+    prize: {}, // 抽奖信息
81
+    record: [] // 中奖列表
82
+  },
83
+  mutations: {
84
+    setUserInfo (state, data) {
85
+      state.userInfo = data
86
+    },
87
+    setPrize (state, data) {
88
+      state.prize = data
89
+    },
90
+    setRecord (state, data) {
91
+      state.record = data
92
+    }
93
+  },
94
+  actions: {
95
+    getUserInfo (context, data) {
96
+      return new Promise((resolve) => {
97
+        http.getUserInfo(data).then((res) => {
98
+          context.commit('setUserInfo', res)
99
+          resolve(res)
100
+        })
101
+      })
102
+    },
103
+
104
+    getPrize (context, data) {
105
+      return new Promise((resolve) => {
106
+        http.getPrize(data).then((res) => {
107
+          context.commit('setPrize', res)
108
+          resolve(res)
109
+        })
110
+      })
111
+    },
112
+
113
+    setPrize (context, data) {
114
+      return new Promise((resolve) => {
115
+        http.setPrize(data).then((res) => {
116
+          resolve(res)
117
+        })
118
+      })
119
+    },
120
+
121
+    getRecord (context, data) {
122
+      return new Promise((resolve) => {
123
+        http.getRecord(data).then((res) => {
124
+          context.commit('setRecord', res)
125
+          resolve(res)
126
+        })
127
+      })
128
+    }
129
+  }
130
+}

+ 26
- 0
src/store/index.js View File

1
+import Vue from 'vue'
2
+import Vuex from 'vuex'
3
+import Ajax from '../util/ajax'
4
+import api from '../util/api'
5
+Vue.use(Vuex)
6
+
7
+const store = new Vuex.Store({
8
+  state: {
9
+    loadding: false,
10
+    pageSize: 10
11
+  }
12
+})
13
+Vuex.Store.prototype.$api = api
14
+Vuex.Store.prototype.$ajax = Ajax
15
+export const modules = {
16
+  app: () => require('./app').default,
17
+  prize: () => require('./prize').default
18
+}
19
+
20
+Object.keys(modules).forEach((modKey) => {
21
+  const modNS = modKey.split('/')
22
+  const getMod = modules[modKey]
23
+  store.registerModule(...modNS, getMod())
24
+})
25
+
26
+export default store

+ 69
- 0
src/store/prize.js View File

1
+import Ajax from '../util/ajax'
2
+import api from '../util/api'
3
+const http = {}
4
+
5
+// 请求数据
6
+http.getLotteryList = (data) => {
7
+  return new Promise((resolve, reject) => {
8
+    Ajax(api.lottery.userRecordList.url, {
9
+      method: api.lottery.userRecordList.method,
10
+      queryData: {
11
+        userid: data.userid
12
+      }
13
+    }).then(res => {
14
+      resolve(res)
15
+    }).catch((err) => {
16
+      reject(err)
17
+    })
18
+  })
19
+}
20
+
21
+http.getLotteryDetail = (data) => {
22
+  return new Promise((resolve, reject) => {
23
+    Ajax(api.lottery.userRecordDetail.url, {
24
+      method: api.lottery.userRecordDetail.method,
25
+      urlData: {
26
+        id: data.id
27
+      }
28
+    }).then(res => {
29
+      resolve(res)
30
+    }).catch((err) => {
31
+      reject(err)
32
+    })
33
+  })
34
+}
35
+
36
+export default {
37
+  namespaced: true,
38
+  state: {
39
+    list: {}, // 奖品列表
40
+    detail: {} // 奖品详情
41
+  },
42
+  mutations: {
43
+    setLotteryList (state, data) {
44
+      state.list = data
45
+    },
46
+    setLotteryDetail (state, data) {
47
+      state.detail = data
48
+    }
49
+  },
50
+  actions: {
51
+    getLotteryList (context, data) {
52
+      return new Promise((resolve) => {
53
+        http.getLotteryList(data).then((res) => {
54
+          context.commit('setLotteryList', res)
55
+          resolve(res)
56
+        })
57
+      })
58
+    },
59
+
60
+    getLotteryDetail (context, data) {
61
+      return new Promise((resolve) => {
62
+        http.getLotteryDetail(data).then((res) => {
63
+          context.commit('setLotteryDetail', res)
64
+          resolve(res)
65
+        })
66
+      })
67
+    }
68
+  }
69
+}

+ 72
- 0
src/style/main.css View File

1
+@charset "utf-8";
2
+html,body{width:100%;height:100%;-webkit-text-size-adjust:100%;position:relative;color:#333;overflow-x:hidden;font-size:100px;}
3
+@media screen and (max-width:320px){html,body{font-size:85px;}}
4
+@media screen and (min-width:375px){html,body{font-size:100px;}}
5
+@media screen and (min-width:414px){html,body{font-size:110px;}}
6
+*{margin:0;padding:0;color:#000;font-family:"微软雅黑";-webkit-tap-highlight-color:rgba(255,0,0,0);-webkit-font-smoothing:antialiased;}
7
+body *{font-size:.13rem;}
8
+a{text-decoration:none;}
9
+a:hover{cursor:pointer;}
10
+em{font-style:normal;}
11
+li{list-style:none;}
12
+img{border:0;vertical-align:middle;}
13
+table{border-collapse:collapse;border-spacing:0;}
14
+p{word-wrap:break-word;}
15
+b{font-weight:normal;}
16
+input,textarea{border:0;-webkit-appearance:none;}
17
+input[type=input]{-webkit-appearance:none;}
18
+input[type=checkbox]{-webkit-appearance:checkbox;}
19
+.text-overflow-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}
20
+.centerLabel{display:block;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);-webkit-transform:translate(-50%,-50%);}
21
+.flex-h{display:flex;display:-webkit-flex;}
22
+.flex-v{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;}
23
+.flex-item{flex:1;-webkit-flex:1;position:relative;overflow:hidden;}
24
+*[class*="text-overflowEllipsis-line"]{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical;}
25
+.text-overflowEllipsis-line2{-webkit-line-clamp:2;}
26
+.text-overflowEllipsis-line3{-webkit-line-clamp:3;}
27
+.text-overflowEllipsis-line4{-webkit-line-clamp:4;}
28
+*[class*="overflow-scroll-y"]{overflow-x:hidden;overflow-y:scroll;-webkit-overflow-scrolling:touch;}
29
+*[class*="overflow-scroll-x"]{overflow-y:hidden;overflow-x:scroll;-webkit-overflow-scrolling:touch;}
30
+.overflow-scroll-y-3d,.overflow-scroll-x-3d{transform:translateZ(0);-webkit-transform:translateZ(0);}
31
+.overflow-scroll-x::-webkit-scrollbar,.overflow-scroll-x-3d::-webkit-scrollbar{width:0;height:0;color:transparent;display:none;}
32
+input:focus,textarea:focus,select:focus {
33
+    outline:none;
34
+}
35
+textarea{
36
+	resize: none;
37
+}
38
+
39
+select{
40
+	direction: rtl;
41
+}
42
+
43
+select option {
44
+    direction: ltr;
45
+}
46
+
47
+*>img.cover{
48
+	width: 100%;
49
+	height: 100%;
50
+	object-fit: cover;
51
+}
52
+
53
+*>img.contain{
54
+	width: 100%;
55
+	height: 100%;
56
+	object-fit: contain;
57
+}
58
+
59
+.mainPage{
60
+	width: 100%;
61
+	height: 100%;
62
+	position: relative;
63
+	background: #fff;
64
+}
65
+
66
+.van-toast div{
67
+	color: white;
68
+}
69
+
70
+.van-toast i{
71
+	color: white;
72
+}

+ 60
- 0
src/util/ajax.js View File

1
+import axios from 'axios'
2
+import qs from 'qs'
3
+import {Toast} from 'vant'
4
+
5
+const Axios = axios.create({
6
+  timeout: 60000,
7
+  responseType: 'json',
8
+  withCredentials: true,
9
+  queryData: {},
10
+  urlData: {},
11
+  headers: {
12
+    'Content-Type': 'multipart/form-data'
13
+  }
14
+})
15
+
16
+Axios.interceptors.request.use((config) => {
17
+  // 处理请求data,若为get请求,拼到url后面,若为post请求,直接添加到body中
18
+  let queryData = qs.stringify(config.queryData)
19
+  // 判断是通过斜杠传参还是通过query传参
20
+  if (config.url.indexOf(':') > -1) {
21
+    if (typeof config.urlData === 'object') {
22
+      config.url = Object.keys(config.urlData).reduce((url, k) => { // 此方法对每个元素进行处理
23
+        const re = new RegExp(`:${k}(?!w)`, 'i')
24
+        return url.replace(re, config.urlData[k])
25
+      }, config.url)
26
+    }
27
+  } else {
28
+    if (queryData) {
29
+      config.url += '?' + queryData
30
+    }
31
+  }
32
+  let fm = new FormData()
33
+  for (let k in config.data) {
34
+    if (Array.isArray(config.data[k])) {
35
+      fm.append(k, ...config.data[k].map(v => `${k}=${encodeURIComponent(v)}`))
36
+    } else {
37
+      fm.append(k, config.data[k])
38
+    }
39
+  }
40
+  config.data = fm
41
+  return config
42
+}, (error) => {
43
+  console.log(error)
44
+})
45
+
46
+const ajax = (...args) => {
47
+  return new Promise((resolve, reject) => {
48
+    Axios(...args).then(({ data }) => {
49
+      const { Message, Status } = data
50
+      if (Status) {
51
+        resolve(Message)
52
+      } else {
53
+        console.log(data)
54
+        Toast.fail(Message)
55
+      }
56
+    }).catch(reject)
57
+  })
58
+}
59
+
60
+export default ajax

+ 39
- 0
src/util/api.js View File

1
+import wechatConfig from '@/config/index'
2
+const baseUrl = '/api'
3
+const wechat = ''
4
+
5
+const $api = {
6
+  lottery: {
7
+    userInfo: { // 获取用户信息
8
+      method: 'get',
9
+      url: `${baseUrl}${wechat}/user`
10
+    },
11
+    getPrize: { // 获取抽奖信息
12
+      method: 'get',
13
+      url: `${baseUrl}${wechat}/luckdraw/:id`
14
+    },
15
+    setPrize: { // 抽奖
16
+      method: 'post',
17
+      url: `${baseUrl}${wechat}/luckdraw/:id`
18
+    },
19
+    getRecord: { // 中奖记录
20
+      method: 'get',
21
+      url: `${baseUrl}${wechat}/record`
22
+    },
23
+    userRecordList: { // 用户中奖记录列表
24
+      method: 'get',
25
+      url: `${baseUrl}${wechat}/user/record`
26
+    },
27
+    userRecordDetail: { // 用户中奖记录详情
28
+      method: 'get',
29
+      url: `${baseUrl}${wechat}/user/record/:id`
30
+    }
31
+  },
32
+  system: {
33
+    getCode: {
34
+      method: 'get',
35
+      url: `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${wechatConfig.appid}&redirect_uri=${wechatConfig.redirect_uri}&response_type=${wechatConfig.response_type}&scope=${wechatConfig.scope}&state=${wechatConfig.state}#wechat_redirect`
36
+    }
37
+  }
38
+}
39
+export default $api

+ 25
- 0
src/util/util.js View File

1
+const toolClass = {
2
+  dateFormat: (timestamp) => {
3
+    let date = new Date(timestamp)
4
+    let y = date.getFullYear()
5
+    let m = date.getMonth() + 1
6
+    let d = date.getDate()
7
+    let h = date.getHours()
8
+    let min = date.getMinutes()
9
+    if (m < 10) {
10
+      m = '0' + m
11
+    }
12
+    if (d < 10) {
13
+      d = '0' + d
14
+    }
15
+    if (h < 10) {
16
+      h = '0' + h
17
+    }
18
+    if (min < 10) {
19
+      min = '0' + min
20
+    }
21
+    return y + '-' + m + '-' + d + ' ' + h + ':' + min
22
+  }
23
+}
24
+
25
+export default toolClass

+ 0
- 0
static/.gitkeep View File


+ 0
- 0
{ View File