luke преди 6 години
родител
ревизия
48e0842188
променени са 100 файла, в които са добавени 1545 реда и са изтрити 0 реда
  1. 30 0
      service_exe/.babelrc
  2. 132 0
      service_exe/.electron-vue/build.js
  3. 40 0
      service_exe/.electron-vue/dev-client.js
  4. 190 0
      service_exe/.electron-vue/dev-runner.js
  5. 72 0
      service_exe/.electron-vue/webpack.main.config.js
  6. 171 0
      service_exe/.electron-vue/webpack.renderer.config.js
  7. 132 0
      service_exe/.electron-vue/webpack.web.config.js
  8. 10 0
      service_exe/.gitignore
  9. 36 0
      service_exe/.travis.yml
  10. 22 0
      service_exe/README.md
  11. 29 0
      service_exe/appveyor.yml
  12. BIN
      service_exe/build/icons/256x256.png
  13. BIN
      service_exe/build/icons/IMG_03.ico
  14. BIN
      service_exe/build/icons/icon.ico
  15. BIN
      service_exe/build/icons/icon.png
  16. 0 0
      service_exe/dist/electron/.gitkeep
  17. 0 0
      service_exe/dist/web/.gitkeep
  18. 104 0
      service_exe/package.json
  19. 24 0
      service_exe/src/index.ejs
  20. 24 0
      service_exe/src/main/index.dev.js
  21. 65 0
      service_exe/src/main/index.js
  22. 338 0
      service_exe/src/renderer/App.vue
  23. 62 0
      service_exe/src/renderer/api/http.js
  24. 60 0
      service_exe/src/renderer/api/ports.js
  25. 0 0
      service_exe/src/renderer/assets/.gitkeep
  26. 4 0
      service_exe/src/renderer/assets/frce.js
  27. BIN
      service_exe/src/renderer/assets/img/0.gif
  28. BIN
      service_exe/src/renderer/assets/img/1.gif
  29. BIN
      service_exe/src/renderer/assets/img/10.gif
  30. BIN
      service_exe/src/renderer/assets/img/11.gif
  31. BIN
      service_exe/src/renderer/assets/img/12.gif
  32. BIN
      service_exe/src/renderer/assets/img/13.gif
  33. BIN
      service_exe/src/renderer/assets/img/14.gif
  34. BIN
      service_exe/src/renderer/assets/img/15.gif
  35. BIN
      service_exe/src/renderer/assets/img/16.gif
  36. BIN
      service_exe/src/renderer/assets/img/17.gif
  37. BIN
      service_exe/src/renderer/assets/img/18.gif
  38. BIN
      service_exe/src/renderer/assets/img/19.gif
  39. BIN
      service_exe/src/renderer/assets/img/2.gif
  40. BIN
      service_exe/src/renderer/assets/img/20.gif
  41. BIN
      service_exe/src/renderer/assets/img/21.gif
  42. BIN
      service_exe/src/renderer/assets/img/22.gif
  43. BIN
      service_exe/src/renderer/assets/img/23.gif
  44. BIN
      service_exe/src/renderer/assets/img/24.gif
  45. BIN
      service_exe/src/renderer/assets/img/25.gif
  46. BIN
      service_exe/src/renderer/assets/img/26.gif
  47. BIN
      service_exe/src/renderer/assets/img/27.gif
  48. BIN
      service_exe/src/renderer/assets/img/28.gif
  49. BIN
      service_exe/src/renderer/assets/img/29.gif
  50. BIN
      service_exe/src/renderer/assets/img/3.gif
  51. BIN
      service_exe/src/renderer/assets/img/30.gif
  52. BIN
      service_exe/src/renderer/assets/img/31.gif
  53. BIN
      service_exe/src/renderer/assets/img/32.gif
  54. BIN
      service_exe/src/renderer/assets/img/33.gif
  55. BIN
      service_exe/src/renderer/assets/img/34.gif
  56. BIN
      service_exe/src/renderer/assets/img/35.gif
  57. BIN
      service_exe/src/renderer/assets/img/36.gif
  58. BIN
      service_exe/src/renderer/assets/img/37.gif
  59. BIN
      service_exe/src/renderer/assets/img/38.gif
  60. BIN
      service_exe/src/renderer/assets/img/39.gif
  61. BIN
      service_exe/src/renderer/assets/img/4.gif
  62. BIN
      service_exe/src/renderer/assets/img/40.gif
  63. BIN
      service_exe/src/renderer/assets/img/41.gif
  64. BIN
      service_exe/src/renderer/assets/img/42.gif
  65. BIN
      service_exe/src/renderer/assets/img/43.gif
  66. BIN
      service_exe/src/renderer/assets/img/44.gif
  67. BIN
      service_exe/src/renderer/assets/img/45.gif
  68. BIN
      service_exe/src/renderer/assets/img/46.gif
  69. BIN
      service_exe/src/renderer/assets/img/47.gif
  70. BIN
      service_exe/src/renderer/assets/img/48.gif
  71. BIN
      service_exe/src/renderer/assets/img/49.gif
  72. BIN
      service_exe/src/renderer/assets/img/5.gif
  73. BIN
      service_exe/src/renderer/assets/img/50.gif
  74. BIN
      service_exe/src/renderer/assets/img/51.gif
  75. BIN
      service_exe/src/renderer/assets/img/52.gif
  76. BIN
      service_exe/src/renderer/assets/img/53.gif
  77. BIN
      service_exe/src/renderer/assets/img/54.gif
  78. BIN
      service_exe/src/renderer/assets/img/55.gif
  79. BIN
      service_exe/src/renderer/assets/img/56.gif
  80. BIN
      service_exe/src/renderer/assets/img/57.gif
  81. BIN
      service_exe/src/renderer/assets/img/58.gif
  82. BIN
      service_exe/src/renderer/assets/img/59.gif
  83. BIN
      service_exe/src/renderer/assets/img/6.gif
  84. BIN
      service_exe/src/renderer/assets/img/60.gif
  85. BIN
      service_exe/src/renderer/assets/img/61.gif
  86. BIN
      service_exe/src/renderer/assets/img/62.gif
  87. BIN
      service_exe/src/renderer/assets/img/63.gif
  88. BIN
      service_exe/src/renderer/assets/img/64.gif
  89. BIN
      service_exe/src/renderer/assets/img/65.gif
  90. BIN
      service_exe/src/renderer/assets/img/66.gif
  91. BIN
      service_exe/src/renderer/assets/img/67.gif
  92. BIN
      service_exe/src/renderer/assets/img/68.gif
  93. BIN
      service_exe/src/renderer/assets/img/69.gif
  94. BIN
      service_exe/src/renderer/assets/img/7.gif
  95. BIN
      service_exe/src/renderer/assets/img/70.gif
  96. BIN
      service_exe/src/renderer/assets/img/71.gif
  97. BIN
      service_exe/src/renderer/assets/img/8.gif
  98. BIN
      service_exe/src/renderer/assets/img/9.gif
  99. BIN
      service_exe/src/renderer/assets/img/Multitap.png
  100. BIN
      service_exe/src/renderer/assets/img/account.png

+ 30 - 0
service_exe/.babelrc

@@ -0,0 +1,30 @@
+{
+  "comments": false,
+  "env": {
+    "main": {
+      "presets": [
+        ["env", {
+          "targets": { "node": 7 }
+        }],
+        "stage-0"
+      ]
+    },
+    "renderer": {
+      "presets": [
+        ["env", {
+          "modules": false
+        }],
+        "stage-0"
+      ]
+    },
+    "web": {
+      "presets": [
+        ["env", {
+          "modules": false
+        }],
+        "stage-0"
+      ]
+    }
+  },
+  "plugins": ["transform-runtime"]
+}

+ 132 - 0
service_exe/.electron-vue/build.js

@@ -0,0 +1,132 @@
+'use strict'
+
+process.env.NODE_ENV = 'production'
+
+const { say } = require('cfonts')
+const chalk = require('chalk')
+const del = require('del')
+const { spawn } = require('child_process')
+const webpack = require('webpack')
+const Multispinner = require('multispinner')
+
+
+const mainConfig = require('./webpack.main.config')
+const rendererConfig = require('./webpack.renderer.config')
+const webConfig = require('./webpack.web.config')
+
+const doneLog = chalk.bgGreen.white(' DONE ') + ' '
+const errorLog = chalk.bgRed.white(' ERROR ') + ' '
+const okayLog = chalk.bgBlue.white(' OKAY ') + ' '
+const isCI = process.env.CI || false
+
+if (process.env.BUILD_TARGET === 'clean') clean()
+else if (process.env.BUILD_TARGET === 'web') web()
+else build()
+
+function clean () {
+  del.sync(['build/*', '!build/icons', '!build/icons/icon.*'])
+  console.log(`\n${doneLog}\n`)
+  process.exit()
+}
+
+function build () {
+  greeting()
+
+  del.sync(['dist/electron/*', '!.gitkeep'])
+
+  const tasks = ['main', 'renderer']
+  const m = new Multispinner(tasks, {
+    preText: 'building',
+    postText: 'process'
+  })
+
+  let results = ''
+
+  m.on('success', () => {
+    process.stdout.write('\x1B[2J\x1B[0f')
+    console.log(`\n\n${results}`)
+    console.log(`${okayLog}take it away ${chalk.yellow('`electron-builder`')}\n`)
+    process.exit()
+  })
+
+  pack(mainConfig).then(result => {
+    results += result + '\n\n'
+    m.success('main')
+  }).catch(err => {
+    m.error('main')
+    console.log(`\n  ${errorLog}failed to build main process`)
+    console.error(`\n${err}\n`)
+    process.exit(1)
+  })
+
+  pack(rendererConfig).then(result => {
+    results += result + '\n\n'
+    m.success('renderer')
+  }).catch(err => {
+    m.error('renderer')
+    console.log(`\n  ${errorLog}failed to build renderer process`)
+    console.error(`\n${err}\n`)
+    process.exit(1)
+  })
+}
+
+function pack (config) {
+  return new Promise((resolve, reject) => {
+    config.mode = 'production'
+    webpack(config, (err, stats) => {
+      if (err) reject(err.stack || err)
+      else if (stats.hasErrors()) {
+        let err = ''
+
+        stats.toString({
+          chunks: false,
+          colors: true
+        })
+        .split(/\r?\n/)
+        .forEach(line => {
+          err += `    ${line}\n`
+        })
+
+        reject(err)
+      } else {
+        resolve(stats.toString({
+          chunks: false,
+          colors: true
+        }))
+      }
+    })
+  })
+}
+
+function web () {
+  del.sync(['dist/web/*', '!.gitkeep'])
+  webConfig.mode = 'production'
+  webpack(webConfig, (err, stats) => {
+    if (err || stats.hasErrors()) console.log(err)
+
+    console.log(stats.toString({
+      chunks: false,
+      colors: true
+    }))
+
+    process.exit()
+  })
+}
+
+function greeting () {
+  const cols = process.stdout.columns
+  let text = ''
+
+  if (cols > 85) text = 'lets-build'
+  else if (cols > 60) text = 'lets-|build'
+  else text = false
+
+  if (text && !isCI) {
+    say(text, {
+      colors: ['yellow'],
+      font: 'simple3d',
+      space: false
+    })
+  } else console.log(chalk.yellow.bold('\n  lets-build'))
+  console.log()
+}

+ 40 - 0
service_exe/.electron-vue/dev-client.js

@@ -0,0 +1,40 @@
+const hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
+
+hotClient.subscribe(event => {
+  /**
+   * Reload browser when HTMLWebpackPlugin emits a new index.html
+   *
+   * Currently disabled until jantimon/html-webpack-plugin#680 is resolved.
+   * https://github.com/SimulatedGREG/electron-vue/issues/437
+   * https://github.com/jantimon/html-webpack-plugin/issues/680
+   */
+  // if (event.action === 'reload') {
+  //   window.location.reload()
+  // }
+
+  /**
+   * Notify `mainWindow` when `main` process is compiling,
+   * giving notice for an expected reload of the `electron` process
+   */
+  if (event.action === 'compiling') {
+    document.body.innerHTML += `
+      <style>
+        #dev-client {
+          background: #4fc08d;
+          border-radius: 4px;
+          bottom: 20px;
+          box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.3);
+          color: #fff;
+          font-family: 'Source Sans Pro', sans-serif;
+          left: 20px;
+          padding: 8px 12px;
+          position: absolute;
+        }
+      </style>
+
+      <div id="dev-client">
+        Compiling Main Process...
+      </div>
+    `
+  }
+})

+ 190 - 0
service_exe/.electron-vue/dev-runner.js

@@ -0,0 +1,190 @@
+'use strict'
+
+const chalk = require('chalk')
+const electron = require('electron')
+const path = require('path')
+const { say } = require('cfonts')
+const { spawn } = require('child_process')
+const webpack = require('webpack')
+const WebpackDevServer = require('webpack-dev-server')
+const webpackHotMiddleware = require('webpack-hot-middleware')
+
+const mainConfig = require('./webpack.main.config')
+const rendererConfig = require('./webpack.renderer.config')
+
+let electronProcess = null
+let manualRestart = false
+let hotMiddleware
+
+function logStats (proc, data) {
+  let log = ''
+
+  log += chalk.yellow.bold(`┏ ${proc} Process ${new Array((19 - proc.length) + 1).join('-')}`)
+  log += '\n\n'
+
+  if (typeof data === 'object') {
+    data.toString({
+      colors: true,
+      chunks: false
+    }).split(/\r?\n/).forEach(line => {
+      log += '  ' + line + '\n'
+    })
+  } else {
+    log += `  ${data}\n`
+  }
+
+  log += '\n' + chalk.yellow.bold(`┗ ${new Array(28 + 1).join('-')}`) + '\n'
+
+  console.log(log)
+}
+
+function startRenderer () {
+  return new Promise((resolve, reject) => {
+    rendererConfig.entry.renderer = [path.join(__dirname, 'dev-client')].concat(rendererConfig.entry.renderer)
+    rendererConfig.mode = 'development'
+    const compiler = webpack(rendererConfig)
+    hotMiddleware = webpackHotMiddleware(compiler, {
+      log: false,
+      heartbeat: 2500
+    })
+
+    compiler.hooks.compilation.tap('compilation', compilation => {
+      compilation.hooks.htmlWebpackPluginAfterEmit.tapAsync('html-webpack-plugin-after-emit', (data, cb) => {
+        hotMiddleware.publish({ action: 'reload' })
+        cb()
+      })
+    })
+
+    compiler.hooks.done.tap('done', stats => {
+      logStats('Renderer', stats)
+    })
+
+    const server = new WebpackDevServer(
+      compiler,
+      {
+        contentBase: path.join(__dirname, '../'),
+        quiet: true,
+        before (app, ctx) {
+          app.use(hotMiddleware)
+          ctx.middleware.waitUntilValid(() => {
+            resolve()
+          })
+        }
+      }
+    )
+
+    server.listen(9080)
+  })
+}
+
+function startMain () {
+  return new Promise((resolve, reject) => {
+    mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main)
+    mainConfig.mode = 'development'
+    const compiler = webpack(mainConfig)
+
+    compiler.hooks.watchRun.tapAsync('watch-run', (compilation, done) => {
+      logStats('Main', chalk.white.bold('compiling...'))
+      hotMiddleware.publish({ action: 'compiling' })
+      done()
+    })
+
+    compiler.watch({}, (err, stats) => {
+      if (err) {
+        console.log(err)
+        return
+      }
+
+      logStats('Main', stats)
+
+      if (electronProcess && electronProcess.kill) {
+        manualRestart = true
+        process.kill(electronProcess.pid)
+        electronProcess = null
+        startElectron()
+
+        setTimeout(() => {
+          manualRestart = false
+        }, 5000)
+      }
+
+      resolve()
+    })
+  })
+}
+
+function startElectron () {
+  var args = [
+    '--inspect=5858',
+    path.join(__dirname, '../dist/electron/main.js')
+  ]
+
+  // detect yarn or npm and process commandline args accordingly
+  if (process.env.npm_execpath.endsWith('yarn.js')) {
+    args = args.concat(process.argv.slice(3))
+  } else if (process.env.npm_execpath.endsWith('npm-cli.js')) {
+    args = args.concat(process.argv.slice(2))
+  }
+
+  electronProcess = spawn(electron, args)
+  
+  electronProcess.stdout.on('data', data => {
+    electronLog(data, 'blue')
+  })
+  electronProcess.stderr.on('data', data => {
+    electronLog(data, 'red')
+  })
+
+  electronProcess.on('close', () => {
+    if (!manualRestart) process.exit()
+  })
+}
+
+function electronLog (data, color) {
+  let log = ''
+  data = data.toString().split(/\r?\n/)
+  data.forEach(line => {
+    log += `  ${line}\n`
+  })
+  if (/[0-9A-z]+/.test(log)) {
+    console.log(
+      chalk[color].bold('┏ Electron -------------------') +
+      '\n\n' +
+      log +
+      chalk[color].bold('┗ ----------------------------') +
+      '\n'
+    )
+  }
+}
+
+function greeting () {
+  const cols = process.stdout.columns
+  let text = ''
+
+  if (cols > 104) text = 'electron-vue'
+  else if (cols > 76) text = 'electron-|vue'
+  else text = false
+
+  if (text) {
+    say(text, {
+      colors: ['yellow'],
+      font: 'simple3d',
+      space: false
+    })
+  } else console.log(chalk.yellow.bold('\n  electron-vue'))
+  console.log(chalk.blue('  getting ready...') + '\n')
+}
+
+function init () {
+  greeting()
+
+  Promise.all([startRenderer(), startMain()])
+    .then(() => {
+      startElectron()
+    })
+    .catch(err => {
+      console.error(err)
+    })
+}
+
+init()

+ 72 - 0
service_exe/.electron-vue/webpack.main.config.js

@@ -0,0 +1,72 @@
+'use strict'
+
+process.env.BABEL_ENV = 'main'
+
+const path = require('path')
+const { dependencies } = require('../package.json')
+const webpack = require('webpack')
+
+const BabiliWebpackPlugin = require('babili-webpack-plugin')
+
+let mainConfig = {
+  entry: {
+    main: path.join(__dirname, '../src/main/index.js')
+  },
+  externals: [
+    ...Object.keys(dependencies || {})
+  ],
+  module: {
+    rules: [
+      {
+        test: /\.js$/,
+        use: 'babel-loader',
+        exclude: /node_modules/
+      },
+      {
+        test: /\.node$/,
+        use: 'node-loader'
+      }
+    ]
+  },
+  node: {
+    __dirname: process.env.NODE_ENV !== 'production',
+    __filename: process.env.NODE_ENV !== 'production'
+  },
+  output: {
+    filename: '[name].js',
+    libraryTarget: 'commonjs2',
+    path: path.join(__dirname, '../dist/electron')
+  },
+  plugins: [
+    new webpack.NoEmitOnErrorsPlugin()
+  ],
+  resolve: {
+    extensions: ['.js', '.json', '.node']
+  },
+  target: 'electron-main'
+}
+
+/**
+ * Adjust mainConfig for development settings
+ */
+if (process.env.NODE_ENV !== 'production') {
+  mainConfig.plugins.push(
+    new webpack.DefinePlugin({
+      '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
+    })
+  )
+}
+
+/**
+ * Adjust mainConfig for production settings
+ */
+if (process.env.NODE_ENV === 'production') {
+  mainConfig.plugins.push(
+    new BabiliWebpackPlugin(),
+    new webpack.DefinePlugin({
+      'process.env.NODE_ENV': '"production"'
+    })
+  )
+}
+
+module.exports = mainConfig

+ 171 - 0
service_exe/.electron-vue/webpack.renderer.config.js

@@ -0,0 +1,171 @@
+'use strict'
+
+process.env.BABEL_ENV = 'renderer'
+
+const path = require('path')
+const { dependencies } = require('../package.json')
+const webpack = require('webpack')
+
+const BabiliWebpackPlugin = require('babili-webpack-plugin')
+const CopyWebpackPlugin = require('copy-webpack-plugin')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const { VueLoaderPlugin } = require('vue-loader')
+
+/**
+ * List of node_modules to include in webpack bundle
+ *
+ * Required for specific packages like Vue UI libraries
+ * that provide pure *.vue files that need compiling
+ * https://simulatedgreg.gitbooks.io/electron-vue/content/en/webpack-configurations.html#white-listing-externals
+ */
+let whiteListedModules = ['vue', 'element-ui']
+
+let rendererConfig = {
+  devtool: '#cheap-module-eval-source-map',
+  entry: {
+    renderer: path.join(__dirname, '../src/renderer/main.js')
+  },
+  externals: [
+    ...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d))
+  ],
+  module: {
+    rules: [
+      {
+        test: /\.less$/,
+        use: ['vue-style-loader', 'css-loader', 'less-loader']
+      },
+      {
+        test: /\.css$/,
+        use: ['vue-style-loader', 'css-loader']
+      },
+      {
+        test: /\.html$/,
+        use: 'vue-html-loader'
+      },
+      {
+        test: /\.js$/,
+        use: 'babel-loader',
+        exclude: /node_modules/
+      },
+      {
+        test: /\.node$/,
+        use: 'node-loader'
+      },
+      {
+        test: /\.vue$/,
+        use: {
+          loader: 'vue-loader',
+          options: {
+            extractCSS: process.env.NODE_ENV === 'production',
+            loaders: {
+              sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
+              scss: 'vue-style-loader!css-loader!sass-loader',
+              less: 'vue-style-loader!css-loader!less-loader'
+            }
+          }
+        }
+      },
+      {
+        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
+        use: {
+          loader: 'url-loader',
+          query: {
+            limit: 10000,
+            name: 'imgs/[name]--[folder].[ext]'
+          }
+        }
+      },
+      {
+        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: 'media/[name]--[folder].[ext]'
+        }
+      },
+      {
+        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
+        use: {
+          loader: 'url-loader',
+          query: {
+            limit: 10000,
+            name: 'fonts/[name]--[folder].[ext]'
+          }
+        }
+      }
+    ]
+  },
+  node: {
+    __dirname: process.env.NODE_ENV !== 'production',
+    __filename: process.env.NODE_ENV !== 'production'
+  },
+  plugins: [
+    new VueLoaderPlugin(),
+    new MiniCssExtractPlugin({filename: 'styles.css'}),
+    new HtmlWebpackPlugin({
+      filename: 'index.html',
+      template: path.resolve(__dirname, '../src/index.ejs'),
+      minify: {
+        collapseWhitespace: true,
+        removeAttributeQuotes: true,
+        removeComments: true
+      },
+      nodeModules: process.env.NODE_ENV !== 'production'
+        ? path.resolve(__dirname, '../node_modules')
+        : false
+    }),
+    new webpack.HotModuleReplacementPlugin(),
+    new webpack.NoEmitOnErrorsPlugin()
+  ],
+  output: {
+    filename: '[name].js',
+    libraryTarget: 'commonjs2',
+    path: path.join(__dirname, '../dist/electron')
+  },
+  resolve: {
+    alias: {
+      '@': path.join(__dirname, '../src/renderer'),
+      'vue$': 'vue/dist/vue.esm.js'
+    },
+    extensions: ['.js', '.vue', '.json', '.css', '.node']
+  },
+  target: 'electron-renderer'
+}
+
+/**
+ * Adjust rendererConfig for development settings
+ */
+if (process.env.NODE_ENV !== 'production') {
+  rendererConfig.plugins.push(
+    new webpack.DefinePlugin({
+      '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
+    })
+  )
+}
+
+/**
+ * Adjust rendererConfig for production settings
+ */
+if (process.env.NODE_ENV === 'production') {
+  rendererConfig.devtool = ''
+
+  rendererConfig.plugins.push(
+    new BabiliWebpackPlugin(),
+    new CopyWebpackPlugin([
+      {
+        from: path.join(__dirname, '../static'),
+        to: path.join(__dirname, '../dist/electron/static'),
+        ignore: ['.*']
+      }
+    ]),
+    new webpack.DefinePlugin({
+      'process.env.NODE_ENV': '"production"'
+    }),
+    new webpack.LoaderOptionsPlugin({
+      minimize: true
+    })
+  )
+}
+
+module.exports = rendererConfig

+ 132 - 0
service_exe/.electron-vue/webpack.web.config.js

@@ -0,0 +1,132 @@
+'use strict'
+
+process.env.BABEL_ENV = 'web'
+
+const path = require('path')
+const webpack = require('webpack')
+
+const BabiliWebpackPlugin = require('babili-webpack-plugin')
+const CopyWebpackPlugin = require('copy-webpack-plugin')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const { VueLoaderPlugin } = require('vue-loader')
+
+let webConfig = {
+  devtool: '#cheap-module-eval-source-map',
+  entry: {
+    web: path.join(__dirname, '../src/renderer/main.js')
+  },
+  module: {
+    rules: [
+      {
+        test: /\.less$/,
+        use: ['vue-style-loader', 'css-loader', 'less-loader']
+      },
+      {
+        test: /\.css$/,
+        use: ['vue-style-loader', 'css-loader']
+      },
+      {
+        test: /\.html$/,
+        use: 'vue-html-loader'
+      },
+      {
+        test: /\.js$/,
+        use: 'babel-loader',
+        include: [ path.resolve(__dirname, '../src/renderer') ],
+        exclude: /node_modules/
+      },
+      {
+        test: /\.vue$/,
+        use: {
+          loader: 'vue-loader',
+          options: {
+            extractCSS: true,
+            loaders: {
+              sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
+              scss: 'vue-style-loader!css-loader!sass-loader',
+              less: 'vue-style-loader!css-loader!less-loader'
+            }
+          }
+        }
+      },
+      {
+        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
+        use: {
+          loader: 'url-loader',
+          query: {
+            limit: 10000,
+            name: 'imgs/[name].[ext]'
+          }
+        }
+      },
+      {
+        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
+        use: {
+          loader: 'url-loader',
+          query: {
+            limit: 10000,
+            name: 'fonts/[name].[ext]'
+          }
+        }
+      }
+    ]
+  },
+  plugins: [
+    new VueLoaderPlugin(),
+    new MiniCssExtractPlugin({filename: 'styles.css'}),
+    new HtmlWebpackPlugin({
+      filename: 'index.html',
+      template: path.resolve(__dirname, '../src/index.ejs'),
+      minify: {
+        collapseWhitespace: true,
+        removeAttributeQuotes: true,
+        removeComments: true
+      },
+      nodeModules: false
+    }),
+    new webpack.DefinePlugin({
+      'process.env.IS_WEB': 'true'
+    }),
+    new webpack.HotModuleReplacementPlugin(),
+    new webpack.NoEmitOnErrorsPlugin()
+  ],
+  output: {
+    filename: '[name].js',
+    path: path.join(__dirname, '../dist/web')
+  },
+  resolve: {
+    alias: {
+      '@': path.join(__dirname, '../src/renderer'),
+      'vue$': 'vue/dist/vue.esm.js'
+    },
+    extensions: ['.js', '.vue', '.json', '.css']
+  },
+  target: 'web'
+}
+
+/**
+ * Adjust webConfig for production settings
+ */
+if (process.env.NODE_ENV === 'production') {
+  webConfig.devtool = ''
+
+  webConfig.plugins.push(
+    new BabiliWebpackPlugin(),
+    new CopyWebpackPlugin([
+      {
+        from: path.join(__dirname, '../static'),
+        to: path.join(__dirname, '../dist/web/static'),
+        ignore: ['.*']
+      }
+    ]),
+    new webpack.DefinePlugin({
+      'process.env.NODE_ENV': '"production"'
+    }),
+    new webpack.LoaderOptionsPlugin({
+      minimize: true
+    })
+  )
+}
+
+module.exports = webConfig

+ 10 - 0
service_exe/.gitignore

@@ -0,0 +1,10 @@
+.DS_Store
+dist/electron/*
+dist/web/*
+build/*
+!build/icons
+node_modules/
+npm-debug.log
+npm-debug.log.*
+thumbs.db
+!.gitkeep

+ 36 - 0
service_exe/.travis.yml

@@ -0,0 +1,36 @@
+osx_image: xcode8.3
+sudo: required
+dist: trusty
+language: c
+matrix:
+  include:
+  - os: osx
+  - os: linux
+    env: CC=clang CXX=clang++ npm_config_clang=1
+    compiler: clang
+cache:
+  directories:
+  - node_modules
+  - "$HOME/.electron"
+  - "$HOME/.cache"
+addons:
+  apt:
+    packages:
+    - libgnome-keyring-dev
+    - icnsutils
+before_install:
+- mkdir -p /tmp/git-lfs && curl -L https://github.com/github/git-lfs/releases/download/v1.2.1/git-lfs-$([
+  "$TRAVIS_OS_NAME" == "linux" ] && echo "linux" || echo "darwin")-amd64-1.2.1.tar.gz
+  | tar -xz -C /tmp/git-lfs --strip-components 1 && /tmp/git-lfs/git-lfs pull
+- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils; fi
+install:
+- nvm install 7
+- curl -o- -L https://yarnpkg.com/install.sh | bash
+- source ~/.bashrc
+- npm install -g xvfb-maybe
+- yarn
+script:
+- yarn run build
+branches:
+  only:
+  - master

+ 22 - 0
service_exe/README.md

@@ -0,0 +1,22 @@
+# my-project
+
+> An electron-vue project
+
+#### Build Setup
+
+``` bash
+# install dependencies
+npm install
+
+# serve with hot reload at localhost:9080
+npm run dev
+
+# build electron application for production
+npm run build
+
+
+```
+
+---
+
+This project was generated with [electron-vue](https://github.com/SimulatedGREG/electron-vue)@[8fae476](https://github.com/SimulatedGREG/electron-vue/tree/8fae4763e9d225d3691b627e83b9e09b56f6c935) using [vue-cli](https://github.com/vuejs/vue-cli). Documentation about the original structure can be found [here](https://simulatedgreg.gitbooks.io/electron-vue/content/index.html).

+ 29 - 0
service_exe/appveyor.yml

@@ -0,0 +1,29 @@
+version: 0.1.{build}
+
+branches:
+  only:
+    - master
+
+image: Visual Studio 2017
+platform:
+  - x64
+
+cache:
+  - node_modules
+  - '%APPDATA%\npm-cache'
+  - '%USERPROFILE%\.electron'
+  - '%USERPROFILE%\AppData\Local\Yarn\cache'
+
+init:
+  - git config --global core.autocrlf input
+
+install:
+  - ps: Install-Product node 8 x64
+  - git reset --hard HEAD
+  - yarn
+  - node --version
+
+build_script:
+  - yarn build
+
+test: off

BIN
service_exe/build/icons/256x256.png


BIN
service_exe/build/icons/IMG_03.ico


BIN
service_exe/build/icons/icon.ico


BIN
service_exe/build/icons/icon.png


+ 0 - 0
service_exe/dist/electron/.gitkeep


+ 0 - 0
service_exe/dist/web/.gitkeep


+ 104 - 0
service_exe/package.json

@@ -0,0 +1,104 @@
+{
+  "name": "my-project",
+  "version": "0.0.1",
+  "author": "luke <123456485@qq.com>",
+  "description": "An electron-vue project",
+  "license": null,
+  "main": "./dist/electron/main.js",
+  "scripts": {
+    "build": "node .electron-vue/build.js && electron-builder",
+    "build:dir": "node .electron-vue/build.js && electron-builder --dir",
+    "build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js",
+    "build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js",
+    "dev": "node .electron-vue/dev-runner.js",
+    "pack": "npm run pack:main && npm run pack:renderer",
+    "pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js",
+    "pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js",
+    "postinstall": ""
+  },
+  "build": {
+    "productName": "my-project",
+    "appId": "com.example.yourapp",
+    "directories": {
+      "output": "build"
+    },
+    "files": [
+      "dist/electron/**/*"
+    ],
+    "dmg": {
+      "contents": [
+        {
+          "x": 410,
+          "y": 150,
+          "type": "link",
+          "path": "/Applications"
+        },
+        {
+          "x": 130,
+          "y": 150,
+          "type": "file"
+        }
+      ]
+    },
+    "mac": {
+      "icon": "build/icons/icon.icns"
+    },
+    "win": {
+      "icon": "build/icons/icon.png"
+    },
+    "linux": {
+      "icon": "build/icons"
+    }
+  },
+  "dependencies": {
+    "vue": "^2.5.16",
+    "axios": "^0.18.0",
+    "vue-electron": "^1.0.6",
+    "vue-router": "^3.0.1",
+    "vuex": "^3.0.1",
+    "vuex-electron": "^1.0.0",
+    "clipboard": "^2.0.4",
+    "element-ui": "^2.11.1",
+    "js-md5": "^0.7.3",
+    "less": "^3.9.0",
+    "less-loader": "^5.0.0",
+    "style-loader": "^0.23.1"
+  },
+  "devDependencies": {
+    "ajv": "^6.5.0",
+    "babel-core": "^6.26.3",
+    "babel-loader": "^7.1.4",
+    "babel-plugin-transform-runtime": "^6.23.0",
+    "babel-preset-env": "^1.7.0",
+    "babel-preset-stage-0": "^6.24.1",
+    "babel-register": "^6.26.0",
+    "babili-webpack-plugin": "^0.1.2",
+    "cfonts": "^2.1.2",
+    "chalk": "^2.4.1",
+    "copy-webpack-plugin": "^4.5.1",
+    "cross-env": "^5.1.6",
+    "css-loader": "^0.28.11",
+    "del": "^3.0.0",
+    "devtron": "^1.4.0",
+    "electron": "^2.0.4",
+    "electron-debug": "^1.5.0",
+    "electron-devtools-installer": "^2.2.4",
+    "electron-builder": "^20.19.2",
+    "mini-css-extract-plugin": "0.4.0",
+    "file-loader": "^1.1.11",
+    "html-webpack-plugin": "^3.2.0",
+    "multispinner": "^0.2.1",
+    "node-loader": "^0.6.0",
+    "style-loader": "^0.21.0",
+    "url-loader": "^1.0.1",
+    "vue-html-loader": "^1.2.4",
+    "vue-loader": "^15.2.4",
+    "vue-style-loader": "^4.1.0",
+    "vue-template-compiler": "^2.5.16",
+    "webpack-cli": "^3.0.8",
+    "webpack": "^4.15.1",
+    "webpack-dev-server": "^3.1.4",
+    "webpack-hot-middleware": "^2.22.2",
+    "webpack-merge": "^4.1.3"
+  }
+}

+ 24 - 0
service_exe/src/index.ejs

@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>大博客服系统</title>
+    <% if (htmlWebpackPlugin.options.nodeModules) { %>
+      <!-- Add `node_modules/` to global paths so `require` works properly in development -->
+      <script>
+        require('module').globalPaths.push('<%= htmlWebpackPlugin.options.nodeModules.replace(/\\/g, '\\\\') %>')
+      </script>
+    <% } %>
+  </head>
+  <body>
+    <div id="app"></div>
+    <!-- Set `__static` path to static files in production -->
+    <% if (!process.browser) { %>
+      <script>
+        if (process.env.NODE_ENV !== 'development') window.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
+      </script>
+    <% } %>
+
+    <!-- webpack builds are automatically injected -->
+  </body>
+</html>

+ 24 - 0
service_exe/src/main/index.dev.js

@@ -0,0 +1,24 @@
+/**
+ * This file is used specifically and only for development. It installs
+ * `electron-debug` & `vue-devtools`. There shouldn't be any need to
+ *  modify this file, but it can be used to extend your development
+ *  environment.
+ */
+
+/* eslint-disable */
+
+// Install `electron-debug` with `devtron`
+require('electron-debug')({ showDevTools: true })
+
+// Install `vue-devtools`
+require('electron').app.on('ready', () => {
+  let installExtension = require('electron-devtools-installer')
+  installExtension.default(installExtension.VUEJS_DEVTOOLS)
+    .then(() => {})
+    .catch(err => {
+      console.log('Unable to install `vue-devtools`: \n', err)
+    })
+})
+
+// Require `main` process to boot app
+require('./index')

+ 65 - 0
service_exe/src/main/index.js

@@ -0,0 +1,65 @@
+import { app, BrowserWindow } from 'electron'
+
+/**
+ * Set `__static` path to static files in production
+ * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
+ */
+if (process.env.NODE_ENV !== 'development') {
+  global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
+}
+
+let mainWindow
+const winURL = process.env.NODE_ENV === 'development'
+  ? `http://localhost:9080`
+  : `file://${__dirname}/index.html`
+
+function createWindow () {
+  /**
+   * Initial window options
+   */
+  mainWindow = new BrowserWindow({
+    height: 563,
+    useContentSize: true,
+    width: 1000
+  })
+
+  mainWindow.loadURL(winURL)
+
+  mainWindow.on('closed', () => {
+    mainWindow = null
+  })
+}
+
+app.on('ready', createWindow)
+
+app.on('window-all-closed', () => {
+  if (process.platform !== 'darwin') {
+    app.quit()
+  }
+})
+
+app.on('activate', () => {
+  if (mainWindow === null) {
+    createWindow()
+  }
+})
+
+/**
+ * Auto Updater
+ *
+ * Uncomment the following code below and install `electron-updater` to
+ * support auto updating. Code Signing with a valid certificate is required.
+ * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-builder.html#auto-updating
+ */
+
+/*
+import { autoUpdater } from 'electron-updater'
+
+autoUpdater.on('update-downloaded', () => {
+  autoUpdater.quitAndInstall()
+})
+
+app.on('ready', () => {
+  if (process.env.NODE_ENV === 'production') autoUpdater.checkForUpdates()
+})
+ */

+ 338 - 0
service_exe/src/renderer/App.vue

@@ -0,0 +1,338 @@
+<template>
+  <div id="app">
+    <transition name='fade' mode="out-in">
+      <router-view/>
+    </transition>
+  </div>
+</template>
+
+<script>
+  import Vue from 'vue';
+  export default {
+    name: 'App',
+    data(){
+      return{
+        reconnectData:null,
+        lockReconnect:false,    //避免重复连接,因为onerror之后会立即触发 onclose
+        timeout:5000,          //10s一次心跳检测
+        timeoutObj:null,
+        serverTimeoutObj:null,
+        apiToken:'',
+        linkfailure:true,
+      }
+    },
+    methods:{
+      /**************************************/
+      //初始化weosocket
+      initWebSocket(apiToken) {
+        // 书写接口信息
+        // http://stadmin.bocai108.com/
+        const wsuri = "ws://kfadmin.bocai186.com:9101?apiToken=" + apiToken;//www.service.com 线上
+        // const wsuri = "ws://192.168.2.187:9101?apiToken=" + apiToken;//www.service.com //192.168.2.186 本地
+        // 创建websocket实例
+        Vue.prototype.$websocket = new WebSocket(wsuri);
+        this.$websocket.onopen = this.websocketonopen; //连接成功
+        this.$websocket.onmessage = this.websocketonmessage; //接收消息
+        this.$websocket.onerror = this.websocketonerror;//链接错误提示
+        this.$websocket.onclose = this.socket_close;//链接断开提示
+      },
+
+      /**************************************/
+      //连接成功
+      websocketonopen() {
+        console.log('已经链接');
+        let user_info = '';
+        // console.log(this.$store.getters.get_user_info != "");
+        if(typeof this.$store.getters.get_user_info  != 'string'){
+          user_info = this.$store.getters.get_user_info;
+        }else if(this.$store.getters.get_user_info!= ""){
+          user_info =  JSON.parse(this.$store.getters.get_user_info);
+        }
+
+        if(user_info){
+          this.$websocket.send(JSON.stringify({
+            type: 'init',
+            data: {
+              uid: 'KF' + user_info.id,
+              group: user_info.group_id,
+              token: user_info.token,
+              name: user_info.user_name,
+              avatar: user_info.user_avatar,
+            }
+          }));
+        }
+
+
+        this.$store.dispatch("SET_SOCKET_OPEN",true);//列表下标
+        this.heatBeat();
+      },
+
+      /*******************************************/
+      //连接关闭触发
+      socket_close(e){
+        console.log('断开连接',e);
+        //this.init()
+        this.reconnect();
+      },
+
+      /******************************************/
+      //数据接收
+      websocketonmessage(e){
+        this.heatBeat();//收到消息会刷新心跳检测,如果一直收到消息,就推迟心跳发送
+        const redata = JSON.parse(e.data);//接收数据源
+        //
+        if(redata.message_type == "ping"){
+          this.$websocket.send('{"type":"pong"}')
+          return false;
+        }
+
+        if(redata.type == "pong") return false;
+        if(redata.type != "pong" || redata.message_type != "ping"){
+          console.log(redata);
+        }
+        let getters = this.$store.getters;
+        //获取vuex数据
+        let session = getters.get_session;//会话列表
+        let offline  = getters.get_offline;//离线列表
+        let sessionType  = getters.get_type;//选择状态(会话/离线)
+        let dataIndex  = getters.get_num;//列表下标
+        let current_session  = getters.get_current;//当前会话
+        let session_name  = getters.get_session_name;//当前用户名
+
+        this.$store.dispatch("SET_SESSION_MESSAGE",JSON.parse(e.data));
+
+        // 用户接入数据
+        if(redata.message_type == "connect"){
+          let _this  = this;
+          let arr =[
+            redata.data,
+            offline,
+            session,
+            sessionType,
+            dataIndex,
+            current_session,
+            session_name,
+          ]
+          _this.$public.visitorsConnect(arr,function(data){
+            //离线匹配列表访客链接回调
+            _this.$store.dispatch("SET_OFFLINE",data);
+
+          },function(data,session,offline,type,num,dataList,name){
+            //将用户添加到会话列表中
+            // console.log('接入用户昵称',name);
+            if(name){
+              data.user_info.name = name;
+              _this.$store.dispatch("SET_SESSION_NAME",name);//当前会话对象名
+            }
+
+            session.push(data.user_info);
+            //获取接入的用户信息
+            //_this.get_user_info(list);
+            //获取接入的用户信息写入vuex
+            _this.$store.dispatch("SET_SESSION",session);//会话列表
+            _this.$store.dispatch("SET_OFFLINE",offline);//离线列表
+            _this.$store.dispatch("SET_TYPE",type);//选择类型(会话/离线)
+            _this.$store.dispatch("SET_NUM",num);//列表下标
+            _this.$store.dispatch("SET_CURRENT",dataList);//当前会话数据
+
+          })
+        }
+
+        //登录验证失败跳转登录页面
+        if(redata.message_type == 'checkfalse'){
+          // this.$router.push({
+          // 	path:'/login',
+          // 	query: { pid:escape("这就是一个编码没有什么用啊") }
+          // })
+        }
+
+        //用户离线后会话窗口切换
+        if(redata.message_type == "userClose"){
+          let _this =this;
+          let	arr= [
+            redata.data,
+            session,
+            offline,
+            sessionType,
+            dataIndex,
+            session_name,
+            current_session,
+          ]
+          _this.$public.userOffline(arr,function(session,offline,type,index,name,list,userInfo){
+            _this.$store.dispatch("SET_CURRENT",list);//当前会话数据
+            _this.$store.dispatch("SET_SESSION_NAME",name);//当前会话对象名
+            _this.$store.dispatch("SET_NUM",index);
+            _this.$store.dispatch("SET_TYPE",type);
+            _this.$store.dispatch("SET_SESSION",session);
+            _this.$store.dispatch("SET_OFFLINE",offline);
+            // _this.get_user_info(userInfo);
+          })
+        }
+
+
+        //用户会话结束窗口切换
+        if(redata.message_type == "delUser"){
+          let _this =this;
+          let	arr= [
+            redata.data,
+            session,
+            offline,
+            sessionType,
+            dataIndex,
+            session_name,
+            current_session,
+          ]
+          _this.$public.sessionEnd(arr,function(session,offline,type,index,name,list,userInfo){
+            console.log('session',session);
+            console.log('offline',offline);
+            _this.$store.dispatch("SET_CURRENT",list);//当前会话数据
+            _this.$store.dispatch("SET_SESSION_NAME",name);//当前会话对象名
+            _this.$store.dispatch("SET_NUM",index);
+            _this.$store.dispatch("SET_TYPE",type);
+            _this.$store.dispatch("SET_SESSION",session);
+            _this.$store.dispatch("SET_OFFLINE",offline);
+            //	_this.get_user_info(userInfo);
+          })
+        }
+
+        //接收用户消息数据
+        if(redata.message_type == "chatMessage"){
+          this.receiveAudio();
+          let _this =this;
+          this.$public.receivesMessage(redata.data,session,this.$frce,function(data,chatList,index){
+            //判断是否是当前对话信息
+            if(dataIndex == index){
+              _this.$store.dispatch("SET_CURRENT",chatList.data);//当前会话数据
+            }else{
+              let num = Number.isInteger(chatList.num) ? chatList.num : 0;
+              // session[index].num = num+1;
+              _this.$set(session[index],'num',num+1)
+            }
+            //更新会话时间
+            session[index].intime =data.time;
+
+            //更新会话列表中最新回复消息
+            if(data.content.text){
+              // _this.$set(chatList,'text',data.content.text)
+              session[index].text =data.content.text;
+            }
+            _this.$store.dispatch("SET_SESSION",session);
+          })
+        }
+        // history
+
+        //reLoginErr
+        if(redata.message_type == "reLoginErr"){
+          // console.log('haha');
+          this.init()
+        }
+
+      },
+
+      /**************************************/
+      //连接断开,失败
+      websocketonerror(e) {
+        console.log('失败',e);
+        if(this.linkfailure){
+          this.init()
+        }
+      },
+
+      /******************************************/
+      //断开链接数据初始化
+      init(){
+        this.$store.dispatch("SET_STATEVALUE",'在线');
+        this.$store.dispatch("SET_SESSION",[]);
+        this.$store.dispatch("SET_USER",'');
+        this.$store.dispatch("SET_OFFLINE",[]);
+        this.$store.dispatch("SET_SESSION",[]);//会话列表
+        this.$store.dispatch("SET_OFFLINE",[]);//离线列表
+        this.$store.dispatch("SET_TYPE",1);//选择类型(会话/离线)
+        this.$store.dispatch("SET_NUM",0);//列表下标
+        this.$store.dispatch("SET_CURRENT",[]);//当前会话数据
+        this.$store.dispatch("SET_SESSION_NAME",'');//当前会话对象名
+        this.$store.dispatch("SET_SESSION_MESSAGE",{});
+        this.$store.dispatch("SET_NAVSTATE",'TheCurrentSession');
+        this.$store.dispatch("SET_IS_INIT",false);
+        this.$token = '';
+        this.$router.push('/login')
+        this.linkfailure = true;
+        //this.reconnect();
+      },
+
+      /*******************************************/
+      // 接收消息音频提示
+      receiveAudio() {
+        let receive = new Audio()
+        receive.src = "../static/audio/receive.wav";
+        receive.play();
+      },
+      /***************************************/
+      //socket重连
+      reconnect(){
+        if(this.lockReconnect){   //这里很关键,因为连接失败之后之后会相继触发 连接关闭,不然会连接上两个 WebSocket
+          return
+        }
+        this.lockReconnect = true;
+        this.reconnectData && clearTimeout(this.reconnectData);
+        this.reconnectData = setTimeout(()=>{
+          this.initWebSocket(this.apiToken);
+          this.lockReconnect = false;
+        },3000)
+      },
+
+      /*************************************/
+      //心跳检测
+      heatBeat(){
+        this.timeoutObj && clearTimeout(this.timeoutObj);
+        this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
+        this.timeoutObj = setTimeout(()=>{
+          // console.log('发送',{type:'ping'});
+          this.$websocket.send(JSON.stringify({type:'ping'}))   //根据后台要求发送
+          this.serverTimeoutObj = setTimeout(()=> {
+            this.$websocket.close(); //如果4秒之后我们没有收到 后台返回的心跳检测数据 断开socket,断开后会启动重连机制
+          }, 4000);
+        }, this.timeout)
+      },
+
+      /******************************/
+
+    },
+    mounted() {
+      Vue.prototype.$socket_open = false;
+      this.apiToken = this.$md5('customer-service'+window.location.origin)
+      this.initWebSocket(this.apiToken);
+      // 获取系统时间
+      //let t = new Date().getTime();
+      //this.get('api'+this.$ports.TIME+'?t='+t).then(res => {
+      // this.$http.get(this.$ports.TIME+'?t='+t).then(res => {
+      // 	if (res.data.code == 1) {
+      // 		let time = res.data.data.time.split(' ');
+      // 		time[0] =(new Date( time[0].replace(/-/g,'/')).getTime()) /1000;
+      // 		sessionStorage.setItem("time",JSON.stringify(time));
+      // 		sessionStorage.setItem("logo",res.data.data.logo);
+
+      // 	}
+      // });
+    },
+    destroyed() {
+      this.lockReconnect = true;
+      this.websock.close()                   //离开路由之后断开websocket连接
+      clearTimeout(this.reconnectData);      //离开清除 timeout
+      clearTimeout(this.timeoutObj);         //离开清除 timeout
+      clearTimeout(this.serverTimeoutObj);   //离开清除 timeout
+      localStorage.removeItem('user');
+      // console.log(123)
+    }
+  }
+</script>
+
+<style>
+  .fade-enter-active, .fade-leave-active {
+    transition: opacity .5s;
+  }
+
+  .fade-enter, .fade-leave-to {
+    opacity: 0;
+  }
+</style>

+ 62 - 0
service_exe/src/renderer/api/http.js

@@ -0,0 +1,62 @@
+import axios from 'axios' // 引入axios
+import qs from 'qs'  // 序列化字符串
+
+// 请求超时时间
+axios.defaults.timeout = 10000
+// 线上
+let Base = 'http://kfadmin.bocai186.com'
+// 开发
+//let Base = 'http://sports.5gogo.com'
+function headerUrl (url) {
+	url = Base +  url
+	return url
+}
+// post请求头
+axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
+export default {
+	/**
+	 * get方法对应get请求
+	 * @param {String}url 请求地址
+	 * @param {Object}params 携带参数
+	 * @returns {Promise}
+	 */
+	get (url, params) {
+		return new Promise((resolve, reject) => {
+			axios.get(headerUrl(url),params)
+				.then(res => {
+					resolve(res)
+				})
+				.catch(err => {
+					reject(err)
+				})
+		})
+	},
+	/**
+	 * post方法对应post请求
+	 * @param {String} url 请求地址
+	 * @param {Object} params 携带参数
+	 * @returns {Promise}
+	 */
+	post (url, params,headers) {
+		return new Promise((resolve, reject) => {
+			axios.post(headerUrl(url), params ?qs.stringify(params):'',headers)
+				.then(res => {
+					resolve(res)
+				})
+				.catch(err => {
+					reject(err)
+				})
+		})
+	},
+	uploadPost(url, params) {
+		return new Promise((resolve, reject) => {
+			axios.post(headerUrl(url), params)
+				.then(res => {
+					resolve(res)
+				})
+				.catch(err => {
+					reject(err)
+				})
+		})
+	}
+}

+ 60 - 0
service_exe/src/renderer/api/ports.js

@@ -0,0 +1,60 @@
+export default {
+  login: '/service/Login/doLogin',
+  // 获取时间
+  TIME:'/index/index/systime',
+  // 快捷回复
+  FastReply:{
+    userWords:'/service/index/userWords',//获取快捷回复列表
+    addWords:'/service/words/addWords',//新增快捷回复
+    deleteWords:'/service/words/deleteWords',//删除快捷回复/service/words/deleteWords
+    updateWords:'/service/words/updateWords',//修改快捷语
+
+    
+  },
+  // 历史会话
+  SessionHistory:{
+    historyList:'/service/history/historyList',//历史会话列表
+  },
+
+  //图片上传
+  uploadImg:'/index/upload/uploadImg',
+
+  //获取配置信息
+  minRound:'/index/evaluate/minRound',
+
+  //获取敏感词
+  sensitiveWords:'/index/index/sensitiveWords',
+
+  //用户信息 
+  userInfo:{
+    updateinfo:'/service/Services/updateinfo',
+    updatepwd:'/service/Services/updatepwd',
+    update:'/service/services/update',//客服编辑用户信息
+    accountInfo:'/service/services/accountInfo'
+  },
+
+  //历史会话消息
+  history:{
+    historyList:'/service/history/historyList',
+    historyInfo:"/service/history/historyInfo",
+  },
+
+  //留言 
+  Message:{
+    dealmessage:'/service/Message/dealmessage',
+    index:'/service/Message/index',
+  },
+  //消息中心
+  center:{
+    readnotice:"/service/index/readnotice",
+    unreadnotice:"/service/index/unreadnotice",
+    updatenotice:"/service/index/updatenotice",//读取信息
+    
+  },
+  //会话总览
+  overview:{
+    allConversation:"/service/history/allConversation",
+    chatByTime:'/service/history/chatByTime',
+  }
+
+}

+ 0 - 0
service_exe/src/renderer/assets/.gitkeep


+ 4 - 0
service_exe/src/renderer/assets/frce.js

@@ -0,0 +1,4 @@
+export default{
+    frce : ["[微笑]","[嘻嘻]","[哈哈]","[可爱]","[可怜]","[挖鼻]","[吃惊]","[害羞]","[挤眼]","[闭嘴]","[鄙视]","[爱你]","[泪]","[偷笑]","[亲亲]","[生病]","[太开心]","[白眼]","[右哼哼]","[左哼哼]","[嘘]","[衰]","[委屈]","[吐]","[哈欠]","[抱抱]","[怒]","[疑问]","[馋嘴]","[拜拜]","[思考]","[汗]","[困]","[睡]","[钱]","[失望]","[酷]","[色]","[哼]","[鼓掌]","[晕]","[悲伤]","[抓狂]","[黑线]","[阴险]","[怒骂]","[互粉]","[心]","[伤心]","[猪头]","[熊猫]","[兔子]","[ok]","[耶]","[good]","[NO]","[赞]","[来]","[弱]","[草泥马]","[神马]","[囧]","[浮云]","[给力]","[围观]","[威武]","[奥特曼]","[礼物]","[钟]","[话筒]","[蜡烛]","[蛋糕]"],
+    arr : ['1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','P','R','T','V','W','X','Y','Z'],
+}

BIN
service_exe/src/renderer/assets/img/0.gif


BIN
service_exe/src/renderer/assets/img/1.gif


BIN
service_exe/src/renderer/assets/img/10.gif


BIN
service_exe/src/renderer/assets/img/11.gif


BIN
service_exe/src/renderer/assets/img/12.gif


BIN
service_exe/src/renderer/assets/img/13.gif


BIN
service_exe/src/renderer/assets/img/14.gif


BIN
service_exe/src/renderer/assets/img/15.gif


BIN
service_exe/src/renderer/assets/img/16.gif


BIN
service_exe/src/renderer/assets/img/17.gif


BIN
service_exe/src/renderer/assets/img/18.gif


BIN
service_exe/src/renderer/assets/img/19.gif


BIN
service_exe/src/renderer/assets/img/2.gif


BIN
service_exe/src/renderer/assets/img/20.gif


BIN
service_exe/src/renderer/assets/img/21.gif


BIN
service_exe/src/renderer/assets/img/22.gif


BIN
service_exe/src/renderer/assets/img/23.gif


BIN
service_exe/src/renderer/assets/img/24.gif


BIN
service_exe/src/renderer/assets/img/25.gif


BIN
service_exe/src/renderer/assets/img/26.gif


BIN
service_exe/src/renderer/assets/img/27.gif


BIN
service_exe/src/renderer/assets/img/28.gif


BIN
service_exe/src/renderer/assets/img/29.gif


BIN
service_exe/src/renderer/assets/img/3.gif


BIN
service_exe/src/renderer/assets/img/30.gif


BIN
service_exe/src/renderer/assets/img/31.gif


BIN
service_exe/src/renderer/assets/img/32.gif


BIN
service_exe/src/renderer/assets/img/33.gif


BIN
service_exe/src/renderer/assets/img/34.gif


BIN
service_exe/src/renderer/assets/img/35.gif


BIN
service_exe/src/renderer/assets/img/36.gif


BIN
service_exe/src/renderer/assets/img/37.gif


BIN
service_exe/src/renderer/assets/img/38.gif


BIN
service_exe/src/renderer/assets/img/39.gif


BIN
service_exe/src/renderer/assets/img/4.gif


BIN
service_exe/src/renderer/assets/img/40.gif


BIN
service_exe/src/renderer/assets/img/41.gif


BIN
service_exe/src/renderer/assets/img/42.gif


BIN
service_exe/src/renderer/assets/img/43.gif


BIN
service_exe/src/renderer/assets/img/44.gif


BIN
service_exe/src/renderer/assets/img/45.gif


BIN
service_exe/src/renderer/assets/img/46.gif


BIN
service_exe/src/renderer/assets/img/47.gif


BIN
service_exe/src/renderer/assets/img/48.gif


BIN
service_exe/src/renderer/assets/img/49.gif


BIN
service_exe/src/renderer/assets/img/5.gif


BIN
service_exe/src/renderer/assets/img/50.gif


BIN
service_exe/src/renderer/assets/img/51.gif


BIN
service_exe/src/renderer/assets/img/52.gif


BIN
service_exe/src/renderer/assets/img/53.gif


BIN
service_exe/src/renderer/assets/img/54.gif


BIN
service_exe/src/renderer/assets/img/55.gif


BIN
service_exe/src/renderer/assets/img/56.gif


BIN
service_exe/src/renderer/assets/img/57.gif


BIN
service_exe/src/renderer/assets/img/58.gif


BIN
service_exe/src/renderer/assets/img/59.gif


BIN
service_exe/src/renderer/assets/img/6.gif


BIN
service_exe/src/renderer/assets/img/60.gif


BIN
service_exe/src/renderer/assets/img/61.gif


BIN
service_exe/src/renderer/assets/img/62.gif


BIN
service_exe/src/renderer/assets/img/63.gif


BIN
service_exe/src/renderer/assets/img/64.gif


BIN
service_exe/src/renderer/assets/img/65.gif


BIN
service_exe/src/renderer/assets/img/66.gif


BIN
service_exe/src/renderer/assets/img/67.gif


BIN
service_exe/src/renderer/assets/img/68.gif


BIN
service_exe/src/renderer/assets/img/69.gif


BIN
service_exe/src/renderer/assets/img/7.gif


BIN
service_exe/src/renderer/assets/img/70.gif


BIN
service_exe/src/renderer/assets/img/71.gif


BIN
service_exe/src/renderer/assets/img/8.gif


BIN
service_exe/src/renderer/assets/img/9.gif


BIN
service_exe/src/renderer/assets/img/Multitap.png


BIN
service_exe/src/renderer/assets/img/account.png


Някои файлове не бяха показани, защото твърде много файлове са промени