Browse Source

first commit

feature/feature-compatible
luobz 7 years ago
commit
731e036a9e
52 changed files with 10880 additions and 0 deletions
  1. BIN
      .DS_Store
  2. 64
      README.md
  3. 35
      build/build.js
  4. 45
      build/check-versions.js
  5. 9
      build/dev-client.js
  6. 89
      build/dev-server.js
  7. 71
      build/utils.js
  8. 12
      build/vue-loader.conf.js
  9. 58
      build/webpack.base.conf.js
  10. 35
      build/webpack.dev.conf.js
  11. 120
      build/webpack.prod.conf.js
  12. 6
      config/dev.env.js
  13. 46
      config/index.js
  14. 3
      config/prod.env.js
  15. 12
      index.html
  16. 9288
      package-lock.json
  17. 67
      package.json
  18. 28
      src/App.vue
  19. 12
      src/api/coupon.js
  20. BIN
      src/assets/.DS_Store
  21. BIN
      src/assets/fonts/iconfont.eot
  22. 91
      src/assets/fonts/iconfont.svg
  23. BIN
      src/assets/fonts/iconfont.ttf
  24. BIN
      src/assets/fonts/iconfont.woff
  25. 45
      src/assets/iconfont.css
  26. BIN
      src/assets/images/arrow-right_03.png
  27. BIN
      src/assets/images/book.png
  28. BIN
      src/assets/images/coupon-bg-red@1x.png
  29. BIN
      src/assets/images/coupon-bg@1x.png
  30. BIN
      src/assets/images/cover.jpg
  31. BIN
      src/assets/images/forest.png
  32. BIN
      src/assets/images/get.png
  33. BIN
      src/assets/images/girl.jpg
  34. BIN
      src/assets/images/hill.png
  35. BIN
      src/assets/images/qrcode.png
  36. BIN
      src/assets/images/received.png
  37. BIN
      src/assets/images/slider-img.png
  38. BIN
      src/assets/images/sunrise.png
  39. BIN
      src/assets/images/sunshine.png
  40. BIN
      src/assets/logo.png
  41. BIN
      src/assets/logotxt.png
  42. 0
      src/assets/styles/main.scss
  43. 288
      src/assets/styles/style.css
  44. 6
      src/bus.js
  45. 62
      src/common/util.js
  46. 18
      src/configs.js
  47. 18
      src/configs.js.default
  48. 18
      src/main.js
  49. 20
      src/models/coupon-model.js
  50. 114
      src/models/utils-model.js
  51. 35
      src/router/index.js
  52. 165
      src/view/month-card.vue

BIN
.DS_Store

64
README.md

@ -0,0 +1,64 @@
> 一个基于vue2.x编写的后台管理项目
## 介绍
### 本项目囊括以下技术和工具:
- [Vue.js](https://cn.vuejs.org/v2/guide/)
- [Sass](https://www.sass.hk/)
- [Webpack](https://doc.webpack-china.org/)
- [Babel](http://babeljs.io/)
- [Element](http://element.eleme.io/#/zh-CN)
- [Axios](https://www.kancloud.cn/yunye/axios)
- [Vue-router](https://router.vuejs.org/zh-cn/installation.html)
### 说明
 这是一个用vuejs2.0和element-ui 2.x搭建的后台管理界面。
### 项目结构
```
├── build #webpack编译相关文件目录,一般不用动
├── config #配置目录
│ ├────dev.env.js #开发环境变量
│ ├────index.js #主配置文件
│ └────prod.env.js #生产环境变量
├── dist #生产环境下build后的文件存放目录(发布目录)
├── src #前端项目源码目录
│ ├───—api #接口地址配置文件目录
│ ├───—assets #资源目录
│ ├───—common #公用方法文件目录
│ ├───—components #组件文件目录
│ ├───—router #路由目录
│ ├───—view #页面文件目录
│ ├───—App.vue #项目入口文件
│ ├───—bus.js #公共通信组件
│ ├───—configs.js #host地址配置文件
│ └────main.js #项目的核心文件
├── index.html #首页入口文件
├── package.json #项目配置文件
└── README.md #项目的说明文档,markdown 格式
```
## 项目编译和运行
``` bash
(1)新开一个命令行窗口
(2)定位到项目目录并安装依赖
> npm install
(3)依赖安装成功后执行启动命令
> npm run dev
# 显示如下内容说明本地启动成功
# DONE Compiled successfully in 7515ms
# Listening at http://localhost:8081
#正式环境编译命令
# build for production with minification
npm run build
```

35
build/build.js

@ -0,0 +1,35 @@
require('./check-versions')()
process.env.NODE_ENV = 'production'
var ora = require('ora')
var rm = require('rimraf')
var path = require('path')
var chalk = require('chalk')
var webpack = require('webpack')
var config = require('../config')
var webpackConfig = require('./webpack.prod.conf')
var spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')
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'
))
})
})

45
build/check-versions.js

@ -0,0 +1,45 @@
var chalk = require('chalk')
var semver = require('semver')
var packageConfig = require('../package.json')
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
}
var versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
},
{
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
}
]
module.exports = function () {
var warnings = []
for (let i = 0; i < versionRequirements.length; i++) {
var 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++) {
var warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}

9
build/dev-client.js

@ -0,0 +1,9 @@
/* eslint-disable */
require('eventsource-polyfill')
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
hotClient.subscribe(function (event) {
if (event.action === 'reload') {
window.location.reload()
}
})

89
build/dev-server.js

@ -0,0 +1,89 @@
require('./check-versions')()
var config = require('../config')
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}
var opn = require('opn')
var path = require('path')
var express = require('express')
var webpack = require('webpack')
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = require('./webpack.dev.conf')
// default port where dev server listens for incoming traffic
var port = process.env.PORT || config.dev.port
// automatically open browser, if not set will be false
var autoOpenBrowser = !!config.dev.autoOpenBrowser
// Define HTTP proxies to your custom API backend
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable
var app = express()
var compiler = webpack(webpackConfig)
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: true
})
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: () => {}
})
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
// proxy api requests
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(options.filter || context, options))
})
// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')())
// serve webpack bundle output
app.use(devMiddleware)
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)
// serve pure static assets
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static('./static'))
var uri = 'http://localhost:' + port
var _resolve
var readyPromise = new Promise(resolve => {
_resolve = resolve
})
console.log('> Starting dev server...')
devMiddleware.waitUntilValid(() => {
console.log('> Listening at ' + uri + '\n')
// when env is testing, don't need open it
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri)
}
_resolve()
})
var server = app.listen(port)
module.exports = {
ready: readyPromise,
close: () => {
server.close()
}
}

71
build/utils.js

@ -0,0 +1,71 @@
var path = require('path')
var config = require('../config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
exports.assetsPath = function (_path) {
var assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
var cssLoader = {
loader: 'css-loader',
options: {
minimize: process.env.NODE_ENV === 'production',
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
var loaders = [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) {
var output = []
var loaders = exports.cssLoaders(options)
for (var extension in loaders) {
var loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}

12
build/vue-loader.conf.js

@ -0,0 +1,12 @@
var utils = require('./utils')
var config = require('../config')
var isProduction = process.env.NODE_ENV === 'production'
module.exports = {
loaders: utils.cssLoaders({
sourceMap: isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap,
extract: isProduction
})
}

58
build/webpack.base.conf.js

@ -0,0 +1,58 @@
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
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')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
}

35
build/webpack.dev.conf.js

@ -0,0 +1,35 @@
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})
module.exports = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
},
// cheap-module-eval-source-map is faster for development
devtool: '#cheap-module-eval-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': config.dev.env
}),
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
new FriendlyErrorsPlugin()
]
})

120
build/webpack.prod.conf.js

@ -0,0 +1,120 @@
var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var CopyWebpackPlugin = require('copy-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
var env = config.build.env
var webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true
})
},
devtool: config.build.productionSourceMap ? '#source-map' : 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 webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css')
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: {
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'
}),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module, count) {
// 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',
chunks: ['vendor']
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
var 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) {
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig

6
config/dev.env.js

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

46
config/index.js

@ -0,0 +1,46 @@
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')
module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,
// 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
},
dev: {
env: require('./dev.env'),
port: 8080,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
// '/api': {
// target: 'http://localhost:3000',
// changeOrigin: true,
// pathRewrite: {
// '^/api': '/api'
// }
// }
},
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false
}
}

3
config/prod.env.js

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

12
index.html

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<title>一号家政</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

9288
package-lock.json
File diff suppressed because it is too large
View File

67
package.json

@ -0,0 +1,67 @@
{
"name": "litadmin",
"version": "1.2.0",
"description": "A Vue.js project for admin",
"author": "jerry9022@qq.com",
"private": true,
"scripts": {
"server": "node server/bin/www",
"dev": "node build/dev-server.js",
"build": "node build/build.js"
},
"dependencies": {
"axios": "^0.16.2",
"echarts": "^3.7.1",
"element-ui": "^2.0.7",
"lodash": "^4.17.4",
"vue": "^2.5.9",
"vue-router": "^2.8.1",
"vue-template-compiler": "^2.5.9"
},
"devDependencies": {
"autoprefixer": "^6.7.2",
"babel-core": "^6.26.0",
"babel-loader": "^6.2.10",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-preset-env": "^1.6.0",
"babel-preset-stage-2": "^6.24.1",
"babel-register": "^6.26.0",
"chalk": "^1.1.3",
"connect-history-api-fallback": "^1.3.0",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.26.4",
"eventsource-polyfill": "^0.9.6",
"express": "^4.15.4",
"extract-text-webpack-plugin": "^2.1.2",
"file-loader": "^0.10.0",
"friendly-errors-webpack-plugin": "^1.1.3",
"function-bind": "^1.1.1",
"html-webpack-plugin": "^2.30.1",
"http-proxy-middleware": "^0.17.3",
"node-sass": "^4.9.0",
"opn": "^4.0.2",
"optimize-css-assets-webpack-plugin": "^1.3.2",
"ora": "^1.3.0",
"rimraf": "^2.6.2",
"sass-loader": "^6.0.6",
"semver": "^5.4.1",
"style-loader": "^0.16.1",
"url-loader": "^0.5.9",
"vue-loader": "^11.1.4",
"vue-style-loader": "^2.0.0",
"webpack": "^2.7.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-middleware": "^1.12.0",
"webpack-hot-middleware": "^2.19.1",
"webpack-merge": "^2.6.1"
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

28
src/App.vue

@ -0,0 +1,28 @@
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style>
body{
padding:0px;
margin:0px auto;
}
a{
text-decoration:none;
}
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: left;
color: #2c3e50;
}
</style>

12
src/api/coupon.js

@ -0,0 +1,12 @@
export default {
// -- 领取优惠券 --
giveCoupon: {
method: 'PUT',
url: '/mall/web/coupon/receive',
},
// -- 获取优惠券信息 --
getCouponInfo: {
method: 'GET',
url: '/mall/web/coupon/:batchNo',
},
}

BIN
src/assets/.DS_Store

BIN
src/assets/fonts/iconfont.eot

91
src/assets/fonts/iconfont.svg

@ -0,0 +1,91 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>
Created by FontForge 20120731 at Fri Apr 14 10:37:19 2017
By admin
</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024" >
<font-face
font-family="iconfont"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
panose-1="2 0 6 3 0 0 0 0 0 0"
ascent="896"
descent="-128"
x-height="792"
bbox="0 -212 1099.6 896"
underline-thickness="0"
underline-position="0"
unicode-range="U+0078-EACD"
/>
<missing-glyph
/>
<glyph glyph-name=".notdef"
/>
<glyph glyph-name=".notdef"
/>
<glyph glyph-name=".null" horiz-adv-x="0"
/>
<glyph glyph-name="nonmarkingreturn" horiz-adv-x="341"
/>
<glyph glyph-name="x" unicode="x" horiz-adv-x="1001"
d="M281 543q-27 -1 -53 -1h-83q-18 0 -36.5 -6t-32.5 -18.5t-23 -32t-9 -45.5v-76h912v41q0 16 -0.5 30t-0.5 18q0 13 -5 29t-17 29.5t-31.5 22.5t-49.5 9h-133v-97h-438v97zM955 310v-52q0 -23 0.5 -52t0.5 -58t-10.5 -47.5t-26 -30t-33 -16t-31.5 -4.5q-14 -1 -29.5 -0.5
t-29.5 0.5h-32l-45 128h-439l-44 -128h-29h-34q-20 0 -45 1q-25 0 -41 9.5t-25.5 23t-13.5 29.5t-4 30v167h911zM163 247q-12 0 -21 -8.5t-9 -21.5t9 -21.5t21 -8.5q13 0 22 8.5t9 21.5t-9 21.5t-22 8.5zM316 123q-8 -26 -14 -48q-5 -19 -10.5 -37t-7.5 -25t-3 -15t1 -14.5
t9.5 -10.5t21.5 -4h37h67h81h80h64h36q23 0 34 12t2 38q-5 13 -9.5 30.5t-9.5 34.5q-5 19 -11 39h-368zM336 498v228q0 11 2.5 23t10 21.5t20.5 15.5t34 6h188q31 0 51.5 -14.5t20.5 -52.5v-227h-327z" />
<glyph glyph-name="user" unicode="&#xe600;"
d="M639 256q59 35 94 96t35 133q0 110 -76.5 187.5t-185 77.5t-185 -77.5t-76.5 -187.5q0 -73 36.5 -135t96.5 -96q-120 -40 -199.5 -139t-91.5 -228q-1 -14 8 -25t23.5 -12.5t25.5 7.5t12 24q13 139 115 232t241.5 93t241.5 -93t114 -232q2 -14 12 -23t23 -9h3
q14 2 23.5 13t7.5 25q-11 132 -93 232t-205 137zM314 485q0 81 56.5 138.5t136 57.5t136 -57.5t56.5 -138.5t-56.5 -138.5t-136 -57.5t-136 57.5t-56.5 138.5z" />
<glyph glyph-name="home1" unicode="&#xe635;"
d="M950 375l-415 416q-5 4 -12 7q-19 8 -35 -7l-415 -416q-10 -9 -10 -22.5t9.5 -23t23 -9.5t22.5 10l393 393l394 -393q9 -10 22.5 -10t22.5 9.5t9 23t-9 22.5zM770 362q-13 0 -22.5 -9.5t-9.5 -22.5v-266h-453v266q0 13 -9.5 22.5t-23 9.5t-22.5 -9.5t-9 -22.5v-298
q0 -12 8.5 -21.5t21.5 -9.5q1 -1 2 -1h517q1 0 2 1h4q8 2 14 6q1 2 2 3h1q1 2 2 3h1q2 3 3 7l0.5 0.5l0.5 0.5v1t1 2v2v0q1 3 1 6v298q0 13 -9.5 22.5t-22.5 9.5z" />
<glyph glyph-name="home" unicode="&#xe6a1;"
d="M979 345l-435 435v0q-13 13 -32 13t-32 -13v0l-435 -435q-18 -18 -18 -45t18 -45v0q19 -19 46 -19h37v-288q0 -4 0.5 -10.5t6 -23t14.5 -29t28.5 -23t46.5 -10.5h128q18 0 31 6.5t19 16t9.5 19t4.5 16.5v6v256h96h96v-256q0 -2 0.5 -6.5t4 -15.5t9.5 -19.5t19 -15.5
t31 -7h128q27 0 46.5 10t28.5 24t14.5 28t6.5 24v10v288h37q27 0 46 19v0q18 18 18 45t-18 45z" />
<glyph glyph-name="setting1" unicode="&#xe601;"
d="M892 402q-14 50 -39 95l74 112l-106 106l-112 -74q-45 25 -95 39l-27 132h-150l-27 -132q-50 -13 -95 -39l-112 74l-106 -106l74 -112q-25 -45 -39 -95l-132 -27v-150l132 -27q14 -50 39 -95l-74 -112l106 -106l112 74q45 -26 95 -39l27 -132h150l27 132q50 13 95 39
l112 -74l106 106l-74 112q25 45 39 95l132 27v150l-132 27v0zM690 300q0 -74 -52 -126t-126 -52t-126 52t-52 126t52 126t126 52t126 -52t52 -126z" />
<glyph glyph-name="setting" unicode="&#xe664;"
d="M896 389l-82 16q-6 17 -14 34l46 70q11 16 9 35t-16 32l-51 51q-11 11 -25 14t-24.5 0.5t-17.5 -7.5l-70 -46q-17 8 -34 14l-16 82q-4 18 -19 30.5t-34 12.5h-72q-19 0 -34 -12.5t-19 -30.5l-16 -82q-17 -6 -34 -14l-70 46q-7 5 -17.5 7.5t-24.5 -0.5t-25 -14l-51 -51
q-14 -13 -16 -32t9 -35l46 -70q-8 -17 -14 -34l-82 -16q-18 -4 -30.5 -19t-12.5 -34v-72q0 -19 12.5 -34t30.5 -19l82 -16q6 -17 14 -34l-46 -70q-11 -16 -9 -35t16 -32l51 -51q16 -16 38 -16q16 0 29 9l70 46q17 -8 34 -14l16 -82q4 -18 19 -30.5t34 -12.5h72q19 0 34 12.5
t19 30.5l16 82q17 6 34 14l70 -46q7 -5 17.5 -7.5t24.5 0.5t25 14l51 51q14 13 16 32t-9 35l-46 70q8 17 14 34l82 16q18 4 30.5 19t12.5 34v72q0 19 -12.5 34t-30.5 19zM511 99q-84 0 -143.5 59.5t-59.5 143.5t59.5 143.5t143.5 59.5t143.5 -59.5t59.5 -143.5t-59.5 -143.5
t-143.5 -59.5zM512 300zM405 300q0 44 31.5 75.5t75.5 31.5t75.5 -31.5t31.5 -75.5t-31.5 -75.5t-75.5 -31.5t-75.5 31.5t-31.5 75.5z" />
<glyph glyph-name="down" unicode="&#xe623;"
d="M240 464l268 -289l268 289h-536z" />
<glyph glyph-name="books1" unicode="&#xe67f;"
d="M979 224l-422 -224q-423 83 -461 96q-18 6 -27 19.5t-8 25t3 19.5q0 11 16 27t29 11q8 -2 122 -28t223 -50l109 -24l442 237l2 2t3.5 5.5t4 9t1 10.5t-4.5 11q-3 12 -11 15t-14 0l-7 -2l-422 -218q-442 96 -467 103q-32 8 -32 57q0 19 22 31.5t42 7.5q25 -7 441 -103v0
l442 237q1 1 2 2.5t3.5 5.5t4 8.5t1 10.5t-4.5 12q-5 8 -15 9.5t-16 -0.5l-7 -3l-416 -211q-435 96 -461 102q-22 5 -30 23t-2 35t25 28.5t45 3.5q12 -2 120.5 -25t206 -42t102.5 -16q13 6 442 236q2 9 0 16t-6.5 10t-8.5 4.5t-8 1.5h-3q-346 58 -416 71q-31 5 -52 5t-26 -2
l-5 -3l-384 -199q-2 0 -6 -1t-15.5 -5.5t-21.5 -12t-21.5 -23t-18.5 -34.5q-10 -21 -6 -40t12.5 -31.5t17 -23.5t8.5 -14q0 -2 -8.5 -7.5t-18 -20t-12.5 -36.5q-1 -22 2.5 -39.5t10.5 -28t13.5 -18t10 -11.5t2.5 -6q0 -1 -7 -4t-16.5 -17t-15.5 -43q-11 -71 48 -109l10 -6
l499 -115l442 250q1 0 2 1.5t3.5 5.5t4 8t1 8.5t-4.5 8.5q-5 8 -13 9.5t-14 -0.5zM518 730l269 -52l-128 -70l-256 58z" />
<glyph glyph-name="leaf" unicode="&#xe645;"
d="M517 714h7q54 -106 61 -120q7 -12 14 -14t19 3q7 3 19 9.5t16 8.5q10 6 13 4q2 -1 2.5 -3t0.5 -3.5t-1 -4.5t-1 -4q-9 -50 -29 -161q-4 -20 -2 -31q3 -19 17 -8q7 5 18 17q33 38 63 74q11 13 15 -4q0 -1 6 -23q5 -17 11 -20.5t22 -0.5q46 10 77 17q10 2 13 -1t0 -13
q-5 -21 -22 -84q-7 -27 -4 -33t28 -19q13 -7 13.5 -10.5t-11.5 -13.5q-9 -8 -58 -49.5t-76 -63.5q-4 -4 -11 -10q-24 -20 -26.5 -27t4.5 -32q4 -11 6 -18q3 -13 1 -16t-16 -1q-96 11 -153 18q-19 2 -19 -17v-20q0 -27 3 -167h-33q-1 20 -1 21q1 20 3.5 76t3.5 87
q0 14 -4 17.5t-19 1.5q-110 -12 -154 -18q-10 -1 -12.5 2.5t0.5 12.5q0 1 3 11t5 15q10 27 -14 46q-49 40 -146 124q-4 3 -10 8t-7.5 5.5t-3 4t-0.5 4t4 3.5t7.5 5t12.5 6q16 8 18.5 13.5t-1.5 22.5q-4 15 -12 45.5t-12 46.5q-3 14 -1 16.5t16 -0.5q3 -1 70 -15
q20 -4 26 -0.5t12 22.5q4 15 4 16q1 1 1.5 5t2 6.5t4.5 3.5q3 0 4.5 -1.5t4 -5t3.5 -3.5q4 -5 27.5 -32t35.5 -42q1 -1 4 -4.5t4.5 -5.5t5 -4.5t5.5 -1.5t7 2q3 1 5 3.5t2.5 6.5t0 6t-1.5 7t-1 7q-6 32 -16.5 91.5t-14.5 82.5q-2 10 1 12q2 2 10.5 -2t22.5 -11.5t17 -8.5
q20 -10 29 8q58 113 62 123zM379 605z" />
<glyph glyph-name="users1" unicode="&#xe65a;"
d="M384.5 765q79.5 0 135.5 -56t56 -135.5t-56 -135.5t-135.5 -56t-135.5 56t-56 135.5t56 135.5t135.5 56zM384 829q-105 0 -180 -75t-75 -180.5t75 -180.5t180.5 -75t180.5 75t75 180.5t-75 180.5t-181 75v0zM384.5 318q64.5 0 124.5 -25q57 -24 101 -68t68 -101
q25 -60 25 -124q0 -27 -18.5 -45.5t-44.5 -18.5h-511q-26 0 -44.5 18.5t-18.5 45.5q0 64 25 124q24 57 68 101t101 68q60 25 124.5 25zM384 382q-104 0 -192 -51t-139 -139t-51 -192q0 -53 37.5 -90.5t89.5 -37.5h511q52 0 89.5 37.5t37.5 90.5q0 104 -51 192t-139.5 139
t-192.5 51v0zM775 425q55 34 87.5 91.5t32.5 124.5q0 106 -75 180.5t-180 74.5q-87 0 -156 -53q34 -13 64 -34q43 23 92 23q79 0 135 -56t56 -135t-56 -135q-55 -55 -132 -56q-17 -36 -44 -67q20 3 41 3q64 0 124 -25q57 -24 101 -68.5t68 -101.5q25 -59 25 -124
q0 -26 -18.5 -45t-44.5 -19h-96v-3q0 -32 -12 -61h108q52 0 89.5 37.5t37.5 90.5q0 121 -68.5 218.5t-178.5 139.5z" />
<glyph glyph-name="menuunfold" unicode="&#xeacc;"
d="M991 703h-959q-13 0 -22.5 9.5t-9.5 22.5v0q0 13 9.5 22.5t22.5 9.5h959q13 0 22.5 -9.5t9.5 -22.5v0q0 -13 -9.5 -22.5t-22.5 -9.5zM672 385h-640q-13 0 -22.5 9.5t-9.5 22.5v0q0 14 9.5 23t22.5 9h640q13 0 22.5 -9t9.5 -23v0q0 -13 -9.5 -22.5t-22.5 -9.5zM991 65
h-959q-13 0 -22.5 9.5t-9.5 22.5v0q0 13 9.5 22.5t22.5 9.5h959q13 0 22.5 -9.5t9.5 -22.5v0q0 -13 -9.5 -22.5t-22.5 -9.5zM832 318v263q0 7 6.5 10t11.5 -1l170 -132q4 -3 4 -8.5t-4 -9.5l-170 -131q-5 -4 -11.5 -1t-6.5 10z" />
<glyph glyph-name="menufold" unicode="&#xeacd;"
d="M1 735v0q0 13 9.5 22.5t22.5 9.5h959q13 0 22.5 -9.5t9.5 -22.5v0q0 -13 -9.5 -22.5t-22.5 -9.5h-959q-13 0 -22.5 9.5t-9.5 22.5zM320 417v0q0 14 9.5 23t22.5 9h640q13 0 22.5 -9t9.5 -23v0q0 -13 -9.5 -22.5t-22.5 -9.5h-640q-13 0 -22.5 9.5t-9.5 22.5zM1 97v0
q0 13 9.5 22.5t22.5 9.5h959q13 0 22.5 -9.5t9.5 -22.5v0q0 -13 -9.5 -22.5t-22.5 -9.5h-959q-13 0 -22.5 9.5t-9.5 22.5zM174 309l-170 131q-4 4 -4 9.5t4 8.5l170 132q5 4 11.5 1t6.5 -10v-264q0 -6 -6.5 -9t-11.5 1z" />
<glyph glyph-name="books" unicode="&#xe605;" horiz-adv-x="1152"
d="M224 768h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5zM192 576h-128v64h128v-64zM544 768h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5
t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5zM512 576h-128v64h128v-64zM765 719l-171 -87q-12 -6 -16 -18.5t1 -24.5l288 -571q6 -12 19 -16.5t24 1.5l172 87q12 6 16 18.5t-2 24.5l-288 571q-6 12 -18.5 16t-24.5 -1zM928 32q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5
t9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5z" />
<glyph glyph-name="users" unicode="&#xe883;" horiz-adv-x="1098"
d="M339 384q-93 -3 -152 -73h-76q-47 0 -79 23t-32 68q0 201 71 201q3 0 24.5 -12t56 -24t67.5 -12q39 0 76 13q-2 -21 -2 -38q0 -79 46 -146zM951 20q0 -69 -42 -108.5t-111 -39.5h-499q-69 0 -111 39.5t-42 108.5q0 30 2 59t8 62.5t15.5 62t24.5 55.5t35 46.5t49 30.5
t64 11q6 0 24.5 -12t41.5 -27t61.5 -27.5t77 -12.5t77 12.5t61.5 27.5t41.5 27t24.5 12q35 0 64 -11t49 -30.5t35.5 -46.5t24.5 -55.5t15 -62t8 -62.5t2 -59zM366 749.5q0 -60.5 -43 -103.5t-103.5 -43t-103.5 43t-43 103.5t43 103.5t103.5 43t103.5 -43t43 -103.5zM768 530
q0 -91 -64.5 -155t-155 -64t-155 64t-64.5 155t64.5 155.5t155 64.5t155 -64.5t64.5 -155.5zM1097 402q0 -45 -32 -68t-79 -23h-76q-59 70 -152 73q47 67 47 146q0 17 -3 38q37 -13 76 -13q33 0 67.5 12t56 24t24.5 12q71 0 71 -201zM1024 749.5q0 -60.5 -43 -103.5
t-103.5 -43t-103.5 43t-43 103.5t43 103.5t103.5 43t103.5 -43t43 -103.5z" />
<glyph glyph-name="books2" unicode="&#xe7b9;"
d="M454 832l-300 -94q-39 -8 -64 -39t-25 -71v-487q0 -40 25 -71t64 -39l300 -94v895zM233 274v223h55v-223h-55zM680 49v672h109q2 0 2 -2v-669q0 -1 -2 -1h-109zM512 -6v782h110v-1v-781v0h-110zM847 105v558h111q1 0 1 -1v-555q0 -2 -2 -2h-110z" />
</font>
</defs></svg>

BIN
src/assets/fonts/iconfont.ttf

BIN
src/assets/fonts/iconfont.woff

45
src/assets/iconfont.css

@ -0,0 +1,45 @@
@font-face {font-family: "iconfont";
src: url('fonts/iconfont.eot?t=1492137439402'); /* IE9*/
src: url('fonts/iconfont.eot?t=1492137439402#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('fonts/iconfont.woff?t=1492137439402') format('woff'), /* chrome, firefox */
url('fonts/iconfont.ttf?t=1492137439402') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('fonts/iconfont.svg?t=1492137439402#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family:"iconfont" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-user:before { content: "\e600"; }
.icon-home1:before { content: "\e635"; }
.icon-home:before { content: "\e6a1"; }
.icon-setting1:before { content: "\e601"; }
.icon-setting:before { content: "\e664"; }
.icon-down:before { content: "\e623"; }
.icon-books1:before { content: "\e67f"; }
.icon-leaf:before { content: "\e645"; }
.icon-users1:before { content: "\e65a"; }
.icon-menuunfold:before { content: "\eacc"; }
.icon-menufold:before { content: "\eacd"; }
.icon-books:before { content: "\e605"; }
.icon-users:before { content: "\e883"; }
.icon-books2:before { content: "\e7b9"; }

BIN
src/assets/images/arrow-right_03.png

Before After
Width: 15  |  Height: 23  |  Size: 1.1 KiB

BIN
src/assets/images/book.png

Before After
Width: 128  |  Height: 128  |  Size: 10 KiB

BIN
src/assets/images/coupon-bg-red@1x.png

Before After
Width: 363  |  Height: 109  |  Size: 17 KiB

BIN
src/assets/images/coupon-bg@1x.png

Before After
Width: 355  |  Height: 50  |  Size: 4.0 KiB

BIN
src/assets/images/cover.jpg

Before After
Width: 1024  |  Height: 601  |  Size: 100 KiB

BIN
src/assets/images/forest.png

Before After
Width: 480  |  Height: 360  |  Size: 396 KiB

BIN
src/assets/images/get.png

Before After
Width: 62  |  Height: 62  |  Size: 3.8 KiB

BIN
src/assets/images/girl.jpg

Before After
Width: 150  |  Height: 220  |  Size: 18 KiB

BIN
src/assets/images/hill.png

Before After
Width: 200  |  Height: 150  |  Size: 46 KiB

BIN
src/assets/images/qrcode.png

Before After
Width: 76  |  Height: 76  |  Size: 6.3 KiB

BIN
src/assets/images/received.png

Before After
Width: 62  |  Height: 62  |  Size: 3.8 KiB

BIN
src/assets/images/slider-img.png

Before After
Width: 375  |  Height: 175  |  Size: 90 KiB

BIN
src/assets/images/sunrise.png

Before After
Width: 480  |  Height: 360  |  Size: 146 KiB

BIN
src/assets/images/sunshine.png

Before After
Width: 480  |  Height: 360  |  Size: 238 KiB

BIN
src/assets/logo.png

Before After
Width: 96  |  Height: 96  |  Size: 8.0 KiB

BIN
src/assets/logotxt.png

Before After
Width: 86  |  Height: 52  |  Size: 8.2 KiB

0
src/assets/styles/main.scss

288
src/assets/styles/style.css

@ -0,0 +1,288 @@
* {
margin: 0;
padding: 0;
}
.m-page {
width: 100%;
height: 100%;
}
/*月卡详情*/
.m-month-card {
width: 100%;
height: 100%;
background-color: #FFF3E8;
}
.m-slider {
height: 175px;
}
.m-slider img {
object-fit: cover;
}
.month-card-title {
background-color: #fff;
padding-bottom: 52px;
padding-top: 10px;
}
.month-card-title h4 {
font-size: 19px;
color: #232323 !important;
line-height: 21px;
}
.month-card-title p {
font-size: 14px;
color: #666;
line-height: 16px;
}
.month-card-title .f-price {
font-size: 15px;
line-height: 17px;
color: #333;
}
.month-card-area {
position: relative;
height: 100%;
background-color: #FFF3E8;
padding-left:15px;
}
.month-card {
position: relative;
top: -40px;
padding: 5px 10px 10px 0;
background: url(../images/coupon-bg-red@1x.png) no-repeat 0 0 /100% 100%;
}
.month-card-left {
box-sizing: border-box;
color: #fff;
padding-left: 16px;
}
.month-card-right {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
/*margin-right: 5px;*/
}
.get-btn {
width: 34px;
height: 38px;
border: none;
background: none;
/*//margin-top: -15px;*/
font-size: 17px;
line-height: 19px;
color: #fff;
}
.new-man {
font-size: 17px;
line-height: 1;
margin-bottom: 6px;
}
.limit-buy {
font-size: 10px;
line-height: 12px;
color: #FFBAA9;
}
.end-date {
margin-top: 10px;
font-size: 9px;
line-height: 14px;
color: #FFBAA9;
}
.qrcode-img {
width: 76px;
height: 76px;
margin: 0 auto;
margin-top: 15px;
/*background-color: #909090;*/
}
.qrcode-img img {
object-fit: cover;
}
@media (max-width: 350px) {
.month-card-area {
padding-left: 10px;
}
.month-card .f-font-45 {
font-size: 30px;
}
.month-card .get-btn {
font-size: 14px;
}
.month-card .f-mr15 {
margin-right: 5px;
}
.month-card .new-man {
font-size: 14px;
}
.month-card .end-date {
margin-top: 4px;
}
.month-card .month-card-left {
padding-left: 13px;
}
}
/*公共样式*/
.btn-md {
border: none;
background: none;
width: 250px;
height: 40px;
line-height: 40px;
border-radius: 2px;
}
.btn-primary {
width: 80px;
border: none;
background: none;
}
.btn-orange {
width: 80px;
/*height: 24px;*/
-webkit-border-radius: 24px;
-moz-border-radius: 24px;
border-radius: 24px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
border: 1px solid #FE9B36;
background: none;
line-height: 23px;
}
.bg-orange {
background-color: #FE9B36;
}
.bg-gray {
background-color: #D4D4D4;
}
.f-mt5 {
margin-top: 5px;
}
.f-mt10 {
margin-top: 10px;
}
.f-mt20 {
margin-top: 20px;
}
.f-mt-10 {
margin-top: -10px;
}
.f-mt-15 {
margin-top: -15px;
}
.f-mt9 {
margin-top: 9px;
}
.f-mt10 {
margin-top: 10px;
}
.f-mb20 {
margin-bottom: 20px;
}
.f-mb25 {
margin-bottom: 25px;
}
.f-ml20 {
margin-left: 20px;
}
.f-ml27 {
margin-left: 27px;
}
.f-mr10 {
margin-right: 10px;
}
.f-mr15 {
margin-right: 15px;
}
.f-mr20 {
margin-right: 20px;
}
.f-mr27 {
margin-right: 27px;
}
.f-flex {
display: flex;
align-items: center;
}
.justify-between {
justify-content: space-between;
}
.justify-center {
justify-content: center;
}
.f-font-11 {
font-size: 11px;
}
.l-height-15 {
line-height: 15px;
}
.f-font-12 {
font-size: 12px;
line-height: 14px;
}
.f-font-13 {
font-size: 13px;
}
.f-font-15 {
font-size: 15px;
line-height: 17px;
}
.f-font-18 {
font-size: 18px;
}
.f-font-23 {
font-size: 23px;
}
.f-font-45 {
font-size: 45px;
line-height: 1;
}
.f-text-center {
text-align: center;
}
.f-bold {
font-weight: bold;
}
.s-orange {
color: #FE9B36;
}
.s-orange-1 {
color: #E6A96C;
}
.s-orange-2 {
color: #FF9363;
}
.s-white {
color: #fff;
}
.s-gray {
color: #999;
}
.s-gray-1 {
color: #909090;
}
.s-black-1 {
color: #333333;
}
.s-red {
font-weight: bold;
color: #F45252 !important;
}
.line-through {
text-decoration: line-through;
}
.f-hide {
display: none;
}

6
src/bus.js

@ -0,0 +1,6 @@
/**
* Created by jerry on 2017/4/14.
*/
import Vue from 'vue'
export let bus = new Vue()

62
src/common/util.js

@ -0,0 +1,62 @@
/**
* Created by jerry on 2017/4/14.
*/
var SIGN_REGEXP = /([yMdhsm])(\1*)/g
var DEFAULT_PATTERN = 'yyyy-MM-dd'
function padding (s, len) {
let l = len - (s + '').length
for (var i = 0; i < l; i++) { s = '0' + s }
return s
};
export default {
getQueryStringByName: function (name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
var r = window.location.search.substr(1).match(reg)
var context = ''
if (r != null) { context = r[2] }
reg = null
r = null
return context === null || context === '' || context === 'undefined' ? '' : context
},
formatDate: {
format: function (date, pattern) {
pattern = pattern || DEFAULT_PATTERN
return pattern.replace(SIGN_REGEXP, function ($0) {
switch ($0.charAt(0)) {
case 'y': return padding(date.getFullYear(), $0.length)
case 'M': return padding(date.getMonth() + 1, $0.length)
case 'd': return padding(date.getDate(), $0.length)
case 'w': return date.getDay() + 1
case 'h': return padding(date.getHours(), $0.length)
case 'm': return padding(date.getMinutes(), $0.length)
case 's': return padding(date.getSeconds(), $0.length)
}
})
},
parse: function (dateString, pattern) {
var matchs1 = pattern.match(SIGN_REGEXP)
var matchs2 = dateString.match(/(\d)+/g)
if (matchs1.length === matchs2.length) {
var _date = new Date(1970, 0, 1)
for (var i = 0; i < matchs1.length; i++) {
var _int = parseInt(matchs2[i])
var sign = matchs1[i]
switch (sign.charAt(0)) {
case 'y': _date.setFullYear(_int); break
case 'M': _date.setMonth(_int - 1); break
case 'd': _date.setDate(_int); break
case 'h': _date.setHours(_int); break
case 'm': _date.setMinutes(_int); break
case 's': _date.setSeconds(_int); break
}
}
return _date
}
return null
}
}
}

18
src/configs.js

@ -0,0 +1,18 @@
/**
* 设置api请求的baseURL
*/
let configs = {
// 请求协议
protocol : 'http',
// 请求域名
host: 'api.1hjz.3ncto.com.cn',
// 基础路径
basePath: ''
}
export default {
baseURL: configs.protocol + '://' + configs.host + configs.basePath,
// baseURL: '',
isDev: false
}

18
src/configs.js.default

@ -0,0 +1,18 @@
/**
* 设置api请求的baseURL
*/
let configs = {
// 请求协议
protocol : 'http',
// 请求域名
host: 'api.lch.3ncto.com.cn',
// 基础路径
basePath: '/api2.php'
}
export default {
baseURL: configs.protocol + '://' + configs.host + configs.basePath,
// baseURL: '',
isDev: false
}

18
src/main.js

@ -0,0 +1,18 @@
// 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 router from './router'
import '@/assets/iconfont.css'
import '@/assets/styles/main.scss'
import '@/assets/styles/style.css'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
template: '<App/>',
components: {App}
})

20
src/models/coupon-model.js

@ -0,0 +1,20 @@
import utilsModel from './utils-model'
import couponApi from '../api/coupon'
export default {
// 获取优惠券信息
getCouponInfo : (batchNo) =>
utilsModel
.config(couponApi.getCouponInfo, {batchNo: batchNo})
.request(),
// 领取优惠券
giveCoupon : (params) =>
utilsModel
.config(couponApi.giveCoupon)
.request({
data : params
}),
}

114
src/models/utils-model.js

@ -0,0 +1,114 @@
import configs from '../configs';
import axios from 'axios'
import {bus} from '../bus.js'
// axios.defaults.withCredentials = true;
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';//配置请求头
// 添加一个请求拦截器
// axios.interceptors.request.use(function (config) {
// console.dir(config);
// return config;
// }, function (error) {
// // Do something with request error
// return Promise.reject(error);
// });
// 添加一个响应拦截器
axios.interceptors.response.use(function (response) {
if (response.data && response.data.errcode) {
if (parseInt(response.data.errcode) === 40001) {
//未登录
bus.$emit('goto', '/login')
}
}
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
//基地址
let basePath = configs.baseURL;
/**
* @param path {string} path
* @param opts {Object} options
* @return {?Object}
*
* @description
* Normalizes the given path, returning a regular expression
* and the original path.
*
* Inspired by pathRexp in visionmedia/express/lib/utils.js.
*/
const pathReplace = function(path, opts) {
const ret = {
originalPath: path,
patternPath: path
}
path = path
.replace(/([().])/g, '\\$1')
.replace(/(\/)?:(\w+)(\*\?|[?*])?/g, function(_, slash, key, option) {
const optional = (option === '?' || option === '*?') ? '?' : null;
const star = (option === '*' || option === '*?') ? '*' : null;
slash = slash || '';
opts[key] = typeof opts[key] === 'number' ? opts[key].toString() : opts[key];
return ''
+ (optional ? '' : slash)
+ (opts[key] != ''
? opts[key] : '${'+ key +'}')
+ (optional || '');
})
ret.patternPath = path;
return ret;
}
// 处理http请求
const config = function(config, params){
//提取接口url路径
const url = basePath + pathReplace(config.url, params || {}).patternPath;
return {
// 发送请求
request: function(obj) {
// 全部接口带token
obj = obj || {}
obj.params = obj.params || {}
obj.params.token = localStorage.getItem('user_key')
//整合请求配置
const newConfig = Object.assign({}, obj || {}, config, {url: url});
//执行http接口请求
return axios(newConfig).then(successCallback, errorCallback);
}
}
}
// 请求成功回调
const successCallback = (result) => {
// -402用户认证失败,请重新登录 -101没有操作权限
if (result.data.error_code === -402) {
sessionStorage.clear()
localStorage.removeItem('user_key')
//未登录
bus.$emit('goto', '/login')
}
return result.data
}
// 请求失败回调
const errorCallback = (result) => {
return result.data
}
export default {
config: config
}

35
src/router/index.js

@ -0,0 +1,35 @@
import Vue from 'vue'
import Router from 'vue-router'
// 懒加载方式,当路由被访问的时候才加载对应组件
const monthCard = resolve => require(['@/view/month-card'], resolve)
Vue.use(Router)
let router = new Router({
// mode: 'history',
routes: [
{
path: '/month-card',
name: '领取优惠券',
component: monthCard
}
]
})
// router.beforeEach((to, from, next) => {
// console.log('to:' + to.path)
// if (to.path.startsWith('/login')) {
// window.localStorage.removeItem('user_key')
// next()
// } else {
// let user = window.localStorage.getItem('user_key')
// if (!user) {
// next({path: '/login'})
// } else {
// next()
// }
// }
// })
export default router

165
src/view/month-card.vue

@ -0,0 +1,165 @@
<template>
<div class="">
<div class="m-slider">
<img src="../assets/images/slider-img.png" width="100%" height="100%" alt="">
</div>
<div class="month-card-title f-text-center">
<h4 class="">{{getData.goodsName}}</h4>
<p class="f-mt5">{{getData.shortDesc}}</p>
<p class="f-price f-mt10 f-flex justify-center">
<span class="s-gray f-mr15">市场价 : &nbsp;<span class="line-through">{{getData.originalPrice | numFilter}}</span></span>
<span>券后价 : </span><span class="f-font-23 s-red">{{getData.couponPrice | numFilter}}</span>
</p>
</div>
<div class="month-card-area">
<div class="month-card f-flex" style="margin-bottom: -35px;">
<div class="month-card-left" style="width: 76%;">
<div class="f-flex f-mt9">
<div class="f-mb20 f-mr10">
<p v-show="getData.type != 3" class="f-font-15" style="line-height:1;"></p>
<!-- 定额券 -->
<div v-show="getData.type == 1" class="f-bold f-font-45" style="text-shadow: 1px 1px #852B0E;">{{getData.amount | numFilter}}</div>
<!-- 满减券 -->
<div v-show="getData.type == 2" class="f-bold f-font-45" style="text-shadow: 1px 1px #852B0E;">{{getData.amount | numFilter}}</div>
<!-- 折扣 -->
<div v-show="getData.type == 3" class="f-bold f-font-45" style="text-shadow: 1px 1px #852B0E;">{{Number(getData.discount/10)}}</div>
<!-- 定额券 -->
<p v-show="getData.type != 2" class="f-font-12 f-mt5" style="margin-left: 6px;">{{couponType[getData.type]}}</p>
<!-- 满减券 -->
<p v-show="getData.type == 2" class="f-font-12 f-mt5" style="margin-left: 6px;">{{getData.fullAmount | numFilter}}可用</p>
</div>
<div class="f-mb20">
<p class="new-man">{{getData.batchName}}</p>
<p class="limit-buy">({{getData.goodsName}})</p>
<p class="end-date">{{getData.invalidTimeDesc}}</p>
</div>
</div>
</div>
<div class="month-card-right justify-center" style="margin-left:10px;">
<div v-show="getData.couponStatus == 0" class="f-mt-15 f-flex">
<img src="../assets/images/arrow-right_03.png" width="7" height="12" alt="" class="f-mr15">
<button class="get-btn" v-on:click="handleGetCoupon">点击领取</button>
</div>
<img v-show="getData.couponStatus > 0" src="../assets/images/get.png" width="60" height="60" alt="" class="f-mt-10">
</div>
</div>
<div class="f-mt10 f-text-center">
<button class="btn-md bg-gray s-white f-font-18">立即使用</button>
</div>
<div style="padding: 0 10px 20px;">
<p class="s-gray-1 f-font-11 f-mt20" style="line-height: 18px;">使用范围广州市天河区海珠区白云区番禺区花都区从化区越秀区黄埔区南沙区荔湾区</p>
<p class="f-mt10 f-font-11 s-orange-2">
使用流程领券下单关注公众号预约服务
</p>
<div class="f-text-center">
<div class="qrcode-img">
<img src="../assets/images/qrcode.png" width='100%' height="100%" alt="">
</div>
<p class="f-font-11 f-mt5 s-black-1">预约服务请关注公众号</p>
</div>
</div>
</div>
</div>
</template>
<script>
import couponModel from '../models/coupon-model';
export default {
data() {
return {
loading: false,
getData: {},
couponType: {
'1': '定额券',
'2': '满减券',
'3': '折扣券',
}
};
},
methods: {
//
handleInit() {
let that = this;
//
couponModel.getCouponInfo('CB180620024554871101').then(function (result) {
console.log(result.response);
that.loading = false;
if (result.code == 0) {
that.getData = result.response
} else {
console.log(result.msg);
}
});
},
//
handleGetCoupon() {
let that = this;
this.loading = true;
let params = {
batchNo: 'CB180620024554871101',
};
//
couponModel.giveCoupon(params).then(function (result) {
that.loading = false;
if (result.code == 0) {
console.log('领取成功')
} else {
console.log('领取失败')
}
});
},
},
filters: {
numFilter(value) {
//
let transformVal = Number(value/100).toFixed(2)
let realVal = transformVal.substring(0, transformVal.length - 1)
// num.toFixed(3)
return Number(realVal)
}
},
mounted() {
//
this.handleInit();
}
}
</script>
<style>
body {
background-color: #FFF3E8;
}
</style>
Loading…
Cancel
Save