├── .babelrc ├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── build ├── setup-dev-server.js ├── vue-loader.config.js ├── webpack.base.config.js ├── webpack.client.config.js └── webpack.server.config.js ├── log ├── err.log └── out.log ├── package-lock.json ├── package.json ├── pmlog.json ├── server.js └── src ├── App.vue ├── app.js ├── assets ├── style │ └── css.less └── views │ └── index.css ├── components ├── Banner.vue ├── BottomNav.vue ├── FloorOne.vue └── Header.vue ├── entry-client.js ├── entry-server.js ├── index.template.html ├── public ├── conf.js └── utils │ ├── api.js │ └── confUtils.js ├── router └── index.js ├── static ├── img │ ├── demo.jpeg │ ├── favicon.ico │ └── service-demo.jpeg └── js │ └── flexible.js ├── store ├── actions.js ├── getters.js ├── index.js ├── modules │ ├── global.js │ └── index.js └── mutation-types.js └── views └── index ├── conf.js ├── index.vue ├── mock.js └── service.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }], 4 | "stage-2" 5 | ], 6 | "plugins": ["syntax-dynamic-import","transform-runtime"], 7 | "comments": false 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | yarn-error.log 6 | .idea 7 | *.iml -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 wangqi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-ssr node 服务端渲染工作流 2 | 3 | ## react 版本服务端渲染 [跳转](https://github.com/wqzwh/react-ssr) 4 | 5 | ## 解决问题 6 | 7 | - 【手机端首屏渲染问题】 8 | - 【SEO 解决搜索引擎抓取问题】 9 | - 【提高页面渲染性能】 10 | 11 | ### 统一的文件系统结构 12 | 13 | - 项目整体目录结构 14 | 15 | ```bash 16 | ├── LICENSE 17 | ├── README.md 18 | ├── build 19 | │   ├── setup-dev-server.js 20 | │   ├── vue-loader.config.js 21 | │   ├── webpack.base.config.js 22 | │   ├── webpack.client.config.js 23 | │   └── webpack.server.config.js 24 | ├── log 25 | │   ├── err.log 26 | │   └── out.log 27 | ├── package.json 28 | ├── pmlog.json 29 | ├── server.js 30 | └── src 31 | ├── App.vue 32 | ├── app.js 33 | ├── assets 34 | │   ├── images 35 | │   ├── style 36 | │   │   └── css.less 37 | │   └── views 38 | │   └── index.css 39 | ├── components 40 | │   ├── Banner.vue 41 | │   ├── BottomNav.vue 42 | │   ├── FloorOne.vue 43 | │   └── Header.vue 44 | ├── entry-client.js 45 | ├── entry-server.js 46 | ├── index.template.html 47 | ├── public 48 | │   ├── conf.js 49 | │   └── utils 50 | │   ├── api.js 51 | │   └── confUtils.js 52 | ├── router 53 | │   └── index.js 54 | ├── static 55 | │   ├── img 56 | │   │   └── favicon.ico 57 | │   └── js 58 | │   └── flexible.js 59 | ├── store 60 | │   ├── actions.js 61 | │   ├── getters.js 62 | │   ├── index.js 63 | │   ├── modules 64 | │   │   └── Home.js 65 | │   ├── mutationtypes.js 66 | │   └── state.js 67 | └── views 68 | └── index 69 | ├── conf.js 70 | ├── index.vue 71 | ├── mock.js 72 | └── service.js 73 | 74 | ``` 75 | 76 | ### 统一的职责划分 77 | 78 | - views 文件夹下分模块文件,模块文件下下又分模块本身的.vue 文件(模版文件),index.js 文件(后台数据交互文件),mock.js(本模块的 mock 假数据),conf.js(配置本模块一些参数,请求路径,模块名称等信息) 79 | - components 公共组件文件夹 80 | - router 主要存放前端路由配置文件,写法规范按照 vue-router 官方例子即可。 81 | - store 主要是存放共享状态文件,里面包含 action.js,getter.js,mutationtype.js 等,后期会根据模块再细分这些。 82 | - public 主要存放公共组件代码和项目使用的公共文件代码,例如后期我们将 axios 封装成公共的 api 库文件等等 83 | - static 文件夹代表静态文件,不会被 webpack 打包的 84 | - pmlog.json 集成了 pm2 监控命令 85 | - app.js 是项目入口文件 86 | - App.vue 是项目入口文件 87 | - entry-client 和 entry-server 分别是客户端入口文件和服务端的入口文件 88 | - index.template.html 是整个项目的模版文件 89 | - server.js 服务端启动服务的入口文件 90 | 91 | ### 开发自动化 92 | 93 | - 自动化搭建本地研发环境,快速响应文件更改并自动刷新浏览器。 94 | - 自动化编译 ES6 或 CommonJS 标准的 JS 代码,自动化生成 source map 便于浏览器端调试。 95 | - 自动化编译 SASS/LESS => CSS 文件,自动化添加 CSS3 的各种浏览器前缀。 96 | - 服务端使用 express,前端使用 webpack 自动化构建打包。 97 | 98 | ## 安装使用 99 | 100 | ### 安装 101 | 102 | - Mac 系统推荐使用 [iterm2](http://iterm2.com/) 及 [oh my zsh](http://ohmyz.sh/) 103 | - 类 Unix 系统,请打开任意终端输入命令执行。 104 | - Windows 用户请先安装 [git](http://git-scm.com/),然后在 [Git Bash](http://git-for-windows.github.io/) 下执行命令 105 | 106 | #### 安装 Node 和 NPM 107 | 108 | - 详细过程参考官网 https://nodejs.org (中文网站 http://nodejs.cn/) 109 | - 支持所有 Node 的发行版本,建议使用最新稳定版 6.x 。 110 | - Ubuntu 用户使用 `apt-get` 安装 node 后,安装的程序名叫 `nodejs`,需要软链成 `node` 111 | - Windows 用户安装完成后需要在 CMD 下确认是否能执行 node 和 npm 112 | 113 | #### 全局安装 webpack 最新版本 114 | 115 | ```bash 116 | npm install webpack -g 117 | ``` 118 | 119 | ### 运行 Demo 示例项目 120 | 121 | #### 安装 NPM 包 122 | 123 | - 进入项目 目录执行以下命令 124 | 125 | ```bash 126 | npm install 127 | ``` 128 | 129 | #### 运行 Demo 示例 130 | 131 | - 在项目目录下执行 132 | 133 | ```bash 134 | // 打包命令 135 | npm run build 136 | ``` 137 | 138 | ```bash 139 | // production模式下启动服务 140 | npm run start 141 | ``` 142 | 143 | ```bash 144 | // dev模式下启动服务 145 | npm run dev 146 | ``` 147 | 148 | npm run dev 启动服务路径http://localhost:6180 149 | 150 | ### 添加 mock 假数据测试 151 | 152 | ```javascript 153 | // /views/index/mock.js 154 | GET: { 155 | "code": 200, 156 | "data": [ 157 | { 158 | name: '推荐', 159 | type: 0 160 | }, 161 | { 162 | name: '居家', 163 | type: 1 164 | }, 165 | { 166 | name: '餐厨', 167 | type: 2 168 | }, 169 | { 170 | name: '服装', 171 | type: 3 172 | }, 173 | { 174 | name: '电器', 175 | type: 4 176 | }, 177 | { 178 | name: '洗护', 179 | type: 5 180 | }, 181 | { 182 | name: '杂货', 183 | type: 6 184 | } 185 | ] 186 | }, 187 | GETBOTTOM: { 188 | "code": 200, 189 | "data": [ 190 | { 191 | href: '/', 192 | value: '首页', 193 | type: 'index' 194 | }, 195 | { 196 | href: '/', 197 | value: '识物', 198 | type: 'topic' 199 | }, 200 | { 201 | href: '/', 202 | value: '分类', 203 | type: 'cate' 204 | }, 205 | { 206 | href: '/', 207 | value: '购物车', 208 | type: 'cart' 209 | }, 210 | { 211 | href: '/', 212 | value: '个人', 213 | type: 'ucenter' 214 | } 215 | ] 216 | } 217 | ``` 218 | 219 | ```javascript 220 | // views/index.vue 221 | serviceGet() { 222 | Service.get().then((data) => { 223 | this.headNavData = data; 224 | }) 225 | Service.getBottom().then((data) => { 226 | this.botNavData = data; 227 | }) 228 | } 229 | ``` 230 | 231 | ### service workers 配置 232 | 233 | ```javascript 234 | // webpack.cliemt.config.js 235 | if (process.env.NODE_ENV === 'production') { 236 | config.plugins.push( 237 | // auto generate service worker 238 | new SWPrecachePlugin({ 239 | cacheId: 'ga-vue', 240 | filename: 'service-worker.js', 241 | minify: true, 242 | dontCacheBustUrlsMatching: /\.\w{8}\./, 243 | staticFileGlobsIgnorePatterns: [/\.map$/, /\.json$/] 244 | }) 245 | ) 246 | } 247 | ``` 248 | 249 | ```javascript 250 | // entry-client.js 251 | if ('serviceWorker' in navigator) { 252 | console.log('SW present !!! ') 253 | navigator.serviceWorker 254 | .register('/service-worker.js', { 255 | //scope: '/toto/' 256 | }) 257 | .then(function(registration) { 258 | console.log('Service worker registered : ', registration.scope) 259 | }) 260 | .catch(function(err) { 261 | console.log('Service worker registration failed : ', err) 262 | }) 263 | } 264 | ``` 265 | 266 | ![最终效果图](https://github.com/wqzwh/ga-vue-ssr/blob/master/src/static/img/service-demo.jpeg) 267 | 268 | ### 发布部署 269 | 270 | node 服务器通过 express/koa 搭建环境,通过 pm2 启动端口服务,一般会在项目目录新建 bin 文件夹,然后新建相应的 sh 脚本命令来启动 node 服务。 271 | 272 | 以下是最终效果截图 273 | 274 | ![最终效果图](https://github.com/wqzwh/ga-vue-ssr/blob/master/src/static/img/demo.jpeg) 275 | -------------------------------------------------------------------------------- /build/setup-dev-server.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const webpack = require('webpack') 3 | const MFS = require('memory-fs') 4 | const clientConfig = require('./webpack.client.config') 5 | const serverConfig = require('./webpack.server.config') 6 | 7 | const readFile = (fs, file) => { 8 | try { 9 | return fs.readFileSync(path.join(clientConfig.output.path, file), 'utf-8') 10 | } catch (e) {} 11 | } 12 | 13 | module.exports = function setupDevServer (app, cb) { 14 | let bundle, clientManifest 15 | let resolve 16 | const readyPromise = new Promise(r => { resolve = r }) 17 | const ready = (...args) => { 18 | resolve() 19 | cb(...args) 20 | } 21 | 22 | // modify client config to work with hot middleware 23 | clientConfig.entry.app = ['webpack-hot-middleware/client', clientConfig.entry.app] 24 | clientConfig.output.filename = '[name].js' 25 | clientConfig.plugins.push( 26 | new webpack.HotModuleReplacementPlugin(), 27 | new webpack.NoEmitOnErrorsPlugin() 28 | ) 29 | 30 | // dev middleware 31 | const clientCompiler = webpack(clientConfig) 32 | const devMiddleware = require('webpack-dev-middleware')(clientCompiler, { 33 | publicPath: clientConfig.output.publicPath, 34 | noInfo: true 35 | }) 36 | app.use(devMiddleware) 37 | clientCompiler.plugin('done', stats => { 38 | stats = stats.toJson() 39 | stats.errors.forEach(err => console.error(err)) 40 | stats.warnings.forEach(err => console.warn(err)) 41 | if (stats.errors.length) return 42 | 43 | clientManifest = JSON.parse(readFile( 44 | devMiddleware.fileSystem, 45 | 'vue-ssr-client-manifest.json' 46 | )) 47 | if (bundle) { 48 | ready(bundle, { 49 | clientManifest 50 | }) 51 | } 52 | }) 53 | 54 | // hot middleware 55 | app.use(require('webpack-hot-middleware')(clientCompiler, { heartbeat: 5000 })) 56 | 57 | // watch and update server renderer 58 | const serverCompiler = webpack(serverConfig) 59 | const mfs = new MFS() 60 | serverCompiler.outputFileSystem = mfs 61 | serverCompiler.watch({}, (err, stats) => { 62 | if (err) throw err 63 | stats = stats.toJson() 64 | if (stats.errors.length) return 65 | 66 | // read bundle generated by vue-ssr-webpack-plugin 67 | bundle = JSON.parse(readFile(mfs, 'vue-ssr-server-bundle.json')) 68 | if (clientManifest) { 69 | ready(bundle, { 70 | clientManifest 71 | }) 72 | } 73 | }) 74 | 75 | return readyPromise 76 | } 77 | -------------------------------------------------------------------------------- /build/vue-loader.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extractCSS: process.env.NODE_ENV === 'production', 3 | preserveWhitespace: false, 4 | postcss: [ 5 | require('autoprefixer')({ 6 | browsers: ['last 3 versions'] 7 | }) 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /build/webpack.base.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const webpack = require('webpack') 3 | const vueConfig = require('./vue-loader.config') 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 5 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 6 | 7 | const isProd = process.env.NODE_ENV === 'production' 8 | 9 | module.exports = { 10 | devtool: isProd ? 11 | false : 12 | '#cheap-module-source-map', 13 | output: { 14 | path: path.resolve(__dirname, '../dist'), 15 | publicPath: '/dist/', 16 | filename: '[name].[chunkhash].js', 17 | chunkFilename: '[name].[chunkhash].js' 18 | }, 19 | resolve: { 20 | extensions: ['.js', '.vue', '.json'], 21 | alias: { 22 | // 'echarts': 'echarts/dist/echarts.common.min.js', 23 | 'vue': 'vue/dist/vue.runtime.min.js', 24 | '@': path.resolve('src'), 25 | 'R': path.resolve('src/components') 26 | } 27 | }, 28 | module: { 29 | noParse: /es6-promise\.js$/, // avoid webpack shimming process 30 | rules: [{ 31 | test: /\.vue$/, 32 | loader: 'vue-loader', 33 | options: vueConfig 34 | }, 35 | { 36 | test: /\.js$/, 37 | loader: 'babel-loader', 38 | exclude: /node_modules/ 39 | }, 40 | { 41 | test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/, 42 | loader: 'url-loader', 43 | options: { 44 | limit: 10000, 45 | name: '[name].[ext]?[hash]' 46 | } 47 | }, 48 | { 49 | test: /\.(less|css)$/, 50 | use: isProd ? 51 | ExtractTextPlugin.extract({ 52 | use: ['css-loader?minimize','less-loader'], 53 | fallback: 'vue-style-loader' 54 | }) : 55 | ['vue-style-loader', 'css-loader', 'less-loader'] 56 | } 57 | ] 58 | }, 59 | performance: { 60 | maxEntrypointSize: 300000, 61 | hints: isProd ? 'warning' : false 62 | }, 63 | plugins: isProd ? 64 | [ 65 | new webpack.optimize.UglifyJsPlugin({ 66 | compress: { 67 | warnings: false, 68 | drop_debugger: true, 69 | drop_console: true 70 | }, 71 | sourceMap: false // true 72 | }), 73 | new ExtractTextPlugin({ 74 | filename: 'common.[chunkhash].css' 75 | }), 76 | new ExtractTextPlugin({ 77 | filename: 'common.[chunkhash].less' 78 | }) 79 | ] : 80 | [ 81 | new FriendlyErrorsPlugin() 82 | ] 83 | } 84 | -------------------------------------------------------------------------------- /build/webpack.client.config.js: -------------------------------------------------------------------------------- 1 | const glob = require('glob') 2 | const webpack = require('webpack') 3 | const merge = require('webpack-merge') 4 | const base = require('./webpack.base.config') 5 | const SWPrecachePlugin = require('sw-precache-webpack-plugin') 6 | const VueSSRClientPlugin = require('vue-server-renderer/client-plugin') 7 | const config = merge(base, { 8 | entry: { 9 | app: './src/entry-client.js', 10 | vendors: ['lodash', 'axios'], 11 | vues: ['vue', 'vuex', 'vue-router'] 12 | }, 13 | plugins: [ 14 | // strip dev-only code in Vue source 15 | new webpack.DefinePlugin({ 16 | 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'), 17 | 'process.env.STATS': JSON.stringify(process.env.NODE_ENV || 'dev'), 18 | 'process.env.VUE_ENV': '"client"' 19 | }), 20 | // extract vendor chunks for better caching 21 | // new webpack.optimize.CommonsChunkPlugin({ 22 | // name: ['vendors'], 23 | // minChunks: function(module) { 24 | // // a module is extracted into the vendor chunk if... 25 | // return ( 26 | // // it's inside node_modules 27 | // /node_modules/.test(module.context) && 28 | // // and not a CSS file (due to extract-text-webpack-plugin limitation) 29 | // !/\.css$/.test(module.request) 30 | // ) 31 | // } 32 | // }), 33 | new webpack.optimize.CommonsChunkPlugin({ 34 | names: ['vendors', 'vues'], 35 | minChunks: 3 36 | }), 37 | // 重要信息:这将 webpack 运行时分离到一个引导 chunk 中, 38 | // 以便可以在之后正确注入异步 chunk。 39 | // 这也为你的 应用程序/vendor 代码提供了更好的缓存。 40 | new webpack.optimize.CommonsChunkPlugin({ 41 | name: 'manifest', 42 | // minChunks: Infinity 43 | chunks: ['vendors', 'vues'] 44 | }), 45 | // 此插件在输出目录中 46 | // 生成 `vue-ssr-client-manifest.json`。 47 | new VueSSRClientPlugin() 48 | ] 49 | }) 50 | 51 | if (process.env.NODE_ENV === 'production') { 52 | config.plugins.push( 53 | // auto generate service worker 54 | new SWPrecachePlugin({ 55 | cacheId: 'ga-vue', 56 | filename: 'service-worker.js', 57 | minify: true, 58 | dontCacheBustUrlsMatching: /\.\w{8}\./, 59 | staticFileGlobsIgnorePatterns: [/\.map$/, /\.json$/] 60 | }) 61 | ) 62 | } 63 | 64 | module.exports = config 65 | -------------------------------------------------------------------------------- /build/webpack.server.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const merge = require('webpack-merge') 3 | const base = require('./webpack.base.config') 4 | const nodeExternals = require('webpack-node-externals') 5 | const VueSSRServerPlugin = require('vue-server-renderer/server-plugin') 6 | 7 | module.exports = merge(base, { 8 | // 这允许 webpack 以 Node 适用方式(Node-appropriate fashion)处理动态导入(dynamic import), 9 | // 并且还会在编译 Vue 组件时, 10 | // 告知 `vue-loader` 输送面向服务器代码(server-oriented code)。 11 | target: 'node', 12 | // 对 bundle renderer 提供 source map 支持 13 | devtool: '#source-map', 14 | entry: './src/entry-server.js', 15 | // 此处告知 server bundle 使用 Node 风格导出模块(Node-style exports) 16 | output: { 17 | filename: 'server-bundle.js', 18 | libraryTarget: 'commonjs2' 19 | }, 20 | // 外置化应用程序依赖模块。可以使服务器构建速度更快, 21 | // 并生成较小的 bundle 文件。 22 | externals: nodeExternals({ 23 | whitelist: /\.css$/ 24 | }), 25 | plugins: [ 26 | new webpack.DefinePlugin({ 27 | 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'), 28 | 'process.env.VUE_ENV': '"server"' 29 | }), 30 | // 这是将服务器的整个输出 31 | // 构建为单个 JSON 文件的插件。 32 | // 默认文件名为 `vue-ssr-server-bundle.json` 33 | new VueSSRServerPlugin() 34 | ] 35 | }) 36 | -------------------------------------------------------------------------------- /log/err.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wqzwh/vue-ssr/cca3e361f4921312c02fdb6ad66af1cf7c95d2c1/log/err.log -------------------------------------------------------------------------------- /log/out.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wqzwh/vue-ssr/cca3e361f4921312c02fdb6ad66af1cf7c95d2c1/log/out.log -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-ssr", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "dev": "node server", 8 | "start": "cross-env NODE_ENV=production node server", 9 | "build": "rimraf dist && npm run build:client && npm run build:server", 10 | "build:client": "cross-env NODE_ENV=production webpack --config build/webpack.client.config.js --progress --hide-modules", 11 | "build:server": "cross-env NODE_ENV=production webpack --config build/webpack.server.config.js --progress --hide-modules" 12 | }, 13 | "author": "wangqi", 14 | "license": "ISC", 15 | "dependencies": { 16 | "axios": "^0.19.0", 17 | "es6-promise": "^4.1.1", 18 | "express": "^4.15.4", 19 | "lodash": "^4.17.4", 20 | "q": "git+https://github.com/kriskowal/q.git", 21 | "qs": "^6.5.0", 22 | "vue": "^2.4.2", 23 | "vue-router": "^2.7.0", 24 | "vue-server-renderer": "^2.4.2", 25 | "vuex": "^2.3.1" 26 | }, 27 | "devDependencies": { 28 | "autoprefixer": "^7.1.2", 29 | "babel-core": "^6.25.0", 30 | "babel-loader": "^7.1.1", 31 | "babel-plugin-syntax-dynamic-import": "^6.18.0", 32 | "babel-plugin-transform-runtime": "^6.22.0", 33 | "babel-preset-env": "^1.6.0", 34 | "babel-preset-stage-2": "^6.22.0", 35 | "compression": "^1.7.1", 36 | "cross-env": "^5.0.5", 37 | "css-loader": "^0.28.4", 38 | "extract-text-webpack-plugin": "^3.0.0", 39 | "file-loader": "^0.11.2", 40 | "friendly-errors-webpack-plugin": "^1.6.1", 41 | "glob": "^7.1.2", 42 | "less": "^2.7.2", 43 | "less-loader": "^2.2.3", 44 | "lru-cache": "^4.1.1", 45 | "mockjs": "^1.0.1-beta3", 46 | "style-loader": "^0.19.0", 47 | "sw-precache-webpack-plugin": "^0.11.4", 48 | "url-loader": "^0.5.9", 49 | "vue-loader": "^13.0.4", 50 | "vue-style-loader": "^3.0.3", 51 | "vue-template-compiler": "^2.4.2", 52 | "vuex-router-sync": "^4.2.0", 53 | "webpack": "^3.5.0", 54 | "webpack-dev-middleware": "^1.12.0", 55 | "webpack-hot-middleware": "^2.18.2", 56 | "webpack-merge": "^4.1.0", 57 | "webpack-node-externals": "^1.6.0" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /pmlog.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "script": "./server.js", 4 | "exec_mode": "cluster", 5 | "error_file": "./log/err.log", 6 | "out_file": "./log/out.log", 7 | "merge_logs": true, 8 | "log_data_format":"YYYY-MM-DD HH:mm: Z", 9 | "instances":4, 10 | "watch":true 11 | } 12 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const Vue = require('vue') 2 | const express = require('express') 3 | const path = require('path') 4 | const LRU = require('lru-cache') 5 | const resolve = file => path.resolve(__dirname, file) 6 | const { createBundleRenderer } = require('vue-server-renderer') 7 | const fs = require('fs') 8 | const net = require('net') 9 | const http = require('http'); 10 | const compression = require('compression'); 11 | 12 | 13 | const template = fs.readFileSync('./src/index.template.html', 'utf-8') 14 | const isProd = process.env.NODE_ENV === 'production' 15 | 16 | const server = express() 17 | 18 | function createRenderer (bundle, options) { 19 | return createBundleRenderer(bundle, Object.assign(options, { 20 | template: template, 21 | cache: LRU({ 22 | max: 1000, 23 | maxAge: 1000 * 60 * 15 24 | }), 25 | basedir: resolve('./dist'), 26 | runInNewContext: false 27 | })) 28 | } 29 | 30 | let renderer; 31 | 32 | let readyPromise 33 | if (isProd) { 34 | const bundle = require('./dist/vue-ssr-server-bundle.json') 35 | const clientManifest = require('./dist/vue-ssr-client-manifest.json') 36 | renderer = createRenderer(bundle, { 37 | clientManifest 38 | }) 39 | } else { 40 | readyPromise = require('./build/setup-dev-server')(server, (bundle, options) => { 41 | renderer = createRenderer(bundle, options) 42 | }) 43 | } 44 | 45 | 46 | const serve = (path, cache) => express.static(resolve(path), { 47 | maxAge: cache && isProd ? 1000 * 60 * 60 * 24 * 30 : 0 48 | }) 49 | server.use(compression()) 50 | server.use('/dist', serve('./dist', true)) 51 | server.use('/static', serve('./src/static', true)) 52 | server.use('/service-worker.js', serve('./dist/service-worker.js')) 53 | 54 | 55 | server.get('*', (req, res) => { 56 | const context = { 57 | title: '网易严选', 58 | url: req.url 59 | } 60 | renderer.renderToString(context, (err, html) => { 61 | if (err) { 62 | res.status(500).end('Internal Server Error') 63 | return 64 | } 65 | res.end(html) 66 | }) 67 | }) 68 | 69 | function probe(port, callback) { 70 | let servers = net.createServer().listen(port) 71 | let calledOnce = false 72 | let timeoutRef = setTimeout(function() { 73 | calledOnce = true 74 | callback(false, port) 75 | }, 2000) 76 | timeoutRef.unref() 77 | let connected = false 78 | 79 | servers.on('listening', function() { 80 | clearTimeout(timeoutRef) 81 | if (servers) 82 | servers.close() 83 | if (!calledOnce) { 84 | calledOnce = true 85 | callback(true, port) 86 | } 87 | }) 88 | 89 | servers.on('error', function(err) { 90 | clearTimeout(timeoutRef) 91 | let result = true 92 | if (err.code === 'EADDRINUSE') 93 | result = false 94 | if (!calledOnce) { 95 | calledOnce = true 96 | callback(result, port) 97 | } 98 | }) 99 | } 100 | const checkPortPromise = new Promise((resolve) => { 101 | (function serverport(_port = 6180) { 102 | // let pt = _port || 8080; 103 | let pt = _port; 104 | probe(pt, function(bl, _pt) { 105 | // 端口被占用 bl 返回false 106 | // _pt:传入的端口号 107 | if (bl === true) { 108 | // console.log("\n Static file server running at" + "\n\n=> http://localhost:" + _pt + '\n'); 109 | resolve(_pt); 110 | } else { 111 | serverport(_pt + 1) 112 | } 113 | }) 114 | })() 115 | 116 | }) 117 | checkPortPromise.then(data => { 118 | uri = 'http://localhost:' + data; 119 | console.log('启动服务路径'+uri) 120 | server.listen(data); 121 | }); 122 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 13 | -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import { createRouter } from './router' 4 | import { createStore } from './store' 5 | import { sync } from 'vuex-router-sync' 6 | require('./assets/style/css.less'); 7 | export function createApp () { 8 | // 创建 router 和 store 实例 9 | const router = createRouter() 10 | const store = createStore() 11 | // 同步路由状态(route state)到 store 12 | sync(store, router) 13 | // 创建应用程序实例,将 router 和 store 注入 14 | const app = new Vue({ 15 | router, 16 | store, 17 | render: h => h(App) 18 | }) 19 | // 暴露 app, router 和 store。 20 | return { app, router, store } 21 | } -------------------------------------------------------------------------------- /src/assets/views/index.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | .m-ftWrap { 3 | border-top: 1px solid rgba(0, 0, 0, .15); 4 | background-color: #414141 5 | } 6 | 7 | .m-ft { 8 | text-align: center; 9 | padding: .72rem .26667rem .37333rem 10 | } 11 | 12 | .m-ft .goApp, 13 | .m-ft .goWeb { 14 | width: 2.29333rem; 15 | font-size: .32rem; 16 | color: #fff 17 | } 18 | 19 | .swiper-slide, 20 | .swiper-wrapper { 21 | width: 100%; 22 | height: 100%; 23 | position: relative 24 | } 25 | 26 | .m-ft .goApp { 27 | margin-right: .66667rem 28 | } 29 | 30 | .m-ft .copyright { 31 | margin-top: .48rem; 32 | font-size: .32rem; 33 | line-height: .42667rem; 34 | color: #999 35 | } 36 | 37 | .swiper-container { 38 | margin-left: auto; 39 | margin-right: auto; 40 | position: relative; 41 | overflow: hidden; 42 | z-index: 1 43 | } 44 | 45 | .swiper-container-no-flexbox .swiper-slide { 46 | float: left 47 | } 48 | 49 | .swiper-container-vertical>.swiper-wrapper { 50 | -webkit-box-orient: vertical; 51 | -moz-box-orient: vertical; 52 | -ms-flex-direction: column; 53 | -webkit-flex-direction: column; 54 | flex-direction: column 55 | } 56 | 57 | .swiper-wrapper { 58 | z-index: 1; 59 | display: -webkit-box; 60 | display: -moz-box; 61 | display: -ms-flexbox; 62 | display: -webkit-flex; 63 | display: flex; 64 | -webkit-transition-property: -webkit-transform; 65 | -moz-transition-property: -moz-transform; 66 | -o-transition-property: -o-transform; 67 | -ms-transition-property: -ms-transform; 68 | transition-property: -webkit-transform; 69 | transition-property: transform; 70 | transition-property: transform, -webkit-transform; 71 | -webkit-box-sizing: content-box; 72 | -moz-box-sizing: content-box; 73 | box-sizing: content-box 74 | } 75 | 76 | .swiper-container-android .swiper-slide, 77 | .swiper-wrapper { 78 | -webkit-transform: translate3d(0, 0, 0); 79 | -moz-transform: translate3d(0, 0, 0); 80 | -o-transform: translate(0, 0); 81 | -ms-transform: translate3d(0, 0, 0); 82 | transform: translate3d(0, 0, 0) 83 | } 84 | 85 | .swiper-container-multirow>.swiper-wrapper { 86 | -webkit-box-lines: multiple; 87 | -moz-box-lines: multiple; 88 | -ms-flex-wrap: wrap; 89 | -webkit-flex-wrap: wrap; 90 | flex-wrap: wrap 91 | } 92 | 93 | .swiper-container-free-mode>.swiper-wrapper { 94 | -webkit-transition-timing-function: ease-out; 95 | -moz-transition-timing-function: ease-out; 96 | -ms-transition-timing-function: ease-out; 97 | -o-transition-timing-function: ease-out; 98 | transition-timing-function: ease-out; 99 | margin: 0 auto 100 | } 101 | 102 | .swiper-slide { 103 | -webkit-flex-shrink: 0; 104 | -ms-flex: 0 0 auto; 105 | -ms-flex-negative: 0; 106 | flex-shrink: 0 107 | } 108 | 109 | .swiper-container-autoheight, 110 | .swiper-container-autoheight .swiper-slide { 111 | height: auto 112 | } 113 | 114 | .swiper-container-autoheight .swiper-wrapper { 115 | -webkit-box-align: start; 116 | -ms-flex-align: start; 117 | -webkit-align-items: flex-start; 118 | -ms-grid-row-align: flex-start; 119 | align-items: flex-start; 120 | -webkit-transition-property: -webkit-transform, height; 121 | -moz-transition-property: -moz-transform; 122 | -o-transition-property: -o-transform; 123 | -ms-transition-property: -ms-transform; 124 | transition-property: height, -webkit-transform; 125 | transition-property: transform, height; 126 | transition-property: transform, height, -webkit-transform 127 | } 128 | 129 | .swiper-container .swiper-notification { 130 | position: absolute; 131 | left: 0; 132 | top: 0; 133 | pointer-events: none; 134 | opacity: 0; 135 | z-index: -1000 136 | } 137 | 138 | .swiper-wp8-horizontal { 139 | -ms-touch-action: pan-y; 140 | touch-action: pan-y 141 | } 142 | 143 | .swiper-wp8-vertical { 144 | -ms-touch-action: pan-x; 145 | touch-action: pan-x 146 | } 147 | 148 | .swiper-button-next, 149 | .swiper-button-prev { 150 | position: absolute; 151 | top: 50%; 152 | width: 27px; 153 | height: 44px; 154 | margin-top: -22px; 155 | z-index: 10; 156 | cursor: pointer; 157 | -moz-background-size: 27px 44px; 158 | -webkit-background-size: 27px 44px; 159 | background-size: 27px 44px; 160 | background-position: center; 161 | background-repeat: no-repeat 162 | } 163 | 164 | .swiper-button-next.swiper-button-disabled, 165 | .swiper-button-prev.swiper-button-disabled { 166 | opacity: .35; 167 | cursor: auto; 168 | pointer-events: none 169 | } 170 | 171 | .swiper-button-prev, 172 | .swiper-container-rtl .swiper-button-next { 173 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E"); 174 | left: 10px; 175 | right: auto 176 | } 177 | 178 | .swiper-button-prev.swiper-button-black, 179 | .swiper-container-rtl .swiper-button-next.swiper-button-black { 180 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E") 181 | } 182 | 183 | .swiper-button-prev.swiper-button-white, 184 | .swiper-container-rtl .swiper-button-next.swiper-button-white { 185 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E") 186 | } 187 | 188 | .swiper-button-next, 189 | .swiper-container-rtl .swiper-button-prev { 190 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E"); 191 | right: 10px; 192 | left: auto 193 | } 194 | 195 | .swiper-button-next.swiper-button-black, 196 | .swiper-container-rtl .swiper-button-prev.swiper-button-black { 197 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E") 198 | } 199 | 200 | .swiper-button-next.swiper-button-white, 201 | .swiper-container-rtl .swiper-button-prev.swiper-button-white { 202 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E") 203 | } 204 | 205 | .swiper-pagination { 206 | position: absolute; 207 | text-align: center; 208 | -webkit-transition: .3s; 209 | -moz-transition: .3s; 210 | -o-transition: .3s; 211 | transition: .3s; 212 | -webkit-transform: translate3d(0, 0, 0); 213 | -ms-transform: translate3d(0, 0, 0); 214 | -o-transform: translate3d(0, 0, 0); 215 | transform: translate3d(0, 0, 0); 216 | z-index: 10 217 | } 218 | 219 | .swiper-pagination.swiper-pagination-hidden { 220 | opacity: 0 221 | } 222 | 223 | .swiper-container-horizontal>.swiper-pagination-bullets, 224 | .swiper-pagination-custom, 225 | .swiper-pagination-fraction { 226 | bottom: 10px; 227 | left: 0; 228 | width: 100% 229 | } 230 | 231 | .swiper-pagination-bullet { 232 | width: 8px; 233 | height: 8px; 234 | display: inline-block; 235 | border-radius: 100%; 236 | background: #000; 237 | opacity: .2 238 | } 239 | 240 | button.swiper-pagination-bullet { 241 | border: none; 242 | margin: 0; 243 | padding: 0; 244 | box-shadow: none; 245 | -moz-appearance: none; 246 | -ms-appearance: none; 247 | -webkit-appearance: none; 248 | appearance: none 249 | } 250 | 251 | .swiper-pagination-clickable .swiper-pagination-bullet { 252 | cursor: pointer 253 | } 254 | 255 | .swiper-pagination-white .swiper-pagination-bullet { 256 | background: #fff 257 | } 258 | 259 | .swiper-pagination-bullet-active { 260 | opacity: 1; 261 | background: #007aff 262 | } 263 | 264 | .swiper-pagination-white .swiper-pagination-bullet-active { 265 | background: #fff 266 | } 267 | 268 | .swiper-pagination-black .swiper-pagination-bullet-active { 269 | background: #000 270 | } 271 | 272 | .swiper-container-vertical>.swiper-pagination-bullets { 273 | right: 10px; 274 | top: 50%; 275 | -webkit-transform: translate3d(0, -50%, 0); 276 | -moz-transform: translate3d(0, -50%, 0); 277 | -o-transform: translate(0, -50%); 278 | -ms-transform: translate3d(0, -50%, 0); 279 | transform: translate3d(0, -50%, 0) 280 | } 281 | 282 | .swiper-container-vertical>.swiper-pagination-bullets .swiper-pagination-bullet { 283 | margin: 5px 0; 284 | display: block 285 | } 286 | 287 | .swiper-container-horizontal>.swiper-pagination-bullets .swiper-pagination-bullet { 288 | margin: 0 5px 289 | } 290 | 291 | .swiper-pagination-progress { 292 | background: rgba(0, 0, 0, .25); 293 | position: absolute 294 | } 295 | 296 | .swiper-pagination-progress .swiper-pagination-progressbar { 297 | background: #007aff; 298 | position: absolute; 299 | left: 0; 300 | top: 0; 301 | width: 100%; 302 | height: 100%; 303 | -webkit-transform: scale(0); 304 | -ms-transform: scale(0); 305 | -o-transform: scale(0); 306 | transform: scale(0); 307 | -webkit-transform-origin: left top; 308 | -moz-transform-origin: left top; 309 | -ms-transform-origin: left top; 310 | -o-transform-origin: left top; 311 | transform-origin: left top 312 | } 313 | 314 | .swiper-container-rtl .swiper-pagination-progress .swiper-pagination-progressbar { 315 | -webkit-transform-origin: right top; 316 | -moz-transform-origin: right top; 317 | -ms-transform-origin: right top; 318 | -o-transform-origin: right top; 319 | transform-origin: right top 320 | } 321 | 322 | .swiper-container-horizontal>.swiper-pagination-progress { 323 | width: 100%; 324 | height: 4px; 325 | left: 0; 326 | top: 0 327 | } 328 | 329 | .swiper-container-vertical>.swiper-pagination-progress { 330 | width: 4px; 331 | height: 100%; 332 | left: 0; 333 | top: 0 334 | } 335 | 336 | .swiper-pagination-progress.swiper-pagination-white { 337 | background: rgba(255, 255, 255, .5) 338 | } 339 | 340 | .swiper-pagination-progress.swiper-pagination-white .swiper-pagination-progressbar { 341 | background: #fff 342 | } 343 | 344 | .swiper-pagination-progress.swiper-pagination-black .swiper-pagination-progressbar { 345 | background: #000 346 | } 347 | 348 | .swiper-container-3d { 349 | -webkit-perspective: 1200px; 350 | -moz-perspective: 1200px; 351 | -o-perspective: 1200px; 352 | perspective: 1200px 353 | } 354 | 355 | .swiper-container-3d .swiper-cube-shadow, 356 | .swiper-container-3d .swiper-slide, 357 | .swiper-container-3d .swiper-slide-shadow-bottom, 358 | .swiper-container-3d .swiper-slide-shadow-left, 359 | .swiper-container-3d .swiper-slide-shadow-right, 360 | .swiper-container-3d .swiper-slide-shadow-top, 361 | .swiper-container-3d .swiper-wrapper { 362 | -webkit-transform-style: preserve-3d; 363 | -moz-transform-style: preserve-3d; 364 | -ms-transform-style: preserve-3d; 365 | transform-style: preserve-3d 366 | } 367 | 368 | .swiper-container-3d .swiper-slide-shadow-bottom, 369 | .swiper-container-3d .swiper-slide-shadow-left, 370 | .swiper-container-3d .swiper-slide-shadow-right, 371 | .swiper-container-3d .swiper-slide-shadow-top { 372 | position: absolute; 373 | left: 0; 374 | top: 0; 375 | width: 100%; 376 | height: 100%; 377 | pointer-events: none; 378 | z-index: 10 379 | } 380 | 381 | .swiper-container-3d .swiper-slide-shadow-left { 382 | background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(transparent)); 383 | background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, .5), transparent); 384 | background-image: -moz-linear-gradient(right, rgba(0, 0, 0, .5), transparent); 385 | background-image: -o-linear-gradient(right, rgba(0, 0, 0, .5), transparent); 386 | background-image: linear-gradient(to left, rgba(0, 0, 0, .5), transparent) 387 | } 388 | 389 | .swiper-container-3d .swiper-slide-shadow-right { 390 | background-image: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, .5)), to(transparent)); 391 | background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5), transparent); 392 | background-image: -moz-linear-gradient(left, rgba(0, 0, 0, .5), transparent); 393 | background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5), transparent); 394 | background-image: linear-gradient(to right, rgba(0, 0, 0, .5), transparent) 395 | } 396 | 397 | .swiper-container-3d .swiper-slide-shadow-top { 398 | background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, .5)), to(transparent)); 399 | background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, .5), transparent); 400 | background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, .5), transparent); 401 | background-image: -o-linear-gradient(bottom, rgba(0, 0, 0, .5), transparent); 402 | background-image: linear-gradient(to top, rgba(0, 0, 0, .5), transparent) 403 | } 404 | 405 | .swiper-container-3d .swiper-slide-shadow-bottom { 406 | background-image: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, .5)), to(transparent)); 407 | background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, .5), transparent); 408 | background-image: -moz-linear-gradient(top, rgba(0, 0, 0, .5), transparent); 409 | background-image: -o-linear-gradient(top, rgba(0, 0, 0, .5), transparent); 410 | background-image: linear-gradient(to bottom, rgba(0, 0, 0, .5), transparent) 411 | } 412 | 413 | .swiper-container-coverflow .swiper-wrapper, 414 | .swiper-container-flip .swiper-wrapper { 415 | -ms-perspective: 1200px 416 | } 417 | 418 | .swiper-container-cube, 419 | .swiper-container-flip { 420 | overflow: visible 421 | } 422 | 423 | .swiper-container-cube .swiper-slide, 424 | .swiper-container-flip .swiper-slide { 425 | pointer-events: none; 426 | -webkit-backface-visibility: hidden; 427 | -moz-backface-visibility: hidden; 428 | -ms-backface-visibility: hidden; 429 | backface-visibility: hidden; 430 | z-index: 1 431 | } 432 | 433 | .swiper-container-cube .swiper-slide .swiper-slide, 434 | .swiper-container-flip .swiper-slide .swiper-slide { 435 | pointer-events: none 436 | } 437 | 438 | .swiper-container-cube .swiper-slide-active, 439 | .swiper-container-cube .swiper-slide-active .swiper-slide-active, 440 | .swiper-container-flip .swiper-slide-active, 441 | .swiper-container-flip .swiper-slide-active .swiper-slide-active { 442 | pointer-events: auto 443 | } 444 | 445 | .swiper-container-cube .swiper-slide-shadow-bottom, 446 | .swiper-container-cube .swiper-slide-shadow-left, 447 | .swiper-container-cube .swiper-slide-shadow-right, 448 | .swiper-container-cube .swiper-slide-shadow-top, 449 | .swiper-container-flip .swiper-slide-shadow-bottom, 450 | .swiper-container-flip .swiper-slide-shadow-left, 451 | .swiper-container-flip .swiper-slide-shadow-right, 452 | .swiper-container-flip .swiper-slide-shadow-top { 453 | z-index: 0; 454 | -webkit-backface-visibility: hidden; 455 | -moz-backface-visibility: hidden; 456 | -ms-backface-visibility: hidden; 457 | backface-visibility: hidden 458 | } 459 | 460 | .swiper-container-cube .swiper-slide { 461 | visibility: hidden; 462 | -webkit-transform-origin: 0 0; 463 | -moz-transform-origin: 0 0; 464 | -ms-transform-origin: 0 0; 465 | transform-origin: 0 0; 466 | width: 100%; 467 | height: 100% 468 | } 469 | 470 | .swiper-container-cube.swiper-container-rtl .swiper-slide { 471 | -webkit-transform-origin: 100% 0; 472 | -moz-transform-origin: 100% 0; 473 | -ms-transform-origin: 100% 0; 474 | transform-origin: 100% 0 475 | } 476 | 477 | .swiper-container-cube .swiper-slide-active, 478 | .swiper-container-cube .swiper-slide-next, 479 | .swiper-container-cube .swiper-slide-next+.swiper-slide, 480 | .swiper-container-cube .swiper-slide-prev { 481 | pointer-events: auto; 482 | visibility: visible 483 | } 484 | 485 | .swiper-container-cube .swiper-cube-shadow { 486 | position: absolute; 487 | left: 0; 488 | bottom: 0; 489 | width: 100%; 490 | height: 100%; 491 | background: #000; 492 | opacity: .6; 493 | -webkit-filter: blur(50px); 494 | filter: blur(50px); 495 | z-index: 0 496 | } 497 | 498 | .swiper-container-fade.swiper-container-free-mode .swiper-slide { 499 | -webkit-transition-timing-function: ease-out; 500 | -moz-transition-timing-function: ease-out; 501 | -ms-transition-timing-function: ease-out; 502 | -o-transition-timing-function: ease-out; 503 | transition-timing-function: ease-out 504 | } 505 | 506 | .swiper-container-fade .swiper-slide { 507 | pointer-events: none; 508 | -webkit-transition-property: opacity; 509 | -moz-transition-property: opacity; 510 | -o-transition-property: opacity; 511 | transition-property: opacity 512 | } 513 | 514 | .swiper-container-fade .swiper-slide .swiper-slide { 515 | pointer-events: none 516 | } 517 | 518 | .swiper-container-fade .swiper-slide-active, 519 | .swiper-container-fade .swiper-slide-active .swiper-slide-active { 520 | pointer-events: auto 521 | } 522 | 523 | .swiper-zoom-container { 524 | width: 100%; 525 | height: 100%; 526 | display: -webkit-box; 527 | display: -moz-box; 528 | display: -ms-flexbox; 529 | display: -webkit-flex; 530 | display: flex; 531 | -webkit-box-pack: center; 532 | -moz-box-pack: center; 533 | -ms-flex-pack: center; 534 | -webkit-justify-content: center; 535 | justify-content: center; 536 | -webkit-box-align: center; 537 | -moz-box-align: center; 538 | -ms-flex-align: center; 539 | -webkit-align-items: center; 540 | align-items: center; 541 | text-align: center 542 | } 543 | 544 | .swiper-zoom-container>canvas, 545 | .swiper-zoom-container>img, 546 | .swiper-zoom-container>svg { 547 | max-width: 100%; 548 | max-height: 100%; 549 | object-fit: contain 550 | } 551 | 552 | .swiper-scrollbar { 553 | border-radius: 10px; 554 | position: relative; 555 | -ms-touch-action: none; 556 | background: rgba(0, 0, 0, .1) 557 | } 558 | 559 | .swiper-container-horizontal>.swiper-scrollbar { 560 | position: absolute; 561 | left: 1%; 562 | bottom: 3px; 563 | z-index: 50; 564 | height: 5px; 565 | width: 98% 566 | } 567 | 568 | .swiper-container-vertical>.swiper-scrollbar { 569 | position: absolute; 570 | right: 3px; 571 | top: 1%; 572 | z-index: 50; 573 | width: 5px; 574 | height: 98% 575 | } 576 | 577 | .swiper-scrollbar-drag { 578 | height: 100%; 579 | width: 100%; 580 | position: relative; 581 | background: rgba(0, 0, 0, .5); 582 | border-radius: 10px; 583 | left: 0; 584 | top: 0 585 | } 586 | 587 | .swiper-scrollbar-cursor-drag { 588 | cursor: move 589 | } 590 | 591 | .swiper-lazy-preloader { 592 | width: 42px; 593 | height: 42px; 594 | position: absolute; 595 | left: 50%; 596 | top: 50%; 597 | margin-left: -21px; 598 | margin-top: -21px; 599 | z-index: 10; 600 | -webkit-transform-origin: 50%; 601 | -moz-transform-origin: 50%; 602 | transform-origin: 50%; 603 | -webkit-animation: swiper-preloader-spin 1s steps(12, end) infinite; 604 | -moz-animation: swiper-preloader-spin 1s steps(12, end) infinite; 605 | animation: swiper-preloader-spin 1s steps(12, end) infinite 606 | } 607 | 608 | .swiper-lazy-preloader:after { 609 | display: block; 610 | content: ""; 611 | width: 100%; 612 | height: 100%; 613 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); 614 | background-position: 50%; 615 | -webkit-background-size: 100%; 616 | background-size: 100%; 617 | background-repeat: no-repeat 618 | } 619 | 620 | .swiper-lazy-preloader-white:after { 621 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") 622 | } 623 | 624 | @-webkit-keyframes swiper-preloader-spin { 625 | 100% { 626 | -webkit-transform: rotate(360deg) 627 | } 628 | } 629 | 630 | @keyframes swiper-preloader-spin { 631 | 100% { 632 | -webkit-transform: rotate(360deg); 633 | transform: rotate(360deg) 634 | } 635 | } 636 | 637 | .m-slide { 638 | position: relative; 639 | width: 100%; 640 | padding-top: 100%; 641 | overflow: hidden 642 | } 643 | 644 | .m-slide .slide-con { 645 | position: absolute; 646 | left: 0; 647 | top: 0; 648 | width: 100%; 649 | height: 100% 650 | } 651 | 652 | .m-slide .swiper-container { 653 | width: 100%; 654 | height: 100% 655 | } 656 | 657 | .m-slide .swiper-container img { 658 | width: 100%; 659 | height: 100%; 660 | background-color: #f9f9f9 661 | } 662 | 663 | .m-slide .swiper-container-horizontal>.swiper-pagination { 664 | bottom: .4rem; 665 | width: 100% 666 | } 667 | 668 | .m-slide .swiper-container-horizontal>.swiper-pagination.detail-pagination-up { 669 | bottom: 1.36rem 670 | } 671 | 672 | .m-slide .swiper-container-horizontal>.swiper-pagination .swiper-pagination-bullet { 673 | margin: 0 .13333rem 0 0 674 | } 675 | 676 | .m-slide .swiper-pagination-bullet { 677 | width: .53333rem; 678 | height: .05333rem; 679 | display: inline-block; 680 | background: #fff; 681 | opacity: .4; 682 | border-radius: 0 683 | } 684 | 685 | .m-slide .swiper-pagination-bullet-active { 686 | opacity: 1; 687 | background: #fff; 688 | border-radius: 0 689 | } 690 | 691 | .m-slide .swiper-container-horizontal>.swiper-pagination-fraction { 692 | left: auto; 693 | right: .4rem; 694 | width: .72rem; 695 | height: .37333rem; 696 | line-height: .37333rem; 697 | border: 1px solid rgba(0, 0, 0, .15); 698 | font-size: .26667rem; 699 | text-align: center; 700 | color: #333; 701 | background-color: #fff; 702 | transition: 0s; 703 | border-radius: 4px; 704 | display: -webkit-box; 705 | display: -webkit-flex; 706 | display: -moz-flex; 707 | display: -ms-flexbox; 708 | display: flex; 709 | -webkit-box-pack: center; 710 | -ms-flex-pack: center; 711 | -webkit-justify-content: center; 712 | -moz-justify-content: center; 713 | justify-content: center; 714 | -webkit-box-align: center; 715 | -ms-flex-align: center; 716 | -webkit-align-items: center; 717 | -moz-align-items: center; 718 | align-items: center 719 | } 720 | 721 | [data-dpr="1"] .m-slide .swiper-container-horizontal>.swiper-pagination-fraction { 722 | border-radius: 2px; 723 | line-height: .42667rem 724 | } 725 | 726 | .m-slide .error { 727 | position: relative 728 | } 729 | 730 | .m-slide .error:before { 731 | content: ' '; 732 | display: block; 733 | position: absolute; 734 | z-index: 1; 735 | top: 0; 736 | left: 0; 737 | right: 0; 738 | bottom: 0; 739 | background-color: #f4f4f4; 740 | background-image: url(http://yanxuan.nosdn.127.net/f159d1b2ec1867ad1a73d5077fcca604.png); 741 | background-repeat: no-repeat; 742 | background-position: center; 743 | background-size: 2.29333rem 744 | } 745 | 746 | .m-tabBar, 747 | .m-tabs>header { 748 | display: -webkit-box; 749 | display: -webkit-flex; 750 | display: -moz-flex; 751 | display: -ms-flexbox; 752 | -webkit-flex-flow: row nowrap 753 | } 754 | 755 | .m-tabBar { 756 | display: flex; 757 | -moz-flex-flow: row nowrap; 758 | -ms-flex-flow: row nowrap; 759 | flex-flow: row nowrap; 760 | -webkit-box-align: center; 761 | -ms-flex-align: center; 762 | -webkit-align-items: center; 763 | -moz-align-items: center; 764 | align-items: center; 765 | -ms-flex-pack: distribute; 766 | -webkit-justify-content: space-around; 767 | -moz-justify-content: space-around; 768 | justify-content: space-around; 769 | position: fixed; 770 | z-index: 5; 771 | left: 0; 772 | bottom: 0; 773 | width: 100%; 774 | height: 1.30667rem; 775 | background-color: #fafafa; 776 | border-top: 1px solid #d9d9d9 777 | } 778 | 779 | .m-tabBar>.item { 780 | position: relative; 781 | text-align: center 782 | } 783 | 784 | .m-tabBar>.item .txt { 785 | display: block; 786 | margin-top: .09333rem; 787 | font-size: .32rem; 788 | color: #666; 789 | line-height: 1 790 | } 791 | 792 | .m-tabBar>.item .badge { 793 | position: absolute; 794 | top: -.01333rem; 795 | right: -.08rem 796 | } 797 | 798 | .m-tabBar>.item.active .txt { 799 | color: #b4282d 800 | } 801 | 802 | .m-badge { 803 | display: inline-block; 804 | width: .37333rem; 805 | height: .37333rem; 806 | border-radius: .18667rem; 807 | background-color: #b4282d; 808 | text-align: center; 809 | line-height: .37333rem; 810 | font-size: .24rem; 811 | color: #fff 812 | } 813 | 814 | .m-badge-1 { 815 | width: .48rem 816 | } 817 | 818 | .m-badge-2 { 819 | width: .64rem 820 | } 821 | 822 | .m-sticker, 823 | .m-sticker .img-swraper img { 824 | width: 1.06667rem; 825 | height: 1.06667rem 826 | } 827 | 828 | .m-sticker { 829 | border-radius: 100%; 830 | border: 1px solid #d9d9d9; 831 | position: absolute; 832 | background: #fff 833 | } 834 | 835 | .m-sticker .img-swraper:after { 836 | position: absolute; 837 | border-radius: 100%; 838 | color: #fff; 839 | content: '\9001'; 840 | text-align: center; 841 | background-color: #f48f18; 842 | width: .48rem; 843 | height: .48rem; 844 | line-height: .48rem; 845 | font-size: .26667rem; 846 | top: -.13333rem; 847 | left: -.13333rem 848 | } 849 | 850 | .m-tabs { 851 | width: 100% 852 | } 853 | 854 | .m-tabs>header { 855 | display: flex; 856 | -moz-flex-flow: row nowrap; 857 | -ms-flex-flow: row nowrap; 858 | flex-flow: row nowrap; 859 | background-color: #fff; 860 | position: relative 861 | } 862 | 863 | .m-tabs>header:after { 864 | content: ''; 865 | position: absolute; 866 | background-color: #d9d9d9; 867 | left: 0; 868 | width: 100%; 869 | height: 1px; 870 | -webkit-transform-origin: 50% 100% 0; 871 | transform-origin: 50% 100% 0; 872 | bottom: 0 873 | } 874 | 875 | [data-dpr="1"] .m-tabs>header:after { 876 | -webkit-transform: scale3d(1, .5, 1); 877 | -moz-transform: scale3d(1, .5, 1); 878 | -ms-transform: scale3d(1, .5, 1); 879 | -o-transform: scale3d(1, .5, 1); 880 | transform: scale3d(1, .5, 1) 881 | } 882 | 883 | .m-tabs>header .tab { 884 | display: -webkit-box; 885 | display: -webkit-flex; 886 | display: -moz-flex; 887 | display: -ms-flexbox; 888 | display: flex; 889 | -webkit-flex-flow: row nowrap; 890 | -moz-flex-flow: row nowrap; 891 | -ms-flex-flow: row nowrap; 892 | flex-flow: row nowrap; 893 | -webkit-box-align: center; 894 | -ms-flex-align: center; 895 | -webkit-align-items: center; 896 | -moz-align-items: center; 897 | align-items: center; 898 | -webkit-box-pack: center; 899 | -ms-flex-pack: center; 900 | -webkit-justify-content: center; 901 | -moz-justify-content: center; 902 | justify-content: center; 903 | position: relative; 904 | z-index: 1; 905 | text-align: center 906 | } 907 | 908 | .m-tabs>header .tab .txt { 909 | display: inline-block; 910 | padding: 0 .21333rem; 911 | line-height: .8rem; 912 | font-size: .37333rem; 913 | color: #333; 914 | text-align: center 915 | } 916 | 917 | .m-tabs>header .tab.active { 918 | color: #b4282d 919 | } 920 | 921 | .m-tabs>header .tab.active .txt { 922 | position: relative; 923 | color: #b4282d 924 | } 925 | 926 | .m-tabs>header .tab.active .txt:after { 927 | content: ' '; 928 | position: absolute; 929 | left: 0; 930 | bottom: 0; 931 | width: 100%; 932 | height: .05333rem; 933 | background-color: #b4282d 934 | } 935 | 936 | .m-tabs .panel { 937 | display: none 938 | } 939 | 940 | .m-tabs .panel.active { 941 | display: block 942 | } 943 | 944 | .m-tabs.scroll>header .inner, 945 | .m-tabs.scroll>header .list { 946 | display: -webkit-box; 947 | display: -webkit-flex; 948 | display: -moz-flex; 949 | display: -ms-flexbox 950 | } 951 | 952 | .m-tabs.scroll>header .inner { 953 | display: flex; 954 | -webkit-flex-flow: row nowrap; 955 | -moz-flex-flow: row nowrap; 956 | -ms-flex-flow: row nowrap; 957 | flex-flow: row nowrap 958 | } 959 | 960 | .m-tabs.scroll>header .list { 961 | display: flex; 962 | -webkit-flex-flow: row nowrap; 963 | -moz-flex-flow: row nowrap; 964 | -ms-flex-flow: row nowrap; 965 | flex-flow: row nowrap; 966 | -webkit-flex-shrink: 0; 967 | -moz-flex-shrink: 0; 968 | -ms-flex-negative: 0; 969 | flex-shrink: 0; 970 | padding: 0 .4rem; 971 | background: #fff 972 | } 973 | 974 | .m-tabs.scroll>header .tab { 975 | -webkit-flex-shrink: 0; 976 | -moz-flex-shrink: 0; 977 | -ms-flex-negative: 0; 978 | flex-shrink: 0; 979 | position: relative; 980 | margin-left: .64rem 981 | } 982 | 983 | .m-tabs.scroll>header .tab:first-of-type { 984 | margin-left: 0 985 | } 986 | 987 | .m-tabs.noScroll>header { 988 | -webkit-box-pack: justify; 989 | -ms-flex-pack: justify; 990 | -webkit-justify-content: space-between; 991 | -moz-justify-content: space-between; 992 | justify-content: space-between; 993 | padding: 0 .4rem 994 | } 995 | 996 | .m-tabs.noScroll>header .tab { 997 | -webkit-box-flex: 1; 998 | -webkit-flex-grow: 1; 999 | -moz-flex-grow: 1; 1000 | -ms-flex-positive: 1; 1001 | flex-grow: 1 1002 | } 1003 | 1004 | .m-tabs.withPanels>header .tab .txt { 1005 | padding-top: .6rem; 1006 | padding-bottom: .33333rem; 1007 | line-height: .45333rem 1008 | } 1009 | 1010 | .m-tabs.l>header { 1011 | height: 1.06667rem 1012 | } 1013 | 1014 | .m-tabs.l>header .tab .txt { 1015 | line-height: 1.06667rem 1016 | } 1017 | 1018 | .m-navForSpecificChannels { 1019 | display: -webkit-box; 1020 | display: -webkit-flex; 1021 | display: -moz-flex; 1022 | display: -ms-flexbox; 1023 | display: flex; 1024 | -webkit-flex-flow: row nowrap; 1025 | -moz-flex-flow: row nowrap; 1026 | -ms-flex-flow: row nowrap; 1027 | flex-flow: row nowrap; 1028 | -webkit-box-align: center; 1029 | -ms-flex-align: center; 1030 | -webkit-align-items: center; 1031 | -moz-align-items: center; 1032 | align-items: center; 1033 | -ms-flex-pack: distribute; 1034 | -webkit-justify-content: space-around; 1035 | -moz-justify-content: space-around; 1036 | justify-content: space-around; 1037 | height: 1.92rem; 1038 | background-color: #fff; 1039 | position: relative 1040 | } 1041 | 1042 | .m-navForSpecificChannels:after { 1043 | content: ''; 1044 | position: absolute; 1045 | background-color: #d9d9d9; 1046 | left: 0; 1047 | width: 100%; 1048 | height: 1px; 1049 | -webkit-transform-origin: 50% 100% 0; 1050 | transform-origin: 50% 100% 0; 1051 | bottom: 0 1052 | } 1053 | 1054 | [data-dpr="1"] .m-navForSpecificChannels:after { 1055 | -webkit-transform: scale3d(1, .5, 1); 1056 | -moz-transform: scale3d(1, .5, 1); 1057 | -ms-transform: scale3d(1, .5, 1); 1058 | -o-transform: scale3d(1, .5, 1); 1059 | transform: scale3d(1, .5, 1) 1060 | } 1061 | 1062 | .m-navForSpecificChannels .item { 1063 | position: relative; 1064 | text-align: center 1065 | } 1066 | 1067 | .m-navForSpecificChannels .item .txt { 1068 | margin-top: .13333rem; 1069 | font-size: .32rem; 1070 | color: #333 1071 | } 1072 | 1073 | .m-navForSpecificChannels .item .badge { 1074 | position: absolute; 1075 | top: -.01333rem; 1076 | right: -.08rem 1077 | } 1078 | 1079 | .m-wapNewUserEntrance { 1080 | position: fixed; 1081 | right: 0; 1082 | bottom: 3.2rem; 1083 | display: block; 1084 | z-index: 10; 1085 | -webkit-animation: .5s moveLeft; 1086 | animation: .5s moveLeft 1087 | } 1088 | 1089 | @-webkit-keyframes moveLeft { 1090 | from { 1091 | -webkit-transform: translateX(1.33333rem); 1092 | -moz-transform: translateX(1.33333rem); 1093 | -ms-transform: translateX(1.33333rem); 1094 | -o-transform: translateX(1.33333rem); 1095 | transform: translateX(1.33333rem) 1096 | } 1097 | to { 1098 | -webkit-transform: translateX(0); 1099 | -moz-transform: translateX(0); 1100 | -ms-transform: translateX(0); 1101 | -o-transform: translateX(0); 1102 | transform: translateX(0) 1103 | } 1104 | } 1105 | 1106 | @keyframes moveLeft { 1107 | from { 1108 | -webkit-transform: translateX(1.33333rem); 1109 | -moz-transform: translateX(1.33333rem); 1110 | -ms-transform: translateX(1.33333rem); 1111 | -o-transform: translateX(1.33333rem); 1112 | transform: translateX(1.33333rem) 1113 | } 1114 | to { 1115 | -webkit-transform: translateX(0); 1116 | -moz-transform: translateX(0); 1117 | -ms-transform: translateX(0); 1118 | -o-transform: translateX(0); 1119 | transform: translateX(0) 1120 | } 1121 | } 1122 | 1123 | .m-newUserItem { 1124 | margin-top: .66667rem; 1125 | background-color: #f4f4f4; 1126 | border-radius: .05333rem; 1127 | height: 3.09333rem; 1128 | width: 100%; 1129 | display: -webkit-box; 1130 | display: -webkit-flex; 1131 | display: -moz-flex; 1132 | display: -ms-flexbox; 1133 | display: flex 1134 | } 1135 | 1136 | .m-newUserItem .img>img { 1137 | width: 3.09333rem; 1138 | height: 3.09333rem 1139 | } 1140 | 1141 | .m-newUserItem .content { 1142 | margin-left: .10667rem; 1143 | -webkit-box-flex: 1; 1144 | -webkit-flex: 1; 1145 | -moz-box-flex: 1; 1146 | -moz-flex: 1; 1147 | -ms-flex: 1; 1148 | flex: 1; 1149 | padding: .57333rem 0 1150 | } 1151 | 1152 | .m-newUserItem .content .itemName { 1153 | font-size: .37333rem; 1154 | width: 3.73333rem; 1155 | text-overflow: ellipsis; 1156 | white-space: nowrap; 1157 | overflow: hidden 1158 | } 1159 | 1160 | .m-newUserItem .content .manu { 1161 | margin-top: .2rem 1162 | } 1163 | 1164 | .m-newUserItem .content .manu .manuTag { 1165 | border: 1px solid #7f7f7f; 1166 | border-radius: .05333rem; 1167 | padding: 0 .10667rem; 1168 | height: .48rem; 1169 | line-height: .48rem 1170 | } 1171 | 1172 | .m-newUserItem .content .price { 1173 | margin-top: .26667rem; 1174 | font-size: .37333rem 1175 | } 1176 | 1177 | .m-newUserItem .content .price .retailPrice { 1178 | color: #b4282d 1179 | } 1180 | 1181 | .m-newUserItem .content .price .comparePrice { 1182 | color: #999; 1183 | display: inline-block; 1184 | margin-left: .10667rem; 1185 | text-decoration: line-through 1186 | } 1187 | 1188 | .m-newWapUserGiftModal { 1189 | position: fixed; 1190 | top: 0; 1191 | left: 0; 1192 | right: 0; 1193 | bottom: 0; 1194 | z-index: 9999 1195 | } 1196 | 1197 | .m-newWapUserGiftModal>.mask { 1198 | position: absolute; 1199 | top: 0; 1200 | left: 0; 1201 | z-index: 0; 1202 | width: 100%; 1203 | height: 100%; 1204 | background-color: rgba(0, 0, 0, .5) 1205 | } 1206 | 1207 | .m-newWapUserGiftModal .close { 1208 | position: fixed; 1209 | right: .4rem; 1210 | top: .8rem; 1211 | z-index: 2 1212 | } 1213 | 1214 | .m-newWapUserGiftModal>.wrap { 1215 | -webkit-transform: translate(-50%, -50%); 1216 | -moz-transform: translate(-50%, -50%); 1217 | -ms-transform: translate(-50%, -50%); 1218 | -o-transform: translate(-50%, -50%); 1219 | transform: translate(-50%, -50%); 1220 | position: absolute; 1221 | top: 50%; 1222 | left: 50%; 1223 | z-index: 1 1224 | } 1225 | 1226 | .m-newWapUserGiftModal .modal { 1227 | width: 8.4rem; 1228 | height: 9.22667rem; 1229 | background-color: #fff; 1230 | border-radius: .21333rem; 1231 | padding: .4rem .32rem 1232 | } 1233 | 1234 | .m-newWapUserGiftModal .modal .title { 1235 | font-size: .53333rem; 1236 | text-align: center 1237 | } 1238 | 1239 | .m-newWapUserGiftModal .modal .title .titleContent { 1240 | display: inline-block; 1241 | position: relative; 1242 | font-weight: 700 1243 | } 1244 | 1245 | .m-newWapUserGiftModal .modal .title .titleContent:after, 1246 | .m-newWapUserGiftModal .modal .title .titleContent:before { 1247 | width: .53333rem; 1248 | height: .05333rem; 1249 | background-color: #333; 1250 | position: absolute; 1251 | top: .37333rem; 1252 | content: '' 1253 | } 1254 | 1255 | .m-newWapUserGiftModal .modal .title .titleContent:before { 1256 | left: -.74667rem 1257 | } 1258 | 1259 | .m-newWapUserGiftModal .modal .title .titleContent:after { 1260 | left: 2.88rem 1261 | } 1262 | 1263 | .m-newWapUserGiftModal .modal .subTitle { 1264 | margin-top: .05333rem; 1265 | font-size: .32rem; 1266 | text-align: center 1267 | } 1268 | 1269 | .m-newWapUserGiftModal .modal .actCouponBtn { 1270 | height: 1.17333rem; 1271 | background-color: #b4282d; 1272 | color: #fff; 1273 | font-size: .37333rem; 1274 | margin-top: .53333rem; 1275 | border-radius: .05333rem; 1276 | text-align: center; 1277 | line-height: 1.17333rem 1278 | } 1279 | 1280 | .m-newWapUserGiftModal .modal .linkBtn { 1281 | height: 1.17333rem; 1282 | border: 1px solid #7F7F7F; 1283 | border-radius: .05333rem; 1284 | text-align: center; 1285 | line-height: 1.17333rem; 1286 | font-size: .37333rem; 1287 | margin-top: .32rem; 1288 | display: block; 1289 | color: #333 1290 | } 1291 | 1292 | .m-indexHd { 1293 | background-color: #fff; 1294 | position: relative 1295 | } 1296 | 1297 | .m-indexHd:after { 1298 | content: ''; 1299 | position: absolute; 1300 | background-color: #d9d9d9; 1301 | left: 0; 1302 | width: 100%; 1303 | height: 1px; 1304 | -webkit-transform-origin: 50% 100% 0; 1305 | transform-origin: 50% 100% 0; 1306 | bottom: 0 1307 | } 1308 | 1309 | [data-dpr="1"] .m-indexHd:after { 1310 | -webkit-transform: scale3d(1, .5, 1); 1311 | -moz-transform: scale3d(1, .5, 1); 1312 | -ms-transform: scale3d(1, .5, 1); 1313 | -o-transform: scale3d(1, .5, 1); 1314 | transform: scale3d(1, .5, 1) 1315 | } 1316 | 1317 | .m-indexHd>.line { 1318 | display: -webkit-box; 1319 | display: -webkit-flex; 1320 | display: -moz-flex; 1321 | display: -ms-flexbox; 1322 | display: flex; 1323 | -webkit-flex-flow: row nowrap; 1324 | -moz-flex-flow: row nowrap; 1325 | -ms-flex-flow: row nowrap; 1326 | flex-flow: row nowrap; 1327 | -webkit-box-align: center; 1328 | -ms-flex-align: center; 1329 | -webkit-align-items: center; 1330 | -moz-align-items: center; 1331 | align-items: center; 1332 | padding: .21333rem .4rem 1333 | } 1334 | 1335 | .m-indexHd>.line .logo { 1336 | width: 1.84rem; 1337 | height: .53333rem; 1338 | background-image: url(//yanxuan.nosdn.127.net/hxm/yanxuan-wap/p/20161201/style/img/icon-normal/indexLogo-11d65342f9.png); 1339 | display: inline-block; 1340 | margin-right: .26667rem; 1341 | background-size: cover; 1342 | background-position: center 1343 | } 1344 | 1345 | .m-indexHd>.line>.ipt { 1346 | -webkit-box-flex: 1; 1347 | -webkit-flex-grow: 1; 1348 | -moz-flex-grow: 1; 1349 | -ms-flex-positive: 1; 1350 | flex-grow: 1 1351 | } 1352 | 1353 | .m-hdForSpecificChannels { 1354 | position: fixed; 1355 | top: 0; 1356 | left: 0; 1357 | z-index: 5 1358 | } 1359 | 1360 | .m-hdForSpecificChannels header { 1361 | height: 1.2rem!important 1362 | } 1363 | 1364 | .m-hdForSpecificChannels .tab .txt { 1365 | line-height: 1.2rem!important 1366 | } 1367 | 1368 | .m-indexTopics .inner .list .item .line1 .title, 1369 | .swiper-container-no-flexbox .swiper-slide { 1370 | float: left 1371 | } 1372 | 1373 | .swiper-slide, 1374 | .swiper-wrapper { 1375 | width: 100%; 1376 | height: 100%; 1377 | position: relative 1378 | } 1379 | 1380 | .swiper-container { 1381 | margin-left: auto; 1382 | margin-right: auto; 1383 | position: relative; 1384 | overflow: hidden; 1385 | z-index: 1 1386 | } 1387 | 1388 | .swiper-container-vertical>.swiper-wrapper { 1389 | -webkit-box-orient: vertical; 1390 | -moz-box-orient: vertical; 1391 | -ms-flex-direction: column; 1392 | -webkit-flex-direction: column; 1393 | flex-direction: column 1394 | } 1395 | 1396 | .swiper-wrapper { 1397 | z-index: 1; 1398 | display: -webkit-box; 1399 | display: -moz-box; 1400 | display: -ms-flexbox; 1401 | display: -webkit-flex; 1402 | display: flex; 1403 | -webkit-transition-property: -webkit-transform; 1404 | -moz-transition-property: -moz-transform; 1405 | -o-transition-property: -o-transform; 1406 | -ms-transition-property: -ms-transform; 1407 | transition-property: -webkit-transform; 1408 | transition-property: transform; 1409 | transition-property: transform, -webkit-transform; 1410 | -webkit-box-sizing: content-box; 1411 | -moz-box-sizing: content-box; 1412 | box-sizing: content-box 1413 | } 1414 | 1415 | .swiper-container-android .swiper-slide, 1416 | .swiper-wrapper { 1417 | -webkit-transform: translate3d(0, 0, 0); 1418 | -moz-transform: translate3d(0, 0, 0); 1419 | -o-transform: translate(0, 0); 1420 | -ms-transform: translate3d(0, 0, 0); 1421 | transform: translate3d(0, 0, 0) 1422 | } 1423 | 1424 | .swiper-container-multirow>.swiper-wrapper { 1425 | -webkit-box-lines: multiple; 1426 | -moz-box-lines: multiple; 1427 | -ms-flex-wrap: wrap; 1428 | -webkit-flex-wrap: wrap; 1429 | flex-wrap: wrap 1430 | } 1431 | 1432 | .swiper-container-free-mode>.swiper-wrapper { 1433 | -webkit-transition-timing-function: ease-out; 1434 | -moz-transition-timing-function: ease-out; 1435 | -ms-transition-timing-function: ease-out; 1436 | -o-transition-timing-function: ease-out; 1437 | transition-timing-function: ease-out; 1438 | margin: 0 auto 1439 | } 1440 | 1441 | .swiper-slide { 1442 | -webkit-flex-shrink: 0; 1443 | -ms-flex: 0 0 auto; 1444 | -ms-flex-negative: 0; 1445 | flex-shrink: 0 1446 | } 1447 | 1448 | .swiper-container-autoheight, 1449 | .swiper-container-autoheight .swiper-slide { 1450 | height: auto 1451 | } 1452 | 1453 | .swiper-container-autoheight .swiper-wrapper { 1454 | -webkit-box-align: start; 1455 | -ms-flex-align: start; 1456 | -webkit-align-items: flex-start; 1457 | -ms-grid-row-align: flex-start; 1458 | align-items: flex-start; 1459 | -webkit-transition-property: -webkit-transform, height; 1460 | -moz-transition-property: -moz-transform; 1461 | -o-transition-property: -o-transform; 1462 | -ms-transition-property: -ms-transform; 1463 | transition-property: height, -webkit-transform; 1464 | transition-property: transform, height; 1465 | transition-property: transform, height, -webkit-transform 1466 | } 1467 | 1468 | .swiper-container .swiper-notification { 1469 | position: absolute; 1470 | left: 0; 1471 | top: 0; 1472 | pointer-events: none; 1473 | opacity: 0; 1474 | z-index: -1000 1475 | } 1476 | 1477 | .swiper-wp8-horizontal { 1478 | -ms-touch-action: pan-y; 1479 | touch-action: pan-y 1480 | } 1481 | 1482 | .swiper-wp8-vertical { 1483 | -ms-touch-action: pan-x; 1484 | touch-action: pan-x 1485 | } 1486 | 1487 | .swiper-button-next, 1488 | .swiper-button-prev { 1489 | position: absolute; 1490 | top: 50%; 1491 | width: 27px; 1492 | height: 44px; 1493 | margin-top: -22px; 1494 | z-index: 10; 1495 | cursor: pointer; 1496 | -moz-background-size: 27px 44px; 1497 | -webkit-background-size: 27px 44px; 1498 | background-size: 27px 44px; 1499 | background-position: center; 1500 | background-repeat: no-repeat 1501 | } 1502 | 1503 | .swiper-button-next.swiper-button-disabled, 1504 | .swiper-button-prev.swiper-button-disabled { 1505 | opacity: .35; 1506 | cursor: auto; 1507 | pointer-events: none 1508 | } 1509 | 1510 | .swiper-button-prev, 1511 | .swiper-container-rtl .swiper-button-next { 1512 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E"); 1513 | left: 10px; 1514 | right: auto 1515 | } 1516 | 1517 | .swiper-button-prev.swiper-button-black, 1518 | .swiper-container-rtl .swiper-button-next.swiper-button-black { 1519 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E") 1520 | } 1521 | 1522 | .swiper-button-prev.swiper-button-white, 1523 | .swiper-container-rtl .swiper-button-next.swiper-button-white { 1524 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E") 1525 | } 1526 | 1527 | .swiper-button-next, 1528 | .swiper-container-rtl .swiper-button-prev { 1529 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E"); 1530 | right: 10px; 1531 | left: auto 1532 | } 1533 | 1534 | .swiper-button-next.swiper-button-black, 1535 | .swiper-container-rtl .swiper-button-prev.swiper-button-black { 1536 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E") 1537 | } 1538 | 1539 | .swiper-button-next.swiper-button-white, 1540 | .swiper-container-rtl .swiper-button-prev.swiper-button-white { 1541 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E") 1542 | } 1543 | 1544 | .swiper-pagination { 1545 | position: absolute; 1546 | text-align: center; 1547 | -webkit-transition: .3s; 1548 | -moz-transition: .3s; 1549 | -o-transition: .3s; 1550 | transition: .3s; 1551 | -webkit-transform: translate3d(0, 0, 0); 1552 | -ms-transform: translate3d(0, 0, 0); 1553 | -o-transform: translate3d(0, 0, 0); 1554 | transform: translate3d(0, 0, 0); 1555 | z-index: 10 1556 | } 1557 | 1558 | .swiper-pagination.swiper-pagination-hidden { 1559 | opacity: 0 1560 | } 1561 | 1562 | .swiper-container-horizontal>.swiper-pagination-bullets, 1563 | .swiper-pagination-custom, 1564 | .swiper-pagination-fraction { 1565 | bottom: 10px; 1566 | left: 0; 1567 | width: 100% 1568 | } 1569 | 1570 | .swiper-pagination-bullet { 1571 | width: 8px; 1572 | height: 8px; 1573 | display: inline-block; 1574 | border-radius: 100%; 1575 | background: #000; 1576 | opacity: .2 1577 | } 1578 | 1579 | button.swiper-pagination-bullet { 1580 | border: none; 1581 | margin: 0; 1582 | padding: 0; 1583 | box-shadow: none; 1584 | -moz-appearance: none; 1585 | -ms-appearance: none; 1586 | -webkit-appearance: none; 1587 | appearance: none 1588 | } 1589 | 1590 | .swiper-pagination-clickable .swiper-pagination-bullet { 1591 | cursor: pointer 1592 | } 1593 | 1594 | .swiper-pagination-white .swiper-pagination-bullet { 1595 | background: #fff 1596 | } 1597 | 1598 | .swiper-pagination-bullet-active { 1599 | opacity: 1; 1600 | background: #007aff 1601 | } 1602 | 1603 | .swiper-pagination-white .swiper-pagination-bullet-active { 1604 | background: #fff 1605 | } 1606 | 1607 | .swiper-pagination-black .swiper-pagination-bullet-active { 1608 | background: #000 1609 | } 1610 | 1611 | .swiper-container-vertical>.swiper-pagination-bullets { 1612 | right: 10px; 1613 | top: 50%; 1614 | -webkit-transform: translate3d(0, -50%, 0); 1615 | -moz-transform: translate3d(0, -50%, 0); 1616 | -o-transform: translate(0, -50%); 1617 | -ms-transform: translate3d(0, -50%, 0); 1618 | transform: translate3d(0, -50%, 0) 1619 | } 1620 | 1621 | .swiper-container-vertical>.swiper-pagination-bullets .swiper-pagination-bullet { 1622 | margin: 5px 0; 1623 | display: block 1624 | } 1625 | 1626 | .m-indexFlash, 1627 | .swiper-zoom-container { 1628 | display: -webkit-box; 1629 | display: -webkit-flex; 1630 | display: -ms-flexbox 1631 | } 1632 | 1633 | .swiper-container-horizontal>.swiper-pagination-bullets .swiper-pagination-bullet { 1634 | margin: 0 5px 1635 | } 1636 | 1637 | .swiper-pagination-progress { 1638 | background: rgba(0, 0, 0, .25); 1639 | position: absolute 1640 | } 1641 | 1642 | .swiper-pagination-progress .swiper-pagination-progressbar { 1643 | background: #007aff; 1644 | position: absolute; 1645 | left: 0; 1646 | top: 0; 1647 | width: 100%; 1648 | height: 100%; 1649 | -webkit-transform: scale(0); 1650 | -ms-transform: scale(0); 1651 | -o-transform: scale(0); 1652 | transform: scale(0); 1653 | -webkit-transform-origin: left top; 1654 | -moz-transform-origin: left top; 1655 | -ms-transform-origin: left top; 1656 | -o-transform-origin: left top; 1657 | transform-origin: left top 1658 | } 1659 | 1660 | .swiper-container-rtl .swiper-pagination-progress .swiper-pagination-progressbar { 1661 | -webkit-transform-origin: right top; 1662 | -moz-transform-origin: right top; 1663 | -ms-transform-origin: right top; 1664 | -o-transform-origin: right top; 1665 | transform-origin: right top 1666 | } 1667 | 1668 | .swiper-container-horizontal>.swiper-pagination-progress { 1669 | width: 100%; 1670 | height: 4px; 1671 | left: 0; 1672 | top: 0 1673 | } 1674 | 1675 | .swiper-container-vertical>.swiper-pagination-progress { 1676 | width: 4px; 1677 | height: 100%; 1678 | left: 0; 1679 | top: 0 1680 | } 1681 | 1682 | .swiper-pagination-progress.swiper-pagination-white { 1683 | background: rgba(255, 255, 255, .5) 1684 | } 1685 | 1686 | .swiper-pagination-progress.swiper-pagination-white .swiper-pagination-progressbar { 1687 | background: #fff 1688 | } 1689 | 1690 | .swiper-pagination-progress.swiper-pagination-black .swiper-pagination-progressbar { 1691 | background: #000 1692 | } 1693 | 1694 | .swiper-container-3d { 1695 | -webkit-perspective: 1200px; 1696 | -moz-perspective: 1200px; 1697 | -o-perspective: 1200px; 1698 | perspective: 1200px 1699 | } 1700 | 1701 | .swiper-container-3d .swiper-cube-shadow, 1702 | .swiper-container-3d .swiper-slide, 1703 | .swiper-container-3d .swiper-slide-shadow-bottom, 1704 | .swiper-container-3d .swiper-slide-shadow-left, 1705 | .swiper-container-3d .swiper-slide-shadow-right, 1706 | .swiper-container-3d .swiper-slide-shadow-top, 1707 | .swiper-container-3d .swiper-wrapper { 1708 | -webkit-transform-style: preserve-3d; 1709 | -moz-transform-style: preserve-3d; 1710 | -ms-transform-style: preserve-3d; 1711 | transform-style: preserve-3d 1712 | } 1713 | 1714 | .swiper-container-3d .swiper-slide-shadow-bottom, 1715 | .swiper-container-3d .swiper-slide-shadow-left, 1716 | .swiper-container-3d .swiper-slide-shadow-right, 1717 | .swiper-container-3d .swiper-slide-shadow-top { 1718 | position: absolute; 1719 | left: 0; 1720 | top: 0; 1721 | width: 100%; 1722 | height: 100%; 1723 | pointer-events: none; 1724 | z-index: 10 1725 | } 1726 | 1727 | .swiper-container-3d .swiper-slide-shadow-left { 1728 | background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(transparent)); 1729 | background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, .5), transparent); 1730 | background-image: -moz-linear-gradient(right, rgba(0, 0, 0, .5), transparent); 1731 | background-image: -o-linear-gradient(right, rgba(0, 0, 0, .5), transparent); 1732 | background-image: linear-gradient(to left, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0)) 1733 | } 1734 | 1735 | .swiper-container-3d .swiper-slide-shadow-right { 1736 | background-image: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, .5)), to(transparent)); 1737 | background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5), transparent); 1738 | background-image: -moz-linear-gradient(left, rgba(0, 0, 0, .5), transparent); 1739 | background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5), transparent); 1740 | background-image: linear-gradient(to right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0)) 1741 | } 1742 | 1743 | .swiper-container-3d .swiper-slide-shadow-top { 1744 | background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, .5)), to(transparent)); 1745 | background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, .5), transparent); 1746 | background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, .5), transparent); 1747 | background-image: -o-linear-gradient(bottom, rgba(0, 0, 0, .5), transparent); 1748 | background-image: linear-gradient(to top, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0)) 1749 | } 1750 | 1751 | .swiper-container-3d .swiper-slide-shadow-bottom { 1752 | background-image: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, .5)), to(transparent)); 1753 | background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, .5), transparent); 1754 | background-image: -moz-linear-gradient(top, rgba(0, 0, 0, .5), transparent); 1755 | background-image: -o-linear-gradient(top, rgba(0, 0, 0, .5), transparent); 1756 | background-image: linear-gradient(to bottom, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0)) 1757 | } 1758 | 1759 | .swiper-container-coverflow .swiper-wrapper, 1760 | .swiper-container-flip .swiper-wrapper { 1761 | -ms-perspective: 1200px 1762 | } 1763 | 1764 | .swiper-container-cube, 1765 | .swiper-container-flip { 1766 | overflow: visible 1767 | } 1768 | 1769 | .swiper-container-cube .swiper-slide, 1770 | .swiper-container-flip .swiper-slide { 1771 | pointer-events: none; 1772 | -webkit-backface-visibility: hidden; 1773 | -moz-backface-visibility: hidden; 1774 | -ms-backface-visibility: hidden; 1775 | backface-visibility: hidden; 1776 | z-index: 1 1777 | } 1778 | 1779 | .swiper-container-cube .swiper-slide .swiper-slide, 1780 | .swiper-container-flip .swiper-slide .swiper-slide { 1781 | pointer-events: none 1782 | } 1783 | 1784 | .swiper-container-cube .swiper-slide-active, 1785 | .swiper-container-cube .swiper-slide-active .swiper-slide-active, 1786 | .swiper-container-flip .swiper-slide-active, 1787 | .swiper-container-flip .swiper-slide-active .swiper-slide-active { 1788 | pointer-events: auto 1789 | } 1790 | 1791 | .swiper-container-cube .swiper-slide-shadow-bottom, 1792 | .swiper-container-cube .swiper-slide-shadow-left, 1793 | .swiper-container-cube .swiper-slide-shadow-right, 1794 | .swiper-container-cube .swiper-slide-shadow-top, 1795 | .swiper-container-flip .swiper-slide-shadow-bottom, 1796 | .swiper-container-flip .swiper-slide-shadow-left, 1797 | .swiper-container-flip .swiper-slide-shadow-right, 1798 | .swiper-container-flip .swiper-slide-shadow-top { 1799 | z-index: 0; 1800 | -webkit-backface-visibility: hidden; 1801 | -moz-backface-visibility: hidden; 1802 | -ms-backface-visibility: hidden; 1803 | backface-visibility: hidden 1804 | } 1805 | 1806 | .swiper-container-cube .swiper-slide { 1807 | visibility: hidden; 1808 | -webkit-transform-origin: 0 0; 1809 | -moz-transform-origin: 0 0; 1810 | -ms-transform-origin: 0 0; 1811 | transform-origin: 0 0; 1812 | width: 100%; 1813 | height: 100% 1814 | } 1815 | 1816 | .swiper-container-cube.swiper-container-rtl .swiper-slide { 1817 | -webkit-transform-origin: 100% 0; 1818 | -moz-transform-origin: 100% 0; 1819 | -ms-transform-origin: 100% 0; 1820 | transform-origin: 100% 0 1821 | } 1822 | 1823 | .swiper-container-cube .swiper-slide-active, 1824 | .swiper-container-cube .swiper-slide-next, 1825 | .swiper-container-cube .swiper-slide-next+.swiper-slide, 1826 | .swiper-container-cube .swiper-slide-prev { 1827 | pointer-events: auto; 1828 | visibility: visible 1829 | } 1830 | 1831 | .swiper-container-cube .swiper-cube-shadow { 1832 | position: absolute; 1833 | left: 0; 1834 | bottom: 0; 1835 | width: 100%; 1836 | height: 100%; 1837 | background: #000; 1838 | opacity: .6; 1839 | -webkit-filter: blur(50px); 1840 | filter: blur(50px); 1841 | z-index: 0 1842 | } 1843 | 1844 | .swiper-container-fade.swiper-container-free-mode .swiper-slide { 1845 | -webkit-transition-timing-function: ease-out; 1846 | -moz-transition-timing-function: ease-out; 1847 | -ms-transition-timing-function: ease-out; 1848 | -o-transition-timing-function: ease-out; 1849 | transition-timing-function: ease-out 1850 | } 1851 | 1852 | .swiper-container-fade .swiper-slide { 1853 | pointer-events: none; 1854 | -webkit-transition-property: opacity; 1855 | -moz-transition-property: opacity; 1856 | -o-transition-property: opacity; 1857 | transition-property: opacity 1858 | } 1859 | 1860 | .swiper-container-fade .swiper-slide .swiper-slide { 1861 | pointer-events: none 1862 | } 1863 | 1864 | .swiper-container-fade .swiper-slide-active, 1865 | .swiper-container-fade .swiper-slide-active .swiper-slide-active { 1866 | pointer-events: auto 1867 | } 1868 | 1869 | .swiper-zoom-container { 1870 | width: 100%; 1871 | height: 100%; 1872 | display: -moz-box; 1873 | display: flex; 1874 | -webkit-box-pack: center; 1875 | -moz-box-pack: center; 1876 | -ms-flex-pack: center; 1877 | -webkit-justify-content: center; 1878 | justify-content: center; 1879 | -webkit-box-align: center; 1880 | -moz-box-align: center; 1881 | -ms-flex-align: center; 1882 | -webkit-align-items: center; 1883 | align-items: center; 1884 | text-align: center 1885 | } 1886 | 1887 | .swiper-zoom-container>canvas, 1888 | .swiper-zoom-container>img, 1889 | .swiper-zoom-container>svg { 1890 | max-width: 100%; 1891 | max-height: 100%; 1892 | object-fit: contain 1893 | } 1894 | 1895 | .swiper-scrollbar { 1896 | border-radius: 10px; 1897 | position: relative; 1898 | -ms-touch-action: none; 1899 | background: rgba(0, 0, 0, .1) 1900 | } 1901 | 1902 | .swiper-container-horizontal>.swiper-scrollbar { 1903 | position: absolute; 1904 | left: 1%; 1905 | bottom: 3px; 1906 | z-index: 50; 1907 | height: 5px; 1908 | width: 98% 1909 | } 1910 | 1911 | .swiper-container-vertical>.swiper-scrollbar { 1912 | position: absolute; 1913 | right: 3px; 1914 | top: 1%; 1915 | z-index: 50; 1916 | width: 5px; 1917 | height: 98% 1918 | } 1919 | 1920 | .swiper-scrollbar-drag { 1921 | height: 100%; 1922 | width: 100%; 1923 | position: relative; 1924 | background: rgba(0, 0, 0, .5); 1925 | border-radius: 10px; 1926 | left: 0; 1927 | top: 0 1928 | } 1929 | 1930 | .swiper-scrollbar-cursor-drag { 1931 | cursor: move 1932 | } 1933 | 1934 | .swiper-lazy-preloader { 1935 | width: 42px; 1936 | height: 42px; 1937 | position: absolute; 1938 | left: 50%; 1939 | top: 50%; 1940 | margin-left: -21px; 1941 | margin-top: -21px; 1942 | z-index: 10; 1943 | -webkit-transform-origin: 50%; 1944 | -moz-transform-origin: 50%; 1945 | transform-origin: 50%; 1946 | -webkit-animation: swiper-preloader-spin 1s steps(12, end) infinite; 1947 | -moz-animation: swiper-preloader-spin 1s steps(12, end) infinite; 1948 | animation: swiper-preloader-spin 1s steps(12, end) infinite 1949 | } 1950 | 1951 | .swiper-lazy-preloader:after { 1952 | display: block; 1953 | content: ""; 1954 | width: 100%; 1955 | height: 100%; 1956 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); 1957 | background-position: 50%; 1958 | -webkit-background-size: 100%; 1959 | background-size: 100%; 1960 | background-repeat: no-repeat 1961 | } 1962 | 1963 | .swiper-lazy-preloader-white:after { 1964 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") 1965 | } 1966 | 1967 | @-webkit-keyframes swiper-preloader-spin { 1968 | 100% { 1969 | -webkit-transform: rotate(360deg) 1970 | } 1971 | } 1972 | 1973 | @keyframes swiper-preloader-spin { 1974 | 100% { 1975 | -webkit-transform: rotate(360deg); 1976 | transform: rotate(360deg) 1977 | } 1978 | } 1979 | 1980 | .m-indexFlash { 1981 | padding: .4rem .53333rem .4rem .74667rem; 1982 | margin-bottom: .26667rem; 1983 | height: 5.06667rem; 1984 | background: #fff; 1985 | display: -moz-flex; 1986 | display: flex 1987 | } 1988 | 1989 | .m-indexFlash .left-item { 1990 | -webkit-box-flex: 1; 1991 | -webkit-flex: 1; 1992 | -moz-box-flex: 1; 1993 | -moz-flex: 1; 1994 | -ms-flex: 1; 1995 | flex: 1; 1996 | display: -webkit-box; 1997 | display: -webkit-flex; 1998 | display: -moz-flex; 1999 | display: -ms-flexbox; 2000 | display: flex; 2001 | -webkit-box-direction: normal; 2002 | -webkit-box-orient: vertical; 2003 | -webkit-flex-direction: column; 2004 | -moz-flex-direction: column; 2005 | -ms-flex-direction: column; 2006 | flex-direction: column; 2007 | padding-top: 1.06667rem 2008 | } 2009 | 2010 | .m-indexFlash .left-item .title { 2011 | font-size: .48rem; 2012 | line-height: .48rem; 2013 | margin-bottom: .32rem; 2014 | color: #333; 2015 | letter-spacing: .16rem 2016 | } 2017 | 2018 | .m-indexFlash .left-item .hours, 2019 | .m-indexFlash .left-item .mins, 2020 | .m-indexFlash .left-item .secs { 2021 | display: inline-block; 2022 | line-height: .74667rem; 2023 | text-align: center; 2024 | width: .82667rem; 2025 | height: .74667rem; 2026 | font-size: .42667rem; 2027 | color: #fff; 2028 | border-radius: .05333rem; 2029 | background: #444 2030 | } 2031 | 2032 | .m-indexFlash .left-item .colon { 2033 | color: #333; 2034 | font-size: .4rem; 2035 | width: .26667rem; 2036 | display: inline-block; 2037 | text-align: center; 2038 | font-weight: 700 2039 | } 2040 | 2041 | .m-indexFlash .right-item .price, 2042 | .m-indexFloor>.hd { 2043 | display: -webkit-box; 2044 | display: -webkit-flex; 2045 | display: -moz-flex; 2046 | display: -ms-flexbox 2047 | } 2048 | 2049 | .m-indexFlash .left-item .next-title { 2050 | margin-top: .53333rem; 2051 | color: #333; 2052 | font-size: .32rem; 2053 | line-height: .32rem; 2054 | height: .32rem 2055 | } 2056 | 2057 | .m-indexFlash .right-item { 2058 | background: #fff; 2059 | width: 4.26667rem; 2060 | height: 4.26667rem; 2061 | position: relative 2062 | } 2063 | 2064 | .m-indexFlash .right-item img { 2065 | width: 100%; 2066 | height: 100% 2067 | } 2068 | 2069 | .m-indexFlash .right-item .rmb1 { 2070 | font-size: .32rem 2071 | } 2072 | 2073 | .m-indexFlash .right-item .rmb2 { 2074 | font-size: .26667rem 2075 | } 2076 | 2077 | .m-indexFlash .right-item .price { 2078 | height: 1.28rem; 2079 | width: 1.28rem; 2080 | background: red; 2081 | position: absolute; 2082 | right: .26667rem; 2083 | bottom: .48rem; 2084 | background-color: rgba(244, 143, 24, .95); 2085 | border-radius: 100%; 2086 | color: #fff; 2087 | text-align: center; 2088 | display: flex; 2089 | -webkit-box-direction: normal; 2090 | -webkit-box-orient: vertical; 2091 | -webkit-flex-direction: column; 2092 | -moz-flex-direction: column; 2093 | -ms-flex-direction: column; 2094 | flex-direction: column; 2095 | -webkit-box-pack: center; 2096 | -ms-flex-pack: center; 2097 | -webkit-justify-content: center; 2098 | -moz-justify-content: center; 2099 | justify-content: center 2100 | } 2101 | 2102 | .m-indexFlash .right-item .price .price-origin20 .t:before, 2103 | .m-indexFlash .right-item .price .price-origin24 .t:before, 2104 | .m-indexFlash .right-item .price .price-origin28 .t:before { 2105 | content: ''; 2106 | top: 0; 2107 | bottom: 0; 2108 | margin: auto; 2109 | width: 115%; 2110 | left: -.10667rem; 2111 | background: #fff 2112 | } 2113 | 2114 | .m-indexFlash .right-item .price .price-now20 { 2115 | font-size: .26667rem; 2116 | line-height: .26667rem; 2117 | height: .26667rem 2118 | } 2119 | 2120 | .m-indexFlash .right-item .price .price-now24 { 2121 | font-size: .32rem; 2122 | line-height: .32rem; 2123 | height: .32rem 2124 | } 2125 | 2126 | .m-indexFlash .right-item .price .price-now28 { 2127 | font-size: .37333rem; 2128 | line-height: .37333rem; 2129 | height: .37333rem 2130 | } 2131 | 2132 | .m-indexFlash .right-item .price .price-origin20 { 2133 | font-size: .26667rem; 2134 | line-height: .26667rem; 2135 | height: .26667rem 2136 | } 2137 | 2138 | .m-indexFlash .right-item .price .price-origin20 .t { 2139 | position: relative; 2140 | color: #fff 2141 | } 2142 | 2143 | .m-indexFlash .right-item .price .price-origin20 .t:before { 2144 | position: absolute; 2145 | height: 1px 2146 | } 2147 | 2148 | [data-dpr="1"] .m-indexFlash .right-item .price .price-origin20 .t:before { 2149 | -moz-transform: scale3d(1, .5, 1); 2150 | -webkit-transform: scale3d(1, .5, 1); 2151 | transform: scale3d(1, .5, 1) 2152 | } 2153 | 2154 | .m-indexFlash .right-item .price .price-origin24 { 2155 | font-size: .32rem; 2156 | line-height: .32rem; 2157 | height: .32rem 2158 | } 2159 | 2160 | .m-indexFlash .right-item .price .price-origin24 .t { 2161 | position: relative; 2162 | color: #fff 2163 | } 2164 | 2165 | .m-indexFlash .right-item .price .price-origin24 .t:before { 2166 | position: absolute; 2167 | height: 1px 2168 | } 2169 | 2170 | [data-dpr="1"] .m-indexFlash .right-item .price .price-origin24 .t:before { 2171 | -moz-transform: scale3d(1, .5, 1); 2172 | -webkit-transform: scale3d(1, .5, 1); 2173 | transform: scale3d(1, .5, 1) 2174 | } 2175 | 2176 | .m-indexFlash .right-item .price .price-origin28 { 2177 | font-size: .37333rem; 2178 | line-height: .37333rem; 2179 | height: .37333rem 2180 | } 2181 | 2182 | .m-indexFlash .right-item .price .price-origin28 .t { 2183 | position: relative; 2184 | color: #fff 2185 | } 2186 | 2187 | .m-indexFlash .right-item .price .price-origin28 .t:before { 2188 | position: absolute; 2189 | height: 1px 2190 | } 2191 | 2192 | .m-indexTopics .inner .list .item .error:before, 2193 | .m-indexTopics-slide .inner .list .item .error:before { 2194 | top: 0; 2195 | right: 0; 2196 | bottom: 0; 2197 | background-image: url(http://yanxuan.nosdn.127.net/f159d1b2ec1867ad1a73d5077fcca604.png); 2198 | background-repeat: no-repeat; 2199 | background-position: center; 2200 | background-size: 2.29333rem 2201 | } 2202 | 2203 | [data-dpr="1"] .m-indexFlash .right-item .price .price-origin28 .t:before { 2204 | -moz-transform: scale3d(1, .5, 1); 2205 | -webkit-transform: scale3d(1, .5, 1); 2206 | transform: scale3d(1, .5, 1) 2207 | } 2208 | 2209 | .m-indexFloor { 2210 | margin-bottom: .26667rem; 2211 | background-color: #fff 2212 | } 2213 | 2214 | .m-indexFloor .hr { 2215 | height: 1px; 2216 | background-color: #d9d9d9 2217 | } 2218 | 2219 | .m-indexFloor>.hd { 2220 | display: flex; 2221 | -webkit-flex-flow: row nowrap; 2222 | -moz-flex-flow: row nowrap; 2223 | -ms-flex-flow: row nowrap; 2224 | flex-flow: row nowrap; 2225 | -webkit-box-align: center; 2226 | -ms-flex-align: center; 2227 | -webkit-align-items: center; 2228 | -moz-align-items: center; 2229 | align-items: center; 2230 | -webkit-box-pack: center; 2231 | -ms-flex-pack: center; 2232 | -webkit-justify-content: center; 2233 | -moz-justify-content: center; 2234 | justify-content: center; 2235 | height: 1.46667rem; 2236 | font-size: .42667rem 2237 | } 2238 | 2239 | .m-indexFloor>.hd .more { 2240 | -webkit-box-align: center; 2241 | -ms-flex-align: center; 2242 | -webkit-align-items: center; 2243 | -moz-align-items: center; 2244 | align-items: center; 2245 | display: -webkit-box; 2246 | display: -webkit-flex; 2247 | display: -moz-flex; 2248 | display: -ms-flexbox; 2249 | display: flex; 2250 | -webkit-flex-flow: row nowrap; 2251 | -moz-flex-flow: row nowrap; 2252 | -ms-flex-flow: row nowrap; 2253 | flex-flow: row nowrap; 2254 | color: #333 2255 | } 2256 | 2257 | .m-indexFloor>.hd .more .icon { 2258 | margin-left: .13333rem 2259 | } 2260 | 2261 | .m-indexFloor-transparent { 2262 | background-color: transparent 2263 | } 2264 | 2265 | .m-indexManufacturersSupplying { 2266 | padding-bottom: .10667rem 2267 | } 2268 | 2269 | .m-indexManufacturersSupplying .list { 2270 | position: relative; 2271 | margin: 0 .21333rem; 2272 | height: 6.24rem; 2273 | overflow: hidden 2274 | } 2275 | 2276 | .m-indexManufacturersSupplying .list .item { 2277 | display: inline-block; 2278 | position: relative; 2279 | margin-bottom: .10667rem; 2280 | width: 4.73333rem; 2281 | height: 3.14667rem; 2282 | overflow: hidden; 2283 | background-color: #f4f4f4 2284 | } 2285 | 2286 | .m-indexManufacturersSupplying .list .item img, 2287 | .m-indexManufacturersSupplying .list .item>a { 2288 | width: 100%; 2289 | height: 100% 2290 | } 2291 | 2292 | .m-indexManufacturersSupplying .list .item .cnt { 2293 | position: absolute; 2294 | left: 0; 2295 | top: 0; 2296 | padding: .26667rem 0 0 .26667rem; 2297 | width: 100%; 2298 | z-index: 4 2299 | } 2300 | 2301 | .m-indexManufacturersSupplying .list .item .cnt .title { 2302 | text-overflow: ellipsis; 2303 | white-space: nowrap; 2304 | overflow: hidden; 2305 | color: #333; 2306 | font-size: .37333rem; 2307 | line-height: .45333rem; 2308 | margin-bottom: .08rem 2309 | } 2310 | 2311 | .m-indexManufacturersSupplying .list .item .cnt .price1 { 2312 | color: #333; 2313 | font-size: .37333rem; 2314 | line-height: .45333rem 2315 | } 2316 | 2317 | .m-indexManufacturersSupplying .list .item .cnt .price2 { 2318 | color: #333; 2319 | font-size: .32rem; 2320 | line-height: .45333rem 2321 | } 2322 | 2323 | .m-indexManufacturersSupplying .list .item .cnt .icon { 2324 | display: block; 2325 | margin-top: .13333rem 2326 | } 2327 | 2328 | .m-indexManufacturersSupplying .list .item:nth-child(1), 2329 | .m-indexManufacturersSupplying .list .item:nth-child(3) { 2330 | margin-right: .10667rem 2331 | } 2332 | 2333 | .m-indexTopics { 2334 | padding-bottom: .48rem; 2335 | overflow: hidden 2336 | } 2337 | 2338 | .m-indexTopics .inner { 2339 | overflow: visible 2340 | } 2341 | 2342 | .m-indexTopics .inner .list, 2343 | .m-indexTopics .inner .list .item { 2344 | width: 100% 2345 | } 2346 | 2347 | .m-indexTopics .inner .list .item .imgWrap { 2348 | display: block; 2349 | width: 100%; 2350 | height: 5.6rem; 2351 | margin-bottom: .30667rem; 2352 | overflow: hidden 2353 | } 2354 | 2355 | .m-indexTopics .inner .list .item .imgWrap img { 2356 | width: auto; 2357 | height: 100%; 2358 | position: relative; 2359 | left: 50%; 2360 | -moz-transform: translateX(-50%); 2361 | -ms-transform: translateX(-50%); 2362 | -webkit-transform: translateX(-50%); 2363 | transform: translateX(-50%) 2364 | } 2365 | 2366 | .m-indexTopics .inner .list .item .error { 2367 | position: relative 2368 | } 2369 | 2370 | .m-indexTopics .inner .list .item .error:before { 2371 | content: ' '; 2372 | display: block; 2373 | position: absolute; 2374 | z-index: 1; 2375 | left: 0; 2376 | background-color: #f4f4f4 2377 | } 2378 | 2379 | .m-indexTopics .inner .list .item .line1 { 2380 | overflow: visible; 2381 | margin-bottom: .16rem; 2382 | padding: 0 .4rem; 2383 | line-height: 1; 2384 | font-size: .42667rem; 2385 | zoom: 1 2386 | } 2387 | 2388 | .m-indexTopics .inner .list .item .line1:after { 2389 | display: block; 2390 | clear: both; 2391 | visibility: hidden; 2392 | height: 0; 2393 | overflow: hidden; 2394 | content: "." 2395 | } 2396 | 2397 | .m-indexTopics .inner .list .item .line1 .price { 2398 | float: right; 2399 | color: #b4282d 2400 | } 2401 | 2402 | .m-indexTopics .inner .list .item .desc { 2403 | padding: 0 .4rem; 2404 | font-size: .32rem; 2405 | line-height: 1; 2406 | color: #7F7F7F 2407 | } 2408 | 2409 | .m-indexTopics-slide { 2410 | padding: 0 .4rem .48rem; 2411 | overflow: hidden 2412 | } 2413 | 2414 | .m-indexTopics-slide .inner { 2415 | overflow: visible 2416 | } 2417 | 2418 | .m-indexTopics-slide .inner .list, 2419 | .m-indexTopics-slide .inner .list .item { 2420 | width: 7.66667rem 2421 | } 2422 | 2423 | .m-indexTopics-slide .inner .list .item .imgWrap { 2424 | display: block; 2425 | width: 7.66667rem; 2426 | height: 4.29333rem; 2427 | margin-bottom: .21333rem; 2428 | border-radius: 8px; 2429 | overflow: hidden 2430 | } 2431 | 2432 | [data-dpr="1"] .m-indexTopics-slide .inner .list .item .imgWrap { 2433 | border-radius: 4px 2434 | } 2435 | 2436 | .m-indexTopics-slide .inner .list .item .imgWrap img { 2437 | height: 100%; 2438 | width: auto; 2439 | position: relative; 2440 | left: 50%; 2441 | -moz-transform: translateX(-50%); 2442 | -ms-transform: translateX(-50%); 2443 | -webkit-transform: translateX(-50%); 2444 | transform: translateX(-50%) 2445 | } 2446 | 2447 | .m-indexTopics-slide .inner .list .item .error { 2448 | position: relative 2449 | } 2450 | 2451 | .m-indexTopics-slide .inner .list .item .error:before { 2452 | content: ' '; 2453 | display: block; 2454 | position: absolute; 2455 | z-index: 1; 2456 | left: 0; 2457 | background-color: #f4f4f4 2458 | } 2459 | 2460 | .m-indexTopics-slide .inner .list .item .line1 { 2461 | height: 41px; 2462 | margin-bottom: .02667rem; 2463 | zoom: 1 2464 | } 2465 | 2466 | .m-indexTopics-slide .inner .list .item .line1:after { 2467 | display: block; 2468 | clear: both; 2469 | visibility: hidden; 2470 | height: 0; 2471 | overflow: hidden; 2472 | content: "." 2473 | } 2474 | 2475 | .m-indexTopics-slide .inner .list .item .line1 .title { 2476 | white-space: nowrap; 2477 | overflow: hidden; 2478 | -ms-text-overflow: ellipsis; 2479 | -o-text-overflow: ellipsis; 2480 | text-overflow: ellipsis; 2481 | width: 5.46667rem; 2482 | float: left; 2483 | font-size: .37333rem 2484 | } 2485 | 2486 | .m-indexTopics-slide .inner .list .item .line1 .price { 2487 | float: right; 2488 | font-size: .37333rem; 2489 | color: #b4282d 2490 | } 2491 | 2492 | .m-indexTopics-slide .inner .list .item .desc { 2493 | white-space: nowrap; 2494 | overflow: hidden; 2495 | -ms-text-overflow: ellipsis; 2496 | -o-text-overflow: ellipsis; 2497 | text-overflow: ellipsis; 2498 | width: 7.66667rem; 2499 | font-size: .32rem; 2500 | color: #7F7F7F 2501 | } 2502 | 2503 | .m-newItems>.hd { 2504 | background: url(//yanxuan.nosdn.127.net/hxm/yanxuan-wap/p/20161201/style/img/icon-normal/bitmap-d4f7b37e32.png); 2505 | background-size: 10rem 3.46667rem; 2506 | height: 3.46667rem; 2507 | margin-bottom: .42667rem; 2508 | position: relative 2509 | } 2510 | 2511 | .m-newItems>.hd>.more { 2512 | display: block; 2513 | text-align: center; 2514 | font-size: .48rem; 2515 | color: #8BA0B6 2516 | } 2517 | 2518 | .m-newItems>.hd>.more .all { 2519 | position: relative; 2520 | margin: .21333rem auto 0; 2521 | width: 3.2rem; 2522 | height: .74667rem; 2523 | font-size: .37333rem; 2524 | line-height: .74667rem; 2525 | background: #D8E5F1 2526 | } 2527 | 2528 | .m-newItems>.hd>.more .all .arrow-right { 2529 | position: absolute; 2530 | top: .22667rem; 2531 | background: url(//yanxuan.nosdn.127.net/hxm/yanxuan-wap/p/20161201/style/img/icon-normal/indexNewArrow-f3b56d449b.png); 2532 | background-size: .13333rem .29333rem; 2533 | display: inline-block; 2534 | height: .29333rem; 2535 | width: .13333rem; 2536 | margin-left: .08rem 2537 | } 2538 | 2539 | .m-newItems>.hd>.more .wrap { 2540 | width: 1.70667rem; 2541 | display: inline-block; 2542 | text-align: left 2543 | } 2544 | 2545 | .m-popularItemList>.hd { 2546 | background: url(//yanxuan.nosdn.127.net/hxm/yanxuan-wap/p/20161201/style/img/icon-normal/bitmap2-d626e0b52a.png); 2547 | background-size: 10rem 3.46667rem; 2548 | height: 3.46667rem; 2549 | margin-bottom: .42667rem; 2550 | position: relative 2551 | } 2552 | 2553 | .m-popularItemList>.hd>.more { 2554 | display: block; 2555 | text-align: center; 2556 | font-size: .48rem; 2557 | color: #B4A078 2558 | } 2559 | 2560 | .m-popularItemList>.hd>.more .all { 2561 | position: relative; 2562 | margin: .21333rem auto 0; 2563 | width: 3.2rem; 2564 | height: .74667rem; 2565 | font-size: .37333rem; 2566 | line-height: .74667rem; 2567 | background: #F4E9CB 2568 | } 2569 | 2570 | .m-popularItemList>.hd>.more .all .arrow-right { 2571 | position: absolute; 2572 | top: .22667rem; 2573 | background: url(//yanxuan.nosdn.127.net/hxm/yanxuan-wap/p/20161201/style/img/icon-normal/indexPopularArrow-fb701819de.png); 2574 | background-size: .13333rem .29333rem; 2575 | display: inline-block; 2576 | height: .29333rem; 2577 | width: .13333rem; 2578 | margin-left: .08rem 2579 | } 2580 | 2581 | .m-popularItemList>.hd>.more .wrap { 2582 | width: 1.70667rem; 2583 | display: inline-block; 2584 | text-align: left 2585 | } 2586 | 2587 | .m-goodGrid-newItem, 2588 | .m-goodGrid-newItem .swiper-container, 2589 | .m-goodGrid-popularItem, 2590 | .m-goodGrid-popularItem .swiper-container { 2591 | height: 6.4rem 2592 | } 2593 | 2594 | .m-goodGrid-newItem .list, 2595 | .m-goodGrid-popularItem .list { 2596 | overflow: visible 2597 | } 2598 | 2599 | .m-goodGrid-newItem .list .item, 2600 | .m-goodGrid-popularItem .list .item { 2601 | padding: 0!important; 2602 | margin-left: .4rem; 2603 | width: 3.73333rem 2604 | } 2605 | 2606 | .m-goodGrid-newItem .list .item .tagWraper, 2607 | .m-goodGrid-popularItem .list .item .tagWraper { 2608 | width: 100%; 2609 | z-index: 1; 2610 | margin: 0 0 .21333rem; 2611 | height: .4rem; 2612 | overflow: hidden 2613 | } 2614 | 2615 | .m-goodGrid-newItem .list .item .status, 2616 | .m-goodGrid-popularItem .list .item .status { 2617 | height: .4rem; 2618 | padding: .06667rem .21333rem; 2619 | line-height: .26667rem; 2620 | text-align: center; 2621 | color: #fff; 2622 | font-size: .26667rem; 2623 | border-radius: .02667rem; 2624 | display: inline-block; 2625 | vertical-align: middle 2626 | } 2627 | 2628 | [data-dpr="1"] .m-goodGrid-newItem .list .item .status, 2629 | [data-dpr="1"] .m-goodGrid-popularItem .list .item .status { 2630 | border-radius: 2px; 2631 | line-height: .32rem 2632 | } 2633 | 2634 | .m-goodGrid-newItem .list .item .status.empty, 2635 | .m-goodGrid-popularItem .list .item .status.empty { 2636 | background-color: #c9c9c9 2637 | } 2638 | 2639 | .m-goodGrid-newItem .list .item .status.almostEmpty, 2640 | .m-goodGrid-popularItem .list .item .status.almostEmpty { 2641 | background-color: #b4282d 2642 | } 2643 | 2644 | .m-goodGrid-newItem .list .item .status.presale, 2645 | .m-goodGrid-popularItem .list .item .status.presale { 2646 | background-color: #f8b551 2647 | } 2648 | 2649 | .m-goodGrid-newItem .list .item .status.newItem, 2650 | .m-goodGrid-popularItem .list .item .status.newItem { 2651 | background-color: #cdb694 2652 | } 2653 | 2654 | .m-goodGrid-newItem .list .item .status.gradientPrice, 2655 | .m-goodGrid-newItem .list .item .status.presell, 2656 | .m-goodGrid-popularItem .list .item .status.gradientPrice, 2657 | .m-goodGrid-popularItem .list .item .status.presell { 2658 | background-color: #f48f18 2659 | } 2660 | 2661 | .m-goodGrid-newItem .list .item .status.anniversary, 2662 | .m-goodGrid-popularItem .list .item .status.anniversary { 2663 | background-color: #e5686d 2664 | } 2665 | 2666 | .m-goodGrid-newItem .list .item .tagWraper .status, 2667 | .m-goodGrid-popularItem .list .item .tagWraper .status { 2668 | margin-left: .16rem 2669 | } 2670 | 2671 | .m-goodGrid-newItem .list .item .manufacturerTag, 2672 | .m-goodGrid-popularItem .list .item .manufacturerTag { 2673 | position: absolute; 2674 | top: .26667rem; 2675 | left: .26667rem; 2676 | padding: 0 .2rem; 2677 | border: 1px solid #999; 2678 | font-size: .32rem; 2679 | line-height: .48rem; 2680 | color: #999; 2681 | z-index: 1; 2682 | border-radius: 4px 2683 | } 2684 | 2685 | [data-dpr="1"] .m-goodGrid-newItem .list .item .manufacturerTag, 2686 | [data-dpr="1"] .m-goodGrid-popularItem .list .item .manufacturerTag { 2687 | border: none 2688 | } 2689 | 2690 | [data-dpr="1"] .m-goodGrid-newItem .list .item .manufacturerTag:after, 2691 | [data-dpr="1"] .m-goodGrid-popularItem .list .item .manufacturerTag:after { 2692 | content: ''; 2693 | position: absolute; 2694 | top: 0; 2695 | left: 0; 2696 | border: 1px solid #999; 2697 | -moz-box-sizing: border-box; 2698 | -webkit-box-sizing: border-box; 2699 | box-sizing: border-box; 2700 | width: 200%; 2701 | height: 200%; 2702 | -moz-transform: scale(.5); 2703 | -ms-transform: scale(.5); 2704 | -webkit-transform: scale(.5); 2705 | transform: scale(.5); 2706 | -moz-transform-origin: left top; 2707 | -ms-transform-origin: left top; 2708 | -webkit-transform-origin: left top; 2709 | transform-origin: left top; 2710 | border-radius: 4px 2711 | } 2712 | 2713 | .m-goodGrid-newItem .list .item .good, 2714 | .m-goodGrid-popularItem .list .item .good { 2715 | display: block 2716 | } 2717 | 2718 | .m-goodGrid-newItem .list .item .good .hd, 2719 | .m-goodGrid-popularItem .list .item .good .hd { 2720 | background-color: #f4f4f4 2721 | } 2722 | 2723 | .m-goodGrid-newItem .list .item .good .hd img, 2724 | .m-goodGrid-popularItem .list .item .good .hd img { 2725 | background-color: #f4f4f4; 2726 | top: 0; 2727 | left: 0; 2728 | width: 100%; 2729 | height: 100% 2730 | } 2731 | 2732 | .m-goodGrid-newItem .list .item .good .hd .wraper, 2733 | .m-goodGrid-popularItem .list .item .good .hd .wraper { 2734 | background-color: #f4f4f4; 2735 | border-radius: 4; 2736 | padding-bottom: 100%; 2737 | margin-bottom: .26667rem 2738 | } 2739 | 2740 | [data-dpr="1"] .m-goodGrid-newItem .list .item .good .hd .wraper, 2741 | [data-dpr="1"] .m-goodGrid-popularItem .list .item .good .hd .wraper { 2742 | border-radius: 2 2743 | } 2744 | 2745 | .m-goodGrid-newItem .list .item .good .hd .desc, 2746 | .m-goodGrid-popularItem .list .item .good .hd .desc { 2747 | display: none 2748 | } 2749 | 2750 | .m-goodGrid-newItem .list .item .good .name, 2751 | .m-goodGrid-popularItem .list .item .good .name { 2752 | margin-bottom: .13333rem; 2753 | padding: 0 .13333rem; 2754 | font-size: .37333rem; 2755 | line-height: .45333rem 2756 | } 2757 | 2758 | .m-goodGrid-newItem .list .item .good .newItemDesc, 2759 | .m-goodGrid-popularItem .list .item .good .newItemDesc { 2760 | display: block; 2761 | margin-bottom: .18667rem; 2762 | font-size: .32rem; 2763 | color: #7f7f7f; 2764 | line-height: .4rem; 2765 | white-space: nowrap; 2766 | text-overflow: ellipsis; 2767 | overflow: hidden; 2768 | padding: 0 .13333rem 2769 | } 2770 | 2771 | .m-goodGrid-newItem .list .item .good .price, 2772 | .m-goodGrid-popularItem .list .item .good .price { 2773 | padding: 0 .13333rem; 2774 | font-size: .37333rem 2775 | } 2776 | 2777 | .m-goodGrid-newItem .list .more, 2778 | .m-goodGrid-popularItem .list .more { 2779 | display: block; 2780 | border: .10667rem solid #F4F4F4; 2781 | width: 3.73333rem; 2782 | height: 3.73333rem; 2783 | margin: 0 .4rem; 2784 | line-height: 3.73333rem; 2785 | text-align: center 2786 | } 2787 | 2788 | .m-goodGrid-newItem .list .more .text, 2789 | .m-goodGrid-popularItem .list .more .text { 2790 | font-size: .37333rem; 2791 | color: #666 2792 | } 2793 | 2794 | .m-indexServicePolicy { 2795 | background: #fff 2796 | } 2797 | 2798 | .m-indexServicePolicy .g-grow { 2799 | width: 100%; 2800 | height: .96rem; 2801 | padding: 0 .4rem; 2802 | display: -webkit-box; 2803 | display: -webkit-flex; 2804 | display: -moz-flex; 2805 | display: -ms-flexbox; 2806 | display: flex; 2807 | -webkit-flex-flow: row nowrap; 2808 | -moz-flex-flow: row nowrap; 2809 | -ms-flex-flow: row nowrap; 2810 | flex-flow: row nowrap; 2811 | -webkit-box-align: center; 2812 | -ms-flex-align: center; 2813 | -webkit-align-items: center; 2814 | -moz-align-items: center; 2815 | align-items: center; 2816 | zoom: 1 2817 | } 2818 | 2819 | .m-indexServicePolicy .g-grow:after { 2820 | display: block; 2821 | clear: both; 2822 | visibility: hidden; 2823 | height: 0; 2824 | overflow: hidden; 2825 | content: "." 2826 | } 2827 | 2828 | .m-indexServicePolicy .item { 2829 | -webkit-box-flex: 1; 2830 | -webkit-flex: 1; 2831 | -moz-box-flex: 1; 2832 | -moz-flex: 1; 2833 | -ms-flex: 1; 2834 | flex: 1; 2835 | float: left 2836 | } 2837 | 2838 | .m-indexServicePolicy .item a { 2839 | display: inline-block; 2840 | vertical-align: middle; 2841 | height: .42667rem 2842 | } 2843 | 2844 | .m-indexServicePolicy .text { 2845 | font-size: .32rem; 2846 | color: #333; 2847 | margin-left: .10667rem; 2848 | line-height: .42667rem; 2849 | display: inline-block; 2850 | vertical-align: middle 2851 | } 2852 | 2853 | .slideWarp { 2854 | height: 5.33333rem; 2855 | position: relative 2856 | } 2857 | 2858 | .m-slide { 2859 | padding-top: 5.33333rem!important 2860 | } 2861 | 2862 | .hasTabBar { 2863 | padding-bottom: 1.30667rem 2864 | } 2865 | 2866 | .m-sale { 2867 | width: 10rem; 2868 | height: 4rem; 2869 | margin-bottom: .26667rem 2870 | } 2871 | 2872 | .m-sale a { 2873 | width: 100%; 2874 | height: 100%; 2875 | display: block 2876 | } 2877 | -------------------------------------------------------------------------------- /src/components/Banner.vue: -------------------------------------------------------------------------------- 1 | 43 | 48 | 53 | -------------------------------------------------------------------------------- /src/components/BottomNav.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /src/components/FloorOne.vue: -------------------------------------------------------------------------------- 1 | 62 | -------------------------------------------------------------------------------- /src/components/Header.vue: -------------------------------------------------------------------------------- 1 | 40 | 58 | 63 | -------------------------------------------------------------------------------- /src/entry-client.js: -------------------------------------------------------------------------------- 1 | import { 2 | createApp 3 | } from './app' 4 | import Q from 'q' 5 | import Vue from 'vue' 6 | 7 | Vue.mixin({ 8 | beforeRouteUpdate(to, from, next) { 9 | const { 10 | asyncData 11 | } = this.$options 12 | if (asyncData) { 13 | asyncData({ 14 | store: this.$store, 15 | route: to 16 | }).then(next).catch(next) 17 | } else { 18 | next() 19 | } 20 | } 21 | }) 22 | 23 | const { 24 | app, 25 | router, 26 | store 27 | } = createApp() 28 | 29 | // 将服务端渲染时候的状态写入vuex中 30 | if (window.__INITIAL_STATE__) { 31 | store.replaceState(window.__INITIAL_STATE__) 32 | } 33 | 34 | router.onReady(() => { 35 | router.beforeResolve((to, from, next) => { 36 | const matched = router.getMatchedComponents(to) 37 | const prevMatched = router.getMatchedComponents(from) 38 | // 我们只关心之前没有渲染的组件 39 | // 所以我们对比它们,找出两个匹配列表的差异组件 40 | let diffed = false 41 | const activated = matched.filter((c, i) => { 42 | return diffed || (diffed = (prevMatched[i] !== c)) 43 | }) 44 | if (!activated.length) { 45 | return next() 46 | } 47 | // 这里如果有加载指示器(loading indicator),就触发 48 | Q.all(activated.map(c => { 49 | if (c.asyncData) { 50 | return c.asyncData({ 51 | store, 52 | route: to 53 | }) 54 | } 55 | })).then(() => { 56 | // 停止加载指示器(loading indicator) 57 | next() 58 | }).catch(next) 59 | }) 60 | app.$mount('#app') 61 | }) 62 | 63 | // service worker 64 | // if ('serviceWorker' in navigator) { 65 | // navigator.serviceWorker.register('/service-worker.js'); 66 | // } 67 | if ('serviceWorker' in navigator) { 68 | console.log("SW present !!! "); 69 | navigator.serviceWorker.register('/service-worker.js', { 70 | //scope: '/toto/' 71 | }).then(function (registration) { 72 | console.log('Service worker registered : ', registration.scope); 73 | }) 74 | .catch(function (err) { 75 | console.log("Service worker registration failed : ", err); 76 | }); 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/entry-server.js: -------------------------------------------------------------------------------- 1 | import { createApp } from './app' 2 | import Q from 'q' 3 | export default context => { 4 | return new Q.Promise((resolve, reject) => { 5 | const { app, router, store } = createApp() 6 | router.push(context.url) 7 | router.onReady(() => { 8 | const matchedComponents = router.getMatchedComponents() 9 | if (!matchedComponents.length) { 10 | return reject({ code: 404 }) 11 | } 12 | // 对所有匹配的路由组件调用 `asyncData()` 13 | Q.all( 14 | matchedComponents.map(Component => { 15 | if (Component.asyncData) { 16 | Component.asyncData({ 17 | store, 18 | route: router.currentRoute 19 | }).then(() => { 20 | return 21 | }) 22 | } 23 | }) 24 | ) 25 | .then(() => { 26 | // 在所有预取钩子(preFetch hook) resolve 后, 27 | // 我们的 store 现在已经填充入渲染应用程序所需的状态。 28 | // 当我们将状态附加到上下文, 29 | // 并且 `template` 选项用于 renderer 时, 30 | // 状态将自动序列化为 `window.__INITIAL_STATE__`,并注入 HTML。 31 | context.state = store.state 32 | resolve(app) 33 | }) 34 | .catch(reject) 35 | }, reject) 36 | }) 37 | } 38 | -------------------------------------------------------------------------------- /src/index.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | {{ title }} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/public/conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 系统 配置项 3 | */ 4 | export default { 5 | HOST: "https://123.baidu.com", 6 | DEBUGMOCK: true && process.env.STATS === 'dev' 7 | } 8 | -------------------------------------------------------------------------------- /src/public/utils/api.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import qs from 'qs' 3 | import Q from 'q' 4 | /** 5 | * 兼容 不支持promise 的低版本浏览器 6 | */ 7 | require('es6-promise').polyfill(); 8 | import C from '../conf' 9 | 10 | axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8' 11 | axios.defaults.withCredentials = true 12 | 13 | function ajax(url, type, options) { 14 | 15 | return Q.Promise((resolve, reject) => { 16 | axios({ 17 | method: type, 18 | url: C.HOST + url, 19 | params: type === 'get' ? options : null, 20 | data: type !== 'get' ? qs.stringify(options) : null 21 | }) 22 | .then((result) => { 23 | if (result && result.status === 401) { 24 | // location.href = '/views/401.html' 25 | } 26 | if (result && result.status === 200) { 27 | if (result.data.code === 200) { 28 | resolve(result.data.data); 29 | } else if (result.data.code === 401) { 30 | reject({ 31 | nopms: true, 32 | msg: result.data.msg 33 | }); 34 | } else { 35 | reject({ 36 | error: true, 37 | msg: result.data.msg 38 | }); 39 | } 40 | } else { 41 | reject({ 42 | errno: result.errno, 43 | msg: result.msg 44 | }); 45 | } 46 | }) 47 | .catch(function(error) { 48 | console.log(error, url); 49 | }); 50 | }) 51 | } 52 | 53 | const config = { 54 | get(url, options) { 55 | return Q.Promise((resolve, reject) => { 56 | ajax(url, 'get', options) 57 | .then((data) => { 58 | resolve(data); 59 | }, (error) => { 60 | reject(error); 61 | }); 62 | }) 63 | }, 64 | 65 | post(url, options) { 66 | return Q.Promise((resolve, reject) => { 67 | ajax(url, 'post', options) 68 | .then((data) => { 69 | resolve(data); 70 | }, (error) => { 71 | reject(error); 72 | }); 73 | }) 74 | }, 75 | 76 | put(url, options) { 77 | return Q.Promise((resolve, reject) => { 78 | ajax(url, 'put', options) 79 | .then((data) => { 80 | resolve(data); 81 | }, (error) => { 82 | reject(error); 83 | }); 84 | }) 85 | }, 86 | 87 | delete(url, options) { 88 | return Q.Promise((resolve, reject) => { 89 | ajax(url, 'delete', options) 90 | .then((data) => { 91 | resolve(data); 92 | }, (error) => { 93 | reject(error); 94 | }); 95 | }) 96 | }, 97 | 98 | jsonp(url, options) { 99 | return Q.Promise((resolve, reject) => { 100 | ajax(url, 'jsonp', options) 101 | .then((data) => { 102 | resolve(data); 103 | }, (error) => { 104 | reject(error); 105 | }); 106 | }) 107 | } 108 | }; 109 | 110 | export default config; 111 | -------------------------------------------------------------------------------- /src/public/utils/confUtils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * [mergeMock 函数] 3 | * @param {[type]} pMock [页面开关] 4 | * @param {[type]} mMock [模块开关] 5 | * @return {[merge 后对象]} 6 | */ 7 | import S from '../conf' 8 | 9 | export const mergeMock = function(pMock, mMock) { 10 | for (let item in mMock) { 11 | mMock[item].MOCK = S.DEBUGMOCK && pMock && mMock[item].MOCK; 12 | } 13 | return mMock; 14 | } 15 | 16 | /** 17 | * 初始化 mock 18 | */ 19 | export const initMock = function(Mock, CONF, mockData) { 20 | 21 | return function() { 22 | const ts = ['GET', 'PUT', 'DELETE', 'POST'], 23 | m = Object.keys(mockData)[0]; 24 | for (let key in CONF[m]['API']) { 25 | const t = key.split('_')[0]; 26 | const type = ts.indexOf(t) !== -1 ? t : 'GET'; 27 | if ('GET' === type) { 28 | const _urlString = m + '/' + (new Date().getTime()) + '/' + t + '/'; 29 | CONF[m]['API'][key] = _urlString; 30 | Mock.mock(new RegExp(S.HOST + _urlString), type.toLocaleLowerCase(), mockData[m]['API'][key]); 31 | } else { 32 | Mock.mock(S.HOST + CONF[m]['API'][key], type.toLocaleLowerCase(), mockData[m]['API'][key]); 33 | } 34 | } 35 | }() 36 | } 37 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router'; 3 | Vue.use(Router) 4 | export function createRouter() { 5 | return new Router({ 6 | mode: 'history', 7 | routes: [{ 8 | name:'Home', 9 | path: '/', 10 | component: () => 11 | import ('../views/index/index.vue') 12 | }] 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /src/static/img/demo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wqzwh/vue-ssr/cca3e361f4921312c02fdb6ad66af1cf7c95d2c1/src/static/img/demo.jpeg -------------------------------------------------------------------------------- /src/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wqzwh/vue-ssr/cca3e361f4921312c02fdb6ad66af1cf7c95d2c1/src/static/img/favicon.ico -------------------------------------------------------------------------------- /src/static/img/service-demo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wqzwh/vue-ssr/cca3e361f4921312c02fdb6ad66af1cf7c95d2c1/src/static/img/service-demo.jpeg -------------------------------------------------------------------------------- /src/static/js/flexible.js: -------------------------------------------------------------------------------- 1 | !function(e,t){function i(){var t=n.getBoundingClientRect().width;t/s>540&&(t=540*s);var i=t/10;n.style.fontSize=i+"px",d.rem=e.rem=i}var a,r=e.document,n=r.documentElement,o=r.querySelector('meta[name="viewport"]'),l=r.querySelector('meta[name="flexible"]'),s=0,m=0,d=t.flexible||(t.flexible={});if(o){console.warn("将根据已有的meta标签来设置缩放比例");var c=o.getAttribute("content").match(/initial\-scale=([\d\.]+)/);c&&(m=parseFloat(c[1]),s=parseInt(1/m))}else if(l){var p=l.getAttribute("content");if(p){var u=p.match(/initial\-dpr=([\d\.]+)/),f=p.match(/maximum\-dpr=([\d\.]+)/);u&&(s=parseFloat(u[1]),m=parseFloat((1/s).toFixed(2))),f&&(s=parseFloat(f[1]),m=parseFloat((1/s).toFixed(2)))}}if(!s&&!m){var v=(e.navigator.appVersion.match(/android/gi),e.navigator.appVersion.match(/iphone/gi)),b=e.devicePixelRatio;s=v?b>=3&&(!s||s>=3)?3:b>=2&&(!s||s>=2)?2:1:1,m=1/s}if(n.setAttribute("data-dpr",s),!o)if(o=r.createElement("meta"),o.setAttribute("name","viewport"),e.webPageScalable?o.setAttribute("content","initial-scale="+m+", user-scalable=yes"):o.setAttribute("content","initial-scale="+m+", maximum-scale="+m+", minimum-scale="+m+", user-scalable=no"),n.firstElementChild)n.firstElementChild.appendChild(o);else{var h=r.createElement("div");h.appendChild(o),r.write(h.innerHTML)}e.addEventListener("resize",function(){clearTimeout(a),a=setTimeout(i,300)},!1),e.addEventListener("pageshow",function(e){e.persisted&&(clearTimeout(a),a=setTimeout(i,300))},!1),"complete"===r.readyState?r.body.style.fontSize=12*s+"px":r.addEventListener("DOMContentLoaded",function(e){r.body.style.fontSize=12*s+"px"},!1),i(),d.dpr=e.dpr=s,d.refreshRem=i,d.rem2px=function(e){var t=parseFloat(e)*this.rem;return"string"==typeof e&&e.match(/rem$/)&&(t+="px"),t},d.px2rem=function(e){var t=parseFloat(e)/this.rem;return"string"==typeof e&&e.match(/px$/)&&(t+="rem"),t}}(window,window.lib||(window.lib={})); -------------------------------------------------------------------------------- /src/store/actions.js: -------------------------------------------------------------------------------- 1 | const makeAction = type => { 2 | return ({ commit }, ...args) => commit(type, ...args) 3 | } 4 | 5 | // global actions 6 | export const setLginInfo = makeAction('SET_LOGIN_INFO') 7 | // 入口组件首次出发的action 8 | export const getData = makeAction('GET_DATA') 9 | -------------------------------------------------------------------------------- /src/store/getters.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | // store.js 2 | import Vue from 'vue' 3 | import Vuex from 'vuex' 4 | import * as actions from './actions' 5 | import getters from './getters' 6 | import modules from './modules/index' 7 | Vue.use(Vuex) 8 | export function createStore() { 9 | return new Vuex.Store({ 10 | actions, 11 | getters, 12 | modules, 13 | strict: false 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /src/store/modules/global.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash' 2 | import * as types from '../mutation-types' 3 | 4 | const state = { 5 | loginfo: {}, 6 | data: {} 7 | } 8 | 9 | const mutations = { 10 | [types.SET_LOGIN_INFO](state, params) { 11 | state.loginfo = _.clone(params) 12 | }, 13 | [types.GET_DATA](state, params) { 14 | state.data = _.clone(params.data) 15 | } 16 | } 17 | 18 | export default { 19 | state, 20 | mutations 21 | } 22 | -------------------------------------------------------------------------------- /src/store/modules/index.js: -------------------------------------------------------------------------------- 1 | const files = require.context('.', false, /\.js$/) 2 | const modules = {} 3 | 4 | files.keys().forEach((key) => { 5 | if (key === './index.js') return 6 | modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default 7 | }) 8 | 9 | export default modules 10 | -------------------------------------------------------------------------------- /src/store/mutation-types.js: -------------------------------------------------------------------------------- 1 | export const SET_LOGIN_INFO = 'SET_LOGIN_INFO' 2 | export const GET_DATA = 'GET_DATA' 3 | -------------------------------------------------------------------------------- /src/views/index/conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 系统级配置 3 | */ 4 | import {mergeMock} from '../../public/utils/confUtils' 5 | /** 6 | * 页面级 MOCK 开关 7 | */ 8 | const PAGEMOCK = true; 9 | /** 10 | * 页面模块级 配置项 11 | * 注意,请求方式 默认是GET、其他特殊格式命名必须 如 PUT_STATUS '_' 链接 ,第一个字段为请求类型 12 | */ 13 | const MODULECONF = { 14 | index: { 15 | NAME: '首页', 16 | MOCK: true, 17 | API: { 18 | GET: '/api/home', 19 | GETBOTTOM: '/api/home', 20 | } 21 | } 22 | }; 23 | 24 | export default mergeMock(PAGEMOCK, MODULECONF); 25 | -------------------------------------------------------------------------------- /src/views/index/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 63 | 68 | -------------------------------------------------------------------------------- /src/views/index/mock.js: -------------------------------------------------------------------------------- 1 | import Mock from 'mockjs'; 2 | import CONF from './conf'; 3 | import { initMock } from '@/public/utils/confUtils'; 4 | 5 | const mData = { 6 | index: { 7 | API: { 8 | GET: { 9 | "code": 200, 10 | "data": [ 11 | { 12 | name: '推荐', 13 | type: 0 14 | }, 15 | { 16 | name: '居家', 17 | type: 1 18 | }, 19 | { 20 | name: '餐厨', 21 | type: 2 22 | }, 23 | { 24 | name: '服装', 25 | type: 3 26 | }, 27 | { 28 | name: '电器', 29 | type: 4 30 | }, 31 | { 32 | name: '洗护', 33 | type: 5 34 | }, 35 | { 36 | name: '杂货', 37 | type: 6 38 | } 39 | ] 40 | }, 41 | GETBOTTOM: { 42 | "code": 200, 43 | "data": [ 44 | { 45 | href: '/', 46 | value: '首页', 47 | type: 'index' 48 | }, 49 | { 50 | href: '/', 51 | value: '识物', 52 | type: 'topic' 53 | }, 54 | { 55 | href: '/', 56 | value: '分类', 57 | type: 'cate' 58 | }, 59 | { 60 | href: '/', 61 | value: '购物车', 62 | type: 'cart' 63 | }, 64 | { 65 | href: '/', 66 | value: '个人', 67 | type: 'ucenter' 68 | } 69 | ] 70 | } 71 | } 72 | } 73 | } 74 | /** 75 | * 接受参数,动态创建 76 | */ 77 | export default initMock(Mock, CONF, mData) 78 | -------------------------------------------------------------------------------- /src/views/index/service.js: -------------------------------------------------------------------------------- 1 | import Q from 'q'; 2 | import CONF from './conf'; 3 | import API from '@/public/utils/api'; 4 | 5 | const M = CONF['index']; 6 | 7 | if (process.env.STATS === 'dev') M.MOCK ? require('./mock') : ''; 8 | 9 | export default { 10 | get(params = {}) { 11 | return Q.Promise((resolve, reject) => { 12 | API.get(M['API']['GET'], params).then((data) => { 13 | resolve(data); 14 | }); 15 | }); 16 | }, 17 | getBottom(params = {}) { 18 | return Q.Promise((resolve, reject) => { 19 | API.get(M['API']['GETBOTTOM'], params).then((data) => { 20 | resolve(data); 21 | }); 22 | }); 23 | } 24 | } 25 | --------------------------------------------------------------------------------