@@ -0,0 +1,18 @@ | |||||
{ | |||||
"presets": [ | |||||
["env", { | |||||
"modules": false, | |||||
"targets": { | |||||
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"] | |||||
} | |||||
}], | |||||
"stage-2" | |||||
], | |||||
"plugins": ["transform-vue-jsx", "transform-runtime",[ | |||||
"component", | |||||
{ | |||||
"libraryName": "element-ui", | |||||
"styleLibraryName": "theme-chalk" | |||||
} | |||||
]] | |||||
} |
@@ -0,0 +1,9 @@ | |||||
root = true | |||||
[*] | |||||
charset = utf-8 | |||||
indent_style = space | |||||
indent_size = 2 | |||||
end_of_line = lf | |||||
insert_final_newline = true | |||||
trim_trailing_whitespace = true |
@@ -0,0 +1,14 @@ | |||||
.DS_Store | |||||
node_modules/ | |||||
/dist/ | |||||
npm-debug.log* | |||||
yarn-debug.log* | |||||
yarn-error.log* | |||||
# Editor directories and files | |||||
.idea | |||||
.vscode | |||||
*.suo | |||||
*.ntvs* | |||||
*.njsproj | |||||
*.sln |
@@ -0,0 +1,10 @@ | |||||
// https://github.com/michael-ciniawsky/postcss-load-config | |||||
module.exports = { | |||||
"plugins": { | |||||
"postcss-import": {}, | |||||
"postcss-url": {}, | |||||
// to edit target browsers: use "browserslist" field in package.json | |||||
"autoprefixer": {} | |||||
} | |||||
} |
@@ -0,0 +1,21 @@ | |||||
# single | |||||
> 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 | |||||
``` | |||||
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). |
@@ -0,0 +1,41 @@ | |||||
'use strict' | |||||
require('./check-versions')() | |||||
process.env.NODE_ENV = 'production' | |||||
const ora = require('ora') | |||||
const rm = require('rimraf') | |||||
const path = require('path') | |||||
const chalk = require('chalk') | |||||
const webpack = require('webpack') | |||||
const config = require('../config') | |||||
const webpackConfig = require('./webpack.prod.conf') | |||||
const spinner = ora('building for production...') | |||||
spinner.start() | |||||
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { | |||||
if (err) throw err | |||||
webpack(webpackConfig, (err, stats) => { | |||||
spinner.stop() | |||||
if (err) throw err | |||||
process.stdout.write(stats.toString({ | |||||
colors: true, | |||||
modules: false, | |||||
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. | |||||
chunks: false, | |||||
chunkModules: false | |||||
}) + '\n\n') | |||||
if (stats.hasErrors()) { | |||||
console.log(chalk.red(' Build failed with errors.\n')) | |||||
process.exit(1) | |||||
} | |||||
console.log(chalk.cyan(' Build complete.\n')) | |||||
console.log(chalk.yellow( | |||||
' Tip: built files are meant to be served over an HTTP server.\n' + | |||||
' Opening index.html over file:// won\'t work.\n' | |||||
)) | |||||
}) | |||||
}) |
@@ -0,0 +1,54 @@ | |||||
'use strict' | |||||
const chalk = require('chalk') | |||||
const semver = require('semver') | |||||
const packageConfig = require('../package.json') | |||||
const shell = require('shelljs') | |||||
function exec (cmd) { | |||||
return require('child_process').execSync(cmd).toString().trim() | |||||
} | |||||
const versionRequirements = [ | |||||
{ | |||||
name: 'node', | |||||
currentVersion: semver.clean(process.version), | |||||
versionRequirement: packageConfig.engines.node | |||||
} | |||||
] | |||||
if (shell.which('npm')) { | |||||
versionRequirements.push({ | |||||
name: 'npm', | |||||
currentVersion: exec('npm --version'), | |||||
versionRequirement: packageConfig.engines.npm | |||||
}) | |||||
} | |||||
module.exports = function () { | |||||
const warnings = [] | |||||
for (let i = 0; i < versionRequirements.length; i++) { | |||||
const mod = versionRequirements[i] | |||||
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { | |||||
warnings.push(mod.name + ': ' + | |||||
chalk.red(mod.currentVersion) + ' should be ' + | |||||
chalk.green(mod.versionRequirement) | |||||
) | |||||
} | |||||
} | |||||
if (warnings.length) { | |||||
console.log('') | |||||
console.log(chalk.yellow('To use this template, you must update following to modules:')) | |||||
console.log() | |||||
for (let i = 0; i < warnings.length; i++) { | |||||
const warning = warnings[i] | |||||
console.log(' ' + warning) | |||||
} | |||||
console.log() | |||||
process.exit(1) | |||||
} | |||||
} |
@@ -0,0 +1,101 @@ | |||||
'use strict' | |||||
const path = require('path') | |||||
const config = require('../config') | |||||
const ExtractTextPlugin = require('extract-text-webpack-plugin') | |||||
const packageConfig = require('../package.json') | |||||
exports.assetsPath = function (_path) { | |||||
const assetsSubDirectory = process.env.NODE_ENV === 'production' | |||||
? config.build.assetsSubDirectory | |||||
: config.dev.assetsSubDirectory | |||||
return path.posix.join(assetsSubDirectory, _path) | |||||
} | |||||
exports.cssLoaders = function (options) { | |||||
options = options || {} | |||||
const cssLoader = { | |||||
loader: 'css-loader', | |||||
options: { | |||||
sourceMap: options.sourceMap | |||||
} | |||||
} | |||||
const postcssLoader = { | |||||
loader: 'postcss-loader', | |||||
options: { | |||||
sourceMap: options.sourceMap | |||||
} | |||||
} | |||||
// generate loader string to be used with extract text plugin | |||||
function generateLoaders (loader, loaderOptions) { | |||||
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] | |||||
if (loader) { | |||||
loaders.push({ | |||||
loader: loader + '-loader', | |||||
options: Object.assign({}, loaderOptions, { | |||||
sourceMap: options.sourceMap | |||||
}) | |||||
}) | |||||
} | |||||
// Extract CSS when that option is specified | |||||
// (which is the case during production build) | |||||
if (options.extract) { | |||||
return ExtractTextPlugin.extract({ | |||||
use: loaders, | |||||
fallback: 'vue-style-loader' | |||||
}) | |||||
} else { | |||||
return ['vue-style-loader'].concat(loaders) | |||||
} | |||||
} | |||||
// https://vue-loader.vuejs.org/en/configurations/extract-css.html | |||||
return { | |||||
css: generateLoaders(), | |||||
postcss: generateLoaders(), | |||||
less: generateLoaders('less'), | |||||
sass: generateLoaders('sass', { indentedSyntax: true }), | |||||
scss: generateLoaders('sass'), | |||||
stylus: generateLoaders('stylus'), | |||||
styl: generateLoaders('stylus') | |||||
} | |||||
} | |||||
// Generate loaders for standalone style files (outside of .vue) | |||||
exports.styleLoaders = function (options) { | |||||
const output = [] | |||||
const loaders = exports.cssLoaders(options) | |||||
for (const extension in loaders) { | |||||
const loader = loaders[extension] | |||||
output.push({ | |||||
test: new RegExp('\\.' + extension + '$'), | |||||
use: loader | |||||
}) | |||||
} | |||||
return output | |||||
} | |||||
exports.createNotifierCallback = () => { | |||||
const notifier = require('node-notifier') | |||||
return (severity, errors) => { | |||||
if (severity !== 'error') return | |||||
const error = errors[0] | |||||
const filename = error.file && error.file.split('!').pop() | |||||
notifier.notify({ | |||||
title: packageConfig.name, | |||||
message: severity + ': ' + error.name, | |||||
subtitle: filename || '', | |||||
icon: path.join(__dirname, 'logo.png') | |||||
}) | |||||
} | |||||
} |
@@ -0,0 +1,22 @@ | |||||
'use strict' | |||||
const utils = require('./utils') | |||||
const config = require('../config') | |||||
const isProduction = process.env.NODE_ENV === 'production' | |||||
const sourceMapEnabled = isProduction | |||||
? config.build.productionSourceMap | |||||
: config.dev.cssSourceMap | |||||
module.exports = { | |||||
loaders: utils.cssLoaders({ | |||||
sourceMap: sourceMapEnabled, | |||||
extract: isProduction | |||||
}), | |||||
cssSourceMap: sourceMapEnabled, | |||||
cacheBusting: config.dev.cacheBusting, | |||||
transformToRequire: { | |||||
video: ['src', 'poster'], | |||||
source: 'src', | |||||
img: 'src', | |||||
image: 'xlink:href' | |||||
} | |||||
} |
@@ -0,0 +1,82 @@ | |||||
'use strict' | |||||
const path = require('path') | |||||
const utils = require('./utils') | |||||
const config = require('../config') | |||||
const vueLoaderConfig = require('./vue-loader.conf') | |||||
function resolve (dir) { | |||||
return path.join(__dirname, '..', dir) | |||||
} | |||||
module.exports = { | |||||
context: path.resolve(__dirname, '../'), | |||||
entry: { | |||||
app: './src/main.js' | |||||
}, | |||||
output: { | |||||
path: config.build.assetsRoot, | |||||
filename: '[name].js', | |||||
publicPath: process.env.NODE_ENV === 'production' | |||||
? config.build.assetsPublicPath | |||||
: config.dev.assetsPublicPath | |||||
}, | |||||
resolve: { | |||||
extensions: ['.js', '.vue', '.json'], | |||||
alias: { | |||||
'vue$': 'vue/dist/vue.esm.js', | |||||
'@': resolve('src'), | |||||
} | |||||
}, | |||||
module: { | |||||
rules: [ | |||||
{ | |||||
test: /\.vue$/, | |||||
loader: 'vue-loader', | |||||
options: vueLoaderConfig | |||||
}, | |||||
{ | |||||
test: /\.js$/, | |||||
loader: 'babel-loader', | |||||
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] | |||||
}, | |||||
{ | |||||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, | |||||
loader: 'url-loader', | |||||
options: { | |||||
limit: 10000, | |||||
name: utils.assetsPath('img/[name].[hash:7].[ext]') | |||||
} | |||||
}, | |||||
{ | |||||
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, | |||||
loader: 'url-loader', | |||||
options: { | |||||
limit: 10000, | |||||
name: utils.assetsPath('media/[name].[hash:7].[ext]') | |||||
} | |||||
}, | |||||
{ | |||||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, | |||||
loader: 'url-loader', | |||||
options: { | |||||
limit: 10000, | |||||
name: utils.assetsPath('fonts/[name].[hash:7].[ext]') | |||||
} | |||||
} | |||||
] | |||||
}, | |||||
node: { | |||||
// prevent webpack from injecting useless setImmediate polyfill because Vue | |||||
// source contains it (although only uses it if it's native). | |||||
setImmediate: false, | |||||
// prevent webpack from injecting mocks to Node native modules | |||||
// that does not make sense for the client | |||||
dgram: 'empty', | |||||
fs: 'empty', | |||||
net: 'empty', | |||||
tls: 'empty', | |||||
child_process: 'empty' | |||||
} | |||||
} |
@@ -0,0 +1,95 @@ | |||||
'use strict' | |||||
const utils = require('./utils') | |||||
const webpack = require('webpack') | |||||
const config = require('../config') | |||||
const merge = require('webpack-merge') | |||||
const path = require('path') | |||||
const baseWebpackConfig = require('./webpack.base.conf') | |||||
const CopyWebpackPlugin = require('copy-webpack-plugin') | |||||
const HtmlWebpackPlugin = require('html-webpack-plugin') | |||||
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') | |||||
const portfinder = require('portfinder') | |||||
const HOST = process.env.HOST | |||||
const PORT = process.env.PORT && Number(process.env.PORT) | |||||
const devWebpackConfig = merge(baseWebpackConfig, { | |||||
module: { | |||||
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) | |||||
}, | |||||
// cheap-module-eval-source-map is faster for development | |||||
devtool: config.dev.devtool, | |||||
// these devServer options should be customized in /config/index.js | |||||
devServer: { | |||||
clientLogLevel: 'warning', | |||||
historyApiFallback: { | |||||
rewrites: [ | |||||
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, | |||||
], | |||||
}, | |||||
hot: true, | |||||
contentBase: false, // since we use CopyWebpackPlugin. | |||||
compress: true, | |||||
host: HOST || config.dev.host, | |||||
port: PORT || config.dev.port, | |||||
open: config.dev.autoOpenBrowser, | |||||
overlay: config.dev.errorOverlay | |||||
? { warnings: false, errors: true } | |||||
: false, | |||||
publicPath: config.dev.assetsPublicPath, | |||||
proxy: config.dev.proxyTable, | |||||
quiet: true, // necessary for FriendlyErrorsPlugin | |||||
watchOptions: { | |||||
poll: config.dev.poll, | |||||
} | |||||
}, | |||||
plugins: [ | |||||
new webpack.DefinePlugin({ | |||||
'process.env': require('../config/dev.env') | |||||
}), | |||||
new webpack.HotModuleReplacementPlugin(), | |||||
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. | |||||
new webpack.NoEmitOnErrorsPlugin(), | |||||
// https://github.com/ampedandwired/html-webpack-plugin | |||||
new HtmlWebpackPlugin({ | |||||
filename: 'index.html', | |||||
template: 'index.html', | |||||
inject: true | |||||
}), | |||||
// copy custom static assets | |||||
new CopyWebpackPlugin([ | |||||
{ | |||||
from: path.resolve(__dirname, '../static'), | |||||
to: config.dev.assetsSubDirectory, | |||||
ignore: ['.*'] | |||||
} | |||||
]) | |||||
] | |||||
}) | |||||
module.exports = new Promise((resolve, reject) => { | |||||
portfinder.basePort = process.env.PORT || config.dev.port | |||||
portfinder.getPort((err, port) => { | |||||
if (err) { | |||||
reject(err) | |||||
} else { | |||||
// publish the new Port, necessary for e2e tests | |||||
process.env.PORT = port | |||||
// add port to devServer config | |||||
devWebpackConfig.devServer.port = port | |||||
// Add FriendlyErrorsPlugin | |||||
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ | |||||
compilationSuccessInfo: { | |||||
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], | |||||
}, | |||||
onErrors: config.dev.notifyOnErrors | |||||
? utils.createNotifierCallback() | |||||
: undefined | |||||
})) | |||||
resolve(devWebpackConfig) | |||||
} | |||||
}) | |||||
}) |
@@ -0,0 +1,145 @@ | |||||
'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 = 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: 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 |
@@ -0,0 +1,7 @@ | |||||
'use strict' | |||||
const merge = require('webpack-merge') | |||||
const prodEnv = require('./prod.env') | |||||
module.exports = merge(prodEnv, { | |||||
NODE_ENV: '"development"' | |||||
}) |
@@ -0,0 +1,76 @@ | |||||
'use strict' | |||||
// Template version: 1.3.1 | |||||
// see http://vuejs-templates.github.io/webpack for documentation. | |||||
const path = require('path') | |||||
module.exports = { | |||||
dev: { | |||||
// Paths | |||||
assetsSubDirectory: 'static', | |||||
assetsPublicPath: '/', | |||||
// Various Dev Server settings | |||||
host: 'localhost', // can be overwritten by process.env.HOST | |||||
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined | |||||
autoOpenBrowser: false, | |||||
errorOverlay: true, | |||||
notifyOnErrors: true, | |||||
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- | |||||
proxyTable: { | |||||
'/api': { | |||||
target:'http://47.101.187.29:8084', // 你请求的第三方接口 | |||||
changeOrigin:true, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题 | |||||
pathRewrite:{ // 路径重写, | |||||
'^/api': '' // 替换target中的请求地址,也就是说以后你在请求http://api.douban.com/v2/XXXXX这个地址的时候直接写成/api即可。 | |||||
} | |||||
} | |||||
}, | |||||
/** | |||||
* Source Maps | |||||
*/ | |||||
// https://webpack.js.org/configuration/devtool/#development | |||||
devtool: 'cheap-module-eval-source-map', | |||||
// If you have problems debugging vue-files in devtools, | |||||
// set this to false - it *may* help | |||||
// https://vue-loader.vuejs.org/en/options.html#cachebusting | |||||
cacheBusting: true, | |||||
cssSourceMap: true | |||||
}, | |||||
build: { | |||||
// Template for index.html | |||||
index: path.resolve(__dirname, '../dist/index.html'), | |||||
// Paths | |||||
assetsRoot: path.resolve(__dirname, '../dist'), | |||||
assetsSubDirectory: 'static', | |||||
assetsPublicPath: '/', | |||||
/** | |||||
* Source Maps | |||||
*/ | |||||
productionSourceMap: false, | |||||
// 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 | |||||
} | |||||
} |
@@ -0,0 +1,4 @@ | |||||
'use strict' | |||||
module.exports = { | |||||
NODE_ENV: '"production"' | |||||
} |
@@ -0,0 +1,12 @@ | |||||
<!DOCTYPE html> | |||||
<html> | |||||
<head> | |||||
<meta charset="utf-8"> | |||||
<meta name="viewport" content="width=device-width,initial-scale=1.0"> | |||||
<title>single</title> | |||||
</head> | |||||
<body> | |||||
<div id="app"></div> | |||||
<!-- built files will be auto injected --> | |||||
</body> | |||||
</html> |
@@ -0,0 +1,65 @@ | |||||
{ | |||||
"name": "single", | |||||
"version": "1.0.0", | |||||
"description": "A Vue.js project", | |||||
"author": "xubinxcode <xubin865453422>", | |||||
"private": true, | |||||
"scripts": { | |||||
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", | |||||
"start": "npm run dev", | |||||
"build": "node build/build.js" | |||||
}, | |||||
"dependencies": { | |||||
"axios": "^0.23.0", | |||||
"element-ui": "^2.15.6", | |||||
"normalize.css": "^8.0.1", | |||||
"vue": "^2.5.2" | |||||
}, | |||||
"devDependencies": { | |||||
"autoprefixer": "^7.1.2", | |||||
"babel-core": "^6.22.1", | |||||
"babel-helper-vue-jsx-merge-props": "^2.0.3", | |||||
"babel-loader": "^7.1.1", | |||||
"babel-plugin-component": "^1.1.1", | |||||
"babel-plugin-syntax-jsx": "^6.18.0", | |||||
"babel-plugin-transform-runtime": "^6.22.0", | |||||
"babel-plugin-transform-vue-jsx": "^3.5.0", | |||||
"babel-preset-env": "^1.3.2", | |||||
"babel-preset-stage-2": "^6.22.0", | |||||
"chalk": "^2.0.1", | |||||
"copy-webpack-plugin": "^4.0.1", | |||||
"css-loader": "^0.28.0", | |||||
"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", | |||||
"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", | |||||
"rimraf": "^2.6.0", | |||||
"semver": "^5.3.0", | |||||
"shelljs": "^0.7.6", | |||||
"uglifyjs-webpack-plugin": "^1.1.1", | |||||
"url-loader": "^0.5.8", | |||||
"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" | |||||
] | |||||
} |
@@ -0,0 +1,27 @@ | |||||
<template> | |||||
<div id="app"> | |||||
<HelloWorld/> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import HelloWorld from './components/HelloWorld' | |||||
export default { | |||||
name: 'App', | |||||
components: { | |||||
HelloWorld | |||||
} | |||||
} | |||||
</script> | |||||
<style> | |||||
#app { | |||||
font-family: 'Avenir', Helvetica, Arial, sans-serif; | |||||
-webkit-font-smoothing: antialiased; | |||||
-moz-osx-font-smoothing: grayscale; | |||||
text-align: center; | |||||
color: #2c3e50; | |||||
margin-top: 60px; | |||||
} | |||||
</style> |
@@ -0,0 +1,184 @@ | |||||
<template> | |||||
<el-form ref="form" :model="orderMain" label-width="100px"> | |||||
<el-row> | |||||
<el-col :span="12"> | |||||
<el-form-item label="订单专员"> | |||||
<el-input v-model="orderMain.commissioner"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="12"></el-col> | |||||
</el-row> | |||||
<el-row> | |||||
<el-col :span="12"> | |||||
<el-form-item label="订单渠道"> | |||||
<el-select style="width: 100%" v-model="orderMain.channel_id" filterable placeholder="请选择"> | |||||
<el-option | |||||
v-for="item in channelListOpt" | |||||
:key="item.id" | |||||
:label="item.name" | |||||
:value="item.id"> | |||||
</el-option> | |||||
</el-select> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="12"> | |||||
<el-form-item label="渠道订单编号"> | |||||
<el-input v-model="orderMain.channel_order_no"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
<el-row> | |||||
<el-col :span="12"> | |||||
<el-form-item label="用户姓名"> | |||||
<el-input v-model="orderMain.user_name"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="12"> | |||||
<el-form-item label="用户电话"> | |||||
<el-input v-model="orderMain.user_phone"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
<el-form-item label="备注"> | |||||
<el-input type="textarea" v-model="orderMain.order_memo"></el-input> | |||||
</el-form-item> | |||||
<el-form-item> | |||||
<el-row type="flex"> | |||||
<el-button type="primary" @click="addHotel">添加酒店</el-button> | |||||
</el-row> | |||||
</el-form-item> | |||||
<template v-for="item in hotelList"> | |||||
<hotel :dataObj="item" :hotelListOpt="hotelListOpt"></hotel> | |||||
</template> | |||||
<el-form-item> | |||||
<el-row type="flex"> | |||||
<el-button type="primary" @click="addHotelOther">添加附加项目</el-button> | |||||
</el-row> | |||||
</el-form-item> | |||||
<template v-for="item in hotelotherList"> | |||||
<hotelother :dataObj="item"></hotelother> | |||||
</template> | |||||
<el-form-item> | |||||
<el-button type="primary" @click="onSubmit">提交订单</el-button> | |||||
</el-form-item> | |||||
</el-form> | |||||
</template> | |||||
<script> | |||||
import hotel from "./hotel" | |||||
import hotelother from "./hotelother" | |||||
import axios from "axios" | |||||
export default { | |||||
components: { | |||||
hotel, | |||||
hotelother | |||||
}, | |||||
data() { | |||||
return { | |||||
orderMain: { | |||||
commissioner: '订单专员', | |||||
channel_id: '订单渠道', | |||||
channel_order_no: '渠道订单编号', | |||||
user_name: '用户姓名', | |||||
user_phone: "111111111111", | |||||
order_memo: "备注", | |||||
}, | |||||
hotelListObj: { | |||||
hotelName: '酒店名称', | |||||
roomName: '房型名称', | |||||
price: '价格方案', | |||||
check_in_date: '', | |||||
check_out_date: '', | |||||
travelerName: '出游人姓名', | |||||
confirmNo: '123456', | |||||
taOrderNo: '123456', | |||||
sourceState: '资源状态', | |||||
roomDesc: '床型说明', | |||||
sourceResponser: '资源负责人', | |||||
priceIntro: '价格方案说明', | |||||
total_amount: '总金额', | |||||
cost_amount: '成本价', | |||||
profit_amount: '利润', | |||||
tableData: [{ | |||||
date: '', | |||||
salePrice: '', | |||||
countPrice: '', | |||||
amount: '', | |||||
note: '', | |||||
provider: 0 | |||||
}] | |||||
}, | |||||
hotelList: [], | |||||
hotelotherListObj: { | |||||
fuStyle: '附加项目类型', | |||||
fuName: '附加项目名称', | |||||
countUnit: '计价单位', | |||||
use_date: '', | |||||
travelerName: '出游人姓名', | |||||
confirmNo: '123456', | |||||
taOrderNo: '123456', | |||||
sourceResponser: '资源负责人', | |||||
sourceState: '资源状态', | |||||
fuIntro: '附加项目说明', | |||||
total_amount: '总金额', | |||||
cost_amount: '成本价', | |||||
profit_amount: '利润', | |||||
tableData: [{ | |||||
date: '', | |||||
salePrice: '', | |||||
countPrice: '', | |||||
amount: '', | |||||
note: '', | |||||
provider: 0 | |||||
}] | |||||
}, | |||||
hotelotherList: [], | |||||
hotelListOpt: [], | |||||
channelListOpt: [], | |||||
} | |||||
}, | |||||
methods: { | |||||
addHotel() { | |||||
this.hotelList.push(this.hotelListObj) | |||||
}, | |||||
addHotelOther() { | |||||
this.hotelotherList.push(this.hotelotherListObj) | |||||
}, | |||||
onSubmit() { | |||||
console.log('submit!'); | |||||
// axios.post("/hotel.php/order_main/newAdd?id=1", {}).then((res) => { | |||||
axios.post("/hotel.php/order_main/newAdd?id=1", { | |||||
orderMain: this.orderMain, //基础数据 | |||||
hotel: this.hotelList, //酒店 | |||||
item: this.hotelotherList //酒店附加数据 | |||||
}).then((res) => { | |||||
console.log(res) | |||||
}).catch((err) => { | |||||
console.log(err) | |||||
}) | |||||
} | |||||
}, | |||||
mounted() { | |||||
if (process.env.NODE_ENV !== 'production') { | |||||
axios.defaults.baseURL = '/api' //关键代码 | |||||
} | |||||
axios.get("/hotel.php/cf_hotel_info/getHotelList").then((res) => { | |||||
console.log(res) | |||||
this.hotelListOpt = res.data.list | |||||
}).catch((err) => { | |||||
console.log(err) | |||||
}) | |||||
axios.get("hotel.php/cf_channel_info/getList").then((res) => { | |||||
console.log(res) | |||||
this.channelListOpt = res.data.list | |||||
}).catch((err) => { | |||||
console.log(err) | |||||
}) | |||||
} | |||||
} | |||||
</script> |
@@ -0,0 +1,264 @@ | |||||
<template> | |||||
<el-card class="card" shadow="hover"> | |||||
<el-form ref="form" :model="dataObj" label-width="100px"> | |||||
<el-collapse> | |||||
<el-collapse-item> | |||||
<template slot="title"> | |||||
<el-row style="margin-top: 25px;padding-right: 20px;"> | |||||
<el-col :span="8"> | |||||
<el-form-item label="酒店名称"> | |||||
<el-select v-model="dataObj.hotelName" filterable placeholder="请选择" @change="selectChange"> | |||||
<el-option | |||||
v-for="item in hotelListOpt" | |||||
:key="item.id" | |||||
:label="item.name" | |||||
:value="item.id"> | |||||
</el-option> | |||||
</el-select> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="8"> | |||||
<el-form-item label="房型名称"> | |||||
<el-select v-model="dataObj.roomName" filterable placeholder="请选择" @change="selectChange"> | |||||
<el-option | |||||
v-for="item in roomListOpt" | |||||
:key="item.id" | |||||
:label="item.name" | |||||
:value="item.id"> | |||||
</el-option> | |||||
</el-select> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="8"> | |||||
<el-form-item label="价格方案"> | |||||
<el-input v-model="dataObj.price"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
</template> | |||||
<el-row> | |||||
<el-col :span="10"> | |||||
<el-form-item label="入离日期"> | |||||
<el-date-picker | |||||
v-model="date" | |||||
type="daterange" | |||||
value-format="yyyy-MM-dd HH:mm:ss" | |||||
range-separator="-" | |||||
start-placeholder="入住日期" | |||||
end-placeholder="离店日期"> | |||||
</el-date-picker> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="8"> | |||||
<el-form-item label-width="100px" label="出游人姓名"> | |||||
<el-input v-model="dataObj.travelerName"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="6"> | |||||
<el-form-item label="确认号"> | |||||
<el-input v-model="dataObj.confirmNo"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
<el-form-item> | |||||
<el-table | |||||
:data="dataObj.tableData" | |||||
border | |||||
height="500" | |||||
:summary-method="getSummaries" | |||||
show-summary | |||||
style="width: 100%; margin-top: 20px"> | |||||
<el-table-column | |||||
prop="date" | |||||
label="日期" | |||||
width="180"> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="salePrice" | |||||
label="售卖价"> | |||||
<template slot-scope="scope"> | |||||
<el-input v-model="scope.row.salePrice"></el-input> | |||||
</template> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="countPrice" | |||||
label="成本价"> | |||||
<template slot-scope="scope"> | |||||
<el-input v-model="scope.row.countPrice"></el-input> | |||||
</template> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="amount" | |||||
label="数量"> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="provider" | |||||
label="供应商"> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="note" | |||||
label="备注"> | |||||
</el-table-column> | |||||
</el-table> | |||||
</el-form-item> | |||||
<el-row> | |||||
<el-col :span="12"> | |||||
<el-form-item label-width="100px" label="对方订单号"> | |||||
<el-input v-model="dataObj.taOrderNo"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="12"> | |||||
<el-form-item label="资源状态"> | |||||
<el-button-group v-model="dataObj.sourceState"> | |||||
<el-button type="primary">未发单</el-button> | |||||
<el-button type="">已发单</el-button> | |||||
<el-button type="">已确认</el-button> | |||||
<el-button type="">已取消</el-button> | |||||
</el-button-group> | |||||
</el-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
<el-row> | |||||
<el-col :span="12"> | |||||
<el-form-item label-width="100px" label="床型说明"> | |||||
<span>{{dataObj.roomDesc}}</span> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="12"> | |||||
<el-form-item label-width="100px" label="资源负责人"> | |||||
<span>{{dataObj.sourceResponser}}</span> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="12"> | |||||
<el-form-item label-width="100px" label="价格方案说明"> | |||||
<span>{{dataObj.priceIntro}}</span> | |||||
</el-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
</el-collapse-item> | |||||
</el-collapse> | |||||
</el-form> | |||||
</el-card> | |||||
</template> | |||||
<script> | |||||
import axios from "axios" | |||||
export default { | |||||
name: "hotel", | |||||
props: {dataObj: Object, hotelListOpt: Array}, | |||||
data() { | |||||
return {roomListOpt: [], date: [], day: []} | |||||
}, | |||||
watch: { | |||||
date(val) { | |||||
console.log(val) | |||||
this.$set(this.dataObj, "check_in_date", val[0]) | |||||
this.$set(this.dataObj, "check_out_date", val[1]) | |||||
let date1 = new Date(val[0]); | |||||
let date2 = new Date(val[1]); | |||||
let day = this.getAllDateCN(date1, date2) | |||||
let tableData = []; | |||||
for (let item of day) { | |||||
tableData.push({ | |||||
date: item, | |||||
salePrice: '', | |||||
countPrice: '', | |||||
amount: 5, | |||||
note: 5, | |||||
provider: 'q' | |||||
}) | |||||
} | |||||
this.dataObj.tableData = tableData; | |||||
this.$set(this.dataObj, 'tableData', tableData) | |||||
} | |||||
}, | |||||
methods: { | |||||
getAllDateCN(startTime, endTime) { | |||||
var date_all = [] | |||||
var i = 0 | |||||
while ((endTime.getTime() - startTime.getTime()) >= 0) { | |||||
var year = startTime.getFullYear() | |||||
var month = startTime.getMonth() + 1 | |||||
var day = startTime.getDate() | |||||
date_all[i] = year + '-' + month + '-' + day | |||||
startTime.setDate(startTime.getDate() + 1) | |||||
i += 1 | |||||
} | |||||
return date_all | |||||
}, | |||||
getSummaries(param) { | |||||
const {columns, data} = param; | |||||
const sums = []; | |||||
columns.forEach((column, index) => { | |||||
if (index === 0) { | |||||
sums[index] = '总价'; | |||||
return; | |||||
} | |||||
if (index === 3) { | |||||
sums[index] = '利润'; | |||||
return; | |||||
} | |||||
const values = data.map(item => Number(item[column.property])); | |||||
if (!values.every(value => isNaN(value))) { | |||||
sums[index] = values.reduce((prev, curr) => { | |||||
const value = Number(curr); | |||||
if (!isNaN(value)) { | |||||
return prev + curr; | |||||
} else { | |||||
return prev; | |||||
} | |||||
}, 0); | |||||
if (index == 1) { | |||||
this.dataObj.total_amount = sums[index]; | |||||
this.$set(this.dataObj, 'total_amount', sums[index]); | |||||
} | |||||
if (index == 2) { | |||||
this.dataObj.cost_amount = sums[index]; | |||||
this.$set(this.dataObj, 'cost_amount', sums[index]); | |||||
} | |||||
if (index == 4) { | |||||
this.dataObj.profit_amount = sums[index]; | |||||
this.$set(this.dataObj, 'profit_amount', sums[index]); | |||||
} | |||||
sums[index] += ' 元'; | |||||
} else { | |||||
sums[index] = 'N/A'; | |||||
} | |||||
}); | |||||
return sums; | |||||
}, | |||||
selectChange(item) { | |||||
console.log(item) | |||||
axios.get("/hotel.php/cf_room_info/getRoomList?hotelId=" + item).then((res) => { | |||||
console.log(res) | |||||
this.roomListOpt = res.data.list | |||||
}).catch((err) => { | |||||
console.log(err) | |||||
}) | |||||
}, | |||||
onSubmit() { | |||||
console.log('submit!'); | |||||
} | |||||
}, | |||||
mounted() { | |||||
if (process.env.NODE_ENV !== 'production') { | |||||
axios.defaults.baseURL = '/api' //关键代码 | |||||
} | |||||
} | |||||
} | |||||
</script> | |||||
<style scoped> | |||||
.card { | |||||
margin: 20px; | |||||
} | |||||
.card /deep/ .el-collapse-item__header { | |||||
height: auto; | |||||
} | |||||
</style> |
@@ -0,0 +1,228 @@ | |||||
<template> | |||||
<el-card class="card" shadow="hover"> | |||||
<el-form ref="form" :model="dataObj" label-width="100px"> | |||||
<el-collapse> | |||||
<el-collapse-item> | |||||
<template slot="title"> | |||||
<el-row style="margin-top: 25px;padding-right: 20px;"> | |||||
<el-col :span="8"> | |||||
<el-form-item label="附加项目类型"> | |||||
<el-input v-model="dataObj.fuStyle"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="8"> | |||||
<el-form-item label="附加项目名称"> | |||||
<el-input v-model="dataObj.fuName"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="8"> | |||||
<el-form-item label="计价单位"> | |||||
<el-input v-model="dataObj.countUnit"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
</template> | |||||
<el-row> | |||||
<el-col :span="10"> | |||||
<el-form-item label="使用日期"> | |||||
<el-col :span="11"> | |||||
<el-date-picker type="date" placeholder="选择日期" v-model="dataObj.use_date" | |||||
style="width: 100%;"></el-date-picker> | |||||
</el-col> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="8"> | |||||
<el-form-item label-width="100px" label="出游人姓名"> | |||||
<el-input v-model="dataObj.travelerName"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="6"> | |||||
<el-form-item label="确认号"> | |||||
<el-input v-model="dataObj.confirmNo"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
<el-form-item> | |||||
<el-table | |||||
:data="dataObj.tableData" | |||||
border | |||||
height="500" | |||||
:summary-method="getSummaries" | |||||
show-summary | |||||
style="width: 100%; margin-top: 20px"> | |||||
<el-table-column | |||||
prop="date" | |||||
label="日期" | |||||
width="180"> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="salePrice" | |||||
label="售卖价"> | |||||
<template slot-scope="scope"> | |||||
<el-input v-model="scope.row.salePrice"></el-input> | |||||
</template> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="countPrice" | |||||
label="成本价"> | |||||
<template slot-scope="scope"> | |||||
<el-input v-model="scope.row.countPrice"></el-input> | |||||
</template> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="amount" | |||||
label="数量"> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="provider" | |||||
label="供应商"> | |||||
</el-table-column> | |||||
<el-table-column | |||||
prop="note" | |||||
label="备注"> | |||||
</el-table-column> | |||||
</el-table> | |||||
</el-form-item> | |||||
<el-row> | |||||
<el-col :span="6"> | |||||
<el-form-item label-width="100px" label="对方订单号"> | |||||
<el-input v-model="dataObj.taOrderNo"></el-input> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="6"> | |||||
<el-form-item label-width="100px" label="资源负责人"> | |||||
<span>{{dataObj.sourceResponser}}</span> | |||||
</el-form-item> | |||||
</el-col> | |||||
<el-col :span="12"> | |||||
<el-form-item label="资源状态"> | |||||
<el-button-group v-model="dataObj.sourceState"> | |||||
<el-button type="primary">未发单</el-button> | |||||
<el-button type="">已发单</el-button> | |||||
<el-button type="">已确认</el-button> | |||||
<el-button type="">已取消</el-button> | |||||
</el-button-group> | |||||
</el-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
<el-row> | |||||
<el-col :span="24"> | |||||
<el-form-item label-width="100px" label="附加项目说明"> | |||||
<span>{{dataObj.fuIntro}}</span> | |||||
</el-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
</el-collapse-item> | |||||
</el-collapse> | |||||
</el-form> | |||||
</el-card> | |||||
</template> | |||||
<script> | |||||
import axios from "axios" | |||||
export default { | |||||
name: "hotelother", | |||||
props: {dataObj: Object}, | |||||
data() { | |||||
return {date: [], day: []} | |||||
}, | |||||
watch: { | |||||
date(val) { | |||||
console.log(val) | |||||
this.$set(this.dataObj, "check_in_date", val[0]) | |||||
this.$set(this.dataObj, "check_out_date", val[1]) | |||||
let date1 = new Date(val[0]); | |||||
let date2 = new Date(val[1]); | |||||
let day = this.getAllDateCN(date1, date2) | |||||
let tableData = []; | |||||
for (let item of day) { | |||||
tableData.push({ | |||||
date: item, | |||||
salePrice: '', | |||||
countPrice: '', | |||||
amount: '', | |||||
note: '', | |||||
provider: '' | |||||
}) | |||||
} | |||||
this.$set(this.dataObj, 'tableData', tableData) | |||||
} | |||||
}, | |||||
methods: { | |||||
getAllDateCN(startTime, endTime) { | |||||
var date_all = [] | |||||
var i = 0 | |||||
while ((endTime.getTime() - startTime.getTime()) >= 0) { | |||||
var year = startTime.getFullYear() | |||||
var month = startTime.getMonth() + 1 | |||||
var day = startTime.getDate() | |||||
date_all[i] = year + '-' + month + '-' + day | |||||
startTime.setDate(startTime.getDate() + 1) | |||||
i += 1 | |||||
} | |||||
return date_all | |||||
}, | |||||
getSummaries(param) { | |||||
const {columns, data} = param; | |||||
const sums = []; | |||||
columns.forEach((column, index) => { | |||||
if (index === 0) { | |||||
sums[index] = '总价'; | |||||
return; | |||||
} | |||||
if (index === 3) { | |||||
sums[index] = '利润'; | |||||
return; | |||||
} | |||||
const values = data.map(item => Number(item[column.property])); | |||||
if (!values.every(value => isNaN(value))) { | |||||
sums[index] = values.reduce((prev, curr) => { | |||||
const value = Number(curr); | |||||
if (!isNaN(value)) { | |||||
return prev + curr; | |||||
} else { | |||||
return prev; | |||||
} | |||||
}, 0); | |||||
if (index == 1) { | |||||
this.dataObj.total_amount = sums[index]; | |||||
this.$set(this.dataObj, 'total_amount', sums[index]); | |||||
} | |||||
if (index == 2) { | |||||
this.dataObj.cost_amount = sums[index]; | |||||
this.$set(this.dataObj, 'cost_amount', sums[index]); | |||||
} | |||||
if (index == 4) { | |||||
this.dataObj.profit_amount = sums[index]; | |||||
this.$set(this.dataObj, 'profit_amount', sums[index]); | |||||
} | |||||
sums[index] += ' 元'; | |||||
} else { | |||||
sums[index] = 'N/A'; | |||||
} | |||||
}); | |||||
return sums; | |||||
}, | |||||
onSubmit() { | |||||
console.log('submit!'); | |||||
} | |||||
}, | |||||
mounted() { | |||||
if (process.env.NODE_ENV !== 'production') { | |||||
axios.defaults.baseURL = '/api' //关键代码 | |||||
} | |||||
} | |||||
} | |||||
</script> | |||||
<style scoped> | |||||
.card { | |||||
margin: 20px; | |||||
} | |||||
.card /deep/ .el-collapse-item__header { | |||||
height: auto; | |||||
} | |||||
</style> |
@@ -0,0 +1,174 @@ | |||||
// 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 App from './App' | |||||
import { | |||||
// Pagination, | |||||
// Dialog, | |||||
// Autocomplete, | |||||
// Dropdown, | |||||
// DropdownMenu, | |||||
// DropdownItem, | |||||
// Menu, | |||||
// Submenu, | |||||
// MenuItem, | |||||
// MenuItemGroup, | |||||
Input, | |||||
// InputNumber, | |||||
// Radio, | |||||
// RadioGroup, | |||||
// RadioButton, | |||||
// Checkbox, | |||||
// CheckboxButton, | |||||
// CheckboxGroup, | |||||
// Switch, | |||||
Select, | |||||
Option, | |||||
OptionGroup, | |||||
Button, | |||||
ButtonGroup, | |||||
Table, | |||||
TableColumn, | |||||
DatePicker, | |||||
TimeSelect, | |||||
TimePicker, | |||||
// Popover, | |||||
// Tooltip, | |||||
// Breadcrumb, | |||||
// BreadcrumbItem, | |||||
Form, | |||||
FormItem, | |||||
// Tabs, | |||||
// TabPane, | |||||
// Tag, | |||||
// Tree, | |||||
// Alert, | |||||
// Slider, | |||||
Icon, | |||||
Row, | |||||
Col, | |||||
// Upload, | |||||
// Progress, | |||||
// Spinner, | |||||
// Badge, | |||||
Card, | |||||
// Rate, | |||||
// Steps, | |||||
// Step, | |||||
// Carousel, | |||||
// CarouselItem, | |||||
Collapse, | |||||
CollapseItem, | |||||
// Cascader, | |||||
// ColorPicker, | |||||
// Transfer, | |||||
// Container, | |||||
// Header, | |||||
// Aside, | |||||
// Main, | |||||
// Footer, | |||||
// Timeline, | |||||
// TimelineItem, | |||||
// Link, | |||||
// Divider, | |||||
// Image, | |||||
// Calendar, | |||||
// Backtop, | |||||
// PageHeader, | |||||
// CascaderPanel, | |||||
Loading, | |||||
MessageBox, | |||||
Message, | |||||
Notification | |||||
} from 'element-ui'; | |||||
// Vue.use(Pagination); | |||||
// Vue.use(Dialog); | |||||
// Vue.use(Autocomplete); | |||||
// Vue.use(Dropdown); | |||||
// Vue.use(DropdownMenu); | |||||
// Vue.use(DropdownItem); | |||||
// Vue.use(Menu); | |||||
// Vue.use(Submenu); | |||||
// Vue.use(MenuItem); | |||||
// Vue.use(MenuItemGroup); | |||||
Vue.use(Input); | |||||
// Vue.use(InputNumber); | |||||
// Vue.use(Radio); | |||||
// Vue.use(RadioGroup); | |||||
// Vue.use(RadioButton); | |||||
// Vue.use(Checkbox); | |||||
// Vue.use(CheckboxButton); | |||||
// Vue.use(CheckboxGroup); | |||||
// Vue.use(Switch); | |||||
Vue.use(Select); | |||||
Vue.use(Option); | |||||
Vue.use(OptionGroup); | |||||
Vue.use(Button); | |||||
Vue.use(ButtonGroup); | |||||
Vue.use(Table); | |||||
Vue.use(TableColumn); | |||||
Vue.use(DatePicker); | |||||
Vue.use(TimeSelect); | |||||
Vue.use(TimePicker); | |||||
// Vue.use(Popover); | |||||
// Vue.use(Tooltip); | |||||
// Vue.use(Breadcrumb); | |||||
// Vue.use(BreadcrumbItem); | |||||
Vue.use(Form); | |||||
Vue.use(FormItem); | |||||
// Vue.use(Tabs); | |||||
// Vue.use(TabPane); | |||||
// Vue.use(Tag); | |||||
// Vue.use(Tree); | |||||
// Vue.use(Alert); | |||||
// Vue.use(Slider); | |||||
Vue.use(Icon); | |||||
Vue.use(Row); | |||||
Vue.use(Col); | |||||
// Vue.use(Upload); | |||||
// Vue.use(Progress); | |||||
// Vue.use(Spinner); | |||||
// Vue.use(Badge); | |||||
Vue.use(Card); | |||||
// Vue.use(Rate); | |||||
// Vue.use(Steps); | |||||
// Vue.use(Step); | |||||
// Vue.use(Carousel); | |||||
// Vue.use(CarouselItem); | |||||
Vue.use(Collapse); | |||||
Vue.use(CollapseItem); | |||||
// Vue.use(Cascader); | |||||
// Vue.use(ColorPicker); | |||||
// Vue.use(Transfer); | |||||
// Vue.use(Container); | |||||
// Vue.use(Header); | |||||
// Vue.use(Aside); | |||||
// Vue.use(Main); | |||||
// Vue.use(Footer); | |||||
// Vue.use(Timeline); | |||||
// Vue.use(TimelineItem); | |||||
// Vue.use(Link); | |||||
// Vue.use(Divider); | |||||
// Vue.use(Image); | |||||
// Vue.use(Calendar); | |||||
// Vue.use(Backtop); | |||||
// Vue.use(PageHeader); | |||||
// Vue.use(CascaderPanel); | |||||
Vue.use(Loading.directive); | |||||
Vue.prototype.$loading = Loading.service; | |||||
Vue.prototype.$msgbox = MessageBox; | |||||
Vue.prototype.$alert = MessageBox.alert; | |||||
Vue.prototype.$confirm = MessageBox.confirm; | |||||
Vue.prototype.$prompt = MessageBox.prompt; | |||||
Vue.prototype.$notify = Notification; | |||||
Vue.prototype.$message = Message; | |||||
Vue.config.productionTip = false | |||||
/* eslint-disable no-new */ | |||||
new Vue({ | |||||
el: '#app', | |||||
render: h => h(App) | |||||
}); |