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 source diff could not be displayed because it is too large. You can view the blob instead.
{
"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
import Axios from 'axios';
var now = new Date(); //当前日期
var nowDayOfWeek = now.getDay(); //今天本周的第几天
var nowDay = now.getDate(); //当前日
var nowMonth = now.getMonth(); //当前月
var nowYear = now.getYear(); //当前年
nowYear += (nowYear < 2000) ? 1900 : 0; //
let util = {
};
util.title = function (title) {
title = title || '';
window.document.title = title;
};
/**
* 返回当前日期
* @returns {string}
*/
util.currentDate = () => {
let myDate = new Date();
let year = parseInt(myDate.getFullYear()); //获取完整的年份(4位,1970-????)
let month = parseInt(myDate.getMonth()) + 1; //获取当前月份(0-11,0代表1月)
let day = parseInt(myDate.getDate()); //获取当前日(1-31)
//小于10的时候
if (month < 10) {
month = 0 + month.toString();
}
if (day < 10) {
day = 0 + day.toString();
}
return year.toString() + '-' + month + '-' +day;
};
/**
* 给一个日期返回时间戳
* @param date
* @returns {number}
*/
util.getTimestamp = (date) => {
if (date) {
return Date.parse(new Date(date));
}
return Date.parse(new Date());
};
util.fullscreenEvent = function (vm) {
vm.$store.commit('initCachepage');
// 权限菜单过滤相关
vm.$store.commit('updateMenulist');
// 全屏相关
};
util.getType = function (obj) {
//tostring会返回对应不同的标签的构造函数
var toString = Object.prototype.toString;
var map = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object'
};
if (obj instanceof Element) {
return 'element';
}
return map[toString.call(obj)];
}
/**
* 深拷贝
* @param {} data
*/
util.deepClone = function (data) {
var type = util.getType(data);
var obj;
if (type === 'array') {
obj = [];
} else if (type === 'object') {
obj = {};
} else {
//不再具有下一层次
return data;
}
if (type === 'array') {
for (var i = 0, len = data.length; i < len; i++) {
obj.push(util.deepClone(data[i]));
}
} else if (type === 'object') {
for (var key in data) {
obj[key] = util.deepClone(data[key]);
}
}
return obj;
}
util.dateFormat = function (str, fmt) {
var usedDate = new Date(str);
var o = {
"M+": usedDate.getMonth() + 1, //月份
"d+": usedDate.getDate(), //日
"h+": usedDate.getHours(), //小时
"m+": usedDate.getMinutes(), //分
"s+": usedDate.getSeconds(), //秒
"q+": Math.floor((usedDate.getMonth() + 3) / 3), //季度
"S": usedDate.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (usedDate.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}
util.cutDate = function (date, cutDay, boolean) {
var Now_Timestamp = date.getTime();
var CutDay_Timestamp = cutDay * 1000 * 60 * 60 * 24;
var New_Timestamp = Now_Timestamp - CutDay_Timestamp;
return util.dateFormat(new Date(New_Timestamp), 'yyyy-MM-dd');
}
/**
* 去字符串空格
* @param {*} str
*/
util.Trim = function (str) {
return str.replace(/(^\s*)|(\s*$)/g, "");
}
/**
* 手机正则验证
*/
util.isMobile = function (value) {
return /^(13[0-9]|15[0-9]|16[0-9]|17[0-9]|1[89][0-9]|14[57])[0-9]{8}$/.test(this.Trim(value)) || /^(0\d{2,3}-\d{7,8})/.test(value);
}
/**
*保留两位小数
//功能:将浮点数四舍五入,取小数点后2位 } x
*/
util.toDecimal = function (x) {
var f = parseFloat(x);
if (isNaN(f)) {
return;
}
f = Math.round(x * 100) / 100;
return f;
}
var _AgentInfo = {
deviceType: "", // pc or mobile
OSname: "", // windows, Android, linux and so on...
browserName: "", // chrome, safari, firefox, IE and so on...
browserVer: "", // browser version, important if in IE environment.
adaptType: 0, // A type value, Adapt to the screen due to width
_init: function () {
_AgentInfo.setDeviceAndOS();
_AgentInfo.setBrowser();
},
setDeviceAndOS: function () {
var name = "unknown";
if (window.navigator.userAgent.indexOf("Android") != -1) {
name = "Android";
} else if (window.navigator.userAgent.indexOf("iPhone") != -1) {
name = "iPhone";
} else if (window.navigator.userAgent.indexOf("SymbianOS") != -1) {
name = "SymbianOS";
} else if (window.navigator.userAgent.indexOf("Windows Phone") != -1) {
name = "Windows Phone";
} else if (window.navigator.userAgent.indexOf("iPad") != -1) {
name = "iPad";
} else if (window.navigator.userAgent.indexOf("iPod") != -1) {
name = "iPod";
}
if (name != "unknown") {
_AgentInfo.OSname = name;
_AgentInfo.deviceType = "mobile";
return;
}
if (window.navigator.userAgent.indexOf("Windows NT 10.0") != -1) {
name = "Windows 10";
} else if (window.navigator.userAgent.indexOf("Windows NT 6.2") != -1) {
name = "Windows 8";
} else if (window.navigator.userAgent.indexOf("Windows NT 6.1") != -1) {
name = "Windows 7";
} else if (window.navigator.userAgent.indexOf("Windows NT 6.0") != -1) {
name = "Windows Vista";
} else if (window.navigator.userAgent.indexOf("Windows NT 5.1") != -1) {
name = "Windows XP";
} else if (window.navigator.userAgent.indexOf("Windows NT 5.0") != -1) {
name = "Windows 2000";
} else if (window.navigator.userAgent.indexOf("Mac") != -1) {
name = "Mac/iOS";
} else if (window.navigator.userAgent.indexOf("Linux") != -1) {
name = "Linux";
} else if (window.navigator.userAgent.indexOf("X11") != -1) {
name = "UNIX";
}
_AgentInfo.OSname = name;
_AgentInfo.deviceType = "pc";
},
setBrowser: function () {
var nAgt = navigator.userAgent;
var browserName = navigator.appName;
var fullVersion = '' + parseFloat(navigator.appVersion);
var majorVersion = parseInt(navigator.appVersion, 10);
var nameOffset, verOffset, ix;
if ((verOffset = nAgt.indexOf("Opera")) != -1) { // In Opera, the true version is after "Opera" or after "Version"
browserName = "Opera";
fullVersion = nAgt.substring(verOffset + 6);
if ((verOffset = nAgt.indexOf("Version")) != -1)
fullVersion = nAgt.substring(verOffset + 8);
} else if ((nAgt.indexOf("Trident")) != -1) { // ( ver >= ie7) In MSIE, the true version is after "MSIE" in userAgent
if ((verOffset = nAgt.indexOf("MSIE")) != -1) {
fullVersion = nAgt.substring(verOffset + 5);
} else {
fullVersion = '11.0';
}
if (fullVersion == 5) {
fullVersion = "11.0";
}
browserName = "IE";
} else if ((verOffset = nAgt.indexOf("Chrome")) != -1) { // In Chrome, the true version is after "Chrome"
browserName = "Chrome";
fullVersion = nAgt.substring(verOffset + 7);
} else if ((verOffset = nAgt.indexOf("Safari")) != -1) { // In Safari, the true version is after "Safari" or after "Version"
browserName = "Safari";
fullVersion = nAgt.substring(verOffset + 7);
if ((verOffset = nAgt.indexOf("Version")) != -1)
fullVersion = nAgt.substring(verOffset + 8);
} else if ((verOffset = nAgt.indexOf("Firefox")) != -1) { // In Firefox, the true version is after "Firefox"
browserName = "Firefox";
fullVersion = nAgt.substring(verOffset + 8);
} else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) < (verOffset = nAgt.lastIndexOf('/'))) { // In most other browsers, "name/version" is at the end of userAgent
browserName = nAgt.substring(nameOffset, verOffset);
fullVersion = nAgt.substring(verOffset + 1);
if (browserName.toLowerCase() == browserName.toUpperCase()) {
browserName = navigator.appName;
}
}
if ((ix = fullVersion.indexOf(";")) != -1) // trim the fullVersion string at semicolon/space if present
fullVersion = fullVersion.substring(0, ix);
if ((ix = fullVersion.indexOf(" ")) != -1)
fullVersion = fullVersion.substring(0, ix);
majorVersion = parseInt('' + fullVersion, 10);
if (isNaN(majorVersion)) {
fullVersion = '' + parseFloat(navigator.appVersion);
majorVersion = parseInt(navigator.appVersion, 10);
}
_AgentInfo.browserName = browserName;
_AgentInfo.browserVer = fullVersion;
},
isMobile: function () {
if (_AgentInfo.deviceType == "mobile") {
return true;
}
return false;
},
setAdaptType() { // A type value, Adapt to the screen due to width. For convenient
if (screen.width <= 374) {
_AgentInfo.adaptType = 0;
} else if (screen.width <= 413) {
_AgentInfo.adaptType = 1;
} else {
_AgentInfo.adaptType = 2;
}
}
}
_AgentInfo._init();
util.agentInfo = _AgentInfo;
util.getWeekStartDate = function () {
var weekStartDate;
if (nowDayOfWeek == 0) {
weekStartDate = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek - 6);
} else {
weekStartDate = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek + 1);
}
return util.dateFormat(weekStartDate, 'yyyy-MM-dd')
}
util.getYearStartDate = function () {
//获得当前年份4位年
var currentYear = now.getFullYear();
//本年第一天
var currentYearFirstDate = new Date(currentYear, 0, 1);
return util.dateFormat(currentYearFirstDate, 'yyyy-MM-dd');
}
/**
* 格式化金额为千分位显示
*/
util.toThousands = function (num) {
if (num) {
return num.toString().replace(/\d+/, function (n) {
return n.replace(/(\d)(?=(\d{3})+$)/g, function ($1) {
return $1 + ",";
});
});
} else {
return 0;
}
}
/**
* 小数转换为百分数
*/
util.toPercent = function (point) {
var str = Number(point * 100).toFixed(2);
str += "%";
return str;
}
util.arrayToTree = function (data, id, pid) { //将ID、ParentID这种数据格式转换为树格式
if (!data || !data.length) return [];
var targetData = []; //存储数据的容器(返回)
var records = {};
var itemLength = data.length; //数据集合的个数
for (var i = 0; i < itemLength; i++) {
var o = data[i];
records[o[id]] = o;
}
for (var i = 0; i < itemLength; i++) {
var currentData = data[i];
var parentData = records[currentData[pid]];
if (!parentData) {
targetData.push(currentData);
continue;
}
parentData.children = parentData.children || [];
parentData.children.push(currentData);
}
return targetData;
}
util.code2name = function(arr,x,y,value){
let data;
arr.map(k=>{
if(k[x] == value){
data = k[y];
}
})
return data;
}
//判断是IOS还是Android
util.isIos = function() {
var userAgent = navigator.userAgent;
var isAndroid = userAgent.indexOf('Android') > -1 || userAgent.indexOf('Adr') > -1; //android终端
var isiOS = !!userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
if (isAndroid) {
return false;
} else if (isiOS) {
return true;
}
}
util.getDate = (type) => {
var date = new Date();
switch(type){
case '本日':
return util.dateFormat(new Date(),'yyyy-MM-dd');
break;
case '本周':
var day = date.getDay() || 7;
return util.dateFormat(new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1 - day),'yyyy-MM-dd');
break;
case '本月':
return util.dateFormat(new Date(),'yyyy-MM') + '-01';
break;
case '本年':
return `${date.getFullYear()}-01-01`
break;
default:
break;
}
}
// util.pageReturn = function(){
// /*微信自带返回按钮,不刷新,刷新页面start*/
// if (util.isIos()) {
// var isPageHide = false;
// window.addEventListener('pageshow', function () {
// if (isPageHide) {
// window.location.reload();
// }
// });
// window.addEventListener('pagehide', function () {
// isPageHide = true;
// });
// } else {
// var needRefresh = sessionStorage.getItem("need-refresh");
// if (needRefresh) {
// sessionStorage.removeItem("need-refresh");
// window.location.reload();
// }
// }
// }
export default util;
\ No newline at end of file
// 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;
@keyframes icon-spin {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
.iconfont-spin {
-webkit-animation: icon-spin 2s infinite linear;
animation: icon-spin 2s infinite linear;
display: inline-block;
}
.iconfont-pulse {
-webkit-animation: icon-spin 1s infinite steps(8);
animation: icon-spin 1s infinite steps(8);
display: inline-block;
}
[class*="icon-"] {
font-family: "iconfont" !important;
font-size: inherit;
font-style: normal;
}
@font-face {font-family: "iconfont";
src: url('//at.alicdn.com/t/font_533566_yfq2d9wdij.eot?t=1545239985831'); /* IE9*/
src: url('//at.alicdn.com/t/font_533566_yfq2d9wdij.eot?t=1545239985831#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
url('//at.alicdn.com/t/font_533566_yfq2d9wdij.ttf?t=1545239985831') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('//at.alicdn.com/t/font_533566_yfq2d9wdij.svg?t=1545239985831#iconfont') format('svg'); /* iOS 4.1- */
}
.icon-appreciate:before { content: "\e644"; }
.icon-check:before { content: "\e645"; }
.icon-close:before { content: "\e646"; }
.icon-edit:before { content: "\e649"; }
.icon-emoji:before { content: "\e64a"; }
.icon-favorfill:before { content: "\e64b"; }
.icon-favor:before { content: "\e64c"; }
.icon-loading:before { content: "\e64f"; }
.icon-locationfill:before { content: "\e650"; }
.icon-location:before { content: "\e651"; }
.icon-phone:before { content: "\e652"; }
.icon-roundcheckfill:before { content: "\e656"; }
.icon-roundcheck:before { content: "\e657"; }
.icon-roundclosefill:before { content: "\e658"; }
.icon-roundclose:before { content: "\e659"; }
.icon-roundrightfill:before { content: "\e65a"; }
.icon-roundright:before { content: "\e65b"; }
.icon-search:before { content: "\e65c"; }
.icon-taxi:before { content: "\e65d"; }
.icon-timefill:before { content: "\e65e"; }
.icon-time:before { content: "\e65f"; }
.icon-unfold:before { content: "\e661"; }
.icon-warnfill:before { content: "\e662"; }
.icon-warn:before { content: "\e663"; }
.icon-camerafill:before { content: "\e664"; }
.icon-camera:before { content: "\e665"; }
.icon-commentfill:before { content: "\e666"; }
.icon-comment:before { content: "\e667"; }
.icon-likefill:before { content: "\e668"; }
.icon-like:before { content: "\e669"; }
.icon-notificationfill:before { content: "\e66a"; }
.icon-notification:before { content: "\e66b"; }
.icon-order:before { content: "\e66c"; }
.icon-samefill:before { content: "\e66d"; }
.icon-same:before { content: "\e66e"; }
.icon-deliver:before { content: "\e671"; }
.icon-evaluate:before { content: "\e672"; }
.icon-pay:before { content: "\e673"; }
.icon-send:before { content: "\e675"; }
.icon-shop:before { content: "\e676"; }
.icon-ticket:before { content: "\e677"; }
.icon-back:before { content: "\e679"; }
.icon-cascades:before { content: "\e67c"; }
.icon-discover:before { content: "\e67e"; }
.icon-list:before { content: "\e682"; }
.icon-more:before { content: "\e684"; }
.icon-scan:before { content: "\e689"; }
.icon-settings:before { content: "\e68a"; }
.icon-questionfill:before { content: "\e690"; }
.icon-question:before { content: "\e691"; }
.icon-shopfill:before { content: "\e697"; }
.icon-form:before { content: "\e699"; }
.icon-pic:before { content: "\e69b"; }
.icon-filter:before { content: "\e69c"; }
.icon-footprint:before { content: "\e69d"; }
.icon-top:before { content: "\e69e"; }
.icon-pulldown:before { content: "\e69f"; }
.icon-pullup:before { content: "\e6a0"; }
.icon-right:before { content: "\e6a3"; }
.icon-refresh:before { content: "\e6a4"; }
.icon-moreandroid:before { content: "\e6a5"; }
.icon-deletefill:before { content: "\e6a6"; }
.icon-refund:before { content: "\e6ac"; }
.icon-cart:before { content: "\e6af"; }
.icon-qrcode:before { content: "\e6b0"; }
.icon-remind:before { content: "\e6b2"; }
.icon-delete:before { content: "\e6b4"; }
.icon-profile:before { content: "\e6b7"; }
.icon-home:before { content: "\e6b8"; }
.icon-cartfill:before { content: "\e6b9"; }
.icon-discoverfill:before { content: "\e6ba"; }
.icon-homefill:before { content: "\e6bb"; }
.icon-message:before { content: "\e6bc"; }
.icon-addressbook:before { content: "\e6bd"; }
.icon-link:before { content: "\e6bf"; }
.icon-lock:before { content: "\e6c0"; }
.icon-unlock:before { content: "\e6c2"; }
.icon-vip:before { content: "\e6c3"; }
.icon-weibo:before { content: "\e6c4"; }
.icon-activity:before { content: "\e6c5"; }
.icon-friendaddfill:before { content: "\e6c9"; }
.icon-friendadd:before { content: "\e6ca"; }
.icon-friendfamous:before { content: "\e6cb"; }
.icon-friend:before { content: "\e6cc"; }
.icon-goods:before { content: "\e6cd"; }
.icon-selection:before { content: "\e6ce"; }
.icon-explore:before { content: "\e6d2"; }
.icon-present:before { content: "\e6d3"; }
.icon-squarecheckfill:before { content: "\e6d4"; }
.icon-square:before { content: "\e6d5"; }
.icon-squarecheck:before { content: "\e6d6"; }
.icon-round:before { content: "\e6d7"; }
.icon-roundaddfill:before { content: "\e6d8"; }
.icon-roundadd:before { content: "\e6d9"; }
.icon-add:before { content: "\e6da"; }
.icon-notificationforbidfill:before { content: "\e6db"; }
.icon-explorefill:before { content: "\e6dd"; }
.icon-fold:before { content: "\e6de"; }
.icon-game:before { content: "\e6df"; }
.icon-redpacket:before { content: "\e6e0"; }
.icon-selectionfill:before { content: "\e6e1"; }
.icon-similar:before { content: "\e6e2"; }
.icon-appreciatefill:before { content: "\e6e3"; }
.icon-infofill:before { content: "\e6e4"; }
.icon-info:before { content: "\e6e5"; }
.icon-forwardfill:before { content: "\e6ea"; }
.icon-forward:before { content: "\e6eb"; }
.icon-rechargefill:before { content: "\e6ec"; }
.icon-recharge:before { content: "\e6ed"; }
.icon-vipcard:before { content: "\e6ee"; }
.icon-voice:before { content: "\e6ef"; }
.icon-voicefill:before { content: "\e6f0"; }
.icon-friendfavor:before { content: "\e6f1"; }
.icon-wifi:before { content: "\e6f2"; }
.icon-share:before { content: "\e6f3"; }
.icon-wefill:before { content: "\e6f4"; }
.icon-we:before { content: "\e6f5"; }
.icon-lightauto:before { content: "\e6f6"; }
.icon-lightforbid:before { content: "\e6f7"; }
.icon-lightfill:before { content: "\e6f8"; }
.icon-camerarotate:before { content: "\e6f9"; }
.icon-light:before { content: "\e6fa"; }
.icon-barcode:before { content: "\e6fb"; }
.icon-flashlightclose:before { content: "\e6fc"; }
.icon-flashlightopen:before { content: "\e6fd"; }
.icon-searchlist:before { content: "\e6fe"; }
.icon-service:before { content: "\e6ff"; }
.icon-sort:before { content: "\e700"; }
.icon-down:before { content: "\e703"; }
.icon-mobile:before { content: "\e704"; }
.icon-mobilefill:before { content: "\e705"; }
.icon-copy:before { content: "\e706"; }
.icon-countdownfill:before { content: "\e707"; }
.icon-countdown:before { content: "\e708"; }
.icon-noticefill:before { content: "\e709"; }
.icon-notice:before { content: "\e70a"; }
.icon-upstagefill:before { content: "\e70e"; }
.icon-upstage:before { content: "\e70f"; }
.icon-babyfill:before { content: "\e710"; }
.icon-baby:before { content: "\e711"; }
.icon-brandfill:before { content: "\e712"; }
.icon-brand:before { content: "\e713"; }
.icon-choicenessfill:before { content: "\e714"; }
.icon-choiceness:before { content: "\e715"; }
.icon-clothesfill:before { content: "\e716"; }
.icon-clothes:before { content: "\e717"; }
.icon-creativefill:before { content: "\e718"; }
.icon-creative:before { content: "\e719"; }
.icon-female:before { content: "\e71a"; }
.icon-keyboard:before { content: "\e71b"; }
.icon-male:before { content: "\e71c"; }
.icon-newfill:before { content: "\e71d"; }
.icon-new:before { content: "\e71e"; }
.icon-pullleft:before { content: "\e71f"; }
.icon-pullright:before { content: "\e720"; }
.icon-rankfill:before { content: "\e721"; }
.icon-rank:before { content: "\e722"; }
.icon-bad:before { content: "\e723"; }
.icon-cameraadd:before { content: "\e724"; }
.icon-focus:before { content: "\e725"; }
.icon-friendfill:before { content: "\e726"; }
.icon-cameraaddfill:before { content: "\e727"; }
.icon-apps:before { content: "\e729"; }
.icon-paintfill:before { content: "\e72a"; }
.icon-paint:before { content: "\e72b"; }
.icon-picfill:before { content: "\e72c"; }
.icon-refresharrow:before { content: "\e72d"; }
.icon-colorlens:before { content: "\e6e6"; }
.icon-markfill:before { content: "\e730"; }
.icon-mark:before { content: "\e731"; }
.icon-presentfill:before { content: "\e732"; }
.icon-repeal:before { content: "\e733"; }
.icon-album:before { content: "\e734"; }
.icon-peoplefill:before { content: "\e735"; }
.icon-people:before { content: "\e736"; }
.icon-servicefill:before { content: "\e737"; }
.icon-repair:before { content: "\e738"; }
.icon-file:before { content: "\e739"; }
.icon-repairfill:before { content: "\e73a"; }
.icon-taoxiaopu:before { content: "\e73b"; }
.icon-weixin:before { content: "\e612"; }
.icon-attentionfill:before { content: "\e73c"; }
.icon-attention:before { content: "\e73d"; }
.icon-commandfill:before { content: "\e73e"; }
.icon-command:before { content: "\e73f"; }
.icon-communityfill:before { content: "\e740"; }
.icon-community:before { content: "\e741"; }
.icon-read:before { content: "\e742"; }
.icon-calendar:before { content: "\e74a"; }
.icon-cut:before { content: "\e74b"; }
.icon-magic:before { content: "\e74c"; }
.icon-backwardfill:before { content: "\e74d"; }
.icon-playfill:before { content: "\e74f"; }
.icon-stop:before { content: "\e750"; }
.icon-tagfill:before { content: "\e751"; }
.icon-tag:before { content: "\e752"; }
.icon-group:before { content: "\e753"; }
.icon-all:before { content: "\e755"; }
.icon-backdelete:before { content: "\e756"; }
.icon-hotfill:before { content: "\e757"; }
.icon-hot:before { content: "\e758"; }
.icon-post:before { content: "\e759"; }
.icon-radiobox:before { content: "\e75b"; }
.icon-rounddown:before { content: "\e75c"; }
.icon-upload:before { content: "\e75d"; }
.icon-writefill:before { content: "\e760"; }
.icon-write:before { content: "\e761"; }
.icon-radioboxfill:before { content: "\e763"; }
.icon-punch:before { content: "\e764"; }
.icon-shake:before { content: "\e765"; }
.icon-move:before { content: "\e768"; }
.icon-safe:before { content: "\e769"; }
.icon-activityfill:before { content: "\e775"; }
.icon-crownfill:before { content: "\e776"; }
.icon-crown:before { content: "\e777"; }
.icon-goodsfill:before { content: "\e778"; }
.icon-messagefill:before { content: "\e779"; }
.icon-profilefill:before { content: "\e77a"; }
.icon-sound:before { content: "\e77b"; }
.icon-sponsorfill:before { content: "\e77c"; }
.icon-sponsor:before { content: "\e77d"; }
.icon-upblock:before { content: "\e77e"; }
.icon-weblock:before { content: "\e77f"; }
.icon-weunblock:before { content: "\e780"; }
.icon-my:before { content: "\e78b"; }
.icon-myfill:before { content: "\e78c"; }
.icon-emojifill:before { content: "\e78d"; }
.icon-emojiflashfill:before { content: "\e78e"; }
.icon-flashbuyfill:before { content: "\e78f"; }
.icon-text:before { content: "\e791"; }
.icon-goodsfavor:before { content: "\e794"; }
.icon-musicfill:before { content: "\e795"; }
.icon-musicforbidfill:before { content: "\e796"; }
.icon-card:before { content: "\e624"; }
.icon-triangledownfill:before { content: "\e79b"; }
.icon-triangleupfill:before { content: "\e79c"; }
.icon-roundleftfill-copy:before { content: "\e79e"; }
.icon-font:before { content: "\e76a"; }
.icon-title:before { content: "\e82f"; }
.icon-recordfill:before { content: "\e7a4"; }
.icon-record:before { content: "\e7a6"; }
.icon-cardboardfill:before { content: "\e7a9"; }
.icon-cardboard:before { content: "\e7aa"; }
.icon-formfill:before { content: "\e7ab"; }
.icon-coin:before { content: "\e7ac"; }
.icon-cardboardforbid:before { content: "\e7af"; }
.icon-circlefill:before { content: "\e7b0"; }
.icon-circle:before { content: "\e7b1"; }
.icon-attentionforbid:before { content: "\e7b2"; }
.icon-attentionforbidfill:before { content: "\e7b3"; }
.icon-attentionfavorfill:before { content: "\e7b4"; }
.icon-attentionfavor:before { content: "\e7b5"; }
.icon-titles:before { content: "\e701"; }
.icon-icloading:before { content: "\e67a"; }
.icon-full:before { content: "\e7bc"; }
.icon-mail:before { content: "\e7bd"; }
.icon-peoplelist:before { content: "\e7be"; }
.icon-goodsnewfill:before { content: "\e7bf"; }
.icon-goodsnew:before { content: "\e7c0"; }
.icon-medalfill:before { content: "\e7c1"; }
.icon-medal:before { content: "\e7c2"; }
.icon-newsfill:before { content: "\e7c3"; }
.icon-newshotfill:before { content: "\e7c4"; }
.icon-newshot:before { content: "\e7c5"; }
.icon-news:before { content: "\e7c6"; }
.icon-videofill:before { content: "\e7c7"; }
.icon-video:before { content: "\e7c8"; }
.icon-exit:before { content: "\e7cb"; }
.icon-skinfill:before { content: "\e7cc"; }
.icon-skin:before { content: "\e7cd"; }
.icon-moneybagfill:before { content: "\e7ce"; }
.icon-usefullfill:before { content: "\e7cf"; }
.icon-usefull:before { content: "\e7d0"; }
.icon-moneybag:before { content: "\e7d1"; }
.icon-redpacket_fill:before { content: "\e7d3"; }
.icon-subscription:before { content: "\e7d4"; }
.icon-loading1:before { content: "\e633"; }
.icon-github:before { content: "\e692"; }
.icon-global:before { content: "\e7eb"; }
.icon-settingsfill:before { content: "\e6ab"; }
.icon-back_android:before { content: "\e7ed"; }
.icon-expressman:before { content: "\e7ef"; }
.icon-evaluate_fill:before { content: "\e7f0"; }
.icon-group_fill:before { content: "\e7f5"; }
.icon-play_forward_fill:before { content: "\e7f6"; }
.icon-deliver_fill:before { content: "\e7f7"; }
.icon-notice_forbid_fill:before { content: "\e7f8"; }
.icon-fork:before { content: "\e60c"; }
.icon-pick:before { content: "\e7fa"; }
.icon-wenzi:before { content: "\e6a7"; }
.icon-ellipse:before { content: "\e600"; }
.icon-qr_code:before { content: "\e61b"; }
.icon-dianhua:before { content: "\e64d"; }
.icon-icon:before { content: "\e602"; }
.icon-loading2:before { content: "\e7f1"; }
.icon-btn:before { content: "\e601"; }
<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>
<style lang="less" scoped>
#chartCustom{
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="chartCustom">
<searchComponent :search="search" />
<h2>客户</h2>
<div ref="myChart1" :style="{width: '100vw', height: '300%',display:pbcustomer.length > 0 ? 'block' : 'none'}"></div>
<img v-if="pbcustomer.length <= 0" src="@/assets/noData.jpg" class="_img" alt="">
<h2>销售员</h2>
<div ref="myChart2" :style="{width: '100vw', height: '300%',display:pbsales.length > 0 ? 'block' : 'none'}"></div>
<img v-if="pbsales.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'
import { clearTimeout, setTimeout } from 'timers';
export default {
name: 'chartCustom',
data () {
return {
pbcustomer:[],
pbsales:[],
search:{
dBeginDate:Util.dateFormat(new Date(),'yyyy-MM-01'),
dEndDate:Util.dateFormat(new Date(),'yyyy-MM-dd'),
},
iProject:5599,
myChart1:null,
myChart2:null,
}
},
async mounted(){
window.c=this
this.createChart('myChart1')
this.createChart('myChart2')
window.addEventListener("resize",()=>{
setTimeout(()=>{
this.resize(this.myChart1)
this.resize(this.myChart2)
})
});
// 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 = this.$route.query.id||window.location.search.slice(1)
this.$store.dispatch('setIproject',this.iProject);
await this.getPbcustomer();
await this.getPbsales();
this.global.$on('searchData',async ()=>{
await this.getPbcustomer();
await this.getPbsales();
});
},
activated(){
setTimeout(()=>{
this.resize(this.myChart1)
this.resize(this.myChart2)
})
},
components:{
searchComponent,
Confirm
},
methods:{
createChart(name){
var charts=this.$echarts.init(this.$refs[name])
let time=0
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(()=>{
this.$vux.confirm.show({
title: '提示',
content: '是否查看详情',
onConfirm : () => {
let data = {};
if(name == 'myChart1'){
data = Object.assign(this.pbcustomer[index],{type:'pbcustomer'})
}else{
data = Object.assign(this.pbsales[index],{type:'pbsales'});
}
this.$store.dispatch('setChartHearData',data).then(()=>{
this.$router.push({name:'chartCustomDetail'});
});
}
})
},500);
}
});
charts.getZr().on('mousemove', (param)=> {
clearTimeout(time);
});
charts.getZr().on('mouseup', (param)=> {
clearTimeout(time);
});
this[name]=charts
},
resize(chart){
var option=chart.getOption()
if(!option)return;
option.dataZoom[0].end=option.dataZoom[0].start+(window.innerWidth*0.9)/option.xAxis[0].data.length
chart.setOption(option)
chart.resize()
},
async getPbcustomer(){
let result = await this.request('getPbcustomer',{
params:this.search
},true,{iProject:this.iProject})
this.pbcustomer = typeof result=='object'&&result.length>0&&result.map(v=>{
v.name=`${v.sCustomerName||''}\n${v.sCustomerNo||''}`
return v
})||[];
this.setChart(this.myChart1,this.pbcustomer)
},
async getPbsales(){
let result= await this.request('getPbsales',{
params:this.search
},true,{iProject:this.iProject})
this.pbsales = typeof result=='object'&&result.length>0&&result.map(v=>{
v.name=`${v.sSalesName||''}\n${v.sSalesNo||''}`
return v
})||[];
this.setChart(this.myChart2,this.pbsales)
},
setChart(myChart,value){
let options = {
title:{
subtext:"长按查看详情",
subtextStyle:{
color:"red",
verticalAlign:"top",
},
padding:[0,0,0,25],
right:6,
},
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: '2%', // 与容器左侧的距离
right: '2%', // 与容器右侧的距离
containLabel: true
},
// legend: {
// data:['金额'],
// x: 'left'
// },
xAxis: [
{
type: 'category',
data: value.map(x => x.name) ,
axisPointer: {
type: 'shadow'
},
axisTick: {
alignWithLabel: true
},
axisLabel: {
interval:0
}
},
],
yAxis: [
{
type: 'value',
name: '金额',
axisLabel: {
formatter: '{value}'
},
scale:true
}
],
series: [
{
name:'金额',
type:'bar',
data: value.map(x => `${x.nAmount}`) ,
barMaxWidth:40,
label:{
show:true,
position:"top",
color:'#6B9BF7',
formatter:val=>{
return `${val.data}`
}
},
itemStyle:{
color:"#6B9BF7",
}
}
],
dataZoom: [{
type: 'inside',
show: true, //flase直接隐藏图形
xAxisIndex: [0],
left: '9%', //滚动条靠左侧的百分比
start: 0,//滚动条的起始位置
end: (window.innerWidth*0.9)/value.length //滚动条的截止位置(按比例分割你的柱状图x轴长度)
}] 
};
myChart.setOption(options);
},
initChart(myChart,id){
myChart.getZr().on('mousedown', (param)=> {
this.timer = setTimeout(()=>{
longPress(param)
},500);
});
myChart.getZr().on('mousemove', (param)=> {
window.clearTimeout(this.timer);
});
myChart.getZr().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>
<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>
<style lang="less" scoped>
#statistics{
background:#f2f2f2;
>.double{
display:flex;
>.card{
flex-grow:1;
width:50%;
}
}
.card{
border-radius: 6px;
background:#fff;
box-shadow: 1px 1px 10px -1px #888;
overflow: hidden;
margin:6px;
position:relative;
.imgBC{
position:absolute;
top:32px;
}
img{
max-height: 80%;
left: 50%;
transform: translate(-50%,0);
}
>.head{
background:#009BDE;
padding:5px 0;
color:#fff;
text-align: center;
}
>.foot{
display:flex;
font-size:10px;
>div{
flex-grow:1;
width:50%;
margin:4px 0;
text-align: center;
>p{
margin:2px 0;
&:last-child{
color:#009BDE;
}
}
}
}
}
}
</style>
<template>
<div id="statistics">
<searchComponent :search='search' />
<div class='double'>
<div class="card">
<div class="head">月总订单金额同比率</div>
<div ref='chart1' style="width:100%;height:150px;"/>
</div>
<div class="card">
<div class="head">月总订单金额环比率</div>
<div ref='chart2' style="width:100%;height:150px;"/>
</div>
</div>
<div class="card">
<div class="head">销售排行</div>
<div ref='chart3' :style="{width:'100%',height:'180px',opacity:chartData.set3.length>0?'1':'0'}" />
<img v-if="chartData.set3.length==0" src="@/assets/noData.jpg" class="imgBC" />
<div class="foot">
<div style="border-right:1px solid #009BDE;">
<p>销售笔数</p>
<p >{{chartData.set4.iSellCount}}</p>
</div>
<div>
<p>销售额</p>
<p>{{chartData.set4.nSellAmount}}</p>
</div>
</div>
</div>
<div class="card">
<div class="head">产品颜色销售排行</div>
<div ref='chart5' :style="{width:'100%',height:'230px',opacity:chartData.set5.length>0?'1':'0'}" />
<img v-if="chartData.set5.length==0" src="@/assets/noData.jpg" class="imgBC" />
</div>
<div class="card">
<div class="head">产品销售排行</div>
<div ref='chart6' :style="{width:'100%',height:'230px',opacity:chartData.set6.length>0?'1':'0'}" />
<img v-if="chartData.set6.length==0" src="@/assets/noData.jpg" class="imgBC" />
</div>
</div>
</template>
<script>
import Util from '@/libs/util.js'
import searchComponent from '@/components/search'
import { Confirm } from 'vux'
import { clearTimeout, setTimeout } from 'timers';
import { toUnicode } from 'punycode';
export default {
name:"statistics",
components:{searchComponent},
data(){
return{
search:{
dBeginDate:Util.dateFormat(new Date(),'yyyy-MM-01'),
dEndDate:Util.dateFormat(new Date(),'yyyy-MM-dd'),
},
iProject:5599,
chartData:{
set3:[],
set4:{
iSellCount:0,
nSellAmount:0,
},
set5:[],
set6:[],
},
chart1:null,
chart2:null,
chart3:null,
chart5:null,
chart6:null,
}
},
created(){
window.s=this
},
activated(){
setTimeout(()=>{
this.chart1.resize()
this.chart2.resize()
this.resize(this.chart3,1.15)
this.resize(this.chart5,1.35)
this.resize(this.chart6,1.35)
})
},
mounted(){
window.h=this
this.createChart('chart1')
this.createChart('chart2')
this.createChart('chart3')
this.createChart('chart5','set5',true)
this.createChart('chart6','set6',true)
window.addEventListener('resize',()=>{
setTimeout(()=>{
this.chart1.resize()
this.chart2.resize()
this.resize(this.chart3,1.15)
this.resize(this.chart5,1.35)
this.resize(this.chart6,1.35)
})
})
this.iProject=this.$route.query.id||window.location.search.slice(1)
this.$store.dispatch('setIproject',this.iProject);
this.searchData()
this.global.$on('searchData',()=>{
this.searchData()
})
},
methods:{
createChart(name,kield,isLinstener){
var myChart=this.$echarts.init(this.$refs[name])
if(isLinstener){
let time=0
myChart.getZr().on('mousedown',param=>{
const pointInPixel = [param.offsetX, param.offsetY]
if (myChart.containPixel('grid', pointInPixel)) {
let index = myChart.convertFromPixel({ seriesIndex: 0 }, [param.offsetX, param.offsetY])[0]
time=setTimeout(()=>{
var data=this.chartData[kield]
var options=myChart.getOption()
options.tooltip[0].show=false
myChart.setOption(options)
this.$vux.confirm.show({
title:"提示",
content:"是否查看详情",
onConfirm:()=>{
this.$store.dispatch('setChartHearData',data[index]).then(()=>{
this.$router.push({name:"chartMmcolorsaleDetail"});
})
options.tooltip[0].show=true
myChart.setOption(options)
},
onCancel(){
options.tooltip[0].show=true
myChart.setOption(options)
}
})
},500)
}
})
myChart.getZr().on('mousemove',()=>{
clearTimeout(time)
})
myChart.getZr().on('mouseup',()=>{
clearTimeout(time)
})
};
this[name]=myChart
},
resize(chart,rate){
var options=chart.getOption()
if(!options)return;
options.dataZoom[0].end=options.dataZoom[0].start+(window.innerWidth*rate)/options.xAxis[0].data.length
chart.setOption(options)
chart.resize()
},
async searchData(){//搜索数据
await this.chart1Data()
await this.chart2Data()
this.showValue()
},
async chart1Data(){
var value =await this.request('sellinfo',{
params:{
dStartDate:this.search.dBeginDate,
dEndDate:this.search.dEndDate
}
},true,{iProject:this.iProject})
Object.assign(this.chartData,{
nOrderSameRatio:Math.round((value.set1&&value.set1[0]&&value.set1[0].nOrderSameRatio||0)*100)/100,
nOrderRingRatio:Math.round((value.set2&&value.set2[0]&&value.set2[0].nOrderRingRatio||0)*100)/100,
set4:{
iSellCount:value.set4&&value.set4[0]&&value.set4[0].iSellCount||0,
nSellAmount:Math.round((value.set4&&value.set4[0]&&value.set4[0].nSellAmount||0)/100)/100
}
})
console.log()
this.chartData.set3=typeof value.set3=='object'&&value.set3.length>0&&value.set3.map(v=>{
v.value=Math.round(v.nAmount/100)/100
return v
})||[]
},
async chart2Data(){
var value=await this.request('getMmcolorsaletop',{
params:this.search
},true,{iProject:this.iProject})
this.chartData.set5=typeof value=='object'&&value.length>0&&value||[]
this.chartData.set5.forEach(v=>v.type='mmcolorsaletop')
var value=await this.request('getMmsaletop',{
params:this.search
},true,{iProject:this.iProject})
this.chartData.set6=typeof value=='object'&&value.length>0&&value||[]
this.chartData.set6.forEach(v=>v.type='mmsaletop')
},
showValue(){
this.drawRing({
e:this.chart1,
value:this.chartData.nOrderSameRatio
})
this.drawRing({
e:this.chart2,
value:this.chartData.nOrderRingRatio
})
this.drawLing({
e:this.chart3,
value:this.chartData.set3
})
this.drawLing2({
e:this.chart5,
value:this.chartData.set5
})
this.drawLing2({
e:this.chart6,
value:this.chartData.set6
})
},
drawRing(data){//仪表盘
data.e.setOption({
tooltip : {
show:false,
},
series: [
{
type: 'gauge',
data: [{value: data.value, name: '比例'}],
radius:"90%",
min:-100,
max:100,
title:{
fontSize:10
},
detail:{
fontSize:11,
formatter:'{value}%',
padding:[50,0,0,0],
},
axisLine:{
show:false,
lineStyle:{
color:[[0.5,'red'],[0.75,'#1CB712'],[0.90,'#156F8E'],[1,'#152989']],
width:15
}
},
splitLine:{
length:15
},
axisLabel:{
fontSize:9,
distance:1,
},
itemStyle:{
opacity:0.3,
},
}
]
})
},
drawLing(data){//折线
data.e.setOption({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#111'
}
},
formatter:val=>{
return data.value[val[0].dataIndex].nAmount
}
},
toolbox: {
feature: {
restore: {show: true},
},
},
grid: {
top:30,
height:130,
right:10,
},
xAxis: {
type:"category",
data:data.value.map(v=>v.sYearMonth),
axisPointer:{
type:"shadow"
},
axisTick:{
alignWithLabel: true
},
axisLabel: {
interval:0
},
minInterval:10,
},
yAxis: {
type: 'value',
name:"金额(万)",
offset:-10,
},
dataZoom: [{
type: 'inside',
xAxisIndex: 0,
show: false, //flase直接隐藏图形
filterMode: 'empty',
start: 0,//滚动条的起始位置
end: (window.innerWidth*1.15)/data.value.length //滚动条的截止位置(按比例分割你的柱状图x轴长度)
}],
series: [
{
id: 'a',
type: 'line',
smooth: true,
symbolSize: 10,
data: data.value.map(v=>v.value),
label:{
show:true,
formatter:val=>{
return `${val.data}万`
}
},
}
]
})
},
drawLing2(data){
data.e.setOption({
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%', // 与容器右侧的距离
height:160,
containLabel: true
},
legend: {
data:['金额','数量'],
x: 'left'
},
xAxis: [{
type: 'category',
data: data.value.map(v=>`${v.sMaterialNo}\n${v.sColorNo || ''}\n${v.sUnit || ''}`),
axisPointer: {
type: 'shadow'
},
axisTick: {
alignWithLabel: true
},
axisLabel: {
interval:0
},
}],
yAxis: [
{
type: 'value',
name: '金额',
axisLabel: {
formatter: '{value}'
},
scale:true,
axisLine:{
lineStyle:{
color:'#5CADFF',
}
}
},
{
type: 'value',
name: '数量',
scale:true,
axisLabel: {
formatter: '{value}'
}
}
],
series: [
{
name:'金额',
type:'bar',
data:data.value.map(v=>v.nAmount),
barWidth:32,
},
{
name:'数量',
type:'line',
yAxisIndex: 1,
data:data.value.map(v=>v.nQty),
}
],
dataZoom: [{
type: 'inside',
show: true, //flase直接隐藏图形
xAxisIndex: [0],
left: '9%', //滚动条靠左侧的百分比
start: 0,//滚动条的起始位置
end: (window.innerWidth*1.35)/data.value.length //滚动条的截止位置(按比例分割你的柱状图x轴长度)
}],
})
}
},
}
</script>
<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>
#_info{
height:100%;
.step_1{
._container{
text-align: center;
margin-top:50px;
#phone_icon{
font-size: 200px;
color: #bcbcbc;
}
}
.title{
text-align: center;
h2{
font-weight: bold;
color:black;
}
h4{
margin-top:20px;
color:gray;
}
}
}
.step_2,.step_3{
.input{
position: relative;
top:0;
}
input{
background: white;
width:100%;
height:80px;
font-size:30px;
color:black;
}
.sendCode{
position: absolute;
right:0;
width:150px;
margin-right:15px;
bottom:10px;
height:60px;
line-height: 60px;
border:2px solid #1E9FFF;
text-align: center;
border-radius:10px;
color:#1E9FFF;
}
._title{
position: absolute;
left:0;
bottom:0px;
font-size:30px;
color:black;
height:80px;
width:200px;
font-weight: bold;
display:flex;
align-items: center;
justify-content: center;
}
}
.step_1,.step_2,.step_3,.unbundl,._info{
.btn{
margin-top:60px;
button{
background-color: #1E9FFF;
height: 80px;
width: 600px;
font-size:30px;
}
}
}
.margin_top_20{
margin-top:20px;
}
.margin_top_40{
margin-top:40px;
}
.margin_top_2{
margin-top:2px;
}
.padding_right_180{
padding-right:180px;
}
.padding_left_120{
padding-left:120px;
}
.padding_left_200{
padding-left:200px;
}
#_phone_icon{
position: absolute;
bottom:0px;
font-size: 50px;
height:80px;
width:120px;
text-align: center;
color: #bcbcbc;
}
.unbundle{
._img{
width:50%;
height:50%;
margin-top:20px;
}
h2{
margin-top:20px;
}
}
._info{
.v-list{
padding:0;
}
.v-list__tile{
height:80px;
box-sizing: border-box;
border-bottom:3px solid #eff4fd;
}
.v-list__tile__title{
padding-left:20px;
font-size: 25px;
}
.title > .v-avatar{
width:150px !important;
height:inherit !important;
justify-content: flex-start;
span{
font-size: 25px;
}
}
}
}
\ No newline at end of file
<template>
<div id="_info">
<div class="step_1" v-if="step == 1">
<v-container grid-list-md text-xs-center>
<v-layout row wrap>
<v-flex xs12>
<div class="_container">
<i class='iconfont icon-mobilefill' id="phone_icon"></i>
<div class="title">
<h2>您还没有绑定手机号</h2>
<h4>绑定手机号,带给您不一样的体验</h4>
</div>
</div>
</v-flex>
<v-flex xs12>
<div class="text-xs-center btn">
<v-btn round color="primary" @click="setStep" dark>绑定手机号</v-btn>
</div>
</v-flex>
</v-layout>
</v-container>
</div>
<div class="step_2" v-if="step == 2">
<v-layout row wrap>
<v-flex xs12>
<div class="input">
<input type="text" name="keyword" autocomplete="off" class="margin_top_40 padding_left_120 padding_right_180" placeholder="请输入手机号码"/>
<i class='iconfont icon-mobilefill' id="_phone_icon"></i>
<div class="sendCode">发送验证码</div>
</div>
<div class="input">
<input type="text" name="keyword" autocomplete="off" class="margin_top_2 padding_left_120 padding_right_180" placeholder="请输入短信验证码"/>
<i class='iconfont icon-lock' id="_phone_icon"></i>
</div>
</v-flex>
<v-flex xs12>
<div class="text-xs-center btn">
<v-btn round color="primary" @click="setStep" dark>绑定手机号</v-btn>
</div>
</v-flex>
</v-layout>
</div>
<div class="step_3" v-if="step == 3">
<v-layout row wrap>
<v-flex xs12>
<div class="input">
<div class="_title">客户账号</div>
<input type="text" name="keyword" autocomplete="off" class="margin_top_40 padding_left_200" placeholder="请输入手机号码"/>
</div>
<div class="input">
<div class="_title">客户密码</div>
<input type="password" name="keyword" autocomplete="off" class="margin_top_2 padding_left_200" placeholder="请输入短信验证码"/>
</div>
</v-flex>
<v-flex xs12>
<div class="text-xs-center btn">
<v-btn round color="primary" dark>确定</v-btn>
</div>
</v-flex>
</v-layout>
</div>
<div class="unbundle" v-if="step == 4">
<v-layout row wrap>
<v-flex xs12>
<div class="text-xs-center">
<img src="@/assets/tick.jpg" class="_img" alt="">
</div>
<div class="text-xs-center">
<h2>您的手机号:18878768888</h2>
</div>
<div class="text-xs-center btn">
<v-btn round color="primary" dark>更换手机号</v-btn>
</div>
</v-flex>
</v-layout>
</div>
<div class="_info" v-if="step == 5">
<v-list subheader>
<v-list-tile
v-for="item in [{title:'客户账号:',name:'william'},{title:'客户名称:',name:'张锡奇'},{title:'手机号:',name:'15158064698'}]"
:key="item.title"
avatar
>
<v-list-tile-avatar class="title">
<span>{{item.title}}</span>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title v-html="item.name"></v-list-tile-title>
</v-list-tile-content>
<v-list-tile-action>
<!-- <v-icon :color="item.active ? 'teal' : 'grey'">chat_bubble</v-icon> -->
</v-list-tile-action>
</v-list-tile>
</v-list>
<v-flex xs12>
<div class="text-xs-center btn">
<v-btn round color="primary" dark>确定</v-btn>
</div>
</v-flex>
</div>
</div>
</template>
<script>
export default {
name: 'info',
data () {
return {
step:1,
}
},
activated(){
},
methods:{
setStep(){
this.step++;
// this.$router.push({path:'/me/help'})
}
}
}
</script>
<style lang="less">
@import "./info.less";
</style>
<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
}
}
}
}
// 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
})
})
// 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": {
}
}
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/**'
]
}
import Vue from 'vue'
Vue.config.productionTip = false
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')
})
})
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