@ -0,0 +1,18 @@ | 
				
			|||
{ | 
				
			|||
  "presets": [ | 
				
			|||
    ["env", { | 
				
			|||
      "modules": false, | 
				
			|||
      "targets": { | 
				
			|||
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] | 
				
			|||
      } | 
				
			|||
    }], | 
				
			|||
    "stage-2" | 
				
			|||
  ], | 
				
			|||
  "plugins": ["transform-vue-jsx", "transform-runtime"], | 
				
			|||
  "env": { | 
				
			|||
    "test": { | 
				
			|||
      "presets": ["env", "stage-2"], | 
				
			|||
      "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"] | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,9 @@ | 
				
			|||
root = true | 
				
			|||
 | 
				
			|||
[*] | 
				
			|||
charset = utf-8 | 
				
			|||
indent_style = space | 
				
			|||
indent_size = 2 | 
				
			|||
end_of_line = lf | 
				
			|||
insert_final_newline = true | 
				
			|||
trim_trailing_whitespace = true | 
				
			|||
@ -0,0 +1,17 @@ | 
				
			|||
.DS_Store | 
				
			|||
node_modules/ | 
				
			|||
/dist/ | 
				
			|||
npm-debug.log* | 
				
			|||
yarn-debug.log* | 
				
			|||
yarn-error.log* | 
				
			|||
/test/unit/coverage/ | 
				
			|||
/test/e2e/reports/ | 
				
			|||
selenium-debug.log | 
				
			|||
 | 
				
			|||
# Editor directories and files | 
				
			|||
.idea | 
				
			|||
.vscode | 
				
			|||
*.suo | 
				
			|||
*.ntvs* | 
				
			|||
*.njsproj | 
				
			|||
*.sln | 
				
			|||
@ -0,0 +1,10 @@ | 
				
			|||
// https://github.com/michael-ciniawsky/postcss-load-config
 | 
				
			|||
 | 
				
			|||
module.exports = { | 
				
			|||
  "plugins": { | 
				
			|||
    "postcss-import": {}, | 
				
			|||
    "postcss-url": {}, | 
				
			|||
    // to edit target browsers: use "browserslist" field in package.json
 | 
				
			|||
    "autoprefixer": {} | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,30 @@ | 
				
			|||
# vote-vue | 
				
			|||
 | 
				
			|||
> A Vue.js project | 
				
			|||
 | 
				
			|||
## Build Setup | 
				
			|||
 | 
				
			|||
``` bash | 
				
			|||
# install dependencies | 
				
			|||
npm install | 
				
			|||
 | 
				
			|||
# serve with hot reload at localhost:8080 | 
				
			|||
npm run dev | 
				
			|||
 | 
				
			|||
# build for production with minification | 
				
			|||
npm run build | 
				
			|||
 | 
				
			|||
# build for production and view the bundle analyzer report | 
				
			|||
npm run build --report | 
				
			|||
 | 
				
			|||
# run unit tests | 
				
			|||
npm run unit | 
				
			|||
 | 
				
			|||
# run e2e tests | 
				
			|||
npm run e2e | 
				
			|||
 | 
				
			|||
# run all tests | 
				
			|||
npm test | 
				
			|||
``` | 
				
			|||
 | 
				
			|||
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). | 
				
			|||
@ -0,0 +1,41 @@ | 
				
			|||
'use strict' | 
				
			|||
require('./check-versions')() | 
				
			|||
 | 
				
			|||
process.env.NODE_ENV = 'production' | 
				
			|||
 | 
				
			|||
const ora = require('ora') | 
				
			|||
const rm = require('rimraf') | 
				
			|||
const path = require('path') | 
				
			|||
const chalk = require('chalk') | 
				
			|||
const webpack = require('webpack') | 
				
			|||
const config = require('../config') | 
				
			|||
const webpackConfig = require('./webpack.prod.conf') | 
				
			|||
 | 
				
			|||
const spinner = ora('building for production...') | 
				
			|||
spinner.start() | 
				
			|||
 | 
				
			|||
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { | 
				
			|||
  if (err) throw err | 
				
			|||
  webpack(webpackConfig, (err, stats) => { | 
				
			|||
    spinner.stop() | 
				
			|||
    if (err) throw err | 
				
			|||
    process.stdout.write(stats.toString({ | 
				
			|||
      colors: true, | 
				
			|||
      modules: false, | 
				
			|||
      children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
 | 
				
			|||
      chunks: false, | 
				
			|||
      chunkModules: false | 
				
			|||
    }) + '\n\n') | 
				
			|||
 | 
				
			|||
    if (stats.hasErrors()) { | 
				
			|||
      console.log(chalk.red('  Build failed with errors.\n')) | 
				
			|||
      process.exit(1) | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    console.log(chalk.cyan('  Build complete.\n')) | 
				
			|||
    console.log(chalk.yellow( | 
				
			|||
      '  Tip: built files are meant to be served over an HTTP server.\n' + | 
				
			|||
      '  Opening index.html over file:// won\'t work.\n' | 
				
			|||
    )) | 
				
			|||
  }) | 
				
			|||
}) | 
				
			|||
@ -0,0 +1,54 @@ | 
				
			|||
'use strict' | 
				
			|||
const chalk = require('chalk') | 
				
			|||
const semver = require('semver') | 
				
			|||
const packageConfig = require('../package.json') | 
				
			|||
const shell = require('shelljs') | 
				
			|||
 | 
				
			|||
function exec (cmd) { | 
				
			|||
  return require('child_process').execSync(cmd).toString().trim() | 
				
			|||
} | 
				
			|||
 | 
				
			|||
const versionRequirements = [ | 
				
			|||
  { | 
				
			|||
    name: 'node', | 
				
			|||
    currentVersion: semver.clean(process.version), | 
				
			|||
    versionRequirement: packageConfig.engines.node | 
				
			|||
  } | 
				
			|||
] | 
				
			|||
 | 
				
			|||
if (shell.which('npm')) { | 
				
			|||
  versionRequirements.push({ | 
				
			|||
    name: 'npm', | 
				
			|||
    currentVersion: exec('npm --version'), | 
				
			|||
    versionRequirement: packageConfig.engines.npm | 
				
			|||
  }) | 
				
			|||
} | 
				
			|||
 | 
				
			|||
module.exports = function () { | 
				
			|||
  const warnings = [] | 
				
			|||
 | 
				
			|||
  for (let i = 0; i < versionRequirements.length; i++) { | 
				
			|||
    const mod = versionRequirements[i] | 
				
			|||
 | 
				
			|||
    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { | 
				
			|||
      warnings.push(mod.name + ': ' + | 
				
			|||
        chalk.red(mod.currentVersion) + ' should be ' + | 
				
			|||
        chalk.green(mod.versionRequirement) | 
				
			|||
      ) | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  if (warnings.length) { | 
				
			|||
    console.log('') | 
				
			|||
    console.log(chalk.yellow('To use this template, you must update following to modules:')) | 
				
			|||
    console.log() | 
				
			|||
 | 
				
			|||
    for (let i = 0; i < warnings.length; i++) { | 
				
			|||
      const warning = warnings[i] | 
				
			|||
      console.log('  ' + warning) | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    console.log() | 
				
			|||
    process.exit(1) | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
| 
		 After Width: | Height: | Size: 6.7 KiB  | 
@ -0,0 +1,101 @@ | 
				
			|||
'use strict' | 
				
			|||
const path = require('path') | 
				
			|||
const config = require('../config') | 
				
			|||
const ExtractTextPlugin = require('extract-text-webpack-plugin') | 
				
			|||
const packageConfig = require('../package.json') | 
				
			|||
 | 
				
			|||
exports.assetsPath = function (_path) { | 
				
			|||
  const assetsSubDirectory = process.env.NODE_ENV === 'production' | 
				
			|||
    ? config.build.assetsSubDirectory | 
				
			|||
    : config.dev.assetsSubDirectory | 
				
			|||
 | 
				
			|||
  return path.posix.join(assetsSubDirectory, _path) | 
				
			|||
} | 
				
			|||
 | 
				
			|||
exports.cssLoaders = function (options) { | 
				
			|||
  options = options || {} | 
				
			|||
 | 
				
			|||
  const cssLoader = { | 
				
			|||
    loader: 'css-loader', | 
				
			|||
    options: { | 
				
			|||
      sourceMap: options.sourceMap | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  const postcssLoader = { | 
				
			|||
    loader: 'postcss-loader', | 
				
			|||
    options: { | 
				
			|||
      sourceMap: options.sourceMap | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  // generate loader string to be used with extract text plugin
 | 
				
			|||
  function generateLoaders (loader, loaderOptions) { | 
				
			|||
    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] | 
				
			|||
 | 
				
			|||
    if (loader) { | 
				
			|||
      loaders.push({ | 
				
			|||
        loader: loader + '-loader', | 
				
			|||
        options: Object.assign({}, loaderOptions, { | 
				
			|||
          sourceMap: options.sourceMap | 
				
			|||
        }) | 
				
			|||
      }) | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    // Extract CSS when that option is specified
 | 
				
			|||
    // (which is the case during production build)
 | 
				
			|||
    if (options.extract) { | 
				
			|||
      return ExtractTextPlugin.extract({ | 
				
			|||
        use: loaders, | 
				
			|||
        fallback: 'vue-style-loader' | 
				
			|||
      }) | 
				
			|||
    } else { | 
				
			|||
      return ['vue-style-loader'].concat(loaders) | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
 | 
				
			|||
  return { | 
				
			|||
    css: generateLoaders(), | 
				
			|||
    postcss: generateLoaders(), | 
				
			|||
    less: generateLoaders('less'), | 
				
			|||
    sass: generateLoaders('sass', { indentedSyntax: true }), | 
				
			|||
    scss: generateLoaders('sass'), | 
				
			|||
    stylus: generateLoaders('stylus'), | 
				
			|||
    styl: generateLoaders('stylus') | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
// Generate loaders for standalone style files (outside of .vue)
 | 
				
			|||
exports.styleLoaders = function (options) { | 
				
			|||
  const output = [] | 
				
			|||
  const loaders = exports.cssLoaders(options) | 
				
			|||
 | 
				
			|||
  for (const extension in loaders) { | 
				
			|||
    const loader = loaders[extension] | 
				
			|||
    output.push({ | 
				
			|||
      test: new RegExp('\\.' + extension + '$'), | 
				
			|||
      use: loader | 
				
			|||
    }) | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  return output | 
				
			|||
} | 
				
			|||
 | 
				
			|||
exports.createNotifierCallback = () => { | 
				
			|||
  const notifier = require('node-notifier') | 
				
			|||
 | 
				
			|||
  return (severity, errors) => { | 
				
			|||
    if (severity !== 'error') return | 
				
			|||
 | 
				
			|||
    const error = errors[0] | 
				
			|||
    const filename = error.file && error.file.split('!').pop() | 
				
			|||
 | 
				
			|||
    notifier.notify({ | 
				
			|||
      title: packageConfig.name, | 
				
			|||
      message: severity + ': ' + error.name, | 
				
			|||
      subtitle: filename || '', | 
				
			|||
      icon: path.join(__dirname, 'logo.png') | 
				
			|||
    }) | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,22 @@ | 
				
			|||
'use strict' | 
				
			|||
const utils = require('./utils') | 
				
			|||
const config = require('../config') | 
				
			|||
const isProduction = process.env.NODE_ENV === 'production' | 
				
			|||
const sourceMapEnabled = isProduction | 
				
			|||
  ? config.build.productionSourceMap | 
				
			|||
  : config.dev.cssSourceMap | 
				
			|||
 | 
				
			|||
module.exports = { | 
				
			|||
  loaders: utils.cssLoaders({ | 
				
			|||
    sourceMap: sourceMapEnabled, | 
				
			|||
    extract: isProduction | 
				
			|||
  }), | 
				
			|||
  cssSourceMap: sourceMapEnabled, | 
				
			|||
  cacheBusting: config.dev.cacheBusting, | 
				
			|||
  transformToRequire: { | 
				
			|||
    video: ['src', 'poster'], | 
				
			|||
    source: 'src', | 
				
			|||
    img: 'src', | 
				
			|||
    image: 'xlink:href' | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,82 @@ | 
				
			|||
'use strict' | 
				
			|||
const path = require('path') | 
				
			|||
const utils = require('./utils') | 
				
			|||
const config = require('../config') | 
				
			|||
const vueLoaderConfig = require('./vue-loader.conf') | 
				
			|||
 | 
				
			|||
function resolve (dir) { | 
				
			|||
  return path.join(__dirname, '..', dir) | 
				
			|||
} | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
module.exports = { | 
				
			|||
  context: path.resolve(__dirname, '../'), | 
				
			|||
  entry: { | 
				
			|||
    app: './src/main.js' | 
				
			|||
  }, | 
				
			|||
  output: { | 
				
			|||
    path: config.build.assetsRoot, | 
				
			|||
    filename: '[name].js', | 
				
			|||
    publicPath: process.env.NODE_ENV === 'production' | 
				
			|||
      ? config.build.assetsPublicPath | 
				
			|||
      : config.dev.assetsPublicPath | 
				
			|||
  }, | 
				
			|||
  resolve: { | 
				
			|||
    extensions: ['.js', '.vue', '.json'], | 
				
			|||
    alias: { | 
				
			|||
      'vue$': 'vue/dist/vue.esm.js', | 
				
			|||
      '@': resolve('src'), | 
				
			|||
    } | 
				
			|||
  }, | 
				
			|||
  module: { | 
				
			|||
    rules: [ | 
				
			|||
      { | 
				
			|||
        test: /\.vue$/, | 
				
			|||
        loader: 'vue-loader', | 
				
			|||
        options: vueLoaderConfig | 
				
			|||
      }, | 
				
			|||
      { | 
				
			|||
        test: /\.js$/, | 
				
			|||
        loader: 'babel-loader', | 
				
			|||
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] | 
				
			|||
      }, | 
				
			|||
      { | 
				
			|||
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, | 
				
			|||
        loader: 'url-loader', | 
				
			|||
        options: { | 
				
			|||
          limit: 10000, | 
				
			|||
          name: utils.assetsPath('img/[name].[hash:7].[ext]') | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      { | 
				
			|||
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, | 
				
			|||
        loader: 'url-loader', | 
				
			|||
        options: { | 
				
			|||
          limit: 10000, | 
				
			|||
          name: utils.assetsPath('media/[name].[hash:7].[ext]') | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      { | 
				
			|||
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, | 
				
			|||
        loader: 'url-loader', | 
				
			|||
        options: { | 
				
			|||
          limit: 10000, | 
				
			|||
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]') | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
    ] | 
				
			|||
  }, | 
				
			|||
  node: { | 
				
			|||
    // prevent webpack from injecting useless setImmediate polyfill because Vue
 | 
				
			|||
    // source contains it (although only uses it if it's native).
 | 
				
			|||
    setImmediate: false, | 
				
			|||
    // prevent webpack from injecting mocks to Node native modules
 | 
				
			|||
    // that does not make sense for the client
 | 
				
			|||
    dgram: 'empty', | 
				
			|||
    fs: 'empty', | 
				
			|||
    net: 'empty', | 
				
			|||
    tls: 'empty', | 
				
			|||
    child_process: 'empty' | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,95 @@ | 
				
			|||
'use strict' | 
				
			|||
const utils = require('./utils') | 
				
			|||
const webpack = require('webpack') | 
				
			|||
const config = require('../config') | 
				
			|||
const merge = require('webpack-merge') | 
				
			|||
const path = require('path') | 
				
			|||
const baseWebpackConfig = require('./webpack.base.conf') | 
				
			|||
const CopyWebpackPlugin = require('copy-webpack-plugin') | 
				
			|||
const HtmlWebpackPlugin = require('html-webpack-plugin') | 
				
			|||
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') | 
				
			|||
const portfinder = require('portfinder') | 
				
			|||
 | 
				
			|||
const HOST = process.env.HOST | 
				
			|||
const PORT = process.env.PORT && Number(process.env.PORT) | 
				
			|||
 | 
				
			|||
const devWebpackConfig = merge(baseWebpackConfig, { | 
				
			|||
  module: { | 
				
			|||
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) | 
				
			|||
  }, | 
				
			|||
  // cheap-module-eval-source-map is faster for development
 | 
				
			|||
  devtool: config.dev.devtool, | 
				
			|||
 | 
				
			|||
  // these devServer options should be customized in /config/index.js
 | 
				
			|||
  devServer: { | 
				
			|||
    clientLogLevel: 'warning', | 
				
			|||
    historyApiFallback: { | 
				
			|||
      rewrites: [ | 
				
			|||
        { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, | 
				
			|||
      ], | 
				
			|||
    }, | 
				
			|||
    hot: true, | 
				
			|||
    contentBase: false, // since we use CopyWebpackPlugin.
 | 
				
			|||
    compress: true, | 
				
			|||
    host: HOST || config.dev.host, | 
				
			|||
    port: PORT || config.dev.port, | 
				
			|||
    open: config.dev.autoOpenBrowser, | 
				
			|||
    overlay: config.dev.errorOverlay | 
				
			|||
      ? { warnings: false, errors: true } | 
				
			|||
      : false, | 
				
			|||
    publicPath: config.dev.assetsPublicPath, | 
				
			|||
    proxy: config.dev.proxyTable, | 
				
			|||
    quiet: true, // necessary for FriendlyErrorsPlugin
 | 
				
			|||
    watchOptions: { | 
				
			|||
      poll: config.dev.poll, | 
				
			|||
    } | 
				
			|||
  }, | 
				
			|||
  plugins: [ | 
				
			|||
    new webpack.DefinePlugin({ | 
				
			|||
      'process.env': require('../config/dev.env') | 
				
			|||
    }), | 
				
			|||
    new webpack.HotModuleReplacementPlugin(), | 
				
			|||
    new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
 | 
				
			|||
    new webpack.NoEmitOnErrorsPlugin(), | 
				
			|||
    // https://github.com/ampedandwired/html-webpack-plugin
 | 
				
			|||
    new HtmlWebpackPlugin({ | 
				
			|||
      filename: 'index.html', | 
				
			|||
      template: 'index.html', | 
				
			|||
      inject: true | 
				
			|||
    }), | 
				
			|||
    // copy custom static assets
 | 
				
			|||
    new CopyWebpackPlugin([ | 
				
			|||
      { | 
				
			|||
        from: path.resolve(__dirname, '../static'), | 
				
			|||
        to: config.dev.assetsSubDirectory, | 
				
			|||
        ignore: ['.*'] | 
				
			|||
      } | 
				
			|||
    ]) | 
				
			|||
  ] | 
				
			|||
}) | 
				
			|||
 | 
				
			|||
module.exports = new Promise((resolve, reject) => { | 
				
			|||
  portfinder.basePort = process.env.PORT || config.dev.port | 
				
			|||
  portfinder.getPort((err, port) => { | 
				
			|||
    if (err) { | 
				
			|||
      reject(err) | 
				
			|||
    } else { | 
				
			|||
      // publish the new Port, necessary for e2e tests
 | 
				
			|||
      process.env.PORT = port | 
				
			|||
      // add port to devServer config
 | 
				
			|||
      devWebpackConfig.devServer.port = port | 
				
			|||
 | 
				
			|||
      // Add FriendlyErrorsPlugin
 | 
				
			|||
      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ | 
				
			|||
        compilationSuccessInfo: { | 
				
			|||
          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], | 
				
			|||
        }, | 
				
			|||
        onErrors: config.dev.notifyOnErrors | 
				
			|||
        ? utils.createNotifierCallback() | 
				
			|||
        : undefined | 
				
			|||
      })) | 
				
			|||
 | 
				
			|||
      resolve(devWebpackConfig) | 
				
			|||
    } | 
				
			|||
  }) | 
				
			|||
}) | 
				
			|||
@ -0,0 +1,149 @@ | 
				
			|||
'use strict' | 
				
			|||
const path = require('path') | 
				
			|||
const utils = require('./utils') | 
				
			|||
const webpack = require('webpack') | 
				
			|||
const config = require('../config') | 
				
			|||
const merge = require('webpack-merge') | 
				
			|||
const baseWebpackConfig = require('./webpack.base.conf') | 
				
			|||
const CopyWebpackPlugin = require('copy-webpack-plugin') | 
				
			|||
const HtmlWebpackPlugin = require('html-webpack-plugin') | 
				
			|||
const ExtractTextPlugin = require('extract-text-webpack-plugin') | 
				
			|||
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') | 
				
			|||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin') | 
				
			|||
 | 
				
			|||
const env = process.env.NODE_ENV === 'testing' | 
				
			|||
  ? require('../config/test.env') | 
				
			|||
  : require('../config/prod.env') | 
				
			|||
 | 
				
			|||
const webpackConfig = merge(baseWebpackConfig, { | 
				
			|||
  module: { | 
				
			|||
    rules: utils.styleLoaders({ | 
				
			|||
      sourceMap: config.build.productionSourceMap, | 
				
			|||
      extract: true, | 
				
			|||
      usePostCSS: true | 
				
			|||
    }) | 
				
			|||
  }, | 
				
			|||
  devtool: config.build.productionSourceMap ? config.build.devtool : false, | 
				
			|||
  output: { | 
				
			|||
    path: config.build.assetsRoot, | 
				
			|||
    filename: utils.assetsPath('js/[name].[chunkhash].js'), | 
				
			|||
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') | 
				
			|||
  }, | 
				
			|||
  plugins: [ | 
				
			|||
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
 | 
				
			|||
    new webpack.DefinePlugin({ | 
				
			|||
      'process.env': env | 
				
			|||
    }), | 
				
			|||
    new UglifyJsPlugin({ | 
				
			|||
      uglifyOptions: { | 
				
			|||
        compress: { | 
				
			|||
          warnings: false | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      sourceMap: config.build.productionSourceMap, | 
				
			|||
      parallel: true | 
				
			|||
    }), | 
				
			|||
    // extract css into its own file
 | 
				
			|||
    new ExtractTextPlugin({ | 
				
			|||
      filename: utils.assetsPath('css/[name].[contenthash].css'), | 
				
			|||
      // Setting the following option to `false` will not extract CSS from codesplit chunks.
 | 
				
			|||
      // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
 | 
				
			|||
      // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 
 | 
				
			|||
      // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
 | 
				
			|||
      allChunks: true, | 
				
			|||
    }), | 
				
			|||
    // Compress extracted CSS. We are using this plugin so that possible
 | 
				
			|||
    // duplicated CSS from different components can be deduped.
 | 
				
			|||
    new OptimizeCSSPlugin({ | 
				
			|||
      cssProcessorOptions: config.build.productionSourceMap | 
				
			|||
        ? { safe: true, map: { inline: false } } | 
				
			|||
        : { safe: true } | 
				
			|||
    }), | 
				
			|||
    // generate dist index.html with correct asset hash for caching.
 | 
				
			|||
    // you can customize output by editing /index.html
 | 
				
			|||
    // see https://github.com/ampedandwired/html-webpack-plugin
 | 
				
			|||
    new HtmlWebpackPlugin({ | 
				
			|||
      filename: process.env.NODE_ENV === 'testing' | 
				
			|||
        ? 'index.html' | 
				
			|||
        : config.build.index, | 
				
			|||
      template: 'index.html', | 
				
			|||
      inject: true, | 
				
			|||
      minify: { | 
				
			|||
        removeComments: true, | 
				
			|||
        collapseWhitespace: true, | 
				
			|||
        removeAttributeQuotes: true | 
				
			|||
        // more options:
 | 
				
			|||
        // https://github.com/kangax/html-minifier#options-quick-reference
 | 
				
			|||
      }, | 
				
			|||
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
 | 
				
			|||
      chunksSortMode: 'dependency' | 
				
			|||
    }), | 
				
			|||
    // keep module.id stable when vendor modules does not change
 | 
				
			|||
    new webpack.HashedModuleIdsPlugin(), | 
				
			|||
    // enable scope hoisting
 | 
				
			|||
    new webpack.optimize.ModuleConcatenationPlugin(), | 
				
			|||
    // split vendor js into its own file
 | 
				
			|||
    new webpack.optimize.CommonsChunkPlugin({ | 
				
			|||
      name: 'vendor', | 
				
			|||
      minChunks (module) { | 
				
			|||
        // any required modules inside node_modules are extracted to vendor
 | 
				
			|||
        return ( | 
				
			|||
          module.resource && | 
				
			|||
          /\.js$/.test(module.resource) && | 
				
			|||
          module.resource.indexOf( | 
				
			|||
            path.join(__dirname, '../node_modules') | 
				
			|||
          ) === 0 | 
				
			|||
        ) | 
				
			|||
      } | 
				
			|||
    }), | 
				
			|||
    // extract webpack runtime and module manifest to its own file in order to
 | 
				
			|||
    // prevent vendor hash from being updated whenever app bundle is updated
 | 
				
			|||
    new webpack.optimize.CommonsChunkPlugin({ | 
				
			|||
      name: 'manifest', | 
				
			|||
      minChunks: Infinity | 
				
			|||
    }), | 
				
			|||
    // This instance extracts shared chunks from code splitted chunks and bundles them
 | 
				
			|||
    // in a separate chunk, similar to the vendor chunk
 | 
				
			|||
    // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
 | 
				
			|||
    new webpack.optimize.CommonsChunkPlugin({ | 
				
			|||
      name: 'app', | 
				
			|||
      async: 'vendor-async', | 
				
			|||
      children: true, | 
				
			|||
      minChunks: 3 | 
				
			|||
    }), | 
				
			|||
 | 
				
			|||
    // copy custom static assets
 | 
				
			|||
    new CopyWebpackPlugin([ | 
				
			|||
      { | 
				
			|||
        from: path.resolve(__dirname, '../static'), | 
				
			|||
        to: config.build.assetsSubDirectory, | 
				
			|||
        ignore: ['.*'] | 
				
			|||
      } | 
				
			|||
    ]) | 
				
			|||
  ] | 
				
			|||
}) | 
				
			|||
 | 
				
			|||
if (config.build.productionGzip) { | 
				
			|||
  const CompressionWebpackPlugin = require('compression-webpack-plugin') | 
				
			|||
 | 
				
			|||
  webpackConfig.plugins.push( | 
				
			|||
    new CompressionWebpackPlugin({ | 
				
			|||
      asset: '[path].gz[query]', | 
				
			|||
      algorithm: 'gzip', | 
				
			|||
      test: new RegExp( | 
				
			|||
        '\\.(' + | 
				
			|||
        config.build.productionGzipExtensions.join('|') + | 
				
			|||
        ')$' | 
				
			|||
      ), | 
				
			|||
      threshold: 10240, | 
				
			|||
      minRatio: 0.8 | 
				
			|||
    }) | 
				
			|||
  ) | 
				
			|||
} | 
				
			|||
 | 
				
			|||
if (config.build.bundleAnalyzerReport) { | 
				
			|||
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin | 
				
			|||
  webpackConfig.plugins.push(new BundleAnalyzerPlugin()) | 
				
			|||
} | 
				
			|||
 | 
				
			|||
module.exports = webpackConfig | 
				
			|||
@ -0,0 +1,7 @@ | 
				
			|||
'use strict' | 
				
			|||
const merge = require('webpack-merge') | 
				
			|||
const prodEnv = require('./prod.env') | 
				
			|||
 | 
				
			|||
module.exports = merge(prodEnv, { | 
				
			|||
  NODE_ENV: '"development"' | 
				
			|||
}) | 
				
			|||
@ -0,0 +1,77 @@ | 
				
			|||
'use strict' | 
				
			|||
// Template version: 1.3.1
 | 
				
			|||
// see http://vuejs-templates.github.io/webpack for documentation.
 | 
				
			|||
 | 
				
			|||
const path = require('path') | 
				
			|||
 | 
				
			|||
module.exports = { | 
				
			|||
  dev: { | 
				
			|||
 | 
				
			|||
    // Paths
 | 
				
			|||
    assetsSubDirectory: 'static', | 
				
			|||
    assetsPublicPath: '/', | 
				
			|||
    proxyTable: { | 
				
			|||
            '/api': { | 
				
			|||
              target: 'http://localhost:8443',//后端application的path配置
 | 
				
			|||
              changeOrigin: true, | 
				
			|||
              pathRewrite: { | 
				
			|||
                '^/api': '' | 
				
			|||
              } | 
				
			|||
            } | 
				
			|||
    }, | 
				
			|||
 | 
				
			|||
    // Various Dev Server settings
 | 
				
			|||
    host: 'localhost', // can be overwritten by process.env.HOST
 | 
				
			|||
    port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
 | 
				
			|||
    autoOpenBrowser: false, | 
				
			|||
    errorOverlay: true, | 
				
			|||
    notifyOnErrors: true, | 
				
			|||
    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Source Maps | 
				
			|||
     */ | 
				
			|||
 | 
				
			|||
    // https://webpack.js.org/configuration/devtool/#development
 | 
				
			|||
    devtool: 'cheap-module-eval-source-map', | 
				
			|||
 | 
				
			|||
    // If you have problems debugging vue-files in devtools,
 | 
				
			|||
    // set this to false - it *may* help
 | 
				
			|||
    // https://vue-loader.vuejs.org/en/options.html#cachebusting
 | 
				
			|||
    cacheBusting: true, | 
				
			|||
 | 
				
			|||
    cssSourceMap: true | 
				
			|||
  }, | 
				
			|||
 | 
				
			|||
  build: { | 
				
			|||
    // Template for index.html
 | 
				
			|||
    index: path.resolve(__dirname, '../dist/index.html'), | 
				
			|||
 | 
				
			|||
    // Paths
 | 
				
			|||
    assetsRoot: path.resolve(__dirname, '../dist'), | 
				
			|||
    assetsSubDirectory: 'static', | 
				
			|||
    assetsPublicPath: '/', | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Source Maps | 
				
			|||
     */ | 
				
			|||
 | 
				
			|||
    productionSourceMap: true, | 
				
			|||
    // https://webpack.js.org/configuration/devtool/#production
 | 
				
			|||
    devtool: '#source-map', | 
				
			|||
 | 
				
			|||
    // Gzip off by default as many popular static hosts such as
 | 
				
			|||
    // Surge or Netlify already gzip all static assets for you.
 | 
				
			|||
    // Before setting to `true`, make sure to:
 | 
				
			|||
    // npm install --save-dev compression-webpack-plugin
 | 
				
			|||
    productionGzip: false, | 
				
			|||
    productionGzipExtensions: ['js', 'css'], | 
				
			|||
 | 
				
			|||
    // Run the build command with an extra argument to
 | 
				
			|||
    // View the bundle analyzer report after build finishes:
 | 
				
			|||
    // `npm run build --report`
 | 
				
			|||
    // Set to `true` or `false` to always turn it on or off
 | 
				
			|||
    bundleAnalyzerReport: process.env.npm_config_report | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,4 @@ | 
				
			|||
'use strict' | 
				
			|||
module.exports = { | 
				
			|||
  NODE_ENV: '"production"' | 
				
			|||
} | 
				
			|||
@ -0,0 +1,7 @@ | 
				
			|||
'use strict' | 
				
			|||
const merge = require('webpack-merge') | 
				
			|||
const devEnv = require('./dev.env') | 
				
			|||
 | 
				
			|||
module.exports = merge(devEnv, { | 
				
			|||
  NODE_ENV: '"testing"' | 
				
			|||
}) | 
				
			|||
@ -0,0 +1,12 @@ | 
				
			|||
<!DOCTYPE html> | 
				
			|||
<html> | 
				
			|||
  <head> | 
				
			|||
    <meta charset="utf-8"> | 
				
			|||
    <meta name="viewport" content="width=device-width,initial-scale=1.0"> | 
				
			|||
    <title>vote-vue</title> | 
				
			|||
  </head> | 
				
			|||
  <body> | 
				
			|||
    <div id="app"></div> | 
				
			|||
    <!-- built files will be auto injected --> | 
				
			|||
  </body> | 
				
			|||
</html> | 
				
			|||
@ -0,0 +1,85 @@ | 
				
			|||
{ | 
				
			|||
  "name": "vote-vue", | 
				
			|||
  "version": "1.0.0", | 
				
			|||
  "description": "A Vue.js project", | 
				
			|||
  "author": "ysh <513701065@qq.com>", | 
				
			|||
  "private": true, | 
				
			|||
  "scripts": { | 
				
			|||
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", | 
				
			|||
    "start": "npm run dev", | 
				
			|||
    "unit": "jest --config test/unit/jest.conf.js --coverage", | 
				
			|||
    "e2e": "node test/e2e/runner.js", | 
				
			|||
    "test": "npm run unit && npm run e2e", | 
				
			|||
    "build": "node build/build.js" | 
				
			|||
  }, | 
				
			|||
  "dependencies": { | 
				
			|||
    "axios": "^0.19.2", | 
				
			|||
    "date-fns": "^2.14.0", | 
				
			|||
    "default-passive-events": "^2.0.0", | 
				
			|||
    "element-ui": "^2.13.2", | 
				
			|||
    "install": "^0.13.0", | 
				
			|||
    "qrcodejs2": "0.0.2", | 
				
			|||
    "quill": "^1.3.7", | 
				
			|||
    "vue": "^2.5.2", | 
				
			|||
    "vue-quill-editor": "^3.0.6", | 
				
			|||
    "vue-router": "^3.0.1", | 
				
			|||
    "vuex": "^3.4.0" | 
				
			|||
  }, | 
				
			|||
  "devDependencies": { | 
				
			|||
    "autoprefixer": "^7.1.2", | 
				
			|||
    "babel-core": "^6.22.1", | 
				
			|||
    "babel-helper-vue-jsx-merge-props": "^2.0.3", | 
				
			|||
    "babel-jest": "^21.0.2", | 
				
			|||
    "babel-loader": "^7.1.1", | 
				
			|||
    "babel-plugin-dynamic-import-node": "^1.2.0", | 
				
			|||
    "babel-plugin-syntax-jsx": "^6.18.0", | 
				
			|||
    "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", | 
				
			|||
    "babel-plugin-transform-runtime": "^6.22.0", | 
				
			|||
    "babel-plugin-transform-vue-jsx": "^3.5.0", | 
				
			|||
    "babel-preset-env": "^1.3.2", | 
				
			|||
    "babel-preset-stage-2": "^6.22.0", | 
				
			|||
    "babel-register": "^6.22.0", | 
				
			|||
    "chalk": "^2.0.1", | 
				
			|||
    "chromedriver": "^2.27.2", | 
				
			|||
    "copy-webpack-plugin": "^4.0.1", | 
				
			|||
    "cross-spawn": "^5.0.1", | 
				
			|||
    "css-loader": "^0.28.0", | 
				
			|||
    "extract-text-webpack-plugin": "^3.0.0", | 
				
			|||
    "file-loader": "^1.1.4", | 
				
			|||
    "friendly-errors-webpack-plugin": "^1.6.1", | 
				
			|||
    "html-webpack-plugin": "^2.30.1", | 
				
			|||
    "jest": "^22.0.4", | 
				
			|||
    "jest-serializer-vue": "^0.3.0", | 
				
			|||
    "nightwatch": "^0.9.12", | 
				
			|||
    "node-notifier": "^5.1.2", | 
				
			|||
    "optimize-css-assets-webpack-plugin": "^3.2.0", | 
				
			|||
    "ora": "^1.2.0", | 
				
			|||
    "portfinder": "^1.0.13", | 
				
			|||
    "postcss-import": "^11.0.0", | 
				
			|||
    "postcss-loader": "^2.0.8", | 
				
			|||
    "postcss-url": "^7.2.1", | 
				
			|||
    "rimraf": "^2.6.0", | 
				
			|||
    "selenium-server": "^3.0.1", | 
				
			|||
    "semver": "^5.3.0", | 
				
			|||
    "shelljs": "^0.7.6", | 
				
			|||
    "uglifyjs-webpack-plugin": "^1.1.1", | 
				
			|||
    "url-loader": "^0.5.8", | 
				
			|||
    "vue-jest": "^1.0.2", | 
				
			|||
    "vue-loader": "^13.3.0", | 
				
			|||
    "vue-style-loader": "^3.0.1", | 
				
			|||
    "vue-template-compiler": "^2.5.2", | 
				
			|||
    "webpack": "^3.6.0", | 
				
			|||
    "webpack-bundle-analyzer": "^2.9.0", | 
				
			|||
    "webpack-dev-server": "^2.9.1", | 
				
			|||
    "webpack-merge": "^4.1.0" | 
				
			|||
  }, | 
				
			|||
  "engines": { | 
				
			|||
    "node": ">= 6.0.0", | 
				
			|||
    "npm": ">= 3.0.0" | 
				
			|||
  }, | 
				
			|||
  "browserslist": [ | 
				
			|||
    "> 1%", | 
				
			|||
    "last 2 versions", | 
				
			|||
    "not ie <= 8" | 
				
			|||
  ] | 
				
			|||
} | 
				
			|||
@ -0,0 +1,22 @@ | 
				
			|||
<template> | 
				
			|||
  <div id="app"> | 
				
			|||
    <router-view/> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
import TopNav from "./components/common/TopNav.vue"; | 
				
			|||
export default { | 
				
			|||
  name: 'App' | 
				
			|||
} | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style> | 
				
			|||
#app { | 
				
			|||
  font-family: 'Avenir', Helvetica, Arial, sans-serif; | 
				
			|||
  -webkit-font-smoothing: antialiased; | 
				
			|||
  -moz-osx-font-smoothing: grayscale; | 
				
			|||
  text-align: center; | 
				
			|||
  color: #2c3e50; | 
				
			|||
} | 
				
			|||
</style> | 
				
			|||
| 
		 After Width: | Height: | Size: 6.7 KiB  | 
@ -0,0 +1,615 @@ | 
				
			|||
<!-- 投票页面 --> | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
     | 
				
			|||
    <el-row> | 
				
			|||
      <el-col :xs="24" :sm="4"> | 
				
			|||
        <el-dialog title="选手详情" :visible.sync="dialogFormVisible" :modal-append-to-body="false" @close="clear" | 
				
			|||
          :width="dialogWidth" style="text-align: center"> | 
				
			|||
          <img :src="itemCoverLink" alt="" :onerror="errorImg01" style="width: 40%;" /> | 
				
			|||
          <p v-html="candidateDesc"> </p> | 
				
			|||
        </el-dialog> | 
				
			|||
        <el-dialog title="请先登录" :visible.sync="dialogForLogin" :modal-append-to-body="false" @close="clear" | 
				
			|||
          :width="dialogWidth"> | 
				
			|||
          <el-form label-position="right" label-width="100px"> | 
				
			|||
            <el-form-item label="账号"> | 
				
			|||
              <el-input v-model="user.userName" placeholder="用户名" class="login-input"></el-input> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item label="密码"> | 
				
			|||
              <el-input v-model="user.password" placeholder="请输入密码" type="password" class="login-input"></el-input> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item label="验证码"> | 
				
			|||
              <el-input v-model="verifyCode" placeholder="请输入右侧验证码" class="login-input"></el-input> | 
				
			|||
              <img :src="captchaPath" @click="updateVerifyCode" class="captcha-code"> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item> | 
				
			|||
              <el-button type="primary" class="login-button" @click="doLogin"> 登 录 </el-button> | 
				
			|||
              <span class="forget-tips-text"> | 
				
			|||
                <a href="/login/forget">忘记密码?</a> | 
				
			|||
              </span> | 
				
			|||
            </el-form-item> | 
				
			|||
          </el-form> | 
				
			|||
        </el-dialog> | 
				
			|||
 | 
				
			|||
        <el-dialog title="投票验证码" :visible.sync="dialogForVote" :modal-append-to-body="false" @close="clear" | 
				
			|||
          :width="dialogWidth" style="text-align: center"> | 
				
			|||
          <el-form> | 
				
			|||
            <el-form-item> | 
				
			|||
              <img :src="captchaPath" @click="updateVerifyCode" class="captcha-code"> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item> | 
				
			|||
              <el-input v-model="verifyCode" placeholder="输入上边验证码" class="verify-code-input"></el-input> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item> | 
				
			|||
              <el-button type="primary" @click="singleVote"> 提 交 </el-button> | 
				
			|||
            </el-form-item> | 
				
			|||
          </el-form> | 
				
			|||
        </el-dialog> | 
				
			|||
 | 
				
			|||
      </el-col> | 
				
			|||
    </el-row> | 
				
			|||
    <el-row> | 
				
			|||
      | 
				
			|||
      <el-col :md="{ span:2, offset: 2}"> | 
				
			|||
        <div class="voteHomeBox" style="margin-top: 12px;"> | 
				
			|||
        <el-breadcrumb separator="/"> | 
				
			|||
      <el-breadcrumb-item :to="{ path: '/' }"><span class="voteHome">首页</span></el-breadcrumb-item> | 
				
			|||
    </el-breadcrumb> | 
				
			|||
  </div>  | 
				
			|||
  </el-col> | 
				
			|||
  | 
				
			|||
         | 
				
			|||
        <el-col :xs="{ span: 24, offset: 0 }" :sm="{ span: 16, offset: 4 }" :md="{ span: 16, offset:  0}"> | 
				
			|||
          <el-collapse> | 
				
			|||
            <el-collapse-item :title="rulesRemindBoxTitle"> | 
				
			|||
              <template slot="title" > | 
				
			|||
                <span class="rulesBox" >投票规则</span> | 
				
			|||
              </template> | 
				
			|||
              <el-card class="activityDescDard"> | 
				
			|||
                <h3>{{ curActivity.title }}</h3> | 
				
			|||
                <h5 style="color: #999">请仔细阅读活动详细规则</h5> | 
				
			|||
                <el-col :xl="4"> </el-col> | 
				
			|||
                <el-col :sm="16"> | 
				
			|||
                  <div style="text-align: left;font: 14px;color: #999;"> | 
				
			|||
                    <div class="activeTime" style="margin: 10px;"> | 
				
			|||
                      活动开始:{{ curActivity.startTime | fmtDate }} <br> | 
				
			|||
                      活动截止:{{ curActivity.endTime | fmtDate }} <br> | 
				
			|||
                    </div> | 
				
			|||
                    <div class="activerule" style="margin: 10px;"> | 
				
			|||
                      投票规则: <br> | 
				
			|||
                      <div> | 
				
			|||
                        <span v-if="activityType.voteType === 'single'">1. | 
				
			|||
                          每个用户可以投{{ activityType.totalVotes }}票,可为同一选手投票{{ activityType.oneVotes }}票</span> | 
				
			|||
                        <span v-else>1. 最少选择{{ activityType.least }}人,最多投{{ activityType.most }}票</span> | 
				
			|||
                        <br> | 
				
			|||
                        <span v-if="activityType.cycleType === 'true'">2. 每天都可以投票</span> | 
				
			|||
                        <span v-else>2. 投票期间只能投一次</span> | 
				
			|||
                        <br> | 
				
			|||
                        <span v-if="curActivity.verifyCode">3. 投票时需要输入验证码</span> | 
				
			|||
                      </div> | 
				
			|||
                    </div> | 
				
			|||
                    <div class="activerule" style="margin: 10px;"> | 
				
			|||
                      活动详情: <br> | 
				
			|||
                      <p style="padding-left: 50px;" v-html="curActivity.content"> | 
				
			|||
 | 
				
			|||
                      </p> | 
				
			|||
                    </div> | 
				
			|||
                  </div> | 
				
			|||
                </el-col> | 
				
			|||
              </el-card> | 
				
			|||
            </el-collapse-item> | 
				
			|||
          </el-collapse> | 
				
			|||
        </el-col> | 
				
			|||
       | 
				
			|||
 | 
				
			|||
    </el-row> | 
				
			|||
    <el-row> | 
				
			|||
      <el-col :xs="{ span: 24, offset: 0 }" :sm="{ span: 16, offset: 4 }" :md="{ span: 16, offset: 4 }"> | 
				
			|||
        <el-tabs v-model="activeName" @tab-click="handleTabClick"> | 
				
			|||
          <el-tab-pane label="进行投票" name="first"> | 
				
			|||
            <h2>参赛选手</h2> | 
				
			|||
            <h5 style="color: #999">请为喜欢的选手投票,点击选手头像查看详细信息</h5> | 
				
			|||
            <div v-if="activityType.voteType === 'single'"> | 
				
			|||
              <el-row> | 
				
			|||
                <div v-for="(item, index) in voteItems" :key="index"> | 
				
			|||
                  <el-col :xs="10" :sm="5" :offset="1"> | 
				
			|||
                    <el-card style="background-color: #F7F7F7; margin-bottom: 10px"> | 
				
			|||
                      <div @click="showDetail(item)"> | 
				
			|||
                        <img :src="item.coverUrl" alt="" :onerror="errorImg01" | 
				
			|||
                          style="width: 66px;height: 66px; border-radius: 50%;"> | 
				
			|||
                        <div style="padding: 14px;color: #999; font-size: 14px;"> | 
				
			|||
                          <span style="font-size: 16px;font-weight: bold; color: #2C3E50;">{{ item.title }}</span><br /> | 
				
			|||
                          <span>编号: {{ item.num }}</span><br> | 
				
			|||
                          <span>得票:<span style="color: red;">{{ item.voteCount }} </span>票</span><br> | 
				
			|||
                        </div> | 
				
			|||
                      </div> | 
				
			|||
                      <el-button type="primary" size="small" style="margin: 10px;" | 
				
			|||
                        @click="handleVote(item)">投一票</el-button> | 
				
			|||
                    </el-card> | 
				
			|||
                  </el-col> | 
				
			|||
                </div> | 
				
			|||
              </el-row><br> | 
				
			|||
            </div> | 
				
			|||
            <div v-else> | 
				
			|||
              <el-row> | 
				
			|||
                <div v-for="(item, index) in voteItems" :key="index"> | 
				
			|||
                  <el-col :xs="10" :sm="5" :offset="1"> | 
				
			|||
                    <el-card style="background-color: #F7F7F7;margin-bottom: 10px"> | 
				
			|||
                      <div @click="showDetail(item)"> | 
				
			|||
                        <img src="../img/defaultImg.png" alt="" :onerror="errorImg01" | 
				
			|||
                          style="width: 66px;height: 66px; border-radius: 50%;"> | 
				
			|||
                        <div style="padding: 14px;color: #999; font-size: 14px;"> | 
				
			|||
                          <span style="font-size: 16px;font-weight: bold; color: #2C3E50;">{{ item.title }}</span><br /> | 
				
			|||
                          <span>编号: {{ item.num }}</span><br> | 
				
			|||
                          <span>得:<span style="color: red;">{{ item.voteCount }} </span>票</span><br> | 
				
			|||
                        </div> | 
				
			|||
                      </div> | 
				
			|||
                      <el-button :type="btnMap.get(item.id)" size="small" style="margin: 10px" | 
				
			|||
                        @click="changeSelected(item.id)" v-if="btnMap.get(item.id) != 'primary'"> | 
				
			|||
                        投一票 | 
				
			|||
                      </el-button> | 
				
			|||
                      <el-button :type="btnMap.get(item.id)" size="small" style="margin: 10px" | 
				
			|||
                        @click="changeSelected(item.id)" v-else> | 
				
			|||
                        已  选 | 
				
			|||
                      </el-button> | 
				
			|||
                    </el-card> | 
				
			|||
                  </el-col> | 
				
			|||
                </div> | 
				
			|||
              </el-row><br> | 
				
			|||
            </div> | 
				
			|||
            <div> | 
				
			|||
              <div v-if="activityType.voteType === 'multiple'" style="float: right;margin-right: 20px"> | 
				
			|||
                <el-button type="primary" @click="multipleVote"> | 
				
			|||
                  提交投票 | 
				
			|||
                </el-button> | 
				
			|||
              </div> | 
				
			|||
              <div style="float: left;margin-left: 20px;margin-bottom: 10px"> | 
				
			|||
                <el-pagination @current-change="handleCurrentChange" :current-page="currentPage" :page-size="pageSize" | 
				
			|||
                  :total="totalSize"> | 
				
			|||
                </el-pagination> | 
				
			|||
              </div> | 
				
			|||
            </div> | 
				
			|||
          </el-tab-pane> | 
				
			|||
          <el-tab-pane label="查看排行" name="second"> | 
				
			|||
            <h2>排行榜</h2> | 
				
			|||
            <h5 style="color: #999">实时显示当前投票排名</h5> | 
				
			|||
            <div v-for="(item, index) in totalItems" :key="index"> | 
				
			|||
              <el-row> | 
				
			|||
                <el-col :xs="{ span: 24, offset: 0 }" :sm="{ span: 16, offset: 4 }" :md="{ span: 16, offset: 4 }"> | 
				
			|||
                  <el-card style="background-color: #F7F7F7; height: 65px;" :body-style="{ padding: '0px' }"> | 
				
			|||
                    <el-col :sm="4" :xs="4" style="margin-top: 22px;color: #999;">第{{ index + 1 }}名</el-col> | 
				
			|||
                    <el-col :sm="4" :xs="4" style="margin-top: 22px;color: #999;">{{ item.title }}</el-col> | 
				
			|||
                    <el-col :sm="4" :xs="4" :offset="1"> <img :src="item.coverUrl" alt="" :onerror="errorImg01" | 
				
			|||
                        style=" width: 55px;height: 55px; border-radius: 50%;margin-top: 5px;"></el-col> | 
				
			|||
                    <el-col :sm="6" :xs="5" style="margin-top: 22px;color: #999;"><el-progress :text-inside="true" | 
				
			|||
                        :stroke-width="18" | 
				
			|||
                        :percentage="parseInt((item.voteCount / sumVotes) * 100) > 0 ? parseInt((item.voteCount / sumVotes) * 100) : 0"></el-progress></el-col> | 
				
			|||
                    <el-col :sm="4" :xs="4" style="margin-top: 22px;color: #999;">{{ item.voteCount }}票</el-col> | 
				
			|||
                  </el-card> | 
				
			|||
                </el-col> | 
				
			|||
              </el-row><br> | 
				
			|||
            </div> | 
				
			|||
          </el-tab-pane> | 
				
			|||
 | 
				
			|||
        </el-tabs> | 
				
			|||
      </el-col> | 
				
			|||
    </el-row> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
export default { | 
				
			|||
  name: "ActivityIndex", | 
				
			|||
  data() { | 
				
			|||
    return { | 
				
			|||
      dialogFormVisible: false, | 
				
			|||
      dialogForLogin: false, | 
				
			|||
      dialogForVote: false, | 
				
			|||
      dialogWidth: '600px', | 
				
			|||
      user: { | 
				
			|||
        userName: 'admin', | 
				
			|||
        password: '123456' | 
				
			|||
      }, | 
				
			|||
      verifyCode: 'verifyCode', | 
				
			|||
      captchaPath: '', | 
				
			|||
      captcha_key: '', | 
				
			|||
      voteItems: [], | 
				
			|||
      totalItems: [], | 
				
			|||
      rankItems: [], | 
				
			|||
      multipleItem: [1, 2, 3, 4], | 
				
			|||
      curActivity: [], | 
				
			|||
      candidateDesc: [], | 
				
			|||
      itemCoverLink: '', | 
				
			|||
      activityType: [], | 
				
			|||
      errorImg01: 'this.src="' + require('../img/defaultImg.png') + '"', | 
				
			|||
      checks: [false, true, true, true], | 
				
			|||
      isActive: true, | 
				
			|||
      btns: [], | 
				
			|||
      btnMap: new Map(), | 
				
			|||
      selectedIds: [], | 
				
			|||
      curUser: [], | 
				
			|||
      activeName: 'first', | 
				
			|||
      sumVotes: 0, | 
				
			|||
      currentPage: 1, | 
				
			|||
      pageSize: 8, | 
				
			|||
      totalSize: 0, | 
				
			|||
      cur_date: new Date(), | 
				
			|||
      selectedItem: [], | 
				
			|||
      voteData: { | 
				
			|||
 | 
				
			|||
      }, | 
				
			|||
      rulesRemindBoxTitle: "投票规则" | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
  }, | 
				
			|||
  mounted() { | 
				
			|||
    window.onresize = () => { | 
				
			|||
      return (() => { | 
				
			|||
        this.setDialogWidth() | 
				
			|||
      })() | 
				
			|||
    } | 
				
			|||
    this.getCandidates() | 
				
			|||
    this.getTotal() | 
				
			|||
    this.getActivity() | 
				
			|||
    this.getCurUser() | 
				
			|||
    this.captcha_key = Date.parse(new Date()) | 
				
			|||
    this.updateVerifyCode(); | 
				
			|||
  }, | 
				
			|||
  methods: { | 
				
			|||
    showDetail(item) { | 
				
			|||
      this.dialogFormVisible = true | 
				
			|||
      this.candidateDesc = item.itemDesc | 
				
			|||
      this.itemCoverLink = item.coverUrl | 
				
			|||
    }, | 
				
			|||
    // goBack() { | 
				
			|||
    //     console.log('/home'); | 
				
			|||
    //   }, | 
				
			|||
    //获取所有所有选手(排好顺序),初始化btnMap | 
				
			|||
    getTotal() { | 
				
			|||
      let _this = this | 
				
			|||
      this.$axios.get('/candidate/list/sequence/' + this.$route.params.id) | 
				
			|||
        .then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            _this.totalItems = resp.data.result | 
				
			|||
            _this.totalSize = resp.data.result.length | 
				
			|||
            _this.sumVotes = 0 | 
				
			|||
            for (let i = 0; i < _this.totalItems.length; i++) { | 
				
			|||
              _this.btnMap.set(_this.totalItems[i].id, '') | 
				
			|||
              _this.sumVotes += this.totalItems[i].voteCount | 
				
			|||
            } | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
    }, | 
				
			|||
    getCandidates() { | 
				
			|||
      let _this = this | 
				
			|||
      this.$axios.get('/candidate/list/' + this.$route.params.id | 
				
			|||
        + '?page=' + _this.currentPage + '&size=' + _this.pageSize).then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            this.voteItems = resp.data.result // 当前页选手 | 
				
			|||
            // this.rankItems = this.voteItems.sort(this.rankCompare) | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
    }, | 
				
			|||
    getActivity() { | 
				
			|||
      this.$axios.get('/activity/' + this.$route.params.id) | 
				
			|||
        .then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            this.curActivity = resp.data.result | 
				
			|||
            this.activityType = JSON.parse(this.curActivity.type) | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
    }, | 
				
			|||
    changeSelected(id) { | 
				
			|||
      if (this.btnMap.get(id) != "primary") { | 
				
			|||
        if (this.selectedIds.length >= this.activityType.most) { | 
				
			|||
          let message = '最多选择' + this.activityType.most + '票!' | 
				
			|||
          this.$message.error(message); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        this.btnMap.set(id, 'primary') | 
				
			|||
        this.selectedIds.push(id) | 
				
			|||
      } else { | 
				
			|||
        this.btnMap.set(id, '') | 
				
			|||
        for (let i = 0; i < this.selectedIds.length; i++) { | 
				
			|||
          if (this.selectedIds[i] === id) { | 
				
			|||
            this.selectedIds.splice(i, 1); | 
				
			|||
          } | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
      this.$forceUpdate(); | 
				
			|||
    }, | 
				
			|||
    handleVote(item) { | 
				
			|||
      let _this = this | 
				
			|||
      // 1. 判断活动状态 | 
				
			|||
      if (this.curActivity.state === '0') { | 
				
			|||
        this.$message.error('该活动暂时禁止投票') | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      //2. 判断活动时间 | 
				
			|||
      let curDate = new Date().getTime | 
				
			|||
      if (curDate < Date.parse(this.curActivity.startTime)) { | 
				
			|||
        this.$message.error("投票还未开始") | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      if (curDate > Date.parse(this.curActivity.endTime)) { | 
				
			|||
        this.$message.error("投票已经结束") | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      // 3. 判断是否登录 | 
				
			|||
      if (this.curUser === "") { | 
				
			|||
        this.dialogForLogin = true | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      // 4.赋值选中的选项 | 
				
			|||
      this.selectedItem = item | 
				
			|||
 | 
				
			|||
      // 5. 判断是否需要验证码 | 
				
			|||
      if (this.curActivity.verifyCode === true) { | 
				
			|||
        this.updateVerifyCode() | 
				
			|||
        this.dialogForVote = true | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      this.singleVote(this.selectedItem) | 
				
			|||
    }, | 
				
			|||
    singleVote() { | 
				
			|||
      let _this = this | 
				
			|||
      if (this.activityType.voteType === 'single') { | 
				
			|||
        this.$axios.post('/vote/single/' + _this.verifyCode + '/' + _this.captcha_key, { | 
				
			|||
          aid: _this.selectedItem.aid, | 
				
			|||
          cid: _this.selectedItem.id, | 
				
			|||
          uid: _this.curUser.id | 
				
			|||
        }).then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            this.$message.success("投票成功") | 
				
			|||
            _this.dialogForVote = false | 
				
			|||
            _this.verifyCode = '' | 
				
			|||
            this.getCandidates() | 
				
			|||
          } else { | 
				
			|||
            let message = resp.data.message | 
				
			|||
            _this.dialogForVote = false | 
				
			|||
            _this.verifyCode = '' | 
				
			|||
            this.$message.error(message) | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      } else { | 
				
			|||
        this.$axios.post('/vote/multiple/' + _this.verifyCode + '/' + _this.captcha_key, { | 
				
			|||
          voteData: { | 
				
			|||
            aid: _this.curActivity.id, | 
				
			|||
            uid: this.curUser.id, | 
				
			|||
            selectedIds: this.selectedIds | 
				
			|||
          } | 
				
			|||
        }).then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            this.$message.success("投票成功") | 
				
			|||
            _this.dialogForVote = false | 
				
			|||
            _this.verifyCode = '' | 
				
			|||
            this.getCandidates() | 
				
			|||
            this.selectedIds = [] | 
				
			|||
            this.getTotal() | 
				
			|||
          } else { | 
				
			|||
            let message = resp.data.message | 
				
			|||
            _this.dialogForVote = false | 
				
			|||
            _this.verifyCode = '' | 
				
			|||
            this.selectedIds = [] | 
				
			|||
            this.getTotal() | 
				
			|||
            this.$message.error(message) | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      } | 
				
			|||
 | 
				
			|||
    }, | 
				
			|||
 | 
				
			|||
    multipleVote() { | 
				
			|||
      // 1. 判断活动状态 | 
				
			|||
      if (this.curActivity.state === '0') { | 
				
			|||
        this.$message.error('该活动暂时禁止投票') | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      //2. 判断活动时间 | 
				
			|||
      let curDate = new Date().getTime | 
				
			|||
      if (curDate < Date.parse(this.curActivity.startTime)) { | 
				
			|||
        this.$message.error("投票还未开始") | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      if (curDate > Date.parse(this.curActivity.endTime)) { | 
				
			|||
        this.$message.error("投票已经结束") | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      //3. 判断是否登录 | 
				
			|||
      if (this.curUser === "") { | 
				
			|||
        this.dialogForLogin = true | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      //4.判断选中选项 | 
				
			|||
      if (this.selectedIds.length < this.activityType.least) { | 
				
			|||
        let message = '最少选择' + this.activityType.least + '票!' | 
				
			|||
        this.$message.error(message) | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      //5.判断是否需要验证码 | 
				
			|||
      if (this.curActivity.verifyCode === true) { | 
				
			|||
        this.updateVerifyCode() | 
				
			|||
        this.dialogForVote = true | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      //6.提交投票 | 
				
			|||
      this.submitVote() | 
				
			|||
    }, | 
				
			|||
 | 
				
			|||
    submitVote() { | 
				
			|||
      let _this = this | 
				
			|||
      this.$axios.post('/vote/multiple/' + _this.verifyCode + '/' + _this.captcha_key, { | 
				
			|||
        voteData: { | 
				
			|||
          aid: _this.curActivity.id, | 
				
			|||
          uid: this.curUser.id, | 
				
			|||
          selectedIds: this.selectedIds, | 
				
			|||
        } | 
				
			|||
      }).then(resp => { | 
				
			|||
        if (resp && resp.data.code === 200) { | 
				
			|||
          this.$message.success("投票成功") | 
				
			|||
          this.selectedIds = [] | 
				
			|||
          this.getTotal() | 
				
			|||
          this.getCandidates() | 
				
			|||
        } else { | 
				
			|||
          let message = resp.data.message | 
				
			|||
          this.selectedIds = [] | 
				
			|||
          this.getTotal() | 
				
			|||
          this.$message.error(message) | 
				
			|||
        } | 
				
			|||
      }) | 
				
			|||
    }, | 
				
			|||
    getCurUser() { | 
				
			|||
      let _this = this | 
				
			|||
      this.$axios.get('/user?userName=' + this.$store.state.user.userName).then(resp => { | 
				
			|||
        if (resp) { | 
				
			|||
          _this.curUser = resp.data | 
				
			|||
        } | 
				
			|||
      }) | 
				
			|||
    }, | 
				
			|||
    handleTabClick(tab, event) { | 
				
			|||
      this.getTotal() | 
				
			|||
      this.$forceUpdate() | 
				
			|||
    }, | 
				
			|||
    clear() { | 
				
			|||
      this.dialogFormVisible = false | 
				
			|||
      this.dialogForLogin = false | 
				
			|||
      this.dialogForVote = false | 
				
			|||
      this.selectedIds = [] | 
				
			|||
      this.verifyCode = '' | 
				
			|||
      this.getTotal() | 
				
			|||
    }, | 
				
			|||
    handleCurrentChange: function (currentPage) { | 
				
			|||
      this.currentPage = currentPage | 
				
			|||
      this.getCandidates() | 
				
			|||
    }, | 
				
			|||
    updateVerifyCode() { | 
				
			|||
      this.captchaPath = 'http://localhost:8443/api/user/captcha?captcha_key=' + this.captcha_key + '&random' + Date.parse(new Date()); | 
				
			|||
    }, | 
				
			|||
    doLogin() { | 
				
			|||
      let _this = this | 
				
			|||
      //判断数据 | 
				
			|||
      if (this.user.userName === '') { | 
				
			|||
        this.$message.error("请输入用户名"); | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      if (this.user.password === '') { | 
				
			|||
        this.$message.error("请输入密码"); | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      if (this.verifyCode === '') { | 
				
			|||
        this.$message.error("请输入验证码"); | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      this.$axios.post('/user/login/' + _this.verifyCode + '/' + _this.captcha_key, { | 
				
			|||
        userName: _this.user.userName, | 
				
			|||
        password: _this.user.password | 
				
			|||
      }).then(resp => { | 
				
			|||
        if (resp.data.code === 200) { | 
				
			|||
          this.$message.success("登录成功"); | 
				
			|||
          _this.dialogForLogin = false | 
				
			|||
          _this.$store.commit('login', _this.user) | 
				
			|||
          _this.getCurUser() | 
				
			|||
        } else { | 
				
			|||
          _this.updateVerifyCode(); | 
				
			|||
          this.$message.error(resp.data.message); | 
				
			|||
        } | 
				
			|||
      }) | 
				
			|||
    }, | 
				
			|||
    setDialogWidth() { | 
				
			|||
      let val = document.body.clientWidth | 
				
			|||
      const def = 500 // 默认宽度 | 
				
			|||
      if (val < def) { | 
				
			|||
        this.dialogWidth = '100%' | 
				
			|||
      } else { | 
				
			|||
        this.dialogWidth = def + 'px' | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
/* .my-header-class { | 
				
			|||
  font-size: 18px; | 
				
			|||
} */ | 
				
			|||
.rulesBox{ | 
				
			|||
  font-size: 28px; | 
				
			|||
  color: #409efe; | 
				
			|||
  font-weight: 600 | 
				
			|||
} | 
				
			|||
   | 
				
			|||
 | 
				
			|||
.voteHome { | 
				
			|||
  font-size: 28px; | 
				
			|||
  color: rgb(64, 158, 254); | 
				
			|||
  font-weight: 600; | 
				
			|||
} | 
				
			|||
.voteHome:hover{ | 
				
			|||
  color: rgb(93, 212, 248); | 
				
			|||
  /* background-color: #d6d6d6; */ | 
				
			|||
} | 
				
			|||
.rulesBox:hover{ | 
				
			|||
  color: rgb(93, 212, 248); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
/* .el-breadcrumb /deep/ .el-breadcrumb__inner { | 
				
			|||
  color: #ccc !important; | 
				
			|||
} */ | 
				
			|||
/*  | 
				
			|||
.BoxTitle { | 
				
			|||
  font-size: 30px; | 
				
			|||
} */ | 
				
			|||
 | 
				
			|||
.activityDescDard { | 
				
			|||
  background-color: #F7F7F7; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.active { | 
				
			|||
  background: #36aaff; | 
				
			|||
  color: white; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.login-input { | 
				
			|||
  width: 55%; | 
				
			|||
  float: left; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
/* .el-input{*/ | 
				
			|||
 | 
				
			|||
/*}*/ | 
				
			|||
 | 
				
			|||
.captcha-code { | 
				
			|||
  cursor: pointer; | 
				
			|||
  vertical-align: middle; | 
				
			|||
  margin-left: 10px; | 
				
			|||
  border: solid 1px #E6E6E6; | 
				
			|||
  width: 120px; | 
				
			|||
  padding-left: 10px; | 
				
			|||
  padding-right: 10px; | 
				
			|||
  height: 40px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.verify-code-input { | 
				
			|||
  width: 60%; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.login-button { | 
				
			|||
  margin-bottom: 0; | 
				
			|||
  float: left; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.forget-tips-text { | 
				
			|||
  float: left; | 
				
			|||
  margin-left: 20px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.forget-tips-text a { | 
				
			|||
  color: #999; | 
				
			|||
  text-decoration: none; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.forget-tips-text a:hover { | 
				
			|||
  color: #A612FF; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,113 @@ | 
				
			|||
<template> | 
				
			|||
  <div class="hello"> | 
				
			|||
    <h1>{{ msg }}</h1> | 
				
			|||
    <h2>Essential Links</h2> | 
				
			|||
    <!-- <ul> | 
				
			|||
      <li> | 
				
			|||
        <a | 
				
			|||
          href="https://vuejs.org" | 
				
			|||
          target="_blank" | 
				
			|||
        > | 
				
			|||
          Core Docs | 
				
			|||
        </a> | 
				
			|||
      </li> | 
				
			|||
      <li> | 
				
			|||
        <a | 
				
			|||
          href="https://forum.vuejs.org" | 
				
			|||
          target="_blank" | 
				
			|||
        > | 
				
			|||
          Forum | 
				
			|||
        </a> | 
				
			|||
      </li> | 
				
			|||
      <li> | 
				
			|||
        <a | 
				
			|||
          href="https://chat.vuejs.org" | 
				
			|||
          target="_blank" | 
				
			|||
        > | 
				
			|||
          Community Chat | 
				
			|||
        </a> | 
				
			|||
      </li> | 
				
			|||
      <li> | 
				
			|||
        <a | 
				
			|||
          href="https://twitter.com/vuejs" | 
				
			|||
          target="_blank" | 
				
			|||
        > | 
				
			|||
          Twitter | 
				
			|||
        </a> | 
				
			|||
      </li> | 
				
			|||
      <br> | 
				
			|||
      <li> | 
				
			|||
        <a | 
				
			|||
          href="http://vuejs-templates.github.io/webpack/" | 
				
			|||
          target="_blank" | 
				
			|||
        > | 
				
			|||
          Docs for This Template | 
				
			|||
        </a> | 
				
			|||
      </li> | 
				
			|||
    </ul> | 
				
			|||
    <h2>Ecosystem</h2> | 
				
			|||
    <ul> | 
				
			|||
      <li> | 
				
			|||
        <a | 
				
			|||
          href="http://router.vuejs.org/" | 
				
			|||
          target="_blank" | 
				
			|||
        > | 
				
			|||
          vue-router | 
				
			|||
        </a> | 
				
			|||
      </li> | 
				
			|||
      <li> | 
				
			|||
        <a | 
				
			|||
          href="http://vuex.vuejs.org/" | 
				
			|||
          target="_blank" | 
				
			|||
        > | 
				
			|||
          vuex | 
				
			|||
        </a> | 
				
			|||
      </li> | 
				
			|||
      <li> | 
				
			|||
        <a | 
				
			|||
          href="http://vue-loader.vuejs.org/" | 
				
			|||
          target="_blank" | 
				
			|||
        > | 
				
			|||
          vue-loader | 
				
			|||
        </a> | 
				
			|||
      </li> | 
				
			|||
      <li> | 
				
			|||
        <a | 
				
			|||
          href="https://github.com/vuejs/awesome-vue" | 
				
			|||
          target="_blank" | 
				
			|||
        > | 
				
			|||
          awesome-vue | 
				
			|||
        </a> | 
				
			|||
      </li> | 
				
			|||
    </ul> --> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
export default { | 
				
			|||
  name: 'HelloWorld', | 
				
			|||
  data () { | 
				
			|||
    return { | 
				
			|||
      msg: 'Welcome to Your Vue.js App' | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<!-- Add "scoped" attribute to limit CSS to this component only --> | 
				
			|||
<style scoped> | 
				
			|||
h1, h2 { | 
				
			|||
  font-weight: normal; | 
				
			|||
} | 
				
			|||
ul { | 
				
			|||
  list-style-type: none; | 
				
			|||
  padding: 0; | 
				
			|||
} | 
				
			|||
li { | 
				
			|||
  display: inline-block; | 
				
			|||
  margin: 0 10px; | 
				
			|||
} | 
				
			|||
a { | 
				
			|||
  color: #42b983; | 
				
			|||
} | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,277 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <div class="header-box"> | 
				
			|||
      <div class="header-left-box"> | 
				
			|||
        <div class="header-logo">投票</div> | 
				
			|||
        <div class="header-right" v-if="curUser.userName" style="float: right"> | 
				
			|||
          <el-button type="primary" style="margin-top: 10px;margin-right: 50px" @click="userCenter">个人中心</el-button> | 
				
			|||
          <el-dropdown style="float: right" class="dropdown-link"> | 
				
			|||
            <span class="el-dropdown-link"> | 
				
			|||
              <img src="../img/defaultImg.png" style="border-radius: 100%;width: 45px"> | 
				
			|||
              <span>{{ curUser.userName }}</span> | 
				
			|||
            </span> | 
				
			|||
            <el-dropdown-menu slot="dropdown"> | 
				
			|||
              <el-dropdown-item @click.native="userInfo">账户信息</el-dropdown-item> | 
				
			|||
              <el-dropdown-item @click.native="logout">退出登录</el-dropdown-item> | 
				
			|||
            </el-dropdown-menu> | 
				
			|||
          </el-dropdown> | 
				
			|||
        </div> | 
				
			|||
        <div class="header-right" v-else> | 
				
			|||
          <a href="/login"> <el-button>登录 | 注册</el-button></a> | 
				
			|||
        </div> | 
				
			|||
      </div> | 
				
			|||
    </div> | 
				
			|||
    <!-- <el-row> | 
				
			|||
    <el-col :xs="{span:24,offset:0}" :sm="{span:18,offset:2}" :lg="{span:18,offset:3}"> | 
				
			|||
    <div class="test-back-img"> | 
				
			|||
      <div class="button-box"> | 
				
			|||
        <el-button type="warning" round class="create-vote-button" @click="createVote" style="margin-left: 50px">创建投票</el-button> | 
				
			|||
      </div> | 
				
			|||
    </div> | 
				
			|||
    </el-col> | 
				
			|||
  </el-row> --> | 
				
			|||
    <div class="vote-case-box"> | 
				
			|||
      <h3>投票案例</h3> | 
				
			|||
      <h5 style="color: #999">点击投票跳转投票页面</h5> | 
				
			|||
      <el-row> | 
				
			|||
        <el-col :xs="{ span: 24, offset: 0 }" :sm="{ span: 16, offset: 3 }" :lg="{ span: 16, offset: 3 }"> | 
				
			|||
          <div id="case-item-box"> | 
				
			|||
            <div v-for="(activities, index) in activitiesGroup" :key="index"> | 
				
			|||
              <el-row> | 
				
			|||
                <a :href="activityLink"> | 
				
			|||
                  <div v-for="(item, index) in activities" :key="index" @mouseenter="enter(index, item.id)" | 
				
			|||
                    @mouseleave="leave(index, item.id)"> | 
				
			|||
                    <el-col :xs="11" :sm="5" :offset="1"> | 
				
			|||
 | 
				
			|||
                      <el-card style="background-color: #F7F7F7;margin: 10px"> | 
				
			|||
 | 
				
			|||
                        <div class="qrcode" ref="qrCodeUrl" | 
				
			|||
                          :style="{ 'margin-left': (codeWidth == 100 ? '10px' : '32px') }" | 
				
			|||
                          v-show="showMap.get(item.id) === 'show'"></div> | 
				
			|||
                        <div v-show="showMap.get(item.id) === ''"> | 
				
			|||
                          <img src="../img/case.jpg" class="image" style="width: 100%"> | 
				
			|||
                        </div> | 
				
			|||
                        <div style="padding: 14px;color: #999; font-size: 12px;"> | 
				
			|||
                          <span>{{ item.title }}</span><br> | 
				
			|||
                        </div> | 
				
			|||
 | 
				
			|||
                      </el-card> | 
				
			|||
 | 
				
			|||
                    </el-col> | 
				
			|||
                  </div> | 
				
			|||
                </a> | 
				
			|||
              </el-row> | 
				
			|||
 | 
				
			|||
            </div> | 
				
			|||
            <!-- <div v-for="(item, index) in activitiesGroup" :key="index" @mouseenter="enter(index, item.id)" | 
				
			|||
              @mouseleave="leave(index, item.id)"> | 
				
			|||
              <div v-for="index in "> | 
				
			|||
                  <el-row v-if="index%4==0"></el-row> | 
				
			|||
                </div> | 
				
			|||
              <div > | 
				
			|||
                   | 
				
			|||
                    <a :href="activityLink"> | 
				
			|||
                  <el-col :xs="11" :sm="5" :offset="1"> | 
				
			|||
                    <el-card style="background-color: #F7F7F7;margin: 10px"> | 
				
			|||
                      <div class="qrcode" ref="qrCodeUrl" :style="{ 'margin-left': (codeWidth == 100 ? '10px' : '32px') }" | 
				
			|||
                        v-show="showMap.get(item.id) === 'show'"></div> | 
				
			|||
                      <div v-show="showMap.get(item.id) === ''"> | 
				
			|||
                        <img src="../img/case.jpg" class="image" style="width: 100%"> | 
				
			|||
                      </div> | 
				
			|||
                      <div style="padding: 14px;color: #999; font-size: 12px;"> | 
				
			|||
                        <span>{{ item.title }}</span><br> | 
				
			|||
                      </div> | 
				
			|||
                    </el-card> | 
				
			|||
                  </el-col> | 
				
			|||
                </a> | 
				
			|||
 | 
				
			|||
 | 
				
			|||
            </div> --> | 
				
			|||
            <!-- <div v-else> | 
				
			|||
                  <a :href="activityLink"> | 
				
			|||
                  <el-col :xs="11" :sm="5" :offset="1"> | 
				
			|||
                    <el-card style="background-color: #F7F7F7;margin: 10px"> | 
				
			|||
                      <div class="qrcode" ref="qrCodeUrl" :style="{ 'margin-left': (codeWidth == 100 ? '10px' : '32px') }" | 
				
			|||
                        v-show="showMap.get(item.id) === 'show'"></div> | 
				
			|||
                      <div v-show="showMap.get(item.id) === ''"> | 
				
			|||
                        <img src="../img/case.jpg" class="image" style="width: 100%"> | 
				
			|||
                      </div> | 
				
			|||
                      <div style="padding: 14px;color: #999; font-size: 12px;"> | 
				
			|||
                        <span>{{ item.title }}</span><br> | 
				
			|||
                      </div> | 
				
			|||
                    </el-card> | 
				
			|||
                  </el-col> | 
				
			|||
                </a> | 
				
			|||
                </div> --> | 
				
			|||
          </div> | 
				
			|||
        </el-col> | 
				
			|||
      </el-row> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
import QRCode from "qrcodejs2"; | 
				
			|||
 | 
				
			|||
export default { | 
				
			|||
  name: "Home", | 
				
			|||
  data() { | 
				
			|||
    return { | 
				
			|||
      drawer: false, | 
				
			|||
      startTime: '', | 
				
			|||
      currentPage: 1, | 
				
			|||
      pageSize: 8, | 
				
			|||
      totalSize: 0, | 
				
			|||
      codeWidth: 100, | 
				
			|||
      showIndex: null, | 
				
			|||
      activities: [], | 
				
			|||
      activitiesGroup: [], | 
				
			|||
      activitiesGroupNum: 4, | 
				
			|||
      userName: this.$store.state.user.userName, | 
				
			|||
      activityLink: '', | 
				
			|||
      showMap: new Map(), | 
				
			|||
      curUser: [], | 
				
			|||
    } | 
				
			|||
  }, | 
				
			|||
  mounted() { | 
				
			|||
    this.setDialogWidth() | 
				
			|||
    window.onresize = () => { | 
				
			|||
      return (() => { | 
				
			|||
        this.setDialogWidth() | 
				
			|||
      })() | 
				
			|||
    } | 
				
			|||
    this.listActivityCase() | 
				
			|||
    this.getCurUser() | 
				
			|||
  }, | 
				
			|||
  methods: { | 
				
			|||
    logout() { | 
				
			|||
      let _this = this | 
				
			|||
      this.$axios.get('/user/logout').then(resp => { | 
				
			|||
        if (resp.data.code === 200) { | 
				
			|||
          _this.$store.commit('logout') | 
				
			|||
          _this.$router.replace('/login') | 
				
			|||
        } | 
				
			|||
      }) | 
				
			|||
    }, | 
				
			|||
    getCurUser() { | 
				
			|||
      let _this = this | 
				
			|||
      this.$axios.get('/user?userName=' + this.$store.state.user.userName) | 
				
			|||
        .then(resp => { | 
				
			|||
          if (resp) { | 
				
			|||
            _this.curUser = resp.data | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
    }, | 
				
			|||
    userInfo() { | 
				
			|||
      this.$router.push('/admin/account/info') | 
				
			|||
    }, | 
				
			|||
    listActivityCase() { | 
				
			|||
      let _this = this; | 
				
			|||
      this.$axios.get('/activity/list/case?page=' + _this.currentPage + '&size=' + _this.pageSize).then(resp => { | 
				
			|||
        if (resp && resp.data.code === 200) { | 
				
			|||
          _this.activities = resp.data.result | 
				
			|||
          _this.totalSize = resp.data.result.length | 
				
			|||
          let tempArray = []; | 
				
			|||
          let tempArrayIndex = 0; | 
				
			|||
          let activitiesGroupIndex = 0; | 
				
			|||
          for (let i = 0; i < _this.activities.length; i++) { | 
				
			|||
            _this.showMap.set(_this.activities[i].id, '') | 
				
			|||
            // debugger; | 
				
			|||
            // 对activities数组进行分组,4个为一组。 | 
				
			|||
            tempArray[tempArrayIndex++] = _this.activities[i]; | 
				
			|||
            if (tempArrayIndex % _this.activitiesGroupNum == 0) { | 
				
			|||
              tempArrayIndex = 0; | 
				
			|||
              _this.activitiesGroup[activitiesGroupIndex] = [...tempArray]; | 
				
			|||
              activitiesGroupIndex++; | 
				
			|||
              tempArray = []; | 
				
			|||
            } | 
				
			|||
          } | 
				
			|||
          _this.activitiesGroup[activitiesGroupIndex] = [...tempArray]; | 
				
			|||
          console.log(_this.activities); | 
				
			|||
          console.log(_this.activitiesGroup); | 
				
			|||
        } | 
				
			|||
      }) | 
				
			|||
    }, | 
				
			|||
    leave(index, id) { | 
				
			|||
      this.$refs.qrCodeUrl[index] = '' | 
				
			|||
      this.showIndex = null | 
				
			|||
      this.showMap.set(id, '') | 
				
			|||
      this.$forceUpdate(); | 
				
			|||
    }, | 
				
			|||
    enter(index, id) { | 
				
			|||
      let _this = this | 
				
			|||
      this.showMap.set(id, 'show') | 
				
			|||
      this.$forceUpdate(); | 
				
			|||
      var qrBox; | 
				
			|||
      this.$nextTick(function () { | 
				
			|||
        qrBox = this.$refs.qrCodeUrl[index] | 
				
			|||
      }) | 
				
			|||
      this.activityLink = 'http://localhost:8080/activityIndex/' + id | 
				
			|||
      this.$nextTick(function () { | 
				
			|||
        let qrcode = new QRCode(qrBox, { | 
				
			|||
          text: this.activityLink, // 需要转换为二维码的内容 | 
				
			|||
          width: _this.codeWidth, | 
				
			|||
          height: _this.codeWidth, | 
				
			|||
          colorDark: '#000000', | 
				
			|||
          colorLight: '#ffffff', | 
				
			|||
          correctLevel: QRCode.CorrectLevel.H | 
				
			|||
        }) | 
				
			|||
      }) | 
				
			|||
    }, | 
				
			|||
    createVote() { | 
				
			|||
      if (this.curUser.userName) { | 
				
			|||
        this.$router.push('/admin/vote/add/index') | 
				
			|||
      } else { | 
				
			|||
        this.$router.push('/login') | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    userCenter() { | 
				
			|||
      this.$router.push('/admin/vote/list') | 
				
			|||
    }, | 
				
			|||
    setDialogWidth() { | 
				
			|||
      let val = document.body.clientWidth | 
				
			|||
      const def = 1570 // 默认宽度 | 
				
			|||
      if (val < def) { | 
				
			|||
        this.codeWidth = 100 | 
				
			|||
      } else { | 
				
			|||
        this.codeWidth = 120 | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
.test-back-img { | 
				
			|||
 | 
				
			|||
  max-width: 1100px; | 
				
			|||
  height: 480px; | 
				
			|||
  margin: 0 auto; | 
				
			|||
  margin-top: 20px; | 
				
			|||
  background-image: url("../img/vote.jpg"); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.button-box { | 
				
			|||
  padding-top: 420px; | 
				
			|||
  margin-right: 60px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.header-box { | 
				
			|||
  padding-bottom: 50px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.header-logo { | 
				
			|||
  width: 10%; | 
				
			|||
  float: left; | 
				
			|||
  margin-left: 100px; | 
				
			|||
  color: #36aaff; | 
				
			|||
  font-size: 20px; | 
				
			|||
  font-weight: 600; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.header-right { | 
				
			|||
  float: right; | 
				
			|||
  margin-right: 150px; | 
				
			|||
} | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,20 @@ | 
				
			|||
<template> | 
				
			|||
    <div> | 
				
			|||
 | 
				
			|||
      <TopNav></TopNav> | 
				
			|||
      <h1>this is index page</h1> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
    import TopNav from "./common/TopNav"; | 
				
			|||
    export default { | 
				
			|||
      name: "Index", | 
				
			|||
      components: {TopNav}, | 
				
			|||
    } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
 | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,48 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <el-row> | 
				
			|||
      <el-col :xs="{span:24,offset:0}" :sm="{span:16,offset:4}" :lg="{span:16,offset:4}"> | 
				
			|||
        <el-card> | 
				
			|||
          <div style="text-align: center"> | 
				
			|||
            <h3>{{curNotice.title}}</h3> | 
				
			|||
            <div style="color: #999" > | 
				
			|||
              {{curNotice.createTime | fmtDate}} | 
				
			|||
            </div> | 
				
			|||
            <div style="text-align: left"> <p v-html="curNotice.content"></p></div> | 
				
			|||
          </div> | 
				
			|||
 | 
				
			|||
        </el-card> | 
				
			|||
      </el-col> | 
				
			|||
 | 
				
			|||
    </el-row> | 
				
			|||
  </div> | 
				
			|||
 | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
    export default { | 
				
			|||
      name: "NoticeIndex", | 
				
			|||
      data(){ | 
				
			|||
        return{ | 
				
			|||
          curNotice:[] | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      mounted() { | 
				
			|||
        this.getCurNotice() | 
				
			|||
      }, | 
				
			|||
      methods:{ | 
				
			|||
        getCurNotice(){ | 
				
			|||
          let _this = this | 
				
			|||
          this.$axios.get('/notice/'+this.$route.params.id).then(resp =>{ | 
				
			|||
            if(resp && resp.data.code === 200){ | 
				
			|||
              _this.curNotice = resp.data.result | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
        }, | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
 | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,58 @@ | 
				
			|||
<template> | 
				
			|||
 | 
				
			|||
  <el-container> | 
				
			|||
    <el-header id="header-box"> | 
				
			|||
      <top-header></top-header> | 
				
			|||
    </el-header> | 
				
			|||
    <el-container> | 
				
			|||
      <el-aside id="left-menu-list-box" width="200px"> | 
				
			|||
        <admin-menu></admin-menu> | 
				
			|||
      </el-aside> | 
				
			|||
      <el-main> | 
				
			|||
        <router-view/> | 
				
			|||
      </el-main> | 
				
			|||
    </el-container> | 
				
			|||
  </el-container> | 
				
			|||
 | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  import AdminMenu from './AdminMenu' | 
				
			|||
  import TopHeader from "./TopHeader"; | 
				
			|||
 | 
				
			|||
  export default { | 
				
			|||
    name: 'AdminIndex', | 
				
			|||
    components: {TopHeader, AdminMenu}, | 
				
			|||
    data () { | 
				
			|||
      return { | 
				
			|||
        dialogVisible: false | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    // 动态设置侧边栏高度 | 
				
			|||
    mounted() { | 
				
			|||
      let leftMenuBox = document.getElementById('left-menu-list-box'); | 
				
			|||
      let headerBox = document.getElementById('header-box'); | 
				
			|||
      let dy = window.innerHeight - headerBox.offsetHeight; | 
				
			|||
      if( leftMenuBox && headerBox){ | 
				
			|||
        leftMenuBox.style.height = dy + 'px'; | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
 | 
				
			|||
  #left-menu-list-box .el-menu{ | 
				
			|||
    border-right: none; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .el-header{ | 
				
			|||
    line-height: 46px; | 
				
			|||
    height: 46px !important; | 
				
			|||
    border-bottom: 1px solid #e6e6e6; | 
				
			|||
  } | 
				
			|||
  .el-aside{ | 
				
			|||
    /* border-right: solid 1px #e6e6e6; */ | 
				
			|||
    line-height: 100px; | 
				
			|||
  } | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,65 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <el-radio-group v-model="isCollapse" style="margin-bottom: 20px;"> | 
				
			|||
      <el-radio-button :label="false">展开</el-radio-button> | 
				
			|||
      <el-radio-button :label="true">收起</el-radio-button> | 
				
			|||
    </el-radio-group> | 
				
			|||
 | 
				
			|||
    <el-menu :default-active="currentPath" class="el-menu-admin" router mode="vertical" @open="handleOpen" @close="handleClose" :collapse="isCollapse"> | 
				
			|||
      <!--index 没有用但是必需字段--> | 
				
			|||
 | 
				
			|||
      <el-submenu v-for="(item, i) in adminMenus" :key="i" :index="(i).toString()" style="text-align: left"> | 
				
			|||
        <template slot="title"> | 
				
			|||
          <i :class="item.iconCls"></i> | 
				
			|||
        </template> | 
				
			|||
        <span slot="title" style="font-size: 17px;"> | 
				
			|||
          <!-- <i :class="item.iconCls"></i> --> | 
				
			|||
          {{ item.nameZh }} | 
				
			|||
        </span> | 
				
			|||
        <el-menu-item v-for="child in item.children" :key="child.path" :index="child.path"> | 
				
			|||
          <i :class="child.icon"></i> | 
				
			|||
          {{ child.nameZh }} | 
				
			|||
        </el-menu-item> | 
				
			|||
      </el-submenu> | 
				
			|||
 | 
				
			|||
    </el-menu> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
export default { | 
				
			|||
  name: 'AdminMenu', | 
				
			|||
  data() { | 
				
			|||
    return { | 
				
			|||
      isCollapse: false | 
				
			|||
    }; | 
				
			|||
  }, | 
				
			|||
  methods: { | 
				
			|||
      handleOpen(key, keyPath) { | 
				
			|||
        console.log(key, keyPath); | 
				
			|||
      }, | 
				
			|||
      handleClose(key, keyPath) { | 
				
			|||
        console.log(key, keyPath); | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
  computed: { | 
				
			|||
    adminMenus() { | 
				
			|||
      return this.$store.state.adminMenus | 
				
			|||
    }, | 
				
			|||
    currentPath() { | 
				
			|||
      return this.$route.path | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
.el-menu-admin:not(.el-menu--collapse) { | 
				
			|||
    width: 200px; | 
				
			|||
    min-height: 200px; | 
				
			|||
  } | 
				
			|||
.el-menu-admin { | 
				
			|||
  border-radius: 5px; | 
				
			|||
  height: 100%; | 
				
			|||
} | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,65 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <div class="header-left-box"> | 
				
			|||
      <div class="header-logo" @click="toHome">投票</div> | 
				
			|||
      <div class="header-right"   v-if="userName"> | 
				
			|||
        <el-dropdown style="float: right" class="dropdown-link"> | 
				
			|||
        <span class="el-dropdown-link" > | 
				
			|||
       <img src="../../img/defaultImg.png" style="border-radius: 100%;width: 45px"> | 
				
			|||
        <span>{{userName}}</span> | 
				
			|||
        </span> | 
				
			|||
          <el-dropdown-menu slot="dropdown"> | 
				
			|||
            <el-dropdown-item @click.native="userInfo">账户信息</el-dropdown-item> | 
				
			|||
            <el-dropdown-item @click.native="logout">退出登录</el-dropdown-item> | 
				
			|||
          </el-dropdown-menu> | 
				
			|||
        </el-dropdown> | 
				
			|||
      </div> | 
				
			|||
      <div v-else> | 
				
			|||
        <a href="Login"> <el-button>登录</el-button></a> | 
				
			|||
        <a href="Register"> <el-button>注册</el-button></a> | 
				
			|||
      </div> | 
				
			|||
    </div> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
    export default { | 
				
			|||
      name: "TopHeader", | 
				
			|||
      data(){ | 
				
			|||
        return{ | 
				
			|||
          userName:this.$store.state.user.userName, | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      methods:{ | 
				
			|||
        logout () { | 
				
			|||
          let _this = this | 
				
			|||
          this.$axios.get('/user/logout').then(resp => { | 
				
			|||
            if (resp.data.code === 200) { | 
				
			|||
              _this.$store.commit('logout') | 
				
			|||
              _this.$router.replace('/login') | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
        }, | 
				
			|||
        userInfo(){ | 
				
			|||
          this.$router.push('/admin/account/info') | 
				
			|||
        }, | 
				
			|||
        toHome(){ | 
				
			|||
          this.$router.push('/home') | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
  .header-logo{ | 
				
			|||
    float: left; | 
				
			|||
    margin-left: 100px; | 
				
			|||
    color: #36aaff; | 
				
			|||
    font-size: 20px; | 
				
			|||
    font-weight: 600; | 
				
			|||
  } | 
				
			|||
  .header-right{ | 
				
			|||
    float: right; | 
				
			|||
    margin-right: 150px; | 
				
			|||
  } | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,198 @@ | 
				
			|||
<!-- 用户信息 | 
				
			|||
     --> | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <div class="center login-center-box"> | 
				
			|||
      <el-dialog | 
				
			|||
        title="修改邮箱" | 
				
			|||
        :visible.sync="dialogForEmail" | 
				
			|||
        :modal-append-to-body="false" | 
				
			|||
        @close="clear" | 
				
			|||
        :width="dialogWidth"> | 
				
			|||
        <el-row :gutter="20"> | 
				
			|||
          <el-form label-position="right" label-width="100px"> | 
				
			|||
            <el-form-item label="邮箱地址" required> | 
				
			|||
              <el-input v-model="email" placeholder="请输入邮箱"></el-input> | 
				
			|||
              <el-button v-if="!isCountDowning" type="primary" class="login-button" style="margin-left: 20px"  @click="getVerifyCode"> | 
				
			|||
                获取验证码 | 
				
			|||
              </el-button> | 
				
			|||
              <el-button v-else type="primary" class="login-button" style="margin-left: 20px" @click.prevent="getVerifyCode" disabled> | 
				
			|||
                {{countDownText}} | 
				
			|||
              </el-button> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item label="邮箱验证码" required> | 
				
			|||
              <el-input v-model="emailCode" placeholder="请输入邮箱验证码"></el-input> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item> | 
				
			|||
              <el-button type="primary" class="login-button" @click="updateEmail" > 修改邮箱 </el-button> | 
				
			|||
            </el-form-item> | 
				
			|||
          </el-form> | 
				
			|||
        </el-row> | 
				
			|||
      </el-dialog> | 
				
			|||
 | 
				
			|||
      <el-row :gutter="20"> | 
				
			|||
        <el-col :span="10"> | 
				
			|||
          <el-form label-position="right" label-width="100px"> | 
				
			|||
            <el-form-item> | 
				
			|||
              <img :src="curUser.avatar" @click="updateAvatar" class="user-avatar"> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item label="用户名" > | 
				
			|||
              <label class="info-label">{{curUser.userName}}</label> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item label="邮箱" > | 
				
			|||
              <label class="info-label">{{curUser.email}}</label> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item label="操作"> | 
				
			|||
              <el-button type="primary"  class="login-button" @click="updatePassword"> 修改密码 </el-button> | 
				
			|||
              <el-button type="success"  class="login-button" @click="toUpdateEmail"> 修改邮箱 </el-button> | 
				
			|||
            </el-form-item> | 
				
			|||
          </el-form> | 
				
			|||
        </el-col> | 
				
			|||
      </el-row> | 
				
			|||
    </div> | 
				
			|||
    <div class="user-info-dialog"> | 
				
			|||
<!--      <avatar-upload field="img"--> | 
				
			|||
<!--                 @crop-success="cropSuccess"--> | 
				
			|||
<!--                 @crop-upload-success="cropUploadSuccess"--> | 
				
			|||
<!--                 @crop-upload-fail="cropUploadFail"--> | 
				
			|||
<!--                 v-model="show"--> | 
				
			|||
<!--                 :width="300"--> | 
				
			|||
<!--                 :height="300"--> | 
				
			|||
<!--                 url="/upload"--> | 
				
			|||
<!--                 :params="params"--> | 
				
			|||
<!--                 :headers="headers"--> | 
				
			|||
<!--                 img-format="png"></avatar-upload>--> | 
				
			|||
    </div> | 
				
			|||
  </div> | 
				
			|||
 | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
    export default { | 
				
			|||
      name: "UserInfo", | 
				
			|||
      data(){ | 
				
			|||
        return{ | 
				
			|||
          dialogForEmail:false, | 
				
			|||
          dialogWidth:'500px', | 
				
			|||
          email:'', | 
				
			|||
          emailCode:'', | 
				
			|||
          isUserNameOkay:'', | 
				
			|||
          isCountDowning:false, | 
				
			|||
          countDownText:'重新发送(60)', | 
				
			|||
          user:{ | 
				
			|||
            userName:'', | 
				
			|||
            password:'' | 
				
			|||
          }, | 
				
			|||
          verifyCode:'', | 
				
			|||
          captchaPath:'', | 
				
			|||
          captcha_key:'', | 
				
			|||
          curUser:[], | 
				
			|||
 | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      mounted() { | 
				
			|||
        this.getCurUser() | 
				
			|||
      }, | 
				
			|||
      methods:{ | 
				
			|||
        getCurUser(){ | 
				
			|||
          let _this = this | 
				
			|||
          this.$axios.get('/user?userName='+this.$store.state.user.userName).then(resp =>{ | 
				
			|||
            if(resp){ | 
				
			|||
              _this.curUser = resp.data | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
        }, | 
				
			|||
        getVerifyCode(){ | 
				
			|||
          let _this = this | 
				
			|||
          if(this.email === ''){ | 
				
			|||
            this.$message.error("请输入邮箱地址"); | 
				
			|||
            return; | 
				
			|||
          } | 
				
			|||
          let reg = /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/ | 
				
			|||
          if (!reg.test(this.email)) { | 
				
			|||
            this.$message.error("邮箱格式不正确"); | 
				
			|||
            return; | 
				
			|||
          } | 
				
			|||
          this.$axios | 
				
			|||
            .get('/user/verify_code?email='+_this.email+'&type=update').then(resp =>{ | 
				
			|||
            if (resp.data.code === 200) { | 
				
			|||
              _this.startCountDown(); | 
				
			|||
            }else { | 
				
			|||
              this.$message.error(resp.data.message); | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
        }, | 
				
			|||
        startCountDown(){ | 
				
			|||
          let _this = this; | 
				
			|||
          let time = 60; | 
				
			|||
          this.isCountDowning = true; | 
				
			|||
          let interval = setInterval(function () { | 
				
			|||
            //执行倒计时 | 
				
			|||
            time--; | 
				
			|||
            if(time <= 0){ | 
				
			|||
              _this.isCountDowning = false; | 
				
			|||
              clearInterval(interval); | 
				
			|||
            } | 
				
			|||
            _this.countDownText = '重新发送('+ time + ')'; | 
				
			|||
          },1000) | 
				
			|||
        }, | 
				
			|||
        clear(){ | 
				
			|||
          this.dialogForEmail = false | 
				
			|||
        }, | 
				
			|||
        updateAvatar(){ | 
				
			|||
 | 
				
			|||
        }, | 
				
			|||
        updatePassword(){ | 
				
			|||
          this.$router.replace('/login/forget') | 
				
			|||
        }, | 
				
			|||
        updateEmail(){ | 
				
			|||
          let _this = this | 
				
			|||
          this.$axios.put('/user/email?email='+_this.email+'&verify_code='+_this.emailCode,{ | 
				
			|||
            id:_this.curUser.id, | 
				
			|||
            userName: _this.curUser.userName | 
				
			|||
          }).then(resp =>{ | 
				
			|||
            if(resp && resp.data.code === 200){ | 
				
			|||
              this.$message.success("修改成功") | 
				
			|||
              this.dialogForEmail = false | 
				
			|||
              this.email = '' | 
				
			|||
              this.emailCode = '' | 
				
			|||
 | 
				
			|||
              this.getCurUser() | 
				
			|||
            }else { | 
				
			|||
              let message = resp.data.message | 
				
			|||
              this.$message.error(message) | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
        }, | 
				
			|||
        toUpdateEmail(){ | 
				
			|||
          this.dialogForEmail = true | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
 | 
				
			|||
  .login-center-box .el-input{ | 
				
			|||
    width: 40%; | 
				
			|||
    float: left; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .login-button{ | 
				
			|||
    margin-left: 20px; | 
				
			|||
    margin-bottom: 0; | 
				
			|||
    float: left; | 
				
			|||
  } | 
				
			|||
  .info-label{ | 
				
			|||
    margin-left: 20px; | 
				
			|||
    margin-bottom: 0; | 
				
			|||
    float: left; | 
				
			|||
  } | 
				
			|||
.user-avatar{ | 
				
			|||
  float: left; | 
				
			|||
  margin-left: 30px; | 
				
			|||
  width: 80px; | 
				
			|||
  height: 80px; | 
				
			|||
  border-radius: 50px; | 
				
			|||
} | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,285 @@ | 
				
			|||
<template> | 
				
			|||
 | 
				
			|||
  <div class="setItemsDiv"> | 
				
			|||
    <el-dialog | 
				
			|||
      title="活动链接" | 
				
			|||
      :visible.sync="dialogFormVisible" | 
				
			|||
      :modal-append-to-body="false" | 
				
			|||
      @close="clear" | 
				
			|||
      :width="dialogWidth"> | 
				
			|||
      <div class="qrcode" ref="qrCodeUrl" style="margin:50px auto;padding-left: 165px"></div> | 
				
			|||
      <div style="color: #36AAFF;"> | 
				
			|||
        <a :href="activityLink" >{{activityLink}}</a> | 
				
			|||
      </div> | 
				
			|||
    </el-dialog> | 
				
			|||
    <el-row> | 
				
			|||
      <el-col :sm="1"  :xl="2"> </el-col> | 
				
			|||
      <el-col :sm="22"  :xs="24"> | 
				
			|||
        <el-card> | 
				
			|||
          <div> | 
				
			|||
            <div style="float: left"> | 
				
			|||
              活动管理 | 
				
			|||
            </div> | 
				
			|||
            <div style="float: right"> | 
				
			|||
              <el-button type="primary" @click="toCreate">创建投票</el-button> | 
				
			|||
            </div> | 
				
			|||
          </div> | 
				
			|||
          <div style="text-align: left"> | 
				
			|||
            <el-table | 
				
			|||
              v-loading="loading" | 
				
			|||
              :data="activities" | 
				
			|||
              stripe | 
				
			|||
              :default-sort = "{prop: 'id', order: 'ascending'}" | 
				
			|||
              style="width: 100%" | 
				
			|||
              ref="multipleTable" | 
				
			|||
              show-overflow-tooltip> | 
				
			|||
              <el-table-column | 
				
			|||
                prop="title" | 
				
			|||
                label="标题" | 
				
			|||
                width="150"> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                prop="author" | 
				
			|||
                label="用户" | 
				
			|||
                fit> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="状态" | 
				
			|||
                fit> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <el-tag type="info"  size="small" v-if="date.getTime() < Date.parse(scope.row.startTime)">未开始</el-tag> | 
				
			|||
                  <el-tag type="danger"  size="small" v-else-if="new Date().getTime() > Date.parse(scope.row.endTime)">已结束</el-tag> | 
				
			|||
                  <el-tag type="success" size="small" v-else>进行中</el-tag> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="活动时间" | 
				
			|||
                width="150"> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <div style="color: #999;">{{scope.row.startTime | fmtDate}}</div> | 
				
			|||
                  <div style="color: #999;">{{scope.row.endTime | fmtDate}}</div> | 
				
			|||
                  <div style="color: #999;"></div> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="属性" | 
				
			|||
                fit> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <el-button type="primary"  size="small" v-if="scope.row.state === '1'">正常</el-button> | 
				
			|||
                  <el-button type="danger"  size="small" v-else-if="scope.row.state === '0'">禁止</el-button> | 
				
			|||
                  <el-button type="info" size="small" v-else>案例</el-button> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="修改属性" | 
				
			|||
                width="120"> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <el-dropdown trigger="click" > | 
				
			|||
                    <span class="el-dropdown-link"> | 
				
			|||
                      <el-button | 
				
			|||
                        plain | 
				
			|||
                        size="small"> | 
				
			|||
                         修改属性<i class=" el-icon-arrow-down"></i> | 
				
			|||
                      </el-button> | 
				
			|||
                    </span> | 
				
			|||
                    <el-dropdown-menu slot="dropdown"> | 
				
			|||
                      <el-dropdown-item @click.native="updateState(scope.row,'1')" > | 
				
			|||
                         正 常 | 
				
			|||
                      </el-dropdown-item> | 
				
			|||
                      <el-dropdown-item @click.native="updateState(scope.row,'0')"> | 
				
			|||
                         禁 止 | 
				
			|||
                      </el-dropdown-item> | 
				
			|||
                      <el-dropdown-item @click.native="updateState(scope.row,'2')"> | 
				
			|||
                         案 例 | 
				
			|||
                      </el-dropdown-item> | 
				
			|||
                    </el-dropdown-menu> | 
				
			|||
                  </el-dropdown> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="操作" | 
				
			|||
                width="300"> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <el-button size="mini" type="danger"  @click="toDelVoteResult(scope.row)">删除</el-button> | 
				
			|||
                  <el-button size="mini" type="success"  @click="toVoteResult(scope.row)">统计</el-button> | 
				
			|||
                  <el-button size="mini" type="warning" @click="showQrCode(scope.row)">二维码</el-button> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
            </el-table> | 
				
			|||
            <div style="float: left;padding: 15px"> | 
				
			|||
              <el-pagination | 
				
			|||
                @current-change="handleCurrentChange" | 
				
			|||
                :current-page="currentPage" | 
				
			|||
                :page-size="pageSize" | 
				
			|||
                :total="totalSize"> | 
				
			|||
              </el-pagination> | 
				
			|||
            </div> | 
				
			|||
          </div> | 
				
			|||
        </el-card> | 
				
			|||
 | 
				
			|||
      </el-col> | 
				
			|||
 | 
				
			|||
    </el-row> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  import QRCode from 'qrcodejs2'; | 
				
			|||
  export default { | 
				
			|||
    name: 'ActivityManagement', | 
				
			|||
    data(){ | 
				
			|||
      return{ | 
				
			|||
        loading: false, | 
				
			|||
        dialogWidth:'500px', | 
				
			|||
        currentPage:1, | 
				
			|||
        pageSize:6, | 
				
			|||
        totalSize:0, | 
				
			|||
        activities:[], | 
				
			|||
        selectedActivity:[], | 
				
			|||
        voteItems:[], | 
				
			|||
        date: new Date(), | 
				
			|||
        date_1:'', | 
				
			|||
        dialogFormVisible:false, | 
				
			|||
        activityLink:'', | 
				
			|||
        cur_date : this.$options.filters.fmtDate(new Date()) | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    mounted() { | 
				
			|||
      window.onresize = () => { | 
				
			|||
        return (() => { | 
				
			|||
          this.setDialogWidth() | 
				
			|||
        })() | 
				
			|||
      } | 
				
			|||
      this.listActivity() | 
				
			|||
    }, | 
				
			|||
    methods:{ | 
				
			|||
      listActivity(){ | 
				
			|||
        let _this = this | 
				
			|||
        this.loading = true | 
				
			|||
        this.$axios.get('/admin/activity/list?page='+_this.currentPage | 
				
			|||
          +'&size='+_this.pageSize | 
				
			|||
          +'&userName='+ _this.$store.state.user.userName) | 
				
			|||
          .then(resp =>{ | 
				
			|||
            if(resp && resp.data.code === 200){ | 
				
			|||
              console.dir(resp); | 
				
			|||
              _this.activities = resp.data.result.content | 
				
			|||
              _this.totalSize = resp.data.result.totalElements | 
				
			|||
              //mybatis | 
				
			|||
              // _this.activities = resp.data.result.activity; | 
				
			|||
              // _this.totalSize = resp.data.result.total; | 
				
			|||
              _this.loading = false | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
      }, | 
				
			|||
      toCreate(){ | 
				
			|||
        this.$store.state.curCreateActivity = [] | 
				
			|||
        this.$router.replace('/admin/vote/add/index') | 
				
			|||
      }, | 
				
			|||
      toDelVoteResult(activity){ | 
				
			|||
        let _this = this | 
				
			|||
        this.loading = true | 
				
			|||
        console.log(activity.id); | 
				
			|||
        // debugger | 
				
			|||
        this.$axios.get('/admin/activity/list/del?activityId='+activity.id    | 
				
			|||
          ).then(resp =>{ | 
				
			|||
            if(resp && resp.data.code === 200){ | 
				
			|||
              // console.log(resp) | 
				
			|||
              if(1 == resp.data.result){ | 
				
			|||
                this.listActivity() | 
				
			|||
                // 成功 | 
				
			|||
 | 
				
			|||
              }else{ | 
				
			|||
                // 失败 | 
				
			|||
 | 
				
			|||
              }  | 
				
			|||
              _this.loading = false | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
      }, | 
				
			|||
      //   this.$confirm('此操作将删除该, 是否继续?', '提示', { | 
				
			|||
      //     confirmButtonText: '确定', | 
				
			|||
      //     cancelButtonText: '取消', | 
				
			|||
      //     type: 'warning' | 
				
			|||
      //   }).then(() => { | 
				
			|||
      //     this.$message({ | 
				
			|||
      //       type: 'success', | 
				
			|||
      //       message: '删除成功!' | 
				
			|||
      //     }); | 
				
			|||
      //   }).catch(() => { | 
				
			|||
      //     this.$message({ | 
				
			|||
      //       type: 'info', | 
				
			|||
      //       message: '已取消删除' | 
				
			|||
      //     });           | 
				
			|||
      //   }); | 
				
			|||
      // }, | 
				
			|||
      toVoteResult(activity){ | 
				
			|||
        this.$store.commit('createActive', activity) | 
				
			|||
        this.$router.replace('/admin/vote/list/result') | 
				
			|||
      }, | 
				
			|||
      showQrCode(activity){ | 
				
			|||
        this.dialogFormVisible = true | 
				
			|||
        this.activityLink = 'http://localhost:8080/activityIndex/'+activity.id | 
				
			|||
        this.$nextTick(function () { | 
				
			|||
          this.creatQrCode() | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      creatQrCode() { | 
				
			|||
        let qrcode = new QRCode(this.$refs.qrCodeUrl, { | 
				
			|||
          text: this.activityLink, // 需要转换为二维码的内容 | 
				
			|||
          width: 120, | 
				
			|||
          height: 120, | 
				
			|||
          colorDark: '#000000', | 
				
			|||
          colorLight: '#ffffff', | 
				
			|||
          correctLevel: QRCode.CorrectLevel.H | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      clear(){ | 
				
			|||
        this.dialogFormVisible = false | 
				
			|||
        this.$refs.qrCodeUrl = '' | 
				
			|||
      }, | 
				
			|||
 | 
				
			|||
      handleCurrentChange(currentPage) { | 
				
			|||
        this.currentPage = currentPage | 
				
			|||
        this.listActivity() | 
				
			|||
      }, | 
				
			|||
      setDialogWidth() { | 
				
			|||
        let val = document.body.clientWidth | 
				
			|||
        const def = 500 // 默认宽度 | 
				
			|||
        if (val < def) { | 
				
			|||
          this.dialogWidth = '100%' | 
				
			|||
        } else { | 
				
			|||
          this.dialogWidth = def + 'px' | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      updateState(activity,state){ | 
				
			|||
        this.$confirm('确定更改属性?', '提示', { | 
				
			|||
          confirmButtonText: '确定', | 
				
			|||
          cancelButtonText: '取消', | 
				
			|||
          type: 'warning' | 
				
			|||
        }).then(() => { | 
				
			|||
          this.$axios.put('/admin/activity/'+activity.id,{ | 
				
			|||
            author: activity.author, | 
				
			|||
            content: activity.content, | 
				
			|||
            createTime: activity.createTime, | 
				
			|||
            signIn: activity.signIn, | 
				
			|||
            startTime: activity.startTime, | 
				
			|||
            endTime:activity.endTime, | 
				
			|||
            state: state, | 
				
			|||
            title: activity.title, | 
				
			|||
            type: activity.type, | 
				
			|||
            verifyCode: activity.verifyCode, | 
				
			|||
          }).then(resp =>{ | 
				
			|||
            if(resp && resp.data.code === 200){ | 
				
			|||
              this.$message.success("更新属性成功") | 
				
			|||
              this.listActivity() | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
        }).catch(() => { | 
				
			|||
        }) | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style> | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,94 @@ | 
				
			|||
<!-- <template> | 
				
			|||
  <div class="setItemsDiv"> | 
				
			|||
    <el-row> | 
				
			|||
      <el-col  :sm="2" :xl="4"> </el-col> | 
				
			|||
      <el-col  :sm="16"  :xs="24"> | 
				
			|||
        <el-card> | 
				
			|||
          <div style="text-align: left"> | 
				
			|||
            <el-form> | 
				
			|||
              <el-form-item> | 
				
			|||
                <span style="font-size: 16px;font-weight: bold">公告标题</span> | 
				
			|||
                <el-input v-model="title"></el-input> | 
				
			|||
              </el-form-item> | 
				
			|||
              <el-form-item> | 
				
			|||
                <span style="font-size: 16px;font-weight: bold">公告内容</span> | 
				
			|||
                <Qeditor ref="qeditor"></Qeditor> | 
				
			|||
              </el-form-item> | 
				
			|||
            </el-form> | 
				
			|||
          </div> | 
				
			|||
 | 
				
			|||
          <div style="padding-top: 50px;margin-top: 20px"> | 
				
			|||
            <el-button type="primary" @click="saveActivity"> 发 布 </el-button> | 
				
			|||
          </div> | 
				
			|||
        </el-card> | 
				
			|||
      </el-col> | 
				
			|||
 | 
				
			|||
    </el-row> | 
				
			|||
  </div> | 
				
			|||
 | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  import Qeditor from "../../common/Qeditor"; | 
				
			|||
  export default { | 
				
			|||
    name: "CaseManagement", | 
				
			|||
    components: {Qeditor}, | 
				
			|||
    data(){ | 
				
			|||
      return{ | 
				
			|||
        title:'', | 
				
			|||
        content:'', | 
				
			|||
        curUser:[] | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    mounted() { | 
				
			|||
      this.getCurUser() | 
				
			|||
    }, | 
				
			|||
    methods:{ | 
				
			|||
      saveActivity() { | 
				
			|||
        if(this.title === ''){ | 
				
			|||
          this.$message.error("标题不能为空"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        if(this.$refs.qeditor.content === ''){ | 
				
			|||
          this.$message.error("公告内容不能为空"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        this.$axios.post('/admin/notice', { | 
				
			|||
          title: this.title, | 
				
			|||
          content:this.$refs.qeditor.content, | 
				
			|||
          uid:this.curUser.id, | 
				
			|||
        }).then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            this.$message.success("公告添加成功") | 
				
			|||
            this.$router.replace('/admin/content/notice') | 
				
			|||
          } | 
				
			|||
        }).catch(() => { | 
				
			|||
          this.$message({ | 
				
			|||
            type: 'info', | 
				
			|||
            message: '已取消创建' | 
				
			|||
          }) | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      getCurUser(){ | 
				
			|||
        let _this = this | 
				
			|||
        this.$axios.get('/user?userName='+this.$store.state.user.userName).then(resp =>{ | 
				
			|||
          if(resp){ | 
				
			|||
            _this.curUser = resp.data | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      } | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
  .setItemsDiv{ | 
				
			|||
    margin: 0px auto; | 
				
			|||
    height: 100%; | 
				
			|||
    width: 100%; | 
				
			|||
 | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
</style> --> | 
				
			|||
@ -0,0 +1,152 @@ | 
				
			|||
<!-- <template> | 
				
			|||
 | 
				
			|||
  <div class="setItemsDiv"> | 
				
			|||
    <el-row> | 
				
			|||
      <el-col :sm="1"  :xl="2"> </el-col> | 
				
			|||
      <el-col :sm="20"  :xs="24"> | 
				
			|||
        <el-card> | 
				
			|||
          <div> | 
				
			|||
            <div style="float: left"> | 
				
			|||
              公告管理 | 
				
			|||
            </div> | 
				
			|||
            <div style="float: right"> | 
				
			|||
              <el-button type="primary" @click="toCreate">创建公告</el-button> | 
				
			|||
            </div> | 
				
			|||
          </div> | 
				
			|||
          <div style="text-align: left"> | 
				
			|||
            <el-table | 
				
			|||
              v-loading="loading" | 
				
			|||
              :data="notices" | 
				
			|||
              stripe | 
				
			|||
              :default-sort = "{prop: 'id', order: 'ascending'}" | 
				
			|||
              style="width: 100%" | 
				
			|||
              ref="multipleTable" | 
				
			|||
              show-overflow-tooltip> | 
				
			|||
              <el-table-column | 
				
			|||
                prop="title" | 
				
			|||
                label="标题" | 
				
			|||
                fit> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="创建时间" | 
				
			|||
                fit> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <div style="color: #999;">{{scope.row.createTime | fmtDate}}</div> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="操作" | 
				
			|||
                width="200"> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <el-button size="mini" type="primary"  @click="showNotice(scope.row.id)">查看</el-button> | 
				
			|||
                  <el-button size="mini" type="danger"  @click="deleteNotice(scope.row)">删除</el-button> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
            </el-table> | 
				
			|||
            <div style="float: left;padding: 15px"> | 
				
			|||
              <el-pagination | 
				
			|||
                @current-change="handleCurrentChange" | 
				
			|||
                :current-page="currentPage" | 
				
			|||
                :page-size="pageSize" | 
				
			|||
                :total="totalSize"> | 
				
			|||
              </el-pagination> | 
				
			|||
            </div> | 
				
			|||
          </div> | 
				
			|||
        </el-card> | 
				
			|||
 | 
				
			|||
      </el-col> | 
				
			|||
 | 
				
			|||
    </el-row> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  import QRCode from 'qrcodejs2'; | 
				
			|||
  export default { | 
				
			|||
    name: 'NoticeManagement', | 
				
			|||
    data(){ | 
				
			|||
      return{ | 
				
			|||
        loading: false, | 
				
			|||
        dialogWidth:'500px', | 
				
			|||
        currentPage:1, | 
				
			|||
        pageSize:6, | 
				
			|||
        totalSize:0, | 
				
			|||
        notices:[], | 
				
			|||
        selectedActivity:[], | 
				
			|||
        voteItems:[], | 
				
			|||
        date: new Date(), | 
				
			|||
        date_1:'', | 
				
			|||
        dialogFormVisible:false, | 
				
			|||
        activityLink:'', | 
				
			|||
        cur_date : this.$options.filters.fmtDate(new Date()) | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    mounted() { | 
				
			|||
      window.onresize = () => { | 
				
			|||
        return (() => { | 
				
			|||
          this.setDialogWidth() | 
				
			|||
        })() | 
				
			|||
      } | 
				
			|||
      this.listNotice() | 
				
			|||
 | 
				
			|||
    }, | 
				
			|||
    methods:{ | 
				
			|||
      listNotice(){ | 
				
			|||
        let _this = this | 
				
			|||
        this.loading = true | 
				
			|||
        this.$axios.get('/notice/list?page='+_this.currentPage | 
				
			|||
          +'&size='+_this.pageSize | 
				
			|||
          +'&userName='+ _this.$store.state.user.userName) | 
				
			|||
          .then(resp =>{ | 
				
			|||
            if(resp && resp.data.code === 200){ | 
				
			|||
              _this.notices = resp.data.result.content | 
				
			|||
              _this.totalSize = resp.data.result.totalElements | 
				
			|||
              _this.loading = false | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
      }, | 
				
			|||
      toCreate(){ | 
				
			|||
        this.$store.state.curCreateActivity = [] | 
				
			|||
        this.$router.replace('/admin/content/add/notice') | 
				
			|||
      }, | 
				
			|||
 | 
				
			|||
      handleCurrentChange(currentPage) { | 
				
			|||
        this.currentPage = currentPage | 
				
			|||
        this.listActivity() | 
				
			|||
      }, | 
				
			|||
      setDialogWidth() { | 
				
			|||
        let val = document.body.clientWidth | 
				
			|||
        const def = 500 // 默认宽度 | 
				
			|||
        if (val < def) { | 
				
			|||
          this.dialogWidth = '100%' | 
				
			|||
        } else { | 
				
			|||
          this.dialogWidth = def + 'px' | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      showNotice(id){ | 
				
			|||
        this.$router.push('/notice/detail/'+id) | 
				
			|||
      }, | 
				
			|||
      deleteNotice(notice){ | 
				
			|||
        this.$confirm('确定删除此公告?', '提示', { | 
				
			|||
          confirmButtonText: '确定', | 
				
			|||
          cancelButtonText: '取消', | 
				
			|||
          type: 'warning' | 
				
			|||
        }).then(() => { | 
				
			|||
          this.$axios.delete('/admin/notice/'+notice.id).then(resp =>{ | 
				
			|||
            if(resp && resp.data.code === 200){ | 
				
			|||
              this.$message.success("删除成功") | 
				
			|||
              this.listNotice() | 
				
			|||
            }else { | 
				
			|||
              let message = resp.data.message | 
				
			|||
              this.$message.error("删除成功") | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
        }).catch(() => { | 
				
			|||
        }) | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style> | 
				
			|||
</style> --> | 
				
			|||
@ -0,0 +1,246 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <el-dialog | 
				
			|||
      title="修改角色信息" | 
				
			|||
      :visible.sync="dialogFormVisible"> | 
				
			|||
      <el-form v-model="selectedRole" style="text-align: left" ref="dataForm"> | 
				
			|||
        <el-form-item label="角色名" label-width="120px" prop="username"> | 
				
			|||
          <el-input v-model="selectedRole.name" autocomplete="off"></el-input> | 
				
			|||
        </el-form-item> | 
				
			|||
        <el-form-item label="角色描述" label-width="120px" prop="name"> | 
				
			|||
          <el-input v-model="selectedRole.nameZh" autocomplete="off"></el-input> | 
				
			|||
        </el-form-item> | 
				
			|||
        <el-form-item label="功能配置" label-width="120px" prop="perms"> | 
				
			|||
          <el-checkbox-group v-model="selectedPermsIds"> | 
				
			|||
            <el-checkbox v-for="(perm,i) in perms" :key="i" :label="perm.id">{{perm.desc_}}</el-checkbox> | 
				
			|||
          </el-checkbox-group> | 
				
			|||
        </el-form-item> | 
				
			|||
        <el-form-item label="菜单配置" label-width="120px" prop="menus"> | 
				
			|||
          <el-tree | 
				
			|||
            :data="menus" | 
				
			|||
            :props="props" | 
				
			|||
            show-checkbox | 
				
			|||
            :default-checked-keys="selectedMenusIds" | 
				
			|||
            node-key="id" | 
				
			|||
            ref="tree"> | 
				
			|||
          </el-tree> | 
				
			|||
        </el-form-item> | 
				
			|||
      </el-form> | 
				
			|||
      <div slot="footer" class="dialog-footer"> | 
				
			|||
        <el-button @click="dialogFormVisible = false">取 消</el-button> | 
				
			|||
        <el-button type="primary" @click="onSubmit(selectedRole)">确 定</el-button> | 
				
			|||
      </div> | 
				
			|||
    </el-dialog> | 
				
			|||
    <el-row style="margin: 18px 0px 0px 30px "> | 
				
			|||
      <el-breadcrumb separator-class="el-icon-arrow-right"> | 
				
			|||
        <el-breadcrumb-item>用户管理</el-breadcrumb-item> | 
				
			|||
        <el-breadcrumb-item>角色配置</el-breadcrumb-item> | 
				
			|||
      </el-breadcrumb> | 
				
			|||
    </el-row> | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    <role-create @onSubmit="listRoles()" style="margin-left: 25px"></role-create> | 
				
			|||
    <el-card style="margin: 18px 2%;width: 95%"> | 
				
			|||
      <el-table | 
				
			|||
        v-loading="loading" | 
				
			|||
        :data="roles" | 
				
			|||
        stripe | 
				
			|||
        style="width: 100%" | 
				
			|||
        :max-height="tableHeight"> | 
				
			|||
        <el-table-column | 
				
			|||
          prop="id" | 
				
			|||
          label="id" | 
				
			|||
          width="100"> | 
				
			|||
        </el-table-column> | 
				
			|||
        <el-table-column | 
				
			|||
          prop="name" | 
				
			|||
          label="角色名" | 
				
			|||
          fit> | 
				
			|||
        </el-table-column> | 
				
			|||
        <el-table-column | 
				
			|||
          prop="nameZh" | 
				
			|||
          label="角色描述" | 
				
			|||
          fit> | 
				
			|||
        </el-table-column> | 
				
			|||
        <el-table-column | 
				
			|||
          label="状态" | 
				
			|||
          width="100"> | 
				
			|||
          <template slot-scope="scope"> | 
				
			|||
            <el-switch | 
				
			|||
              v-model="scope.row.enabled" | 
				
			|||
              active-color="#13ce66" | 
				
			|||
              inactive-color="#ff4949" | 
				
			|||
              @change="(value) => commitStatusChange(value, scope.row)"> | 
				
			|||
            </el-switch> | 
				
			|||
          </template> | 
				
			|||
        </el-table-column> | 
				
			|||
        <el-table-column | 
				
			|||
          label="操作" | 
				
			|||
          width="120"> | 
				
			|||
          <template slot-scope="scope"> | 
				
			|||
            <el-button | 
				
			|||
              type="primary" | 
				
			|||
              size="small" | 
				
			|||
              @click="editRole(scope.row)"> | 
				
			|||
              编辑 | 
				
			|||
            </el-button> | 
				
			|||
          </template> | 
				
			|||
        </el-table-column> | 
				
			|||
      </el-table> | 
				
			|||
    </el-card> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  import RoleCreate from './RoleCreate' | 
				
			|||
  export default { | 
				
			|||
    name: 'UserRole', | 
				
			|||
    components: {RoleCreate}, | 
				
			|||
    data () { | 
				
			|||
      return { | 
				
			|||
        loading:false, | 
				
			|||
        dialogFormVisible: false, | 
				
			|||
        roles: [], | 
				
			|||
        perms: [], | 
				
			|||
        menus: [], | 
				
			|||
        selectedRole: [], | 
				
			|||
        selectedPermsIds: [], | 
				
			|||
        selectedMenusIds: [], | 
				
			|||
        props: { | 
				
			|||
          id: 'id', | 
				
			|||
          label: 'nameZh', | 
				
			|||
          children: 'children' | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    mounted () { | 
				
			|||
      this.listRoles() | 
				
			|||
      this.listPerms() | 
				
			|||
      this.listMenus() | 
				
			|||
    }, | 
				
			|||
    computed: { | 
				
			|||
      tableHeight () { | 
				
			|||
        return window.innerHeight - 320 | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    methods: { | 
				
			|||
      listRoles () { | 
				
			|||
        let _this = this | 
				
			|||
        _this.loading = true; | 
				
			|||
        this.$axios.get('/admin/role').then(resp => { | 
				
			|||
          if (resp && resp.status === 200) { | 
				
			|||
            _this.roles = resp.data.result | 
				
			|||
            _this.loading = false | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      listPerms () { | 
				
			|||
        let _this = this | 
				
			|||
        this.$axios.get('/admin/role/perm').then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            _this.perms = resp.data.result | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      listMenus () { | 
				
			|||
        let _this = this | 
				
			|||
        this.$axios.get('/admin/role/menu').then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            _this.menus = resp.data.result | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      commitStatusChange (value, role) { | 
				
			|||
        if (role.id !== 1) { | 
				
			|||
          this.$confirm('是否更改角色状态?', '提示', { | 
				
			|||
            confirmButtonText: '确定', | 
				
			|||
            cancelButtonText: '取消', | 
				
			|||
            type: 'warning' | 
				
			|||
          }).then(() => { | 
				
			|||
            this.$axios.put('/admin/role/status', { | 
				
			|||
              enabled: value, | 
				
			|||
              id: role.id | 
				
			|||
            }).then(resp => { | 
				
			|||
              if (resp && resp.data.code === 200) { | 
				
			|||
                if (value) { | 
				
			|||
                  this.$message('角色 [' + role.nameZh + '] 已启用') | 
				
			|||
                } else { | 
				
			|||
                  this.$message('角色 [' + role.nameZh + '] 已禁用') | 
				
			|||
                } | 
				
			|||
              } | 
				
			|||
            }) | 
				
			|||
          }).catch(() => { | 
				
			|||
            role.enabled = !role.enabled | 
				
			|||
            this.$message({ | 
				
			|||
              type: 'info', | 
				
			|||
              message: '已取消' | 
				
			|||
            }) | 
				
			|||
          }) | 
				
			|||
        } else { | 
				
			|||
          role.enabled = true | 
				
			|||
          this.$alert('无法禁用系统管理员!') | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      editRole (role) { | 
				
			|||
        this.dialogFormVisible = true | 
				
			|||
        this.selectedRole = role | 
				
			|||
        let permIds = [] | 
				
			|||
        for (let i = 0; i < role.perms.length; i++) { | 
				
			|||
          permIds.push(role.perms[i].id) | 
				
			|||
        } | 
				
			|||
        this.selectedPermsIds = permIds | 
				
			|||
        let menuIds = [] | 
				
			|||
        for (let i = 0; i < role.menus.length; i++) { | 
				
			|||
          menuIds.push(role.menus[i].id) | 
				
			|||
          for (let j = 0; j < role.menus[i].children.length; j++) { | 
				
			|||
            menuIds.push(role.menus[i].children[j].id) | 
				
			|||
          } | 
				
			|||
        } | 
				
			|||
        this.selectedMenusIds = menuIds | 
				
			|||
        // 判断树是否已经加载,第一次打开对话框前树不存在,会报错。所以需要设置 default-checked | 
				
			|||
        if (this.$refs.tree) { | 
				
			|||
          this.$refs.tree.setCheckedKeys(menuIds) | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      onSubmit (role) { | 
				
			|||
        let _this = this | 
				
			|||
        // 根据视图绑定的角色 id 向后端传送角色信息 | 
				
			|||
        let perms = [] | 
				
			|||
        for (let i = 0; i < _this.selectedPermsIds.length; i++) { | 
				
			|||
          for (let j = 0; j < _this.perms.length; j++) { | 
				
			|||
            if (_this.selectedPermsIds[i] === _this.perms[j].id) { | 
				
			|||
              perms.push(_this.perms[j]) | 
				
			|||
            } | 
				
			|||
          } | 
				
			|||
        } | 
				
			|||
        this.$axios.put('/admin/role', { | 
				
			|||
          id: role.id, | 
				
			|||
          name: role.name, | 
				
			|||
          nameZh: role.nameZh, | 
				
			|||
          enabled: role.enabled, | 
				
			|||
          perms: perms | 
				
			|||
        }).then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            this.$alert(resp.data.result) | 
				
			|||
            this.dialogFormVisible = false | 
				
			|||
            this.listRoles() | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
        this.$axios.put('/admin/role/menu?rid=' + role.id, { | 
				
			|||
          menusIds: this.$refs.tree.getCheckedKeys() | 
				
			|||
        }).then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            console.log(resp.data.result) | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
  .add-button { | 
				
			|||
    float: left; | 
				
			|||
    margin: 18px 0 18px 10px; | 
				
			|||
  } | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,84 @@ | 
				
			|||
<template> | 
				
			|||
  <div style="text-align: left"> | 
				
			|||
    <el-button class="add-button" type="success" @click="dialogFormVisible = true">添加角色</el-button> | 
				
			|||
    <el-dialog | 
				
			|||
      title="添加角色" | 
				
			|||
      :visible.sync="dialogFormVisible" | 
				
			|||
      @close="clear" | 
				
			|||
      width="25%"> | 
				
			|||
      <el-form :model="roleForm" :rules="rules" label-position="left" | 
				
			|||
               label-width="0px" v-loading="loading"> | 
				
			|||
        <el-form-item prop="name"> | 
				
			|||
          <el-input type="text" v-model="roleForm.name" | 
				
			|||
                    auto-complete="off" placeholder="角色名"></el-input> | 
				
			|||
        </el-form-item> | 
				
			|||
        <el-form-item prop="nameZh"> | 
				
			|||
          <el-input type="text" v-model="roleForm.nameZh" | 
				
			|||
                    auto-complete="off" placeholder="角色描述"></el-input> | 
				
			|||
        </el-form-item> | 
				
			|||
        <el-form-item style="width: 100%"> | 
				
			|||
          <el-button type="primary" style="width: 40%;background: #505458;border: none" v-on:click="createRole">添加</el-button> | 
				
			|||
        </el-form-item> | 
				
			|||
        <el-form-item prop="username"> | 
				
			|||
          <el-tag>初始权限:无</el-tag> | 
				
			|||
        </el-form-item> | 
				
			|||
      </el-form> | 
				
			|||
    </el-dialog> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  export default { | 
				
			|||
    name: 'RoleCreate', | 
				
			|||
    data () { | 
				
			|||
      return { | 
				
			|||
        dialogFormVisible: false, | 
				
			|||
        rules: { | 
				
			|||
          name: [{required: true, message: '角色名不能为空', trigger: 'blur'}] | 
				
			|||
        }, | 
				
			|||
        checked: true, | 
				
			|||
        roleForm: { | 
				
			|||
          name: '', | 
				
			|||
          nameZh: '' | 
				
			|||
        }, | 
				
			|||
        loading: false | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    methods: { | 
				
			|||
      clear () { | 
				
			|||
        this.roleForm = { | 
				
			|||
          name: '', | 
				
			|||
          nameZh: '' | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      createRole () { | 
				
			|||
        this.$axios | 
				
			|||
          .post('/admin/role', { | 
				
			|||
            name: this.roleForm.name, | 
				
			|||
            nameZh: this.roleForm.nameZh | 
				
			|||
          }) | 
				
			|||
          .then(resp => { | 
				
			|||
            if (resp.data.code === 200) { | 
				
			|||
              this.$alert(resp.data.result, '提示', { | 
				
			|||
                confirmButtonText: '确定' | 
				
			|||
              }) | 
				
			|||
              this.clear() | 
				
			|||
              this.$emit('onSubmit') | 
				
			|||
            } else { | 
				
			|||
              this.$alert(resp.data.message, '提示', { | 
				
			|||
                confirmButtonText: '确定' | 
				
			|||
              }) | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
          .catch(failResponse => {}) | 
				
			|||
        this.dialogFormVisible = false | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
  .add-button { | 
				
			|||
    margin: 18px 0 0 10px; | 
				
			|||
  } | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,231 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <!--修改用户信息对话框--> | 
				
			|||
    <el-dialog | 
				
			|||
      title="修改用户信息" | 
				
			|||
      :visible.sync="dialogFormVisible"> | 
				
			|||
      <el-form v-model="selectedUser" label-position="right"  label-width="120px" style="text-align: left" ref="dataForm"> | 
				
			|||
        <el-form-item label="用户名" prop="userName"> | 
				
			|||
          <label >{{selectedUser.userName}}</label> | 
				
			|||
        </el-form-item> | 
				
			|||
        <el-form-item label="邮箱"  prop="email"> | 
				
			|||
          <el-input v-model="selectedUser.email" autocomplete="off"></el-input> | 
				
			|||
        </el-form-item> | 
				
			|||
        <el-form-item label="角色分配"  prop="roles | 
				
			|||
 | 
				
			|||
"> | 
				
			|||
          <el-checkbox-group v-model="selectedRolesIds"> | 
				
			|||
            <el-checkbox v-for="(role,i) in roles" :key="i" :label="role.id">{{role.nameZh}}</el-checkbox> | 
				
			|||
          </el-checkbox-group> | 
				
			|||
        </el-form-item> | 
				
			|||
      </el-form> | 
				
			|||
      <div slot="footer" class="dialog-footer"> | 
				
			|||
        <el-button @click="dialogFormVisible = false">取 消</el-button> | 
				
			|||
        <el-button type="primary" @click="onSubmit(selectedUser)">确 定</el-button> | 
				
			|||
      </div> | 
				
			|||
    </el-dialog> | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    <!--面包屑导航--> | 
				
			|||
    <el-row style="margin: 18px 0px 0px 18px "> | 
				
			|||
      <el-breadcrumb separator-class="el-icon-arrow-right"> | 
				
			|||
        <el-breadcrumb-item>用户管理</el-breadcrumb-item> | 
				
			|||
        <el-breadcrumb-item>用户信息</el-breadcrumb-item> | 
				
			|||
      </el-breadcrumb> | 
				
			|||
    </el-row> | 
				
			|||
 | 
				
			|||
    <!-- 用户列表表格--> | 
				
			|||
    <el-card style="margin: 18px 2%;width: 95%"> | 
				
			|||
      <el-table | 
				
			|||
        v-loading="loading" | 
				
			|||
        :data="users" | 
				
			|||
        stripe | 
				
			|||
        :default-sort = "{prop: 'id', order: 'ascending'}" | 
				
			|||
        style="width: 100%" | 
				
			|||
        :max-height="tableHeight"> | 
				
			|||
        <el-table-column | 
				
			|||
          prop="id" | 
				
			|||
          label="id" | 
				
			|||
          sortable | 
				
			|||
          width="55"> | 
				
			|||
        </el-table-column> | 
				
			|||
        <el-table-column | 
				
			|||
          prop="userName" | 
				
			|||
          label="用户名" | 
				
			|||
          width="200"> | 
				
			|||
        </el-table-column> | 
				
			|||
        <el-table-column | 
				
			|||
          label="头像" | 
				
			|||
          fit> | 
				
			|||
          <template slot-scope="scope"> | 
				
			|||
            <el-avatar size="medium" :src="scope.row.avatar"></el-avatar> | 
				
			|||
          </template> | 
				
			|||
        </el-table-column> | 
				
			|||
        <el-table-column | 
				
			|||
          prop="email" | 
				
			|||
          label="邮箱" | 
				
			|||
          width="180"> | 
				
			|||
        </el-table-column> | 
				
			|||
        <el-table-column | 
				
			|||
          label="状态" | 
				
			|||
          width="100"> | 
				
			|||
          <template slot-scope="scope"> | 
				
			|||
            <el-switch | 
				
			|||
              v-model="scope.row.state" | 
				
			|||
              active-color="#13ce66" | 
				
			|||
              inactive-color="#ff4949" | 
				
			|||
              @change="(value) => commitStatusChange(value, scope.row)"> | 
				
			|||
            </el-switch> | 
				
			|||
          </template> | 
				
			|||
        </el-table-column> | 
				
			|||
 | 
				
			|||
        <el-table-column | 
				
			|||
          label="操作" | 
				
			|||
          width="200"> | 
				
			|||
          <template slot-scope="scope"> | 
				
			|||
            <el-button type="primary" size="small" @click="editUser(scope.row)">编辑</el-button> | 
				
			|||
            <el-button type="warning" size="small" @click="resetPassword(scope.row.id)">重置密码</el-button> | 
				
			|||
          </template> | 
				
			|||
        </el-table-column> | 
				
			|||
      </el-table> | 
				
			|||
      <div style="float: left;padding: 15px"> | 
				
			|||
        <el-pagination | 
				
			|||
          @current-change="handleCurrentChange" | 
				
			|||
          :current-page="currentPage" | 
				
			|||
          :page-size="pageSize" | 
				
			|||
          :total="totalSize"> | 
				
			|||
        </el-pagination> | 
				
			|||
      </div> | 
				
			|||
    </el-card> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  export default { | 
				
			|||
    name: 'UserFile', | 
				
			|||
    data () { | 
				
			|||
      return { | 
				
			|||
        loading: false, | 
				
			|||
        currentPage:1, | 
				
			|||
        pageSize:6, | 
				
			|||
        totalSize:0, | 
				
			|||
        users: [], | 
				
			|||
        roles: [], | 
				
			|||
        dialogFormVisible: false, | 
				
			|||
        selectedUser: [], | 
				
			|||
        selectedRolesIds: [] | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    mounted () { | 
				
			|||
      this.listRoles() | 
				
			|||
      this.listUsers() | 
				
			|||
    }, | 
				
			|||
    computed: { | 
				
			|||
      tableHeight () { | 
				
			|||
        return window.innerHeight - 320 | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    methods: { | 
				
			|||
      listUsers () { | 
				
			|||
        let _this = this; | 
				
			|||
        _this.loading = true; | 
				
			|||
        this.$axios.get('/admin/user/list?page='+_this.currentPage+'&size='+_this.pageSize).then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            _this.users = resp.data.result.content | 
				
			|||
            _this.totalSize = resp.data.result.totalElements | 
				
			|||
            _this.loading = false | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      listRoles () { | 
				
			|||
        console.log('list roles ... ') | 
				
			|||
        let _this = this | 
				
			|||
        this.$axios.get('/admin/role').then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            _this.roles = resp.data.result | 
				
			|||
            console.log('roles === > ',_this.roles) | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      commitStatusChange (value, user) { | 
				
			|||
        if (user.userName !== 'admin') { | 
				
			|||
          this.$axios.put('/admin/user/state/'+user.id+'?state='+value).then(resp => { | 
				
			|||
            if (resp && resp.data.code === 200) { | 
				
			|||
              if (value) { | 
				
			|||
                this.$message('用户 [' + user.userName + '] 已启用') | 
				
			|||
              } else { | 
				
			|||
                this.$message('用户 [' + user.userName + '] 已禁用') | 
				
			|||
              } | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
        } else { | 
				
			|||
          user.state = true | 
				
			|||
          this.$alert('不能禁用管理员账户') | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      onSubmit (user) { | 
				
			|||
        let _this = this | 
				
			|||
        if(user.userName === 'admin'){ | 
				
			|||
          this.$message.error("不可修改系统管理员的信息"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        //判断信息 | 
				
			|||
        if(user.email === ''){ | 
				
			|||
          this.$message.error("邮箱不能为空"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        let reg = /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/ | 
				
			|||
        if (!reg.test(user.email)) { | 
				
			|||
          this.$message.error("邮箱格式不正确"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        // 根据视图绑定的角色 id 向后端传送角色信息 | 
				
			|||
        let roles = [] | 
				
			|||
        for (let i = 0; i < _this.selectedRolesIds.length; i++) { | 
				
			|||
          for (let j = 0; j < _this.roles.length; j++) { | 
				
			|||
            if (_this.selectedRolesIds[i] === _this.roles[j].id) { | 
				
			|||
              roles.push(_this.roles[j]) | 
				
			|||
            } | 
				
			|||
          } | 
				
			|||
        } | 
				
			|||
        this.$axios.put('/admin/user/'+user.id, { | 
				
			|||
          id:user.id, | 
				
			|||
          userName: user.userName, | 
				
			|||
          email: user.email, | 
				
			|||
          roles: roles | 
				
			|||
        }).then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            this.$message.success("用户信息修改成功"); | 
				
			|||
            this.dialogFormVisible = false | 
				
			|||
            // 修改角色后重新请求用户信息,实现视图更新 | 
				
			|||
            this.listUsers() | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      editUser (user) { | 
				
			|||
        this.dialogFormVisible = true | 
				
			|||
        this.selectedUser = user | 
				
			|||
        let roleIds = [] | 
				
			|||
        for (let i = 0; i < user.roles.length; i++) { | 
				
			|||
          roleIds.push(user.roles[i].id) | 
				
			|||
        } | 
				
			|||
        this.selectedRolesIds = roleIds | 
				
			|||
      }, | 
				
			|||
      resetPassword (id) { | 
				
			|||
        this.$axios.put('/admin/user/repassword/'+id).then(resp => { | 
				
			|||
          if (resp && resp.data.code === 200) { | 
				
			|||
            this.$alert('密码已重置为 123') | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      handleCurrentChange(currentPage) { | 
				
			|||
        this.currentPage = currentPage | 
				
			|||
        this.listUsers() | 
				
			|||
      }, | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
 | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,38 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <router-view/> | 
				
			|||
    <!-- <Create></Create> --> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
    import Create from "./Create"; | 
				
			|||
    export default { | 
				
			|||
      name: "AddActivity", | 
				
			|||
      components: {Create}, | 
				
			|||
      data(){ | 
				
			|||
        return{ | 
				
			|||
          addIndex:true, | 
				
			|||
          curPath:'' | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      computed: { | 
				
			|||
        // setter | 
				
			|||
        set: function () { | 
				
			|||
          this.curPath = this.$route.path | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      methods:{ | 
				
			|||
 | 
				
			|||
      }, | 
				
			|||
      onMounted:{ | 
				
			|||
        function () { | 
				
			|||
          // this.$route.push(import('../vote/Create.vue')); | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
 | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,165 @@ | 
				
			|||
<template> | 
				
			|||
  <div class="setItemsDiv"> | 
				
			|||
    <CreateNav ref="createBase"></CreateNav> | 
				
			|||
    <el-row> | 
				
			|||
      <el-col  :sm="2" :xl="4"> </el-col> | 
				
			|||
      <el-col  :sm="16"  :xs="24"> | 
				
			|||
        <el-card> | 
				
			|||
          <div style="text-align: left"> | 
				
			|||
            <el-form> | 
				
			|||
              <el-form-item> | 
				
			|||
                <span style="font-size: 16px;font-weight: bold">投票标题</span> | 
				
			|||
                <el-input v-model="title"></el-input> | 
				
			|||
              </el-form-item> | 
				
			|||
              <el-form-item> | 
				
			|||
                <div style="width: 50%;float: left"> | 
				
			|||
                  <span class="demonstration">投票开始时间</span> | 
				
			|||
                  <el-date-picker | 
				
			|||
                    v-model="startTime" | 
				
			|||
                    type="datetime" | 
				
			|||
                    placeholder="选择开始时间"> | 
				
			|||
                  </el-date-picker> | 
				
			|||
                </div> | 
				
			|||
                <div style="width: 50%;float: right"> | 
				
			|||
                  <span class="demonstration">投票结束时间</span> | 
				
			|||
                  <el-date-picker | 
				
			|||
                    v-model="endTime" | 
				
			|||
                    type="datetime" | 
				
			|||
                    placeholder="选择结束时间"> | 
				
			|||
                  </el-date-picker> | 
				
			|||
                </div> | 
				
			|||
              </el-form-item> | 
				
			|||
              <el-form-item> | 
				
			|||
                <Qeditor ref="qeditor"></Qeditor> | 
				
			|||
              </el-form-item> | 
				
			|||
            </el-form> | 
				
			|||
          </div> | 
				
			|||
 | 
				
			|||
          <div style="padding-top: 50px;margin-top: 20px"> | 
				
			|||
            <el-button @click="comeBcak" >返回</el-button> | 
				
			|||
            <el-button type="primary" @click="saveActivity">下一步</el-button> | 
				
			|||
          </div> | 
				
			|||
        </el-card> | 
				
			|||
      </el-col> | 
				
			|||
 | 
				
			|||
    </el-row> | 
				
			|||
  </div> | 
				
			|||
 | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  import Qeditor from "../../common/Qeditor"; | 
				
			|||
  import CreateNav from "./CreateNav"; | 
				
			|||
  export default { | 
				
			|||
    name: "Create", | 
				
			|||
    components: {CreateNav, Qeditor}, | 
				
			|||
    data(){ | 
				
			|||
      return{ | 
				
			|||
        startTime: '', | 
				
			|||
        endTime: '', | 
				
			|||
        title:'', | 
				
			|||
        content:'', | 
				
			|||
        type:{}, | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    mounted(){ | 
				
			|||
      this.getCurActivity() | 
				
			|||
    }, | 
				
			|||
    methods:{ | 
				
			|||
      testContent(){ | 
				
			|||
        this.content = this.$refs.qeditor.content | 
				
			|||
      }, | 
				
			|||
      saveActivity() { | 
				
			|||
        if(this.title === ''){ | 
				
			|||
          this.$message.error("活动标题不能为空"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        if(this.startTime === ''){ | 
				
			|||
          this.$message.error("开始时间不能为空"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        if(this.endTime === ''){ | 
				
			|||
          this.$message.error("结束时间不能为空"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        if(this.startTime > this.endTime){ | 
				
			|||
          this.$message.error("开始时间不能再结束时间后"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        if(this.$refs.qeditor.content === ''){ | 
				
			|||
          this.$message.error("活动描述不能为空"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        //如果state里面有id,证明是已存在的活动 | 
				
			|||
        //点击下一步是对已有的活动进行更新 | 
				
			|||
        if(this.$store.state.curCreateActivity.id){ | 
				
			|||
          let activityId = this.$store.state.curCreateActivity.id; | 
				
			|||
          this.$axios.put('/admin/activity/'+activityId,{ | 
				
			|||
            title: this.title, | 
				
			|||
            startTime:this.startTime, | 
				
			|||
            endTime: this.endTime, | 
				
			|||
            content:this.$refs.qeditor.content, | 
				
			|||
            type:this.type | 
				
			|||
          }).then(resp =>{ | 
				
			|||
            if(resp.data.code === 200){ | 
				
			|||
              this.$message.success("活动更新成功") | 
				
			|||
              this.$router.replace('/admin/vote/add/item'); | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
        }else{ | 
				
			|||
          this.$axios.post('/admin/activity', { | 
				
			|||
            title: this.title, | 
				
			|||
            startTime:this.startTime, | 
				
			|||
            endTime: this.endTime, | 
				
			|||
            content:this.$refs.qeditor.content, | 
				
			|||
            author:this.$store.state.user.userName, | 
				
			|||
            type:JSON.stringify(this.type) | 
				
			|||
          }).then(resp => { | 
				
			|||
            if (resp && resp.data.code === 200) { | 
				
			|||
              this.$message.success("活动创建成功") | 
				
			|||
              let data = resp.data.result | 
				
			|||
              this.$store.commit('createActive', data) | 
				
			|||
              this.$router.replace('/admin/vote/add/item') | 
				
			|||
            } | 
				
			|||
          }).catch(() => { | 
				
			|||
            this.$message({ | 
				
			|||
              type: 'info', | 
				
			|||
              message: '已取消创建' | 
				
			|||
            }) | 
				
			|||
          }) | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      comeBcak(){ | 
				
			|||
 | 
				
			|||
      }, | 
				
			|||
      getCurActivity(){ | 
				
			|||
        if(this.$store.state.curCreateActivity.id){ | 
				
			|||
          let curId = this.$store.state.curCreateActivity.id | 
				
			|||
           | 
				
			|||
          this.$axios.get('/activity/'+ curId).then(resp =>{ | 
				
			|||
            if(resp && resp.data.code === 200){ | 
				
			|||
              let curActivity = resp.data.result | 
				
			|||
              this.startTime = curActivity.startTime | 
				
			|||
              this.endTime = curActivity.endTime | 
				
			|||
              this.title =  curActivity.title | 
				
			|||
              this.$refs.qeditor.content = curActivity.content | 
				
			|||
              this.type = curActivity.type | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
  .setItemsDiv{ | 
				
			|||
    margin: 0px auto; | 
				
			|||
    height: 100%; | 
				
			|||
    width: 100%; | 
				
			|||
 | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,111 @@ | 
				
			|||
<template> | 
				
			|||
  <el-row :gutter="22"> | 
				
			|||
    <el-col :sm="2" :xl="4"> </el-col> | 
				
			|||
    <el-col :sm="4" :xs="22" > | 
				
			|||
      <div class="createItem" v-bind:class="{ active: isCreate }" > | 
				
			|||
               <!-- <router-link  :to="{ path: '/voteItem' }">跳转</router-link> --> | 
				
			|||
        <h4>1.基本信息</h4> | 
				
			|||
        <div class="createItemDesc" @click="voteCreatePath"> | 
				
			|||
          <span>标题、时间、描述</span> | 
				
			|||
        </div> | 
				
			|||
      </div> | 
				
			|||
    </el-col> | 
				
			|||
    <el-col  :sm="4" :xs="22" :offset="2"> | 
				
			|||
      <div class="createItem"  @click="voteItemPath"  v-bind:class="{ active: isVoteItem }" > | 
				
			|||
        <h4>2.选手管理</h4> | 
				
			|||
        <div class="createItemDesc"> | 
				
			|||
          <span>管理投票选手</span> | 
				
			|||
        </div> | 
				
			|||
      </div> | 
				
			|||
    </el-col> | 
				
			|||
    <el-col  :sm="4" :xs="22" :offset="2"> | 
				
			|||
      <div class="createItem" @click="voteEditPath"  v-bind:class="{ active: isVoteEdit}" > | 
				
			|||
        <h4>3.自定义配置</h4> | 
				
			|||
        <div class="createItemDesc"> | 
				
			|||
          <span>投票类型设置</span> | 
				
			|||
        </div> | 
				
			|||
      </div> | 
				
			|||
    </el-col> | 
				
			|||
  </el-row> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  export default { | 
				
			|||
    name: "CreateNav", | 
				
			|||
    data(){ | 
				
			|||
      return{ | 
				
			|||
        curPath:'', | 
				
			|||
        isCreate:false, | 
				
			|||
        isVoteItem:false, | 
				
			|||
        isVoteEdit:false, | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    mounted(){ | 
				
			|||
      this.handleBackground() | 
				
			|||
    }, | 
				
			|||
    computed: { | 
				
			|||
      // setter | 
				
			|||
      set: function () { | 
				
			|||
        this.curPath = this.$route.path | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    methods:{ | 
				
			|||
 | 
				
			|||
      voteCreatePath(){ | 
				
			|||
        if(this.$store.state.curCreateActivity.id) { | 
				
			|||
          this.$router.push({path:'/admin/vote/add/index'}) | 
				
			|||
        } | 
				
			|||
        this.$router.push({path:'/admin/vote/add/index'}) | 
				
			|||
      }, | 
				
			|||
      voteItemPath(){ | 
				
			|||
        if(this.$store.state.curCreateActivity.id) { | 
				
			|||
          this.$router.push({path: '/admin/vote/add/item'}) | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      voteEditPath(){ | 
				
			|||
        if(this.$store.state.curCreateActivity.id) { | 
				
			|||
          this.$router.push({path:'/admin/vote/add/setting'}) | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      handleBackground(){ | 
				
			|||
        if(this.$route.path === '/admin/vote/add' || this.$route.path === '/admin/vote/add/index' ){ | 
				
			|||
          this.isCreate = true | 
				
			|||
        }else { | 
				
			|||
          this.isCreate = false | 
				
			|||
        } | 
				
			|||
        if(this.$route.path === '/admin/vote/add/item' ){ | 
				
			|||
          this.isVoteItem = true | 
				
			|||
        }else { | 
				
			|||
          this.isVoteItem = false | 
				
			|||
        } | 
				
			|||
        if(this.$route.path === '/admin/vote/add/setting' ){ | 
				
			|||
          this.isVoteEdit = true | 
				
			|||
        }else { | 
				
			|||
          this.isVoteEdit = false | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
  .createItem{ | 
				
			|||
    margin: 0px auto 40px auto; | 
				
			|||
    text-align: center; | 
				
			|||
    border: 1px solid #eaeaea; | 
				
			|||
    border-radius: 8px; | 
				
			|||
    box-shadow: 0 0 25px #cac6c6; | 
				
			|||
  } | 
				
			|||
  .createItem:hover{ | 
				
			|||
    background-color: #36aaff; | 
				
			|||
    color: white; | 
				
			|||
  } | 
				
			|||
  .createItemDesc{ | 
				
			|||
    padding: 0px 0px 10px 0px; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .active{ | 
				
			|||
    background-color: #36aaff;color: white | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,83 @@ | 
				
			|||
<template> | 
				
			|||
      <el-dialog | 
				
			|||
        title="修改描述" | 
				
			|||
        :visible.sync="dialogFormVisible" | 
				
			|||
        :modal-append-to-body="false" | 
				
			|||
        @close="clear" | 
				
			|||
        :width=dialogWidth> | 
				
			|||
        <qeditor ref="qeditor"></qeditor> | 
				
			|||
        <div style="padding-top: 50px;margin-top: 20px"> | 
				
			|||
          <el-button type="primary" @click="submit">确定</el-button> | 
				
			|||
          <el-button @click="clear">取消</el-button> | 
				
			|||
        </div> | 
				
			|||
      </el-dialog> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
    import Qeditor from "../../common/Qeditor"; | 
				
			|||
    export default { | 
				
			|||
        name: "EditDesc", | 
				
			|||
        components: {Qeditor}, | 
				
			|||
        data(){ | 
				
			|||
          return{ | 
				
			|||
            dialogFormVisible:false, | 
				
			|||
            id:0, | 
				
			|||
            num:0, | 
				
			|||
            content:'', | 
				
			|||
            coverUrl:'', | 
				
			|||
            videoUrl:'', | 
				
			|||
            title:'', | 
				
			|||
            state:'', | 
				
			|||
            voteItemId:0, | 
				
			|||
            dialogWidth:'500px', | 
				
			|||
          } | 
				
			|||
      }, | 
				
			|||
      mounted(){ | 
				
			|||
          this.handleBindContent() | 
				
			|||
          window.onresize = () => { | 
				
			|||
            return (() => { | 
				
			|||
              this.setDialogWidth() | 
				
			|||
            })() | 
				
			|||
          } | 
				
			|||
      }, | 
				
			|||
      methods:{ | 
				
			|||
        clear(){ | 
				
			|||
          this.dialogFormVisible = false | 
				
			|||
          this.$refs.qeditor.content = '' | 
				
			|||
        }, | 
				
			|||
        submit(){ | 
				
			|||
          this.content = this.$refs.qeditor.content | 
				
			|||
          this.$axios.put('/admin/candidate/'+this.voteItemId,{ | 
				
			|||
            num: this.num, | 
				
			|||
            title:this.title, | 
				
			|||
            itemDesc : this.content, | 
				
			|||
            aid:this.$store.state.curCreateActivity.id, | 
				
			|||
            coverUrl:this.coverUrl, | 
				
			|||
            videoUrl:this.videoUrl, | 
				
			|||
            state:this.state | 
				
			|||
          }).then(resp =>{ | 
				
			|||
            if(resp && resp.data.code === 200){ | 
				
			|||
              this.$emit('onSubmit') | 
				
			|||
              this.clear() | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
        }, | 
				
			|||
        handleBindContent(){ | 
				
			|||
          this.$refs.qeditor.content = this.content | 
				
			|||
        }, | 
				
			|||
        setDialogWidth() { | 
				
			|||
          let val = document.body.clientWidth | 
				
			|||
          const def = 500 // 默认宽度 | 
				
			|||
          if (val < def) { | 
				
			|||
            this.dialogWidth = '100%' | 
				
			|||
          } else { | 
				
			|||
            this.dialogWidth = def + 'px' | 
				
			|||
          } | 
				
			|||
        }, | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
 | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,59 @@ | 
				
			|||
<template> | 
				
			|||
  <el-upload | 
				
			|||
    class="img-upload" | 
				
			|||
    ref="upload" | 
				
			|||
    action="http://localhost:8443/api/covers" | 
				
			|||
    with-credentials | 
				
			|||
    :on-preview="handlePreview" | 
				
			|||
    :on-remove="handleRemove" | 
				
			|||
    :before-remove="beforeRemove" | 
				
			|||
    :on-success="handleSuccess" | 
				
			|||
    multiple | 
				
			|||
    :limit="1" | 
				
			|||
    :on-exceed="handleExceed" | 
				
			|||
    :file-list="fileList"> | 
				
			|||
    <span>点击上传</span> | 
				
			|||
  </el-upload> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  export default { | 
				
			|||
    name: 'ImgUpload', | 
				
			|||
    data () { | 
				
			|||
      return { | 
				
			|||
        fileList: [], | 
				
			|||
        url: '' | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    methods: { | 
				
			|||
      handleRemove (file, fileList) { | 
				
			|||
        console.log(file, fileList) | 
				
			|||
      }, | 
				
			|||
      handlePreview (file) { | 
				
			|||
        console.log(file) | 
				
			|||
        // 此处的 file 是整个文件 | 
				
			|||
        // console.log(file.response) | 
				
			|||
      }, | 
				
			|||
      handleExceed (files, fileList) { | 
				
			|||
        this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`) | 
				
			|||
      }, | 
				
			|||
      beforeRemove (file, fileList) { | 
				
			|||
        return this.$confirm(`确定移除 ${file.name}?`) | 
				
			|||
      }, | 
				
			|||
      handleSuccess (response) { | 
				
			|||
        this.url = response | 
				
			|||
        this.$emit('onUpload') | 
				
			|||
        this.$message.warning('上传成功') | 
				
			|||
      }, | 
				
			|||
      clear () { | 
				
			|||
        this.$refs.upload.clearFiles() | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
  .img-upload { | 
				
			|||
    /*height: 200px;*/ | 
				
			|||
  } | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,307 @@ | 
				
			|||
<template> | 
				
			|||
 | 
				
			|||
  <div class="setItemsDiv"> | 
				
			|||
    <el-dialog | 
				
			|||
      title="活动链接" | 
				
			|||
      :visible.sync="dialogFormVisible" | 
				
			|||
      :modal-append-to-body="false" | 
				
			|||
      @close="clear" | 
				
			|||
      :width="dialogWidth"> | 
				
			|||
      <div class="qrcode" ref="qrCodeUrl" style="margin:50px auto;padding-left: 165px"></div> | 
				
			|||
      <div style="color: #36AAFF;"> | 
				
			|||
        <router-link :to="'/activityIndex/'+activityId">{{activityLink}}</router-link> | 
				
			|||
<!--        <a :href="activityLink" >{{activityLink}}</a>--> | 
				
			|||
      </div> | 
				
			|||
    </el-dialog> | 
				
			|||
    <el-row> | 
				
			|||
      <el-col :sm="1"  :xl="2"> </el-col> | 
				
			|||
      <el-col :sm="20"  :xs="24"> | 
				
			|||
        <el-card> | 
				
			|||
          <div> | 
				
			|||
            <div style="float: left"> | 
				
			|||
              最近的投票 | 
				
			|||
            </div> | 
				
			|||
            <div style="float: right"> | 
				
			|||
              <el-button type="primary" @click="toCreate">创建投票</el-button> | 
				
			|||
            </div> | 
				
			|||
          </div> | 
				
			|||
          <div style="text-align: left"> | 
				
			|||
            <el-table | 
				
			|||
              v-loading="loading" | 
				
			|||
              :data="activities" | 
				
			|||
              stripe | 
				
			|||
              :default-sort = "{prop: 'id', order: 'ascending'}" | 
				
			|||
              style="width: 100%" | 
				
			|||
              ref="multipleTable"> | 
				
			|||
              <el-table-column | 
				
			|||
                prop="title" | 
				
			|||
                label="标题" | 
				
			|||
                width="200"> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="状态" | 
				
			|||
                fit> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <el-tag type="info"  size="small" v-if="date.getTime() < Date.parse(scope.row.startTime)">未开始</el-tag> | 
				
			|||
                  <el-tag type="danger"  size="small" v-else-if="new Date().getTime() > Date.parse(scope.row.endTime)">已结束</el-tag> | 
				
			|||
                  <el-tag type="success" size="small" v-else>进行中</el-tag> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="活动时间" | 
				
			|||
                width="200"> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <div style="color: #999;">{{scope.row.startTime | fmtDate}}</div> | 
				
			|||
                  <!-- <div style="color: #999;">{{fmtDate}}</div> --> | 
				
			|||
                  <div style="color: #999;">{{scope.row.endTime | fmtDate}}</div> | 
				
			|||
                  <!-- <div style="color: #999;"></div> --> | 
				
			|||
                  <!-- <el-button  @click="test(scope)">wu</el-button> --> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="操作" | 
				
			|||
                width="500px"> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <el-button size="mini" type="danger"  @click="toDelVoteResult(scope.row)">删除</el-button> | 
				
			|||
                  <el-button size="mini" type="primary"  @click="editActivity(scope.row)">编辑</el-button> | 
				
			|||
                  <el-button size="mini" type="primary"  @click="editCandidate(scope.row)">选手管理</el-button> | 
				
			|||
                  <el-button size="mini" type="success"  @click="toVoteResult(scope.row)">统计</el-button> | 
				
			|||
                  <el-button size="mini"  type="warning" @click="showQrCode(scope.row)">链接</el-button> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
            </el-table> | 
				
			|||
            <div style="float: left;padding: 15px"> | 
				
			|||
              <el-pagination | 
				
			|||
                @current-change="handleCurrentChange" | 
				
			|||
                :current-page="currentPage" | 
				
			|||
                :page-size="pageSize" | 
				
			|||
                :total="totalSize"> | 
				
			|||
              </el-pagination> | 
				
			|||
          </div> | 
				
			|||
          </div> | 
				
			|||
        </el-card> | 
				
			|||
 | 
				
			|||
      </el-col> | 
				
			|||
 | 
				
			|||
    </el-row> | 
				
			|||
 | 
				
			|||
    <!-- <el-row> | 
				
			|||
      <el-col :sm="1"  :xl="2"> </el-col> | 
				
			|||
      <el-col :sm="20"  :xs="24"> | 
				
			|||
        <el-card style="margin-top: 20px"> | 
				
			|||
          <div style="float: left;margin-bottom: 20px"> | 
				
			|||
            最新公告 | 
				
			|||
          </div> | 
				
			|||
          <div style="text-align: left;"> | 
				
			|||
            <el-table | 
				
			|||
              v-loading="noticeLoading" | 
				
			|||
              :data="notices" | 
				
			|||
              stripe | 
				
			|||
              :default-sort = "{prop: 'id', order: 'ascending'}" | 
				
			|||
              style="width: 100%" | 
				
			|||
              ref="multipleTable" | 
				
			|||
              show-overflow-tooltip> | 
				
			|||
              <el-table-column | 
				
			|||
                label="标题" | 
				
			|||
                fit> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <router-link :to="'/notice/detail/'+scope.row.id" class="notice-link">{{scope.row.title}}</router-link> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="发布时间" | 
				
			|||
                fit> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <div style="color: #999;">{{scope.row.createTime | fmtDate}}</div> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
            </el-table> | 
				
			|||
            <div style="float: left;padding: 15px"> | 
				
			|||
              <el-pagination | 
				
			|||
                @current-change="handleNoticeCurrentChange" | 
				
			|||
                :current-page="noticeCurrentPage" | 
				
			|||
                :page-size="noticePageSize" | 
				
			|||
                :total="noticeTotalSize"> | 
				
			|||
              </el-pagination> | 
				
			|||
            </div> | 
				
			|||
            </div> | 
				
			|||
        </el-card> | 
				
			|||
 | 
				
			|||
      </el-col> | 
				
			|||
 | 
				
			|||
    </el-row> --> | 
				
			|||
 | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  import QRCode from 'qrcodejs2'; | 
				
			|||
  export default { | 
				
			|||
    name: 'ListActivity', | 
				
			|||
    data(){ | 
				
			|||
      return{ | 
				
			|||
        noticeLoading:false, | 
				
			|||
        loading: false, | 
				
			|||
        dialogWidth:'500px', | 
				
			|||
        currentPage:1, | 
				
			|||
        pageSize:6, | 
				
			|||
        totalSize:0, | 
				
			|||
        noticeCurrentPage:1, | 
				
			|||
        noticePageSize:4, | 
				
			|||
        noticeTotalSize:0, | 
				
			|||
        notices:[], | 
				
			|||
        activities:[], | 
				
			|||
        voteItems:[], | 
				
			|||
        date: new Date(), | 
				
			|||
        date_1:'', | 
				
			|||
        dialogFormVisible:false, | 
				
			|||
        activityLink:'', | 
				
			|||
        activityId:'', | 
				
			|||
        cur_date : this.$options.filters.fmtDate(new Date()) | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    mounted() { | 
				
			|||
      window.onresize = () => { | 
				
			|||
        return (() => { | 
				
			|||
          this.setDialogWidth() | 
				
			|||
        })() | 
				
			|||
      } | 
				
			|||
      this.listActivity() | 
				
			|||
      // this.listNotice() | 
				
			|||
 | 
				
			|||
    }, | 
				
			|||
    methods:{ | 
				
			|||
      // test(data){ | 
				
			|||
      //   console.dir(data); | 
				
			|||
      // }, | 
				
			|||
      listActivity(){ | 
				
			|||
 | 
				
			|||
        let _this = this | 
				
			|||
        this.loading = true | 
				
			|||
 | 
				
			|||
        this.$axios.get('/admin/activity/list/self?page='+_this.currentPage | 
				
			|||
          +'&size='+_this.pageSize | 
				
			|||
          +'&userName='+ _this.$store.state.user.userName) | 
				
			|||
          .then(resp =>{ | 
				
			|||
            if(resp && resp.data.code === 200){ | 
				
			|||
              console.dir(resp); | 
				
			|||
              _this.activities = resp.data.result.content | 
				
			|||
              _this.totalSize = resp.data.result.totalElements | 
				
			|||
              //mybatis | 
				
			|||
              // _this.activities = resp.data.result.activity; | 
				
			|||
              // _this.totalSize = resp.data.result.total; | 
				
			|||
              _this.loading = false | 
				
			|||
              console.dir(resp); | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
      }, | 
				
			|||
      //删除按钮对应的组件 | 
				
			|||
      // toDelVoteResult(activity){ | 
				
			|||
      //   let _this = this | 
				
			|||
      //   this.loading = true | 
				
			|||
      //   console.log(activity.id); | 
				
			|||
      //   // debugger | 
				
			|||
      //   this.$axios.get('/admin/activity/list/del?activityId='+activity.id    | 
				
			|||
      //     ).then(resp =>{ | 
				
			|||
      //       if(resp && resp.data.code === 200){ | 
				
			|||
      //         // console.log(resp) | 
				
			|||
      //         if(1 == resp.data.result){ | 
				
			|||
      //           _this.listActivity() | 
				
			|||
      //           // 成功 | 
				
			|||
 | 
				
			|||
      //         }else{ | 
				
			|||
      //           // 失败 | 
				
			|||
 | 
				
			|||
      //         }  | 
				
			|||
      //         _this.loading = false | 
				
			|||
      //       } | 
				
			|||
      //     }) | 
				
			|||
      // }, | 
				
			|||
      // { | 
				
			|||
      //   // function (data){ | 
				
			|||
 | 
				
			|||
      //   // }, | 
				
			|||
 | 
				
			|||
      //   // () => { | 
				
			|||
      //   // } | 
				
			|||
      // }, | 
				
			|||
      toCreate(){ | 
				
			|||
        this.$store.state.curCreateActivity = [] | 
				
			|||
        this.$router.replace('/admin/vote/add/index') | 
				
			|||
      }, | 
				
			|||
      editActivity(activity){ | 
				
			|||
        this.$store.commit('createActive', activity) | 
				
			|||
        this.$router.replace('/admin/vote/add/index') | 
				
			|||
      }, | 
				
			|||
      editCandidate(activity){ | 
				
			|||
        this.$store.commit('createActive', activity) | 
				
			|||
        this.$router.replace('/admin/vote/add/item') | 
				
			|||
      }, | 
				
			|||
      toVoteResult(activity){ | 
				
			|||
        this.$store.commit('createActive', activity) | 
				
			|||
        this.$router.replace('/admin/vote/list/result') | 
				
			|||
      }, | 
				
			|||
      showQrCode(activity){ | 
				
			|||
        this.dialogFormVisible = true | 
				
			|||
        this.activityId = activity.id | 
				
			|||
        this.activityLink = 'http://localhost:8080/activityIndex/'+activity.id | 
				
			|||
        this.$nextTick(function () { | 
				
			|||
          this.creatQrCode() | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      // creatQrCode() { | 
				
			|||
      //   let qrcode = new QRCode(this.$refs.qrCodeUrl, { | 
				
			|||
      //     text: this.activityLink, // 需要转换为二维码的内容 | 
				
			|||
      //     width: 120, | 
				
			|||
      //     height: 120, | 
				
			|||
      //     colorDark: '#000000', | 
				
			|||
      //     colorLight: '#ffffff', | 
				
			|||
      //     correctLevel: QRCode.CorrectLevel.H | 
				
			|||
      //   }) | 
				
			|||
      // }, | 
				
			|||
      clear(){ | 
				
			|||
        this.dialogFormVisible = false | 
				
			|||
        this.$refs.qrCodeUrl = '' | 
				
			|||
      }, | 
				
			|||
 | 
				
			|||
      handleCurrentChange(currentPage) { | 
				
			|||
        this.currentPage = currentPage | 
				
			|||
        this.listActivity() | 
				
			|||
      }, | 
				
			|||
      handleNoticeCurrentChange(noticeCurrentPage){ | 
				
			|||
        this.currentPage = noticeCurrentPage | 
				
			|||
        this.listNotice() | 
				
			|||
      }, | 
				
			|||
      listNotice(){ | 
				
			|||
        let _this = this | 
				
			|||
        this.noticeLoading = true | 
				
			|||
        this.$axios.get('/notice/list?page='+_this.noticeCurrentPage | 
				
			|||
          +'&size='+_this.noticePageSize) | 
				
			|||
          .then(resp =>{ | 
				
			|||
            if(resp && resp.data.code === 200){ | 
				
			|||
              _this.notices = resp.data.result.content | 
				
			|||
              _this.totalSize = resp.data.result.totalElements | 
				
			|||
              _this.noticeLoading = false | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
      }, | 
				
			|||
      }, | 
				
			|||
      setDialogWidth() { | 
				
			|||
        let val = document.body.clientWidth | 
				
			|||
        const def = 500 // 默认宽度 | 
				
			|||
        if (val < def) { | 
				
			|||
          this.dialogWidth = '100%' | 
				
			|||
        } else { | 
				
			|||
          this.dialogWidth = def + 'px' | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style> | 
				
			|||
 | 
				
			|||
  .notice-link{ | 
				
			|||
    color: #999; | 
				
			|||
    text-decoration:none; | 
				
			|||
  } | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,197 @@ | 
				
			|||
<template> | 
				
			|||
  <div class="setItemsDiv"> | 
				
			|||
    <CreateNav></CreateNav> | 
				
			|||
    <el-row> | 
				
			|||
      <el-col :sm="2" :xl="4"> </el-col> | 
				
			|||
      <el-col  :sm="16"  :xs="24"> | 
				
			|||
        <el-card> | 
				
			|||
          <el-form> | 
				
			|||
            <el-form-item> | 
				
			|||
                <div style="text-align: left;padding: 20px" > | 
				
			|||
                    <h3>投票规则</h3><hr> | 
				
			|||
                    <div style="width: 30%;float: left"> | 
				
			|||
                      <h4>投票类型</h4> | 
				
			|||
                         <el-radio v-model="voteType" label="single" >单选</el-radio> | 
				
			|||
                         <el-radio v-model="voteType" label="multiple" >多选</el-radio> | 
				
			|||
                    </div> | 
				
			|||
                  <div  style="width: 30%;float: left"> | 
				
			|||
                    <h4>投票时需要输入验证码</h4> | 
				
			|||
                    <el-radio v-model="verifyCode" label="1">是</el-radio> | 
				
			|||
                    <el-radio v-model="verifyCode" label="0">否</el-radio> | 
				
			|||
                  </div> | 
				
			|||
                  <div  style="width: 30%;float: left"> | 
				
			|||
                    <h4>周期设置</h4> | 
				
			|||
                    <el-radio v-model="cycleType" label="false">投完不能再投</el-radio> | 
				
			|||
                    <el-radio v-model="cycleType" label="true">每天都可以投</el-radio> | 
				
			|||
                  </div> | 
				
			|||
                </div> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item v-if="voteType === 'single' "> | 
				
			|||
                <div style="text-align: left;padding: 20px"> | 
				
			|||
                  <h4>[单选]票次限制</h4><hr> | 
				
			|||
                  <el-input placeholder="输入用户可以投的总票数" v-model="totalVotes" @blur="BlurText($event)" style="width: 45%;float: left"> | 
				
			|||
                    <template slot="prepend">每个用户可以投</template> | 
				
			|||
                    <template slot="append">票</template> | 
				
			|||
                  </el-input> | 
				
			|||
                  <el-input placeholder="输入可为同一选手投的票数" v-model="oneVotes"  @blur="BlurText($event)" style="width: 45%;float: right"> | 
				
			|||
                    <template slot="prepend">可为同一选手投</template> | 
				
			|||
                    <template slot="append">票</template> | 
				
			|||
                  </el-input> | 
				
			|||
                </div> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item v-else> | 
				
			|||
                <div style="text-align: left;padding: 20px"> | 
				
			|||
                  <h4>[多选]选手设置</h4><hr> | 
				
			|||
                  <el-input placeholder="输入最少可以选择的选手" v-model="least" @blur="BlurText($event)" style="width: 45%;float: left"> | 
				
			|||
                    <template slot="prepend">最少选择</template> | 
				
			|||
                    <template slot="append">个选手</template> | 
				
			|||
                  </el-input> | 
				
			|||
                  <el-input placeholder="输入最多可以选择的选手" v-model="most"  @blur="BlurText($event)" style="width: 45%;float: right"> | 
				
			|||
                    <template slot="prepend">最多选择</template> | 
				
			|||
                    <template slot="append">个选手</template> | 
				
			|||
                  </el-input> | 
				
			|||
                </div> | 
				
			|||
            </el-form-item> | 
				
			|||
          </el-form> | 
				
			|||
          <div style="padding-top:50px;"> | 
				
			|||
            <el-button @click="comeBack "> 返 回 </el-button> | 
				
			|||
            <el-button type="primary" @click="save()"> 发 布 </el-button> | 
				
			|||
          </div> | 
				
			|||
        </el-card> | 
				
			|||
      </el-col> | 
				
			|||
 | 
				
			|||
    </el-row> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
    import CreateNav from "./CreateNav"; | 
				
			|||
    export default { | 
				
			|||
        name: "VoteEdit", | 
				
			|||
      components: {CreateNav}, | 
				
			|||
      data(){ | 
				
			|||
            return{ | 
				
			|||
              voteType:'multiple', | 
				
			|||
              cycleType:'false', | 
				
			|||
              verifyCode:'0', | 
				
			|||
              input3:'', | 
				
			|||
              type:{}, | 
				
			|||
              totalVotes:'', | 
				
			|||
              oneVotes:'', | 
				
			|||
              least:'', | 
				
			|||
              most:'', | 
				
			|||
              curId:'', | 
				
			|||
              curActivity:[], | 
				
			|||
              singleType:{ | 
				
			|||
                  "voteType":'single', | 
				
			|||
                  "cycleType":'', | 
				
			|||
                  "totalVotes":'', | 
				
			|||
                  "oneVotes":'' | 
				
			|||
               }, | 
				
			|||
              multipleType:{ | 
				
			|||
                  "voteType":'multiple', | 
				
			|||
                  "cycleType":'', | 
				
			|||
                  "least":'', | 
				
			|||
                  "most":'' | 
				
			|||
              } | 
				
			|||
            } | 
				
			|||
        }, | 
				
			|||
        mounted() { | 
				
			|||
          this.getCurActivity() | 
				
			|||
        }, | 
				
			|||
        methods:{ | 
				
			|||
          getCurActivity(){ | 
				
			|||
              let curId = this.$store.state.curCreateActivity.id | 
				
			|||
              this.$axios.get('/activity/'+ curId).then(resp =>{ | 
				
			|||
                if(resp && resp.data.code === 200){ | 
				
			|||
                    this.curActivity = resp.data.result | 
				
			|||
                    let setType = JSON.parse(this.curActivity.type) | 
				
			|||
                    this.voteType = setType.voteType | 
				
			|||
                    this.cycleType = setType.cycleType | 
				
			|||
                    this.oneVotes = setType.oneVotes | 
				
			|||
                    this.totalVotes = setType.totalVotes | 
				
			|||
                    this.least = setType.least | 
				
			|||
                    this.most = setType.most | 
				
			|||
                    if(this.curActivity.verifyCode){ | 
				
			|||
                      this.verifyCode = '1' | 
				
			|||
                    } | 
				
			|||
                } | 
				
			|||
              }) | 
				
			|||
          }, | 
				
			|||
          save(){ | 
				
			|||
            if(this.voteType === 'single'){ | 
				
			|||
              this.singleType.cycleType = this.cycleType | 
				
			|||
              this.singleType.totalVotes = this.totalVotes | 
				
			|||
              this.singleType.oneVotes = this.oneVotes | 
				
			|||
              this.type = this.singleType | 
				
			|||
              if(this.totalVotes === undefined){ | 
				
			|||
                this.$message.error("请输入用户可以投的总票数") | 
				
			|||
                return; | 
				
			|||
              } | 
				
			|||
              if(this.oneVotes === undefined){ | 
				
			|||
                this.$message.error("请输入可为同一选手投的票数") | 
				
			|||
                return; | 
				
			|||
              } | 
				
			|||
              if(this.oneVotes > this.totalVotes){ | 
				
			|||
                this.$message.error("总票数不能大于为同一选手投的票数") | 
				
			|||
                return; | 
				
			|||
              } | 
				
			|||
            }else{ | 
				
			|||
             this.multipleType.cycleType = this.cycleType | 
				
			|||
             this.multipleType.least = this.least | 
				
			|||
             this.multipleType.most = this.most | 
				
			|||
             this.type = this.multipleType | 
				
			|||
              if(this.least === '' || this.least === undefined){ | 
				
			|||
                this.$message.error("请输入最少选择的选手") | 
				
			|||
                return; | 
				
			|||
              } | 
				
			|||
              if(this.most === '' || this.most === undefined){ | 
				
			|||
                this.$message.error("请输入最多选择的选手") | 
				
			|||
                return; | 
				
			|||
              } | 
				
			|||
              if(this.least > this.most){ | 
				
			|||
                this.$message.error("最多选择不能大于最少选择") | 
				
			|||
                return; | 
				
			|||
              } | 
				
			|||
            } | 
				
			|||
            let setVerifyCode = this.verifyCode === '1'? true : false | 
				
			|||
            console.log('verifyCode ===  1 == > ',this.verifyCode === '1') | 
				
			|||
            this.$axios.put('/admin/activity/'+this.curActivity.id,{ | 
				
			|||
              title:this.curActivity.title, | 
				
			|||
              startTime:this.curActivity.startTime, | 
				
			|||
              endTime:this.curActivity.endTime, | 
				
			|||
              content:this.curActivity.content, | 
				
			|||
              type:JSON.stringify(this.type), | 
				
			|||
              verifyCode: setVerifyCode, | 
				
			|||
              author:this.$store.state.user.userName | 
				
			|||
            }).then(resp =>{ | 
				
			|||
              if(resp && resp.data.code === 200){ | 
				
			|||
                this.$store.state.curCreateActivity = [] | 
				
			|||
                this.$message.success('发布成功') | 
				
			|||
                this.$router.replace('/admin/vote/list') | 
				
			|||
              } | 
				
			|||
            }) | 
				
			|||
          }, | 
				
			|||
          comeBack(){ | 
				
			|||
            this.$router.replace('/admin/vote/add/item') | 
				
			|||
          }, | 
				
			|||
          BlurText(e){ | 
				
			|||
            let boolean = new RegExp("^[1-9][0-9]*$").test(e.target.value) | 
				
			|||
            if(!boolean){ | 
				
			|||
              this.$message.warning("请输入一个正整数") | 
				
			|||
              e.target.value = '' | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
          } | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
  .setItemsDiv{ | 
				
			|||
    margin: 0 auto; | 
				
			|||
    height: 100%; | 
				
			|||
    width: 100%; | 
				
			|||
 | 
				
			|||
  } | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,394 @@ | 
				
			|||
<template> | 
				
			|||
  <div class="setItemsDiv"> | 
				
			|||
 | 
				
			|||
    <EditDesc  @onSubmit="listItem" ref="editDescDialog"></EditDesc> | 
				
			|||
 | 
				
			|||
    <el-dialog | 
				
			|||
      title="图片地址" | 
				
			|||
      :visible.sync="dialogFormVisible" | 
				
			|||
      :modal-append-to-body="false" | 
				
			|||
      @close="clear" | 
				
			|||
      width="30%"> | 
				
			|||
      <el-input v-model="imageLink"></el-input> | 
				
			|||
      <div style="margin-top: 20px"> | 
				
			|||
        <el-button type="primary" size="small" @click="submitImgLink">确定</el-button> | 
				
			|||
        <el-button size="small" @click="clear">取消</el-button> | 
				
			|||
      </div> | 
				
			|||
    </el-dialog> | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    <CreateNav></CreateNav> | 
				
			|||
    <el-row> | 
				
			|||
      <el-col :sm="2"  :xl="4"> </el-col> | 
				
			|||
      <el-col :sm="16"  :xs="24"> | 
				
			|||
        <el-card> | 
				
			|||
          <div style="text-align: left"> | 
				
			|||
            <el-button type="primary" @click="saveCandidate">添加选手</el-button> | 
				
			|||
            <el-button @click="toggleSelection()">取消选择</el-button> | 
				
			|||
            <!-- <el-button  @click="multipleRemove()">批量删除</el-button> --> | 
				
			|||
            <el-table | 
				
			|||
              v-loading="loading" | 
				
			|||
              :data="voteItems" | 
				
			|||
              stripe | 
				
			|||
              :default-sort = "{prop: 'id', order: 'ascending'}" | 
				
			|||
              style="width: 100%" | 
				
			|||
              ref="multipleTable" | 
				
			|||
              @selection-change="handleSelectionChange" | 
				
			|||
            > | 
				
			|||
              <el-table-column | 
				
			|||
                type="selection" | 
				
			|||
                width="55"> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                prop="coverUrl" | 
				
			|||
                label="封面" | 
				
			|||
                fit> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <img  :src="scope.row.coverUrl" alt=""  :onerror="errorImg01" style="width: 60px;height: 60px"> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                prop="num" | 
				
			|||
                label="编号" | 
				
			|||
                sortable | 
				
			|||
                fit> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <el-input  v-model="scope.row.num" placeholder="编号" style="width: 80%" @change="updateCandidate(scope.row)"></el-input> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="标题" | 
				
			|||
                fit> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <el-input  v-model="scope.row.title" placeholder="标题" @change="updateCandidate(scope.row)"></el-input> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="操作" | 
				
			|||
                width="380px"> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <el-button | 
				
			|||
                    plain | 
				
			|||
                    size="small" | 
				
			|||
                    @click="editItemDesc(scope.row)"> | 
				
			|||
                    修改描述<i class="el-icon-edit  el-icon--right"></i> | 
				
			|||
                  </el-button> | 
				
			|||
                  <el-dropdown trigger="click" > | 
				
			|||
                    <span class="el-dropdown-link"> | 
				
			|||
                      <el-button | 
				
			|||
                        plain | 
				
			|||
                        size="small"> | 
				
			|||
                         修改封面<i class="el-icon-picture  el-icon-right"></i> | 
				
			|||
                      </el-button> | 
				
			|||
                    </span> | 
				
			|||
                    <el-dropdown-menu slot="dropdown"> | 
				
			|||
                      <el-dropdown-item @click.native="inputImgLink(scope.row)"> | 
				
			|||
                          图片链接 | 
				
			|||
                      </el-dropdown-item> | 
				
			|||
                     <el-dropdown-item  @click.native="setCurCandidate(scope.row)"> | 
				
			|||
                         <el-upload | 
				
			|||
                           ref="upload" | 
				
			|||
                           action="http://localhost:8080/api/admin/candidate/covers" | 
				
			|||
                           with-credentials | 
				
			|||
                           :show-file-list="false" | 
				
			|||
                           :on-success="handleSuccess" | 
				
			|||
                            > | 
				
			|||
                           <span>点击上传</span> | 
				
			|||
                         </el-upload> | 
				
			|||
                      </el-dropdown-item> | 
				
			|||
                    </el-dropdown-menu> | 
				
			|||
                  </el-dropdown> | 
				
			|||
<!--                  <el-dropdown >--> | 
				
			|||
<!--                    <span class="el-dropdown-link">--> | 
				
			|||
<!--                      <el-button--> | 
				
			|||
<!--                        plain--> | 
				
			|||
<!--                        size="small">--> | 
				
			|||
<!--                         上传视频<i class="el-icon-upload  el-icon-right"></i>--> | 
				
			|||
<!--                      </el-button>--> | 
				
			|||
<!--                    </span>--> | 
				
			|||
<!--                    <el-dropdown-menu slot="dropdown">--> | 
				
			|||
<!--                      <el-dropdown-item @click.native="inputImgLink">--> | 
				
			|||
<!--                        视频链接--> | 
				
			|||
<!--                      </el-dropdown-item>--> | 
				
			|||
<!--                      <el-dropdown-item>--> | 
				
			|||
<!--                          <img-upload @onUpload="uploadImg" ref="imgUpload"></img-upload>--> | 
				
			|||
<!--                      </el-dropdown-item>--> | 
				
			|||
<!--                    </el-dropdown-menu>--> | 
				
			|||
<!--                  </el-dropdown>--> | 
				
			|||
                    <el-button | 
				
			|||
                      type="danger" plain | 
				
			|||
                      size="small" @click="deleteItem(scope.row)" > | 
				
			|||
                      删除选项<i class="el-icon-delete el-icon--right"></i> | 
				
			|||
                    </el-button> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="状态" | 
				
			|||
                fit> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <el-switch | 
				
			|||
                    v-model="scope.row.state" | 
				
			|||
                    active-color="#13ce66" | 
				
			|||
                    inactive-color="#ff4949" | 
				
			|||
                    @change="(value) => commitStatusChange(value, scope.row)"> | 
				
			|||
                  </el-switch> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
            </el-table> | 
				
			|||
          </div> | 
				
			|||
          <div style="float: left;padding: 20px"> | 
				
			|||
            <el-pagination | 
				
			|||
              @current-change="handleCurrentChange" | 
				
			|||
              :current-page="currentPage" | 
				
			|||
              :page-size="pageSize" | 
				
			|||
              :total="totalSize"> | 
				
			|||
            </el-pagination> | 
				
			|||
          </div> | 
				
			|||
          <div style="padding-top:  20px"> | 
				
			|||
            <el-button  @click="comeBack"> 返  回 </el-button> | 
				
			|||
            <el-button type="primary" @click="nextStep">下一步</el-button> | 
				
			|||
          </div> | 
				
			|||
        </el-card> | 
				
			|||
      </el-col> | 
				
			|||
 | 
				
			|||
    </el-row> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  import Qeditor from "../../common/Qeditor"; | 
				
			|||
  import CreateNav from "./CreateNav"; | 
				
			|||
  import EditDesc from "./EditDesc"; | 
				
			|||
  // import ImgUpload from "./ImgUpload"; ImgUpload, | 
				
			|||
  export default { | 
				
			|||
    name: "VoteItem", | 
				
			|||
    components: {EditDesc, CreateNav, Qeditor}, | 
				
			|||
    data(){ | 
				
			|||
      return{ | 
				
			|||
        loading:false, | 
				
			|||
        dialogFormVisible:false, | 
				
			|||
        currentPage:1, | 
				
			|||
        pageSize:5, | 
				
			|||
        totalSize:0, | 
				
			|||
        value1: '', | 
				
			|||
        value2: '', | 
				
			|||
        voteItems:[], | 
				
			|||
        num:0, | 
				
			|||
        testLink:'', | 
				
			|||
        imageLink:'', | 
				
			|||
        curItemId:0, | 
				
			|||
        curCandidate:{ | 
				
			|||
          id:0, | 
				
			|||
          num:0, | 
				
			|||
          title:'新增的标题', | 
				
			|||
          subTitle:'', | 
				
			|||
          itemDesc:'', | 
				
			|||
          coverUrl:'', | 
				
			|||
          videoUrl:'', | 
				
			|||
          getVote:0, | 
				
			|||
          state:'' | 
				
			|||
        }, | 
				
			|||
        errorImg01: 'this.src="' + require('../../../img/defaultImg.png') + '"', | 
				
			|||
        multipleSelection:[], | 
				
			|||
        selectedCandidateIds:[], | 
				
			|||
        dialogWidth:'100%', | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    mounted(){ | 
				
			|||
      this.listItem() | 
				
			|||
    }, | 
				
			|||
    methods:{ | 
				
			|||
      handleSelectionChange(val){ | 
				
			|||
         this.multipleSelection = val; | 
				
			|||
      }, | 
				
			|||
      toggleSelection(rows) { | 
				
			|||
          if (rows) { | 
				
			|||
            rows.forEach(row => { | 
				
			|||
              this.$refs.multipleTable.toggleRowSelection(row); | 
				
			|||
            }); | 
				
			|||
          } else { | 
				
			|||
            this.$refs.multipleTable.clearSelection(); | 
				
			|||
          } | 
				
			|||
      }, | 
				
			|||
      editItemDesc(item){ | 
				
			|||
        this.$refs.editDescDialog.dialogFormVisible = true | 
				
			|||
        setTimeout(()=>{ | 
				
			|||
          this.$refs.editDescDialog.content = item.itemDesc | 
				
			|||
          this.$refs.editDescDialog.voteItemId = item.id | 
				
			|||
          this.$refs.editDescDialog.num = item.num | 
				
			|||
          this.$refs.editDescDialog.coverUrl = item.coverUrl | 
				
			|||
          this.$refs.editDescDialog.videoUrl = item.videoUrl | 
				
			|||
          this.$refs.editDescDialog.title = item.title | 
				
			|||
          this.$refs.editDescDialog.state = item.state | 
				
			|||
          this.$refs.editDescDialog.handleBindContent() | 
				
			|||
        },10) | 
				
			|||
      }, | 
				
			|||
      inputImgLink(item){ | 
				
			|||
        this.dialogFormVisible = true | 
				
			|||
        this.curCandidate.id = item.id | 
				
			|||
        this.curCandidate.title = item.title | 
				
			|||
        this.curCandidate.num = item.num | 
				
			|||
        this.curCandidate.subTitle = item.subTitle | 
				
			|||
        this.curCandidate.itemDesc = item.itemDesc | 
				
			|||
        this.curCandidate.coverUrl = item.coverUrl | 
				
			|||
        this.curCandidate.videoUrl= item.videoUrl | 
				
			|||
        this.curCandidate.aid = item.aid | 
				
			|||
        this.curCandidate.state = item.state | 
				
			|||
        this.imageLink = item.coverUrl | 
				
			|||
      }, | 
				
			|||
      setCurCandidate(item){ | 
				
			|||
        this.curCandidate.id = item.id | 
				
			|||
        this.curCandidate.title = item.title | 
				
			|||
        this.curCandidate.num = item.num | 
				
			|||
        this.curCandidate.subTitle = item.subTitle | 
				
			|||
        this.curCandidate.itemDesc = item.itemDesc | 
				
			|||
        this.curCandidate.coverUrl = item.coverUrl | 
				
			|||
        this.curCandidate.videoUrl= item.videoUrl | 
				
			|||
        this.curCandidate.aid = item.aid | 
				
			|||
      }, | 
				
			|||
      clear(){ | 
				
			|||
        this.dialogFormVisible = false | 
				
			|||
        this.imageLink = '' | 
				
			|||
      }, | 
				
			|||
      submitImgLink(){ | 
				
			|||
        this.$axios.put('/admin/candidate/'+this.curCandidate.id,{ | 
				
			|||
          title:this.curCandidate.title, | 
				
			|||
          num:this.curCandidate.num, | 
				
			|||
          subTitle:this.curCandidate.subTitle, | 
				
			|||
          itemDesc:this.curCandidate.itemDesc, | 
				
			|||
          coverUrl:this.imageLink, | 
				
			|||
          videoUrl:this.curCandidate.videoUrl, | 
				
			|||
          state:this.curCandidate.state, | 
				
			|||
          aid:this.curCandidate.aid | 
				
			|||
        }).then(resp =>{ | 
				
			|||
          this.dialogFormVisible = false | 
				
			|||
          this.listItem() | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      listItem(){ | 
				
			|||
        let _this = this | 
				
			|||
        this.loading = true | 
				
			|||
        this.$axios.get('/admin/candidate/list/'+this.$store.state.curCreateActivity.id | 
				
			|||
          +'?page='+_this.currentPage+'&size='+_this.pageSize).then(resp =>{ | 
				
			|||
          if(resp && resp.data.code === 200){ | 
				
			|||
            // console.dir(resp.data); | 
				
			|||
            this.totalSize = resp.data.result.totalElements | 
				
			|||
            this.voteItems = resp.data.result.content | 
				
			|||
            this.loading =  false | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      saveCandidate(){ | 
				
			|||
        this.num = ++this.voteItems.length; // 0 1 2 3 4 5 | 
				
			|||
        // console.log(this.num); | 
				
			|||
        this.$axios.post('/admin/candidate',{ | 
				
			|||
          num:this.num, | 
				
			|||
          coverUrl:'', | 
				
			|||
          title:'新增的标题', | 
				
			|||
          aid:this.$store.state.curCreateActivity.id | 
				
			|||
        }).then(resp =>{ | 
				
			|||
            this.listItem() | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      updateCandidate(item){ | 
				
			|||
        this.$axios.put('/admin/candidate/'+item.id,{ | 
				
			|||
          title: item.title, | 
				
			|||
          num:item.num, | 
				
			|||
          subTitle:item.subTitle, | 
				
			|||
          itemDesc:item.itemDesc, | 
				
			|||
          coverUrl:item.coverUrl, | 
				
			|||
          videoUrl:item.videoUrl, | 
				
			|||
          getVote:item.getVote, | 
				
			|||
          state:item.state, | 
				
			|||
          aid:item.aid | 
				
			|||
        }).then(resp =>{ | 
				
			|||
          this.listItem() | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      deleteItem(item){ | 
				
			|||
        this.$confirm('确认删除选项?', '提示', { | 
				
			|||
          confirmButtonText: '确定', | 
				
			|||
          cancelButtonText: '取消', | 
				
			|||
          type: 'warning' | 
				
			|||
        }).then(() => { | 
				
			|||
            this.$axios | 
				
			|||
              .delete('/admin/candidate/'+item.id).then(resp => { | 
				
			|||
              if (resp && resp.data.code === 200) { | 
				
			|||
                this.listItem() | 
				
			|||
                this.$message({ | 
				
			|||
                  type: 'info', | 
				
			|||
                  message: '删除成功' | 
				
			|||
                }) | 
				
			|||
              } | 
				
			|||
            }) | 
				
			|||
          } | 
				
			|||
        ).catch(() => { | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      commitStatusChange(value, item) { | 
				
			|||
          this.$axios.put('/admin/candidate/state/'+item.id+'?state='+value).then(resp => { | 
				
			|||
            if (resp && resp.data.code === 200) { | 
				
			|||
              if (value) { | 
				
			|||
                this.$message('候选人 [' + item.title + '] 已启用') | 
				
			|||
              } else { | 
				
			|||
                this.$message('候选人 [' + item.title + '] 已禁用') | 
				
			|||
              } | 
				
			|||
            } | 
				
			|||
          }) | 
				
			|||
      }, | 
				
			|||
      uploadImg(){ | 
				
			|||
             this.testLink = this.$refs.imgUpload.url | 
				
			|||
             this.$refs.imgUpload.clear() | 
				
			|||
      }, | 
				
			|||
      comeBack(){ | 
				
			|||
        this.$router.replace('/admin/vote/add/index') | 
				
			|||
      }, | 
				
			|||
      nextStep(){ | 
				
			|||
        this.$router.replace('/admin/vote/add/setting') | 
				
			|||
      }, | 
				
			|||
 | 
				
			|||
      handleSuccess (response) { | 
				
			|||
        this.imageLink = response | 
				
			|||
        this.submitImgLink() | 
				
			|||
        this.$message.warning('上传成功') | 
				
			|||
      }, | 
				
			|||
      multipleRemove(){ | 
				
			|||
        if(this.multipleSelection.length < 1){ | 
				
			|||
          this.$message.error("请选择所要删除的选项") | 
				
			|||
          return | 
				
			|||
        } | 
				
			|||
        this.$confirm('确认删除选项?', '提示', { | 
				
			|||
          confirmButtonText: '确定', | 
				
			|||
          cancelButtonText: '取消', | 
				
			|||
          type: 'warning'}).then(() =>{ | 
				
			|||
            for(let i = 0; i<this.multipleSelection.length; i++){ | 
				
			|||
              this.selectedCandidateIds += this.multipleSelection[i].id + ' ' | 
				
			|||
            } | 
				
			|||
            this.$axios.delete('/admin/candidate/batch?selectedCandidateIds='+ this.selectedCandidateIds,{ | 
				
			|||
            }).then(resp =>{ | 
				
			|||
              if(resp.data.code === 200){ | 
				
			|||
                this.$alert("删除成功") | 
				
			|||
                this.selectedCandidateIds='' | 
				
			|||
                this.listItem() | 
				
			|||
                // this.$router.replace('/admin/vote/add/item') | 
				
			|||
              } | 
				
			|||
            }) | 
				
			|||
          }) | 
				
			|||
      }, | 
				
			|||
      handleCurrentChange(currentPage) { | 
				
			|||
        this.currentPage = currentPage | 
				
			|||
        this.listItem() | 
				
			|||
      }, | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
  .setItemsDiv{ | 
				
			|||
    /* border: 2px; */ | 
				
			|||
    margin: 0px auto; | 
				
			|||
    height: 100%; | 
				
			|||
    width: 100%; | 
				
			|||
 | 
				
			|||
  } | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,103 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <el-row> | 
				
			|||
      <el-col :sm="1"  :xl="2"> </el-col> | 
				
			|||
      <el-col :sm="20"  :xs="24"> | 
				
			|||
        <div style="margin: 20px"> | 
				
			|||
          <el-breadcrumb separator="/"> | 
				
			|||
            <el-breadcrumb-item :to="{ path: '/admin/vote/list' }">投票管理</el-breadcrumb-item> | 
				
			|||
            <el-breadcrumb-item >结果统计</el-breadcrumb-item> | 
				
			|||
          </el-breadcrumb> | 
				
			|||
        </div> | 
				
			|||
        <el-card> | 
				
			|||
          <div style="text-align: left"> | 
				
			|||
            投票结果 | 
				
			|||
           <a :href="'http://localhost:8443/api/download-result/'+this.$store.state.curCreateActivity.id"> | 
				
			|||
             <el-button type="primary" size="mini" style="float: right;margin-bottom: 20px">导出为Excel</el-button> | 
				
			|||
           </a> | 
				
			|||
            <hr style= "border:1px dashed #999" /> | 
				
			|||
            <el-table | 
				
			|||
              :data="voteItems" | 
				
			|||
              stripe | 
				
			|||
              :default-sort = "{prop: 'id', order: 'ascending'}" | 
				
			|||
              style="width: 100%" | 
				
			|||
              ref="multipleTable" | 
				
			|||
              > | 
				
			|||
              <el-table-column | 
				
			|||
                label="排名" | 
				
			|||
                fit | 
				
			|||
                type="index" | 
				
			|||
                :index="countIndex" | 
				
			|||
                width="100"> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                prop="coverUrl" | 
				
			|||
                label="封面" | 
				
			|||
                fit> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <img  :src="scope.row.coverUrl" alt=""  :onerror="errorImg01" style="width: 60px;height: 60px"> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                prop="title" | 
				
			|||
                label="标题" | 
				
			|||
                fit> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                label="占比" | 
				
			|||
                width="200"> | 
				
			|||
                <template slot-scope="scope"> | 
				
			|||
                  <el-progress :text-inside="true" :stroke-width="18" :percentage="parseInt((scope.row.voteCount/sumVotes)*100) > 0 ? parseInt((scope.row.voteCount/sumVotes)*100) : 0"></el-progress> | 
				
			|||
                </template> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column | 
				
			|||
                prop="voteCount" | 
				
			|||
                label="得票" | 
				
			|||
                fit> | 
				
			|||
              </el-table-column> | 
				
			|||
 | 
				
			|||
            </el-table> | 
				
			|||
          </div> | 
				
			|||
        </el-card> | 
				
			|||
      </el-col> | 
				
			|||
    </el-row> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  export default { | 
				
			|||
    name: "VoteResult", | 
				
			|||
    data(){ | 
				
			|||
      return{ | 
				
			|||
        sumVotes:0, | 
				
			|||
        voteItems:[], | 
				
			|||
        errorImg01: 'this.src="' + require('../../../img/defaultImg.png') + '"', | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    mounted() { | 
				
			|||
      this.getTotal() | 
				
			|||
    }, | 
				
			|||
    methods:{ | 
				
			|||
      getTotal(){ | 
				
			|||
        let _this = this | 
				
			|||
        this.$axios.get('/candidate/list/sequence/'+this.$store.state.curCreateActivity.id).then(resp =>{ | 
				
			|||
          if(resp && resp.data.code === 200){ | 
				
			|||
            _this.voteItems = resp.data.result | 
				
			|||
            _this.totalSize = resp.data.result.length | 
				
			|||
            _this.sumVotes = 0 | 
				
			|||
            for(let i=0; i<_this.voteItems.length; i++){ | 
				
			|||
              _this.sumVotes+=this.voteItems[i].voteCount | 
				
			|||
            } | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      countIndex(index){ | 
				
			|||
        return index+1 | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
 | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,214 @@ | 
				
			|||
<template> | 
				
			|||
  <div class="qeidtor"> | 
				
			|||
    <div class="upload-img-container"> | 
				
			|||
      <el-upload | 
				
			|||
        class="avatarUploader" | 
				
			|||
        action="http://localhost:8443/api/admin/candidate/covers" | 
				
			|||
        with-credentials | 
				
			|||
        :show-file-list="false" | 
				
			|||
        :on-success="handleAvatarSuccess" | 
				
			|||
        :before-upload="beforeAvatarUpload"> | 
				
			|||
        <img v-if="imageUrl" :src="imageUrl" class="avatar" /> | 
				
			|||
        <i v-else class="el-icon-plus avatar-uploader-icon"></i> | 
				
			|||
      </el-upload> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
    <quill-editor | 
				
			|||
      class="el_quill" | 
				
			|||
      id="myQuillEditorId" | 
				
			|||
      v-model="content" | 
				
			|||
      ref="myQuillEditor" | 
				
			|||
      :options="editorOption" | 
				
			|||
      @blur="onEditorBlur($event)" @focus="onEditorFocus($event)" | 
				
			|||
      @change="onEditorChange($event)"> | 
				
			|||
    </quill-editor> | 
				
			|||
    <div> | 
				
			|||
    </div> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  const toolbarOptions = [ | 
				
			|||
    ['bold', 'italic', 'underline', 'strike'], //加粗,斜体,下划线,删除线 | 
				
			|||
    ['blockquote', 'code-block'], //引用、代码块儿 | 
				
			|||
    [{ header: 1 }, { header: 2 }], //标题,键值对的形式;1、2表示字体大小 | 
				
			|||
    [{ list: 'ordered' }, { list: 'bullet' }], //列表 | 
				
			|||
    [{ script: 'sub' }, { script: 'super' }], //上下标 | 
				
			|||
    // [{ indent: '-1' }, { indent: '+1' }], //缩进 | 
				
			|||
    [{ direction: 'rtl' }], //文本方向 | 
				
			|||
    [{ size: ['small', false, 'large', 'huge'] }], //字体大小 | 
				
			|||
    [{ header: [1, 2, 3, 4, 5, 6, false] }], //几级标题 | 
				
			|||
    [{ color: [] }, { background: [] }], //字体颜色,字体背景颜色 | 
				
			|||
    [{ font: [] }], //字体 | 
				
			|||
    [{ align: [] }], //对齐方式 | 
				
			|||
    ['clean'], //清除字体样式 | 
				
			|||
    ['image'], //上传图片、上传视频(video)、超链接(link) | 
				
			|||
  ] | 
				
			|||
  export default { | 
				
			|||
    name:'Qeditor', | 
				
			|||
    data(){ | 
				
			|||
      return { | 
				
			|||
        content: `<p></p>`, | 
				
			|||
        imageUrl: '', | 
				
			|||
        editorOption: { | 
				
			|||
          modules: { | 
				
			|||
            clipboard: { | 
				
			|||
              // 粘贴版,处理粘贴时候的自带样式 | 
				
			|||
              matchers: [[Node.ELEMENT_NODE, this.HandleCustomMatcher]], | 
				
			|||
            }, | 
				
			|||
            toolbar: { | 
				
			|||
              container: toolbarOptions, // 工具栏 | 
				
			|||
              handlers: { | 
				
			|||
                image: function(value) { | 
				
			|||
                  if (value) { | 
				
			|||
                    // 获取隐藏的上传图片的class,不一定是.el-icon-plus。触发上传图片事件 | 
				
			|||
                    document.querySelector('.el-icon-plus').click() | 
				
			|||
                  } else { | 
				
			|||
                    this.quill.format('image', false) | 
				
			|||
                  } | 
				
			|||
                }, | 
				
			|||
              }, | 
				
			|||
            }, | 
				
			|||
          }, | 
				
			|||
          placeholder: '', | 
				
			|||
          theme:'snow' | 
				
			|||
        }, | 
				
			|||
 | 
				
			|||
 | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    computed: {}, | 
				
			|||
    async mounted() {}, | 
				
			|||
    methods: { | 
				
			|||
      handleAvatarSuccess(res) { | 
				
			|||
        // 图片上传成功后的回调 | 
				
			|||
        let quill = this.$refs.myQuillEditor.quill | 
				
			|||
        // 上传服务成功后,按根据光标位置把图片插入编辑器中 | 
				
			|||
        if (res) { | 
				
			|||
          // 获取光标所在位置,data.url表示上传服务后返回的图片地址 | 
				
			|||
          let length = quill.getSelection().index | 
				
			|||
          // 插入图片,data.url为服务返回的图片链接地址 | 
				
			|||
          quill.insertEmbed(length, 'image', res) | 
				
			|||
          // 调整光标到最后 | 
				
			|||
          quill.setSelection(length + 1) | 
				
			|||
        } else { | 
				
			|||
          this.$message.closeAll() | 
				
			|||
          this.$message.error('图片插入失败') | 
				
			|||
        } | 
				
			|||
      }, | 
				
			|||
      beforeAvatarUpload(data) { | 
				
			|||
        // 思路:上传图片至服务后,拿到返回的图片地址。直接创建image标签插入光标所在的位置 | 
				
			|||
        // 图片上传服务(本地服务或者阿里云服务) | 
				
			|||
        // 获取富文本组件实例 | 
				
			|||
 | 
				
			|||
      }, | 
				
			|||
      onEditorReady(editor) { // 准备编辑器 | 
				
			|||
      }, | 
				
			|||
      onEditorBlur(){}, // 失去焦点事件 | 
				
			|||
      onEditorFocus(){}, // 获得焦点事件 | 
				
			|||
      onEditorChange(el){// 内容改变事件 | 
				
			|||
      }, | 
				
			|||
      saveHtml:function(event){ | 
				
			|||
        alert(this.content); | 
				
			|||
      }, | 
				
			|||
      HandleCustomMatcher(node, Delta) { | 
				
			|||
        // 文字、图片等,从别处复制而来,清除自带样式,转为纯文本 | 
				
			|||
        let ops = [] | 
				
			|||
        Delta.ops.forEach(op => { | 
				
			|||
          if (op.insert && typeof op.insert === 'string') { | 
				
			|||
            ops.push({ | 
				
			|||
              insert: op.insert, | 
				
			|||
            }) | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
        Delta.ops = ops | 
				
			|||
        return Delta | 
				
			|||
      }, | 
				
			|||
    }, | 
				
			|||
 | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style> | 
				
			|||
  .qeidtor{ | 
				
			|||
    height: 420px; | 
				
			|||
  } | 
				
			|||
  .el_quill{ | 
				
			|||
    height:380px; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
  .ql-snow .ql-tooltip[data-mode=link]::before { | 
				
			|||
    content: "请输入链接地址:" !important; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-tooltip.ql-editing a.ql-action::after { | 
				
			|||
    border-right: 0px; | 
				
			|||
    content: '保存' !important; | 
				
			|||
    padding-right: 0px; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-tooltip[data-mode=video]::before { | 
				
			|||
    content: "请输入视频地址:" !important; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-picker.ql-size .ql-picker-label::before, | 
				
			|||
  .ql-snow .ql-picker.ql-size .ql-picker-item::before { | 
				
			|||
    content: '14px' !important; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before, | 
				
			|||
  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before { | 
				
			|||
    content: '10px' !important; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before, | 
				
			|||
  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before { | 
				
			|||
    content: '18px' !important; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before, | 
				
			|||
  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before { | 
				
			|||
    content: '32px' !important; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-label::before, | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-item::before { | 
				
			|||
    content: '文本' !important; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { | 
				
			|||
    content: '标题1' !important; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { | 
				
			|||
    content: '标题2' !important; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { | 
				
			|||
    content: '标题3' !important; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { | 
				
			|||
    content: '标题4' !important; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { | 
				
			|||
    content: '标题5' !important; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, | 
				
			|||
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { | 
				
			|||
    content: '标题6' !important; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .ql-snow .ql-picker.ql-font .ql-picker-label::before, | 
				
			|||
  .ql-snow .ql-picker.ql-font .ql-picker-item::before { | 
				
			|||
    content: '标准字体' !important; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before, | 
				
			|||
  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before { | 
				
			|||
    content: '衬线字体' !important; | 
				
			|||
  } | 
				
			|||
  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before, | 
				
			|||
  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before { | 
				
			|||
    content: '等宽字体' !important; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .upload-img-container{ | 
				
			|||
    display: none; | 
				
			|||
  } | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,85 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <el-row :gutter="20"> | 
				
			|||
      <el-col :xs="20" :sm="18"> | 
				
			|||
        <div class="grid-content bg-purple" style="margin-left: 20%" v-if="userName"> | 
				
			|||
          <el-menu | 
				
			|||
            :default-active="'/index'" | 
				
			|||
            router | 
				
			|||
            mode="horizontal" | 
				
			|||
            background-color="white" | 
				
			|||
            style="min-width: 1300px"> | 
				
			|||
            <el-menu-item v-for="(item,i) in navList" :key="i" :index="item.name"> | 
				
			|||
              {{ item.navItem }} | 
				
			|||
            </el-menu-item> | 
				
			|||
          </el-menu> | 
				
			|||
        </div> | 
				
			|||
      </el-col> | 
				
			|||
      <el-col :xs="4" :sm="6"> | 
				
			|||
        <div class="grid-content bg-purple" style="float: left"  v-if="userName"> | 
				
			|||
          <el-dropdown style="float: right" class="dropdown-link"> | 
				
			|||
        <span class="el-dropdown-link" > | 
				
			|||
       <img src="../../img/defaultImg.png" style="border-radius: 100%;width: 45px"> | 
				
			|||
        <span>{{userName}}</span> | 
				
			|||
        </span> | 
				
			|||
            <el-dropdown-menu slot="dropdown"> | 
				
			|||
              <el-dropdown-item>账户信息</el-dropdown-item> | 
				
			|||
              <el-dropdown-item @click.native="logout">退出登录</el-dropdown-item> | 
				
			|||
            </el-dropdown-menu> | 
				
			|||
          </el-dropdown> | 
				
			|||
        </div> | 
				
			|||
        <div v-else> | 
				
			|||
          <a href="Login"> <el-button>登录</el-button></a> | 
				
			|||
          <a href="Register"> <el-button>注册</el-button></a> | 
				
			|||
        </div> | 
				
			|||
      </el-col> | 
				
			|||
    </el-row> | 
				
			|||
    <el-row  v-if="username"> | 
				
			|||
      <el-col :xl="4"> </el-col> | 
				
			|||
      <el-col :sm="16"  :xs="24"> | 
				
			|||
 | 
				
			|||
      </el-col> | 
				
			|||
    </el-row> | 
				
			|||
  </div> | 
				
			|||
 | 
				
			|||
 | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  export default { | 
				
			|||
    name: "TopNav", | 
				
			|||
    data(){ | 
				
			|||
      return{ | 
				
			|||
        userName:this.$store.state.user.userName, | 
				
			|||
        activeIndex: 'listActivity', | 
				
			|||
        navList: [ | 
				
			|||
          {name: '/index', navItem: '首页'}, | 
				
			|||
          {name: '/listActivity', navItem: '投票管理'}, | 
				
			|||
          {name: '/userProfile', navItem: '账户信息'}, | 
				
			|||
        ], | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    methods:{ | 
				
			|||
      logout () { | 
				
			|||
        let _this = this | 
				
			|||
        this.$axios.get('/logout').then(resp => { | 
				
			|||
          if (resp.data.code === 200) { | 
				
			|||
            _this.$store.commit('logout') | 
				
			|||
            _this.$router.replace('/login') | 
				
			|||
        } | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      handleSelect(key, keyPath) { | 
				
			|||
        console.log(key, keyPath); | 
				
			|||
      } | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
  .dropdown-link{ | 
				
			|||
    margin-right: 100px; | 
				
			|||
    margin-top: 10px; | 
				
			|||
  } | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,159 @@ | 
				
			|||
<!-- <template> | 
				
			|||
    <div> | 
				
			|||
      <el-container style="height: 500px; border: 1px solid #eee"> | 
				
			|||
        <el-aside width="200px" style="background-color: rgb(238, 241, 246)"> | 
				
			|||
          <el-menu :default-openeds="['1', '3']"> | 
				
			|||
            <el-submenu index="1"> | 
				
			|||
              <template slot="title"><i class="el-icon-message"></i>导航一</template> | 
				
			|||
              <el-menu-item-group> | 
				
			|||
                <template slot="title">分组一</template> | 
				
			|||
                <el-menu-item index="1-1">选项1</el-menu-item> | 
				
			|||
                <el-menu-item index="1-2">选项2</el-menu-item> | 
				
			|||
              </el-menu-item-group> | 
				
			|||
              <el-menu-item-group title="分组2"> | 
				
			|||
                <el-menu-item index="1-3">选项3</el-menu-item> | 
				
			|||
              </el-menu-item-group> | 
				
			|||
              <el-submenu index="1-4"> | 
				
			|||
                <template slot="title">选项4</template> | 
				
			|||
                <el-menu-item index="1-4-1">选项4-1</el-menu-item> | 
				
			|||
              </el-submenu> | 
				
			|||
            </el-submenu> | 
				
			|||
            <el-submenu index="2"> | 
				
			|||
              <template slot="title"><i class="el-icon-menu"></i>导航二</template> | 
				
			|||
              <el-menu-item-group> | 
				
			|||
                <template slot="title">分组一</template> | 
				
			|||
                <el-menu-item index="2-1">选项1</el-menu-item> | 
				
			|||
                <el-menu-item index="2-2">选项2</el-menu-item> | 
				
			|||
              </el-menu-item-group> | 
				
			|||
              <el-menu-item-group title="分组2"> | 
				
			|||
                <el-menu-item index="2-3">选项3</el-menu-item> | 
				
			|||
              </el-menu-item-group> | 
				
			|||
              <el-submenu index="2-4"> | 
				
			|||
                <template slot="title">选项4</template> | 
				
			|||
                <el-menu-item index="2-4-1">选项4-1</el-menu-item> | 
				
			|||
              </el-submenu> | 
				
			|||
            </el-submenu> | 
				
			|||
            <el-submenu index="3"> | 
				
			|||
              <template slot="title"><i class="el-icon-setting"></i>导航三</template> | 
				
			|||
              <el-menu-item-group> | 
				
			|||
                <template slot="title">分组一</template> | 
				
			|||
                <el-menu-item index="3-1">选项1</el-menu-item> | 
				
			|||
                <el-menu-item index="3-2">选项2</el-menu-item> | 
				
			|||
              </el-menu-item-group> | 
				
			|||
              <el-menu-item-group title="分组2"> | 
				
			|||
                <el-menu-item index="3-3">选项3</el-menu-item> | 
				
			|||
              </el-menu-item-group> | 
				
			|||
              <el-submenu index="3-4"> | 
				
			|||
                <template slot="title">选项4</template> | 
				
			|||
                <el-menu-item index="3-4-1">选项4-1</el-menu-item> | 
				
			|||
              </el-submenu> | 
				
			|||
            </el-submenu> | 
				
			|||
          </el-menu> | 
				
			|||
        </el-aside> | 
				
			|||
 | 
				
			|||
        <el-container> | 
				
			|||
          <el-header style="text-align: right; font-size: 12px"> | 
				
			|||
            <el-dropdown> | 
				
			|||
              <i class="el-icon-setting" style="margin-right: 15px"></i> | 
				
			|||
              <el-dropdown-menu slot="dropdown"> | 
				
			|||
                <el-dropdown-item>查看</el-dropdown-item> | 
				
			|||
                <el-dropdown-item>新增</el-dropdown-item> | 
				
			|||
                <el-dropdown-item>删除</el-dropdown-item> | 
				
			|||
              </el-dropdown-menu> | 
				
			|||
            </el-dropdown> | 
				
			|||
            <span>王小虎</span> | 
				
			|||
          </el-header> | 
				
			|||
 | 
				
			|||
          <el-main aria-rowindex="200"> | 
				
			|||
            <el-table :data="tableData"> | 
				
			|||
              <el-table-column prop="date" label="日期" width="140"> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column prop="name" label="姓名" width="120"> | 
				
			|||
              </el-table-column> | 
				
			|||
              <el-table-column prop="address" label="地址"> | 
				
			|||
              </el-table-column> | 
				
			|||
            </el-table> | 
				
			|||
          </el-main> | 
				
			|||
        </el-container> | 
				
			|||
      </el-container> | 
				
			|||
 | 
				
			|||
      <el-aside width="200px" style="background-color: rgb(238, 241, 246);float: right"> | 
				
			|||
        <el-menu :default-openeds="['1', '3']"> | 
				
			|||
          <el-submenu index="1"> | 
				
			|||
            <template slot="title"><i class="el-icon-message"></i>导航一</template> | 
				
			|||
            <el-menu-item-group> | 
				
			|||
              <template slot="title">分组一</template> | 
				
			|||
              <el-menu-item index="1-1">选项1</el-menu-item> | 
				
			|||
              <el-menu-item index="1-2">选项2</el-menu-item> | 
				
			|||
            </el-menu-item-group> | 
				
			|||
            <el-menu-item-group title="分组2"> | 
				
			|||
              <el-menu-item index="1-3">选项3</el-menu-item> | 
				
			|||
            </el-menu-item-group> | 
				
			|||
            <el-submenu index="1-4"> | 
				
			|||
              <template slot="title">选项4</template> | 
				
			|||
              <el-menu-item index="1-4-1">选项4-1</el-menu-item> | 
				
			|||
            </el-submenu> | 
				
			|||
          </el-submenu> | 
				
			|||
          <el-submenu index="2"> | 
				
			|||
            <template slot="title"><i class="el-icon-menu"></i>导航二</template> | 
				
			|||
            <el-menu-item-group> | 
				
			|||
              <template slot="title">分组一</template> | 
				
			|||
              <el-menu-item index="2-1">选项1</el-menu-item> | 
				
			|||
              <el-menu-item index="2-2">选项2</el-menu-item> | 
				
			|||
            </el-menu-item-group> | 
				
			|||
            <el-menu-item-group title="分组2"> | 
				
			|||
              <el-menu-item index="2-3">选项3</el-menu-item> | 
				
			|||
            </el-menu-item-group> | 
				
			|||
            <el-submenu index="2-4"> | 
				
			|||
              <template slot="title">选项4</template> | 
				
			|||
              <el-menu-item index="2-4-1">选项4-1</el-menu-item> | 
				
			|||
            </el-submenu> | 
				
			|||
          </el-submenu> | 
				
			|||
          <el-submenu index="3"> | 
				
			|||
            <template slot="title"><i class="el-icon-setting"></i>导航三</template> | 
				
			|||
            <el-menu-item-group> | 
				
			|||
              <template slot="title">分组一</template> | 
				
			|||
              <el-menu-item index="3-1">选项1</el-menu-item> | 
				
			|||
              <el-menu-item index="3-2">选项2</el-menu-item> | 
				
			|||
            </el-menu-item-group> | 
				
			|||
            <el-menu-item-group title="分组2"> | 
				
			|||
              <el-menu-item index="3-3">选项3</el-menu-item> | 
				
			|||
            </el-menu-item-group> | 
				
			|||
            <el-submenu index="3-4"> | 
				
			|||
              <template slot="title">选项4</template> | 
				
			|||
              <el-menu-item index="3-4-1">选项4-1</el-menu-item> | 
				
			|||
            </el-submenu> | 
				
			|||
          </el-submenu> | 
				
			|||
        </el-menu> | 
				
			|||
      </el-aside> | 
				
			|||
 | 
				
			|||
    </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
    export default { | 
				
			|||
      name: "test", | 
				
			|||
      data() { | 
				
			|||
        const item = { | 
				
			|||
          date: '2016-05-02', | 
				
			|||
          name: '王小虎', | 
				
			|||
          address: '上海市普陀区金沙江路 1518 弄' | 
				
			|||
        }; | 
				
			|||
        return { | 
				
			|||
          tableData: Array(20).fill(item) | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
  .el-header { | 
				
			|||
    background-color: #B3C0D1; | 
				
			|||
    color: #333; | 
				
			|||
    line-height: 60px; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .el-aside { | 
				
			|||
    color: #333; | 
				
			|||
  } | 
				
			|||
</style> --> | 
				
			|||
@ -0,0 +1,16 @@ | 
				
			|||
import Vue from 'vue' | 
				
			|||
// import moment from 'moment'
 | 
				
			|||
 | 
				
			|||
import { format } from 'date-fns' | 
				
			|||
 | 
				
			|||
// 自定义过滤器
 | 
				
			|||
Vue.filter('date-format', function (value, formatStr = 'yyyy-MM-yy HH:mm:ss') { | 
				
			|||
 return format(value,formatStr) | 
				
			|||
}) | 
				
			|||
 | 
				
			|||
Vue.filter('fmtDate', | 
				
			|||
function renderTime(date) { | 
				
			|||
  var dateee = new Date(date).toJSON(); | 
				
			|||
  return new Date(+new Date(dateee) + 8 * 3600 * 1000).toISOString().replace(/T/g, ' ').replace(/\.[\d]{3}Z/, '') | 
				
			|||
} | 
				
			|||
) | 
				
			|||
| 
		 After Width: | Height: | Size: 17 KiB  | 
| 
		 After Width: | Height: | Size: 128 KiB  | 
| 
		 After Width: | Height: | Size: 30 KiB  | 
| 
		 After Width: | Height: | Size: 102 KiB  | 
| 
		 After Width: | Height: | Size: 3.6 KiB  | 
| 
		 After Width: | Height: | Size: 27 KiB  | 
| 
		 After Width: | Height: | Size: 193 KiB  | 
| 
		 After Width: | Height: | Size: 36 KiB  | 
@ -0,0 +1,236 @@ | 
				
			|||
<template> | 
				
			|||
  <div class="admin-login-box"> | 
				
			|||
    <div class="admin-login-header-box"> | 
				
			|||
      <div class="admin-login-header-center"> | 
				
			|||
        <div class="admin-login-logo"> | 
				
			|||
          投票 | 
				
			|||
        </div> | 
				
			|||
      </div> | 
				
			|||
    </div> | 
				
			|||
    <!--中间内容--> | 
				
			|||
    <div class="admin-login-center-box"> | 
				
			|||
      <div class="center login-center-box"> | 
				
			|||
        <el-row :gutter="20"> | 
				
			|||
          <el-col :span="10"> | 
				
			|||
            <div class="forget-title-tips"> | 
				
			|||
              <span class="forget-title">找回密码</span> | 
				
			|||
            </div> | 
				
			|||
            <div> | 
				
			|||
             <p v-bind:style="{ fontWeight: 'bold' }">请联系管理员</p> | 
				
			|||
             <img :src="cat" style="height: 200px;"/> | 
				
			|||
           </div> | 
				
			|||
            <!-- <div class="verify-code-container" v-if="showType === 'verifyCode'" style="width: 1000px;"> | 
				
			|||
              <el-form label-position="right" label-width="100px"> | 
				
			|||
                <el-form-item label="邮箱地址" required> | 
				
			|||
                  <el-input v-model="user.email" placeholder="请输入邮箱"></el-input> | 
				
			|||
                  <el-button v-if="!isCountDowning" type="primary" class="login-button" style="margin-left: 20px"  @click="getVerifyCode"> | 
				
			|||
                    获取验证码 | 
				
			|||
                  </el-button> | 
				
			|||
                  <el-button v-else type="primary" class="login-button" style="margin-left: 20px" @click.prevent="getVerifyCode" disabled> | 
				
			|||
                    {{countDownText}} | 
				
			|||
                  </el-button> | 
				
			|||
                </el-form-item> | 
				
			|||
                <el-form-item label="邮箱验证码" required> | 
				
			|||
                  <el-input v-model="emailCode" placeholder="请输入邮箱验证码"></el-input> | 
				
			|||
                </el-form-item> | 
				
			|||
                <el-form-item> | 
				
			|||
                  <el-button type="primary"  @click="resetPassword" style="float:left;"> 找回密码  </el-button> | 
				
			|||
                </el-form-item> | 
				
			|||
              </el-form> | 
				
			|||
            </div> --> | 
				
			|||
            <div class="forget-reset-password-container" v-if="showType === 'resetPassword'"> | 
				
			|||
              <el-form label-position="right" label-width="100px"> | 
				
			|||
                <el-form-item label="新密码" required> | 
				
			|||
                  <el-input v-model="user.password" placeholder="请输入密码" type="password"></el-input> | 
				
			|||
                </el-form-item> | 
				
			|||
                <el-form-item label="确认密码" required> | 
				
			|||
                  <el-input v-model="repassword" placeholder="请再次输入密码" type="password"></el-input> | 
				
			|||
                </el-form-item> | 
				
			|||
                <el-form-item> | 
				
			|||
                  <el-button type="primary"  @click="setPassword" style="float:left;"> 设置密码  </el-button> | 
				
			|||
                </el-form-item> | 
				
			|||
              </el-form> | 
				
			|||
            </div> | 
				
			|||
          </el-col> | 
				
			|||
        </el-row> | 
				
			|||
      </div> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  export default { | 
				
			|||
    name: "forget.vue", | 
				
			|||
    data(){ | 
				
			|||
      return{ | 
				
			|||
        cat: require('../img/weixin.jpg'), | 
				
			|||
        showType:'verifyCode', | 
				
			|||
        isUserNameOkay:'', | 
				
			|||
        isCountDowning:false, | 
				
			|||
        countDownText:'重新发送(60)', | 
				
			|||
        user:{ | 
				
			|||
          userName:'', | 
				
			|||
          password:'', | 
				
			|||
          email:'', | 
				
			|||
        }, | 
				
			|||
        captchaPath:'', | 
				
			|||
        verifyCode:'', | 
				
			|||
        captcha_key:'', | 
				
			|||
        emailCode:'', | 
				
			|||
        repassword:'', | 
				
			|||
 | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
 | 
				
			|||
    methods:{ | 
				
			|||
      updateVerifyCode(){ | 
				
			|||
        this.captchaPath = 'http://localhost:8443//api/user/captcha?captcha_key='+this.captcha_key + '&random'+Date.parse(new Date()); | 
				
			|||
        console.log(this.captchaPath) | 
				
			|||
      }, | 
				
			|||
      getVerifyCode(){ | 
				
			|||
        let _this = this | 
				
			|||
        if(this.user.email === ''){ | 
				
			|||
          this.$message.error("请输入邮箱地址"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        let reg = /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/ | 
				
			|||
        if (!reg.test(this.user.email)) { | 
				
			|||
          this.$message.error("邮箱格式不正确"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        this.$axios | 
				
			|||
          .get('/user/verify_code?email='+_this.user.email+'&type=forget').then(resp =>{ | 
				
			|||
          if (resp.data.code === 200) { | 
				
			|||
            _this.startCountDown(); | 
				
			|||
          }else { | 
				
			|||
            this.$message.error(resp.data.message); | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      startCountDown(){ | 
				
			|||
        console.log('执行倒计时。。。') | 
				
			|||
        let _this = this; | 
				
			|||
        let time = 60; | 
				
			|||
        this.isCountDowning = true; | 
				
			|||
        let interval = setInterval(function () { | 
				
			|||
          //执行倒计时 | 
				
			|||
          time--; | 
				
			|||
          if(time <= 0){ | 
				
			|||
            _this.isCountDowning = false; | 
				
			|||
            clearInterval(interval); | 
				
			|||
          } | 
				
			|||
          _this.countDownText = '重新发送('+ time + ')'; | 
				
			|||
        },1000) | 
				
			|||
      }, | 
				
			|||
      resetPassword(){ | 
				
			|||
        let _this = this; | 
				
			|||
        if(this.user.email === ''){ | 
				
			|||
          this.$message.error("请输入邮箱"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        if(this.emailCode === ''){ | 
				
			|||
          this.$message.error("请输入邮箱验证码"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        this.$axios.get('/user/check_email_code?email='+_this.user.email+'&emailCode='+this.emailCode).then(resp =>{ | 
				
			|||
            if(resp.data.code === 200){ | 
				
			|||
              _this.showType = 'resetPassword'; | 
				
			|||
            }else { | 
				
			|||
              this.$message.error(resp.data.message); | 
				
			|||
            } | 
				
			|||
        }) | 
				
			|||
      }, | 
				
			|||
      setPassword(){ | 
				
			|||
        let _this = this; | 
				
			|||
        if(this.user.password === ''){ | 
				
			|||
          this.$message.error("请输入新的密码"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        if(this.user.password != this.repassword){ | 
				
			|||
          this.$message.error("两次密码输入不一致"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        //更新密码 | 
				
			|||
        this.$axios.put('/user/password',{ | 
				
			|||
          email:_this.user.email, | 
				
			|||
          password:_this.user.password | 
				
			|||
        }).then(resp =>{ | 
				
			|||
          if(resp.data.code === 200){ | 
				
			|||
            if(resp.data.code === 200){ | 
				
			|||
              this.$message.success("更新成功"); | 
				
			|||
              location.href="/login" | 
				
			|||
            }else { | 
				
			|||
              this.$message.error(resp.data.message); | 
				
			|||
            } | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
      } | 
				
			|||
 | 
				
			|||
    }, | 
				
			|||
    mounted() { | 
				
			|||
      this.captcha_key = Date.parse(new Date()) | 
				
			|||
      this.updateVerifyCode(); | 
				
			|||
    }, | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
 | 
				
			|||
  .admin-login-header-box{ | 
				
			|||
    width: 100%; | 
				
			|||
    height: 46px; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .admin-login-header-center{ | 
				
			|||
    line-height: 46px; | 
				
			|||
    margin: 0 auto; | 
				
			|||
    width: 1140px; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .admin-login-logo{ | 
				
			|||
    width: 200px; | 
				
			|||
    color: dodgerblue; | 
				
			|||
    font-size: 20px; | 
				
			|||
    font-weight: 600; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .login-center-box{ | 
				
			|||
    margin: 0 auto; | 
				
			|||
    margin-top: 30px; | 
				
			|||
    border-radius: 5px; | 
				
			|||
    padding: 20px; | 
				
			|||
    width: 600px; | 
				
			|||
    height: 400px; | 
				
			|||
    background-color: #fff; | 
				
			|||
    box-shadow: 0 1px 10px 0 #afafaf; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .login-center-box .el-input{ | 
				
			|||
    width: 20%; | 
				
			|||
    float: left; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .login-button{ | 
				
			|||
    margin-bottom: 0; | 
				
			|||
    float: left; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .forget-tips-text a{ | 
				
			|||
    color: #999; | 
				
			|||
    text-decoration:none; | 
				
			|||
  } | 
				
			|||
  .forget-tips-text a:hover{ | 
				
			|||
    color: #A612FF; | 
				
			|||
  } | 
				
			|||
  .forget-title-tips{ | 
				
			|||
    width: 80%; | 
				
			|||
    font-size: 20px; | 
				
			|||
    font-weight: 600; | 
				
			|||
    padding: 20px; | 
				
			|||
    margin-bottom: 20px; | 
				
			|||
    text-align: left; | 
				
			|||
    color: #505458; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,89 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <div class="admin-login-box"> | 
				
			|||
      <div class="admin-login-header-box"> | 
				
			|||
        <div class="admin-login-header-center"> | 
				
			|||
          <div class="admin-login-logo" @click="toHome"> | 
				
			|||
            投票 | 
				
			|||
          </div> | 
				
			|||
        </div> | 
				
			|||
    <!--中间内容--> | 
				
			|||
    <div class="login-tab-container"> | 
				
			|||
      <el-tabs v-model="activeName" @tab-click="toLogin" class="index-box"> | 
				
			|||
        <el-tab-pane  label="登录" name="first" class=""> | 
				
			|||
          <login ref="loginBox"></login> | 
				
			|||
        </el-tab-pane> | 
				
			|||
        <el-tab-pane label="注册" name="second" @tab-click="toRegister"> | 
				
			|||
          <register @onSubmit="handleTab()" ref="registerBox" style="width: 1000px;"></register> | 
				
			|||
        </el-tab-pane> | 
				
			|||
 | 
				
			|||
      </el-tabs> | 
				
			|||
    </div> | 
				
			|||
     </div> | 
				
			|||
    </div> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
<script> | 
				
			|||
  import Login from "../login/login"; | 
				
			|||
  import Register from "../login/register"; | 
				
			|||
  export default { | 
				
			|||
    components: {Register, Login}, | 
				
			|||
    data() { | 
				
			|||
      return { | 
				
			|||
        activeName: 'first' | 
				
			|||
      }; | 
				
			|||
    }, | 
				
			|||
    methods: { | 
				
			|||
      toLogin(){ | 
				
			|||
        this.activeName = 'first'; | 
				
			|||
        this.$refs.loginBox.updateVerifyCode(); | 
				
			|||
      }, | 
				
			|||
      toRegister(){ | 
				
			|||
        this.activeName = 'second'; | 
				
			|||
        this.$refs.registerBox.updateVerifyCode(); | 
				
			|||
      }, | 
				
			|||
      handleTab(){ | 
				
			|||
        this.activeName = 'first'; | 
				
			|||
        this.$refs.loginBox.updateVerifyCode(); | 
				
			|||
      }, | 
				
			|||
      toHome(){ | 
				
			|||
        this.$router.push('/home') | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
 | 
				
			|||
  }; | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
  .admin-login-header-box{ | 
				
			|||
    width: 100%; | 
				
			|||
    height: 46px; | 
				
			|||
    border-bottom: solid 1px #e6e6e6; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .admin-login-header-center{ | 
				
			|||
    line-height: 46px; | 
				
			|||
    margin: 0 auto; | 
				
			|||
    width: 1140px; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .admin-login-logo{ | 
				
			|||
    width: 200px; | 
				
			|||
    color: dodgerblue; | 
				
			|||
    font-size: 20px; | 
				
			|||
    font-weight: 600; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
  .login-tab-container{ | 
				
			|||
    margin: 0 auto; | 
				
			|||
    margin-top: 30px; | 
				
			|||
    border-radius: 5px; | 
				
			|||
    padding: 20px; | 
				
			|||
    width: 600px; | 
				
			|||
    height: 400px; | 
				
			|||
    background-color: #fff; | 
				
			|||
    box-shadow: 0 1px 10px 0 #afafaf; | 
				
			|||
  } | 
				
			|||
</style> | 
				
			|||
 | 
				
			|||
@ -0,0 +1,183 @@ | 
				
			|||
<template> | 
				
			|||
    <!--中间内容--> | 
				
			|||
    <div class="admin-login-center-box"> | 
				
			|||
      <div class="login-center-box"> | 
				
			|||
        <el-row :gutter="20"> | 
				
			|||
          <el-col :span="10"> | 
				
			|||
            <el-form label-position="left" label-width="80px" style="width: 400px;"> | 
				
			|||
              <el-form-item label="账号" required> | 
				
			|||
                <el-input v-model="user.userName" placeholder="用户名"></el-input> | 
				
			|||
              </el-form-item> | 
				
			|||
              <el-form-item label="密码" required> | 
				
			|||
                <el-input v-model="user.password" placeholder="请输入密码" type="password"></el-input> | 
				
			|||
              </el-form-item> | 
				
			|||
              <!-- <el-form-item label="验证码" required> | 
				
			|||
                <el-input v-model="verifyCode" placeholder="请输入右侧验证码"></el-input> | 
				
			|||
                <img :src="captchaPath" @click="updateVerifyCode" class="captcha-code"> | 
				
			|||
              </el-form-item> --> | 
				
			|||
              <el-form-item> | 
				
			|||
                <el-button type="primary"  class="login-button" @click="doLogin"> 登 录 </el-button> | 
				
			|||
                <span class="forget-tips-text"> | 
				
			|||
                  <a href="/login/forget">忘记密码?</a> | 
				
			|||
                </span> | 
				
			|||
              </el-form-item> | 
				
			|||
            </el-form> | 
				
			|||
          </el-col> | 
				
			|||
        </el-row> | 
				
			|||
      </div> | 
				
			|||
    </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
  export default { | 
				
			|||
    name: "index.vue", | 
				
			|||
    data(){ | 
				
			|||
      return{ | 
				
			|||
        user:{ | 
				
			|||
          userName:'admin', | 
				
			|||
          password:'123456' | 
				
			|||
        }, | 
				
			|||
        verifyCode:'', | 
				
			|||
        captchaPath:'', | 
				
			|||
        captcha_key:'' | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
 | 
				
			|||
    methods:{ | 
				
			|||
      doLogin(){ | 
				
			|||
        let _this = this | 
				
			|||
        //判断数据 | 
				
			|||
        if(this.user.userName === ''){ | 
				
			|||
          this.$message.error("请输入用户名"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        if(this.user.password === ''){ | 
				
			|||
          this.$message.error("请输入密码"); | 
				
			|||
          return; | 
				
			|||
        } | 
				
			|||
        this.verifyCode = 1; | 
				
			|||
        // if(this.verifyCode === ''){ | 
				
			|||
        //   this.$message.error("请输入验证码"); | 
				
			|||
        //   return; | 
				
			|||
        // } | 
				
			|||
        this.$axios.post('/user/login/'+_this.verifyCode+'/'+_this.captcha_key, { | 
				
			|||
           userName:_this.user.userName, | 
				
			|||
           password:_this.user.password | 
				
			|||
        }).then(resp => { | 
				
			|||
          if(resp.data.code === 200){ | 
				
			|||
            this.$message.success("登录成功"); | 
				
			|||
            _this.$store.commit('login', _this.user) | 
				
			|||
            var path = this.$route.query.redirect | 
				
			|||
            this.$router.push({path: path === '/' || path === undefined ? '/admin' : path}) | 
				
			|||
          }else { | 
				
			|||
            _this.updateVerifyCode(); | 
				
			|||
            this.$message.error(resp.data.message); | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
 | 
				
			|||
      }, | 
				
			|||
      updateVerifyCode(){ | 
				
			|||
        this.captchaPath = 'http://localhost:8443/api/user/captcha?captcha_key='+this.captcha_key + '&random'+Date.parse(new Date()); | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
    mounted() { | 
				
			|||
      this.captcha_key = Date.parse(new Date()) | 
				
			|||
      this.updateVerifyCode(); | 
				
			|||
    }, | 
				
			|||
  } | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
 | 
				
			|||
  .admin-login-header-box{ | 
				
			|||
    width: 100%; | 
				
			|||
    height: 46px; | 
				
			|||
    background-color: dodgerblue; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .admin-login-header-center{ | 
				
			|||
    line-height: 46px; | 
				
			|||
    margin: 0 auto; | 
				
			|||
    width: 1140px; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .admin-login-logo{ | 
				
			|||
    width: 200px; | 
				
			|||
    color: #fff; | 
				
			|||
    font-size: 20px; | 
				
			|||
    font-weight: 600; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  /*.login-center-box{*/ | 
				
			|||
  /*  margin: 0 auto;*/ | 
				
			|||
  /*  margin-top: 30px;*/ | 
				
			|||
  /*  border-radius: 5px;*/ | 
				
			|||
  /*  padding: 20px;*/ | 
				
			|||
  /*  width: 1100px;*/ | 
				
			|||
  /*  height: 400px;*/ | 
				
			|||
  /*  background-color: #fff;*/ | 
				
			|||
  /*  box-shadow: 0 1px 10px 0 #afafaf;*/ | 
				
			|||
  /*}*/ | 
				
			|||
 | 
				
			|||
  .login-center-box .el-input{ | 
				
			|||
    width: 159px; | 
				
			|||
    float: left; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .captcha-code{ | 
				
			|||
    cursor: pointer; | 
				
			|||
    vertical-align: middle; | 
				
			|||
    margin-left: 10px; | 
				
			|||
    border:solid 1px #E6E6E6; | 
				
			|||
    width: 120px; | 
				
			|||
    padding-left: 10px; | 
				
			|||
    padding-right: 10px; | 
				
			|||
    height: 40px; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
  .login-button{ | 
				
			|||
    margin-bottom: 0; | 
				
			|||
    float: left; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  .forget-tips-text{ | 
				
			|||
    float: left; | 
				
			|||
    margin-left: 20px; | 
				
			|||
  } | 
				
			|||
  .forget-tips-text a{ | 
				
			|||
    color: #999; | 
				
			|||
    text-decoration:none; | 
				
			|||
  } | 
				
			|||
  .forget-tips-text a:hover{ | 
				
			|||
    color: #A612FF; | 
				
			|||
 | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  /*.login-center-box .el-input{*/ | 
				
			|||
  /*  width: 200px;*/ | 
				
			|||
  /*}*/ | 
				
			|||
 | 
				
			|||
  /*.el-form-item .login-center-box{*/ | 
				
			|||
  /*  border-radius: 4px;*/ | 
				
			|||
  /*  width: 1100px;*/ | 
				
			|||
  /*  padding: 20px;*/ | 
				
			|||
  /*  background-color: #fff;*/ | 
				
			|||
  /*}*/ | 
				
			|||
 | 
				
			|||
  /*.el-form-item .el-input__inner{*/ | 
				
			|||
  /*  border:solid 1px #E6E6E6;*/ | 
				
			|||
  /*  height: 42px;*/ | 
				
			|||
  /*  border-radius: 0;*/ | 
				
			|||
  /*}*/ | 
				
			|||
 | 
				
			|||
  /*.el-form-item__label{*/ | 
				
			|||
  /*  background-color: aliceblue;*/ | 
				
			|||
  /*  border-left: solid 1px #e6e6e6;*/ | 
				
			|||
  /*  border-top: solid 1px #e6e6e6;*/ | 
				
			|||
  /*  border-bottom: solid 1px #e6e6e6;*/ | 
				
			|||
  /*  text-align: center;*/ | 
				
			|||
  /*}*/ | 
				
			|||
 | 
				
			|||
 | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,214 @@ | 
				
			|||
<template> | 
				
			|||
  <div class="admin-login-center-box"> | 
				
			|||
    <div class="center login-center-box"> | 
				
			|||
      <el-row :gutter="20"> | 
				
			|||
        <el-col :span="10" > | 
				
			|||
          <el-form label-position="left" label-width="100px"> | 
				
			|||
            <el-form-item label="用户名" required> | 
				
			|||
              <el-input v-model="user.userName" placeholder="用户名" @blur="checkUserName"></el-input> | 
				
			|||
              <span class="el-icon-error" v-if="isUserNameOkay === '1'">用户名已被注册</span> | 
				
			|||
              <span class="el-icon-success" v-if="isUserNameOkay === '0'">用户名可用</span> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item label="密码" required> | 
				
			|||
              <el-input v-model="user.password" placeholder="请输入密码" type="password"></el-input> | 
				
			|||
            </el-form-item> | 
				
			|||
            <el-form-item label="邮箱地址" required inline> | 
				
			|||
                <el-input v-model="user.email" placeholder="请输入邮箱"></el-input> | 
				
			|||
                <!-- <el-button v-if="!isCountDowning" type="primary" class="login-button" style="margin-left: 20px"  @click="getVerifyCode"> | 
				
			|||
                  获取验证码 | 
				
			|||
                </el-button> | 
				
			|||
                <el-button v-else type="primary" class="login-button" style="margin-left: 20px" @click.prevent="getVerifyCode" disabled> | 
				
			|||
                  {{countDownText}} --> | 
				
			|||
                <!-- </el-button> --> | 
				
			|||
              </el-form-item> | 
				
			|||
            <!-- <el-form-item label="邮箱验证码" required> | 
				
			|||
              <el-input v-model="emailCode" placeholder="请输入邮箱验证码"></el-input> | 
				
			|||
            </el-form-item> --> | 
				
			|||
            <!-- <el-form-item label="验证码" required> | 
				
			|||
                <el-input v-model="verifyCode" placeholder="请输入右侧验证码"></el-input> | 
				
			|||
                <img :src="captchaPath" @click="updateVerifyCode" class="captcha-code"> | 
				
			|||
              </el-form-item> --> | 
				
			|||
            <el-form-item> | 
				
			|||
              <el-button type="primary" class="login-button" @click="doRegister"> 注 册 </el-button> | 
				
			|||
            </el-form-item> | 
				
			|||
          </el-form> | 
				
			|||
        </el-col> | 
				
			|||
      </el-row> | 
				
			|||
    </div> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
export default { | 
				
			|||
  name: "register.vue", | 
				
			|||
  data() { | 
				
			|||
    return { | 
				
			|||
      isUserNameOkay: '', | 
				
			|||
      isCountDowning: false, | 
				
			|||
      countDownText: '重新发送(60)', | 
				
			|||
      user: { | 
				
			|||
        userName: '', | 
				
			|||
        password: '', | 
				
			|||
        email: '', | 
				
			|||
      }, | 
				
			|||
      captchaPath: '', | 
				
			|||
      verifyCode: '', | 
				
			|||
      captcha_key: '', | 
				
			|||
      emailCode: '' | 
				
			|||
    } | 
				
			|||
  }, | 
				
			|||
  methods: { | 
				
			|||
    doLogin() { | 
				
			|||
    }, | 
				
			|||
    updateVerifyCode() { | 
				
			|||
      this.captchaPath = 'http://localhost:8443/api/user/captcha?captcha_key=' + this.captcha_key + '&random' + Date.parse(new Date()); | 
				
			|||
    }, | 
				
			|||
    getVerifyCode() { | 
				
			|||
      let _this = this | 
				
			|||
      if (this.user.email === '') { | 
				
			|||
        this.$message.error("请输入邮箱地址"); | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      let reg = /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/ | 
				
			|||
      if (!reg.test(this.user.email)) { | 
				
			|||
        this.$message.error("邮箱格式不正确"); | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      this.$axios | 
				
			|||
        .get('/user/verify_code?email=' + _this.user.email + '&type=register').then(resp => { | 
				
			|||
          if (resp.data.code === 200) { | 
				
			|||
            _this.startCountDown(); | 
				
			|||
          } else { | 
				
			|||
            this.$message.error(resp.data.message); | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
    }, | 
				
			|||
    startCountDown() { | 
				
			|||
      let _this = this; | 
				
			|||
      let time = 60; | 
				
			|||
      this.isCountDowning = true; | 
				
			|||
      let interval = setInterval(function () { | 
				
			|||
        //执行倒计时 | 
				
			|||
        time--; | 
				
			|||
        if (time <= 0) { | 
				
			|||
          _this.isCountDowning = false; | 
				
			|||
          clearInterval(interval); | 
				
			|||
        } | 
				
			|||
        _this.countDownText = '重新发送(' + time + ')'; | 
				
			|||
      }, 1000) | 
				
			|||
    }, | 
				
			|||
    checkUserName() { | 
				
			|||
      if (this.user.userName == '') { | 
				
			|||
        this.isUserNameOkay = ''; | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      let _this = this | 
				
			|||
      this.$axios | 
				
			|||
        .get('/user/user_name?userName=' + this.user.userName).then(resp => { | 
				
			|||
          if (resp.data.code === 200) { | 
				
			|||
            //已存在 | 
				
			|||
            _this.isUserNameOkay = '1'; | 
				
			|||
          } else { | 
				
			|||
            //不存在,可以用 | 
				
			|||
            _this.isUserNameOkay = '0'; | 
				
			|||
          } | 
				
			|||
        }) | 
				
			|||
    }, | 
				
			|||
    doRegister() { | 
				
			|||
      let _this = this; | 
				
			|||
      if (this.user.userName === '') { | 
				
			|||
        this.$message.error("请输入用户名"); | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      if (this.user.password === '') { | 
				
			|||
        this.$message.error("请输入密码"); | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      if (this.user.email === '') { | 
				
			|||
        this.$message.error("请输入邮箱"); | 
				
			|||
        return; | 
				
			|||
      } | 
				
			|||
      // this.verifyCode === 1 | 
				
			|||
      // if (this.emailCode === '') { | 
				
			|||
      //   this.$message.error("请输入邮箱验证码"); | 
				
			|||
      //   return; | 
				
			|||
      // } | 
				
			|||
      this.verifyCode === 1 | 
				
			|||
      // if (this.verifyCode === '') { | 
				
			|||
      //   this.$message.error("请输入验证码"); | 
				
			|||
      //   return; | 
				
			|||
      // } | 
				
			|||
      this.$axios.post('/user/join_in?' + 'captcha_code=' + _this.verifyCode + '&captcha_key=' + _this.captcha_key + '&email_code=' + _this.emailCode, { | 
				
			|||
        userName: _this.user.userName, | 
				
			|||
        password: _this.user.password, | 
				
			|||
        email: _this.user.email | 
				
			|||
      }).then(resp => { | 
				
			|||
        console.dir(resp); | 
				
			|||
        console.log("code: ", resp.data.code); | 
				
			|||
        console.log("message: ", resp.data.message); | 
				
			|||
        console.log("data: ", resp.data.data); | 
				
			|||
        if (resp.data.code === 200) { | 
				
			|||
          this.$message.success("注册成功"); | 
				
			|||
          this.$emit('onSubmit') | 
				
			|||
          location.href = "/login" | 
				
			|||
        } else { | 
				
			|||
          _this.updateVerifyCode(); | 
				
			|||
          this.$message.error(resp.data.message); | 
				
			|||
        } | 
				
			|||
      }) | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
  }, | 
				
			|||
  mounted() { | 
				
			|||
    this.captcha_key = Date.parse(new Date()) | 
				
			|||
    this.updateVerifyCode(); | 
				
			|||
  }, | 
				
			|||
} | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped> | 
				
			|||
 | 
				
			|||
 | 
				
			|||
.login-center-box .el-input { | 
				
			|||
  width: 50%; | 
				
			|||
  float: left; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.captcha-code { | 
				
			|||
  cursor: pointer; | 
				
			|||
  vertical-align: middle; | 
				
			|||
  margin-left: 10px; | 
				
			|||
  border: solid 1px #E6E6E6; | 
				
			|||
  width: 120px; | 
				
			|||
  padding-left: 10px; | 
				
			|||
  padding-right: 10px; | 
				
			|||
  height: 40px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
 | 
				
			|||
.login-button { | 
				
			|||
  margin-bottom: 0; | 
				
			|||
  float: left; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.forget-tips-text a { | 
				
			|||
  color: #999; | 
				
			|||
  text-decoration: none; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.forget-tips-text a:hover { | 
				
			|||
  color: #A612FF; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.el-icon-success { | 
				
			|||
  color: #67C23A; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.el-icon-error { | 
				
			|||
  color: #F56C6C; | 
				
			|||
} | 
				
			|||
</style> | 
				
			|||
@ -0,0 +1,123 @@ | 
				
			|||
// The Vue build version to load with the `import` command
 | 
				
			|||
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
 | 
				
			|||
import Vue from 'vue' | 
				
			|||
import App from './App' | 
				
			|||
import router from './router' | 
				
			|||
import store from  './store' | 
				
			|||
import './filter'// 加载过滤器
 | 
				
			|||
import 'default-passive-events'//
 | 
				
			|||
// 设置反向代理,前端请求默认发送到 http://localhost:8443/api
 | 
				
			|||
var axios = require('axios') | 
				
			|||
axios.defaults.baseURL = 'http://localhost:8443/api' | 
				
			|||
// 全局注册,之后可在其他组件中通过 this.$axios 发送数据
 | 
				
			|||
Vue.prototype.$axios = axios | 
				
			|||
Vue.config.productionTip = false | 
				
			|||
axios.defaults.withCredentials = true | 
				
			|||
 | 
				
			|||
import ElementUI from 'element-ui' | 
				
			|||
import 'element-ui/lib/theme-chalk/index.css' | 
				
			|||
Vue.use(ElementUI) | 
				
			|||
 | 
				
			|||
import VueQuillEditor from 'vue-quill-editor' | 
				
			|||
// require styles
 | 
				
			|||
import 'quill/dist/quill.core.css' | 
				
			|||
import 'quill/dist/quill.snow.css' | 
				
			|||
import 'quill/dist/quill.bubble.css' | 
				
			|||
 | 
				
			|||
import QRCode from 'qrcodejs2' | 
				
			|||
Vue.use(VueQuillEditor) | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
router.beforeEach((to, from, next) => { | 
				
			|||
    if (store.state.user.userName && to.path.startsWith('/admin')) { | 
				
			|||
      initAdminMenu(router, store) | 
				
			|||
    } | 
				
			|||
    // if(store.state.user.userName && this.$route.path === '/admin'){
 | 
				
			|||
    //   this.router.redirect('/admin/vote/list')
 | 
				
			|||
    // }
 | 
				
			|||
    // 已登录状态下访问 login 页面直接跳转到后台首页
 | 
				
			|||
    if (store.state.userName && to.path.startsWith('/login')) { | 
				
			|||
      next({ | 
				
			|||
        path: 'admin/vote' | 
				
			|||
      }) | 
				
			|||
    } | 
				
			|||
    if (to.meta.requireAuth) { | 
				
			|||
      if (store.state.user) { | 
				
			|||
        axios.get('/authentication').then(resp => { | 
				
			|||
          if (resp) next() | 
				
			|||
        }) | 
				
			|||
      } else { | 
				
			|||
        next({ | 
				
			|||
          path: 'login', | 
				
			|||
          query: {redirect: to.fullPath} | 
				
			|||
        }) | 
				
			|||
      } | 
				
			|||
    } else { | 
				
			|||
      next() | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
) | 
				
			|||
 | 
				
			|||
const initAdminMenu = (router, store) => { | 
				
			|||
  if (store.state.adminMenus.length > 0) { | 
				
			|||
    return; | 
				
			|||
  } | 
				
			|||
  axios.get('/menu').then(resp => { | 
				
			|||
    if (resp && resp.status === 200) { | 
				
			|||
      var fmtRoutes = formatRoutes(resp.data.result) | 
				
			|||
      router.addRoutes(fmtRoutes) | 
				
			|||
      store.commit('initAdminMenu', fmtRoutes) | 
				
			|||
      // console.log('menu')
 | 
				
			|||
      console.dir(resp.data); | 
				
			|||
      // console.dir(fmtRoutes);
 | 
				
			|||
    } | 
				
			|||
  }) | 
				
			|||
} | 
				
			|||
 | 
				
			|||
const formatRoutes = (routes) => { | 
				
			|||
  let fmtRoutes = [] | 
				
			|||
  routes.forEach(route => { | 
				
			|||
    if (route.children) { | 
				
			|||
      route.children = formatRoutes(route.children) | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    let fmtRoute = { | 
				
			|||
      path: route.path, | 
				
			|||
      component: resolve => { | 
				
			|||
        require(['./components/admin/' + route.component + '.vue'], resolve) | 
				
			|||
      }, | 
				
			|||
      name: route.name, | 
				
			|||
      nameZh: route.nameZh, | 
				
			|||
      iconCls: route.iconCls, | 
				
			|||
      meta: { | 
				
			|||
        requireAuth: true | 
				
			|||
      }, | 
				
			|||
      children: route.children | 
				
			|||
    } | 
				
			|||
    fmtRoutes.push(fmtRoute) | 
				
			|||
  }) | 
				
			|||
  return fmtRoutes | 
				
			|||
} | 
				
			|||
 | 
				
			|||
Vue.prototype.setDialogWidth = function () { | 
				
			|||
    let val = document.body.clientWidth | 
				
			|||
    console.log('val===>',val) | 
				
			|||
    const def = 800 // 默认宽度
 | 
				
			|||
    if (val < def) { | 
				
			|||
      this.dialogWidth = '100%' | 
				
			|||
    } else { | 
				
			|||
      this.dialogWidth = '30%' | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
 | 
				
			|||
/* eslint-disable no-new */ | 
				
			|||
new Vue({ | 
				
			|||
  el: '#app', | 
				
			|||
  render: h => h(App), | 
				
			|||
  router, | 
				
			|||
  store, | 
				
			|||
  components: { App }, | 
				
			|||
  template: '<App/>' | 
				
			|||
}) | 
				
			|||
@ -0,0 +1,61 @@ | 
				
			|||
import Vue from 'vue' | 
				
			|||
import Router from 'vue-router' | 
				
			|||
import ActivityIndex from "../components/ActivityIndex"; | 
				
			|||
import Home from "../components/Home"; | 
				
			|||
import loginTab from "../login/index"; | 
				
			|||
import forget from "../login/forget"; | 
				
			|||
import AdminIndex from "../components/admin/AdminIndex"; | 
				
			|||
import NoticeIndex from "../components/NoticeIndex"; | 
				
			|||
import test from "../components/test"; | 
				
			|||
 | 
				
			|||
Vue.use(Router) | 
				
			|||
 | 
				
			|||
export default new Router({ | 
				
			|||
  mode: 'history', | 
				
			|||
  routes: [ | 
				
			|||
    { | 
				
			|||
      path: '/', | 
				
			|||
      name: 'Home', | 
				
			|||
      component: Home, | 
				
			|||
      redirect: '/home' | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      path: '/admin', | 
				
			|||
      redirect: '/admin/vote/list' | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      path: '/home', | 
				
			|||
      name:'home', | 
				
			|||
      component: Home | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      path: '/notice/detail/:id', | 
				
			|||
      name: 'noticeDetail', | 
				
			|||
      component: NoticeIndex | 
				
			|||
    }, | 
				
			|||
     | 
				
			|||
    { | 
				
			|||
      path:'/activityIndex/:id', | 
				
			|||
      name:'ActivityIndex', | 
				
			|||
      component:ActivityIndex | 
				
			|||
    }, | 
				
			|||
 | 
				
			|||
    { | 
				
			|||
      path:'/login/forget', | 
				
			|||
      component:forget | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      path:'/login', | 
				
			|||
      component:loginTab | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      path: '/admin', | 
				
			|||
      component: AdminIndex | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      path:'/test', | 
				
			|||
      component: test | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
  ] | 
				
			|||
}) | 
				
			|||
@ -0,0 +1,34 @@ | 
				
			|||
import Vue from 'vue' | 
				
			|||
import Vuex from 'vuex' | 
				
			|||
 | 
				
			|||
Vue.use(Vuex) | 
				
			|||
 | 
				
			|||
export default new Vuex.Store({ | 
				
			|||
  state: { | 
				
			|||
    user: { | 
				
			|||
      userName: window.localStorage.getItem('user' || '[]') == null ? '' : JSON.parse(window.localStorage.getItem('user' || '[]')).userName, | 
				
			|||
      password: window.localStorage.getItem('user' || '[]') == null ? '' : JSON.parse(window.localStorage.getItem('user' || '[]')).password, | 
				
			|||
    }, | 
				
			|||
    curCreateActivity:{ | 
				
			|||
    }, | 
				
			|||
    adminMenus: [], | 
				
			|||
    dialogWidth:'100%' | 
				
			|||
  }, | 
				
			|||
  mutations: { | 
				
			|||
    login (state, user) { | 
				
			|||
      state.user = user | 
				
			|||
      window.localStorage.setItem('user', JSON.stringify(user)) | 
				
			|||
    }, | 
				
			|||
    logout(state){ | 
				
			|||
      state.user = [] | 
				
			|||
      window.localStorage.removeItem('user') | 
				
			|||
    }, | 
				
			|||
    createActive(state,data){ | 
				
			|||
       state.curCreateActivity = data | 
				
			|||
       window.localStorage.setItem('curCreateActivity', JSON.stringify(data)) | 
				
			|||
    }, | 
				
			|||
    initAdminMenu (state, menus) { | 
				
			|||
      state.adminMenus = menus | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
}) | 
				
			|||
@ -0,0 +1,27 @@ | 
				
			|||
// A custom Nightwatch assertion.
 | 
				
			|||
// The assertion name is the filename.
 | 
				
			|||
// Example usage:
 | 
				
			|||
//
 | 
				
			|||
//   browser.assert.elementCount(selector, count)
 | 
				
			|||
//
 | 
				
			|||
// For more information on custom assertions see:
 | 
				
			|||
// http://nightwatchjs.org/guide#writing-custom-assertions
 | 
				
			|||
 | 
				
			|||
exports.assertion = function (selector, count) { | 
				
			|||
  this.message = 'Testing if element <' + selector + '> has count: ' + count | 
				
			|||
  this.expected = count | 
				
			|||
  this.pass = function (val) { | 
				
			|||
    return val === this.expected | 
				
			|||
  } | 
				
			|||
  this.value = function (res) { | 
				
			|||
    return res.value | 
				
			|||
  } | 
				
			|||
  this.command = function (cb) { | 
				
			|||
    var self = this | 
				
			|||
    return this.api.execute(function (selector) { | 
				
			|||
      return document.querySelectorAll(selector).length | 
				
			|||
    }, [selector], function (res) { | 
				
			|||
      cb.call(self, res) | 
				
			|||
    }) | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,46 @@ | 
				
			|||
require('babel-register') | 
				
			|||
var config = require('../../config') | 
				
			|||
 | 
				
			|||
// http://nightwatchjs.org/gettingstarted#settings-file
 | 
				
			|||
module.exports = { | 
				
			|||
  src_folders: ['test/e2e/specs'], | 
				
			|||
  output_folder: 'test/e2e/reports', | 
				
			|||
  custom_assertions_path: ['test/e2e/custom-assertions'], | 
				
			|||
 | 
				
			|||
  selenium: { | 
				
			|||
    start_process: true, | 
				
			|||
    server_path: require('selenium-server').path, | 
				
			|||
    host: '127.0.0.1', | 
				
			|||
    port: 4444, | 
				
			|||
    cli_args: { | 
				
			|||
      'webdriver.chrome.driver': require('chromedriver').path | 
				
			|||
    } | 
				
			|||
  }, | 
				
			|||
 | 
				
			|||
  test_settings: { | 
				
			|||
    default: { | 
				
			|||
      selenium_port: 4444, | 
				
			|||
      selenium_host: 'localhost', | 
				
			|||
      silent: true, | 
				
			|||
      globals: { | 
				
			|||
        devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
 | 
				
			|||
    chrome: { | 
				
			|||
      desiredCapabilities: { | 
				
			|||
        browserName: 'chrome', | 
				
			|||
        javascriptEnabled: true, | 
				
			|||
        acceptSslCerts: true | 
				
			|||
      } | 
				
			|||
    }, | 
				
			|||
 | 
				
			|||
    firefox: { | 
				
			|||
      desiredCapabilities: { | 
				
			|||
        browserName: 'firefox', | 
				
			|||
        javascriptEnabled: true, | 
				
			|||
        acceptSslCerts: true | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,48 @@ | 
				
			|||
// 1. start the dev server using production config
 | 
				
			|||
process.env.NODE_ENV = 'testing' | 
				
			|||
 | 
				
			|||
const webpack = require('webpack') | 
				
			|||
const DevServer = require('webpack-dev-server') | 
				
			|||
 | 
				
			|||
const webpackConfig = require('../../build/webpack.prod.conf') | 
				
			|||
const devConfigPromise = require('../../build/webpack.dev.conf') | 
				
			|||
 | 
				
			|||
let server | 
				
			|||
 | 
				
			|||
devConfigPromise.then(devConfig => { | 
				
			|||
  const devServerOptions = devConfig.devServer | 
				
			|||
  const compiler = webpack(webpackConfig) | 
				
			|||
  server = new DevServer(compiler, devServerOptions) | 
				
			|||
  const port = devServerOptions.port | 
				
			|||
  const host = devServerOptions.host | 
				
			|||
  return server.listen(port, host) | 
				
			|||
}) | 
				
			|||
.then(() => { | 
				
			|||
  // 2. run the nightwatch test suite against it
 | 
				
			|||
  // to run in additional browsers:
 | 
				
			|||
  //    1. add an entry in test/e2e/nightwatch.conf.js under "test_settings"
 | 
				
			|||
  //    2. add it to the --env flag below
 | 
				
			|||
  // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
 | 
				
			|||
  // For more information on Nightwatch's config file, see
 | 
				
			|||
  // http://nightwatchjs.org/guide#settings-file
 | 
				
			|||
  let opts = process.argv.slice(2) | 
				
			|||
  if (opts.indexOf('--config') === -1) { | 
				
			|||
    opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) | 
				
			|||
  } | 
				
			|||
  if (opts.indexOf('--env') === -1) { | 
				
			|||
    opts = opts.concat(['--env', 'chrome']) | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  const spawn = require('cross-spawn') | 
				
			|||
  const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) | 
				
			|||
 | 
				
			|||
  runner.on('exit', function (code) { | 
				
			|||
    server.close() | 
				
			|||
    process.exit(code) | 
				
			|||
  }) | 
				
			|||
 | 
				
			|||
  runner.on('error', function (err) { | 
				
			|||
    server.close() | 
				
			|||
    throw err | 
				
			|||
  }) | 
				
			|||
}) | 
				
			|||
@ -0,0 +1,19 @@ | 
				
			|||
// For authoring Nightwatch tests, see
 | 
				
			|||
// http://nightwatchjs.org/guide#usage
 | 
				
			|||
 | 
				
			|||
module.exports = { | 
				
			|||
  'default e2e tests': function (browser) { | 
				
			|||
    // automatically uses dev Server port from /config.index.js
 | 
				
			|||
    // default: http://localhost:8080
 | 
				
			|||
    // see nightwatch.conf.js
 | 
				
			|||
    const devServer = browser.globals.devServerURL | 
				
			|||
 | 
				
			|||
    browser | 
				
			|||
      .url(devServer) | 
				
			|||
      .waitForElementVisible('#app', 5000) | 
				
			|||
      .assert.elementPresent('.hello') | 
				
			|||
      .assert.containsText('h1', 'Welcome to Your Vue.js App') | 
				
			|||
      .assert.elementCount('img', 1) | 
				
			|||
      .end() | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,7 @@ | 
				
			|||
{ | 
				
			|||
  "env": {  | 
				
			|||
    "jest": true | 
				
			|||
  }, | 
				
			|||
  "globals": {  | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,30 @@ | 
				
			|||
const path = require('path') | 
				
			|||
 | 
				
			|||
module.exports = { | 
				
			|||
  rootDir: path.resolve(__dirname, '../../'), | 
				
			|||
  moduleFileExtensions: [ | 
				
			|||
    'js', | 
				
			|||
    'json', | 
				
			|||
    'vue' | 
				
			|||
  ], | 
				
			|||
  moduleNameMapper: { | 
				
			|||
    '^@/(.*)$': '<rootDir>/src/$1' | 
				
			|||
  }, | 
				
			|||
  transform: { | 
				
			|||
    '^.+\\.js$': '<rootDir>/node_modules/babel-jest', | 
				
			|||
    '.*\\.(vue)$': '<rootDir>/node_modules/vue-jest' | 
				
			|||
  }, | 
				
			|||
  testPathIgnorePatterns: [ | 
				
			|||
    '<rootDir>/test/e2e' | 
				
			|||
  ], | 
				
			|||
  snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'], | 
				
			|||
  setupFiles: ['<rootDir>/test/unit/setup'], | 
				
			|||
  mapCoverage: true, | 
				
			|||
  coverageDirectory: '<rootDir>/test/unit/coverage', | 
				
			|||
  collectCoverageFrom: [ | 
				
			|||
    'src/**/*.{js,vue}', | 
				
			|||
    '!src/main.js', | 
				
			|||
    '!src/router/index.js', | 
				
			|||
    '!**/node_modules/**' | 
				
			|||
  ] | 
				
			|||
} | 
				
			|||
@ -0,0 +1,3 @@ | 
				
			|||
import Vue from 'vue' | 
				
			|||
 | 
				
			|||
Vue.config.productionTip = false | 
				
			|||
@ -0,0 +1,11 @@ | 
				
			|||
import Vue from 'vue' | 
				
			|||
import HelloWorld from '@/components/HelloWorld' | 
				
			|||
 | 
				
			|||
describe('HelloWorld.vue', () => { | 
				
			|||
  it('should render correct contents', () => { | 
				
			|||
    const Constructor = Vue.extend(HelloWorld) | 
				
			|||
    const vm = new Constructor().$mount() | 
				
			|||
    expect(vm.$el.querySelector('.hello h1').textContent) | 
				
			|||
      .toEqual('Welcome to Your Vue.js App') | 
				
			|||
  }) | 
				
			|||
}) | 
				
			|||
@ -1,22 +0,0 @@ | 
				
			|||
<?xml version="1.0" encoding="UTF-8"?> | 
				
			|||
<project version="4"> | 
				
			|||
  <component name="CompilerConfiguration"> | 
				
			|||
    <annotationProcessing> | 
				
			|||
      <profile default="true" name="Default" enabled="true" /> | 
				
			|||
      <profile name="Maven default annotation processors profile" enabled="true"> | 
				
			|||
        <sourceOutputDir name="target/generated-sources/annotations" /> | 
				
			|||
        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" /> | 
				
			|||
        <outputRelativeToContentRoot value="true" /> | 
				
			|||
        <module name="vote" /> | 
				
			|||
      </profile> | 
				
			|||
    </annotationProcessing> | 
				
			|||
    <bytecodeTargetLevel> | 
				
			|||
      <module name="vote" target="1.8" /> | 
				
			|||
    </bytecodeTargetLevel> | 
				
			|||
  </component> | 
				
			|||
  <component name="JavacSettings"> | 
				
			|||
    <option name="ADDITIONAL_OPTIONS_OVERRIDE"> | 
				
			|||
      <module name="vote" options="-parameters" /> | 
				
			|||
    </option> | 
				
			|||
  </component> | 
				
			|||
</project> | 
				
			|||
@ -1,7 +0,0 @@ | 
				
			|||
<?xml version="1.0" encoding="UTF-8"?> | 
				
			|||
<project version="4"> | 
				
			|||
  <component name="Encoding"> | 
				
			|||
    <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" /> | 
				
			|||
    <file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" /> | 
				
			|||
  </component> | 
				
			|||
</project> | 
				
			|||
| 
		 After Width: | Height: | Size: 3.6 KiB  | 
| 
		 After Width: | Height: | Size: 133 KiB  | 
| 
		 After Width: | Height: | Size: 100 KiB  | 
| 
		 After Width: | Height: | Size: 100 KiB  | 
| 
		 After Width: | Height: | Size: 116 KiB  | 
@ -0,0 +1,43 @@ | 
				
			|||
package com.votesystem.ssl; | 
				
			|||
 | 
				
			|||
import com.google.gson.Gson; | 
				
			|||
import com.votesystem.ssl.utils.RedisUtils; | 
				
			|||
import lombok.extern.slf4j.Slf4j; | 
				
			|||
import org.springframework.boot.SpringApplication; | 
				
			|||
import org.springframework.boot.autoconfigure.SpringBootApplication; | 
				
			|||
import org.springframework.context.annotation.Bean; | 
				
			|||
import springfox.documentation.swagger2.annotations.EnableSwagger2; | 
				
			|||
import com.votesystem.ssl.utils.IdWorker; | 
				
			|||
 | 
				
			|||
import java.util.Random; | 
				
			|||
 | 
				
			|||
@Slf4j | 
				
			|||
@EnableSwagger2 | 
				
			|||
@SpringBootApplication | 
				
			|||
public class VoteApplication { | 
				
			|||
 | 
				
			|||
    public static void main(String[] args) { | 
				
			|||
        log.info("SpringBootApplication run..."); | 
				
			|||
        SpringApplication.run(VoteApplication.class, args); | 
				
			|||
    } | 
				
			|||
    @Bean | 
				
			|||
    public Random createRandom(){ | 
				
			|||
        return new Random(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Bean | 
				
			|||
    public Gson createGson(){ | 
				
			|||
        return new Gson(); | 
				
			|||
    } | 
				
			|||
    @Bean | 
				
			|||
    public IdWorker createIdWorker(){ | 
				
			|||
        return new IdWorker(0,0); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Bean | 
				
			|||
    public RedisUtils createRedisUtil(){ | 
				
			|||
        return new RedisUtils(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,29 @@ | 
				
			|||
package com.votesystem.ssl.config; | 
				
			|||
/*配置了一个ThreadPoolTaskExecutor,它是一个用于执行异步任务的线程池。 | 
				
			|||
设置线程池的核心线程数为2,最大线程数为10。这个表示线程池中最小应该存在的线程数为2,最大可以存在的线程数为10,当线程池中的任务数超过了2时,线程池会自动创建新的线程,直到线程数达到了10的上限。 | 
				
			|||
设置了线程池中线程的名称前缀为"vote_task_worker-",这个可以方便在日志中查看线程池的执行情况。 | 
				
			|||
设置线程池的队列容量为30,这个表示当线程池中的任务数超过了最大线程数,未被线程执行的任务将被放入队列里等待执行,队列容量为30表示队列中最多可以存放30个等待执行的任务。 | 
				
			|||
通过@Bean注解标记asyncExecutor()方法,表示这个方法会被Spring容器自动加载并且在程序中创建一个线程池。*/ | 
				
			|||
import org.springframework.context.annotation.Bean; | 
				
			|||
import org.springframework.context.annotation.Configuration; | 
				
			|||
import org.springframework.scheduling.annotation.EnableAsync; | 
				
			|||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | 
				
			|||
 | 
				
			|||
import java.util.concurrent.Executor; | 
				
			|||
 | 
				
			|||
@Configuration | 
				
			|||
@EnableAsync | 
				
			|||
public class AsyncConfiguration { | 
				
			|||
 | 
				
			|||
    @Bean | 
				
			|||
    public Executor asyncExecutor() { | 
				
			|||
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); | 
				
			|||
        executor.setCorePoolSize(2); | 
				
			|||
        executor.setMaxPoolSize(10); | 
				
			|||
        executor.setThreadNamePrefix("vote_task_worker-"); | 
				
			|||
        executor.setQueueCapacity(30); | 
				
			|||
        executor.initialize(); | 
				
			|||
        return executor; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,35 @@ | 
				
			|||
package com.votesystem.ssl.config; | 
				
			|||
/*处理CORS跨域请求 | 
				
			|||
  配置静态资源映射*/ | 
				
			|||
import org.springframework.beans.factory.annotation.Value; | 
				
			|||
import org.springframework.boot.SpringBootConfiguration; | 
				
			|||
import org.springframework.web.servlet.config.annotation.CorsRegistry; | 
				
			|||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; | 
				
			|||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | 
				
			|||
 | 
				
			|||
@SpringBootConfiguration | 
				
			|||
public class MyWebConfiguration implements WebMvcConfigurer { | 
				
			|||
 | 
				
			|||
    @Override | 
				
			|||
    public void addCorsMappings(CorsRegistry registry) { | 
				
			|||
        registry.addMapping("/**") | 
				
			|||
                .allowCredentials(true) | 
				
			|||
                .allowedOrigins("*") | 
				
			|||
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") | 
				
			|||
                .allowedHeaders("*") | 
				
			|||
                .maxAge(3600); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Value("${image.save-path}") | 
				
			|||
    private String imagePath; | 
				
			|||
 | 
				
			|||
    @Override | 
				
			|||
    public void addResourceHandlers(ResourceHandlerRegistry registry) { | 
				
			|||
        registry.addResourceHandler("/api/file/**").addResourceLocations("file:" + imagePath + "/"); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
//    @Override
 | 
				
			|||
//    public void addResourceHandlers(ResourceHandlerRegistry registry) {
 | 
				
			|||
//        registry.addResourceHandler("/api/file/**").addResourceLocations("file:" + "E:/project/vote/vote/img/");
 | 
				
			|||
//    }
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,100 @@ | 
				
			|||
package com.votesystem.ssl.config; | 
				
			|||
 | 
				
			|||
import com.votesystem.ssl.filter.URLPathMatchingFilter; | 
				
			|||
import com.votesystem.ssl.realm.MyRealm; | 
				
			|||
import org.apache.shiro.authc.credential.HashedCredentialsMatcher; | 
				
			|||
import org.apache.shiro.mgt.SecurityManager; | 
				
			|||
import org.apache.shiro.spring.LifecycleBeanPostProcessor; | 
				
			|||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; | 
				
			|||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean; | 
				
			|||
import org.apache.shiro.web.mgt.CookieRememberMeManager; | 
				
			|||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager; | 
				
			|||
import org.apache.shiro.web.servlet.SimpleCookie; | 
				
			|||
import org.springframework.context.annotation.Bean; | 
				
			|||
import org.springframework.context.annotation.Configuration; | 
				
			|||
 | 
				
			|||
import javax.servlet.Filter; | 
				
			|||
import java.util.HashMap; | 
				
			|||
import java.util.LinkedHashMap; | 
				
			|||
import java.util.Map; | 
				
			|||
 | 
				
			|||
@Configuration | 
				
			|||
public class ShiroConfiguration { | 
				
			|||
//    Shiro的一个配置项
 | 
				
			|||
    @Bean | 
				
			|||
    public static LifecycleBeanPostProcessor getLifecycleBeanProcessor() { | 
				
			|||
        return new LifecycleBeanPostProcessor(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Bean | 
				
			|||
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { | 
				
			|||
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); | 
				
			|||
        shiroFilterFactoryBean.setSecurityManager(securityManager); | 
				
			|||
        shiroFilterFactoryBean.setLoginUrl("/nowhere"); | 
				
			|||
 | 
				
			|||
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); | 
				
			|||
        Map<String, Filter> customizedFilter = new HashMap<>();  | 
				
			|||
 | 
				
			|||
        customizedFilter.put("url", getURLPathMatchingFilter()); | 
				
			|||
 | 
				
			|||
        filterChainDefinitionMap.put("/api/menu", "authc"); | 
				
			|||
        filterChainDefinitionMap.put("/api/admin/**", "authc"); | 
				
			|||
 | 
				
			|||
        filterChainDefinitionMap.put("/api/admin/**", "url");  | 
				
			|||
 | 
				
			|||
        shiroFilterFactoryBean.setFilters(customizedFilter);  | 
				
			|||
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); | 
				
			|||
        return shiroFilterFactoryBean;    /*在该配置中,将所有自定义过滤器添加到ShiroFilter中。*/ | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public Filter getURLPathMatchingFilter() { | 
				
			|||
        return new URLPathMatchingFilter(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Bean | 
				
			|||
    public SecurityManager securityManager() { | 
				
			|||
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); | 
				
			|||
        securityManager.setRealm(getMyRealm()); | 
				
			|||
        securityManager.setRememberMeManager(rememberMeManager()); | 
				
			|||
        return securityManager; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public CookieRememberMeManager rememberMeManager() { | 
				
			|||
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); | 
				
			|||
        cookieRememberMeManager.setCookie(rememberMeCookie()); | 
				
			|||
        cookieRememberMeManager.setCipherKey("EVANNIGHTLY_WAOU".getBytes()); | 
				
			|||
        return cookieRememberMeManager; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Bean | 
				
			|||
    public SimpleCookie rememberMeCookie() { | 
				
			|||
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); | 
				
			|||
        simpleCookie.setMaxAge(259200); | 
				
			|||
        return simpleCookie; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @Bean | 
				
			|||
    public MyRealm getMyRealm() { | 
				
			|||
        MyRealm myRealm = new MyRealm(); | 
				
			|||
        myRealm.setCredentialsMatcher(hashedCredentialsMatcher()); | 
				
			|||
        return myRealm; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Bean | 
				
			|||
    public HashedCredentialsMatcher hashedCredentialsMatcher() { | 
				
			|||
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); | 
				
			|||
        hashedCredentialsMatcher.setHashAlgorithmName("md5"); | 
				
			|||
        hashedCredentialsMatcher.setHashIterations(2); | 
				
			|||
        return hashedCredentialsMatcher; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Bean | 
				
			|||
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { | 
				
			|||
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); | 
				
			|||
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); | 
				
			|||
        return authorizationAttributeSourceAdvisor; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,64 @@ | 
				
			|||
package com.votesystem.ssl.config; | 
				
			|||
 | 
				
			|||
import org.springframework.context.annotation.Bean; | 
				
			|||
import org.springframework.context.annotation.Configuration; | 
				
			|||
import springfox.documentation.builders.ApiInfoBuilder; | 
				
			|||
import springfox.documentation.builders.PathSelectors; | 
				
			|||
import springfox.documentation.builders.RequestHandlerSelectors; | 
				
			|||
import springfox.documentation.service.ApiInfo; | 
				
			|||
import springfox.documentation.spi.DocumentationType; | 
				
			|||
import springfox.documentation.spring.web.plugins.Docket; | 
				
			|||
 | 
				
			|||
@Configuration | 
				
			|||
public class Swagger2Configuration { | 
				
			|||
 | 
				
			|||
    //版本
 | 
				
			|||
    public static final String VERSION = "1.0.0"; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 管理中心api,接口前缀:admin | 
				
			|||
     * | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @Bean | 
				
			|||
    public Docket adminApi() { | 
				
			|||
        return new Docket(DocumentationType.SWAGGER_12) | 
				
			|||
                .apiInfo(adminApiInfo()) | 
				
			|||
                .select() | 
				
			|||
                .apis(RequestHandlerSelectors.basePackage("com.votesystem.ssl.controller.admin")) | 
				
			|||
                .paths(PathSelectors.any()) // 可以根据url路径设置哪些请求加入文档,忽略哪些请求
 | 
				
			|||
                .build() | 
				
			|||
                .groupName("管理中心"); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    private ApiInfo adminApiInfo() { | 
				
			|||
        return new ApiInfoBuilder() | 
				
			|||
                .title("投票系统管理中心接口文档") //设置文档的标题
 | 
				
			|||
                .description("管理中心接口") // 设置文档的描述
 | 
				
			|||
                .version(VERSION) // 设置文档的版本信息-> 1.0.0 Version information
 | 
				
			|||
                .build(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @Bean | 
				
			|||
    public Docket UserApi() { | 
				
			|||
        return new Docket(DocumentationType.SWAGGER_12) | 
				
			|||
                .apiInfo(userApiInfo()) | 
				
			|||
                .select() | 
				
			|||
                .apis(RequestHandlerSelectors.basePackage("com.votesystem.ssl.controller.user")) | 
				
			|||
                .paths(PathSelectors.any()) // 可以根据url路径设置哪些请求加入文档,忽略哪些请求
 | 
				
			|||
                .build() | 
				
			|||
                .groupName("用户中心"); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private ApiInfo userApiInfo() { | 
				
			|||
        return new ApiInfoBuilder() | 
				
			|||
                .title("投票系统用户接口") //设置文档的标题
 | 
				
			|||
                .description("用户接口的接口") // 设置文档的描述
 | 
				
			|||
                .version(VERSION) // 设置文档的版本信息-> 1.0.0 Version information
 | 
				
			|||
                .build(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,31 @@ | 
				
			|||
package com.votesystem.ssl.controller; | 
				
			|||
 | 
				
			|||
import lombok.extern.slf4j.Slf4j; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.web.bind.annotation.GetMapping; | 
				
			|||
import org.springframework.web.bind.annotation.RequestMapping; | 
				
			|||
import org.springframework.web.bind.annotation.RequestParam; | 
				
			|||
import org.springframework.web.bind.annotation.RestController; | 
				
			|||
import com.votesystem.ssl.result.Result; | 
				
			|||
import com.votesystem.ssl.service.IUserService; | 
				
			|||
 | 
				
			|||
import javax.servlet.http.HttpServletRequest; | 
				
			|||
import javax.servlet.http.HttpServletResponse; | 
				
			|||
 | 
				
			|||
@Slf4j | 
				
			|||
@RestController | 
				
			|||
@RequestMapping("/api/admin") | 
				
			|||
public class TestAdminController { | 
				
			|||
    @Autowired | 
				
			|||
    IUserService userService; | 
				
			|||
 | 
				
			|||
    @GetMapping("/list-user") | 
				
			|||
    public Result listUsers( | 
				
			|||
            HttpServletRequest request, | 
				
			|||
            HttpServletResponse response, | 
				
			|||
            @RequestParam("page")int page, | 
				
			|||
            @RequestParam("size")int size){ | 
				
			|||
 | 
				
			|||
        return userService.listUsers(request,response,page,size); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,69 @@ | 
				
			|||
package com.votesystem.ssl.controller; | 
				
			|||
 | 
				
			|||
import com.votesystem.ssl.utils.Constants; | 
				
			|||
import com.votesystem.ssl.utils.RedisUtils; | 
				
			|||
import com.wf.captcha.SpecCaptcha; | 
				
			|||
import com.wf.captcha.base.Captcha; | 
				
			|||
import lombok.extern.slf4j.Slf4j; | 
				
			|||
import org.apache.shiro.SecurityUtils; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.web.bind.annotation.GetMapping; | 
				
			|||
import org.springframework.web.bind.annotation.RequestMapping; | 
				
			|||
import org.springframework.web.bind.annotation.ResponseBody; | 
				
			|||
import org.springframework.web.bind.annotation.RestController; | 
				
			|||
 | 
				
			|||
import javax.servlet.http.HttpServletRequest; | 
				
			|||
import javax.servlet.http.HttpServletResponse; | 
				
			|||
 | 
				
			|||
@Slf4j | 
				
			|||
@RestController | 
				
			|||
public class TestController { | 
				
			|||
 | 
				
			|||
    @Autowired | 
				
			|||
    RedisUtils redisUtils; | 
				
			|||
 | 
				
			|||
    //http://localhost:8443/test/captcha
 | 
				
			|||
    @RequestMapping("/test/captcha") | 
				
			|||
    public void captcha(HttpServletRequest request, HttpServletResponse response) throws Exception { | 
				
			|||
        // 设置请求头为输出图片类型
 | 
				
			|||
        response.setContentType("image/gif"); | 
				
			|||
        response.setHeader("Pragma", "No-cache"); | 
				
			|||
        response.setHeader("Cache-Control", "no-cache"); | 
				
			|||
        response.setDateHeader("Expires", 0); | 
				
			|||
 | 
				
			|||
        // 三个参数分别为宽、高、位数
 | 
				
			|||
        SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 5); | 
				
			|||
        // 设置字体
 | 
				
			|||
        // specCaptcha.setFont(new Font("Verdana", Font.PLAIN, 32));  // 有默认字体,可以不用设置
 | 
				
			|||
        specCaptcha.setFont(Captcha.FONT_1); | 
				
			|||
        // 设置类型,纯数字、纯字母、字母数字混合
 | 
				
			|||
        //specCaptcha.setCharType(Captcha.TYPE_ONLY_NUMBER);
 | 
				
			|||
        specCaptcha.setCharType(Captcha.TYPE_DEFAULT); | 
				
			|||
 | 
				
			|||
        String content = specCaptcha.text().toLowerCase(); | 
				
			|||
        log.info("captcha content == > " + content); | 
				
			|||
        // 验证码存入session
 | 
				
			|||
//        request.getSession().setAttribute("captcha", content);
 | 
				
			|||
        //存到redis
 | 
				
			|||
        //10分钟有效
 | 
				
			|||
        redisUtils.set(Constants.User.KEY_CAPTCHA_CONTENT +"123456",content,60 * 10); | 
				
			|||
 | 
				
			|||
        // 输出图片流
 | 
				
			|||
        specCaptcha.out(response.getOutputStream()); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @RequestMapping("/test/getCurrentUser") | 
				
			|||
    public void getCurrentUser(){ | 
				
			|||
        String username = SecurityUtils.getSubject().getPrincipal().toString(); | 
				
			|||
        log.info("username == > " + username); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @ResponseBody | 
				
			|||
    @GetMapping(value = "api/authentication") | 
				
			|||
    public String authentication(){ | 
				
			|||
        return "身份认证成功"; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,22 @@ | 
				
			|||
package com.votesystem.ssl.controller.admin; | 
				
			|||
 | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.web.bind.annotation.*; | 
				
			|||
import com.votesystem.ssl.result.Result; | 
				
			|||
import com.votesystem.ssl.result.ResultFactory; | 
				
			|||
import com.votesystem.ssl.service.AdminMenuService; | 
				
			|||
 | 
				
			|||
@RestController | 
				
			|||
public class MenuController { | 
				
			|||
    @Autowired | 
				
			|||
    AdminMenuService adminMenuService; | 
				
			|||
 | 
				
			|||
    @GetMapping("/api/menu") | 
				
			|||
    public Result menu() {return ResultFactory.buildSuccessResult(adminMenuService.getMenusByCurrentUser()); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @GetMapping("/api/admin/role/menu") | 
				
			|||
    public Result listAllMenus() { | 
				
			|||
        return ResultFactory.buildSuccessResult(adminMenuService.getMenusByRoleId(1)); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,42 @@ | 
				
			|||
package com.votesystem.ssl.controller.admin; | 
				
			|||
 | 
				
			|||
import com.votesystem.ssl.pojo.Notice; | 
				
			|||
import lombok.extern.slf4j.Slf4j; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.web.bind.annotation.*; | 
				
			|||
import com.votesystem.ssl.result.Result; | 
				
			|||
import com.votesystem.ssl.service.INoticeService; | 
				
			|||
 | 
				
			|||
@Slf4j | 
				
			|||
@RestController | 
				
			|||
@RequestMapping("/api") | 
				
			|||
public class NoticeController { | 
				
			|||
 | 
				
			|||
    @Autowired | 
				
			|||
    INoticeService noticeService; | 
				
			|||
 | 
				
			|||
    @PostMapping("/admin/notice") | 
				
			|||
    public Result addNotice(@RequestBody Notice notice){ | 
				
			|||
        return noticeService.addNotice(notice); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @DeleteMapping("/admin/notice/{noticeId}") | 
				
			|||
    public Result deleteNotice(@PathVariable("noticeId") String  noticeId){ | 
				
			|||
        return noticeService.deleteNotice(noticeId); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @GetMapping("/notice/{noticeId}") | 
				
			|||
    public Result getNotice(@PathVariable("noticeId") String  noticeId){ | 
				
			|||
        return noticeService.getNotice(noticeId); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @GetMapping("/notice/list") | 
				
			|||
    public Result listNotice(@RequestParam("page")int page,@RequestParam("size")int size){ | 
				
			|||
        return noticeService.listNotice(page,size); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @PutMapping("/admin/notice/{noticeId}") | 
				
			|||
    public Result updateNotice(@PathVariable("noticeId") String  noticeId,Notice notice){ | 
				
			|||
        return noticeService.updateNotice(noticeId,notice); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,73 @@ | 
				
			|||
package com.votesystem.ssl.controller.admin; | 
				
			|||
 | 
				
			|||
import com.votesystem.ssl.pojo.AdminRole; | 
				
			|||
import lombok.extern.slf4j.Slf4j; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.web.bind.annotation.*; | 
				
			|||
import com.votesystem.ssl.result.Result; | 
				
			|||
import com.votesystem.ssl.result.ResultFactory; | 
				
			|||
import com.votesystem.ssl.service.AdminPermissionService; | 
				
			|||
import com.votesystem.ssl.service.AdminRoleMenuService; | 
				
			|||
import com.votesystem.ssl.service.AdminRolePermissionService; | 
				
			|||
import com.votesystem.ssl.service.AdminRoleService; | 
				
			|||
 | 
				
			|||
import java.util.LinkedHashMap; | 
				
			|||
 | 
				
			|||
@Slf4j | 
				
			|||
@RestController | 
				
			|||
@RequestMapping("/api/admin/role") | 
				
			|||
public class RoleController { | 
				
			|||
 | 
				
			|||
    @Autowired | 
				
			|||
    AdminRoleService adminRoleService; | 
				
			|||
    @Autowired | 
				
			|||
    AdminPermissionService adminPermissionService; | 
				
			|||
    @Autowired | 
				
			|||
    AdminRolePermissionService adminRolePermissionService; | 
				
			|||
    @Autowired | 
				
			|||
    AdminRoleMenuService adminRoleMenuService; | 
				
			|||
 | 
				
			|||
    @GetMapping | 
				
			|||
    public Result listRoles(){ | 
				
			|||
        return ResultFactory.buildSuccessResult(adminRoleService.list()); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @PutMapping("/status") | 
				
			|||
    public Result updateRoleStatus(@RequestBody AdminRole requestRole) { | 
				
			|||
        AdminRole adminRole = adminRoleService.updateRoleStatus(requestRole); | 
				
			|||
        String message = "用户" + adminRole.getNameZh() + "状态更新成功"; | 
				
			|||
        return ResultFactory.buildSuccessResult(message); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @PutMapping | 
				
			|||
    public Result editRole(@RequestBody AdminRole requestRole) { | 
				
			|||
        adminRoleService.addOrUpdate(requestRole); | 
				
			|||
        adminRolePermissionService.savePermChanges(requestRole.getId(), requestRole.getPerms()); | 
				
			|||
        String message = "修改角色信息成功"; | 
				
			|||
        return ResultFactory.buildSuccessResult(message); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @PostMapping | 
				
			|||
    public Result addRole(@RequestBody AdminRole requestRole) { | 
				
			|||
        if (adminRoleService.editRole(requestRole)) { | 
				
			|||
            return ResultFactory.buildSuccessResult("修改用户成功"); | 
				
			|||
        } else { | 
				
			|||
            return ResultFactory.buildFailResult("参数错误,修改失败"); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @GetMapping("/perm") | 
				
			|||
    public Result listPerms() { | 
				
			|||
        return ResultFactory.buildSuccessResult(adminPermissionService.list()); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @PutMapping("/menu") | 
				
			|||
    public Result updateRoleMenu(@RequestParam int rid, @RequestBody LinkedHashMap menusIds) { | 
				
			|||
        if(adminRoleMenuService.updateRoleMenu(rid, menusIds)) { | 
				
			|||
            return ResultFactory.buildSuccessResult("更新成功"); | 
				
			|||
        } else { | 
				
			|||
            return ResultFactory.buildFailResult("参数错误,更新失败"); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,19 @@ | 
				
			|||
package com.votesystem.ssl.controller.admin; | 
				
			|||
 | 
				
			|||
import lombok.extern.slf4j.Slf4j; | 
				
			|||
import org.springframework.web.bind.annotation.RequestMapping; | 
				
			|||
import org.springframework.web.bind.annotation.RestController; | 
				
			|||
 | 
				
			|||
@Slf4j | 
				
			|||
@RestController | 
				
			|||
@RequestMapping("/api/admin/user") | 
				
			|||
public class UserController { | 
				
			|||
 | 
				
			|||
    //分页列出用户
 | 
				
			|||
 | 
				
			|||
    //更改用户状态
 | 
				
			|||
 | 
				
			|||
    //重置用户密码
 | 
				
			|||
 | 
				
			|||
    //修改用户信息
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,75 @@ | 
				
			|||
package com.votesystem.ssl.controller.user; | 
				
			|||
 | 
				
			|||
import com.votesystem.ssl.pojo.Activity; | 
				
			|||
import jdk.nashorn.internal.ir.RuntimeNode; | 
				
			|||
import lombok.extern.slf4j.Slf4j; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.web.bind.annotation.*; | 
				
			|||
import com.votesystem.ssl.result.Result; | 
				
			|||
import com.votesystem.ssl.service.IActivityService; | 
				
			|||
 | 
				
			|||
import javax.servlet.http.HttpServletRequest; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
@Slf4j | 
				
			|||
@RestController | 
				
			|||
@RequestMapping("/api") | 
				
			|||
public class ActivityController { | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @Autowired | 
				
			|||
    IActivityService activityService; | 
				
			|||
 | 
				
			|||
    @PostMapping("/admin/activity") | 
				
			|||
    public Result addActivity(@RequestBody Activity activity){ | 
				
			|||
        return activityService.addActivity(activity); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @DeleteMapping("/admin/activity/{activityId}") | 
				
			|||
    public Result deleteActivity(@PathVariable("activityId") String  activityId){ | 
				
			|||
        return activityService.deleteActivity(activityId); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @GetMapping("/activity/{activityId}") | 
				
			|||
    public Result getActivity(@PathVariable("activityId") String  activityId){ | 
				
			|||
        return activityService.getActivity(activityId); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @GetMapping("/admin/activity/list") | 
				
			|||
    public Result listActivity(@RequestParam("page")int page,@RequestParam("size")int size,@RequestParam("userName") String userName){ | 
				
			|||
        return activityService.listActivity(page,size); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 内容管理页面的删除 | 
				
			|||
     * @param activityId | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @GetMapping("/admin/activity/list/del") | 
				
			|||
    public Result delActivity(@RequestParam("activityId") String activityId){ | 
				
			|||
        log.info(activityId); | 
				
			|||
        return activityService.validActivity(activityId); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @GetMapping("/activity/list/case") | 
				
			|||
    public Result listActivityByCase(@RequestParam("page")int page, | 
				
			|||
                                     @RequestParam("size")int size){ | 
				
			|||
        return activityService.listActivityByCase(page,size); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @GetMapping("/admin/activity/list/self") | 
				
			|||
    public Result listActivityByUser(@RequestParam("userName") String userName, | 
				
			|||
                                     @RequestParam("page")int page, | 
				
			|||
                                     @RequestParam("size")int size){ | 
				
			|||
        return activityService.listActivityByUser(userName,page,size); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @PutMapping("/admin/activity/{activityId}") | 
				
			|||
    public Result updateActivity(@PathVariable("activityId") String activityId, | 
				
			|||
                                 @RequestBody Activity activity){ | 
				
			|||
        return activityService.updateActivity(activityId,activity); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,139 @@ | 
				
			|||
package com.votesystem.ssl.controller.user; | 
				
			|||
 | 
				
			|||
import com.votesystem.ssl.pojo.Candidate; | 
				
			|||
import com.votesystem.ssl.utils.StringUtils; | 
				
			|||
import lombok.extern.slf4j.Slf4j; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.beans.factory.annotation.Value; | 
				
			|||
import org.springframework.web.bind.annotation.*; | 
				
			|||
import org.springframework.web.multipart.MultipartFile; | 
				
			|||
import com.votesystem.ssl.result.Result; | 
				
			|||
import com.votesystem.ssl.result.ResultFactory; | 
				
			|||
import com.votesystem.ssl.service.ICandidateService; | 
				
			|||
 | 
				
			|||
import java.io.File; | 
				
			|||
import java.io.IOException; | 
				
			|||
 | 
				
			|||
@Slf4j | 
				
			|||
@RestController | 
				
			|||
@RequestMapping("/api") | 
				
			|||
public class CandidateController { | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @Autowired | 
				
			|||
    ICandidateService candidateService; | 
				
			|||
    @PostMapping("/admin/candidate") | 
				
			|||
    public Result addACandidate(@RequestBody Candidate candidate){ | 
				
			|||
        return candidateService.addCandidate(candidate); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @DeleteMapping("/admin/candidate/{candidateId}") | 
				
			|||
    public Result deleteCandidate(@PathVariable("candidateId") String  candidateId){ | 
				
			|||
        return candidateService.deleteCandidate(candidateId); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @PutMapping("/admin/candidate/state/{candidateId}") | 
				
			|||
    public Result updateState(@PathVariable("candidateId") String  candidateId,@RequestParam("state") boolean state){ | 
				
			|||
        return candidateService.updateState(candidateId,state); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @GetMapping("/candidate/{candidateId}") | 
				
			|||
    public Result getCandidate(@PathVariable("candidateId") String  candidateId){ | 
				
			|||
        return candidateService.getCandidate(candidateId); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 候选人编辑 | 
				
			|||
     * 根据活动分页列出候选人   == > 获取全部候选人(接口前要加admin) | 
				
			|||
     * @param page | 
				
			|||
     * @param size | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @GetMapping("/admin/candidate/list/{activityId}") | 
				
			|||
    public Result listCandidate(@PathVariable("activityId")String activityId, | 
				
			|||
                                @RequestParam("page")int page, | 
				
			|||
                                @RequestParam("size")int size){ | 
				
			|||
        return candidateService.listCandidate(activityId,page,size); | 
				
			|||
    } | 
				
			|||
    /** | 
				
			|||
     * 根据活动列出状态正常的候选人 === > (接口前面不用加/admin) | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @GetMapping("/candidate/list/all/{activityId}") | 
				
			|||
    public Result listAllNormalCandidate(@PathVariable("activityId")String activityId){ | 
				
			|||
        return candidateService.listAllNormalCandidate(activityId); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 根据活动分页列出状态正常的候选人  === > (接口前面不用加/admin) | 
				
			|||
     * @param page | 
				
			|||
     * @param size | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @GetMapping("/candidate/list/{activityId}") | 
				
			|||
    public Result listNormalCandidate(@PathVariable("activityId")String activityId, | 
				
			|||
                                @RequestParam("page")int page, | 
				
			|||
                                @RequestParam("size")int size){ | 
				
			|||
        return candidateService.listNormalCandidate(activityId,page,size); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 排序列出 | 
				
			|||
     * @param activityId | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @GetMapping("/candidate/list/sequence/{activityId}") | 
				
			|||
    public Result listNormalCandidate(@PathVariable("activityId")String activityId){ | 
				
			|||
        return candidateService.listRankCandidate(activityId); | 
				
			|||
    } | 
				
			|||
    /** | 
				
			|||
     * 分页列出状态正常的候选人 | 
				
			|||
     * @param candidateId | 
				
			|||
     * @param candidate | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @PutMapping("/admin/candidate/{candidateId}") | 
				
			|||
    public Result updateCandidate(@PathVariable("candidateId") String  candidateId,@RequestBody Candidate candidate){ | 
				
			|||
        return candidateService.updateCandidate(candidateId,candidate); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @DeleteMapping("/batch") | 
				
			|||
    public Result multipleRemove(@RequestParam String selectedCandidateIds){ | 
				
			|||
        System.out.println(selectedCandidateIds); | 
				
			|||
        String[] cids =  selectedCandidateIds.split(" "); | 
				
			|||
//        return ResultFactory.buildSuccessResult("删除成功");
 | 
				
			|||
        try { | 
				
			|||
            for(String cid : cids){ | 
				
			|||
                candidateService.deleteCandidate(cid); | 
				
			|||
            } | 
				
			|||
        }catch (Exception e){ | 
				
			|||
            e.printStackTrace(); | 
				
			|||
            String message = "删除失败"; | 
				
			|||
            return ResultFactory.buildFailResult(message); | 
				
			|||
        } | 
				
			|||
        return ResultFactory.buildSuccessResult("删除成功"); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @Value("${image.save-path}") | 
				
			|||
    private String imagePath; | 
				
			|||
 | 
				
			|||
    @PostMapping("/admin/candidate/covers") | 
				
			|||
    public String coversUpload(MultipartFile file) throws Exception { | 
				
			|||
        String folder = imagePath; | 
				
			|||
        File imageFolder = new File(folder); | 
				
			|||
        File f = new File(imageFolder, StringUtils.getRandomString(6) + file.getOriginalFilename() | 
				
			|||
                .substring(file.getOriginalFilename().length() - 4)); | 
				
			|||
        if (!f.getParentFile().exists()) | 
				
			|||
            f.getParentFile().mkdirs(); | 
				
			|||
        try { | 
				
			|||
            file.transferTo(f); | 
				
			|||
            String imgURL = "http://localhost:8443/api/file/" + f.getName(); | 
				
			|||
            return imgURL; | 
				
			|||
        } catch (IOException e) { | 
				
			|||
            e.printStackTrace(); | 
				
			|||
            return ""; | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,4 @@ | 
				
			|||
package com.votesystem.ssl.controller.user; | 
				
			|||
 | 
				
			|||
public class ImageController { | 
				
			|||
} | 
				
			|||
@ -0,0 +1,258 @@ | 
				
			|||
package com.votesystem.ssl.controller.user; | 
				
			|||
 | 
				
			|||
import com.votesystem.ssl.pojo.User; | 
				
			|||
import io.swagger.annotations.ApiResponse; | 
				
			|||
import io.swagger.annotations.ApiResponses; | 
				
			|||
import lombok.extern.slf4j.Slf4j; | 
				
			|||
import org.apache.shiro.SecurityUtils; | 
				
			|||
import org.apache.shiro.subject.Subject; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.web.bind.annotation.*; | 
				
			|||
import com.votesystem.ssl.result.Result; | 
				
			|||
import com.votesystem.ssl.result.ResultFactory; | 
				
			|||
import com.votesystem.ssl.service.IUserService; | 
				
			|||
 | 
				
			|||
import javax.servlet.http.HttpServletRequest; | 
				
			|||
import javax.servlet.http.HttpServletResponse; | 
				
			|||
 | 
				
			|||
@Slf4j | 
				
			|||
@RestController | 
				
			|||
@RequestMapping("/api") | 
				
			|||
public class UserApi { | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @Autowired | 
				
			|||
    IUserService userService; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @GetMapping("/admin/user/list") | 
				
			|||
    public Result listUsers( | 
				
			|||
            HttpServletRequest request, | 
				
			|||
            HttpServletResponse response, | 
				
			|||
            @RequestParam("page")int page, | 
				
			|||
            @RequestParam("size")int size){ | 
				
			|||
        return userService.listUsers(request,response,page,size); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @GetMapping("/user") | 
				
			|||
    public User getUserByName(@RequestParam("userName")String userName){ | 
				
			|||
        return userService.getByUserName(userName); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @PutMapping("/admin/user/state/{userId}") | 
				
			|||
    public Result changeUserState(@PathVariable("userId") int userId,@RequestParam("state") boolean state){ | 
				
			|||
        return userService.changeUserState(userId,state); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 注册 | 
				
			|||
     * @param user | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @PostMapping("/user/join_in") | 
				
			|||
    public Result register(@RequestBody User user, | 
				
			|||
                           @RequestParam("email_code")String emailCode, | 
				
			|||
                           @RequestParam("captcha_code")String captchaCode, | 
				
			|||
                           @RequestParam("captcha_key")String captchaKey, | 
				
			|||
                           HttpServletRequest request){ | 
				
			|||
 | 
				
			|||
//
 | 
				
			|||
//        auto res = userService.register(user,emailCode,captchaCode,captchaKey,request);
 | 
				
			|||
//        return res;
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
        return  userService.register(user,emailCode,captchaCode,captchaKey,request); | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
//    captchaKey = @RequestParam("captcha_key");
 | 
				
			|||
//    public Result register(User user,String emailCode, String captchaCode, String captchaKey, HttpServletRequest request){
 | 
				
			|||
//        captchaKey;
 | 
				
			|||
//    }
 | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 登录 sign-up | 
				
			|||
     * | 
				
			|||
     * 需要提交的数据 | 
				
			|||
     * 1、用户账号-昵称/邮箱, | 
				
			|||
     * 2、密码 | 
				
			|||
     * 3、图灵验证码 | 
				
			|||
     * 4、图灵验证码的key | 
				
			|||
     * @param captcha | 
				
			|||
     * @param captchaKey | 
				
			|||
     * @param user | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @PostMapping("/user/login/{captcha}/{captcha_key}") | 
				
			|||
    public Result login(@PathVariable("captcha") String captcha, | 
				
			|||
                        @PathVariable("captcha_key") String captchaKey, | 
				
			|||
                        @RequestBody User user, | 
				
			|||
                        HttpServletRequest request, | 
				
			|||
                        HttpServletResponse response){ | 
				
			|||
        log.info("login"); | 
				
			|||
        return userService.doLogin(captcha,captchaKey,user,request,response); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 退出登录 | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @GetMapping("/user/logout") | 
				
			|||
    public Result logout() { | 
				
			|||
        Subject subject = SecurityUtils.getSubject(); | 
				
			|||
        subject.logout(); | 
				
			|||
        return ResultFactory.buildSuccessResult("成功登出"); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 获取图灵验证码 | 
				
			|||
     * 有效时长10分钟 | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @GetMapping("/user/captcha") | 
				
			|||
    public void getCaptcha(HttpServletResponse response,@RequestParam("captcha_key")String captchaKey)  { | 
				
			|||
        try{ | 
				
			|||
            userService.createCaptcha(response,captchaKey); | 
				
			|||
        }catch (Exception e){ | 
				
			|||
            log.error(e.toString()); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 发送邮箱email | 
				
			|||
     * 使用场景: 注册、找回密码、修改邮箱(会输入新的邮箱) | 
				
			|||
     * 注册:已经注册过,提示已被注册 | 
				
			|||
     * 找回密码:如果没有注册过,提示没有注册 | 
				
			|||
     * 修改邮箱:新的邮箱地址--如果已经注册,提示被注册 | 
				
			|||
     * @param request | 
				
			|||
     * @param emailAddress | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
 | 
				
			|||
    @GetMapping("/user/verify_code") | 
				
			|||
    public Result sendVerifyCode(HttpServletRequest request, | 
				
			|||
                                 @RequestParam("type")String type, | 
				
			|||
                                 @RequestParam("email")String emailAddress){ | 
				
			|||
        log.info("email == > " + emailAddress); | 
				
			|||
        return userService.sendEmail(type,request,emailAddress); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 修改密码 | 
				
			|||
     * @param user | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @PutMapping("/user/password") | 
				
			|||
    public Result updatePassword( @RequestBody User user){ | 
				
			|||
        return userService.updatePassword(user); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 重置密码 | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @PutMapping("/admin/user/repassword/{userId}") | 
				
			|||
    public Result reSetPassword( @PathVariable("userId") int userId){ | 
				
			|||
        return userService.reSetPassword(userId); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 修改邮箱 | 
				
			|||
     * @param user | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @PutMapping("/user/email") | 
				
			|||
    public Result updateEmail(@RequestParam("email") String email, | 
				
			|||
                              @RequestParam("verify_code") String verifyCode, | 
				
			|||
                              @RequestBody User user){ | 
				
			|||
        return userService.updateEmail(email,verifyCode,user); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 修改用户信息 | 
				
			|||
     * <P> | 
				
			|||
     *     允许用户修改的内容 | 
				
			|||
     *     1. 头像 | 
				
			|||
     *     2. 用户名(唯一) | 
				
			|||
     *     2.5 签名 | 
				
			|||
     *     3. 密码(单独修改) | 
				
			|||
     *     4. Email(唯一,单独修改) | 
				
			|||
     * </P> | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @PutMapping("/admin/user/{userId}") | 
				
			|||
    public Result updateUserInfo(HttpServletRequest request, | 
				
			|||
                                 HttpServletResponse response, | 
				
			|||
                                 @PathVariable("userId")int userId, | 
				
			|||
                                 @RequestBody User user){ | 
				
			|||
 | 
				
			|||
        return userService.updateUserInfo(request, response, userId, user); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 需要管理员权限 | 
				
			|||
     * | 
				
			|||
     * @param userId | 
				
			|||
     * @return | 
				
			|||
     */ | 
				
			|||
    @DeleteMapping("/user/{userId}") | 
				
			|||
    public Result deleteUser(HttpServletResponse response, HttpServletRequest request, | 
				
			|||
                             @PathVariable("userId") int userId) { | 
				
			|||
        //判断当前操作的用户是谁
 | 
				
			|||
        //根据用户角色判断是否可以删除
 | 
				
			|||
        //TODO:通过注解的方式来控制权限
 | 
				
			|||
        return userService.deleteUserById(userId, request, response); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 检查邮箱是否已经被注册 | 
				
			|||
     * | 
				
			|||
     * @param email | 
				
			|||
     * @return SUCCESS == > 已经注册了 | 
				
			|||
     *         FAIL    == > 没有注册 | 
				
			|||
     */ | 
				
			|||
    @ApiResponses({ | 
				
			|||
            @ApiResponse(code = 200,message = "当前邮箱已经被注册了"), | 
				
			|||
            @ApiResponse(code = 400,message = "当前邮箱未被注册了") | 
				
			|||
    }) | 
				
			|||
 | 
				
			|||
    @GetMapping("/user/email") | 
				
			|||
    public Result checkEmail(@RequestParam("email")String email ){ | 
				
			|||
        return userService.checkEmail(email); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 检查用户名是否已经被注册 | 
				
			|||
     * | 
				
			|||
     * @param userName | 
				
			|||
     * @return SUCCESS == > 已经注册了 | 
				
			|||
     *         FAIL    == > 没有注册 | 
				
			|||
     */ | 
				
			|||
    @ApiResponses({ | 
				
			|||
            @ApiResponse(code = 200,message = "用户名已经被注册了"), | 
				
			|||
            @ApiResponse(code = 400,message = "用户名未被注册了") | 
				
			|||
    }) | 
				
			|||
 | 
				
			|||
    @GetMapping("/user/user_name") | 
				
			|||
    public Result checkUserName(@RequestParam("userName")String userName ){ | 
				
			|||
        return userService.checkUserName(userName); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @GetMapping("/user/check_email_code") | 
				
			|||
    public Result checkEmailCode(@RequestParam("email") String email, | 
				
			|||
                                 @RequestParam("emailCode") String emailCode){ | 
				
			|||
        return userService.checkEmailCode(email,emailCode); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,70 @@ | 
				
			|||
package com.votesystem.ssl.controller.user; | 
				
			|||
 | 
				
			|||
import com.alibaba.fastjson.JSONObject; | 
				
			|||
import com.votesystem.ssl.dao.CandidateDAO; | 
				
			|||
import com.votesystem.ssl.pojo.Candidate; | 
				
			|||
import com.votesystem.ssl.pojo.CandidateForResult; | 
				
			|||
import com.votesystem.ssl.pojo.VoteRecord; | 
				
			|||
import com.votesystem.ssl.utils.DownExcel; | 
				
			|||
import lombok.extern.slf4j.Slf4j; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.web.bind.annotation.*; | 
				
			|||
import com.votesystem.ssl.result.Result; | 
				
			|||
import com.votesystem.ssl.service.IVoteRecordService; | 
				
			|||
 | 
				
			|||
import javax.servlet.http.HttpServletResponse; | 
				
			|||
import java.io.IOException; | 
				
			|||
import java.util.ArrayList; | 
				
			|||
import java.util.List; | 
				
			|||
 | 
				
			|||
@Slf4j | 
				
			|||
@RestController | 
				
			|||
@RequestMapping("/api") | 
				
			|||
public class VoteRecordController { | 
				
			|||
 | 
				
			|||
    @Autowired | 
				
			|||
    CandidateDAO candidateDAO; | 
				
			|||
 | 
				
			|||
    @Autowired | 
				
			|||
    IVoteRecordService voteRecordService; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
    @PostMapping(value = {"/vote/single/{captcha}/{captcha_key}","/vote/single/{captcha_key}"}) | 
				
			|||
    public Result singleVote(@PathVariable(value = "captcha",required = false) String captcha, | 
				
			|||
                             @PathVariable(value = "captcha_key",required = false) String captchaKey, | 
				
			|||
                             @RequestBody VoteRecord voteRecord){ | 
				
			|||
        return voteRecordService.singleVote(captcha,captchaKey,voteRecord); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @PostMapping(value = {"/vote/multiple/{captcha}/{captcha_key}","/vote/multiple/{captcha_key}"}) | 
				
			|||
    public Result multipleVote(@PathVariable(value = "captcha",required = false) String captcha, | 
				
			|||
                               @PathVariable(value = "captcha_key",required = false) String captchaKey, | 
				
			|||
                               @RequestBody JSONObject voteData){ | 
				
			|||
        log.info("voteData === > ",voteData); | 
				
			|||
        return voteRecordService.multipleVote(captcha,captchaKey,voteData); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    //导出为Excel
 | 
				
			|||
    @RequestMapping("/download-result/{activityId}") | 
				
			|||
    public void getExcel(@PathVariable("activityId")String activityId, HttpServletResponse response) throws IllegalAccessException, IOException, | 
				
			|||
            InstantiationException { | 
				
			|||
        List<Candidate> candidates = candidateDAO.listRankCandidate(activityId); | 
				
			|||
        List<CandidateForResult> listResult = new ArrayList<>(); | 
				
			|||
        int rank = 1; | 
				
			|||
        for(Candidate c : candidates){ | 
				
			|||
            CandidateForResult candidateForResult = new CandidateForResult(); | 
				
			|||
            candidateForResult.setRank(rank++); | 
				
			|||
            candidateForResult.setId(c.getId()); | 
				
			|||
            candidateForResult.setNum(c.getNum()); | 
				
			|||
            candidateForResult.setTitle(c.getTitle()); | 
				
			|||
            candidateForResult.setVoteCount(c.getVoteCount()); | 
				
			|||
            candidateForResult.setAid(c.getAid()); | 
				
			|||
            candidateForResult.setCoverUrl(c.getCoverUrl()); | 
				
			|||
            candidateForResult.setItemDesc(c.getItemDesc()); | 
				
			|||
            candidateForResult.setCreateTime(c.getCreateTime()); | 
				
			|||
            candidateForResult.setUpdateTime(c.getUpdateTime()); | 
				
			|||
            listResult.add(candidateForResult); | 
				
			|||
        } | 
				
			|||
        DownExcel.download(response, CandidateForResult.class,listResult); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,156 @@ | 
				
			|||
package com.votesystem.ssl.dao; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
import com.votesystem.ssl.pojo.Activity; | 
				
			|||
import org.apache.ibatis.annotations.Insert; | 
				
			|||
import org.apache.ibatis.annotations.Mapper; | 
				
			|||
import org.apache.ibatis.annotations.Select; | 
				
			|||
import org.apache.ibatis.annotations.Update; | 
				
			|||
import org.springframework.data.domain.Page; | 
				
			|||
import org.springframework.data.domain.Pageable; | 
				
			|||
import org.springframework.data.jpa.repository.JpaRepository; | 
				
			|||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; | 
				
			|||
import org.springframework.data.jpa.repository.Modifying; | 
				
			|||
import org.springframework.data.jpa.repository.Query; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
import java.util.List; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
import org.apache.ibatis.annotations.Insert; | 
				
			|||
import org.apache.ibatis.annotations.Mapper; | 
				
			|||
import org.apache.ibatis.annotations.Select; | 
				
			|||
import org.apache.ibatis.annotations.Update; | 
				
			|||
import org.springframework.data.domain.Page; | 
				
			|||
import org.springframework.data.domain.Pageable; | 
				
			|||
 | 
				
			|||
import java.util.List; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
import org.springframework.data.domain.Page; | 
				
			|||
import org.springframework.data.domain.Pageable; | 
				
			|||
import org.springframework.data.jpa.repository.JpaRepository; | 
				
			|||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; | 
				
			|||
import org.springframework.data.jpa.repository.Modifying; | 
				
			|||
import org.springframework.data.jpa.repository.Query; | 
				
			|||
 | 
				
			|||
import java.util.List; | 
				
			|||
 | 
				
			|||
public interface ActivityDAO extends JpaRepository<Activity,String>, JpaSpecificationExecutor<Activity> { | 
				
			|||
 | 
				
			|||
    @Modifying | 
				
			|||
    @Query(nativeQuery = true, value = "UPDATE `tb_acticity` SET `state` = '0' WHERE `id` = ?") | 
				
			|||
    int deleteActivityByState(String activityId); | 
				
			|||
 | 
				
			|||
    Activity findOneById(String activityId); | 
				
			|||
 | 
				
			|||
//    Page<Activity> findAll(Pageable pageable);
 | 
				
			|||
 | 
				
			|||
    @Query(value = "SELECT * FROM tb_activity a WHERE a.state != '-1'",nativeQuery = true) | 
				
			|||
    Page<Activity> findAllValidActivity(Pageable pageable); | 
				
			|||
//@Query(value = "SELECT * FROM tb_activity a WHERE a.state != '-2'",nativeQuery = true)
 | 
				
			|||
 | 
				
			|||
    @Modifying | 
				
			|||
    @Query(nativeQuery = true, value = "UPDATE `tb_activity` SET `state` = '-1' WHERE `id` = ?") | 
				
			|||
    int validActivityById(String activityId); | 
				
			|||
    //由boolen改成了int
 | 
				
			|||
    //分页列出案例
 | 
				
			|||
    @Query(value = " select * from tb_activity a where  a.state = '2'",nativeQuery = true) | 
				
			|||
    List<Activity> findByState(Pageable pageable); | 
				
			|||
    //这个不对
 | 
				
			|||
//    @Query(value = "SELECT * FROM tb_activity WHERE state = 1 ",nativeQuery = true)
 | 
				
			|||
    Page<Activity> findAllByAuthor(String author ,Pageable pageable); | 
				
			|||
 | 
				
			|||
 | 
				
			|||
} | 
				
			|||
 | 
				
			|||
//@Mapper
 | 
				
			|||
//public interface ActivityDAO {
 | 
				
			|||
//
 | 
				
			|||
//    @Update("UPDATE `tb_acticity` SET `state` = '0' WHERE `id` = #{activityId,jdbcType=VARCHAR}")
 | 
				
			|||
//    int deleteActivityByState(String activityId);
 | 
				
			|||
//    @Select("SELECT * FROM tb_activity WHERE id = #{activityId}")
 | 
				
			|||
//    Activity findOneById(String activityId);
 | 
				
			|||
//    // 你这几句都没写对应的SQL语句。
 | 
				
			|||
//    @Select("SELECT * FROM tb_activity")
 | 
				
			|||
//    Page<Activity> findAll(Pageable pageable);
 | 
				
			|||
//    @Select( "select * from tb_activity a where  a.state = '2'")
 | 
				
			|||
//    List<Activity> findByState(Pageable pageable);
 | 
				
			|||
//    @Select("SELECT * FROM tb_activity WHERE author = #{author}")
 | 
				
			|||
//    Page<Activity> findAllByAuthor(String author ,Pageable pageable);
 | 
				
			|||
//    @Insert("Insert into tb_activity (id,author,title,content,state,type,sign_in,verify_code,start_time,end_time,create_time,update_time)"
 | 
				
			|||
//            + "values (#{id,jdbcType=VARCHAR},#{author,jdbcType=VARCHAR},"
 | 
				
			|||
//            + "#{title,jdbcType=VARCHAR},#{content,jdbcType=VARCHAR},"
 | 
				
			|||
//            + "#{state,jdbcType=VARCHAR},#{type,jdbcType=VARCHAR},#{sign_in,jdbcType=VARCHAR},"
 | 
				
			|||
//            + "#{verify_code,jdbcType=BOOLEAN},#{start_time,jdbcType=VARCHAR},"
 | 
				
			|||
//            + "#{end_time,jdbcType=VARCHAR},#{create_time,jdbcType=VARCHAR},#{update_time,jdbcType=VARCHAR});")
 | 
				
			|||
//    boolean save(Activity activity);
 | 
				
			|||
//}
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
//import com.votesystem.ssl.pojo.Activity;
 | 
				
			|||
//import org.apache.ibatis.annotations.Insert;
 | 
				
			|||
//import org.apache.ibatis.annotations.Mapper;
 | 
				
			|||
//import org.apache.ibatis.annotations.Select;
 | 
				
			|||
//import org.apache.ibatis.annotations.Update;
 | 
				
			|||
//import org.springframework.data.domain.Page;
 | 
				
			|||
//import org.springframework.data.domain.Pageable;
 | 
				
			|||
//import org.springframework.data.jpa.repository.JpaRepository;
 | 
				
			|||
//import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 | 
				
			|||
//import org.springframework.data.jpa.repository.Modifying;
 | 
				
			|||
//import org.springframework.data.jpa.repository.Query;
 | 
				
			|||
//
 | 
				
			|||
//import java.util.List;
 | 
				
			|||
////
 | 
				
			|||
////public interface ActivityDAO extends JpaRepository<Activity,String>, JpaSpecificationExecutor<Activity> {
 | 
				
			|||
////
 | 
				
			|||
////    @Modifying
 | 
				
			|||
////    @Query(nativeQuery = true, value = "UPDATE `tb_acticity` SET `state` = '0' WHERE `id` = ?")
 | 
				
			|||
////    int deleteActivityByState(String activityId);
 | 
				
			|||
////
 | 
				
			|||
////    Activity findOneById(String activityId);
 | 
				
			|||
////
 | 
				
			|||
////    Page<Activity> findAll(Pageable pageable);
 | 
				
			|||
////
 | 
				
			|||
////    //分页列出案例
 | 
				
			|||
////    @Query(value = " select * from tb_activity a where  a.state = '2'",nativeQuery = true)
 | 
				
			|||
////    List<Activity> findByState(Pageable pageable);
 | 
				
			|||
////
 | 
				
			|||
////    Page<Activity> findAllByAuthor(String author ,Pageable pageable);
 | 
				
			|||
////
 | 
				
			|||
////
 | 
				
			|||
////
 | 
				
			|||
////}
 | 
				
			|||
//@Mapper
 | 
				
			|||
//public interface ActivityDAO {
 | 
				
			|||
//
 | 
				
			|||
//    @Update("UPDATE `tb_acticity` SET `state` = '0' WHERE `id` = #{activityId,jdbcType=VARCHAR}")
 | 
				
			|||
//    int deleteActivityByState(String activityId);
 | 
				
			|||
//
 | 
				
			|||
//    @Select("SELECT * FROM tb_activity WHERE id = #{activityId}")
 | 
				
			|||
//    Activity findOneById(String activityId);
 | 
				
			|||
//
 | 
				
			|||
////    @Select("SELECT * FROM tb_activity LIMIT #{pageable.pageNumber}, #{pageable.pageSize}")  //这样?你问我?  应该是这样吧
 | 
				
			|||
////    Page<Activity> findAll(Pageable pageable);
 | 
				
			|||
//
 | 
				
			|||
//    //    @Select("SELECT * FROM tb_activity")  //这样? 先这样 不行再那样
 | 
				
			|||
////    List<Activity> findAll();
 | 
				
			|||
////    List<Activity> findAll(Pageable pageable);
 | 
				
			|||
//    @Select("SELECT * FROM tb_activity")
 | 
				
			|||
//    List<Activity> findAll();
 | 
				
			|||
//
 | 
				
			|||
//
 | 
				
			|||
//    @Select("SELECT * FROM tb_activity WHERE state = '2'")
 | 
				
			|||
//    List<Activity> findByState();
 | 
				
			|||
////    List<Activity> findByState(Pageable pageable);
 | 
				
			|||
//
 | 
				
			|||
//    @Select("SELECT * FROM tb_activity WHERE author = #{author}")
 | 
				
			|||
//    List<Activity> findAllByAuthor(String author);
 | 
				
			|||
////    List<Activity> findAllByAuthor(String author, Pageable pageable);
 | 
				
			|||
//
 | 
				
			|||
//    @Insert("INSERT INTO tb_activity(id, author, title, content, state, type, sign_in, verify_code, start_time, end_time, create_time, update_time) VALUES (#{id}, #{author}, #{title}, #{content}, #{state}, #{type}, #{signIn}, #{verifyCode}, #{startTime}, #{endTime}, #{createTime}, #{updateTime})")
 | 
				
			|||
//    boolean save(Activity activity);
 | 
				
			|||
//
 | 
				
			|||
//    @Update("UPDATE tb_activity SET author = #{author}, title = #{title}, content = #{content}, state = #{state}, type = #{type}, signIn = #{sign_in}, verifyCode = #{verify_code}, startTime = #{start_time}, endTime = #{end_time}, createTime = #{create_time}, updateTime = #{update_time} WHERE id = #{id}")
 | 
				
			|||
//    boolean updat(Activity activityFromDb);
 | 
				
			|||
//}
 | 
				
			|||