Browse Source

1

pull/1/head
pengda 8 months ago
commit
b1b20eb195
  1. 18
      .babelrc
  2. 9
      .editorconfig
  3. 5
      .eslintignore
  4. 29
      .eslintrc.js
  5. 17
      .gitignore
  6. 10
      .postcssrc.js
  7. 30
      README.md
  8. 41
      build/build.js
  9. 54
      build/check-versions.js
  10. BIN
      build/logo.png
  11. 101
      build/utils.js
  12. 22
      build/vue-loader.conf.js
  13. 92
      build/webpack.base.conf.js
  14. 95
      build/webpack.dev.conf.js
  15. 149
      build/webpack.prod.conf.js
  16. 7
      config/dev.env.js
  17. 76
      config/index.js
  18. 4
      config/prod.env.js
  19. 7
      config/test.env.js
  20. 65
      index.html
  21. 14460
      package-lock.json
  22. 86
      package.json
  23. 194
      src/App.vue
  24. 10
      src/assets/btn_add.svg
  25. 10
      src/assets/btn_back.svg
  26. 10
      src/assets/btn_checked.svg
  27. 10
      src/assets/btn_close.svg
  28. 10
      src/assets/btn_next.svg
  29. 10
      src/assets/btn_personal.svg
  30. 10
      src/assets/btn_unchecked.svg
  31. 89
      src/assets/css/layout.css
  32. BIN
      src/assets/images/card_secret_buy/buy_pic.png
  33. BIN
      src/assets/images/card_secret_buy/tabs_buy.png
  34. BIN
      src/assets/images/card_secret_buy/tabs_buy_on.png
  35. BIN
      src/assets/images/card_secret_buy/tabs_search.png
  36. BIN
      src/assets/images/card_secret_buy/tabs_search_on.png
  37. BIN
      src/assets/images/order_sample/order_sample_1.png
  38. BIN
      src/assets/images/order_sample/order_sample_2.png
  39. BIN
      src/assets/images/order_sample/order_sample_3.png
  40. BIN
      src/assets/images/order_sample/order_sample_one.png
  41. BIN
      src/assets/images/order_sample/order_sample_three.png
  42. BIN
      src/assets/images/order_sample/order_sample_two.png
  43. BIN
      src/assets/images/title_pic.png
  44. BIN
      src/assets/logo.png
  45. 14
      src/assets/pic_direction.svg
  46. 126
      src/components/H5OpenError.vue
  47. 113
      src/components/HelloWorld.vue
  48. 353
      src/components/cardSecretBuy.vue
  49. 194
      src/components/cardSecretQuery.vue
  50. 100
      src/components/common/Login.vue
  51. 141
      src/components/common/headTitle.vue
  52. 74
      src/components/orderSample.vue
  53. 10
      src/components/utils/Global.vue
  54. 64
      src/main.js
  55. 79
      src/router/index.js
  56. 0
      static/.gitkeep
  57. BIN
      static/loading.gif
  58. 27
      test/e2e/custom-assertions/elementCount.js
  59. 46
      test/e2e/nightwatch.conf.js
  60. 48
      test/e2e/runner.js
  61. 19
      test/e2e/specs/test.js
  62. 7
      test/unit/.eslintrc
  63. 30
      test/unit/jest.conf.js
  64. 3
      test/unit/setup.js
  65. 11
      test/unit/specs/HelloWorld.spec.js

18
.babelrc

@ -0,0 +1,18 @@
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"],
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
}
}
}

9
.editorconfig

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

5
.eslintignore

@ -0,0 +1,5 @@
/build/
/config/
/dist/
/*.js
/test/unit/coverage/

29
.eslintrc.js

@ -0,0 +1,29 @@
// https://eslint.org/docs/user-guide/configuring
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint'
},
env: {
browser: true,
},
extends: [
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
'plugin:vue/essential',
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
'standard'
],
// required to lint *.vue files
plugins: [
'vue'
],
// add your custom rules here
rules: {
// allow async-await
'generator-star-spacing': 'off',
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
}
}

17
.gitignore

@ -0,0 +1,17 @@
.DS_Store
node_modules/
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
/test/unit/coverage/
/test/e2e/reports/
selenium-debug.log
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln

10
.postcssrc.js

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

30
README.md

@ -0,0 +1,30 @@
# project_kuaile_serviceh5
> A Vue.js project
## Build Setup
``` bash
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
# run unit tests
npm run unit
# run e2e tests
npm run e2e
# run all tests
npm test
```
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).

41
build/build.js

@ -0,0 +1,41 @@
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})

54
build/check-versions.js

@ -0,0 +1,54 @@
'use strict'
const chalk = require('chalk')
const semver = require('semver')
const packageConfig = require('../package.json')
const shell = require('shelljs')
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
}
const versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
}
]
if (shell.which('npm')) {
versionRequirements.push({
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
})
}
module.exports = function () {
const warnings = []
for (let i = 0; i < versionRequirements.length; i++) {
const mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
warnings.push(mod.name + ': ' +
chalk.red(mod.currentVersion) + ' should be ' +
chalk.green(mod.versionRequirement)
)
}
}
if (warnings.length) {
console.log('')
console.log(chalk.yellow('To use this template, you must update following to modules:'))
console.log()
for (let i = 0; i < warnings.length; i++) {
const warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}

BIN
build/logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

101
build/utils.js

@ -0,0 +1,101 @@
'use strict'
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
const cssLoader = {
loader: 'css-loader',
options: {
sourceMap: options.sourceMap
}
}
const postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
exports.createNotifierCallback = () => {
const notifier = require('node-notifier')
return (severity, errors) => {
if (severity !== 'error') return
const error = errors[0]
const filename = error.file && error.file.split('!').pop()
notifier.notify({
title: packageConfig.name,
message: severity + ': ' + error.name,
subtitle: filename || '',
icon: path.join(__dirname, 'logo.png')
})
}
}

22
build/vue-loader.conf.js

@ -0,0 +1,22 @@
'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap
module.exports = {
loaders: utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
}

92
build/webpack.base.conf.js

@ -0,0 +1,92 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}

95
build/webpack.dev.conf.js

@ -0,0 +1,95 @@
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors
? utils.createNotifierCallback()
: undefined
}))
resolve(devWebpackConfig)
}
})
})

149
build/webpack.prod.conf.js

@ -0,0 +1,149 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const env = process.env.NODE_ENV === 'testing'
? require('../config/test.env')
: require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: process.env.NODE_ENV === 'testing'
? 'index.html'
: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig

7
config/dev.env.js

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

76
config/index.js

@ -0,0 +1,76 @@
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
// Use Eslint Loader?
// If true, your code will be linted during bundling and
// linting errors and warnings will be shown in the console.
useEslint: false,
// If true, eslint errors and warnings will also be shown in the error overlay
// in the browser.
showEslintErrorsInOverlay: false,
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
}

4
config/prod.env.js

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

7
config/test.env.js

@ -0,0 +1,7 @@
'use strict'
const merge = require('webpack-merge')
const devEnv = require('./dev.env')
module.exports = merge(devEnv, {
NODE_ENV: '"testing"'
})

65
index.html

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no,minimum-scale=1.0">
<title></title>
<script>
if(location.href.indexOf('check.cnkicom.com') > -1){
(function() {var _53code = document.createElement("script");_53code.src = "https://tb.53kf.com/code/code/2109215fd7c9fa4051aa17091f1d8f9d3/10";var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(_53code, s);})();
}
</script>
<script type="text/javascript">
(function(doc, win) {
var userAgentInfo = navigator.userAgent;
var Agents = ["Android", "iPhone",
"SymbianOS", "Windows Phone",
"iPad", "iPod"];
var isphone = false;
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
isphone = true;
break;
}
}
if(!isphone) {
var jump_true = decodeURIComponent(location.href.split('?url=')[1]);
if(jump_true) {
location.href=jump_true;
}
}
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
var recalc = function() {
var width = docEl.clientWidth;
if (width < 300) {
width = 300;
}
if(width>414){
width=414;
}
docEl.dataset.width = width
docEl.dataset.percent = 100 * (width / 750);
docEl.style.fontSize = 100 * (width / 750) + 'px';
};
recalc();
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
})(document, window);
</script>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
<script src="http://lib.baomitu.com/vue/2.6.10/vue.min.js"></script>
<script src="http://lib.baomitu.com/vue-resource/1.5.1/vue-resource.min.js"></script>
<script src="http://lib.baomitu.com/vue-lazyload/1.2.6/vue-lazyload.js"></script>
<script src="http://lib.baomitu.com/vue-router/3.0.2/vue-router.min.js"></script>
<script src="http://css.chachongz.com/assets_v2/js/vue-cookies.js"></script>
<script src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
<script src="http://cdn.bootcdn.net/ajax/libs/echarts/4.1.0/echarts.min.js"></script>
<script src="http://cdn.bootcdn.net/ajax/libs/vue-echarts/4.0.2/vue-echarts.min.js"></script>
</body>
</html>

14460
package-lock.json

File diff suppressed because it is too large

86
package.json

@ -0,0 +1,86 @@
{
"name": "project_kuaile_serviceh5",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "pengda <10266652509@qq.com>",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"build": "node build/build.js"
},
"dependencies": {
"clipboard": "^2.0.11",
"qrcode": "^1.2.0",
"qrcodejs2": "^0.0.2",
"vue": "^2.5.2",
"vue-clipboard2": "^0.1.0",
"vue-cookies": "^1.5.6",
"vue-loading-template": "^0.1.7",
"vue-resource": "^1.3.5",
"vue-router": "^2.8.0",
"vue-simple-spinner": "^1.2.10",
"vue-touch": "^2.0.0-beta.4",
"vue-wechat-title": "^2.0.4",
"vuex": "^3.1.3",
"weui": "^2.3.0",
"weui.js": "^1.2.2"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"compression-webpack-plugin": "^1.1.11",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"es6-promise": "^4.0.5",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"jquery": "^3.3.1",
"node-notifier": "^5.1.2",
"node-sass": "^4.8.3",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"sass-loader": "^6.0.7",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-lazyload": "^1.2.6",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.11.5",
"webpack-merge": "^4.1.0"
},
"externals": {
"vue-echarts": "VueECharts",
"echarts": "echarts"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

194
src/App.vue

@ -0,0 +1,194 @@
<template>
<div id="app">
<router-view :key="key" v-wechat-title="$route.meta.title"/>
</div>
</template>
<script>
export default {
name: 'App',
computed: {
key() {
return this.$route.name !== undefined ? this.$route.name + +new Date() : this.$route + +new Date();
}
},
created: function () {
}
}
</script>
<style>
@charset "utf-8";
html,
body,
h1,
h2,
h3,
h4,
h5,
p,
span,
a,
div,
ol,
ul,
li,
dl,
dt,
dd,
table,
tbody,
tfoot,
thead,
tr,
th,
td,
input,
textarea,
form {
margin: 0;
padding: 0;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
color: #404040;
}
html {
height: 100%;
}
body {
background-color: #f7f7f7;
-webkit-text-size-adjust: 100%;
min-width: 300px;
font: 0.13rem/2em sans-serif;
height: 100%;
}
em,
i {
font-style: normal;
font-weight: normal;
}
input,
textarea {
outline: none;
}
input[type="text"],
input[type="text"],
textarea {
border-radius: 0;
-webkit-appearance: none;
}
textarea {
border: 1px solid #ccc;
}
ul,
ol,
li {
list-style: none;
}
select {
background-color: #fff;
}
#app {
background: #f7f7f7;
overflow: auto;
-webkit-overflow-scrolling: touch;
height: 100%;
}
.fl {
float: left;
}
.fr {
float: right;
}
.clear:after {
display: block;
content: '';
clear: both;
}
.hide {
display: none;
}
.prompt {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 110;
}
.promptbg {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 120;
background: #000000;
opacity: 0.3;
}
.promptbox {
width: 70%;
margin-left: 15%;
position: absolute;
top: 30%;
left: 0;
z-index: 130;
background: #ffffff;
border-radius: 0.16rem;
}
.promptcontent {
font-size: 0.32rem;
color: #262626;
line-height: 0.48rem;
padding: 0.3rem;
text-align: center;
border-radius: 0.16rem 0.16rem 0 0;
word-break: break-all;
}
.promptbtn {
width: 100%;
height: 0.8rem;
border-top: 0.02rem solid #f7f7f7;
line-height: 0.8rem;
text-align: center;
font-size: 0.28rem;
color: #262626;
border-radius: 0 0 0.16rem 0.16rem;
}
.prompt-alert{
position: fixed;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
line-height: 24px;
padding: 12px 15px;
z-index: 110;
background: #000;
opacity: 0.5;
color: #fff;
border-radius: 5px;
}
.weui-btn {
z-index: 899;
}
</style>

10
src/assets/btn_add.svg

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="42px" height="42px" viewBox="0 0 42 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>Shape Copy 5</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="快乐论文" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M20.8233823,3 C10.7866977,3 3,11.1220167 3,21.1396181 C3,31.1570131 10.7866977,39 20.8233823,39 C30.8623432,39 39,31.1570131 39,21.1396181 C39,11.1220167 30.8623432,3 20.8233823,3 M0,20.9999029 C0,9.40163096 9.40163096,0 20.9999029,0 C32.5981749,0 42,9.40163096 42,20.9999029 C42,32.5960377 32.5981749,42 20.9999029,42 C9.40163096,42 0,32.5960377 0,20.9999029 Z M22.5,22.5 L22.5,29.3810196 C22.5,30.5404388 22.1760296,31.47897 21.0168046,31.47897 C19.8534999,31.47897 19.5,30.5404388 19.5,29.3810196 L19.5,22.5 L12.6127637,22.5 C11.4533445,22.5 10.514619,22.1402834 10.514619,20.9812527 C10.514619,19.8177537 11.4533445,19.5 12.6127637,19.5 L19.5,19.5 L19.5,12.5770175 C19.5,11.4175983 19.8534999,10.4790671 21.0125305,10.4790671 C22.1760296,10.4790671 22.5,11.4175983 22.5,12.5770175 L22.5,19.5 L29.4167658,19.5 C30.5759908,19.5 31.5145219,19.8177537 31.5145219,20.9769787 C31.5145219,22.1402834 30.5759908,22.5 29.4167658,22.5 L22.5,22.5 Z" id="Shape-Copy-5" fill="#000000" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

10
src/assets/btn_back.svg

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="28px" viewBox="0 0 16 28" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>btn_back copy</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="快乐论文" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M13.575363,27.9649932 L0.034472459,14.3991281 C-0.010987721,14.151118 -0.01199118,13.8511864 0.034472459,13.6011361 L13.575363,0.0352710123 C13.6798734,-0.0103313378 13.9743421,-0.0131613869 14.3718859,0.0352710123 L15.9649319,1.63125514 C16.010311,2.04803483 16.012475,2.34864736 15.9649319,2.4292472 L4.81361029,13.6011361 C4.65365222,13.8482151 4.65047328,14.1498552 4.81361029,14.3991281 L15.9649319,25.571017 C16.009296,25.6494229 16.014023,25.9494958 15.9649319,26.3690091 L14.3718859,27.9649932 C13.9780541,28.010692 13.6808768,28.0126358 13.575363,27.9649932 Z" id="btn_back-copy" fill="#000000"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

10
src/assets/btn_checked.svg

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="44px" height="44px" viewBox="0 0 44 44" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>Combined Shape Copy 2</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="快乐论文" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M44,22.2716049 C44,34.1505185 34.1505185,44 21.7283951,44 C9.84948148,44 0,34.1505185 0,22.2716049 C0,9.84948148 9.84948148,0 21.7283951,0 C34.1505185,0 44,9.84948148 44,22.2716049 Z M10.2985938,23.5127427 L16.8939563,30.6992903 C17.2698835,31.1089142 17.8816604,31.1169808 18.2638059,30.7210203 L33.7294911,14.696233 C34.1145876,14.2972149 34.1139542,13.6595793 33.7346676,13.2652045 L33.7661197,13.2979078 C33.3906309,12.9074818 32.7444989,12.8775364 32.331426,13.2398428 L18.320299,25.5290064 C17.9106714,25.8882908 17.2212814,25.9017169 16.7881987,25.5522448 L11.7469113,21.4842236 C11.3181075,21.1382042 10.7044384,21.2214936 10.3858003,21.6779677 L10.1976252,21.9475433 C9.87944354,22.4033634 9.92419217,23.104781 10.2985938,23.5127427 Z" id="Combined-Shape-Copy-2" fill="#3471EF"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

10
src/assets/btn_close.svg

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>Combined Shape Copy</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="快乐论文" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.300000012">
<path d="M18.8035221,16 L31.4193716,3.38415054 C32.1935428,2.60997929 32.1935428,1.35479969 31.4193716,0.580628439 C30.6452003,-0.193542813 29.3900207,-0.193542813 28.6158495,0.580628439 L16,13.1964779 L3.38415054,0.580628439 C2.60997929,-0.193542813 1.35479969,-0.193542813 0.580628439,0.580628439 C-0.193542813,1.35479969 -0.193542813,2.60997929 0.580628439,3.38415054 L13.1964779,16 L0.580628439,28.6158495 C-0.193542813,29.3900207 -0.193542813,30.6452003 0.580628439,31.4193716 C1.35479969,32.1935428 2.60997929,32.1935428 3.38415054,31.4193716 L16,18.8035221 L28.6158495,31.4193716 C29.3900207,32.1935428 30.6452003,32.1935428 31.4193716,31.4193716 C32.1935428,30.6452003 32.1935428,29.3900207 31.4193716,28.6158495 L18.8035221,16 Z" id="Combined-Shape-Copy" fill="#262626"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

10
src/assets/btn_next.svg

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="20px" viewBox="0 0 12 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>Rectangle Copy 5</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="快乐论文" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.300000012">
<path d="M10.1815222,19.9749951 L0.0258543443,10.2850915 C-0.00824079078,10.1079414 -0.008993385,9.8937046 0.0258543443,9.71509719 L10.1815222,0.0251935802 C10.259905,-0.00737952699 10.4807566,-0.00940099063 10.7789145,0.0251935802 L11.9736989,1.16518224 C12.0077333,1.46288202 12.0093562,1.67760526 11.9736989,1.73517657 L3.61020772,9.71509719 C3.49023917,9.8915822 3.48785496,10.1070394 3.61020772,10.2850915 L11.9736989,18.2650121 C12.006972,18.3210163 12.0105172,18.5353541 11.9736989,18.8350065 L10.7789145,19.9749951 C10.4835406,20.0076371 10.2606576,20.0090256 10.1815222,19.9749951 Z" id="Rectangle--Copy-5" fill="#000000" transform="translate(6.000000, 10.000000) scale(-1, 1) translate(-6.000000, -10.000000) "></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

10
src/assets/btn_personal.svg

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="42px" viewBox="0 0 40 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>Shape Copy</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="快乐论文" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M26.5127924,6.08183308 C24.7871441,4.36977011 22.4433669,3.4088286 20.0000012,3.41160851 C17.5566355,3.4088286 15.2128583,4.36977011 13.48721,6.08183308 C11.7560063,7.78903425 10.7842011,10.1090967 10.7871561,12.5278715 C10.7871561,15.0450807 11.8192735,17.3252241 13.48721,18.9739099 C15.207654,20.6818159 17.5436862,21.6424726 19.980404,21.6441345 L20.0195984,21.6441345 C22.4562204,21.6419983 24.7920764,20.6814141 26.5127924,18.9739099 C28.2425848,17.2659487 29.2134775,14.946194 29.2106688,12.5278715 C29.2134775,10.109549 28.2425848,7.78979435 26.5127924,6.08183308 M28.9493732,3.6702259 C31.3279244,6.01619151 32.6626434,9.20437082 32.6575923,12.5278715 C32.6575923,15.9868791 31.2422415,19.1204598 28.9493732,21.3855171 C28.3753032,21.955215 27.7466957,22.4683926 27.0724003,22.9178251 C29.7218457,23.9116216 32.128517,25.4496779 34.1339121,27.4306985 C37.8913641,31.1261588 40.0029692,35.1532393 39.9999969,40.3960376 C39.9439031,41.2973999 39.1889575,42 38.2765351,42 C37.3641126,42 36.609167,41.2973999 36.5530733,40.3960376 C36.5530733,36.881009 34.7022299,32.7970094 31.710396,29.8423057 C28.6092875,26.7763402 24.4050069,25.054656 20.0217758,25.0557288 C10.8580672,25.0545318 3.45894476,32.3672078 3.44692911,40.3960376 C3.39083534,41.2973999 2.63588973,42 1.72346731,42 C0.811044883,42 0.0560992708,41.2973999 5.50191689e-06,40.3960376 C-0.00393396768,35.1530486 2.1078195,31.1256147 5.86609024,27.4306985 C7.87035116,25.4493194 10.2763978,23.911188 12.9254246,22.9178251 C9.43595875,20.5876335 7.34380312,16.6941455 7.34241003,12.5278715 C7.34241003,9.06886391 8.75993828,5.93743835 11.0484517,3.6702259 C13.4196541,1.31613037 16.6414727,-0.00484277948 20.0000012,1.41377072e-05 C23.3579188,-0.00498513359 26.5791137,1.31605363 28.9493732,3.6702259 Z" id="Shape-Copy" fill="#262626" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

10
src/assets/btn_unchecked.svg

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="46px" height="46px" viewBox="0 0 46 46" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>Fill Copy</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="快乐论文" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-opacity="0.6">
<path d="M45,23.2716049 C45,10.8494815 35.1505185,1 22.7283951,1 C10.8494815,1 1,10.8494815 1,23.2716049 C1,35.1505185 10.8494815,45 22.7283951,45 C35.1505185,45 45,35.1505185 45,23.2716049 Z" id="Fill--Copy" stroke="#979797" stroke-width="2"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 737 B

89
src/assets/css/layout.css

@ -0,0 +1,89 @@
/*! common.css | Just for layout*/
body * {
box-sizing: border-box;
}
body {
padding: 0;
margin: 0;
font-family: PingFangSC-Regular, Roboto, Helvetica Neue, Helvetica, Tahoma,
Arial, PingFang SC-Light, Microsoft YaHei;
}
body {
scrollbar-width: none; /* firefox */
-ms-overflow-style: none; /* IE 10+ */
overflow-x: hidden;
overflow-y: auto;
}
::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
button {
margin: 0;
padding: 0;
border: 1px solid transparent;
outline: none;
background-color: transparent;
}
button:active {
opacity: 0.6;
}
.flex-col {
display: flex;
flex-direction: column;
}
.flex-row {
display: flex;
flex-direction: row;
}
.justify-start {
display: flex;
justify-content: flex-start;
}
.justify-center {
display: flex;
justify-content: center;
}
.justify-end {
display: flex;
justify-content: flex-end;
}
.justify-evenly {
display: flex;
justify-content: space-evenly;
}
.justify-around {
display: flex;
justify-content: space-around;
}
.justify-between {
display: flex;
justify-content: space-between;
}
.align-start {
display: flex;
align-items: flex-start;
}
.align-center {
display: flex;
align-items: center;
}
.align-end {
display: flex;
align-items: flex-end;
}

BIN
src/assets/images/card_secret_buy/buy_pic.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

BIN
src/assets/images/card_secret_buy/tabs_buy.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

BIN
src/assets/images/card_secret_buy/tabs_buy_on.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

BIN
src/assets/images/card_secret_buy/tabs_search.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
src/assets/images/card_secret_buy/tabs_search_on.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 942 B

BIN
src/assets/images/order_sample/order_sample_1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 B

BIN
src/assets/images/order_sample/order_sample_2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

BIN
src/assets/images/order_sample/order_sample_3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 B

BIN
src/assets/images/order_sample/order_sample_one.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
src/assets/images/order_sample/order_sample_three.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
src/assets/images/order_sample/order_sample_two.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
src/assets/images/title_pic.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
src/assets/logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

14
src/assets/pic_direction.svg

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="324px" height="100px" viewBox="0 0 324 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>Group Copy</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="快乐论文" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group-Copy">
<path d="M109.667147,53.5617677 C108.745829,53.5617677 108,54.4091825 108,55.4533186 C108.497219,56.4844395 109.052935,57 109.667147,57 L182.743763,57 C183.665081,57 184.234527,56.1846754 183.906379,55.8143012 L171.629451,43.0885539 C171.430155,42.858763 170.865909,43.0761901 169.936714,43.7408353 C169.286308,44.5053758 169.286308,45.6509478 169.936714,46.4154883 L174.389752,51.3629915 C175.042306,52.1281332 175.042306,52.2442931 174.389752,53.0094348 C174.090323,53.3573065 173.662696,53.557939 173.212512,53.5617677 L109.667147,53.5617677 Z M249.256835,100 L298.696554,100 L298.696554,95.8105 L287.858638,95.8105 L287.858638,85.575 L309.99552,85.575 C317.66503,85.575 323.902939,79.335 323.902939,71.662 L323.902939,13.913 C323.902939,10.179 322.470837,6.701 319.812433,4.092 C317.20398,1.483 313.676925,0 309.99502,0 L237.906919,0 C230.237409,0 224,6.2405 224,13.913 L224,71.611 C224,79.2835 230.237409,85.524 237.906919,85.524 L260.0448,85.524 L260.0448,95.759 L249.256835,95.759 L249.256835,100 Z M283.67118,95.8105 L264.230759,95.8105 L264.230759,85.575 L283.67118,85.575 L283.67118,95.8105 Z M312.045971,81.386 L235.95737,81.386 C231.714014,81.386 228.237409,75.908 228.237409,71.662 L228.237409,63.9385 L319.817881,63.9385 L319.817881,72.174 C319.459731,76.164 316.136476,81.386 312.045971,81.386 Z M228.186459,59.7495 L228.186459,13.913 C228.186459,9.6675 232.663063,4.189 236.906919,4.189 L310.99502,4.189 C315.238876,4.189 319.714981,9.6675 319.714981,13.913 L319.714981,59.7495 L228.186459,59.7495 Z M33.9841964,90.0967742 C36.6654754,90.0967742 38.8390816,87.9304101 38.8390816,85.2580646 C38.8390816,82.585719 36.6654754,80.4193549 33.9841964,80.4193549 C31.3029173,80.4193549 29.1293112,82.585719 29.1293112,85.2580646 C29.1293112,87.9304101 31.3029173,90.0967742 33.9841964,90.0967742 Z M55.0220322,0 L12.9463606,0 C5.796733,0 0,5.783871 0,12.9193549 L0,87.0806451 C0.00533788111,94.2073086 5.79588534,99.9857772 12.9463606,100 L55.0220322,100 C62.1716597,100 67.9683926,94.216129 67.9683927,87.0806451 L67.9683927,12.9193549 C67.9630549,5.7926914 62.1725074,0.0142228382 55.0220322,0 Z M10.9463606,4.45161289 L57.0220322,4.45161289 C60.5822813,4.45161289 63.4855026,9.35161289 63.4952125,12.9032258 L4.47318024,12.9032258 C4.48289003,9.33870967 7.37640154,4.45161289 10.9463606,4.45161289 Z M4.47318024,17.3548387 L63.4952125,17.3548387 L63.4952125,70.516129 L4.47318024,70.516129 L4.47318024,17.3548387 Z M11.9463606,95.5483871 C9.38287486,95.5483871 4.47318024,91 4.47318024,88.0806451 L4.47318024,74.9677419 L63.4952198,74.9677419 L63.4952125,88.0806451 C63.4952125,91.0806451 59,95.5483871 56.0220322,95.5483871 L11.9463606,95.5483871 Z" id="Combined-Shape" fill="#262626" opacity="0.599999964"></path>
<path d="M228.186459,59.7495 L228.186459,13.913 C228.186459,9.6675 232.663063,4.189 236.906919,4.189 L310.99502,4.189 C315.238876,4.189 319.714981,9.6675 319.714981,13.913 L319.714981,59.7495 L228.186459,59.7495 Z" id="Path" fill="#9ECFEC"></path>
<polygon id="Path" fill="#FFFFFF" points="4.47318024 17.3548387 63.4952125 17.3548387 63.4952125 70.516129 4.47318024 70.516129"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

126
src/components/H5OpenError.vue

@ -0,0 +1,126 @@
<template>
<div class="h5openerror">
<div v-wechat-title='msg'></div>
<head-title :title="title_error" :showBtn="false" :showleft="false"></head-title>
<div class="ios">
<i></i>
<div class="notsupport">{{ detail_error_one }}</div>
<div class="movetopc">{{ detail_error_two }}</div>
<div class="movetopc">{{ copy_url_host }}</div>
<div v-if="copy_url_host" class="operatebtn" v-clipboard:copy="copy_url_host" v-clipboard:success="onCopy" v-clipboard:error="onError">
复制链接
</div>
</div>
<div class="prompt" v-if="showprompt">
<div class="promptbg"></div>
<div class="promptbox">
<div class="promptcontent">{{ promptcontent }}</div>
<div class="promptbtn" @click="closeprompt">确定</div>
</div>
</div>
</div>
</template>
<script>
import headTitle from './common/headTitle.vue'
export default {
name: 'h5openerror',
data() {
return {
msg: '错误页',
copy_url_host: this.$route.query.url,
title_error: '',
detail_error_one: '',
detail_error_two: '',
promptcontent: '',
showprompt: false,
device: ''
}
},
components: {
headTitle
},
methods: {
promptshow: function (content) {
this.showprompt = true;
this.promptcontent = content;
},
closeprompt: function () {
this.showprompt = false;
this.promptcontent = '';
},
onCopy: function (e) {
this.promptshow("地址已复制,请发送到" + this.device + "去访问吧");
},
onError: function (e) {
this.promptshow('此浏览器不支持点击复制,请更换到手机微信浏览器中打开!');
},
},
mounted: function () {
let error = JSON.parse(localStorage.getItem('H5OpenError'));
this.title_error = error.title_error;
this.detail_error_one = error.detail_error_one;
this.detail_error_two = error.detail_error_two;
this.device = error.device;
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.xh5 {
background: #ffffff;
height: 100%;
}
.ios {
width: 100%;
height: 100%;
background: #f7f7f7;
position: fixed;
top: 0;
left: 0;
z-index: 10;
}
.ios i {
display: block;
width: 3.24rem;
height: 1rem;
margin: 3rem auto 0;
background: url(../assets/pic_direction.svg) 0 0 no-repeat;
background-size: 3.24rem 1rem;
}
.notsupport {
margin-top: 0.8rem;
opacity: 0.6;
font-size: 0.4rem;
color: #404B67;
line-height: 0.56rem;
text-align: center;
}
.movetopc {
margin-top: 0.3rem;
opacity: 0.4;
font-size: 0.28rem;
line-height: 0.4rem;
color: #404B67;
text-align: center;
}
.operatebtn {
width: 1.86rem;
height: 0.74rem;
border: 0.02rem solid rgba(38, 38, 38, 0.10);
border-radius: 1rem;
text-align: center;
line-height: 0.74rem;
margin-left: 2.8rem;
margin-top: 0.40rem;
font-size: 0.28rem;
}
</style>

113
src/components/HelloWorld.vue

@ -0,0 +1,113 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>Essential Links</h2>
<ul>
<li>
<a
href="https://vuejs.org"
target="_blank"
>
Core Docs
</a>
</li>
<li>
<a
href="https://forum.vuejs.org"
target="_blank"
>
Forum
</a>
</li>
<li>
<a
href="https://chat.vuejs.org"
target="_blank"
>
Community Chat
</a>
</li>
<li>
<a
href="https://twitter.com/vuejs"
target="_blank"
>
Twitter
</a>
</li>
<br>
<li>
<a
href="http://vuejs-templates.github.io/webpack/"
target="_blank"
>
Docs for This Template
</a>
</li>
</ul>
<h2>Ecosystem</h2>
<ul>
<li>
<a
href="http://router.vuejs.org/"
target="_blank"
>
vue-router
</a>
</li>
<li>
<a
href="http://vuex.vuejs.org/"
target="_blank"
>
vuex
</a>
</li>
<li>
<a
href="http://vue-loader.vuejs.org/"
target="_blank"
>
vue-loader
</a>
</li>
<li>
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
>
awesome-vue
</a>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

353
src/components/cardSecretBuy.vue

@ -0,0 +1,353 @@
<template>
<div class="cardSecretBuy">
<login :page="login_page" :mckey="mckey" @loaded="loginLoaded"></login>
<div v-if="prompt" class="prompt-alert">{{ prompt }}</div>
<div class="card-secret-buy">
<div class="card-content">
<div class="card-buy" v-if="tab==0">
<div class="card-title">
<div class="card-circle">卡密购买</div>
</div>
<div class="card-types">
<div class="card-type" v-for="(item, key) in card_type_list" @click="buyCard(item)">
<div class="type-name">{{ item.title }}</div>
<div class="type-price">{{ item.price }}</div>
</div>
</div>
</div>
<div class="card-search" v-if="tab==1">
<div class="card-title">
<div class="card-circle">卡密查询</div>
<div @click="toOrderSample()" class="card-order">订单编号指引</div>
</div>
<div class="search-input">
<input type="text" placeholder="请输入订单编号" v-model="inputValue">
<div @click="search()">搜索</div>
</div>
</div>
</div>
<div class="footernav">
<div class="itemList" @click="toTab(0)">
<img v-if="tab==0" class="tabbar_item_img1" src="../assets/images/card_secret_buy/tabs_buy_on.png" alt="">
<img v-else class="tabbar_item_img1" src="../assets/images/card_secret_buy/tabs_buy.png" alt="">
<span v-bind:class="[{'selected':tab==0}]">卡密购买</span>
</div>
<div class="itemList" @click="toTab(1)">
<img v-if="tab==1" class="tabbar_item_img1" src="../assets/images/card_secret_buy/tabs_search_on.png" alt="">
<img v-else class="tabbar_item_img1" src="../assets/images/card_secret_buy/tabs_search.png" alt="">
<span v-bind:class="[{'selected':tab==1}]">卡密搜索</span>
</div>
</div>
</div>
</div>
</template>
<script>
import Login from './common/Login.vue'
export default {
data() {
return {
prompt: '',
agent_url: "",
islogin:false,
login_page: "cardSecretBuy",
mckey: this.$route.query.mckey,
tab: 0,
card_type_list: [],
inputValue: '',
orderid: "",
};
},
methods: {
loginLoaded(){
this.islogin = true
},
promptshow(content) {
this.prompt = content;
setTimeout(() => {
this.prompt = ""
}, 2000);
},
getCardSecretTypes: function () {
this.$http.post(this.agent_url + "/h5_get_card_secret_types", {}).then(response => {
if (response.data.status) {
this.card_type_list = response.data.data;
} else {
this.promptshow(response.data.info);
}
},
response => {
this.promptshow("网络错误,请重试");
});
},
toTab: function (tab) {
this.tab = tab;
localStorage.setItem('cardSecretBuyTab', tab)
},
search: function () {
this.tid = this.inputValue;
if (this.tid == '') {
this.promptshow('请输入订单编号');
return;
}
this.$http.post(this.agent_url + "/h5_get_card_secret", {
orderid: this.tid,
}).then(response => {
if (response.data.status) {
this.is_buy = false;
this.inputValue = "";
this.toCardSecretQuery();
} else {
this.promptshow(response.data.info);
}
},
response => {
this.promptshow("网络错误,请重试");
});
},
toOrderSample: function () {
location.href = `#/orderSample/?url=${this.$route.query.url}`;
},
buyCard: function (card) {
let openid = this.$cookies.get('openid_' + this.$cookies.get('site_uid'));
var total_fee = card.price < 0.01 ? 0.01 : card.price;
let param = {
identity: openid,
total_fee: total_fee,
unique_id: card.id,
page_id: 888,
buytype: 'cardsecret',
back_url: this.agent_url,
desc: card.desc,
};
this.$http.post(this.agent_url + "/h5_service_awaken_pay", param).then(response => {
if (response.data.status) {
this.tid = response.data.data.tid;
this.callpay(response.data.data);
} else {
this.promptshow(response.data.info);
}
},
response => {
this.promptshow("网络错误,请重试");
});
},
callpay: function (data) {
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', this.jsApiCall, false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', this.jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', this.jsApiCall);
}
} else {
this.jsApiCall(data);
}
},
jsApiCall: function (data) {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": data.appId,
"timeStamp": data.timeStamp + '',
"nonceStr": data.nonceStr,
"package": data.package,
"signType": data.signType,
"paySign": data.paySign
}, (res) => {
//
if (res.errMsg.indexOf('ok') > -1) {
this.checkpayresult();
} else if (res.errMsg.indexOf('cancel') > -1) {
} else {
this.promptshow('支付失败');
}
});
},
checkpayresult: function () {
var paytype = 2;
this.$http.post(this.agent_url + "/h5_pay_result", {
tid: this.tid,
pay_type: paytype
}).then(response => {
if (response.data.status) {
this.toCardSecretQuery();
} else {
this.promptshow(response.data.info);
}
},
response => {
this.promptshow("网络错误,请重试");
});
},
toCardSecretQuery() {
location.href = "#/cardSecretQuery/?orderid=" + this.tid;
}
},
components: {
Login
},
mounted() {
if(this.islogin){
this.agent_url = localStorage.getItem('agent_url');
this.getCardSecretTypes();
}
if(localStorage.getItem('cardSecretBuyTab') != null){
this.tab = localStorage.getItem('cardSecretBuyTab')
}
}
};
</script>
<style lang="scss" scoped>
.cardSecretBuy {
background: #F8F8F8;
font-size: 17px;
height: 100vh;
}
.card-content {
padding: 20px 20px;
}
.card-title {
line-height: 20px;
display: flex;
}
.card-circle {
width: 50%;
padding-left: 30px;
background-image: url(../assets/images/title_pic.png);
background-repeat: no-repeat;
background-position: 0 70%;
}
.card-types {
background: #fff;
padding: 0 20px;
margin-top: 30px;
border: 1px solid #F8F8F8;
border-radius: 10px;
box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.1);
}
.card-type {
border-top: 1px solid #E8ECF0;
line-height: 84px;
display: flex;
}
.card-type:first-child {
border: none;
}
.type-name {
color: #071432;
width: 50%;
text-align: left;
}
.type-price {
color: #0F83FF;
width: 50%;
text-align: right;
padding-right: 20px;
background-image: url(../assets/images/card_secret_buy/buy_pic.png);
background-repeat: no-repeat;
background-position: 100% 52%;
}
.card-order {
width: 50%;
display: inline-block;
text-align: right;
font-size: 15px;
}
.search-input {
background: #fff;
display: flex;
margin: 30px 0;
border: 1px solid #BED4F1;
border-radius: 6px;
overflow: hidden;
}
.search-input input {
padding: 10px;
width: 100%;
border: none;
font-size: 16px;
}
.search-input div {
width: 105px;
line-height: 44px;
background: #fff;
color: #0F83FF;
box-sizing: border-box;
}
.search-input div:before {
content: '';
height: 5px;
border-left: 2px solid #BED4F1;
padding-right: 20px;
}
.footernav {
display: flex;
justify-content: center;
border-top: 1px solid #EEEEEE;
width: 100%;
height: 90px;
position: fixed;
z-index: 9;
box-sizing: border-box;
bottom: 0;
background: #FFFFFF;
}
.itemList {
display: flex;
justify-content: center;
align-content: center;
float: left;
width: 50%;
height: 100%;
box-sizing: border-box;
position: relative;
text-align: center;
}
.selected {
color: #000 !important;
}
.tabbar_item_img1 {
position: absolute;
width: 30px;
height: 30px;
bottom: 45px;
}
.itemList span {
font-size: 12px;
line-height: 15px;
font-weight: 400;
color: #979797;
display: block;
position: absolute;
width: 100%;
bottom: 26px;
text-align: center;
}
</style>

194
src/components/cardSecretQuery.vue

@ -0,0 +1,194 @@
<template>
<div class="cardSecretBuy">
<div v-if="prompt" class="prompt-alert">{{ prompt }}</div>
<div class="card-secret-detail">
<div class="detail-content">
<div class="detail-title">
<div class="msg1">卡密提取成功</div>
<div class="msg2">你可以<span class="blue">复制</span><span class="blue">截屏</span>或者<span
class="blue">拍照</span>留存以免遗忘
</div>
</div>
<div class="detail-info">
<div>订单编号:</div>
<div>{{ orderid }}</div>
</div>
<div class="detail-info">
<div>卡号:</div>
<div>{{ cardid }}</div>
</div>
<div class="detail-btn">
<div @click="back()" class="back">返回</div>
<div ref="copyBtn" class="copy" v-model="copyText">复制卡密</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Clipboard from 'clipboard';
export default {
data() {
return {
prompt: '',
agent_url: localStorage.getItem('agent_url'),
orderid: this.$route.query.orderid,
cardid: "",
copyText: '',
clipboardInstance: null,
};
},
methods: {
promptshow(content) {
this.prompt = content;
setTimeout(() => {
this.prompt = ""
}, 2000);
},
initClipboard() {
if (this.clipboardInstance) {
this.clipboardInstance.destroy();
}
// Clipboard
this.clipboardInstance = new Clipboard(this.$refs.copyBtn, {
text: () => this.copyText, // copyText
});
//
this.clipboardInstance.on("success", () => {
this.promptshow("复制成功");
});
//
this.clipboardInstance.on("error", () => {
this.promptshow("复制失败,请手动复制。");
});
},
getCardSecret() {
this.$http.post(this.agent_url + "/h5_get_card_secret", {
orderid: this.orderid,
}).then(response => {
if (response.data.status) {
this.cardid = response.data.data.cardid;
this.copyText = "订单编号:" + this.orderid + "\n" + "卡号:" + this.cardid;
} else {
this.promptshow(response.data.info);
}
},
response => {
this.promptshow("网络错误,请重试");
});
},
back: function () {
this.$router.go(-1);
}
},
mounted() {
this.getCardSecret()
// ref
if (this.$refs.copyBtn) {
this.initClipboard()
} else {
console.error('复制按钮未找到');
}
},
beforeDestroy() {
// Clipboard
if (this.clipboardInstance) {
this.clipboardInstance.destroy();
}
}
};
</script>
<style lang="scss" scoped>
.cardSecretBuy {
background: #F8F8F8;
font-size: 17px;
height: 100vh;
}
.card-secret-detail {
height: 100vh;
overflow: hidden;
}
.detail-content {
height: calc(100% - 120px);
background: #fff;
margin: 40px 20px;
padding: 20px;
position: relative;
}
.detail-title {
border-bottom: 1px solid #ccc;
line-height: 30px;
text-align: center;
padding: 20px 0 40px;
}
.msg1 {
font-weight: bold;
}
.msg2 {
color: #747B8B;
}
.blue {
color: #0F83FF;
}
.detail-info {
margin-top: 30px;
display: flex;
line-height: 20px;
}
.detail-info div:first-child {
text-align: left;
width: 50%;
color: #828897;
}
.detail-info div:last-child {
text-align: right;
width: 50%;
color: #071432;
}
.detail-btn {
display: flex;
width: 100%;
position: absolute;
bottom: 20px;
left: 0;
}
.back {
border: 1px solid #0F83FF;
color: #0F83FF;
}
.copy {
border: 1px solid #0F83FF;
background: #0F83FF;
color: #fff;
}
.back, .copy {
margin: 20px;
padding: 12px;
width: 50%;
text-align: center;
border-radius: 5px;
}
</style>

100
src/components/common/Login.vue

@ -0,0 +1,100 @@
<template>
<div class="login"></div>
</template>
<script>
import _global from "../utils/Global.vue";
export default {
name: 'Login',
data() {
return {
query_url:"",
agent_url: localStorage.getItem('agent_url'),
}
},
props: {
page: {
type: String,
default: ""
},
mckey: {
type: String,
default: ""
},
},
methods: {
tologin: function () {
this.$http.post(this.agent_url + "/get_wxlogin_url", {
query_url: this.query_url,
page: this.page
}).then(res => {
if (!res.data.status) {
alert("登录失败," + res.data.info);
} else {
location.href = res.data.data.loginurl;
}
}, response => {
alert("网络错误,请重试");
});
}
},
mounted() {
this.query_url = this.$route.query.url
if(!this.query_url){
let error = {
title_error:"商家尚未开通手机访问功能",
detail_error_one:"商家尚未开通手机访问功能",
}
localStorage.setItem('H5OpenError', JSON.stringify(error));
location.href = _global.hostname + '/index.html#/h5OpenError';
}
const parsedUrl = new URL(decodeURIComponent(this.query_url));
this.agent_url = parsedUrl.origin
localStorage.setItem('agent_url', this.agent_url);
this.$emit('loaded');
let isweixin = navigator.userAgent.toLowerCase().indexOf('micromessenger') > -1;
isweixin = true
if (!isweixin) {
let error = {
title_error:"只支持在微信中访问",
detail_error_one:"移动端只能在微信浏览器中访问",
detail_error_two:"请复制链接发送到手机微信端或者电脑端访问",
device:"手机微信端或者电脑端",
}
localStorage.setItem('H5OpenError', JSON.stringify(error));
location.href = _global.hostname + '/index.html#/h5OpenError?url=' + this.query_url;
}
if (this.mckey) {
this.$http.post(this.agent_url + "/h5_get_wxlogin_info", {mckey: this.mckey}).then(response => {
if (!response.data.status) {
this.tologin();
return false;
}
let uid = response.data.data.site_uid
let openid = response.data.data.openid
if (!uid || !openid) {
this.tologin();
return false;
}
window.islogin = true;
this.$cookies.set("site_uid", uid);
this.$cookies.set("openid_" + uid, openid);
}, response => {
alert("网络错误,请重试");
});
return;
}
if (!window.islogin) {
this.tologin();
}
}
}
</script>

141
src/components/common/headTitle.vue

@ -0,0 +1,141 @@
<template>
<div class="headtitle" v-cloak v-bind:class="{headerbg:headerbg}">
<div class="leftbtn" v-on:click="leftbtn" v-if="showleft"></div>
<div class="rightbtn" v-if="showBtn" v-on:click="rightbtn"></div>
<div class="rightconcern" v-if="showconcern" v-on:click="shareqrcode">+关注</div>
<div class="addbtn" v-if="showadd" v-on:click="addbtn"><i></i>添加</div>
<div class="titlecontent" v-if="!title.isredhead && title.title">{{title.title}}</div>
<div class="titlecontent" v-else-if="title.isredhead" v-bind:class="{ redstyle : title.isredhead }">正品保障 直通官网</div>
<div class="titlecontent" v-else>{{title}}</div>
</div>
</template>
<script>
export default {
name: "headTitle",
data() {
return {};
},
props: {
title: {
type: String,
default: ""
},
showBtn: {
type: Boolean,
default: true
},
headerbg: {
type: Boolean,
default: false
},
showadd: {
type: Boolean,
default: false
},
showleft: {
type: Boolean,
default: true
},
showconcern: {
type: Boolean,
default: false
}
},
methods: {
leftbtn() {
window.history.back();
},
rightbtn() {
},
addbtn() {
},
shareqrcode: function() {
},
},
};
</script>
<style scoped>
.headtitle {
width: 100%;
height: 1rem;
background: #ffffff;
position: fixed;
top: 0;
left: 0;
z-index: 100;
}
.leftbtn {
width: 0.16rem;
height: 0.28rem;
background: url(../../assets/btn_back.svg) 0.32rem 0.36rem no-repeat;
background-size: 0.16rem 0.28rem;
padding: 0.36rem 0.5rem 0.36rem 0.32rem;
position: absolute;
left: 0;
top: 0;
}
.rightbtn {
width: 0.4rem;
height: 0.42rem;
background: url(../../assets/btn_personal.svg) 0.29rem 0.32rem no-repeat;
background-size: 0.4rem 0.42rem;
padding: 0.29rem 0.32rem;
position: absolute;
bottom: 0;
right: 0;
}
.rightconcern {
width: 1.5rem;
height: 0.75rem;
padding:0;
box-sizing:border-box;
background: #FE6710/* red *//* #3471EF */;
line-height: 0.75rem;
text-align: center;
font-size: 0.32rem;
position: absolute;
border-radius: 0.1rem;
bottom: 0.125rem;
right: 0.35rem;
color:white;
}
.titlecontent {
text-align: center;
height: 100%;
line-height: 1rem;
font-size: 0.32rem;
color: #262626;
}
.addbtn {
height: 100%;
width: 2rem;
line-height: 1rem;
position: absolute;
bottom: 0;
right: 0.4rem;
font-size: 0.28rem;
color: #262626;
text-align: right;
}
.addbtn i {
position: absolute;
bottom: 0;
right: 0.66rem;
width: 0.42rem;
height: 0.42rem;
background: url(../../assets/btn_add.svg) 0.1rem 0.29rem no-repeat;
background-size: 0.42rem;
padding: 0.29rem 0.1rem;
}
.headerbg{
background:#E8E8E8;
}
.redstyle {
color:red;
}
[v-cloak] {
display: none;
}
</style>

74
src/components/orderSample.vue

@ -0,0 +1,74 @@
<template>
<div class="orderSample">
<div class="sample-title">
<div class="sample-circle">微信支付</div>
</div>
<div class="sample-content">
<div class="sample-step step1">微信列表找到微信支付</div>
<img class="step-icon" src="../assets/images/order_sample/order_sample_one.png" alt="" srcset="">
<div class="sample-step step2">微信列表找到微信支付</div>
<img class="step-icon" src="../assets/images/order_sample/order_sample_two.png" alt="" srcset="">
<div class="sample-step step3">微信列表找到微信支付</div>
<img class="step-icon" src="../assets/images/order_sample/order_sample_three.png" alt="" srcset="">
</div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.orderSample {
background: #F8F8F8;
font-size: 17px;
}
.sample-title {
line-height: 20px;
display: flex;
padding: 20px;
}
.sample-circle {
width: 50%;
padding-left: 30px;
background-image: url(../assets/images/title_pic.png);
background-repeat: no-repeat;
background-position: 0 70%;
}
.sample-content {
background: #fff;
padding:0 20px 20px;
margin:0 20px 20px;
border: 1px solid #F8F8F8;
border-radius: 10px;
box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.1);
}
.sample-step {
background-repeat: no-repeat;
background-position: 0 50%;
line-height: 60px;
padding-left: 30px;
}
.step1 {
background-image: url("../assets/images/order_sample/order_sample_1.png");
}
.step2 {
background-image: url("../assets/images/order_sample/order_sample_2.png");
}
.step3 {
background-image: url("../assets/images/order_sample/order_sample_3.png");
}
.step-icon {
width: 100%;
}
</style>

10
src/components/utils/Global.vue

@ -0,0 +1,10 @@
<script type="text/javascript">
const hostname = "http://" + window.location.hostname; //
// const hostname = "http://localhost:8082"; //
const css_url = "//css.pengda.checkcopy.com";
export default {
hostname,
css_url
};
</script>

64
src/main.js

@ -0,0 +1,64 @@
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import 'babel-polyfill';
import App from './App'
import router from './router'
import VueWechatTitle from 'vue-wechat-title'
import VueTouch from 'vue-touch'
import VueClipboard from 'vue-clipboard2'
// 导入全局变量模块
import _global from './components/utils/Global'
Vue.prototype.GLOBAL = _global
//倒入全局weui
import 'weui'
import weui from 'weui.js'
Vue.prototype.$weui = weui;
require('es6-promise').polyfill();
Vue.config.productionTip = false
Vue.use(VueWechatTitle)
Vue.use(VueTouch)
Vue.use(VueClipboard)
Vue.use(VueLazyload, {
error: '',//这个是请求失败后显示的图片
loading: 'static/loading.gif',//这个是加载的loading过渡效果
try: 4 // 这个是加载图片数量
})
Vue.http.interceptors.push(function (request, next) {//拦截器
// 跨域携带cookie
request.credentials = true;
request.crossDomain = true;
// request.Cookies = document.cookie;
next()
})
Vue.http.headers = {'Content-Type': 'application/x-www-form-urlencoded'}
Vue.http.options.xhr = {withCredentials: true}
Vue.http.options.emulateJSON = true
//判断是否登录
let cookieobj = document.cookie;
let Cookies = {};
cookieobj.split(';').forEach(l => {
var parts = l.split('=');
Cookies[parts[0].trim()] = (parts[1] || '').trim();
});
let islogin = false;
let site_uid = Cookies['site_uid'];
let openid = 'openid_' + site_uid;
if (Cookies[openid] && Cookies['site_uid']) {
islogin = true;
}
window.islogin = islogin;
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: {App},
template: '<App/>',
mounted: function () {
}
});

79
src/router/index.js

@ -0,0 +1,79 @@
import _global from "../components/utils/Global.vue";
var router = new VueRouter({
routes: [
{
path: '/h5OpenError',
name: '/H5OpenError',
component: resolve => require(['@/components/H5OpenError'], resolve), //打开页面不正确
meta: { title: '' },
},
{
path: '/cardSecretBuy',
name: '/cardSecretBuy',
component: resolve => require(['@/components/cardSecretBuy'], resolve),
meta: { title: '购买卡密' },
},
{
path: '/cardSecretQuery',
name: '/cardSecretQuery',
component: resolve => require(['@/components/cardSecretQuery'], resolve),
meta: { title: '卡密提取' },
},
{
path: '/orderSample',
name: '/orderSample',
component: resolve => require(['@/components/orderSample'], resolve),
meta: { title: '订单指引' },
}
]
});
router.afterEach((to, from) => {
(function(doc, win) {
var userAgentInfo = navigator.userAgent;
var Agents = ["Android", "iPhone",
"SymbianOS", "Windows Phone",
"iPad", "iPod"];
var isphone = false;
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
isphone = true;
break;
}
}
if(!isphone) {
var jump_true = decodeURIComponent(location.href.split('?url=')[1]);
if(jump_true) {
location.href=jump_true;
}
}
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
var recalc = function() {
var width = docEl.clientWidth;
if (width < 300) {
width = 300;
}
if(width>414){
width=414;
}
docEl.dataset.width = width
docEl.dataset.percent = 100 * (width / 750);
docEl.style.fontSize = 100 * (width / 750) + 'px';
};
recalc();
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
})(document, window);
if(typeof(islogin)!='undefined'){
if(!islogin) {
return;
}
}
window.hashistory = from.path;
document.getElementById('app') && document.getElementById('app').scrollTo(0,0);
});
export default router;

0
static/.gitkeep

BIN
static/loading.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

27
test/e2e/custom-assertions/elementCount.js

@ -0,0 +1,27 @@
// A custom Nightwatch assertion.
// The assertion name is the filename.
// Example usage:
//
// browser.assert.elementCount(selector, count)
//
// For more information on custom assertions see:
// http://nightwatchjs.org/guide#writing-custom-assertions
exports.assertion = function (selector, count) {
this.message = 'Testing if element <' + selector + '> has count: ' + count
this.expected = count
this.pass = function (val) {
return val === this.expected
}
this.value = function (res) {
return res.value
}
this.command = function (cb) {
var self = this
return this.api.execute(function (selector) {
return document.querySelectorAll(selector).length
}, [selector], function (res) {
cb.call(self, res)
})
}
}

46
test/e2e/nightwatch.conf.js

@ -0,0 +1,46 @@
require('babel-register')
var config = require('../../config')
// http://nightwatchjs.org/gettingstarted#settings-file
module.exports = {
src_folders: ['test/e2e/specs'],
output_folder: 'test/e2e/reports',
custom_assertions_path: ['test/e2e/custom-assertions'],
selenium: {
start_process: true,
server_path: require('selenium-server').path,
host: '127.0.0.1',
port: 4444,
cli_args: {
'webdriver.chrome.driver': require('chromedriver').path
}
},
test_settings: {
default: {
selenium_port: 4444,
selenium_host: 'localhost',
silent: true,
globals: {
devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
}
},
chrome: {
desiredCapabilities: {
browserName: 'chrome',
javascriptEnabled: true,
acceptSslCerts: true
}
},
firefox: {
desiredCapabilities: {
browserName: 'firefox',
javascriptEnabled: true,
acceptSslCerts: true
}
}
}
}

48
test/e2e/runner.js

@ -0,0 +1,48 @@
// 1. start the dev server using production config
process.env.NODE_ENV = 'testing'
const webpack = require('webpack')
const DevServer = require('webpack-dev-server')
const webpackConfig = require('../../build/webpack.prod.conf')
const devConfigPromise = require('../../build/webpack.dev.conf')
let server
devConfigPromise.then(devConfig => {
const devServerOptions = devConfig.devServer
const compiler = webpack(webpackConfig)
server = new DevServer(compiler, devServerOptions)
const port = devServerOptions.port
const host = devServerOptions.host
return server.listen(port, host)
})
.then(() => {
// 2. run the nightwatch test suite against it
// to run in additional browsers:
// 1. add an entry in test/e2e/nightwatch.conf.js under "test_settings"
// 2. add it to the --env flag below
// or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
// For more information on Nightwatch's config file, see
// http://nightwatchjs.org/guide#settings-file
let opts = process.argv.slice(2)
if (opts.indexOf('--config') === -1) {
opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
}
if (opts.indexOf('--env') === -1) {
opts = opts.concat(['--env', 'chrome'])
}
const spawn = require('cross-spawn')
const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
runner.on('exit', function (code) {
server.close()
process.exit(code)
})
runner.on('error', function (err) {
server.close()
throw err
})
})

19
test/e2e/specs/test.js

@ -0,0 +1,19 @@
// For authoring Nightwatch tests, see
// http://nightwatchjs.org/guide#usage
module.exports = {
'default e2e tests': function (browser) {
// automatically uses dev Server port from /config.index.js
// default: http://localhost:8080
// see nightwatch.conf.js
const devServer = browser.globals.devServerURL
browser
.url(devServer)
.waitForElementVisible('#app', 5000)
.assert.elementPresent('.hello')
.assert.containsText('h1', 'Welcome to Your Vue.js App')
.assert.elementCount('img', 1)
.end()
}
}

7
test/unit/.eslintrc

@ -0,0 +1,7 @@
{
"env": {
"jest": true
},
"globals": {
}
}

30
test/unit/jest.conf.js

@ -0,0 +1,30 @@
const path = require('path')
module.exports = {
rootDir: path.resolve(__dirname, '../../'),
moduleFileExtensions: [
'js',
'json',
'vue'
],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
transform: {
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
'.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
},
testPathIgnorePatterns: [
'<rootDir>/test/e2e'
],
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
setupFiles: ['<rootDir>/test/unit/setup'],
mapCoverage: true,
coverageDirectory: '<rootDir>/test/unit/coverage',
collectCoverageFrom: [
'src/**/*.{js,vue}',
'!src/main.js',
'!src/router/index.js',
'!**/node_modules/**'
]
}

3
test/unit/setup.js

@ -0,0 +1,3 @@
import Vue from 'vue'
Vue.config.productionTip = false

11
test/unit/specs/HelloWorld.spec.js

@ -0,0 +1,11 @@
import Vue from 'vue'
import HelloWorld from '@/components/HelloWorld'
describe('HelloWorld.vue', () => {
it('should render correct contents', () => {
const Constructor = Vue.extend(HelloWorld)
const vm = new Constructor().$mount()
expect(vm.$el.querySelector('.hello h1').textContent)
.toEqual('Welcome to Your Vue.js App')
})
})
Loading…
Cancel
Save