├── .editorconfig ├── .gitignore ├── README.md ├── assets ├── README.md └── main.css ├── components ├── air │ ├── flightsAside.vue │ ├── flightsFilters.vue │ ├── flightsItem.vue │ ├── flightsListHead.vue │ ├── orderAside.vue │ ├── orderForm.vue │ └── searchForm.vue ├── footer.vue ├── header.vue ├── post │ └── menuItem.vue ├── slotButton.vue └── user │ ├── loginForm.vue │ └── registerForm.vue ├── layouts ├── README.md └── default.vue ├── middleware └── README.md ├── nuxt.config.js ├── package-lock.json ├── package.json ├── pages ├── air │ ├── flights.vue │ ├── index.vue │ ├── order.vue │ └── pay.vue ├── hotel │ └── index.vue ├── index.vue ├── post │ └── index.vue ├── slot.vue ├── tab.vue └── user │ └── login.vue ├── plugins ├── axios.js ├── element-ui.js └── localStorage.js ├── static ├── README.md ├── favicon.ico └── qrcode.js ├── store ├── air.js ├── post.js └── user.js └── utils └── utils.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # nyc test coverage 23 | .nyc_output 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Bower dependency directory (https://bower.io/) 29 | bower_components 30 | 31 | # node-waf configuration 32 | .lock-wscript 33 | 34 | # Compiled binary addons (https://nodejs.org/api/addons.html) 35 | build/Release 36 | 37 | # Dependency directories 38 | node_modules/ 39 | jspm_packages/ 40 | 41 | # TypeScript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # parcel-bundler cache (https://parceljs.org/) 63 | .cache 64 | 65 | # next.js build output 66 | .next 67 | 68 | # nuxt.js build output 69 | .nuxt 70 | 71 | # Nuxt generate 72 | dist 73 | 74 | # vuepress build output 75 | .vuepress/dist 76 | 77 | # Serverless directories 78 | .serverless 79 | 80 | # IDE / Editor 81 | .idea 82 | 83 | # Service worker 84 | sw.* 85 | 86 | # Mac OSX 87 | .DS_Store 88 | 89 | # Vim swap files 90 | *.swp 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xianyun 2 | 3 | > My doozie Nuxt.js project 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | $ npm run install 10 | 11 | # serve with hot reload at localhost:3000 12 | $ npm run dev 13 | 14 | # build for production and launch server 15 | $ npm run build 16 | $ npm run start 17 | 18 | # generate static project 19 | $ npm run generate 20 | ``` 21 | 22 | For detailed explanation on how things work, check out [Nuxt.js docs](https://nuxtjs.org). 23 | -------------------------------------------------------------------------------- /assets/README.md: -------------------------------------------------------------------------------- 1 | # ASSETS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your un-compiled assets such as LESS, SASS, or JavaScript. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked). 8 | -------------------------------------------------------------------------------- /assets/main.css: -------------------------------------------------------------------------------- 1 | /* 页面切换时候过渡样式 */ 2 | .page-enter-active, .page-leave-active { 3 | transition: opacity .5s; 4 | } 5 | 6 | /* 打开时候过渡样式 */ 7 | .page-enter, .page-leave-active { 8 | opacity: 0; 9 | } 10 | 11 | /* 页面顶部页面加载进度条 */ 12 | .nuxt-progress{ 13 | background:#409eff; 14 | height: 1px; 15 | } -------------------------------------------------------------------------------- /components/air/flightsAside.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 50 | 51 | -------------------------------------------------------------------------------- /components/air/flightsFilters.vue: -------------------------------------------------------------------------------- 1 | 71 | 72 | 156 | 157 | -------------------------------------------------------------------------------- /components/air/flightsItem.vue: -------------------------------------------------------------------------------- 1 | 65 | 66 | 96 | 97 | -------------------------------------------------------------------------------- /components/air/flightsListHead.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 27 | 28 | -------------------------------------------------------------------------------- /components/air/orderAside.vue: -------------------------------------------------------------------------------- 1 | 48 | 49 | 74 | 75 | -------------------------------------------------------------------------------- /components/air/orderForm.vue: -------------------------------------------------------------------------------- 1 | 94 | 95 | 248 | 249 | -------------------------------------------------------------------------------- /components/air/searchForm.vue: -------------------------------------------------------------------------------- 1 | 69 | 70 | 247 | 248 | 351 | -------------------------------------------------------------------------------- /components/footer.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 50 | 51 | 99 | -------------------------------------------------------------------------------- /components/header.vue: -------------------------------------------------------------------------------- 1 | 53 | 64 | -------------------------------------------------------------------------------- /components/post/menuItem.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /components/slotButton.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /components/user/loginForm.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 76 | 77 | 98 | -------------------------------------------------------------------------------- /components/user/registerForm.vue: -------------------------------------------------------------------------------- 1 | 57 | 58 | 155 | 156 | -------------------------------------------------------------------------------- /layouts/README.md: -------------------------------------------------------------------------------- 1 | # LAYOUTS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your Application Layouts. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts). 8 | -------------------------------------------------------------------------------- /layouts/default.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 25 | 26 | 57 | -------------------------------------------------------------------------------- /middleware/README.md: -------------------------------------------------------------------------------- 1 | # MIDDLEWARE 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your application middleware. 6 | Middleware let you define custom functions that can be run before rendering either a page or a group of pages. 7 | 8 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware). 9 | -------------------------------------------------------------------------------- /nuxt.config.js: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | mode: 'universal', 4 | /* 5 | ** Headers of the page 6 | */ 7 | head: { 8 | title: "世界上最大的旅游网站", 9 | meta: [ 10 | { charset: 'utf-8' }, 11 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 12 | { hid: 'description', name: 'description', content: process.env.npm_package_description || '' } 13 | ], 14 | link: [ 15 | { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }, 16 | { rel: 'stylesheet', type: 'text/css', href: '//at.alicdn.com/t/font_1168872_ehvuah8v57g.css'} // 新增全局字体样式 17 | ] 18 | }, 19 | /* 20 | ** Customize the progress-bar color 21 | */ 22 | loading: { color: '#fff' }, 23 | /* 24 | ** Global CSS 25 | */ 26 | css: [ 27 | 'element-ui/lib/theme-chalk/index.css', 28 | 'assets/main.css' // 新增自定义的页面过渡样式 29 | ], 30 | /* 31 | ** Plugins to load before mounting the App 32 | */ 33 | plugins: [ 34 | '@/plugins/element-ui', 35 | "@/plugins/axios", 36 | { src: '@/plugins/localStorage.js', ssr: false } 37 | ], 38 | /* 39 | ** Nuxt.js dev-modules 40 | */ 41 | buildModules: [ 42 | ], 43 | /* 44 | ** Nuxt.js modules 45 | */ 46 | modules: [ 47 | // Doc: https://axios.nuxtjs.org/usage 48 | '@nuxtjs/axios', 49 | ], 50 | /* 51 | ** Axios module configuration 52 | ** See https://axios.nuxtjs.org/options 53 | */ 54 | axios: { 55 | baseURL: "http://127.0.0.1:1337" // 新增axios默认请求路径 56 | }, 57 | /* 58 | ** Build configuration 59 | */ 60 | build: { 61 | transpile: [/^element-ui/], 62 | /* 63 | ** You can extend webpack config here 64 | */ 65 | extend (config, ctx) { 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xianyun", 3 | "version": "1.0.0", 4 | "description": "My doozie Nuxt.js project", 5 | "author": "itcast-hsian", 6 | "private": true, 7 | "scripts": { 8 | "dev": "nuxt", 9 | "build": "nuxt build", 10 | "start": "nuxt start", 11 | "generate": "nuxt generate" 12 | }, 13 | "dependencies": { 14 | "@nuxtjs/axios": "^5.3.6", 15 | "element-ui": "^2.4.11", 16 | "less": "^3.10.3", 17 | "less-loader": "^5.0.0", 18 | "moment": "^2.24.0", 19 | "nuxt": "^2.0.0", 20 | "qrcode": "^1.4.2", 21 | "vuex-persistedstate": "^2.5.4" 22 | }, 23 | "devDependencies": {} 24 | } 25 | -------------------------------------------------------------------------------- /pages/air/flights.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 159 | 160 | -------------------------------------------------------------------------------- /pages/air/index.vue: -------------------------------------------------------------------------------- 1 | 57 | 58 | 84 | 85 | -------------------------------------------------------------------------------- /pages/air/order.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 49 | 50 | -------------------------------------------------------------------------------- /pages/air/pay.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 97 | 98 | -------------------------------------------------------------------------------- /pages/hotel/index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 92 | 93 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 52 | 53 | 100 | 101 | -------------------------------------------------------------------------------- /pages/post/index.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 67 | -------------------------------------------------------------------------------- /pages/slot.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 20 | 21 | -------------------------------------------------------------------------------- /pages/tab.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 53 | 54 | -------------------------------------------------------------------------------- /pages/user/login.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 54 | 55 | 99 | -------------------------------------------------------------------------------- /plugins/axios.js: -------------------------------------------------------------------------------- 1 | import { Message } from 'element-ui'; 2 | 3 | // nuxt插件的固定写法 4 | // context包含nuxt下所有的方法,固定有的参数 5 | export default (context) => { 6 | // 拦截错误的响应信息, 根以前项目的中main.js中拦截器不一样. 7 | // main.js中拦截器: 拦截所有的请求响应 8 | // 当前的拦截只拦截错误,如果请求错误就会执行onError中的函数 9 | context.$axios.onError(res => { 10 | // res是错误的对象, Error的对象可以通过response获取详细信息 11 | const {message, statusCode} = res.response.data; 12 | 13 | if(statusCode === 400){ 14 | Message.error(message) 15 | } 16 | 17 | // if(statusCode === 403 || statusCode === 401){ 18 | if( [401, 403].indexOf(statusCode) > -1 ){ 19 | // 路由重定向的方法 20 | context.redirect("/user/login"); 21 | } 22 | }) 23 | } -------------------------------------------------------------------------------- /plugins/element-ui.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Element from 'element-ui' 3 | import locale from 'element-ui/lib/locale/lang/zh-CN' 4 | 5 | Vue.use(Element, { locale }) 6 | -------------------------------------------------------------------------------- /plugins/localStorage.js: -------------------------------------------------------------------------------- 1 | import createPersistedState from 'vuex-persistedstate' 2 | 3 | export default ({store}) => { 4 | window.onNuxtReady(() => { 5 | createPersistedState({ 6 | 7 | })(store) 8 | }) 9 | } -------------------------------------------------------------------------------- /static/README.md: -------------------------------------------------------------------------------- 1 | # STATIC 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your static files. 6 | Each file inside this directory is mapped to `/`. 7 | Thus you'd want to delete this README.md before deploying to production. 8 | 9 | Example: `/static/robots.txt` is mapped as `/robots.txt`. 10 | 11 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static). 12 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itcast-hsian/xianyun-36/8f1064e55bc484257ed8a934606eae051a40a5d5/static/favicon.ico -------------------------------------------------------------------------------- /static/qrcode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview 3 | * - Using the 'QRCode for Javascript library' 4 | * - Fixed dataset of 'QRCode for Javascript library' for support full-spec. 5 | * - this library has no dependencies. 6 | * 7 | * @author davidshimjs 8 | * @see http://www.d-project.com/ 9 | * @see http://jeromeetienne.github.com/jquery-qrcode/ 10 | */ 11 | var QRCode; 12 | 13 | (function () { 14 | //--------------------------------------------------------------------- 15 | // QRCode for JavaScript 16 | // 17 | // Copyright (c) 2009 Kazuhiko Arase 18 | // 19 | // URL: http://www.d-project.com/ 20 | // 21 | // Licensed under the MIT license: 22 | // http://www.opensource.org/licenses/mit-license.php 23 | // 24 | // The word "QR Code" is registered trademark of 25 | // DENSO WAVE INCORPORATED 26 | // http://www.denso-wave.com/qrcode/faqpatent-e.html 27 | // 28 | //--------------------------------------------------------------------- 29 | function QR8bitByte(data) { 30 | this.mode = QRMode.MODE_8BIT_BYTE; 31 | this.data = data; 32 | this.parsedData = []; 33 | 34 | // Added to support UTF-8 Characters 35 | for (var i = 0, l = this.data.length; i < l; i++) { 36 | var byteArray = []; 37 | var code = this.data.charCodeAt(i); 38 | 39 | if (code > 0x10000) { 40 | byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18); 41 | byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12); 42 | byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6); 43 | byteArray[3] = 0x80 | (code & 0x3F); 44 | } else if (code > 0x800) { 45 | byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12); 46 | byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6); 47 | byteArray[2] = 0x80 | (code & 0x3F); 48 | } else if (code > 0x80) { 49 | byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6); 50 | byteArray[1] = 0x80 | (code & 0x3F); 51 | } else { 52 | byteArray[0] = code; 53 | } 54 | 55 | this.parsedData.push(byteArray); 56 | } 57 | 58 | this.parsedData = Array.prototype.concat.apply([], this.parsedData); 59 | 60 | if (this.parsedData.length != this.data.length) { 61 | this.parsedData.unshift(191); 62 | this.parsedData.unshift(187); 63 | this.parsedData.unshift(239); 64 | } 65 | } 66 | 67 | QR8bitByte.prototype = { 68 | getLength: function (buffer) { 69 | return this.parsedData.length; 70 | }, 71 | write: function (buffer) { 72 | for (var i = 0, l = this.parsedData.length; i < l; i++) { 73 | buffer.put(this.parsedData[i], 8); 74 | } 75 | } 76 | }; 77 | 78 | function QRCodeModel(typeNumber, errorCorrectLevel) { 79 | this.typeNumber = typeNumber; 80 | this.errorCorrectLevel = errorCorrectLevel; 81 | this.modules = null; 82 | this.moduleCount = 0; 83 | this.dataCache = null; 84 | this.dataList = []; 85 | } 86 | 87 | QRCodeModel.prototype={addData:function(data){var newData=new QR8bitByte(data);this.dataList.push(newData);this.dataCache=null;},isDark:function(row,col){if(row<0||this.moduleCount<=row||col<0||this.moduleCount<=col){throw new Error(row+","+col);} 88 | return this.modules[row][col];},getModuleCount:function(){return this.moduleCount;},make:function(){this.makeImpl(false,this.getBestMaskPattern());},makeImpl:function(test,maskPattern){this.moduleCount=this.typeNumber*4+17;this.modules=new Array(this.moduleCount);for(var row=0;row=7){this.setupTypeNumber(test);} 90 | if(this.dataCache==null){this.dataCache=QRCodeModel.createData(this.typeNumber,this.errorCorrectLevel,this.dataList);} 91 | this.mapData(this.dataCache,maskPattern);},setupPositionProbePattern:function(row,col){for(var r=-1;r<=7;r++){if(row+r<=-1||this.moduleCount<=row+r)continue;for(var c=-1;c<=7;c++){if(col+c<=-1||this.moduleCount<=col+c)continue;if((0<=r&&r<=6&&(c==0||c==6))||(0<=c&&c<=6&&(r==0||r==6))||(2<=r&&r<=4&&2<=c&&c<=4)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}},getBestMaskPattern:function(){var minLostPoint=0;var pattern=0;for(var i=0;i<8;i++){this.makeImpl(true,i);var lostPoint=QRUtil.getLostPoint(this);if(i==0||minLostPoint>lostPoint){minLostPoint=lostPoint;pattern=i;}} 92 | return pattern;},createMovieClip:function(target_mc,instance_name,depth){var qr_mc=target_mc.createEmptyMovieClip(instance_name,depth);var cs=1;this.make();for(var row=0;row>i)&1)==1);this.modules[Math.floor(i/3)][i%3+this.moduleCount-8-3]=mod;} 98 | for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[i%3+this.moduleCount-8-3][Math.floor(i/3)]=mod;}},setupTypeInfo:function(test,maskPattern){var data=(this.errorCorrectLevel<<3)|maskPattern;var bits=QRUtil.getBCHTypeInfo(data);for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<6){this.modules[i][8]=mod;}else if(i<8){this.modules[i+1][8]=mod;}else{this.modules[this.moduleCount-15+i][8]=mod;}} 99 | for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<8){this.modules[8][this.moduleCount-i-1]=mod;}else if(i<9){this.modules[8][15-i-1+1]=mod;}else{this.modules[8][15-i-1]=mod;}} 100 | this.modules[this.moduleCount-8][8]=(!test);},mapData:function(data,maskPattern){var inc=-1;var row=this.moduleCount-1;var bitIndex=7;var byteIndex=0;for(var col=this.moduleCount-1;col>0;col-=2){if(col==6)col--;while(true){for(var c=0;c<2;c++){if(this.modules[row][col-c]==null){var dark=false;if(byteIndex>>bitIndex)&1)==1);} 101 | var mask=QRUtil.getMask(maskPattern,row,col-c);if(mask){dark=!dark;} 102 | this.modules[row][col-c]=dark;bitIndex--;if(bitIndex==-1){byteIndex++;bitIndex=7;}}} 103 | row+=inc;if(row<0||this.moduleCount<=row){row-=inc;inc=-inc;break;}}}}};QRCodeModel.PAD0=0xEC;QRCodeModel.PAD1=0x11;QRCodeModel.createData=function(typeNumber,errorCorrectLevel,dataList){var rsBlocks=QRRSBlock.getRSBlocks(typeNumber,errorCorrectLevel);var buffer=new QRBitBuffer();for(var i=0;itotalDataCount*8){throw new Error("code length overflow. (" 106 | +buffer.getLengthInBits() 107 | +">" 108 | +totalDataCount*8 109 | +")");} 110 | if(buffer.getLengthInBits()+4<=totalDataCount*8){buffer.put(0,4);} 111 | while(buffer.getLengthInBits()%8!=0){buffer.putBit(false);} 112 | while(true){if(buffer.getLengthInBits()>=totalDataCount*8){break;} 113 | buffer.put(QRCodeModel.PAD0,8);if(buffer.getLengthInBits()>=totalDataCount*8){break;} 114 | buffer.put(QRCodeModel.PAD1,8);} 115 | return QRCodeModel.createBytes(buffer,rsBlocks);};QRCodeModel.createBytes=function(buffer,rsBlocks){var offset=0;var maxDcCount=0;var maxEcCount=0;var dcdata=new Array(rsBlocks.length);var ecdata=new Array(rsBlocks.length);for(var r=0;r=0)?modPoly.get(modIndex):0;}} 117 | var totalCodeCount=0;for(var i=0;i=0){d^=(QRUtil.G15<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)));} 121 | return((data<<10)|d)^QRUtil.G15_MASK;},getBCHTypeNumber:function(data){var d=data<<12;while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)>=0){d^=(QRUtil.G18<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)));} 122 | return(data<<12)|d;},getBCHDigit:function(data){var digit=0;while(data!=0){digit++;data>>>=1;} 123 | return digit;},getPatternPosition:function(typeNumber){return QRUtil.PATTERN_POSITION_TABLE[typeNumber-1];},getMask:function(maskPattern,i,j){switch(maskPattern){case QRMaskPattern.PATTERN000:return(i+j)%2==0;case QRMaskPattern.PATTERN001:return i%2==0;case QRMaskPattern.PATTERN010:return j%3==0;case QRMaskPattern.PATTERN011:return(i+j)%3==0;case QRMaskPattern.PATTERN100:return(Math.floor(i/2)+Math.floor(j/3))%2==0;case QRMaskPattern.PATTERN101:return(i*j)%2+(i*j)%3==0;case QRMaskPattern.PATTERN110:return((i*j)%2+(i*j)%3)%2==0;case QRMaskPattern.PATTERN111:return((i*j)%3+(i+j)%2)%2==0;default:throw new Error("bad maskPattern:"+maskPattern);}},getErrorCorrectPolynomial:function(errorCorrectLength){var a=new QRPolynomial([1],0);for(var i=0;i5){lostPoint+=(3+sameCount-5);}}} 129 | for(var row=0;row=256){n-=255;} 136 | return QRMath.EXP_TABLE[n];},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)};for(var i=0;i<8;i++){QRMath.EXP_TABLE[i]=1<>>(7-index%8))&1)==1;},put:function(num,length){for(var i=0;i>>(length-i-1))&1)==1);}},getLengthInBits:function(){return this.length;},putBit:function(bit){var bufIndex=Math.floor(this.length/8);if(this.buffer.length<=bufIndex){this.buffer.push(0);} 151 | if(bit){this.buffer[bufIndex]|=(0x80>>>(this.length%8));} 152 | this.length++;}};var QRCodeLimitLength=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]]; 153 | 154 | function _isSupportCanvas() { 155 | return typeof CanvasRenderingContext2D != "undefined"; 156 | } 157 | 158 | // android 2.x doesn't support Data-URI spec 159 | function _getAndroid() { 160 | var android = false; 161 | var sAgent = navigator.userAgent; 162 | 163 | if (/android/i.test(sAgent)) { // android 164 | android = true; 165 | var aMat = sAgent.toString().match(/android ([0-9]\.[0-9])/i); 166 | 167 | if (aMat && aMat[1]) { 168 | android = parseFloat(aMat[1]); 169 | } 170 | } 171 | 172 | return android; 173 | } 174 | 175 | var svgDrawer = (function() { 176 | 177 | var Drawing = function (el, htOption) { 178 | this._el = el; 179 | this._htOption = htOption; 180 | }; 181 | 182 | Drawing.prototype.draw = function (oQRCode) { 183 | var _htOption = this._htOption; 184 | var _el = this._el; 185 | var nCount = oQRCode.getModuleCount(); 186 | var nWidth = Math.floor(_htOption.width / nCount); 187 | var nHeight = Math.floor(_htOption.height / nCount); 188 | 189 | this.clear(); 190 | 191 | function makeSVG(tag, attrs) { 192 | var el = document.createElementNS('http://www.w3.org/2000/svg', tag); 193 | for (var k in attrs) 194 | if (attrs.hasOwnProperty(k)) el.setAttribute(k, attrs[k]); 195 | return el; 196 | } 197 | 198 | var svg = makeSVG("svg" , {'viewBox': '0 0 ' + String(nCount) + " " + String(nCount), 'width': '100%', 'height': '100%', 'fill': _htOption.colorLight}); 199 | svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink"); 200 | _el.appendChild(svg); 201 | 202 | svg.appendChild(makeSVG("rect", {"fill": _htOption.colorLight, "width": "100%", "height": "100%"})); 203 | svg.appendChild(makeSVG("rect", {"fill": _htOption.colorDark, "width": "1", "height": "1", "id": "template"})); 204 | 205 | for (var row = 0; row < nCount; row++) { 206 | for (var col = 0; col < nCount; col++) { 207 | if (oQRCode.isDark(row, col)) { 208 | var child = makeSVG("use", {"x": String(col), "y": String(row)}); 209 | child.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#template") 210 | svg.appendChild(child); 211 | } 212 | } 213 | } 214 | }; 215 | Drawing.prototype.clear = function () { 216 | while (this._el.hasChildNodes()) 217 | this._el.removeChild(this._el.lastChild); 218 | }; 219 | return Drawing; 220 | })(); 221 | 222 | var useSVG = document.documentElement.tagName.toLowerCase() === "svg"; 223 | 224 | // Drawing in DOM by using Table tag 225 | var Drawing = useSVG ? svgDrawer : !_isSupportCanvas() ? (function () { 226 | var Drawing = function (el, htOption) { 227 | this._el = el; 228 | this._htOption = htOption; 229 | }; 230 | 231 | /** 232 | * Draw the QRCode 233 | * 234 | * @param {QRCode} oQRCode 235 | */ 236 | Drawing.prototype.draw = function (oQRCode) { 237 | var _htOption = this._htOption; 238 | var _el = this._el; 239 | var nCount = oQRCode.getModuleCount(); 240 | var nWidth = Math.floor(_htOption.width / nCount); 241 | var nHeight = Math.floor(_htOption.height / nCount); 242 | var aHTML = ['']; 243 | 244 | for (var row = 0; row < nCount; row++) { 245 | aHTML.push(''); 246 | 247 | for (var col = 0; col < nCount; col++) { 248 | aHTML.push(''); 249 | } 250 | 251 | aHTML.push(''); 252 | } 253 | 254 | aHTML.push('
'); 255 | _el.innerHTML = aHTML.join(''); 256 | 257 | // Fix the margin values as real size. 258 | var elTable = _el.childNodes[0]; 259 | var nLeftMarginTable = (_htOption.width - elTable.offsetWidth) / 2; 260 | var nTopMarginTable = (_htOption.height - elTable.offsetHeight) / 2; 261 | 262 | if (nLeftMarginTable > 0 && nTopMarginTable > 0) { 263 | elTable.style.margin = nTopMarginTable + "px " + nLeftMarginTable + "px"; 264 | } 265 | }; 266 | 267 | /** 268 | * Clear the QRCode 269 | */ 270 | Drawing.prototype.clear = function () { 271 | this._el.innerHTML = ''; 272 | }; 273 | 274 | return Drawing; 275 | })() : (function () { // Drawing in Canvas 276 | function _onMakeImage() { 277 | this._elImage.src = this._elCanvas.toDataURL("image/png"); 278 | this._elImage.style.display = "block"; 279 | this._elCanvas.style.display = "none"; 280 | } 281 | 282 | // Android 2.1 bug workaround 283 | // http://code.google.com/p/android/issues/detail?id=5141 284 | if (this._android && this._android <= 2.1) { 285 | var factor = 1 / window.devicePixelRatio; 286 | var drawImage = CanvasRenderingContext2D.prototype.drawImage; 287 | CanvasRenderingContext2D.prototype.drawImage = function (image, sx, sy, sw, sh, dx, dy, dw, dh) { 288 | if (("nodeName" in image) && /img/i.test(image.nodeName)) { 289 | for (var i = arguments.length - 1; i >= 1; i--) { 290 | arguments[i] = arguments[i] * factor; 291 | } 292 | } else if (typeof dw == "undefined") { 293 | arguments[1] *= factor; 294 | arguments[2] *= factor; 295 | arguments[3] *= factor; 296 | arguments[4] *= factor; 297 | } 298 | 299 | drawImage.apply(this, arguments); 300 | }; 301 | } 302 | 303 | /** 304 | * Check whether the user's browser supports Data URI or not 305 | * 306 | * @private 307 | * @param {Function} fSuccess Occurs if it supports Data URI 308 | * @param {Function} fFail Occurs if it doesn't support Data URI 309 | */ 310 | function _safeSetDataURI(fSuccess, fFail) { 311 | var self = this; 312 | self._fFail = fFail; 313 | self._fSuccess = fSuccess; 314 | 315 | // Check it just once 316 | if (self._bSupportDataURI === null) { 317 | var el = document.createElement("img"); 318 | var fOnError = function() { 319 | self._bSupportDataURI = false; 320 | 321 | if (self._fFail) { 322 | self._fFail.call(self); 323 | } 324 | }; 325 | var fOnSuccess = function() { 326 | self._bSupportDataURI = true; 327 | 328 | if (self._fSuccess) { 329 | self._fSuccess.call(self); 330 | } 331 | }; 332 | 333 | el.onabort = fOnError; 334 | el.onerror = fOnError; 335 | el.onload = fOnSuccess; 336 | el.src = "data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; // the Image contains 1px data. 337 | return; 338 | } else if (self._bSupportDataURI === true && self._fSuccess) { 339 | self._fSuccess.call(self); 340 | } else if (self._bSupportDataURI === false && self._fFail) { 341 | self._fFail.call(self); 342 | } 343 | }; 344 | 345 | /** 346 | * Drawing QRCode by using canvas 347 | * 348 | * @constructor 349 | * @param {HTMLElement} el 350 | * @param {Object} htOption QRCode Options 351 | */ 352 | var Drawing = function (el, htOption) { 353 | this._bIsPainted = false; 354 | this._android = _getAndroid(); 355 | 356 | this._htOption = htOption; 357 | this._elCanvas = document.createElement("canvas"); 358 | this._elCanvas.width = htOption.width; 359 | this._elCanvas.height = htOption.height; 360 | el.appendChild(this._elCanvas); 361 | this._el = el; 362 | this._oContext = this._elCanvas.getContext("2d"); 363 | this._bIsPainted = false; 364 | this._elImage = document.createElement("img"); 365 | this._elImage.alt = "Scan me!"; 366 | this._elImage.style.display = "none"; 367 | this._el.appendChild(this._elImage); 368 | this._bSupportDataURI = null; 369 | }; 370 | 371 | /** 372 | * Draw the QRCode 373 | * 374 | * @param {QRCode} oQRCode 375 | */ 376 | Drawing.prototype.draw = function (oQRCode) { 377 | var _elImage = this._elImage; 378 | var _oContext = this._oContext; 379 | var _htOption = this._htOption; 380 | 381 | var nCount = oQRCode.getModuleCount(); 382 | var nWidth = _htOption.width / nCount; 383 | var nHeight = _htOption.height / nCount; 384 | var nRoundedWidth = Math.round(nWidth); 385 | var nRoundedHeight = Math.round(nHeight); 386 | 387 | _elImage.style.display = "none"; 388 | this.clear(); 389 | 390 | for (var row = 0; row < nCount; row++) { 391 | for (var col = 0; col < nCount; col++) { 392 | var bIsDark = oQRCode.isDark(row, col); 393 | var nLeft = col * nWidth; 394 | var nTop = row * nHeight; 395 | _oContext.strokeStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight; 396 | _oContext.lineWidth = 1; 397 | _oContext.fillStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight; 398 | _oContext.fillRect(nLeft, nTop, nWidth, nHeight); 399 | 400 | // 안티 앨리어싱 방지 처리 401 | _oContext.strokeRect( 402 | Math.floor(nLeft) + 0.5, 403 | Math.floor(nTop) + 0.5, 404 | nRoundedWidth, 405 | nRoundedHeight 406 | ); 407 | 408 | _oContext.strokeRect( 409 | Math.ceil(nLeft) - 0.5, 410 | Math.ceil(nTop) - 0.5, 411 | nRoundedWidth, 412 | nRoundedHeight 413 | ); 414 | } 415 | } 416 | 417 | this._bIsPainted = true; 418 | }; 419 | 420 | /** 421 | * Make the image from Canvas if the browser supports Data URI. 422 | */ 423 | Drawing.prototype.makeImage = function () { 424 | if (this._bIsPainted) { 425 | _safeSetDataURI.call(this, _onMakeImage); 426 | } 427 | }; 428 | 429 | /** 430 | * Return whether the QRCode is painted or not 431 | * 432 | * @return {Boolean} 433 | */ 434 | Drawing.prototype.isPainted = function () { 435 | return this._bIsPainted; 436 | }; 437 | 438 | /** 439 | * Clear the QRCode 440 | */ 441 | Drawing.prototype.clear = function () { 442 | this._oContext.clearRect(0, 0, this._elCanvas.width, this._elCanvas.height); 443 | this._bIsPainted = false; 444 | }; 445 | 446 | /** 447 | * @private 448 | * @param {Number} nNumber 449 | */ 450 | Drawing.prototype.round = function (nNumber) { 451 | if (!nNumber) { 452 | return nNumber; 453 | } 454 | 455 | return Math.floor(nNumber * 1000) / 1000; 456 | }; 457 | 458 | return Drawing; 459 | })(); 460 | 461 | /** 462 | * Get the type by string length 463 | * 464 | * @private 465 | * @param {String} sText 466 | * @param {Number} nCorrectLevel 467 | * @return {Number} type 468 | */ 469 | function _getTypeNumber(sText, nCorrectLevel) { 470 | var nType = 1; 471 | var length = _getUTF8Length(sText); 472 | 473 | for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) { 474 | var nLimit = 0; 475 | 476 | switch (nCorrectLevel) { 477 | case QRErrorCorrectLevel.L : 478 | nLimit = QRCodeLimitLength[i][0]; 479 | break; 480 | case QRErrorCorrectLevel.M : 481 | nLimit = QRCodeLimitLength[i][1]; 482 | break; 483 | case QRErrorCorrectLevel.Q : 484 | nLimit = QRCodeLimitLength[i][2]; 485 | break; 486 | case QRErrorCorrectLevel.H : 487 | nLimit = QRCodeLimitLength[i][3]; 488 | break; 489 | } 490 | 491 | if (length <= nLimit) { 492 | break; 493 | } else { 494 | nType++; 495 | } 496 | } 497 | 498 | if (nType > QRCodeLimitLength.length) { 499 | throw new Error("Too long data"); 500 | } 501 | 502 | return nType; 503 | } 504 | 505 | function _getUTF8Length(sText) { 506 | var replacedText = encodeURI(sText).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a'); 507 | return replacedText.length + (replacedText.length != sText ? 3 : 0); 508 | } 509 | 510 | /** 511 | * @class QRCode 512 | * @constructor 513 | * @example 514 | * new QRCode(document.getElementById("test"), "http://jindo.dev.naver.com/collie"); 515 | * 516 | * @example 517 | * var oQRCode = new QRCode("test", { 518 | * text : "http://naver.com", 519 | * width : 128, 520 | * height : 128 521 | * }); 522 | * 523 | * oQRCode.clear(); // Clear the QRCode. 524 | * oQRCode.makeCode("http://map.naver.com"); // Re-create the QRCode. 525 | * 526 | * @param {HTMLElement|String} el target element or 'id' attribute of element. 527 | * @param {Object|String} vOption 528 | * @param {String} vOption.text QRCode link data 529 | * @param {Number} [vOption.width=256] 530 | * @param {Number} [vOption.height=256] 531 | * @param {String} [vOption.colorDark="#000000"] 532 | * @param {String} [vOption.colorLight="#ffffff"] 533 | * @param {QRCode.CorrectLevel} [vOption.correctLevel=QRCode.CorrectLevel.H] [L|M|Q|H] 534 | */ 535 | QRCode = function (el, vOption) { 536 | this._htOption = { 537 | width : 256, 538 | height : 256, 539 | typeNumber : 4, 540 | colorDark : "#000000", 541 | colorLight : "#ffffff", 542 | correctLevel : QRErrorCorrectLevel.H 543 | }; 544 | 545 | if (typeof vOption === 'string') { 546 | vOption = { 547 | text : vOption 548 | }; 549 | } 550 | 551 | // Overwrites options 552 | if (vOption) { 553 | for (var i in vOption) { 554 | this._htOption[i] = vOption[i]; 555 | } 556 | } 557 | 558 | if (typeof el == "string") { 559 | el = document.getElementById(el); 560 | } 561 | 562 | if (this._htOption.useSVG) { 563 | Drawing = svgDrawer; 564 | } 565 | 566 | this._android = _getAndroid(); 567 | this._el = el; 568 | this._oQRCode = null; 569 | this._oDrawing = new Drawing(this._el, this._htOption); 570 | 571 | if (this._htOption.text) { 572 | this.makeCode(this._htOption.text); 573 | } 574 | }; 575 | 576 | /** 577 | * Make the QRCode 578 | * 579 | * @param {String} sText link data 580 | */ 581 | QRCode.prototype.makeCode = function (sText) { 582 | this._oQRCode = new QRCodeModel(_getTypeNumber(sText, this._htOption.correctLevel), this._htOption.correctLevel); 583 | this._oQRCode.addData(sText); 584 | this._oQRCode.make(); 585 | this._el.title = sText; 586 | this._oDrawing.draw(this._oQRCode); 587 | this.makeImage(); 588 | }; 589 | 590 | /** 591 | * Make the Image from Canvas element 592 | * - It occurs automatically 593 | * - Android below 3 doesn't support Data-URI spec. 594 | * 595 | * @private 596 | */ 597 | QRCode.prototype.makeImage = function () { 598 | if (typeof this._oDrawing.makeImage == "function" && (!this._android || this._android >= 3)) { 599 | this._oDrawing.makeImage(); 600 | } 601 | }; 602 | 603 | /** 604 | * Clear the QRCode 605 | */ 606 | QRCode.prototype.clear = function () { 607 | this._oDrawing.clear(); 608 | }; 609 | 610 | /** 611 | * @name QRCode.CorrectLevel 612 | */ 613 | QRCode.CorrectLevel = QRErrorCorrectLevel; 614 | })(); -------------------------------------------------------------------------------- /store/air.js: -------------------------------------------------------------------------------- 1 | export const state = () => { 2 | return { 3 | // 搜索的历史记录 4 | history: [] 5 | } 6 | } 7 | 8 | export const mutations = { 9 | // 设置history的值,data是搜索表单的对象 10 | setHistory(state, data){ 11 | // 把最新的记录追加到第一个 12 | state.history.unshift(data); 13 | } 14 | } -------------------------------------------------------------------------------- /store/post.js: -------------------------------------------------------------------------------- 1 | // 存放的是同步修改state的方法 2 | export const mutation = { 3 | 4 | } -------------------------------------------------------------------------------- /store/user.js: -------------------------------------------------------------------------------- 1 | // 固定的写法,暴露出state 2 | export const state = () => { 3 | return { 4 | userInfo: {} 5 | } 6 | } 7 | 8 | // 存放的是同步修改state的方法 9 | export const mutations = { 10 | // mutaion下的值必须是一个函数,函数中会有一个固定的参数state,第二个参数是用户调用方法时候传进来 11 | // data是登录成功后返回的对象数据 12 | setUserInfo(state, data){ 13 | state.userInfo = data; 14 | } 15 | } 16 | 17 | // 存放的是异步修改state的方法 18 | export const actions = { 19 | // 封装登录的方法 20 | // store是固定必须要有的参数,执行当前的store == 组件内this.$store 21 | async login(store, data){ 22 | var res = await this.$axios({ 23 | url: "/accounts/login", 24 | method: "POST", 25 | data 26 | }) 27 | 28 | if(res.status === 200){ 29 | store.commit("setUserInfo", res.data); 30 | } 31 | 32 | return res; 33 | }, 34 | 35 | // 发送手机验证码, tel是传入的手机号码 36 | async sendCaptcha(store, tel){ 37 | const res = await this.$axios({ 38 | url: "/captchas", 39 | method: "POST", 40 | data: { 41 | tel // 手机号码 42 | } 43 | }); 44 | 45 | return res; 46 | } 47 | } -------------------------------------------------------------------------------- /utils/utils.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @desc: 计算相隔时间 4 | * 5 | * @param: 参数 | 属性说明 | 参考值 6 | * @param: arr_time | 到达时间 | 14:10 7 | * @param: dep_time | 出发时间 | 12: 00 8 | * 9 | * @return: 相隔时间的字符串 10 | */ 11 | export function computeTime( arr_time, dep_time ){ 12 | // 如果参数有一个是空值,直接返回 13 | if(!arr_time || !dep_time) return; 14 | 15 | const arrTime = arr_time.split(":"); // 14: 10 = [14, 10] 16 | const depTime = dep_time.split(":"); // 12: 30 = [12, 30] 17 | 18 | // 第二天 19 | if(arrTime[0] < depTime[0]){ 20 | arrTime[0] += 24; 21 | } 22 | 23 | // 到达时间的分钟 24 | const end = arrTime[0] * 60 + (+arrTime[1]); 25 | // 出发时间的分钟 26 | const start = depTime[0] * 60 + (+depTime[1]); 27 | // 相隔的分钟 28 | const dis = end - start; 29 | 30 | 31 | // 小时 32 | const hours = Math.floor(dis / 60); 33 | // 分钟 34 | const min = dis % 60; 35 | 36 | return `${hours}小时${min}分钟`; 37 | } 38 | 39 | /** 40 | * 41 | */ 42 | export function abc(){ 43 | 44 | } 45 | --------------------------------------------------------------------------------