Commit e3160d4f authored by godwithdh's avatar godwithdh

111

parents
Pipeline #6045 failed with stages
{
"presets": [
["env", {
"modules": false
}],
"stage-2"
],
"plugins": ["transform-runtime"],
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": ["istanbul"]
}
}
}
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
.DS_Store
node_modules/
dist/
npm-debug.log
yarn-error.log
/test/unit/coverage/
/test/e2e/reports/
selenium-debug.log
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
// to edit target browsers: use "browserslist" field in package.json
"postcss-import": {},
"autoprefixer": {}
}
}
# mobile
> 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).
'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'
))
})
})
'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)
}
}
'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
}
}
// const px2remLoader = {
// loader: 'px2rem-loader',
// options: {
// remUint: 1
// }
// }
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
// const loaders = options.usePostCSS ? [cssLoader, postcssLoader, px2remLoader] : [cssLoader, px2remLoader]
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',
publicPath: '../../' // 修改路径
})
} 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')
})
}
}
'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'
}
}
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
const vuxLoader = require('vux-loader')
const webpack = require('webpack')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
let webpackConfig = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{
test: /\.scss$/,
loaders: ["style", "css", "sass","style-loader!css-loader!less-loader"]
},
]
},
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'
},
externals:{
}
}
module.exports = vuxLoader.merge(webpackConfig, {
plugins: [
'vux-ui',
'progress-bar',
{
name: 'duplicate-style',
options: {
cssProcessorOptions : {
safe: true,
zindex: false,
autoprefixer: {
add: true,
browsers: [
'iOS >= 7',
'Android >= 4.1'
]
}
}
}
},
new webpack.DefinePlugin({
'process.env':{
NODE_ENV:'"development"'
}
})
]
})
'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,
},
disableHostCheck: true
},
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)
}
})
})
'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
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
let host = 'https://weixin.huansi.net/apiproxy/huansi/Mall';
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api': {
target: host,
pathRewrite: { '^/api': '' },
changeOrigin: true,
secure: false
}
},
// Various Dev Server settings
host: '0.0.0.0', // can be overwritten by process.env.HOST
port: 8001, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/apiproxy/huansi/hszh_report/',
/**
* 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
}
}
'use strict'
module.exports = {
NODE_ENV: '"production"'
}
'use strict'
const merge = require('webpack-merge')
const devEnv = require('./dev.env')
module.exports = merge(devEnv, {
NODE_ENV: '"testing"'
})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1,minimum-scale=1,user-scalable=no">
<link href='https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons' rel="stylesheet">
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
<title>图表</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
This diff is collapsed.
{
"name": "mobile",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "zhangxiqi <tryhardagain@yeah.net>",
"private": true,
"scripts": {
"dev": "webpack-dev-server --disableHostCheck=true --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"unit": "jest --config test/unit/jest.conf.js --coverage",
"e2e": "node test/e2e/runner.js",
"test": "npm run unit && npm run e2e",
"build": "node build/build.js"
},
"dependencies": {
"axios": "^0.18.0",
"babel-polyfill": "^6.26.0",
"crypto-js": "^3.1.9-1",
"fastclick": "^1.0.6",
"layui-src": "^2.4.5",
"less": "^3.9.0",
"less-loader": "^5.0.0",
"lib-flexible": "^0.3.2",
"vue": "^2.5.2",
"vue-router": "^3.0.1",
"vue-wechat-title": "^2.0.5",
"vuetify": "^1.5.14",
"vuex": "^3.1.1",
"vux": "^2.9.4",
"vux-loader": "^1.2.9"
},
"devDependencies": {
"@babel/preset-env": "^7.4.5",
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-jest": "^21.0.2",
"babel-loader": "^7.1.1",
"babel-plugin-dynamic-import-node": "^1.2.0",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.22.0",
"chalk": "^2.0.1",
"chromedriver": "^2.27.2",
"copy-webpack-plugin": "^4.0.1",
"cross-spawn": "^5.0.1",
"css-loader": "^0.28.0",
"echarts": "^4.2.1",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"jest": "^22.0.4",
"jest-serializer-vue": "^0.3.0",
"nightwatch": "^0.9.12",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"px2rem-loader": "^0.1.9",
"rimraf": "^2.6.0",
"selenium-server": "^3.0.1",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-jest": "^1.0.2",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
<template>
<div id="app">
<v-app>
<keep-alive>
<router-view v-wechat-title="$route.meta.title"/>
</keep-alive>
</v-app>
</div>
</template>
<script>
export default {
name: 'App',
mounted(){
}
}
</script>
<style lang="less">
@import "./styles/icon";
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
background: #eef4fe;
height:100%;
width:100%;
}
* {
touch-action: pan-y;
}
</style>
<template>
<div class="hello">
<i class="layui-icon layui-icon-face-smile"></i>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
}
}
}
</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>
<template>
<div class="searchComponent">
<group>
<flexbox style="min-height:40px;border-bottom:1px solid #5E9AFE;padding:0 0.1rem;padding:0 10px;">
<div style="width:50px;text-align:center;font-size:12px;">时间纬度</div>
<flexbox-item class="padding-left-15 btns">
<button @click="changeDate(index)" v-for="(item,index) in btns" :key="index" :class="index == active ? 'active' : ''">
{{item}}
</button>
</flexbox-item>
</flexbox>
<flexbox style="min-height:40px;padding:0 10px;">
<div style="width:50px;text-align:center;font-size:12px;">日期范围</div>
<flexbox-item class="padding-left-15">
<datetime v-model="search.dBeginDate" format="YYYY-MM-DD" @on-change="searchData($event,1)"></datetime>
</flexbox-item>
<flexbox-item class="padding-right-15">
<datetime :start-date="search.dBeginDate" v-model="search.dEndDate" format="YYYY-MM-DD" @on-change="searchData($event,2)"></datetime>
</flexbox-item>
</flexbox>
</group>
</div>
</template>
<script>
import { Flexbox, FlexboxItem ,Search,Selector,XButton,Datetime,Group, Cell,Scroller,XHeader} from 'vux';
import Util from '@/libs/util.js'
export default {
name: 'searchComponent',
data () {
return {
btns:['本日','本周','本月','本年'],
active:2
}
},
props:['search'],
methods:{
searchData(e,type){
let dateList = this.btns.map(x=>Util.getDate(x));
let endDate = Util.dateFormat(new Date(),'yyyy-MM-dd');
if(type == 1){
if(dateList.indexOf(e) != -1 && this.search.dEndDate == endDate){
this.active = dateList.indexOf(e);
}else{
this.active = -1;
}
}else{
if(endDate == e && dateList.indexOf(this.search.dBeginDate) != -1){
this.active = dateList.indexOf(e);
}else{
this.active = -1;
}
}
this.global.$emit('searchData');
},
changeDate(index){
this.active = index;
this.search.dEndDate = Util.dateFormat(new Date(),'yyyy-MM-dd');
this.search.dBeginDate = Util.getDate(this.btns[index]);
}
},
components: {
Search,
Selector,
Flexbox,
FlexboxItem,
XButton,
Datetime,
XHeader,
Group,
Cell,
Scroller
},
}
</script>
<style lang="less">
.searchComponent{
.btns{
text-align: right;
font-size:12px;
button{
height: 20px;
width: 50px;
border: 1px solid grey;
border-radius: 50px;
margin-left:10px;
}
.active{
color:#5E9AFE;
border:1px solid #5E9AFE;
}
}
/deep/ .vux-cell-value{
font-size:12px;
}
}
</style>
let url = 'https://weixin.huansi.net/apiproxy/huansi/Mall'
const methodMap = {
/**
* 产品颜色销售排行TOP50
*/
getMmcolorsaletop:{url:url+'/bianalysis/mmcolorsaletop/',method:'get'},
getMmcolorsaledtltop:{url:url+'/bianalysis/mmcolorsaledtltop/',method:'get'},
/**
* 产品销售排行TOP25
*/
getMmsaletop:{url:url+'/bianalysis/mmsaletop/',method:'get'},
getMmsaledtltop:{url:url+'/bianalysis/mmsaledtltop/',method:'get'},
/**
* 客户
*/
getPbcustomer:{url:url+'/bianalysis/pbcustomer/',method:'get'},
getPbcustomerDtl:{url:url+'/bianalysis/pbcustomerdtl/',method:'get'},
/**
* 销售员
*/
getPbsales:{url:url+'/bianalysis/pbsales/',method:'get'},
getPbsalesDtl:{url:url+'/bianalysis/pbsalesdtl/',method:'get'},
/**
* 应收应付 || 实收实付
*/
getPayable:{url:url+'/bianalysis/payable/',method:'get'},
getReceivepay:{url:url+'/bianalysis/receivepay/',method:'get'},
/**
* 销售统计
*/
sellinfo:{url:`${url}/bianalysis/sellinfo/`,method:'get'},
};
export default methodMap;
import Axios from 'axios';
import Qs from 'qs';
const config = {
baseURL: '',
timeout: 300000,
withCredentials: true, //是否允许跨域
headers: {'Content-Type': 'application/json;charset=UTF-8', 'X-Requested-With': 'XMLHttpRequest'},
//返回数据类型
responseType: 'json'
};
const AsInst = Axios.create(config);
// AsInst.defaults.timeout = 300000;
//请求拦截器
AsInst.interceptors.request.use((config) => {
//若是有做鉴权token , 就给头部带上token
// if (window.localStorage.getItem('loginToken')) {
// config.headers.Authorization = `${window.localStorage.getItem('loginToken')}`;
// }
return config;
}, (err) => {
return Promise.reject(err);
});
//响应拦截器
AsInst.interceptors.response.use(response => {
//检查数据是否返回NULL
// if (response.data === null) {
// return Promise.reject(response);
// }
// //检查是否有错误
// if(response.data.code!=0){
// return Promise.reject(response);
// }
return response;
}, (error) => {
// 下面是接口回调的status ,因为我做了一些错误页面,所以都会指向对应的报错页面
if (error.response.status === 404) {
Message.error('后端服务请求404错误');
}
//请求错误时做些事
return Promise.reject(error);
});
export default AsInst;
export default {
}
import UTF8 from 'crypto-js/enc-utf8'
import sha256 from 'crypto-js/hmac-sha256'
const _getHeaderUrl = Symbol('_getHeaderUrl')
const secretKey = '018f162e804f945ee6b23aebfa863639';
const signatureUtil={
makeSignPlain(queryStringMap, body, timestamp, nonce) {
let signPlain = '';
[...queryStringMap.keys()].sort((a, b) => {
if (a.toString().toLowerCase() > b.toString().toLowerCase()) {
return 1
}
return -1
}).forEach(key => {
if (queryStringMap.get(key) !== '') {
signPlain += `${key}=${queryStringMap.get(key)}&`
}
})
if (signPlain.length > 1) {
signPlain = signPlain.substring(0, signPlain.length - 1)
}
if (body) {
signPlain += JSON.stringify(body)
}
signPlain += timestamp.toString() + nonce.toString()
// console.log('签名结果:', signPlain)
// signPlain = sha256.hmac('018f162e804f945ee6b23aebfa863639', signPlain);
signPlain = sha256(signPlain, secretKey).toString(UTF8.Utfd)
return signPlain
},
getRandom(len = 5) {
return parseInt(Math.random() * Math.pow(10, len))
},
getTimeStamp() {
return parseInt(new Date().getTime() / 1000)
},
IgnoreTransform(a, b) {
if (a.toString().toLowerCase() > b.toString().toLowerCase()) {
return 1
}
return -1
}
}
export default class HSHttpClient{
// pathData:路由参数 query: 问号参数 body: body参数
constructor(url, pathData = {}, query = {}, body = '') {
this.urlParams = new Map()
this.realUrl = url
this[_getHeaderUrl](pathData) // 处理路由参数
this.newUrl = this.getSignRequestUrl(query, body) // 处理问号参数和body参数
}
[_getHeaderUrl](params) {
for (let key in params.data) {
params.routerUrl = params.routerUrl.replace(key, encodeURIComponent(params.data[key]))
this.urlParams.set(key, params.data[key])
}
if (params.routerUrl) {
this.realUrl = this.realUrl + params.routerUrl + '/'
}
}
getSignRequestUrl(paramsObj, body = '') {
let returnUrl = ''
let tempParamsUrl = ''
if (paramsObj) {
for (var key in paramsObj) {
tempParamsUrl += `&${key}=${encodeURIComponent(paramsObj[key])}`
this.urlParams.set(key, paramsObj[key])
}
}
let timestamp = signatureUtil.getTimeStamp()
let nonce = signatureUtil.getRandom(5)
let signaPlain = signatureUtil.makeSignPlain(this.urlParams, body, timestamp, nonce)
returnUrl = `${this.realUrl}?timestamp=${timestamp}&nonce=${nonce}&signature=${signaPlain}${tempParamsUrl}`
return returnUrl
}
}
\ No newline at end of file
/**
Converts a timestamp into another date format.
```html
{{ Date.now() | date '%T' }} => '13:34:36'
{{ 'Wed Jan 20 2016 13:34:36 GMT+0800' | date '%T' }} => '13:34:36'
{{ 1453268193752 | date '%Y-%m-%d' }} => '2016-01-20'
{{ new Date | date '%I:%M:%s %p' }} => '1:39:22 PM'
```
**more date parameters are listed below:**
| param | explanation | example |
|:--:|:--|:--|
|%a | Abbreviated weekday. |`{{ timestamp | date "%a" }} => "Sat" `|
|%A |Full weekday name. |`{{ timestamp | date "%A" }} => "Tuesday" `|
|%b |Abbreviated month name. |`{{ timestamp | date "%b" }} => "Jan" `|
|%B |Full month name |`{{ timestamp | date "%B" }} => "January" `|
|%c |Preferred local date and time representation |`{{ timestamp | date "%c" }} => "Tue Apr 22 11:16:09 2014" `|
|%d |Day of the month, zero-padded (01, 02, 03, etc.). |`{{ timestamp | date "%d" }} => "04" `|
%-d |Day of the month, not zero-padded (1,2,3, etc.). |`{{ timestamp | date "%-d" }} => "4" `|
|%D |Formats the date (dd/mm/yy). |`{{ timestamp | date "%D" }} => "04/22/14" `|
|%e |Day of the month, blank-padded ( 1, 2, 3, etc.). |`{{ timestamp | date "%e" }} => "3" `|
|%F |Returns the date in ISO 8601 format (yyyy-mm-dd). |`{{ timestamp | date "%F" }} => "2014-04-22" `|
|%H |Hour of the day, 24-hour clock (00 - 23). |`{{ timestamp | date "%H" }} => "15" `|
|%I |Hour of the day, 12-hour clock (1 - 12). |`{{ timestamp | date "%I" }} => "7" `|
|%j |Day of the year (001 - 366). |`{{ timestamp | date "%j" }} => "245" `|
|%k |Hour of the day, 24-hour clock (1 - 24). |`{{ timestamp | date "%k" }} => "14" `|
|%m |Month of the year (01 - 12). |`{{ timestamp | date "%m" }} => "04" `|
|%M |Minute of the hour (00 - 59). |`{{ timestamp | date "%M" }} => "53" `|
|%p |Meridian indicator (AM/PM). |`{{ timestamp | date "%p" }} => "PM" `|
|%r |12-hour time (%I:%M:%S %p) |`{{ timestamp | date "%r" }} => "03:20:07 PM" `|
|%R |24-hour time (%H:%M) |`{{ timestamp | date "%R" }} => "15:21" `|
|%T |24-hour time (%H:%M:%S) |`{{ timestamp | date "%T" }} => "15:22:13" `|
|%U |The number of the week in the current year, starting with the first Sunday as the first day of the first week. |`{{ timestamp | date "%U" }} => "16" `|
|%W |The number of the week in the current year, starting with the first Monday as the first day of the first week. |`{{ timestamp | date "%W" }} => "16" `|
|%w |Day of the week (0 - 6, with Sunday being 0). |`{{ timestamp | date "%w" }} => "2" `|
|%x |Preferred representation for the date alone, no time. (mm/dd/yy). |`{{ timestamp | date "%x" }} => "04/22/14" `|
|%X |Preferred representation for the time. (hh:mm:ss). |`{{ timestamp | date "%X" }} => "13:17:24" `|
|%y |Year without a century (00.99). |`{{ timestamp | date "%y" }} => "14" `|
|%Y |Year with a century. |`{{ timestamp | date "%Y" }} => "2014" `|
*/
// let weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
let weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
let weekday = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
// let months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
let months = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']
// let timezone = ['上午', '下午']
// let timezones = ['AM', 'PM']
export default function date (date, formatString) {
var d = new Date(date)
var hours = 0
var month = 0
var zeroize = function (value, length) {
if (!length) {
length = 2
}
value = '' + value
for (var i = 0, zeros = ''; i < (length - value.length); i++) {
zeros += '0'
}
return zeros + value
}
function getDays () {
var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
var year = d.getFullYear()
var month = d.getMonth()
var day = d.getDate()
if (year % 100 === 0 && year % 400 === 0 || year % 4 === 0) {
days[1] = 29
}
var n = 0
for (var i = 0; i < month; i++) {
n += days[i]
}
return n + day
}
function cb (c) {
var ret = ''
switch (c) {
case '%a':
// ret = weekdays[d.getDay()].slice(0, 3)
ret = weekday[d.getDay()]
break
case '%A':
ret = weekdays[d.getDay()]
break
case '%b':
// ret = months[d.getMonth()].slice(0, 3)
ret = months[d.getMonth()]
break
case '%B':
ret = months[d.getMonth()]
break
case '%c':
ret = d.toLocaleDateString() + ' ' + d.toLocaleTimeString()
break
case '%d':
var day = d.getDate()
ret = zeroize(day)
break
case '%-d':
ret = d.getDate()
break
case '%D':
ret = '%m/%d/%Y'
break
case '%e':
ret = d.getDate()
break
case '%F':
ret = '%Y-%m-%d'
break
case '%H':
hours = d.getHours()
ret = zeroize(hours)
break
case '%I':
hours = d.getHours()
if (hours !== 12) {
hours = hours % 12
}
ret = zeroize(hours)
break
case '%j':
ret = zeroize(getDays(), 3)
break
case 'k':
ret = d.getHours()
break
case '%m':
month = d.getMonth() + 1
ret = zeroize(month, 2)
break
case '%M':
ret = zeroize(d.getMinutes(), 2)
break
case '%s':
ret = zeroize(d.getSeconds(), 2)
break
case '%p':
ret = d.getHours() < 12 ? 'AM' : 'PM'
break
case '%P':
ret = d.getHours() < 12 ? '上午' : '下午'
break
case '%r':
ret = '%I:%M:%s %p'
break
case '%R':
ret = '%H:%M'
break
case '%T':
ret = '%H:%M:%s'
break
case '%U':
ret = Math.ceil(getDays() / 7)
break
case '%w':
ret = d.getDay()
break
case '%x':
ret = '%m/%d/%y'
break
case '%X':
ret = '%h:%M:%s'
break
case '%y':
ret = d.getFullYear() % 100
break
case '%Y':
ret = d.getFullYear()
break
case '%z':
ret = '%A %P%I:%M'
break
default:
ret = c
}
return ret
}
var re = /%-?[\w]/g
if (!formatString) {
formatString = '%c'
}
formatString = formatString.replace(re, cb)
formatString = formatString.replace(re, cb)
return formatString
}
\ No newline at end of file
// 导出date的全部方法
import date from './date'
export {
date
}
\ No newline at end of file
import methodMap from './apiMap';
import AsInst from './axios';
import HSHttpClient from './crypto'
class Http {
}
Http.install = function (Vue) {
/**
* 全局请求接口
* @param method 方法
* @param opts 参数
* @param toast 是否提示
* @returns {string}
*/
Vue.prototype.request = function (method, opts, toast,header) {
let m = methodMap[method];
if (m) {
let optsType = typeof (opts);
if (optsType === null || optsType !== 'object') {
opts = {};
}
if (typeof m.method === 'undefined') {
console.log('method 错误', '缺少请求 method 方法', '\n');
return false;
}
//如果有给 toast 参数则显示 loading 加载数据
if (toast && typeof (toast) === 'boolean') {
loading();
} else if (toast && typeof (toast) === 'string') {
loading(toast);
}
let _params = opts.hasOwnProperty('params') ? opts.params : {};
let url = new HSHttpClient(m.url,{},_params).newUrl;
if (m.method === 'get') {
return Vue.prototype.apiGet(url,opts.data,toast,header);
} else if (m.method === 'post') {
return Vue.prototype.apiPost(url, opts.data,toast,header);
} else {
return false;
}
} else {
closeLoading();
console.log('url 错误', '返回结果:err = ', '无法请求,无效的请求!', '\n');
}
};
/**
* POST 请求 无提示
* @param url 请求URL
* @param data 请求数据
* @param toast 是否显示 modal
* @returns {Promise}
*/
Vue.prototype.apiPost = function (url, data, toast = false,header) {
if(!!header && JSON.stringify(header) != "{}"){
AsInst.defaults.headers.common['iProject'] = header.iProject;
}
if (toast && typeof (toast) === 'boolean') {
loading();
} else if (toast && typeof (toast) === 'string') {
loading(toast);
}
return new Promise((resolve, reject) => {
AsInst.post(url, data).then((response) => {
closeLoading();
resolve(response.data);
}).catch((error) => {
if (error.status === 200) {
if (!error.data) {
console.log('Customize Notice', error);
} else if (error.data && error.data.code == '0') {
resolve(error.data)
console.log('Customize Notice', error);
}
} else if (error.status === 500) {
console.log('Customize Notice', error);
} else {
console.log('Customize Notice', error);
}
closeLoading();
reject(error);
});
});
};
/**
* GET 请求 无提示
* @param url 请求URL
* @param data 请求数据
* @returns {Promise}
*/
Vue.prototype.apiGet = function (url, data, toast = false,header) {
if (toast && typeof (toast) === 'boolean') {
loading();
} else if (toast && typeof (toast) === 'string') {
loading(toast);
}
return new Promise((resolve, reject) => {
if(!!header && JSON.stringify(header) != "{}"){
AsInst.defaults.headers.common['iProjectId'] = header.iProject;
}
AsInst.get(url, {
params: data
}).then((response) => {
setTimeout(() => closeLoading(), 800);
resolve(response.data);
}).catch((error) => {
if (error.status === 200) {
if (!error.data) {
console.log('Customize Notice', error);
}
} else if (error.status === 500) {
console.log('Customize Notice', error);
} else {
console.log('Customize Notice', error);
}
closeLoading();
reject(error);
});
});
};
/**
* 关闭方法
*/
function loading(str){
Vue.prototype.$loading(str || '')
}
function closeLoading() {
Vue.prototype.$loading.close();
}
};
export default Http;
import './toast.css';
class Toast {
}
Toast.install = function (Vue, options) {
let opt = {
defaultType: 'bottom',
duration: '2500'
};
for (let property in options) {
opt[property] = options[property];
}
Vue.prototype.$toast = function (tips, type) {
let curType;
if (type) {
curType = type;
} else {
curType = opt.defaultType;
}
if (document.querySelector('.lx-toast')) {
// 如果toast还在,则不再执行
return;
}
const ToastTpl = Vue.extend({
template: '<div class="lx-toast lx-toast-' + curType + '">' + tips + '</div>'
});
const tpl = new ToastTpl().$mount().$el;
document.body.appendChild(tpl);
setTimeout(function () {
document.body.removeChild(tpl);
}, opt.duration);
};
['bottom', 'center', 'top'].forEach(function (type) {
Vue.prototype.$toast[type] = function (tips) {
return Vue.prototype.$toast(tips, type);
};
});
Vue.prototype.$loading = function (tips, type = '') {
let load = document.querySelector('.lx-load-mark');
if (type === 'close') {
load && document.body.removeChild(load);
} else {
if (load) {
// 如果loading还在,则不再执行
return;
}
const LoadTpl = Vue.extend({
template: '<div class="lx-load-mark"><div class="lx-load-box"><div class="lx-loading"><div class="loading_leaf loading_leaf_0"></div><div class="loading_leaf loading_leaf_1"></div><div class="loading_leaf loading_leaf_3"></div><div class="loading_leaf loading_leaf_4"></div><div class="loading_leaf loading_leaf_5"></div><div class="loading_leaf loading_leaf_6"></div><div class="loading_leaf loading_leaf_7"></div><div class="loading_leaf loading_leaf_8"></div><div class="loading_leaf loading_leaf_9"></div><div class="loading_leaf loading_leaf_10"></div><div class="loading_leaf loading_leaf_11"></div></div><div class="lx-load-content">' + tips + '</div></div></div>'
});
const tpl = new LoadTpl().$mount().$el;
document.body.appendChild(tpl);
}
};
['open', 'close'].forEach(function (type) {
Vue.prototype.$loading[type] = function (tips) {
return Vue.prototype.$loading(tips, type);
};
});
};
export default Toast;
.lx-toast{
position: fixed;
bottom:100px;
left:50%;
width:180px;
height:40px;
line-height: 40px;
padding:0 10px;
margin-left: -100px;
text-align: center;
z-index:9999;
font-size:14px;
color: #fff;
border-radius: 5px;
background: rgba(0,0,0,0.7);
animation: show-toast .5s;
-webkit-animation: show-toast .5s;
overflow: hidden;
text-overflow:ellipsis;
white-space:nowrap;
}
.lx-toast.lx-toast-top{
top:50px;
bottom:inherit;
}
.lx-toast.lx-toast-center{
top:50%;
margin-top: -20px;
bottom:inherit;
}
@keyframes show-toast
{
from {
opacity: 0;
transform: translateY(-10px);
-webkit-transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
-webkit-transform: translateY(0);
}
}
.lx-load-mark{
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 9999;
}
.lx-load-box {
position: fixed;
z-index: 3;
width: 7.6em;
min-height: 7.6em;
top: 180px;
left: 50%;
margin-left: -3.8em;
background: rgba(0,0,0,0.7);
text-align: center;
border-radius: 5px;
color: #FFFFFF;
}
.lx-load-content {
margin-top: 64%;
font-size: 14px;
}
.lx-loading{
position: absolute;
width: 0px;
left: 50%;
top: 38%;
}
.loading_leaf{
position: absolute;
top: -1px;
opacity: 0.25;
}
.loading_leaf:before {
content: " ";
position: absolute;
width: 9.14px;
height: 3.08px;
background: #d1d1d5;
box-shadow: rgba(0, 0, 0, 0.0980392) 0px 0px 1px;
border-radius: 1px;
-webkit-transform-origin: left 50% 0px;
transform-origin: left 50% 0px;
}
.loading_leaf_0 {
-webkit-animation: opacity-0 1.25s linear infinite;
animation: opacity-0 1.25s linear infinite;
}
.loading_leaf_0:before {
-webkit-transform: rotate(0deg) translate(7.92px, 0px);
transform: rotate(0deg) translate(7.92px, 0px);
}
.loading_leaf_1 {
-webkit-animation: opacity-1 1.25s linear infinite;
animation: opacity-1 1.25s linear infinite;
}
.loading_leaf_1:before {
-webkit-transform: rotate(30deg) translate(7.92px, 0px);
transform: rotate(30deg) translate(7.92px, 0px);
}
.loading_leaf_2 {
-webkit-animation: opacity-2 1.25s linear infinite;
animation: opacity-2 1.25s linear infinite;
}
.loading_leaf_2:before {
-webkit-transform: rotate(60deg) translate(7.92px, 0px);
transform: rotate(60deg) translate(7.92px, 0px);
}
.loading_leaf_3 {
-webkit-animation: opacity-3 1.25s linear infinite;
animation: opacity-3 1.25s linear infinite;
}
.loading_leaf_3:before {
-webkit-transform: rotate(90deg) translate(7.92px, 0px);
transform: rotate(90deg) translate(7.92px, 0px);
}
.loading_leaf_4 {
-webkit-animation: opacity-4 1.25s linear infinite;
animation: opacity-4 1.25s linear infinite;
}
.loading_leaf_4:before {
-webkit-transform: rotate(120deg) translate(7.92px, 0px);
transform: rotate(120deg) translate(7.92px, 0px);
}
.loading_leaf_5 {
-webkit-animation: opacity-5 1.25s linear infinite;
animation: opacity-5 1.25s linear infinite;
}
.loading_leaf_5:before {
-webkit-transform: rotate(150deg) translate(7.92px, 0px);
transform: rotate(150deg) translate(7.92px, 0px);
}
.loading_leaf_6 {
-webkit-animation: opacity-6 1.25s linear infinite;
animation: opacity-6 1.25s linear infinite;
}
.loading_leaf_6:before {
-webkit-transform: rotate(180deg) translate(7.92px, 0px);
transform: rotate(180deg) translate(7.92px, 0px);
}
.loading_leaf_7 {
-webkit-animation: opacity-7 1.25s linear infinite;
animation: opacity-7 1.25s linear infinite;
}
.loading_leaf_7:before {
-webkit-transform: rotate(210deg) translate(7.92px, 0px);
transform: rotate(210deg) translate(7.92px, 0px);
}
.loading_leaf_8 {
-webkit-animation: opacity-8 1.25s linear infinite;
animation: opacity-8 1.25s linear infinite;
}
.loading_leaf_8:before {
-webkit-transform: rotate(240deg) translate(7.92px, 0px);
transform: rotate(240deg) translate(7.92px, 0px);
}
.loading_leaf_9 {
-webkit-animation: opacity-9 1.25s linear infinite;
animation: opacity-9 1.25s linear infinite;
}
.loading_leaf_9:before {
-webkit-transform: rotate(270deg) translate(7.92px, 0px);
transform: rotate(270deg) translate(7.92px, 0px);
}
.loading_leaf_10 {
-webkit-animation: opacity-10 1.25s linear infinite;
animation: opacity-10 1.25s linear infinite;
}
.loading_leaf_10:before {
-webkit-transform: rotate(300deg) translate(7.92px, 0px);
transform: rotate(300deg) translate(7.92px, 0px);
}
.loading_leaf_11 {
-webkit-animation: opacity-11 1.25s linear infinite;
animation: opacity-11 1.25s linear infinite;
}
.loading_leaf_11:before {
-webkit-transform: rotate(330deg) translate(7.92px, 0px);
transform: rotate(330deg) translate(7.92px, 0px);
}
@-webkit-keyframes opacity-0 {
0% { opacity: 0.25; }
0.01% { opacity: 0.25; }
0.02% { opacity: 1; }
60.01% { opacity: 0.25; }
100% { opacity: 0.25; }
}
@-webkit-keyframes opacity-1 {
0% { opacity: 0.25; }
8.34333% { opacity: 0.25; }
8.35333% { opacity: 1; }
68.3433% { opacity: 0.25; }
100% { opacity: 0.25; }
}
@-webkit-keyframes opacity-2 {
0% { opacity: 0.25; }
16.6767% { opacity: 0.25; }
16.6867% { opacity: 1; }
76.6767% { opacity: 0.25; }
100% { opacity: 0.25; }
}
@-webkit-keyframes opacity-3 {
0% { opacity: 0.25; }
25.01% { opacity: 0.25; }
25.02% { opacity: 1; }
85.01% { opacity: 0.25; }
100% { opacity: 0.25; }
}
@-webkit-keyframes opacity-4 {
0% { opacity: 0.25; }
33.3433% { opacity: 0.25; }
33.3533% { opacity: 1; }
93.3433% { opacity: 0.25; }
100% { opacity: 0.25; }
}
@-webkit-keyframes opacity-5 {
0% { opacity: 0.270958333333333; }
41.6767% { opacity: 0.25; }
41.6867% { opacity: 1; }
1.67667% { opacity: 0.25; }
100% { opacity: 0.270958333333333; }
}
@-webkit-keyframes opacity-6 {
0% { opacity: 0.375125; }
50.01% { opacity: 0.25; }
50.02% { opacity: 1; }
10.01% { opacity: 0.25; }
100% { opacity: 0.375125; }
}
@-webkit-keyframes opacity-7 {
0% { opacity: 0.479291666666667; }
58.3433% { opacity: 0.25; }
58.3533% { opacity: 1; }
18.3433% { opacity: 0.25; }
100% { opacity: 0.479291666666667; }
}
@-webkit-keyframes opacity-8 {
0% { opacity: 0.583458333333333; }
66.6767% { opacity: 0.25; }
66.6867% { opacity: 1; }
26.6767% { opacity: 0.25; }
100% { opacity: 0.583458333333333; }
}
@-webkit-keyframes opacity-9 {
0% { opacity: 0.687625; }
75.01% { opacity: 0.25; }
75.02% { opacity: 1; }
35.01% { opacity: 0.25; }
100% { opacity: 0.687625; }
}
@-webkit-keyframes opacity-10 {
0% { opacity: 0.791791666666667; }
83.3433% { opacity: 0.25; }
83.3533% { opacity: 1; }
43.3433% { opacity: 0.25; }
100% { opacity: 0.791791666666667; }
}
@-webkit-keyframes opacity-11 {
0% { opacity: 0.895958333333333; }
91.6767% { opacity: 0.25; }
91.6867% { opacity: 1; }
51.6767% { opacity: 0.25; }
100% { opacity: 0.895958333333333; }
}
\ No newline at end of file
This diff is collapsed.
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue';
import FastClick from 'fastclick';
import VueRouter from 'vue-router';
import App from './App';
import Http from './libs/http';
import routes from './router';
import Util from './libs/util';
import store from './store';
import VueWechatTitle from 'vue-wechat-title';
import Toast from './libs/toast/';
// import 'lib-flexible';
// import 'layui-src/dist/css/layui.css'
// import 'layui-src/dist/layui.js'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css' // Ensure you are using css-loader
import 'babel-polyfill'
import echarts from 'echarts'
import { ConfirmPlugin } from 'vux'
Vue.use(Vuetify)
Vue.use(VueWechatTitle);
Vue.use(VueRouter);
Vue.use(Http);
Vue.use(Toast)
Vue.use(ConfirmPlugin);
Vue.prototype.global = new Vue({});
Vue.prototype.util = Util;
Vue.prototype.$echarts = echarts
function getAbsolutePath () {
let path = location.pathname
return path.substring(0, path.lastIndexOf('/') + 1)
}
const router = new VueRouter({
mode:'history',
routes,
base: getAbsolutePath()
})
FastClick.attach(document.body)
Vue.config.productionTip = false;
router.beforeEach((to, from, next) => {
next();
})
/* eslint-disable no-new */
new Vue({
router,
render: h => h(App),
router: router,
store: store,
data: {
},
mounted(){
},
created(){
}
}).$mount('#app')
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
let routes = [
{
path:'/me',
name:'me',
component: () => import('@/view/me/index.vue'),
meta: {
title: '我的'
},
redirect:'/me/info',
children:[
{
path:'/me/info',
name:'我的信息',
component: () => import('@/view/me/info.vue'),
meta: {
title: '我的信息'
}
},
{
path:'/me/help',
name:'帮助',
component: () => import('@/view/me/help.vue'),
meta: {
title: '帮助'
}
}
]
},
{
name:'main',
component: () => import('@/view/main.vue'),
path:'/chart',
children:[
{
path:'/sales',
name:'chartMmcolorsale',
component:()=> import('@/view/chart/sales/index.vue'),
meta:{
title: '图表'
}
},
{
path:'/salesDetail',
name:'chartMmcolorsaleDetail',
component:()=> import('@/view/chart/sales/detail.vue'),
meta:{
title: '图表'
}
},
{
path:'/custom',
name:'chartCustom',
component:()=> import('@/view/chart/custom/index.vue'),
meta:{
title: '图表'
}
},
{
path:'/customDetail',
name:'chartCustomDetail',
component:()=> import('@/view/chart/custom/detail.vue'),
meta:{
title: '图表'
}
},
{
path:'/income',
name:'chartIncome',
component:()=> import('@/view/chart/income/index.vue'),
meta:{
title: '图表'
}
},
{
path:'/salesStatistics',
name:'chartStatistics',
component:()=> import('@/view/chart/sales/statistics.vue'),
meta:{
title: '销售统计'
}
}
]
}
];
export default routes;
\ No newline at end of file
import Vue from 'vue';
import Vuex from 'vuex';
import app from './modules/app';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
//
},
mutations: {
//
},
actions: {},
modules: {
app
}
});
export default store;
import Util from '@/libs/util';
import Vue from 'vue';
const app = {
state: {
userInfo:{},
chartHearData:{},
iProject:5599
},
mutations: {
getUserInfo(state,obj){
state.userInfo = obj;
},
setChartHearData(state,obj){
state.chartHearData = obj;
},
setIproject(state,data){
state.iProject = data;
}
},
actions: {
getUserInfo({commit},obj){
commit('getUserInfo',obj);
},
setChartHearData({commit},obj){
commit('setChartHearData',obj);
},
setIproject({commit},data){
commit('setIproject',data)
}
}
};
export default app;
This diff is collapsed.
<style lang="less" scoped>
#chartCustomDetail{
font-size:12px;
h2{
text-align: center;
}
.center{
text-align: center;
}
/deep/ .weui-cells{
margin-top:0;
}
/deep/ .vux-datetime{
div>p{
margin-bottom: 0;
}
}
/deep/ .weui-cell_access{
padding-right: 10px;
}
/deep/ .weui-cell_access .weui-cell__ft:after{
height: 10px;
width: 10px;
margin-top: -4px;
right: 0;
}
/deep/ .weui-dialog{
max-width:60px;
}
img{
width:100%;
}
}
</style>
<template>
<div id="chartCustomDetail">
<h2>{{title}}</h2>
<div ref='chart' :style="{width: '100vw', height: '100vh',display:value.length> 0 ? 'block' : 'none'}"></div>
<img v-if="value.length<= 0" src="@/assets/noData.jpg" class="_img" alt="">
</div>
</template>
<script>
import Util from '@/libs/util.js'
import { mapState } from 'vuex';
export default {
name: 'chartCustomDetail',
data () {
return {
value:[],
title:''
}
},
async activated(){
if(this.chartHearData.type == 'pbcustomer'){
this.title = '客户';
await this.getPbcustomerDtl();
}else{
this.title = '销售员';
await this.getPbsalesDtl();
}
this.setChart()
},
computed:{
...mapState({
chartHearData:state => state.app.chartHearData,
iProject:state => state.app.iProject
})
},
mounted(){
this.myChart=this.$echarts.init(this.$refs.chart)
window.addEventListener("resize",()=>{
this.myChart.resize()
var options=this.myChart.getOption()
options.dataZoom[0].end = document.documentElement.clientWidth > document.documentElement.clientHeight ? 40 : 20
this.myChart.setOption(options);
});
},
methods:{
async getPbcustomerDtl(){
let result = await this.request('getPbcustomerDtl',{
params:this.chartHearData
},true,{iProject:this.iProject})
this.value=typeof result=='object'&&result.length>0&&result||[]
},
async getPbsalesDtl(){
let result= await this.request('getPbsalesDtl',{
params:this.chartHearData
},true,{iProject:this.iProject})
this.value=typeof result=='object'&&result.length>0&&result||[]
},
setChart(){
let options = {
color:['#5CADFF'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999'
}
}
},
toolbox: {
feature: {
// dataView: {show: true, readOnly: false},
magicType: {show: true, type: ['line', 'bar']},
restore: {show: true},
// saveAsImage: {show: true}
},
},
grid: {
left: '3%', // 与容器左侧的距离
right: '3%', // 与容器右侧的距离
containLabel: true
},
legend: {
data:['金额'],
x: 'left'
},
xAxis: [
{
type: 'category',
data: this.value.map(x => `${x.sYearMonth}`) ,
axisPointer: {
type: 'shadow'
},
axisTick: {
alignWithLabel: true
},
axisLabel: {
interval:0
}
},
],
yAxis: [
{
type: 'value',
name: '金额',
axisLabel: {
formatter: '¥{value}'
},
scale:true
}
],
series: [
{
name:'金额',
type:'bar',
data: this.value.map(x => `${x.nAmount||0}`) ,
}
],
dataZoom: [{
type: 'inside',
show: true, //flase直接隐藏图形
xAxisIndex: [0],
left: '9%', //滚动条靠左侧的百分比
start: 0,//滚动条的起始位置
end: 20 //滚动条的截止位置(按比例分割你的柱状图x轴长度)
}] 
};
this.myChart.setOption(options);
this.myChart.resize()
}
}
}
</script>
This diff is collapsed.
<style lang="less" scoped>
#chartIncome{
font-size:12px;
h2{
text-align: center;
}
.center{
text-align: center;
}
/deep/ .weui-cells{
margin-top:0;
}
/deep/ .vux-datetime{
div>p{
margin-bottom: 0;
}
}
/deep/ .weui-cell_access{
padding-right: 10px;
}
/deep/ .weui-cell_access .weui-cell__ft:after{
height: 10px;
width: 10px;
margin-top: -4px;
right: 0;
}
/deep/ .weui-dialog{
max-width:60px;
}
img{
width:100%;
}
}
</style>
<template>
<div id="chartIncome">
<searchComponent :search="search" />
<h2 style="margin-top:0.2rem;">应收-应付</h2>
<div id="myChart1" :style="{width: '100vw', height: '300%',display:payable.length > 0 ? 'block' : 'none'}"></div>
<img v-if="payable.length <= 0" src="@/assets/noData.jpg" class="_img" alt="">
<h2>实收-实付</h2>
<div id="myChart2" :style="{width: '100vw', height: '300%',display:receivepay.length > 0 ? 'block' : 'none'}"></div>
<img v-if="receivepay.length <= 0" src="@/assets/noData.jpg" class="_img" alt="">
</div>
</template>
<script>
import Util from '@/libs/util.js'
import searchComponent from '@/components/search'
import { Confirm } from 'vux'
export default {
name: 'chartIncome',
data () {
return {
payable:[],
receivepay:[],
search:{
dBeginDate:Util.dateFormat(new Date(),'yyyy-MM-01'),
dEndDate:Util.dateFormat(new Date(),'yyyy-MM-dd'),
},
iProject:5599,
toUrl:{
"myChart20":"/shopVersion/pages/form/revenue",
"myChart21":"/shopVersion/pages/form/expenditure",
"myChart10":"/shopVersion/pages/form/receipts",
"myChart11":"/shopVersion/pages/form/payment",
},
myChart1:null,
myChart2:null,
}
},
activated(){
setTimeout(()=>{
this.myChart1.resize()
this.myChart2.resize()
})
},
async mounted(){
this.createChart('myChart1')
this.createChart('myChart2')
window.addEventListener('resize',()=>{
setTimeout(()=>{
this.myChart1.resize()
this.myChart2.resize()
})
})
this.iProject = this.$route.query.id||window.location.search.slice(1)
this.$store.dispatch('setIproject',this.iProject);
await this.getPayable();
await this.getReceivepay();
this.global.$on('searchData',async ()=>{
await this.getPayable();
await this.getReceivepay();
});
},
components:{
searchComponent,
Confirm
},
methods:{
createChart(name){
let time=null
// 基于准备好的dom,初始化echarts实例
var charts=this.$echarts.init(document.getElementById(name))
charts.getZr().on('mousedown',param=>{
const pointInPixel = [param.offsetX, param.offsetY]
if(charts.containPixel('grid',pointInPixel)){
let index=charts.convertFromPixel({ seriesIndex: 0 }, [param.offsetX, param.offsetY])[0]
time=setTimeout(()=>{
if(param.name=='差价')return;
var options=charts.getOption()
options.tooltip[0].show=false
charts.setOption(options)
this.$vux.confirm.show({
title:"提示",
content:"是否查看详情",
onConfirm:()=>{
wx.miniProgram.navigateTo({
url:this.toUrl[name+index]
})
options.tooltip[0].show=true
charts.setOption(options)
},
onCancel(){
options.tooltip[0].show=true
charts.setOption(options)
}
})
},500)
}
})
charts.getZr().on('mousemove',()=>{
clearTimeout(time)
})
charts.getZr().on('mouseup',()=>{
clearTimeout(time)
})
this[name]=charts
},
async getPayable(){
let result = await this.request('getPayable',{
params:this.search
},true,{iProject:this.iProject})
this.payable = result;
this.drawLine1('myChart1');
},
async getReceivepay(){
let result= await this.request('getReceivepay',{
params:this.search
},true,{iProject:this.iProject})
this.receivepay = result;
this.drawLine2('myChart2');
},
drawLine1(id){
// 绘制图表
this.setChart(this.myChart1,'myChart1')
},
drawLine2(id){
// 绘制图表
this.setChart(this.myChart2,'myChart2')
},
setChart(myChart,id){
let seriesData = [];
let xAxisData = [];
let data = id == 'myChart1' ? this.payable[0] : this.receivepay[0];
let fieldNames = ['nSumReceive','nSumPay','nAmountYE']
for(let x of fieldNames){
let fieldName;
if(x == 'nSumPay'){
fieldName = id == 'myChart1' ? '应付' : '实付';
}else if(x == 'nSumReceive'){
fieldName = id == 'myChart1' ? '应收' : '实收';
}else if(x == 'nAmountYE'){
fieldName = '差价'
}
xAxisData.push(fieldName);
if(data[x] > 0){
seriesData.push(data[x]||0)
}else{
seriesData.push(data[x]||0)
}
}
let options = {
tooltip : {
trigger: 'axis',
axisPointer : { // 坐标轴指示器,坐标轴触发有效
type : 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
legend: {
data:seriesData
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type : 'category',
axisTick : {show: false},
data : xAxisData
},
yAxis: {
type : 'value',
position: 'top',
splitLine: {lineStyle:{type:'dashed'}},
},
series : [
{
name:'',
type:'bar',
stack: '总量',
label: {
normal: {
show: false,
formatter: '{b}'
}
},
barMaxWidth:40,
data:seriesData
}
]
}
myChart.setOption(options);
}
}
}
</script>
<style lang="less" scoped>
#chartMmcolorsale{
font-size:12px;
h2{
text-align: center;
}
.center{
text-align: center;
}
/deep/ .weui-cells{
margin-top:0;
}
/deep/ .vux-datetime{
div>p{
margin-bottom: 0;
}
}
/deep/ .weui-cell_access{
padding-right: 10px;
}
/deep/ .weui-cell_access .weui-cell__ft:after{
height: 10px;
width: 10px;
margin-top: -4px;
right: 0;
}
/deep/ .weui-dialog{
max-width:60px;
}
img{
width:100%;
}
}
</style>
<template>
<div id="chartMmcolorsale">
<h2>{{title}}</h2>
<div ref='chart' :style="{width: '100vw', height: '100vh',display:value.length > 0 ? 'block' : 'none'}"></div>
<img v-if="value.lenght<= 0" src="@/assets/noData.jpg" class="_img" alt="">
</div>
</template>
<script>
import Util from '@/libs/util.js';
import { mapState } from 'vuex';
export default {
name: 'chartMmcolorsaleDetail',
data () {
return {
mmcolorsaledeltop:[],
mmsaledtltop:[],
value:[],
title:'',
myChart:null
}
},
async activated(){
if(this.chartHearData.type == 'mmsaletop'){
this.title = '产品销售排行';
await this.getMmsaledtltop();
}else{
this.title = '产品颜色销售排行';
await this.getMmcolorsaledtltop();
}
this.setChart()
},
computed:{
...mapState({
chartHearData:state => state.app.chartHearData,
iProject:state => state.app.iProject
})
},
mounted(){
this.myChart=this.$echarts.init(this.$refs.chart)
window.addEventListener("resize",()=>{
var options=this.myChart.getOption()
options.dataZoom[0].end = document.documentElement.clientWidth > document.documentElement.clientHeight ? 40 : 20
this.myChart.setOption(options);
this.myChart.resize()
});
},
methods:{
async getMmcolorsaledtltop(){
let result = await this.request('getMmcolorsaledtltop',{
params:this.chartHearData
},true,{iProject:this.iProject})
this.value=typeof result=='object'&&result.length>0&&result||[]
},
async getMmsaledtltop(){
let result= await this.request('getMmsaledtltop',{
params:this.chartHearData
},true,{iProject:this.iProject})
this.value=typeof result=='object'&&result.length>0&&result||[]
},
setChart(){
let options = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999'
}
}
},
toolbox: {
feature: {
// dataView: {show: true, readOnly: false},
magicType: {show: true, type: ['line', 'bar']},
restore: {show: true},
// saveAsImage: {show: true}
},
},
grid: {
left: '3%',
right: '3%',
bottom: '10%',
containLabel: true
},
legend: {
data:['金额','数量'],
x: 'left'
},
xAxis: [
{
type: 'category',
data: this.value.map(x => `${x.sYearMonth}`),
axisPointer: {
type: 'shadow'
},
axisTick: {
alignWithLabel: true
},
axisLabel: {
interval:0
}
},
],
yAxis: [
{
type: 'value',
name: '金额',
axisLabel: {
formatter: '¥{value}'
},
scale:true
},
{
type: 'value',
name: '数量',
scale:true,
axisLabel: {
formatter: '¥{value}'
}
}
],
series: [
{
name:'金额',
type:'bar',
data:this.value.map(x => `${x.nAmount}`)
},
{
name:'数量',
type:'line',
yAxisIndex: 1,
data:this.value.map(x => `${x.nQty}`)
}
],
dataZoom: [{
            type: 'inside',
            show: true, //flase直接隐藏图形
            xAxisIndex: [0],
            left: '9%', //滚动条靠左侧的百分比
            start: 0,//滚动条的起始位置
            end: 20 //滚动条的截止位置(按比例分割你的柱状图x轴长度)
            }] 
};
this.myChart.setOption(options);
this.myChart.resize()
}
}
}
</script>
<style lang="less" scoped>
#chartMmcolorsale{
font-size:12px;
h2{
text-align: center;
}
.center{
text-align: center;
}
/deep/ .weui-cells{
margin-top:0;
}
/deep/ .vux-datetime{
div>p{
margin-bottom: 0;
}
}
/deep/ .weui-cell_access{
padding-right: 10px;
}
/deep/ .weui-cell_access .weui-cell__ft:after{
height: 10px;
width: 10px;
margin-top: -4px;
right: 0;
}
/deep/ .weui-dialog{
max-width:60px;
}
img{
width:100%;
}
}
</style>
<template>
<div id="chartMmcolorsale">
<searchComponent :search="search" />
<h2 >产品颜色销售排行</h2>
<div id="myChart1" :style="{width: '100vw', height: '300%',display:mmcolorsaletop.length > 0 ? 'block' : 'none'}"></div>
<img v-if="mmcolorsaletop.length <= 0" src="@/assets/noData.jpg" class="_img" alt="">
<h2>产品销售排行</h2>
<div id="myChart2" :style="{width: '100vw', height: '300%',display:mmsaletop.length > 0 ? 'block' : 'none'}"></div>
<img v-if="mmcolorsaletop.length <= 0" src="@/assets/noData.jpg" class="_img" alt="">
</div>
</template>
<script>
import Util from '@/libs/util.js'
import searchComponent from '@/components/search'
import { Confirm } from 'vux'
export default {
name: 'chartMmcolorsale',
data () {
return {
mmcolorsaletop:[],
mmsaletop:[],
search:{
dBeginDate:Util.dateFormat(new Date(),'yyyy-MM-01'),
dEndDate:Util.dateFormat(new Date(),'yyyy-MM-dd'),
},
timer:null,
iProject:5599,
i:0,
myChart1:null,
myChart2:null
}
},
async mounted(){
this.myChart1 = this.$echarts.init(document.getElementById('myChart1'))
this.myChart2 = this.$echarts.init(document.getElementById('myChart2'))
this.initChart(this.myChart1,'myChart1');
this.initChart(this.myChart2,'myChart2');
this.iProject = window.location.search.slice(1,window.location.search.length)
this.$store.dispatch('setIproject',this.iProject);
await this.getMmcolorsaletop();
await this.getMmsaletop();
this.global.$on('searchData',async ()=>{
await this.getMmcolorsaletop();
await this.getMmsaletop();
});
},
components:{
searchComponent,
Confirm
},
methods:{
async getMmcolorsaletop(){
let result = await this.request('getMmcolorsaletop',{
params:this.search
},true,{iProject:this.iProject})
this.mmcolorsaletop = result;
this.setChart(this.myChart1,'myChart1')
},
async getMmsaletop(){
let result= await this.request('getMmsaletop',{
params:this.search
},true,{iProject:this.iProject})
this.mmsaletop = result;
this.setChart(this.myChart2,'myChart2')
},
setChart(myChart,id){
var that = this;
let options = {
color:['#5cadff','#1c2438'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#111'
}
}
},
toolbox: {
feature: {
// dataView: {show: true, readOnly: false},
magicType: {show: true, type: ['line', 'bar']},
restore: {show: true},
// saveAsImage: {show: true}
},
},
grid: {
left: '2%', // 与容器左侧的距离
right: '2%', // 与容器右侧的距离
containLabel: true
},
legend: {
data:['金额','数量'],
x: 'left'
},
xAxis: [
{
type: 'category',
data: id == 'myChart1' ? this.mmcolorsaletop.map(x => `${x.sMaterialNo}\n${x.sColorNo || ''}\n${x.sUnit || ''}`) : this.mmsaletop.map(x => `${x.sMaterialNo}\n${x.sUnit || ''}`),
axisPointer: {
type: 'shadow'
},
axisTick: {
alignWithLabel: true
},
axisLabel: {
interval:0
}
},
],
yAxis: [
{
type: 'value',
name: '金额',
axisLabel: {
formatter: '{value}'
},
scale:true
},
{
type: 'value',
name: '数量',
scale:true,
axisLabel: {
formatter: '{value}'
}
}
],
series: [
{
name:'金额',
type:'bar',
data:id == 'myChart1' ? this.mmcolorsaletop.map(x => `${x.nAmount}`) : this.mmsaletop.map(x => `${x.nAmount}`),
barMaxWidth:40
},
{
name:'数量',
type:'line',
yAxisIndex: 1,
data:'myChart1' ? this.mmcolorsaletop.map(x => `${x.nQty}`) : this.mmsaletop.map(x => `${x.nQty}`),
barMaxWidth:40
}
],
dataZoom: [{
            type: 'inside',
            show: true, //flase直接隐藏图形
            xAxisIndex: [0],
            left: '9%', //滚动条靠左侧的百分比
            start: 0,//滚动条的起始位置
            end: 15 //滚动条的截止位置(按比例分割你的柱状图x轴长度)
            }],
};
myChart.setOption(options);
window.addEventListener("resize",function(){
myChart.resize()
if(id == 'myChart1'){
options.dataZoom[0].end = document.documentElement.clientWidth > document.documentElement.clientHeight ? 20 : 10
}else{
options.dataZoom[0].end = document.documentElement.clientWidth > document.documentElement.clientHeight ? 70 : 50
}
myChart.setOption(options);
});
},
initChart(myChart,id){
myChart.on('mousedown', (param)=> {
// this.switch = false;
this.timer = setTimeout(()=>{
// this.i = 0;
// options.tooltip.show = false;
// myChart.setOption(options);
// if(!this.switch){
longPress(param)
// }
},2000);
});
myChart.on('mousemove', (param)=> {
window.clearTimeout(this.timer);
});
myChart.on('mouseup', (param)=> {
console.log(this.timer)
window.clearTimeout(this.timer);
});
var that = this;
function longPress(param){
that.$vux.confirm.show({
title: '提示',
content: '是否查看详情',
// 组件除show外的属性
onCancel : () => {
// options.tooltip.show = true;
// myChart.setOption(options);
},
onConfirm : () => {
let index = param.dataIndex;
let data = {};
if(id == 'myChart1'){
data = Object.assign(that.pbcustomer[index],{type:'pbcustomer'})
}else{
data = Object.assign(that.pbsales[index],{type:'pbsales'});
}
that.$store.dispatch('setChartHearData',data).then(()=>{
that.$router.push({name:'chartCustomDetail'});
});
// options.tooltip.show = true;
// myChart.setOption(options);
}
})
}
}
}
}
</script>
This diff is collapsed.
<template>
<div class="main">
<v-app>
<keep-alive>
<router-view></router-view>
</keep-alive>
</v-app>
</div>
</template>
<script>
export default {
name: 'main',
data () {
return {
}
}
}
</script>
<style lang="less">
</style>
<template>
<div class="about">
</div>
</template>
<script>
export default {
name: 'about',
data () {
return {
}
}
}
</script>
<style lang="less">
</style>
<template>
<div class="help">
1111
</div>
</template>
<script>
export default {
name: 'help',
data () {
return {
}
},
created(){
}
}
</script>
<style lang="less">
</style>
<template>
<div class="me_index">
<v-app>
<keep-alive>
<router-view></router-view>
</keep-alive>
</v-app>
</div>
</template>
<script>
export default {
name: 'me_index',
data () {
return {
}
}
}
</script>
<style lang="less">
</style>
This diff is collapsed.
This diff is collapsed.
<template>
<div class="orderList">
</div>
</template>
<script>
export default {
name: 'orderList',
data () {
return {
}
}
}
</script>
<style lang="less">
</style>
// 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)
})
}
}
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
}
}
}
}
This diff is collapsed.
// 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()
}
}
{
"env": {
"jest": true
},
"globals": {
}
}
This diff is collapsed.
import Vue from 'vue'
Vue.config.productionTip = false
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment