├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .postcssrc.js
├── README.md
├── build
├── build.js
├── check-versions.js
├── logo.png
├── utils.js
├── vue-loader.conf.js
├── webpack.base.conf.js
├── webpack.dev.conf.js
└── webpack.prod.conf.js
├── config
├── dev.env.js
├── index.js
├── prod.env.js
└── test.env.js
├── index.html
├── package.json
├── src
├── App.vue
├── components
│ ├── Aside.vue
│ ├── AsideContent.vue
│ ├── NotFound.vue
│ ├── SectionContent.vue
│ ├── header.vue
│ └── setting.vue
├── config
│ └── env.js
├── directives
│ └── index.js
├── filters
│ └── index.js
├── lang
│ ├── en.js
│ └── zhCHS.js
├── main.js
├── mixin
│ └── index.js
├── plugins
│ └── toast
│ │ ├── toast.css
│ │ └── toast.js
├── router
│ └── index.js
├── service
│ ├── index.js
│ └── modules
│ │ ├── common.js
│ │ ├── userInfo.js
│ │ └── wx.js
├── store
│ ├── index.js
│ ├── modules
│ │ ├── common.js
│ │ ├── main.js
│ │ ├── userInfo.js
│ │ └── wx.js
│ └── mutation-types.js
├── style
│ ├── 1px.scss
│ ├── common.scss
│ ├── content.scss
│ ├── mixin
│ │ └── setOnepx.scss
│ └── reset.scss
├── utils
│ ├── dict.js
│ ├── regular.js
│ └── utils.js
└── view
│ ├── login
│ └── login.vue
│ ├── management
│ ├── index.vue
│ └── menu.vue
│ └── wechat
│ ├── children
│ ├── wxChatContent.vue
│ ├── wxChatHeader.vue
│ ├── wxChatItem.vue
│ ├── wxChatList.vue
│ ├── wxChatSendBox.vue
│ ├── wxChatSideBar.vue
│ └── wxLogin.vue
│ └── index.vue
├── static
├── .gitkeep
├── css
│ └── emoji.css
├── images
│ ├── 404.png
│ ├── avatar.jpg
│ ├── bg.jpg
│ ├── emoji.png
│ ├── emoji2.png
│ ├── faceqqemoji.png
│ ├── fhemoji.png
│ ├── login_bg.jpg
│ ├── logo.png
│ ├── refresh-34re.png
│ └── timg.png
└── js
│ └── walden.js
└── test
├── e2e
├── custom-assertions
│ └── elementCount.js
├── nightwatch.conf.js
├── runner.js
└── specs
│ └── test.js
└── unit
├── .eslintrc
├── jest.conf.js
├── setup.js
└── specs
└── HelloWorld.spec.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": [
12 | [
13 | "component",
14 | {
15 | "libraryName": "element-ui",
16 | "styleLibraryName": "theme-chalk"
17 | }
18 | ],
19 | "transform-vue-jsx",
20 | "transform-runtime"
21 | ],
22 | "env": {
23 | "test": {
24 | "presets": ["env", "stage-2"],
25 | "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | /build/
2 | /config/
3 | /dist/
4 | /*.js
5 | /test/unit/coverage/
6 | /src/utils/regular.js
7 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // https://eslint.org/docs/user-guide/configuring
2 |
3 | module.exports = {
4 | root: true,
5 | parserOptions: {
6 | parser: 'babel-eslint'
7 | },
8 | env: {
9 | browser: true,
10 | },
11 | extends: [
12 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
13 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
14 | 'plugin:vue/essential',
15 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md
16 | 'standard'
17 | ],
18 | // required to lint *.vue files
19 | plugins: [
20 | 'vue'
21 | ],
22 | // add your custom rules here
23 | rules: {
24 | // allow async-await
25 | 'generator-star-spacing': 'off',
26 | // allow debugger during development
27 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | /test/unit/coverage/
8 | /test/e2e/reports/
9 | selenium-debug.log
10 |
11 | # Editor directories and files
12 | .idea
13 | .vscode
14 | *.suo
15 | *.ntvs*
16 | *.njsproj
17 | *.sln
18 | src/view/wechat/index - 副本.vue
19 |
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-wechat
2 | ### Web版微信主要参考Web微信协议进行设计开发
3 |
4 | ### 我们希望实现的功能包括基本的登录、聊天群发功能(文本/表情/图片/文件/公众号链接)、公众号阅读、聊天记录导出保存、用户画像、聊天机器人
5 |
--------------------------------------------------------------------------------
/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hty7/vue-wechat/cedcde1f098f862385b77f56b5a8e07d270d7ad0/build/logo.png
--------------------------------------------------------------------------------
/build/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const config = require('../config')
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
5 | const packageConfig = require('../package.json')
6 |
7 | exports.assetsPath = function (_path) {
8 | const assetsSubDirectory = process.env.NODE_ENV === 'production'
9 | ? config.build.assetsSubDirectory
10 | : config.dev.assetsSubDirectory
11 |
12 | return path.posix.join(assetsSubDirectory, _path)
13 | }
14 |
15 | exports.cssLoaders = function (options) {
16 | options = options || {}
17 |
18 | const cssLoader = {
19 | loader: 'css-loader',
20 | options: {
21 | sourceMap: options.sourceMap
22 | }
23 | }
24 |
25 | const postcssLoader = {
26 | loader: 'postcss-loader',
27 | options: {
28 | sourceMap: options.sourceMap
29 | }
30 | }
31 |
32 | // generate loader string to be used with extract text plugin
33 | function generateLoaders (loader, loaderOptions) {
34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
35 |
36 | if (loader) {
37 | loaders.push({
38 | loader: loader + '-loader',
39 | options: Object.assign({}, loaderOptions, {
40 | sourceMap: options.sourceMap
41 | })
42 | })
43 | }
44 |
45 | // Extract CSS when that option is specified
46 | // (which is the case during production build)
47 | if (options.extract) {
48 | return ExtractTextPlugin.extract({
49 | use: loaders,
50 | fallback: 'vue-style-loader'
51 | })
52 | } else {
53 | return ['vue-style-loader'].concat(loaders)
54 | }
55 | }
56 |
57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
58 | return {
59 | css: generateLoaders(),
60 | postcss: generateLoaders(),
61 | less: generateLoaders('less'),
62 | sass: generateLoaders('sass', { indentedSyntax: true }),
63 | scss: generateLoaders('sass'),
64 | stylus: generateLoaders('stylus'),
65 | styl: generateLoaders('stylus')
66 | }
67 | }
68 |
69 | // Generate loaders for standalone style files (outside of .vue)
70 | exports.styleLoaders = function (options) {
71 | const output = []
72 | const loaders = exports.cssLoaders(options)
73 |
74 | for (const extension in loaders) {
75 | const loader = loaders[extension]
76 | output.push({
77 | test: new RegExp('\\.' + extension + '$'),
78 | use: loader
79 | })
80 | }
81 |
82 | return output
83 | }
84 |
85 | exports.createNotifierCallback = () => {
86 | const notifier = require('node-notifier')
87 |
88 | return (severity, errors) => {
89 | if (severity !== 'error') return
90 |
91 | const error = errors[0]
92 | const filename = error.file && error.file.split('!').pop()
93 |
94 | notifier.notify({
95 | title: packageConfig.name,
96 | message: severity + ': ' + error.name,
97 | subtitle: filename || '',
98 | icon: path.join(__dirname, 'logo.png')
99 | })
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 | const createLintingRule = () => ({
12 | test: /\.(js|vue)$/,
13 | loader: 'eslint-loader',
14 | enforce: 'pre',
15 | include: [resolve('src'), resolve('test')],
16 | options: {
17 | formatter: require('eslint-friendly-formatter'),
18 | emitWarning: !config.dev.showEslintErrorsInOverlay
19 | }
20 | })
21 |
22 | module.exports = {
23 | context: path.resolve(__dirname, '../'),
24 | entry: {
25 | app: './src/main.js'
26 | },
27 | output: {
28 | path: config.build.assetsRoot,
29 | filename: '[name].js',
30 | publicPath: process.env.NODE_ENV === 'production'
31 | ? config.build.assetsPublicPath
32 | : config.dev.assetsPublicPath
33 | },
34 | resolve: {
35 | extensions: ['.js', '.vue', '.json'],
36 | alias: {
37 | 'vue$': 'vue/dist/vue.esm.js',
38 | '@': resolve('src'),
39 | }
40 | },
41 | module: {
42 | rules: [
43 | ...(config.dev.useEslint ? [createLintingRule()] : []),
44 | {
45 | test: /\.vue$/,
46 | loader: 'vue-loader',
47 | options: vueLoaderConfig
48 | },
49 | {
50 | test: /\.js$/,
51 | loader: 'babel-loader',
52 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
53 | },
54 | {
55 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
56 | loader: 'url-loader',
57 | options: {
58 | limit: 10000,
59 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
60 | }
61 | },
62 | {
63 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
64 | loader: 'url-loader',
65 | options: {
66 | limit: 10000,
67 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
68 | }
69 | },
70 | {
71 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
72 | loader: 'url-loader',
73 | options: {
74 | limit: 10000,
75 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
76 | }
77 | }
78 | ]
79 | },
80 | node: {
81 | // prevent webpack from injecting useless setImmediate polyfill because Vue
82 | // source contains it (although only uses it if it's native).
83 | setImmediate: false,
84 | // prevent webpack from injecting mocks to Node native modules
85 | // that does not make sense for the client
86 | dgram: 'empty',
87 | fs: 'empty',
88 | net: 'empty',
89 | tls: 'empty',
90 | child_process: 'empty'
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const webpack = require('webpack')
4 | const config = require('../config')
5 | const merge = require('webpack-merge')
6 | const path = require('path')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
11 | const portfinder = require('portfinder')
12 |
13 | const HOST = process.env.HOST
14 | const PORT = process.env.PORT && Number(process.env.PORT)
15 |
16 | const devWebpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
19 | },
20 | // cheap-module-eval-source-map is faster for development
21 | devtool: config.dev.devtool,
22 |
23 | // these devServer options should be customized in /config/index.js
24 | devServer: {
25 | clientLogLevel: 'warning',
26 | historyApiFallback: {
27 | rewrites: [
28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
29 | ],
30 | },
31 | hot: true,
32 | contentBase: false, // since we use CopyWebpackPlugin.
33 | compress: true,
34 | host: HOST || config.dev.host,
35 | port: PORT || config.dev.port,
36 | open: config.dev.autoOpenBrowser,
37 | overlay: config.dev.errorOverlay
38 | ? { warnings: false, errors: true }
39 | : false,
40 | publicPath: config.dev.assetsPublicPath,
41 | proxy: config.dev.proxyTable,
42 | quiet: true, // necessary for FriendlyErrorsPlugin
43 | watchOptions: {
44 | poll: config.dev.poll,
45 | }
46 | },
47 | plugins: [
48 | new webpack.DefinePlugin({
49 | 'process.env': require('../config/dev.env')
50 | }),
51 | new webpack.HotModuleReplacementPlugin(),
52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
53 | new webpack.NoEmitOnErrorsPlugin(),
54 | // https://github.com/ampedandwired/html-webpack-plugin
55 | new HtmlWebpackPlugin({
56 | filename: 'index.html',
57 | template: 'index.html',
58 | inject: true
59 | }),
60 | // copy custom static assets
61 | new CopyWebpackPlugin([
62 | {
63 | from: path.resolve(__dirname, '../static'),
64 | to: config.dev.assetsSubDirectory,
65 | ignore: ['.*']
66 | }
67 | ])
68 | ]
69 | })
70 |
71 | module.exports = new Promise((resolve, reject) => {
72 | portfinder.basePort = process.env.PORT || config.dev.port
73 | portfinder.getPort((err, port) => {
74 | if (err) {
75 | reject(err)
76 | } else {
77 | // publish the new Port, necessary for e2e tests
78 | process.env.PORT = port
79 | // add port to devServer config
80 | devWebpackConfig.devServer.port = port
81 |
82 | // Add FriendlyErrorsPlugin
83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
84 | compilationSuccessInfo: {
85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
86 | },
87 | onErrors: config.dev.notifyOnErrors
88 | ? utils.createNotifierCallback()
89 | : undefined
90 | }))
91 |
92 | resolve(devWebpackConfig)
93 | }
94 | })
95 | })
96 |
--------------------------------------------------------------------------------
/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const webpack = require('webpack')
5 | const config = require('../config')
6 | const merge = require('webpack-merge')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
13 |
14 | const env = process.env.NODE_ENV === 'testing'
15 | ? require('../config/test.env')
16 | : require('../config/prod.env')
17 |
18 | const webpackConfig = merge(baseWebpackConfig, {
19 | module: {
20 | rules: utils.styleLoaders({
21 | sourceMap: config.build.productionSourceMap,
22 | extract: true,
23 | usePostCSS: true
24 | })
25 | },
26 | devtool: config.build.productionSourceMap ? config.build.devtool : false,
27 | output: {
28 | path: config.build.assetsRoot,
29 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
30 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
31 | },
32 | plugins: [
33 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
34 | new webpack.DefinePlugin({
35 | 'process.env': env
36 | }),
37 | new UglifyJsPlugin({
38 | uglifyOptions: {
39 | compress: {
40 | warnings: false
41 | }
42 | },
43 | sourceMap: config.build.productionSourceMap,
44 | parallel: true
45 | }),
46 | // extract css into its own file
47 | new ExtractTextPlugin({
48 | filename: utils.assetsPath('css/[name].[contenthash].css'),
49 | // Setting the following option to `false` will not extract CSS from codesplit chunks.
50 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
51 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
52 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
53 | allChunks: true,
54 | }),
55 | // Compress extracted CSS. We are using this plugin so that possible
56 | // duplicated CSS from different components can be deduped.
57 | new OptimizeCSSPlugin({
58 | cssProcessorOptions: config.build.productionSourceMap
59 | ? { safe: true, map: { inline: false } }
60 | : { safe: true }
61 | }),
62 | // generate dist index.html with correct asset hash for caching.
63 | // you can customize output by editing /index.html
64 | // see https://github.com/ampedandwired/html-webpack-plugin
65 | new HtmlWebpackPlugin({
66 | filename: process.env.NODE_ENV === 'testing'
67 | ? 'index.html'
68 | : config.build.index,
69 | template: 'index.html',
70 | inject: true,
71 | minify: {
72 | removeComments: true,
73 | collapseWhitespace: true,
74 | removeAttributeQuotes: true
75 | // more options:
76 | // https://github.com/kangax/html-minifier#options-quick-reference
77 | },
78 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
79 | chunksSortMode: 'dependency'
80 | }),
81 | // keep module.id stable when vendor modules does not change
82 | new webpack.HashedModuleIdsPlugin(),
83 | // enable scope hoisting
84 | new webpack.optimize.ModuleConcatenationPlugin(),
85 | // split vendor js into its own file
86 | new webpack.optimize.CommonsChunkPlugin({
87 | name: 'vendor',
88 | minChunks (module) {
89 | // any required modules inside node_modules are extracted to vendor
90 | return (
91 | module.resource &&
92 | /\.js$/.test(module.resource) &&
93 | module.resource.indexOf(
94 | path.join(__dirname, '../node_modules')
95 | ) === 0
96 | )
97 | }
98 | }),
99 | // extract webpack runtime and module manifest to its own file in order to
100 | // prevent vendor hash from being updated whenever app bundle is updated
101 | new webpack.optimize.CommonsChunkPlugin({
102 | name: 'manifest',
103 | minChunks: Infinity
104 | }),
105 | // This instance extracts shared chunks from code splitted chunks and bundles them
106 | // in a separate chunk, similar to the vendor chunk
107 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
108 | new webpack.optimize.CommonsChunkPlugin({
109 | name: 'app',
110 | async: 'vendor-async',
111 | children: true,
112 | minChunks: 3
113 | }),
114 |
115 | // copy custom static assets
116 | new CopyWebpackPlugin([
117 | {
118 | from: path.resolve(__dirname, '../static'),
119 | to: config.build.assetsSubDirectory,
120 | ignore: ['.*']
121 | }
122 | ])
123 | ]
124 | })
125 |
126 | if (config.build.productionGzip) {
127 | const CompressionWebpackPlugin = require('compression-webpack-plugin')
128 |
129 | webpackConfig.plugins.push(
130 | new CompressionWebpackPlugin({
131 | asset: '[path].gz[query]',
132 | algorithm: 'gzip',
133 | test: new RegExp(
134 | '\\.(' +
135 | config.build.productionGzipExtensions.join('|') +
136 | ')$'
137 | ),
138 | threshold: 10240,
139 | minRatio: 0.8
140 | })
141 | )
142 | }
143 |
144 | if (config.build.bundleAnalyzerReport) {
145 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
146 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
147 | }
148 |
149 | module.exports = webpackConfig
150 |
--------------------------------------------------------------------------------
/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | })
8 |
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.3.1
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 | // Paths
10 | assetsSubDirectory: 'static',
11 | assetsPublicPath: '/',
12 | proxyTable: {
13 | // 微信接口
14 | '/wx1': {
15 | target: 'https://wx.qq.com',
16 | secure: false,
17 | changeOrigin: true,
18 | headers: {
19 | Referer: 'https://wx.qq.com'
20 | },
21 | pathRewrite: {
22 | '^/wx1': '/'
23 | },
24 | onProxyRes: (proxyRes, req, res) => {
25 | let cookies = proxyRes.headers['set-cookie']
26 | let cookieRegex = /Secure/i
27 | //修改cookie secure
28 | if (cookies) {
29 | let newCookie = cookies.map((cookie) => {
30 | if (cookieRegex.test(cookie)) {
31 | return cookie.replace(cookieRegex, '')
32 | }
33 | return cookie
34 | })
35 | //修改cookie path
36 | delete proxyRes.headers['set-cookie']
37 | proxyRes.headers['set-cookie'] = newCookie
38 | }
39 | },
40 | // 重写cookie domian
41 | cookieDomainRewrite: {
42 | '*': 'localhost'
43 | }
44 | },
45 | '/wx2': {
46 | target: 'https://wx2.qq.com',
47 | secure: false,
48 | changeOrigin: true,
49 | headers: {
50 | Referer: 'https://wx2.qq.com'
51 | },
52 | pathRewrite: {
53 | '^/wx2': '/'
54 | },
55 | onProxyRes: function(proxyRes, req, res) {
56 | var cookies = proxyRes.headers['set-cookie']
57 | var cookieRegex = /Secure/i
58 | //修改cookie secure
59 | if (cookies) {
60 | var newCookie = cookies.map(function(cookie) {
61 | if (cookieRegex.test(cookie)) {
62 | return cookie.replace(cookieRegex, '')
63 | }
64 | return cookie
65 | })
66 | //修改cookie path
67 | delete proxyRes.headers['set-cookie']
68 | proxyRes.headers['set-cookie'] = newCookie
69 | }
70 | },
71 | // 重写cookie domian
72 | cookieDomainRewrite: {
73 | '*': 'localhost'
74 | }
75 | },
76 | '/login': {
77 | target: 'https://login.wx.qq.com',
78 | secure: false,
79 | changeOrigin: true,
80 | headers: {
81 | Referer: 'https://login.wx.qq.com'
82 | },
83 | pathRewrite: {
84 | '^/login': '/'
85 | }
86 | },
87 | '/check1': {
88 | target: 'https://webpush.wx.qq.com',
89 | secure: false,
90 | changeOrigin: true,
91 | headers: {
92 | Referer: 'https://webpush.wx.qq.com'
93 | },
94 | pathRewrite: {
95 | '^/check1': '/'
96 | }
97 | },
98 | '/check2': {
99 | target: 'https://webpush.wx2.qq.com',
100 | secure: false,
101 | changeOrigin: true,
102 | headers: {
103 | Referer: 'https://webpush.wx2.qq.com'
104 | },
105 | pathRewrite: {
106 | '^/check2': '/'
107 | }
108 | },
109 | '/upload1': {
110 | target: 'https://file.wx.qq.com',
111 | secure: false,
112 | changeOrigin: true,
113 | headers: {
114 | Referer: 'https://file.wx.qq.com'
115 | },
116 | pathRewrite: {
117 | '^/upload1': '/'
118 | },
119 | },
120 | '/upload2': {
121 | target: 'https://file.wx2.qq.com',
122 | secure: false,
123 | changeOrigin: true,
124 | headers: {
125 | Referer: 'https://file.wx2.qq.com'
126 | },
127 | pathRewrite: {
128 | '^/upload2': '/'
129 | }
130 | }
131 | },
132 |
133 | // Various Dev Server settings
134 | host: 'localhost', // can be overwritten by process.env.HOST localhost
135 | port: process.env.PORT || 8060, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
136 | autoOpenBrowser: true,
137 | errorOverlay: true,
138 | notifyOnErrors: true,
139 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
140 |
141 | // Use Eslint Loader?
142 | // If true, your code will be linted during bundling and
143 | // linting errors and warnings will be shown in the console.
144 | useEslint: true,
145 | // If true, eslint errors and warnings will also be shown in the error overlay
146 | // in the browser.
147 | showEslintErrorsInOverlay: false,
148 |
149 | /**
150 | * Source Maps
151 | */
152 |
153 | // https://webpack.js.org/configuration/devtool/#development
154 | devtool: 'cheap-module-eval-source-map',
155 |
156 | // If you have problems debugging vue-files in devtools,
157 | // set this to false - it *may* help
158 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
159 | cacheBusting: true,
160 |
161 | cssSourceMap: true
162 | },
163 |
164 | build: {
165 | // Template for index.html
166 | index: path.resolve(__dirname, '../dist/index.html'),
167 |
168 | // Paths
169 | assetsRoot: path.resolve(__dirname, '../dist'),
170 | assetsSubDirectory: 'static',
171 | assetsPublicPath: '/wechat/',
172 |
173 | /**
174 | * Source Maps
175 | */
176 |
177 | productionSourceMap: true,
178 | // https://webpack.js.org/configuration/devtool/#production
179 | devtool: '#source-map',
180 |
181 | // Gzip off by default as many popular static hosts such as
182 | // Surge or Netlify already gzip all static assets for you.
183 | // Before setting to `true`, make sure to:
184 | // npm install --save-dev compression-webpack-plugin
185 | productionGzip: false,
186 | productionGzipExtensions: ['js', 'css'],
187 |
188 | // Run the build command with an extra argument to
189 | // View the bundle analyzer report after build finishes:
190 | // `npm run build --report`
191 | // Set to `true` or `false` to always turn it on or off
192 | bundleAnalyzerReport: process.env.npm_config_report
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | }
5 |
--------------------------------------------------------------------------------
/config/test.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const devEnv = require('./dev.env')
4 |
5 | module.exports = merge(devEnv, {
6 | NODE_ENV: '"testing"'
7 | })
8 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | WECHAT
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wechat",
3 | "version": "1.0.0",
4 | "description": "A Vue template for wechat",
5 | "author": "YJ <1553937164@qq.com>",
6 | "private": true,
7 | "scripts": {
8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
9 | "start": "npm run dev",
10 | "unit": "jest --config test/unit/jest.conf.js --coverage",
11 | "e2e": "node test/e2e/runner.js",
12 | "test": "npm run unit && npm run e2e",
13 | "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
14 | "build": "node build/build.js",
15 | "neibuild": "nei build -k a157765ccb4a0601d44810f21c78052a",
16 | "nei-run": "nei server"
17 | },
18 | "dependencies": {
19 | "axios": "^0.18.0",
20 | "babel-polyfill": "^6.26.0",
21 | "element-ui": "^2.4.1",
22 | "vue": "^2.5.2",
23 | "vue-axios": "^2.0.2",
24 | "vue-i18n": "^7.6.0",
25 | "vue-lazyload": "^1.2.2",
26 | "vue-router": "^3.0.1",
27 | "vuetify": "^1.1.1",
28 | "vuex": "^3.0.1",
29 | "vuex-router-sync": "^5.0.0"
30 | },
31 | "devDependencies": {
32 | "autoprefixer": "^7.1.2",
33 | "babel-core": "^6.22.1",
34 | "babel-eslint": "^8.2.1",
35 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
36 | "babel-jest": "^21.0.2",
37 | "babel-loader": "^7.1.1",
38 | "babel-plugin-component": "^1.1.1",
39 | "babel-plugin-dynamic-import-node": "^1.2.0",
40 | "babel-plugin-syntax-jsx": "^6.18.0",
41 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
42 | "babel-plugin-transform-runtime": "^6.22.0",
43 | "babel-plugin-transform-vue-jsx": "^3.5.0",
44 | "babel-preset-env": "^1.3.2",
45 | "babel-preset-stage-2": "^6.22.0",
46 | "babel-register": "^6.22.0",
47 | "chalk": "^2.0.1",
48 | "chromedriver": "^2.27.2",
49 | "copy-webpack-plugin": "^4.0.1",
50 | "cross-spawn": "^5.0.1",
51 | "css-loader": "^0.28.0",
52 | "echarts": "^4.1.0",
53 | "eslint": "^4.15.0",
54 | "eslint-config-standard": "^10.2.1",
55 | "eslint-friendly-formatter": "^3.0.0",
56 | "eslint-loader": "^1.7.1",
57 | "eslint-plugin-import": "^2.7.0",
58 | "eslint-plugin-node": "^5.2.0",
59 | "eslint-plugin-promise": "^3.4.0",
60 | "eslint-plugin-standard": "^3.0.1",
61 | "eslint-plugin-vue": "^4.0.0",
62 | "esri-loader": "^2.3.0",
63 | "extract-text-webpack-plugin": "^3.0.0",
64 | "file-loader": "^1.1.4",
65 | "friendly-errors-webpack-plugin": "^1.6.1",
66 | "html-webpack-plugin": "^2.30.1",
67 | "jest": "^22.0.4",
68 | "jest-serializer-vue": "^0.3.0",
69 | "nightwatch": "^0.9.12",
70 | "node-notifier": "^5.1.2",
71 | "node-sass": "^4.9.0",
72 | "optimize-css-assets-webpack-plugin": "^3.2.0",
73 | "ora": "^1.2.0",
74 | "portfinder": "^1.0.13",
75 | "postcss-import": "^11.0.0",
76 | "postcss-loader": "^2.0.8",
77 | "postcss-url": "^7.2.1",
78 | "rimraf": "^2.6.0",
79 | "sass-loader": "^6.0.7",
80 | "selenium-server": "^3.0.1",
81 | "semver": "^5.3.0",
82 | "shelljs": "^0.7.6",
83 | "uglifyjs-webpack-plugin": "^1.1.1",
84 | "url-loader": "^0.5.8",
85 | "vue-jest": "^1.0.2",
86 | "vue-loader": "^13.3.0",
87 | "vue-particles": "^1.0.9",
88 | "vue-style-loader": "^3.0.1",
89 | "vue-template-compiler": "^2.5.2",
90 | "webpack": "^3.11.0",
91 | "webpack-bundle-analyzer": "^2.9.0",
92 | "webpack-dev-server": "^2.9.1",
93 | "webpack-merge": "^4.1.0"
94 | },
95 | "engines": {
96 | "node": ">= 6.0.0",
97 | "npm": ">= 3.0.0"
98 | },
99 | "browserslist": [
100 | "> 1%",
101 | "last 5 versions",
102 | "not ie <= 8"
103 | ]
104 | }
105 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
15 |
26 |
--------------------------------------------------------------------------------
/src/components/Aside.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
98 |
160 |
--------------------------------------------------------------------------------
/src/components/AsideContent.vue:
--------------------------------------------------------------------------------
1 |
2 | wwww
3 |
4 |
16 |
18 |
--------------------------------------------------------------------------------
/src/components/NotFound.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 错误页面
5 |
6 |
7 |
8 |
9 |
12 |
13 |
15 |
--------------------------------------------------------------------------------
/src/components/SectionContent.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
28 |
30 |
--------------------------------------------------------------------------------
/src/components/header.vue:
--------------------------------------------------------------------------------
1 |
2 |
88 |
89 |
90 |
160 |
168 |
--------------------------------------------------------------------------------
/src/components/setting.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | account_circle
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
24 |
25 |
26 |
27 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | 账号密码成功,{{3 - timeOut}}秒后将重新登陆
43 |
44 |
45 |
46 | 关闭
47 | 更新
48 |
49 |
50 |
51 |
52 |
53 |
114 |
115 |
133 |
--------------------------------------------------------------------------------
/src/config/env.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 配置编译环境和线上环境之间的切换
3 | * baseUrl: 域名地址
4 | * routerMode: 路由模式
5 | * imgBaseUrl: 图片所在域名地址
6 | */
7 |
8 | let baseUrl = ''
9 | let routerMode = 'hash'
10 | let imgBaseUrl
11 |
12 | if (process.env.NODE_ENV === 'development') {
13 | imgBaseUrl = ''
14 | } else if (process.env.NODE_ENV === 'production') {
15 | baseUrl = '/vue-pc'
16 | imgBaseUrl = '/vue-pc'
17 | }
18 |
19 | export {
20 | baseUrl,
21 | routerMode,
22 | imgBaseUrl
23 | }
24 |
--------------------------------------------------------------------------------
/src/directives/index.js:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/filters/index.js:
--------------------------------------------------------------------------------
1 | // 字符串转化为数值
2 | export const toNumber = value => {
3 | if (value) return parseInt(value)
4 | return ''
5 | }
6 |
7 | export const setRoleType = value => {
8 | if (value) {
9 | switch (value) {
10 | case '1':
11 | return '超级管理员'
12 | case '2':
13 | return '采集员'
14 | case '3':
15 | return '区域管理员'
16 | case '4':
17 | return '用户'
18 | }
19 | } else {
20 | return ''
21 | }
22 | }
23 | export const setStar = (value, arg1, arg2) => {
24 | var result
25 | var addOne = true
26 | if (parseFloat(arg2) === parseInt(arg2)) {
27 | addOne = true
28 | } else {
29 | addOne = false
30 | }
31 | if (arg1 < arg2) {
32 | result = 'star'
33 | } else if (arg1 === Math.ceil(arg2)) {
34 | result = addOne ? 'star' : 'star_half'
35 | } else {
36 | result = 'star_border'
37 | }
38 | return result
39 | }
40 |
--------------------------------------------------------------------------------
/src/lang/en.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | buttom: {
3 | cancel: 'cancel',
4 | determine: 'ok',
5 | login: 'login',
6 | signOut: 'signOut',
7 | registered: 'registered',
8 | search: 'search',
9 | submit: 'submit',
10 | save: 'save',
11 | rememberPW: 'Remember password'
12 | },
13 | optionMessage: {
14 | systemName: 'Back office management system',
15 | admin: 'ADMIN',
16 | pushButton: 'Accept push',
17 | hints: 'Switch skin',
18 | skin1: 'Dark Forest',
19 | skin2: 'Ivory',
20 | lang: 'Lang',
21 | zh: 'SChinese',
22 | zhCHT: 'TChinese',
23 | en: 'English'
24 | },
25 | message: {
26 | name: 'name',
27 | sex: 'sex',
28 | address: 'address',
29 | career: 'Career',
30 | date: 'date',
31 | accout: 'accout',
32 | password: 'passWord'
33 | },
34 | routers: [
35 | {path: 'user', router: true, title: 'User Management', icon: 'folder_shared', color: 'white', id: '1000'},
36 | {path: 'role', router: true, title: 'role management', icon: 'security', color: 'white', id: '2000'}
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/src/lang/zhCHS.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | buttom: {
3 | cancel: '取消',
4 | determine: '确定',
5 | login: '登录',
6 | signOut: '退出登录',
7 | registered: '注册',
8 | search: '查询',
9 | submit: '提交',
10 | save: '保存',
11 | rememberPW: '记住密码'
12 | },
13 | optionMessage: {
14 | systemName: '蜂巢选址平台',
15 | admin: '管理员',
16 | pushButton: '接受推送',
17 | hints: '切换皮肤',
18 | skin1: '黑暗森林',
19 | skin2: '象牙白',
20 | lang: '语言',
21 | zh: '简体中文',
22 | zhCHT: '繁体中文',
23 | en: '英文'
24 | },
25 | message: {
26 | name: '名称',
27 | sex: '性别',
28 | address: '地址',
29 | career: '职业',
30 | date: '日期',
31 | accout: '账号',
32 | password: '密码'
33 | },
34 | routers: [
35 | {path: 'user', router: true, title: '用户管理', icon: 'folder_shared', color: 'white', id: '1000'},
36 | {path: 'wechat', router: true, title: '微信聊天', icon: 'android', color: 'white', id: '2000'}
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import App from './App'
2 | import axios from './service/'
3 | import router from './router'
4 | import store from './store/'
5 | import { sync } from 'vuex-router-sync'
6 | import Vue from 'vue'
7 | import Vuetify from 'vuetify'
8 | import VueLazyLoad from 'vue-lazyload'
9 | import VueI18n from 'vue-i18n'
10 | import mixin from './mixin'
11 | import * as directives from './directives'
12 | import * as filters from './filters'
13 | import * as methods from './utils/utils'
14 | import 'vuetify/dist/vuetify.min.css'
15 | import './plugins/toast/toast.css'
16 | import { Cascader, DatePicker, MessageBox, Loading, Upload } from 'element-ui'
17 | import 'babel-polyfill'
18 | /* 平台国际语言静态字典 */
19 | import LangEn from './lang/en'
20 | import LangZhCHS from './lang/zhCHS'
21 |
22 | Vue.config.productionTip = false
23 | Vue.prototype.$confirm = MessageBox.confirm
24 | Vue.prototype.$loading = Loading.service
25 |
26 | // 注册插件
27 | Vue.use(Vuetify)
28 | Vue.use(VueLazyLoad, {
29 | preLoad: 1.3,
30 | error: 'static/images/404.png',
31 | loading: 'static/images/loading-spin.svg',
32 | attempt: 1
33 | })
34 | Vue.use(VueI18n)
35 | Vue.use(Cascader)
36 | Vue.use(DatePicker)
37 | Vue.use(Upload)
38 |
39 | // 全局混入
40 | Vue.mixin(mixin)
41 |
42 | // 设置语言项
43 | const i18n = new VueI18n({
44 | locale: 'zh',
45 | messages: {
46 | 'en': LangEn,
47 | 'zh': LangZhCHS
48 | }
49 | })
50 |
51 | // 注册指令&&过滤器&&公有方法
52 | Object.keys(directives).forEach(k => Vue.directive(k, directives[k]))
53 | Object.keys(filters).forEach(k => Vue.filter(k, filters[k]))
54 | Object.keys(methods).forEach(k => { Vue.prototype[k] = methods[k] })
55 |
56 | // 动态路由
57 | sync(store, router)
58 |
59 | /* eslint-disable no-new */
60 | new Vue({
61 | el: '#app',
62 | router,
63 | axios,
64 | store,
65 | i18n,
66 | components: { App },
67 | template: ''
68 | })
69 |
--------------------------------------------------------------------------------
/src/mixin/index.js:
--------------------------------------------------------------------------------
1 | // 全局混入模式
2 | export default {
3 | methods: {
4 | // 判断元素是否具有权限
5 | hasPermission (id) {
6 | if (!id) return true
7 | let {permissionMap} = this.$store.state.common
8 | return permissionMap.find(el => { return el === id })
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/plugins/toast/toast.css:
--------------------------------------------------------------------------------
1 | .vue-toast {
2 | position: fixed;
3 | bottom: 100px;
4 | left: 50%;
5 | box-sizing: border-box;
6 | max-width: 80%;
7 | height: 40px;
8 | line-height: 20px;
9 | padding: 10px 20px;
10 | transform: translateX(-50%);
11 | -webkit-transform: translateX(-50%);
12 | text-align: center;
13 | z-index: 9999;
14 | font-size: 14px;
15 | color: #fff;
16 | border-radius: 5px;
17 | background: rgba(0, 0, 0, 0.7);
18 | animation: show-toast .5s;
19 | -webkit-animation: show-toast .5s;
20 | overflow: hidden;
21 | text-overflow: ellipsis;
22 | white-space: nowrap;
23 | }
--------------------------------------------------------------------------------
/src/plugins/toast/toast.js:
--------------------------------------------------------------------------------
1 | var Toast = {}
2 | Toast.install = function (Vue, options) {
3 | let opt = {
4 | defaultType: 'bottom',
5 | duration: '2500'
6 | }
7 | for (let property in options) {
8 | opt[property] = options[property]
9 | }
10 | Vue.prototype.$toast = (tips, type) => {
11 | if (type) opt.defaultType = type
12 | if (document.getElementsByClassName('vue-toast').length) return
13 | // 创建构造器,定义好提示信息的模板
14 | let ToastTpl = Vue.extend({
15 | template: `${tips}
`
16 | })
17 | // 创建实例,挂载到文档以后的地方
18 | let tpl = new ToastTpl().$mount().$el
19 | // 把创建的实例添加到body中
20 | document.body.appendChild(tpl)
21 | setTimeout(function () {
22 | document.body.removeChild(tpl)
23 | }, opt.duration)
24 | }
25 | // 显示不同位置
26 | ['bottom', 'center', 'top'].forEach(type => {
27 | Vue.prototype.$toast[type] = (tips) => {
28 | return Vue.prototype.$toast(tips, type)
29 | }
30 | })
31 | }
32 | module.exports = Toast
33 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import {routerMode} from '@/config/env'
4 |
5 | Vue.use(Router)
6 |
7 | const NotFound = r => require.ensure([], () => (require('@/components/NotFound')), 'NotFound')
8 | const login = r => require.ensure([], () => (require('@/view/login/login')), 'login')
9 | const management = r => require.ensure([], () => (require('@/view/management/')), 'management')
10 | const wechat = r => require.ensure([], () => (require('@/view/wechat/')), 'wechat')
11 |
12 | let routes = [{
13 | path: '/',
14 | component: management,
15 | redirect: '/wechat',
16 | children: [
17 | {
18 | path: '/wechat',
19 | component: wechat,
20 | meta: {
21 | id: '2000',
22 | permission: 'wechat_view'
23 | }
24 | }
25 | ]
26 | }, {
27 | path: '/login',
28 | component: login
29 | }]
30 |
31 | /**
32 | * [path 404跳转]
33 | * @type {String}
34 | */
35 | routes.push({
36 | path: '*',
37 | component: NotFound
38 | })
39 |
40 | const router = new Router({
41 | routes,
42 | mode: routerMode,
43 | strict: process.env.NODE_ENV !== 'production'
44 | })
45 |
46 | router.beforeEach((to, from, next) => {
47 | next()
48 | })
49 |
50 | export default router
51 |
--------------------------------------------------------------------------------
/src/service/index.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import router from '@/router/'
3 |
4 | // axios 配置
5 | axios.defaults.withCredentials = true
6 | /**
7 | * http request 拦截器
8 | * token 判断是否存在token,如果存在的话,则http header加上token
9 | */
10 | axios.interceptors.request.use(config => {
11 | return config
12 | }, err => {
13 | return Promise.reject(err)
14 | })
15 |
16 | axios.interceptors.response.use(res => {
17 | if (res.status === 200) {
18 | if (res.data.state) {
19 | switch (res.data.state.code) {
20 | case 200:
21 | return res.data.data
22 | // 无权限
23 | case 401:
24 | router.push('/login')
25 | return Promise.reject(res.data.state.msg)
26 | // session过期或者未登陆
27 | case 403:
28 | router.push('/login')
29 | return Promise.reject(res.data.state.msg)
30 | }
31 | }
32 | return res.data
33 | }
34 | return Promise.reject(res.data)
35 | }, err => {
36 | return Promise.reject(err)
37 | })
38 |
39 | export default axios
40 |
--------------------------------------------------------------------------------
/src/service/modules/common.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | export const getProvince = params => {
4 | return axios.post('/system/provAll', params)
5 | }
6 |
7 | export const getCity = params => {
8 | return axios.post('/system/cityAllByProv', params)
9 | }
10 | export const getDistrict = params => {
11 | return axios.post('/system/distAllByCity', params)
12 | }
13 | export const getAllIndustry = params => {
14 | return axios.post('/system/industryAll')
15 | }
16 | export const getAllRole = params => {
17 | return axios.post('/system/roleList', params)
18 | }
19 | export const getRoleModules = params => {
20 | return axios.post('/system/modeleListByRoseId', params)
21 | }
22 |
--------------------------------------------------------------------------------
/src/service/modules/userInfo.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | export const login = param => {
4 | return axios.post('/login/login', param)
5 | }
6 | export const logout = param => {
7 | return axios.post('/login/logout', param)
8 | }
9 | export const getUserList = param => {
10 | return axios.post('/user/list', param)
11 | }
12 | export const updateUserData = param => {
13 | return axios.post('/user/update', param)
14 | }
15 |
--------------------------------------------------------------------------------
/src/service/modules/wx.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import store from '@/store'
3 | let type = null
4 | // 获取微信唯一uid
5 | export const getUUID = params => {
6 | return axios.get('/login/jslogin', {params: params})
7 | }
8 | // 显示二维码
9 | export const getQRcode = params => {
10 | return axios.get(`/login/qrcode/${params}`)
11 | }
12 | // 等待扫码登陆
13 | export const waitScanCode = params => {
14 | return axios.get('/login/cgi-bin/mmwebwx-bin/login', {params: params})
15 | }
16 | // 版本1微信用户获取登录参数
17 | export const getLoginMessage = params => {
18 | type = store.state.wx.redirectUriType
19 | return axios.get(`/cgi-bin/mmwebwx-bin/webwxnewloginpage?${params}`, {baseURL: type ? '/wx2' : '/wx1'})
20 | }
21 | // 登陆初始化
22 | export const getWxUserInfo = (urlContrnt, params) => {
23 | type = store.state.wx.redirectUriType
24 | return axios.post(`/cgi-bin/mmwebwx-bin/webwxinit?r=${urlContrnt.r}&lang=${urlContrnt.lang}&pass_ticket=${urlContrnt.pass_ticket}`, params, {baseURL: type ? '/wx2' : '/wx1'})
25 | }
26 | // 获取微信图片
27 | export const getUserHeadImg = params => {
28 | return axios.get(`${params}`, {baseURL: type ? '/wx2' : '/wx1'})
29 | }
30 | // 开启微信状态通知
31 | export const setWxStatusNotify = (urlContrnt, params) => {
32 | return axios.post(`/cgi-bin/mmwebwx-bin/webwxstatusnotify?lang=${urlContrnt.lang}&pass_ticket=${urlContrnt.pass_ticket}`, params, {baseURL: type ? '/wx2' : '/wx1'})
33 | }
34 | // 获取微信联系人
35 | export const getWxContact = params => {
36 | return axios.get('/cgi-bin/mmwebwx-bin/webwxgetcontact', {params: params, baseURL: type ? '/wx2' : '/wx1'})
37 | }
38 | // 发送消息
39 | export const sendWxMsg = (urlContrnt, params) => {
40 | return axios.post(`/cgi-bin/mmwebwx-bin/webwxsendmsg?lang=${urlContrnt.lang}&pass_ticket=${urlContrnt.pass_ticket}`, params, {baseURL: type ? '/wx2' : '/wx1'})
41 | }
42 | // 心态检测
43 | export const checkWebSync = params => {
44 | return axios.get('/cgi-bin/mmwebwx-bin/synccheck', {params: params, baseURL: type ? '/check2' : '/check1'})
45 | }
46 | // 获取新消息
47 | export const getWebWXSync = (urlContrnt, params) => {
48 | return axios.post(`/cgi-bin/mmwebwx-bin/webwxsync?lang=${urlContrnt.lang}&pass_ticket=${urlContrnt.pass_ticket}&skey=${urlContrnt.skey}&sid=${urlContrnt.sid}`, params, {baseURL: type ? '/wx2' : '/wx1'})
49 | }
50 | // 已读标记
51 | export const setWxMsgStatus = params => {
52 | return axios.post(`/cgi-bin/mmwebwx-bin/webwxstatusnotify`, params, {baseURL: type ? '/wx2' : '/wx1'})
53 | }
54 | // 获取聊天会话列表
55 | export const getWxBatchGetContact = (urlContrnt, params) => {
56 | return axios.post(`/cgi-bin/mmwebwx-bin/webwxbatchgetcontact?type=ex&r=${urlContrnt.r}`, params, {baseURL: type ? '/wx2' : '/wx1'})
57 | }
58 | // 上传附件
59 | export const uploadMedia = params => {
60 | return axios.post('/cgi-bin/mmwebwx-bin/webwxuploadmedia?f=json', params, {baseURL: type ? '/upload2' : '/upload1'})
61 | }
62 | // 发送图片
63 | export const sendMsgImg = params => {
64 | return axios.post('/cgi-bin/mmwebwx-bin/webwxsendmsgimg?fun=async&f=json', params, {baseURL: type ? '/wx2' : '/wx1'})
65 | }
66 | // 语音接口
67 | export const getWxVoice = params => {
68 | return axios.get(`/cgi-bin/mmwebwx-bin/webwxgetvoice?msgid=${params.msgid}&skey=${params.skey}`, {baseURL: type ? '/wx2' : '/wx1'})
69 | }
70 | // 微信登出
71 | export const wxLogout = (urlContrnt, params) => {
72 | return axios.post(`/cgi-bin/mmwebwx-bin/webwxlogout?redirect=${urlContrnt.redirect}&type=${urlContrnt.type}&skey=${urlContrnt.skey}`, params, {baseURL: type ? '/wx2' : '/wx1'})
73 | }
74 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import main from './modules/main'
4 | import common from './modules/common'
5 | import wx from './modules/wx'
6 | import userInfo from './modules/userInfo'
7 |
8 | Vue.use(Vuex)
9 |
10 | export default new Vuex.Store({
11 | modules: {
12 | main,
13 | userInfo,
14 | common,
15 | wx
16 | }
17 | })
18 |
--------------------------------------------------------------------------------
/src/store/modules/common.js:
--------------------------------------------------------------------------------
1 | import {getRoleModules} from '@/service/modules/common'
2 | import * as types from '../mutation-types'
3 | const state = {
4 | permissionMap: []
5 | }
6 |
7 | const getters = {
8 | permissionMap: state => state.permissionMap
9 | }
10 |
11 | const actions = {
12 | async getRoleModules ({commit}, params) {
13 | let data = await getRoleModules(params)
14 | commit(types.GET_ROLEMODULES, data)
15 | }
16 | }
17 |
18 | const mutations = {
19 | [types.GET_ROLEMODULES] (state, data) {
20 | state.permissionMap = data.map(item => {
21 | return item.moduleId
22 | })
23 | }
24 | }
25 |
26 | export default {
27 | state,
28 | getters,
29 | actions,
30 | mutations
31 | }
32 |
--------------------------------------------------------------------------------
/src/store/modules/main.js:
--------------------------------------------------------------------------------
1 | import * as types from '../mutation-types'
2 | const state = {
3 | // 框架配置
4 | controlsOption: {
5 | settingShow: true, // 显示侧边菜单
6 | drawer: true, // 侧边菜单显示
7 | hints: false // 界面样式
8 | }
9 | }
10 |
11 | const getters = {
12 | controlsOption: state => state.controlsOption
13 | }
14 |
15 | const actions = {
16 | }
17 |
18 | const mutations = {
19 | [types.SET_CONTROLSOPTION] (state, data) {
20 | Object.assign(state.controlsOption, data)
21 | }
22 | }
23 |
24 | export default {
25 | state,
26 | getters,
27 | actions,
28 | mutations
29 | }
30 |
--------------------------------------------------------------------------------
/src/store/modules/userInfo.js:
--------------------------------------------------------------------------------
1 | import {login, getUserList} from '@/service/modules/userInfo'
2 | import * as types from '../mutation-types'
3 | const state = {
4 | userList: {
5 | data: [],
6 | size: 10,
7 | currentPage: 1
8 | }
9 | }
10 |
11 | const getters = {
12 | userList: state => state.userList
13 | }
14 |
15 | const actions = {
16 | async loginTo ({commit}, params) {
17 | let data = await login(params)
18 | commit(types.GET_CURRENTDATA, data)
19 | return data
20 | },
21 | async getUserList ({commit}, params) {
22 | let data = await getUserList(params)
23 | commit(types.GET_USERLIST, data)
24 | return data
25 | }
26 | }
27 |
28 | const mutations = {
29 | [types.GET_CURRENTDATA] (state, data) {
30 | },
31 | [types.GET_USERLIST] (state, data) {
32 | state.userList = data
33 | }
34 | }
35 |
36 | export default {
37 | state,
38 | getters,
39 | actions,
40 | mutations
41 | }
42 |
--------------------------------------------------------------------------------
/src/store/modules/wx.js:
--------------------------------------------------------------------------------
1 | import {getWxContact, setWxMsgStatus} from '@/service/modules/wx'
2 | import * as types from '../mutation-types'
3 | import {getLocalStorage, setLocalStorage} from '@/utils/utils'
4 | const state = {
5 | userInfo: JSON.parse(getLocalStorage('userInfo')),
6 | selectSideMenu: 1, // 侧边功能按钮
7 | isWXLogin: JSON.parse(getLocalStorage('isWXLogin')), // 用户微信登陆状态
8 | hasCheckLoading: 0, // 心跳是否正常
9 | loginWxUserInfo: JSON.parse(getLocalStorage('loginWxuserInfo')), // 微信用户信息
10 | wxUserTab: [], // 用户标签
11 | chatLogShow: false,
12 | redirectUriType: JSON.parse(getLocalStorage('redirectUriType')), // 重定向地址
13 | synckey: {},
14 | chatRecordList: [], // 聊天记录
15 | userMemberList: [], // 微信用户通讯录列表
16 | addressBookIndex: {}, // 微信用户通讯录索引
17 | chatUserList: [], // 侧边栏聊天客户
18 | activeUser: {
19 | HeadImgUrl: '/static/images/logo.png'
20 | }, // 高亮用户
21 | activeIndex: 0, // 聊天高亮节点
22 | activeMessageList: [], // 当前聊天用户聊天记录
23 | userChatLog: {}, // 用户聊天记录列表
24 | startCheckWebSync: 0, // 启动微信心跳
25 | hasWxUserList: {}
26 | }
27 |
28 | const getters = {
29 | userInfo: state => state.userInfo,
30 | selectSideMenu: state => state.selectSideMenu,
31 | hasWxUserList: state => state.hasWxUserList,
32 | isWXLogin: state => state.isWXLogin,
33 | hasCheckLoading: state => state.hasCheckLoading,
34 | loginWxUserInfo: state => state.loginWxUserInfo,
35 | wxUserTab: state => state.wxUserTab,
36 | chatLogShow: state => state.chatLogShow,
37 | redirectUriType: state => state.redirectUriType,
38 | synckey: state => state.synckey,
39 | chatRecordList: state => state.chatRecordList,
40 | userMemberList: state => state.userMemberList,
41 | addressBookIndex: state => state.addressBookIndex,
42 | chatUserList: state => state.chatUserList,
43 | activeUser: state => state.activeUser,
44 | activeIndex: state => state.activeIndex,
45 | activeMessageList: state => state.activeMessageList,
46 | userChatLog: state => state.userChatLog,
47 | startCheckWebSync: state => state.startCheckWebSync
48 | }
49 |
50 | const actions = {
51 | // 获取微信通讯录
52 | async getWxContact ({commit}, param) {
53 | let LoginInit = JSON.parse(getLocalStorage('loginInit'))
54 | let params = {
55 | lang: 'zh_CN',
56 | pass_ticket: LoginInit.passTicket,
57 | r: new Date().getTime(),
58 | seq: 0,
59 | skey: LoginInit.skey
60 | }
61 | let res = await getWxContact(params)
62 | commit(types.SET_USERMEMBERLIST, res.MemberList)
63 | },
64 | // 标记已读
65 | async setWxMsgStatus ({commit}, param) {
66 | let LoginInit = JSON.parse(getLocalStorage('loginInit'))
67 | let params = {
68 | BaseRequest: {
69 | DeviceID: 'e' + ('' + Math.random().toFixed(15)).substring(2, 17),
70 | Sid: LoginInit.wxsid,
71 | Skey: LoginInit.skey,
72 | Uin: LoginInit.wxuin
73 | },
74 | Code: 1,
75 | FromUserName: state.loginWxUserInfo.User.UserName,
76 | ToUserName: state.activeUser.UserName,
77 | ClientMsgId: new Date().getTime()
78 | }
79 | await setWxMsgStatus(params)
80 | }
81 | }
82 |
83 | const mutations = {
84 | [types.SET_SELECTSIDEMENU] (state, data) {
85 | state.selectSideMenu = data
86 | },
87 | [types.SET_USERCHATLOG] (state, data) {
88 | state.userChatLog = data
89 | },
90 | [types.SET_UPDATEHASWXUSERLIST] (state, data) {
91 | state.userMemberList.forEach(el => {
92 | if (state.hasWxUserList[el.NickName]) {
93 | el.isSync = 1
94 | } else {
95 | el.isSync = 0
96 | }
97 | })
98 | },
99 | [types.GET_HASWXUSERLIST] (state, data) {
100 | data.forEach(e => {
101 | state.hasWxUserList[e.nickName] = e
102 | })
103 | },
104 | [types.GET_WXUSERTAB] (state, data) {
105 | state.wxUserTab = data
106 | },
107 | [types.SET_WXLOGINSTATUS] (state, data) {
108 | state.isWXLogin = data
109 | setLocalStorage('isWXLogin', data)
110 | },
111 | [types.SET_HASCHECKLOADING] (state, data) {
112 | state.hasCheckLoading = data
113 | },
114 | [types.SET_CHATLOGSHOW] (state, data) {
115 | state.chatLogShow = data
116 | },
117 | [types.SET_REDIRECTURITYPE] (state, data) {
118 | setLocalStorage('redirectUriType', data)
119 | state.redirectUriType = data
120 | },
121 | [types.SET_SYNCKEY] (state, data) {
122 | state.synckey = data
123 | },
124 | [types.GET_CHATRECORDS] (state, data) {
125 | if (data.current > 1) {
126 | state.chatRecordList.records.push(...data.records)
127 | state.chatRecordList.current = data.current
128 | } else {
129 | state.chatRecordList = data
130 | }
131 | },
132 | [types.SET_USERMEMBERLIST] (state, data) {
133 | let userMemberList = []
134 | data.forEach((el, index) => {
135 | if (el.VerifyFlag === 0) {
136 | if (el.StarFriend) {
137 | userMemberList.unshift(el)
138 | } else {
139 | userMemberList.push(el)
140 | }
141 | }
142 | })
143 | state.userMemberList = userMemberList
144 | userMemberList.forEach((e, index) => {
145 | state.addressBookIndex[e.NickName] = index
146 | })
147 | setLocalStorage('wxContact', userMemberList)
148 | },
149 | [types.SET_CHATUSERLIST] (state, data) {
150 | state.chatUserList = data
151 | },
152 | [types.SET_ACTIVEUSER] (state, data) {
153 | state.activeUser = data
154 | },
155 | [types.SET_ACTIVEINDEX] (state, data) {
156 | state.activeIndex = data
157 | },
158 | [types.SET_ACTIVEINDEX] (state, data) {
159 | state.activeIndex = data
160 | },
161 | [types.SET_ACTIVEMESSAGELIST] (state, data) {
162 | state.activeMessageList = data
163 | },
164 | [types.SET_LOGINWXUSERINFO] (state, data) {
165 | state.loginWxUserInfo = data
166 | },
167 | [types.START_CHECKWEBSYNC] (state, data) {
168 | state.startCheckWebSync = data
169 | }
170 | }
171 |
172 | export default {
173 | state,
174 | getters,
175 | actions,
176 | mutations
177 | }
178 |
--------------------------------------------------------------------------------
/src/store/mutation-types.js:
--------------------------------------------------------------------------------
1 | export const GET_CURRENTDATA = 'GET_CURRENTDATA'
2 | export const SET_CONTROLSOPTION = 'SET_CONTROLSOPTION'
3 | export const SET_WXLOGINSTATUS = 'SET_WXLOGINSTATUS'
4 | /* 用户管理 */
5 | export const GET_USERLIST = 'GET_USERLIST'
6 |
7 | // 登陆用户权限
8 | export const GET_ROLEMODULES = 'GET_ROLEMODULES'
9 |
10 | // 聊天会话
11 | export const SET_SELECTSIDEMENU = 'SET_SELECTSIDEMENU'
12 | export const GET_HASWXUSERLIST = 'GET_HASWXUSERLIST'
13 | export const GET_WXUSERTAB = 'GET_WXUSERTAB'
14 | export const SET_CHATLOGSHOW = 'SET_CHATLOGSHOW'
15 | export const SET_HASCHECKLOADING = 'SET_HASCHECKLOADING'
16 | export const SET_LOGINWXUSERINFO = 'SET_LOGINWXUSERINFO'
17 | export const SET_REDIRECTURITYPE = 'SET_REDIRECTURITYPE'
18 | export const SET_SYNCKEY = 'SET_SYNCKEY'
19 | export const GET_CHATRECORDS = 'GET_CHATRECORDS'
20 | export const SET_USERMEMBERLIST = 'SET_USERMEMBERLIST'
21 | export const SET_CHATUSERLIST = 'SET_CHATUSERLIST'
22 | export const SET_ACTIVEUSER = 'SET_ACTIVEUSER'
23 | export const SET_ACTIVEINDEX = 'SET_ACTIVEINDEX'
24 | export const SET_ACTIVEMESSAGELIST = 'SET_ACTIVEMESSAGELIST'
25 | export const SET_USERCHATLOG = 'SET_USERCHATLOG'
26 | export const START_CHECKWEBSYNC = 'START_CHECKWEBSYNC'
27 | export const SET_UPDATEHASWXUSERLIST = 'SET_UPDATEHASWXUSERLIST'
28 |
29 | // 权限列表
30 | export const GET_ALLMENULIST = 'GET_ALLMENULIST'
31 |
--------------------------------------------------------------------------------
/src/style/1px.scss:
--------------------------------------------------------------------------------
1 | @import "./mixin/setOnepx.scss";
2 | .onepx,
3 | .onepx-t,
4 | .onepx-b,
5 | .onepx-tb,
6 | .onepx-l,
7 | .onepx-r {
8 | position: relative;
9 | }
10 |
11 | .onepx {
12 | &:before {
13 | @include setLine(#c7c7c7);
14 | }
15 | }
16 |
17 | .onepx-t {
18 | &:before {
19 | @include setTopLine(#c7c7c7);
20 | }
21 | }
22 |
23 | .onepx-b {
24 | &:after {
25 | @include setBottomLine(#c7c7c7);
26 | }
27 | }
28 |
29 | .onepx-tb {
30 | &:before {
31 | @include setBottomLine(#c7c7c7);
32 | }
33 | &:after {
34 | @include setBottomLine(#c7c7c7);
35 | }
36 | }
37 |
38 | .onepx-l {
39 | &:before {
40 | @include setLeftLine(#c7c7c7);
41 | }
42 | }
43 |
44 | .onepx-r {
45 | &:after {
46 | @include setRightLine(#c7c7c7);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/style/common.scss:
--------------------------------------------------------------------------------
1 | @import './content.scss'; // 公共样式
2 | @import './1px.scss'; // 解决1px样式问题
3 | @import './reset.scss'; // 重置样式
4 |
--------------------------------------------------------------------------------
/src/style/content.scss:
--------------------------------------------------------------------------------
1 | // .toolbar__content {
2 | // height: 48px !important;
3 | // }
4 | // vuetify样式修改
5 | .application.theme--light {
6 | background: none !important;
7 | }
8 | .v-navigation-drawer {
9 | background-color: rgba(220, 220, 220, 0)!important;
10 | }
11 | .v-navigation-drawer .v-list {
12 | border-radius: 3px;
13 | background: rgba(48,48,48,.26) !important;
14 | box-shadow: 1px 1px 0px rgba(3, 3, 3, 0.2)
15 | }
16 | .v-navigation-drawer .v-list__tile__title {
17 | color: #fff;
18 | }
19 | .v-navigation-drawer .v-list__tile--active {
20 | color: #fff !important;
21 | border-right: 3px #008eff solid;
22 | background: none 0px 0px repeat scroll rgba(0, 0, 0, 0.3);
23 | }
24 | .v-navigation-drawer>.v-list .v-list__tile--active .v-list__tile__title {
25 | color: #2196F3 !important;
26 | font-weight: bold;
27 | }
28 | .v-content__wrap {
29 | background: #f0f0f0;
30 | }
31 | .v-label, .v-input {
32 | font-size: 14px !important;
33 | }
34 | .v-input__slot {
35 | min-height: 36px !important;
36 | margin: 6px 0 5px 0;
37 | }
38 | // .v-text-field--solo .v-text-field__slot input {
39 | // color: rgba(255, 255, 255, 0.8)!important;
40 | // }
41 | // .v-text-field--solo .v-input__slot {
42 | // background: rgba(255, 255, 255, 0) !important;
43 | // border: 1px #b0b0b1 solid;
44 | // }
45 | // .v-text-field--solo .v-input__slot .v-label {
46 | // color: rgba(255, 255, 255, 0.8);
47 | // }
48 | // .v-text-field--solo .v-input__slot .v-select__selections {
49 | // color: rgba(255, 255, 255, 0.8);
50 | // }
51 | // .v-list__tile {
52 | // font-size: 14px;
53 | // }
54 | // .theme--light .v-table {
55 | // background-color: rgba(255, 255, 255, 0.12);
56 | // color: rgba(255, 255, 255, 0.87);
57 | // }
58 | // .theme--light .v-table thead th {
59 | // color: rgb(255, 255, 255);
60 | // font-weight: bold;
61 | // background-color: rgba(255, 255, 255, 0.3);
62 | // }
63 | // .theme--light .v-datatable .v-datatable__actions {
64 | // background-color: rgba(255, 255, 255, 0);
65 | // color: rgba(255, 255, 255, 0.98);
66 | // border-top: 1px solid rgba(0, 0, 0, 0.2);
67 | // }
68 | // .v-datatable__actions .theme--light .v-btn.v-btn--disabled {
69 | // color: rgba(255, 255, 255, 0.18)!important;
70 | // }
71 | // .theme--light .v-table tbody tr:hover:not(.datatable__expand-row) {
72 | // background: rgba(36, 154, 247, 0.25);
73 | // }
74 | // 隐藏地图底部标识字段
75 | .esri-ui .esri-attribution {
76 | display: none;
77 | }
78 | .esriControlsBR, .esriSimpleSliderTL{
79 | display: none;
80 | }
81 | .esriBasemapGallery {
82 | position: fixed;
83 | left: 0;
84 | bottom: 0;
85 | width: 100%;
86 | z-index: 5;
87 | padding: 0px 10px 10px 50px;
88 | box-shadow: 0px -2px 5px rgba(0, 0, 0, 0.2);
89 | background: rgba(70, 70, 70, 0.32);
90 | border-radius: 5px;
91 | }
92 | // 弹窗样式
93 | .esriPopupWrapper {
94 | .title {
95 | font-size: 15px!important;
96 | padding: 5px;
97 | line-height: 1.3!important;
98 | }
99 | .titlePane {
100 | background-color: #0288d1!important;
101 | }
102 | .pointer.top {
103 | background: #0288d1!important;
104 | }
105 | .content {
106 | display: block;
107 | }
108 | }
109 | .showtext text {
110 | pointer-events: none;
111 | display: block;
112 | }
113 | .hidetext text {
114 | pointer-events: none;
115 | display: none;
116 | }
117 | // .menuable__content__active {
118 | // z-index: 20!important;
119 | // }
120 | /* 设置chrome滚动条的样式 */
121 | ::-webkit-scrollbar {
122 | width: 8px;
123 | height: 8px;
124 | }
125 | /* 滚动槽 */
126 | ::-webkit-scrollbar-track {
127 | -webkit-box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.1);
128 | border-radius: 10px;
129 | }
130 | /* 滚动条滑块 */
131 | ::-webkit-scrollbar-thumb {
132 | border-radius: 10px;
133 | background: rgba(138, 138, 138, 0.3);
134 | -webkit-box-shadow: inset 0 0 2px rgba(0,0,0,0.3);
135 | }
136 | ::-webkit-scrollbar-thumb:window-inactive {
137 | background: rgba(138, 138, 138, 0.4);
138 | }
139 | /*设置ie浏览器滚动条的样式*/
140 | div{
141 | /*三角箭头的颜色*/
142 | scrollbar-arrow-color: #73ccff;
143 | /*滚动条滑块按钮的颜色*/
144 | scrollbar-face-color: rgba(47, 65, 88, 0);
145 | /*滚动条整体颜色*/
146 | scrollbar-highlight-color: rgb(158, 158, 158);
147 | /*滚动条阴影*/
148 | scrollbar-shadow-color: rgba(51, 103, 133, 0);
149 | /*滚动条轨道颜色*/
150 | scrollbar-track-color: rgba(51, 103, 133, 0);
151 | }
152 |
--------------------------------------------------------------------------------
/src/style/mixin/setOnepx.scss:
--------------------------------------------------------------------------------
1 | @mixin setLine($c) {
2 | content: " ";
3 | position: absolute;
4 | left: 0;
5 | top: 0;
6 | width: 200%;
7 | height: 1px;
8 | border: 1px solid $c;
9 | color: $c;
10 | height: 200%;
11 | transform-origin: left top;
12 | transform: scale(0.5);
13 | }
14 |
15 | @mixin setTopLine($c) {
16 | content: " ";
17 | position: absolute;
18 | left: 0;
19 | right: 0;
20 | top: 0;
21 | height: 1px;
22 | border-top: 1px solid $c;
23 | color: $c;
24 | transform-origin: 0 0;
25 | transform: scaleY(0.5);
26 | }
27 |
28 | @mixin setBottomLine($c) {
29 | content: " ";
30 | position: absolute;
31 | left: 0;
32 | right: 0;
33 | bottom: 0;
34 | height: 1px;
35 | border-bottom: 1px solid $c;
36 | color: $c;
37 | transform-origin: 0 100%;
38 | transform: scaleY(0.5);
39 | }
40 |
41 | @mixin setLeftLine($c) {
42 | content: " ";
43 | position: absolute;
44 | left: 0;
45 | top: 0;
46 | bottom: 0;
47 | width: 1px;
48 | border-left: 1px solid $c;
49 | color: $c;
50 | transform-origin: 0 0;
51 | transform: scaleX(0.5);
52 | }
53 |
54 | @mixin setRightLine($c) {
55 | content: " ";
56 | position: absolute;
57 | right: 0;
58 | top: 0;
59 | bottom: 0;
60 | width: 1px;
61 | border-right: 1px solid $c;
62 | color: $c;
63 | transform-origin: 100% 0;
64 | transform: scaleX(0.5);
65 | }
66 |
--------------------------------------------------------------------------------
/src/style/reset.scss:
--------------------------------------------------------------------------------
1 | body,
2 | html {
3 | margin: 0;
4 | padding: 0;
5 | height: 100%;
6 | font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
7 | overflow: auto!important;
8 | font-weight: 400;
9 | font-size: 62.5%;
10 | -webkit-font-smoothing: antialiased;
11 | }
12 |
13 | hr {
14 | height: 1px;
15 | border: none;
16 | border-top: 1px solid rgba(155, 155, 155, 0.5);
17 | }
18 |
19 | h1,
20 | h2,
21 | h3,
22 | h4,
23 | h5,
24 | h6,
25 | p {
26 | margin: 0;
27 | padding: 0;
28 | }
29 |
30 | li,
31 | ul {
32 | margin: 0;
33 | padding: 0;
34 | list-style: none;
35 | }
36 |
37 | body {
38 | font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', SimSun, sans-serif;
39 | overflow: auto;
40 | font-weight: 400;
41 | -webkit-font-smoothing: antialiased;
42 | }
43 |
44 | a {
45 | color: rgba(0, 0, 0, 0.1);
46 | font-size: 14px;
47 | text-decoration: none;
48 | &:hover {
49 | text-decoration: none;
50 | }
51 | }
52 |
53 | img {
54 | max-width: 100%;
55 | }
56 |
57 | button,
58 | input,
59 | select,
60 | textarea {
61 | font-family: inherit;
62 | font-size: inherit;
63 | line-height: inherit;
64 | color: inherit;
65 | }
66 |
67 | * {
68 | box-sizing: border-box;
69 | }
70 |
--------------------------------------------------------------------------------
/src/utils/dict.js:
--------------------------------------------------------------------------------
1 | // 数据字典
2 | module.exports = {
3 | QQFaceList: ['微笑', '撇嘴', '色', '发呆', '得意', '流泪', '害羞', '闭嘴', '睡', '大哭', '尴尬', '发怒', '调皮', '呲牙', '惊讶', '难过', '酷', '冷汗', '抓狂', '吐', '偷笑', '愉快', '白眼', '傲慢', '饥饿', '困', '惊恐', '流汗', '憨笑', '悠闲', '奋斗', '咒骂', '疑问', '嘘', '晕', '疯了', '衰', '骷髅', '敲打', '再见', '擦汗', '抠鼻', '鼓掌', '糗大了', '坏笑', '左哼哼', '右哼哼', '哈欠', '鄙视', '委屈', '快哭了', '阴险', '亲亲', '吓', '可怜', '菜刀', '西瓜', '啤酒', '篮球', '乒乓', '咖啡', '饭', '猪头', '玫瑰', '凋谢', '嘴唇', '爱心', '心碎', '蛋糕', '闪电', '炸弹', '刀', '足球', '瓢虫', '便便', '月亮', '太阳', '礼物', '拥抱', '强', '弱', '握手', '胜利', '抱拳', '勾引', '拳头', '差劲', '爱你', 'NO', 'OK', '爱情', '飞吻', '跳跳', '发抖', '怄火', '转圈', '磕头', '回头', '跳绳', '投降', '激动', '乱舞', '献吻', '左太极', '右太极'],
4 | EmojiList: ['笑脸', '生病', '破涕为笑', '吐舌', '脸红', '恐惧', '失望', '无语', '嘿哈', '捂脸', '奸笑', '机智', '皱眉', '耶', '鬼魂', '合十', '强壮', '庆祝', '礼物', '红包', '鸡', '开心', '大笑', '热情', '眨眼', '色', '接吻', '亲吻', '露齿笑', '满意', '戏弄', '得意', '汗', '低落', '呸', '焦虑', '担心', '震惊', '悔恨', '眼泪', '哭', '晕', '心烦', '生气', '睡觉', '恶魔', '外星人', '心', '心碎', '丘比特', '闪烁', '星星', '叹号', '问号', '睡着', '水滴', '音乐', '火', '便便', '弱', '拳头', '胜利', '上', '下', '右', '左', '第一', '吻', '热恋', '男孩', '女孩', '女士', '男士', '天使', '骷髅', '红唇', '太阳', '下雨', '多云', '雪人', '月亮', '闪电', '海浪', '猫', '小狗', '老鼠', '仓鼠', '兔子', '狗', '青蛙', '老虎', '考拉', '熊', '猪', '牛', '野猪', '猴子', '马', '蛇', '鸽子', '鸡', '企鹅', '毛虫', '章鱼', '鱼', '鲸鱼', '海豚', '玫瑰', '花', '棕榈树', '仙人掌', '礼盒', '南瓜灯', '圣诞老人', '圣诞树', '礼物', '铃', '气球', 'CD', '相机', '录像机', '电脑', '电视', '电话', '解锁', '锁', '钥匙', '成交', '灯泡', '邮箱', '浴缸', '钱', '炸弹', '手枪', '药丸', '橄榄球', '篮球', '足球', '棒球', '高尔夫', '奖杯', '入侵者', '唱歌', '吉他', '比基尼', '皇冠', '雨伞', '手提包', '口红', '戒指', '钻石', '咖啡', '啤酒', '干杯', '鸡尾酒', '汉堡', '薯条', '意面', '寿司', '面条', '煎蛋', '冰激凌', '蛋糕', '苹果', '飞机', '火箭', '自行车', '高铁', '警告', '旗', '男人', '女人', 'O', 'X', '版权', '注册商标', '商标'],
5 | QQFaceMap: {
6 | '微笑': '0',
7 | '撇嘴': '1',
8 | '色': '2',
9 | '发呆': '3',
10 | '得意': '4',
11 | '流泪': '5',
12 | '害羞': '6',
13 | '闭嘴': '7',
14 | '睡': '8',
15 | '大哭': '9',
16 | '尴尬': '10',
17 | '发怒': '11',
18 | '调皮': '12',
19 | '呲牙': '13',
20 | '惊讶': '14',
21 | '难过': '15',
22 | '酷': '16',
23 | '冷汗': '17',
24 | '抓狂': '18',
25 | '吐': '19',
26 | '偷笑': '20',
27 | '可爱': '21',
28 | '愉快': '21',
29 | '白眼': '22',
30 | '傲慢': '23',
31 | '饥饿': '24',
32 | '困': '25',
33 | '惊恐': '26',
34 | '流汗': '27',
35 | '憨笑': '28',
36 | '悠闲': '29',
37 | '大兵': '29',
38 | '奋斗': '30',
39 | '咒骂': '31',
40 | '疑问': '32',
41 | '嘘': '33',
42 | '晕': '34',
43 | '疯了': '35',
44 | '折磨': '35',
45 | '衰': '36',
46 | '骷髅': '37',
47 | '敲打': '38',
48 | '再见': '39',
49 | '擦汗': '40',
50 | '抠鼻': '41',
51 | '鼓掌': '42',
52 | '糗大了': '43',
53 | '坏笑': '44',
54 | '左哼哼': '45',
55 | '右哼哼': '46',
56 | '哈欠': '47',
57 | '鄙视': '48',
58 | '委屈': '49',
59 | '快哭了': '50',
60 | '阴险': '51',
61 | '亲亲': '52',
62 | '吓': '53',
63 | '可怜': '54',
64 | '菜刀': '55',
65 | '西瓜': '56',
66 | '啤酒': '57',
67 | '篮球': '58',
68 | '乒乓': '59',
69 | '咖啡': '60',
70 | '饭': '61',
71 | '猪头': '62',
72 | '玫瑰': '63',
73 | '凋谢': '64',
74 | '嘴唇': '65',
75 | '示爱': '65',
76 | '爱心': '66',
77 | '心碎': '67',
78 | '蛋糕': '68',
79 | '闪电': '69',
80 | '炸弹': '70',
81 | '刀': '71',
82 | '足球': '72',
83 | '瓢虫': '73',
84 | '便便': '74',
85 | '月亮': '75',
86 | '太阳': '76',
87 | '礼物': '77',
88 | '拥抱': '78',
89 | '强': '79',
90 | '弱': '80',
91 | '握手': '81',
92 | '胜利': '82',
93 | '抱拳': '83',
94 | '勾引': '84',
95 | '拳头': '85',
96 | '差劲': '86',
97 | '爱你': '87',
98 | NO: '88',
99 | OK: '89',
100 | '爱情': '90',
101 | '飞吻': '91',
102 | '跳跳': '92',
103 | '发抖': '93',
104 | '怄火': '94',
105 | '转圈': '95',
106 | '磕头': '96',
107 | '回头': '97',
108 | '跳绳': '98',
109 | '投降': '99',
110 | '激动': '100',
111 | '乱舞': '101',
112 | '献吻': '102',
113 | '左太极': '103',
114 | '右太极': '104',
115 | '嘿哈': '105',
116 | '捂脸': '106',
117 | '奸笑': '107',
118 | '机智': '108',
119 | '皱眉': '109',
120 | '耶': '110',
121 | '鸡': '111',
122 | '红包': '112',
123 | Smile: '0',
124 | Grimace: 'emoji emoji',
125 | Drool: '2',
126 | Scowl: '3',
127 | Chill: '4',
128 | CoolGuy: '4',
129 | Sob: '5',
130 | Shy: '6',
131 | Shutup: '7',
132 | Silent: '7',
133 | Sleep: '8',
134 | Cry: '9',
135 | Awkward: '10',
136 | Pout: '11',
137 | Angry: '11',
138 | Wink: '12',
139 | Tongue: '12',
140 | Grin: '13',
141 | Surprised: '14',
142 | Surprise: '14',
143 | Frown: '15',
144 | Cool: '16',
145 | Ruthless: '16',
146 | Tension: '17',
147 | Blush: '17',
148 | Scream: '18',
149 | Crazy: '18',
150 | Puke: '19',
151 | Chuckle: '20',
152 | Joyful: '21',
153 | Slight: '22',
154 | Smug: '23',
155 | Hungry: '24',
156 | Drowsy: '25',
157 | Panic: '26',
158 | Sweat: '27',
159 | Laugh: '28',
160 | Loafer: '29',
161 | Commando: '29',
162 | Strive: '30',
163 | Determined: '30',
164 | Scold: '31',
165 | Doubt: '32',
166 | Shocked: '32',
167 | Shhh: '33',
168 | Dizzy: '34',
169 | Tormented: '35',
170 | BadLuck: '36',
171 | Toasted: '36',
172 | Skull: '37',
173 | Hammer: '38',
174 | Wave: '39',
175 | Relief: '40',
176 | Speechless: '40',
177 | DigNose: '41',
178 | NosePick: '41',
179 | Clap: '42',
180 | Shame: '43',
181 | Trick: '44',
182 | 'Bah!L': '45',
183 | 'Bah!R': '46',
184 | Yawn: '47',
185 | Lookdown: '48',
186 | 'Pooh-pooh': '48',
187 | Wronged: '49',
188 | Shrunken: '49',
189 | Puling: '50',
190 | TearingUp: '50',
191 | Sly: '51',
192 | Kiss: '52',
193 | 'Uh-oh': '53',
194 | Wrath: '53',
195 | Whimper: '54',
196 | Cleaver: '55',
197 | Melon: '56',
198 | Watermelon: '56',
199 | Beer: '57',
200 | Basketball: '58',
201 | PingPong: '59',
202 | Coffee: '60',
203 | Rice: '61',
204 | Pig: '62',
205 | Rose: '63',
206 | Wilt: '64',
207 | Lip: '65',
208 | Lips: '65',
209 | Heart: '66',
210 | BrokenHeart: '67',
211 | Cake: '68',
212 | Lightning: '69',
213 | Bomb: '70',
214 | Dagger: '71',
215 | Soccer: '72',
216 | Ladybug: '73',
217 | Poop: '74',
218 | Moon: '75',
219 | Sun: '76',
220 | Gift: '77',
221 | Hug: '78',
222 | Strong: '79',
223 | ThumbsUp: '79',
224 | Weak: '80',
225 | ThumbsDown: '80',
226 | Shake: '81',
227 | Victory: '82',
228 | Peace: '82',
229 | Admire: '83',
230 | Fight: '83',
231 | Beckon: '84',
232 | Fist: '85',
233 | Pinky: '86',
234 | Love: '2',
235 | RockOn: '87',
236 | No: '88',
237 | 'Nuh-uh': '88',
238 | InLove: '90',
239 | Blowkiss: '91',
240 | Waddle: '92',
241 | Tremble: '93',
242 | 'Aaagh!': '94',
243 | Twirl: '95',
244 | Kotow: '96',
245 | Lookback: '97',
246 | Dramatic: '97',
247 | Jump: '98',
248 | JumpRope: '98',
249 | 'Give-in': '99',
250 | Surrender: '99',
251 | Hooray: '100',
252 | HeyHey: '101',
253 | Meditate: '101',
254 | Smooch: '102',
255 | 'TaiJi L': '103',
256 | 'TaiChi L': '103',
257 | 'TaiJi R': '104',
258 | 'TaiChi R': '104',
259 | Hey: '105',
260 | Facepalm: '106',
261 | Smirk: '107',
262 | Smart: '108',
263 | Concerned: '109',
264 | 'Yeah!': '110',
265 | Chicken: '111',
266 | Packet: '112',
267 | '發呆': '3',
268 | '流淚': '5',
269 | '閉嘴': '7',
270 | '尷尬': '10',
271 | '發怒': '11',
272 | '調皮': '12',
273 | '驚訝': '14',
274 | '難過': '15',
275 | '饑餓': '24',
276 | '累': '25',
277 | '驚恐': '26',
278 | '悠閑': '29',
279 | '奮鬥': '30',
280 | '咒罵': '31',
281 | '疑問': '32',
282 | '噓': '33',
283 | '暈': '34',
284 | '瘋了': '35',
285 | '骷髏頭': '37',
286 | '再見': '39',
287 | '摳鼻': '41',
288 | '羞辱': '43',
289 | '壞笑': '44',
290 | '鄙視': '48',
291 | '陰險': '51',
292 | '親親': '52',
293 | '嚇': '53',
294 | '可憐': '54',
295 | '籃球': '58',
296 | '飯': '61',
297 | '豬頭': '62',
298 | '枯萎': '64',
299 | '愛心': '66',
300 | '閃電': '69',
301 | '炸彈': '70',
302 | '甲蟲': '73',
303 | '太陽': '76',
304 | '禮物': '77',
305 | '擁抱': '78',
306 | '強': '79',
307 | '勝利': '82',
308 | '拳頭': '85',
309 | '差勁': '86',
310 | '愛你': '88',
311 | '愛情': '90',
312 | '飛吻': '91',
313 | '發抖': '93',
314 | '噴火': '94',
315 | '轉圈': '95',
316 | '磕頭': '96',
317 | '回頭': '97',
318 | '跳繩': '98',
319 | '激動': '100',
320 | '亂舞': '101',
321 | '獻吻': '102',
322 | '左太極': '103',
323 | '右太極': '104',
324 | '吼嘿': '105',
325 | '掩面': '106',
326 | '機智': '108',
327 | '皺眉': '109',
328 | '歐耶': '110',
329 | '雞': '111',
330 | '紅包': '112',
331 | '[笑脸]': '1f604',
332 | '[笑臉]': '1f604',
333 | '[Laugh]': '1f604',
334 | '[开心]': '1f60a',
335 | '[開心]': '1f60a',
336 | '[Happy]': '1f60a',
337 | '[大笑]': '1f603',
338 | '[Big Smile]': '1f603',
339 | '[热情]': '263a',
340 | '[熱情]': '263a',
341 | '[Glowing]': '263a',
342 | '[眨眼]': '1f609',
343 | '[Wink]': '1f609',
344 | '[色]': '1f60d',
345 | '[Love]': '1f60d',
346 | '[Drool]': '1f60d',
347 | '[接吻]': '1f618',
348 | '[Smooch]': '1f618',
349 | '[亲吻]': '1f61a',
350 | '[親吻]': '1f61a',
351 | '[Kiss]': '1f61a',
352 | '[脸红]': '1f633',
353 | '[臉紅]': '1f633',
354 | '[Blush]': '1f633',
355 | '[露齿笑]': '1f63c',
356 | '[露齒笑]': '1f63c',
357 | '[Grin]': '1f63c',
358 | '[满意]': '1f60c',
359 | '[滿意]': '1f60c',
360 | '[Satisfied]': '1f60c',
361 | '[戏弄]': '1f61c',
362 | '[戲弄]': '1f61c',
363 | '[Tease]': '1f61c',
364 | '[吐舌]': '1f445',
365 | '[Tongue]': '1f445',
366 | '[无语]': '1f612',
367 | '[無語]': '1f612',
368 | '[Speechless]': '1f612',
369 | '[得意]': '1f60f',
370 | '[Smirk]': '1f60f',
371 | '[CoolGuy]': '1f60f',
372 | '[汗]': '1f613',
373 | '[Sweat]': '1f613',
374 | '[失望]': '1f640',
375 | '[Let Down]': '1f640',
376 | '[合十]': '1f64f',
377 | '[祈禱]': '1f64f',
378 | '[低落]': '1f61e',
379 | '[Low]': '1f61e',
380 | '[呸]': '1f616',
381 | '[Ugh]': '1f616',
382 | '[焦虑]': '1f625',
383 | '[焦慮]': '1f625',
384 | '[Anxious]': '1f625',
385 | '[担心]': '1f630',
386 | '[擔心]': '1f630',
387 | '[Worried]': '1f630',
388 | '[震惊]': '1f628',
389 | '[震驚]': '1f628',
390 | '[Shocked]': '1f628',
391 | '[悔恨]': '1f62b',
392 | '[D’oh!]': '1f62b',
393 | '[眼泪]': '1f622',
394 | '[眼淚]': '1f622',
395 | '[Tear]': '1f622',
396 | '[哭]': '1f62d',
397 | '[Cry]': '1f62d',
398 | '[破涕为笑]': '1f602',
399 | '[破涕為笑]': '1f602',
400 | '[Lol]': '1f602',
401 | '[晕]': '1f632',
402 | '[Dead]': '1f632',
403 | '[Dizzy]': '1f632',
404 | '[恐惧]': '1f631',
405 | '[恐懼]': '1f631',
406 | '[Terror]': '1f631',
407 | '[心烦]': '1f620',
408 | '[心煩]': '1f620',
409 | '[Upset]': '1f620',
410 | '[生气]': '1f63e',
411 | '[生氣]': '1f63e',
412 | '[Angry]': '1f63e',
413 | '[睡觉]': '1f62a',
414 | '[睡覺]': '1f62a',
415 | '[Zzz]': '1f62a',
416 | '[生病]': '1f637',
417 | '[Sick]': '1f637',
418 | '[恶魔]': '1f47f',
419 | '[惡魔]': '1f47f',
420 | '[Demon]': '1f47f',
421 | '[外星人]': '1f47d',
422 | '[Alien]': '1f47d',
423 | '[心]': '2764',
424 | '[Heart]': '2764',
425 | '[心碎]': '1f494',
426 | '[Heartbroken]': '1f494',
427 | '[BrokenHeart]': '1f494',
428 | '[丘比特]': '1f498',
429 | '[Cupid]': '1f498',
430 | '[闪烁]': '2728',
431 | '[閃爍]': '2728',
432 | '[Twinkle]': '2728',
433 | '[星星]': '1f31f',
434 | '[Star]': '1f31f',
435 | '[叹号]': '2755',
436 | '[嘆號]': '2755',
437 | '[!]': '2755',
438 | '[问号]': '2754',
439 | '[問號]': '2754',
440 | '[?]': '2754',
441 | '[睡着]': '1f4a4',
442 | '[睡著]': '1f4a4',
443 | '[Asleep]': '1f4a4',
444 | '[水滴]': '1f4a6',
445 | '[Drops]': '1f4a6',
446 | '[音乐]': '1f3b5',
447 | '[音樂]': '1f3b5',
448 | '[Music]': '1f3b5',
449 | '[火]': '1f525',
450 | '[Fire]': '1f525',
451 | '[便便]': '1f4a9',
452 | '[Poop]': '1f4a9',
453 | '[强]': '1f44d',
454 | '[強]': '1f44d',
455 | '[ThumbsUp]': '1f44d',
456 | '[弱]': '1f44e',
457 | '[ThumbsDown]': '1f44e',
458 | '[拳头]': '1f44a',
459 | '[拳頭]': '1f44a',
460 | '[Punch]': '1f44a',
461 | '[Fist]': '1f44a',
462 | '[胜利]': '270c',
463 | '[勝利]': '270c',
464 | '[Peace]': '270c',
465 | '[上]': '1f446',
466 | '[Up]': '1f446',
467 | '[下]': '1f447',
468 | '[Down]': '1f447',
469 | '[右]': '1f449',
470 | '[Right]': '1f449',
471 | '[左]': '1f448',
472 | '[Left]': '1f448',
473 | '[第一]': '261d',
474 | '[#emoji emoji]': '261d',
475 | '[强壮]': '1f4aa',
476 | '[強壯]': '1f4aa',
477 | '[Strong]': '1f4aa',
478 | '[吻]': '1f48f',
479 | '[Kissing]': '1f48f',
480 | '[热恋]': '1f491',
481 | '[熱戀]': '1f491',
482 | '[Couple]': '1f491',
483 | '[男孩]': '1f466',
484 | '[Boy]': '1f466',
485 | '[女孩]': '1f467',
486 | '[Girl]': '1f467',
487 | '[女士]': '1f469',
488 | '[Lady]': '1f469',
489 | '[男士]': '1f468',
490 | '[Man]': '1f468',
491 | '[天使]': '1f47c',
492 | '[Angel]': '1f47c',
493 | '[骷髅]': '1f480',
494 | '[骷髏頭]': '1f480',
495 | '[骷髏]': '1f480',
496 | '[Skull]': '1f480',
497 | '[红唇]': '1f48b',
498 | '[紅唇]': '1f48b',
499 | '[Lips]': '1f48b',
500 | '[太阳]': '2600',
501 | '[太陽]': '2600',
502 | '[Sun]': '2600',
503 | '[下雨]': '2614',
504 | '[Rain]': '2614',
505 | '[多云]': '2601',
506 | '[多雲]': '2601',
507 | '[Cloud]': '2601',
508 | '[雪人]': '26c4',
509 | '[Snowman]': '26c4',
510 | '[月亮]': '1f319',
511 | '[Moon]': '1f319',
512 | '[闪电]': '26a1',
513 | '[閃電]': '26a1',
514 | '[Lightning]': '26a1',
515 | '[海浪]': '1f30a',
516 | '[Waves]': '1f30a',
517 | '[猫]': '1f431',
518 | '[貓]': '1f431',
519 | '[Cat]': '1f431',
520 | '[小狗]': '1f429',
521 | '[Doggy]': '1f429',
522 | '[老鼠]': '1f42d',
523 | '[Mouse]': '1f42d',
524 | '[仓鼠]': '1f439',
525 | '[倉鼠]': '1f439',
526 | '[Hamster]': '1f439',
527 | '[兔子]': '1f430',
528 | '[Rabbit]': '1f430',
529 | '[狗]': '1f43a',
530 | '[Dog]': '1f43a',
531 | '[青蛙]': '1f438',
532 | '[Frog]': '1f438',
533 | '[老虎]': '1f42f',
534 | '[Tiger]': '1f42f',
535 | '[考拉]': '1f428',
536 | '[Koala]': '1f428',
537 | '[熊]': '1f43b',
538 | '[Bear]': '1f43b',
539 | '[猪]': '1f437',
540 | '[豬]': '1f437',
541 | '[Pig]': '1f437',
542 | '[牛]': '1f42e',
543 | '[Cow]': '1f42e',
544 | '[野猪]': '1f417',
545 | '[野豬]': '1f417',
546 | '[Boar]': '1f417',
547 | '[猴子]': '1f435',
548 | '[Monkey]': '1f435',
549 | '[马]': '1f434',
550 | '[馬]': '1f434',
551 | '[Horse]': '1f434',
552 | '[蛇]': '1f40d',
553 | '[Snake]': '1f40d',
554 | '[鸽子]': '1f426',
555 | '[鴿子]': '1f426',
556 | '[Pigeon]': '1f426',
557 | '[鸡]': '1f414',
558 | '[雞]': '1f414',
559 | '[Chicken]': '1f414',
560 | '[企鹅]': '1f427',
561 | '[企鵝]': '1f427',
562 | '[Penguin]': '1f427',
563 | '[毛虫]': '1f41b',
564 | '[毛蟲]': '1f41b',
565 | '[Caterpillar]': '1f41b',
566 | '[章鱼]': '1f419',
567 | '[八爪魚]': '1f419',
568 | '[Octopus]': '1f419',
569 | '[鱼]': '1f420',
570 | '[魚]': '1f420',
571 | '[Fish]': '1f420',
572 | '[鲸鱼]': '1f433',
573 | '[鯨魚]': '1f433',
574 | '[Whale]': '1f433',
575 | '[海豚]': '1f42c',
576 | '[Dolphin]': '1f42c',
577 | '[玫瑰]': '1f339',
578 | '[Rose]': '1f339',
579 | '[花]': '1f33a',
580 | '[Flower]': '1f33a',
581 | '[棕榈树]': '1f334',
582 | '[棕櫚樹]': '1f334',
583 | '[Palm]': '1f334',
584 | '[仙人掌]': '1f335',
585 | '[Cactus]': '1f335',
586 | '[礼盒]': '1f49d',
587 | '[禮盒]': '1f49d',
588 | '[Candy Box]': '1f49d',
589 | '[南瓜灯]': '1f383',
590 | '[南瓜燈]': '1f383',
591 | '[Jack-o-lantern]': '1f383',
592 | '[鬼魂]': '1f47b',
593 | '[Ghost]': '1f47b',
594 | '[圣诞老人]': '1f385',
595 | '[聖誕老人]': '1f385',
596 | '[Santa]': '1f385',
597 | '[圣诞树]': '1f384',
598 | '[聖誕樹]': '1f384',
599 | '[Xmas Tree]': '1f384',
600 | '[礼物]': '1f381',
601 | '[禮物]': '1f381',
602 | '[Gift]': '1f381',
603 | '[铃]': '1f514',
604 | '[鈴鐺]': '1f514',
605 | '[Bell]': '1f514',
606 | '[庆祝]': '1f389',
607 | '[慶祝]': '1f389',
608 | '[Party]': '1f389',
609 | '[气球]': '1f388',
610 | '[氣球]': '1f388',
611 | '[Balloon]': '1f388',
612 | '[CD]': '1f4bf',
613 | '[相机]': '1f4f7',
614 | '[相機]': '1f4f7',
615 | '[Camera]': '1f4f7',
616 | '[录像机]': '1f3a5',
617 | '[錄影機]': '1f3a5',
618 | '[Film Camera]': '1f3a5',
619 | '[电脑]': '1f4bb',
620 | '[電腦]': '1f4bb',
621 | '[Computer]': '1f4bb',
622 | '[电视]': '1f4fa',
623 | '[電視]': '1f4fa',
624 | '[TV]': '1f4fa',
625 | '[电话]': '1f4de',
626 | '[電話]': '1f4de',
627 | '[Phone]': '1f4de',
628 | '[解锁]': '1f513',
629 | '[解鎖]': '1f513',
630 | '[Unlocked]': '1f513',
631 | '[锁]': '1f512',
632 | '[鎖]': '1f512',
633 | '[Locked]': '1f512',
634 | '[钥匙]': '1f511',
635 | '[鑰匙]': '1f511',
636 | '[Key]': '1f511',
637 | '[成交]': '1f528',
638 | '[Judgement]': '1f528',
639 | '[灯泡]': '1f4a1',
640 | '[燈泡]': '1f4a1',
641 | '[Light bulb]': '1f4a1',
642 | '[邮箱]': '1f4eb',
643 | '[郵箱]': '1f4eb',
644 | '[Mail]': '1f4eb',
645 | '[浴缸]': '1f6c0',
646 | '[Wash]': '1f6c0',
647 | '[钱]': '1f4b2',
648 | '[錢]': '1f4b2',
649 | '[Money]': '1f4b2',
650 | '[炸弹]': '1f4a3',
651 | '[炸彈]': '1f4a3',
652 | '[Bomb]': '1f4a3',
653 | '[手枪]': '1f52b',
654 | '[手槍]': '1f52b',
655 | '[Pistol]': '1f52b',
656 | '[药丸]': '1f48a',
657 | '[藥丸]': '1f48a',
658 | '[Pill]': '1f48a',
659 | '[橄榄球]': '1f3c8',
660 | '[橄欖球]': '1f3c8',
661 | '[Football]': '1f3c8',
662 | '[篮球]': '1f3c0',
663 | '[籃球]': '1f3c0',
664 | '[Basketball]': '1f3c0',
665 | '[足球]': '26bd',
666 | '[Soccer Ball]': '26bd',
667 | '[Soccer]': '26bd',
668 | '[棒球]': '26be',
669 | '[Baseball]': '26be',
670 | '[高尔夫]': '26f3',
671 | '[高爾夫]': '26f3',
672 | '[Golf]': '26f3',
673 | '[奖杯]': '1f3c6',
674 | '[獎盃]': '1f3c6',
675 | '[Trophy]': '1f3c6',
676 | '[入侵者]': '1f47e',
677 | '[Invader]': '1f47e',
678 | '[唱歌]': '1f3a4',
679 | '[Singing]': '1f3a4',
680 | '[吉他]': '1f3b8',
681 | '[Guitar]': '1f3b8',
682 | '[比基尼]': '1f459',
683 | '[Bikini]': '1f459',
684 | '[皇冠]': '1f451',
685 | '[Crown]': '1f451',
686 | '[雨伞]': '1f302',
687 | '[雨傘]': '1f302',
688 | '[Umbrella]': '1f302',
689 | '[手提包]': '1f45c',
690 | '[Purse]': '1f45c',
691 | '[口红]': '1f484',
692 | '[口紅]': '1f484',
693 | '[Lipstick]': '1f484',
694 | '[戒指]': '1f48d',
695 | '[Ring]': '1f48d',
696 | '[钻石]': '1f48e',
697 | '[鑽石]': '1f48e',
698 | '[Gem]': '1f48e',
699 | '[咖啡]': '2615',
700 | '[Coffee]': '2615',
701 | '[啤酒]': '1f37a',
702 | '[Beer]': '1f37a',
703 | '[干杯]': '1f37b',
704 | '[乾杯]': '1f37b',
705 | '[Toast]': '1f37b',
706 | '[鸡尾酒]': '1f377',
707 | '[雞尾酒]': '1f377',
708 | '[Martini]': '1f377',
709 | '[汉堡]': '1f354',
710 | '[漢堡]': '1f354',
711 | '[Burger]': '1f354',
712 | '[薯条]': '1f35f',
713 | '[薯條]': '1f35f',
714 | '[Fries]': '1f35f',
715 | '[意面]': '1f35d',
716 | '[意粉]': '1f35d',
717 | '[Sphaghetti]': '1f35d',
718 | '[寿司]': '1f363',
719 | '[壽司]': '1f363',
720 | '[Sushi]': '1f363',
721 | '[面条]': '1f35c',
722 | '[麵條]': '1f35c',
723 | '[Noodles]': '1f35c',
724 | '[煎蛋]': '1f373',
725 | '[Eggs]': '1f373',
726 | '[冰激凌]': '1f366',
727 | '[雪糕]': '1f366',
728 | '[Ice Cream]': '1f366',
729 | '[蛋糕]': '1f382',
730 | '[Cake]': '1f382',
731 | '[苹果]': '1f34f',
732 | '[蘋果]': '1f34f',
733 | '[Apple]': '1f34f',
734 | '[飞机]': '2708',
735 | '[飛機]': '2708',
736 | '[Plane]': '2708',
737 | '[火箭]': '1f680',
738 | '[Rocket ship]': '1f680',
739 | '[自行车]': '1f6b2',
740 | '[單車]': '1f6b2',
741 | '[Bike]': '1f6b2',
742 | '[高铁]': '1f684',
743 | '[高鐵]': '1f684',
744 | '[Bullet Train]': '1f684',
745 | '[警告]': '26a0',
746 | '[Warning]': '26a0',
747 | '[旗]': '1f3c1',
748 | '[Flag]': '1f3c1',
749 | '[男人]': '1f6b9',
750 | '[男]': '1f6b9',
751 | '[Men]': '1f6b9',
752 | '[女人]': '1f6ba',
753 | '[女]': '1f6ba',
754 | '[Women]': '1f6ba',
755 | '[O]': '2b55',
756 | '[X]': '274e',
757 | '[版权]': 'a9',
758 | '[版權]': 'a9',
759 | '[Copyright]': 'a9',
760 | '[注册商标]': 'ae',
761 | '[注冊商標]': 'ae',
762 | '[Registered TM]': 'ae',
763 | '[商标]': '2122',
764 | '[商標]': '2122',
765 | '[Trademark]': '2122'
766 | },
767 | CodeEmojiMap: {
768 | '': '1f64f',
769 | '': '1f604',
770 | '': '1f60a',
771 | '': '1f603',
772 | '': '263a',
773 | '': '1f609',
774 | '': '1f60d',
775 | '': '1f618',
776 | '': '1f61a',
777 | '': '1f633',
778 | '': '1f63c',
779 | '': '1f60c',
780 | '': '1f61c',
781 | '': '1f445',
782 | '': '1f612',
783 | '': '1f60f',
784 | '': '1f613',
785 | '': '1f640',
786 | '': '1f61e',
787 | '': '1f616',
788 | '': '1f625',
789 | '': '1f630',
790 | '': '1f628',
791 | '': '1f62b',
792 | '': '1f622',
793 | '': '1f62d',
794 | '': '1f602',
795 | '': '1f632',
796 | '': '1f631',
797 | '': '1f620',
798 | '': '1f63e',
799 | '': '1f62a',
800 | '': '1f637',
801 | '': '1f47f',
802 | '': '1f47d',
803 | '': 2764,
804 | '': '1f494',
805 | '': '1f498',
806 | '': 2728,
807 | '': '1f31f',
808 | '': 2755,
809 | '': 2754,
810 | '': '1f4a4',
811 | '': '1f4a6',
812 | '': '1f3b5',
813 | '': '1f525',
814 | '': '1f4a9',
815 | '': '1f44d',
816 | '': '1f44e',
817 | '': '1f44a',
818 | '': '270c',
819 | '': '1f446',
820 | '': '1f447',
821 | '': '1f449',
822 | '': '1f448',
823 | '': '261d',
824 | '': '1f4aa',
825 | '': '1f48f',
826 | '': '1f491',
827 | '': '1f466',
828 | '': '1f467',
829 | '': '1f469',
830 | '': '1f468',
831 | '': '1f47c',
832 | '': '1f480',
833 | '': '1f48b',
834 | '': 2600,
835 | '': 2614,
836 | '': 2601,
837 | '': '26c4',
838 | '': '1f319',
839 | '': '26a1',
840 | '': '1f30a',
841 | '': '1f431',
842 | '': '1f429',
843 | '': '1f42d',
844 | '': '1f439',
845 | '': '1f430',
846 | '': '1f43a',
847 | '': '1f438',
848 | '': '1f42f',
849 | '': '1f428',
850 | '': '1f43b',
851 | '': '1f437',
852 | '': '1f42e',
853 | '': '1f417',
854 | '': '1f435',
855 | '': '1f434',
856 | '': '1f40d',
857 | '': '1f426',
858 | '': '1f414',
859 | '': '1f427',
860 | '': '1f41b',
861 | '': '1f419',
862 | '': '1f420',
863 | '': '1f433',
864 | '': '1f42c',
865 | '': '1f339',
866 | '': '1f33a',
867 | '': '1f334',
868 | '': '1f335',
869 | '': '1f49d',
870 | '': '1f383',
871 | '': '1f47b',
872 | '': '1f385',
873 | '': '1f384',
874 | '': '1f381',
875 | '': '1f514',
876 | '': '1f389',
877 | '': '1f388',
878 | '': '1f4bf',
879 | '': '1f4f7',
880 | '': '1f3a5',
881 | '': '1f4bb',
882 | '': '1f4fa',
883 | '': '1f4de',
884 | '': '1f513',
885 | '': '1f512',
886 | '': '1f511',
887 | '': '1f528',
888 | '': '1f4a1',
889 | '': '1f4eb',
890 | '': '1f6c0',
891 | '': '1f4b2',
892 | '': '1f4a3',
893 | '': '1f52b',
894 | '': '1f48a',
895 | '': '1f3c8',
896 | '': '1f3c0',
897 | '': '26bd',
898 | '': '26be',
899 | '': '26f3',
900 | '': '1f3c6',
901 | '': '1f47e',
902 | '': '1f3a4',
903 | '': '1f3b8',
904 | '': '1f459',
905 | '': '1f451',
906 | '': '1f302',
907 | '': '1f45c',
908 | '': '1f484',
909 | '': '1f48d',
910 | '': '1f48e',
911 | '': 2615,
912 | '': '1f37a',
913 | '': '1f37b',
914 | '': '1f377',
915 | '': '1f354',
916 | '': '1f35f',
917 | '': '1f35d',
918 | '': '1f363',
919 | '': '1f35c',
920 | '': '1f373',
921 | '': '1f366',
922 | '': '1f382',
923 | '': '1f34f',
924 | '': 2708,
925 | '': '1f680',
926 | '': '1f6b2',
927 | '': '1f684',
928 | '': '26a0',
929 | '': '1f3c1',
930 | '': '1f6b9',
931 | '': '1f6ba',
932 | '': '2b55',
933 | '': '274e',
934 | '': 'a9',
935 | '': 'ae',
936 | '': 2122
937 | },
938 | EmojiCodeMap: {
939 | '1f64f': '',
940 | '1f604': '',
941 | '1f60a': '',
942 | '1f603': '',
943 | '263a': '',
944 | '1f609': '',
945 | '1f60d': '',
946 | '1f618': '',
947 | '1f61a': '',
948 | '1f633': '',
949 | '1f63c': '',
950 | '1f60c': '',
951 | '1f61c': '',
952 | '1f445': '',
953 | '1f612': '',
954 | '1f60f': '',
955 | '1f613': '',
956 | '1f640': '',
957 | '1f61e': '',
958 | '1f616': '',
959 | '1f625': '',
960 | '1f630': '',
961 | '1f628': '',
962 | '1f62b': '',
963 | '1f622': '',
964 | '1f62d': '',
965 | '1f602': '',
966 | '1f632': '',
967 | '1f631': '',
968 | '1f620': '',
969 | '1f63e': '',
970 | '1f62a': '',
971 | '1f637': '',
972 | '1f47f': '',
973 | '1f47d': '',
974 | 2764: '',
975 | '1f494': '',
976 | '1f498': '',
977 | 2728: '',
978 | '1f31f': '',
979 | 2755: '',
980 | 2754: '',
981 | '1f4a4': '',
982 | '1f4a6': '',
983 | '1f3b5': '',
984 | '1f525': '',
985 | '1f4a9': '',
986 | '1f44d': '',
987 | '1f44e': '',
988 | '1f44a': '',
989 | '270c': '',
990 | '1f446': '',
991 | '1f447': '',
992 | '1f449': '',
993 | '1f448': '',
994 | '261d': '',
995 | '1f4aa': '',
996 | '1f48f': '',
997 | '1f491': '',
998 | '1f466': '',
999 | '1f467': '',
1000 | '1f469': '',
1001 | '1f468': '',
1002 | '1f47c': '',
1003 | '1f480': '',
1004 | '1f48b': '',
1005 | 2600: '',
1006 | 2614: '',
1007 | 2601: '',
1008 | '26c4': '',
1009 | '1f319': '',
1010 | '26a1': '',
1011 | '1f30a': '',
1012 | '1f431': '',
1013 | '1f429': '',
1014 | '1f42d': '',
1015 | '1f439': '',
1016 | '1f430': '',
1017 | '1f43a': '',
1018 | '1f438': '',
1019 | '1f42f': '',
1020 | '1f428': '',
1021 | '1f43b': '',
1022 | '1f437': '',
1023 | '1f42e': '',
1024 | '1f417': '',
1025 | '1f435': '',
1026 | '1f434': '',
1027 | '1f40d': '',
1028 | '1f426': '',
1029 | '1f414': '',
1030 | '1f427': '',
1031 | '1f41b': '',
1032 | '1f419': '',
1033 | '1f420': '',
1034 | '1f433': '',
1035 | '1f42c': '',
1036 | '1f339': '',
1037 | '1f33a': '',
1038 | '1f334': '',
1039 | '1f335': '',
1040 | '1f49d': '',
1041 | '1f383': '',
1042 | '1f47b': '',
1043 | '1f385': '',
1044 | '1f384': '',
1045 | '1f381': '',
1046 | '1f514': '',
1047 | '1f389': '',
1048 | '1f388': '',
1049 | '1f4bf': '',
1050 | '1f4f7': '',
1051 | '1f3a5': '',
1052 | '1f4bb': '',
1053 | '1f4fa': '',
1054 | '1f4de': '',
1055 | '1f513': '',
1056 | '1f512': '',
1057 | '1f511': '',
1058 | '1f528': '',
1059 | '1f4a1': '',
1060 | '1f4eb': '',
1061 | '1f6c0': '',
1062 | '1f4b2': '',
1063 | '1f4a3': '',
1064 | '1f52b': '',
1065 | '1f48a': '',
1066 | '1f3c8': '',
1067 | '1f3c0': '',
1068 | '26bd': '',
1069 | '26be': '',
1070 | '26f3': '',
1071 | '1f3c6': '',
1072 | '1f47e': '',
1073 | '1f3a4': '',
1074 | '1f3b8': '',
1075 | '1f459': '',
1076 | '1f451': '',
1077 | '1f302': '',
1078 | '1f45c': '',
1079 | '1f484': '',
1080 | '1f48d': '',
1081 | '1f48e': '',
1082 | 2615: '',
1083 | '1f37a': '',
1084 | '1f37b': '',
1085 | '1f377': '',
1086 | '1f354': '',
1087 | '1f35f': '',
1088 | '1f35d': '',
1089 | '1f363': '',
1090 | '1f35c': '',
1091 | '1f373': '',
1092 | '1f366': '',
1093 | '1f382': '',
1094 | '1f34f': '',
1095 | 2708: '',
1096 | '1f680': '',
1097 | '1f6b2': '',
1098 | '1f684': '',
1099 | '26a0': '',
1100 | '1f3c1': '',
1101 | '1f6b9': '',
1102 | '1f6ba': '',
1103 | '2b55': '',
1104 | '274e': '',
1105 | a9: '',
1106 | ae: '',
1107 | 2122: ''
1108 | },
1109 | gdPostion: {
1110 | '广州市': {
1111 | '荔湾区': [113.206456, 23.072519],
1112 | '越秀区': [113.254567, 23.134813],
1113 | '海珠区': [113.286889, 23.073221],
1114 | '天河区': [113.331517, 23.153941],
1115 | '白云区': [113.246472, 23.271988],
1116 | '黄埔区': [113.440421, 23.096076],
1117 | '增城区': [113.686029, 23.335733],
1118 | '花都区': [113.130846, 23.436016],
1119 | '从化区': [113.538423, 23.612996],
1120 | '番禺区': [113.348983, 22.926093],
1121 | '南沙区': [113.512817, 22.700692],
1122 | '萝岗区': [113.479566, 23.200053]
1123 | },
1124 | '韶关市': {
1125 | '乐昌市': [113.208631, 25.267923],
1126 | '仁化县': [113.746962, 25.143670],
1127 | '南雄市': [114.356703, 25.200843],
1128 | '始兴县': [114.062818, 24.842455],
1129 | '曲江区': [113.595900, 24.650389],
1130 | '浈江区': [113.516249, 24.939621],
1131 | '乳源瑶族自治县': [113.107008, 24.832485],
1132 | '武江区': [113.373426, 24.700305],
1133 | '翁源县': [113.966688, 24.388005],
1134 | '新丰县': [114.076551, 24.059884]
1135 | },
1136 | '清远市': {
1137 | '佛冈县': [113.505269, 23.867876],
1138 | '清城区': [113.065815, 23.626530],
1139 | '清新县': [112.799397, 23.872900],
1140 | '英德市': [113.288289, 24.221540],
1141 | '阳山县': [112.596150, 24.494268],
1142 | '连州市': [112.420369, 24.908481],
1143 | '连南瑶族自治县': [112.217122, 24.531754],
1144 | '连山壮族瑶族自治县': [112.027607, 24.674096]
1145 | },
1146 | '湛江市': {
1147 | '麻章区': [110.380419, 21.030339],
1148 | '霞山区': [110.358865, 21.193021],
1149 | '坡头区': [110.484267, 21.275207],
1150 | '赤坎区': [110.362784, 21.282510],
1151 | '吴川市': [110.660652, 21.430379],
1152 | '廉江市': [110.104185, 21.647265],
1153 | '遂溪县': [110.021890, 21.293521],
1154 | '雷州市': [109.951352, 20.790621],
1155 | '徐闻县': [110.262895, 20.432658]
1156 | },
1157 | '珠海市': {
1158 | '金湾区': [113.283787, 22.078821],
1159 | '香洲区': [113.513997, 22.236720],
1160 | '斗门区': [113.229847, 22.230479]
1161 | },
1162 | '梅州市': {
1163 | '五华县': [115.610512, 23.796830],
1164 | '兴宁市': [115.725197, 24.235132],
1165 | '丰顺县': [116.250930, 23.929615],
1166 | '梅县': [116.266210, 24.404268],
1167 | '梅江区': [116.119176, 24.295779],
1168 | '平远县': [115.891293, 24.695504],
1169 | '蕉岭县': [116.158319, 24.681661],
1170 | '大埔县': [116.624849, 24.306431]
1171 | },
1172 | '河源市': {
1173 | '紫金县': [115.005786, 23.524560],
1174 | '东源县': [114.818682, 23.963408],
1175 | '连平县': [114.489223, 24.376099],
1176 | '和平县': [114.988328, 24.455997],
1177 | '龙川县': [115.342697, 24.345363]
1178 | },
1179 | '肇庆市': {
1180 | '怀集县': [112.127418, 24.002762],
1181 | '封开县': [111.665777, 23.522385],
1182 | '德庆县': [111.987563, 23.275078],
1183 | '广宁县': [112.413953, 23.660958],
1184 | '高要市': [112.432975, 22.924725],
1185 | '端州区': [112.463894, 23.100161],
1186 | '鼎湖区': [112.585413, 23.196445],
1187 | '四会市': [112.649472, 23.432046]
1188 | },
1189 | '惠州市': {
1190 | '龙门县': [114.120331, 23.661709],
1191 | '博罗县': [114.229969, 23.314406],
1192 | '惠城区': [114.627852, 23.282012],
1193 | '惠阳区': [114.441594, 22.846923],
1194 | '惠东县': [114.985885, 23.120341]
1195 | },
1196 | '茂名市': {
1197 | '信宜市': [111.060067, 22.453958],
1198 | '高州市': [110.929351, 22.012073],
1199 | '电白县': [111.218387, 21.664179],
1200 | '化州市': [110.487191, 21.803418],
1201 | '茂港区': [110.937157, 21.489907],
1202 | '茂南区': [110.828000, 21.678896]
1203 | },
1204 | '江门市': {
1205 | '恩平市': [112.220129, 22.218151],
1206 | '台山市': [112.724268, 22.031199],
1207 | '开平市': [112.572168, 22.454779],
1208 | '鹤山市': [112.802560, 22.642855],
1209 | '新会区': [113.009516, 22.363590],
1210 | '江海区': [113.111000, 22.545216],
1211 | '蓬江区': [113.038792, 22.642739]
1212 | },
1213 | '阳江市': {
1214 | '阳春市': [111.636694, 22.251231],
1215 | '阳西县': [111.547944, 21.716837],
1216 | '江城区': [111.903503, 21.752994],
1217 | '阳东县': [112.116047, 21.939571]
1218 | },
1219 | '云浮市': {
1220 | '郁南县': [111.604310, 22.994563],
1221 | '罗定市': [111.470042, 22.657111],
1222 | '云安县': [111.949937, 22.751793],
1223 | '云城区': [112.149885, 22.969215],
1224 | '新兴县': [112.165662, 22.594563]
1225 | },
1226 | '汕尾市': {
1227 | '海丰县': [115.253324, 22.979036],
1228 | '陆河县': [115.597494, 23.260053],
1229 | '陆丰市': [115.731250, 22.966802],
1230 | '城区': [115.409779, 22.752311]
1231 | },
1232 | '揭阳市': {
1233 | '揭西县': [115.890705, 23.491294],
1234 | '普宁市': [116.085955, 23.271638],
1235 | '惠来县': [116.234100, 23.000322],
1236 | '揭东县': [116.278983, 23.650253],
1237 | '榕城区': [116.340611, 23.517186]
1238 | },
1239 | '佛山市': {
1240 | '高明区': [112.680590, 22.832121],
1241 | '三水区': [112.876986, 23.254978],
1242 | '南海区': [112.984038, 23.103913],
1243 | '顺德区': [113.157335, 22.816437],
1244 | '禅城区': [113.028001, 23.003829]
1245 | },
1246 | '潮州市': {
1247 | '饶平县': [116.845910, 23.821253],
1248 | '潮安县': [116.568296, 23.813889],
1249 | '湘桥区': [116.650326, 23.688871]
1250 | },
1251 | '汕头市': {
1252 | '潮南区': [116.371622, 23.157354],
1253 | '潮阳区': [116.441186, 23.354512],
1254 | '金平区': [116.630054, 23.390254],
1255 | '龙湖区': [116.737756, 23.380376],
1256 | '澄海区': [116.788856, 23.520913],
1257 | '南澳县': [117.047836, 23.436979],
1258 | '濠江区': [116.678218, 23.293485]
1259 | },
1260 | '深圳市': {
1261 | '宝安区': [113.885130, 22.716748],
1262 | '南山区': [113.935588, 22.562105],
1263 | '福田区': [114.029126, 22.545733],
1264 | '龙岗区': [114.312007, 22.696489],
1265 | '罗湖区': [114.132199, 22.562225],
1266 | '盐田区': [114.255829, 22.593947]
1267 | },
1268 | '东莞市': {
1269 | '东莞市': [113.859153, 22.974071]
1270 | },
1271 | '中山市': {
1272 | '中山市': [113.357764, 22.535839]
1273 | }
1274 | }
1275 | }
1276 |
--------------------------------------------------------------------------------
/src/utils/regular.js:
--------------------------------------------------------------------------------
1 | export const matchRegDQuotes = (val) => {
2 | // 获取双引号内的字段
3 | const matchREG = /\"(.+?)\"/
4 | let newVal = val.match(matchREG)[1]
5 | return newVal
6 | }
7 | export const matchRegSpecialChar = (val) => {
8 | const matchREG = /\=(.+?)\;/
9 | let newVal = val.match(matchREG)[1]
10 | return newVal
11 | }
12 | export const matchRegQuestionMark = (val) => {
13 | // 获取url问号后字段
14 | const matchREG = /\?(\S*)/
15 | let newVal = val.match(matchREG)[1]
16 | return newVal
17 | }
18 | export const matchRegApostrophe = (val) => {
19 | // 获取u单引号间字段
20 | const matchREG = /\'(.+?)\'/
21 | let newVal = val.match(matchREG)[1]
22 | return newVal
23 | }
24 | export const matchRegDbrackets = (val) => {
25 | const matchREG = /\"(.+?)\"/g
26 | let newVal = val.match(matchREG)
27 | return newVal
28 | }
29 | export const matchRegDBrackets = (val) => {
30 | // 获取双括号内的字段
31 | const matchREG = /\[(.+?)\]/g
32 | let newVal = val.match(matchREG)
33 | return newVal
34 | }
35 | export const replacehRegDBrackets = (val) => {
36 | // 获取双括号内的字段
37 | const matchREG = /\[(.+?)\]/g
38 | let newVal = val.replace(matchREG, ',')
39 | return newVal
40 | }
41 |
--------------------------------------------------------------------------------
/src/utils/utils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 存储localStorage
3 | */
4 | export const setLocalStorage = (name, content) => {
5 | if (!name) return
6 | if (typeof content !== 'string') {
7 | content = JSON.stringify(content)
8 | }
9 | window.localStorage.setItem(name, content)
10 | }
11 |
12 | /**
13 | * 获取localStorage
14 | */
15 | export const getLocalStorage = name => {
16 | if (!name) return
17 | return window.localStorage.getItem(name)
18 | }
19 |
20 | /**
21 | * 删除localStorage
22 | */
23 | export const removeLocalStorage = name => {
24 | if (!name) return
25 | window.localStorage.removeItem(name)
26 | }
27 |
28 | /**
29 | * 设置sessionStorage
30 | */
31 | export const setSessionStorage = (name, content) => {
32 | if (!name) return
33 | if (typeof content !== 'string') {
34 | content = JSON.stringify(content)
35 | }
36 | window.sessionStorage.setItem(name, content)
37 | }
38 |
39 | /**
40 | * 获取sessionStorage
41 | */
42 | export const getSessionStorage = name => {
43 | if (!name) return
44 | return window.sessionStorage.getItem(name)
45 | }
46 |
47 | /**
48 | * 删除sessionStorage
49 | */
50 | export const removeSessionStorage = name => {
51 | if (!name) return
52 | window.sessionStorage.removeItem(name)
53 | }
54 |
55 | /**
56 | * 保存cookie
57 | */
58 | export const setCookie = (name, value) => {
59 | let days = 30
60 | let exp = new Date()
61 | exp.setTime(exp.getTime() + days * 24 * 60 * 60 * 1000)
62 | document.cookie = name + '=' + escape(value) + ';expires=' + exp.toGMTString()
63 | }
64 |
65 | /**
66 | * 获取cookie
67 | */
68 | export const getCookie = (name, defaultValue) => {
69 | let arr = null
70 | let reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)')
71 | arr = document.cookie.match(reg)
72 | if (arr) {
73 | return unescape(arr[2])
74 | } else {
75 | return defaultValue
76 | }
77 | }
78 |
79 | /**
80 | * 删除cookie
81 | */
82 | export const delCookie = (name) => {
83 | let exp = new Date()
84 | exp.setTime(exp.getTime() - 1)
85 | let cval = getCookie(name)
86 | if (cval !== null) document.cookie = name + '=' + cval + ';expires=' + exp.toGMTString()
87 | }
88 |
89 | /**
90 | * web sql database
91 | */
92 | // if (!window.openDatabase) {
93 | // console.log('该浏览器不支持数据库')
94 | // return false
95 | // } else {
96 | // /*
97 | // * 创建数据库
98 | // * openDatabase使用现有数据库或创建新数据库创建数据库对象
99 | // * (数据库名称, 版本号, 数据库的描述, 数据的大小, 回调函数)
100 | // */
101 | // let dataBase = window.openDatabase('tvi.db', '1.0', 'gisHeatMap', 10 * 1024 * 1024)
102 | // /*
103 | // * 创建数据表
104 | // * transaction访问数据库
105 | // * executeSql异步执行真实的SQL查询
106 | // * (查询的字符串, 插入到查询中问号所在处的字符串数据, 成功回调函数, 失败回调函数)
107 | // */
108 | // dataBase.transaction((tx) => {
109 | // tx.executeSql(
110 | // 'create table if not exists TEMPLATE (template_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, template_name TEXT)',
111 | // [],
112 | // (res) => {
113 | // console.log('创建模板表成功')
114 | // },
115 | // (error) => {
116 | // console.log('创建模板表失败:' + error.message)
117 | // }
118 | // )
119 | // })
120 | // /*
121 | // * 数据增删查改
122 | // */
123 | // dataBase.transaction((tx) => {
124 | // tx.executeSql(
125 | // 'insert into TEMPLATE (id, name) values(?, ?)',
126 | // ['1', 'YJ'],
127 | // (res) => {
128 | // console.log('添加数据成功')
129 | // },
130 | // (error) => {
131 | // console.log('添加数据失败:' + error.message)
132 | // }
133 | // )
134 | // })
135 | // dataBase.transaction((tx) => {
136 | // tx.executeSql(
137 | // 'select * from TEMPLATE',
138 | // [],
139 | // (tx, res) => {
140 | // console.log('查询数据成功', res)
141 | // },
142 | // (error) => {
143 | // console.log('查询数据失败:' + error.message)
144 | // }
145 | // )
146 | // })
147 | // }
148 |
149 | /**
150 | * 获取浏览器配置语言
151 | */
152 | export const getNavigatorLang = (language) => {
153 | let type = navigator.appName
154 | let lang = null
155 | if (type === 'Netscape') {
156 | lang = navigator.language // 获取非IE浏览器语言
157 | } else {
158 | lang = navigator.userLanguage // 获取IE5+浏览器语言
159 | }
160 | switch (lang) {
161 | case 'zh-CN':
162 | return 'zh'
163 | case 'en-US':
164 | return 'en'
165 | default:
166 | return 'zh'
167 | }
168 | }
169 |
170 | /*
171 | * 日期格式化
172 | * _this Data()
173 | */
174 | export const setDateFormat = (_this, timeLong, cb) => {
175 | _this = new Date(_this.getTime() + timeLong * 24 * 60 * 60 * 1000)
176 | let o = {
177 | 'M+': _this.getMonth() + 1,
178 | 'd+': _this.getDate(),
179 | 'h+': _this.getHours(),
180 | 'm+': _this.getMinutes(),
181 | 's+': _this.getSeconds(),
182 | 'q+': Math.floor((_this.getMonth() + 3) / 3),
183 | 'S': _this.getMilliseconds()
184 | }
185 | if (/(y+)/.test(cb)) cb = cb.replace(RegExp.$1, (_this.getFullYear() + '').substr(4 - RegExp.$1.length))
186 | for (let k in o) {
187 | if (new RegExp('(' + k + ')').test(cb)) {
188 | cb = cb.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
189 | }
190 | }
191 | return cb
192 | }
193 |
--------------------------------------------------------------------------------
/src/view/login/login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | 移动蜂巢选址平台
11 |
12 |
13 |
14 |
21 |
22 |
31 |
32 |
33 |
34 |
35 | {{$t('buttom.login')}}
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
91 |
92 |
102 |
--------------------------------------------------------------------------------
/src/view/management/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
31 |
--------------------------------------------------------------------------------
/src/view/management/menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | {{item.title}}
12 |
13 |
14 |
15 |
16 | {{ subItem.title }}
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
52 |
--------------------------------------------------------------------------------
/src/view/wechat/children/wxChatContent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
暂无新消息
8 |
9 |
10 |
11 |
12 |
![]()
13 |
![]()
14 |
15 |
16 |
信息已被撤回
17 |
18 |
23 |
24 |
25 |
![]()
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
66 |
67 |
200 |
--------------------------------------------------------------------------------
/src/view/wechat/children/wxChatHeader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | remove
10 |
11 |
12 | list
13 |
14 |
15 | edit
16 |
17 |
18 | search
19 |
20 |
21 | account_circle
22 |
23 |
24 |
25 |
26 |
27 |
46 |
47 |
73 |
--------------------------------------------------------------------------------
/src/view/wechat/children/wxChatItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
66 |
67 |
69 |
--------------------------------------------------------------------------------
/src/view/wechat/children/wxChatList.vue:
--------------------------------------------------------------------------------
1 |
2 |
83 |
84 |
85 |
156 |
157 |
240 |
--------------------------------------------------------------------------------
/src/view/wechat/children/wxChatSendBox.vue:
--------------------------------------------------------------------------------
1 | /* 微信信息发送模块
2 | * YJ
3 | * 2018-08-08
4 | */
5 |
6 |
7 |
8 |
9 | qq表情
10 | 符号表情
11 |
12 |
15 |
16 |
17 |
22 |
23 |
24 |
25 |
26 |
27 | face
28 |
29 |
38 |
39 | unarchive
40 |
41 |
42 |
43 | camera_alt
44 |
45 |
46 | track_changes
47 |
48 |
49 |
50 |
51 |
52 | 按下ctrl + enter发送信息send
53 |
54 |
55 |
56 |
57 |
58 |
260 |
261 |
289 |
297 |
--------------------------------------------------------------------------------
/src/view/wechat/children/wxChatSideBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
41 |
42 |
53 |
--------------------------------------------------------------------------------
/src/view/wechat/children/wxLogin.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |

8 |
9 |
![]()
10 |
11 |
12 | {{wxInvalid?'二维码失效,点击刷新':'使用手机微信扫码登陆'}}
13 |
14 |
15 | 微信聊天会话需要先登陆
16 |
17 |
18 |
19 |
20 |
![用户头像]()
21 |
22 | 请在手机端确定登陆
23 |
24 |
切换账号
25 |
26 |
27 |
28 |
29 |
30 |
31 |
144 |
145 |
238 |
--------------------------------------------------------------------------------
/src/view/wechat/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
242 |
243 |
264 |
--------------------------------------------------------------------------------
/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hty7/vue-wechat/cedcde1f098f862385b77f56b5a8e07d270d7ad0/static/.gitkeep
--------------------------------------------------------------------------------
/static/images/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hty7/vue-wechat/cedcde1f098f862385b77f56b5a8e07d270d7ad0/static/images/404.png
--------------------------------------------------------------------------------
/static/images/avatar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hty7/vue-wechat/cedcde1f098f862385b77f56b5a8e07d270d7ad0/static/images/avatar.jpg
--------------------------------------------------------------------------------
/static/images/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hty7/vue-wechat/cedcde1f098f862385b77f56b5a8e07d270d7ad0/static/images/bg.jpg
--------------------------------------------------------------------------------
/static/images/emoji.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hty7/vue-wechat/cedcde1f098f862385b77f56b5a8e07d270d7ad0/static/images/emoji.png
--------------------------------------------------------------------------------
/static/images/emoji2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hty7/vue-wechat/cedcde1f098f862385b77f56b5a8e07d270d7ad0/static/images/emoji2.png
--------------------------------------------------------------------------------
/static/images/faceqqemoji.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hty7/vue-wechat/cedcde1f098f862385b77f56b5a8e07d270d7ad0/static/images/faceqqemoji.png
--------------------------------------------------------------------------------
/static/images/fhemoji.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hty7/vue-wechat/cedcde1f098f862385b77f56b5a8e07d270d7ad0/static/images/fhemoji.png
--------------------------------------------------------------------------------
/static/images/login_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hty7/vue-wechat/cedcde1f098f862385b77f56b5a8e07d270d7ad0/static/images/login_bg.jpg
--------------------------------------------------------------------------------
/static/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hty7/vue-wechat/cedcde1f098f862385b77f56b5a8e07d270d7ad0/static/images/logo.png
--------------------------------------------------------------------------------
/static/images/refresh-34re.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hty7/vue-wechat/cedcde1f098f862385b77f56b5a8e07d270d7ad0/static/images/refresh-34re.png
--------------------------------------------------------------------------------
/static/images/timg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hty7/vue-wechat/cedcde1f098f862385b77f56b5a8e07d270d7ad0/static/images/timg.png
--------------------------------------------------------------------------------
/static/js/walden.js:
--------------------------------------------------------------------------------
1 | (function (root, factory) {
2 | if (typeof define === 'function' && define.amd) {
3 | // AMD. Register as an anonymous module.
4 | define(['exports', 'echarts'], factory)
5 | } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
6 | // CommonJS
7 | factory(exports, require('echarts'))
8 | } else {
9 | // Browser globals
10 | factory({}, root.echarts)
11 | }
12 | }(this, function (exports, echarts) {
13 | var log = function (msg) {
14 | if (typeof console !== 'undefined') {
15 | console && console.error && console.error(msg)
16 | }
17 | }
18 | if (!echarts) {
19 | log('ECharts is not Loaded')
20 | return
21 | }
22 | echarts.registerTheme('walden', {
23 | 'color': [
24 | '#67c8f2',
25 | '#6be6c1',
26 | '#626c91',
27 | '#a0a7e6',
28 | '#c4ebad',
29 | '#96dee8'
30 | ],
31 | 'backgroundColor': 'rgba(252,252,252,0)',
32 | 'textStyle': {},
33 | 'title': {
34 | 'textStyle': {
35 | 'color': '#666666'
36 | },
37 | 'subtextStyle': {
38 | 'color': '#999999'
39 | }
40 | },
41 | 'line': {
42 | 'itemStyle': {
43 | 'normal': {
44 | 'borderWidth': '2'
45 | }
46 | },
47 | 'lineStyle': {
48 | 'normal': {
49 | 'width': '2'
50 | }
51 | },
52 | 'symbolSize': '5',
53 | 'symbol': 'circle',
54 | 'smooth': true
55 | },
56 | 'radar': {
57 | 'itemStyle': {
58 | 'normal': {
59 | 'borderWidth': '2'
60 | }
61 | },
62 | 'lineStyle': {
63 | 'normal': {
64 | 'width': '2'
65 | }
66 | },
67 | 'symbolSize': '5',
68 | 'symbol': 'circle',
69 | 'smooth': true
70 | },
71 | 'bar': {
72 | 'itemStyle': {
73 | 'normal': {
74 | 'barBorderWidth': 0,
75 | 'barBorderColor': '#ccc'
76 | },
77 | 'emphasis': {
78 | 'barBorderWidth': 0,
79 | 'barBorderColor': '#ccc'
80 | }
81 | }
82 | },
83 | 'pie': {
84 | 'itemStyle': {
85 | 'normal': {
86 | 'borderWidth': 0,
87 | 'borderColor': '#ccc'
88 | },
89 | 'emphasis': {
90 | 'borderWidth': 0,
91 | 'borderColor': '#ccc'
92 | }
93 | }
94 | },
95 | 'scatter': {
96 | 'itemStyle': {
97 | 'normal': {
98 | 'borderWidth': 0,
99 | 'borderColor': '#ccc'
100 | },
101 | 'emphasis': {
102 | 'borderWidth': 0,
103 | 'borderColor': '#ccc'
104 | }
105 | }
106 | },
107 | 'boxplot': {
108 | 'itemStyle': {
109 | 'normal': {
110 | 'borderWidth': 0,
111 | 'borderColor': '#ccc'
112 | },
113 | 'emphasis': {
114 | 'borderWidth': 0,
115 | 'borderColor': '#ccc'
116 | }
117 | }
118 | },
119 | 'parallel': {
120 | 'itemStyle': {
121 | 'normal': {
122 | 'borderWidth': 0,
123 | 'borderColor': '#ccc'
124 | },
125 | 'emphasis': {
126 | 'borderWidth': 0,
127 | 'borderColor': '#ccc'
128 | }
129 | }
130 | },
131 | 'sankey': {
132 | 'itemStyle': {
133 | 'normal': {
134 | 'borderWidth': 0,
135 | 'borderColor': '#ccc'
136 | },
137 | 'emphasis': {
138 | 'borderWidth': 0,
139 | 'borderColor': '#ccc'
140 | }
141 | }
142 | },
143 | 'funnel': {
144 | 'itemStyle': {
145 | 'normal': {
146 | 'borderWidth': 0,
147 | 'borderColor': '#ccc'
148 | },
149 | 'emphasis': {
150 | 'borderWidth': 0,
151 | 'borderColor': '#ccc'
152 | }
153 | }
154 | },
155 | 'gauge': {
156 | 'itemStyle': {
157 | 'normal': {
158 | 'borderWidth': 0,
159 | 'borderColor': '#ccc'
160 | },
161 | 'emphasis': {
162 | 'borderWidth': 0,
163 | 'borderColor': '#ccc'
164 | }
165 | }
166 | },
167 | 'candlestick': {
168 | 'itemStyle': {
169 | 'normal': {
170 | 'color': '#e6a0d2',
171 | 'color0': 'transparent',
172 | 'borderColor': '#e6a0d2',
173 | 'borderColor0': '#3fb1e3',
174 | 'borderWidth': '2'
175 | }
176 | }
177 | },
178 | 'graph': {
179 | 'itemStyle': {
180 | 'normal': {
181 | 'borderWidth': 0,
182 | 'borderColor': '#ccc'
183 | }
184 | },
185 | 'lineStyle': {
186 | 'normal': {
187 | 'width': '1',
188 | 'color': '#cccccc'
189 | }
190 | },
191 | 'symbolSize': '5',
192 | 'symbol': 'circle',
193 | 'smooth': true,
194 | 'color': [
195 | '#67c8f2',
196 | '#6be6c1',
197 | '#626c91',
198 | '#a0a7e6',
199 | '#c4ebad',
200 | '#96dee8'
201 | ],
202 | 'label': {
203 | 'normal': {
204 | 'textStyle': {
205 | 'color': '#ffffff'
206 | }
207 | }
208 | }
209 | },
210 | 'map': {
211 | 'itemStyle': {
212 | 'normal': {
213 | 'areaColor': '#eeeeee',
214 | 'borderColor': '#aaaaaa',
215 | 'borderWidth': 0.5
216 | },
217 | 'emphasis': {
218 | 'areaColor': 'rgba(63,177,227,0.25)',
219 | 'borderColor': '#3fb1e3',
220 | 'borderWidth': 1
221 | }
222 | },
223 | 'label': {
224 | 'normal': {
225 | 'textStyle': {
226 | 'color': '#ffffff'
227 | }
228 | },
229 | 'emphasis': {
230 | 'textStyle': {
231 | 'color': 'rgb(63,177,227)'
232 | }
233 | }
234 | }
235 | },
236 | 'geo': {
237 | 'itemStyle': {
238 | 'normal': {
239 | 'areaColor': '#eeeeee',
240 | 'borderColor': '#aaaaaa',
241 | 'borderWidth': 0.5
242 | },
243 | 'emphasis': {
244 | 'areaColor': 'rgba(63,177,227,0.25)',
245 | 'borderColor': '#3fb1e3',
246 | 'borderWidth': 1
247 | }
248 | },
249 | 'label': {
250 | 'normal': {
251 | 'textStyle': {
252 | 'color': '#ffffff'
253 | }
254 | },
255 | 'emphasis': {
256 | 'textStyle': {
257 | 'color': 'rgb(63,177,227)'
258 | }
259 | }
260 | }
261 | },
262 | 'categoryAxis': {
263 | 'axisLine': {
264 | 'show': false,
265 | 'lineStyle': {
266 | 'color': '#cccccc'
267 | }
268 | },
269 | 'axisTick': {
270 | 'show': false,
271 | 'lineStyle': {
272 | 'color': '#333'
273 | }
274 | },
275 | 'axisLabel': {
276 | 'show': true,
277 | 'textStyle': {
278 | 'color': '#999999'
279 | }
280 | },
281 | 'splitLine': {
282 | 'show': false,
283 | 'lineStyle': {
284 | 'color': [
285 | '#eeeeee'
286 | ]
287 | }
288 | },
289 | 'splitArea': {
290 | 'show': false,
291 | 'areaStyle': {
292 | 'color': [
293 | 'rgba(250,250,250,0.05)',
294 | 'rgba(200,200,200,0.02)'
295 | ]
296 | }
297 | }
298 | },
299 | 'valueAxis': {
300 | 'axisLine': {
301 | 'show': false,
302 | 'lineStyle': {
303 | 'color': '#cccccc'
304 | }
305 | },
306 | 'axisTick': {
307 | 'show': false,
308 | 'lineStyle': {
309 | 'color': '#333'
310 | }
311 | },
312 | 'axisLabel': {
313 | 'show': true,
314 | 'textStyle': {
315 | 'color': '#999999'
316 | }
317 | },
318 | 'splitLine': {
319 | 'show': false,
320 | 'lineStyle': {
321 | 'color': [
322 | '#eeeeee'
323 | ]
324 | }
325 | },
326 | 'splitArea': {
327 | 'show': false,
328 | 'areaStyle': {
329 | 'color': [
330 | 'rgba(250,250,250,0.05)',
331 | 'rgba(200,200,200,0.02)'
332 | ]
333 | }
334 | }
335 | },
336 | 'logAxis': {
337 | 'axisLine': {
338 | 'show': true,
339 | 'lineStyle': {
340 | 'color': '#cccccc'
341 | }
342 | },
343 | 'axisTick': {
344 | 'show': false,
345 | 'lineStyle': {
346 | 'color': '#333'
347 | }
348 | },
349 | 'axisLabel': {
350 | 'show': true,
351 | 'textStyle': {
352 | 'color': '#999999'
353 | }
354 | },
355 | 'splitLine': {
356 | 'show': true,
357 | 'lineStyle': {
358 | 'color': [
359 | '#eeeeee'
360 | ]
361 | }
362 | },
363 | 'splitArea': {
364 | 'show': false,
365 | 'areaStyle': {
366 | 'color': [
367 | 'rgba(250,250,250,0.05)',
368 | 'rgba(200,200,200,0.02)'
369 | ]
370 | }
371 | }
372 | },
373 | 'timeAxis': {
374 | 'axisLine': {
375 | 'show': true,
376 | 'lineStyle': {
377 | 'color': '#cccccc'
378 | }
379 | },
380 | 'axisTick': {
381 | 'show': false,
382 | 'lineStyle': {
383 | 'color': '#333'
384 | }
385 | },
386 | 'axisLabel': {
387 | 'show': true,
388 | 'textStyle': {
389 | 'color': '#999999'
390 | }
391 | },
392 | 'splitLine': {
393 | 'show': true,
394 | 'lineStyle': {
395 | 'color': [
396 | '#eeeeee'
397 | ]
398 | }
399 | },
400 | 'splitArea': {
401 | 'show': false,
402 | 'areaStyle': {
403 | 'color': [
404 | 'rgba(250,250,250,0.05)',
405 | 'rgba(200,200,200,0.02)'
406 | ]
407 | }
408 | }
409 | },
410 | 'toolbox': {
411 | 'iconStyle': {
412 | 'normal': {
413 | 'borderColor': '#999999'
414 | },
415 | 'emphasis': {
416 | 'borderColor': '#666666'
417 | }
418 | }
419 | },
420 | 'legend': {
421 | 'textStyle': {
422 | 'color': '#999999'
423 | }
424 | },
425 | 'tooltip': {
426 | 'axisPointer': {
427 | 'lineStyle': {
428 | 'color': '#cccccc',
429 | 'width': 1
430 | },
431 | 'crossStyle': {
432 | 'color': '#cccccc',
433 | 'width': 1
434 | }
435 | }
436 | },
437 | 'timeline': {
438 | 'lineStyle': {
439 | 'color': '#626c91',
440 | 'width': 1
441 | },
442 | 'itemStyle': {
443 | 'normal': {
444 | 'color': '#626c91',
445 | 'borderWidth': 1
446 | },
447 | 'emphasis': {
448 | 'color': '#626c91'
449 | }
450 | },
451 | 'controlStyle': {
452 | 'normal': {
453 | 'color': '#626c91',
454 | 'borderColor': '#626c91',
455 | 'borderWidth': 0.5
456 | },
457 | 'emphasis': {
458 | 'color': '#626c91',
459 | 'borderColor': '#626c91',
460 | 'borderWidth': 0.5
461 | }
462 | },
463 | 'checkpointStyle': {
464 | 'color': '#3fb1e3',
465 | 'borderColor': 'rgba(63,177,227,0.15)'
466 | },
467 | 'label': {
468 | 'normal': {
469 | 'textStyle': {
470 | 'color': '#626c91'
471 | }
472 | },
473 | 'emphasis': {
474 | 'textStyle': {
475 | 'color': '#626c91'
476 | }
477 | }
478 | }
479 | },
480 | 'visualMap': {
481 | 'color': [
482 | '#2a99c9',
483 | '#afe8ff'
484 | ]
485 | },
486 | 'dataZoom': {
487 | 'backgroundColor': 'rgba(255,255,255,0.8)',
488 | 'dataBackgroundColor': 'rgba(222,222,222,1)',
489 | 'fillerColor': 'rgba(114,230,212,0.25)',
490 | 'handleColor': '#969a97',
491 | 'handleSize': '150%',
492 | 'textStyle': {
493 | 'color': '#cc660f'
494 | }
495 | },
496 | 'markPoint': {
497 | 'label': {
498 | 'normal': {
499 | 'textStyle': {
500 | 'color': '#9e9e9e'
501 | }
502 | },
503 | 'emphasis': {
504 | 'textStyle': {
505 | 'color': '#9e9e9e'
506 | }
507 | }
508 | }
509 | }
510 | })
511 | }))
512 |
--------------------------------------------------------------------------------
/test/e2e/custom-assertions/elementCount.js:
--------------------------------------------------------------------------------
1 | // A custom Nightwatch assertion.
2 | // The assertion name is the filename.
3 | // Example usage:
4 | //
5 | // browser.assert.elementCount(selector, count)
6 | //
7 | // For more information on custom assertions see:
8 | // http://nightwatchjs.org/guide#writing-custom-assertions
9 |
10 | exports.assertion = function (selector, count) {
11 | this.message = 'Testing if element <' + selector + '> has count: ' + count
12 | this.expected = count
13 | this.pass = function (val) {
14 | return val === this.expected
15 | }
16 | this.value = function (res) {
17 | return res.value
18 | }
19 | this.command = function (cb) {
20 | var self = this
21 | return this.api.execute(function (selector) {
22 | return document.querySelectorAll(selector).length
23 | }, [selector], function (res) {
24 | cb.call(self, res)
25 | })
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/test/e2e/nightwatch.conf.js:
--------------------------------------------------------------------------------
1 | require('babel-register')
2 | var config = require('../../config')
3 |
4 | // http://nightwatchjs.org/gettingstarted#settings-file
5 | module.exports = {
6 | src_folders: ['test/e2e/specs'],
7 | output_folder: 'test/e2e/reports',
8 | custom_assertions_path: ['test/e2e/custom-assertions'],
9 |
10 | selenium: {
11 | start_process: true,
12 | server_path: require('selenium-server').path,
13 | host: '127.0.0.1',
14 | port: 4444,
15 | cli_args: {
16 | 'webdriver.chrome.driver': require('chromedriver').path
17 | }
18 | },
19 |
20 | test_settings: {
21 | default: {
22 | selenium_port: 4444,
23 | selenium_host: 'localhost',
24 | silent: true,
25 | globals: {
26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
27 | }
28 | },
29 |
30 | chrome: {
31 | desiredCapabilities: {
32 | browserName: 'chrome',
33 | javascriptEnabled: true,
34 | acceptSslCerts: true
35 | }
36 | },
37 |
38 | firefox: {
39 | desiredCapabilities: {
40 | browserName: 'firefox',
41 | javascriptEnabled: true,
42 | acceptSslCerts: true
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/test/e2e/runner.js:
--------------------------------------------------------------------------------
1 | // 1. start the dev server using production config
2 | process.env.NODE_ENV = 'testing'
3 |
4 | const webpack = require('webpack')
5 | const DevServer = require('webpack-dev-server')
6 |
7 | const webpackConfig = require('../../build/webpack.prod.conf')
8 | const devConfigPromise = require('../../build/webpack.dev.conf')
9 |
10 | let server
11 |
12 | devConfigPromise.then(devConfig => {
13 | const devServerOptions = devConfig.devServer
14 | const compiler = webpack(webpackConfig)
15 | server = new DevServer(compiler, devServerOptions)
16 | const port = devServerOptions.port
17 | const host = devServerOptions.host
18 | return server.listen(port, host)
19 | })
20 | .then(() => {
21 | // 2. run the nightwatch test suite against it
22 | // to run in additional browsers:
23 | // 1. add an entry in test/e2e/nightwatch.conf.js under "test_settings"
24 | // 2. add it to the --env flag below
25 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
26 | // For more information on Nightwatch's config file, see
27 | // http://nightwatchjs.org/guide#settings-file
28 | let opts = process.argv.slice(2)
29 | if (opts.indexOf('--config') === -1) {
30 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
31 | }
32 | if (opts.indexOf('--env') === -1) {
33 | opts = opts.concat(['--env', 'chrome'])
34 | }
35 |
36 | const spawn = require('cross-spawn')
37 | const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
38 |
39 | runner.on('exit', function (code) {
40 | server.close()
41 | process.exit(code)
42 | })
43 |
44 | runner.on('error', function (err) {
45 | server.close()
46 | throw err
47 | })
48 | })
49 |
--------------------------------------------------------------------------------
/test/e2e/specs/test.js:
--------------------------------------------------------------------------------
1 | // For authoring Nightwatch tests, see
2 | // http://nightwatchjs.org/guide#usage
3 |
4 | module.exports = {
5 | 'default e2e tests': function (browser) {
6 | // automatically uses dev Server port from /config.index.js
7 | // default: http://localhost:8080
8 | // see nightwatch.conf.js
9 | const devServer = browser.globals.devServerURL
10 |
11 | browser
12 | .url(devServer)
13 | .waitForElementVisible('#app', 5000)
14 | .assert.elementPresent('.hello')
15 | .assert.containsText('h1', 'Welcome to Your Vue.js App')
16 | .assert.elementCount('img', 1)
17 | .end()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/test/unit/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "jest": true
4 | },
5 | "globals": {
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/test/unit/jest.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | module.exports = {
4 | rootDir: path.resolve(__dirname, '../../'),
5 | moduleFileExtensions: [
6 | 'js',
7 | 'json',
8 | 'vue'
9 | ],
10 | moduleNameMapper: {
11 | '^@/(.*)$': '/src/$1'
12 | },
13 | transform: {
14 | '^.+\\.js$': '/node_modules/babel-jest',
15 | '.*\\.(vue)$': '/node_modules/vue-jest'
16 | },
17 | testPathIgnorePatterns: [
18 | '/test/e2e'
19 | ],
20 | snapshotSerializers: ['/node_modules/jest-serializer-vue'],
21 | setupFiles: ['/test/unit/setup'],
22 | mapCoverage: true,
23 | coverageDirectory: '/test/unit/coverage',
24 | collectCoverageFrom: [
25 | 'src/**/*.{js,vue}',
26 | '!src/main.js',
27 | '!src/router/index.js',
28 | '!**/node_modules/**'
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/test/unit/setup.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | Vue.config.productionTip = false
4 |
--------------------------------------------------------------------------------
/test/unit/specs/HelloWorld.spec.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import HelloWorld from '@/components/HelloWorld'
3 |
4 | describe('HelloWorld.vue', () => {
5 | it('should render correct contents', () => {
6 | const Constructor = Vue.extend(HelloWorld)
7 | const vm = new Constructor().$mount()
8 | expect(vm.$el.querySelector('.hello h1').textContent)
9 | .toEqual('Welcome to Your Vue.js App')
10 | })
11 | })
12 |
--------------------------------------------------------------------------------