├── .babelrc ├── .editorconfig ├── .eslintignore ├── .gitignore ├── README.md ├── build ├── build.js ├── dev-client.js ├── dev-server.js ├── utils.js ├── webpack.base.conf.js ├── webpack.dev.conf.js └── webpack.prod.conf.js ├── config ├── dev.env.js ├── index.js ├── prod.env.js └── test.env.js ├── dist ├── common.js ├── common.js.map ├── index.html └── static │ ├── Img │ ├── jx.png │ ├── logo.png │ ├── logo_default.png │ ├── logo_default_s.jpg │ └── tou_xiang.png │ ├── base.css │ ├── common │ ├── jx-ajax.js │ ├── jx-common-app.js │ ├── jx-common.js │ ├── jx-contpointer.js │ ├── jx-contpointerutil.js │ ├── jx-downloadapp.js │ ├── jx-footmenu.js │ ├── jx-h5cache.js │ └── jx-log.js │ ├── css │ ├── app.bf4f8152f201de6b2d08f1d2509a6d2f.css │ └── app.bf4f8152f201de6b2d08f1d2509a6d2f.css.map │ ├── data │ ├── live.json │ └── video.json │ ├── js │ ├── app.a6459d949a79a9a25e5c.js │ ├── app.a6459d949a79a9a25e5c.js.map │ ├── manifest.7f7248d867a534d27f5e.js │ ├── manifest.7f7248d867a534d27f5e.js.map │ ├── vendor.e8fc08e1558ac1c1c7b7.js │ └── vendor.e8fc08e1558ac1c1c7b7.js.map │ ├── liveStreaming │ ├── img │ │ ├── arrow.png │ │ ├── boy.png │ │ ├── fullscreen.png │ │ ├── girl.png │ │ ├── movie.png │ │ └── share.png │ ├── live.css │ └── live.html │ └── plugin │ ├── jquery.cookie.js │ ├── jquery.js │ └── md5.min.js ├── favicon.ico ├── index.html ├── package.json ├── params.json ├── src ├── App.vue ├── assets │ ├── css │ │ └── liveList.css │ └── img │ │ ├── jx.png │ │ ├── logo.png │ │ ├── logo_default.png │ │ ├── logo_default_s.jpg │ │ └── tou_xiang.png ├── components │ ├── Video.vue │ └── toload.vue ├── config_router.js ├── filter.js ├── main.js ├── services │ ├── live.js │ └── sns.js ├── utils │ ├── convert │ │ └── date.js │ └── jx │ │ ├── ajax.js │ │ ├── common-app.js │ │ ├── common.js │ │ ├── config.js │ │ ├── contpointer.js │ │ ├── h5cache.js │ │ └── log.js ├── views │ └── live │ │ ├── Live.vue │ │ ├── Replays.vue │ │ └── Wonderfuls.vue └── vuex │ ├── actions.js │ ├── modules │ └── live.js │ ├── mutation-types.js │ └── store.js ├── static ├── .gitkeep ├── Img │ ├── jx.png │ ├── logo.png │ ├── logo_default.png │ ├── logo_default_s.jpg │ └── tou_xiang.png ├── base.css ├── common │ ├── jx-ajax.js │ ├── jx-common-app.js │ ├── jx-common.js │ ├── jx-contpointer.js │ ├── jx-contpointerutil.js │ ├── jx-downloadapp.js │ ├── jx-footmenu.js │ ├── jx-h5cache.js │ └── jx-log.js ├── data │ ├── live.json │ └── video.json ├── js │ ├── video-js-cdn.css │ ├── video.js │ └── videojs-contrib-hls.js ├── liveStreaming │ ├── img │ │ ├── arrow.png │ │ ├── boy.png │ │ ├── fullscreen.png │ │ ├── girl.png │ │ ├── movie.png │ │ └── share.png │ ├── live.css │ └── live.html └── plugin │ ├── jquery.cookie.js │ ├── jquery.js │ └── md5.min.js └── test ├── e2e ├── custom-assertions │ └── elementCount.js ├── nightwatch.conf.js ├── runner.js └── specs │ └── test.js └── unit ├── .eslintrc ├── index.js ├── karma.conf.js └── specs └── Hello.spec.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | // "passPerPreset": true, 3 | "presets": [ 4 | "es2015", 5 | "stage-2" 6 | ], 7 | "plugins": [ 8 | "transform-runtime" 9 | ], 10 | "comments": false 11 | } 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | selenium-debug.log 6 | test/unit/coverage 7 | test/e2e/reports 8 | target/ 9 | .settings/ 10 | .idea/ 11 | *.iml 12 | *.project 13 | *.classpath 14 | .idea/ 15 | .git/ 16 | .history/ 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Vue](http://cn.vuejs.org/) + [Webpack](http://webpack.github.io/) 实践 2 | 3 | ## 参考 4 | - [vue-tutorial](https://github.com/MeCKodo/vue-tutorial) 5 | - [Vue+Webpack开发可复用的单页面富应用教程](https://www.talkingcoder.com/article/6310756346094488391) 6 | - [Vue+Webpack使用规范](https://www.talkingcoder.com/article/6309726065044556372) 7 | [对比其他框架](http://cn.vuejs.org/guide/comparison.html) 8 | 9 | 10 | 推荐代码使用 CommonJS 或 ES6 模块,然后使用 [Webpack](http://webpack.github.io/) 或 [Browserify](http://browserify.org/) 打包。 11 | 12 | 你可以使用 Webpack + [vue-loader](https://github.com/vuejs/vue-loader) 或 Browserify + [vueify](https://github.com/vuejs/vueify) 构建这些单文件 Vue 组件。 13 | > 可以在 [Webpackbin.com](http://www.webpackbin.com/vue) 上在线尝试! 14 | > **chrome开发工具 : [vue-developertools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)** 15 | 16 | ## 安装 17 | 18 | 1. 我们将会使用webpack去为我们的模块打包,预处理,热加载。如果你对webpack不熟悉,它就是可以帮助我们把多个js文件打包为1个入口文件,并且可以达到按需加载。这就意味着,我们不用去担心由于太多的组件,导致了过多的HTTP请求,这是非常有益于产品体验的。但,我们并不只是为了这个而使用webpack,我们需要用webpack去编译.vue文件,如果没有使用一个loader去转换我们.vue文件里的style,js,html,那么浏览器就无法识别。 19 | 2. 模块热加载是webpack的一个非常碉堡的特性,将会为我们的单页应用带来极大的便利。 20 | 通常来说,当我们修改了代码刷新页面,那应用里的所有状态就都没有了。这对于开发一个单页应用来说是非常痛苦的,因为需要重新在跑一遍流程。如果有模块热加载,当你修改了代码,你的代码会直接修改,页面并不会刷新,所以状态也会被保留。 21 | 3. Vue也为我们提供了CSS预处理,所以我们可以选择在.vue文件里写LESS或者SASS去代替原生CSS。 22 | 4. 我们过去通常需要使用npm下载一堆的依赖,但是现在我们可以选择Vue-cli。这是一个vue生态系统中一个伟大创举。这意味着我们不需要手动构建我们的项目,而它就可以很快地为我们生成。 23 | 24 | > 使用脚手架工具 [vue-cli](https://github.com/vuejs/vue-cli) 可以快速地构建项目:单文件 Vue 组件,热加载,保存时检查代码,单元测试等。 25 | - 安装vue-cli (确保你有node和npm) 26 | ``` 27 | $ npm install -g vue-cli 28 | ``` 29 | 30 | - 使用脚手架初始创建项目 31 | ``` 32 | $ vue init 33 | ``` 34 | 35 | Example:*创建一个webpack项目* 36 | 37 | ``` 38 | $ vue init webpack my-project 39 | ``` 40 | 41 | - 项目模版下载好了之后需要安装项目用到的依赖包 42 | ``` 43 | $ cd my-project 44 | $ npm install 45 | ``` 46 | 47 | - 这时可以将项目运行起来看看效果了 48 | ``` 49 | $ npm run dev 50 | ``` 51 | 这一行命令代表着它会去找到`package.json`的`scripts`对象,执行`node bulid/dev-server.js`。在这文件里,配置了Webpack,会让它去编译项目文件,并且运行服务器,我们在`localhost:8080`即可查看我们的应用。 52 | 53 | ![](https://cdn.scotch.io/9/vFba0QgQRReyNZPgFpKU_vue-time-1.png) 54 | 55 | ### vue-cli 构建的目录结构 56 | ``` 57 | . 58 | ├── build/ # webpack config files 59 | │ └── ... 60 | ├── config/ 61 | │ ├── index.js # main project config 62 | │ └── ... 63 | ├── src/ 64 | │ ├── main.js # app entry file 65 | │ ├── App.vue # main app component 66 | │ ├── components/ # ui components 67 | │ │ └── ... 68 | │ └── assets/ # module assets (processed by webpack) 69 | │ └── ... 70 | ├── static/ # pure static assets (directly copied) 71 | ├── test/ 72 | │ └── unit/ # unit tests 73 | │ │ ├── specs/ # test spec files 74 | │ │ ├── index.js # test build entry file 75 | │ │ └── karma.conf.js # test runner config file 76 | │ └── e2e/ # e2e tests 77 | │ │ ├── specs/ # test spec files 78 | │ │ ├── custom-assertions/ # custom assertions for e2e tests 79 | │ │ ├── runner.js # test runner script 80 | │ │ └── nightwatch.conf.js # test runner config file 81 | ├── .babelrc # babel config 82 | ├── .editorconfig.js # editor config 83 | ├── .eslintrc.js # eslint config 84 | ├── index.html # index.html template 85 | └── package.json # build scripts and dependencies 86 | ``` 87 | 88 | 更多内容参照[https://vuejs-templates.github.io/webpack](https://vuejs-templates.github.io/webpack) 89 | 90 | ## Vue 指令 91 | 常用指令: 92 | - v-if 93 | - v-show 94 | - v-else 95 | - v-for 96 | - v-bind 97 | - v-on 98 | - v-model 99 | 更多指令请移步[Vue 指令](http://cn.vuejs.org/api/#u6307_u4EE4) 100 | 101 | ## 初始化(main.js) 102 | 103 | 对于单页应用,推荐使用[官方库 vue-router](https://github.com/vuejs/vue-router)。详细请查看它的[文档](http://vuejs.github.io/vue-router/)。 104 | 105 | ### 添加route配置 106 | ```js 107 | import VueRouter from 'vue-router' 108 | import VueResource from 'vue-resource' 109 | 110 | import Hello from './components/Hello.vue' 111 | import Page from './components/Page.vue' 112 | 113 | //注册两个插件 114 | Vue.use(VueResource) 115 | Vue.use(VueRouter) 116 | 117 | const router = new VueRouter() 118 | 119 | // 路由map 120 | router.map({ 121 | '/hello': { 122 | component: Hello 123 | }, 124 | '/page': { 125 | component: Page 126 | } 127 | }) 128 | 129 | router.redirect({ 130 | '*': '/hello' 131 | }) 132 | 133 | router.start(App, '#app')//设置启动页面 134 | ``` 135 | index.html 136 | ```html 137 |
138 | 139 |
140 | ``` 141 | 142 | ### 应用route 143 | ```html 144 | 153 | ``` 154 | 155 | ## 创建&应用组件 156 | ![](http://cn.vuejs.org/images/vue-component.png) 157 | 如果你喜欢预处理器,甚至可以这么做: 158 | ![](http://cn.vuejs.org/images/vue-component-with-pre-processors.png) 159 | 160 | 定义View: 161 | ```html 162 | 165 | ``` 166 | 定义Model和ViewModel: 167 | ```js 168 | var vueComponent = require('../components/vue-component'); 169 | module.exports = { 170 | components: { 171 | vueComponent 172 | } 173 | } 174 | ``` 175 | 176 | ## 数据请求:[vue-resource](http://www.cnblogs.com/keepfool/p/5657065.html) 177 | ```js 178 | //在main.js中注册vue-resource 179 | import VueResource from 'vue-resource' 180 | Vue.use(VueResource) 181 | ``` 182 | ```js 183 | // 基于全局Vue对象使用http 184 | Vue.http.get('//webapi.busi.inke.com/web/live_hotlist_pc', {}).then((response) => { 185 | console.log('[Leo]Vue-resource:success=>', response); 186 | }, (response) => { 187 | console.log('[Leo]Vue-resource:error=>', response); 188 | }); 189 | // 在一个Vue实例内使用$http 190 | this.$http.get('//webapi.busi.inke.com/web/live_hotlist_pc', {}).then((response) => { 191 | console.log('[Leo]Vue-resource:success=>', response); 192 | }, (response) => { 193 | console.log('[Leo]Vue-resource:error=>', response); 194 | }); 195 | ``` 196 | 197 | # run dev - 启动开发环境 198 | 开发的时候启动webpack热替换 199 | ``` 200 | npm run dev 201 | ``` 202 | 203 | ## 端口 204 | 默认端口号是`8080` 205 | 如果希望修改端口号,则进入`~\config\index.js`,修改`dev`下的`port`为希望启动的端口号 206 | ``` 207 | 例如: port: 80, 208 | ``` 209 | 210 | ## 跨域 211 | ### webpack+Express 212 | 进入`~\config\index.js`,在`dev`下的`proxyTable`就是网址映射 213 | ```js 214 | proxyTable: { 215 | '/api': { 216 | target: 'http://localhost:6060',//要跨域访问的API域名 217 | rewrite: function(req) { 218 | //可以用正則方式替代掉,這樣往後 /api/xxx/xxx 之類的網址,就會自動匹配了 219 | req.url = req.url.replace(/^\/api/, ''); 220 | } 221 | } 222 | } 223 | ``` 224 | 這樣當你呼叫 `/api` 時: 225 | ```js 226 | this.$http.get('/api') 227 | ``` 228 | 就會幫你自動導向 `http://localhost:8080/api`,是為了當 Server 和 前端 不在同個網域或是Port時,可以方便調試,例如我 Server 在 `localhost:6060`,前端在 `localhost:5050` ,就可以直接調用 `/api`,而不用每次都要加上完整網址 229 | 更多信息可参考:[https://webpack.github.io/docs/webpack-dev-server.html#proxy](https://webpack.github.io/docs/webpack-dev-server.html#proxy) 230 | 231 | ### Fetch.js 232 | 参考地址:[http://wwsun.github.io/posts/fetch-api-intro.html](http://wwsun.github.io/posts/fetch-api-intro.html) 233 | 234 | ### ngrok 235 | 236 | # run build - 发布服务器 237 | 进入项目所在目录运行 238 | ``` 239 | npm run build 240 | ``` 241 | 242 | ## 修改build生成的静态文件路径 243 | 进入`~\config\index.js` 244 | 在`build`下的`assetsPublicPath`默认情况下是`'/'`,此时打包的index.html文件中的资源文件(js、css、img)默认情况都是以`/`开头的绝对路径,指向http服务器的根路径 245 | 如果想修改为相对路径则需要将`assetsPublicPath`的值修改为`'./'`,这样就是指向index.html的相对路径了 246 | 247 | ## 部署SPA 248 | > 将打包生成好的项目部署到服务器,但是访问SPA项目的前端路由会出现`404`,这是由于HTTP服务器默认情况下访问的是对应目录下的index.html,此时需要对HTTP服务器做下路由映射,将前端路由地址映射到index.html。 249 | 250 | 以下是SPA项目常用的几种部署方式: 251 | *例如前端路由地址:[http://localhost/live/292/wonderful](http://localhost/live/292/wonderful)* 252 | 253 | ### Apache 254 | 如果只使用Apache做HTTP服务器,可以设置Apache的url重定向,将所有的请求路由到index.html 255 | 1. 打开`~\Apache\conf\httpd.conf`文件 256 | 2. 去除httpd.conf文件中`LoadModule rewrite_module modules/mod_rewrite.so`前面的`#`号 257 | 3. 在httpd.conf文件中添加重定向规则 258 | ``` 259 | RewriteEngine on 260 | # 当访问路由地址为 /live 开头的,则将路由重定向到 /index.html 261 | RewriteRule \/live.*$ /index.html 262 | ``` 263 | 264 | ### nginx 265 | 使用nginx做反向代理服务器,配置文件参考: 266 | ``` 267 | server { 268 | listen 80; 269 | server_name localhost:80; 270 | index index.html; 271 | root /wwwroot/; 272 | location / { 273 | try_files $uri $uri/ /index.html; 274 | } 275 | } 276 | ``` 277 | 278 | ### node.js 279 | 使用node.js做反向代理服务器,配置文件参考: 280 | ``` 281 | var config = require("./webpack.config.js"); 282 | var webpack = require("webpack") 283 | var webpackDevServer=require("webpack-dev-server") 284 | 285 | config.entry.unshift("webpack-dev-server/client?http://localhost:80", "webpack/hot/dev-server"); 286 | var compiler = webpack(config); 287 | 288 | var server = new webpackDevServer(compiler, { 289 | contentBase: "build", 290 | hot: true, 291 | inline: true, 292 | historyApiFallback: true, 293 | proxy: { 294 | '/*': { 295 | target: 'loaclhost:8080/', 296 | secure: false 297 | }, 298 | } 299 | }); 300 | 301 | server.listen(80); 302 | ``` 303 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | // https://github.com/shelljs/shelljs 2 | require('shelljs/global') 3 | env.NODE_ENV = 'production' 4 | 5 | var path = require('path') 6 | var config = require('../config') 7 | var ora = require('ora') 8 | var webpack = require('webpack') 9 | var webpackConfig = require('./webpack.prod.conf') 10 | 11 | console.log( 12 | ' Tip:\n' + 13 | ' Built files are meant to be served over an HTTP server.\n' + 14 | ' Opening index.html over file:// won\'t work.\n' 15 | ) 16 | 17 | var spinner = ora('building for production...') 18 | spinner.start() 19 | 20 | var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory) 21 | rm('-rf', assetsPath) 22 | mkdir('-p', assetsPath) 23 | cp('-R', 'static/', assetsPath) 24 | 25 | webpack(webpackConfig, function (err, stats) { 26 | spinner.stop() 27 | if (err) throw err 28 | process.stdout.write(stats.toString({ 29 | colors: true, 30 | modules: false, 31 | children: false, 32 | chunks: false, 33 | chunkModules: false 34 | }) + '\n') 35 | }) 36 | -------------------------------------------------------------------------------- /build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /build/dev-server.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var express = require('express') 3 | var webpack = require('webpack') 4 | var config = require('../config') 5 | var proxyMiddleware = require('http-proxy-middleware') 6 | var webpackConfig = process.env.NODE_ENV === 'testing' 7 | ? require('./webpack.prod.conf') 8 | : require('./webpack.dev.conf') 9 | 10 | // default port where dev server listens for incoming traffic 11 | var port = process.env.PORT || config.dev.port 12 | // Define HTTP proxies to your custom API backend 13 | // https://github.com/chimurai/http-proxy-middleware 14 | var proxyTable = config.dev.proxyTable 15 | 16 | var app = express() 17 | var compiler = webpack(webpackConfig) 18 | 19 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 20 | publicPath: webpackConfig.output.publicPath, 21 | stats: { 22 | colors: true, 23 | chunks: false 24 | } 25 | }) 26 | 27 | var hotMiddleware = require('webpack-hot-middleware')(compiler) 28 | // force page reload when html-webpack-plugin template changes 29 | compiler.plugin('compilation', function (compilation) { 30 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 31 | hotMiddleware.publish({ action: 'reload' }) 32 | cb() 33 | }) 34 | }) 35 | 36 | // proxy api requests 37 | Object.keys(proxyTable).forEach(function (context) { 38 | var options = proxyTable[context] 39 | if (typeof options === 'string') { 40 | options = { target: options } 41 | } 42 | app.use(proxyMiddleware(context, options)) 43 | }) 44 | 45 | // handle fallback for HTML5 history API 46 | app.use(require('connect-history-api-fallback')()) 47 | 48 | // serve webpack bundle output 49 | app.use(devMiddleware) 50 | 51 | // enable hot-reload and state-preserving 52 | // compilation error display 53 | app.use(hotMiddleware) 54 | 55 | // serve pure static assets 56 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 57 | app.use(staticPath, express.static('./static')) 58 | 59 | module.exports = app.listen(port, function (err) { 60 | if (err) { 61 | console.log(err) 62 | return 63 | } 64 | console.log('Listening at http://localhost:' + port + '\n') 65 | }) 66 | -------------------------------------------------------------------------------- /build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | // generate loader string to be used with extract text plugin 15 | function generateLoaders (loaders) { 16 | var sourceLoader = loaders.map(function (loader) { 17 | var extraParamChar 18 | if (/\?/.test(loader)) { 19 | loader = loader.replace(/\?/, '-loader?') 20 | extraParamChar = '&' 21 | } else { 22 | loader = loader + '-loader' 23 | extraParamChar = '?' 24 | } 25 | return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '') 26 | }).join('!') 27 | 28 | if (options.extract) { 29 | return ExtractTextPlugin.extract('vue-style-loader', sourceLoader) 30 | } else { 31 | return ['vue-style-loader', sourceLoader].join('!') 32 | } 33 | } 34 | 35 | // http://vuejs.github.io/vue-loader/configurations/extract-css.html 36 | return { 37 | css: generateLoaders(['css']), 38 | postcss: generateLoaders(['css']), 39 | less: generateLoaders(['css', 'less']), 40 | sass: generateLoaders(['css', 'sass?indentedSyntax']), 41 | scss: generateLoaders(['css', 'sass']), 42 | stylus: generateLoaders(['css', 'stylus']), 43 | styl: generateLoaders(['css', 'stylus']) 44 | } 45 | } 46 | 47 | // Generate loaders for standalone style files (outside of .vue) 48 | exports.styleLoaders = function (options) { 49 | var output = [] 50 | var loaders = exports.cssLoaders(options) 51 | for (var extension in loaders) { 52 | var loader = loaders[extension] 53 | output.push({ 54 | test: new RegExp('\\.' + extension + '$'), 55 | loader: loader 56 | }) 57 | } 58 | return output 59 | } 60 | -------------------------------------------------------------------------------- /build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var webpack = require("webpack") 2 | var path = require('path') 3 | var config = require('../config') 4 | var utils = require('./utils') 5 | var projectRoot = path.resolve(__dirname, '../') 6 | 7 | module.exports = { 8 | entry: { 9 | app: './src/main.js' 10 | }, 11 | output: { 12 | path: config.build.assetsRoot, 13 | publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath, 14 | filename: '[name].js' 15 | }, 16 | resolve: { 17 | extensions: ['', '.js', '.vue'], 18 | fallback: [path.join(__dirname, '../node_modules')], 19 | alias: { 20 | 'src': path.resolve(__dirname, '../src'), 21 | 'assets': path.resolve(__dirname, '../src/assets'), 22 | 'utils': path.resolve(__dirname, '../src/utils'), 23 | 'components': path.resolve(__dirname, '../src/components'), 24 | 'views': path.resolve(__dirname, '../src/views'), 25 | 'jquery': 'jquery' 26 | } 27 | }, 28 | resolveLoader: { 29 | fallback: [path.join(__dirname, '../node_modules')] 30 | }, 31 | module: { 32 | noParse: [ 33 | /node_modules\/video.js\/dist\/video.js/ 34 | ], 35 | loaders: [ 36 | { 37 | test: /\.vue$/, 38 | loader: 'vue' 39 | }, { 40 | test: /\.js$/, 41 | loader: 'babel', 42 | include: projectRoot, 43 | exclude: /node_modules/ 44 | }, { 45 | test: /\.json$/, 46 | loader: 'json' 47 | }, { 48 | test: /\.html$/, 49 | loader: 'vue-html' 50 | }, { 51 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 52 | loader: 'url', 53 | query: { 54 | limit: 10000, 55 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 56 | } 57 | }, { 58 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 59 | loader: 'url', 60 | query: { 61 | limit: 10000, 62 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 63 | } 64 | }, { 65 | test: /\.less$/, 66 | loader: 'style!css!less' 67 | }, { 68 | test: /\.scss$/, 69 | loader: 'style!css!sass' 70 | } 71 | ] 72 | }, 73 | vue: { 74 | loaders: utils.cssLoaders() 75 | }, 76 | plugins: [ 77 | new webpack.optimize.CommonsChunkPlugin('common.js'), 78 | new webpack.ProvidePlugin({ 79 | jQuery: "jquery", 80 | $: "jquery" 81 | }) 82 | ] 83 | } 84 | -------------------------------------------------------------------------------- /build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var config = require('../config') 2 | var webpack = require('webpack') 3 | var merge = require('webpack-merge') 4 | var utils = require('./utils') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | 8 | // add hot-reload related code to entry chunks 9 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 10 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 11 | }) 12 | 13 | module.exports = merge(baseWebpackConfig, { 14 | module: { 15 | loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 16 | }, 17 | // eval-source-map is faster for development 18 | devtool: '#eval-source-map', 19 | plugins: [ 20 | new webpack.DefinePlugin({ 21 | 'process.env': config.dev.env 22 | }), 23 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 24 | new webpack.optimize.OccurenceOrderPlugin(), 25 | new webpack.HotModuleReplacementPlugin(), 26 | new webpack.NoErrorsPlugin(), 27 | // https://github.com/ampedandwired/html-webpack-plugin 28 | new HtmlWebpackPlugin({ 29 | filename: 'index.html', 30 | template: 'index.html', 31 | inject: true 32 | }) 33 | ] 34 | }) 35 | -------------------------------------------------------------------------------- /build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseWebpackConfig = require('./webpack.base.conf') 7 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 8 | var HtmlWebpackPlugin = require('html-webpack-plugin') 9 | var env = process.env.NODE_ENV === 'testing' 10 | ? require('../config/test.env') 11 | : config.build.env 12 | 13 | var webpackConfig = merge(baseWebpackConfig, { 14 | module: { 15 | loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }) 16 | }, 17 | devtool: config.build.productionSourceMap ? '#source-map' : false, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 21 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 22 | }, 23 | vue: { 24 | loaders: utils.cssLoaders({ 25 | sourceMap: config.build.productionSourceMap, 26 | extract: true 27 | }) 28 | }, 29 | plugins: [ 30 | // http://vuejs.github.io/vue-loader/workflow/production.html 31 | new webpack.DefinePlugin({ 32 | 'process.env': env 33 | }), 34 | new webpack.optimize.UglifyJsPlugin({ 35 | compress: { 36 | warnings: false 37 | } 38 | }), 39 | new webpack.optimize.OccurenceOrderPlugin(), 40 | // extract css into its own file 41 | new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')), 42 | // generate dist index.html with correct asset hash for caching. 43 | // you can customize output by editing /index.html 44 | // see https://github.com/ampedandwired/html-webpack-plugin 45 | new HtmlWebpackPlugin({ 46 | filename: process.env.NODE_ENV === 'testing' 47 | ? 'index.html' 48 | : config.build.index, 49 | template: 'index.html', 50 | inject: true, 51 | minify: { 52 | removeComments: true, 53 | collapseWhitespace: true, 54 | removeAttributeQuotes: true 55 | // more options: 56 | // https://github.com/kangax/html-minifier#options-quick-reference 57 | }, 58 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 59 | chunksSortMode: 'dependency' 60 | }), 61 | // split vendor js into its own file 62 | new webpack.optimize.CommonsChunkPlugin({ 63 | name: 'vendor', 64 | minChunks: function (module, count) { 65 | // any required modules inside node_modules are extracted to vendor 66 | return ( 67 | module.resource && 68 | /\.js$/.test(module.resource) && 69 | module.resource.indexOf( 70 | path.join(__dirname, '../node_modules') 71 | ) === 0 72 | ) 73 | } 74 | }), 75 | // extract webpack runtime and module manifest to its own file in order to 76 | // prevent vendor hash from being updated whenever app bundle is updated 77 | new webpack.optimize.CommonsChunkPlugin({ 78 | name: 'manifest', 79 | chunks: ['vendor'] 80 | }) 81 | ] 82 | }) 83 | 84 | if (config.build.productionGzip) { 85 | var CompressionWebpackPlugin = require('compression-webpack-plugin') 86 | 87 | webpackConfig.plugins.push( 88 | new CompressionWebpackPlugin({ 89 | asset: '[path].gz[query]', 90 | algorithm: 'gzip', 91 | test: new RegExp( 92 | '\\.(' + 93 | config.build.productionGzipExtensions.join('|') + 94 | ')$' 95 | ), 96 | threshold: 10240, 97 | minRatio: 0.8 98 | }) 99 | ) 100 | } 101 | 102 | module.exports = webpackConfig 103 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'] 18 | }, 19 | dev: { 20 | env: require('./dev.env'), 21 | port: 8080, 22 | assetsSubDirectory: 'static', 23 | assetsPublicPath: '/', 24 | proxyTable: {}, 25 | // CSS Sourcemaps off by default because relative paths are "buggy" 26 | // with this option, according to the CSS-Loader README 27 | // (https://github.com/webpack/css-loader#sourcemaps) 28 | // In our experience, they generally work as expected, 29 | // just be aware of this issue when enabling this option. 30 | cssSourceMap: false 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /dist/common.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([2,0,3],[]); 2 | //# sourceMappingURL=common.js.map -------------------------------------------------------------------------------- /dist/common.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///common.js"],"names":["webpackJsonp"],"mappings":"AAAAA,cAAc,EAAE,EAAE","file":"common.js","sourcesContent":["webpackJsonp([2,0,3],[]);\n\n\n/** WEBPACK FOOTER **\n ** common.js\n **/"],"sourceRoot":""} -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 直播分享
-------------------------------------------------------------------------------- /dist/static/Img/jx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/dist/static/Img/jx.png -------------------------------------------------------------------------------- /dist/static/Img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/dist/static/Img/logo.png -------------------------------------------------------------------------------- /dist/static/Img/logo_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/dist/static/Img/logo_default.png -------------------------------------------------------------------------------- /dist/static/Img/logo_default_s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/dist/static/Img/logo_default_s.jpg -------------------------------------------------------------------------------- /dist/static/Img/tou_xiang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/dist/static/Img/tou_xiang.png -------------------------------------------------------------------------------- /dist/static/base.css: -------------------------------------------------------------------------------- 1 | @CHARSET "utf-8"; 2 | /* 3 | * @Author: Meta 4 | * @Date: 2016-04-28 17:40:41 5 | * @Last Modified by: liuyuanyuan 6 | * @Last Modified time: 2016-07-25 18:23:30 7 | */ 8 | *{ 9 | margin:0;padding:0; 10 | -webkit-tap-highlight-color:rgba(0,0,0,0); 11 | -webkit-text-size-adjust:100%; 12 | -webkit-user-select:none; 13 | font-weight:normal; 14 | font-style:normal; 15 | box-sizing:border-box; 16 | -webkit-box-sizing:border-box; /* Safari */ 17 | -moz-box-sizing:border-box; /* Firefox */ 18 | -ms-text-size-adjust: 100%; 19 | -ms-user-select:none; 20 | user-select:none; 21 | -webkit-overflow-scrolling: touch; 22 | } 23 | ::-webkit-search-cancel-button { display: none;} 24 | html{font:20px/1.25'微软雅黑',Arial,sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;} 25 | body,p,form,input,button,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6{margin:0;padding:0;overflow-x:hidden;} 26 | h1,h2,h3,h4,h5,h6{font-size:100%;} 27 | input,textarea,select{-webkit-user-select:text;-ms-user-select:text;user-select:text;-webkit-appearance:none;} 28 | textarea{resize:none;} 29 | table{border-collapse:collapse;} 30 | input,select,textarea{outline:none;border:none;background:none;font-size:0.7rem;font-family:"微软雅黑"} 31 | a{text-decoration:none;-WebKit-touch-callout:none;outline:0;cursor:pointer;color:#666;} 32 | em,i{font-style:normal;} 33 | li,ol{list-style:none;} 34 | .clearfix{*zoom:1;} 35 | .clearfix:after{display:block;overflow:hidden;clear:both;height:0;visibility:hidden;content:".";} 36 | body{margin:0 auto;width:100%;background-color:#f4f4f4;color:#666;font-size:0.7rem;} 37 | img{border:none;width:100%;vertical-align:top;} 38 | ::-webkit-scrollbar{width: 0;height: 0;} 39 | ::-webkit-scrollbar-track {background-color: transparent;} /* 滚动条的滑轨背景颜色 */ 40 | ::-webkit-scrollbar-thumb {background-color: transparent;} /* 滑块颜色 */ 41 | ::-webkit-scrollbar-button {background-color: transparent;} /* 滑轨两头的监听按钮颜色 */ 42 | ::-webkit-scrollbar-corner {background-color: transparent;} /* 横向滚动条和纵向滚动条相交处尖角的颜色 */ 43 | /*公共样式*/ 44 | .fl{float:left;} 45 | .fr{float:right;} 46 | .txtalign-l{text-align: left !important;} 47 | .txtalign-c{text-align: center !important;} 48 | .txtalign-r{text-align: right !important;} 49 | .m-top{margin-top: 1rem!important;} 50 | .bg-fff{background-color:#fff;} 51 | .s-m-top{margin-top: 0.5rem!important;} 52 | .m-r{margin-right:1rem!important;} 53 | .s-m-r{margin-right:0.5rem!important;} 54 | .line-top{border-top: 1px solid #E1E1E1;} 55 | .line-bottom{border-bottom: 1px solid #E1E1E1;} 56 | .hide{display:none;} 57 | .show{display:block;} 58 | .text{font-size:0.6rem!important;} 59 | .red{color:#fa4619!important;} 60 | 61 | .dest_header{width: 100%;height:2.2rem;line-height: 2.2rem;background-color: #FFAF00;font-weight: normal;font-size: 0.75rem;position: relative;color:#000;} 62 | .icon_arrow_l,.icon_arrow_b,.icon_arrow_c{width: 2.2rem;height: 2.2rem;background-position: 0 0;position: absolute;top: 0.05rem;left: 0;-webkit-background-size: 100%;background-size: 100%;background-image: url('../../img/back.png');} 63 | .dest_header > .submit-btn{position:absolute;padding:0 0.75rem;font-size:0.8;right:0;top:0} 64 | .righthide{position:absolute;left:0;width:100%;top:0;bottom:0;right:0;overflow:hidden;background:#f4f4f4;transform:translate(100%,0px) translateZ(0);z-index:999;} 65 | .righthide .wrap{padding-bottom:2.4rem;transform: translate(0px, 0px) translateZ(0);} 66 | .no-data-img {position: absolute;left: 50%;top: 50%;margin-top: -2rem;margin-left: -1.75rem;width: 3.5rem;height: 3.5rem;} 67 | .no-data-desc {position: absolute;top: 50%;width: 100%;text-align: center;margin-top: 2rem;} 68 | .jx-tip{display:none;position:fixed;bottom:2rem;font-size:0.7rem;line-height:2;background:rgba(0,0,0,0.8);color:#fff;border-radius:0.2rem;padding:0.4rem 0.6rem;z-index:9999;} 69 | /*alert*/ 70 | #pagemask{display:none;position:absolute;background:rgba(0,0,0,0.8);left:0;top:0;bottom:0;right:0;z-index:9998;} 71 | #model-box {background:rgba(0,0,0,0.3);position: fixed;top:0; left: 0; right: 0; bottom: 0;z-index: 9998 } 72 | #model-box .model-main { width: 14rem; height: auto; background: #fff; border: 1px solid #ccc; box-shadow: 1px 2px 3px #999;position: absolute; top:0; left: 0; } 73 | #model-box .model-main .content { padding: 1rem; padding-bottom: 0; line-height:2;text-align: center; font-size: 0.8rem; color: #222} 74 | #model-box .model-main .confirm { text-align: center; margin: 1rem; } 75 | #model-box .model-main button { width: 4rem; text-align: center; background: #ffaf00; border: none; padding: 0.4rem; margin: 0 0.5rem;} 76 | #page-package{position:absolute;left:0;top:0;bottom:0;right:0;overflow:hidden;background:#f4f4f4;z-index:1001;} 77 | #page-package .wrap, 78 | #page-orderpay .wrap{padding-bottom: 2.4rem;} 79 | #page-calendar .wrap{padding-bottom:0;} 80 | #page-addVisitor { z-index:999} 81 | 82 | .page-in{-webkit-transition: -webkit-transform 400ms;-webkit-transform: translate3d(0,0,0);} 83 | .page-left-out{-webkit-transition:-webkit-transform 400ms;-webkit-transform: translate3d(-100%,0,0);} 84 | .page-right-out{-webkit-transition:-webkit-transform 400ms;-webkit-transform: translate3d(100%,0,0);} 85 | 86 | 87 | /* 使用浏览器打开 */ 88 | .openBrowser { position: absolute; z-index: 9999999; background: #363636 url(../../img/springboard.jpg) 0 0 no-repeat; top: 0; left: 0; right: 0; bottom: 0; -webkit-background-size: 100%; 89 | background-size: 100%; } 90 | /*顶部logo打开下载app*/ 91 | .download_mask{ 92 | position: fixed; 93 | top:0; 94 | width: 100%; 95 | height: 2.5rem; 96 | background-color: rgba(0,0,0,0.65); 97 | padding:0.4rem 0.75rem; 98 | z-index: 999999; 99 | display: none; 100 | } 101 | .download_masks { height: 2.5rem; } 102 | /*-------提示下载部分-------------*/ 103 | .download_mask .logo{ 104 | width: 4.8rem; 105 | border-radius: 0.2rem; 106 | } 107 | .download_btn{ 108 | position: absolute; 109 | right:0.75rem; 110 | top:0.6rem; 111 | width: 3rem; 112 | height:1.4rem; 113 | line-height: 1.4rem; 114 | border-radius: 0.2rem; 115 | border: 1px solid #fff; 116 | text-align:center; 117 | } 118 | .download_btn a{ 119 | display: block; 120 | width: 100%; 121 | height: 100%; 122 | color:#fff; 123 | font-size: 0.55rem; 124 | } 125 | 126 | /*下载二*/ 127 | .show-go-download-div{ 128 | position: fixed; 129 | top: 0rem; 130 | width: 100%; 131 | height: 100%; 132 | padding: 0 0.5rem; 133 | background: rgba(0,0,0,0.3); 134 | text-align: center; 135 | padding-top:6rem ; 136 | padding-left: 2rem; 137 | padding-right: 2rem; 138 | z-index: 999; 139 | display: none; 140 | } 141 | .show-go-download{ 142 | border-radius: 0.3rem; 143 | background: url('../../img/show-download-bg.png') no-repeat center center; 144 | background-size: 100%; 145 | height: 16.3rem; 146 | } 147 | .go-pic{ 148 | height: 7.5rem; 149 | } 150 | .go-desc{ 151 | text-align: center; 152 | font-size: 0.8rem; 153 | margin-bottom: 1.5rem; 154 | margin-top: 1.5rem; 155 | color: #000; 156 | } 157 | .go-btn{ 158 | text-align: center; 159 | margin-top: 0.3rem; 160 | margin-bottom: 0.3rem; 161 | height: 3.5rem; 162 | } 163 | .go-pic-close{ 164 | width: 0.8rem; 165 | height: 0.8rem; 166 | float: right; 167 | margin-top:0.2rem; 168 | margin-right: 1.05rem; 169 | } 170 | /*-------------------------------------------------------------*/ 171 | @media screen and (min-width: 320px) {html{font-size:106.6666%;}} 172 | @media screen and (min-width: 360px) {html{font-size:120%;}} 173 | @media screen and (min-width: 375px) {html{font-size:125%;}} 174 | @media screen and (min-width: 400px) {html{font-size:133.3333%;}} 175 | @media screen and (min-width: 414px) {html{font-size:138%;}} 176 | @media screen and (min-width: 440px) {html{font-size:146.6666%;}} 177 | @media screen and (min-width: 480px) {html{font-size:160%;}} 178 | @media screen and (min-width: 520px) {html{font-size:173.3333%;}} 179 | @media screen and (min-width: 560px) {html{font-size:186.6666%;}} 180 | @media screen and (min-width: 600px) {html{font-size:200%;}} 181 | @media screen and (min-width: 640px) {html{font-size:213.3333%;}} 182 | @media screen and (min-width: 680px) {html{font-size:226.6666%;}} 183 | @media screen and (min-width: 720px) {html{font-size:240%;}} 184 | @media screen and (min-width: 760px) {html{font-size:253.3333%;}} 185 | @media screen and (min-width: 800px) {html{font-size:266.6666%;}} 186 | @media screen and (min-width: 1200px) {html{font-size:400%;}} 187 | @media screen and (min-width: 1280px) {html{font-size:426.6666%;}} 188 | 189 | 190 | -------------------------------------------------------------------------------- /dist/static/common/jx-common-app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 与app交互的方法 3 | */ 4 | window.jx_common_app = { 5 | callApp : function(opration,data){ 6 | if($("#jx-app-hidden-div").size() > 0){ 7 | $("#jx-app-hidden-div").remove(); 8 | } 9 | $("body").append("
") 10 | var hidden = document.getElementById("jx-app-hidden-div"); 11 | var iframe = document.createElement("iframe"); 12 | iframe.src = "yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\""+opration+"\",\"DATA\":"+data+"}"; 13 | iframe.style.display = "none"; 14 | hidden.appendChild(iframe); 15 | return false; 16 | }, 17 | openApp : function(){ 18 | window.location.href = "yimay://app"; 19 | }, 20 | openAppShop : function(shopId,shopName){ 21 | shopName = encodeURIComponent(shopName); 22 | var operation = "SHOP_HOME_PAGE"; 23 | var data = "{\"id\":\""+shopId+"\",\"name\":\""+shopName+"\"}"; 24 | var _self = this; 25 | _self.callApp(operation,data); 26 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"SHOP_HOME_PAGE\",\"DATA\":{\"id\":\""+shopId+"\",\"name\":\""+shopName+"\"}}"; 27 | }, 28 | openAppItemDetail : function(itemId,itemType,title){ 29 | title = encodeURIComponent(title); 30 | var operation = ""; 31 | var data = "{\"id\":\""+itemId+"\",\"title\":\""+title+"\"}"; 32 | //跟团游 33 | if(itemType == "TOUR_LINE"){ 34 | operation = "PACKAGE_TOUR_DETAIL"; 35 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"PACKAGE_TOUR_DETAIL\",\"DATA\":{\"id\":\""+itemId+"\",\"title\":\""+title+"\"}}"; 36 | //return false; 37 | } 38 | //周边游 39 | else if(itemType == "ARROUND_FUN"){ 40 | operation = "AROUND_FUN_DETAIL"; 41 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"AROUND_FUN_DETAIL\",\"DATA\":{\"id\":\""+itemId+"\",\"title\":\""+title+"\"}}"; 42 | //return false; 43 | } 44 | //同城玩乐 45 | else if(itemType == "CITY_ACTIVITY"){ 46 | operation = "CITY_ACTIVITY_DETAIL"; 47 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"CITY_ACTIVITY_DETAIL\",\"DATA\":{\"id\":\""+itemId+"\",\"title\":\""+title+"\"}}"; 48 | //return false; 49 | } 50 | //自由行 51 | else if(itemType == "FREE_LINE"){ 52 | operation = "FREE_TOUR_DETAIL"; 53 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"FREE_TOUR_DETAIL\",\"DATA\":{\"id\":\""+itemId+"\",\"title\":\""+title+"\"}}"; 54 | //return false; 55 | } 56 | //酒店 57 | else if(itemType == "HOTEL"){ 58 | operation = "HOTEL"; 59 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"HOTEL\",\"DATA\":{\"id\":\""+itemId+"\",\"name\":\""+title+"\"}}"; 60 | //return false; 61 | } 62 | //境外自由行:FREE_TOUR_ABOARD_DETAIL 63 | else if(itemType == "FREE_TOUR_ABOARD_DETAIL"){ 64 | operation = "FREE_TOUR_ABOARD_DETAIL"; 65 | } 66 | //境外跟团游:PACKAGE_TOUR_ABOARD_DETAIL 67 | else if(itemType == "PACKAGE_TOUR_ABOARD_DETAIL"){ 68 | operation = "PACKAGE_TOUR_ABOARD_DETAIL"; 69 | } 70 | //积分商城商品详情 71 | else if(itemType == "INTEGRAL_MALL_DETAIL"){ 72 | operation = "VIEW_INTEGRAL_MALL_DETAIL"; 73 | data = "{\"id\":\""+itemId+"\"}"; 74 | } 75 | //美食 76 | else if(itemType == "JIUXIU_BUY_DETAIL"){ 77 | operation = "JIUXIU_BUY_DETAIL"; 78 | } 79 | else{ 80 | alert("暂不支持类型:"+itemType); 81 | return false; 82 | } 83 | var _self = this; 84 | _self.callApp(operation,data); 85 | }, 86 | openAppShare : function(shareTitle,shareContent,shareImageUrl,shareWebPage,shareWay){ 87 | shareTitle = encodeURIComponent(shareTitle); 88 | shareContent = encodeURIComponent(shareContent); 89 | shareImageUrl = encodeURIComponent(shareImageUrl); 90 | shareWebPage = encodeURIComponent(shareWebPage); 91 | if(!shareWay || shareWay == null || shareWay == ""){ 92 | shareWay = "-1"; 93 | } 94 | if(shareWay != "-1" //全部 95 | && shareWay != "1" //微信 96 | && shareWay != "2" //微信朋友圈 97 | && shareWay != "3" //QQ 98 | && shareWay != "4" //Weibo 99 | && shareWay != "5" //达人圈 100 | ){ 101 | alert("暂不支持分享类型"); 102 | return false; 103 | } 104 | var operation = "WEB_SHARE"; 105 | var data = '{"shareTitle":"'+shareTitle+'","shareContent":"'+shareContent+'","shareImageUrl":"'+shareImageUrl+'","shareWebPage":"'+shareWebPage+'","shareWay":"'+shareWay+'"}'; 106 | var _self = this; 107 | _self.callApp(operation,data); 108 | //window.location.href ='yimay://app?content={"TYPE":"JIUXIU","OPERATION":"WEB_SHARE","DATA":{"shareTitle":"'+shareTitle+'","shareContent":"'+shareContent+'","shareImageUrl":"'+shareImageUrl+'","shareWebPage":"'+shareWebPage+'","shareWay":"'+shareWay+'"}}'; 109 | }, 110 | openAppLogin:function(){ 111 | var operation = "LOGIN"; 112 | var data = '{}'; 113 | var _self = this; 114 | _self.callApp(operation,data); 115 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"LOGIN\",\"DATA\":{}}"; 116 | return false; 117 | }, 118 | openAppTopic:function(topicName){ 119 | topicName = encodeURIComponent(topicName); 120 | var operation = "VIEW_TOPIC_DETAIL"; 121 | var data = "{\"topicName\":\""+topicName+"\"}"; 122 | var _self = this; 123 | _self.callApp(operation,data); 124 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"VIEW_TOPIC_DETAIL\",\"DATA\":{\"topicName\":\""+topicName+"\"}}"; 125 | }, 126 | openAppBack:function() { 127 | var _self = this; 128 | _self.closeWindow(); 129 | }, 130 | openAppConsult:function(id) { 131 | var operation = "VIEW_CONSULTING_SERVICE_DETAIL"; 132 | var data = "{\"id\":\""+id+"\"}"; 133 | var _self = this; 134 | _self.callApp(operation,data); 135 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"VIEW_CONSULTING_SERVICE_DETAIL\",\"DATA\":{\"id\":\""+id+"\"}}"; 136 | return false; 137 | }, 138 | openAppDarenPage:function(id,option,title) { 139 | var operation = "MASTER_DETAIL"; 140 | var data = "{\"id\":\""+id+"\",\"option\":\""+option+"\",\"title\":\""+title+"\"}"; 141 | var _self = this; 142 | _self.callApp(operation,data); 143 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"MASTER_DETAIL\",\"DATA\":{\"id\":\""+id+"\",\"option\":\""+option+"\",\"title\":\""+title+"\"}}"; 144 | return false; 145 | }, 146 | openAppMall:function(){ 147 | var operation = "VIEW_INTEGRAL_MALL"; 148 | var data = "{}"; 149 | var _self = this; 150 | _self.callApp(operation,data); 151 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"VIEW_INTEGRAL_MALL\",\"DATA\":{}}"; 152 | return false; 153 | }, 154 | openH5Mall:function(){ 155 | var operation = "WEB_INTEGRAL_MALL"; 156 | var data = "{}"; 157 | var _self = this; 158 | _self.callApp(operation,data); 159 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"VIEW_INTEGRAL_MALL\",\"DATA\":{}}"; 160 | return false; 161 | }, 162 | openAppTaskList:function(){ 163 | var operation = "VIEW_INTEGRAL_TASK_LIST"; 164 | var data = "{}"; 165 | var _self = this; 166 | _self.callApp(operation,data); 167 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"VIEW_INTEGRAL_TASK_LIST\",\"DATA\":{}}"; 168 | return false; 169 | }, 170 | closeWindow:function(){ 171 | var operation = "CLOSE_WINDOW"; 172 | var data = "{}"; 173 | var _self = this; 174 | _self.callApp(operation,data); 175 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"CLOSE_WINDOW\",\"DATA\":{}}"; 176 | return false; 177 | }, 178 | openAppTitle:function(title){ 179 | title = encodeURIComponent(title); 180 | var operation = "WEBVIEW_TITLE"; 181 | var data = "{\"title\":\""+title+"\"}"; 182 | var _self = this; 183 | _self.callApp(operation,data); 184 | return false; 185 | }, 186 | //积分明细 187 | openAppJiFenDetail:function(){ 188 | var operation = "VIEW_INTEGRAL_DETAIL"; 189 | var data = "{}"; 190 | var _self = this; 191 | _self.callApp(operation,data); 192 | return false; 193 | }, 194 | //积分任务列表 195 | openAppJiFenTaskList : function(){ 196 | var operation = "VIEW_INTEGRAL_TASK_LIST"; 197 | var data = "{}"; 198 | var _self = this; 199 | _self.callApp(operation,data); 200 | return false; 201 | }, 202 | //打开app中内嵌的H5页面 203 | openAppWeb:function(_url){ 204 | var _self = this; 205 | var operation = "OPEN_WEB"; 206 | var data = "{\"link\":\""+_url+"\",\"isCleanCookie\":\""+false+"\"}"; 207 | _self.callApp(operation,data); 208 | }, 209 | // app打开所有版本的商城 210 | openAllMall : function () { 211 | var _self = this, 212 | versionCode = jx_common.getAppVersionCode(); 213 | if(!versionCode){ 214 | _self.openAppMall(); 215 | return false; 216 | } 217 | versionCode = versionCode.substr(0,3); 218 | if(versionCode == "200"){ 219 | window.location.href="http://"+document.domain+"/view/mall/index.html"; 220 | return false; 221 | } 222 | if(versionCode== "210" || versionCode== "215"){ 223 | _self.openH5Mall(); 224 | return false; 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /dist/static/common/jx-contpointer.js: -------------------------------------------------------------------------------- 1 | ;(function($){ 2 | $.extend({ 3 | //action_name动作编码 4 | //action_params可变参数,例如{'pid':'122012','pname':'蔬菜'}。具体的根据文档规定传,action_name不同action_params也会不同。 5 | monitors:function(url,action_and_params,app_id,domain_id,userid,channelCode,activity_info){ 6 | var stamps=new Date().getTime(),auto_params=[]; 7 | for(var key in action_and_params){ 8 | var obj={ 9 | "2001": key, 10 | "2002": "", 11 | "2003": stamps, 12 | "2004": action_and_params[key], 13 | "2005": "", 14 | "2006": userid, 15 | "2007": "", 16 | "2008": activity_info 17 | }; 18 | auto_params.push(obj); 19 | } 20 | 21 | config={ 22 | "1001": "九休旅行", 23 | "1002": app_id, 24 | "1003": "", 25 | "1004": "", 26 | "1005": "", 27 | "1006": "", 28 | "1007": "", 29 | "1008": this.ck_system(), 30 | "1009": this.ios_or_android(), 31 | "1010": "", 32 | "1011": channelCode, 33 | "1012": "", 34 | "1013": "", 35 | "1014": this.ck_browser(), 36 | "1015": "", 37 | "1016": "", 38 | "1017": auto_params, 39 | "1018": domain_id 40 | }; 41 | $.ajax({ 42 | dataType : "jsonp", 43 | url: url,//记录数据请求地址 44 | data: {msg:encodeURI(JSON.stringify(config))} 45 | }); 46 | }, 47 | ck_system:function() { 48 | var bIsAndroid = navigator.userAgent.match(/android/i) == "android",isIphone = (navigator.platform.toLowerCase() == "iphone") ; 49 | if (isIphone||bIsAndroid) return "MOBILE"; 50 | var isWin = (navigator.platform.toLowerCase() == "win32") || (navigator.platform.toLowerCase() == "windows"); 51 | var isMac = (navigator.platform.toLowerCase() == "mac68k") || (navigator.platform.toLowerCase() == "macppc") 52 | || (navigator.platform.toLowerCase() == "macintosh") || (navigator.platform.toLowerCase() == "macintel"); 53 | var isUnix = (navigator.platform.toLowerCase() == "x11") && !isWin && !isMac; 54 | var isLinux = (String(navigator.platform.toLowerCase()).indexOf("linux") > -1); 55 | if (isWin||isMac||isUnix||isLinux) return "PC"; 56 | return "PAD"; 57 | }, 58 | ios_or_android:function() { 59 | var isIphone = (navigator.platform.toLowerCase() == "iphone") ; 60 | if (isIphone) return "ios"; 61 | var bIsAndroid = (navigator.platform.toLowerCase() == "android"); 62 | if(bIsAndroid) return "android"; 63 | return ''; 64 | }, 65 | ck_browser:function(){ 66 | var userAgent = navigator.userAgent.toLowerCase(); 67 | var isOpera = userAgent.indexOf("opera") > -1; 68 | if (isOpera) { 69 | return "Opera浏览器" 70 | } 71 | if (userAgent.indexOf("firefox") > -1) { 72 | return "Firefox浏览器"; 73 | } 74 | if (userAgent.indexOf("chrome") > -1){ 75 | return "Chrome浏览器"; 76 | } 77 | if (userAgent.indexOf("safari") > -1) { 78 | return "Safari浏览器"; 79 | } 80 | if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("msie") > -1 && !isOpera) { 81 | return "IE浏览器"; 82 | } 83 | if(userAgent.indexOf("micromessenger") > -1) { 84 | return "微信内嵌浏览器"; 85 | } 86 | if(userAgent.indexOf(" qq") > -1) { 87 | return "QQ内嵌浏览器"; 88 | } 89 | } 90 | }); 91 | })(jQuery); 92 | 93 | /*$(function(){ 94 | //monitors函数,具体调用的例子。 95 | //$.monitors('Submit_Order',{'pid':'122012','pname':'蔬菜'}); 96 | $.monitors("http://test.data.jiuxiulvxing.com/newlogwithgzip.jsp",{ 97 | 'pv_uv':{'pid':'122012','pname':'蔬菜'} 98 | },"23","1200"); 99 | });*/ 100 | 101 | -------------------------------------------------------------------------------- /dist/static/common/jx-contpointerutil.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: liuyuanyuan 3 | * @Date: 2016-06-20 12:21:05 4 | * @Last Modified by: liuyuanyuan 5 | * @Last Modified time: 2016-07-07 11:49:29 6 | */ 7 | 8 | 'use strict'; 9 | 10 | var _contpointer_config = {api : _wap_config.contpointersApi} 11 | 12 | //公共参数 13 | _contpointer_config.monitorsAction=function(params,user_id,activity_info){ 14 | $.monitors(_contpointer_config.api,params,jx_ajax.getAid(),_wap_config.domid,user_id,jx_ajax.getCh(),activity_info); 15 | }; 16 | -------------------------------------------------------------------------------- /dist/static/common/jx-downloadapp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | window.jx_downloadapp={ 5 | show : function (){ 6 | var htl = [] ; 7 | htl.push("
"); 8 | htl.push(""); 11 | htl.push("
"); 12 | htl.push("

下载九休旅行App

"); 13 | htl.push("

来云南,选九休

"); 14 | htl.push("
"); 15 | htl.push("
"); 16 | htl.push(" 免费下载"); 17 | htl.push("
"); 18 | htl.push("
"); 19 | $("body").append(htl.join("")); 20 | }, 21 | hide : function(){ 22 | $(".download_mask").remove(); 23 | } 24 | }; -------------------------------------------------------------------------------- /dist/static/common/jx-footmenu.js: -------------------------------------------------------------------------------- 1 | /** 2 | * footer-menu 3 | * 首先要引入jQuery.js 4 | * author:zhangjianfeng 5 | * date:2016-05-07 6 | */ 7 | window.jx_footMenu = { 8 | show : function(type){ 9 | $(".foot-menu").remove(); 10 | var menuHtlArr =[]; 11 | menuHtlArr.push("
"); 12 | menuHtlArr.push(" "); 32 | menuHtlArr.push("
"); 33 | $("body").append(menuHtlArr.join("")); 34 | if(!type){ 35 | return ; 36 | } 37 | if(type == "index"){ 38 | var infor_img=$(".index_img").parent().find('.infor'); 39 | $(".index_img").addClass("index_img_choose"); 40 | $(".index_img").removeClass("index_img"); 41 | infor_img.addClass('choose').siblings().removeClass('choose'); 42 | } 43 | if(type == "my"){ 44 | var infor_account=$(".index_acount").parent().find('.infor'); 45 | $(".index_acount").addClass("index_acount_choose"); 46 | $(".index_acount").removeClass("index_acount"); 47 | infor_account.addClass('choose').siblings().removeClass('choose'); 48 | } 49 | if(type == "app"){ 50 | var infor_app=$(".index_app").parent().find('.infor'); 51 | $(".index_app").addClass("index_app_choose"); 52 | $(".index_app").removeClass("index_app"); 53 | infor_app.addClass('choose').siblings().removeClass('choose'); 54 | } 55 | 56 | }, 57 | 58 | hide : function(){ 59 | $(".foot-menu").hide(); 60 | } 61 | 62 | }; 63 | -------------------------------------------------------------------------------- /dist/static/common/jx-h5cache.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 需要md5加密 3 | * 支持单页面上缓存存储 4 | */ 5 | window.jx_h5cache = { 6 | setCache : function(key,value,timeout){ 7 | var _self = this; 8 | if(!window.localStorage){ 9 | return false; 10 | } 11 | _self.getStorageHref(key); 12 | window.localStorage.setItem(key,value); 13 | var timeoutKey = key+"_timeout"; 14 | if(timeout){ 15 | window.localStorage.setItem(timeoutKey,(new Date()).getTime() + (timeout *1000)); 16 | }else{ 17 | window.localStorage.setItem(timeoutKey,-1); 18 | } 19 | }, 20 | getCache : function(key){ 21 | var _self = this; 22 | if(!window.localStorage){ 23 | return ""; 24 | } 25 | _self.getStorageHref(key); 26 | var timeoutKey = key + "_timeout"; 27 | var timeout = window.localStorage.getItem(timeoutKey); 28 | if(!timeout || "" == timeout){ 29 | return ""; 30 | } 31 | if(timeout == -1 || timeout > (new Date()).getTime()){ 32 | return window.localStorage.getItem(key); 33 | } 34 | window.localStorage.setItem(key,""); 35 | return ""; 36 | }, 37 | delCache : function (key) { 38 | var _self = this; 39 | if(!window.localStorage){ 40 | return ""; 41 | } 42 | _self.getStorageHref(key); 43 | window.localStorage.removeItem(key); 44 | window.localStorage.removeItem(key + '_timeout'); 45 | }, 46 | getStorageHref : function (key) { 47 | if(localStorage.locationHref){ 48 | key = md5(localStorage.locationHref)+"_"+key; 49 | }else { 50 | key = md5(window.location.href)+"_"+key; 51 | } 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /dist/static/common/jx-log.js: -------------------------------------------------------------------------------- 1 | window.jx_log={ 2 | monitors:function(action_and_params,activity_info){ 3 | var auto_params=[]; 4 | for(var key in action_and_params){ 5 | var obj={ 6 | "2001": key, 7 | "2002": "", 8 | "2003": (new Date()).getTime(), 9 | "2004": action_and_params[key], 10 | "2005": "", 11 | "2006": "", 12 | "2007": "", 13 | "2008": activity_info?activity_info:"" 14 | }; 15 | auto_params.push(obj); 16 | } 17 | 18 | var config={ 19 | "1001": "九休旅行", 20 | "1002": jx_ajax.getAid(), 21 | "1003": "", 22 | "1004": "", 23 | "1005": "", 24 | "1006": "", 25 | "1007": "", 26 | "1008": this.ck_system(), 27 | "1009": jx_common.isIOS() ? "ios" : "android", 28 | "1010": "", 29 | "1011": jx_ajax.getCh(), 30 | "1012": "", 31 | "1013": "", 32 | "1014": this.ck_browser(), 33 | "1015": "", 34 | "1016": "", 35 | "1017": auto_params, 36 | "1018": _wap_config.domid 37 | }; 38 | $.ajax({ 39 | dataType : "jsonp", 40 | url: _wap_config.contpointersApi,//记录数据请求地址 41 | data: {msg:encodeURIComponent(JSON.stringify(config))} 42 | }); 43 | /*if($("#jx-app-hidden-div-log").size() > 0){ 44 | $("#jx-app-hidden-div-log").remove(); 45 | } 46 | $("body").append("
") 47 | var hidden = document.getElementById("jx-app-hidden-div-log"); 48 | var iframe = document.createElement("iframe"); 49 | iframe.src = _wap_config.contpointersApi+"?msg="+encodeURIComponent(JSON.stringify(config)); 50 | iframe.style.display = "none"; 51 | hidden.appendChild(iframe);*/ 52 | }, 53 | ck_system:function() { 54 | var bIsAndroid = navigator.userAgent.match(/android/i) == "android",isIphone = (navigator.platform.toLowerCase() == "iphone") ; 55 | if (isIphone||bIsAndroid) return "MOBILE"; 56 | var isWin = (navigator.platform.toLowerCase() == "win32") || (navigator.platform.toLowerCase() == "windows"); 57 | var isMac = (navigator.platform.toLowerCase() == "mac68k") || (navigator.platform.toLowerCase() == "macppc") 58 | || (navigator.platform.toLowerCase() == "macintosh") || (navigator.platform.toLowerCase() == "macintel"); 59 | var isUnix = (navigator.platform.toLowerCase() == "x11") && !isWin && !isMac; 60 | var isLinux = (String(navigator.platform.toLowerCase()).indexOf("linux") > -1); 61 | if (isWin||isMac||isUnix||isLinux) return "PC"; 62 | return "PAD"; 63 | }, 64 | ck_browser:function(){ 65 | var userAgent = navigator.userAgent.toLowerCase(); 66 | var isOpera = userAgent.indexOf("opera") > -1; 67 | if (isOpera) { 68 | return "Opera浏览器" 69 | } 70 | if (userAgent.indexOf("firefox") > -1) { 71 | return "Firefox浏览器"; 72 | } 73 | if (userAgent.indexOf("chrome") > -1){ 74 | return "Chrome浏览器"; 75 | } 76 | if (userAgent.indexOf("safari") > -1) { 77 | return "Safari浏览器"; 78 | } 79 | if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("msie") > -1 && !isOpera) { 80 | return "IE浏览器"; 81 | } 82 | if(userAgent.indexOf("micromessenger") > -1) { 83 | return "微信内嵌浏览器"; 84 | } 85 | if(userAgent.indexOf(" qq") > -1) { 86 | return "QQ内嵌浏览器"; 87 | } 88 | } 89 | }; -------------------------------------------------------------------------------- /dist/static/css/app.bf4f8152f201de6b2d08f1d2509a6d2f.css: -------------------------------------------------------------------------------- 1 | [v-cloak]{display:none}.pos-re{position:relative}.vedioBox{width:100%;height:12rem;overflow:hidden}.online{width:4.475rem;height:2.25rem;background:rgba(0,0,0,.15);color:#fff;font-size:.625rem;line-height:1.125rem;position:absolute;bottom:.75rem;left:.75rem;border-radius:.2rem;padding-left:.375rem}.msgBox{height:6rem;padding:0 .75rem;background-color:#fff}.msgBox h3{font-size:.75rem;line-height:2.425rem}.msgBox span{display:inline-block;margin-left:.375rem;line-height:1.125rem;font-size:.625rem}.msgBox span i{color:#333;font-weight:700}.touPic{width:2.375rem;height:2.375rem;border-radius:50%;overflow:hidden;float:left}.liver i{padding-right:1rem;background-position:.13rem -.15rem;background-size:.7rem 1rem;background-repeat:no-repeat}.liver i.girl{background-image:url(/static/liveStreaming/img/girl.png)}.liver i.boy{background-image:url(/static/liveStreaming/img/boy.png)}.shar{position:relative;float:right;width:1.6rem;height:2.125rem;margin-top:-1rem;text-align:center}.shar:before{content:'';position:absolute;left:-.7rem;height:100%;width:0;border-left:1px solid #e1e1e1;padding-left:10px}.shar i{display:block;width:100%;height:1.125rem;background:url(/static/liveStreaming/img/share.png) no-repeat;background-position:50%;background-size:1.2rem 1rem}.shar span{margin:0}.liveList{margin-top:.5rem;background-color:#fff}.listTab li{width:50%;height:2.5rem;line-height:2.5rem;font-size:.75rem;color:#555;float:left;box-sizing:border-box;overflow:hidden}.listTab .active{color:#ffaf00;border-bottom:2px solid #ffaf00}.toshar{width:100%;height:100%;z-index:50;position:fixed;top:0;left:0;bottom:0;right:0;background-color:rgba(0,0,0,.45);color:#fff}.toshar i{display:inline-block;width:2.625rem;height:5.5rem;background:url(/static/liveStreaming/img/arrow.png) no-repeat;background-size:100%;float:right;margin-top:1.25rem;margin-right:.75rem}.toshar p{font-size:.75rem;float:right;margin-top:5.625rem;margin-right:.5rem}[v-cloak]{display:none}video::-webkit-media-controls{display:none!important}.video-wrap,.video-wrap .video-js{height:100%;width:100%;max-height:100%}.vjs-control-bar,.vjs-fade-in,.vjs-fade-out{visibility:visible!important;opacity:1!important;-webkit-transition-duration:0s!important;transition-duration:0s!important}.video-js .vjs-control-bar{background-color:rgba(43,51,63,0)}.vjs-has-started .vjs-control-bar{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.toload{height:2.25rem;background:rgba(0,0,0,.65);color:#fff;padding:.35rem .75rem;position:fixed;left:0;bottom:0;width:100%}.log{float:left;border-radius:.5rem;width:1.5rem;height:1.5rem;overflow:hidden}.toload span{display:block;margin-left:2.4rem}.main-tit{font-size:.625rem}.sub-tit{font-size:.5rem;margin-top:.1rem}.sub-tit i{color:#ffaf00}.logbtn{float:right;border:1px solid #fff;width:4.05rem;height:1.3rem;line-height:1.3rem;border-radius:.2rem;margin-top:-1.4rem}.list{padding:0 .75rem .5rem}.list li{padding-top:.5rem;float:left;width:48%;overflow:hidden}.list li:nth-child(2n){margin-left:.65rem}.list .listbox{height:6rem;overflow:hidden}.liverName{line-height:1.7rem;font-size:.75rem;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.liverName i{padding-right:1.5rem;background:url(/static/liveStreaming/img/movie.png) no-repeat;background-position:.3rem 0;background-size:1rem 1rem}.listbox span{display:inline-block;position:absolute;color:#fff;font-size:.6rem}.listbox .state{width:1.7rem;height:.9rem;line-height:.9rem;background:rgba(0,0,0,.25);top:.375rem;right:.5rem;border-right:.5rem}.listbox .name{bottom:.5rem;left:.375rem}.listbox .num{bottom:.5rem;right:.375rem} 2 | /*# sourceMappingURL=app.bf4f8152f201de6b2d08f1d2509a6d2f.css.map*/ -------------------------------------------------------------------------------- /dist/static/css/app.bf4f8152f201de6b2d08f1d2509a6d2f.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///webpack:///src/views/live/Live.vue","webpack:///webpack:///src/components/Video.vue","webpack:///webpack:///src/components/toload.vue","webpack:///webpack:///src/assets/css/liveList.css"],"names":[],"mappings":"AAsWA,UACI,YAAc,CAGlB,QACI,iBAAmB,CAGvB,UACI,WACA,aACA,eAAiB,CAGrB,QACI,eACA,eACA,2BACA,WACA,kBACA,qBACA,kBACA,cACA,YACA,oBACA,oBAAuB,CAG3B,QACI,YACA,iBACA,qBAAuB,CAG3B,WACI,iBACA,oBAAsB,CAG1B,aACI,qBACA,oBACA,qBACA,iBAAoB,CAGxB,eACI,WACA,eAAkB,CAGtB,QACI,eACA,gBACA,kBACA,gBACA,UAAY,CAGhB,SACI,mBACA,mCACA,2BACA,2BAA6B,CAGjC,cACI,wDAA0D,CAG9D,aACI,uDAAyD,CAG7D,MACI,kBACA,YACA,aACA,gBACA,iBACA,iBAAmB,CAGvB,aACI,WACA,kBACA,YACA,YACA,QACA,8BACA,iBAAmB,CAGvB,QACI,cACA,WACA,gBACA,8DACA,wBACA,2BAA6B,CAGjC,WACI,QAAU,CAGd,UACI,iBACA,qBAAuB,CAG3B,YACI,UACA,cACA,mBACA,iBACA,WACA,WACA,sBACA,eAAiB,CAGrB,iBACI,cACA,+BAAiC,CAIrC,QACI,WACA,YACA,WACA,eACA,MACA,OACA,SACA,QACA,iCACA,UAAY,CAGhB,UACI,qBACA,eACA,cACA,8DACA,qBACA,YACA,mBACA,mBAAsB,CAG1B,UACI,iBACA,YACA,oBACA,kBAAqB,CCrQzB,UACI,YAAc,CAIlB,8BACI,sBAAyB,CAG7B,kCACI,YACA,WACA,eAAiB,CAIrB,4CACI,6BACA,oBACA,yCACQ,gCAAmC,CAG/C,2BACI,iCAAsC,CAG1C,kCACI,qBACI,kBACI,wBAA0B,CCnQtC,QACI,eACA,2BACA,WACA,sBACA,eACA,OACA,SACA,UAAY,CAGhB,KACI,WACA,oBACA,aACA,cACA,eAAiB,CAGrB,aACI,cACA,kBAAoB,CAGxB,UACI,iBAAoB,CAGxB,SACI,gBACA,gBAAmB,CAGvB,WACI,aAAe,CAGnB,QACI,YACA,sBACA,cACA,cACA,mBACA,oBACA,kBAAoB,CCpExB,MACC,sBAAiC,CAElC,SACC,kBACA,WACA,UACA,eAAiB,CAElB,uBACC,kBAAoB,CAErB,eACC,YACA,eAAiB,CAElB,WACC,mBACA,iBACA,gBACA,mBACA,sBAAwB,CAEzB,aACC,qBACA,8DACA,4BACA,yBAA0B,CAG3B,cACC,qBACA,kBACA,WACA,eAAiB,CAElB,gBACC,aACA,aACA,kBACA,2BACA,YACA,YACA,kBAAqB,CAEtB,eACG,aACA,YAAe,CAElB,cACC,aACA,aAAgB","file":"static/css/app.bf4f8152f201de6b2d08f1d2509a6d2f.css","sourcesContent":["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[v-cloak] {\n display: none;\n}\n\n.pos-re {\n position: relative;\n}\n\n.vedioBox {\n width: 100%;\n height: 12rem;\n overflow: hidden;\n}\n\n.online {\n width: 4.475rem;\n height: 2.25rem;\n background: rgba(0, 0, 0, 0.15);\n color: #fff;\n font-size: 0.625rem;\n line-height: 1.125rem;\n position: absolute;\n bottom: 0.75rem;\n left: 0.75rem;\n border-radius: 0.2rem;\n padding-left: 0.375rem;\n}\n\n.msgBox {\n height: 6rem;\n padding: 0 0.75rem;\n background-color: #fff;\n}\n\n.msgBox h3 {\n font-size: 0.75rem;\n line-height: 2.425rem;\n}\n\n.msgBox span {\n display: inline-block;\n margin-left: 0.375rem;\n line-height: 1.125rem;\n font-size: 0.625rem;\n}\n\n.msgBox span i {\n color: #333;\n font-weight: bold;\n}\n\n.touPic {\n width: 2.375rem;\n height: 2.375rem;\n border-radius: 50%;\n overflow: hidden;\n float: left;\n}\n\n.liver i {\n padding-right: 1.0rem;\n background-position: 0.13rem -0.15rem;\n background-size: 0.7rem 1rem;\n background-repeat: no-repeat;\n}\n\n.liver i.girl {\n background-image: url(/static/liveStreaming/img/girl.png);\n}\n\n.liver i.boy {\n background-image: url(/static/liveStreaming/img/boy.png);\n}\n\n.shar {\n position: relative;\n float: right;\n width: 1.6rem;\n height: 2.125rem;\n margin-top: -1rem;\n text-align: center;\n}\n\n.shar::before {\n content: '';\n position: absolute;\n left: -0.7rem;\n height: 100%;\n width: 0;\n border-left: 1px solid #e1e1e1;\n padding-left: 10px;\n}\n\n.shar i {\n display: block;\n width: 100%;\n height: 1.125rem;\n background: url(/static/liveStreaming/img/share.png) no-repeat;\n background-position: center center;\n background-size: 1.2rem 1rem;\n}\n\n.shar span {\n margin: 0;\n}\n\n.liveList {\n margin-top: 0.5rem;\n background-color: #fff;\n}\n\n.listTab li {\n width: 50%;\n height: 2.5rem;\n line-height: 2.5rem;\n font-size: 0.75rem;\n color: #555;\n float: left;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n.listTab .active {\n color: #FFAF00;\n border-bottom: 2px solid #FFAF00;\n}\n\n/* 分享浮层 */\n.toshar {\n width: 100%;\n height: 100%;\n z-index: 50;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n right: 0;\n background-color: rgba(0, 0, 0, 0.45);\n color: #fff;\n}\n\n.toshar i {\n display: inline-block;\n width: 2.625rem;\n height: 5.5rem;\n background: url(/static/liveStreaming/img/arrow.png) no-repeat;\n background-size: 100%;\n float: right;\n margin-top: 1.25rem;\n margin-right: 0.75rem;\n}\n\n.toshar p {\n font-size: 0.75rem;\n float: right;\n margin-top: 5.625rem;\n margin-right: 0.5rem;\n}\n\n\n\n\n/** WEBPACK FOOTER **\n ** webpack:///src/views/live/Live.vue\n **/","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[v-cloak] {\n display: none;\n}\n\n/*隐藏系统自带播放器控制栏*/\nvideo::-webkit-media-controls {\n display: none !important;\n}\n\n.video-wrap, .video-wrap .video-js {\n height: 100%;\n width: 100%;\n max-height: 100%;\n}\n\n/*让videojs的控制栏始终显示*/\n.vjs-control-bar, .vjs-fade-in, .vjs-fade-out {\n visibility: visible !important;\n opacity: 1 !important;\n -webkit-transition-duration: 0s !important;\n transition-duration: 0s !important;\n}\n\n.video-js .vjs-control-bar {\n background-color: rgba(43, 51, 63, 0);\n}\n\n.vjs-has-started .vjs-control-bar {\n -webkit-box-pack: end;\n -ms-flex-pack: end;\n justify-content: flex-end;\n}\n\n/* Video.js Controls Style Overrides */\n/*.vjs-default-skin .vjs-fullscreen-control {*/\n/*display: none;*/\n/*}*/\n\n\n\n/** WEBPACK FOOTER **\n ** webpack:///src/components/Video.vue\n **/","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.toload {\n height: 2.25rem;\n background: rgba(0, 0, 0, 0.65);\n color: #fff;\n padding: 0.35rem 0.75rem;\n position: fixed;\n left: 0;\n bottom: 0;\n width: 100%;\n}\n\n.log {\n float: left;\n border-radius: 0.5rem;\n width: 1.5rem;\n height: 1.5rem;\n overflow: hidden;\n}\n\n.toload span {\n display: block;\n margin-left: 2.4rem;\n}\n\n.main-tit {\n font-size: 0.625rem;\n}\n\n.sub-tit {\n font-size: 0.5rem;\n margin-top: 0.1rem;\n}\n\n.sub-tit i {\n color: #ffaf00;\n}\n\n.logbtn {\n float: right;\n border: 1px solid #fff;\n width: 4.05rem;\n height: 1.3rem;\n line-height: 1.3rem;\n border-radius: 0.2rem;\n margin-top: -1.4rem;\n}\n\n\n\n/** WEBPACK FOOTER **\n ** webpack:///src/components/toload.vue\n **/",".list{\r\n\tpadding:0 0.75rem 0.5rem 0.75rem;\r\n}\r\n.list li{\r\n\tpadding-top: 0.5rem;\r\n\tfloat: left;\r\n\twidth:48%;\r\n\toverflow: hidden;\r\n}\r\n.list li:nth-child(2n){\r\n\tmargin-left:0.65rem;\r\n}\r\n.list .listbox{\r\n\theight:6rem;\r\n\toverflow: hidden;\r\n}\r\n.liverName{\r\n\tline-height:1.7rem;\r\n\tfont-size:0.75rem;\r\n\toverflow: hidden;\r\n\twhite-space: nowrap;\r\n\ttext-overflow: ellipsis;\r\n}\r\n.liverName i{\r\n\tpadding-right:1.5rem;\r\n\tbackground: url(/static/liveStreaming/img/movie.png) no-repeat;\r\n\tbackground-position:0.3rem 0rem;\r\n\tbackground-size:1rem 1rem;\r\n\r\n}\r\n.listbox span{\r\n\tdisplay: inline-block;\r\n\tposition: absolute;\r\n\tcolor: #fff;\r\n\tfont-size:0.6rem;\r\n}\r\n.listbox .state{\r\n\twidth:1.7rem;\r\n\theight:0.9rem;\r\n\tline-height: 0.9rem;\r\n\tbackground: rgba(0,0,0,0.25);\r\n\ttop:0.375rem;\r\n\tright: 0.5rem;\r\n\tborder-right: 0.5rem;\r\n}\r\n.listbox .name{\r\n bottom:0.5rem;\r\n left: 0.375rem;\r\n}\r\n.listbox .num{\r\n\tbottom: 0.5rem;\r\n\tright: 0.375rem;\r\n}\r\n\n\n\n/** WEBPACK FOOTER **\n ** webpack:///src/assets/css/liveList.css\n **/"],"sourceRoot":""} -------------------------------------------------------------------------------- /dist/static/data/live.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 0, 3 | "src": "http://record2.a8.com/mp4/1472734874787582.mp4", 4 | "poster": "/static/img/logo_default.png", 5 | "online": "100", 6 | "room": "101", 7 | "title": "热带云南8天7晚,2015穿越北北回归线", 8 | "photo": "/static/img/tou_xiang.png", 9 | "liver": "王璐岢", 10 | "focus": "20", 11 | "fans": "100", 12 | "replay":[{ 13 | "img":"/static/img/logo_default_s.jpg", 14 | "state":"1", 15 | "liver":"xxx", 16 | "viewer":"1000", 17 | "title":"123456qwerty" 18 | },{ 19 | "img":"/static/img/logo_default_s.jpg", 20 | "state":"1", 21 | "liver":"xxx2", 22 | "viewer":"1000", 23 | "title":"123456qwerty" 24 | },{ 25 | "img":"/static/img/logo_default_s.jpg", 26 | "state":"1", 27 | "liver":"xxx3", 28 | "viewer":"1000", 29 | "title":"123456qwerty" 30 | },{ 31 | "img":"/static/img/logo_default_s.jpg", 32 | "state":"1", 33 | "liver":"xxx", 34 | "viewer":"1000", 35 | "title":"123456qwerty" 36 | }], 37 | "wonderfulList":[{ 38 | "id":"111111", 39 | "img":"/static/img/logo_default_s.jpg", 40 | "state":"START_LIVE", 41 | "liver":"AAA", 42 | "viewer":"1000", 43 | "title":"123456qwerty" 44 | },{ 45 | "id":"2222222", 46 | "img":"/static/img/logo_default_s.jpg", 47 | "state":"REPLAY_LIVE", 48 | "liver":"bbb", 49 | "viewer":"1000", 50 | "title":"123456qwerty" 51 | }] 52 | } 53 | -------------------------------------------------------------------------------- /dist/static/data/video.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 1, 3 | "src": "http://record2.a8.com/mp4/1472734874787582.mp4", 4 | "poster": "/static/img/logo_default.png", 5 | "online": "100", 6 | "room": "101", 7 | "title": "热带云南8天7晚,2015穿越北北回归线", 8 | "photo": "/static/img/tou_xiang.png", 9 | "liver": "王璐岢", 10 | "focus": "20", 11 | "fans": "10" 12 | } 13 | -------------------------------------------------------------------------------- /dist/static/js/manifest.7f7248d867a534d27f5e.js: -------------------------------------------------------------------------------- 1 | !function(e){function t(a){if(n[a])return n[a].exports;var r=n[a]={exports:{},id:a,loaded:!1};return e[a].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var a=window.webpackJsonp;window.webpackJsonp=function(c,o){for(var p,s,l=0,i=[];l 2 | 3 | 4 | 5 | 分享直播 6 | 7 | 8 | 9 | 10 |
11 | 12 |

点击右上角分享

13 |
14 |
15 |
16 | 17 | 18 | 在线: 1234
19 | 房号: 16100 20 |
21 | 22 | 23 |
24 |
25 |

热带云南8天7晚,2015穿越北北回归线

26 | 27 | 28 | 29 | adbli
30 | 关注 67 31 | 粉丝 5128 32 |
33 | 34 | 分享 35 |
36 |
37 |
38 |
39 |
    40 |
  • 精彩推荐
  • 41 |
  • Ta的回放
  • 42 |
43 |
    44 |
  • 45 |
    46 | 47 | 直播 48 | sun 49 | 23335看过 50 |
    51 |
    52 | 2015穿越回归线 53 |
    54 |
  • 55 |
  • 56 |
    57 | 58 | 直播 59 | sun 60 | 23335看过 61 |
    62 |
    63 | 2015穿越回归线 64 |
    65 |
  • 66 |
  • 67 |
    68 | 69 | 直播 70 | sun 71 | 23335看过 72 |
    73 |
    74 | 2015穿越回归线 75 |
    76 |
  • 77 |
  • 78 |
    79 | 80 | 直播 81 | sun 82 | 23335看过 83 |
    84 |
    85 | 2015穿越回归线 86 |
    87 |
  • 88 |
89 |
90 |
91 |
92 | 93 |
94 | 想每天看旅游直播? 95 | 下载九休旅行送5元 96 |
立即下载
97 |
98 | 99 | -------------------------------------------------------------------------------- /dist/static/plugin/jquery.cookie.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery Cookie Plugin v1.4.1 3 | * https://github.com/carhartl/jquery-cookie 4 | * 5 | * Copyright 2013 Klaus Hartl 6 | * Released under the MIT license 7 | */ 8 | (function (factory) { 9 | if (typeof define === 'function' && define.amd) { 10 | // AMD 11 | define(['jquery'], factory); 12 | } else if (typeof exports === 'object') { 13 | // CommonJS 14 | factory(require('jquery')); 15 | } else { 16 | // Browser globals 17 | factory(jQuery); 18 | } 19 | }(function ($) { 20 | 21 | var pluses = /\+/g; 22 | 23 | function encode(s) { 24 | return config.raw ? s : encodeURIComponent(s); 25 | } 26 | 27 | function decode(s) { 28 | return config.raw ? s : decodeURIComponent(s); 29 | } 30 | 31 | function stringifyCookieValue(value) { 32 | return encode(config.json ? JSON.stringify(value) : String(value)); 33 | } 34 | 35 | function parseCookieValue(s) { 36 | if (s.indexOf('"') === 0) { 37 | // This is a quoted cookie as according to RFC2068, unescape... 38 | s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); 39 | } 40 | 41 | try { 42 | // Replace server-side written pluses with spaces. 43 | // If we can't decode the cookie, ignore it, it's unusable. 44 | // If we can't parse the cookie, ignore it, it's unusable. 45 | s = decodeURIComponent(s.replace(pluses, ' ')); 46 | return config.json ? JSON.parse(s) : s; 47 | } catch(e) {} 48 | } 49 | 50 | function read(s, converter) { 51 | var value = config.raw ? s : parseCookieValue(s); 52 | return $.isFunction(converter) ? converter(value) : value; 53 | } 54 | 55 | var config = $.cookie = function (key, value, options) { 56 | 57 | // Write 58 | 59 | if (value !== undefined && !$.isFunction(value)) { 60 | options = $.extend({}, config.defaults, options); 61 | 62 | if (typeof options.expires === 'number') { 63 | var days = options.expires, t = options.expires = new Date(); 64 | t.setTime(+t + days * 864e+5); 65 | } 66 | 67 | return (document.cookie = [ 68 | encode(key), '=', stringifyCookieValue(value), 69 | options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE 70 | options.path ? '; path=' + options.path : '', 71 | options.domain ? '; domain=' + options.domain : '', 72 | options.secure ? '; secure' : '' 73 | ].join('')); 74 | } 75 | 76 | // Read 77 | 78 | var result = key ? undefined : {}; 79 | 80 | // To prevent the for loop in the first place assign an empty array 81 | // in case there are no cookies at all. Also prevents odd result when 82 | // calling $.cookie(). 83 | var cookies = document.cookie ? document.cookie.split('; ') : []; 84 | 85 | for (var i = 0, l = cookies.length; i < l; i++) { 86 | var parts = cookies[i].split('='); 87 | var name = decode(parts.shift()); 88 | var cookie = parts.join('='); 89 | 90 | if (key && key === name) { 91 | // If second argument (value) is a function it's a converter... 92 | result = read(cookie, value); 93 | break; 94 | } 95 | 96 | // Prevent storing a cookie that we couldn't decode. 97 | if (!key && (cookie = read(cookie)) !== undefined) { 98 | result[name] = cookie; 99 | } 100 | } 101 | 102 | return result; 103 | }; 104 | 105 | config.defaults = {}; 106 | 107 | $.removeCookie = function (key, options) { 108 | if ($.cookie(key) === undefined) { 109 | return false; 110 | } 111 | 112 | // Must not alter options, thus extending a fresh object... 113 | $.cookie(key, '', $.extend({}, options, { expires: -1 })); 114 | return !$.cookie(key); 115 | }; 116 | 117 | })); 118 | -------------------------------------------------------------------------------- /dist/static/plugin/md5.min.js: -------------------------------------------------------------------------------- 1 | !function(a){"use strict";function b(a,b){var c=(65535&a)+(65535&b),d=(a>>16)+(b>>16)+(c>>16);return d<<16|65535&c}function c(a,b){return a<>>32-b}function d(a,d,e,f,g,h){return b(c(b(b(d,a),b(f,h)),g),e)}function e(a,b,c,e,f,g,h){return d(b&c|~b&e,a,b,f,g,h)}function f(a,b,c,e,f,g,h){return d(b&e|c&~e,a,b,f,g,h)}function g(a,b,c,e,f,g,h){return d(b^c^e,a,b,f,g,h)}function h(a,b,c,e,f,g,h){return d(c^(b|~e),a,b,f,g,h)}function i(a,c){a[c>>5]|=128<>>9<<4)+14]=c;var d,i,j,k,l,m=1732584193,n=-271733879,o=-1732584194,p=271733878;for(d=0;d>5]>>>b%32&255);return c}function k(a){var b,c=[];for(c[(a.length>>2)-1]=void 0,b=0;b>5]|=(255&a.charCodeAt(b/8))<16&&(e=i(e,8*a.length)),c=0;16>c;c+=1)f[c]=909522486^e[c],g[c]=1549556828^e[c];return d=i(f.concat(k(b)),512+8*b.length),j(i(g.concat(d),640))}function n(a){var b,c,d="0123456789abcdef",e="";for(c=0;c>>4&15)+d.charAt(15&b);return e}function o(a){return unescape(encodeURIComponent(a))}function p(a){return l(o(a))}function q(a){return n(p(a))}function r(a,b){return m(o(a),o(b))}function s(a,b){return n(r(a,b))}function t(a,b,c){return b?c?r(b,a):s(b,a):c?p(a):q(a)}"function"==typeof define&&define.amd?define(function(){return t}):a.md5=t}(this); -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/favicon.ico -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 直播分享 19 | 20 | 21 | 24 | 27 | 28 | 29 | 30 | 31 | 32 |
33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "live", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "", 6 | "private": true, 7 | "scripts": { 8 | "dev": "node build/dev-server.js", 9 | "build": "node build/build.js", 10 | "unit": "karma start test/unit/karma.conf.js --single-run", 11 | "e2e": "node test/e2e/runner.js", 12 | "test": "npm run unit && npm run e2e" 13 | }, 14 | "dependencies": { 15 | "vue": "^1.0.21", 16 | "babel-runtime": "^6.0.0", 17 | "vue-resource": "^0.6.1", 18 | "vue-router": "^0.7.11", 19 | "vuex": "^0.6.3", 20 | "vue-infinite-scroll":"^0.2.3", 21 | "jquery": "^2.2.3", 22 | "js-cookie": "^2.1.3", 23 | "blueimp-md5":"^2.3.1", 24 | "video.js": "^5.11.6", 25 | "videojs-contrib-hls": "^3.5.3" 26 | }, 27 | "devDependencies": { 28 | "babel-core": "^6.0.0", 29 | "babel-loader": "^6.0.0", 30 | "babel-plugin-transform-runtime": "^6.0.0", 31 | "babel-preset-es2015": "^6.0.0", 32 | "babel-preset-stage-2": "^6.0.0", 33 | "babel-register": "^6.0.0", 34 | "connect-history-api-fallback": "^1.1.0", 35 | "css-loader": "^0.23.0", 36 | "style-loader": "^0.12.3", 37 | "sass-loader": "^4.0.0", 38 | "node-sass": "^3.7.0", 39 | "less": "^2.7.1", 40 | "less-loader": "^2.2.3", 41 | "eventsource-polyfill": "^0.9.6", 42 | "express": "^4.13.3", 43 | "extract-text-webpack-plugin": "^1.0.1", 44 | "file-loader": "^0.8.4", 45 | "function-bind": "^1.0.2", 46 | "html-webpack-plugin": "^2.8.1", 47 | "http-proxy-middleware": "^0.12.0", 48 | "json-loader": "^0.5.4", 49 | "karma": "^0.13.15", 50 | "karma-coverage": "^0.5.5", 51 | "karma-mocha": "^0.2.2", 52 | "karma-phantomjs-launcher": "^1.0.0", 53 | "karma-sinon-chai": "^1.2.0", 54 | "karma-sourcemap-loader": "^0.3.7", 55 | "karma-spec-reporter": "0.0.24", 56 | "karma-webpack": "^1.7.0", 57 | "lolex": "^1.4.0", 58 | "mocha": "^2.4.5", 59 | "chai": "^3.5.0", 60 | "sinon": "^1.17.3", 61 | "sinon-chai": "^2.8.0", 62 | "inject-loader": "^2.0.1", 63 | "isparta-loader": "^2.0.0", 64 | "phantomjs-prebuilt": "^2.1.3", 65 | "chromedriver": "^2.21.2", 66 | "cross-spawn": "^2.1.5", 67 | "nightwatch": "^0.8.18", 68 | "selenium-server": "2.53.0", 69 | "ora": "^0.2.0", 70 | "shelljs": "^0.6.0", 71 | "url-loader": "^0.5.7", 72 | "vue-hot-reload-api": "^1.2.0", 73 | "vue-html-loader": "^1.0.0", 74 | "vue-loader": "^8.3.0", 75 | "vue-style-loader": "^1.0.0", 76 | "webpack": "^1.12.2", 77 | "webpack-dev-middleware": "^1.4.0", 78 | "webpack-hot-middleware": "^2.6.0", 79 | "webpack-merge": "^0.8.3" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /params.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Vue-demo", 3 | "tagline": "vue全家桶的单页直播", 4 | "body": "### Welcome to GitHub Pages.\r\nThis automatic page generator is the easiest way to create beautiful pages for all of your projects. Author your page content here [using GitHub Flavored Markdown](https://guides.github.com/features/mastering-markdown/), select a template crafted by a designer, and publish. After your page is generated, you can check out the new `gh-pages` branch locally. If you’re using GitHub Desktop, simply sync your repository and you’ll see the new branch.\r\n\r\n### Designer Templates\r\nWe’ve crafted some handsome templates for you to use. Go ahead and click 'Continue to layouts' to browse through them. You can easily go back to edit your page before publishing. After publishing your page, you can revisit the page generator and switch to another theme. Your Page content will be preserved.\r\n\r\n### Creating pages manually\r\nIf you prefer to not use the automatic generator, push a branch named `gh-pages` to your repository to create a page manually. In addition to supporting regular HTML content, GitHub Pages support Jekyll, a simple, blog aware static site generator. Jekyll makes it easy to create site-wide headers and footers without having to copy them across every page. It also offers intelligent blog support and other advanced templating features.\r\n\r\n### Authors and Contributors\r\nYou can @mention a GitHub username to generate a link to their profile. The resulting `` element will link to the contributor’s GitHub Profile. For example: In 2007, Chris Wanstrath (@defunkt), PJ Hyett (@pjhyett), and Tom Preston-Werner (@mojombo) founded GitHub.\r\n\r\n### Support or Contact\r\nHaving trouble with Pages? Check out our [documentation](https://help.github.com/pages) or [contact support](https://github.com/contact) and we’ll help you sort it out.\r\n", 5 | "note": "Don't delete this file! It's used internally to help with page regeneration." 6 | } -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 2 | 7 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/assets/css/liveList.css: -------------------------------------------------------------------------------- 1 | .list{ 2 | padding:0 0.75rem 0.5rem 0.75rem; 3 | } 4 | .list li{ 5 | padding-top: 0.5rem; 6 | float: left; 7 | width:48%; 8 | overflow: hidden; 9 | } 10 | .list li:nth-child(2n){ 11 | margin-left:0.65rem; 12 | } 13 | .list .listbox{ 14 | height:6rem; 15 | overflow: hidden; 16 | } 17 | .liverName{ 18 | line-height:1.7rem; 19 | font-size:0.75rem; 20 | overflow: hidden; 21 | white-space: nowrap; 22 | text-overflow: ellipsis; 23 | } 24 | .liverName i{ 25 | padding-right:1.5rem; 26 | background: url(/static/liveStreaming/img/movie.png) no-repeat; 27 | background-position:0.3rem 0rem; 28 | background-size:1rem 1rem; 29 | 30 | } 31 | .listbox span{ 32 | display: inline-block; 33 | position: absolute; 34 | color: #fff; 35 | font-size:0.6rem; 36 | } 37 | .listbox .state{ 38 | width:1.7rem; 39 | height:0.9rem; 40 | line-height: 0.9rem; 41 | background: rgba(0,0,0,0.25); 42 | top:0.375rem; 43 | right: 0.5rem; 44 | border-right: 0.5rem; 45 | } 46 | .listbox .name{ 47 | bottom:0.5rem; 48 | left: 0.375rem; 49 | } 50 | .listbox .num{ 51 | bottom: 0.5rem; 52 | right: 0.375rem; 53 | } 54 | -------------------------------------------------------------------------------- /src/assets/img/jx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/src/assets/img/jx.png -------------------------------------------------------------------------------- /src/assets/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/src/assets/img/logo.png -------------------------------------------------------------------------------- /src/assets/img/logo_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/src/assets/img/logo_default.png -------------------------------------------------------------------------------- /src/assets/img/logo_default_s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/src/assets/img/logo_default_s.jpg -------------------------------------------------------------------------------- /src/assets/img/tou_xiang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/src/assets/img/tou_xiang.png -------------------------------------------------------------------------------- /src/components/toload.vue: -------------------------------------------------------------------------------- 1 | 14 | 24 | 72 | -------------------------------------------------------------------------------- /src/config_router.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 路由配置 3 | */ 4 | 5 | import Live from 'views/live/Live' 6 | import Wonderfuls from 'views/live/Wonderfuls' 7 | import Replays from 'views/live/Replays' 8 | 9 | export function configRouter(router) { 10 | /** 11 | * 路由映射 12 | */ 13 | router.map({ 14 | '/live/:id': {//直播 15 | name: 'live', 16 | title: '直播分享', 17 | component: Live, 18 | subRoutes: { 19 | '/':{ 20 | name: 'wonderfulList', 21 | title: '精彩推荐', 22 | component:Wonderfuls 23 | }, 24 | '/wonderful': {//精彩推荐 25 | name: 'wonderfulList', 26 | title: '精彩推荐', 27 | component: (resolve) => require(['views/live/Wonderfuls'], resolve) //定义为动态组件载入 lazy load//Wonderfuls// 28 | }, 29 | '/replay': {//Ta的回放 30 | name: 'replayList', 31 | title: 'Ta的回放', 32 | component: (resolve) => require(['views/live/Replays'], resolve)//定义为动态组件载入 lazy loadReplays// 33 | } 34 | } 35 | } 36 | }) 37 | 38 | /** 39 | * 重定向规则 40 | */ 41 | router.redirect({ 42 | '/': '/live' 43 | }) 44 | 45 | /** 46 | * For every new route scroll to the top of the page 47 | */ 48 | router.beforeEach(function () { 49 | window.scrollTo(0, 0) 50 | }) 51 | 52 | /** 53 | * document title change 54 | */ 55 | // router.afterEach((transition) => { 56 | // document.title = transition.to.title || '直播分享' 57 | // if (navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)) { 58 | // let src = '/static/fixrouter.html?' + Math.random() 59 | // iframeLoad(src) 60 | // } 61 | // }) 62 | 63 | /** 64 | * fix ios title刷新不了的bug 65 | * @iframeLoad 66 | * @author hiluluke 67 | */ 68 | // const iframeLoad = function (src) { 69 | // let iframe = document.createElement('iframe') 70 | // iframe.style.display = 'none' 71 | // iframe.src = src 72 | // document.body.appendChild(iframe) 73 | // iframe.addEventListener('load', function () { 74 | // setTimeout(function () { 75 | // iframe.remove() 76 | // }, 0) 77 | // }) 78 | // } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/filter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 自定义过滤器 3 | */ 4 | 5 | let myFilter = {} 6 | 7 | myFilter.install = function (Vue) { 8 | /** 9 | * 完整日期时间格式化 10 | */ 11 | Vue.filter('fullDate', val => { 12 | let date = new Date(val) 13 | return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()} 14 | ${date.getHours()}:${date.getMinutes()}` 15 | }) 16 | 17 | /** 18 | * 字符串倒序 19 | * 单向过滤器 20 | */ 21 | Vue.filter('reverse', function (value) { 22 | return value.split('').reverse().join('') 23 | }) 24 | 25 | /** 26 | * 价格格式化 27 | * 双向过滤器 28 | */ 29 | Vue.filter('currencyDisplay', { 30 | // model -> view 31 | // 在更新 `` 元素之前格式化值 32 | read: function (val) { 33 | return '$' + val.toFixed(2) 34 | }, 35 | // view -> model 36 | // 在写回数据之前格式化值 37 | write: function (val, oldVal) { 38 | var number = +val.replace(/[^\d.]/g, '') 39 | return isNaN(number) ? 0 : parseFloat(number.toFixed(2)) 40 | } 41 | }) 42 | 43 | Vue.filter('canvertUrl', function (val) { 44 | if (!val) { 45 | return '/static/img/logo_default_s.jpg' 46 | } 47 | /*else if (/^http/.test(val)) {*/ 48 | return val 49 | /*} 50 | return "//" + val*/ 51 | }) 52 | } 53 | 54 | export default myFilter 55 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueResource from 'vue-resource' 3 | import VueRouter from 'vue-router' 4 | import {configRouter} from './config_router' 5 | import infiniteScroll from 'vue-infinite-scroll' 6 | import filter from './filter' 7 | import App from './App' 8 | 9 | /** 10 | * 注册插件 11 | */ 12 | Vue.use(VueResource)// Ajax数据请求请求 13 | Vue.use(VueRouter)// 路由 14 | Vue.use(infiniteScroll)//无限滚动 https://github.com/ElemeFE/vue-infinite-scroll 15 | Vue.use(filter)//自定义过滤器 16 | 17 | /** 18 | * VueResource配置 19 | */ 20 | //Vue.http.options.xhr = {withCredentials: true} 21 | 22 | /** 23 | * 路由配置 24 | * @type {Router} 25 | */ 26 | Vue.config.debug = true//开启debug模式 27 | var router = new VueRouter({ 28 | //root:'/live', 29 | hashbang: true, 30 | history: false, 31 | saveScrollPosition: true, 32 | suppressTransitionError: false // TODO:开发环境 33 | //suppressTransitionError: true // TODO:生产环境 34 | }) 35 | window.router = router 36 | configRouter(router) 37 | router.start(App, '#app')//路由起始页 38 | 39 | /*new Vue({ 40 | el: 'body', 41 | components: {App} 42 | })*/ 43 | 44 | -------------------------------------------------------------------------------- /src/services/live.js: -------------------------------------------------------------------------------- 1 | /** 2 | * live 3 | * 4 | * @Author: lxbin 5 | * @Date: 2016/9/21 0021 6 | * @Time: 15:28 7 | * Created with JetBrains WebStorm. 8 | */ 9 | 10 | import _wap_config from 'utils/jx/config' 11 | import jx_ajax from 'utils/jx/ajax' 12 | import jx_common from 'utils/jx/common' 13 | import date from 'utils/convert/date' 14 | 15 | export default { 16 | /** 17 | * 获取直播项 18 | * @param id 直播ID 19 | * @example 20 | * getLiveRecord(387) 21 | */ 22 | getLiveRecord(id) { 23 | let promise = jx_ajax.get(_wap_config.api, { 24 | _mt: 'live.getLiveRecord', 25 | liveId: id 26 | }) 27 | return promise 28 | }, 29 | 30 | /** 31 | * 获取直播列表 32 | * @param liveRecordAPIPageQuery 直播列表分页条件查询 33 | * @example 34 | * getLiveList({ 35 | * //userId: _self.video.userId, 36 | * //liveStatus: ["START_LIVE", "REPLAY_LIVE"], 37 | * //locationCityCode: _self.video.locationCityCode, 38 | * pageNo: _self.replayList.pageNo + 1, 39 | * pageSize: _self.replayList.pageSize 40 | * }) 41 | */ 42 | getLiveList(liveRecordAPIPageQuery){ 43 | 44 | }, 45 | 46 | /** 47 | * 获取用户直播列表 48 | * @param liveRecordListQuery 49 | * @example 50 | * getLiveListByUserId({ 51 | * userId: _self.video.userId, 52 | * liveStatus: ["REPLAY_LIVE"], 53 | * pageNo: _self.wonderfulList.pageNo + 1, 54 | * pageSize: _self.wonderfulList.pageSize 55 | * }) 56 | */ 57 | getLiveListByUserId(liveRecordListQuery){ 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/services/sns.js: -------------------------------------------------------------------------------- 1 | /** 2 | * sns 3 | * 4 | * @Author: lxbin 5 | * @Date: 2016/9/21 0021 6 | * @Time: 15:28 7 | * Created with JetBrains WebStorm. 8 | */ 9 | 10 | import _wap_config from 'utils/jx/config' 11 | import jx_ajax from 'utils/jx/ajax' 12 | import jx_common from 'utils/jx/common' 13 | import date from 'utils/convert/date' 14 | 15 | export default { 16 | /** 17 | * 查询我的粉丝、关注、ugc数量 18 | * @param userId 对方用户id 19 | */ 20 | queryUserSnsCountInfo(userId) { 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/utils/convert/date.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 日期格式化 3 | * 4 | * @Author: lxbin 5 | * @Date: 2016/9/20 0020 6 | * @Time: 10:31 7 | * Created with JetBrains WebStorm. 8 | */ 9 | 10 | /** 11 | * ---- 日期格式化 ---- 12 | * 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符, 13 | * 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字) 14 | * @param {DateString} date 被格式化的日期 15 | * @param {String} fmt 转换格式,eg.yyyy-MM-dd 16 | * @return {DateString} fmt 转换后的日期 17 | */ 18 | exports.DateFormat = function (date, fmt) { 19 | date = date.replace(/-/g, '/'); 20 | if (!fmt)fmt = 'yyyy-MM-dd hh:mm:ss'; 21 | var d = new Date(date); 22 | var o = { 23 | "M+": d.getMonth() + 1, //月份 24 | "d+": d.getDate(), //日 25 | "h+": d.getHours(), //小时 26 | "m+": d.getMinutes(), //分 27 | "s+": d.getSeconds(), //秒 28 | "q+": Math.floor((d.getMonth() + 3) / 3), //季度 29 | "S": d.getMilliseconds() //毫秒 30 | }; 31 | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (d.getFullYear() + "").substr(4 - RegExp.$1.length)); 32 | for (var k in o) 33 | if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); 34 | //console.log(d, date, o, fmt); 35 | return fmt; 36 | } 37 | 38 | /** 39 | * ---- 时间戳转换日期 ---- 40 | * http://www.cnblogs.com/yjf512/p/3796229.html 41 | * @param {Int} timestamp 被格式化的时间戳 42 | * @example getLocalTime(1439136000000); 43 | */ 44 | exports.getLocalTime = function (timestamp) { 45 | return new Date(parseInt(timestamp)).toLocaleString().replace(/:\d{1,2}$/, ' '); 46 | } 47 | 48 | /** 49 | * ---- 日期转时间戳 ---- 50 | * http://www.cnblogs.com/yjf512/p/3796229.html 51 | * @param {Object} date 日期字符串 52 | */ 53 | exports.getTimestamp = function (dateStr) { 54 | if (!/^\d{4}[-|\/|年]\d{1,2}[-|\/|月]\d{1,2}日?\s\d{1,2}:\d{1,2}(:\d{1,2})?$/.test(dateStr)) { 55 | return 0; 56 | } 57 | var dateStrArr = dateStr.replace(/[\/|年|月]/g, '-').replace(/日/, "").split((/-|\:|\ /)); 58 | var date = new Date(dateStrArr[0], dateStrArr[1] - 1, dateStrArr[2], dateStrArr[3], dateStrArr[4], dateStrArr[5]); 59 | return Date.parse(date); 60 | } 61 | 62 | /** 63 | * 获取上一个月 64 | * @date 格式为yyyy-mm-dd的日期,如:2014-01-25 65 | */ 66 | exports.getPreMonth = function (date) { 67 | var arr = date.split('-'); 68 | var year = arr[0]; //获取当前日期的年份 69 | var month = arr[1]; //获取当前日期的月份 70 | var day = arr[2]; //获取当前日期的日 71 | var days = new Date(year, month, 0); 72 | days = days.getDate(); //获取当前日期中月的天数 73 | var year2 = year; 74 | var month2 = parseInt(month) - 1; 75 | if (month2 == 0) { 76 | year2 = parseInt(year2) - 1; 77 | month2 = 12; 78 | } 79 | var day2 = day; 80 | var days2 = new Date(year2, month2, 0); 81 | days2 = days2.getDate(); 82 | if (day2 > days2) { 83 | day2 = days2; 84 | } 85 | if (month2 < 10) { 86 | month2 = '0' + month2; 87 | } 88 | var t2 = year2 + '-' + month2 + '-' + day2; 89 | return t2; 90 | } 91 | 92 | /** 93 | * 获取下一个月 94 | * @date 格式为yyyy-mm-dd的日期,如:2014-01-25 95 | */ 96 | exports.getNextMonth = function (date) { 97 | var arr = date.split('-'); 98 | var year = arr[0]; //获取当前日期的年份 99 | var month = arr[1]; //获取当前日期的月份 100 | var day = arr[2]; //获取当前日期的日 101 | var days = new Date(year, month, 0); 102 | days = days.getDate(); //获取当前日期中的月的天数 103 | var year2 = year; 104 | var month2 = parseInt(month) + 1; 105 | if (month2 == 13) { 106 | year2 = parseInt(year2) + 1; 107 | month2 = 1; 108 | } 109 | var day2 = day; 110 | var days2 = new Date(year2, month2, 0); 111 | days2 = days2.getDate(); 112 | if (day2 > days2) { 113 | day2 = days2; 114 | } 115 | if (month2 < 10) { 116 | month2 = '0' + month2; 117 | } 118 | 119 | var t2 = year2 + '-' + month2 + '-' + day2; 120 | return t2; 121 | } 122 | -------------------------------------------------------------------------------- /src/utils/jx/ajax.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jx-ajax 3 | * 首先要引入jQuery.js、md5.js 4 | * @Author: lxbin 5 | * @Date: 2016/9/22 0022 6 | * @Time: 13:51 7 | * Created with JetBrains WebStorm. 8 | */ 9 | 10 | import $ from 'jquery' 11 | import md5 from 'blueimp-md5' 12 | import Cookies from 'js-cookie' 13 | 14 | import _wap_config from './config' 15 | import jx_common from './common' 16 | import jx_common_app from './common-app' 17 | 18 | export default { 19 | post: function (url, obj, successFunc, errorFunc, noLoginCallback) { 20 | const _self = this; 21 | let type = obj.type || "POST"; 22 | return _self.ajax(type, url, obj, successFunc, errorFunc, noLoginCallback); 23 | }, 24 | get: function (url, obj, successFunc, errorFunc, noLoginCallback) { 25 | const _self = this; 26 | return _self.ajax("GET", url, obj, successFunc, errorFunc, noLoginCallback); 27 | }, 28 | ajax: function (type, url, obj, successFunc, errorFunc, noLoginCallback) { 29 | const _self = this; 30 | let _jx_async = obj["async"]; 31 | if (jx_common.isNull(_jx_async)) { 32 | _jx_async = true; 33 | } 34 | let promise = new Promise((resolve, reject)=> { 35 | let _jx_ajax_frame = $.ajax({ 36 | xhrFields: { 37 | withCredentials: true // 38 | }, 39 | crossDomain: true, 40 | type: type, 41 | async: _jx_async, 42 | url: url, 43 | timeout: _wap_config.timeout, 44 | data: _self.encryptRequestParam(obj), 45 | success: function (res) { 46 | if (!res) { 47 | jx_common.tip("api无数据返回"); 48 | //reject() 49 | return; 50 | } 51 | if (res["stat"]["code"] == "-160" || res["stat"]["code"] == "-360") { 52 | if (jx_common.isInJXApp()) { 53 | jx_common.cleanCookie("_wtk"); 54 | jx_common.cleanCookie("_uid"); 55 | } else { 56 | jx_common.cleanCookie("jx_token"); 57 | jx_common.cleanCookie("jx_uid"); 58 | jx_common.cleanCookie("jx_u_phone"); 59 | } 60 | if (noLoginCallback && typeof noLoginCallback == "function") { 61 | noLoginCallback(); 62 | //reject() 63 | return false; 64 | } 65 | if (jx_common.isInJXApp()) { 66 | jx_common_app.openAppLogin(); 67 | } else { 68 | jx_common.tip("token失效重新登录"); 69 | //reject() 70 | window.setTimeout(function () { 71 | jx_common.openUrl("../../view/login/login.html?returnUrl=" + encodeURIComponent(window.location.href)); 72 | }, 1000); 73 | } 74 | return; 75 | } 76 | if (res["stat"]["code"] == "-260") { 77 | jx_common.tip("请输入正确验证码"); 78 | //reject() 79 | return; 80 | } 81 | if (res["stat"]["code"] != 0) { 82 | jx_common.tip("api错误(" + res["stat"]["code"] + ")"); 83 | //reject() 84 | return; 85 | } 86 | if (jx_common.isNull(res["content"])) { 87 | jx_common.tip("无结果数据"); 88 | //reject() 89 | return; 90 | } 91 | let errorEntry = res["stat"]["stateList"][0] 92 | if (errorEntry["code"] == "-100") { 93 | jx_common.tip("服务器开小差!"); 94 | //reject() 95 | return; 96 | } 97 | successFunc && (typeof successFunc == "function") && successFunc(res["content"][0], errorEntry, res["stat"]) 98 | resolve(res["content"][0]) 99 | }, 100 | error: function () { 101 | errorFunc && (typeof errorFunc == "function") && errorFunc(); 102 | jx_common.tip("系统繁忙"); 103 | //reject() 104 | return; 105 | }, 106 | complete: function (XMLHttpRequest, status) { 107 | if (status == 'timeout') { //超时,status还有success,error等值的情况 108 | _jx_ajax_frame.abort(); 109 | jx_common.tip("系统超时"); 110 | //reject() 111 | } 112 | } 113 | }) 114 | }) 115 | return promise 116 | }, 117 | encryptRequestParam: function (options) { 118 | const _self = this, 119 | _params = {}; 120 | let params = {}; 121 | try { 122 | _params._sm = _wap_config.sm; 123 | _params._aid = _self.getAid(); 124 | _params._domid = _wap_config.domid; 125 | _params._ft = _wap_config.ft; 126 | _params._ch = _self.getCh(); 127 | _params._tk = jx_common.getTk(); 128 | _params._uid = jx_common.getUid(); 129 | _params._did = jx_common.getDid(); 130 | _params._dsig = jx_common.getDsig(); 131 | 132 | let s = ""; 133 | let keys = []; 134 | params = $.extend(_params, options); 135 | for (let k in params) { 136 | keys.push(k); 137 | } 138 | keys.sort(); 139 | for (let i = 0; i < keys.length; i++) { 140 | s = s + keys[i] + '=' + params[keys[i]]; 141 | } 142 | s += _wap_config.domainUrl; 143 | params._sig = md5(s); 144 | 145 | return params; 146 | } catch (e) { 147 | jx_common.tip("本地加签错误"); 148 | } 149 | return params; 150 | }, 151 | getCh: function () { 152 | let ch = jx_common.getCookie("jx_ch"); 153 | if (!jx_common.isNull(ch)) { 154 | return ch; 155 | } 156 | if (jx_common.isInJXApp()) { 157 | return _wap_config.ch.jxapp; 158 | } 159 | if (jx_common.isWxbrowser()) { 160 | return _wap_config.ch.weixin; 161 | } 162 | return _wap_config.ch.jxwap; 163 | }, 164 | getAid: function () { 165 | if (jx_common.isInJXApp()) { 166 | return _wap_config.aid.jxapp; 167 | } 168 | if (jx_common.isWxbrowser()) { 169 | return _wap_config.aid.weixin; 170 | } 171 | return _wap_config.aid.wap; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/utils/jx/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * config 3 | * 4 | * @Author: lxbin 5 | * @Date: 2016/9/22 0022 6 | * @Time: 13:59 7 | * Created with JetBrains WebStorm. 8 | */ 9 | 10 | let _wap_config = { 11 | api: "http://api.test.jiuxiulvxing.com/web.api", 12 | domainUrl: "0ce37dd6b927730161a1e559c2336d0a", 13 | imgUrl: "http://img.test.yimayholiday.com/v1/tfs/", 14 | linkUrl: 'http://m.test.jiuxiulvxing.com/', 15 | contpointersApi: 'http://test.log.jiuxiulvxing.com/newlogwithgzip.jsp', 16 | appid: 'wx14e984a0a6863004', 17 | wxcenter: "http://weixin.test.jiuxiulvxing.com/", 18 | yydbUrl: "http://hd.test.jiuxiulvxing.com/yydb", 19 | movieUrl: "http://s0.test.jiuxiulvxing.com/Test/movieticket/view/content/login.html?ch=dstyyy_360zqhd" 20 | }; 21 | let _linkUrl = window.location.href; 22 | 23 | //2套环境 24 | if (_linkUrl.indexOf("m2.test.jiuxiulvxing.com") != -1) { 25 | _wap_config.api = "http://api.secondtest.jiuxiulvxing.com/web.api"; 26 | } 27 | 28 | //预发 29 | if (_linkUrl.indexOf("m.pre.jiuxiulvxing.com") != -1) { 30 | _wap_config = { 31 | api: "http://api.pre.jiuxiulvxing.com/web.api", 32 | domainUrl: "0ce37dd6b927730161a1e559c2336d0a", 33 | imgUrl: "http://img.yimayholiday.com/v1/tfs/", 34 | linkUrl: 'http://m.pre.jiuxiulvxing.com/', 35 | contpointersApi: 'http://log.jiuxiulvxing.com/newlogwithgzip.jsp', 36 | appid: 'wx14e984a0a6863004', 37 | wxcenter: "http://wxapi.pre.jiuxiulvxing.com/", 38 | yydbUrl: "http://m.pre.jiuxiulvxing.com/view/listpage/listpage.html?code=JIUXIU_WAP_HOME_YY_2&title=" + encodeURIComponent("冰点特惠旅行"), 39 | movieUrl: "http://mt.hd.pre.jiuxiulvxing.com/view/content/login.html?ch=dstyyy_360zqhd" 40 | } 41 | } 42 | 43 | //线上 44 | if (_linkUrl.indexOf("m.jiuxiulvxing.com") != -1 45 | || _linkUrl.indexOf("m.hb.jiuxiulvxing.com") != -1 46 | || _linkUrl.indexOf("m.9xiulvxing.com") != -1 47 | || _linkUrl.indexOf("app.jiuxiulvxing.com") != -1) { 48 | _wap_config = { 49 | api: "http://api.jiuxiulvxing.com/web.api", 50 | domainUrl: "0ce37dd6b927730161a1e559c2336d0a", 51 | imgUrl: "http://img.yimayholiday.com/v1/tfs/", 52 | linkUrl: 'http://m.jiuxiulvxing.com/', 53 | contpointersApi: 'http://log.jiuxiulvxing.com/newlogwithgzip.jsp', 54 | appid: 'wx1deb965a51860f61', 55 | wxcenter: "http://wxapi.jiuxiulvxing.com/", 56 | yydbUrl: "http://m.jiuxiulvxing.com/view/listpage/listpage.html?code=JIUXIU_WAP_HOME_YY_2&title=" + encodeURIComponent("冰点特惠旅行"), 57 | movieUrl: "http://mt.hd.jiuxiulvxing.com/view/content/login.html?ch=dstyyy_360zqhd" 58 | } 59 | } 60 | 61 | //性能测试 62 | if (_linkUrl.indexOf("m.xntest.jiuxiulvxing.com") != -1) { 63 | _wap_config = { 64 | api: "http://api.stest.jiuxiulvxing.com/web.api", 65 | domainUrl: "0ce37dd6b927730161a1e559c2336d0a", 66 | imgUrl: "http://img.test.yimayholiday.com/v1/tfs/", 67 | linkUrl: 'http://m.xntest.jiuxiulvxing.com/', 68 | contpointersApi: 'http://test.data.jiuxiulvxing.com/newlogwithgzip.jsp', 69 | appid: 'wx14e984a0a6863004', 70 | wxcenter: "http://weixin.test.jiuxiulvxing.com/" 71 | } 72 | } 73 | 74 | //公共参数 75 | _wap_config.sm = "md5"; 76 | //_wap_config.aid = "23"; 77 | //_wap_config.aid_wx = "25"; 78 | _wap_config.aid = { 79 | wap: "23", 80 | weixin: "25", 81 | jxapp: "28" 82 | }; 83 | _wap_config.domid = "1200"; 84 | _wap_config.ft = "json"; 85 | _wap_config.ch = { 86 | jxwap: "jxwap", 87 | weixin: "weixin", 88 | jxapp: "jxapp" 89 | }; 90 | _wap_config.timeout = "3000"; 91 | 92 | export default _wap_config 93 | -------------------------------------------------------------------------------- /src/utils/jx/contpointer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * contpointer 3 | * 4 | * @Author: lxbin 5 | * @Date: 2016/9/22 0022 6 | * @Time: 14:39 7 | * Created with JetBrains WebStorm. 8 | */ 9 | ;(function($){ 10 | $.extend({ 11 | //action_name动作编码 12 | //action_params可变参数,例如{'pid':'122012','pname':'蔬菜'}。具体的根据文档规定传,action_name不同action_params也会不同。 13 | monitors:function(url,action_and_params,app_id,domain_id,userid,channelCode,activity_info){ 14 | let stamps=new Date().getTime(),auto_params=[]; 15 | for(let key in action_and_params){ 16 | let obj={ 17 | "2001": key, 18 | "2002": "", 19 | "2003": stamps, 20 | "2004": action_and_params[key], 21 | "2005": "", 22 | "2006": userid, 23 | "2007": "", 24 | "2008": activity_info 25 | }; 26 | auto_params.push(obj); 27 | } 28 | 29 | config={ 30 | "1001": "九休旅行", 31 | "1002": app_id, 32 | "1003": "", 33 | "1004": "", 34 | "1005": "", 35 | "1006": "", 36 | "1007": "", 37 | "1008": this.ck_system(), 38 | "1009": this.ios_or_android(), 39 | "1010": "", 40 | "1011": channelCode, 41 | "1012": "", 42 | "1013": "", 43 | "1014": this.ck_browser(), 44 | "1015": "", 45 | "1016": "", 46 | "1017": auto_params, 47 | "1018": domain_id 48 | }; 49 | $.ajax({ 50 | dataType : "jsonp", 51 | url: url,//记录数据请求地址 52 | data: {msg:encodeURI(JSON.stringify(config))} 53 | }); 54 | }, 55 | ck_system:function() { 56 | let bIsAndroid = navigator.userAgent.match(/android/i) == "android",isIphone = (navigator.platform.toLowerCase() == "iphone") ; 57 | if (isIphone||bIsAndroid) return "MOBILE"; 58 | let isWin = (navigator.platform.toLowerCase() == "win32") || (navigator.platform.toLowerCase() == "windows"); 59 | let isMac = (navigator.platform.toLowerCase() == "mac68k") || (navigator.platform.toLowerCase() == "macppc") 60 | || (navigator.platform.toLowerCase() == "macintosh") || (navigator.platform.toLowerCase() == "macintel"); 61 | let isUnix = (navigator.platform.toLowerCase() == "x11") && !isWin && !isMac; 62 | let isLinux = (String(navigator.platform.toLowerCase()).indexOf("linux") > -1); 63 | if (isWin||isMac||isUnix||isLinux) return "PC"; 64 | return "PAD"; 65 | }, 66 | ios_or_android:function() { 67 | let isIphone = (navigator.platform.toLowerCase() == "iphone") ; 68 | if (isIphone) return "ios"; 69 | let bIsAndroid = (navigator.platform.toLowerCase() == "android"); 70 | if(bIsAndroid) return "android"; 71 | return ''; 72 | }, 73 | ck_browser:function(){ 74 | let userAgent = navigator.userAgent.toLowerCase(); 75 | let isOpera = userAgent.indexOf("opera") > -1; 76 | if (isOpera) { 77 | return "Opera浏览器" 78 | } 79 | if (userAgent.indexOf("firefox") > -1) { 80 | return "Firefox浏览器"; 81 | } 82 | if (userAgent.indexOf("chrome") > -1){ 83 | return "Chrome浏览器"; 84 | } 85 | if (userAgent.indexOf("safari") > -1) { 86 | return "Safari浏览器"; 87 | } 88 | if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("msie") > -1 && !isOpera) { 89 | return "IE浏览器"; 90 | } 91 | if(userAgent.indexOf("micromessenger") > -1) { 92 | return "微信内嵌浏览器"; 93 | } 94 | if(userAgent.indexOf(" qq") > -1) { 95 | return "QQ内嵌浏览器"; 96 | } 97 | } 98 | }); 99 | })(jQuery); 100 | 101 | /*$(function(){ 102 | //monitors函数,具体调用的例子。 103 | //$.monitors('Submit_Order',{'pid':'122012','pname':'蔬菜'}); 104 | $.monitors("http://test.data.jiuxiulvxing.com/newlogwithgzip.jsp",{ 105 | 'pv_uv':{'pid':'122012','pname':'蔬菜'} 106 | },"23","1200"); 107 | });*/ 108 | 109 | -------------------------------------------------------------------------------- /src/utils/jx/h5cache.js: -------------------------------------------------------------------------------- 1 | /** 2 | * h5cache 3 | * 需要md5加密 4 | * 支持单页面上缓存存储 5 | * 6 | * @Author: lxbin 7 | * @Date: 2016/9/22 0022 8 | * @Time: 14:47 9 | * Created with JetBrains WebStorm. 10 | */ 11 | 12 | import md5 from 'blueimp-md5' 13 | 14 | export default { 15 | setCache: function (key, value, timeout) { 16 | let _self = this; 17 | if (!window.localStorage) { 18 | return false; 19 | } 20 | _self.getStorageHref(key); 21 | window.localStorage.setItem(key, value); 22 | let timeoutKey = key + "_timeout"; 23 | if (timeout) { 24 | window.localStorage.setItem(timeoutKey, (new Date()).getTime() + (timeout * 1000)); 25 | } else { 26 | window.localStorage.setItem(timeoutKey, -1); 27 | } 28 | }, 29 | getCache: function (key) { 30 | let _self = this; 31 | if (!window.localStorage) { 32 | return ""; 33 | } 34 | _self.getStorageHref(key); 35 | let timeoutKey = key + "_timeout"; 36 | let timeout = window.localStorage.getItem(timeoutKey); 37 | if (!timeout || "" == timeout) { 38 | return ""; 39 | } 40 | if (timeout == -1 || timeout > (new Date()).getTime()) { 41 | return window.localStorage.getItem(key); 42 | } 43 | window.localStorage.setItem(key, ""); 44 | return ""; 45 | }, 46 | delCache: function (key) { 47 | let _self = this; 48 | if (!window.localStorage) { 49 | return ""; 50 | } 51 | _self.getStorageHref(key); 52 | window.localStorage.removeItem(key); 53 | window.localStorage.removeItem(key + '_timeout'); 54 | }, 55 | getStorageHref: function (key) { 56 | if (localStorage.locationHref) { 57 | key = md5(localStorage.locationHref) + "_" + key; 58 | } else { 59 | key = md5(window.location.href) + "_" + key; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/utils/jx/log.js: -------------------------------------------------------------------------------- 1 | /** 2 | * log 3 | * 4 | * @Author: lxbin 5 | * @Date: 2016/9/22 0022 6 | * @Time: 14:50 7 | * Created with JetBrains WebStorm. 8 | */ 9 | 10 | import _wap_config from './config' 11 | import jx_common from './common' 12 | import jx_ajax from './ajax' 13 | 14 | export default { 15 | monitors: function (action_and_params, activity_info) { 16 | let auto_params = []; 17 | for (let key in action_and_params) { 18 | let obj = { 19 | "2001": key, 20 | "2002": "", 21 | "2003": (new Date()).getTime(), 22 | "2004": action_and_params[key], 23 | "2005": "", 24 | "2006": "", 25 | "2007": "", 26 | "2008": activity_info ? activity_info : "" 27 | }; 28 | auto_params.push(obj); 29 | } 30 | 31 | let config = { 32 | "1001": "九休旅行", 33 | "1002": jx_ajax.getAid(), 34 | "1003": "", 35 | "1004": "", 36 | "1005": "", 37 | "1006": "", 38 | "1007": "", 39 | "1008": this.ck_system(), 40 | "1009": jx_common.isIOS() ? "ios" : "android", 41 | "1010": "", 42 | "1011": jx_ajax.getCh(), 43 | "1012": "", 44 | "1013": "", 45 | "1014": this.ck_browser(), 46 | "1015": "", 47 | "1016": "", 48 | "1017": auto_params, 49 | "1018": _wap_config.domid 50 | }; 51 | $.ajax({ 52 | dataType: "jsonp", 53 | url: _wap_config.contpointersApi,//记录数据请求地址 54 | data: {msg: encodeURIComponent(JSON.stringify(config))} 55 | }); 56 | /*if($("#jx-app-hidden-div-log").size() > 0){ 57 | $("#jx-app-hidden-div-log").remove(); 58 | } 59 | $("body").append("
") 60 | let hidden = document.getElementById("jx-app-hidden-div-log"); 61 | let iframe = document.createElement("iframe"); 62 | iframe.src = _wap_config.contpointersApi+"?msg="+encodeURIComponent(JSON.stringify(config)); 63 | iframe.style.display = "none"; 64 | hidden.appendChild(iframe);*/ 65 | }, 66 | ck_system: function () { 67 | let bIsAndroid = navigator.userAgent.match(/android/i) == "android", isIphone = (navigator.platform.toLowerCase() == "iphone"); 68 | if (isIphone || bIsAndroid) return "MOBILE"; 69 | let isWin = (navigator.platform.toLowerCase() == "win32") || (navigator.platform.toLowerCase() == "windows"); 70 | let isMac = (navigator.platform.toLowerCase() == "mac68k") || (navigator.platform.toLowerCase() == "macppc") 71 | || (navigator.platform.toLowerCase() == "macintosh") || (navigator.platform.toLowerCase() == "macintel"); 72 | let isUnix = (navigator.platform.toLowerCase() == "x11") && !isWin && !isMac; 73 | let isLinux = (String(navigator.platform.toLowerCase()).indexOf("linux") > -1); 74 | if (isWin || isMac || isUnix || isLinux) return "PC"; 75 | return "PAD"; 76 | }, 77 | ck_browser: function () { 78 | let userAgent = navigator.userAgent.toLowerCase(); 79 | let isOpera = userAgent.indexOf("opera") > -1; 80 | if (isOpera) { 81 | return "Opera浏览器" 82 | } 83 | if (userAgent.indexOf("firefox") > -1) { 84 | return "Firefox浏览器"; 85 | } 86 | if (userAgent.indexOf("chrome") > -1) { 87 | return "Chrome浏览器"; 88 | } 89 | if (userAgent.indexOf("safari") > -1) { 90 | return "Safari浏览器"; 91 | } 92 | if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("msie") > -1 && !isOpera) { 93 | return "IE浏览器"; 94 | } 95 | if (userAgent.indexOf("micromessenger") > -1) { 96 | return "微信内嵌浏览器"; 97 | } 98 | if (userAgent.indexOf(" qq") > -1) { 99 | return "QQ内嵌浏览器"; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/views/live/Replays.vue: -------------------------------------------------------------------------------- 1 | 40 | 56 | 59 | -------------------------------------------------------------------------------- /src/views/live/Wonderfuls.vue: -------------------------------------------------------------------------------- 1 | 40 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/vuex/actions.js: -------------------------------------------------------------------------------- 1 | // import * as types from './mutation-types' 2 | // export const setToken = ({ dispatch }, token) => { 3 | // dispatch(types.SET_TOKEN, token) 4 | // } 5 | 6 | /** 7 | * 用统一的函数处理并分发mutations。 8 | * @param type 9 | * @returns {function({dispatch: *}, ...[*]): *} 10 | */ 11 | function makeAction (type) { 12 | return ({ dispatch }, ...args) => dispatch(type, ...args) 13 | } 14 | 15 | /** 16 | * live actions 17 | */ 18 | export const setVideoInfo = makeAction('SET_VIDEO_INFO') 19 | export const setSnsInfo = makeAction('SET_SNS_INFO') 20 | export const addWonderfullList = makeAction('ADD_WONDERFULL_LIST') 21 | export const removeWonderfullList = makeAction('REMOVE_WONDERFULL_LIST') 22 | export const addReplayList = makeAction('ADD_REPLAY_LIST') 23 | export const removeReplayList = makeAction('REMOVE_REPLAY_LIST') 24 | -------------------------------------------------------------------------------- /src/vuex/modules/live.js: -------------------------------------------------------------------------------- 1 | // 该模块的初始状态 2 | const state = { 3 | //直播相关信息 4 | video: { 5 | /** 6 | * live 7 | */ 8 | liveId: 0, //直播ID 9 | userId: 0, //用户ID 10 | roomId: 0, //直播间ID 11 | liveCategoryCode: 0, //直播类别code 12 | liveCategoryName: "", //直播类别name 13 | liveTitle: "", //直播标题 14 | liveCover: "", //直播封面 15 | liveStatus: "", //直播状态:直播、结束、回放 16 | locationCityCode: "", //城市code 17 | locationCityName: "", //城市名称 18 | startDate: 0, //开始时间 19 | endDate: 0, //结束时间 20 | onlineCount: 0, //在线人数 21 | viewCount: 0, //观看次数 22 | replayUrls: [], //回放地址 23 | pushStreamUrl: "", //拉流地址 24 | pullStreamUrl: "", //推流地址 25 | userInfo: {}, //用户信息 26 | liveConfig: {}, //直播配置 27 | /** 28 | * snscenter 29 | */ 30 | followingCount: 0, //关注数量 31 | fansCount: 0, //粉丝数量 32 | ugcCount: 0 //UGC数量 33 | }, 34 | //精彩推荐 35 | wonderfulList: { 36 | pageNo: 0, // 第几页 37 | pageSize: 6, // 一页多少 38 | totalCount: 0, // 共多少条 39 | hasNext: true, // 是否有下一页 40 | list: [] 41 | }, 42 | //Ta的回放 43 | replayList: { 44 | pageNo: 0, // 第几页 45 | pageSize: 6, // 一页多少 46 | totalCount: 0, // 共多少条 47 | hasNext: true, // 是否有下一页 48 | list: [] 49 | } 50 | } 51 | 52 | //导入mutation改变状态 53 | // import { 54 | // SET_VIDEO_INFO, 55 | // ADD_WONDERFULL_LIST, 56 | // REMOVE_WONDERFULL_LIST, 57 | // ADD_REPLAY_LIST, 58 | // REMOVE_REPLAY_LIST 59 | // } from '../mutation-types' 60 | const SET_VIDEO_INFO = 'SET_VIDEO_INFO' 61 | const SET_SNS_INFO = 'SET_SNS_INFO' 62 | const ADD_WONDERFULL_LIST = 'ADD_WONDERFULL_LIST' 63 | const REMOVE_WONDERFULL_LIST = 'REMOVE_WONDERFULL_LIST' 64 | const ADD_REPLAY_LIST = 'ADD_REPLAY_LIST' 65 | const REMOVE_REPLAY_LIST = 'REMOVE_REPLAY_LIST' 66 | 67 | // 相关的 mutations 68 | const mutations = { 69 | //添加video信息 70 | [SET_VIDEO_INFO](state, videoInfo) { 71 | console.log('[Leo]video info => ', videoInfo) 72 | state.video.liveId = videoInfo.liveId; //直播ID 73 | state.video.roomId = videoInfo.roomId; //直播间ID 74 | state.video.liveCategoryCode = videoInfo.liveCategoryCode; //直播类别code 75 | state.video.liveCategoryName = videoInfo.liveCategoryName; //直播类别name 76 | state.video.liveTitle = videoInfo.liveTitle; //直播标题 77 | state.video.liveCover = videoInfo.liveCover; //直播封面 78 | state.video.liveStatus = videoInfo.liveStatus; //直播状态:直播、结束、回放 79 | state.video.locationCityCode = videoInfo.locationCityCode; //城市code 80 | state.video.locationCityName = videoInfo.locationCityName; //城市名称 81 | state.video.startDate = videoInfo.startDate; //开始时间 82 | state.video.endDate = videoInfo.endDate; //结束时间 83 | state.video.onlineCount = videoInfo.onlineCount; //在线人数 84 | state.video.viewCount = videoInfo.viewCount; //观看次数 85 | 86 | state.video.replayUrls.length>0 && state.video.replayUrls.splice(0, state.video.replayUrls.length) 87 | if (videoInfo.replayUrls && videoInfo.replayUrls.length) {//回放地址 88 | for (let url of videoInfo.replayUrls) state.video.replayUrls.push(url) 89 | } 90 | 91 | state.video.pushStreamUrl = videoInfo.pushStreamUrl; //拉流地址 92 | state.video.pullStreamUrl = videoInfo.pullStreamUrl; //推流地址 93 | state.video.userInfo = videoInfo.userInfo || {}; //用户信息 94 | state.video.liveConfig = videoInfo.liveConfig || {}; //直播配置 95 | }, 96 | //添加SNS信息 97 | [SET_SNS_INFO](state, snsInfo) { 98 | state.video.followingCount = snsInfo.followingCount 99 | state.video.fansCount = snsInfo.fansCount 100 | state.video.ugcCount = snsInfo.ugcCount 101 | }, 102 | //添加“精选推荐”列表项 103 | [ADD_WONDERFULL_LIST](state, wonderfuls) { 104 | state.wonderfulList.pageNo = wonderfuls.pageNo 105 | state.wonderfulList.pageSize = wonderfuls.pageSize 106 | state.wonderfulList.totalCount = wonderfuls.totalCount 107 | state.wonderfulList.hasNext = wonderfuls.hasNext 108 | 109 | let list = wonderfuls.list 110 | for (var key in list) { 111 | if (state.wonderfulList.list.hasOwnProperty(key)) 112 | continue 113 | state.wonderfulList.list.push(list[key]) 114 | } 115 | }, 116 | //移除“精选推荐”列表项 117 | [REMOVE_WONDERFULL_LIST](state) { 118 | if (state.wonderfulList.list) { 119 | state.wonderfulList.list = [] 120 | } 121 | }, 122 | //添加“Ta的回放”列表项 123 | [ADD_REPLAY_LIST](state, replays) { 124 | state.replayList.pageNo = replays.pageNo 125 | state.replayList.pageSize = replays.pageSize 126 | state.replayList.totalCount = replays.totalCount 127 | state.replayList.hasNext = replays.hasNext 128 | 129 | let list = replays.list 130 | for (var key in list) { 131 | if (state.replayList.list.hasOwnProperty(key)) 132 | continue 133 | state.replayList.list.push(list[key]) 134 | } 135 | }, 136 | //移除“Ta的回放”列表项 137 | [REMOVE_REPLAY_LIST](state) { 138 | if (state.replayList.list) { 139 | state.replayList.list = [] 140 | } 141 | } 142 | } 143 | 144 | export default { 145 | state, 146 | mutations 147 | } 148 | -------------------------------------------------------------------------------- /src/vuex/mutation-types.js: -------------------------------------------------------------------------------- 1 | // export const SET_VIDEO_INFO = 'SET_VIDEO_INFO' 2 | // export const ADD_WONDERFULL_LIST = 'ADD_WONDERFULL_LIST' 3 | // export const REMOVE_WONDERFULL_LIST = 'REMOVE_WONDERFULL_LIST' 4 | // export const ADD_REPLAY_LIST = 'ADD_REPLAY_LIST' 5 | // export const REMOVE_REPLAY_LIST = 'REMOVE_REPLAY_LIST' -------------------------------------------------------------------------------- /src/vuex/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | // 导入各个模块的初始状态和 mutations 7 | import live from './modules/live' 8 | export default new Vuex.Store({ 9 | // 组合各个模块 10 | modules: { 11 | live 12 | } 13 | }) -------------------------------------------------------------------------------- /static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/static/.gitkeep -------------------------------------------------------------------------------- /static/Img/jx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/static/Img/jx.png -------------------------------------------------------------------------------- /static/Img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/static/Img/logo.png -------------------------------------------------------------------------------- /static/Img/logo_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/static/Img/logo_default.png -------------------------------------------------------------------------------- /static/Img/logo_default_s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/static/Img/logo_default_s.jpg -------------------------------------------------------------------------------- /static/Img/tou_xiang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/static/Img/tou_xiang.png -------------------------------------------------------------------------------- /static/base.css: -------------------------------------------------------------------------------- 1 | @CHARSET "utf-8"; 2 | /* 3 | * @Author: Meta 4 | * @Date: 2016-04-28 17:40:41 5 | * @Last Modified by: liuyuanyuan 6 | * @Last Modified time: 2016-07-25 18:23:30 7 | */ 8 | *{ 9 | margin:0;padding:0; 10 | -webkit-tap-highlight-color:rgba(0,0,0,0); 11 | -webkit-text-size-adjust:100%; 12 | -webkit-user-select:none; 13 | font-weight:normal; 14 | font-style:normal; 15 | box-sizing:border-box; 16 | -webkit-box-sizing:border-box; /* Safari */ 17 | -moz-box-sizing:border-box; /* Firefox */ 18 | -ms-text-size-adjust: 100%; 19 | -ms-user-select:none; 20 | user-select:none; 21 | -webkit-overflow-scrolling: touch; 22 | } 23 | ::-webkit-search-cancel-button { display: none;} 24 | html{font:20px/1.25'微软雅黑',Arial,sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;} 25 | body,p,form,input,button,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6{margin:0;padding:0;overflow-x:hidden;} 26 | h1,h2,h3,h4,h5,h6{font-size:100%;} 27 | input,textarea,select{-webkit-user-select:text;-ms-user-select:text;user-select:text;-webkit-appearance:none;} 28 | textarea{resize:none;} 29 | table{border-collapse:collapse;} 30 | input,select,textarea{outline:none;border:none;background:none;font-size:0.7rem;font-family:"微软雅黑"} 31 | a{text-decoration:none;-WebKit-touch-callout:none;outline:0;cursor:pointer;color:#666;} 32 | em,i{font-style:normal;} 33 | li,ol{list-style:none;} 34 | .clearfix{*zoom:1;} 35 | .clearfix:after{display:block;overflow:hidden;clear:both;height:0;visibility:hidden;content:".";} 36 | body{margin:0 auto;width:100%;background-color:#f4f4f4;color:#666;font-size:0.7rem;} 37 | img{border:none;width:100%;vertical-align:top;} 38 | ::-webkit-scrollbar{width: 0;height: 0;} 39 | ::-webkit-scrollbar-track {background-color: transparent;} /* 滚动条的滑轨背景颜色 */ 40 | ::-webkit-scrollbar-thumb {background-color: transparent;} /* 滑块颜色 */ 41 | ::-webkit-scrollbar-button {background-color: transparent;} /* 滑轨两头的监听按钮颜色 */ 42 | ::-webkit-scrollbar-corner {background-color: transparent;} /* 横向滚动条和纵向滚动条相交处尖角的颜色 */ 43 | /*公共样式*/ 44 | .fl{float:left;} 45 | .fr{float:right;} 46 | .txtalign-l{text-align: left !important;} 47 | .txtalign-c{text-align: center !important;} 48 | .txtalign-r{text-align: right !important;} 49 | .m-top{margin-top: 1rem!important;} 50 | .bg-fff{background-color:#fff;} 51 | .s-m-top{margin-top: 0.5rem!important;} 52 | .m-r{margin-right:1rem!important;} 53 | .s-m-r{margin-right:0.5rem!important;} 54 | .line-top{border-top: 1px solid #E1E1E1;} 55 | .line-bottom{border-bottom: 1px solid #E1E1E1;} 56 | .hide{display:none;} 57 | .show{display:block;} 58 | .text{font-size:0.6rem!important;} 59 | .red{color:#fa4619!important;} 60 | 61 | .dest_header{width: 100%;height:2.2rem;line-height: 2.2rem;background-color: #FFAF00;font-weight: normal;font-size: 0.75rem;position: relative;color:#000;} 62 | .icon_arrow_l,.icon_arrow_b,.icon_arrow_c{width: 2.2rem;height: 2.2rem;background-position: 0 0;position: absolute;top: 0.05rem;left: 0;-webkit-background-size: 100%;background-size: 100%;background-image: url('../../img/back.png');} 63 | .dest_header > .submit-btn{position:absolute;padding:0 0.75rem;font-size:0.8;right:0;top:0} 64 | .righthide{position:absolute;left:0;width:100%;top:0;bottom:0;right:0;overflow:hidden;background:#f4f4f4;transform:translate(100%,0px) translateZ(0);z-index:999;} 65 | .righthide .wrap{padding-bottom:2.4rem;transform: translate(0px, 0px) translateZ(0);} 66 | .no-data-img {position: absolute;left: 50%;top: 50%;margin-top: -2rem;margin-left: -1.75rem;width: 3.5rem;height: 3.5rem;} 67 | .no-data-desc {position: absolute;top: 50%;width: 100%;text-align: center;margin-top: 2rem;} 68 | .jx-tip{display:none;position:fixed;bottom:2rem;font-size:0.7rem;line-height:2;background:rgba(0,0,0,0.8);color:#fff;border-radius:0.2rem;padding:0.4rem 0.6rem;z-index:9999;} 69 | /*alert*/ 70 | #pagemask{display:none;position:absolute;background:rgba(0,0,0,0.8);left:0;top:0;bottom:0;right:0;z-index:9998;} 71 | #model-box {background:rgba(0,0,0,0.3);position: fixed;top:0; left: 0; right: 0; bottom: 0;z-index: 9998 } 72 | #model-box .model-main { width: 14rem; height: auto; background: #fff; border: 1px solid #ccc; box-shadow: 1px 2px 3px #999;position: absolute; top:0; left: 0; } 73 | #model-box .model-main .content { padding: 1rem; padding-bottom: 0; line-height:2;text-align: center; font-size: 0.8rem; color: #222} 74 | #model-box .model-main .confirm { text-align: center; margin: 1rem; } 75 | #model-box .model-main button { width: 4rem; text-align: center; background: #ffaf00; border: none; padding: 0.4rem; margin: 0 0.5rem;} 76 | #page-package{position:absolute;left:0;top:0;bottom:0;right:0;overflow:hidden;background:#f4f4f4;z-index:1001;} 77 | #page-package .wrap, 78 | #page-orderpay .wrap{padding-bottom: 2.4rem;} 79 | #page-calendar .wrap{padding-bottom:0;} 80 | #page-addVisitor { z-index:999} 81 | 82 | .page-in{-webkit-transition: -webkit-transform 400ms;-webkit-transform: translate3d(0,0,0);} 83 | .page-left-out{-webkit-transition:-webkit-transform 400ms;-webkit-transform: translate3d(-100%,0,0);} 84 | .page-right-out{-webkit-transition:-webkit-transform 400ms;-webkit-transform: translate3d(100%,0,0);} 85 | 86 | 87 | /* 使用浏览器打开 */ 88 | .openBrowser { position: absolute; z-index: 9999999; background: #363636 url(../../img/springboard.jpg) 0 0 no-repeat; top: 0; left: 0; right: 0; bottom: 0; -webkit-background-size: 100%; 89 | background-size: 100%; } 90 | /*顶部logo打开下载app*/ 91 | .download_mask{ 92 | position: fixed; 93 | top:0; 94 | width: 100%; 95 | height: 2.5rem; 96 | background-color: rgba(0,0,0,0.65); 97 | padding:0.4rem 0.75rem; 98 | z-index: 999999; 99 | display: none; 100 | } 101 | .download_masks { height: 2.5rem; } 102 | /*-------提示下载部分-------------*/ 103 | .download_mask .logo{ 104 | width: 4.8rem; 105 | border-radius: 0.2rem; 106 | } 107 | .download_btn{ 108 | position: absolute; 109 | right:0.75rem; 110 | top:0.6rem; 111 | width: 3rem; 112 | height:1.4rem; 113 | line-height: 1.4rem; 114 | border-radius: 0.2rem; 115 | border: 1px solid #fff; 116 | text-align:center; 117 | } 118 | .download_btn a{ 119 | display: block; 120 | width: 100%; 121 | height: 100%; 122 | color:#fff; 123 | font-size: 0.55rem; 124 | } 125 | 126 | /*下载二*/ 127 | .show-go-download-div{ 128 | position: fixed; 129 | top: 0rem; 130 | width: 100%; 131 | height: 100%; 132 | padding: 0 0.5rem; 133 | background: rgba(0,0,0,0.3); 134 | text-align: center; 135 | padding-top:6rem ; 136 | padding-left: 2rem; 137 | padding-right: 2rem; 138 | z-index: 999; 139 | display: none; 140 | } 141 | .show-go-download{ 142 | border-radius: 0.3rem; 143 | background: url('../../img/show-download-bg.png') no-repeat center center; 144 | background-size: 100%; 145 | height: 16.3rem; 146 | } 147 | .go-pic{ 148 | height: 7.5rem; 149 | } 150 | .go-desc{ 151 | text-align: center; 152 | font-size: 0.8rem; 153 | margin-bottom: 1.5rem; 154 | margin-top: 1.5rem; 155 | color: #000; 156 | } 157 | .go-btn{ 158 | text-align: center; 159 | margin-top: 0.3rem; 160 | margin-bottom: 0.3rem; 161 | height: 3.5rem; 162 | } 163 | .go-pic-close{ 164 | width: 0.8rem; 165 | height: 0.8rem; 166 | float: right; 167 | margin-top:0.2rem; 168 | margin-right: 1.05rem; 169 | } 170 | /*-------------------------------------------------------------*/ 171 | @media screen and (min-width: 320px) {html{font-size:106.6666%;}} 172 | @media screen and (min-width: 360px) {html{font-size:120%;}} 173 | @media screen and (min-width: 375px) {html{font-size:125%;}} 174 | @media screen and (min-width: 400px) {html{font-size:133.3333%;}} 175 | @media screen and (min-width: 414px) {html{font-size:138%;}} 176 | @media screen and (min-width: 440px) {html{font-size:146.6666%;}} 177 | @media screen and (min-width: 480px) {html{font-size:160%;}} 178 | @media screen and (min-width: 520px) {html{font-size:173.3333%;}} 179 | @media screen and (min-width: 560px) {html{font-size:186.6666%;}} 180 | @media screen and (min-width: 600px) {html{font-size:200%;}} 181 | @media screen and (min-width: 640px) {html{font-size:213.3333%;}} 182 | @media screen and (min-width: 680px) {html{font-size:226.6666%;}} 183 | @media screen and (min-width: 720px) {html{font-size:240%;}} 184 | @media screen and (min-width: 760px) {html{font-size:253.3333%;}} 185 | @media screen and (min-width: 800px) {html{font-size:266.6666%;}} 186 | @media screen and (min-width: 1200px) {html{font-size:400%;}} 187 | @media screen and (min-width: 1280px) {html{font-size:426.6666%;}} 188 | 189 | 190 | -------------------------------------------------------------------------------- /static/common/jx-ajax.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jx-ajax 3 | * 首先要引入jQuery.js、md5.js 4 | * author:zhangjianfeng 5 | * date:2016-05-07 6 | */ 7 | const $ = require('jquery'); 8 | const md5 = require('blueimp-md5'); 9 | const jx_common = require('./jx-common'); 10 | 11 | var _wap_config = { 12 | api: "http://api.test.jiuxiulvxing.com/web.api", 13 | domainUrl: "0ce37dd6b927730161a1e559c2336d0a", 14 | imgUrl: "http://img.test.yimayholiday.com/v1/tfs/", 15 | linkUrl: 'http://m.test.jiuxiulvxing.com/', 16 | contpointersApi: 'http://test.log.jiuxiulvxing.com/newlogwithgzip.jsp', 17 | appid: 'wx14e984a0a6863004', 18 | wxcenter: "http://weixin.test.jiuxiulvxing.com/", 19 | yydbUrl: "http://hd.test.jiuxiulvxing.com/yydb", 20 | movieUrl: "http://s0.test.jiuxiulvxing.com/Test/movieticket/view/content/login.html?ch=dstyyy_360zqhd" 21 | }; 22 | var _linkUrl = window.location.href; 23 | 24 | //2套环境 25 | if (_linkUrl.indexOf("m2.test.jiuxiulvxing.com") != -1) { 26 | _wap_config.api = "http://api.secondtest.jiuxiulvxing.com/web.api"; 27 | } 28 | 29 | //预发 30 | if (_linkUrl.indexOf("m.pre.jiuxiulvxing.com") != -1) { 31 | _wap_config = { 32 | api: "http://api.pre.jiuxiulvxing.com/web.api", 33 | domainUrl: "0ce37dd6b927730161a1e559c2336d0a", 34 | imgUrl: "http://img.yimayholiday.com/v1/tfs/", 35 | linkUrl: 'http://m.pre.jiuxiulvxing.com/', 36 | contpointersApi: 'http://log.jiuxiulvxing.com/newlogwithgzip.jsp', 37 | appid: 'wx14e984a0a6863004', 38 | wxcenter: "http://wxapi.pre.jiuxiulvxing.com/", 39 | yydbUrl: "http://m.pre.jiuxiulvxing.com/view/listpage/listpage.html?code=JIUXIU_WAP_HOME_YY_2&title=" + encodeURIComponent("冰点特惠旅行"), 40 | movieUrl: "http://mt.hd.pre.jiuxiulvxing.com/view/content/login.html?ch=dstyyy_360zqhd" 41 | } 42 | } 43 | 44 | //线上 45 | if (_linkUrl.indexOf("m.jiuxiulvxing.com") != -1 46 | || _linkUrl.indexOf("m.hb.jiuxiulvxing.com") != -1 47 | || _linkUrl.indexOf("m.9xiulvxing.com") != -1 48 | || _linkUrl.indexOf("app.jiuxiulvxing.com") != -1) { 49 | _wap_config = { 50 | api: "http://api.jiuxiulvxing.com/web.api", 51 | domainUrl: "0ce37dd6b927730161a1e559c2336d0a", 52 | imgUrl: "http://img.yimayholiday.com/v1/tfs/", 53 | linkUrl: 'http://m.jiuxiulvxing.com/', 54 | contpointersApi: 'http://log.jiuxiulvxing.com/newlogwithgzip.jsp', 55 | appid: 'wx1deb965a51860f61', 56 | wxcenter: "http://wxapi.jiuxiulvxing.com/", 57 | yydbUrl: "http://m.jiuxiulvxing.com/view/listpage/listpage.html?code=JIUXIU_WAP_HOME_YY_2&title=" + encodeURIComponent("冰点特惠旅行"), 58 | movieUrl: "http://mt.hd.jiuxiulvxing.com/view/content/login.html?ch=dstyyy_360zqhd" 59 | } 60 | } 61 | 62 | //性能测试 63 | if (_linkUrl.indexOf("m.xntest.jiuxiulvxing.com") != -1) { 64 | _wap_config = { 65 | api: "http://api.stest.jiuxiulvxing.com/web.api", 66 | domainUrl: "0ce37dd6b927730161a1e559c2336d0a", 67 | imgUrl: "http://img.test.yimayholiday.com/v1/tfs/", 68 | linkUrl: 'http://m.xntest.jiuxiulvxing.com/', 69 | contpointersApi: 'http://test.data.jiuxiulvxing.com/newlogwithgzip.jsp', 70 | appid: 'wx14e984a0a6863004', 71 | wxcenter: "http://weixin.test.jiuxiulvxing.com/" 72 | } 73 | } 74 | 75 | //公共参数 76 | _wap_config.sm = "md5"; 77 | //_wap_config.aid = "23"; 78 | //_wap_config.aid_wx = "25"; 79 | _wap_config.aid = { 80 | wap: "23", 81 | weixin: "25", 82 | jxapp: "28" 83 | }; 84 | _wap_config.domid = "1200"; 85 | _wap_config.ft = "json"; 86 | _wap_config.ch = { 87 | jxwap: "jxwap", 88 | weixin: "weixin", 89 | jxapp: "jxapp" 90 | }; 91 | _wap_config.timeout = "3000"; 92 | 93 | var jx__api = _wap_config.api; 94 | 95 | window.jx_ajax = { 96 | post: function (url, obj, successFunc, errorFunc, noLoginCallback) { 97 | var _self = this; 98 | var type = obj.type || "POST"; 99 | _self.ajax(type, url, obj, successFunc, errorFunc, noLoginCallback); 100 | }, 101 | get: function (url, obj, successFunc, errorFunc, noLoginCallback) { 102 | var _self = this; 103 | _self.ajax("GET", url, obj, successFunc, errorFunc, noLoginCallback); 104 | }, 105 | ajax: function (type, url, obj, successFunc, errorFunc, noLoginCallback) { 106 | var _self = this; 107 | var _jx_async = obj["async"]; 108 | if (jx_common.isNull(_jx_async)) { 109 | _jx_async = true; 110 | } 111 | var _jx_ajax_frame = $.ajax({ 112 | xhrFields: { 113 | withCredentials: true // 114 | }, 115 | crossDomain: true, 116 | type: type, 117 | async: _jx_async, 118 | url: url, 119 | timeout: _wap_config.timeout, 120 | data: _self.encryptRequestParam(obj), 121 | success: function (res) { 122 | if (!res) { 123 | jx_common.tip("api无数据返回"); 124 | return; 125 | } 126 | if (res["stat"]["code"] == "-160" || res["stat"]["code"] == "-360") { 127 | if (jx_common.isInJXApp()) { 128 | jx_common.cleanCookie("_wtk"); 129 | jx_common.cleanCookie("_uid"); 130 | } else { 131 | jx_common.cleanCookie("jx_token"); 132 | jx_common.cleanCookie("jx_uid"); 133 | jx_common.cleanCookie("jx_u_phone"); 134 | } 135 | if (noLoginCallback && typeof noLoginCallback == "function") { 136 | noLoginCallback(); 137 | return false; 138 | } 139 | if (jx_common.isInJXApp()) { 140 | jx_common_app.openAppLogin(); 141 | } else { 142 | jx_common.tip("token失效重新登录"); 143 | window.setTimeout(function () { 144 | jx_common.openUrl("../../view/login/login.html?returnUrl=" + encodeURIComponent(window.location.href)); 145 | }, 1000); 146 | } 147 | return; 148 | } 149 | if (res["stat"]["code"] == "-260") { 150 | jx_common.tip("请输入正确验证码"); 151 | return; 152 | } 153 | 154 | 155 | if (res["stat"]["code"] != 0) { 156 | jx_common.tip("api错误(" + res["stat"]["code"] + ")"); 157 | return; 158 | } 159 | 160 | if (jx_common.isNull(res["content"])) { 161 | jx_common.tip("无结果数据"); 162 | return; 163 | } 164 | var errorEntry = res["stat"]["stateList"][0]; 165 | if (errorEntry["code"] == "-100") { 166 | jx_common.tip("服务器开小差!"); 167 | return; 168 | } 169 | successFunc(res["content"][0], errorEntry, res["stat"]); 170 | }, 171 | error: function () { 172 | if (errorFunc && (typeof errorFunc == "function")) { 173 | errorFunc(); 174 | return; 175 | } 176 | jx_common.tip("系统繁忙"); 177 | }, 178 | complete: function (XMLHttpRequest, status) { 179 | if (status == 'timeout') { //超时,status还有success,error等值的情况 180 | _jx_ajax_frame.abort(); 181 | jx_common.tip("系统超时"); 182 | } 183 | } 184 | }); 185 | }, 186 | encryptRequestParam: function (options) { 187 | var _self = this, _params = {}; 188 | try { 189 | _params._sm = _wap_config.sm; 190 | _params._aid = _self.getAid(); 191 | _params._domid = _wap_config.domid; 192 | _params._ft = _wap_config.ft; 193 | _params._ch = _self.getCh(); 194 | _params._tk = jx_common.getTk(); 195 | _params._uid = jx_common.getUid(); 196 | _params._did = jx_common.getDid(); 197 | _params._dsig = jx_common.getDsig(); 198 | 199 | var s = ""; 200 | var keys = []; 201 | var params = $.extend(_params, options); 202 | for (var k in params) { 203 | keys.push(k); 204 | } 205 | keys.sort(); 206 | for (var i = 0; i < keys.length; i++) { 207 | s = s + keys[i] + '=' + params[keys[i]]; 208 | } 209 | s += _wap_config.domainUrl; 210 | //alert(s); 211 | params._sig = md5(s); 212 | return params; 213 | } catch (e) { 214 | jx_common.tip("本地加签错误"); 215 | } 216 | return params; 217 | }, 218 | getCh: function () { 219 | var ch = jx_common.getCookie("jx_ch"); 220 | if (!jx_common.isNull(ch)) { 221 | return ch; 222 | } 223 | if (jx_common.isInJXApp()) { 224 | return _wap_config.ch.jxapp; 225 | } 226 | if (jx_common.isWxbrowser()) { 227 | return _wap_config.ch.weixin; 228 | } 229 | return _wap_config.ch.jxwap; 230 | }, 231 | getAid: function () { 232 | if (jx_common.isInJXApp()) { 233 | return _wap_config.aid.jxapp; 234 | } 235 | if (jx_common.isWxbrowser()) { 236 | return _wap_config.aid.weixin; 237 | } 238 | return _wap_config.aid.wap; 239 | } 240 | } 241 | 242 | module.exports = { 243 | _wap_config: _wap_config, 244 | jx_ajax: window.jx_ajax 245 | } 246 | -------------------------------------------------------------------------------- /static/common/jx-common-app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 与app交互的方法 3 | */ 4 | window.jx_common_app = { 5 | callApp : function(opration,data){ 6 | if($("#jx-app-hidden-div").size() > 0){ 7 | $("#jx-app-hidden-div").remove(); 8 | } 9 | $("body").append("
") 10 | var hidden = document.getElementById("jx-app-hidden-div"); 11 | var iframe = document.createElement("iframe"); 12 | iframe.src = "yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\""+opration+"\",\"DATA\":"+data+"}"; 13 | iframe.style.display = "none"; 14 | hidden.appendChild(iframe); 15 | return false; 16 | }, 17 | openApp : function(){ 18 | window.location.href = "yimay://app"; 19 | }, 20 | openAppShop : function(shopId,shopName){ 21 | shopName = encodeURIComponent(shopName); 22 | var operation = "SHOP_HOME_PAGE"; 23 | var data = "{\"id\":\""+shopId+"\",\"name\":\""+shopName+"\"}"; 24 | var _self = this; 25 | _self.callApp(operation,data); 26 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"SHOP_HOME_PAGE\",\"DATA\":{\"id\":\""+shopId+"\",\"name\":\""+shopName+"\"}}"; 27 | }, 28 | openAppItemDetail : function(itemId,itemType,title){ 29 | title = encodeURIComponent(title); 30 | var operation = ""; 31 | var data = "{\"id\":\""+itemId+"\",\"title\":\""+title+"\"}"; 32 | //跟团游 33 | if(itemType == "TOUR_LINE"){ 34 | operation = "PACKAGE_TOUR_DETAIL"; 35 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"PACKAGE_TOUR_DETAIL\",\"DATA\":{\"id\":\""+itemId+"\",\"title\":\""+title+"\"}}"; 36 | //return false; 37 | } 38 | //周边游 39 | else if(itemType == "ARROUND_FUN"){ 40 | operation = "AROUND_FUN_DETAIL"; 41 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"AROUND_FUN_DETAIL\",\"DATA\":{\"id\":\""+itemId+"\",\"title\":\""+title+"\"}}"; 42 | //return false; 43 | } 44 | //同城玩乐 45 | else if(itemType == "CITY_ACTIVITY"){ 46 | operation = "CITY_ACTIVITY_DETAIL"; 47 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"CITY_ACTIVITY_DETAIL\",\"DATA\":{\"id\":\""+itemId+"\",\"title\":\""+title+"\"}}"; 48 | //return false; 49 | } 50 | //自由行 51 | else if(itemType == "FREE_LINE"){ 52 | operation = "FREE_TOUR_DETAIL"; 53 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"FREE_TOUR_DETAIL\",\"DATA\":{\"id\":\""+itemId+"\",\"title\":\""+title+"\"}}"; 54 | //return false; 55 | } 56 | //酒店 57 | else if(itemType == "HOTEL"){ 58 | operation = "HOTEL"; 59 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"HOTEL\",\"DATA\":{\"id\":\""+itemId+"\",\"name\":\""+title+"\"}}"; 60 | //return false; 61 | } 62 | //境外自由行:FREE_TOUR_ABOARD_DETAIL 63 | else if(itemType == "FREE_TOUR_ABOARD_DETAIL"){ 64 | operation = "FREE_TOUR_ABOARD_DETAIL"; 65 | } 66 | //境外跟团游:PACKAGE_TOUR_ABOARD_DETAIL 67 | else if(itemType == "PACKAGE_TOUR_ABOARD_DETAIL"){ 68 | operation = "PACKAGE_TOUR_ABOARD_DETAIL"; 69 | } 70 | //积分商城商品详情 71 | else if(itemType == "INTEGRAL_MALL_DETAIL"){ 72 | operation = "VIEW_INTEGRAL_MALL_DETAIL"; 73 | data = "{\"id\":\""+itemId+"\"}"; 74 | } 75 | //美食 76 | else if(itemType == "JIUXIU_BUY_DETAIL"){ 77 | operation = "JIUXIU_BUY_DETAIL"; 78 | } 79 | else{ 80 | alert("暂不支持类型:"+itemType); 81 | return false; 82 | } 83 | var _self = this; 84 | _self.callApp(operation,data); 85 | }, 86 | openAppShare : function(shareTitle,shareContent,shareImageUrl,shareWebPage,shareWay){ 87 | shareTitle = encodeURIComponent(shareTitle); 88 | shareContent = encodeURIComponent(shareContent); 89 | shareImageUrl = encodeURIComponent(shareImageUrl); 90 | shareWebPage = encodeURIComponent(shareWebPage); 91 | if(!shareWay || shareWay == null || shareWay == ""){ 92 | shareWay = "-1"; 93 | } 94 | if(shareWay != "-1" //全部 95 | && shareWay != "1" //微信 96 | && shareWay != "2" //微信朋友圈 97 | && shareWay != "3" //QQ 98 | && shareWay != "4" //Weibo 99 | && shareWay != "5" //达人圈 100 | ){ 101 | alert("暂不支持分享类型"); 102 | return false; 103 | } 104 | var operation = "WEB_SHARE"; 105 | var data = '{"shareTitle":"'+shareTitle+'","shareContent":"'+shareContent+'","shareImageUrl":"'+shareImageUrl+'","shareWebPage":"'+shareWebPage+'","shareWay":"'+shareWay+'"}'; 106 | var _self = this; 107 | _self.callApp(operation,data); 108 | //window.location.href ='yimay://app?content={"TYPE":"JIUXIU","OPERATION":"WEB_SHARE","DATA":{"shareTitle":"'+shareTitle+'","shareContent":"'+shareContent+'","shareImageUrl":"'+shareImageUrl+'","shareWebPage":"'+shareWebPage+'","shareWay":"'+shareWay+'"}}'; 109 | }, 110 | openAppLogin:function(){ 111 | var operation = "LOGIN"; 112 | var data = '{}'; 113 | var _self = this; 114 | _self.callApp(operation,data); 115 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"LOGIN\",\"DATA\":{}}"; 116 | return false; 117 | }, 118 | openAppTopic:function(topicName){ 119 | topicName = encodeURIComponent(topicName); 120 | var operation = "VIEW_TOPIC_DETAIL"; 121 | var data = "{\"topicName\":\""+topicName+"\"}"; 122 | var _self = this; 123 | _self.callApp(operation,data); 124 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"VIEW_TOPIC_DETAIL\",\"DATA\":{\"topicName\":\""+topicName+"\"}}"; 125 | }, 126 | openAppBack:function() { 127 | var _self = this; 128 | _self.closeWindow(); 129 | }, 130 | openAppConsult:function(id) { 131 | var operation = "VIEW_CONSULTING_SERVICE_DETAIL"; 132 | var data = "{\"id\":\""+id+"\"}"; 133 | var _self = this; 134 | _self.callApp(operation,data); 135 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"VIEW_CONSULTING_SERVICE_DETAIL\",\"DATA\":{\"id\":\""+id+"\"}}"; 136 | return false; 137 | }, 138 | openAppDarenPage:function(id,option,title) { 139 | var operation = "MASTER_DETAIL"; 140 | var data = "{\"id\":\""+id+"\",\"option\":\""+option+"\",\"title\":\""+title+"\"}"; 141 | var _self = this; 142 | _self.callApp(operation,data); 143 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"MASTER_DETAIL\",\"DATA\":{\"id\":\""+id+"\",\"option\":\""+option+"\",\"title\":\""+title+"\"}}"; 144 | return false; 145 | }, 146 | openAppMall:function(){ 147 | var operation = "VIEW_INTEGRAL_MALL"; 148 | var data = "{}"; 149 | var _self = this; 150 | _self.callApp(operation,data); 151 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"VIEW_INTEGRAL_MALL\",\"DATA\":{}}"; 152 | return false; 153 | }, 154 | openH5Mall:function(){ 155 | var operation = "WEB_INTEGRAL_MALL"; 156 | var data = "{}"; 157 | var _self = this; 158 | _self.callApp(operation,data); 159 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"VIEW_INTEGRAL_MALL\",\"DATA\":{}}"; 160 | return false; 161 | }, 162 | openAppTaskList:function(){ 163 | var operation = "VIEW_INTEGRAL_TASK_LIST"; 164 | var data = "{}"; 165 | var _self = this; 166 | _self.callApp(operation,data); 167 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"VIEW_INTEGRAL_TASK_LIST\",\"DATA\":{}}"; 168 | return false; 169 | }, 170 | closeWindow:function(){ 171 | var operation = "CLOSE_WINDOW"; 172 | var data = "{}"; 173 | var _self = this; 174 | _self.callApp(operation,data); 175 | //window.location.href="yimay://app?content={\"TYPE\":\"JIUXIU\",\"OPERATION\":\"CLOSE_WINDOW\",\"DATA\":{}}"; 176 | return false; 177 | }, 178 | openAppTitle:function(title){ 179 | title = encodeURIComponent(title); 180 | var operation = "WEBVIEW_TITLE"; 181 | var data = "{\"title\":\""+title+"\"}"; 182 | var _self = this; 183 | _self.callApp(operation,data); 184 | return false; 185 | }, 186 | //积分明细 187 | openAppJiFenDetail:function(){ 188 | var operation = "VIEW_INTEGRAL_DETAIL"; 189 | var data = "{}"; 190 | var _self = this; 191 | _self.callApp(operation,data); 192 | return false; 193 | }, 194 | //积分任务列表 195 | openAppJiFenTaskList : function(){ 196 | var operation = "VIEW_INTEGRAL_TASK_LIST"; 197 | var data = "{}"; 198 | var _self = this; 199 | _self.callApp(operation,data); 200 | return false; 201 | }, 202 | //打开app中内嵌的H5页面 203 | openAppWeb:function(_url){ 204 | var _self = this; 205 | var operation = "OPEN_WEB"; 206 | var data = "{\"link\":\""+_url+"\",\"isCleanCookie\":\""+false+"\"}"; 207 | _self.callApp(operation,data); 208 | }, 209 | // app打开所有版本的商城 210 | openAllMall : function () { 211 | var _self = this, 212 | versionCode = jx_common.getAppVersionCode(); 213 | if(!versionCode){ 214 | _self.openAppMall(); 215 | return false; 216 | } 217 | versionCode = versionCode.substr(0,3); 218 | if(versionCode == "200"){ 219 | window.location.href="http://"+document.domain+"/view/mall/index.html"; 220 | return false; 221 | } 222 | if(versionCode== "210" || versionCode== "215"){ 223 | _self.openH5Mall(); 224 | return false; 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /static/common/jx-contpointer.js: -------------------------------------------------------------------------------- 1 | ;(function($){ 2 | $.extend({ 3 | //action_name动作编码 4 | //action_params可变参数,例如{'pid':'122012','pname':'蔬菜'}。具体的根据文档规定传,action_name不同action_params也会不同。 5 | monitors:function(url,action_and_params,app_id,domain_id,userid,channelCode,activity_info){ 6 | var stamps=new Date().getTime(),auto_params=[]; 7 | for(var key in action_and_params){ 8 | var obj={ 9 | "2001": key, 10 | "2002": "", 11 | "2003": stamps, 12 | "2004": action_and_params[key], 13 | "2005": "", 14 | "2006": userid, 15 | "2007": "", 16 | "2008": activity_info 17 | }; 18 | auto_params.push(obj); 19 | } 20 | 21 | config={ 22 | "1001": "九休旅行", 23 | "1002": app_id, 24 | "1003": "", 25 | "1004": "", 26 | "1005": "", 27 | "1006": "", 28 | "1007": "", 29 | "1008": this.ck_system(), 30 | "1009": this.ios_or_android(), 31 | "1010": "", 32 | "1011": channelCode, 33 | "1012": "", 34 | "1013": "", 35 | "1014": this.ck_browser(), 36 | "1015": "", 37 | "1016": "", 38 | "1017": auto_params, 39 | "1018": domain_id 40 | }; 41 | $.ajax({ 42 | dataType : "jsonp", 43 | url: url,//记录数据请求地址 44 | data: {msg:encodeURI(JSON.stringify(config))} 45 | }); 46 | }, 47 | ck_system:function() { 48 | var bIsAndroid = navigator.userAgent.match(/android/i) == "android",isIphone = (navigator.platform.toLowerCase() == "iphone") ; 49 | if (isIphone||bIsAndroid) return "MOBILE"; 50 | var isWin = (navigator.platform.toLowerCase() == "win32") || (navigator.platform.toLowerCase() == "windows"); 51 | var isMac = (navigator.platform.toLowerCase() == "mac68k") || (navigator.platform.toLowerCase() == "macppc") 52 | || (navigator.platform.toLowerCase() == "macintosh") || (navigator.platform.toLowerCase() == "macintel"); 53 | var isUnix = (navigator.platform.toLowerCase() == "x11") && !isWin && !isMac; 54 | var isLinux = (String(navigator.platform.toLowerCase()).indexOf("linux") > -1); 55 | if (isWin||isMac||isUnix||isLinux) return "PC"; 56 | return "PAD"; 57 | }, 58 | ios_or_android:function() { 59 | var isIphone = (navigator.platform.toLowerCase() == "iphone") ; 60 | if (isIphone) return "ios"; 61 | var bIsAndroid = (navigator.platform.toLowerCase() == "android"); 62 | if(bIsAndroid) return "android"; 63 | return ''; 64 | }, 65 | ck_browser:function(){ 66 | var userAgent = navigator.userAgent.toLowerCase(); 67 | var isOpera = userAgent.indexOf("opera") > -1; 68 | if (isOpera) { 69 | return "Opera浏览器" 70 | } 71 | if (userAgent.indexOf("firefox") > -1) { 72 | return "Firefox浏览器"; 73 | } 74 | if (userAgent.indexOf("chrome") > -1){ 75 | return "Chrome浏览器"; 76 | } 77 | if (userAgent.indexOf("safari") > -1) { 78 | return "Safari浏览器"; 79 | } 80 | if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("msie") > -1 && !isOpera) { 81 | return "IE浏览器"; 82 | } 83 | if(userAgent.indexOf("micromessenger") > -1) { 84 | return "微信内嵌浏览器"; 85 | } 86 | if(userAgent.indexOf(" qq") > -1) { 87 | return "QQ内嵌浏览器"; 88 | } 89 | } 90 | }); 91 | })(jQuery); 92 | 93 | /*$(function(){ 94 | //monitors函数,具体调用的例子。 95 | //$.monitors('Submit_Order',{'pid':'122012','pname':'蔬菜'}); 96 | $.monitors("http://test.data.jiuxiulvxing.com/newlogwithgzip.jsp",{ 97 | 'pv_uv':{'pid':'122012','pname':'蔬菜'} 98 | },"23","1200"); 99 | });*/ 100 | 101 | -------------------------------------------------------------------------------- /static/common/jx-contpointerutil.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: liuyuanyuan 3 | * @Date: 2016-06-20 12:21:05 4 | * @Last Modified by: liuyuanyuan 5 | * @Last Modified time: 2016-07-07 11:49:29 6 | */ 7 | 8 | 'use strict'; 9 | 10 | var _contpointer_config = {api : _wap_config.contpointersApi} 11 | 12 | //公共参数 13 | _contpointer_config.monitorsAction=function(params,user_id,activity_info){ 14 | $.monitors(_contpointer_config.api,params,jx_ajax.getAid(),_wap_config.domid,user_id,jx_ajax.getCh(),activity_info); 15 | }; 16 | -------------------------------------------------------------------------------- /static/common/jx-downloadapp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | window.jx_downloadapp={ 5 | show : function (){ 6 | var htl = [] ; 7 | htl.push("
"); 8 | htl.push(""); 11 | htl.push("
"); 12 | htl.push("

下载九休旅行App

"); 13 | htl.push("

来云南,选九休

"); 14 | htl.push("
"); 15 | htl.push("
"); 16 | htl.push(" 免费下载"); 17 | htl.push("
"); 18 | htl.push("
"); 19 | $("body").append(htl.join("")); 20 | }, 21 | hide : function(){ 22 | $(".download_mask").remove(); 23 | } 24 | }; -------------------------------------------------------------------------------- /static/common/jx-footmenu.js: -------------------------------------------------------------------------------- 1 | /** 2 | * footer-menu 3 | * 首先要引入jQuery.js 4 | * author:zhangjianfeng 5 | * date:2016-05-07 6 | */ 7 | window.jx_footMenu = { 8 | show : function(type){ 9 | $(".foot-menu").remove(); 10 | var menuHtlArr =[]; 11 | menuHtlArr.push("
"); 12 | menuHtlArr.push(" "); 32 | menuHtlArr.push("
"); 33 | $("body").append(menuHtlArr.join("")); 34 | if(!type){ 35 | return ; 36 | } 37 | if(type == "index"){ 38 | var infor_img=$(".index_img").parent().find('.infor'); 39 | $(".index_img").addClass("index_img_choose"); 40 | $(".index_img").removeClass("index_img"); 41 | infor_img.addClass('choose').siblings().removeClass('choose'); 42 | } 43 | if(type == "my"){ 44 | var infor_account=$(".index_acount").parent().find('.infor'); 45 | $(".index_acount").addClass("index_acount_choose"); 46 | $(".index_acount").removeClass("index_acount"); 47 | infor_account.addClass('choose').siblings().removeClass('choose'); 48 | } 49 | if(type == "app"){ 50 | var infor_app=$(".index_app").parent().find('.infor'); 51 | $(".index_app").addClass("index_app_choose"); 52 | $(".index_app").removeClass("index_app"); 53 | infor_app.addClass('choose').siblings().removeClass('choose'); 54 | } 55 | 56 | }, 57 | 58 | hide : function(){ 59 | $(".foot-menu").hide(); 60 | } 61 | 62 | }; 63 | -------------------------------------------------------------------------------- /static/common/jx-h5cache.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 需要md5加密 3 | * 支持单页面上缓存存储 4 | */ 5 | window.jx_h5cache = { 6 | setCache : function(key,value,timeout){ 7 | var _self = this; 8 | if(!window.localStorage){ 9 | return false; 10 | } 11 | _self.getStorageHref(key); 12 | window.localStorage.setItem(key,value); 13 | var timeoutKey = key+"_timeout"; 14 | if(timeout){ 15 | window.localStorage.setItem(timeoutKey,(new Date()).getTime() + (timeout *1000)); 16 | }else{ 17 | window.localStorage.setItem(timeoutKey,-1); 18 | } 19 | }, 20 | getCache : function(key){ 21 | var _self = this; 22 | if(!window.localStorage){ 23 | return ""; 24 | } 25 | _self.getStorageHref(key); 26 | var timeoutKey = key + "_timeout"; 27 | var timeout = window.localStorage.getItem(timeoutKey); 28 | if(!timeout || "" == timeout){ 29 | return ""; 30 | } 31 | if(timeout == -1 || timeout > (new Date()).getTime()){ 32 | return window.localStorage.getItem(key); 33 | } 34 | window.localStorage.setItem(key,""); 35 | return ""; 36 | }, 37 | delCache : function (key) { 38 | var _self = this; 39 | if(!window.localStorage){ 40 | return ""; 41 | } 42 | _self.getStorageHref(key); 43 | window.localStorage.removeItem(key); 44 | window.localStorage.removeItem(key + '_timeout'); 45 | }, 46 | getStorageHref : function (key) { 47 | if(localStorage.locationHref){ 48 | key = md5(localStorage.locationHref)+"_"+key; 49 | }else { 50 | key = md5(window.location.href)+"_"+key; 51 | } 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /static/common/jx-log.js: -------------------------------------------------------------------------------- 1 | window.jx_log={ 2 | monitors:function(action_and_params,activity_info){ 3 | var auto_params=[]; 4 | for(var key in action_and_params){ 5 | var obj={ 6 | "2001": key, 7 | "2002": "", 8 | "2003": (new Date()).getTime(), 9 | "2004": action_and_params[key], 10 | "2005": "", 11 | "2006": "", 12 | "2007": "", 13 | "2008": activity_info?activity_info:"" 14 | }; 15 | auto_params.push(obj); 16 | } 17 | 18 | var config={ 19 | "1001": "九休旅行", 20 | "1002": jx_ajax.getAid(), 21 | "1003": "", 22 | "1004": "", 23 | "1005": "", 24 | "1006": "", 25 | "1007": "", 26 | "1008": this.ck_system(), 27 | "1009": jx_common.isIOS() ? "ios" : "android", 28 | "1010": "", 29 | "1011": jx_ajax.getCh(), 30 | "1012": "", 31 | "1013": "", 32 | "1014": this.ck_browser(), 33 | "1015": "", 34 | "1016": "", 35 | "1017": auto_params, 36 | "1018": _wap_config.domid 37 | }; 38 | $.ajax({ 39 | dataType : "jsonp", 40 | url: _wap_config.contpointersApi,//记录数据请求地址 41 | data: {msg:encodeURIComponent(JSON.stringify(config))} 42 | }); 43 | /*if($("#jx-app-hidden-div-log").size() > 0){ 44 | $("#jx-app-hidden-div-log").remove(); 45 | } 46 | $("body").append("
") 47 | var hidden = document.getElementById("jx-app-hidden-div-log"); 48 | var iframe = document.createElement("iframe"); 49 | iframe.src = _wap_config.contpointersApi+"?msg="+encodeURIComponent(JSON.stringify(config)); 50 | iframe.style.display = "none"; 51 | hidden.appendChild(iframe);*/ 52 | }, 53 | ck_system:function() { 54 | var bIsAndroid = navigator.userAgent.match(/android/i) == "android",isIphone = (navigator.platform.toLowerCase() == "iphone") ; 55 | if (isIphone||bIsAndroid) return "MOBILE"; 56 | var isWin = (navigator.platform.toLowerCase() == "win32") || (navigator.platform.toLowerCase() == "windows"); 57 | var isMac = (navigator.platform.toLowerCase() == "mac68k") || (navigator.platform.toLowerCase() == "macppc") 58 | || (navigator.platform.toLowerCase() == "macintosh") || (navigator.platform.toLowerCase() == "macintel"); 59 | var isUnix = (navigator.platform.toLowerCase() == "x11") && !isWin && !isMac; 60 | var isLinux = (String(navigator.platform.toLowerCase()).indexOf("linux") > -1); 61 | if (isWin||isMac||isUnix||isLinux) return "PC"; 62 | return "PAD"; 63 | }, 64 | ck_browser:function(){ 65 | var userAgent = navigator.userAgent.toLowerCase(); 66 | var isOpera = userAgent.indexOf("opera") > -1; 67 | if (isOpera) { 68 | return "Opera浏览器" 69 | } 70 | if (userAgent.indexOf("firefox") > -1) { 71 | return "Firefox浏览器"; 72 | } 73 | if (userAgent.indexOf("chrome") > -1){ 74 | return "Chrome浏览器"; 75 | } 76 | if (userAgent.indexOf("safari") > -1) { 77 | return "Safari浏览器"; 78 | } 79 | if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("msie") > -1 && !isOpera) { 80 | return "IE浏览器"; 81 | } 82 | if(userAgent.indexOf("micromessenger") > -1) { 83 | return "微信内嵌浏览器"; 84 | } 85 | if(userAgent.indexOf(" qq") > -1) { 86 | return "QQ内嵌浏览器"; 87 | } 88 | } 89 | }; -------------------------------------------------------------------------------- /static/data/live.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 0, 3 | "src": "http://record2.a8.com/mp4/1472734874787582.mp4", 4 | "poster": "/static/img/logo_default.png", 5 | "online": "100", 6 | "room": "101", 7 | "title": "热带云南8天7晚,2015穿越北北回归线", 8 | "photo": "/static/img/tou_xiang.png", 9 | "liver": "王璐岢", 10 | "focus": "20", 11 | "fans": "100", 12 | "replay":[{ 13 | "img":"/static/img/logo_default_s.jpg", 14 | "state":"1", 15 | "liver":"xxx", 16 | "viewer":"1000", 17 | "title":"123456qwerty" 18 | },{ 19 | "img":"/static/img/logo_default_s.jpg", 20 | "state":"1", 21 | "liver":"xxx2", 22 | "viewer":"1000", 23 | "title":"123456qwerty" 24 | },{ 25 | "img":"/static/img/logo_default_s.jpg", 26 | "state":"1", 27 | "liver":"xxx3", 28 | "viewer":"1000", 29 | "title":"123456qwerty" 30 | },{ 31 | "img":"/static/img/logo_default_s.jpg", 32 | "state":"1", 33 | "liver":"xxx", 34 | "viewer":"1000", 35 | "title":"123456qwerty" 36 | }], 37 | "wonderfulList":[{ 38 | "id":"111111", 39 | "img":"/static/img/logo_default_s.jpg", 40 | "state":"START_LIVE", 41 | "liver":"AAA", 42 | "viewer":"1000", 43 | "title":"123456qwerty" 44 | },{ 45 | "id":"2222222", 46 | "img":"/static/img/logo_default_s.jpg", 47 | "state":"REPLAY_LIVE", 48 | "liver":"bbb", 49 | "viewer":"1000", 50 | "title":"123456qwerty" 51 | }] 52 | } 53 | -------------------------------------------------------------------------------- /static/data/video.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 1, 3 | "src": "http://record2.a8.com/mp4/1472734874787582.mp4", 4 | "poster": "/static/img/logo_default.png", 5 | "online": "100", 6 | "room": "101", 7 | "title": "热带云南8天7晚,2015穿越北北回归线", 8 | "photo": "/static/img/tou_xiang.png", 9 | "liver": "王璐岢", 10 | "focus": "20", 11 | "fans": "10" 12 | } 13 | -------------------------------------------------------------------------------- /static/liveStreaming/img/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/static/liveStreaming/img/arrow.png -------------------------------------------------------------------------------- /static/liveStreaming/img/boy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/static/liveStreaming/img/boy.png -------------------------------------------------------------------------------- /static/liveStreaming/img/fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/static/liveStreaming/img/fullscreen.png -------------------------------------------------------------------------------- /static/liveStreaming/img/girl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/static/liveStreaming/img/girl.png -------------------------------------------------------------------------------- /static/liveStreaming/img/movie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/static/liveStreaming/img/movie.png -------------------------------------------------------------------------------- /static/liveStreaming/img/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrLeo/vue-demo/857203f8b23b01426492791b9c6fe4f5db55f301/static/liveStreaming/img/share.png -------------------------------------------------------------------------------- /static/liveStreaming/live.css: -------------------------------------------------------------------------------- 1 | .no-display{ 2 | display: none; 3 | } 4 | .pos-re{ 5 | position: relative; 6 | } 7 | 8 | /*直播首推*/ 9 | .vedioBox{ 10 | width: 100%; 11 | height:12rem; 12 | overflow: hidden; 13 | } 14 | .online{ 15 | width:4.475rem; 16 | height: 2.25rem; 17 | background: rgba(0,0,0,0.15); 18 | color: #fff; 19 | font-size:0.625rem; 20 | line-height: 1.125rem; 21 | position: absolute; 22 | bottom: 0.75rem; 23 | left: 0.75rem; 24 | border-radius: 0.2rem; 25 | padding-left: 0.375rem; 26 | } 27 | .fullscree{ 28 | width: 1.625rem; 29 | height:1.625rem; 30 | display: block; 31 | position: absolute; 32 | bottom: 0.75rem; 33 | right: 0.75rem; 34 | background: url(img/fullscreen.png) no-repeat; 35 | background-position:0.3rem 0.3rem; 36 | background-color: rgba(0,0,0,0.15); 37 | border-radius: 50%; 38 | } 39 | .msgBox{ 40 | height:6rem; 41 | padding:0 0.75rem; 42 | background-color: #fff; 43 | } 44 | .msgBox h3{ 45 | font-size: 0.75rem; 46 | line-height: 2.425rem; 47 | } 48 | .msgBox span{ 49 | display: inline-block; 50 | margin-left: 0.375rem; 51 | line-height: 1.125rem; 52 | font-size: 0.625rem; 53 | } 54 | .msgBox span i{ 55 | color: #333; 56 | } 57 | .touPic{ 58 | width: 2.375rem; 59 | height: 2.375rem; 60 | border-radius: 50%; 61 | overflow: hidden; 62 | float: left; 63 | } 64 | .liver i{ 65 | background: url(img/girl.png) no-repeat; 66 | padding-right:1.0rem; 67 | background-position:0.1rem -0.15rem; 68 | } 69 | .shar{ 70 | width: 1.6rem; 71 | height: 2.125rem; 72 | float: right; 73 | margin-top:-1rem; 74 | } 75 | .shar i{ 76 | display:block; 77 | width: 100%; 78 | height:1.125rem; 79 | background: url(img/share.png) no-repeat; 80 | } 81 | .shar span{ 82 | margin: 0; 83 | } 84 | /* 直播列表 */ 85 | .liveList{ 86 | margin-top: 0.5rem; 87 | background-color: #fff; 88 | } 89 | .listTab li{ 90 | width: 50%; 91 | height:2.5rem; 92 | line-height: 2.5rem; 93 | font-size: 0.75rem; 94 | color: #555; 95 | float: left; 96 | box-sizing: border-box; 97 | overflow: hidden; 98 | } 99 | .listTab .active{ 100 | color: #FFAF00; 101 | border-bottom: 5px solid #FFAF00; 102 | } 103 | .list{ 104 | padding:0 0.75rem 0.5rem 0.75rem; 105 | } 106 | .list li{ 107 | padding-top: 0.5rem; 108 | float: left; 109 | width:48%; 110 | overflow: hidden; 111 | } 112 | .list li:nth-child(2n){ 113 | margin-left:30px; 114 | } 115 | .list .listbox{ 116 | height:6.3rem; 117 | overflow: hidden; 118 | } 119 | .liverName{ 120 | line-height:1.7rem; 121 | font-size:0.75rem; 122 | overflow: hidden; 123 | white-space: nowrap; 124 | text-overflow: ellipsis; 125 | } 126 | .liverName i{ 127 | padding-right:1.5rem; 128 | background: url(img/movie.png) no-repeat; 129 | background-position:0.3rem 0rem; 130 | 131 | } 132 | .listbox span{ 133 | display: inline-block; 134 | position: absolute; 135 | color: #fff; 136 | font-size:0.6rem; 137 | } 138 | .listbox .state{ 139 | width:1.7rem; 140 | height:0.9rem; 141 | line-height: 0.9rem; 142 | background: rgba(0,0,0,0.25); 143 | top:0.375rem; 144 | right: 0.5rem; 145 | border-right: 0.5rem; 146 | } 147 | .listbox .name{ 148 | bottom:0.5rem; 149 | left: 0.375rem; 150 | } 151 | .listbox .num{ 152 | bottom: 0.5rem; 153 | right: 0.375rem; 154 | } 155 | /* 去下载 */ 156 | .toload{ 157 | height:2.25rem; 158 | background: rgba(0,0,0,0.65); 159 | color:#fff; 160 | padding:0.35rem 0.75rem; 161 | position: fixed; 162 | left: 0; 163 | bottom: 0; 164 | width: 100%; 165 | } 166 | .log{ 167 | float: left; 168 | border-radius: 0.5rem; 169 | width:1.5rem; 170 | height: 1.5rem; 171 | overflow: hidden; 172 | } 173 | .toload span{ 174 | display:block; 175 | margin-left:2.4rem; 176 | } 177 | .main-tit{ 178 | font-size:0.625rem; 179 | } 180 | 181 | .sub-tit{ 182 | font-size: 0.5rem; 183 | margin-top: 0.1rem; 184 | } 185 | .sub-tit i{ 186 | color:#ffaf00; 187 | } 188 | .logbtn{ 189 | float: right; 190 | border: 1px solid #fff; 191 | width:4.05rem; 192 | height: 1.3rem; 193 | line-height: 1.3rem; 194 | border-radius: 0.2rem; 195 | margin-top: -1.3rem; 196 | } 197 | /* 分享浮层 */ 198 | .toshar{ 199 | width:100%; 200 | height: 100%; 201 | z-index: 50; 202 | position: fixed; 203 | top: 0; 204 | left: 0; 205 | bottom: 0; 206 | right: 0; 207 | background-color:rgba(0,0,0,0.45); 208 | color: #fff; 209 | } 210 | .toshar i{ 211 | display: inline-block; 212 | width: 2.625rem; 213 | height: 5.5rem; 214 | background:url(../img/sprite.png) no-repeat; 215 | background-position: 0 -2.25rem; 216 | float: right; 217 | margin-top: 1.25rem; 218 | margin-right:0.75rem; 219 | } 220 | .toshar p{ 221 | font-size: 0.75rem; 222 | float: right; 223 | margin-top: 5.625rem; 224 | margin-right: 0.5rem; 225 | } 226 | -------------------------------------------------------------------------------- /static/liveStreaming/live.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 分享直播 6 | 7 | 8 | 9 | 10 |
11 | 12 |

点击右上角分享

13 |
14 |
15 |
16 | 17 | 18 | 在线: 1234
19 | 房号: 16100 20 |
21 | 22 | 23 |
24 |
25 |

热带云南8天7晚,2015穿越北北回归线

26 | 27 | 28 | 29 | adbli
30 | 关注 67 31 | 粉丝 5128 32 |
33 | 34 | 分享 35 |
36 |
37 |
38 |
39 |
    40 |
  • 精彩推荐
  • 41 |
  • Ta的回放
  • 42 |
43 |
    44 |
  • 45 |
    46 | 47 | 直播 48 | sun 49 | 23335看过 50 |
    51 |
    52 | 2015穿越回归线 53 |
    54 |
  • 55 |
  • 56 |
    57 | 58 | 直播 59 | sun 60 | 23335看过 61 |
    62 |
    63 | 2015穿越回归线 64 |
    65 |
  • 66 |
  • 67 |
    68 | 69 | 直播 70 | sun 71 | 23335看过 72 |
    73 |
    74 | 2015穿越回归线 75 |
    76 |
  • 77 |
  • 78 |
    79 | 80 | 直播 81 | sun 82 | 23335看过 83 |
    84 |
    85 | 2015穿越回归线 86 |
    87 |
  • 88 |
89 |
90 |
91 |
92 | 93 |
94 | 想每天看旅游直播? 95 | 下载九休旅行送5元 96 |
立即下载
97 |
98 | 99 | -------------------------------------------------------------------------------- /static/plugin/jquery.cookie.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery Cookie Plugin v1.4.1 3 | * https://github.com/carhartl/jquery-cookie 4 | * 5 | * Copyright 2013 Klaus Hartl 6 | * Released under the MIT license 7 | */ 8 | (function (factory) { 9 | if (typeof define === 'function' && define.amd) { 10 | // AMD 11 | define(['jquery'], factory); 12 | } else if (typeof exports === 'object') { 13 | // CommonJS 14 | factory(require('jquery')); 15 | } else { 16 | // Browser globals 17 | factory(jQuery); 18 | } 19 | }(function ($) { 20 | 21 | var pluses = /\+/g; 22 | 23 | function encode(s) { 24 | return config.raw ? s : encodeURIComponent(s); 25 | } 26 | 27 | function decode(s) { 28 | return config.raw ? s : decodeURIComponent(s); 29 | } 30 | 31 | function stringifyCookieValue(value) { 32 | return encode(config.json ? JSON.stringify(value) : String(value)); 33 | } 34 | 35 | function parseCookieValue(s) { 36 | if (s.indexOf('"') === 0) { 37 | // This is a quoted cookie as according to RFC2068, unescape... 38 | s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); 39 | } 40 | 41 | try { 42 | // Replace server-side written pluses with spaces. 43 | // If we can't decode the cookie, ignore it, it's unusable. 44 | // If we can't parse the cookie, ignore it, it's unusable. 45 | s = decodeURIComponent(s.replace(pluses, ' ')); 46 | return config.json ? JSON.parse(s) : s; 47 | } catch(e) {} 48 | } 49 | 50 | function read(s, converter) { 51 | var value = config.raw ? s : parseCookieValue(s); 52 | return $.isFunction(converter) ? converter(value) : value; 53 | } 54 | 55 | var config = $.cookie = function (key, value, options) { 56 | 57 | // Write 58 | 59 | if (value !== undefined && !$.isFunction(value)) { 60 | options = $.extend({}, config.defaults, options); 61 | 62 | if (typeof options.expires === 'number') { 63 | var days = options.expires, t = options.expires = new Date(); 64 | t.setTime(+t + days * 864e+5); 65 | } 66 | 67 | return (document.cookie = [ 68 | encode(key), '=', stringifyCookieValue(value), 69 | options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE 70 | options.path ? '; path=' + options.path : '', 71 | options.domain ? '; domain=' + options.domain : '', 72 | options.secure ? '; secure' : '' 73 | ].join('')); 74 | } 75 | 76 | // Read 77 | 78 | var result = key ? undefined : {}; 79 | 80 | // To prevent the for loop in the first place assign an empty array 81 | // in case there are no cookies at all. Also prevents odd result when 82 | // calling $.cookie(). 83 | var cookies = document.cookie ? document.cookie.split('; ') : []; 84 | 85 | for (var i = 0, l = cookies.length; i < l; i++) { 86 | var parts = cookies[i].split('='); 87 | var name = decode(parts.shift()); 88 | var cookie = parts.join('='); 89 | 90 | if (key && key === name) { 91 | // If second argument (value) is a function it's a converter... 92 | result = read(cookie, value); 93 | break; 94 | } 95 | 96 | // Prevent storing a cookie that we couldn't decode. 97 | if (!key && (cookie = read(cookie)) !== undefined) { 98 | result[name] = cookie; 99 | } 100 | } 101 | 102 | return result; 103 | }; 104 | 105 | config.defaults = {}; 106 | 107 | $.removeCookie = function (key, options) { 108 | if ($.cookie(key) === undefined) { 109 | return false; 110 | } 111 | 112 | // Must not alter options, thus extending a fresh object... 113 | $.cookie(key, '', $.extend({}, options, { expires: -1 })); 114 | return !$.cookie(key); 115 | }; 116 | 117 | })); 118 | -------------------------------------------------------------------------------- /static/plugin/md5.min.js: -------------------------------------------------------------------------------- 1 | !function(a){"use strict";function b(a,b){var c=(65535&a)+(65535&b),d=(a>>16)+(b>>16)+(c>>16);return d<<16|65535&c}function c(a,b){return a<>>32-b}function d(a,d,e,f,g,h){return b(c(b(b(d,a),b(f,h)),g),e)}function e(a,b,c,e,f,g,h){return d(b&c|~b&e,a,b,f,g,h)}function f(a,b,c,e,f,g,h){return d(b&e|c&~e,a,b,f,g,h)}function g(a,b,c,e,f,g,h){return d(b^c^e,a,b,f,g,h)}function h(a,b,c,e,f,g,h){return d(c^(b|~e),a,b,f,g,h)}function i(a,c){a[c>>5]|=128<>>9<<4)+14]=c;var d,i,j,k,l,m=1732584193,n=-271733879,o=-1732584194,p=271733878;for(d=0;d>5]>>>b%32&255);return c}function k(a){var b,c=[];for(c[(a.length>>2)-1]=void 0,b=0;b>5]|=(255&a.charCodeAt(b/8))<16&&(e=i(e,8*a.length)),c=0;16>c;c+=1)f[c]=909522486^e[c],g[c]=1549556828^e[c];return d=i(f.concat(k(b)),512+8*b.length),j(i(g.concat(d),640))}function n(a){var b,c,d="0123456789abcdef",e="";for(c=0;c>>4&15)+d.charAt(15&b);return e}function o(a){return unescape(encodeURIComponent(a))}function p(a){return l(o(a))}function q(a){return n(p(a))}function r(a,b){return m(o(a),o(b))}function s(a,b){return n(r(a,b))}function t(a,b,c){return b?c?r(b,a):s(b,a):c?p(a):q(a)}"function"==typeof define&&define.amd?define(function(){return t}):a.md5=t}(this); -------------------------------------------------------------------------------- /test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | 3 | // http://nightwatchjs.org/guide#settings-file 4 | module.exports = { 5 | "src_folders": ["test/e2e/specs"], 6 | "output_folder": "test/e2e/reports", 7 | "custom_assertions_path": ["test/e2e/custom-assertions"], 8 | 9 | "selenium": { 10 | "start_process": true, 11 | "server_path": "node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.0.jar", 12 | "host": "127.0.0.1", 13 | "port": 4444, 14 | "cli_args": { 15 | "webdriver.chrome.driver": require('chromedriver').path 16 | } 17 | }, 18 | 19 | "test_settings": { 20 | "default": { 21 | "selenium_port": 4444, 22 | "selenium_host": "localhost", 23 | "silent": true 24 | }, 25 | 26 | "chrome": { 27 | "desiredCapabilities": { 28 | "browserName": "chrome", 29 | "javascriptEnabled": true, 30 | "acceptSslCerts": true 31 | } 32 | }, 33 | 34 | "firefox": { 35 | "desiredCapabilities": { 36 | "browserName": "firefox", 37 | "javascriptEnabled": true, 38 | "acceptSslCerts": true 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | var server = require('../../build/dev-server.js') 4 | 5 | // 2. run the nightwatch test suite against it 6 | // to run in additional browsers: 7 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 8 | // 2. add it to the --env flag below 9 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 10 | // For more information on Nightwatch's config file, see 11 | // http://nightwatchjs.org/guide#settings-file 12 | var opts = process.argv.slice(2) 13 | if (opts.indexOf('--config') === -1) { 14 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 15 | } 16 | if (opts.indexOf('--env') === -1) { 17 | opts = opts.concat(['--env', 'chrome']) 18 | } 19 | 20 | var spawn = require('cross-spawn') 21 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 22 | 23 | runner.on('exit', function (code) { 24 | server.close() 25 | process.exit(code) 26 | }) 27 | 28 | runner.on('error', function (err) { 29 | server.close() 30 | throw err 31 | }) 32 | -------------------------------------------------------------------------------- /test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | browser 7 | .url('http://localhost:8080') 8 | .waitForElementVisible('#app', 5000) 9 | .assert.elementPresent('.logo') 10 | .assert.containsText('h1', 'Hello World!') 11 | .assert.elementCount('p', 3) 12 | .end() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/unit/index.js: -------------------------------------------------------------------------------- 1 | // Polyfill fn.bind() for PhantomJS 2 | /* eslint-disable no-extend-native */ 3 | Function.prototype.bind = require('function-bind') 4 | 5 | // require all test files (files that ends with .spec.js) 6 | var testsContext = require.context('./specs', true, /\.spec$/) 7 | testsContext.keys().forEach(testsContext) 8 | 9 | // require all src files except main.js for coverage. 10 | // you can also change this to match only the subset of files that 11 | // you want coverage for. 12 | var srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) 13 | srcContext.keys().forEach(srcContext) 14 | -------------------------------------------------------------------------------- /test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var path = require('path') 7 | var merge = require('webpack-merge') 8 | var baseConfig = require('../../build/webpack.base.conf') 9 | var utils = require('../../build/utils') 10 | var webpack = require('webpack') 11 | var projectRoot = path.resolve(__dirname, '../../') 12 | 13 | var webpackConfig = merge(baseConfig, { 14 | // use inline sourcemap for karma-sourcemap-loader 15 | module: { 16 | loaders: utils.styleLoaders() 17 | }, 18 | devtool: '#inline-source-map', 19 | vue: { 20 | loaders: { 21 | js: 'isparta' 22 | } 23 | }, 24 | plugins: [ 25 | new webpack.DefinePlugin({ 26 | 'process.env': require('../../config/test.env') 27 | }) 28 | ] 29 | }) 30 | 31 | // no need for app entry during tests 32 | delete webpackConfig.entry 33 | 34 | // make sure isparta loader is applied before eslint 35 | webpackConfig.module.preLoaders = webpackConfig.module.preLoaders || [] 36 | webpackConfig.module.preLoaders.unshift({ 37 | test: /\.js$/, 38 | loader: 'isparta', 39 | include: path.resolve(projectRoot, 'src') 40 | }) 41 | 42 | // only apply babel for test files when using isparta 43 | webpackConfig.module.loaders.some(function (loader, i) { 44 | if (loader.loader === 'babel') { 45 | loader.include = path.resolve(projectRoot, 'test/unit') 46 | return true 47 | } 48 | }) 49 | 50 | module.exports = function (config) { 51 | config.set({ 52 | // to run in additional browsers: 53 | // 1. install corresponding karma launcher 54 | // http://karma-runner.github.io/0.13/config/browsers.html 55 | // 2. add it to the `browsers` array below. 56 | browsers: ['PhantomJS'], 57 | frameworks: ['mocha', 'sinon-chai'], 58 | reporters: ['spec', 'coverage'], 59 | files: ['./index.js'], 60 | preprocessors: { 61 | './index.js': ['webpack', 'sourcemap'] 62 | }, 63 | webpack: webpackConfig, 64 | webpackMiddleware: { 65 | noInfo: true 66 | }, 67 | coverageReporter: { 68 | dir: './coverage', 69 | reporters: [ 70 | { type: 'lcov', subdir: '.' }, 71 | { type: 'text-summary' } 72 | ] 73 | } 74 | }) 75 | } 76 | -------------------------------------------------------------------------------- /test/unit/specs/Hello.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Hello from 'src/components/Hello' 3 | 4 | describe('Hello.vue', () => { 5 | it('should render correct contents', () => { 6 | const vm = new Vue({ 7 | template: '
', 8 | components: { Hello } 9 | }).$mount() 10 | expect(vm.$el.querySelector('.hello h1').textContent).to.contain('Hello World!') 11 | }) 12 | }) 13 | --------------------------------------------------------------------------------