2632c460 by simon

默认提交

0 parents
Showing 397 changed files with 15366 additions and 0 deletions
1 root = true;
2
3 [*]
4 # indent_style = tab
5 indent_style = space
6 # indent_size = 4
7 indent_size = 2
8 tab_width = 2
9 end_of_line = lf
10 trim_trailing_whitespace = true
11 insert_final_newline = true
12
13 # [*.{json,yml,wxml,html}]
14 # indent_style = tab
15 # indent_size = 4
16 # tab_width = 2
17
18
19 [README.md]
20 trim_trailing_whitespace = ignore
1 .idea
2 .DS_Store
3 dist
4 tmp
5 node_modules
6 _old
7 config.custom.js
8
9 src/assets/images/filetype.png
10
11 src/assets/images/filetype@2x.png
1 .gitignore
2 .editorconfig
3 .eslintrc
4 .idea
5 node_modules/
6 npm-debug.log
7 CHANGELOG.md
8 test
9 examples
10 gulpfile.js
11 .travis.yml
12 appveyor.yml
13 .DS_Store
14 dist
15 tmp
16 _old
17 config.custom.js
18 src/assets/images/filetype.png
19 src/assets/images/filetype@2x.png
1 sudo: false
2 language: node_js
3 node_js:
4 - "6"
5 - "7"
6 - "8"
7 - "stable"
8 before_script:
9 - npm install -g gulp@next
1 MIT License
2
3 Copyright (c) 2017 Jeff Ma
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.
1 ## 介绍
2
3 mp-gulp-framework 是一个专门为开发微信小程序打造的前端开发工作流,基于Gulp 4 开发,旨在通过工作流的方式解决微信小程序开发过程中写前端代码的痛点。
4
5 借鉴于:[https://github.com/Jeff2Ma/WeApp-Workflow](https://github.com/Jeff2Ma/WeApp-Workflow)
6 在此基础上作修改。
7
8 ## 功能
9
10 ### SCSS 实时编译为 WXSS
11
12 使用Sass 预处理器,让写CSS 更加顺畅。`.scss`文件会实时编译为微信小程序支持的`.wxss`文件。
13
14 ### WXSS(CSS) 中px 单位转小程序单位rpx
15
16 以官方推荐的iPhone 6 为标准设计格式,开发中直接写`px` 即可自动转换为`rpx`
17
18 其中屏幕铺满为750px。
19
20 ```css
21 // Input: src/pages/index/index.scss
22 .index__header {
23 font-size: 14px;
24 margin-top: 20PX; /* 如果为大写的`PX`单位则不会转换 */
25 }
26
27 // Output: dist/pages/index/index.wxss
28 .index__header {
29 font-size: 28rpx;
30 margin-top: 20PX; /* 如果为大写的`PX`单位则不会转换 */
31 }
32
33 ```
34
35 ### 图片压缩
36
37 实时压缩图片并采用增量方式防止被重复压缩。
38
39 ### 自动上传图片到CDN 并更新路径为https 绝对路径
40
41 小程序不支持相对路径的图片引用,仅支持带`https`协议头的绝对路径。本工作流可以将WXML 以及WXSS 文件中引用的相对路径图片上传到云存储CDN 或通过FTP/SFTP 协议上传到个人服务器空间。目前支持腾讯云,七牛云。
42
43 ```html
44 // Input: src/pages/index/index.wxml
45 <image src="%ASSETS_IMG%/t.png"></image>
46
47 // Output: dist/pages/index/index.wxml
48 <image src="https://cdn.devework.com/weapp/devework/t.png"></image>
49 ```
50
51 ### Font 文件转为base64 编码
52
53 小程序不支持相对路径的字体文件,本工作流可将CSS 中引用到的Font 文件转码为base64 并替换原路径。
54
55 ```
56 // Input: src/pages/index/index.scss
57 @font-face {
58 font-family: 'fontello';
59 src: url("assets/fonts/fontello.ttf") format('truetype');
60 }
61
62 // Output: dist/pages/index/index.wxss
63 @font-face {
64 font-family: 'fontello';
65 src: url(data:application/font-sfnt;charset=utf-8;base64,AAEAAAAPAIAA....FsASNsQIARAAA) format("truetype");
66 }
67
68 ```
69 ### 全自动构建雪碧图及生成相应CSS
70
71 本功能由[postcss-lazysprite](https://github.com/Jeff2Ma/postcss-lazysprite) 插件驱动。开发中准备好图片后仅仅写一句类似`@lazysprite "xxxx"`的代码,即可全自动构建雪碧图及生成相应CSS。
72
73 ```css
74 // Input: src/app.scss
75 @lazysprite "filetype";
76
77 // Output: dist/app.wxss
78 .icon-filetype-doc {
79 background-image: url(../sprites/filetype.png);
80 background-position: 0 0;
81 width: 80px;
82 height: 80px;
83 }
84
85 .icon-filetype-pdf {
86 background-image: url(../sprites/filetype.png);
87 background-position: -90px 0;
88 width: 80px;
89 height: 80px;
90 }
91
92 @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio:2) {
93 .icon-filetype-doc {
94 background-image: url(../sprites/filetype@2x.png);
95 background-position: 0 0;
96 background-size: 170px 170px;
97 }
98
99 .icon-filetype-pdf {
100 background-image: url(../sprites/filetype@2x.png);
101 background-position: -90px 0;
102 background-size: 170px 170px;
103 }
104 }
105 ```
106
107
108 ## 项目结构
109
110 ```
111 .
112 ├── config.custom.js // gulp自定义配置,会覆盖config.js
113 ├── config.js // gulp 配置文件
114 ├── gulpfile.js
115 ├── package.json
116 ├── src // 开发目录
117 │   ├── app.js
118 │   ├── app.json
119 │   ├── app.scss
120 │   ├── assets // 开发相关的静态文件原始资源
121 │  │   ├── fonts //字体文件
122 │  │   ├── images // 图片文件,可被上传到CDN
123 │  │   ├── scss // 一般放置SCSS 的minxins 等被import 的SCSS 文件
124 │  │   └── sprites // 生成雪碧图小图的目录
125 │   ├── image // 小程序专用的图片资源(如tabbar icon)目录
126 │   ├── pages
127 │   └── utils
128 ├── tmp // 通过src 目录编译后生成的缓存目录
129 └── dist // 通过src 目录编译后生成的文件目录,也是小程序开发的项目目录
130
131 ```
1 # Notes:
2 # - Minimal appveyor.yml file is an empty file. All sections are optional.
3 # - Indent each level of configuration with 2 spaces. Do not use tabs!
4 # - All section names are case-sensitive.
5 # - Section names should be unique on each level.
6
7 #---------------------------------#
8 # general configuration #
9 #---------------------------------#
10
11 # branches to build
12 #branches:
13 # # whitelist
14 # only:
15 # - master
16 # - test
17
18 # Do not build on tags (GitHub and BitBucket)
19 skip_tags: true
20
21 # Do not build feature branch with open Pull Requests
22 skip_branch_with_pr: true
23
24 # Build worker image (VM template)
25 image: Visual Studio 2015
26
27 environment:
28 matrix:
29 - nodejs_version: 4.7.0
30
31 # scripts that run after cloning repository
32 install:
33 # to run script as a PowerShell command prepend it with ps:
34 - ps: Install-Product node $env:nodejs_version
35 # batch commands start from cmd:
36 - npm cache clean
37 - npm i
38 - npm install -g gulp@next
39
40 # to run your custom scripts instead of automatic tests
41 test_script:
42 # Output useful info for debugging.
43 - node --version && npm --version
44 - npm i
45 - pwd
46 - gulp test
47
48 # Don't actually build.
49 build: off
50
51 matrix:
52 fast_finish: true
53
54 cache:
55 # local npm modules
56 - C:\Users\appveyor\AppData\Roaming\npm-cache -> package.json # npm cache
57 - node_modules -> package.json
1 /**
2 * ------------------------------------------------------------------
3 * 配置文件
4 *
5 * 建议复制一份并重命名为 config.custom.js ,即可在config.custom.js 上根据需求进行配置
6 * ------------------------------------------------------------------
7 *
8 */
9
10 module.exports = {
11 "enabledQcloud": false, //是否开启腾讯云COS 上传功能
12 // 腾讯云COS 上传功能配置表
13 "qcloud": {
14 "appid": "1111111",
15 "secretId": "xxx",
16 "secretKey": "xxxxx",
17 "bucket": "xxxx",
18 "region": "sh",
19 "prefix": "what-ever/you-want",
20 "overWrite": true,
21 "headers": {
22 "Cache-Control": "max-age=5184000"
23 }
24 },
25 // 静态资源CDN 域名,配合CDN 功能实用,线上请确保在mp管理端已经注册域名
26 "assetsCDN": "https://res.jianhui.org/"
27 };
1 # chmod u+x git.sh
2 unset msg
3
4 read -p "请输入commit提交的描述: " msg
5
6 if [[ $msg == "" ]]; then
7 msg="默认提交"
8 fi
9 git add -A
10 git commit -m $msg
11 git push
12 git status
1 /**
2 * ------------------------------------------------------------------
3 * gulpfile 文件
4 * ------------------------------------------------------------------
5 */
6
7 var path = require('path');
8 var gulp = require('gulp');
9 var changed = require('gulp-changed');
10 var sass = require('gulp-sass');
11 var rename = require('gulp-rename');
12 var imagemin = require('gulp-imagemin');
13 var sftp = require('gulp-sftp');
14 var del = require('del');
15 var replace = require('gulp-replace');
16 var postcss = require('gulp-postcss');
17 var qcloudUpload = require('gulp-qcloud-upload');
18 var gulpif = require('gulp-if');
19 var gutil = require('gulp-util');
20 var newer = require('gulp-newer');
21 var cache = require('gulp-cached');
22 var debug = require('gulp-debug');
23 var pxtorpx = require('postcss-px2rpx');
24 // var base64 = require('postcss-font-base64');
25 // var lazysprite = require('postcss-lazysprite');
26 var argv = require('yargs').argv;
27 var config = null;
28
29 // 获取用户配置
30 try {
31 config = require('./config.custom.js');
32 } catch (e) {
33 try {
34 config = require('./config.js');
35 } catch (e) {
36 log(gutil.colors.red('丢失配置文件(config.js/config.custom.js)'));
37 }
38 }
39
40 // 相关路径配置
41 var paths = {
42 src: {
43 baseDir: 'src',
44 imgDir: 'src/image',
45 spriteDir: 'src/assets/sprites',
46 scssDir: 'src/assets/scss',
47 imgFiles: 'src/image/**/*',
48 scssFiles: 'src/**/*.scss',
49 baseFiles: ['src/**/*.{png,js,json,wxml,wxss,wxs,ts,woff2}', '!src/assets/**/*', '!src/image/**/*'],
50 busFiles: ['src/**/*.{js,json}', '!src/assets/**/*', '!src/image/**/*', '!src/ui/**/*'],
51 assetsDir: 'src/assets',
52 assetsImgFiles: 'src/assets/images/**/*.{png,jpg,jpeg,svg,gif}',
53 wxmlFiles: ['src/**/*.wxml'],
54 jsFiles: 'src/**/*.js'
55 },
56 dist: {
57 baseDir: 'dist',
58 imgDir: 'dist/image',
59 wxssFiles: 'dist/**/*.wxss',
60 },
61 tmp: {
62 baseDir: 'tmp',
63 imgDir: 'tmp/assets/images',
64 imgFiles: 'tmp/assets/images/**/*.{png,jpg,jpeg,svg,gif}'
65 }
66 };
67
68 // 雪碧图的配置
69 var lazyspriteConfig = {
70 imagePath: paths.src.spriteDir,
71 stylesheetInput: paths.src.scssDir,
72 stylesheetRelative: paths.src.assetsDir,
73 spritePath: paths.src.assetsDir + '/images',
74 smartUpdate: false,
75 cssSeparator: '-',
76 outputExtralCSS: true,
77 nameSpace: 'icon-'
78 };
79
80 // Log for output msg.
81 function log() {
82 var data = Array.prototype.slice.call(arguments);
83 gutil.log.apply(false, data);
84 }
85
86 // 压缩图片
87 function imageMin() {
88 // return gulp.src(paths.src.imgFiles, {si≤nce: gulp.lastRun(imageMin)})
89 return gulp.src(paths.src.imgFiles)
90 .pipe(newer(paths.dist.imgDir))
91 .pipe(imagemin({
92 progressive: true,
93 svgoPlugins: [{
94 removeViewBox: false
95 }]
96 }))
97 .pipe(gulp.dest(paths.dist.imgDir));
98 }
99
100 // assets 文件夹下的图片处理
101 function assetsImgMin() {
102 return gulp.src(paths.src.assetsImgFiles)
103 .pipe(newer(paths.tmp.imgDir))
104 .pipe(imagemin({
105 progressive: true,
106 svgoPlugins: [{
107 removeViewBox: false
108 }]
109 }))
110 .pipe(gulp.dest(paths.tmp.imgDir))
111 }
112
113 // Sass 编译
114 function sassCompile() {
115 var res = config.assetsCDN + config.qcloud.prefix + '/';
116 // 缩放比例 1为750
117 var pxtorpxOpts = {
118 times: 1
119 };
120 return gulp.src(paths.src.scssFiles)
121 .pipe(sass({
122 errLogToConsole: true,
123 outputStyle: 'expanded'
124 })
125 .on('error', sass.logError))
126 .pipe(gulpif(Boolean(argv.debug), debug({
127 title: '`sassCompile` Debug:'
128 })))
129 // .pipe(postcss([lazysprite(lazyspriteConfig), pxtorpx(pxtorpxOpts), base64()]))
130 .pipe(postcss([pxtorpx(pxtorpxOpts)]))
131 .pipe(rename({
132 'extname': '.wxss'
133 }))
134 .pipe(replace('.scss', '.wxss'))
135 // .pipe(replace('%ASSETS_IMG%/', res))
136 // .pipe(replace('src/assets/images', res)) // 雪碧图CSS RUL 中的图片路径
137 .pipe(gulp.dest(paths.dist.baseDir))
138 }
139
140 // 复制业务文件 只复制修改过的文件
141 function copyModifyFiles() {
142 return gulp.src(paths.src.busFiles)
143 .pipe(changed(paths.dist.baseDir))
144 .pipe(gulp.dest(paths.dist.baseDir));
145 }
146
147 // 复制基础文件
148 function copyBasicFiles() {
149 return gulp.src(paths.src.baseFiles, {})
150 .pipe(gulp.dest(paths.dist.baseDir));
151 }
152
153 // 复制 WXML
154 function copyWXML() {
155 return gulp.src(paths.src.wxmlFiles, {})
156 .pipe(gulp.dest(paths.dist.baseDir));
157 }
158
159
160 // 重写WXML 中 image 标签中的图片路径
161 function wxmlImgRewrite() {
162 var res = config.assetsCDN + config.qcloud.prefix + '/';
163 return gulp.src(paths.src.wxmlFiles)
164 // .pipe(replace('%ASSETS_IMG%/', res))
165 .pipe(gulp.dest(paths.dist.baseDir))
166 }
167
168 // clean 任务, dist 目录
169 function cleanDist() {
170 return del(paths.dist.baseDir);
171 }
172
173 // clean tmp 目录
174 function cleanTmp() {
175 return del(paths.tmp.baseDir);
176 }
177
178 // 腾讯云上传任务
179 function qcloudCDN(cb) {
180 if (config.enabledQcloud) {
181 // return gulp.src(paths.src.assetsImgFiles, {since: gulp.lastRun(qcloudCDN)})
182 return gulp.src(paths.tmp.imgFiles)
183 .pipe(cache('qcloudCache'))
184 .pipe(qcloudUpload({
185 appid: config.qcloud.appid,
186 secretId: config.qcloud.secretId,
187 secretKey: config.qcloud.secretKey,
188 bucket: config.qcloud.bucket,
189 region: config.qcloud.region,
190 prefix: config.qcloud.prefix,
191 overWrite: config.qcloud.overWrite,
192 headers: config.qcloud.headers
193 }));
194 }
195 cb();
196 }
197
198
199 var watchHandler = function (type, file) {
200 var extname = path.extname(file);
201 // SCSS 文件
202 if (extname === '.scss') {
203 if (type === 'removed') {
204 var tmp = file.replace('src/', 'dist/').replace(extname, '.wxss');
205 del([tmp]);
206 } else {
207 sassCompile();
208 }
209 }
210 // 图片文件
211 else if (extname === '.png' || extname === '.jpg' || extname === '.jpeg' || extname === '.svg' || extname === '.gif') {
212 if (type === 'removed') {
213 if (file.indexOf('assets') > -1) {
214 del([file.replace('src/', 'tmp/')]);
215 } else {
216 del([file.replace('src/', 'dist/')]);
217 }
218 } else {
219 imageMin();
220 // assetsImgMin();
221 // qcloudCDN();
222 wxmlImgRewrite();
223 }
224 }
225
226 // wxml
227 else if (extname === '.wxml') {
228 if (type === 'removed') {
229 var tmp = file.replace('src/', 'dist/')
230 del([tmp]);
231 } else {
232 copyWXML();
233 wxmlImgRewrite();
234 }
235 }
236
237 // 其余文件
238 else {
239 if (type === 'removed') {
240 var tmp = file.replace('src/', 'dist/');
241 del([tmp]);
242 } else {
243 // copyBasicFiles();
244 copyModifyFiles(); // 复制修改过的业务文件
245 // copyWXML();
246 wxmlImgRewrite();
247 }
248 }
249 };
250
251 //监听文件
252 function watch(cb) {
253 var watcher = gulp.watch([
254 paths.src.baseDir,
255 paths.tmp.imgDir
256 ], {
257 ignored: /[\/\\]\./
258 });
259 watcher
260 .on('change', function (file) {
261 log(gutil.colors.yellow(file) + ' is changed');
262 watchHandler('changed', file);
263 })
264 .on('add', function (file) {
265 log(gutil.colors.yellow(file) + ' is added');
266 watchHandler('add', file);
267 })
268 .on('unlink', function (file) {
269 log(gutil.colors.yellow(file) + ' is deleted');
270 watchHandler('removed', file);
271 });
272
273 cb();
274 }
275
276 //注册默认任务
277 gulp.task('default', gulp.series(
278 cleanTmp,
279 copyBasicFiles,
280 gulp.parallel(
281 sassCompile,
282 imageMin,
283 copyWXML
284 ),
285 wxmlImgRewrite,
286 // assetsImgMin,
287 // qcloudCDN,
288 watch
289 ));
290
291 //注册测试任务
292 gulp.task('test', gulp.series(
293 cleanTmp,
294 copyBasicFiles,
295 gulp.parallel(
296 sassCompile,
297 imageMin,
298 copyWXML
299 ),
300 wxmlImgRewrite,
301 // assetsImgMin,
302 // qcloudCDN
303 ));
304
305 // 删除任务
306 gulp.task('clean', gulp.parallel(
307 cleanTmp,
308 cleanDist
309 ));
This diff could not be displayed because it is too large.
1 {
2 "name": "mp-gulp-frame-work",
3 "version": "0.0.5",
4 "description": "A workflow for better weapp developing.",
5 "main": "index.js",
6 "scripts": {
7 "test": "gulp test",
8 "dev": "gulp"
9 },
10 "repository": {
11 "type": "git",
12 "url": "http://admin@www.simonfungc.com:10086/r/mp/mp-gulp-framework.git"
13 },
14 "keywords": [
15 "gulp",
16 "gulpjs",
17 "workflow",
18 "weapp",
19 "wexin",
20 "wechat",
21 "css",
22 "wxml",
23 "wxss"
24 ],
25 "author": "SimonFungc",
26 "license": "MIT",
27 "bugs": {
28 "url": "https://www.simonfungc.com/"
29 },
30 "homepage": "https://www.simonfungc.com/",
31 "devDependencies": {
32 "del": "^4.0.0",
33 "gulp": "^4.0.0",
34 "gulp-changed": "^4.0.2",
35 "gulp-cached": "^1.1.1",
36 "gulp-debug": "^4.0.0",
37 "gulp-if": "^2.0.2",
38 "gulp-imagemin": "^5.0.0",
39 "gulp-newer": "^1.3.0",
40 "gulp-postcss": "^8.0.0",
41 "gulp-qcloud-upload": "^2.2.0",
42 "gulp-rename": "^1.2.2",
43 "gulp-replace": "^1.0.0",
44 "gulp-sass": "^4.0.0",
45 "gulp-sftp": "^0.1.5",
46 "gulp-util": "^3.0.8",
47 "postcss-font-base64": "^1.0.4",
48 "postcss-lazysprite": "^2.0.0",
49 "postcss-px2rpx": "0.0.4",
50 "yargs": "^13.1.0"
51 }
52 }
1 {
2 "client": "./dist",
3 "svr": "./server",
4 "setting": {
5 "urlCheck": false,
6 "es6": true,
7 "postcss": true,
8 "minified": true,
9 "newFeature": true
10 },
11 "appid": "wxc57ed87f2569f701",
12 "projectname": "gulp-example",
13 "condition": {}
14 }
1 //app.js
2 let fetchApi = require('./http/fetch-api.js');
3 let api = require('./http/api');
4 let config = require('./config');
5 let router = require('./router/index');
6 let store = require('./utils/stroage');
7
8 require('./http/mock-data');
9
10 App({
11 get: fetchApi.fetch,
12 post: (params) => {
13 params.method = 'post';
14 return fetchApi.fetch(params);
15 },
16 api: api,
17 config: config,
18 router: router,
19 store: store,
20 onLaunch(options) {
21 let scene = options.scene;
22 // 根据场景值判断分享入口
23 // https://developers.weixin.qq.com/miniprogram/dev/reference/scene-list.html
24 // 小程序由分享进入
25 // if (scene == 1007 || scene == 1008 || scene == 1011 || scene == 1012 || scene == 1013) {
26 // this.globalData.share = true
27 // } else {
28 // this.globalData.share = false
29 // };
30 const MenuRect = wx.getMenuButtonBoundingClientRect();
31 const statusBarHeight = wx.getSystemInfoSync().statusBarHeight;
32 const height = (MenuRect.top - statusBarHeight) * 2 + MenuRect.height + MenuRect.top;
33 this.globalData.statusBarHeight = wx.getSystemInfoSync().statusBarHeight;
34 this.globalData.barHeight = height;
35 this.share();
36 },
37 globalData: {
38 share: false,
39 indexInfo: null,
40 userInfo: null,
41 wxcode: store.getItem("wxcode"),
42 tlMemberCode: "",
43 },
44 //重写分享方法
45 share: function () {
46 //监听路由切换
47 //间接实现全局设置分享内容
48 wx.onAppRoute(function (res) {
49 //获取加载的页面
50 let pages = getCurrentPages();
51 //获取当前页面的对象
52 let view = pages[pages.length - 1];
53 let data;
54 if (view) {
55 data = view.data;
56 if (!data.isOverShare) {
57 data.isOverShare = true;
58 view.onShareAppMessage = function (res) {
59 //分享配置
60 return {
61 title: '模板标题',
62 path: 'pages/index/index',
63 // imageUrl: ''
64 };
65 };
66 }
67 }
68 })
69 },
70 })
1 {
2 "pages": [
3 "pages/index/index",
4 "pages/more/more",
5 "pages/poster-example/poster-example",
6 "pages/authorize/authorize",
7 "pages/demo/demo"
8 ],
9 "window": {
10 "backgroundTextStyle": "light",
11 "navigationBarBackgroundColor": "#fff",
12 "navigationBarTitleText": "mp-gulp-framework",
13 "navigationBarTextStyle": "black"
14 },
15 "tabBar": {
16 "color": "#7A7E83",
17 "selectedColor": "#CF4646",
18 "borderStyle": "black",
19 "backgroundColor": "#ffffff",
20 "list": [{
21 "pagePath": "pages/index/index",
22 "iconPath": "image/tabbar/home_D.png",
23 "selectedIconPath": "image/tabbar/home.png",
24 "text": "介绍"
25 },
26 {
27 "pagePath": "pages/more/more",
28 "iconPath": "image/tabbar/set_D.png",
29 "selectedIconPath": "image/tabbar/set.png",
30 "text": "更多"
31 }
32 ]
33 },
34 "usingComponents": {
35 "authorize-comp": "../../component/authorize-comp/authorize-comp",
36 "empty-tips": "../../component/empty-tips/empty-tips",
37 "van-popup": "../../ui/vant-weapp/popup/index"
38 }
39 }
1 /**
2 * ------------------------------------------------------------------
3 * app.scss 入口文件
4 *
5 * ------------------------------------------------------------------
6 *
7 */
8
9 // 支持文件
10 @import "assets/scss/support";
11
12 // 原子类
13 @import "assets/scss/utils";
14
15 // 图标
16 // @import 'styles/iconfont.wxss';
17
18 // 雪碧图
19 // @lazysprite "filetype";
20
21 // .test {
22 // background-image: url(%ASSETS_IMG%/qr-r.jpg);
23 // }
24
25 .app {
26 height: 100%;
27 justify-content: space-between;
28 // text-align: center;
29 box-sizing: border-box;
30 font-family: -apple-system-font, Helvetica Neue, Helvetica, sans-serif, FZY3JW-GB1-0;
31 }
32
33 .app__width {
34 width: 750px;
35 }
36
37 .app__width {
38 width: 750px;
39 }
40
41 .app__inner {
42 margin: 20px;
43 }
44
45 .app__title {
46 font-size: $fontSize;
47 line-height: $fontSize + 4px;
48 font-weight: bold;
49 padding-bottom: 10px;
50 margin-bottom: 20px;
51 border-bottom: .5px solid #EEEEEE;
52 }
53
54 .app__desc {
55 font-size: $fontSizeSmaller;
56 line-height: $fontSizeSmaller +2px;
57 margin-bottom: 20px;
58 color: $colorGray;
59 }
60
61 .app__bgc {
62 position: fixed;
63 background-color: #ffffff;
64 width: 100%;
65 height: 100%;
66 }
67
68 .app__bg {
69 position: absolute;
70 width: 100%;
71 height: 100%;
72 }
73
74 .app__top-shadow {
75 position: fixed;
76 width: 750px;
77 height: 1px;
78 box-shadow: 0px 4px 0.9px 0.1px rgba(6, 0, 1, 0.07);
79 background-color: #ffffff;
80 }
81
82 .app__content {
83 position: relative;
84 }
85
86
87 // web font icon
88
89 @font-face {
90 font-family: "iconfont";
91 src:url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAOsAAsAAAAAB6gAAANdAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgqDDIJmATYCJAMMCwgABCAFhG0HORuvBsgOJUHBwIABAAlgPHyN/f7c3UVEk0mi+3QSQxJNJCoexUrxUhhKIyT4UsKbL89+kizTNWb3wyt7UkR96ayA4xev1q04fZzIa32ey/Gt5wc26luWy5iT9qKFAcYBBbQ3RgEFWiAJesPYlRdxn0C9YccRqxl5ZcBCYSwLxJFS3gwsUk6lpj7UCtUle4t4Yqo2XaeXAHj0vx//QUhYkFRlxtq1w/Q2kPRz+iOmhipDoM51Gx7PD3aIjBlAITZLgxuoMDODUq8YTerLqxUhjRU3GgFfqeqrzT88kiCqGbWNYAJlEz+nbQmJP1h91rUZVMPcGeAZM51XhqohJw97O/vO23paqy3T6coNhsqQ1esr3nVWF19mTZ3YnOwtWwPk5bvMfvYCQV11V+xUzZx02tPO6H02TtP0y4dn5a7M9ravfPvs/poNl43TTmVrW87O66dcKzd3myo2Tjo5rW07l6+fcXXd3KmUDdBKXH240GtvAAw49qfa2BeatkTevUsumTJX5pzRRVy781FXe+YP15YALi0+kkDHQRm8OLz2sP/U1NGjIPxKdyVpafxHpKWvbajtddvnaxmZHLP0XGY1d2wvLarJWrd3LMD6Q1DiSPHusrPgvOxtlAKDyt7bk32nH3emP+npcwo2dKU/Vj040Jn2+HTvAU5VFtOf5vZDf683NVrpbEvIO7N3IX421A40MRbmdVIPQGXQhMi7/+o3vjanTBtt4/7Vygr4/p/GIHW7aqBWorXqz7QVQMVYCK4xXLnISlup57Ntpvcth3Ju8j8aod2b/tauu8+FWl0xkhpDyGqNEIWZQZUG86hWawH1pmUebtBBQolShynjAKHVFSTNPpG1ekUU5jWqdPuGaq1Bod56OJ7ZYCyUdKqEmjFqgy3dUNkqCozlwXRQX4Lk7VyzlNT4XAWSNMo4DA4IyuYzkYCkMTZoOuQhGDOQkUQeZoDHEMeJUC2JKtSKAxQYq2MCA5myFwW0ijygrZAgzTCkDdSiG6TUSiRg3MEYnft8CUSuHaeZVNNTka6ASDSUo0PBAgS1IDKNQquea3lGo4NcCAxjQAyJiAdlgFkIhyOC1OWzVJBWWABFj5RajECzH9PWGDC/mX++Q1DPGJsjRY6i5hgx1hSNwhTxatwNAAAAAA==') format('woff2'),
92 }
93
94 .iconfont {
95 font-family: "iconfont" !important;
96 font-size: 16px;
97 font-style: normal;
98 -webkit-font-smoothing: antialiased;
99 -moz-osx-font-smoothing: grayscale;
100 }
101
102 .iconrefresh:before {
103 content: "\e874";
104 }
105
106 .iconempty:before {
107 content: "\e6a6";
108 }
109
110 .drop-down-item :last-child {
111 border-bottom: none;
112 }
1 @charset "UTF-8";
2
3 /*!
4 * animate.css -http://daneden.me/animate
5 * Version - 3.6.0
6 * Licensed under the MIT license - http://opensource.org/licenses/MIT
7 *
8 * Copyright (c) 2018 Daniel Eden
9 */
10
11 .animated {
12 -webkit-animation-duration: 1s;
13 animation-duration: 1s;
14 -webkit-animation-fill-mode: both;
15 animation-fill-mode: both;
16 }
17
18 .animated.infinite {
19 -webkit-animation-iteration-count: infinite;
20 animation-iteration-count: infinite;
21 }
22
23 @-webkit-keyframes bounce {
24 from,
25 20%,
26 53%,
27 80%,
28 to {
29 -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
30 animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
31 -webkit-transform: translate3d(0, 0, 0);
32 transform: translate3d(0, 0, 0);
33 }
34
35 40%,
36 43% {
37 -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
38 animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
39 -webkit-transform: translate3d(0, -30px, 0);
40 transform: translate3d(0, -30px, 0);
41 }
42
43 70% {
44 -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
45 animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
46 -webkit-transform: translate3d(0, -15px, 0);
47 transform: translate3d(0, -15px, 0);
48 }
49
50 90% {
51 -webkit-transform: translate3d(0, -4px, 0);
52 transform: translate3d(0, -4px, 0);
53 }
54 }
55
56 @keyframes bounce {
57 from,
58 20%,
59 53%,
60 80%,
61 to {
62 -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
63 animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
64 -webkit-transform: translate3d(0, 0, 0);
65 transform: translate3d(0, 0, 0);
66 }
67
68 40%,
69 43% {
70 -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
71 animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
72 -webkit-transform: translate3d(0, -30px, 0);
73 transform: translate3d(0, -30px, 0);
74 }
75
76 70% {
77 -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
78 animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
79 -webkit-transform: translate3d(0, -15px, 0);
80 transform: translate3d(0, -15px, 0);
81 }
82
83 90% {
84 -webkit-transform: translate3d(0, -4px, 0);
85 transform: translate3d(0, -4px, 0);
86 }
87 }
88
89 .bounce {
90 -webkit-animation-name: bounce;
91 animation-name: bounce;
92 -webkit-transform-origin: center bottom;
93 transform-origin: center bottom;
94 }
95
96 @-webkit-keyframes flash {
97 from,
98 50%,
99 to {
100 opacity: 1;
101 }
102
103 25%,
104 75% {
105 opacity: 0;
106 }
107 }
108
109 @keyframes flash {
110 from,
111 50%,
112 to {
113 opacity: 1;
114 }
115
116 25%,
117 75% {
118 opacity: 0;
119 }
120 }
121
122 .flash {
123 -webkit-animation-name: flash;
124 animation-name: flash;
125 }
126
127 @-webkit-keyframes pulse {
128 from {
129 -webkit-transform: scale3d(1, 1, 1);
130 transform: scale3d(1, 1, 1);
131 }
132
133 50% {
134 -webkit-transform: scale3d(1.05, 1.05, 1.05);
135 transform: scale3d(1.05, 1.05, 1.05);
136 }
137
138 to {
139 -webkit-transform: scale3d(1, 1, 1);
140 transform: scale3d(1, 1, 1);
141 }
142 }
143
144 @keyframes pulse {
145 from {
146 -webkit-transform: scale3d(1, 1, 1);
147 transform: scale3d(1, 1, 1);
148 }
149
150 50% {
151 -webkit-transform: scale3d(1.05, 1.05, 1.05);
152 transform: scale3d(1.05, 1.05, 1.05);
153 }
154
155 to {
156 -webkit-transform: scale3d(1, 1, 1);
157 transform: scale3d(1, 1, 1);
158 }
159 }
160
161 .pulse {
162 -webkit-animation-name: pulse;
163 animation-name: pulse;
164 }
165
166 @-webkit-keyframes rubberBand {
167 from {
168 -webkit-transform: scale3d(1, 1, 1);
169 transform: scale3d(1, 1, 1);
170 }
171
172 30% {
173 -webkit-transform: scale3d(1.25, 0.75, 1);
174 transform: scale3d(1.25, 0.75, 1);
175 }
176
177 40% {
178 -webkit-transform: scale3d(0.75, 1.25, 1);
179 transform: scale3d(0.75, 1.25, 1);
180 }
181
182 50% {
183 -webkit-transform: scale3d(1.15, 0.85, 1);
184 transform: scale3d(1.15, 0.85, 1);
185 }
186
187 65% {
188 -webkit-transform: scale3d(0.95, 1.05, 1);
189 transform: scale3d(0.95, 1.05, 1);
190 }
191
192 75% {
193 -webkit-transform: scale3d(1.05, 0.95, 1);
194 transform: scale3d(1.05, 0.95, 1);
195 }
196
197 to {
198 -webkit-transform: scale3d(1, 1, 1);
199 transform: scale3d(1, 1, 1);
200 }
201 }
202
203 @keyframes rubberBand {
204 from {
205 -webkit-transform: scale3d(1, 1, 1);
206 transform: scale3d(1, 1, 1);
207 }
208
209 30% {
210 -webkit-transform: scale3d(1.25, 0.75, 1);
211 transform: scale3d(1.25, 0.75, 1);
212 }
213
214 40% {
215 -webkit-transform: scale3d(0.75, 1.25, 1);
216 transform: scale3d(0.75, 1.25, 1);
217 }
218
219 50% {
220 -webkit-transform: scale3d(1.15, 0.85, 1);
221 transform: scale3d(1.15, 0.85, 1);
222 }
223
224 65% {
225 -webkit-transform: scale3d(0.95, 1.05, 1);
226 transform: scale3d(0.95, 1.05, 1);
227 }
228
229 75% {
230 -webkit-transform: scale3d(1.05, 0.95, 1);
231 transform: scale3d(1.05, 0.95, 1);
232 }
233
234 to {
235 -webkit-transform: scale3d(1, 1, 1);
236 transform: scale3d(1, 1, 1);
237 }
238 }
239
240 .rubberBand {
241 -webkit-animation-name: rubberBand;
242 animation-name: rubberBand;
243 }
244
245 @-webkit-keyframes shake {
246 from,
247 to {
248 -webkit-transform: translate3d(0, 0, 0);
249 transform: translate3d(0, 0, 0);
250 }
251
252 10%,
253 30%,
254 50%,
255 70%,
256 90% {
257 -webkit-transform: translate3d(-10px, 0, 0);
258 transform: translate3d(-10px, 0, 0);
259 }
260
261 20%,
262 40%,
263 60%,
264 80% {
265 -webkit-transform: translate3d(10px, 0, 0);
266 transform: translate3d(10px, 0, 0);
267 }
268 }
269
270 @keyframes shake {
271 from,
272 to {
273 -webkit-transform: translate3d(0, 0, 0);
274 transform: translate3d(0, 0, 0);
275 }
276
277 10%,
278 30%,
279 50%,
280 70%,
281 90% {
282 -webkit-transform: translate3d(-10px, 0, 0);
283 transform: translate3d(-10px, 0, 0);
284 }
285
286 20%,
287 40%,
288 60%,
289 80% {
290 -webkit-transform: translate3d(10px, 0, 0);
291 transform: translate3d(10px, 0, 0);
292 }
293 }
294
295 .shake {
296 -webkit-animation-name: shake;
297 animation-name: shake;
298 }
299
300 @-webkit-keyframes headShake {
301 0% {
302 -webkit-transform: translateX(0);
303 transform: translateX(0);
304 }
305
306 6.5% {
307 -webkit-transform: translateX(-6px) rotateY(-9deg);
308 transform: translateX(-6px) rotateY(-9deg);
309 }
310
311 18.5% {
312 -webkit-transform: translateX(5px) rotateY(7deg);
313 transform: translateX(5px) rotateY(7deg);
314 }
315
316 31.5% {
317 -webkit-transform: translateX(-3px) rotateY(-5deg);
318 transform: translateX(-3px) rotateY(-5deg);
319 }
320
321 43.5% {
322 -webkit-transform: translateX(2px) rotateY(3deg);
323 transform: translateX(2px) rotateY(3deg);
324 }
325
326 50% {
327 -webkit-transform: translateX(0);
328 transform: translateX(0);
329 }
330 }
331
332 @keyframes headShake {
333 0% {
334 -webkit-transform: translateX(0);
335 transform: translateX(0);
336 }
337
338 6.5% {
339 -webkit-transform: translateX(-6px) rotateY(-9deg);
340 transform: translateX(-6px) rotateY(-9deg);
341 }
342
343 18.5% {
344 -webkit-transform: translateX(5px) rotateY(7deg);
345 transform: translateX(5px) rotateY(7deg);
346 }
347
348 31.5% {
349 -webkit-transform: translateX(-3px) rotateY(-5deg);
350 transform: translateX(-3px) rotateY(-5deg);
351 }
352
353 43.5% {
354 -webkit-transform: translateX(2px) rotateY(3deg);
355 transform: translateX(2px) rotateY(3deg);
356 }
357
358 50% {
359 -webkit-transform: translateX(0);
360 transform: translateX(0);
361 }
362 }
363
364 .headShake {
365 -webkit-animation-timing-function: ease-in-out;
366 animation-timing-function: ease-in-out;
367 -webkit-animation-name: headShake;
368 animation-name: headShake;
369 }
370
371 @-webkit-keyframes swing {
372 20% {
373 -webkit-transform: rotate3d(0, 0, 1, 15deg);
374 transform: rotate3d(0, 0, 1, 15deg);
375 }
376
377 40% {
378 -webkit-transform: rotate3d(0, 0, 1, -10deg);
379 transform: rotate3d(0, 0, 1, -10deg);
380 }
381
382 60% {
383 -webkit-transform: rotate3d(0, 0, 1, 5deg);
384 transform: rotate3d(0, 0, 1, 5deg);
385 }
386
387 80% {
388 -webkit-transform: rotate3d(0, 0, 1, -5deg);
389 transform: rotate3d(0, 0, 1, -5deg);
390 }
391
392 to {
393 -webkit-transform: rotate3d(0, 0, 1, 0deg);
394 transform: rotate3d(0, 0, 1, 0deg);
395 }
396 }
397
398 @keyframes swing {
399 20% {
400 -webkit-transform: rotate3d(0, 0, 1, 15deg);
401 transform: rotate3d(0, 0, 1, 15deg);
402 }
403
404 40% {
405 -webkit-transform: rotate3d(0, 0, 1, -10deg);
406 transform: rotate3d(0, 0, 1, -10deg);
407 }
408
409 60% {
410 -webkit-transform: rotate3d(0, 0, 1, 5deg);
411 transform: rotate3d(0, 0, 1, 5deg);
412 }
413
414 80% {
415 -webkit-transform: rotate3d(0, 0, 1, -5deg);
416 transform: rotate3d(0, 0, 1, -5deg);
417 }
418
419 to {
420 -webkit-transform: rotate3d(0, 0, 1, 0deg);
421 transform: rotate3d(0, 0, 1, 0deg);
422 }
423 }
424
425 .swing {
426 -webkit-transform-origin: top center;
427 transform-origin: top center;
428 -webkit-animation-name: swing;
429 animation-name: swing;
430 }
431
432 @-webkit-keyframes tada {
433 from {
434 -webkit-transform: scale3d(1, 1, 1);
435 transform: scale3d(1, 1, 1);
436 }
437
438 10%,
439 20% {
440 -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
441 transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
442 }
443
444 30%,
445 50%,
446 70%,
447 90% {
448 -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
449 transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
450 }
451
452 40%,
453 60%,
454 80% {
455 -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
456 transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
457 }
458
459 to {
460 -webkit-transform: scale3d(1, 1, 1);
461 transform: scale3d(1, 1, 1);
462 }
463 }
464
465 @keyframes tada {
466 from {
467 -webkit-transform: scale3d(1, 1, 1);
468 transform: scale3d(1, 1, 1);
469 }
470
471 10%,
472 20% {
473 -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
474 transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
475 }
476
477 30%,
478 50%,
479 70%,
480 90% {
481 -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
482 transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
483 }
484
485 40%,
486 60%,
487 80% {
488 -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
489 transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
490 }
491
492 to {
493 -webkit-transform: scale3d(1, 1, 1);
494 transform: scale3d(1, 1, 1);
495 }
496 }
497
498 .tada {
499 -webkit-animation-name: tada;
500 animation-name: tada;
501 }
502
503 @-webkit-keyframes wobble {
504 from {
505 -webkit-transform: translate3d(0, 0, 0);
506 transform: translate3d(0, 0, 0);
507 }
508
509 15% {
510 -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
511 transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
512 }
513
514 30% {
515 -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
516 transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
517 }
518
519 45% {
520 -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
521 transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
522 }
523
524 60% {
525 -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
526 transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
527 }
528
529 75% {
530 -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
531 transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
532 }
533
534 to {
535 -webkit-transform: translate3d(0, 0, 0);
536 transform: translate3d(0, 0, 0);
537 }
538 }
539
540 @keyframes wobble {
541 from {
542 -webkit-transform: translate3d(0, 0, 0);
543 transform: translate3d(0, 0, 0);
544 }
545
546 15% {
547 -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
548 transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
549 }
550
551 30% {
552 -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
553 transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
554 }
555
556 45% {
557 -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
558 transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
559 }
560
561 60% {
562 -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
563 transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
564 }
565
566 75% {
567 -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
568 transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
569 }
570
571 to {
572 -webkit-transform: translate3d(0, 0, 0);
573 transform: translate3d(0, 0, 0);
574 }
575 }
576
577 .wobble {
578 -webkit-animation-name: wobble;
579 animation-name: wobble;
580 }
581
582 @-webkit-keyframes jello {
583 from,
584 11.1%,
585 to {
586 -webkit-transform: translate3d(0, 0, 0);
587 transform: translate3d(0, 0, 0);
588 }
589
590 22.2% {
591 -webkit-transform: skewX(-12.5deg) skewY(-12.5deg);
592 transform: skewX(-12.5deg) skewY(-12.5deg);
593 }
594
595 33.3% {
596 -webkit-transform: skewX(6.25deg) skewY(6.25deg);
597 transform: skewX(6.25deg) skewY(6.25deg);
598 }
599
600 44.4% {
601 -webkit-transform: skewX(-3.125deg) skewY(-3.125deg);
602 transform: skewX(-3.125deg) skewY(-3.125deg);
603 }
604
605 55.5% {
606 -webkit-transform: skewX(1.5625deg) skewY(1.5625deg);
607 transform: skewX(1.5625deg) skewY(1.5625deg);
608 }
609
610 66.6% {
611 -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg);
612 transform: skewX(-0.78125deg) skewY(-0.78125deg);
613 }
614
615 77.7% {
616 -webkit-transform: skewX(0.390625deg) skewY(0.390625deg);
617 transform: skewX(0.390625deg) skewY(0.390625deg);
618 }
619
620 88.8% {
621 -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
622 transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
623 }
624 }
625
626 @keyframes jello {
627 from,
628 11.1%,
629 to {
630 -webkit-transform: translate3d(0, 0, 0);
631 transform: translate3d(0, 0, 0);
632 }
633
634 22.2% {
635 -webkit-transform: skewX(-12.5deg) skewY(-12.5deg);
636 transform: skewX(-12.5deg) skewY(-12.5deg);
637 }
638
639 33.3% {
640 -webkit-transform: skewX(6.25deg) skewY(6.25deg);
641 transform: skewX(6.25deg) skewY(6.25deg);
642 }
643
644 44.4% {
645 -webkit-transform: skewX(-3.125deg) skewY(-3.125deg);
646 transform: skewX(-3.125deg) skewY(-3.125deg);
647 }
648
649 55.5% {
650 -webkit-transform: skewX(1.5625deg) skewY(1.5625deg);
651 transform: skewX(1.5625deg) skewY(1.5625deg);
652 }
653
654 66.6% {
655 -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg);
656 transform: skewX(-0.78125deg) skewY(-0.78125deg);
657 }
658
659 77.7% {
660 -webkit-transform: skewX(0.390625deg) skewY(0.390625deg);
661 transform: skewX(0.390625deg) skewY(0.390625deg);
662 }
663
664 88.8% {
665 -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
666 transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
667 }
668 }
669
670 .jello {
671 -webkit-animation-name: jello;
672 animation-name: jello;
673 -webkit-transform-origin: center;
674 transform-origin: center;
675 }
676
677 @-webkit-keyframes bounceIn {
678 from,
679 20%,
680 40%,
681 60%,
682 80%,
683 to {
684 -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
685 animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
686 }
687
688 0% {
689 opacity: 0;
690 -webkit-transform: scale3d(0.3, 0.3, 0.3);
691 transform: scale3d(0.3, 0.3, 0.3);
692 }
693
694 20% {
695 -webkit-transform: scale3d(1.1, 1.1, 1.1);
696 transform: scale3d(1.1, 1.1, 1.1);
697 }
698
699 40% {
700 -webkit-transform: scale3d(0.9, 0.9, 0.9);
701 transform: scale3d(0.9, 0.9, 0.9);
702 }
703
704 60% {
705 opacity: 1;
706 -webkit-transform: scale3d(1.03, 1.03, 1.03);
707 transform: scale3d(1.03, 1.03, 1.03);
708 }
709
710 80% {
711 -webkit-transform: scale3d(0.97, 0.97, 0.97);
712 transform: scale3d(0.97, 0.97, 0.97);
713 }
714
715 to {
716 opacity: 1;
717 -webkit-transform: scale3d(1, 1, 1);
718 transform: scale3d(1, 1, 1);
719 }
720 }
721
722 @keyframes bounceIn {
723 from,
724 20%,
725 40%,
726 60%,
727 80%,
728 to {
729 -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
730 animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
731 }
732
733 0% {
734 opacity: 0;
735 -webkit-transform: scale3d(0.3, 0.3, 0.3);
736 transform: scale3d(0.3, 0.3, 0.3);
737 }
738
739 20% {
740 -webkit-transform: scale3d(1.1, 1.1, 1.1);
741 transform: scale3d(1.1, 1.1, 1.1);
742 }
743
744 40% {
745 -webkit-transform: scale3d(0.9, 0.9, 0.9);
746 transform: scale3d(0.9, 0.9, 0.9);
747 }
748
749 60% {
750 opacity: 1;
751 -webkit-transform: scale3d(1.03, 1.03, 1.03);
752 transform: scale3d(1.03, 1.03, 1.03);
753 }
754
755 80% {
756 -webkit-transform: scale3d(0.97, 0.97, 0.97);
757 transform: scale3d(0.97, 0.97, 0.97);
758 }
759
760 to {
761 opacity: 1;
762 -webkit-transform: scale3d(1, 1, 1);
763 transform: scale3d(1, 1, 1);
764 }
765 }
766
767 .bounceIn {
768 -webkit-animation-duration: 0.75s;
769 animation-duration: 0.75s;
770 -webkit-animation-name: bounceIn;
771 animation-name: bounceIn;
772 }
773
774 @-webkit-keyframes bounceInDown {
775 from,
776 60%,
777 75%,
778 90%,
779 to {
780 -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
781 animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
782 }
783
784 0% {
785 opacity: 0;
786 -webkit-transform: translate3d(0, -3000px, 0);
787 transform: translate3d(0, -3000px, 0);
788 }
789
790 60% {
791 opacity: 1;
792 -webkit-transform: translate3d(0, 25px, 0);
793 transform: translate3d(0, 25px, 0);
794 }
795
796 75% {
797 -webkit-transform: translate3d(0, -10px, 0);
798 transform: translate3d(0, -10px, 0);
799 }
800
801 90% {
802 -webkit-transform: translate3d(0, 5px, 0);
803 transform: translate3d(0, 5px, 0);
804 }
805
806 to {
807 -webkit-transform: translate3d(0, 0, 0);
808 transform: translate3d(0, 0, 0);
809 }
810 }
811
812 @keyframes bounceInDown {
813 from,
814 60%,
815 75%,
816 90%,
817 to {
818 -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
819 animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
820 }
821
822 0% {
823 opacity: 0;
824 -webkit-transform: translate3d(0, -3000px, 0);
825 transform: translate3d(0, -3000px, 0);
826 }
827
828 60% {
829 opacity: 1;
830 -webkit-transform: translate3d(0, 25px, 0);
831 transform: translate3d(0, 25px, 0);
832 }
833
834 75% {
835 -webkit-transform: translate3d(0, -10px, 0);
836 transform: translate3d(0, -10px, 0);
837 }
838
839 90% {
840 -webkit-transform: translate3d(0, 5px, 0);
841 transform: translate3d(0, 5px, 0);
842 }
843
844 to {
845 -webkit-transform: translate3d(0, 0, 0);
846 transform: translate3d(0, 0, 0);
847 }
848 }
849
850 .bounceInDown {
851 -webkit-animation-name: bounceInDown;
852 animation-name: bounceInDown;
853 }
854
855 @-webkit-keyframes bounceInLeft {
856 from,
857 60%,
858 75%,
859 90%,
860 to {
861 -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
862 animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
863 }
864
865 0% {
866 opacity: 0;
867 -webkit-transform: translate3d(-3000px, 0, 0);
868 transform: translate3d(-3000px, 0, 0);
869 }
870
871 60% {
872 opacity: 1;
873 -webkit-transform: translate3d(25px, 0, 0);
874 transform: translate3d(25px, 0, 0);
875 }
876
877 75% {
878 -webkit-transform: translate3d(-10px, 0, 0);
879 transform: translate3d(-10px, 0, 0);
880 }
881
882 90% {
883 -webkit-transform: translate3d(5px, 0, 0);
884 transform: translate3d(5px, 0, 0);
885 }
886
887 to {
888 -webkit-transform: translate3d(0, 0, 0);
889 transform: translate3d(0, 0, 0);
890 }
891 }
892
893 @keyframes bounceInLeft {
894 from,
895 60%,
896 75%,
897 90%,
898 to {
899 -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
900 animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
901 }
902
903 0% {
904 opacity: 0;
905 -webkit-transform: translate3d(-3000px, 0, 0);
906 transform: translate3d(-3000px, 0, 0);
907 }
908
909 60% {
910 opacity: 1;
911 -webkit-transform: translate3d(25px, 0, 0);
912 transform: translate3d(25px, 0, 0);
913 }
914
915 75% {
916 -webkit-transform: translate3d(-10px, 0, 0);
917 transform: translate3d(-10px, 0, 0);
918 }
919
920 90% {
921 -webkit-transform: translate3d(5px, 0, 0);
922 transform: translate3d(5px, 0, 0);
923 }
924
925 to {
926 -webkit-transform: translate3d(0, 0, 0);
927 transform: translate3d(0, 0, 0);
928 }
929 }
930
931 .bounceInLeft {
932 -webkit-animation-name: bounceInLeft;
933 animation-name: bounceInLeft;
934 }
935
936 @-webkit-keyframes bounceInRight {
937 from,
938 60%,
939 75%,
940 90%,
941 to {
942 -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
943 animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
944 }
945
946 from {
947 opacity: 0;
948 -webkit-transform: translate3d(3000px, 0, 0);
949 transform: translate3d(3000px, 0, 0);
950 }
951
952 60% {
953 opacity: 1;
954 -webkit-transform: translate3d(-25px, 0, 0);
955 transform: translate3d(-25px, 0, 0);
956 }
957
958 75% {
959 -webkit-transform: translate3d(10px, 0, 0);
960 transform: translate3d(10px, 0, 0);
961 }
962
963 90% {
964 -webkit-transform: translate3d(-5px, 0, 0);
965 transform: translate3d(-5px, 0, 0);
966 }
967
968 to {
969 -webkit-transform: translate3d(0, 0, 0);
970 transform: translate3d(0, 0, 0);
971 }
972 }
973
974 @keyframes bounceInRight {
975 from,
976 60%,
977 75%,
978 90%,
979 to {
980 -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
981 animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
982 }
983
984 from {
985 opacity: 0;
986 -webkit-transform: translate3d(3000px, 0, 0);
987 transform: translate3d(3000px, 0, 0);
988 }
989
990 60% {
991 opacity: 1;
992 -webkit-transform: translate3d(-25px, 0, 0);
993 transform: translate3d(-25px, 0, 0);
994 }
995
996 75% {
997 -webkit-transform: translate3d(10px, 0, 0);
998 transform: translate3d(10px, 0, 0);
999 }
1000
1001 90% {
1002 -webkit-transform: translate3d(-5px, 0, 0);
1003 transform: translate3d(-5px, 0, 0);
1004 }
1005
1006 to {
1007 -webkit-transform: translate3d(0, 0, 0);
1008 transform: translate3d(0, 0, 0);
1009 }
1010 }
1011
1012 .bounceInRight {
1013 -webkit-animation-name: bounceInRight;
1014 animation-name: bounceInRight;
1015 }
1016
1017 @-webkit-keyframes bounceInUp {
1018 from,
1019 60%,
1020 75%,
1021 90%,
1022 to {
1023 -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
1024 animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
1025 }
1026
1027 from {
1028 opacity: 0;
1029 -webkit-transform: translate3d(0, 3000px, 0);
1030 transform: translate3d(0, 3000px, 0);
1031 }
1032
1033 60% {
1034 opacity: 1;
1035 -webkit-transform: translate3d(0, -20px, 0);
1036 transform: translate3d(0, -20px, 0);
1037 }
1038
1039 75% {
1040 -webkit-transform: translate3d(0, 10px, 0);
1041 transform: translate3d(0, 10px, 0);
1042 }
1043
1044 90% {
1045 -webkit-transform: translate3d(0, -5px, 0);
1046 transform: translate3d(0, -5px, 0);
1047 }
1048
1049 to {
1050 -webkit-transform: translate3d(0, 0, 0);
1051 transform: translate3d(0, 0, 0);
1052 }
1053 }
1054
1055 @keyframes bounceInUp {
1056 from,
1057 60%,
1058 75%,
1059 90%,
1060 to {
1061 -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
1062 animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
1063 }
1064
1065 from {
1066 opacity: 0;
1067 -webkit-transform: translate3d(0, 3000px, 0);
1068 transform: translate3d(0, 3000px, 0);
1069 }
1070
1071 60% {
1072 opacity: 1;
1073 -webkit-transform: translate3d(0, -20px, 0);
1074 transform: translate3d(0, -20px, 0);
1075 }
1076
1077 75% {
1078 -webkit-transform: translate3d(0, 10px, 0);
1079 transform: translate3d(0, 10px, 0);
1080 }
1081
1082 90% {
1083 -webkit-transform: translate3d(0, -5px, 0);
1084 transform: translate3d(0, -5px, 0);
1085 }
1086
1087 to {
1088 -webkit-transform: translate3d(0, 0, 0);
1089 transform: translate3d(0, 0, 0);
1090 }
1091 }
1092
1093 .bounceInUp {
1094 -webkit-animation-name: bounceInUp;
1095 animation-name: bounceInUp;
1096 }
1097
1098 @-webkit-keyframes bounceOut {
1099 20% {
1100 -webkit-transform: scale3d(0.9, 0.9, 0.9);
1101 transform: scale3d(0.9, 0.9, 0.9);
1102 }
1103
1104 50%,
1105 55% {
1106 opacity: 1;
1107 -webkit-transform: scale3d(1.1, 1.1, 1.1);
1108 transform: scale3d(1.1, 1.1, 1.1);
1109 }
1110
1111 to {
1112 opacity: 0;
1113 -webkit-transform: scale3d(0.3, 0.3, 0.3);
1114 transform: scale3d(0.3, 0.3, 0.3);
1115 }
1116 }
1117
1118 @keyframes bounceOut {
1119 20% {
1120 -webkit-transform: scale3d(0.9, 0.9, 0.9);
1121 transform: scale3d(0.9, 0.9, 0.9);
1122 }
1123
1124 50%,
1125 55% {
1126 opacity: 1;
1127 -webkit-transform: scale3d(1.1, 1.1, 1.1);
1128 transform: scale3d(1.1, 1.1, 1.1);
1129 }
1130
1131 to {
1132 opacity: 0;
1133 -webkit-transform: scale3d(0.3, 0.3, 0.3);
1134 transform: scale3d(0.3, 0.3, 0.3);
1135 }
1136 }
1137
1138 .bounceOut {
1139 -webkit-animation-duration: 0.75s;
1140 animation-duration: 0.75s;
1141 -webkit-animation-name: bounceOut;
1142 animation-name: bounceOut;
1143 }
1144
1145 @-webkit-keyframes bounceOutDown {
1146 20% {
1147 -webkit-transform: translate3d(0, 10px, 0);
1148 transform: translate3d(0, 10px, 0);
1149 }
1150
1151 40%,
1152 45% {
1153 opacity: 1;
1154 -webkit-transform: translate3d(0, -20px, 0);
1155 transform: translate3d(0, -20px, 0);
1156 }
1157
1158 to {
1159 opacity: 0;
1160 -webkit-transform: translate3d(0, 2000px, 0);
1161 transform: translate3d(0, 2000px, 0);
1162 }
1163 }
1164
1165 @keyframes bounceOutDown {
1166 20% {
1167 -webkit-transform: translate3d(0, 10px, 0);
1168 transform: translate3d(0, 10px, 0);
1169 }
1170
1171 40%,
1172 45% {
1173 opacity: 1;
1174 -webkit-transform: translate3d(0, -20px, 0);
1175 transform: translate3d(0, -20px, 0);
1176 }
1177
1178 to {
1179 opacity: 0;
1180 -webkit-transform: translate3d(0, 2000px, 0);
1181 transform: translate3d(0, 2000px, 0);
1182 }
1183 }
1184
1185 .bounceOutDown {
1186 -webkit-animation-name: bounceOutDown;
1187 animation-name: bounceOutDown;
1188 }
1189
1190 @-webkit-keyframes bounceOutLeft {
1191 20% {
1192 opacity: 1;
1193 -webkit-transform: translate3d(20px, 0, 0);
1194 transform: translate3d(20px, 0, 0);
1195 }
1196
1197 to {
1198 opacity: 0;
1199 -webkit-transform: translate3d(-2000px, 0, 0);
1200 transform: translate3d(-2000px, 0, 0);
1201 }
1202 }
1203
1204 @keyframes bounceOutLeft {
1205 20% {
1206 opacity: 1;
1207 -webkit-transform: translate3d(20px, 0, 0);
1208 transform: translate3d(20px, 0, 0);
1209 }
1210
1211 to {
1212 opacity: 0;
1213 -webkit-transform: translate3d(-2000px, 0, 0);
1214 transform: translate3d(-2000px, 0, 0);
1215 }
1216 }
1217
1218 .bounceOutLeft {
1219 -webkit-animation-name: bounceOutLeft;
1220 animation-name: bounceOutLeft;
1221 }
1222
1223 @-webkit-keyframes bounceOutRight {
1224 20% {
1225 opacity: 1;
1226 -webkit-transform: translate3d(-20px, 0, 0);
1227 transform: translate3d(-20px, 0, 0);
1228 }
1229
1230 to {
1231 opacity: 0;
1232 -webkit-transform: translate3d(2000px, 0, 0);
1233 transform: translate3d(2000px, 0, 0);
1234 }
1235 }
1236
1237 @keyframes bounceOutRight {
1238 20% {
1239 opacity: 1;
1240 -webkit-transform: translate3d(-20px, 0, 0);
1241 transform: translate3d(-20px, 0, 0);
1242 }
1243
1244 to {
1245 opacity: 0;
1246 -webkit-transform: translate3d(2000px, 0, 0);
1247 transform: translate3d(2000px, 0, 0);
1248 }
1249 }
1250
1251 .bounceOutRight {
1252 -webkit-animation-name: bounceOutRight;
1253 animation-name: bounceOutRight;
1254 }
1255
1256 @-webkit-keyframes bounceOutUp {
1257 20% {
1258 -webkit-transform: translate3d(0, -10px, 0);
1259 transform: translate3d(0, -10px, 0);
1260 }
1261
1262 40%,
1263 45% {
1264 opacity: 1;
1265 -webkit-transform: translate3d(0, 20px, 0);
1266 transform: translate3d(0, 20px, 0);
1267 }
1268
1269 to {
1270 opacity: 0;
1271 -webkit-transform: translate3d(0, -2000px, 0);
1272 transform: translate3d(0, -2000px, 0);
1273 }
1274 }
1275
1276 @keyframes bounceOutUp {
1277 20% {
1278 -webkit-transform: translate3d(0, -10px, 0);
1279 transform: translate3d(0, -10px, 0);
1280 }
1281
1282 40%,
1283 45% {
1284 opacity: 1;
1285 -webkit-transform: translate3d(0, 20px, 0);
1286 transform: translate3d(0, 20px, 0);
1287 }
1288
1289 to {
1290 opacity: 0;
1291 -webkit-transform: translate3d(0, -2000px, 0);
1292 transform: translate3d(0, -2000px, 0);
1293 }
1294 }
1295
1296 .bounceOutUp {
1297 -webkit-animation-name: bounceOutUp;
1298 animation-name: bounceOutUp;
1299 }
1300
1301 @-webkit-keyframes fadeIn {
1302 from {
1303 opacity: 0;
1304 }
1305
1306 to {
1307 opacity: 1;
1308 }
1309 }
1310
1311 @keyframes fadeIn {
1312 from {
1313 opacity: 0;
1314 }
1315
1316 to {
1317 opacity: 1;
1318 }
1319 }
1320
1321 .fadeIn {
1322 -webkit-animation-name: fadeIn;
1323 animation-name: fadeIn;
1324 }
1325
1326 @-webkit-keyframes fadeInDown {
1327 from {
1328 opacity: 0;
1329 -webkit-transform: translate3d(0, -100%, 0);
1330 transform: translate3d(0, -100%, 0);
1331 }
1332
1333 to {
1334 opacity: 1;
1335 -webkit-transform: translate3d(0, 0, 0);
1336 transform: translate3d(0, 0, 0);
1337 }
1338 }
1339
1340 @keyframes fadeInDown {
1341 from {
1342 opacity: 0;
1343 -webkit-transform: translate3d(0, -100%, 0);
1344 transform: translate3d(0, -100%, 0);
1345 }
1346
1347 to {
1348 opacity: 1;
1349 -webkit-transform: translate3d(0, 0, 0);
1350 transform: translate3d(0, 0, 0);
1351 }
1352 }
1353
1354 .fadeInDown {
1355 -webkit-animation-name: fadeInDown;
1356 animation-name: fadeInDown;
1357 }
1358
1359 @-webkit-keyframes fadeInDownBig {
1360 from {
1361 opacity: 0;
1362 -webkit-transform: translate3d(0, -2000px, 0);
1363 transform: translate3d(0, -2000px, 0);
1364 }
1365
1366 to {
1367 opacity: 1;
1368 -webkit-transform: translate3d(0, 0, 0);
1369 transform: translate3d(0, 0, 0);
1370 }
1371 }
1372
1373 @keyframes fadeInDownBig {
1374 from {
1375 opacity: 0;
1376 -webkit-transform: translate3d(0, -2000px, 0);
1377 transform: translate3d(0, -2000px, 0);
1378 }
1379
1380 to {
1381 opacity: 1;
1382 -webkit-transform: translate3d(0, 0, 0);
1383 transform: translate3d(0, 0, 0);
1384 }
1385 }
1386
1387 .fadeInDownBig {
1388 -webkit-animation-name: fadeInDownBig;
1389 animation-name: fadeInDownBig;
1390 }
1391
1392 @-webkit-keyframes fadeInLeft {
1393 from {
1394 opacity: 0;
1395 -webkit-transform: translate3d(-100%, 0, 0);
1396 transform: translate3d(-100%, 0, 0);
1397 }
1398
1399 to {
1400 opacity: 1;
1401 -webkit-transform: translate3d(0, 0, 0);
1402 transform: translate3d(0, 0, 0);
1403 }
1404 }
1405
1406 @keyframes fadeInLeft {
1407 from {
1408 opacity: 0;
1409 -webkit-transform: translate3d(-100%, 0, 0);
1410 transform: translate3d(-100%, 0, 0);
1411 }
1412
1413 to {
1414 opacity: 1;
1415 -webkit-transform: translate3d(0, 0, 0);
1416 transform: translate3d(0, 0, 0);
1417 }
1418 }
1419
1420 .fadeInLeft {
1421 -webkit-animation-name: fadeInLeft;
1422 animation-name: fadeInLeft;
1423 }
1424
1425 @-webkit-keyframes fadeInLeftBig {
1426 from {
1427 opacity: 0;
1428 -webkit-transform: translate3d(-2000px, 0, 0);
1429 transform: translate3d(-2000px, 0, 0);
1430 }
1431
1432 to {
1433 opacity: 1;
1434 -webkit-transform: translate3d(0, 0, 0);
1435 transform: translate3d(0, 0, 0);
1436 }
1437 }
1438
1439 @keyframes fadeInLeftBig {
1440 from {
1441 opacity: 0;
1442 -webkit-transform: translate3d(-2000px, 0, 0);
1443 transform: translate3d(-2000px, 0, 0);
1444 }
1445
1446 to {
1447 opacity: 1;
1448 -webkit-transform: translate3d(0, 0, 0);
1449 transform: translate3d(0, 0, 0);
1450 }
1451 }
1452
1453 .fadeInLeftBig {
1454 -webkit-animation-name: fadeInLeftBig;
1455 animation-name: fadeInLeftBig;
1456 }
1457
1458 @-webkit-keyframes fadeInRight {
1459 from {
1460 opacity: 0;
1461 -webkit-transform: translate3d(100%, 0, 0);
1462 transform: translate3d(100%, 0, 0);
1463 }
1464
1465 to {
1466 opacity: 1;
1467 -webkit-transform: translate3d(0, 0, 0);
1468 transform: translate3d(0, 0, 0);
1469 }
1470 }
1471
1472 @keyframes fadeInRight {
1473 from {
1474 opacity: 0;
1475 -webkit-transform: translate3d(100%, 0, 0);
1476 transform: translate3d(100%, 0, 0);
1477 }
1478
1479 to {
1480 opacity: 1;
1481 -webkit-transform: translate3d(0, 0, 0);
1482 transform: translate3d(0, 0, 0);
1483 }
1484 }
1485
1486 .fadeInRight {
1487 -webkit-animation-name: fadeInRight;
1488 animation-name: fadeInRight;
1489 }
1490
1491 @-webkit-keyframes fadeInRightBig {
1492 from {
1493 opacity: 0;
1494 -webkit-transform: translate3d(2000px, 0, 0);
1495 transform: translate3d(2000px, 0, 0);
1496 }
1497
1498 to {
1499 opacity: 1;
1500 -webkit-transform: translate3d(0, 0, 0);
1501 transform: translate3d(0, 0, 0);
1502 }
1503 }
1504
1505 @keyframes fadeInRightBig {
1506 from {
1507 opacity: 0;
1508 -webkit-transform: translate3d(2000px, 0, 0);
1509 transform: translate3d(2000px, 0, 0);
1510 }
1511
1512 to {
1513 opacity: 1;
1514 -webkit-transform: translate3d(0, 0, 0);
1515 transform: translate3d(0, 0, 0);
1516 }
1517 }
1518
1519 .fadeInRightBig {
1520 -webkit-animation-name: fadeInRightBig;
1521 animation-name: fadeInRightBig;
1522 }
1523
1524 @-webkit-keyframes fadeInUp {
1525 from {
1526 opacity: 0;
1527 -webkit-transform: translate3d(0, 100%, 0);
1528 transform: translate3d(0, 100%, 0);
1529 }
1530
1531 to {
1532 opacity: 1;
1533 -webkit-transform: translate3d(0, 0, 0);
1534 transform: translate3d(0, 0, 0);
1535 }
1536 }
1537
1538 @keyframes fadeInUp {
1539 from {
1540 opacity: 0;
1541 -webkit-transform: translate3d(0, 100%, 0);
1542 transform: translate3d(0, 100%, 0);
1543 }
1544
1545 to {
1546 opacity: 1;
1547 -webkit-transform: translate3d(0, 0, 0);
1548 transform: translate3d(0, 0, 0);
1549 }
1550 }
1551
1552 .fadeInUp {
1553 -webkit-animation-name: fadeInUp;
1554 animation-name: fadeInUp;
1555 }
1556
1557 @-webkit-keyframes fadeInUpBig {
1558 from {
1559 opacity: 0;
1560 -webkit-transform: translate3d(0, 2000px, 0);
1561 transform: translate3d(0, 2000px, 0);
1562 }
1563
1564 to {
1565 opacity: 1;
1566 -webkit-transform: translate3d(0, 0, 0);
1567 transform: translate3d(0, 0, 0);
1568 }
1569 }
1570
1571 @keyframes fadeInUpBig {
1572 from {
1573 opacity: 0;
1574 -webkit-transform: translate3d(0, 2000px, 0);
1575 transform: translate3d(0, 2000px, 0);
1576 }
1577
1578 to {
1579 opacity: 1;
1580 -webkit-transform: translate3d(0, 0, 0);
1581 transform: translate3d(0, 0, 0);
1582 }
1583 }
1584
1585 .fadeInUpBig {
1586 -webkit-animation-name: fadeInUpBig;
1587 animation-name: fadeInUpBig;
1588 }
1589
1590 @-webkit-keyframes fadeOut {
1591 from {
1592 opacity: 1;
1593 }
1594
1595 to {
1596 opacity: 0;
1597 }
1598 }
1599
1600 @keyframes fadeOut {
1601 from {
1602 opacity: 1;
1603 }
1604
1605 to {
1606 opacity: 0;
1607 }
1608 }
1609
1610 .fadeOut {
1611 -webkit-animation-name: fadeOut;
1612 animation-name: fadeOut;
1613 }
1614
1615 @-webkit-keyframes fadeOutDown {
1616 from {
1617 opacity: 1;
1618 }
1619
1620 to {
1621 opacity: 0;
1622 -webkit-transform: translate3d(0, 100%, 0);
1623 transform: translate3d(0, 100%, 0);
1624 }
1625 }
1626
1627 @keyframes fadeOutDown {
1628 from {
1629 opacity: 1;
1630 }
1631
1632 to {
1633 opacity: 0;
1634 -webkit-transform: translate3d(0, 100%, 0);
1635 transform: translate3d(0, 100%, 0);
1636 }
1637 }
1638
1639 .fadeOutDown {
1640 -webkit-animation-name: fadeOutDown;
1641 animation-name: fadeOutDown;
1642 }
1643
1644 @-webkit-keyframes fadeOutDownBig {
1645 from {
1646 opacity: 1;
1647 }
1648
1649 to {
1650 opacity: 0;
1651 -webkit-transform: translate3d(0, 2000px, 0);
1652 transform: translate3d(0, 2000px, 0);
1653 }
1654 }
1655
1656 @keyframes fadeOutDownBig {
1657 from {
1658 opacity: 1;
1659 }
1660
1661 to {
1662 opacity: 0;
1663 -webkit-transform: translate3d(0, 2000px, 0);
1664 transform: translate3d(0, 2000px, 0);
1665 }
1666 }
1667
1668 .fadeOutDownBig {
1669 -webkit-animation-name: fadeOutDownBig;
1670 animation-name: fadeOutDownBig;
1671 }
1672
1673 @-webkit-keyframes fadeOutLeft {
1674 from {
1675 opacity: 1;
1676 }
1677
1678 to {
1679 opacity: 0;
1680 -webkit-transform: translate3d(-100%, 0, 0);
1681 transform: translate3d(-100%, 0, 0);
1682 }
1683 }
1684
1685 @keyframes fadeOutLeft {
1686 from {
1687 opacity: 1;
1688 }
1689
1690 to {
1691 opacity: 0;
1692 -webkit-transform: translate3d(-100%, 0, 0);
1693 transform: translate3d(-100%, 0, 0);
1694 }
1695 }
1696
1697 .fadeOutLeft {
1698 -webkit-animation-name: fadeOutLeft;
1699 animation-name: fadeOutLeft;
1700 }
1701
1702 @-webkit-keyframes fadeOutLeftBig {
1703 from {
1704 opacity: 1;
1705 }
1706
1707 to {
1708 opacity: 0;
1709 -webkit-transform: translate3d(-2000px, 0, 0);
1710 transform: translate3d(-2000px, 0, 0);
1711 }
1712 }
1713
1714 @keyframes fadeOutLeftBig {
1715 from {
1716 opacity: 1;
1717 }
1718
1719 to {
1720 opacity: 0;
1721 -webkit-transform: translate3d(-2000px, 0, 0);
1722 transform: translate3d(-2000px, 0, 0);
1723 }
1724 }
1725
1726 .fadeOutLeftBig {
1727 -webkit-animation-name: fadeOutLeftBig;
1728 animation-name: fadeOutLeftBig;
1729 }
1730
1731 @-webkit-keyframes fadeOutRight {
1732 from {
1733 opacity: 1;
1734 }
1735
1736 to {
1737 opacity: 0;
1738 -webkit-transform: translate3d(100%, 0, 0);
1739 transform: translate3d(100%, 0, 0);
1740 }
1741 }
1742
1743 @keyframes fadeOutRight {
1744 from {
1745 opacity: 1;
1746 }
1747
1748 to {
1749 opacity: 0;
1750 -webkit-transform: translate3d(100%, 0, 0);
1751 transform: translate3d(100%, 0, 0);
1752 }
1753 }
1754
1755 .fadeOutRight {
1756 -webkit-animation-name: fadeOutRight;
1757 animation-name: fadeOutRight;
1758 }
1759
1760 @-webkit-keyframes fadeOutRightBig {
1761 from {
1762 opacity: 1;
1763 }
1764
1765 to {
1766 opacity: 0;
1767 -webkit-transform: translate3d(2000px, 0, 0);
1768 transform: translate3d(2000px, 0, 0);
1769 }
1770 }
1771
1772 @keyframes fadeOutRightBig {
1773 from {
1774 opacity: 1;
1775 }
1776
1777 to {
1778 opacity: 0;
1779 -webkit-transform: translate3d(2000px, 0, 0);
1780 transform: translate3d(2000px, 0, 0);
1781 }
1782 }
1783
1784 .fadeOutRightBig {
1785 -webkit-animation-name: fadeOutRightBig;
1786 animation-name: fadeOutRightBig;
1787 }
1788
1789 @-webkit-keyframes fadeOutUp {
1790 from {
1791 opacity: 1;
1792 }
1793
1794 to {
1795 opacity: 0;
1796 -webkit-transform: translate3d(0, -100%, 0);
1797 transform: translate3d(0, -100%, 0);
1798 }
1799 }
1800
1801 @keyframes fadeOutUp {
1802 from {
1803 opacity: 1;
1804 }
1805
1806 to {
1807 opacity: 0;
1808 -webkit-transform: translate3d(0, -100%, 0);
1809 transform: translate3d(0, -100%, 0);
1810 }
1811 }
1812
1813 .fadeOutUp {
1814 -webkit-animation-name: fadeOutUp;
1815 animation-name: fadeOutUp;
1816 }
1817
1818 @-webkit-keyframes fadeOutUpBig {
1819 from {
1820 opacity: 1;
1821 }
1822
1823 to {
1824 opacity: 0;
1825 -webkit-transform: translate3d(0, -2000px, 0);
1826 transform: translate3d(0, -2000px, 0);
1827 }
1828 }
1829
1830 @keyframes fadeOutUpBig {
1831 from {
1832 opacity: 1;
1833 }
1834
1835 to {
1836 opacity: 0;
1837 -webkit-transform: translate3d(0, -2000px, 0);
1838 transform: translate3d(0, -2000px, 0);
1839 }
1840 }
1841
1842 .fadeOutUpBig {
1843 -webkit-animation-name: fadeOutUpBig;
1844 animation-name: fadeOutUpBig;
1845 }
1846
1847 @-webkit-keyframes flip {
1848 from {
1849 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
1850 transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
1851 -webkit-animation-timing-function: ease-out;
1852 animation-timing-function: ease-out;
1853 }
1854
1855 40% {
1856 -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
1857 transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
1858 -webkit-animation-timing-function: ease-out;
1859 animation-timing-function: ease-out;
1860 }
1861
1862 50% {
1863 -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
1864 transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
1865 -webkit-animation-timing-function: ease-in;
1866 animation-timing-function: ease-in;
1867 }
1868
1869 80% {
1870 -webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95);
1871 transform: perspective(400px) scale3d(0.95, 0.95, 0.95);
1872 -webkit-animation-timing-function: ease-in;
1873 animation-timing-function: ease-in;
1874 }
1875
1876 to {
1877 -webkit-transform: perspective(400px);
1878 transform: perspective(400px);
1879 -webkit-animation-timing-function: ease-in;
1880 animation-timing-function: ease-in;
1881 }
1882 }
1883
1884 @keyframes flip {
1885 from {
1886 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
1887 transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
1888 -webkit-animation-timing-function: ease-out;
1889 animation-timing-function: ease-out;
1890 }
1891
1892 40% {
1893 -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
1894 transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
1895 -webkit-animation-timing-function: ease-out;
1896 animation-timing-function: ease-out;
1897 }
1898
1899 50% {
1900 -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
1901 transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
1902 -webkit-animation-timing-function: ease-in;
1903 animation-timing-function: ease-in;
1904 }
1905
1906 80% {
1907 -webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95);
1908 transform: perspective(400px) scale3d(0.95, 0.95, 0.95);
1909 -webkit-animation-timing-function: ease-in;
1910 animation-timing-function: ease-in;
1911 }
1912
1913 to {
1914 -webkit-transform: perspective(400px);
1915 transform: perspective(400px);
1916 -webkit-animation-timing-function: ease-in;
1917 animation-timing-function: ease-in;
1918 }
1919 }
1920
1921 .animated.flip {
1922 -webkit-backface-visibility: visible;
1923 backface-visibility: visible;
1924 -webkit-animation-name: flip;
1925 animation-name: flip;
1926 }
1927
1928 @-webkit-keyframes flipInX {
1929 from {
1930 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
1931 transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
1932 -webkit-animation-timing-function: ease-in;
1933 animation-timing-function: ease-in;
1934 opacity: 0;
1935 }
1936
1937 40% {
1938 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
1939 transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
1940 -webkit-animation-timing-function: ease-in;
1941 animation-timing-function: ease-in;
1942 }
1943
1944 60% {
1945 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
1946 transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
1947 opacity: 1;
1948 }
1949
1950 80% {
1951 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
1952 transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
1953 }
1954
1955 to {
1956 -webkit-transform: perspective(400px);
1957 transform: perspective(400px);
1958 }
1959 }
1960
1961 @keyframes flipInX {
1962 from {
1963 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
1964 transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
1965 -webkit-animation-timing-function: ease-in;
1966 animation-timing-function: ease-in;
1967 opacity: 0;
1968 }
1969
1970 40% {
1971 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
1972 transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
1973 -webkit-animation-timing-function: ease-in;
1974 animation-timing-function: ease-in;
1975 }
1976
1977 60% {
1978 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
1979 transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
1980 opacity: 1;
1981 }
1982
1983 80% {
1984 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
1985 transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
1986 }
1987
1988 to {
1989 -webkit-transform: perspective(400px);
1990 transform: perspective(400px);
1991 }
1992 }
1993
1994 .flipInX {
1995 -webkit-backface-visibility: visible !important;
1996 backface-visibility: visible !important;
1997 -webkit-animation-name: flipInX;
1998 animation-name: flipInX;
1999 }
2000
2001 @-webkit-keyframes flipInY {
2002 from {
2003 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
2004 transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
2005 -webkit-animation-timing-function: ease-in;
2006 animation-timing-function: ease-in;
2007 opacity: 0;
2008 }
2009
2010 40% {
2011 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
2012 transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
2013 -webkit-animation-timing-function: ease-in;
2014 animation-timing-function: ease-in;
2015 }
2016
2017 60% {
2018 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
2019 transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
2020 opacity: 1;
2021 }
2022
2023 80% {
2024 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
2025 transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
2026 }
2027
2028 to {
2029 -webkit-transform: perspective(400px);
2030 transform: perspective(400px);
2031 }
2032 }
2033
2034 @keyframes flipInY {
2035 from {
2036 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
2037 transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
2038 -webkit-animation-timing-function: ease-in;
2039 animation-timing-function: ease-in;
2040 opacity: 0;
2041 }
2042
2043 40% {
2044 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
2045 transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
2046 -webkit-animation-timing-function: ease-in;
2047 animation-timing-function: ease-in;
2048 }
2049
2050 60% {
2051 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
2052 transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
2053 opacity: 1;
2054 }
2055
2056 80% {
2057 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
2058 transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
2059 }
2060
2061 to {
2062 -webkit-transform: perspective(400px);
2063 transform: perspective(400px);
2064 }
2065 }
2066
2067 .flipInY {
2068 -webkit-backface-visibility: visible !important;
2069 backface-visibility: visible !important;
2070 -webkit-animation-name: flipInY;
2071 animation-name: flipInY;
2072 }
2073
2074 @-webkit-keyframes flipOutX {
2075 from {
2076 -webkit-transform: perspective(400px);
2077 transform: perspective(400px);
2078 }
2079
2080 30% {
2081 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
2082 transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
2083 opacity: 1;
2084 }
2085
2086 to {
2087 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
2088 transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
2089 opacity: 0;
2090 }
2091 }
2092
2093 @keyframes flipOutX {
2094 from {
2095 -webkit-transform: perspective(400px);
2096 transform: perspective(400px);
2097 }
2098
2099 30% {
2100 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
2101 transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
2102 opacity: 1;
2103 }
2104
2105 to {
2106 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
2107 transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
2108 opacity: 0;
2109 }
2110 }
2111
2112 .flipOutX {
2113 -webkit-animation-duration: 0.75s;
2114 animation-duration: 0.75s;
2115 -webkit-animation-name: flipOutX;
2116 animation-name: flipOutX;
2117 -webkit-backface-visibility: visible !important;
2118 backface-visibility: visible !important;
2119 }
2120
2121 @-webkit-keyframes flipOutY {
2122 from {
2123 -webkit-transform: perspective(400px);
2124 transform: perspective(400px);
2125 }
2126
2127 30% {
2128 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
2129 transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
2130 opacity: 1;
2131 }
2132
2133 to {
2134 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
2135 transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
2136 opacity: 0;
2137 }
2138 }
2139
2140 @keyframes flipOutY {
2141 from {
2142 -webkit-transform: perspective(400px);
2143 transform: perspective(400px);
2144 }
2145
2146 30% {
2147 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
2148 transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
2149 opacity: 1;
2150 }
2151
2152 to {
2153 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
2154 transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
2155 opacity: 0;
2156 }
2157 }
2158
2159 .flipOutY {
2160 -webkit-animation-duration: 0.75s;
2161 animation-duration: 0.75s;
2162 -webkit-backface-visibility: visible !important;
2163 backface-visibility: visible !important;
2164 -webkit-animation-name: flipOutY;
2165 animation-name: flipOutY;
2166 }
2167
2168 @-webkit-keyframes lightSpeedIn {
2169 from {
2170 -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
2171 transform: translate3d(100%, 0, 0) skewX(-30deg);
2172 opacity: 0;
2173 }
2174
2175 60% {
2176 -webkit-transform: skewX(20deg);
2177 transform: skewX(20deg);
2178 opacity: 1;
2179 }
2180
2181 80% {
2182 -webkit-transform: skewX(-5deg);
2183 transform: skewX(-5deg);
2184 opacity: 1;
2185 }
2186
2187 to {
2188 -webkit-transform: translate3d(0, 0, 0);
2189 transform: translate3d(0, 0, 0);
2190 opacity: 1;
2191 }
2192 }
2193
2194 @keyframes lightSpeedIn {
2195 from {
2196 -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
2197 transform: translate3d(100%, 0, 0) skewX(-30deg);
2198 opacity: 0;
2199 }
2200
2201 60% {
2202 -webkit-transform: skewX(20deg);
2203 transform: skewX(20deg);
2204 opacity: 1;
2205 }
2206
2207 80% {
2208 -webkit-transform: skewX(-5deg);
2209 transform: skewX(-5deg);
2210 opacity: 1;
2211 }
2212
2213 to {
2214 -webkit-transform: translate3d(0, 0, 0);
2215 transform: translate3d(0, 0, 0);
2216 opacity: 1;
2217 }
2218 }
2219
2220 .lightSpeedIn {
2221 -webkit-animation-name: lightSpeedIn;
2222 animation-name: lightSpeedIn;
2223 -webkit-animation-timing-function: ease-out;
2224 animation-timing-function: ease-out;
2225 }
2226
2227 @-webkit-keyframes lightSpeedOut {
2228 from {
2229 opacity: 1;
2230 }
2231
2232 to {
2233 -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
2234 transform: translate3d(100%, 0, 0) skewX(30deg);
2235 opacity: 0;
2236 }
2237 }
2238
2239 @keyframes lightSpeedOut {
2240 from {
2241 opacity: 1;
2242 }
2243
2244 to {
2245 -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
2246 transform: translate3d(100%, 0, 0) skewX(30deg);
2247 opacity: 0;
2248 }
2249 }
2250
2251 .lightSpeedOut {
2252 -webkit-animation-name: lightSpeedOut;
2253 animation-name: lightSpeedOut;
2254 -webkit-animation-timing-function: ease-in;
2255 animation-timing-function: ease-in;
2256 }
2257
2258 @-webkit-keyframes rotateIn {
2259 from {
2260 -webkit-transform-origin: center;
2261 transform-origin: center;
2262 -webkit-transform: rotate3d(0, 0, 1, -200deg);
2263 transform: rotate3d(0, 0, 1, -200deg);
2264 opacity: 0;
2265 }
2266
2267 to {
2268 -webkit-transform-origin: center;
2269 transform-origin: center;
2270 -webkit-transform: translate3d(0, 0, 0);
2271 transform: translate3d(0, 0, 0);
2272 opacity: 1;
2273 }
2274 }
2275
2276 @keyframes rotateIn {
2277 from {
2278 -webkit-transform-origin: center;
2279 transform-origin: center;
2280 -webkit-transform: rotate3d(0, 0, 1, -200deg);
2281 transform: rotate3d(0, 0, 1, -200deg);
2282 opacity: 0;
2283 }
2284
2285 to {
2286 -webkit-transform-origin: center;
2287 transform-origin: center;
2288 -webkit-transform: translate3d(0, 0, 0);
2289 transform: translate3d(0, 0, 0);
2290 opacity: 1;
2291 }
2292 }
2293
2294 .rotateIn {
2295 -webkit-animation-name: rotateIn;
2296 animation-name: rotateIn;
2297 }
2298
2299 @-webkit-keyframes rotateInDownLeft {
2300 from {
2301 -webkit-transform-origin: left bottom;
2302 transform-origin: left bottom;
2303 -webkit-transform: rotate3d(0, 0, 1, -45deg);
2304 transform: rotate3d(0, 0, 1, -45deg);
2305 opacity: 0;
2306 }
2307
2308 to {
2309 -webkit-transform-origin: left bottom;
2310 transform-origin: left bottom;
2311 -webkit-transform: translate3d(0, 0, 0);
2312 transform: translate3d(0, 0, 0);
2313 opacity: 1;
2314 }
2315 }
2316
2317 @keyframes rotateInDownLeft {
2318 from {
2319 -webkit-transform-origin: left bottom;
2320 transform-origin: left bottom;
2321 -webkit-transform: rotate3d(0, 0, 1, -45deg);
2322 transform: rotate3d(0, 0, 1, -45deg);
2323 opacity: 0;
2324 }
2325
2326 to {
2327 -webkit-transform-origin: left bottom;
2328 transform-origin: left bottom;
2329 -webkit-transform: translate3d(0, 0, 0);
2330 transform: translate3d(0, 0, 0);
2331 opacity: 1;
2332 }
2333 }
2334
2335 .rotateInDownLeft {
2336 -webkit-animation-name: rotateInDownLeft;
2337 animation-name: rotateInDownLeft;
2338 }
2339
2340 @-webkit-keyframes rotateInDownRight {
2341 from {
2342 -webkit-transform-origin: right bottom;
2343 transform-origin: right bottom;
2344 -webkit-transform: rotate3d(0, 0, 1, 45deg);
2345 transform: rotate3d(0, 0, 1, 45deg);
2346 opacity: 0;
2347 }
2348
2349 to {
2350 -webkit-transform-origin: right bottom;
2351 transform-origin: right bottom;
2352 -webkit-transform: translate3d(0, 0, 0);
2353 transform: translate3d(0, 0, 0);
2354 opacity: 1;
2355 }
2356 }
2357
2358 @keyframes rotateInDownRight {
2359 from {
2360 -webkit-transform-origin: right bottom;
2361 transform-origin: right bottom;
2362 -webkit-transform: rotate3d(0, 0, 1, 45deg);
2363 transform: rotate3d(0, 0, 1, 45deg);
2364 opacity: 0;
2365 }
2366
2367 to {
2368 -webkit-transform-origin: right bottom;
2369 transform-origin: right bottom;
2370 -webkit-transform: translate3d(0, 0, 0);
2371 transform: translate3d(0, 0, 0);
2372 opacity: 1;
2373 }
2374 }
2375
2376 .rotateInDownRight {
2377 -webkit-animation-name: rotateInDownRight;
2378 animation-name: rotateInDownRight;
2379 }
2380
2381 @-webkit-keyframes rotateInUpLeft {
2382 from {
2383 -webkit-transform-origin: left bottom;
2384 transform-origin: left bottom;
2385 -webkit-transform: rotate3d(0, 0, 1, 45deg);
2386 transform: rotate3d(0, 0, 1, 45deg);
2387 opacity: 0;
2388 }
2389
2390 to {
2391 -webkit-transform-origin: left bottom;
2392 transform-origin: left bottom;
2393 -webkit-transform: translate3d(0, 0, 0);
2394 transform: translate3d(0, 0, 0);
2395 opacity: 1;
2396 }
2397 }
2398
2399 @keyframes rotateInUpLeft {
2400 from {
2401 -webkit-transform-origin: left bottom;
2402 transform-origin: left bottom;
2403 -webkit-transform: rotate3d(0, 0, 1, 45deg);
2404 transform: rotate3d(0, 0, 1, 45deg);
2405 opacity: 0;
2406 }
2407
2408 to {
2409 -webkit-transform-origin: left bottom;
2410 transform-origin: left bottom;
2411 -webkit-transform: translate3d(0, 0, 0);
2412 transform: translate3d(0, 0, 0);
2413 opacity: 1;
2414 }
2415 }
2416
2417 .rotateInUpLeft {
2418 -webkit-animation-name: rotateInUpLeft;
2419 animation-name: rotateInUpLeft;
2420 }
2421
2422 @-webkit-keyframes rotateInUpRight {
2423 from {
2424 -webkit-transform-origin: right bottom;
2425 transform-origin: right bottom;
2426 -webkit-transform: rotate3d(0, 0, 1, -90deg);
2427 transform: rotate3d(0, 0, 1, -90deg);
2428 opacity: 0;
2429 }
2430
2431 to {
2432 -webkit-transform-origin: right bottom;
2433 transform-origin: right bottom;
2434 -webkit-transform: translate3d(0, 0, 0);
2435 transform: translate3d(0, 0, 0);
2436 opacity: 1;
2437 }
2438 }
2439
2440 @keyframes rotateInUpRight {
2441 from {
2442 -webkit-transform-origin: right bottom;
2443 transform-origin: right bottom;
2444 -webkit-transform: rotate3d(0, 0, 1, -90deg);
2445 transform: rotate3d(0, 0, 1, -90deg);
2446 opacity: 0;
2447 }
2448
2449 to {
2450 -webkit-transform-origin: right bottom;
2451 transform-origin: right bottom;
2452 -webkit-transform: translate3d(0, 0, 0);
2453 transform: translate3d(0, 0, 0);
2454 opacity: 1;
2455 }
2456 }
2457
2458 .rotateInUpRight {
2459 -webkit-animation-name: rotateInUpRight;
2460 animation-name: rotateInUpRight;
2461 }
2462
2463 @-webkit-keyframes rotateOut {
2464 from {
2465 -webkit-transform-origin: center;
2466 transform-origin: center;
2467 opacity: 1;
2468 }
2469
2470 to {
2471 -webkit-transform-origin: center;
2472 transform-origin: center;
2473 -webkit-transform: rotate3d(0, 0, 1, 200deg);
2474 transform: rotate3d(0, 0, 1, 200deg);
2475 opacity: 0;
2476 }
2477 }
2478
2479 @keyframes rotateOut {
2480 from {
2481 -webkit-transform-origin: center;
2482 transform-origin: center;
2483 opacity: 1;
2484 }
2485
2486 to {
2487 -webkit-transform-origin: center;
2488 transform-origin: center;
2489 -webkit-transform: rotate3d(0, 0, 1, 200deg);
2490 transform: rotate3d(0, 0, 1, 200deg);
2491 opacity: 0;
2492 }
2493 }
2494
2495 .rotateOut {
2496 -webkit-animation-name: rotateOut;
2497 animation-name: rotateOut;
2498 }
2499
2500 @-webkit-keyframes rotateOutDownLeft {
2501 from {
2502 -webkit-transform-origin: left bottom;
2503 transform-origin: left bottom;
2504 opacity: 1;
2505 }
2506
2507 to {
2508 -webkit-transform-origin: left bottom;
2509 transform-origin: left bottom;
2510 -webkit-transform: rotate3d(0, 0, 1, 45deg);
2511 transform: rotate3d(0, 0, 1, 45deg);
2512 opacity: 0;
2513 }
2514 }
2515
2516 @keyframes rotateOutDownLeft {
2517 from {
2518 -webkit-transform-origin: left bottom;
2519 transform-origin: left bottom;
2520 opacity: 1;
2521 }
2522
2523 to {
2524 -webkit-transform-origin: left bottom;
2525 transform-origin: left bottom;
2526 -webkit-transform: rotate3d(0, 0, 1, 45deg);
2527 transform: rotate3d(0, 0, 1, 45deg);
2528 opacity: 0;
2529 }
2530 }
2531
2532 .rotateOutDownLeft {
2533 -webkit-animation-name: rotateOutDownLeft;
2534 animation-name: rotateOutDownLeft;
2535 }
2536
2537 @-webkit-keyframes rotateOutDownRight {
2538 from {
2539 -webkit-transform-origin: right bottom;
2540 transform-origin: right bottom;
2541 opacity: 1;
2542 }
2543
2544 to {
2545 -webkit-transform-origin: right bottom;
2546 transform-origin: right bottom;
2547 -webkit-transform: rotate3d(0, 0, 1, -45deg);
2548 transform: rotate3d(0, 0, 1, -45deg);
2549 opacity: 0;
2550 }
2551 }
2552
2553 @keyframes rotateOutDownRight {
2554 from {
2555 -webkit-transform-origin: right bottom;
2556 transform-origin: right bottom;
2557 opacity: 1;
2558 }
2559
2560 to {
2561 -webkit-transform-origin: right bottom;
2562 transform-origin: right bottom;
2563 -webkit-transform: rotate3d(0, 0, 1, -45deg);
2564 transform: rotate3d(0, 0, 1, -45deg);
2565 opacity: 0;
2566 }
2567 }
2568
2569 .rotateOutDownRight {
2570 -webkit-animation-name: rotateOutDownRight;
2571 animation-name: rotateOutDownRight;
2572 }
2573
2574 @-webkit-keyframes rotateOutUpLeft {
2575 from {
2576 -webkit-transform-origin: left bottom;
2577 transform-origin: left bottom;
2578 opacity: 1;
2579 }
2580
2581 to {
2582 -webkit-transform-origin: left bottom;
2583 transform-origin: left bottom;
2584 -webkit-transform: rotate3d(0, 0, 1, -45deg);
2585 transform: rotate3d(0, 0, 1, -45deg);
2586 opacity: 0;
2587 }
2588 }
2589
2590 @keyframes rotateOutUpLeft {
2591 from {
2592 -webkit-transform-origin: left bottom;
2593 transform-origin: left bottom;
2594 opacity: 1;
2595 }
2596
2597 to {
2598 -webkit-transform-origin: left bottom;
2599 transform-origin: left bottom;
2600 -webkit-transform: rotate3d(0, 0, 1, -45deg);
2601 transform: rotate3d(0, 0, 1, -45deg);
2602 opacity: 0;
2603 }
2604 }
2605
2606 .rotateOutUpLeft {
2607 -webkit-animation-name: rotateOutUpLeft;
2608 animation-name: rotateOutUpLeft;
2609 }
2610
2611 @-webkit-keyframes rotateOutUpRight {
2612 from {
2613 -webkit-transform-origin: right bottom;
2614 transform-origin: right bottom;
2615 opacity: 1;
2616 }
2617
2618 to {
2619 -webkit-transform-origin: right bottom;
2620 transform-origin: right bottom;
2621 -webkit-transform: rotate3d(0, 0, 1, 90deg);
2622 transform: rotate3d(0, 0, 1, 90deg);
2623 opacity: 0;
2624 }
2625 }
2626
2627 @keyframes rotateOutUpRight {
2628 from {
2629 -webkit-transform-origin: right bottom;
2630 transform-origin: right bottom;
2631 opacity: 1;
2632 }
2633
2634 to {
2635 -webkit-transform-origin: right bottom;
2636 transform-origin: right bottom;
2637 -webkit-transform: rotate3d(0, 0, 1, 90deg);
2638 transform: rotate3d(0, 0, 1, 90deg);
2639 opacity: 0;
2640 }
2641 }
2642
2643 .rotateOutUpRight {
2644 -webkit-animation-name: rotateOutUpRight;
2645 animation-name: rotateOutUpRight;
2646 }
2647
2648 @-webkit-keyframes hinge {
2649 0% {
2650 -webkit-transform-origin: top left;
2651 transform-origin: top left;
2652 -webkit-animation-timing-function: ease-in-out;
2653 animation-timing-function: ease-in-out;
2654 }
2655
2656 20%,
2657 60% {
2658 -webkit-transform: rotate3d(0, 0, 1, 80deg);
2659 transform: rotate3d(0, 0, 1, 80deg);
2660 -webkit-transform-origin: top left;
2661 transform-origin: top left;
2662 -webkit-animation-timing-function: ease-in-out;
2663 animation-timing-function: ease-in-out;
2664 }
2665
2666 40%,
2667 80% {
2668 -webkit-transform: rotate3d(0, 0, 1, 60deg);
2669 transform: rotate3d(0, 0, 1, 60deg);
2670 -webkit-transform-origin: top left;
2671 transform-origin: top left;
2672 -webkit-animation-timing-function: ease-in-out;
2673 animation-timing-function: ease-in-out;
2674 opacity: 1;
2675 }
2676
2677 to {
2678 -webkit-transform: translate3d(0, 700px, 0);
2679 transform: translate3d(0, 700px, 0);
2680 opacity: 0;
2681 }
2682 }
2683
2684 @keyframes hinge {
2685 0% {
2686 -webkit-transform-origin: top left;
2687 transform-origin: top left;
2688 -webkit-animation-timing-function: ease-in-out;
2689 animation-timing-function: ease-in-out;
2690 }
2691
2692 20%,
2693 60% {
2694 -webkit-transform: rotate3d(0, 0, 1, 80deg);
2695 transform: rotate3d(0, 0, 1, 80deg);
2696 -webkit-transform-origin: top left;
2697 transform-origin: top left;
2698 -webkit-animation-timing-function: ease-in-out;
2699 animation-timing-function: ease-in-out;
2700 }
2701
2702 40%,
2703 80% {
2704 -webkit-transform: rotate3d(0, 0, 1, 60deg);
2705 transform: rotate3d(0, 0, 1, 60deg);
2706 -webkit-transform-origin: top left;
2707 transform-origin: top left;
2708 -webkit-animation-timing-function: ease-in-out;
2709 animation-timing-function: ease-in-out;
2710 opacity: 1;
2711 }
2712
2713 to {
2714 -webkit-transform: translate3d(0, 700px, 0);
2715 transform: translate3d(0, 700px, 0);
2716 opacity: 0;
2717 }
2718 }
2719
2720 .hinge {
2721 -webkit-animation-duration: 2s;
2722 animation-duration: 2s;
2723 -webkit-animation-name: hinge;
2724 animation-name: hinge;
2725 }
2726
2727 @-webkit-keyframes jackInTheBox {
2728 from {
2729 opacity: 0;
2730 -webkit-transform: scale(0.1) rotate(30deg);
2731 transform: scale(0.1) rotate(30deg);
2732 -webkit-transform-origin: center bottom;
2733 transform-origin: center bottom;
2734 }
2735
2736 50% {
2737 -webkit-transform: rotate(-10deg);
2738 transform: rotate(-10deg);
2739 }
2740
2741 70% {
2742 -webkit-transform: rotate(3deg);
2743 transform: rotate(3deg);
2744 }
2745
2746 to {
2747 opacity: 1;
2748 -webkit-transform: scale(1);
2749 transform: scale(1);
2750 }
2751 }
2752
2753 @keyframes jackInTheBox {
2754 from {
2755 opacity: 0;
2756 -webkit-transform: scale(0.1) rotate(30deg);
2757 transform: scale(0.1) rotate(30deg);
2758 -webkit-transform-origin: center bottom;
2759 transform-origin: center bottom;
2760 }
2761
2762 50% {
2763 -webkit-transform: rotate(-10deg);
2764 transform: rotate(-10deg);
2765 }
2766
2767 70% {
2768 -webkit-transform: rotate(3deg);
2769 transform: rotate(3deg);
2770 }
2771
2772 to {
2773 opacity: 1;
2774 -webkit-transform: scale(1);
2775 transform: scale(1);
2776 }
2777 }
2778
2779 .jackInTheBox {
2780 -webkit-animation-name: jackInTheBox;
2781 animation-name: jackInTheBox;
2782 }
2783
2784 @-webkit-keyframes rollIn {
2785 from {
2786 opacity: 0;
2787 -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
2788 transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
2789 }
2790
2791 to {
2792 opacity: 1;
2793 -webkit-transform: translate3d(0, 0, 0);
2794 transform: translate3d(0, 0, 0);
2795 }
2796 }
2797
2798 @keyframes rollIn {
2799 from {
2800 opacity: 0;
2801 -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
2802 transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
2803 }
2804
2805 to {
2806 opacity: 1;
2807 -webkit-transform: translate3d(0, 0, 0);
2808 transform: translate3d(0, 0, 0);
2809 }
2810 }
2811
2812 .rollIn {
2813 -webkit-animation-name: rollIn;
2814 animation-name: rollIn;
2815 }
2816
2817 @-webkit-keyframes rollOut {
2818 from {
2819 opacity: 1;
2820 }
2821
2822 to {
2823 opacity: 0;
2824 -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
2825 transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
2826 }
2827 }
2828
2829 @keyframes rollOut {
2830 from {
2831 opacity: 1;
2832 }
2833
2834 to {
2835 opacity: 0;
2836 -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
2837 transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
2838 }
2839 }
2840
2841 .rollOut {
2842 -webkit-animation-name: rollOut;
2843 animation-name: rollOut;
2844 }
2845
2846 @-webkit-keyframes zoomIn {
2847 from {
2848 opacity: 0;
2849 -webkit-transform: scale3d(0.3, 0.3, 0.3);
2850 transform: scale3d(0.3, 0.3, 0.3);
2851 }
2852
2853 50% {
2854 opacity: 1;
2855 }
2856 }
2857
2858 @keyframes zoomIn {
2859 from {
2860 opacity: 0;
2861 -webkit-transform: scale3d(0.3, 0.3, 0.3);
2862 transform: scale3d(0.3, 0.3, 0.3);
2863 }
2864
2865 50% {
2866 opacity: 1;
2867 }
2868 }
2869
2870 .zoomIn {
2871 -webkit-animation-name: zoomIn;
2872 animation-name: zoomIn;
2873 }
2874
2875 @-webkit-keyframes zoomInDown {
2876 from {
2877 opacity: 0;
2878 -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
2879 transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
2880 -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
2881 animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
2882 }
2883
2884 60% {
2885 opacity: 1;
2886 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
2887 transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
2888 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
2889 animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
2890 }
2891 }
2892
2893 @keyframes zoomInDown {
2894 from {
2895 opacity: 0;
2896 -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
2897 transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
2898 -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
2899 animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
2900 }
2901
2902 60% {
2903 opacity: 1;
2904 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
2905 transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
2906 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
2907 animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
2908 }
2909 }
2910
2911 .zoomInDown {
2912 -webkit-animation-name: zoomInDown;
2913 animation-name: zoomInDown;
2914 }
2915
2916 @-webkit-keyframes zoomInLeft {
2917 from {
2918 opacity: 0;
2919 -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
2920 transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
2921 -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
2922 animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
2923 }
2924
2925 60% {
2926 opacity: 1;
2927 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
2928 transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
2929 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
2930 animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
2931 }
2932 }
2933
2934 @keyframes zoomInLeft {
2935 from {
2936 opacity: 0;
2937 -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
2938 transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
2939 -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
2940 animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
2941 }
2942
2943 60% {
2944 opacity: 1;
2945 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
2946 transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
2947 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
2948 animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
2949 }
2950 }
2951
2952 .zoomInLeft {
2953 -webkit-animation-name: zoomInLeft;
2954 animation-name: zoomInLeft;
2955 }
2956
2957 @-webkit-keyframes zoomInRight {
2958 from {
2959 opacity: 0;
2960 -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
2961 transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
2962 -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
2963 animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
2964 }
2965
2966 60% {
2967 opacity: 1;
2968 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
2969 transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
2970 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
2971 animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
2972 }
2973 }
2974
2975 @keyframes zoomInRight {
2976 from {
2977 opacity: 0;
2978 -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
2979 transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
2980 -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
2981 animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
2982 }
2983
2984 60% {
2985 opacity: 1;
2986 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
2987 transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
2988 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
2989 animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
2990 }
2991 }
2992
2993 .zoomInRight {
2994 -webkit-animation-name: zoomInRight;
2995 animation-name: zoomInRight;
2996 }
2997
2998 @-webkit-keyframes zoomInUp {
2999 from {
3000 opacity: 0;
3001 -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
3002 transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
3003 -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
3004 animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
3005 }
3006
3007 60% {
3008 opacity: 1;
3009 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
3010 transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
3011 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
3012 animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
3013 }
3014 }
3015
3016 @keyframes zoomInUp {
3017 from {
3018 opacity: 0;
3019 -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
3020 transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
3021 -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
3022 animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
3023 }
3024
3025 60% {
3026 opacity: 1;
3027 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
3028 transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
3029 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
3030 animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
3031 }
3032 }
3033
3034 .zoomInUp {
3035 -webkit-animation-name: zoomInUp;
3036 animation-name: zoomInUp;
3037 }
3038
3039 @-webkit-keyframes zoomOut {
3040 from {
3041 opacity: 1;
3042 }
3043
3044 50% {
3045 opacity: 0;
3046 -webkit-transform: scale3d(0.3, 0.3, 0.3);
3047 transform: scale3d(0.3, 0.3, 0.3);
3048 }
3049
3050 to {
3051 opacity: 0;
3052 }
3053 }
3054
3055 @keyframes zoomOut {
3056 from {
3057 opacity: 1;
3058 }
3059
3060 50% {
3061 opacity: 0;
3062 -webkit-transform: scale3d(0.3, 0.3, 0.3);
3063 transform: scale3d(0.3, 0.3, 0.3);
3064 }
3065
3066 to {
3067 opacity: 0;
3068 }
3069 }
3070
3071 .zoomOut {
3072 -webkit-animation-name: zoomOut;
3073 animation-name: zoomOut;
3074 }
3075
3076 @-webkit-keyframes zoomOutDown {
3077 40% {
3078 opacity: 1;
3079 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
3080 transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
3081 -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
3082 animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
3083 }
3084
3085 to {
3086 opacity: 0;
3087 -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
3088 transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
3089 -webkit-transform-origin: center bottom;
3090 transform-origin: center bottom;
3091 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
3092 animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
3093 }
3094 }
3095
3096 @keyframes zoomOutDown {
3097 40% {
3098 opacity: 1;
3099 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
3100 transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
3101 -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
3102 animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
3103 }
3104
3105 to {
3106 opacity: 0;
3107 -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
3108 transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
3109 -webkit-transform-origin: center bottom;
3110 transform-origin: center bottom;
3111 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
3112 animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
3113 }
3114 }
3115
3116 .zoomOutDown {
3117 -webkit-animation-name: zoomOutDown;
3118 animation-name: zoomOutDown;
3119 }
3120
3121 @-webkit-keyframes zoomOutLeft {
3122 40% {
3123 opacity: 1;
3124 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
3125 transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
3126 }
3127
3128 to {
3129 opacity: 0;
3130 -webkit-transform: scale(0.1) translate3d(-2000px, 0, 0);
3131 transform: scale(0.1) translate3d(-2000px, 0, 0);
3132 -webkit-transform-origin: left center;
3133 transform-origin: left center;
3134 }
3135 }
3136
3137 @keyframes zoomOutLeft {
3138 40% {
3139 opacity: 1;
3140 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
3141 transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
3142 }
3143
3144 to {
3145 opacity: 0;
3146 -webkit-transform: scale(0.1) translate3d(-2000px, 0, 0);
3147 transform: scale(0.1) translate3d(-2000px, 0, 0);
3148 -webkit-transform-origin: left center;
3149 transform-origin: left center;
3150 }
3151 }
3152
3153 .zoomOutLeft {
3154 -webkit-animation-name: zoomOutLeft;
3155 animation-name: zoomOutLeft;
3156 }
3157
3158 @-webkit-keyframes zoomOutRight {
3159 40% {
3160 opacity: 1;
3161 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
3162 transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
3163 }
3164
3165 to {
3166 opacity: 0;
3167 -webkit-transform: scale(0.1) translate3d(2000px, 0, 0);
3168 transform: scale(0.1) translate3d(2000px, 0, 0);
3169 -webkit-transform-origin: right center;
3170 transform-origin: right center;
3171 }
3172 }
3173
3174 @keyframes zoomOutRight {
3175 40% {
3176 opacity: 1;
3177 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
3178 transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
3179 }
3180
3181 to {
3182 opacity: 0;
3183 -webkit-transform: scale(0.1) translate3d(2000px, 0, 0);
3184 transform: scale(0.1) translate3d(2000px, 0, 0);
3185 -webkit-transform-origin: right center;
3186 transform-origin: right center;
3187 }
3188 }
3189
3190 .zoomOutRight {
3191 -webkit-animation-name: zoomOutRight;
3192 animation-name: zoomOutRight;
3193 }
3194
3195 @-webkit-keyframes zoomOutUp {
3196 40% {
3197 opacity: 1;
3198 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
3199 transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
3200 -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
3201 animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
3202 }
3203
3204 to {
3205 opacity: 0;
3206 -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
3207 transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
3208 -webkit-transform-origin: center bottom;
3209 transform-origin: center bottom;
3210 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
3211 animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
3212 }
3213 }
3214
3215 @keyframes zoomOutUp {
3216 40% {
3217 opacity: 1;
3218 -webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
3219 transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
3220 -webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
3221 animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
3222 }
3223
3224 to {
3225 opacity: 0;
3226 -webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
3227 transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
3228 -webkit-transform-origin: center bottom;
3229 transform-origin: center bottom;
3230 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
3231 animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
3232 }
3233 }
3234
3235 .zoomOutUp {
3236 -webkit-animation-name: zoomOutUp;
3237 animation-name: zoomOutUp;
3238 }
3239
3240 @-webkit-keyframes slideInDown {
3241 from {
3242 -webkit-transform: translate3d(0, -100%, 0);
3243 transform: translate3d(0, -100%, 0);
3244 visibility: visible;
3245 }
3246
3247 to {
3248 -webkit-transform: translate3d(0, 0, 0);
3249 transform: translate3d(0, 0, 0);
3250 }
3251 }
3252
3253 @keyframes slideInDown {
3254 from {
3255 -webkit-transform: translate3d(0, -100%, 0);
3256 transform: translate3d(0, -100%, 0);
3257 visibility: visible;
3258 }
3259
3260 to {
3261 -webkit-transform: translate3d(0, 0, 0);
3262 transform: translate3d(0, 0, 0);
3263 }
3264 }
3265
3266 .slideInDown {
3267 -webkit-animation-name: slideInDown;
3268 animation-name: slideInDown;
3269 }
3270
3271 @-webkit-keyframes slideInLeft {
3272 from {
3273 -webkit-transform: translate3d(-100%, 0, 0);
3274 transform: translate3d(-100%, 0, 0);
3275 visibility: visible;
3276 }
3277
3278 to {
3279 -webkit-transform: translate3d(0, 0, 0);
3280 transform: translate3d(0, 0, 0);
3281 }
3282 }
3283
3284 @keyframes slideInLeft {
3285 from {
3286 -webkit-transform: translate3d(-100%, 0, 0);
3287 transform: translate3d(-100%, 0, 0);
3288 visibility: visible;
3289 }
3290
3291 to {
3292 -webkit-transform: translate3d(0, 0, 0);
3293 transform: translate3d(0, 0, 0);
3294 }
3295 }
3296
3297 .slideInLeft {
3298 -webkit-animation-name: slideInLeft;
3299 animation-name: slideInLeft;
3300 }
3301
3302 @-webkit-keyframes slideInRight {
3303 from {
3304 -webkit-transform: translate3d(100%, 0, 0);
3305 transform: translate3d(100%, 0, 0);
3306 visibility: visible;
3307 }
3308
3309 to {
3310 -webkit-transform: translate3d(0, 0, 0);
3311 transform: translate3d(0, 0, 0);
3312 }
3313 }
3314
3315 @keyframes slideInRight {
3316 from {
3317 -webkit-transform: translate3d(100%, 0, 0);
3318 transform: translate3d(100%, 0, 0);
3319 visibility: visible;
3320 }
3321
3322 to {
3323 -webkit-transform: translate3d(0, 0, 0);
3324 transform: translate3d(0, 0, 0);
3325 }
3326 }
3327
3328 .slideInRight {
3329 -webkit-animation-name: slideInRight;
3330 animation-name: slideInRight;
3331 }
3332
3333 @-webkit-keyframes slideInUp {
3334 from {
3335 -webkit-transform: translate3d(0, 100%, 0);
3336 transform: translate3d(0, 100%, 0);
3337 visibility: visible;
3338 }
3339
3340 to {
3341 -webkit-transform: translate3d(0, 0, 0);
3342 transform: translate3d(0, 0, 0);
3343 }
3344 }
3345
3346 @keyframes slideInUp {
3347 from {
3348 -webkit-transform: translate3d(0, 100%, 0);
3349 transform: translate3d(0, 100%, 0);
3350 visibility: visible;
3351 }
3352
3353 to {
3354 -webkit-transform: translate3d(0, 0, 0);
3355 transform: translate3d(0, 0, 0);
3356 }
3357 }
3358
3359 .slideInUp {
3360 -webkit-animation-name: slideInUp;
3361 animation-name: slideInUp;
3362 }
3363
3364 @-webkit-keyframes slideOutDown {
3365 from {
3366 -webkit-transform: translate3d(0, 0, 0);
3367 transform: translate3d(0, 0, 0);
3368 }
3369
3370 to {
3371 visibility: hidden;
3372 -webkit-transform: translate3d(0, 100%, 0);
3373 transform: translate3d(0, 100%, 0);
3374 }
3375 }
3376
3377 @keyframes slideOutDown {
3378 from {
3379 -webkit-transform: translate3d(0, 0, 0);
3380 transform: translate3d(0, 0, 0);
3381 }
3382
3383 to {
3384 visibility: hidden;
3385 -webkit-transform: translate3d(0, 100%, 0);
3386 transform: translate3d(0, 100%, 0);
3387 }
3388 }
3389
3390 .slideOutDown {
3391 -webkit-animation-name: slideOutDown;
3392 animation-name: slideOutDown;
3393 }
3394
3395 @-webkit-keyframes slideOutLeft {
3396 from {
3397 -webkit-transform: translate3d(0, 0, 0);
3398 transform: translate3d(0, 0, 0);
3399 }
3400
3401 to {
3402 visibility: hidden;
3403 -webkit-transform: translate3d(-100%, 0, 0);
3404 transform: translate3d(-100%, 0, 0);
3405 }
3406 }
3407
3408 @keyframes slideOutLeft {
3409 from {
3410 -webkit-transform: translate3d(0, 0, 0);
3411 transform: translate3d(0, 0, 0);
3412 }
3413
3414 to {
3415 visibility: hidden;
3416 -webkit-transform: translate3d(-100%, 0, 0);
3417 transform: translate3d(-100%, 0, 0);
3418 }
3419 }
3420
3421 .slideOutLeft {
3422 -webkit-animation-name: slideOutLeft;
3423 animation-name: slideOutLeft;
3424 }
3425
3426 @-webkit-keyframes slideOutRight {
3427 from {
3428 -webkit-transform: translate3d(0, 0, 0);
3429 transform: translate3d(0, 0, 0);
3430 }
3431
3432 to {
3433 visibility: hidden;
3434 -webkit-transform: translate3d(100%, 0, 0);
3435 transform: translate3d(100%, 0, 0);
3436 }
3437 }
3438
3439 @keyframes slideOutRight {
3440 from {
3441 -webkit-transform: translate3d(0, 0, 0);
3442 transform: translate3d(0, 0, 0);
3443 }
3444
3445 to {
3446 visibility: hidden;
3447 -webkit-transform: translate3d(100%, 0, 0);
3448 transform: translate3d(100%, 0, 0);
3449 }
3450 }
3451
3452 .slideOutRight {
3453 -webkit-animation-name: slideOutRight;
3454 animation-name: slideOutRight;
3455 }
3456
3457 @-webkit-keyframes slideOutUp {
3458 from {
3459 -webkit-transform: translate3d(0, 0, 0);
3460 transform: translate3d(0, 0, 0);
3461 }
3462
3463 to {
3464 visibility: hidden;
3465 -webkit-transform: translate3d(0, -100%, 0);
3466 transform: translate3d(0, -100%, 0);
3467 }
3468 }
3469
3470 @keyframes slideOutUp {
3471 from {
3472 -webkit-transform: translate3d(0, 0, 0);
3473 transform: translate3d(0, 0, 0);
3474 }
3475
3476 to {
3477 visibility: hidden;
3478 -webkit-transform: translate3d(0, -100%, 0);
3479 transform: translate3d(0, -100%, 0);
3480 }
3481 }
3482
3483 .slideOutUp {
3484 -webkit-animation-name: slideOutUp;
3485 animation-name: slideOutUp;
3486 }
1 // 居中按钮样式
2 @mixin btn-center($width, $height) {
3 width: $width;
4 height: $height;
5 line-height: $height;
6 text-align: center;
7 }
8
9 // 超过多少行自动省略 默认一行
10 @mixin ellipsis($line:1) {
11 display: -webkit-box;
12 word-break: break-all;
13 -webkit-box-orient: vertical;
14 -webkit-line-clamp: $line;
15 overflow: hidden;
16 text-overflow: ellipsis;
17 }
18
19 // 文字截取
20 @mixin text-overflow() {
21 overflow: hidden;
22 white-space: normal;
23 text-overflow: ellipsis;
24 word-break: break-all;
25 word-wrap: normal;
26 }
27
28 @mixin word-break() {
29 word-break: break-all;
30 word-wrap: break-word;
31 white-space: normal;
32 }
33
34 // No wrap
35 @mixin no-wrap() {
36 word-break: normal;
37 word-wrap: normal;
38 white-space: nowrap;
39 }
40
41 // 清除浮动
42 @mixin clearfix() {
43
44 &:before,
45 &:after {
46 content: " "; // 1
47 display: table; // 2
48 }
49
50 &:after {
51 clear: both;
52 }
53 }
54
55 // Single side border-radius
56 @mixin border-top-radius($radius) {
57 border-top-right-radius: $radius;
58 border-top-left-radius: $radius;
59 }
60
61 @mixin border-right-radius($radius) {
62 border-bottom-right-radius: $radius;
63 border-top-right-radius: $radius;
64 }
65
66 @mixin border-bottom-radius($radius) {
67 border-bottom-right-radius: $radius;
68 border-bottom-left-radius: $radius;
69 }
70
71 @mixin border-left-radius($radius) {
72 border-bottom-left-radius: $radius;
73 border-top-left-radius: $radius;
74 }
75
76 // Center-align a block level element
77 @mixin center-block() {
78 display: block;
79 margin-left: auto;
80 margin-right: auto;
81 }
82
83 // CSS image replacement
84 // Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757
85 @mixin hide-text() {
86 font-size: 0;
87 line-height: 0;
88 color: transparent;
89 text-shadow: none;
90 background-color: transparent;
91 border: 0;
92 }
93
94
95 // 居中按钮样式
96 @mixin btc($width, $height) {
97 width: $width;
98 height: $height;
99 line-height: $height;
100 text-align: center;
101 }
102
103
104 // 通用按钮
105 @mixin cb($width:320px, $height:84px, $fontSize:32px) {
106 color: #FFFFFF;
107 position: relative;
108 width: $width;
109 height: $height;
110 line-height: $height;
111 text-align: center;
112 font-size: $fontSize;
113 border-radius: 8px;
114 background-color: #3680EB;
115 }
116
117 // 通用按钮
118 @mixin cb2($width:320px, $height:84px, $fontSize:32px) {
119 position: relative;
120 width: $width;
121 height: $height;
122 line-height: $height;
123 text-align: center;
124 font-size: $fontSize;
125 border-radius: 8px;
126 color: #3680EB;
127 border: solid 1PX #3680EB;
128 }
129
130
131 @mixin app-width() {
132 width: 750px;
133 }
1
2 @import "mixins";
3
4 @import "var";
1 @import "support";
2
3 // // Margin
4 // .u-mt-smaller {
5 // margin-top: $marginTopSmaller;
6 // }
7
8 // .u-mt-small {
9 // margin-top: $marginTopSmall;
10 // }
11
12 // .u-mt-medium {
13 // margin-top: $marginTopMedium;
14 // }
15
16 // .u-mt-large {
17 // margin-top: $marginTopLarge;
18 // }
19
20 // .u-mt-larger {
21 // margin-top: $marginTopLarger;
22 // }
23
24 // .u-mb-smaller {
25 // margin-bottom: $marginTopSmaller;
26 // }
27
28 // .u-mb-small {
29 // margin-bottom: $marginTopSmall;
30 // }
31
32 // .u-mb-medium {
33 // margin-bottom: $marginTopMedium;
34 // }
35
36 // .u-mb-large {
37 // margin-bottom: $marginTopLarge;
38 // }
39
40 // .u-mb-larger {
41 // margin-bottom: $marginTopLarger;
42 // }
43
44 // // Padding
45 // .u-pt-smaller {
46 // padding-top: $paddingTopSmaller;
47 // }
48
49 // .u-pt-small {
50 // padding-top: $paddingTopSmall;
51 // }
52
53 // .u-pt-medium {
54 // padding-top: $paddingTopMedium;
55 // }
56
57 // .u-pt-large {
58 // padding-top: $paddingTopLarge;
59 // }
60
61 // .u-pt-larger {
62 // padding-top: $paddingTopLarger;
63 // }
64
65 // .u-pb-smaller {
66 // padding-bottom: $paddingTopSmaller;
67 // }
68
69 // .u-pb-small {
70 // padding-bottom: $paddingTopSmall;
71 // }
72
73 // .u-pb-medium {
74 // padding-bottom: $paddingTopMedium;
75 // }
76
77 // .u-pb-large {
78 // padding-bottom: $paddingTopLarge;
79 // }
80
81 // .u-pb-larger {
82 // padding-bottom: $paddingTopLarger;
83 // }
84
85 // // 布局方位
86 // .u-ta-c {
87 // text-align: center !important;
88 // }
89
90 // .u-ta-l {
91 // text-align: left !important;
92 // }
93
94 // .u-ta-r {
95 // text-align: right !important;
96 // }
97
98 // .u-fl-l {
99 // float: left;
100 // }
101
102 // .u-fl-n {
103 // float: none;
104 // }
105
106 // .u-fl-r {
107 // float: right;
108 // }
109
110 // .u-d-b {
111 // display: block;
112 // }
113
114 // .u-d-i {
115 // display: inline !important;
116 // }
117
118 // .u-d-ib {
119 // display: inline-block !important;
120 // }
121
122 // .u-d-n {
123 // display: none !important;
124 // }
125
126 // .u-d-t {
127 // display: table;
128 // table-layout: fixed;
129 // }
130
131 // .u-d-tc {
132 // display: table-cell;
133 // }
134
135 // .u-va-b {
136 // vertical-align: bottom;
137 // }
138
139 // .u-va-m {
140 // vertical-align: middle;
141 // }
142
143 // .u-va-t {
144 // vertical-align: top;
145 // }
146
147 // // clearfix
148 // .u-clearfix {
149 // @include clearfix;
150 // }
151
152 // // 虚拟格式
153 // .u-cur-d {
154 // cursor: default;
155 // }
156
157 // .u-cur-p {
158 // cursor: pointer;
159 // }
160
161 // // flex
162 // .u-flex {
163 // display: -webkit-box;
164 // display: -webkit-flex;
165 // display: flex;
166 // }
167
168 // .u-flex-item {
169 // -webkit-box-flex: 1;
170 // -webkit-flex: 1;
171 // flex: 1;
172 // }
173
174 // // 小程序中模拟ul、li
175 // .u-ul {
176 // padding-left: 30px;
177 // text-align: left;
178 // display: block;
179 // }
180
181 // .u-li {
182 // position: relative;
183 // font-size: $fontSizeSmall;
184 // line-height: $fontSizeSmall + 4px;
185 // margin-bottom: $marginTopSmall;
186 // &:before {
187 // position: absolute;
188 // content: " ";
189 // top: 14px;
190 // left: -20px;
191 // width: 8px;
192 // height: 8px;
193 // border-radius: 8px;
194 // background-color: $colorBlack;
195 // }
196 // }
197
198
199
200 .bis {
201 background-repeat: no-repeat;
202 background-size: 100% 100%;
203 }
204
205
206 //flex 布局和 子元素 对其方式
207 .fl {
208 display: flex;
209 }
210
211 .fj {
212 display: flex;
213 justify-content: space-between;
214 }
215
216
217
218 .fje {
219 display: flex;
220 justify-content: flex-end;
221 }
222
223 //水平和垂直居中
224 .fcc {
225 display: flex;
226 justify-content: center;
227 align-items: center;
228 }
229
230 // 为元素设定的宽度和高度决定了元素的边框盒。
231 .bb {
232 box-sizing: border-box;
233 }
234
235 // 满屏
236 .fullp {
237 width: 100%;
238 height: 100%;
239 }
240
241 .shadow {
242 box-shadow: 0 6px 18px 0 rgba(0, 0, 0, 0.10);
243 border-radius: 8px;
244 }
245
246 .linear {
247 background-image: linear-gradient(to right, #1bade8, #3680EB);
248 }
1
2
3 // // Margin
4 // $marginTopSmaller: 20px;
5 // $marginTopSmall: 30px;
6 // $marginTopMedium: 40px;
7 // $marginTopLarge: 60px;
8 // $marginTopLarger: 80px;
9
10 // // Padding
11 // $paddingTopSmaller: 20px;
12 // $paddingTopSmall: 30px;
13 // $paddingTopMedium: 40px;
14 // $paddingTopLarge: 60px;
15 // $paddingTopLarger: 80px;
16
17 // // Color
18 $colorBlue: #20A0FF;
19 $colorGreen: #13CE66;
20 $colorGray: #475669;
21 $colorBlack: #000;
22 $colorRed: #FF4949;
23 $colorYellow: #F7BA2A;
24
25 $color: #787878;
26 // $colorLink: #1D8CE0;
27
28 // $backGroundColor: #fff;
29
30 // // Font
31 $fontSize: 32px;
32 $fontSizeSmall: 28px;
33 $fontSizeSmaller: 24px;
34 $fontSizeLarge: 36px;
35 $fontSizeLarger: 44px;
36
37
38 // // 主题颜色
39 $colorMain:#3680EB;
40
41 $pageBottom:80px;
1 let app = getApp();
2 Component({
3 properties: {
4 // 这里定义了innerText属性,属性值可以在组件使用时指定
5 innerText: {
6 type: String,
7 value: 'default value',
8 },
9 // 用户拒绝授权后是否后退页面
10 cancelBack: {
11 type: Boolean,
12 value: false,
13 },
14 // 用户拒绝授权后描述
15 cancelDesc: {
16 type: String,
17 value: "同意授权才能获得更多体验哦~",
18 }
19 },
20 data: {
21 // 这里是一些组件内部数据
22 someData: {}
23 },
24 methods: {
25 // 这里是一个自定义方法
26 customMethod() {
27 this.triggerEvent('evtcomp', {
28 name: "_evt_custom"
29 })
30 },
31 // 隐藏蒙层
32 hideMask() {
33 this.triggerEvent('evtcomp', {
34 name: "_evt_hide_mask"
35 });
36 },
37
38 // 授权成功事件
39 authComplete() {
40 this.triggerEvent('evtcomp', {
41 name: "_evt_auth_complete"
42 });
43
44
45 },
46
47 // 点击暂不授权按钮
48 cancelAuth(e) {
49 this.hideMask();
50 // this.triggerEvent('evtcomp', {
51 // name: "_evt_auth_cancel"
52 // });
53 // if (this.properties.cancelBack) {
54 // wx.navigateBack({
55 // delta: 1
56 // });
57 // }
58 },
59
60 // 点击确认授权按钮
61 bindGetUserInfo(e) {
62 wx.showLoading();
63 this.getUserInfo(e.detail);
64 },
65
66 // 授权操作
67 getUserInfo(e) {
68 let _this = this;
69 if (e.encryptedData && e.iv) {
70 // 同意授权
71 app.post({
72 url: app.api.register,
73 sid: false,
74 data: {
75 encryptedData: e.encryptedData,
76 iv: e.iv,
77 code: app.store.getItem("wxcode"),
78 tlMemberCode: app.globalData.tlMemberCode
79 }
80 }).then((res2) => {
81 wx.hideLoading();
82 if (res2 && res2.sessionId) {
83 app.store.setItem('sessionId', res2.sessionId);
84 }
85 _this.hideMask();
86 _this.authComplete();
87 _this.initPage();
88 }).catch((err) => {})
89 } else {
90 // 取消授权
91 if (_this.properties.cancelBack) {
92 wx.navigateBack({
93 delta: 1
94 });
95 } else {
96 if (_this.properties.cancelDesc) {
97 wx.showToast({
98 title: _this.properties.cancelDesc,
99 icon: "none"
100 })
101 }
102 }
103 }
104 },
105
106 /**
107 * 尝试重拉信息
108 */
109 initPage() {
110 let pages = getCurrentPages();
111 let view = pages[pages.length - 1];
112 console.log("@authorize-comp view:", view);
113 if (view) {
114 try {
115 view.hideMask();
116 console.log("@authorize-comp || hideMask");
117 } catch (error) {}
118 try {
119 view.initData();
120 console.log("@authorize-comp || initData");
121 } catch (error) {}
122 }
123 }
124 }
125 })
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4
5 .comp-item {
6 width: 650px;
7 min-height: 496px;
8 border-radius: 10px;
9 background-color: #ffffff;
10
11 .cspace {
12 height: 80px;
13 }
14
15 .cont {
16 text-align: center;
17 width: 520px;
18 margin: 0 auto;
19
20 .logo {
21 margin: 0 auto;
22 width: 200px;
23 height: 153px;
24
25 image {
26 width: 200px;
27 height: 153px;
28 }
29 }
30
31 .tit {
32 font-size: 40px;
33 color: #333333;
34 }
35
36 .tips {
37 margin-top: 28px;
38 font-size: 32px;
39 color: #333333;
40 padding-bottom: 244px;
41 }
42 }
43
44 .btn-wrap {
45 position: absolute;
46 left: 0;
47 right: 0;
48 bottom: 80px;
49 margin: 0 auto;
50 display: flex;
51 justify-content: center;
52 }
53
54 .btn {
55 @include cb(240px, 80px);
56 margin: 0 24px;
57 }
58
59
60 .btn2 {
61 @include cb2(240px, 80px);
62 }
63
64 }
1 <view class="comp-item">
2 <view class="cspace"></view>
3 <view class="cont">
4 <!-- <view class="logo">
5 <image mode="widthFix" src="../../image/logo.png" />
6 </view> -->
7 <view class="tit">深士照明</view>
8 <view class="tips">
9 <text>需要获取您的微信昵称等信息才可以获取积分和兑换奖品哦</text>
10 </view>
11 </view>
12 <view class="btn-wrap">
13 <button class="btn btn2" bindtap="cancelAuth">暂不授权</button>
14 <button class="btn" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">确认授权</button>
15 </view>
16 </view>
1 Component({
2 properties: {
3 // 这里定义了innerText属性,属性值可以在组件使用时指定
4 innerText: {
5 type: String,
6 value: 'default value',
7 },
8 bottomVisible: {
9 type: Boolean,
10 value: false
11 }
12 },
13 data: {
14 // 这里是一些组件内部数据
15 someData: {}
16 },
17 methods: {
18 // 这里是一个自定义方法
19 customMethod() {}
20 }
21 })
1 // 底线
2 .bottom-tips {
3 position: relative;
4 padding: 40px 0;
5 width: 100%;
6 text-align: center;
7 color: #666666;
8
9 .line {
10 border-bottom: dashed 1px #cccccc;
11 width: 80%;
12 position: absolute;
13 top: 50%;
14 left: 0;
15 right: 0;
16 margin: 0 auto;
17 }
18
19 .tips-wrap {
20 position: relative;
21 font-size: 28px;
22
23 .tips {
24 padding: 0 20px;
25 background-color: #ffffff;
26 }
27 }
28 }
1 <view class="bottom-tips" wx:if="{{bottomVisible}}">
2 <view class="line"></view>
3 <view class="tips-wrap">
4 <text class="tips">我是有底线的</text>
5 </view>
6 </view>
1 let app = getApp();
2 Component({
3 // 样式隔离
4 // 详见 https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html
5 // isolated 表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(一般情况下的默认值);
6 // apply-shared 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面;
7 // shared 表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置了 apply-shared 或 shared 的自定义组件。(这个选项在插件中不可用。)
8 options: {
9 styleIsolation: 'isolated'
10 },
11 properties: {
12 // 这里定义了innerText属性,属性值可以在组件使用时指定
13 innerText: {
14 type: String,
15 value: 'default value',
16 }
17 },
18 data: {
19 // 这里是一些组件内部数据
20 someData: {}
21 },
22 methods: {
23 // 这里是一个自定义方法
24 customMethod() {
25 this.triggerEvent('evtcomp', {
26 name: "_evt_custom"
27 })
28 },
29 // 隐藏蒙层
30 hideMask() {
31 this.triggerEvent('evtcomp', {
32 name: "_evt_hide_product_detail_mask"
33 });
34 }
35 }
36 })
1 <view class="demo-item">demo-item</view>
1 Component({
2 options: {
3 styleIsolation: 'apply-shared' // 接受外部样式
4 },
5 properties: {
6 // 这里定义了innerText属性,属性值可以在组件使用时指定
7 innerText: {
8 type: String,
9 value: 'default value',
10 },
11 emptyVisible: {
12 type: Boolean,
13 value: false
14 }
15 },
16 data: {
17 // 这里是一些组件内部数据
18 someData: {}
19 },
20 methods: {
21 // 这里是一个自定义方法
22 customMethod() {}
23 }
24 })
1 //用的fixed 请确保 内容为空
2 .empty-tips {
3 position: fixed;
4 text-align: center;
5 color: #666666;
6 font-size: 32px;
7 width: 100%;
8 height: 100%;
9 display: flex;
10 justify-content: center;
11 top:35%;
12
13 .iconfont{
14 font-size: 100px;
15 }
16
17 .tips {
18 padding: 20px;
19 }
20 }
1 <view class="empty-tips" wx:if="{{emptyVisible}}">
2 <view class="tips">
3 <span class="iconfont iconempty"></span>
4 <view class="tips">这里空空如也~</view>
5 </view>
6 </view>
1 const app = getApp()
2 Component({
3 options: {
4 styleIsolation: 'apply-shared'
5 },
6 properties: {
7 navbarData: { //navbarData 由父页面传递的数据,变量名字自命名
8 type: Object,
9 value: {},
10 // observer: function (newVal, oldVal) {}
11 },
12 share: {
13 type: Boolean,
14 value: false
15 }
16 },
17 data: {
18 height: '',
19 barHeight: app.globalData.barHeight,
20 //默认值 默认显示左上角
21 // navbarData: {
22 // showCapsule: 1,
23 // }
24 },
25 attached: function () {
26 // 获取是否是通过分享进入的小程序
27 // this.setData({
28 // share: app.globalData.share
29 // })
30 // 定义导航栏的高度 方便对齐
31 this.setData({
32 statusBarHeight: app.globalData.statusBarHeight,
33 height: app.globalData.barHeight
34 })
35 },
36 methods: {
37 // 返回上一页面
38 _navback() {
39 wx.navigateBack()
40 },
41 //返回到首页
42 _backhome() {
43 app.router.push({
44 path: "index",
45 openType: "reLaunch"
46 })
47 // wx.navigateBack({
48 // delta: 999999
49 // })
50 }
51 },
52 ready() {
53 // console.log("navbarData.title}:", this.properties.navbarData.title);
54 }
55
56 })
1 {
2 "component": true
3 }
1 /* 顶部要固定定位 标题要居中 自定义按钮和标题要和右边微信原生的胶囊上下对齐 */
2 .nav-wrap {
3 position: fixed;
4 width: 100%;
5 top: 0;
6 background: #fff;
7 color: #000;
8 z-index: 999999;
9 }
10
11 /* 标题要居中 */
12 .nav-title {
13 position: absolute;
14 text-align: center;
15 max-width: 400px;
16 overflow: hidden;
17 text-overflow: ellipsis;
18 white-space: nowrap;
19 top: 0;
20 left: 0;
21 right: 0;
22 bottom: 0;
23 margin: auto;
24 font-size: 32px;
25 color: #2c2b2b;
26 font-weight: 600;
27 }
28
29 .nav-capsule {
30 display: flex;
31 align-items: center;
32 margin-left: 30px;
33 width: 120px;
34 justify-content: space-between;
35 height: 100%;
36 }
37
38 .navbar-v-line {
39 width: 1px;
40 height: 32px;
41 background-color: #e5e5e5;
42 }
43
44 .back-pre,
45 .back-home {
46 width: 32px;
47 height: 36px;
48 line-height: 36px;
49 margin-top: 4px;
50 padding: 10px;
51 }
52
53 .nav-capsule .back-home {
54 width: 36px;
55 height: 40px;
56 margin-top: 3px;
57 }
58
59 .iconfont {
60 font-size: 40px;
61 }
1 <view class='nav-wrap' style='height: {{height}}px;'>
2 <view class='nav-title' style='line-height: {{height+statusBarHeight}}px;'>{{navbarData.title}}</view>
3 <view style='display: flex; justify-content: space-around;flex-direction: column'>
4 <view class='nav-capsule' style='height: {{height+statusBarHeight}}px;' wx:if='{{navbarData.showCapsule}}'>
5 <view bindtap='_navback' wx:if='{{!share}}'>
6 <span class="iconfont iconbackicon1"></span>
7 </view>
8 <view class='navbar-v-line' wx:if='{{!share}}'></view>
9 <view bindtap='_backhome'>
10 <span class="iconfont iconhome"></span>
11 </view>
12 </view>
13 </view>
14 </view>
1 let ENV_CONFIG = require('./env/index');
2
3 const APPID = ''
4 /** ====每次发布版本记得修改此环境配置==== */
5 const ENV = 'dev'; // Dev Prod
6 const NET_CONFIG = ENV_CONFIG[ENV];
7 const MOCKAPI = ENV_CONFIG.mockApi;
8
9 module.exports = {
10 APPID,
11 ENV,
12 NET_CONFIG,
13 MOCKAPI
14 }
1 module.exports = {
2 mockApi: 'http://mock.simonfungc.com',
3 Dev: {
4 baseApi: 'https://ow.go.qudone.com/xxx',
5 commonApi: 'https://api.k.wxpai.cn/bizproxy'
6 },
7 Test: {
8 baseApi: 'https://test-api.xxx.com'
9 },
10 Slave: {
11 baseApi: 'https://slave-api.xxx.com'
12 },
13 Prod: {
14 baseApi: 'https://api.k.wxpai.cn/bizproxy/xxx',
15 commonApi: 'https://api.k.wxpai.cn/bizproxy'
16 }
17 }
1 # chmod u+x git.sh
2 unset msg
3
4 read -p "请输入commit提交的描述: " msg
5
6 if [[ $msg == "" ]]; then
7 msg="默认提交"
8 fi
9 git add -A
10 git commit -m $msg
11 git push
12 git status
1 module.exports = {
2 login: "/login", // post 通过wxcode换取sessionId
3 register: '/register', // post 注册(用户授权)
4
5 dataList: '/dataList', // 测试接口
6
7 /**
8 * 通用接口
9 * 请求时 "mode"传"custom"
10 */
11 areaQuery: 'https://api.k.wxpai.cn/bizproxy/kdapi/area', // post 区域查询
12 }
1 let config = require('./../config');
2 let Store = require('./../utils/stroage');
3 let Router = require('./../router/index');
4 const errMsg = '服务异常,请稍后重试';
5
6 // let isWxLogin = false;
7
8 function wxLogin() {
9 return new Promise((resolve, reject) => {
10 wx.login({
11 success: function (res) {
12 // isWxLogin = true;
13 Store.setItem('wxcode', res.code);
14 resolve();
15 }
16 });
17 });
18 }
19
20
21 // 检查并获取sessionid
22 function checkSessionId(sid) {
23 return new Promise((resolve, reject) => {
24 if (!sid) {
25 resolve();
26 return;
27 }
28 let sessionId = Store.getItem('sessionId');
29 if (sessionId) {
30 resolve();
31 } else {
32 // 没有sessionId则获取并埋值
33 login().then((result) => {
34 resolve();
35 }).catch((err) => {
36 reject();
37 });
38 }
39 });
40 }
41
42 // session丢失
43 function login() {
44 return new Promise((resolve, reject) => {
45 wxLogin().then((result) => {
46 let baseUrl = config.NET_CONFIG.baseApi;
47 wx.request({
48 url: baseUrl + '/login',
49 sid: false,
50 data: {
51 code: Store.getItem('wxcode')
52 },
53 method: 'POST',
54 success: function (res2) {
55 let {
56 code,
57 content
58 } = res2.data;
59 if (code == 200 && content.sessionId) {
60 Store.setItem('sessionId', content.sessionId);
61 resolve();
62 } else {
63 wx.hideLoading();
64 let pages = getCurrentPages();
65 let view = pages[pages.length - 1];
66 if (view) {
67 try {
68 wx.login({
69 success: function (res) {
70 Store.setItem('wxcode', res.code);
71 view.showAuth();
72 }
73 });
74 } catch (error) {}
75 }
76 reject();
77 }
78 }
79 })
80 })
81
82 });
83 }
84
85 const fetch = function ({
86 loading = true,
87 toast = true,
88 sid = true,
89 auth = true,
90 mode,
91 isMock,
92 url,
93 data,
94 method
95 }) {
96 if (loading && mode != 'log') wx.showLoading();
97 // 新建promise对象
98 let promise = new Promise((resolve, reject) => {
99 /**
100 * isMock设置单个接口Mock开启
101 * mode:目前针对不同业务的接口进行处理,log标识本地埋点上传
102 */
103 let baseUrl = config.NET_CONFIG.baseApi;
104 if (isMock && mode != 'log') {
105 baseUrl = config.MOCKAPI; //环境配置
106 }
107 // 使用通用接口前缀
108 if (mode == "common") {
109 baseUrl = config.NET_CONFIG.commonApi
110 }
111 // 自定义前缀,即不使用前缀
112 if (mode == "custom") {
113 baseUrl = ""
114 }
115 checkSessionId(sid).then((result) => {
116 wx.request({
117 url: baseUrl + url, //请求地址
118 data: data, //自定义参数
119 method: method || 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
120 header: {
121 sessionId: Store.getItem("sessionId")
122 },
123 success: function (result) {
124 // 日志上传不需要处理结果
125 if (mode == 'log') return;
126 let res = result.data;
127 // 登陆失效拦截,根据项目需要添加自己的配置
128 if (res.code == 404) {
129 //登陆失效的回调
130 Store.clear("sessionId");
131 // wx.reLaunch({
132 // url: '/pages/index/index'
133 // })
134 // 404后拉取登陆后再做一次
135 login().then((resultLogin) => {
136 wx.request({
137 url: baseUrl + url, //请求地址
138 data: data, //自定义参数
139 method: method || 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
140 header: {
141 sessionId: Store.getItem("sessionId")
142 },
143 success: function (result) {
144 // 日志上传不需要处理结果
145 if (mode == 'log') return;
146 let res = result.data;
147 if (res.code === 200) {
148 if (loading) {
149 wx.hideLoading();
150 }
151 resolve(res.content);
152 } else {
153 // 有些特殊状况不需要toast 需要弹窗
154 if (toast) {
155 wx.showToast({
156 title: res.errMsg || errMsg,
157 icon: 'none'
158 })
159 } else {
160 wx.hideLoading();
161 }
162 // 返回错误信息
163 reject(res);
164 }
165 }
166 });
167 })
168 return;
169 }
170 // 内部统一的成功code拦截码
171 if (res.code === 200) {
172 if (loading) {
173 wx.hideLoading();
174 }
175 resolve(res.content);
176 } else {
177 // 有些特殊状况不需要toast 需要弹窗
178 if (toast) {
179 wx.showToast({
180 title: res.errMsg || errMsg,
181 icon: 'none'
182 })
183 } else {
184 wx.hideLoading();
185 }
186 // 返回错误信息
187 reject(res);
188 }
189 },
190 fail: function (e = {
191 CODE: -1,
192 msg: errMsg,
193 errMsg
194 }) {
195 let msg = e.errMsg;
196 if (e.errMsg == 'request:fail timeout') {
197 msg = '服务请求超时,请稍后重试'
198 }
199 wx.showToast({
200 title: msg,
201 icon: 'none'
202 });
203 reject(e)
204 },
205 complete: function () {
206 // complete
207 }
208 })
209 })
210 });
211 return promise;
212 }
213
214 module.exports = {
215 fetch
216 }
1 // https://github.com/webx32/WxMock
2
3 let Mock = require('../utils/mockSdk.js');
4
5 let config = require('../config')
6 let env = config.MOCKAPI;
7
8 Mock.mock(env + '/eatClassifyService', {
9 data: {
10 resultCode: 0,
11 content: function () {
12 return Mock.Random.ip();
13 }
14 }
15 });
1 let app = getApp();
2
3 Page({
4 data: {
5 barHeight: app.globalData.barHeight,
6 navbarData: {
7 showCapsule: 0, //是否显示左上角图标 1表示显示 0表示不显示
8 title: '微信授权' //导航栏 中间的标题
9 },
10 loginData: null,
11 authorized: false,
12 canIUse: wx.canIUse('button.open-type.getUserInfo'),
13 parentMemberCode: "",
14 },
15 onLoad(options) {},
16 onReady() {
17 app.store.clear("sessionId");
18 let _this = this;
19 wx.login({
20 success: function (res) {
21 _this.data.loginData = res;
22 }
23 });
24 },
25 bindGetUserInfo(e) {
26 wx.showLoading();
27 this.getUserInfo(e.detail);
28 },
29 getUserInfo(e) {
30 let _this = this;
31 app.globalData.userInfo = e.userInfo;
32 // console.log("loginData:",_this.data.loginData);
33 app.post({
34 url: app.api.register,
35 sid: false,
36 data: {
37 encryptedData: e.encryptedData,
38 iv: e.iv,
39 code: _this.data.loginData.code,
40 parentMemberCode: _this.data.parentMemberCode,
41 }
42 }).then((res2) => {
43 app.store.setItem('sessionId', res2.sessionId);
44 _this.setData({
45 authorized: true
46 })
47 _this.toIndex();
48 }).catch((err) => {
49 console.log("@authorize || err:", err);
50 })
51 },
52 toIndex() {
53 console.log("@authorize || toIndex ");
54 setTimeout(() => {
55 app.router.push({
56 path: "index",
57 query: {},
58 openType: "redirect"
59 })
60 wx.hideLoading();
61 }, 2000);
62 }
63 })
1 {
2 "usingComponents": {
3 "navbar": "../../component/navbar/index"
4 },
5 "navigationStyle": "custom"
6 }
1 @import '../../assets/scss/mixins';
2
3 .page {
4 position: relative;
5 overflow: hidden;
6
7 .bgc {
8 // background-color: transparent;
9 // background-color: black;
10 background-color: #fafafc;
11 }
12
13
14 .main {
15
16 position: relative;
17
18 .top-space {
19 height: 60px;
20 }
21
22
23 .login {
24 position: relative;
25 width: 650px;
26 margin: 0 auto;
27 text-align: center;
28
29 &-logo {
30 width: 140px;
31 height: 140px;
32 }
33
34 &-name {
35 margin-top: 32px;
36 font-size: 32px;
37 color: #333333;
38 }
39
40 &-line {
41 margin-top: 70px;
42 width: 650px;
43 height: 2px;
44 background-color: #eaeaec;
45 }
46
47 &-title {
48 margin-top: 40px;
49 font-size: 32px;
50 text-align: left;
51 color: #333333;
52 }
53
54
55 &-tips {
56 margin-top: 28px;
57 font-size: 26px;
58 text-align: left;
59 color: #666666;
60 }
61
62 &-btn {
63 margin-top: 102px;
64 width: 650px;
65 height: 90px;
66 line-height: 90px;
67 border-radius: 8px;
68 background-color: #00c200;
69 font-size: 32px;
70 color: #ffffff;
71 }
72
73 }
74
75 }
76
77 }
1 <navbar navbar-data='{{navbarData}}'></navbar>
2 <view style='height: {{barHeight}}px'></view>
3 <view class="page-authorize page">
4 <view class="app__bgc bgc"></view>
5 <view class="app__bg bg"></view>
6 <!-- <view class="app__top-shadow"></view> -->
7 <view class="app__content main">
8 <view class="top-space"></view>
9 <view class="login">
10 <image class="login-logo" src="../../image/logo.png" mode="aspectFit" />
11 <view class="login-name">美赞臣</view>
12 <view class="login-line"></view>
13 <view class="login-title">完整体验小程序功能,需要您的微信授权哦</view>
14 <view class="login-tips">· 获取您的公开信息(昵称、头像等)</view>
15 <button type="default" class="login-btn" wx:if="{{!authorized}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">
16 确认授权
17 </button>
18 </view>
19 </view>
20 </view>
1 let app = getApp();
2
3 Page({
4 data: {
5 barHeight: app.globalData.barHeight,
6 navbarData: {
7 showCapsule: 0, //是否显示左上角图标 1表示显示 0表示不显示
8 title: '微信授权' //导航栏 中间的标题
9 },
10 loginData: null,
11 authorized: false,
12 canIUse: wx.canIUse('button.open-type.getUserInfo'),
13 parentMemberCode: "",
14 },
15 onLoad(options) {},
16 onReady() {
17 app.store.clear("sessionId");
18 let _this = this;
19 wx.login({
20 success: function (res) {
21 _this.data.loginData = res;
22 }
23 });
24 },
25 bindGetUserInfo(e) {
26 wx.showLoading();
27 this.getUserInfo(e.detail);
28 },
29 getUserInfo(e) {
30 let _this = this;
31 app.globalData.userInfo = e.userInfo;
32 // console.log("loginData:",_this.data.loginData);
33 app.post({
34 url: app.api.register,
35 sid: false,
36 data: {
37 encryptedData: e.encryptedData,
38 iv: e.iv,
39 code: _this.data.loginData.code,
40 parentMemberCode: _this.data.parentMemberCode,
41 }
42 }).then((res2) => {
43 app.store.setItem('sessionId', res2.sessionId);
44 _this.setData({
45 authorized: true
46 })
47 _this.toIndex();
48 }).catch((err) => {
49 console.log("@authorize || err:", err);
50 })
51 },
52 toIndex() {
53 console.log("@authorize || toIndex ");
54 setTimeout(() => {
55 app.router.push({
56 path: "index",
57 query: {},
58 openType: "redirect"
59 })
60 wx.hideLoading();
61 }, 2000);
62 }
63 })
1 {
2 "navigationStyle": "custom"
3 }
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4 .page {
5 position: relative;
6 overflow: hidden;
7
8 .bgc {}
9
10 .bg {
11 @include app-width;
12
13 image {
14 @include app-width;
15 }
16 }
17
18 // 右下角图标背景内容补充
19 .br-wrap {
20 $brWidth: 168px;
21 $brHeight: 172px;
22 width: $brWidth;
23 height: $brHeight;
24 position: fixed;
25 bottom: 0;
26 right: 0;
27 background-color: transparent;
28
29 image {
30 width: $brWidth;
31 height: $brHeight;
32 }
33 }
34
35
36
37 .main {
38 position: relative;
39 min-height: 1206px;
40
41 .content {
42 position: relative;
43 }
44
45 .login-wrap {
46 padding-top: 886px;
47
48 .terms-wrap {
49 margin-top: 24px;
50 display: flex;
51 justify-content: center;
52 margin-bottom: 16px;
53 font-size: 28px;
54 color: #333333;
55
56 .terms {
57 text-align: center;
58 padding: 0 12px;
59
60 .t1 {
61 color: #4bc2ed;
62 display: inline-block;
63 }
64 }
65 }
66
67
68
69 .login-btn {
70 width: 340px;
71 height: 80px;
72 line-height: 80px;
73 border-radius: 40px;
74 border: solid 3px #4bc2ed;
75 margin: 0 auto;
76 font-size: 36px;
77 color: #4bc2ed;
78 text-align: center;
79 background-color: transparent;
80 }
81
82 .gray {
83 color: #8f8f8f;
84 border-color: #8f8f8f;
85 }
86 }
87 }
88
89 }
90
91 .space1 {
92 height: 116px;
93 }
94
95
96 .terms-cont {
97 width: 690px;
98 height: 1000px;
99 position: relative;
100 background-color: #fff;
101
102 .cont {
103 position: relative;
104 width: 690px;
105 height: 900px;
106 overflow: auto;
107 padding: 28px;
108 @extend .bb;
109 font-size: 24px;
110
111
112 .tit {
113 text-align: center;
114 font-size: 32px;
115 font-weight: bold;
116 }
117
118 .desc {}
119
120 .t1 {
121 color: #4bc2ed;
122 display: inline-block;
123 margin-top: 16px;
124 }
125 }
126
127 .btn {
128
129 position: absolute;
130 bottom: 0;
131 left: 0;
132 right: 0;
133 }
134 }
1 <view class="page-authorize page">
2 <view class="app__bgc bgc"></view>
3 <view class="app__bg bg"></view>
4 <!-- <view class="app__top-shadow"></view> -->
5 <view class="app__content main">
6 <view class="top-space"></view>
7 <view class="login">
8 <image class="login-logo" src="../../image/logo.png" mode="aspectFit" />
9 <view class="login-name">小程序</view>
10 <view class="login-line"></view>
11 <view class="login-title">完整体验小程序功能,需要您的微信授权哦</view>
12 <view class="login-tips">· 获取您的公开信息(昵称、头像等)</view>
13 <button type="default" class="login-btn" wx:if="{{!authorized}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">
14 确认授权
15 </button>
16 </view>
17 </view>
18 </view>
1 import {
2 getBindtapData
3 } from '../../utils/util';
4
5 let app = getApp();
6 Page({
7 data: {
8 authorizeVisible: false,
9 total: 0,
10 page: 1,
11 size: 10,
12 productList: [], // 产品列表
13 indexInfo: {},
14 userInfo: {},
15 },
16 onShareAppMessage() {},
17 showAuth() {
18 this.setData({
19 authorizeVisible: true
20 })
21 },
22 onLoad(options) {},
23
24 /**
25 * 基础方法
26 * 授权完毕重拉数据用
27 */
28 initData() {
29
30 },
31 /**
32 * 到达底部
33 * 做加载更多操作
34 */
35 onReachBottom() {
36 if (this.data.dataList.length < this.data.total) {
37 this.setData({
38 page: this.data.page + 1
39 });
40 this.queryDataList();
41 }
42 },
43
44 // 重置页面列表 点击搜索条件时需要
45 resetPage() {
46 this.setData({
47 page: 1,
48 dataList: []
49 })
50 },
51
52 /**
53 * 请求DataList
54 */
55 queryDataList() {
56 return;
57 return new Promise((resolve, reject) => {
58 app.post({
59 sid: false,
60 url: app.api.dataList,
61 data: {
62 page: this.data.page,
63 size: this.data.size,
64 },
65 }).then((result) => {
66 let dataList = result.list;
67 dataList = this.data.dataList.concat(dataList);
68 this.setData({
69 dataList: dataList,
70 total: result.total
71 })
72 resolve();
73 })
74 });
75 },
76
77 /**
78 * 隐藏蒙层
79 */
80 hideMask() {
81 this.setData({
82 productDetailVisible: false,
83 authorizeVisible: false,
84 })
85 },
86 /**
87 * 子组件事件
88 * @param {*} evt
89 */
90 evtcomp(evt) {
91 let {
92 name,
93 data
94 } = evt.detail;
95 switch (name) {
96
97 // 隐藏蒙层
98 case "_evt_hide_mask":
99 this.hideMask();
100 break;
101
102 /**
103 * 重拉数据已在
104 */
105 case "_evt_auth_complete":
106 // this.initData();
107 this.hideMask();
108 break;
109
110 default:
111 break;
112 }
113 },
114 })
1 {
2 "navigationBarTitleText": ""
3 }
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4 .page {
5 .bgc {}
6
7 .bg {}
8
9 .main {
10 .top-space {
11 height: 0px;
12 }
13
14 .content {
15 position: relative;
16 }
17 }
18 }
1 <view class="page">
2 <view class="app__bgc bgc"></view>
3 <view class="app__bg bg"></view>
4 <view class="app__content main">
5 <view class="top-space"></view>
6 <view class="content"></view>
7 </view>
8 </view>
1 let app = getApp();
2 Page({
3 data: {},
4 onLoad(options) {
5 }
6 })
1 {
2 "navigationBarTitleText": "首页"
3 }
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4 .page {
5 .bgc {}
6
7 .bg {}
8
9 .main {
10 .top-space {
11 height: 0px;
12 }
13
14 .content {
15 position: relative;
16 }
17 }
18 }
1 <view class="page">
2 <view class="app__bgc bgc"></view>
3 <view class="app__bg bg"></view>
4 <!-- <view class="app__top-shadow"></view> -->
5 <view class="app__content main">
6 <view class="top-space"></view>
7 <view class="content">index</view>
8 </view>
9 </view>
1 let app = getApp();
2 Page({
3 data: {},
4 onLoad(options) {}
5 })
1 {
2 "navigationBarTitleText": "demo"
3 }
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4 .page {
5 .bgc {}
6
7 .bg {}
8
9 .main {
10 .top-space {
11 height: 0px;
12 }
13
14 .content {
15 position: relative;
16 }
17 }
18 }
1 <view class="page">
2 <view class="app__bgc bgc"></view>
3 <view class="app__bg bg"></view>
4 <!-- <view class="app__top-shadow"></view> -->
5 <view class="app__content main">
6 <view class="top-space"></view>
7 <view class="content"></view>
8 </view>
9 </view>
1 import {
2 getBindtapData
3 } from '../../utils/util';
4 // 二维码
5 import QR from '../../utils/qrcode'
6 // 海报
7 import Poster from '../../plugin/poster/poster/poster';
8
9 let app = getApp();
10 Page({
11 data: {
12 authorizeVisible: false,
13 },
14 onShareAppMessage() {},
15 showAuth() {
16 this.setData({
17 authorizeVisible: true
18 })
19 },
20 onLoad(options) {},
21 initData() {
22 this.initPoster();
23 this.initQrcode();
24 },
25
26 // 创建海报
27 initPoster() {
28 // 获取海报数据
29 let posterData = this.getPosterConfig();
30 // 绘制设置海报
31 this.onCreatePoster(posterData);
32 },
33
34 // 创建二维码
35 initQrcode() {
36 createQrCode('wxapp-qrcode', 'qrcode', 300, 300)
37 },
38
39 // ---- START 海报合成 ----
40 // 详情见: https://github.com/jasondu/wxa-plugin-canvas
41
42 // 海报合成成功
43 onPosterSuccess(e) {
44 wx.hideLoading();
45 const {
46 detail
47 } = e;
48 this.setData({
49 imageUrl: detail
50 })
51 },
52
53 // 合成失败
54 onPosterFail(err) {
55 wx.hideLoading();
56 console.error(err);
57 },
58
59 // 异步生成海报
60 onCreatePoster(posterConfig) {
61 this.setData({
62 posterConfig: posterConfig
63 }, () => {
64 Poster.create(true); // 入参:true为抹掉重新生成
65 });
66 },
67
68 // 获取海报数据
69 getPosterConfig() {
70 let blocks = [{
71 x: 0,
72 y: 0,
73 width: 690,
74 height: 900,
75 backgroundColor: "#ffffff",
76 borderRadius: 10,
77 }];
78 let images = [];
79 let lines = [];
80 let texts = [{
81 x: 690 / 2,
82 y: 192,
83 width: 690,
84 fontSize: 36,
85 color: "#3680EB",
86 textAlign: "center",
87 zIndex: 11,
88 text: "nickname",
89 }];
90
91 let posterData = {
92 width: 690,
93 height: 900,
94 debug: false,
95 blocks: blocks,
96 images: images,
97 lines: lines,
98 texts: texts,
99 }
100 return posterData;
101 },
102
103 // ---- END 海报合成 ----
104
105
106
107 /**
108 ---------------- 分界线 ----------------
109 */
110
111
112
113 // ---- START 二维码生成 ----
114 // 详情见: https://github.com/demi520/wxapp-qrcode
115
116 // 创建二维码
117 createQrCode(content, canvasId, cavW, cavH) {
118 //调用插件中的draw方法,绘制二维码图片
119 QR.api.draw(content, canvasId, cavW, cavH);
120 this.canvasToTempImage(canvasId);
121 },
122 //获取临时缓存图片路径,存入data中
123 canvasToTempImage(canvasId) {
124 let that = this;
125 wx.canvasToTempFilePath({
126 canvasId, // 这里canvasId即之前创建的canvas-id
127 success: function (res) {
128 let tempFilePath = res.tempFilePath;
129 console.log(tempFilePath);
130 that.setData({ // 如果采用mpvue,即 this.imagePath = tempFilePath
131 qrImagePath: tempFilePath,
132 });
133 },
134 fail: function (res) {
135 console.log(res);
136 }
137 });
138 },
139 //适配不同屏幕大小的canvas
140 setCanvasSize(sz) {
141 var size = {};
142 try {
143 var res = wx.getSystemInfoSync();
144 var scale = 750 / sz; //不同屏幕下canvas的适配比例;设计稿是750宽
145 var width = res.windowWidth / scale;
146 var height = width; //canvas画布为正方形
147 size.w = width;
148 size.h = height;
149 } catch (e) {
150 // Do something when catch error
151 console.log("获取设备信息失败" + e);
152 }
153 return size;
154 },
155 // ---- END 二维码生成 ----
156
157
158 })
1 {
2 "navigationBarTitleText": "海报合成/二维码示例",
3 "usingComponents": {
4 "poster": "/plugin/poster/poster/index"
5 }
6 }
1 @import '../../assets/scss/mixins';
2 @import '../../assets/scss/utils';
3
4 .page {
5 .bgc {}
6
7 .bg {}
8
9 .main {
10 .top-space {
11 height: 0px;
12 }
13
14 .content {
15 position: relative;
16 }
17 }
18 }
1 <poster id="poster" hide-loading="{{true}}" preload="{{false}}" config="{{posterConfig}}" bind:success="onPosterSuccess" bind:fail="onPosterFail"></poster>
2 <canvas canvas-id="qrcode" style="width: 200rpx;height: 200rpx;background:#0f0f0f;" />
3 <view class="page">
4 <view class="app__bgc bgc"></view>
5 <view class="app__bg bg"></view>
6 <view class="app__content main">
7 <view class="top-space"></view>
8 <view class="content">poster</view>
9 </view>
10 </view>
1 let app = getApp();
2 Page({
3 data: {
4 isShow: false, // 控制组件显示隐藏
5 url: ''
6 },
7 onLoad: function (options = {}) {
8 let url = options.url;
9 if (url) {
10 this.setData({
11 url: url,
12 isShow: true
13 })
14 } else {
15 wx.showToast({
16 title: '未找到页面地址',
17 title: 'none',
18 });
19 }
20 }
21 })
1 {
2 "navigationBarTitleText": "webview"
3 }
1 <view class="loading-wrap">
2 <view class="loading">
3 <view class="icon"></view>
4 <view class="text">加载中...</view>
5 </view>
6 </view>
7 <web-view wx:if="{{isShow}}" src="{{url}}" bindload="loadSucc"/>
1 const main = {
2 /**
3 * 渲染块
4 * @param {Object} params
5 */
6 drawBlock({ text, width = 0, height, x, y, paddingLeft = 0, paddingRight = 0, borderWidth, backgroundColor, borderColor, borderRadius = 0, opacity = 1 }) {
7 // 判断是否块内有文字
8 let blockWidth = 0; // 块的宽度
9 let textX = 0;
10 let textY = 0;
11 if (typeof text !== 'undefined') {
12 // 如果有文字并且块的宽度小于文字宽度,块的宽度为 文字的宽度 + 内边距
13 const textWidth = this._getTextWidth(typeof text.text === 'string' ? text : text.text);
14 blockWidth = textWidth > width ? textWidth : width;
15 blockWidth += paddingLeft + paddingLeft;
16
17 const { textAlign = 'left', text: textCon } = text;
18 textY = height / 2 + y; // 文字的y轴坐标在块中线
19 if (textAlign === 'left') {
20 // 如果是右对齐,那x轴在块的最左边
21 textX = x + paddingLeft;
22 } else if (textAlign === 'center') {
23 textX = blockWidth / 2 + x;
24 } else {
25 textX = x + blockWidth - paddingRight;
26 }
27 } else {
28 blockWidth = width;
29 }
30
31 if (backgroundColor) {
32 // 画面
33 this.ctx.save();
34 this.ctx.setGlobalAlpha(opacity);
35 this.ctx.setFillStyle(backgroundColor);
36 if (borderRadius > 0) {
37 // 画圆角矩形
38 this._drawRadiusRect(x, y, blockWidth, height, borderRadius);
39 this.ctx.fill();
40 } else {
41 this.ctx.fillRect(this.toPx(x), this.toPx(y), this.toPx(blockWidth), this.toPx(height));
42 }
43 this.ctx.restore();
44 }
45 if (borderWidth) {
46 // 画线
47 this.ctx.save();
48 this.ctx.setGlobalAlpha(opacity);
49 this.ctx.setStrokeStyle(borderColor);
50 this.ctx.setLineWidth(this.toPx(borderWidth));
51 if (borderRadius > 0) {
52 // 画圆角矩形边框
53 this._drawRadiusRect(x, y, blockWidth, height, borderRadius);
54 this.ctx.stroke();
55 } else {
56 this.ctx.strokeRect(this.toPx(x), this.toPx(y), this.toPx(blockWidth), this.toPx(height));
57 }
58 this.ctx.restore();
59 }
60
61 if (text) {
62 this.drawText(Object.assign(text, { x: textX, y: textY }))
63 }
64 },
65
66 /**
67 * 渲染文字
68 * @param {Object} params
69 */
70 drawText(params) {
71 const { x, y, fontSize, color, baseLine, textAlign, text, opacity = 1, width, lineNum, lineHeight } = params;
72 if (Object.prototype.toString.call(text) === '[object Array]') {
73 let preText = { x, y, baseLine };
74 text.forEach(item => {
75 preText.x += item.marginLeft || 0;
76 const textWidth = this._drawSingleText(Object.assign(item, {
77 ...preText,
78 }));
79 preText.x += textWidth + (item.marginRight || 0); // 下一段字的x轴为上一段字x + 上一段字宽度
80 })
81 } else {
82 this._drawSingleText(params);
83 }
84 },
85
86 /**
87 * 渲染图片
88 */
89 drawImage(data) {
90 const { imgPath, x, y, w, h, sx, sy, sw, sh, borderRadius = 0, borderWidth = 0, borderColor } = data;
91 this.ctx.save();
92 if (borderRadius > 0) {
93 this._drawRadiusRect(x, y, w, h, borderRadius);
94 this.ctx.strokeStyle = 'rgba(255,255,255,0)';
95 this.ctx.stroke();
96 this.ctx.clip();
97 this.ctx.drawImage(imgPath, this.toPx(sx), this.toPx(sy), this.toPx(sw), this.toPx(sh), this.toPx(x), this.toPx(y), this.toPx(w), this.toPx(h));
98 if (borderWidth > 0) {
99 this.ctx.setStrokeStyle(borderColor);
100 this.ctx.setLineWidth(this.toPx(borderWidth));
101 this.ctx.stroke();
102 }
103 } else {
104 this.ctx.drawImage(imgPath, this.toPx(sx), this.toPx(sy), this.toPx(sw), this.toPx(sh), this.toPx(x), this.toPx(y), this.toPx(w), this.toPx(h));
105 }
106 this.ctx.restore();
107 },
108 /**
109 * 渲染线
110 * @param {*} param0
111 */
112 drawLine({ startX, startY, endX, endY, color, width }) {
113 this.ctx.save();
114 this.ctx.beginPath();
115 this.ctx.setStrokeStyle(color);
116 this.ctx.setLineWidth(this.toPx(width));
117 this.ctx.moveTo(this.toPx(startX), this.toPx(startY));
118 this.ctx.lineTo(this.toPx(endX), this.toPx(endY));
119 this.ctx.stroke();
120 this.ctx.closePath();
121 this.ctx.restore();
122 },
123 downloadResource(images = []) {
124 const drawList = [];
125 this.drawArr = [];
126 images.forEach((image, index) => drawList.push(this._downloadImageAndInfo(image, index)));
127 return Promise.all(drawList);
128 },
129 initCanvas(w, h, debug) {
130 return new Promise((resolve) => {
131 this.setData({
132 pxWidth: this.toPx(w),
133 pxHeight: this.toPx(h),
134 debug,
135 }, resolve);
136 });
137 }
138 }
139 const handle = {
140 /**
141 * 画圆角矩形
142 */
143 _drawRadiusRect(x, y, w, h, r) {
144 const br = r / 2;
145 this.ctx.beginPath();
146 this.ctx.moveTo(this.toPx(x + br), this.toPx(y)); // 移动到左上角的点
147 this.ctx.lineTo(this.toPx(x + w - br), this.toPx(y));
148 this.ctx.arc(this.toPx(x + w - br), this.toPx(y + br), this.toPx(br), 2 * Math.PI * (3 / 4), 2 * Math.PI * (4 / 4))
149 this.ctx.lineTo(this.toPx(x + w), this.toPx(y + h - br));
150 this.ctx.arc(this.toPx(x + w - br), this.toPx(y + h - br), this.toPx(br), 0, 2 * Math.PI * (1 / 4))
151 this.ctx.lineTo(this.toPx(x + br), this.toPx(y + h));
152 this.ctx.arc(this.toPx(x + br), this.toPx(y + h - br), this.toPx(br), 2 * Math.PI * (1 / 4), 2 * Math.PI * (2 / 4))
153 this.ctx.lineTo(this.toPx(x), this.toPx(y + br));
154 this.ctx.arc(this.toPx(x + br), this.toPx(y + br), this.toPx(br), 2 * Math.PI * (2 / 4), 2 * Math.PI * (3 / 4))
155 },
156 /**
157 * 计算文本长度
158 * @param {Array|Object}} text 数组 或者 对象
159 */
160 _getTextWidth(text) {
161 let texts = [];
162 if (Object.prototype.toString.call(text) === '[object Object]') {
163 texts.push(text);
164 } else {
165 texts = text;
166 }
167 let width = 0;
168 texts.forEach(({ fontSize, text, marginLeft = 0, marginRight = 0 }) => {
169 this.ctx.setFontSize(this.toPx(fontSize));
170 width += this.ctx.measureText(text).width + marginLeft + marginRight;
171 })
172
173 return this.toRpx(width);
174 },
175 /**
176 * 渲染一段文字
177 */
178 _drawSingleText({ x, y, fontSize, color, baseLine, textAlign = 'left', text, opacity = 1, textDecoration = 'none',
179 width, lineNum = 1, lineHeight = 0, fontWeight = 'normal', fontStyle = 'normal', fontFamily = "sans-serif"}) {
180 this.ctx.save();
181 this.ctx.beginPath();
182 this.ctx.font = fontStyle + " " + fontWeight + " " + this.toPx(fontSize, true) + "px " + fontFamily
183 this.ctx.setGlobalAlpha(opacity);
184 // this.ctx.setFontSize(this.toPx(fontSize));
185 this.ctx.setFillStyle(color);
186 this.ctx.setTextBaseline(baseLine);
187 this.ctx.setTextAlign(textAlign);
188 let textWidth = this.toRpx(this.ctx.measureText(text).width);
189 const textArr = [];
190 if (textWidth > width) {
191 // 文本宽度 大于 渲染宽度
192 let fillText = '';
193 let line = 1;
194 for (let i = 0; i <= text.length - 1 ; i++) { // 将文字转为数组,一行文字一个元素
195 fillText = fillText + text[i];
196 if (this.toRpx(this.ctx.measureText(fillText).width) >= width) {
197 if (line === lineNum) {
198 if (i !== text.length - 1) {
199 fillText = fillText.substring(0, fillText.length - 1) + '...';
200 }
201 }
202 if(line <= lineNum) {
203 textArr.push(fillText);
204 }
205 fillText = '';
206 line++;
207 } else {
208 if(line <= lineNum) {
209 if(i === text.length -1){
210 textArr.push(fillText);
211 }
212 }
213 }
214 }
215 textWidth = width;
216 } else {
217 textArr.push(text);
218 }
219
220 textArr.forEach((item, index) => {
221 this.ctx.fillText(item, this.toPx(x), this.toPx(y + (lineHeight || fontSize) * index));
222 })
223
224 this.ctx.restore();
225
226 // textDecoration
227 if (textDecoration !== 'none') {
228 let lineY = y;
229 if (textDecoration === 'line-through') {
230 // 目前只支持贯穿线
231 lineY = y;
232 }
233 this.ctx.save();
234 this.ctx.moveTo(this.toPx(x), this.toPx(lineY));
235 this.ctx.lineTo(this.toPx(x) + this.toPx(textWidth), this.toPx(lineY));
236 this.ctx.setStrokeStyle(color);
237 this.ctx.stroke();
238 this.ctx.restore();
239 }
240
241 return textWidth;
242 },
243 }
244 const helper = {
245 /**
246 * 下载图片并获取图片信息
247 */
248 _downloadImageAndInfo(image, index) {
249 return new Promise((resolve, reject) => {
250 const { x, y, url, zIndex } = image;
251 const imageUrl = url;
252 // 下载图片
253 this._downImage(imageUrl, index)
254 // 获取图片信息
255 .then(imgPath => this._getImageInfo(imgPath, index))
256 .then(({ imgPath, imgInfo }) => {
257 // 根据画布的宽高计算出图片绘制的大小,这里会保证图片绘制不变形
258 let sx;
259 let sy;
260 const borderRadius = image.borderRadius || 0;
261 const setWidth = image.width;
262 const setHeight = image.height;
263 const width = this.toRpx(imgInfo.width);
264 const height = this.toRpx(imgInfo.height);
265
266 if (width / height <= setWidth / setHeight) {
267 sx = 0;
268 sy = (height - ((width / setWidth) * setHeight)) / 2;
269 } else {
270 sy = 0;
271 sx = (width - ((height / setHeight) * setWidth)) / 2;
272 }
273 this.drawArr.push({
274 type: 'image',
275 borderRadius,
276 borderWidth: image.borderWidth,
277 borderColor: image.borderColor,
278 zIndex: typeof zIndex !== 'undefined' ? zIndex : index,
279 imgPath,
280 sx,
281 sy,
282 sw: (width - (sx * 2)),
283 sh: (height - (sy * 2)),
284 x,
285 y,
286 w: setWidth,
287 h: setHeight,
288 });
289 resolve();
290 })
291 .catch(err => reject(err));
292 });
293 },
294 /**
295 * 下载图片资源
296 * @param {*} imageUrl
297 */
298 _downImage(imageUrl) {
299 return new Promise((resolve, reject) => {
300 if (/^http/.test(imageUrl) && !new RegExp(wx.env.USER_DATA_PATH).test(imageUrl)) {
301 wx.downloadFile({
302 url: this._mapHttpToHttps(imageUrl),
303 success: (res) => {
304 if (res.statusCode === 200) {
305 resolve(res.tempFilePath);
306 } else {
307 reject(res.errMsg);
308 }
309 },
310 fail(err) {
311 reject(err);
312 },
313 });
314 } else {
315 // 支持本地地址
316 resolve(imageUrl);
317 }
318 });
319 },
320 /**
321 * 获取图片信息
322 * @param {*} imgPath
323 * @param {*} index
324 */
325 _getImageInfo(imgPath, index) {
326 return new Promise((resolve, reject) => {
327 wx.getImageInfo({
328 src: imgPath,
329 success(res) {
330 resolve({ imgPath, imgInfo: res, index });
331 },
332 fail(err) {
333 reject(err);
334 },
335 });
336 });
337 },
338 toPx(rpx, int) {
339 if (int) {
340 return parseInt(rpx * this.factor);
341 }
342 return rpx * this.factor;
343 },
344 toRpx(px, int) {
345 if (int) {
346 return parseInt(px / this.factor);
347 }
348 return px / this.factor;
349 },
350 /**
351 * 将http转为https
352 * @param {String}} rawUrl 图片资源url
353 */
354 _mapHttpToHttps(rawUrl) {
355 if (rawUrl.indexOf(':') < 0) {
356 return rawUrl;
357 }
358 const urlComponent = rawUrl.split(':');
359 if (urlComponent.length === 2) {
360 if (urlComponent[0] === 'http') {
361 urlComponent[0] = 'https';
362 return `${urlComponent[0]}:${urlComponent[1]}`;
363 }
364 }
365 return rawUrl;
366 },
367 }
368 Component({
369 properties: {
370 },
371 created() {
372 const sysInfo = wx.getSystemInfoSync();
373 const screenWidth = sysInfo.screenWidth;
374 this.factor = screenWidth / 750;
375 },
376 methods: Object.assign({
377 /**
378 * 计算画布的高度
379 * @param {*} config
380 */
381 getHeight(config) {
382 const getTextHeight = (text) => {
383 let fontHeight = text.lineHeight || text.fontSize;
384 let height = 0;
385 if (text.baseLine === 'top') {
386 height = fontHeight;
387 } else if (text.baseLine === 'middle') {
388 height = fontHeight / 2;
389 } else {
390 height = 0;
391 }
392 return height;
393 }
394 const heightArr = [];
395 (config.blocks || []).forEach((item) => {
396 heightArr.push(item.y + item.height);
397 });
398 (config.texts || []).forEach((item) => {
399 let height;
400 if (Object.prototype.toString.call(item.text) === '[object Array]') {
401 item.text.forEach((i) => {
402 height = getTextHeight({...i, baseLine: item.baseLine});
403 heightArr.push(item.y + height);
404 });
405 } else {
406 height = getTextHeight(item);
407 heightArr.push(item.y + height);
408 }
409 });
410 (config.images || []).forEach((item) => {
411 heightArr.push(item.y + item.height);
412 });
413 (config.lines || []).forEach((item) => {
414 heightArr.push(item.startY);
415 heightArr.push(item.endY);
416 });
417 const sortRes = heightArr.sort((a, b) => b - a);
418 let canvasHeight = 0;
419 if (sortRes.length > 0) {
420 canvasHeight = sortRes[0];
421 }
422 if (config.height < canvasHeight || !config.height) {
423 return canvasHeight;
424 } else {
425 return config.height;
426 }
427 },
428 create(config) {
429 this.ctx = wx.createCanvasContext('canvasid', this);
430
431 const height = this.getHeight(config);
432 this.initCanvas(config.width, height, config.debug)
433 .then(() => {
434 // 设置画布底色
435 if (config.backgroundColor) {
436 this.ctx.save();
437 this.ctx.setFillStyle(config.backgroundColor);
438 this.ctx.fillRect(0, 0, this.toPx(config.width), this.toPx(height));
439 this.ctx.restore();
440 }
441 const { texts = [], images = [], blocks = [], lines = [] } = config;
442 const queue = this.drawArr
443 .concat(texts.map((item) => {
444 item.type = 'text';
445 item.zIndex = item.zIndex || 0;
446 return item;
447 }))
448 .concat(blocks.map((item) => {
449 item.type = 'block';
450 item.zIndex = item.zIndex || 0;
451 return item;
452 }))
453 .concat(lines.map((item) => {
454 item.type = 'line';
455 item.zIndex = item.zIndex || 0;
456 return item;
457 }));
458 // 按照顺序排序
459 queue.sort((a, b) => a.zIndex - b.zIndex);
460
461 queue.forEach((item) => {
462 if (item.type === 'image') {
463 this.drawImage(item)
464 } else if (item.type === 'text') {
465 this.drawText(item)
466 } else if (item.type === 'block') {
467 this.drawBlock(item)
468 } else if (item.type === 'line') {
469 this.drawLine(item)
470 }
471 });
472
473 const res = wx.getSystemInfoSync();
474 const platform = res.platform;
475 let time = 0;
476 if (platform === 'android') {
477 // 在安卓平台,经测试发现如果海报过于复杂在转换时需要做延时,要不然样式会错乱
478 time = 300;
479 }
480 this.ctx.draw(false, () => {
481 setTimeout(() => {
482 wx.canvasToTempFilePath({
483 canvasId: 'canvasid',
484 success: (res) => {
485 this.triggerEvent('success', res.tempFilePath);
486 },
487 fail: (err) => {
488 this.triggerEvent('fail', err);
489 },
490 }, this);
491 }, time);
492 });
493 })
494 .catch((err) => {
495 wx.showToast({ icon: 'none', title: err.errMsg || '生成失败' });
496 console.error(err);
497 });
498 },
499 }, main, handle, helper),
500 });
501
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <!--index.wxml-->
2 <view class="container">
3 <canvas canvas-id='canvasid' class="canvas {{debug ? 'debug' : 'pro'}}" style='width: {{pxWidth}}px; height: {{pxHeight}}px;'></canvas>
4 </view>
1 .canvas {
2 width: 750rpx;
3 height: 750rpx;
4 }
5 .canvas.pro {
6 position: absolute;
7 bottom: 0;
8 left: 0;
9 transform: translate3d(-9999rpx, 0, 0);
10 }
11 .canvas.debug {
12 position: absolute;
13 bottom: 0;
14 left: 0;
15 border: 1rpx solid #ccc;
16 }
...\ No newline at end of file ...\ No newline at end of file
1 Component({
2 properties: {
3 config: {
4 type: Object,
5 value: {},
6 },
7 preload: { // 是否预下载图片资源
8 type: Boolean,
9 value: false,
10 },
11 hideLoading: { // 是否隐藏loading
12 type: Boolean,
13 value: false,
14 }
15 },
16 ready() {
17 if (this.data.preload) {
18 const poster = this.selectComponent('#poster');
19 this.downloadStatus = 'doing';
20 poster.downloadResource(this.data.config.images).then(() => {
21 this.downloadStatus = 'success';
22 this.trigger('downloadSuccess');
23 }).catch((e) => {
24 this.downloadStatus = 'fail';
25 this.trigger('downloadFail', e);
26 });
27 }
28 },
29 methods: {
30 trigger(event, data) {
31 if (this.listener && typeof this.listener[event] === 'function') {
32 this.listener[event](data);
33 }
34 },
35 once(event, fun) {
36 if (typeof this.listener === 'undefined') {
37 this.listener = {};
38 }
39 this.listener[event] = fun;
40 },
41 downloadResource(reset) {
42 return new Promise((resolve, reject) => {
43 if (reset) {
44 this.downloadStatus = null;
45 }
46 const poster = this.selectComponent('#poster');
47 if (this.downloadStatus && this.downloadStatus !== 'fail') {
48 if (this.downloadStatus === 'success') {
49 resolve();
50 } else {
51 this.once('downloadSuccess', () => resolve());
52 this.once('downloadFail', (e) => reject(e));
53 }
54 } else {
55 poster.downloadResource(this.data.config.images)
56 .then(() => {
57 this.downloadStatus = 'success';
58 resolve();
59 })
60 .catch((e) => reject(e));
61 }
62 })
63 },
64 onCreate(reset = false) {
65 !this.data.hideLoading && wx.showLoading({ mask: true, title: '生成中' });
66 return this.downloadResource(typeof reset === 'boolean' && reset).then(() => {
67 !this.data.hideLoading && wx.hideLoading();
68 const poster = this.selectComponent('#poster');
69 poster.create(this.data.config);
70 })
71 .catch((err) => {
72 !this.data.hideLoading && wx.hideLoading();
73 wx.showToast({ icon: 'none', title: err.errMsg || '生成失败' });
74 console.error(err);
75 this.triggerEvent('fail', err);
76 })
77 },
78 onCreateSuccess(e) {
79 const { detail } = e;
80 this.triggerEvent('success', detail);
81 },
82 onCreateFail(err) {
83 console.error(err);
84 this.triggerEvent('fail', err);
85 }
86 }
87 })
...\ No newline at end of file ...\ No newline at end of file
1 {
2 "component": true,
3 "usingComponents": {
4 "we-canvas": "../index/index"
5 }
6 }
...\ No newline at end of file ...\ No newline at end of file
1 <view bindtap='onCreate'>
2 <slot/>
3 </view>
4 <we-canvas id="poster" bind:success="onCreateSuccess" bind:fail="onCreateFail"/>
...\ No newline at end of file ...\ No newline at end of file
1 const defaultOptions = {
2 selector: '#poster'
3 };
4
5 function Poster(options = {}) {
6 options = {
7 ...defaultOptions,
8 ...options,
9 };
10
11 const pages = getCurrentPages();
12 const ctx = pages[pages.length - 1];
13
14 const poster = ctx.selectComponent(options.selector);
15 delete options.selector;
16
17 return poster;
18 };
19
20 Poster.create = (reset = false) => {
21 const poster = Poster();
22 if (!poster) {
23 console.error('请设置组件的id="poster"!!!');
24 } else {
25 return Poster().onCreate(reset);
26 }
27 }
28
29 export default Poster;
...\ No newline at end of file ...\ No newline at end of file
1 const routerPath = {
2 index: '/pages/index/index',
3 authorize: '/pages/authorize/authorize', // 授权
4 example: '/pages/example/example',
5 more: '/pages/more/more',
6 }
7
8 function parse(data) {
9 let tempArr = [];
10 for (let key in data) {
11 tempArr.push(key + '=' + encodeURIComponent(data[key]));
12 }
13 return tempArr.join('&');
14 }
15
16 function push(path, option = {}) {
17 if (typeof path == 'string') {
18 option.path = path; //兼容无参数路径
19 } else {
20 option = path;
21 }
22 // console.log("option:", option);
23 // 配置key值找到对应path
24 let url = routerPath[option.path] || routerPath['index'];
25 // console.log("url:", url);
26 // 读取传入的配置参数
27 let {
28 query = {}, openType = 'navigate', duration = 0
29 } = option;
30 // json 转换为 字符串拼接参数
31 let params = parse(query)
32 // console.log("params:", params);
33 if (params) {
34 url = url + '?' + params;
35 }
36 // 是否需要延时跳转
37 duration ? setTimeout(() => {
38 to(openType, url);
39 }, duration) : to(openType, url);
40 }
41
42 function to(openType, url) {
43 let obj = {
44 url
45 };
46
47 if (openType == 'redirect') {
48 wx.redirectTo(obj);
49 } else if (openType == 'reLaunch') {
50 wx.reLaunch(obj);
51 } else if (openType == 'switchTab') {
52 wx.switchTab(obj);
53 } else if (openType == 'back') {
54 wx.navigateBack({
55 delta: 1
56 });
57 } else {
58 wx.navigateTo(obj);
59 }
60 }
61
62 module.exports = {
63 parse,
64 push,
65 to
66 }
1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({
4 mixins: [safeArea()],
5 props: {
6 show: Boolean,
7 title: String,
8 cancelText: String,
9 zIndex: {
10 type: Number,
11 value: 100
12 },
13 actions: {
14 type: Array,
15 value: []
16 },
17 overlay: {
18 type: Boolean,
19 value: true
20 },
21 closeOnClickOverlay: {
22 type: Boolean,
23 value: true
24 }
25 },
26 methods: {
27 onSelect(event) {
28 const { index } = event.currentTarget.dataset;
29 const item = this.data.actions[index];
30 if (item && !item.disabled && !item.loading) {
31 this.$emit('select', item);
32 }
33 },
34 onCancel() {
35 this.$emit('cancel');
36 },
37 onClose() {
38 this.$emit('close');
39 }
40 }
41 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-popup": "../popup/index",
6 "van-loading": "../loading/index"
7 }
8 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <van-popup
4 show="{{ show }}"
5 position="bottom"
6 z-index="{{ zIndex }}"
7 overlay="{{ overlay }}"
8 custom-class="van-action-sheet"
9 safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
10 close-on-click-overlay="{{ closeOnClickOverlay }}"
11 bind:close="onClose"
12 >
13 <view wx:if="{{ title }}" class="van-hairline--bottom van-action-sheet__header">
14 {{ title }}
15 <van-icon
16 name="close"
17 custom-class="van-action-sheet__close"
18 bind:click="onClose"
19 />
20 </view>
21 <view wx:if="{{ actions && actions.length }}">
22 <!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
23 <button
24 wx:for="{{ actions }}"
25 wx:key="index"
26 open-type="{{ item.openType }}"
27 class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} van-hairline--top {{ item.className || '' }}"
28 hover-class="van-action-sheet__item--hover"
29 data-index="{{ index }}"
30 bind:tap="onSelect"
31 >
32 <block wx:if="{{ !item.loading }}">
33 {{ item.name }}
34 <text wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</text>
35 </block>
36 <van-loading wx:else size="20px" />
37 </button>
38 </view>
39 <slot />
40 <view
41 wx:if="{{ cancelText }}"
42 class="van-action-sheet__cancel"
43 hover-class="van-action-sheet__cancel--hover"
44 hover-stay-time="70"
45 bind:tap="onCancel"
46 >
47 {{ cancelText }}
48 </view>
49 </van-popup>
1 @import '../common/index.wxss';.van-action-sheet{max-height:90%!important;color:#333}.van-action-sheet__cancel,.van-action-sheet__item{height:50px;font-size:16px;line-height:50px;text-align:center;background-color:#fff}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5}.van-action-sheet__cancel{height:60px}.van-action-sheet__cancel:before{display:block;height:10px;background-color:#f8f8f8;content:" "}.van-action-sheet__item--disabled{color:#c9c9c9}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:#fff}.van-action-sheet__subname{margin-left:5px;font-size:12px;color:#7d7e80}.van-action-sheet__header{font-size:16px;font-weight:500;line-height:44px;text-align:center}.van-action-sheet__close{position:absolute!important;top:0;right:0;padding:0 15px;font-size:18px!important;line-height:inherit!important;color:#999}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 classes: ['active-class', 'toolbar-class', 'column-class'],
4 props: {
5 title: String,
6 value: String,
7 loading: Boolean,
8 cancelButtonText: String,
9 confirmButtonText: String,
10 itemHeight: {
11 type: Number,
12 value: 44
13 },
14 visibleItemCount: {
15 type: Number,
16 value: 5
17 },
18 columnsNum: {
19 type: [String, Number],
20 value: 3
21 },
22 areaList: {
23 type: Object,
24 value: {}
25 }
26 },
27 data: {
28 columns: [{ values: [] }, { values: [] }, { values: [] }],
29 displayColumns: [{ values: [] }, { values: [] }, { values: [] }]
30 },
31 watch: {
32 value(value) {
33 this.code = value;
34 this.setValues();
35 },
36 areaList: 'setValues',
37 columnsNum(value) {
38 this.set({
39 displayColumns: this.data.columns.slice(0, +value)
40 });
41 }
42 },
43 methods: {
44 getPicker() {
45 if (this.picker == null) {
46 this.picker = this.selectComponent('.van-area__picker');
47 }
48 return this.picker;
49 },
50 onCancel(event) {
51 this.emit('cancel', event.detail);
52 },
53 onConfirm(event) {
54 this.emit('confirm', event.detail);
55 },
56 emit(type, detail) {
57 detail.values = detail.value;
58 delete detail.value;
59 this.$emit(type, detail);
60 },
61 onChange(event) {
62 const { index, picker, value } = event.detail;
63 this.code = value[index].code;
64 this.setValues().then(() => {
65 this.$emit('change', {
66 picker,
67 values: picker.getValues(),
68 index
69 });
70 });
71 },
72 getConfig(type) {
73 const { areaList } = this.data;
74 return (areaList && areaList[`${type}_list`]) || {};
75 },
76 getList(type, code) {
77 let result = [];
78 if (type !== 'province' && !code) {
79 return result;
80 }
81 const list = this.getConfig(type);
82 result = Object.keys(list).map(code => ({
83 code,
84 name: list[code]
85 }));
86 if (code) {
87 // oversea code
88 if (code[0] === '9' && type === 'city') {
89 code = '9';
90 }
91 result = result.filter(item => item.code.indexOf(code) === 0);
92 }
93 return result;
94 },
95 getIndex(type, code) {
96 let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
97 const list = this.getList(type, code.slice(0, compareNum - 2));
98 // oversea code
99 if (code[0] === '9' && type === 'province') {
100 compareNum = 1;
101 }
102 code = code.slice(0, compareNum);
103 for (let i = 0; i < list.length; i++) {
104 if (list[i].code.slice(0, compareNum) === code) {
105 return i;
106 }
107 }
108 return 0;
109 },
110 setValues() {
111 const county = this.getConfig('county');
112 let code = this.code || Object.keys(county)[0] || '';
113 const province = this.getList('province');
114 const city = this.getList('city', code.slice(0, 2));
115 const picker = this.getPicker();
116 if (!picker) {
117 return;
118 }
119 const stack = [];
120 stack.push(picker.setColumnValues(0, province, false));
121 stack.push(picker.setColumnValues(1, city, false));
122 if (city.length && code.slice(2, 4) === '00') {
123 ;
124 [{ code }] = city;
125 }
126 stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
127 return Promise.all(stack)
128 .catch(() => { })
129 .then(() => picker.setIndexes([
130 this.getIndex('province', code),
131 this.getIndex('city', code),
132 this.getIndex('county', code)
133 ]))
134 .catch(() => { });
135 },
136 getValues() {
137 const picker = this.getPicker();
138 return picker ? picker.getValues().filter(value => !!value) : [];
139 },
140 getDetail() {
141 const values = this.getValues();
142 const area = {
143 code: '',
144 country: '',
145 province: '',
146 city: '',
147 county: ''
148 };
149 if (!values.length) {
150 return area;
151 }
152 const names = values.map((item) => item.name);
153 area.code = values[values.length - 1].code;
154 if (area.code[0] === '9') {
155 area.country = names[1] || '';
156 area.province = names[2] || '';
157 }
158 else {
159 area.province = names[0] || '';
160 area.city = names[1] || '';
161 area.county = names[2] || '';
162 }
163 return area;
164 },
165 reset() {
166 this.code = '';
167 return this.setValues();
168 }
169 }
170 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-picker": "../picker/index"
5 }
6 }
1 <van-picker
2 class="van-area__picker"
3 active-class="active-class"
4 toolbar-class="toolbar-class"
5 column-class="column-class"
6 show-toolbar
7 value-key="name"
8 title="{{ title }}"
9 loading="{{ loading }}"
10 columns="{{ displayColumns }}"
11 item-height="{{ itemHeight }}"
12 visible-item-count="{{ visibleItemCount }}"
13 cancel-button-text="{{ cancelButtonText }}"
14 confirm-button-text="{{ confirmButtonText }}"
15 bind:change="onChange"
16 bind:confirm="onConfirm"
17 bind:cancel="onCancel"
18 />
1 @import '../common/index.wxss';
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { isNumber } from '../common/utils';
3 VantComponent({
4 relation: {
5 name: 'badge',
6 type: 'descendant',
7 linked(target) {
8 this.badges.push(target);
9 this.setActive();
10 },
11 unlinked(target) {
12 this.badges = this.badges.filter(item => item !== target);
13 this.setActive();
14 }
15 },
16 props: {
17 active: {
18 type: Number,
19 value: 0
20 }
21 },
22 watch: {
23 active: 'setActive'
24 },
25 beforeCreate() {
26 this.badges = [];
27 this.currentActive = -1;
28 },
29 methods: {
30 setActive(badge) {
31 let { active } = this.data;
32 const { badges } = this;
33 if (badge && !isNumber(badge)) {
34 active = badges.indexOf(badge);
35 }
36 if (active === this.currentActive) {
37 return;
38 }
39 if (this.currentActive !== -1 && badges[this.currentActive]) {
40 this.$emit('change', active);
41 badges[this.currentActive].setActive(false);
42 }
43 if (badges[active]) {
44 badges[active].setActive(true);
45 this.currentActive = active;
46 }
47 }
48 }
49 });
1 <view class="van-badge-group van-hairline--top-bottom custom-class">
2 <slot />
3 </view>
1 @import '../common/index.wxss';.van-badge-group{width:85px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 relation: {
4 type: 'ancestor',
5 name: 'badge-group'
6 },
7 props: {
8 info: null,
9 title: String
10 },
11 methods: {
12 onClick() {
13 const group = this.getRelationNodes('../badge-group/index')[0];
14 if (group) {
15 group.setActive(this);
16 }
17 },
18 setActive(active) {
19 this.set({ active });
20 }
21 }
22 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-info": "../info/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="{{ utils.bem('badge', { active }) }} van-hairline custom-class"
5 hover-class="van-badge--hover"
6 hover-stay-time="70"
7 bind:tap="onClick"
8 >
9 <view class="van-badge__text">
10 <van-info
11 wx:if="{{ info !== null }}"
12 info="{{ info }}"
13 custom-style="right: 4px"
14 />
15 {{ title }}
16 </view>
17 </view>
1 @import '../common/index.wxss';.van-badge{display:block;padding:20px 12px 20px 9px;overflow:hidden;font-size:14px;line-height:1.4;color:#7d7e80;word-break:break-all;background-color:#f8f8f8;border-left:3px solid transparent;box-sizing:border-box;-webkit-user-select:none;user-select:none}.van-badge--hover{background-color:#f2f3f5}.van-badge:after{border-bottom-width:1px}.van-badge--active{font-weight:700;color:#333;border-color:#f44}.van-badge--active:after{border-right-width:1px}.van-badge--active,.van-badge--active.van-badge--hover{background-color:#fff}.van-badge__text{position:relative}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { button } from '../mixins/button';
3 import { openType } from '../mixins/open-type';
4 VantComponent({
5 mixins: [button, openType],
6 classes: ['hover-class', 'loading-class'],
7 props: {
8 plain: Boolean,
9 block: Boolean,
10 round: Boolean,
11 square: Boolean,
12 loading: Boolean,
13 hairline: Boolean,
14 disabled: Boolean,
15 loadingText: String,
16 type: {
17 type: String,
18 value: 'default'
19 },
20 size: {
21 type: String,
22 value: 'normal'
23 },
24 loadingSize: {
25 type: String,
26 value: '20px'
27 }
28 },
29 methods: {
30 onClick() {
31 if (!this.data.disabled && !this.data.loading) {
32 this.$emit('click');
33 }
34 }
35 }
36 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-loading": "../loading/index"
5 }
6 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <button
4 id="{{ id }}"
5 class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
6 open-type="{{ openType }}"
7 hover-class="van-button--active hover-class"
8 lang="{{ lang }}"
9 business-id="{{ businessId }}"
10 session-from="{{ sessionFrom }}"
11 send-message-title="{{ sendMessageTitle }}"
12 send-message-path="{{ sendMessagePath }}"
13 send-message-img="{{ sendMessageImg }}"
14 show-message-card="{{ showMessageCard }}"
15 app-parameter="{{ appParameter }}"
16 aria-label="{{ ariaLabel }}"
17 bindtap="onClick"
18 bindgetuserinfo="bindGetUserInfo"
19 bindcontact="bindContact"
20 bindgetphonenumber="bindGetPhoneNumber"
21 binderror="bindError"
22 bindlaunchapp="bindLaunchApp"
23 bindopensetting="bindOpenSetting"
24 >
25 <block wx:if="{{ loading }}">
26 <van-loading
27 custom-class="loading-class"
28 size="{{ loadingSize }}"
29 color="{{ type === 'default' ? '#c9c9c9' : '' }}"
30 />
31 <view
32 wx:if="{{ loadingText }}"
33 class="van-button__loading-text"
34 >
35 {{ loadingText }}
36 </view>
37 </block>
38 <slot wx:else />
39 </button>
1 @import '../common/index.wxss';.van-button{position:relative;display:inline-block;height:44px;padding:0;font-size:16px;line-height:42px;text-align:center;vertical-align:middle;box-sizing:border-box;border-radius:2px;-webkit-appearance:none;-webkit-text-size-adjust:100%}.van-button:before{position:absolute;top:50%;left:50%;width:100%;height:100%;background-color:#000;border:inherit;border-color:#000;border-radius:inherit;content:" ";opacity:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{color:#333;background-color:#fff;border:1px solid #eee}.van-button--primary{color:#fff;background-color:#07c160;border:1px solid #07c160}.van-button--info{color:#fff;background-color:#1989fa;border:1px solid #1989fa}.van-button--danger{color:#fff;background-color:#f44;border:1px solid #f44}.van-button--warning{color:#fff;background-color:#ff976a;border:1px solid #ff976a}.van-button--plain{background-color:#fff}.van-button--plain.van-button--primary{color:#07c160}.van-button--plain.van-button--info{color:#1989fa}.van-button--plain.van-button--danger{color:#f44}.van-button--plain.van-button--warning{color:#ff976a}.van-button--large{width:100%;height:50px;line-height:48px}.van-button--normal{padding:0 15px;font-size:14px}.van-button--small{height:30px;min-width:60px;padding:0 8px;font-size:12px;line-height:28px}.van-button--mini{display:inline-block;width:50px;height:22px;font-size:10px;line-height:20px}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:block;width:100%}.van-button--round{border-radius:10em}.van-button--square{border-radius:0}.van-button--disabled{opacity:.5}.van-button__loading-text{margin-left:5px;display:inline-block;vertical-align:middle}.van-button--hairline{border-width:0;padding-top:1px}.van-button--hairline:after{border-width:1px;border-color:inherit;border-radius:4px}.van-button--hairline.van-button--round:after{border-radius:10em}.van-button--hairline.van-button--square:after{border-radius:0}
...\ No newline at end of file ...\ No newline at end of file
1 import { link } from '../mixins/link';
2 import { VantComponent } from '../common/component';
3 VantComponent({
4 classes: [
5 'num-class',
6 'desc-class',
7 'thumb-class',
8 'title-class',
9 'price-class',
10 'origin-price-class',
11 ],
12 mixins: [link],
13 props: {
14 tag: String,
15 num: String,
16 desc: String,
17 thumb: String,
18 title: String,
19 price: String,
20 centered: Boolean,
21 lazyLoad: Boolean,
22 thumbLink: String,
23 originPrice: String,
24 thumbMode: {
25 type: String,
26 value: 'aspectFit'
27 },
28 currency: {
29 type: String,
30 value: '¥'
31 }
32 },
33 methods: {
34 onClickThumb() {
35 this.jumpLink('thumbLink');
36 }
37 }
38 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-tag": "../tag/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="custom-class van-card">
4 <view class="{{ utils.bem('card__header', { center: centered }) }}">
5 <view class="van-card__thumb" bind:tap="onClickThumb">
6 <image
7 wx:if="{{ thumb }}"
8 src="{{ thumb }}"
9 mode="{{ thumbMode }}"
10 lazy-load="{{ lazyLoad }}"
11 class="van-card__img thumb-class"
12 />
13 <slot name="thumb" />
14 <van-tag
15 wx:if="{{ tag }}"
16 mark
17 type="danger"
18 custom-class="van-card__tag"
19 >
20 {{ tag }}
21 </van-tag>
22 </view>
23
24 <view class="van-card__content">
25 <view wx:if="{{ title }}" class="van-card__title title-class">{{ title }}</view>
26 <slot wx:else name="title" />
27
28 <view wx:if="{{ desc }}" class="van-card__desc desc-class">{{ desc }}</view>
29 <slot wx:else name="desc" />
30
31 <slot name="tags" />
32
33 <view class="van-card__bottom">
34 <view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">{{ currency }} {{ price }}</view>
35 <view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
36 <view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
37 </view>
38 </view>
39 </view>
40
41 <view class="van-card__footer">
42 <slot name="footer" />
43 </view>
44 </view>
1 @import '../common/index.wxss';.van-card{position:relative;padding:5px 15px;font-size:12px;color:#333;background-color:#fafafa;box-sizing:border-box}.van-card__header{display:-webkit-flex;display:flex}.van-card__header--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-card__thumb{position:relative;width:90px;height:90px;margin-right:10px;-webkit-flex:none;flex:none}.van-card__thumb:empty{display:none}.van-card__img{width:100%;height:100%}.van-card__content{position:relative;min-width:0;-webkit-flex:1;flex:1}.van-card__desc,.van-card__title{word-break:break-all}.van-card__title{font-weight:700;line-height:16px}.van-card__desc{color:#7d7e80}.van-card__bottom,.van-card__desc{line-height:20px}.van-card__price{display:inline-block;font-weight:700;color:#f44}.van-card__origin-price{display:inline-block;margin-left:5px;font-size:10px;color:#7d7e80;text-decoration:line-through}.van-card__num{float:right}.van-card__tag{position:absolute;top:2px;left:0}.van-card__footer{width:100%;text-align:right;-webkit-flex:none;flex:none}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 title: String,
5 border: {
6 type: Boolean,
7 value: true
8 }
9 }
10 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <view
2 wx:if="{{ title }}"
3 class="van-cell-group__title"
4 >
5 {{ title }}
6 </view>
7 <view class="custom-class van-cell-group {{ border ? 'van-hairline--top-bottom' : '' }}">
8 <slot />
9 </view>
1 @import '../common/index.wxss';.van-cell-group__title{font-size:14px;padding:15px 15px 5px;color:#999;line-height:16px}
...\ No newline at end of file ...\ No newline at end of file
1 import { link } from '../mixins/link';
2 import { VantComponent } from '../common/component';
3 VantComponent({
4 classes: [
5 'title-class',
6 'label-class',
7 'value-class',
8 'right-icon-class',
9 'hover-class'
10 ],
11 mixins: [link],
12 props: {
13 title: null,
14 value: null,
15 icon: String,
16 size: String,
17 label: String,
18 center: Boolean,
19 isLink: Boolean,
20 required: Boolean,
21 clickable: Boolean,
22 titleWidth: String,
23 customStyle: String,
24 arrowDirection: String,
25 border: {
26 type: Boolean,
27 value: true
28 }
29 },
30 methods: {
31 onClick(event) {
32 this.$emit('click', event.detail);
33 this.jumpLink();
34 }
35 }
36 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ utils.bem('cell', [size, { center, required, borderless: !border, clickable: isLink || clickable }]) }}"
5 hover-class="van-cell--hover hover-class"
6 hover-stay-time="70"
7 style="{{ customStyle }}"
8 bind:tap="onClick"
9 >
10 <van-icon
11 wx:if="{{ icon }}"
12 name="{{ icon }}"
13 class="van-cell__left-icon-wrap"
14 custom-class="van-cell__left-icon"
15 />
16 <slot wx:else name="icon" />
17
18 <view
19 style="{{ titleWidth ? 'max-width:' + titleWidth + ';min-width:' + titleWidth : '' }}"
20 class="van-cell__title title-class"
21 >
22 <block wx:if="{{ title }}">
23 {{ title }}
24 <view wx:if="{{ label }}" class="van-cell__label label-class">{{ label }}</view>
25 </block>
26 <slot wx:else name="title" />
27 </view>
28
29 <view class="van-cell__value value-class">
30 <block wx:if="{{ value || value === 0 }}">{{ value }}</block>
31 <slot wx:else />
32 </view>
33
34 <van-icon
35 wx:if="{{ isLink }}"
36 name="{{ arrowDirection ? 'arrow' + '-' + arrowDirection : 'arrow' }}"
37 class="van-cell__right-icon-wrap right-icon-class"
38 custom-class="van-cell__right-icon"
39 />
40 <slot wx:else name="right-icon" />
41
42 <slot name="extra" />
43 </view>
1 @import '../common/index.wxss';.van-cell{position:relative;display:-webkit-flex;display:flex;width:100%;padding:10px 15px;font-size:14px;line-height:24px;color:#333;background-color:#fff;box-sizing:border-box}.van-cell:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:auto;left:15px;right:0;bottom:0;-webkit-transform:scaleY(.5);transform:scaleY(.5);border-bottom:1px solid #eee}.van-cell--borderless:after{display:none}.van-cell-group{background-color:#fff}.van-cell__label{margin-top:3px;font-size:12px;line-height:18px;color:#999}.van-cell__value{overflow:hidden;color:#999;text-align:right;vertical-align:middle}.van-cell__title,.van-cell__value{-webkit-flex:1;flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{display:-webkit-flex;display:flex;height:24px;font-size:16px;-webkit-align-items:center;align-items:center}.van-cell__left-icon-wrap{margin-right:5px}.van-cell__right-icon-wrap{margin-left:5px;color:#999}.van-cell__left-icon{line-height:24px;vertical-align:middle}.van-cell__right-icon{line-height:24px}.van-cell--clickable.van-cell--hover{background-color:#f2f3f5}.van-cell--required{overflow:visible}.van-cell--required:before{position:absolute;left:7px;font-size:14px;color:#f44;content:"*"}.van-cell--center{-webkit-align-items:center;align-items:center}.van-cell--large{padding-top:12px;padding-bottom:12px}.van-cell--large .van-cell__title{font-size:16px}.van-cell--large .van-cell__label{font-size:14px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 relation: {
5 name: 'checkbox',
6 type: 'descendant',
7 linked(target) {
8 const { value, disabled } = this.data;
9 target.set({
10 value: value.indexOf(target.data.name) !== -1,
11 disabled: disabled || target.data.disabled
12 });
13 }
14 },
15 props: {
16 max: Number,
17 value: Array,
18 disabled: Boolean
19 },
20 watch: {
21 value(value) {
22 const children = this.getRelationNodes('../checkbox/index');
23 children.forEach(child => {
24 child.set({ value: value.indexOf(child.data.name) !== -1 });
25 });
26 },
27 disabled(disabled) {
28 const children = this.getRelationNodes('../checkbox/index');
29 children.forEach(child => {
30 child.set({ disabled: disabled || child.data.disabled });
31 });
32 }
33 }
34 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 @import '../common/index.wxss';
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 relation: {
5 name: 'checkbox-group',
6 type: 'ancestor'
7 },
8 classes: ['icon-class', 'label-class'],
9 props: {
10 value: null,
11 disabled: Boolean,
12 useIconSlot: Boolean,
13 checkedColor: String,
14 labelPosition: String,
15 labelDisabled: Boolean,
16 shape: {
17 type: String,
18 value: 'round'
19 }
20 },
21 methods: {
22 emitChange(value) {
23 const parent = this.getRelationNodes('../checkbox-group/index')[0];
24 if (parent) {
25 this.setParentValue(parent, value);
26 }
27 else {
28 this.$emit('input', value);
29 this.$emit('change', value);
30 }
31 },
32 toggle() {
33 if (!this.data.disabled) {
34 this.emitChange(!this.data.value);
35 }
36 },
37 onClickLabel() {
38 if (!this.data.disabled && !this.data.labelDisabled) {
39 this.emitChange(!this.data.value);
40 }
41 },
42 setParentValue(parent, value) {
43 const parentValue = parent.data.value.slice();
44 const { name } = this.data;
45 if (value) {
46 if (parent.data.max && parentValue.length >= parent.data.max) {
47 return;
48 }
49 /* istanbul ignore else */
50 if (parentValue.indexOf(name) === -1) {
51 parentValue.push(name);
52 parent.$emit('input', parentValue);
53 parent.$emit('change', parentValue);
54 }
55 }
56 else {
57 const index = parentValue.indexOf(name);
58 /* istanbul ignore else */
59 if (index !== -1) {
60 parentValue.splice(index, 1);
61 parent.$emit('input', parentValue);
62 parent.$emit('change', parentValue);
63 }
64 }
65 }
66 }
67 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="van-checkbox custom-class">
4 <view class="van-checkbox__icon-wrap" bindtap="toggle">
5 <slot wx:if="{{ useIconSlot }}" name="icon" />
6 <van-icon
7 wx:else
8 name="success"
9 class="{{ utils.bem('checkbox__icon', [shape, { disabled, checked: value }]) }}"
10 style="{{ checkedColor && value && !disabled ? 'border-color:' + checkedColor + '; background-color:' + checkedColor : '' }}"
11 custom-class="icon-class"
12 custom-style="line-height: 20px;"
13 />
14 </view>
15 <view class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled }]) }}" bindtap="onClickLabel">
16 <slot />
17 </view>
18 </view>
1 @import '../common/index.wxss';.van-checkbox{overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox__icon-wrap,.van-checkbox__label{display:inline-block;line-height:20px;vertical-align:middle}.van-checkbox__icon{display:block;font-size:14px;width:20px;height:20px;color:transparent;text-align:center;box-sizing:border-box;border:1px solid #e5e5e5;transition:.2s}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;border-color:#1989fa;background-color:#1989fa}.van-checkbox__icon--disabled{border-color:#c9c9c9;background-color:#eee}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c9c9c9}.van-checkbox__label{color:#333;margin-left:10px}.van-checkbox__label--left{float:left;margin:0 10px 0 0}.van-checkbox__label--disabled{color:#c9c9c9}.van-checkbox__label:empty{margin:0}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 relation: {
4 name: 'row',
5 type: 'ancestor'
6 },
7 props: {
8 span: Number,
9 offset: Number
10 },
11 data: {
12 style: ''
13 },
14 methods: {
15 setGutter(gutter) {
16 const padding = `${gutter / 2}px`;
17 const style = gutter ? `padding-left: ${padding}; padding-right: ${padding};` : '';
18 if (style !== this.data.style) {
19 this.set({ style });
20 }
21 }
22 }
23 });
1 {
2 "component": true
3 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ utils.bem('col', [span]) }} {{ offset ? 'van-col--offset-' + offset : '' }}"
5 style="{{ style }}"
6 >
7 <slot />
8 </view>
1 @import '../common/index.wxss';.van-col{float:left;box-sizing:border-box}.van-col--1{width:4.16666667%}.van-col--offset-1{margin-left:4.16666667%}.van-col--2{width:8.33333333%}.van-col--offset-2{margin-left:8.33333333%}.van-col--3{width:12.5%}.van-col--offset-3{margin-left:12.5%}.van-col--4{width:16.66666667%}.van-col--offset-4{margin-left:16.66666667%}.van-col--5{width:20.83333333%}.van-col--offset-5{margin-left:20.83333333%}.van-col--6{width:25%}.van-col--offset-6{margin-left:25%}.van-col--7{width:29.16666667%}.van-col--offset-7{margin-left:29.16666667%}.van-col--8{width:33.33333333%}.van-col--offset-8{margin-left:33.33333333%}.van-col--9{width:37.5%}.van-col--offset-9{margin-left:37.5%}.van-col--10{width:41.66666667%}.van-col--offset-10{margin-left:41.66666667%}.van-col--11{width:45.83333333%}.van-col--offset-11{margin-left:45.83333333%}.van-col--12{width:50%}.van-col--offset-12{margin-left:50%}.van-col--13{width:54.16666667%}.van-col--offset-13{margin-left:54.16666667%}.van-col--14{width:58.33333333%}.van-col--offset-14{margin-left:58.33333333%}.van-col--15{width:62.5%}.van-col--offset-15{margin-left:62.5%}.van-col--16{width:66.66666667%}.van-col--offset-16{margin-left:66.66666667%}.van-col--17{width:70.83333333%}.van-col--offset-17{margin-left:70.83333333%}.van-col--18{width:75%}.van-col--offset-18{margin-left:75%}.van-col--19{width:79.16666667%}.van-col--offset-19{margin-left:79.16666667%}.van-col--20{width:83.33333333%}.van-col--offset-20{margin-left:83.33333333%}.van-col--21{width:87.5%}.van-col--offset-21{margin-left:87.5%}.van-col--22{width:91.66666667%}.van-col--offset-22{margin-left:91.66666667%}.van-col--23{width:95.83333333%}.van-col--offset-23{margin-left:95.83333333%}.van-col--24{width:100%}.van-col--offset-24{margin-left:100%}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 const nextTick = () => new Promise(resolve => setTimeout(resolve, 20));
3 VantComponent({
4 classes: ['title-class', 'content-class'],
5 relation: {
6 name: 'collapse',
7 type: 'ancestor',
8 linked(parent) {
9 this.parent = parent;
10 }
11 },
12 props: {
13 name: null,
14 title: null,
15 value: null,
16 icon: String,
17 label: String,
18 disabled: Boolean,
19 border: {
20 type: Boolean,
21 value: true
22 },
23 isLink: {
24 type: Boolean,
25 value: true
26 }
27 },
28 data: {
29 contentHeight: 0,
30 expanded: false,
31 transition: false
32 },
33 mounted() {
34 this.updateExpanded()
35 .then(nextTick)
36 .then(() => {
37 this.set({ transition: true });
38 });
39 },
40 methods: {
41 updateExpanded() {
42 if (!this.parent) {
43 return Promise.resolve();
44 }
45 const { value, accordion } = this.parent.data;
46 const { children = [] } = this.parent;
47 const { name } = this.data;
48 const index = children.indexOf(this);
49 const currentName = name == null ? index : name;
50 const expanded = accordion
51 ? value === currentName
52 : (value || []).some((name) => name === currentName);
53 const stack = [];
54 if (expanded !== this.data.expanded) {
55 stack.push(this.updateStyle(expanded));
56 }
57 stack.push(this.set({ index, expanded }));
58 return Promise.all(stack);
59 },
60 updateStyle(expanded) {
61 return this.getRect('.van-collapse-item__content')
62 .then((rect) => rect.height)
63 .then((height) => {
64 if (expanded) {
65 return this.set({
66 contentHeight: height ? `${height}px` : 'auto'
67 });
68 }
69 else {
70 return this.set({ contentHeight: `${height}px` })
71 .then(nextTick)
72 .then(() => this.set({ contentHeight: 0 }));
73 }
74 });
75 },
76 onClick() {
77 if (this.data.disabled) {
78 return;
79 }
80 const { name, expanded } = this.data;
81 const index = this.parent.children.indexOf(this);
82 const currentName = name == null ? index : name;
83 this.parent.switch(currentName, !expanded);
84 },
85 onTransitionEnd() {
86 if (this.data.expanded) {
87 this.set({
88 contentHeight: 'auto'
89 });
90 }
91 }
92 }
93 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-cell": "../cell/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="van-collapse-item custom-class {{ index !== 0 ? 'van-hairline--top' : '' }}">
4 <van-cell
5 title="{{ title }}"
6 title-class="title-class"
7 icon="{{ icon }}"
8 is-link="{{ isLink }}"
9 value="{{ value }}"
10 label="{{ label }}"
11 border="{{ border && expanded }}"
12 class="{{ utils.bem('collapse-item__title', { disabled, expanded }) }}"
13 right-icon-class="van-cell__right-icon"
14 custom-class="van-cell"
15 hover-class="van-cell--hover"
16 bind:click="onClick"
17 >
18 <slot
19 name="title"
20 slot="title"
21 />
22 <slot
23 name="icon"
24 slot="icon"
25 />
26 <slot name="value" />
27 <slot
28 name="right-icon"
29 slot="right-icon"
30 />
31 </van-cell>
32 <view
33 class="{{ utils.bem('collapse-item__wrapper', { transition }) }}"
34 style="height: {{ contentHeight }};"
35 bind:transitionend="onTransitionEnd"
36 >
37 <view
38 class="van-collapse-item__content content-class"
39 >
40 <slot />
41 </view>
42 </view>
43 </view>
1 @import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{-webkit-transform:rotate(90deg);transform:rotate(90deg);transition:.3s}.van-collapse-item__title--expanded .van-cell__right-icon{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:#c9c9c9!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__wrapper--transition{transition:height .3s ease-in-out}.van-collapse-item__content{padding:15px;font-size:13px;line-height:1.5;color:#999;background-color:#fff}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 relation: {
4 name: 'collapse-item',
5 type: 'descendant',
6 linked(child) {
7 this.children.push(child);
8 }
9 },
10 props: {
11 value: {
12 type: null,
13 observer: 'updateExpanded'
14 },
15 accordion: {
16 type: Boolean,
17 observer: 'updateExpanded'
18 },
19 border: {
20 type: Boolean,
21 value: true
22 }
23 },
24 beforeCreate() {
25 this.children = [];
26 },
27 methods: {
28 updateExpanded() {
29 this.children.forEach((child) => {
30 child.updateExpanded();
31 });
32 },
33 switch(name, expanded) {
34 const { accordion, value } = this.data;
35 if (!accordion) {
36 name = expanded
37 ? (value || []).concat(name)
38 : (value || []).filter((activeName) => activeName !== name);
39 }
40 else {
41 name = expanded ? name : '';
42 }
43 this.$emit('change', name);
44 this.$emit('input', name);
45 }
46 }
47 });
1 <view class="custom-class van-collapse {{ border ? 'van-hairline--top-bottom' : '' }}">
2 <slot />
3 </view>
1 @import '../common/index.wxss';
...\ No newline at end of file ...\ No newline at end of file
1 export declare const RED = "#f44";
2 export declare const BLUE = "#1989fa";
3 export declare const GREEN = "#07c160";
1 export const RED = '#f44';
2 export const BLUE = '#1989fa';
3 export const GREEN = '#07c160';
1 declare function VantComponent<Data, Props, Watch, Methods, Computed>(vantOptions?: VantComponentOptions<Data, Props, Watch, Methods, Computed, CombinedComponentInstance<Data, Props, Watch, Methods, Computed>>): void;
2 export { VantComponent };
1 import { basic } from '../mixins/basic';
2 import { observe } from '../mixins/observer/index';
3 function mapKeys(source, target, map) {
4 Object.keys(map).forEach(key => {
5 if (source[key]) {
6 target[map[key]] = source[key];
7 }
8 });
9 }
10 function VantComponent(vantOptions = {}) {
11 const options = {};
12 mapKeys(vantOptions, options, {
13 data: 'data',
14 props: 'properties',
15 mixins: 'behaviors',
16 methods: 'methods',
17 beforeCreate: 'created',
18 created: 'attached',
19 mounted: 'ready',
20 relations: 'relations',
21 destroyed: 'detached',
22 classes: 'externalClasses'
23 });
24 const { relation } = vantOptions;
25 if (relation) {
26 options.relations = Object.assign(options.relations || {}, {
27 [`../${relation.name}/index`]: relation
28 });
29 }
30 // add default externalClasses
31 options.externalClasses = options.externalClasses || [];
32 options.externalClasses.push('custom-class');
33 // add default behaviors
34 options.behaviors = options.behaviors || [];
35 options.behaviors.push(basic);
36 // map field to form-field behavior
37 if (vantOptions.field) {
38 options.behaviors.push('wx://form-field');
39 }
40 // add default options
41 options.options = {
42 multipleSlots: true,
43 addGlobalClass: true
44 };
45 observe(vantOptions, options);
46 Component(options);
47 }
48 export { VantComponent };
1 .van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{content:"";display:table;clear:both}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);border:0 solid #eee}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
...\ No newline at end of file ...\ No newline at end of file
1 .van-clearfix:after{content:"";display:table;clear:both}
...\ No newline at end of file ...\ No newline at end of file
1 .van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}
...\ No newline at end of file ...\ No newline at end of file
1 .van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);border:0 solid #eee}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
...\ No newline at end of file ...\ No newline at end of file
1 declare function isDef(value: any): boolean;
2 declare function isObj(x: any): boolean;
3 declare function isNumber(value: any): boolean;
4 declare function range(num: number, min: number, max: number): number;
5 export { isObj, isDef, isNumber, range };
1 function isDef(value) {
2 return value !== undefined && value !== null;
3 }
4 function isObj(x) {
5 const type = typeof x;
6 return x !== null && (type === 'object' || type === 'function');
7 }
8 function isNumber(value) {
9 return /^\d+$/.test(value);
10 }
11 function range(num, min, max) {
12 return Math.min(Math.max(num, min), max);
13 }
14 export { isObj, isDef, isNumber, range };
1 import { VantComponent } from '../common/component';
2 import { isDef } from '../common/utils';
3 const currentYear = new Date().getFullYear();
4 function isValidDate(date) {
5 return isDef(date) && !isNaN(new Date(date).getTime());
6 }
7 function range(num, min, max) {
8 return Math.min(Math.max(num, min), max);
9 }
10 function padZero(val) {
11 return `00${val}`.slice(-2);
12 }
13 function times(n, iteratee) {
14 let index = -1;
15 const result = Array(n);
16 while (++index < n) {
17 result[index] = iteratee(index);
18 }
19 return result;
20 }
21 function getTrueValue(formattedValue) {
22 if (!formattedValue)
23 return;
24 while (isNaN(parseInt(formattedValue, 10))) {
25 formattedValue = formattedValue.slice(1);
26 }
27 return parseInt(formattedValue, 10);
28 }
29 function getMonthEndDay(year, month) {
30 return 32 - new Date(year, month - 1, 32).getDate();
31 }
32 VantComponent({
33 props: {
34 value: null,
35 title: String,
36 loading: Boolean,
37 itemHeight: {
38 type: Number,
39 value: 44
40 },
41 visibleItemCount: {
42 type: Number,
43 value: 5
44 },
45 confirmButtonText: {
46 type: String,
47 value: '确认'
48 },
49 cancelButtonText: {
50 type: String,
51 value: '取消'
52 },
53 type: {
54 type: String,
55 value: 'datetime'
56 },
57 showToolbar: {
58 type: Boolean,
59 value: true
60 },
61 minDate: {
62 type: Number,
63 value: new Date(currentYear - 10, 0, 1).getTime()
64 },
65 maxDate: {
66 type: Number,
67 value: new Date(currentYear + 10, 11, 31).getTime()
68 },
69 minHour: {
70 type: Number,
71 value: 0
72 },
73 maxHour: {
74 type: Number,
75 value: 23
76 },
77 minMinute: {
78 type: Number,
79 value: 0
80 },
81 maxMinute: {
82 type: Number,
83 value: 59
84 }
85 },
86 data: {
87 innerValue: Date.now(),
88 columns: []
89 },
90 watch: {
91 value(val) {
92 const { data } = this;
93 val = this.correctValue(val);
94 const isEqual = val === data.innerValue;
95 if (!isEqual) {
96 this.updateColumnValue(val).then(() => {
97 this.$emit('input', val);
98 });
99 }
100 },
101 type: 'updateColumns',
102 minHour: 'updateColumns',
103 maxHour: 'updateColumns',
104 minMinute: 'updateColumns',
105 maxMinute: 'updateColumns'
106 },
107 methods: {
108 getPicker() {
109 if (this.picker == null) {
110 const picker = this.picker = this.selectComponent('.van-datetime-picker');
111 const { setColumnValues } = picker;
112 picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]);
113 }
114 return this.picker;
115 },
116 updateColumns() {
117 const results = this.getRanges().map(({ type, range }, index) => {
118 const values = times(range[1] - range[0] + 1, index => {
119 let value = range[0] + index;
120 value = type === 'year' ? `${value}` : padZero(value);
121 return value;
122 });
123 return { values };
124 });
125 return this.set({ columns: results });
126 },
127 getRanges() {
128 const { data } = this;
129 if (data.type === 'time') {
130 return [
131 {
132 type: 'hour',
133 range: [data.minHour, data.maxHour]
134 },
135 {
136 type: 'minute',
137 range: [data.minMinute, data.maxMinute]
138 }
139 ];
140 }
141 const { maxYear, maxDate, maxMonth, maxHour, maxMinute } = this.getBoundary('max', data.innerValue);
142 const { minYear, minDate, minMonth, minHour, minMinute } = this.getBoundary('min', data.innerValue);
143 const result = [
144 {
145 type: 'year',
146 range: [minYear, maxYear]
147 },
148 {
149 type: 'month',
150 range: [minMonth, maxMonth]
151 },
152 {
153 type: 'day',
154 range: [minDate, maxDate]
155 },
156 {
157 type: 'hour',
158 range: [minHour, maxHour]
159 },
160 {
161 type: 'minute',
162 range: [minMinute, maxMinute]
163 }
164 ];
165 if (data.type === 'date')
166 result.splice(3, 2);
167 if (data.type === 'year-month')
168 result.splice(2, 3);
169 return result;
170 },
171 correctValue(value) {
172 const { data } = this;
173 // validate value
174 const isDateType = data.type !== 'time';
175 if (isDateType && !isValidDate(value)) {
176 value = data.minDate;
177 }
178 else if (!isDateType && !value) {
179 const { minHour } = data;
180 value = `${padZero(minHour)}:00`;
181 }
182 // time type
183 if (!isDateType) {
184 let [hour, minute] = value.split(':');
185 hour = padZero(range(hour, data.minHour, data.maxHour));
186 minute = padZero(range(minute, data.minMinute, data.maxMinute));
187 return `${hour}:${minute}`;
188 }
189 // date type
190 value = Math.max(value, data.minDate);
191 value = Math.min(value, data.maxDate);
192 return value;
193 },
194 getBoundary(type, innerValue) {
195 const value = new Date(innerValue);
196 const boundary = new Date(this.data[`${type}Date`]);
197 const year = boundary.getFullYear();
198 let month = 1;
199 let date = 1;
200 let hour = 0;
201 let minute = 0;
202 if (type === 'max') {
203 month = 12;
204 date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1);
205 hour = 23;
206 minute = 59;
207 }
208 if (value.getFullYear() === year) {
209 month = boundary.getMonth() + 1;
210 if (value.getMonth() + 1 === month) {
211 date = boundary.getDate();
212 if (value.getDate() === date) {
213 hour = boundary.getHours();
214 if (value.getHours() === hour) {
215 minute = boundary.getMinutes();
216 }
217 }
218 }
219 }
220 return {
221 [`${type}Year`]: year,
222 [`${type}Month`]: month,
223 [`${type}Date`]: date,
224 [`${type}Hour`]: hour,
225 [`${type}Minute`]: minute
226 };
227 },
228 onCancel() {
229 this.$emit('cancel');
230 },
231 onConfirm() {
232 this.$emit('confirm', this.data.innerValue);
233 },
234 onChange() {
235 const { data } = this;
236 let value;
237 const picker = this.getPicker();
238 if (data.type === 'time') {
239 const indexes = picker.getIndexes();
240 value = `${indexes[0] + data.minHour}:${indexes[1] + data.minMinute}`;
241 }
242 else {
243 const values = picker.getValues();
244 const year = getTrueValue(values[0]);
245 const month = getTrueValue(values[1]);
246 const maxDate = getMonthEndDay(year, month);
247 let date = getTrueValue(values[2]);
248 if (data.type === 'year-month') {
249 date = 1;
250 }
251 date = date > maxDate ? maxDate : date;
252 let hour = 0;
253 let minute = 0;
254 if (data.type === 'datetime') {
255 hour = getTrueValue(values[3]);
256 minute = getTrueValue(values[4]);
257 }
258 value = new Date(year, month - 1, date, hour, minute);
259 }
260 value = this.correctValue(value);
261 this.updateColumnValue(value).then(() => {
262 this.$emit('input', value);
263 this.$emit('change', picker);
264 });
265 },
266 updateColumnValue(value) {
267 let values = [];
268 const { data } = this;
269 const picker = this.getPicker();
270 if (data.type === 'time') {
271 const pair = value.split(':');
272 values = [pair[0], pair[1]];
273 }
274 else {
275 const date = new Date(value);
276 values = [`${date.getFullYear()}`, padZero(date.getMonth() + 1)];
277 if (data.type === 'date') {
278 values.push(padZero(date.getDate()));
279 }
280 if (data.type === 'datetime') {
281 values.push(padZero(date.getDate()), padZero(date.getHours()), padZero(date.getMinutes()));
282 }
283 }
284 return this.set({ innerValue: value })
285 .then(() => this.updateColumns())
286 .then(() => picker.setValues(values));
287 }
288 },
289 created() {
290 const innerValue = this.correctValue(this.data.value);
291 this.updateColumnValue(innerValue).then(() => {
292 this.$emit('input', innerValue);
293 });
294 }
295 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-picker": "../picker/index"
5 }
6 }
1 <van-picker
2 class="van-datetime-picker"
3 title="{{ title }}"
4 columns="{{ columns }}"
5 item-height="{{ itemHeight }}"
6 show-toolbar="{{ showToolbar }}"
7 visible-item-count="{{ visibleItemCount }}"
8 confirm-button-text="{{ confirmButtonText }}"
9 cancel-button-text="{{ cancelButtonText }}"
10 bind:change="onChange"
11 bind:confirm="onConfirm"
12 bind:cancel="onCancel"
13 />
1 @import '../common/index.wxss';
...\ No newline at end of file ...\ No newline at end of file
1 declare type DialogAction = 'confirm' | 'cancel';
2 declare type DialogOptions = {
3 lang?: string;
4 show?: boolean;
5 title?: string;
6 zIndex?: number;
7 context?: any;
8 message?: string;
9 overlay?: boolean;
10 selector?: string;
11 ariaLabel?: string;
12 transition?: string;
13 asyncClose?: boolean;
14 businessId?: number;
15 sessionFrom?: string;
16 appParameter?: string;
17 messageAlign?: string;
18 sendMessageImg?: string;
19 showMessageCard?: boolean;
20 sendMessagePath?: string;
21 sendMessageTitle?: string;
22 confirmButtonText?: string;
23 cancelButtonText?: string;
24 showConfirmButton?: boolean;
25 showCancelButton?: boolean;
26 closeOnClickOverlay?: boolean;
27 confirmButtonOpenType?: string;
28 };
29 interface Dialog {
30 (options: DialogOptions): Promise<DialogAction>;
31 alert?: (options: DialogOptions) => Promise<DialogAction>;
32 confirm?: (options: DialogOptions) => Promise<DialogAction>;
33 close?: () => void;
34 stopLoading?: () => void;
35 install?: () => void;
36 setDefaultOptions?: (options: DialogOptions) => void;
37 resetDefaultOptions?: () => void;
38 defaultOptions?: DialogOptions;
39 currentOptions?: DialogOptions;
40 }
41 declare const Dialog: Dialog;
42 export default Dialog;
1 let queue = [];
2 function getContext() {
3 const pages = getCurrentPages();
4 return pages[pages.length - 1];
5 }
6 const Dialog = options => {
7 options = Object.assign({}, Dialog.currentOptions, options);
8 return new Promise((resolve, reject) => {
9 const context = options.context || getContext();
10 const dialog = context.selectComponent(options.selector);
11 delete options.selector;
12 if (dialog) {
13 dialog.set(Object.assign({ onCancel: reject, onConfirm: resolve }, options));
14 queue.push(dialog);
15 }
16 else {
17 console.warn('未找到 van-dialog 节点,请确认 selector 及 context 是否正确');
18 }
19 });
20 };
21 Dialog.defaultOptions = {
22 show: true,
23 title: '',
24 message: '',
25 zIndex: 100,
26 overlay: true,
27 asyncClose: false,
28 messageAlign: '',
29 transition: 'scale',
30 selector: '#van-dialog',
31 confirmButtonText: '确认',
32 cancelButtonText: '取消',
33 showConfirmButton: true,
34 showCancelButton: false,
35 closeOnClickOverlay: false,
36 confirmButtonOpenType: ''
37 };
38 Dialog.alert = Dialog;
39 Dialog.confirm = options => Dialog(Object.assign({ showCancelButton: true }, options));
40 Dialog.close = () => {
41 queue.forEach(dialog => {
42 dialog.close();
43 });
44 queue = [];
45 };
46 Dialog.stopLoading = () => {
47 queue.forEach(dialog => {
48 dialog.stopLoading();
49 });
50 };
51 Dialog.setDefaultOptions = options => {
52 Object.assign(Dialog.currentOptions, options);
53 };
54 Dialog.resetDefaultOptions = () => {
55 Dialog.currentOptions = Object.assign({}, Dialog.defaultOptions);
56 };
57 Dialog.resetDefaultOptions();
58 export default Dialog;
1 import { VantComponent } from '../common/component';
2 import { button } from '../mixins/button';
3 import { openType } from '../mixins/open-type';
4 VantComponent({
5 mixins: [button, openType],
6 props: {
7 show: Boolean,
8 title: String,
9 message: String,
10 useSlot: Boolean,
11 asyncClose: Boolean,
12 messageAlign: String,
13 showCancelButton: Boolean,
14 closeOnClickOverlay: Boolean,
15 confirmButtonOpenType: String,
16 zIndex: {
17 type: Number,
18 value: 2000
19 },
20 confirmButtonText: {
21 type: String,
22 value: '确认'
23 },
24 cancelButtonText: {
25 type: String,
26 value: '取消'
27 },
28 showConfirmButton: {
29 type: Boolean,
30 value: true
31 },
32 overlay: {
33 type: Boolean,
34 value: true
35 },
36 transition: {
37 type: String,
38 value: 'scale'
39 }
40 },
41 data: {
42 loading: {
43 confirm: false,
44 cancel: false
45 }
46 },
47 watch: {
48 show(show) {
49 !show && this.stopLoading();
50 }
51 },
52 methods: {
53 onConfirm() {
54 this.handleAction('confirm');
55 },
56 onCancel() {
57 this.handleAction('cancel');
58 },
59 onClickOverlay() {
60 this.onClose('overlay');
61 },
62 handleAction(action) {
63 if (this.data.asyncClose) {
64 this.set({
65 [`loading.${action}`]: true
66 });
67 }
68 this.onClose(action);
69 },
70 close() {
71 this.set({
72 show: false
73 });
74 },
75 stopLoading() {
76 this.set({
77 loading: {
78 confirm: false,
79 cancel: false
80 }
81 });
82 },
83 onClose(action) {
84 if (!this.data.asyncClose) {
85 this.close();
86 }
87 this.$emit('close', action);
88 //把 dialog 实例传递出去,可以通过 stopLoading() 在外部关闭按钮的 loading
89 this.$emit(action, { dialog: this });
90 const callback = this.data[action === 'confirm' ? 'onConfirm' : 'onCancel'];
91 if (callback) {
92 callback(this);
93 }
94 }
95 }
96 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-popup": "../popup/index",
5 "van-button": "../button/index"
6 }
7 }
1 <van-popup
2 show="{{ show }}"
3 z-index="{{ zIndex }}"
4 overlay="{{ overlay }}"
5 custom-class="van-dialog"
6 transition="{{ transition }}"
7 close-on-click-overlay="{{ closeOnClickOverlay }}"
8 bind:close="onClickOverlay"
9 >
10 <view
11 wx:if="{{ title }}"
12 class="van-dialog__header {{ message || useSlot ? '' : 'van-dialog--isolated' }}"
13 >
14 {{ title }}
15 </view>
16
17 <slot wx:if="{{ useSlot }}" />
18 <view
19 wx:elif="{{ message }}"
20 class="van-dialog__message {{ title ? 'van-dialog__message--has-title' : '' }} {{ messageAlign ? 'van-dialog__message--' + messageAlign : '' }}"
21 >
22 <text>{{ message }}</text>
23 </view>
24
25 <view class="van-hairline--top van-dialog__footer">
26 <van-button
27 wx:if="{{ showCancelButton }}"
28 size="large"
29 loading="{{ loading.cancel }}"
30 class="van-dialog__button van-hairline--right"
31 custom-class="van-dialog__cancel"
32 bind:click="onCancel"
33 >
34 {{ cancelButtonText }}
35 </van-button>
36 <van-button
37 wx:if="{{ showConfirmButton }}"
38 size="large"
39 class="van-dialog__button"
40 loading="{{ loading.confirm }}"
41 custom-class="van-dialog__confirm"
42
43 open-type="{{ confirmButtonOpenType }}"
44 lang="{{ lang }}"
45 business-id="{{ businessId }}"
46 session-from="{{ sessionFrom }}"
47 send-message-title="{{ sendMessageTitle }}"
48 send-message-path="{{ sendMessagePath }}"
49 send-message-img="{{ sendMessageImg }}"
50 show-message-card="{{ showMessageCard }}"
51 app-parameter="{{ appParameter }}"
52
53 bind:click="onConfirm"
54 bindgetuserinfo="bindGetUserInfo"
55 bindcontact="bindContact"
56 bindgetphonenumber="bindGetPhoneNumber"
57 binderror="bindError"
58 bindlaunchapp="bindLaunchApp"
59 bindopensetting="bindOpenSetting"
60 >
61 {{ confirmButtonText }}
62 </van-button>
63 </view>
64 </van-popup>
1 @import '../common/index.wxss';.van-dialog{width:85%;overflow:hidden;font-size:16px;background-color:#fff;border-radius:4px}.van-dialog__header{padding-top:25px;font-weight:500;text-align:center}.van-dialog__header--isolated{padding:25px 0}.van-dialog__message{max-height:60vh;padding:25px;overflow-y:auto;font-size:14px;line-height:1.5;text-align:center;-webkit-overflow-scrolling:touch}.van-dialog__message--has-title{padding-top:12px;color:#7d7e80}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__footer{display:-webkit-flex;display:flex}.van-dialog__button{-webkit-flex:1;flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog__confirm{color:#1989fa!important}.van-dialog-bounce-enter{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7)}.van-dialog-bounce-leave-active{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.9);transform:translate3d(-50%,-50%,0) scale(.9)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 classes: ['input-class'],
5 props: {
6 size: String,
7 icon: String,
8 label: String,
9 error: Boolean,
10 fixed: Boolean,
11 focus: Boolean,
12 center: Boolean,
13 isLink: Boolean,
14 leftIcon: String,
15 disabled: Boolean,
16 autosize: Boolean,
17 readonly: Boolean,
18 required: Boolean,
19 iconClass: String,
20 clearable: Boolean,
21 inputAlign: String,
22 errorMessageAlign: String,
23 customClass: String,
24 confirmType: String,
25 confirmHold: Boolean,
26 errorMessage: String,
27 placeholder: String,
28 customStyle: String,
29 useIconSlot: Boolean,
30 useButtonSlot: Boolean,
31 showConfirmBar: {
32 type: Boolean,
33 value: true
34 },
35 placeholderStyle: String,
36 adjustPosition: {
37 type: Boolean,
38 value: true
39 },
40 cursorSpacing: {
41 type: Number,
42 value: 50
43 },
44 maxlength: {
45 type: Number,
46 value: -1
47 },
48 type: {
49 type: String,
50 value: 'text'
51 },
52 border: {
53 type: Boolean,
54 value: true
55 },
56 titleWidth: {
57 type: String,
58 value: '90px'
59 }
60 },
61 data: {
62 showClear: false
63 },
64 beforeCreate() {
65 this.focused = false;
66 },
67 methods: {
68 onInput(event) {
69 const { value = '' } = event.detail || {};
70 this.set({
71 value,
72 showClear: this.getShowClear(value)
73 }, () => {
74 this.emitChange(value);
75 });
76 },
77 onFocus(event) {
78 const { value = '', height = 0 } = event.detail || {};
79 this.$emit('focus', { value, height });
80 this.focused = true;
81 this.blurFromClear = false;
82 this.set({
83 showClear: this.getShowClear()
84 });
85 },
86 onBlur(event) {
87 const { value = '', cursor = 0 } = event.detail || {};
88 this.$emit('blur', { value, cursor });
89 this.focused = false;
90 const showClear = this.getShowClear();
91 if (this.data.value === value) {
92 this.set({
93 showClear
94 });
95 }
96 else if (!this.blurFromClear) {
97 // fix: the handwritten keyboard does not trigger input change
98 this.set({
99 value,
100 showClear
101 }, () => {
102 this.emitChange(value);
103 });
104 }
105 },
106 onClickIcon() {
107 this.$emit('click-icon');
108 },
109 getShowClear(value) {
110 value = value === undefined ? this.data.value : value;
111 return (this.data.clearable && this.focused && value && !this.data.readonly);
112 },
113 onClear() {
114 this.blurFromClear = true;
115 this.set({
116 value: '',
117 showClear: this.getShowClear('')
118 }, () => {
119 this.emitChange('');
120 this.$emit('clear', '');
121 });
122 },
123 onConfirm() {
124 this.$emit('confirm', this.data.value);
125 },
126 emitChange(value) {
127 this.$emit('input', value);
128 this.$emit('change', value);
129 }
130 }
131 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-cell": "../cell/index",
5 "van-icon": "../icon/index"
6 }
7 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <van-cell
4 icon="{{ leftIcon }}"
5 title="{{ label }}"
6 center="{{ center }}"
7 border="{{ border }}"
8 is-link="{{ isLink }}"
9 required="{{ required }}"
10 custom-style="{{ customStyle }}"
11 title-width="{{ titleWidth }}"
12 custom-class="van-field"
13 size="{{ size }}"
14 >
15 <slot name="left-icon" slot="icon" />
16 <slot name="label" slot="title" />
17 <view class="van-field__body {{ type === 'textarea' ? 'van-field__body--textarea' : '' }}">
18 <textarea
19 wx:if="{{ type === 'textarea' }}"
20 class="input-class {{ utils.bem('field__input', [inputAlign, { disabled, error }]) }}"
21 fixed="{{ fixed }}"
22 focus="{{ focus }}"
23 value="{{ value }}"
24 disabled="{{ disabled || readonly }}"
25 maxlength="{{ maxlength }}"
26 auto-height="{{ autosize }}"
27 placeholder="{{ placeholder }}"
28 placeholder-style="{{ placeholderStyle }}"
29 placeholder-class="{{ error ? 'van-field__input--error' : 'van-field__placeholder' }}"
30 cursor-spacing="{{ cursorSpacing }}"
31 adjust-position="{{ adjustPosition }}"
32 show-confirm-bar="{{ showConfirmBar }}"
33 bindinput="onInput"
34 bind:blur="onBlur"
35 bind:focus="onFocus"
36 bind:confirm="onConfirm"
37 />
38 <input
39 wx:else
40 class="input-class {{ utils.bem('field__input', [inputAlign, { disabled, error }]) }}"
41 type="{{ type }}"
42 focus="{{ focus }}"
43 value="{{ value }}"
44 disabled="{{ disabled || readonly }}"
45 maxlength="{{ maxlength }}"
46 placeholder="{{ placeholder }}"
47 placeholder-style="{{ placeholderStyle }}"
48 placeholder-class="{{ error ? 'van-field__input--error' : 'van-field__placeholder' }}"
49 confirm-type="{{ confirmType }}"
50 confirm-hold="{{ confirmHold }}"
51 cursor-spacing="{{ cursorSpacing }}"
52 adjust-position="{{ adjustPosition }}"
53 bindinput="onInput"
54 bind:blur="onBlur"
55 bind:focus="onFocus"
56 bind:confirm="onConfirm"
57 />
58 <van-icon
59 wx:if="{{ showClear }}"
60 size="16px"
61 name="clear"
62 class="van-field__clear-root"
63 custom-class="van-field__clear"
64 bind:touchstart="onClear"
65 />
66 <view class="van-field__icon-container" wx:if="{{ icon || useIconSlot }}" bind:tap="onClickIcon">
67 <van-icon
68 wx:if="{{ icon }}"
69 size="16px"
70 name="{{ icon }}"
71 custom-class="van-field__icon {{ iconClass }}"
72 />
73 <slot wx:else name="icon" />
74 </view>
75 <view wx:if="{{ useButtonSlot }}" class="van-field__button">
76 <slot name="button" />
77 </view>
78 </view>
79 <view wx:if="{{ errorMessage }}" class="van-field__error-message {{ utils.bem('field__error', [errorMessageAlign, { disabled, error }]) }}">
80 {{ errorMessage }}
81 </view>
82 </van-cell>
1 @import '../common/index.wxss';.van-field__body{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center}.van-field__body--textarea{min-height:24px}.van-field__input{display:block;width:100%;height:24px;min-height:24px;padding:0;margin:0;line-height:inherit;color:#333;text-align:left;background-color:initial;border:0;box-sizing:border-box;resize:none}.van-field__input--disabled{color:#999;background-color:initial;opacity:1}.van-field__input--center{text-align:center}.van-field__input--right{text-align:right}.van-field__input--error{color:#f44}.van-field__placeholder{color:#999}.van-field__clear-root{display:-webkit-flex;display:flex;height:24px;-webkit-align-items:center;align-items:center}.van-field__button,.van-field__clear,.van-field__icon-container{-webkit-flex-shrink:0;flex-shrink:0}.van-field__clear,.van-field__icon-container{padding:0 10px;margin-right:-10px;line-height:inherit;vertical-align:middle}.van-field__clear{color:#c9c9c9}.van-field__icon-container{color:#999}.van-field__icon{display:block!important}.van-field__button{padding-left:10px}.van-field__error-message{font-size:12px;color:#f44;text-align:left}.van-field__error--center{text-align:center}.van-field__error--right{text-align:right}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { link } from '../mixins/link';
3 import { button } from '../mixins/button';
4 import { openType } from '../mixins/open-type';
5 VantComponent({
6 mixins: [link, button, openType],
7 props: {
8 text: String,
9 loading: Boolean,
10 disabled: Boolean,
11 type: {
12 type: String,
13 value: 'danger'
14 }
15 },
16 methods: {
17 onClick(event) {
18 this.$emit('click', event.detail);
19 this.jumpLink();
20 }
21 }
22 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-button": "../button/index"
5 }
6 }
1 <van-button
2 square
3 id="{{ id }}"
4 size="large"
5 lang="{{ lang }}"
6 type="{{ type }}"
7 loading="{{ loading }}"
8 disabled="{{ disabled }}"
9 open-type="{{ openType }}"
10 custom-class="custom-class"
11 business-id="{{ businessId }}"
12 session-from="{{ sessionFrom }}"
13 app-parameter="{{ appParameter }}"
14 send-message-img="{{ sendMessageImg }}"
15 send-message-path="{{ sendMessagePath }}"
16 show-message-card="{{ showMessageCard }}"
17 send-message-title="{{ sendMessageTitle }}"
18 bind:click="onClick"
19 binderror="bindError"
20 bindcontact="bindContact"
21 bindopensetting="bindOpenSetting"
22 bindgetuserinfo="bindGetUserInfo"
23 bindgetphonenumber="bindGetPhoneNumber"
24 bindlaunchapp="bindLaunchApp"
25 >
26 {{ text }}
27 </van-button>
1 @import '../common/index.wxss';:host{-webkit-flex:1;flex:1}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { link } from '../mixins/link';
3 import { button } from '../mixins/button';
4 import { openType } from '../mixins/open-type';
5 VantComponent({
6 classes: ['icon-class', 'text-class'],
7 mixins: [link, button, openType],
8 props: {
9 text: String,
10 info: String,
11 icon: String,
12 disabled: Boolean,
13 loading: Boolean
14 },
15 methods: {
16 onClick(event) {
17 this.$emit('click', event.detail);
18 this.jumpLink();
19 }
20 }
21 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-button": "../button/index"
6 }
7 }
1 <van-button
2 square
3 id="{{ id }}"
4 size="large"
5 lang="{{ lang }}"
6 loading="{{ loading }}"
7 disabled="{{ disabled }}"
8 open-type="{{ openType }}"
9 business-id="{{ businessId }}"
10 custom-class="van-goods-action-icon"
11 session-from="{{ sessionFrom }}"
12 app-parameter="{{ appParameter }}"
13 send-message-img="{{ sendMessageImg }}"
14 send-message-path="{{ sendMessagePath }}"
15 show-message-card="{{ showMessageCard }}"
16 send-message-title="{{ sendMessageTitle }}"
17 bind:click="onClick"
18 binderror="bindError"
19 bindcontact="bindContact"
20 bindopensetting="bindOpenSetting"
21 bindgetuserinfo="bindGetUserInfo"
22 bindgetphonenumber="bindGetPhoneNumber"
23 bindlaunchapp="bindLaunchApp"
24 >
25 <view class="van-goods-action-icon__content van-hairline--right">
26 <van-icon
27 size="20px"
28 name="{{ icon }}"
29 info="{{ info }}"
30 class="van-goods-action-icon__icon"
31 custom-class="icon-class"
32 />
33 <text class="text-class">{{ text }}</text>
34 </view>
35 </van-button>
1 @import '../common/index.wxss';.van-goods-action-icon{width:50px!important;border:none!important}.van-goods-action-icon__content{display:-webkit-flex;display:flex;height:100%;font-size:10px;line-height:1;color:#7d7e80;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center}.van-goods-action-icon__icon{margin-bottom:4px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({
4 mixins: [safeArea()]
5 });
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="custom-class {{ utils.bem('goods-action', { safe: isIPhoneX && safeAreaInsetBottom }) }}">
4 <slot />
5 </view>
1 @import '../common/index.wxss';.van-goods-action{position:fixed;right:0;bottom:0;left:0;display:-webkit-flex;display:flex;background-color:#fff}.van-goods-action--safe{padding-bottom:34px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 info: null,
5 name: String,
6 size: String,
7 color: String,
8 customStyle: String,
9 classPrefix: {
10 type: String,
11 value: 'van-icon'
12 }
13 },
14 methods: {
15 onClick() {
16 this.$emit('click');
17 }
18 }
19 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-info": "../info/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ classPrefix }} {{ utils.isSrc(name) ? 'van-icon--image' : classPrefix + '-' + name }}"
5 style="{{ color ? 'color: ' + color + ';' : '' }}{{ size ? 'font-size: ' + size + ';' : '' }}{{ customStyle }}"
6 bind:tap="onClick"
7 >
8 <van-info
9 wx:if="{{ info !== null }}"
10 info="{{ info }}"
11 custom-class="van-icon__info"
12 />
13 <image
14 wx:if="{{ utils.isSrc(name) }}"
15 src="{{ name }}"
16 class="van-icon__image"
17 />
18 </view>
1 @import '../common/index.wxss';@font-face{font-style:normal;font-weight:400;font-family:vant-icon;src:url(https://img.yzcdn.cn/vant/vant-icon-29f643.woff2) format("woff2"),url(https://img.yzcdn.cn/vant/vant-icon-29f643.woff) format("woff"),url(https://img.yzcdn.cn/vant/vant-icon-29f643.ttf) format("truetype")}.van-icon{position:relative;font:normal normal normal 14px/1 vant-icon;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased}.van-icon,.van-icon:before{display:inline-block}.van-icon-add-o:before{content:"\F000"}.van-icon-add-square:before{content:"\F001"}.van-icon-add:before{content:"\F002"}.van-icon-after-sale:before{content:"\F003"}.van-icon-aim:before{content:"\F004"}.van-icon-alipay:before{content:"\F005"}.van-icon-apps-o:before{content:"\F006"}.van-icon-arrow-down:before{content:"\F007"}.van-icon-arrow-left:before{content:"\F008"}.van-icon-arrow-up:before{content:"\F009"}.van-icon-arrow:before{content:"\F00A"}.van-icon-ascending:before{content:"\F00B"}.van-icon-audio:before{content:"\F00C"}.van-icon-award-o:before{content:"\F00D"}.van-icon-award:before{content:"\F00E"}.van-icon-bag-o:before{content:"\F00F"}.van-icon-bag:before{content:"\F010"}.van-icon-balance-list-o:before{content:"\F011"}.van-icon-balance-list:before{content:"\F012"}.van-icon-balance-o:before{content:"\F013"}.van-icon-balance-pay:before{content:"\F014"}.van-icon-bar-chart-o:before{content:"\F015"}.van-icon-bars:before{content:"\F016"}.van-icon-bell:before{content:"\F017"}.van-icon-bill-o:before{content:"\F018"}.van-icon-bill:before{content:"\F019"}.van-icon-birthday-cake-o:before{content:"\F01A"}.van-icon-bookmark-o:before{content:"\F01B"}.van-icon-bookmark:before{content:"\F01C"}.van-icon-browsing-history-o:before{content:"\F01D"}.van-icon-browsing-history:before{content:"\F01E"}.van-icon-brush-o:before{content:"\F01F"}.van-icon-bulb-o:before{content:"\F020"}.van-icon-bullhorn-o:before{content:"\F021"}.van-icon-calender-o:before{content:"\F022"}.van-icon-card:before{content:"\F023"}.van-icon-cart-circle-o:before{content:"\F024"}.van-icon-cart-circle:before{content:"\F025"}.van-icon-cart-o:before{content:"\F026"}.van-icon-cart:before{content:"\F027"}.van-icon-cash-back-record:before{content:"\F028"}.van-icon-cash-on-deliver:before{content:"\F029"}.van-icon-cashier-o:before{content:"\F02A"}.van-icon-certificate:before{content:"\F02B"}.van-icon-chart-trending-o:before{content:"\F02C"}.van-icon-chat-o:before{content:"\F02D"}.van-icon-chat:before{content:"\F02E"}.van-icon-checked:before{content:"\F02F"}.van-icon-circle:before{content:"\F030"}.van-icon-clear:before{content:"\F031"}.van-icon-clock-o:before{content:"\F032"}.van-icon-clock:before{content:"\F033"}.van-icon-close:before{content:"\F034"}.van-icon-closed-eye:before{content:"\F035"}.van-icon-cluster-o:before{content:"\F036"}.van-icon-cluster:before{content:"\F037"}.van-icon-column:before{content:"\F038"}.van-icon-comment-circle-o:before{content:"\F039"}.van-icon-comment-o:before{content:"\F03A"}.van-icon-comment:before{content:"\F03B"}.van-icon-completed:before{content:"\F03C"}.van-icon-contact:before{content:"\F03D"}.van-icon-coupon-o:before{content:"\F03E"}.van-icon-coupon:before{content:"\F03F"}.van-icon-credit-pay:before{content:"\F040"}.van-icon-cross:before{content:"\F041"}.van-icon-debit-pay:before{content:"\F042"}.van-icon-delete:before{content:"\F043"}.van-icon-descending:before{content:"\F044"}.van-icon-description:before{content:"\F045"}.van-icon-desktop-o:before{content:"\F046"}.van-icon-diamond-o:before{content:"\F047"}.van-icon-diamond:before{content:"\F048"}.van-icon-discount:before{content:"\F049"}.van-icon-ecard-pay:before{content:"\F04A"}.van-icon-edit:before{content:"\F04B"}.van-icon-ellipsis:before{content:"\F04C"}.van-icon-empty:before{content:"\F04D"}.van-icon-envelop-o:before{content:"\F04E"}.van-icon-exchange:before{content:"\F04F"}.van-icon-expand-o:before{content:"\F050"}.van-icon-expand:before{content:"\F051"}.van-icon-eye-o:before{content:"\F052"}.van-icon-eye:before{content:"\F053"}.van-icon-fail:before{content:"\F054"}.van-icon-failure:before{content:"\F055"}.van-icon-filter-o:before{content:"\F056"}.van-icon-fire-o:before{content:"\F057"}.van-icon-fire:before{content:"\F058"}.van-icon-flag-o:before{content:"\F059"}.van-icon-flower-o:before{content:"\F05A"}.van-icon-free-postage:before{content:"\F05B"}.van-icon-friends-o:before{content:"\F05C"}.van-icon-friends:before{content:"\F05D"}.van-icon-gem-o:before{content:"\F05E"}.van-icon-gem:before{content:"\F05F"}.van-icon-gift-card-o:before{content:"\F060"}.van-icon-gift-card:before{content:"\F061"}.van-icon-gift-o:before{content:"\F062"}.van-icon-gift:before{content:"\F063"}.van-icon-gold-coin-o:before{content:"\F064"}.van-icon-gold-coin:before{content:"\F065"}.van-icon-goods-collect-o:before{content:"\F066"}.van-icon-goods-collect:before{content:"\F067"}.van-icon-graphic:before{content:"\F068"}.van-icon-home-o:before{content:"\F069"}.van-icon-hot-o:before{content:"\F06A"}.van-icon-hot-sale-o:before{content:"\F06B"}.van-icon-hot-sale:before{content:"\F06C"}.van-icon-hot:before{content:"\F06D"}.van-icon-hotel-o:before{content:"\F06E"}.van-icon-idcard:before{content:"\F06F"}.van-icon-info-o:before{content:"\F070"}.van-icon-info:before{content:"\F071"}.van-icon-invition:before{content:"\F072"}.van-icon-label-o:before{content:"\F073"}.van-icon-label:before{content:"\F074"}.van-icon-like-o:before{content:"\F075"}.van-icon-like:before{content:"\F076"}.van-icon-live:before{content:"\F077"}.van-icon-location-o:before{content:"\F078"}.van-icon-location:before{content:"\F079"}.van-icon-lock:before{content:"\F07A"}.van-icon-logistics:before{content:"\F07B"}.van-icon-manager-o:before{content:"\F07C"}.van-icon-manager:before{content:"\F07D"}.van-icon-map-marked:before{content:"\F07E"}.van-icon-medel-o:before{content:"\F07F"}.van-icon-medel:before{content:"\F080"}.van-icon-more-o:before{content:"\F081"}.van-icon-more:before{content:"\F082"}.van-icon-music-o:before{content:"\F083"}.van-icon-new-arrival-o:before{content:"\F084"}.van-icon-new-arrival:before{content:"\F085"}.van-icon-new-o:before{content:"\F086"}.van-icon-new:before{content:"\F087"}.van-icon-newspaper-o:before{content:"\F088"}.van-icon-notes-o:before{content:"\F089"}.van-icon-orders-o:before{content:"\F08A"}.van-icon-other-pay:before{content:"\F08B"}.van-icon-paid:before{content:"\F08C"}.van-icon-passed:before{content:"\F08D"}.van-icon-pause-circle-o:before{content:"\F08E"}.van-icon-pause-circle:before{content:"\F08F"}.van-icon-pause:before{content:"\F090"}.van-icon-peer-pay:before{content:"\F091"}.van-icon-pending-payment:before{content:"\F092"}.van-icon-phone-circle-o:before{content:"\F093"}.van-icon-phone-o:before{content:"\F094"}.van-icon-phone:before{content:"\F095"}.van-icon-photo-o:before{content:"\F096"}.van-icon-photo:before{content:"\F097"}.van-icon-photograph:before{content:"\F098"}.van-icon-play-circle-o:before{content:"\F099"}.van-icon-play-circle:before{content:"\F09A"}.van-icon-play:before{content:"\F09B"}.van-icon-plus:before{content:"\F09C"}.van-icon-point-gift-o:before{content:"\F09D"}.van-icon-point-gift:before{content:"\F09E"}.van-icon-points:before{content:"\F09F"}.van-icon-printer:before{content:"\F0A0"}.van-icon-qr-invalid:before{content:"\F0A1"}.van-icon-qr:before{content:"\F0A2"}.van-icon-question-o:before{content:"\F0A3"}.van-icon-question:before{content:"\F0A4"}.van-icon-records:before{content:"\F0A5"}.van-icon-refund-o:before{content:"\F0A6"}.van-icon-replay:before{content:"\F0A7"}.van-icon-scan:before{content:"\F0A8"}.van-icon-search:before{content:"\F0A9"}.van-icon-send-gift-o:before{content:"\F0AA"}.van-icon-send-gift:before{content:"\F0AB"}.van-icon-service-o:before{content:"\F0AC"}.van-icon-service:before{content:"\F0AD"}.van-icon-setting-o:before{content:"\F0AE"}.van-icon-setting:before{content:"\F0AF"}.van-icon-share:before{content:"\F0B0"}.van-icon-shop-collect-o:before{content:"\F0B1"}.van-icon-shop-collect:before{content:"\F0B2"}.van-icon-shop-o:before{content:"\F0B3"}.van-icon-shop:before{content:"\F0B4"}.van-icon-shopping-cart-o:before{content:"\F0B5"}.van-icon-shopping-cart:before{content:"\F0B6"}.van-icon-shrink:before{content:"\F0B7"}.van-icon-sign:before{content:"\F0B8"}.van-icon-smile-comment-o:before{content:"\F0B9"}.van-icon-smile-comment:before{content:"\F0BA"}.van-icon-smile-o:before{content:"\F0BB"}.van-icon-star-o:before{content:"\F0BC"}.van-icon-star:before{content:"\F0BD"}.van-icon-stop-circle-o:before{content:"\F0BE"}.van-icon-stop-circle:before{content:"\F0BF"}.van-icon-stop:before{content:"\F0C0"}.van-icon-success:before{content:"\F0C1"}.van-icon-thumb-circle-o:before{content:"\F0C2"}.van-icon-todo-list-o:before{content:"\F0C3"}.van-icon-todo-list:before{content:"\F0C4"}.van-icon-tosend:before{content:"\F0C5"}.van-icon-tv-o:before{content:"\F0C6"}.van-icon-umbrella-circle:before{content:"\F0C7"}.van-icon-underway-o:before{content:"\F0C8"}.van-icon-underway:before{content:"\F0C9"}.van-icon-upgrade:before{content:"\F0CA"}.van-icon-user-circle-o:before{content:"\F0CB"}.van-icon-user-o:before{content:"\F0CC"}.van-icon-video-o:before{content:"\F0CD"}.van-icon-video:before{content:"\F0CE"}.van-icon-vip-card-o:before{content:"\F0CF"}.van-icon-vip-card:before{content:"\F0D0"}.van-icon-volume-o:before{content:"\F0D1"}.van-icon-volume:before{content:"\F0D2"}.van-icon-wap-home:before{content:"\F0D3"}.van-icon-wap-nav:before{content:"\F0D4"}.van-icon-warn-o:before{content:"\F0D5"}.van-icon-warning-o:before{content:"\F0D6"}.van-icon-weapp-nav:before{content:"\F0D7"}.van-icon-wechat:before{content:"\F0D8"}.van-icon-youzan-shield:before{content:"\F0D9"}.van-icon--image{width:1em;height:1em}.van-icon__image{position:absolute;top:0;right:0;bottom:0;left:0;max-width:100%;max-height:100%;margin:auto}.van-icon__info{z-index:1}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 info: null,
5 customStyle: String
6 }
7 });
1 {
2 "component": true
3 }
1 <view
2 wx:if="{{ info !== null }}"
3 class="custom-class van-info"
4 style="{{ customStyle }}"
5 >{{ info }}</view>
1 @import '../common/index.wxss';.van-info{position:absolute;top:-8px;right:0;min-width:16px;padding:0 3px;font-family:PingFang SC,Helvetica Neue,Arial,sans-serif;font-size:12px;font-weight:500;line-height:14px;color:#fff;text-align:center;white-space:nowrap;background-color:#f44;border:1px solid #fff;border-radius:16px;-webkit-transform:translateX(50%);transform:translateX(50%);box-sizing:border-box;-webkit-transform-origin:100%;transform-origin:100%}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 size: {
5 type: String,
6 value: '30px'
7 },
8 type: {
9 type: String,
10 value: 'circular'
11 },
12 color: {
13 type: String,
14 value: '#c9c9c9'
15 }
16 }
17 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <view
2 class="van-loading custom-class"
3 style="width: {{ size }}; height: {{ size }}"
4 >
5 <view
6 class="van-loading__spinner van-loading__spinner--{{ type }}"
7 style="color: {{ color }};"
8 >
9 <view
10 wx:if="{{ type === 'spinner' }}"
11 wx:for="item in 12"
12 wx:key="index"
13 class="van-loading__dot"
14 />
15 </view>
16 </view>
1 @import '../common/index.wxss';.van-loading{z-index:0;line-height:0;vertical-align:middle}.van-loading,.van-loading__spinner{position:relative;display:inline-block}.van-loading__spinner{z-index:-1;width:100%;height:100%;box-sizing:border-box;-webkit-animation:van-rotate .8s linear infinite;animation:van-rotate .8s linear infinite}.van-loading__spinner--spinner{-webkit-animation-timing-function:steps(12);animation-timing-function:steps(12)}.van-loading__spinner--circular{border-radius:100%;border:1px solid transparent;border-top-color:initial}.van-loading__dot{top:0;left:0;width:100%;height:100%;position:absolute}.van-loading__dot:before{width:2px;height:25%;content:" ";display:block;margin:0 auto;border-radius:40%;background-color:currentColor}.van-loading__dot:first-of-type{opacity:1;-webkit-transform:rotate(30deg);transform:rotate(30deg)}.van-loading__dot:nth-of-type(2){opacity:.9375;-webkit-transform:rotate(60deg);transform:rotate(60deg)}.van-loading__dot:nth-of-type(3){opacity:.875;-webkit-transform:rotate(90deg);transform:rotate(90deg)}.van-loading__dot:nth-of-type(4){opacity:.8125;-webkit-transform:rotate(120deg);transform:rotate(120deg)}.van-loading__dot:nth-of-type(5){opacity:.75;-webkit-transform:rotate(150deg);transform:rotate(150deg)}.van-loading__dot:nth-of-type(6){opacity:.6875;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.van-loading__dot:nth-of-type(7){opacity:.625;-webkit-transform:rotate(210deg);transform:rotate(210deg)}.van-loading__dot:nth-of-type(8){opacity:.5625;-webkit-transform:rotate(240deg);transform:rotate(240deg)}.van-loading__dot:nth-of-type(9){opacity:.5;-webkit-transform:rotate(270deg);transform:rotate(270deg)}.van-loading__dot:nth-of-type(10){opacity:.4375;-webkit-transform:rotate(300deg);transform:rotate(300deg)}.van-loading__dot:nth-of-type(11){opacity:.375;-webkit-transform:rotate(330deg);transform:rotate(330deg)}.van-loading__dot:nth-of-type(12){opacity:.3125;-webkit-transform:rotate(1turn);transform:rotate(1turn)}@-webkit-keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}
...\ No newline at end of file ...\ No newline at end of file
1 export declare const basic: void;
1 export const basic = Behavior({
2 methods: {
3 $emit() {
4 this.triggerEvent.apply(this, arguments);
5 },
6 getRect(selector, all) {
7 return new Promise(resolve => {
8 wx.createSelectorQuery()
9 .in(this)[all ? 'selectAll' : 'select'](selector)
10 .boundingClientRect(rect => {
11 if (all && Array.isArray(rect) && rect.length) {
12 resolve(rect);
13 }
14 if (!all && rect) {
15 resolve(rect);
16 }
17 })
18 .exec();
19 });
20 }
21 }
22 });
1 export declare const button: void;
1 export const button = Behavior({
2 externalClasses: ['hover-class'],
3 properties: {
4 id: String,
5 lang: {
6 type: String,
7 value: 'en'
8 },
9 businessId: Number,
10 sessionFrom: String,
11 sendMessageTitle: String,
12 sendMessagePath: String,
13 sendMessageImg: String,
14 showMessageCard: Boolean,
15 appParameter: String,
16 ariaLabel: String
17 }
18 });
1 export declare const link: void;
1 export const link = Behavior({
2 properties: {
3 url: String,
4 linkType: {
5 type: String,
6 value: 'navigateTo'
7 }
8 },
9 methods: {
10 jumpLink(urlKey = 'url') {
11 const url = this.data[urlKey];
12 if (url) {
13 wx[this.data.linkType]({ url });
14 }
15 }
16 }
17 });
1 export declare const behavior: void;
1 function setAsync(context, data) {
2 return new Promise(resolve => {
3 context.setData(data, resolve);
4 });
5 }
6 ;
7 export const behavior = Behavior({
8 created() {
9 if (!this.$options) {
10 return;
11 }
12 const cache = {};
13 const { computed } = this.$options();
14 const keys = Object.keys(computed);
15 this.calcComputed = () => {
16 const needUpdate = {};
17 keys.forEach(key => {
18 const value = computed[key].call(this);
19 if (cache[key] !== value) {
20 cache[key] = needUpdate[key] = value;
21 }
22 });
23 return needUpdate;
24 };
25 },
26 attached() {
27 this.set();
28 },
29 methods: {
30 // set data and set computed data
31 set(data, callback) {
32 const stack = [];
33 if (data) {
34 stack.push(setAsync(this, data));
35 }
36 if (this.calcComputed) {
37 stack.push(setAsync(this, this.calcComputed()));
38 }
39 return Promise.all(stack).then(res => {
40 if (callback && typeof callback === 'function') {
41 callback.call(this);
42 }
43 return res;
44 });
45 }
46 }
47 });
1 export declare function observe(vantOptions: any, options: any): void;
1 import { behavior } from './behavior';
2 import { observeProps } from './props';
3 export function observe(vantOptions, options) {
4 const { watch, computed } = vantOptions;
5 options.behaviors.push(behavior);
6 if (watch) {
7 const props = options.properties || {};
8 Object.keys(watch).forEach(key => {
9 if (key in props) {
10 let prop = props[key];
11 if (prop === null || !('type' in prop)) {
12 prop = { type: prop };
13 }
14 prop.observer = watch[key];
15 props[key] = prop;
16 }
17 });
18 options.properties = props;
19 }
20 if (computed) {
21 options.methods = options.methods || {};
22 options.methods.$options = () => vantOptions;
23 if (options.properties) {
24 observeProps(options.properties);
25 }
26 }
27 }
1 export declare function observeProps(props: any): void;
1 export function observeProps(props) {
2 if (!props) {
3 return;
4 }
5 Object.keys(props).forEach(key => {
6 let prop = props[key];
7 if (prop === null || !('type' in prop)) {
8 prop = { type: prop };
9 }
10 let { observer } = prop;
11 prop.observer = function () {
12 if (observer) {
13 if (typeof observer === 'string') {
14 observer = this[observer];
15 }
16 observer.apply(this, arguments);
17 }
18 this.set();
19 };
20 props[key] = prop;
21 });
22 }
1 export declare const openType: void;
1 export const openType = Behavior({
2 properties: {
3 openType: String
4 },
5 methods: {
6 bindGetUserInfo(event) {
7 this.$emit('getuserinfo', event.detail);
8 },
9 bindContact(event) {
10 this.$emit('contact', event.detail);
11 },
12 bindGetPhoneNumber(event) {
13 this.$emit('getphonenumber', event.detail);
14 },
15 bindError(event) {
16 this.$emit('error', event.detail);
17 },
18 bindLaunchApp(event) {
19 this.$emit('launchapp', event.detail);
20 },
21 bindOpenSetting(event) {
22 this.$emit('opensetting', event.detail);
23 },
24 }
25 });
1 export declare const safeArea: ({ safeAreaInsetBottom, safeAreaInsetTop }?: {
2 safeAreaInsetBottom?: boolean;
3 safeAreaInsetTop?: boolean;
4 }) => void;
1 let cache = null;
2 function getSafeArea() {
3 return new Promise((resolve, reject) => {
4 if (cache != null) {
5 resolve(cache);
6 }
7 else {
8 wx.getSystemInfo({
9 success: ({ model, screenHeight, statusBarHeight }) => {
10 const iphoneX = /iphone x/i.test(model);
11 const iphoneNew = /iPhone11/i.test(model) && screenHeight === 812;
12 cache = {
13 isIPhoneX: iphoneX || iphoneNew,
14 statusBarHeight
15 };
16 resolve(cache);
17 },
18 fail: reject
19 });
20 }
21 });
22 }
23 export const safeArea = ({ safeAreaInsetBottom = true, safeAreaInsetTop = false } = {}) => Behavior({
24 properties: {
25 safeAreaInsetTop: {
26 type: Boolean,
27 value: safeAreaInsetTop
28 },
29 safeAreaInsetBottom: {
30 type: Boolean,
31 value: safeAreaInsetBottom
32 }
33 },
34 created() {
35 getSafeArea().then(({ isIPhoneX, statusBarHeight }) => {
36 this.set({ isIPhoneX, statusBarHeight });
37 });
38 }
39 });
1 export declare const touch: void;
1 export const touch = Behavior({
2 methods: {
3 touchStart(event) {
4 const touch = event.touches[0];
5 this.direction = '';
6 this.deltaX = 0;
7 this.deltaY = 0;
8 this.offsetX = 0;
9 this.offsetY = 0;
10 this.startX = touch.clientX;
11 this.startY = touch.clientY;
12 },
13 touchMove(event) {
14 const touch = event.touches[0];
15 this.deltaX = touch.clientX - this.startX;
16 this.deltaY = touch.clientY - this.startY;
17 this.offsetX = Math.abs(this.deltaX);
18 this.offsetY = Math.abs(this.deltaY);
19 this.direction =
20 this.offsetX > this.offsetY
21 ? 'horizontal'
22 : this.offsetX < this.offsetY
23 ? 'vertical'
24 : '';
25 }
26 }
27 });
1 export declare const transition: (showDefaultValue: boolean) => void;
1 import { isObj } from '../common/utils';
2 const getClassNames = (name) => ({
3 enter: `van-${name}-enter van-${name}-enter-active enter-class enter-active-class`,
4 'enter-to': `van-${name}-enter-to van-${name}-enter-active enter-to-class enter-active-class`,
5 leave: `van-${name}-leave van-${name}-leave-active leave-class leave-active-class`,
6 'leave-to': `van-${name}-leave-to van-${name}-leave-active leave-to-class leave-active-class`
7 });
8 const nextTick = () => new Promise(resolve => setTimeout(resolve, 1000 / 30));
9 export const transition = function (showDefaultValue) {
10 return Behavior({
11 properties: {
12 customStyle: String,
13 show: {
14 type: Boolean,
15 value: showDefaultValue,
16 observer: 'observeShow'
17 },
18 duration: {
19 type: [Number, Object],
20 value: 300,
21 observer: 'observeDuration'
22 },
23 name: {
24 type: String,
25 value: 'fade',
26 observer: 'updateClasses'
27 }
28 },
29 data: {
30 type: '',
31 inited: false,
32 display: false,
33 classNames: getClassNames('fade')
34 },
35 attached() {
36 if (this.data.show) {
37 this.show();
38 }
39 },
40 methods: {
41 observeShow(value) {
42 if (value) {
43 this.show();
44 }
45 else {
46 this.leave();
47 }
48 },
49 updateClasses(name) {
50 this.set({
51 classNames: getClassNames(name)
52 });
53 },
54 show() {
55 const { classNames, duration } = this.data;
56 const currentDuration = isObj(duration) ? duration.leave : duration;
57 Promise.resolve()
58 .then(nextTick)
59 .then(() => this.set({
60 inited: true,
61 display: true,
62 classes: classNames.enter,
63 currentDuration
64 }))
65 .then(nextTick)
66 .then(() => this.set({
67 classes: classNames['enter-to']
68 }));
69 },
70 leave() {
71 const { classNames, duration } = this.data;
72 const currentDuration = isObj(duration) ? duration.leave : duration;
73 if (+currentDuration === 0) {
74 this.onTransitionEnd();
75 return;
76 }
77 Promise.resolve()
78 .then(nextTick)
79 .then(() => this.set({
80 classes: classNames.leave,
81 currentDuration
82 }))
83 .then(nextTick)
84 .then(() => this.set({
85 classes: classNames['leave-to']
86 }));
87 },
88 onTransitionEnd() {
89 if (!this.data.show) {
90 this.set({ display: false });
91 this.$emit('transitionEnd');
92 }
93 }
94 }
95 });
96 };
1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({
4 mixins: [safeArea({ safeAreaInsetTop: true })],
5 classes: ['title-class'],
6 props: {
7 title: String,
8 fixed: Boolean,
9 leftText: String,
10 rightText: String,
11 leftArrow: Boolean,
12 border: {
13 type: Boolean,
14 value: true
15 },
16 zIndex: {
17 type: Number,
18 value: 120
19 }
20 },
21 methods: {
22 onClickLeft() {
23 this.$emit('click-left');
24 },
25 onClickRight() {
26 this.$emit('click-right');
27 }
28 }
29 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="{{ utils.bem('nav-bar', { fixed }) }} custom-class {{ border ? 'van-hairline--bottom' : '' }}"
5 style="z-index: {{ zIndex }}; {{ safeAreaInsetTop ? 'padding-top: ' + statusBarHeight + 'px;' : '' }}"
6 >
7 <view class="van-nav-bar__left" bind:tap="onClickLeft">
8 <block wx:if="{{ leftArrow || leftText }}">
9 <van-icon
10 wx:if="{{ leftArrow }}"
11 size="16px"
12 name="arrow-left"
13 custom-class="van-nav-bar__arrow"
14 />
15 <view
16 wx:if="{{ leftText }}"
17 class="van-nav-bar__text"
18 hover-class="van-nav-bar__text--hover"
19 hover-stay-time="70"
20 >{{ leftText }}</view>
21 </block>
22 <slot wx:else name="left" />
23 </view>
24 <view class="van-nav-bar__title title-class van-ellipsis">
25 <block wx:if="{{ title }}">{{ title }}</block>
26 <slot wx:else name="title" />
27 </view>
28 <view class="van-nav-bar__right" bind:tap="onClickRight">
29 <view
30 wx:if="{{ rightText }}"
31 class="van-nav-bar__text"
32 hover-class="van-nav-bar__text--hover"
33 hover-stay-time="70"
34 >{{ rightText }}</view>
35 <slot wx:else name="right" />
36 </view>
37 </view>
1 @import '../common/index.wxss';.van-nav-bar{position:relative;height:44px;line-height:44px;text-align:center;background-color:#fff;-webkit-user-select:none;user-select:none}.van-nav-bar__text{display:inline-block;padding:0 15px;margin:0 -15px;color:#1989fa;vertical-align:middle}.van-nav-bar__text--hover{background-color:#f2f3f5}.van-nav-bar__arrow{color:#1989fa;vertical-align:middle}.van-nav-bar__arrow+.van-nav-bar__text{padding-left:25px;margin-left:-20px}.van-nav-bar--fixed{position:fixed;top:0;left:0;width:100%}.van-nav-bar__title{max-width:60%;margin:0 auto;font-size:16px;font-weight:500}.van-nav-bar__left,.van-nav-bar__right{position:absolute;bottom:0;font-size:14px}.van-nav-bar__left{left:15px}.van-nav-bar__right{right:15px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 const FONT_COLOR = '#ed6a0c';
3 const BG_COLOR = '#fffbe8';
4 VantComponent({
5 props: {
6 text: {
7 type: String,
8 value: ''
9 },
10 mode: {
11 type: String,
12 value: ''
13 },
14 url: {
15 type: String,
16 value: ''
17 },
18 openType: {
19 type: String,
20 value: 'navigate'
21 },
22 delay: {
23 type: Number,
24 value: 0
25 },
26 speed: {
27 type: Number,
28 value: 50
29 },
30 scrollable: {
31 type: Boolean,
32 value: true
33 },
34 leftIcon: {
35 type: String,
36 value: ''
37 },
38 color: {
39 type: String,
40 value: FONT_COLOR
41 },
42 backgroundColor: {
43 type: String,
44 value: BG_COLOR
45 }
46 },
47 data: {
48 show: true,
49 hasRightIcon: false
50 },
51 watch: {
52 text() {
53 this.set({}, this.init);
54 }
55 },
56 created() {
57 if (this.data.mode) {
58 this.set({
59 hasRightIcon: true
60 });
61 }
62 this.resetAnimation = wx.createAnimation({
63 duration: 0,
64 timingFunction: 'linear'
65 });
66 },
67 destroyed() {
68 this.timer && clearTimeout(this.timer);
69 },
70 methods: {
71 init() {
72 Promise.all([
73 this.getRect('.van-notice-bar__content'),
74 this.getRect('.van-notice-bar__content-wrap')
75 ]).then((rects) => {
76 const [contentRect, wrapRect] = rects;
77 if (contentRect == null ||
78 wrapRect == null ||
79 !contentRect.width ||
80 !wrapRect.width) {
81 return;
82 }
83 const { speed, scrollable, delay } = this.data;
84 if (scrollable && wrapRect.width < contentRect.width) {
85 const duration = (contentRect.width / speed) * 1000;
86 this.wrapWidth = wrapRect.width;
87 this.contentWidth = contentRect.width;
88 this.duration = duration;
89 this.animation = wx.createAnimation({
90 duration,
91 timingFunction: 'linear',
92 delay
93 });
94 this.scroll();
95 }
96 });
97 },
98 scroll() {
99 this.timer && clearTimeout(this.timer);
100 this.timer = null;
101 this.set({
102 animationData: this.resetAnimation
103 .translateX(this.wrapWidth)
104 .step()
105 .export()
106 });
107 setTimeout(() => {
108 this.set({
109 animationData: this.animation
110 .translateX(-this.contentWidth)
111 .step()
112 .export()
113 });
114 }, 20);
115 this.timer = setTimeout(() => {
116 this.scroll();
117 }, this.duration);
118 },
119 onClickIcon() {
120 this.timer && clearTimeout(this.timer);
121 this.timer = null;
122 this.set({ show: false });
123 },
124 onClick(event) {
125 this.$emit('click', event);
126 }
127 }
128 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
...\ No newline at end of file ...\ No newline at end of file
1 <view
2 wx:if="{{ show }}"
3 class="custom-class van-notice-bar {{ hasRightIcon ? 'van-notice-bar--within-icon' : '' }}"
4 style="color: {{ color }}; background-color: {{ backgroundColor }};"
5 bind:tap="onClick"
6 >
7 <view wx:if="{{ leftIcon }}" class="van-notice-bar__left-icon">
8 <image src="{{ leftIcon }}" />
9 </view>
10 <view class="van-notice-bar__content-wrap">
11 <view class="van-notice-bar__content {{ scrollable ? '' : 'van-ellipsis' }}" animation="{{ animationData }}">
12 {{ text }}
13 </view>
14 </view>
15
16 <van-icon
17 wx:if="{{ mode === 'closeable' }}"
18 class="van-notice-bar__right-icon"
19 name="cross"
20 bind:tap="onClickIcon"
21 />
22 <navigator
23 wx:if="{{ mode === 'link' }}"
24 url="{{ url }}"
25 open-type="{{ openType }}"
26 >
27 <van-icon class="van-notice-bar__right-icon" name="arrow" />
28 </navigator>
29 </view>
1 @import '../common/index.wxss';.van-notice-bar{display:-webkit-flex;display:flex;height:40px;padding:0 15px;font-size:14px;line-height:24px;-webkit-align-items:center;align-items:center}.van-notice-bar--within-icon{position:relative;padding-right:40px}.van-notice-bar__left-icon{height:18px;min-width:20px;box-sizing:border-box}.van-notice-bar__left-icon>image{width:16px;height:16px}.van-notice-bar__right-icon{position:absolute;top:10px;right:15px;font-size:16px}.van-notice-bar__content-wrap{position:relative;height:24px;overflow:hidden;-webkit-flex:1;flex:1}.van-notice-bar__content{position:absolute;white-space:nowrap}.van-notice-bar__content.van-ellipsis{max-width:100%}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { RED } from '../common/color';
3 import { safeArea } from '../mixins/safe-area';
4 VantComponent({
5 mixins: [safeArea()],
6 props: {
7 text: String,
8 color: {
9 type: String,
10 value: '#fff'
11 },
12 backgroundColor: {
13 type: String,
14 value: RED
15 },
16 duration: {
17 type: Number,
18 value: 3000
19 }
20 },
21 methods: {
22 show() {
23 const { duration } = this.data;
24 clearTimeout(this.timer);
25 this.set({
26 show: true
27 });
28 if (duration > 0 && duration !== Infinity) {
29 this.timer = setTimeout(() => {
30 this.hide();
31 }, duration);
32 }
33 },
34 hide() {
35 clearTimeout(this.timer);
36 this.set({
37 show: false
38 });
39 }
40 }
41 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-transition": "../transition/index"
5 }
6 }
1 <van-transition
2 name="slide-down"
3 show="{{ show }}"
4 custom-class="van-notify"
5 custom-style="background-color:{{ backgroundColor }}; color: {{ color }};"
6 >
7 <view wx:if="{{ safeAreaInsetTop }}" class="van-notify__safe-top" style="padding-top: {{ statusBarHeight }}px"></view>
8 {{ text }}
9 </van-transition>
1 @import '../common/index.wxss';.van-notify{position:fixed;top:0;z-index:110;width:100%;padding:6px 15px;font-size:14px;line-height:20px;text-align:center;word-break:break-all;box-sizing:border-box}.van-notify__safe-top{height:44px}
...\ No newline at end of file ...\ No newline at end of file
1 declare type NotifyOptions = {
2 text: string;
3 color?: string;
4 backgroundColor?: string;
5 duration?: number;
6 selector?: string;
7 context?: any;
8 safeAreaInsetTop?: boolean;
9 };
10 export default function Notify(options: NotifyOptions | string): void;
11 export {};
1 import { isObj } from '../common/utils';
2 const defaultOptions = {
3 selector: '#van-notify',
4 duration: 3000
5 };
6 function parseOptions(text) {
7 return isObj(text) ? text : { text };
8 }
9 function getContext() {
10 const pages = getCurrentPages();
11 return pages[pages.length - 1];
12 }
13 export default function Notify(options) {
14 options = Object.assign({}, defaultOptions, parseOptions(options));
15 const context = options.context || getContext();
16 const notify = context.selectComponent(options.selector);
17 delete options.selector;
18 if (notify) {
19 notify.set(options);
20 notify.show();
21 }
22 else {
23 console.warn('未找到 van-notify 节点,请确认 selector 及 context 是否正确');
24 }
25 }
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 show: Boolean,
5 mask: Boolean,
6 customStyle: String,
7 duration: {
8 type: [Number, Object],
9 value: 300
10 },
11 zIndex: {
12 type: Number,
13 value: 1
14 }
15 },
16 methods: {
17 onClick() {
18 this.$emit('click');
19 },
20 // for prevent touchmove
21 noop() { }
22 }
23 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-transition": "../transition/index"
5 }
6 }
1 <van-transition
2 show="{{ show }}"
3 custom-class="van-overlay"
4 custom-style="z-index: {{ zIndex }}; {{ mask ? 'background-color: rgba(0, 0, 0, .7);' : '' }}; {{ customStyle }}"
5 duration="{{ duration }}"
6 bind:tap="onClick"
7 catch:touchmove="noop"
8 />
1 @import '../common/index.wxss';.van-overlay{position:fixed;top:0;right:0;bottom:0;left:0}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 classes: ['header-class', 'footer-class'],
4 props: {
5 desc: String,
6 title: String,
7 status: String,
8 useFooterSlot: Boolean
9 }
10 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-cell": "../cell/index"
5 }
6 }
1 <view class="van-panel van-hairline--top-bottom custom-class">
2 <van-cell
3 wx:if="{{ title || desc || status }}"
4 title="{{ title }}"
5 label="{{ desc }}"
6 value="{{ status }}"
7 custom-class="header-class"
8 value-class="van-panel__header-value"
9 />
10 <slot wx:else name="header" />
11
12 <view class="van-panel__content">
13 <slot />
14 </view>
15
16 <view wx:if="{{ useFooterSlot }}" class="van-panel__footer van-hairline--top footer-class">
17 <slot name="footer" />
18 </view>
19 </view>
1 @import '../common/index.wxss';.van-panel{background:#fff}.van-panel__header-value{color:#f44}.van-panel__footer{padding:10px 15px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { isObj, range } from '../common/utils';
3 const DEFAULT_DURATION = 200;
4 VantComponent({
5 classes: ['active-class'],
6 props: {
7 valueKey: String,
8 className: String,
9 itemHeight: Number,
10 visibleItemCount: Number,
11 initialOptions: {
12 type: Array,
13 value: []
14 },
15 defaultIndex: {
16 type: Number,
17 value: 0
18 }
19 },
20 data: {
21 startY: 0,
22 offset: 0,
23 duration: 0,
24 startOffset: 0,
25 options: [],
26 currentIndex: 0
27 },
28 created() {
29 const { defaultIndex, initialOptions } = this.data;
30 this.set({
31 currentIndex: defaultIndex,
32 options: initialOptions
33 }).then(() => {
34 this.setIndex(defaultIndex);
35 });
36 },
37 computed: {
38 count() {
39 return this.data.options.length;
40 },
41 baseOffset() {
42 const { data } = this;
43 return (data.itemHeight * (data.visibleItemCount - 1)) / 2;
44 },
45 wrapperStyle() {
46 const { data } = this;
47 return [
48 `transition: ${data.duration}ms`,
49 `transform: translate3d(0, ${data.offset + data.baseOffset}px, 0)`,
50 `line-height: ${data.itemHeight}px`
51 ].join('; ');
52 }
53 },
54 watch: {
55 defaultIndex(value) {
56 this.setIndex(value);
57 }
58 },
59 methods: {
60 onTouchStart(event) {
61 this.set({
62 startY: event.touches[0].clientY,
63 startOffset: this.data.offset,
64 duration: 0
65 });
66 },
67 onTouchMove(event) {
68 const { data } = this;
69 const deltaY = event.touches[0].clientY - data.startY;
70 this.set({
71 offset: range(data.startOffset + deltaY, -(data.count * data.itemHeight), data.itemHeight)
72 });
73 },
74 onTouchEnd() {
75 const { data } = this;
76 if (data.offset !== data.startOffset) {
77 this.set({
78 duration: DEFAULT_DURATION
79 });
80 const index = range(Math.round(-data.offset / data.itemHeight), 0, data.count - 1);
81 this.setIndex(index, true);
82 }
83 },
84 onClickItem(event) {
85 const { index } = event.currentTarget.dataset;
86 this.setIndex(index, true);
87 },
88 adjustIndex(index) {
89 const { data } = this;
90 index = range(index, 0, data.count);
91 for (let i = index; i < data.count; i++) {
92 if (!this.isDisabled(data.options[i]))
93 return i;
94 }
95 for (let i = index - 1; i >= 0; i--) {
96 if (!this.isDisabled(data.options[i]))
97 return i;
98 }
99 },
100 isDisabled(option) {
101 return isObj(option) && option.disabled;
102 },
103 getOptionText(option) {
104 const { data } = this;
105 return isObj(option) && data.valueKey in option
106 ? option[data.valueKey]
107 : option;
108 },
109 setIndex(index, userAction) {
110 const { data } = this;
111 index = this.adjustIndex(index) || 0;
112 const offset = -index * data.itemHeight;
113 if (index !== data.currentIndex) {
114 return this.set({ offset, currentIndex: index }).then(() => {
115 userAction && this.$emit('change', index);
116 });
117 }
118 else {
119 return this.set({ offset });
120 }
121 },
122 setValue(value) {
123 const { options } = this.data;
124 for (let i = 0; i < options.length; i++) {
125 if (this.getOptionText(options[i]) === value) {
126 return this.setIndex(i);
127 }
128 }
129 return Promise.resolve();
130 },
131 getValue() {
132 const { data } = this;
133 return data.options[data.currentIndex];
134 }
135 }
136 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <view
2 class="van-picker-column custom-class"
3 style="height: {{ itemHeight * visibleItemCount }}px"
4 bind:touchstart="onTouchStart"
5 catch:touchmove="onTouchMove"
6 bind:touchend="onTouchEnd"
7 bind:touchcancel="onTouchEnd"
8 >
9 <view style="{{ wrapperStyle }}">
10 <view
11 wx:for="{{ options }}"
12 wx:for-item="option"
13 wx:key="index"
14 data-index="{{ index }}"
15 style="height: {{ itemHeight }}px"
16 class="van-ellipsis van-picker-column__item {{ option && option.disabled ? 'van-picker-column__item--disabled' : '' }} {{ index === currentIndex ? 'van-picker-column__item--selected active-class' : '' }}"
17 bindtap="onClickItem"
18 >{{ getOptionText(option, valueKey) }}</view>
19 </view>
20 </view>
21
22 <wxs module="getOptionText">
23 function isObj(x) {
24 var type = typeof x;
25 return x !== null && (type === 'object' || type === 'function');
26 }
27
28 module.exports = function (option, valueKey) {
29 return isObj(option) && option[valueKey] ? option[valueKey] : option;
30 }
31 </wxs>
1 @import '../common/index.wxss';.van-picker-column{overflow:hidden;font-size:16px;text-align:center}.van-picker-column__item{padding:0 5px;color:#999}.van-picker-column__item--selected{font-weight:500;color:#333}.van-picker-column__item--disabled{opacity:.3}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 function isSimple(columns) {
3 return columns.length && !columns[0].values;
4 }
5 VantComponent({
6 classes: ['active-class', 'toolbar-class', 'column-class'],
7 props: {
8 title: String,
9 loading: Boolean,
10 showToolbar: Boolean,
11 confirmButtonText: String,
12 cancelButtonText: String,
13 visibleItemCount: {
14 type: Number,
15 value: 5
16 },
17 valueKey: {
18 type: String,
19 value: 'text'
20 },
21 itemHeight: {
22 type: Number,
23 value: 44
24 },
25 columns: {
26 type: Array,
27 value: [],
28 observer(columns = []) {
29 this.simple = isSimple(columns);
30 this.children = this.selectAllComponents('.van-picker__column');
31 if (Array.isArray(this.children) && this.children.length) {
32 this.setColumns().catch(() => { });
33 }
34 }
35 }
36 },
37 beforeCreate() {
38 this.children = [];
39 },
40 methods: {
41 noop() { },
42 setColumns() {
43 const { data } = this;
44 const columns = this.simple ? [{ values: data.columns }] : data.columns;
45 const stack = columns.map((column, index) => this.setColumnValues(index, column.values));
46 return Promise.all(stack);
47 },
48 emit(event) {
49 const { type } = event.currentTarget.dataset;
50 if (this.simple) {
51 this.$emit(type, {
52 value: this.getColumnValue(0),
53 index: this.getColumnIndex(0)
54 });
55 }
56 else {
57 this.$emit(type, {
58 value: this.getValues(),
59 index: this.getIndexes()
60 });
61 }
62 },
63 onChange(event) {
64 if (this.simple) {
65 this.$emit('change', {
66 picker: this,
67 value: this.getColumnValue(0),
68 index: this.getColumnIndex(0)
69 });
70 }
71 else {
72 this.$emit('change', {
73 picker: this,
74 value: this.getValues(),
75 index: event.currentTarget.dataset.index
76 });
77 }
78 },
79 // get column instance by index
80 getColumn(index) {
81 return this.children[index];
82 },
83 // get column value by index
84 getColumnValue(index) {
85 const column = this.getColumn(index);
86 return column && column.getValue();
87 },
88 // set column value by index
89 setColumnValue(index, value) {
90 const column = this.getColumn(index);
91 if (column == null) {
92 return Promise.reject('setColumnValue: 对应列不存在');
93 }
94 return column.setValue(value);
95 },
96 // get column option index by column index
97 getColumnIndex(columnIndex) {
98 return (this.getColumn(columnIndex) || {}).data.currentIndex;
99 },
100 // set column option index by column index
101 setColumnIndex(columnIndex, optionIndex) {
102 const column = this.getColumn(columnIndex);
103 if (column == null) {
104 return Promise.reject('setColumnIndex: 对应列不存在');
105 }
106 return column.setIndex(optionIndex);
107 },
108 // get options of column by index
109 getColumnValues(index) {
110 return (this.children[index] || {}).data.options;
111 },
112 // set options of column by index
113 setColumnValues(index, options, needReset = true) {
114 const column = this.children[index];
115 if (column == null) {
116 return Promise.reject('setColumnValues: 对应列不存在');
117 }
118 const isSame = JSON.stringify(column.data.options) === JSON.stringify(options);
119 if (isSame) {
120 return Promise.resolve();
121 }
122 return column.set({ options }).then(() => {
123 if (needReset) {
124 column.setIndex(0);
125 }
126 });
127 },
128 // get values of all columns
129 getValues() {
130 return this.children.map((child) => child.getValue());
131 },
132 // set values of all columns
133 setValues(values) {
134 const stack = values.map((value, index) => this.setColumnValue(index, value));
135 return Promise.all(stack);
136 },
137 // get indexes of all columns
138 getIndexes() {
139 return this.children.map((child) => child.data.currentIndex);
140 },
141 // set indexes of all columns
142 setIndexes(indexes) {
143 const stack = indexes.map((optionIndex, columnIndex) => this.setColumnIndex(columnIndex, optionIndex));
144 return Promise.all(stack);
145 }
146 }
147 });
1 {
2 "component": true,
3 "usingComponents": {
4 "picker-column": "../picker-column/index",
5 "loading": "../loading/index"
6 }
7 }
1 <view class="van-picker custom-class">
2 <view
3 wx:if="{{ showToolbar }}"
4 class="van-picker__toolbar van-hairline--top-bottom toolbar-class"
5 >
6 <view
7 class="van-picker__cancel"
8 hover-class="van-picker__cancel--hover"
9 hover-stay-time="70"
10 data-type="cancel"
11 bindtap="emit"
12 >
13 {{ cancelButtonText || '取消' }}
14 </view>
15 <view wx:if="{{ title }}" class="van-picker__title van-ellipsis">{{ title }}</view>
16 <view
17 class="van-picker__confirm"
18 hover-class="van-picker__confirm--hover"
19 hover-stay-time="70"
20 data-type="confirm"
21 bindtap="emit"
22 >
23 {{ confirmButtonText || '确认' }}
24 </view>
25 </view>
26 <view wx:if="{{ loading }}" class="van-picker__loading">
27 <loading color="#1989fa"/>
28 </view>
29 <view
30 class="van-picker__columns"
31 style="height: {{ itemHeight * visibleItemCount }}px"
32 catch:touchmove="noop"
33 >
34 <picker-column
35 class="van-picker__column"
36 wx:for="{{ isSimple(columns) ? [columns] : columns }}"
37 wx:key="{{ index }}"
38 data-index="{{ index }}"
39 custom-class="column-class"
40 value-key="{{ valueKey }}"
41 initial-options="{{ isSimple(columns) ? item : item.values }}"
42 default-index="{{ item.defaultIndex }}"
43 item-height="{{ itemHeight }}"
44 visible-item-count="{{ visibleItemCount }}"
45 active-class="active-class"
46 bind:change="onChange"
47 />
48 <view
49 class="van-picker__frame van-hairline--top-bottom"
50 style="height: {{ itemHeight }}px"
51 />
52 </view>
53 </view>
54
55 <wxs module="isSimple">
56 function isSimple(columns) {
57 return columns.length && !columns[0].values;
58 }
59 module.exports = isSimple;
60 </wxs>
1 @import '../common/index.wxss';.van-picker{position:relative;overflow:hidden;-webkit-text-size-adjust:100%;background-color:#fff;-webkit-user-select:none;user-select:none}.van-picker__toolbar{display:-webkit-flex;display:flex;height:44px;line-height:44px;-webkit-justify-content:space-between;justify-content:space-between}.van-picker__cancel,.van-picker__confirm{padding:0 15px;font-size:14px;color:#1989fa}.van-picker__cancel--hover,.van-picker__confirm--hover{background-color:#f2f3f5}.van-picker__title{max-width:50%;font-size:16px;font-weight:500;text-align:center}.van-picker__columns{position:relative;display:-webkit-flex;display:flex}.van-picker__column{-webkit-flex:1 1;flex:1 1;width:0}.van-picker__loading{position:absolute;top:0;right:0;bottom:0;left:0;z-index:4;display:-webkit-flex;display:flex;background-color:hsla(0,0%,100%,.9);-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-picker__frame,.van-picker__loading .van-loading{position:absolute;top:50%;left:0;z-index:1;width:100%;pointer-events:none;-webkit-transform:translateY(-50%);transform:translateY(-50%)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { transition } from '../mixins/transition';
3 import { safeArea } from '../mixins/safe-area';
4 VantComponent({
5 classes: [
6 'enter-class',
7 'enter-active-class',
8 'enter-to-class',
9 'leave-class',
10 'leave-active-class',
11 'leave-to-class'
12 ],
13 mixins: [transition(false), safeArea()],
14 props: {
15 transition: {
16 type: String,
17 observer: 'observeClass'
18 },
19 customStyle: String,
20 overlayStyle: String,
21 zIndex: {
22 type: Number,
23 value: 100
24 },
25 overlay: {
26 type: Boolean,
27 value: true
28 },
29 closeOnClickOverlay: {
30 type: Boolean,
31 value: true
32 },
33 position: {
34 type: String,
35 value: 'center',
36 observer: 'observeClass'
37 }
38 },
39 created() {
40 this.observeClass();
41 },
42 methods: {
43 onClickOverlay() {
44 this.$emit('click-overlay');
45 if (this.data.closeOnClickOverlay) {
46 this.$emit('close');
47 }
48 },
49 observeClass() {
50 const { transition, position } = this.data;
51 this.updateClasses(transition || position);
52 if (transition === 'none') {
53 this.set({ duration: 0 });
54 }
55 }
56 }
57 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-overlay": "../overlay/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <van-overlay
4 wx:if="{{ inited && overlay }}"
5 mask
6 show="{{ show }}"
7 z-index="{{ zIndex }}"
8 custom-style="{{ overlayStyle }}"
9 duration="{{ duration }}"
10 bind:click="onClickOverlay"
11 />
12 <view
13 wx:if="{{ inited }}"
14 class="custom-class {{ classes }} {{ utils.bem('popup', [position, { safe: isIPhoneX && safeAreaInsetBottom }]) }}"
15 style="z-index: {{ zIndex }}; -webkit-transition-duration:{{ currentDuration }}ms; transition-duration:{{ currentDuration }}ms; {{ display ? '' : 'display: none;' }} {{ customStyle }}"
16 bind:transitionend="onTransitionEnd"
17 >
18 <view wx:if="{{ safeAreaInsetTop }}" class="van-popup__safe-top" style="padding-top: {{ statusBarHeight }}px;"></view>
19 <slot />
20 </view>
1 @import '../common/index.wxss';.van-popup{position:fixed;top:50%;left:50%;max-height:100%;overflow-y:auto;background-color:#fff;box-sizing:border-box;-webkit-animation:ease both;animation:ease both;-webkit-overflow-scrolling:touch;transition-timing-function:ease}.van-popup--center{-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-popup--top{top:0;right:auto;bottom:auto;left:50%;width:100%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-popup--right{top:50%;right:0;bottom:auto;left:auto;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--bottom{top:auto;right:auto;bottom:0;left:50%;width:100%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-popup--left{top:50%;right:auto;bottom:auto;left:0;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--bottom.van-popup--safe{padding-bottom:34px}.van-popup--left .van-popup__safe-top,.van-popup--right .van-popup__safe-top,.van-popup--top .van-popup__safe-top{height:44px}.van-popup--bottom .van-popup__safe-top,.van-popup--center .van-popup__safe-top{padding-top:0!important}.van-scale-enter-active,.van-scale-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-scale-enter,.van-scale-leave-to{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7)}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-center-enter-active,.van-center-leave-active{transition-property:opacity}.van-center-enter,.van-center-leave-to{opacity:0}.van-bottom-enter-active,.van-bottom-leave-active,.van-left-enter-active,.van-left-leave-active,.van-right-enter-active,.van-right-leave-active,.van-top-enter-active,.van-top-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-bottom-enter,.van-bottom-leave-to{-webkit-transform:translate3d(-50%,100%,0);transform:translate3d(-50%,100%,0)}.van-top-enter,.van-top-leave-to{-webkit-transform:translate3d(-50%,-100%,0);transform:translate3d(-50%,-100%,0)}.van-left-enter,.van-left-leave-to{-webkit-transform:translate3d(-100%,-50%,0);transform:translate3d(-100%,-50%,0)}.van-right-enter,.van-right-leave-to{-webkit-transform:translate3d(100%,-50%,0);transform:translate3d(100%,-50%,0)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { BLUE } from '../common/color';
3 VantComponent({
4 props: {
5 inactive: Boolean,
6 percentage: Number,
7 pivotText: String,
8 pivotColor: String,
9 showPivot: {
10 type: Boolean,
11 value: true
12 },
13 color: {
14 type: String,
15 value: BLUE
16 },
17 textColor: {
18 type: String,
19 value: '#fff'
20 }
21 },
22 data: {
23 pivotWidth: 0,
24 progressWidth: 0
25 },
26 watch: {
27 pivotText: 'getWidth',
28 showPivot: 'getWidth'
29 },
30 computed: {
31 portionStyle() {
32 const width = (this.data.progressWidth - this.data.pivotWidth) * this.data.percentage / 100 + 'px';
33 const background = this.getCurrentColor();
34 return `width: ${width}; background: ${background}; `;
35 },
36 pivotStyle() {
37 const color = this.data.textColor;
38 const background = this.data.pivotColor || this.getCurrentColor();
39 return `color: ${color}; background: ${background}`;
40 },
41 text() {
42 return this.data.pivotText || this.data.percentage + '%';
43 }
44 },
45 mounted() {
46 this.getWidth();
47 },
48 methods: {
49 getCurrentColor() {
50 return this.data.inactive ? '#cacaca' : this.data.color;
51 },
52 getWidth() {
53 this.getRect('.van-progress').then(rect => {
54 this.set({
55 progressWidth: rect.width
56 });
57 });
58 this.getRect('.van-progress__pivot').then(rect => {
59 this.set({
60 pivotWidth: rect.width || 0
61 });
62 });
63 }
64 }
65 });
1 <view class="van-progress custom-class">
2 <view
3 class="van-progress__portion {{ showPivot && text ? 'van-progress__portion--with-pivot' : '' }}"
4 style="{{ portionStyle }}"
5 >
6 <view
7 wx:if="{{ showPivot && text }}"
8 style="{{ pivotStyle }}"
9 class="van-progress__pivot"
10 >
11 {{ text }}
12 </view>
13 </view>
14 </view>
1 @import '../common/index.wxss';.van-progress{height:4px;position:relative;border-radius:4px;background:#e5e5e5}.van-progress__portion{left:0;height:100%;position:absolute;border-radius:inherit}.van-progress__portion--with-pivot{border-top-right-radius:0;border-bottom-right-radius:0}.van-progress__pivot{top:50%;right:0;min-width:2em;padding:0 5px;font-size:10px;position:absolute;line-height:1.6;text-align:center;border-radius:1em;word-break:keep-all;box-sizing:border-box;background-color:#e5e5e5;-webkit-transform:translate(100%,-50%);transform:translate(100%,-50%)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 relation: {
5 name: 'radio',
6 type: 'descendant',
7 linked(target) {
8 const { value, disabled } = this.data;
9 target.set({
10 value: value,
11 disabled: disabled || target.data.disabled
12 });
13 }
14 },
15 props: {
16 value: null,
17 disabled: Boolean
18 },
19 watch: {
20 value(value) {
21 const children = this.getRelationNodes('../radio/index');
22 children.forEach(child => {
23 child.set({ value });
24 });
25 },
26 disabled(disabled) {
27 const children = this.getRelationNodes('../radio/index');
28 children.forEach(child => {
29 child.set({ disabled: disabled || child.data.disabled });
30 });
31 }
32 }
33 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 @import '../common/index.wxss';
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 relation: {
5 name: 'radio-group',
6 type: 'ancestor'
7 },
8 classes: ['icon-class', 'label-class'],
9 props: {
10 name: null,
11 value: null,
12 disabled: Boolean,
13 labelDisabled: Boolean,
14 labelPosition: String,
15 checkedColor: String
16 },
17 methods: {
18 emitChange(value) {
19 const instance = this.getRelationNodes('../radio-group/index')[0] || this;
20 instance.$emit('input', value);
21 instance.$emit('change', value);
22 },
23 onChange(event) {
24 this.emitChange(event.detail.value);
25 },
26 onClickLabel() {
27 if (!this.data.disabled && !this.data.labelDisabled) {
28 this.emitChange(this.data.name);
29 }
30 }
31 }
32 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="van-radio custom-class">
4 <view class="van-radio__input">
5 <radio-group bindchange="onChange">
6 <radio
7 value="{{ name }}"
8 checked="{{ value === name }}"
9 disabled="{{ disabled }}"
10 class="van-radio__control"
11 />
12 </radio-group>
13 <van-icon
14 class="{{ utils.bem('radio__icon', { disabled, checked: !disabled && name === value, check: !disabled && name !== value }) }}"
15 custom-class="icon-class"
16 color="{{ value === name ? checkedColor : '' }}"
17 name="{{ value === name ? 'checked' : 'circle' }}"
18 />
19 </view>
20 <view class="van-radio__label van-radio__label--{{ labelPosition }} label-class" bindtap="onClickLabel">
21 <slot />
22 </view>
23 </view>
1 @import '../common/index.wxss';.van-radio{overflow:hidden;line-height:1;-webkit-user-select:none;user-select:none}.van-radio__input,.van-radio__label{display:inline-block;vertical-align:middle}.van-radio__input{position:relative;font-size:20px}.van-radio__control{z-index:1;position:absolute;top:0;left:0;width:100%;height:100%;margin:0;opacity:0}.van-radio__label{margin-left:10px;color:#333;font-size:16px;line-height:20px}.van-radio__label--left{margin:0 10px 0 0;float:left}.van-radio__label:empty{margin:0}.van-radio__icon{pointer-events:none;display:block;line-height:0}.van-radio__icon--disabled{color:#e5e5e5}.van-radio__icon--checked{color:#1989fa}.van-radio__icon--check{color:#c9c9c9}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 classes: ['icon-class'],
5 props: {
6 readonly: Boolean,
7 disabled: Boolean,
8 size: {
9 type: Number,
10 value: 20
11 },
12 icon: {
13 type: String,
14 value: 'star'
15 },
16 voidIcon: {
17 type: String,
18 value: 'star-o'
19 },
20 color: {
21 type: String,
22 value: '#ffd21e'
23 },
24 voidColor: {
25 type: String,
26 value: '#c7c7c7'
27 },
28 disabledColor: {
29 type: String,
30 value: '#bdbdbd'
31 },
32 count: {
33 type: Number,
34 value: 5
35 },
36 value: {
37 type: Number,
38 value: 0
39 }
40 },
41 data: {
42 innerValue: 0
43 },
44 watch: {
45 value(value) {
46 if (value !== this.data.innerValue) {
47 this.set({ innerValue: value });
48 }
49 }
50 },
51 computed: {
52 list() {
53 const { count, innerValue } = this.data;
54 return Array.from({ length: count }, (_, index) => index < innerValue);
55 }
56 },
57 methods: {
58 onSelect(event) {
59 const { data } = this;
60 const { index } = event.currentTarget.dataset;
61 if (!data.disabled && !data.readonly) {
62 this.set({ innerValue: index + 1 });
63 this.$emit('input', index + 1);
64 this.$emit('change', index + 1);
65 }
66 },
67 onTouchMove(event) {
68 const { clientX, clientY } = event.touches[0];
69 this.getRect('.van-rate__item', true).then(list => {
70 const target = list.find(item => clientX >= item.left &&
71 clientX <= item.right &&
72 clientY >= item.top &&
73 clientY <= item.bottom);
74 if (target != null) {
75 this.onSelect(Object.assign({}, event, { currentTarget: target }));
76 }
77 });
78 }
79 }
80 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 <view
2 class="van-rate custom-class"
3 bind:touchmove="onTouchMove"
4 >
5 <van-icon
6 wx:for="{{ list }}"
7 wx:key="index"
8 class="van-rate__item"
9 custom-class="icon-class"
10 size="{{ size }}px"
11 data-index="{{ index }}"
12 name="{{ item ? icon : voidIcon }}"
13 color="{{ disabled ? disabledColor : item ? color : voidColor }}"
14 bind:click="onSelect"
15 />
16 </view>
1 @import '../common/index.wxss';.van-rate{-webkit-user-select:none;user-select:none}.van-rate__item{width:1em;padding:0 2px;box-sizing:initial}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 relation: {
4 name: 'col',
5 type: 'descendant',
6 linked(target) {
7 if (this.data.gutter) {
8 target.setGutter(this.data.gutter);
9 }
10 }
11 },
12 props: {
13 gutter: Number
14 },
15 watch: {
16 gutter: 'setGutter'
17 },
18 mounted() {
19 if (this.data.gutter) {
20 this.setGutter();
21 }
22 },
23 methods: {
24 setGutter() {
25 const { gutter } = this.data;
26 const margin = `-${Number(gutter) / 2}px`;
27 const style = gutter
28 ? `margin-right: ${margin}; margin-left: ${margin};`
29 : '';
30 this.set({ style });
31 this.getRelationNodes('../col/index').forEach(col => {
32 col.setGutter(this.data.gutter);
33 });
34 }
35 }
36 });
1 {
2 "component": true
3 }
1 <view class="custom-class van-row" style="{{ style }}">
2 <slot />
3 </view>
1 @import '../common/index.wxss';.van-row:after{content:"";display:table;clear:both}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 classes: ['field-class', 'input-class', 'cancel-class'],
5 props: {
6 focus: Boolean,
7 error: Boolean,
8 disabled: Boolean,
9 readonly: Boolean,
10 inputAlign: String,
11 showAction: Boolean,
12 useActionSlot: Boolean,
13 placeholder: String,
14 placeholderStyle: String,
15 background: {
16 type: String,
17 value: '#ffffff'
18 },
19 maxlength: {
20 type: Number,
21 value: -1
22 },
23 shape: {
24 type: String,
25 value: 'square'
26 },
27 label: String
28 },
29 methods: {
30 onChange(event) {
31 this.set({ value: event.detail });
32 this.$emit('change', event.detail);
33 },
34 onCancel() {
35 this.set({ value: '' });
36 this.$emit('cancel');
37 this.$emit('change', '');
38 },
39 onSearch() {
40 this.$emit('search', this.data.value);
41 },
42 onFocus() {
43 this.$emit('focus');
44 },
45 onBlur() {
46 this.$emit('blur');
47 },
48 onClear() {
49 this.$emit('clear');
50 },
51 }
52 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-field": "../field/index"
6 }
7 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="{{ utils.bem('search', { withaction: showAction || useActionSlot }) }} custom-class"
5 style="background: {{ background }}"
6 >
7 <view class="{{ utils.bem('search__content', [shape]) }}">
8 <view class="van-search__label" wx:if="{{ label }}">{{ label }}</view>
9 <slot wx:else name="label" />
10
11 <van-field
12 clearable
13 type="search"
14 left-icon="search"
15 focus="{{ focus }}"
16 error="{{ error }}"
17 border="{{ false }}"
18 confirm-type="search"
19 class="van-search__field field-class"
20 value="{{ value }}"
21 disabled="{{ disabled }}"
22 readonly="{{ readonly }}"
23 maxlength="{{ maxlength }}"
24 input-align="{{ inputAlign }}"
25 input-class="input-class"
26 placeholder="{{ placeholder }}"
27 placeholder-style="{{ placeholderStyle }}"
28 custom-style="padding: 5px 10px 5px 0; background-color: transparent;"
29 bind:blur="onBlur"
30 bind:focus="onFocus"
31 bind:change="onChange"
32 bind:confirm="onSearch"
33 bind:clear="onClear"
34 />
35 </view>
36
37 <view
38 wx:if="{{ showAction || useActionSlot }}"
39 class="van-search__action"
40 hover-class="van-search__action--hover"
41 hover-stay-time="70"
42 >
43 <slot wx:if="{{ useActionSlot }}" name="action" />
44 <view wx:else bind:tap="onCancel" class="cancel-class">取消</view>
45 </view>
46 </view>
1 @import '../common/index.wxss';.van-search{padding:10px 16px;-webkit-align-items:center;align-items:center;box-sizing:border-box}.van-search,.van-search__content{display:-webkit-flex;display:flex}.van-search__content{padding-left:10px;background-color:#f7f8fa;border-radius:2px;-webkit-flex:1;flex:1}.van-search__content--round{border-radius:17px}.van-search__label{padding:0 5px;font-size:14px;line-height:34px;color:#333}.van-search__field{-webkit-flex:1;flex:1}.van-search__field__left-icon{color:#999}.van-search--withaction{padding-right:0}.van-search input::-webkit-search-cancel-button,.van-search input::-webkit-search-decoration,.van-search input::-webkit-search-results-button,.van-search input::-webkit-search-results-decoration{display:none}.van-search__action{padding:0 10px;font-size:14px;line-height:34px;color:#333}.van-search__action--hover{background-color:#f2f3f5}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { touch } from '../mixins/touch';
3 VantComponent({
4 mixins: [touch],
5 props: {
6 disabled: Boolean,
7 useButtonSlot: Boolean,
8 activeColor: String,
9 inactiveColor: String,
10 max: {
11 type: Number,
12 value: 100
13 },
14 min: {
15 type: Number,
16 value: 0
17 },
18 step: {
19 type: Number,
20 value: 1
21 },
22 value: {
23 type: Number,
24 value: 0
25 },
26 barHeight: {
27 type: String,
28 value: '2px'
29 }
30 },
31 watch: {
32 value(value) {
33 this.updateValue(value, false);
34 }
35 },
36 created() {
37 this.updateValue(this.data.value);
38 },
39 methods: {
40 onTouchStart(event) {
41 if (this.data.disabled)
42 return;
43 this.touchStart(event);
44 this.startValue = this.format(this.data.value);
45 },
46 onTouchMove(event) {
47 if (this.data.disabled)
48 return;
49 this.touchMove(event);
50 this.getRect('.van-slider').then((rect) => {
51 const diff = this.deltaX / rect.width * 100;
52 this.updateValue(this.startValue + diff, false, true);
53 });
54 },
55 onTouchEnd() {
56 if (this.data.disabled)
57 return;
58 this.updateValue(this.data.value, true);
59 },
60 onClick(event) {
61 if (this.data.disabled)
62 return;
63 this.getRect('.van-slider').then((rect) => {
64 const value = (event.detail.x - rect.left) / rect.width * 100;
65 this.updateValue(value, true);
66 });
67 },
68 updateValue(value, end, drag) {
69 value = this.format(value);
70 this.set({
71 value,
72 barStyle: `width: ${value}%; height: ${this.data.barHeight};`
73 });
74 if (drag) {
75 this.$emit('drag', { value });
76 }
77 if (end) {
78 this.$emit('change', value);
79 }
80 },
81 format(value) {
82 const { max, min, step } = this.data;
83 return Math.round(Math.max(min, Math.min(value, max)) / step) * step;
84 }
85 }
86 });
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ utils.bem('slider', { disabled }) }}"
5 style="{{ inactiveColor ? 'background:' + inactiveColor : '' }}"
6 bind:tap="onClick"
7 >
8 <view
9 class="van-slider__bar"
10 style="{{ barStyle }}; {{ activeColor ? 'background:' + activeColor : '' }}"
11 >
12 <view
13 class="van-slider__button-wrapper"
14 bind:touchstart="onTouchStart"
15 catch:touchmove="onTouchMove"
16 bind:touchend="onTouchEnd"
17 bind:touchcancel="onTouchEnd"
18 >
19 <slot
20 wx:if="{{ useButtonSlot }}"
21 name="button"
22 />
23 <view
24 wx:else
25 class="van-slider__button"
26 />
27 </view>
28 </view>
29 </view>
1 @import '../common/index.wxss';.van-slider{position:relative;border-radius:999px;background-color:#e5e5e5}.van-slider__bar{position:relative;border-radius:inherit;background-color:#1989fa}.van-slider__button{width:20px;height:20px;border-radius:50%;background-color:#fff;box-shadow:0 1px 2px rgba(0,0,0,.5)}.van-slider__button-wrapper{position:absolute;top:50%;right:0;-webkit-transform:translate3d(50%,-50%,0);transform:translate3d(50%,-50%,0)}.van-slider__button-wrapper:after{content:"";position:absolute;width:200%;height:200%;top:-50%;left:-50%}.van-slider--disabled{opacity:.3}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 classes: [
5 'input-class',
6 'plus-class',
7 'minus-class'
8 ],
9 props: {
10 value: null,
11 integer: Boolean,
12 disabled: Boolean,
13 inputWidth: String,
14 asyncChange: Boolean,
15 disableInput: Boolean,
16 min: {
17 type: null,
18 value: 1
19 },
20 max: {
21 type: null,
22 value: Number.MAX_SAFE_INTEGER
23 },
24 step: {
25 type: null,
26 value: 1
27 }
28 },
29 computed: {
30 minusDisabled() {
31 return this.data.disabled || this.data.value <= this.data.min;
32 },
33 plusDisabled() {
34 return this.data.disabled || this.data.value >= this.data.max;
35 }
36 },
37 watch: {
38 value(value) {
39 if (value === '') {
40 return;
41 }
42 const newValue = this.range(value);
43 if (typeof newValue === 'number' && value !== newValue) {
44 this.set({ value: newValue });
45 }
46 }
47 },
48 data: {
49 focus: false
50 },
51 created() {
52 this.set({
53 value: this.range(this.data.value)
54 });
55 },
56 methods: {
57 onFocus(event) {
58 this.$emit('focus', event.detail);
59 },
60 onBlur(event) {
61 const value = this.range(this.data.value);
62 this.triggerInput(value);
63 this.$emit('blur', event.detail);
64 },
65 // limit value range
66 range(value) {
67 return Math.max(Math.min(this.data.max, value), this.data.min);
68 },
69 onInput(event) {
70 const { value = '' } = event.detail || {};
71 this.triggerInput(value);
72 },
73 onChange(type) {
74 if (this.data[`${type}Disabled`]) {
75 this.$emit('overlimit', type);
76 return;
77 }
78 const diff = type === 'minus' ? -this.data.step : +this.data.step;
79 const value = Math.round((this.data.value + diff) * 100) / 100;
80 this.triggerInput(this.range(value));
81 this.$emit(type);
82 },
83 onMinus() {
84 this.onChange('minus');
85 },
86 onPlus() {
87 this.onChange('plus');
88 },
89 triggerInput(value) {
90 this.set({
91 value: this.data.asyncChange ? this.data.value : value
92 });
93 this.$emit('change', value);
94 }
95 }
96 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="van-stepper custom-class">
4 <view
5 class="minus-class {{ utils.bem('stepper__minus', { disabled: minusDisabled }) }}"
6 hover-class="van-stepper__minus--hover"
7 hover-stay-time="70"
8 bind:tap="onMinus"
9 />
10 <input
11 type="{{ integer ? 'number' : 'digit' }}"
12 class="input-class {{ utils.bem('stepper__input', { disabled: disabled || disableInput }) }}"
13 style="{{ inputWidth ? 'width: ' + inputWidth : '' }}"
14 value="{{ value }}"
15 focus="{{ focus }}"
16 disabled="{{ disabled || disableInput }}"
17 bindinput="onInput"
18 bind:focus="onFocus"
19 bind:blur="onBlur"
20 />
21 <view
22 class="plus-class {{ utils.bem('stepper__plus', { disabled: plusDisabled }) }}"
23 hover-class="van-stepper__plus--hover"
24 hover-stay-time="70"
25 bind:tap="onPlus"
26 />
27 </view>
1 @import '../common/index.wxss';.van-stepper{font-size:0}.van-stepper__minus,.van-stepper__plus{position:relative;display:inline-block;width:28px;height:28px;padding:5px;margin:1px;vertical-align:middle;background-color:#f2f3f5;border:0;box-sizing:border-box}.van-stepper__minus:before,.van-stepper__plus:before{width:9px;height:1px}.van-stepper__minus:after,.van-stepper__plus:after{width:1px;height:9px}.van-stepper__minus:after,.van-stepper__minus:before,.van-stepper__plus:after,.van-stepper__plus:before{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;background-color:#333;content:""}.van-stepper__minus--hover,.van-stepper__plus--hover{background-color:#e8e8e8}.van-stepper__minus--disabled,.van-stepper__plus--disabled{background-color:#f7f8fa}.van-stepper__minus--disabled:after,.van-stepper__minus--disabled:before,.van-stepper__plus--disabled:after,.van-stepper__plus--disabled:before{background-color:#c9c9c9}.van-stepper__minus--disabled.van-stepper__minus--hover,.van-stepper__minus--disabled.van-stepper__plus--hover,.van-stepper__plus--disabled.van-stepper__minus--hover,.van-stepper__plus--disabled.van-stepper__plus--hover{background-color:#f7f8fa}.van-stepper__minus{border-radius:4px 0 0 4px}.van-stepper__minus:after{display:none}.van-stepper__plus{border-radius:0 4px 4px 0}.van-stepper__input{display:inline-block;width:30px;height:26px;padding:1px;margin:1px;font-size:14px;color:#333;text-align:center;vertical-align:middle;background-color:#f2f3f5;border:0;border-width:1px 0;border-radius:0;box-sizing:initial;-webkit-appearance:none}.van-stepper__input--disabled{color:#c9c9c9;background-color:#f2f3f5}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { GREEN } from '../common/color';
3 VantComponent({
4 props: {
5 icon: String,
6 steps: Array,
7 active: Number,
8 direction: {
9 type: String,
10 value: 'horizontal'
11 },
12 activeColor: {
13 type: String,
14 value: GREEN
15 }
16 }
17 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="custom-class {{ utils.bem('steps', [direction]) }}">
4 <view class="van-step__wrapper">
5 <view
6 wx:for="{{ steps }}"
7 wx:key="index"
8 class="{{ utils.bem('step', [direction, status(index, active)]) }} van-hairline"
9 >
10 <view class="van-step__title" style="{{ index === active ? 'color: ' + activeColor : '' }}">
11 <view>{{ item.text }}</view>
12 <view>{{ item.desc }}</view>
13 </view>
14 <view class="van-step__circle-container">
15 <view class="van-step__circle" wx:if="{{ index !== active }}" style="{{ index < active ? 'background-color: ' + activeColor : '' }}" />
16 <van-icon wx:else name="checked" color="{{ activeColor }}" custom-class="van-step__active" />
17 </view>
18 <view wx:if="{{ index !== steps.length - 1 }}" class="van-step__line" style="{{ index < active ? 'background-color: ' + activeColor : '' }}" />
19 </view>
20 </view>
21 </view>
22
23 <wxs module="status">
24 function get(index, active) {
25 if (index < active) {
26 return 'finish';
27 } else if (index === active) {
28 return 'process';
29 }
30
31 return '';
32 }
33
34 module.exports = get;
35 </wxs>
1 @import '../common/index.wxss';.van-steps{overflow:hidden;background-color:#fff}.van-steps--horizontal{padding:10px}.van-steps--horizontal .van-step__wrapper{position:relative;display:-webkit-flex;display:flex;overflow:hidden}.van-steps--vertical{padding-left:10px}.van-steps--vertical .van-step__wrapper{padding:0 0 0 20px}.van-step{position:relative;-webkit-flex:1;flex:1;font-size:14px;color:#999}.van-step--finish{color:#333}.van-step__circle{width:5px;height:5px;background-color:#999;border-radius:50%}.van-step--horizontal{padding-bottom:14px}.van-step--horizontal:first-child .van-step__title{-webkit-transform:none;transform:none}.van-step--horizontal:first-child .van-step__circle-container{padding:0 8px 0 0;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal:last-child{position:absolute;right:0;width:auto}.van-step--horizontal:last-child .van-step__title{text-align:right;-webkit-transform:none;transform:none}.van-step--horizontal:last-child .van-step__circle-container{right:0;padding:0 0 0 8px;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal .van-step__circle-container{position:absolute;bottom:6px;z-index:1;padding:0 8px;background-color:#fff;-webkit-transform:translate3d(-50%,50%,0);transform:translate3d(-50%,50%,0)}.van-step--horizontal .van-step__title{display:inline-block;font-size:12px;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-step--horizontal .van-step__line{position:absolute;right:0;bottom:6px;left:0;height:1px;background-color:#eee;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal.van-step--process{color:#333}.van-step--horizontal.van-step--process .van-step__active{display:block;font-size:12px;line-height:1}.van-step--vertical{padding:10px 10px 10px 0;font-size:14px;line-height:18px}.van-step--vertical:after{border-bottom-width:1px}.van-step--vertical:last-child:after{border-bottom-width:none}.van-step--vertical:first-child:before{position:absolute;top:0;left:-15px;z-index:1;width:1px;height:20px;background-color:#fff;content:""}.van-step--vertical .van-step__active,.van-step--vertical .van-step__circle,.van-step--vertical .van-step__line{position:absolute;top:19px;left:-14px;z-index:2;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-step--vertical .van-step__active{font-size:12px;line-height:1}.van-step--vertical .van-step__line{z-index:1;width:1px;height:100%;background-color:#eee;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({
4 mixins: [safeArea()],
5 classes: [
6 'bar-class',
7 'price-class',
8 'button-class'
9 ],
10 props: {
11 tip: null,
12 type: Number,
13 price: null,
14 label: String,
15 loading: Boolean,
16 disabled: Boolean,
17 buttonText: String,
18 currency: {
19 type: String,
20 value: '¥'
21 },
22 buttonType: {
23 type: String,
24 value: 'danger'
25 }
26 },
27 computed: {
28 hasPrice() {
29 return typeof this.data.price === 'number';
30 },
31 priceStr() {
32 return (this.data.price / 100).toFixed(2);
33 },
34 tipStr() {
35 const { tip } = this.data;
36 return typeof tip === 'string' ? tip : '';
37 }
38 },
39 methods: {
40 onSubmit(event) {
41 this.$emit('submit', event.detail);
42 }
43 }
44 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-button": "../button/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="van-submit-bar custom-class">
4 <slot name="top" />
5
6 <view wx:if="{{ tip }}" class="van-submit-bar__tip">
7 {{ tipStr }}<slot name="tip" />
8 </view>
9
10 <view class="bar-class {{ utils.bem('submit-bar__bar', { safe: safeAreaInsetBottom && isIPhoneX }) }}">
11 <slot />
12 <view class="van-submit-bar__text">
13 <block wx:if="{{ hasPrice }}">
14 <text>{{ label || '合计:' }}</text>
15 <text class="van-submit-bar__price price-class">
16 <text class="van-submit-bar__currency">{{ currency }}</text> {{ priceStr }}
17 </text>
18 </block>
19 </view>
20 <van-button
21 square
22 size="large"
23 type="{{ buttonType }}"
24 loading="{{ loading }}"
25 disabled="{{ disabled }}"
26 class="van-submit-bar__button"
27 custom-class="button-class"
28 bind:click="onSubmit"
29 >
30 {{ loading ? '' : buttonText }}
31 </van-button>
32 </view>
33 </view>
1 @import '../common/index.wxss';.van-submit-bar{z-index:100;position:fixed;bottom:0;left:0;width:100%;-webkit-user-select:none;user-select:none}.van-submit-bar__tip{padding:10px;color:#f56723;font-size:12px;line-height:18px;background-color:#fff7cc}.van-submit-bar__bar{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:50px;background-color:#fff;font-size:14px}.van-submit-bar__bar--safe{padding-bottom:34px}.van-submit-bar__text{-webkit-flex:1;flex:1;color:#333;font-weight:500;text-align:right}.van-submit-bar__price{color:#f44;font-size:18px;padding-right:12px}.van-submit-bar__currency{font-size:14px}.van-submit-bar__button button{width:110px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { touch } from '../mixins/touch';
3 const THRESHOLD = 0.3;
4 VantComponent({
5 props: {
6 disabled: Boolean,
7 leftWidth: {
8 type: Number,
9 value: 0
10 },
11 rightWidth: {
12 type: Number,
13 value: 0
14 },
15 asyncClose: Boolean
16 },
17 mixins: [touch],
18 data: {
19 catchMove: true
20 },
21 created() {
22 this.offset = 0;
23 },
24 methods: {
25 open(position) {
26 const { leftWidth, rightWidth } = this.data;
27 const offset = position === 'left' ? leftWidth : -rightWidth;
28 this.swipeMove(offset);
29 },
30 close() {
31 this.swipeMove(0);
32 },
33 swipeMove(offset = 0) {
34 this.offset = offset;
35 const transform = `translate3d(${offset}px, 0, 0)`;
36 const transition = this.draging
37 ? 'none'
38 : '.6s cubic-bezier(0.18, 0.89, 0.32, 1)';
39 this.set({
40 wrapperStyle: `
41 -webkit-transform: ${transform};
42 -webkit-transition: ${transition};
43 transform: ${transform};
44 transition: ${transition};
45 `
46 });
47 },
48 swipeLeaveTransition() {
49 const { leftWidth, rightWidth } = this.data;
50 const { offset } = this;
51 if (rightWidth > 0 && -offset > rightWidth * THRESHOLD) {
52 this.open('right');
53 }
54 else if (leftWidth > 0 && offset > leftWidth * THRESHOLD) {
55 this.open('left');
56 }
57 else {
58 this.swipeMove(0);
59 }
60 },
61 startDrag(event) {
62 if (this.data.disabled) {
63 return;
64 }
65 this.draging = true;
66 this.startOffset = this.offset;
67 this.firstDirection = '';
68 this.touchStart(event);
69 },
70 noop() { },
71 onDrag(event) {
72 if (this.data.disabled) {
73 return;
74 }
75 this.touchMove(event);
76 if (!this.firstDirection) {
77 this.firstDirection = this.direction;
78 this.set({ catchMove: this.firstDirection === 'horizontal' });
79 }
80 if (this.firstDirection === 'vertical') {
81 return;
82 }
83 const { leftWidth, rightWidth } = this.data;
84 const offset = this.startOffset + this.deltaX;
85 if ((rightWidth > 0 && -offset > rightWidth) ||
86 (leftWidth > 0 && offset > leftWidth)) {
87 return;
88 }
89 this.swipeMove(offset);
90 },
91 endDrag() {
92 if (this.data.disabled) {
93 return;
94 }
95 this.draging = false;
96 this.swipeLeaveTransition();
97 },
98 onClick(event) {
99 const { key: position = 'outside' } = event.currentTarget.dataset;
100 this.$emit('click', position);
101 if (!this.offset) {
102 return;
103 }
104 if (this.data.asyncClose) {
105 this.$emit('close', { position, instance: this });
106 }
107 else {
108 this.swipeMove(0);
109 }
110 }
111 }
112 });
1 <view
2 class="van-swipe-cell"
3 data-key="cell"
4 catchtap="onClick"
5 bindtouchstart="startDrag"
6 catchtouchmove="{{ catchMove ? 'noop' : '' }}"
7 capture-bind:touchmove="onDrag"
8 catchtouchend="endDrag"
9 catchtouchcancel="endDrag"
10 >
11 <view style="{{ wrapperStyle }}">
12 <view wx:if="{{ leftWidth }}" class="van-swipe-cell__left" data-key="left" catch:tap="onClick">
13 <slot name="left" />
14 </view>
15 <slot />
16 <view wx:if="{{ rightWidth }}" class="van-swipe-cell__right" data-key="right" catch:tap="onClick">
17 <slot name="right" />
18 </view>
19 </view>
20 </view>
1 @import '../common/index.wxss';.van-swipe-cell{position:relative;overflow:hidden}.van-swipe-cell__left,.van-swipe-cell__right{position:absolute;top:0;height:100%}.van-swipe-cell__left{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-swipe-cell__right{right:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 props: {
5 value: null,
6 title: String,
7 border: Boolean,
8 checked: Boolean,
9 loading: Boolean,
10 disabled: Boolean,
11 activeColor: String,
12 inactiveColor: String,
13 size: {
14 type: String,
15 value: '24px'
16 },
17 activeValue: {
18 type: null,
19 value: true
20 },
21 inactiveValue: {
22 type: null,
23 value: false
24 }
25 },
26 watch: {
27 checked(value) {
28 this.set({ value });
29 }
30 },
31 created() {
32 this.set({ value: this.data.checked });
33 },
34 methods: {
35 onChange(event) {
36 this.$emit('change', event.detail);
37 }
38 }
39 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-cell": "../cell/index",
5 "van-switch": "../switch/index"
6 }
7 }
1 <van-cell
2 center
3 title="{{ title }}"
4 border="{{ border }}"
5 custom-class="van-switch-cell"
6 >
7 <van-switch
8 size="{{ size }}"
9 checked="{{ checked }}"
10 loading="{{ loading }}"
11 disabled="{{ disabled }}"
12 active-color="{{ activeColor }}"
13 inactive-color="{{ inactiveColor }}"
14 active-value="{{ activeValue }}"
15 inactive-value="{{ inactiveValue }}"
16 custom-class="van-switch-cell__switch"
17 bind:change="onChange"
18 />
19 </van-cell>
1 @import '../common/index.wxss';.van-switch-cell{padding-top:9px;padding-bottom:9px}.van-switch-cell__switch{vertical-align:middle}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 field: true,
4 classes: ['node-class'],
5 props: {
6 checked: null,
7 loading: Boolean,
8 disabled: Boolean,
9 activeColor: String,
10 inactiveColor: String,
11 size: {
12 type: String,
13 value: '30px'
14 },
15 activeValue: {
16 type: null,
17 value: true
18 },
19 inactiveValue: {
20 type: null,
21 value: false
22 }
23 },
24 watch: {
25 checked(value) {
26 this.set({ value });
27 }
28 },
29 created() {
30 this.set({ value: this.data.checked });
31 },
32 methods: {
33 onClick() {
34 const { activeValue, inactiveValue } = this.data;
35 if (!this.data.disabled && !this.data.loading) {
36 const checked = this.data.checked === activeValue;
37 const value = checked ? inactiveValue : activeValue;
38 this.$emit('input', value);
39 this.$emit('change', value);
40 }
41 }
42 }
43 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-loading": "../loading/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ utils.bem('switch', { on: value === activeValue, disabled }) }}"
5 style="font-size: {{ size }}; {{ (checked ? activeColor : inactiveColor) ? 'background-color: ' + (checked ? activeColor : inactiveColor ) : '' }}"
6 bind:tap="onClick"
7 >
8 <view class="van-switch__node node-class">
9 <van-loading wx:if="{{ loading }}" size="50%" custom-class="van-switch__loading" />
10 </view>
11 </view>
1 @import '../common/index.wxss';.van-switch{display:inline-block;position:relative;width:2em;border:1px solid rgba(0,0,0,.1);border-radius:1em;box-sizing:initial;transition:background-color .3s}.van-switch,.van-switch__node{height:1em;background-color:#fff}.van-switch__node{top:0;left:0;position:absolute;border-radius:100%;width:1em;z-index:1;transition:.3s;box-shadow:0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05)}.van-switch__loading{top:25%;left:25%;position:absolute!important}.van-switch--on{background-color:#1989fa}.van-switch--on .van-switch__node{-webkit-transform:translateX(1em);transform:translateX(1em)}.van-switch--disabled{opacity:.4}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 relation: {
4 name: 'tabs',
5 type: 'ancestor'
6 },
7 props: {
8 dot: Boolean,
9 info: null,
10 title: String,
11 disabled: Boolean,
12 titleStyle: String
13 },
14 data: {
15 width: null,
16 inited: false,
17 active: false,
18 animated: false
19 },
20 watch: {
21 title: 'update',
22 disabled: 'update',
23 dot: 'update',
24 info: 'update',
25 titleStyle: 'update'
26 },
27 methods: {
28 update() {
29 const parent = this.getRelationNodes('../tabs/index')[0];
30 if (parent) {
31 parent.updateTabs();
32 }
33 }
34 }
35 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 wx:if="{{ animated || inited }}"
5 class="custom-class {{ utils.bem('tab__pane', { active, inactive: !active }) }}"
6 style="{{ animated || active ? '' : 'display: none;' }} {{ width ? 'width:' + width + 'px;' : '' }}"
7 >
8 <slot />
9 </view>
1 @import '../common/index.wxss';.van-tab__pane{box-sizing:border-box;overflow-y:auto}.van-tab__pane--active{height:auto}.van-tab__pane--inactive{height:0;overflow:visible}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 info: null,
5 icon: String,
6 dot: Boolean
7 },
8 relation: {
9 name: 'tabbar',
10 type: 'ancestor',
11 linked(target) {
12 this.parent = target;
13 }
14 },
15 data: {
16 active: false
17 },
18 methods: {
19 onClick() {
20 if (this.parent) {
21 this.parent.onChange(this);
22 }
23 this.$emit('click');
24 },
25 setActive({ active, color }) {
26 if (this.data.active !== active) {
27 return this.set({ active, color });
28 }
29 return Promise.resolve();
30 }
31 }
32 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-info": "../info/index"
6 }
7 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="{{ utils.bem('tabbar-item', { active }) }} custom-class"
5 style="{{ active && color ? 'color: ' + color : '' }}"
6 bind:tap="onClick"
7 >
8 <view class="{{ utils.bem('tabbar-item__icon', { dot }) }}">
9 <van-icon
10 wx:if="{{ icon }}"
11 name="{{ icon }}"
12 customStyle="display: block"
13 />
14 <block wx:else>
15 <slot
16 wx:if="{{ active }}"
17 name="icon-active"
18 />
19 <slot wx:else name="icon" />
20 </block>
21 <van-info
22 wx:if="{{ info !== null }}"
23 info="{{ info }}"
24 custom-style="margin-top: 2px"
25 />
26 </view>
27 <view class="van-tabbar-item__text">
28 <slot />
29 </view>
30 </view>
1 @import '../common/index.wxss';:host{-webkit-flex:1;flex:1}.van-tabbar-item{color:#7d7e80;height:100%;display:-webkit-flex;display:flex;line-height:1;font-size:12px;-webkit-align-items:center;align-items:center;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center}.van-tabbar-item__icon{font-size:18px;margin-bottom:5px;position:relative}.van-tabbar-item__icon--dot:after{top:0;right:-8px;width:8px;height:8px;content:" ";position:absolute;border-radius:100%;background-color:#f44}.van-tabbar-item__icon image{width:30px;height:18px;display:block}.van-tabbar-item--active{color:#1989fa}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { safeArea } from '../mixins/safe-area';
3 VantComponent({
4 mixins: [safeArea()],
5 relation: {
6 name: 'tabbar-item',
7 type: 'descendant',
8 linked(target) {
9 this.children = this.children || [];
10 this.children.push(target);
11 this.setActiveItem();
12 },
13 unlinked(target) {
14 this.children = this.children || [];
15 this.children = this.children.filter(item => item !== target);
16 this.setActiveItem();
17 }
18 },
19 props: {
20 active: Number,
21 activeColor: String,
22 fixed: {
23 type: Boolean,
24 value: true
25 },
26 zIndex: {
27 type: Number,
28 value: 1
29 }
30 },
31 watch: {
32 active(active) {
33 this.currentActive = active;
34 this.setActiveItem();
35 }
36 },
37 created() {
38 this.currentActive = this.data.active;
39 },
40 methods: {
41 setActiveItem() {
42 if (!Array.isArray(this.children) || !this.children.length) {
43 return Promise.resolve();
44 }
45 return Promise.all(this.children.map((item, index) => item.setActive({
46 active: index === this.currentActive,
47 color: this.data.activeColor
48 })));
49 },
50 onChange(child) {
51 const active = (this.children || []).indexOf(child);
52 if (active !== this.currentActive && active !== -1) {
53 this.currentActive = active;
54 this.setActiveItem().then(() => {
55 this.$emit('change', active);
56 });
57 }
58 }
59 }
60 });
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class van-hairline--top-bottom {{ utils.bem('tabbar', { fixed, safe: isIPhoneX && safeAreaInsetBottom }) }}"
5 style="{{ zIndex ? 'z-index: ' + zIndex : '' }}"
6 >
7 <slot />
8 </view>
1 @import '../common/index.wxss';.van-tabbar{display:-webkit-flex;display:flex;width:100%;height:50px;background-color:#fff}.van-tabbar--fixed{position:fixed;bottom:0;left:0}.van-tabbar--safe{padding-bottom:34px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { touch } from '../mixins/touch';
3 VantComponent({
4 mixins: [touch],
5 classes: ['nav-class', 'tab-class', 'tab-active-class', 'line-class'],
6 relation: {
7 name: 'tab',
8 type: 'descendant',
9 linked(child) {
10 this.child.push(child);
11 this.updateTabs(this.data.tabs.concat(child.data));
12 },
13 unlinked(child) {
14 const index = this.child.indexOf(child);
15 const { tabs } = this.data;
16 tabs.splice(index, 1);
17 this.child.splice(index, 1);
18 this.updateTabs(tabs);
19 }
20 },
21 props: {
22 color: String,
23 sticky: Boolean,
24 animated: Boolean,
25 swipeable: Boolean,
26 lineWidth: {
27 type: Number,
28 value: -1
29 },
30 lineHeight: {
31 type: Number,
32 value: -1
33 },
34 active: {
35 type: Number,
36 value: 0
37 },
38 type: {
39 type: String,
40 value: 'line'
41 },
42 border: {
43 type: Boolean,
44 value: true
45 },
46 duration: {
47 type: Number,
48 value: 0.3
49 },
50 zIndex: {
51 type: Number,
52 value: 1
53 },
54 swipeThreshold: {
55 type: Number,
56 value: 4
57 },
58 offsetTop: {
59 type: Number,
60 value: 0
61 }
62 },
63 data: {
64 tabs: [],
65 lineStyle: '',
66 scrollLeft: 0,
67 scrollable: false,
68 trackStyle: '',
69 wrapStyle: '',
70 position: ''
71 },
72 watch: {
73 swipeThreshold() {
74 this.set({
75 scrollable: this.child.length > this.data.swipeThreshold
76 });
77 },
78 color: 'setLine',
79 lineWidth: 'setLine',
80 lineHeight: 'setLine',
81 active: 'setActiveTab',
82 animated: 'setTrack',
83 offsetTop: 'setWrapStyle'
84 },
85 beforeCreate() {
86 this.child = [];
87 },
88 mounted() {
89 this.setLine(true);
90 this.setTrack();
91 this.scrollIntoView();
92 this.getRect('.van-tabs__wrap').then((rect) => {
93 this.navHeight = rect.height;
94 this.observerContentScroll();
95 });
96 },
97 destroyed() {
98 this.createIntersectionObserver().disconnect();
99 },
100 methods: {
101 updateTabs(tabs) {
102 tabs = tabs || this.data.tabs;
103 this.set({
104 tabs,
105 scrollable: tabs.length > this.data.swipeThreshold
106 });
107 this.setActiveTab();
108 },
109 trigger(eventName, index) {
110 this.$emit(eventName, {
111 index,
112 title: this.data.tabs[index].title
113 });
114 },
115 onTap(event) {
116 const { index } = event.currentTarget.dataset;
117 if (this.data.tabs[index].disabled) {
118 this.trigger('disabled', index);
119 }
120 else {
121 this.trigger('click', index);
122 this.setActive(index);
123 }
124 },
125 setActive(active) {
126 if (active !== this.data.active) {
127 this.trigger('change', active);
128 this.set({ active });
129 this.setActiveTab();
130 }
131 },
132 setLine(skipTransition) {
133 if (this.data.type !== 'line') {
134 return;
135 }
136 const { color, active, duration, lineWidth, lineHeight } = this.data;
137 this.getRect('.van-tab', true).then((rects) => {
138 const rect = rects[active];
139 const width = lineWidth !== -1 ? lineWidth : rect.width / 2;
140 const height = lineHeight !== -1 ? `height: ${lineHeight}px;` : '';
141 let left = rects
142 .slice(0, active)
143 .reduce((prev, curr) => prev + curr.width, 0);
144 left += (rect.width - width) / 2;
145 const transition = skipTransition
146 ? ''
147 : `transition-duration: ${duration}s; -webkit-transition-duration: ${duration}s;`;
148 this.set({
149 lineStyle: `
150 ${height}
151 width: ${width}px;
152 background-color: ${color};
153 -webkit-transform: translateX(${left}px);
154 transform: translateX(${left}px);
155 ${transition}
156 `
157 });
158 });
159 },
160 setTrack() {
161 const { animated, active, duration } = this.data;
162 if (!animated)
163 return '';
164 this.getRect('.van-tabs__content').then((rect) => {
165 const { width } = rect;
166 this.set({
167 trackStyle: `
168 width: ${width * this.child.length}px;
169 left: ${-1 * active * width}px;
170 transition: left ${duration}s;
171 display: -webkit-box;
172 display: flex;
173 `
174 });
175 const props = { width, animated };
176 this.child.forEach((item) => {
177 item.set(props);
178 });
179 });
180 },
181 setActiveTab() {
182 this.child.forEach((item, index) => {
183 const data = {
184 active: index === this.data.active
185 };
186 if (data.active) {
187 data.inited = true;
188 }
189 if (data.active !== item.data.active) {
190 item.set(data);
191 }
192 });
193 this.set({}, () => {
194 this.setLine();
195 this.setTrack();
196 this.scrollIntoView();
197 });
198 },
199 // scroll active tab into view
200 scrollIntoView() {
201 const { active, scrollable } = this.data;
202 if (!scrollable) {
203 return;
204 }
205 Promise.all([
206 this.getRect('.van-tab', true),
207 this.getRect('.van-tabs__nav')
208 ]).then(([tabRects, navRect]) => {
209 const tabRect = tabRects[active];
210 const offsetLeft = tabRects
211 .slice(0, active)
212 .reduce((prev, curr) => prev + curr.width, 0);
213 this.set({
214 scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2
215 });
216 });
217 },
218 onTouchStart(event) {
219 if (!this.data.swipeable)
220 return;
221 this.touchStart(event);
222 },
223 onTouchMove(event) {
224 if (!this.data.swipeable)
225 return;
226 this.touchMove(event);
227 },
228 // watch swipe touch end
229 onTouchEnd() {
230 if (!this.data.swipeable)
231 return;
232 const { active, tabs } = this.data;
233 const { direction, deltaX, offsetX } = this;
234 const minSwipeDistance = 50;
235 if (direction === 'horizontal' && offsetX >= minSwipeDistance) {
236 if (deltaX > 0 && active !== 0) {
237 this.setActive(active - 1);
238 }
239 else if (deltaX < 0 && active !== tabs.length - 1) {
240 this.setActive(active + 1);
241 }
242 }
243 },
244 setWrapStyle() {
245 const { offsetTop, position } = this.data;
246 let wrapStyle;
247 switch (position) {
248 case 'top':
249 wrapStyle = `
250 top: ${offsetTop}px;
251 position: fixed;
252 `;
253 break;
254 case 'bottom':
255 wrapStyle = `
256 top: auto;
257 bottom: 0;
258 `;
259 break;
260 default:
261 wrapStyle = '';
262 }
263 // cut down `set`
264 if (wrapStyle === this.data.wrapStyle)
265 return;
266 this.set({ wrapStyle });
267 },
268 observerContentScroll() {
269 if (!this.data.sticky) {
270 return;
271 }
272 const { offsetTop } = this.data;
273 const { windowHeight } = wx.getSystemInfoSync();
274 this.createIntersectionObserver().disconnect();
275 this.createIntersectionObserver()
276 .relativeToViewport({ top: -(this.navHeight + offsetTop) })
277 .observe('.van-tabs', (res) => {
278 const { top } = res.boundingClientRect;
279 if (top > offsetTop) {
280 return;
281 }
282 const position = res.intersectionRatio > 0 ? 'top' : 'bottom';
283 this.$emit('scroll', {
284 scrollTop: top + offsetTop,
285 isFixed: position === 'top'
286 });
287 this.setPosition(position);
288 });
289 this.createIntersectionObserver()
290 .relativeToViewport({ bottom: -(windowHeight - 1 - offsetTop) })
291 .observe('.van-tabs', (res) => {
292 const { top, bottom } = res.boundingClientRect;
293 if (bottom < this.navHeight) {
294 return;
295 }
296 const position = res.intersectionRatio > 0 ? 'top' : '';
297 this.$emit('scroll', {
298 scrollTop: top + offsetTop,
299 isFixed: position === 'top'
300 });
301 this.setPosition(position);
302 });
303 },
304 setPosition(position) {
305 if (position !== this.data.position) {
306 this.set({ position }).then(() => {
307 this.setWrapStyle();
308 });
309 }
310 }
311 }
312 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-info": "../info/index"
5 }
6 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view class="custom-class {{ utils.bem('tabs', [type]) }}">
4 <view style="z-index: {{ zIndex }}; {{ wrapStyle }}" class="{{ utils.bem('tabs__wrap', { scrollable }) }} {{ type === 'line' && border ? 'van-hairline--top-bottom' : '' }}">
5 <slot name="nav-left" />
6
7 <scroll-view
8 scroll-x="{{ scrollable }}"
9 scroll-with-animation
10 scroll-left="{{ scrollLeft }}"
11 class="van-tabs__scroll--{{ type }}"
12 style="{{ color ? 'border-color: ' + color : '' }}"
13 >
14 <view class="{{ utils.bem('tabs__nav', [type]) }} nav-class">
15 <view wx:if="{{ type === 'line' }}" class="van-tabs__line" style="{{ lineStyle }}" />
16 <view
17 wx:for="{{ tabs }}"
18 wx:key="index"
19 data-index="{{ index }}"
20 class="van-ellipsis tab-class {{ index === active ? 'tab-active-class' : '' }} {{ utils.bem('tab', { active: index === active, disabled: item.disabled }) }}"
21 style="{{ color && index !== active && type === 'card' && !item.disabled ? 'color: ' + color : '' }} {{ color && index === active && type === 'card' ? ';background-color:' + color : '' }} {{ color ? ';border-color: ' + color : '' }} {{ scrollable ? ';flex-basis:' + (88 / swipeThreshold) + '%' : '' }}"
22 bind:tap="onTap"
23 >
24 <view class="van-ellipsis {{ utils.bem('tab__title', { dot: item.dot }) }}" style="{{ item.titleStyle }}">
25 {{ item.title }}
26 <van-info
27 wx:if="{{ item.info !== null }}"
28 info="{{ item.info }}"
29 custom-class="van-tab__title__info"
30 />
31 </view>
32 </view>
33 </view>
34 </scroll-view>
35
36 <slot name="nav-right" />
37 </view>
38 <view
39 class="van-tabs__content"
40 bind:touchstart="onTouchStart"
41 bind:touchmove="onTouchMove"
42 bind:touchend="onTouchEnd"
43 bind:touchcancel="onTouchEnd"
44 >
45 <view class="van-tabs__track" style="{{ trackStyle }}">
46 <slot />
47 </view>
48 </view>
49 </view>
1 @import '../common/index.wxss';.van-tabs{position:relative;-webkit-tap-highlight-color:transparent}.van-tabs__wrap{position:absolute;top:0;right:0;left:0;display:-webkit-flex;display:flex;background-color:#fff}.van-tabs__wrap--page-top{position:fixed}.van-tabs__wrap--content-bottom{top:auto;bottom:0}.van-tabs__wrap--scrollable .van-tab{-webkit-flex:0 0 22%;flex:0 0 22%}.van-tabs__scroll--card{border:1px solid #f44;border-radius:2px}.van-tabs__nav{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none}.van-tabs__nav--line{height:100%}.van-tabs__nav--card{height:30px}.van-tabs__nav--card .van-tab{line-height:30px;color:#f44;border-right:1px solid #f44}.van-tabs__nav--card .van-tab:last-child{border-right:none}.van-tabs__nav--card .van-tab.van-tab--active{color:#fff;background-color:#f44}.van-tabs__line{position:absolute;bottom:0;left:0;z-index:1;height:3px;background-color:#f44;border-radius:3px}.van-tabs--line{padding-top:44px}.van-tabs--line .van-tabs__wrap{height:44px}.van-tabs--card{padding-top:30px;margin:0 15px}.van-tabs--card .van-tabs__wrap{height:30px}.van-tabs__content{overflow:hidden}.van-tab,.van-tabs__track{position:relative}.van-tab{min-width:0;padding:0 5px;font-size:14px;line-height:44px;color:#7d7e80;text-align:center;cursor:pointer;box-sizing:border-box;-webkit-flex:1;flex:1}.van-tab--active{font-weight:500;color:#333}.van-tab--disabled{color:#c9c9c9}.van-tab__title--dot:after{display:inline-block;width:8px;height:8px;vertical-align:middle;background-color:#f44;border-radius:100%;content:""}.van-tab__title__info{position:relative!important;top:-1px!important;display:inline-block;-webkit-transform:translateX(0)!important;transform:translateX(0)!important}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 import { RED, BLUE, GREEN } from '../common/color';
3 const DEFAULT_COLOR = '#999';
4 const COLOR_MAP = {
5 danger: RED,
6 primary: BLUE,
7 success: GREEN
8 };
9 VantComponent({
10 props: {
11 size: String,
12 type: String,
13 mark: Boolean,
14 color: String,
15 plain: Boolean,
16 round: Boolean,
17 textColor: String
18 },
19 computed: {
20 style() {
21 const color = this.data.color || COLOR_MAP[this.data.type] || DEFAULT_COLOR;
22 const key = this.data.plain ? 'color' : 'background-color';
23 const style = { [key]: color };
24 if (this.data.textColor) {
25 style.color = this.data.textColor;
26 }
27 return Object.keys(style).map(key => `${key}: ${style[key]}`).join(';');
28 }
29 }
30 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="custom-class {{ utils.bem('tag', [size, { mark, plain, round }]) }} {{ plain ? 'van-hairline--surround' : '' }}"
5 style="{{ style }}"
6 >
7 <slot />
8 </view>
1 @import '../common/index.wxss';.van-tag{color:#fff;font-size:10px;padding:.2em .5em;line-height:normal;border-radius:.2em;display:inline-block}.van-tag:after{border-color:currentColor;border-radius:.4em}.van-tag--mark{padding-right:.6em;border-radius:0 .8em .8em 0}.van-tag--mark:after{border-radius:0 1.6em 1.6em 0}.van-tag--round{border-radius:.8em}.van-tag--round:after{border-radius:1.6em}.van-tag--medium{font-size:12px}.van-tag--large{font-size:14px}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 VantComponent({
3 props: {
4 show: Boolean,
5 mask: Boolean,
6 message: String,
7 forbidClick: Boolean,
8 zIndex: {
9 type: Number,
10 value: 1000
11 },
12 type: {
13 type: String,
14 value: 'text'
15 },
16 loadingType: {
17 type: String,
18 value: 'circular'
19 },
20 position: {
21 type: String,
22 value: 'middle'
23 }
24 },
25 methods: {
26 clear() {
27 this.set({
28 show: false
29 });
30 },
31 // for prevent touchmove
32 noop() { }
33 }
34 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-loading": "../loading/index",
6 "van-overlay": "../overlay/index",
7 "van-transition": "../transition/index"
8 }
9 }
1 <van-overlay
2 wx:if="{{ mask || forbidClick }}"
3 show="{{ show }}"
4 mask="{{ mask }}"
5 z-index="{{ zIndex }}"
6 />
7 <van-transition
8 show="{{ show }}"
9 custom-style="z-index: {{ zIndex }}"
10 custom-class="van-toast__container"
11 >
12 <view
13 class="van-toast van-toast--{{ type === 'text' ? 'text' : 'icon' }} van-toast--{{ position }}"
14 catch:touchmove="noop"
15 >
16 <!-- text only -->
17 <text wx:if="{{ type === 'text' }}">{{ message }}</text>
18
19 <!-- with icon -->
20 <block wx:else>
21 <van-loading
22 wx:if="{{ type === 'loading' }}"
23 color="white"
24 type="{{ loadingType }}"
25 custom-class="van-toast__loading"
26 />
27 <van-icon wx:else class="van-toast__icon" name="{{ type }}" />
28 <text wx:if="{{ message }}" class="van-toast__text">{{ message }}</text>
29 </block>
30 </view>
31 </van-transition>
1 @import '../common/index.wxss';.van-toast{display:-webkit-flex;display:flex;color:#fff;font-size:14px;line-height:20px;border-radius:4px;word-break:break-all;-webkit-align-items:center;align-items:center;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center;box-sizing:initial;background-color:rgba(51,51,51,.88);white-space:pre-wrap}.van-toast__container{position:fixed;top:50%;left:50%;max-width:70%;width:-webkit-fit-content;width:fit-content;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.van-toast--text{padding:8px 12px;min-width:96px}.van-toast--icon{width:90px;padding:15px;min-height:90px}.van-toast--icon .van-toast__icon{font-size:48px}.van-toast--icon .van-toast__text{padding-top:5px}.van-toast__loading{margin:10px 0}.van-toast--top{-webkit-transform:translateY(-30vh);transform:translateY(-30vh)}.van-toast--bottom{-webkit-transform:translateY(30vh);transform:translateY(30vh)}
...\ No newline at end of file ...\ No newline at end of file
1 declare type ToastMessage = string | number;
2 export declare type ToastOptions = {
3 show?: boolean;
4 type?: string;
5 mask?: boolean;
6 zIndex?: number;
7 context?: any;
8 position?: string;
9 duration?: number;
10 selector?: string;
11 forbidClick?: boolean;
12 loadingType?: string;
13 message?: ToastMessage;
14 };
15 export interface Toast {
16 (message: ToastOptions | ToastMessage, options?: ToastOptions): Weapp.Component;
17 loading?(options?: ToastOptions | ToastMessage): Weapp.Component;
18 success?(options?: ToastOptions | ToastMessage): Weapp.Component;
19 fail?(options?: ToastOptions | ToastMessage): Weapp.Component;
20 clear?(): void;
21 setDefaultOptions?(options: ToastOptions): void;
22 resetDefaultOptions?(): void;
23 }
24 declare const Toast: Toast;
25 export default Toast;
1 import { isObj } from '../common/utils';
2 const defaultOptions = {
3 type: 'text',
4 mask: false,
5 message: '',
6 show: true,
7 zIndex: 1000,
8 duration: 3000,
9 position: 'middle',
10 forbidClick: false,
11 loadingType: 'circular',
12 selector: '#van-toast'
13 };
14 let queue = [];
15 let currentOptions = Object.assign({}, defaultOptions);
16 function parseOptions(message) {
17 return isObj(message) ? message : { message };
18 }
19 function getContext() {
20 const pages = getCurrentPages();
21 return pages[pages.length - 1];
22 }
23 const Toast = (options = {}) => {
24 options = Object.assign({}, currentOptions, parseOptions(options));
25 const context = options.context || getContext();
26 const toast = context.selectComponent(options.selector);
27 if (!toast) {
28 console.warn('未找到 van-toast 节点,请确认 selector 及 context 是否正确');
29 return;
30 }
31 delete options.context;
32 delete options.selector;
33 queue.push(toast);
34 toast.set(options);
35 clearTimeout(toast.timer);
36 if (options.duration > 0) {
37 toast.timer = setTimeout(() => {
38 toast.clear();
39 queue = queue.filter(item => item !== toast);
40 }, options.duration);
41 }
42 return toast;
43 };
44 const createMethod = type => options => Toast(Object.assign({ type }, parseOptions(options)));
45 ['loading', 'success', 'fail'].forEach(method => {
46 Toast[method] = createMethod(method);
47 });
48 Toast.clear = () => {
49 queue.forEach(toast => {
50 toast.clear();
51 });
52 queue = [];
53 };
54 Toast.setDefaultOptions = options => {
55 Object.assign(currentOptions, options);
56 };
57 Toast.resetDefaultOptions = () => {
58 currentOptions = Object.assign({}, defaultOptions);
59 };
60 export default Toast;
1 import { VantComponent } from '../common/component';
2 import { transition } from '../mixins/transition';
3 VantComponent({
4 classes: [
5 'enter-class',
6 'enter-active-class',
7 'enter-to-class',
8 'leave-class',
9 'leave-active-class',
10 'leave-to-class'
11 ],
12 mixins: [transition(true)]
13 });
1 {
2 "component": true
3 }
...\ No newline at end of file ...\ No newline at end of file
1 <view
2 wx:if="{{ inited }}"
3 class="van-transition custom-class {{ classes }}"
4 style="-webkit-transition-duration:{{ currentDuration }}ms; transition-duration:{{ currentDuration }}ms; {{ display ? '' : 'display: none;' }} {{ customStyle }}"
5 bind:transitionend="onTransitionEnd"
6 >
7 <slot />
8 </view>
1 @import '../common/index.wxss';.van-transition{transition-timing-function:ease}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-fade-down-enter-active,.van-fade-down-leave-active,.van-fade-left-enter-active,.van-fade-left-leave-active,.van-fade-right-enter-active,.van-fade-right-leave-active,.van-fade-up-enter-active,.van-fade-up-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-fade-up-enter,.van-fade-up-leave-to{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-fade-down-enter,.van-fade-down-leave-to{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-fade-left-enter,.van-fade-left-leave-to{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-fade-right-enter,.van-fade-right-leave-to{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.van-slide-down-enter-active,.van-slide-down-leave-active,.van-slide-left-enter-active,.van-slide-left-leave-active,.van-slide-right-enter-active,.van-slide-right-leave-active,.van-slide-up-enter-active,.van-slide-up-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-slide-up-enter,.van-slide-up-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-slide-down-enter,.van-slide-down-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-slide-left-enter,.van-slide-left-leave-to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-slide-right-enter,.van-slide-right-leave-to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}
...\ No newline at end of file ...\ No newline at end of file
1 import { VantComponent } from '../common/component';
2 const ITEM_HEIGHT = 44;
3 VantComponent({
4 classes: [
5 'main-item-class',
6 'content-item-class',
7 'main-active-class',
8 'content-active-class',
9 'main-disabled-class',
10 'content-disabled-class'
11 ],
12 props: {
13 items: Array,
14 mainActiveIndex: {
15 type: Number,
16 value: 0
17 },
18 activeId: {
19 type: [Number, String]
20 },
21 maxHeight: {
22 type: Number,
23 value: 300
24 }
25 },
26 data: {
27 subItems: [],
28 mainHeight: 0,
29 itemHeight: 0
30 },
31 watch: {
32 items() {
33 this.updateSubItems().then(() => {
34 this.updateMainHeight();
35 });
36 },
37 maxHeight() {
38 this.updateItemHeight(this.data.subItems);
39 this.updateMainHeight();
40 },
41 mainActiveIndex: 'updateSubItems'
42 },
43 methods: {
44 // 当一个子项被选择时
45 onSelectItem(event) {
46 const { item } = event.currentTarget.dataset;
47 if (!item.disabled) {
48 this.$emit('click-item', item);
49 }
50 },
51 // 当一个导航被点击时
52 onClickNav(event) {
53 const { index } = event.currentTarget.dataset;
54 const item = this.data.items[index];
55 if (!item.disabled) {
56 this.$emit('click-nav', { index });
57 }
58 },
59 // 更新子项列表
60 updateSubItems() {
61 const { items, mainActiveIndex } = this.data;
62 const { children = [] } = items[mainActiveIndex] || {};
63 this.updateItemHeight(children);
64 return this.set({ subItems: children });
65 },
66 // 更新组件整体高度,根据最大高度和当前组件需要展示的高度来决定
67 updateMainHeight() {
68 const { items = [], subItems = [] } = this.data;
69 const maxHeight = Math.max(items.length * ITEM_HEIGHT, subItems.length * ITEM_HEIGHT);
70 this.set({ mainHeight: Math.min(maxHeight, this.data.maxHeight) });
71 },
72 // 更新子项列表高度,根据可展示的最大高度和当前子项列表的高度决定
73 updateItemHeight(subItems) {
74 const itemHeight = Math.min(subItems.length * ITEM_HEIGHT, this.data.maxHeight);
75 return this.set({ itemHeight });
76 }
77 }
78 });
1 {
2 "component": true,
3 "usingComponents": {
4 "van-icon": "../icon/index",
5 "van-cell": "../cell/index"
6 }
7 }
1 <wxs src="../wxs/utils.wxs" module="utils" />
2
3 <view
4 class="van-tree-select"
5 style="height: {{ mainHeight }}px"
6 >
7 <scroll-view scroll-y class="van-tree-select__nav">
8 <view
9 wx:for="{{ items }}"
10 wx:key="index"
11 class="van-ellipsis main-item-class {{ utils.bem('tree-select__nitem', { active: mainActiveIndex === index, disabled: item.disabled }) }} {{ mainActiveIndex === index ? 'main-active-class' : '' }} {{ item.disabled ? 'main-disabled-class' : '' }}"
12 data-index="{{ index }}"
13 bind:tap="onClickNav"
14 >
15 {{ item.text }}
16 </view>
17 </scroll-view>
18 <scroll-view
19 scroll-y
20 class="van-tree-select__content"
21 style="height: {{ itemHeight }}px"
22 >
23 <view
24 wx:for="{{ subItems }}"
25 wx:key="id"
26 class="van-ellipsis van-hairline--bottom content-item-class {{ utils.bem('tree-select__item', { active: activeId === item.id, disabled: item.disabled }) }} {{ activeId === item.id ? 'content-active-class' : '' }} {{ item.disabled ? 'content-disabled-class' : '' }}"
27 data-item="{{ item }}"
28 bind:tap="onSelectItem"
29 >
30 {{ item.text }}
31 <van-icon
32 wx:if="{{ activeId === item.id }}"
33 name="checked"
34 size="16px"
35 class="van-tree-select__selected"
36 />
37 </view>
38 </scroll-view>
39 </view>
1 @import '../common/index.wxss';.van-tree-select{position:relative;font-size:14px;-webkit-user-select:none;user-select:none}.van-tree-select__nav{position:absolute;top:0;bottom:0;left:0;width:35%;min-width:120px;background-color:#fafafa}.van-tree-select__nitem{position:relative;padding:0 9px 0 15px;line-height:44px}.van-tree-select__nitem--active:after{position:absolute;top:0;bottom:0;left:0;width:3.6px;background-color:#f44;content:""}.van-tree-select__nitem--active{font-weight:700;background-color:#fff}.van-tree-select__nitem--disabled{color:#999}.van-tree-select__content{width:65%;padding-left:15px;margin-left:35%;background-color:#fff;box-sizing:border-box}.van-tree-select__item{position:relative;font-weight:700;line-height:44px}.van-tree-select__item--active{color:#f44}.van-tree-select__item--disabled{color:#999}.van-tree-select__selected{position:absolute;top:0;right:15px;bottom:0;height:24px;margin:auto 0;line-height:24px}
...\ No newline at end of file ...\ No newline at end of file
1 function isArray(array) {
2 return array && array.constructor === 'Array';
3 }
4
5 module.exports.isArray = isArray;
1 var array = require('./array.wxs');
2 var object = require('./object.wxs');
3 var PREFIX = 'van-';
4
5 function join(name, mods) {
6 name = PREFIX + name;
7 mods = mods.map(function(mod) {
8 return name + '--' + mod;
9 });
10 mods.unshift(name);
11 return mods.join(' ');
12 }
13
14 function traversing(mods, conf) {
15 if (!conf) {
16 return;
17 }
18
19 if (typeof conf === 'string' || typeof conf === 'number') {
20 mods.push(conf);
21 } else if (array.isArray(conf)) {
22 conf.forEach(function(item) {
23 traversing(mods, item);
24 });
25 } else if (typeof conf === 'object') {
26 object.keys(conf).forEach(function(key) {
27 conf[key] && mods.push(key);
28 });
29 }
30 }
31
32 function bem(name, conf) {
33 var mods = [];
34 traversing(mods, conf);
35 return join(name, mods);
36 }
37
38 module.exports.bem = bem;
1 /**
2 * Simple memoize
3 * wxs doesn't support fn.apply, so this memoize only support up to 2 args
4 */
5
6 function isPrimitive(value) {
7 var type = typeof value;
8 return (
9 type === 'boolean' ||
10 type === 'number' ||
11 type === 'string' ||
12 type === 'undefined' ||
13 value === null
14 );
15 }
16
17 // mock simple fn.call in wxs
18 function call(fn, args) {
19 if (args.length === 2) {
20 return fn(args[0], args[1]);
21 }
22
23 if (args.length === 1) {
24 return fn(args[0]);
25 }
26
27 return fn();
28 }
29
30 function serializer(args) {
31 if (args.length === 1 && isPrimitive(args[0])) {
32 return args[0];
33 }
34 var obj = {};
35 for (var i = 0; i < args.length; i++) {
36 obj['key' + i] = args[i];
37 }
38 return JSON.stringify(obj);
39 }
40
41 function memoize(fn) {
42 var cache = {};
43
44 return function() {
45 var key = serializer(arguments);
46 if (cache[key] === undefined) {
47 cache[key] = call(fn, arguments);
48 }
49
50 return cache[key];
51 };
52 }
53
54 module.exports.memoize = memoize;
1 /* eslint-disable */
2 var REGEXP = getRegExp('{|}|"', 'g');
3
4 function keys(obj) {
5 return JSON.stringify(obj)
6 .replace(REGEXP, '')
7 .split(',')
8 .map(function(item) {
9 return item.split(':')[0];
10 });
11 }
12
13 module.exports.keys = keys;
1 var bem = require('./bem.wxs').bem;
2 var memoize = require('./memoize.wxs').memoize;
3
4 function isSrc(url) {
5 return url.indexOf('http') === 0 || url.indexOf('data:image') === 0 || url.indexOf('//') === 0;
6 }
7
8 module.exports = {
9 bem: memoize(bem),
10 isSrc: isSrc,
11 memoize: memoize
12 };
1 /**
2 * @version: 1.0 Alpha-1
3 * @author: Coolite Inc. http://www.coolite.com/
4 * @date: 2008-05-13
5 * @copyright: Copyright (c) 2006-2008, Coolite Inc. (http://www.coolite.com/). All rights reserved.
6 * @license: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
7 * @website: http://www.datejs.com/
8 */
9
10 Date.CultureInfo = {
11 name: "en-US",
12 englishName: "English (United States)",
13 nativeName: "English (United States)",
14 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
15 abbreviatedDayNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
16 shortestDayNames: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
17 firstLetterDayNames: ["S", "M", "T", "W", "T", "F", "S"],
18 monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
19 abbreviatedMonthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
20 amDesignator: "AM",
21 pmDesignator: "PM",
22 firstDayOfWeek: 0,
23 twoDigitYearMax: 2029,
24 dateElementOrder: "mdy",
25 formatPatterns: {
26 shortDate: "M/d/yyyy",
27 longDate: "dddd, MMMM dd, yyyy",
28 shortTime: "h:mm tt",
29 longTime: "h:mm:ss tt",
30 fullDateTime: "dddd, MMMM dd, yyyy h:mm:ss tt",
31 sortableDateTime: "yyyy-MM-ddTHH:mm:ss",
32 universalSortableDateTime: "yyyy-MM-dd HH:mm:ssZ",
33 rfc1123: "ddd, dd MMM yyyy HH:mm:ss GMT",
34 monthDay: "MMMM dd",
35 yearMonth: "MMMM, yyyy"
36 },
37 regexPatterns: {
38 jan: /^jan(uary)?/i,
39 feb: /^feb(ruary)?/i,
40 mar: /^mar(ch)?/i,
41 apr: /^apr(il)?/i,
42 may: /^may/i,
43 jun: /^jun(e)?/i,
44 jul: /^jul(y)?/i,
45 aug: /^aug(ust)?/i,
46 sep: /^sep(t(ember)?)?/i,
47 oct: /^oct(ober)?/i,
48 nov: /^nov(ember)?/i,
49 dec: /^dec(ember)?/i,
50 sun: /^su(n(day)?)?/i,
51 mon: /^mo(n(day)?)?/i,
52 tue: /^tu(e(s(day)?)?)?/i,
53 wed: /^we(d(nesday)?)?/i,
54 thu: /^th(u(r(s(day)?)?)?)?/i,
55 fri: /^fr(i(day)?)?/i,
56 sat: /^sa(t(urday)?)?/i,
57 future: /^next/i,
58 past: /^last|past|prev(ious)?/i,
59 add: /^(\+|aft(er)?|from|hence)/i,
60 subtract: /^(\-|bef(ore)?|ago)/i,
61 yesterday: /^yes(terday)?/i,
62 today: /^t(od(ay)?)?/i,
63 tomorrow: /^tom(orrow)?/i,
64 now: /^n(ow)?/i,
65 millisecond: /^ms|milli(second)?s?/i,
66 second: /^sec(ond)?s?/i,
67 minute: /^mn|min(ute)?s?/i,
68 hour: /^h(our)?s?/i,
69 week: /^w(eek)?s?/i,
70 month: /^m(onth)?s?/i,
71 day: /^d(ay)?s?/i,
72 year: /^y(ear)?s?/i,
73 shortMeridian: /^(a|p)/i,
74 longMeridian: /^(a\.?m?\.?|p\.?m?\.?)/i,
75 timezone: /^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt|utc)/i,
76 ordinalSuffix: /^\s*(st|nd|rd|th)/i,
77 timeContext: /^\s*(\:|a(?!u|p)|p)/i
78 },
79 timezones: [{
80 name: "UTC",
81 offset: "-000"
82 }, {
83 name: "GMT",
84 offset: "-000"
85 }, {
86 name: "EST",
87 offset: "-0500"
88 }, {
89 name: "EDT",
90 offset: "-0400"
91 }, {
92 name: "CST",
93 offset: "-0600"
94 }, {
95 name: "CDT",
96 offset: "-0500"
97 }, {
98 name: "MST",
99 offset: "-0700"
100 }, {
101 name: "MDT",
102 offset: "-0600"
103 }, {
104 name: "PST",
105 offset: "-0800"
106 }, {
107 name: "PDT",
108 offset: "-0700"
109 }]
110 };
111 (function () {
112 var $D = Date,
113 $P = $D.prototype,
114 $C = $D.CultureInfo,
115 p = function (s, l) {
116 if (!l) {
117 l = 2;
118 }
119 return ("000" + s).slice(l * -1);
120 };
121 $P.clearTime = function () {
122 this.setHours(0);
123 this.setMinutes(0);
124 this.setSeconds(0);
125 this.setMilliseconds(0);
126 return this;
127 };
128 $P.setTimeToNow = function () {
129 var n = new Date();
130 this.setHours(n.getHours());
131 this.setMinutes(n.getMinutes());
132 this.setSeconds(n.getSeconds());
133 this.setMilliseconds(n.getMilliseconds());
134 return this;
135 };
136 $D.today = function () {
137 return new Date().clearTime();
138 };
139 $D.compare = function (date1, date2) {
140 if (isNaN(date1) || isNaN(date2)) {
141 throw new Error(date1 + " - " + date2);
142 } else if (date1 instanceof Date && date2 instanceof Date) {
143 return (date1 < date2) ? -1 : (date1 > date2) ? 1 : 0;
144 } else {
145 throw new TypeError(date1 + " - " + date2);
146 }
147 };
148 $D.equals = function (date1, date2) {
149 return (date1.compareTo(date2) === 0);
150 };
151 $D.getDayNumberFromName = function (name) {
152 var n = $C.dayNames,
153 m = $C.abbreviatedDayNames,
154 o = $C.shortestDayNames,
155 s = name.toLowerCase();
156 for (var i = 0; i < n.length; i++) {
157 if (n[i].toLowerCase() == s || m[i].toLowerCase() == s || o[i].toLowerCase() == s) {
158 return i;
159 }
160 }
161 return -1;
162 };
163 $D.getMonthNumberFromName = function (name) {
164 var n = $C.monthNames,
165 m = $C.abbreviatedMonthNames,
166 s = name.toLowerCase();
167 for (var i = 0; i < n.length; i++) {
168 if (n[i].toLowerCase() == s || m[i].toLowerCase() == s) {
169 return i;
170 }
171 }
172 return -1;
173 };
174 $D.isLeapYear = function (year) {
175 return ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);
176 };
177 $D.getDaysInMonth = function (year, month) {
178 return [31, ($D.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
179 };
180 $D.getTimezoneAbbreviation = function (offset) {
181 var z = $C.timezones,
182 p;
183 for (var i = 0; i < z.length; i++) {
184 if (z[i].offset === offset) {
185 return z[i].name;
186 }
187 }
188 return null;
189 };
190 $D.getTimezoneOffset = function (name) {
191 var z = $C.timezones,
192 p;
193 for (var i = 0; i < z.length; i++) {
194 if (z[i].name === name.toUpperCase()) {
195 return z[i].offset;
196 }
197 }
198 return null;
199 };
200 $P.clone = function () {
201 return new Date(this.getTime());
202 };
203 $P.compareTo = function (date) {
204 return Date.compare(this, date);
205 };
206 $P.equals = function (date) {
207 return Date.equals(this, date || new Date());
208 };
209 $P.between = function (start, end) {
210 return this.getTime() >= start.getTime() && this.getTime() <= end.getTime();
211 };
212 $P.isAfter = function (date) {
213 return this.compareTo(date || new Date()) === 1;
214 };
215 $P.isBefore = function (date) {
216 return (this.compareTo(date || new Date()) === -1);
217 };
218 $P.isToday = function () {
219 return this.isSameDay(new Date());
220 };
221 $P.isSameDay = function (date) {
222 return this.clone().clearTime().equals(date.clone().clearTime());
223 };
224 $P.addMilliseconds = function (value) {
225 this.setMilliseconds(this.getMilliseconds() + value);
226 return this;
227 };
228 $P.addSeconds = function (value) {
229 return this.addMilliseconds(value * 1000);
230 };
231 $P.addMinutes = function (value) {
232 return this.addMilliseconds(value * 60000);
233 };
234 $P.addHours = function (value) {
235 return this.addMilliseconds(value * 3600000);
236 };
237 $P.addDays = function (value) {
238 this.setDate(this.getDate() + value);
239 return this;
240 };
241 $P.addWeeks = function (value) {
242 return this.addDays(value * 7);
243 };
244 $P.addMonths = function (value) {
245 var n = this.getDate();
246 this.setDate(1);
247 this.setMonth(this.getMonth() + value);
248 this.setDate(Math.min(n, $D.getDaysInMonth(this.getFullYear(), this.getMonth())));
249 return this;
250 };
251 $P.addYears = function (value) {
252 return this.addMonths(value * 12);
253 };
254 $P.add = function (config) {
255 if (typeof config == "number") {
256 this._orient = config;
257 return this;
258 }
259 var x = config;
260 if (x.milliseconds) {
261 this.addMilliseconds(x.milliseconds);
262 }
263 if (x.seconds) {
264 this.addSeconds(x.seconds);
265 }
266 if (x.minutes) {
267 this.addMinutes(x.minutes);
268 }
269 if (x.hours) {
270 this.addHours(x.hours);
271 }
272 if (x.weeks) {
273 this.addWeeks(x.weeks);
274 }
275 if (x.months) {
276 this.addMonths(x.months);
277 }
278 if (x.years) {
279 this.addYears(x.years);
280 }
281 if (x.days) {
282 this.addDays(x.days);
283 }
284 return this;
285 };
286 var $y, $m, $d;
287 $P.getWeek = function () {
288 var a, b, c, d, e, f, g, n, s, w;
289 $y = (!$y) ? this.getFullYear() : $y;
290 $m = (!$m) ? this.getMonth() + 1 : $m;
291 $d = (!$d) ? this.getDate() : $d;
292 if ($m <= 2) {
293 a = $y - 1;
294 b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0);
295 c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0);
296 s = b - c;
297 e = 0;
298 f = $d - 1 + (31 * ($m - 1));
299 } else {
300 a = $y;
301 b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0);
302 c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0);
303 s = b - c;
304 e = s + 1;
305 f = $d + ((153 * ($m - 3) + 2) / 5) + 58 + s;
306 }
307 g = (a + b) % 7;
308 d = (f + g - e) % 7;
309 n = (f + 3 - d) | 0;
310 if (n < 0) {
311 w = 53 - ((g - s) / 5 | 0);
312 } else if (n > 364 + s) {
313 w = 1;
314 } else {
315 w = (n / 7 | 0) + 1;
316 }
317 $y = $m = $d = null;
318 return w;
319 };
320 $P.getISOWeek = function () {
321 $y = this.getUTCFullYear();
322 $m = this.getUTCMonth() + 1;
323 $d = this.getUTCDate();
324 return p(this.getWeek());
325 };
326 $P.setWeek = function (n) {
327 return this.moveToDayOfWeek(1).addWeeks(n - this.getWeek());
328 };
329 $D._validate = function (n, min, max, name) {
330 if (typeof n == "undefined") {
331 return false;
332 } else if (typeof n != "number") {
333 throw new TypeError(n + " is not a Number.");
334 } else if (n < min || n > max) {
335 throw new RangeError(n + " is not a valid value for " + name + ".");
336 }
337 return true;
338 };
339 $D.validateMillisecond = function (value) {
340 return $D._validate(value, 0, 999, "millisecond");
341 };
342 $D.validateSecond = function (value) {
343 return $D._validate(value, 0, 59, "second");
344 };
345 $D.validateMinute = function (value) {
346 return $D._validate(value, 0, 59, "minute");
347 };
348 $D.validateHour = function (value) {
349 return $D._validate(value, 0, 23, "hour");
350 };
351 $D.validateDay = function (value, year, month) {
352 return $D._validate(value, 1, $D.getDaysInMonth(year, month), "day");
353 };
354 $D.validateMonth = function (value) {
355 return $D._validate(value, 0, 11, "month");
356 };
357 $D.validateYear = function (value) {
358 return $D._validate(value, 0, 9999, "year");
359 };
360 $P.set = function (config) {
361 if ($D.validateMillisecond(config.millisecond)) {
362 this.addMilliseconds(config.millisecond - this.getMilliseconds());
363 }
364 if ($D.validateSecond(config.second)) {
365 this.addSeconds(config.second - this.getSeconds());
366 }
367 if ($D.validateMinute(config.minute)) {
368 this.addMinutes(config.minute - this.getMinutes());
369 }
370 if ($D.validateHour(config.hour)) {
371 this.addHours(config.hour - this.getHours());
372 }
373 if ($D.validateMonth(config.month)) {
374 this.addMonths(config.month - this.getMonth());
375 }
376 if ($D.validateYear(config.year)) {
377 this.addYears(config.year - this.getFullYear());
378 }
379 if ($D.validateDay(config.day, this.getFullYear(), this.getMonth())) {
380 this.addDays(config.day - this.getDate());
381 }
382 if (config.timezone) {
383 this.setTimezone(config.timezone);
384 }
385 if (config.timezoneOffset) {
386 this.setTimezoneOffset(config.timezoneOffset);
387 }
388 if (config.week && $D._validate(config.week, 0, 53, "week")) {
389 this.setWeek(config.week);
390 }
391 return this;
392 };
393 $P.moveToFirstDayOfMonth = function () {
394 return this.set({
395 day: 1
396 });
397 };
398 $P.moveToLastDayOfMonth = function () {
399 return this.set({
400 day: $D.getDaysInMonth(this.getFullYear(), this.getMonth())
401 });
402 };
403 $P.moveToNthOccurrence = function (dayOfWeek, occurrence) {
404 var shift = 0;
405 if (occurrence > 0) {
406 shift = occurrence - 1;
407 } else if (occurrence === -1) {
408 this.moveToLastDayOfMonth();
409 if (this.getDay() !== dayOfWeek) {
410 this.moveToDayOfWeek(dayOfWeek, -1);
411 }
412 return this;
413 }
414 return this.moveToFirstDayOfMonth().addDays(-1).moveToDayOfWeek(dayOfWeek, +1).addWeeks(shift);
415 };
416 $P.moveToDayOfWeek = function (dayOfWeek, orient) {
417 var diff = (dayOfWeek - this.getDay() + 7 * (orient || +1)) % 7;
418 return this.addDays((diff === 0) ? diff += 7 * (orient || +1) : diff);
419 };
420 $P.moveToMonth = function (month, orient) {
421 var diff = (month - this.getMonth() + 12 * (orient || +1)) % 12;
422 return this.addMonths((diff === 0) ? diff += 12 * (orient || +1) : diff);
423 };
424 $P.getOrdinalNumber = function () {
425 return Math.ceil((this.clone().clearTime() - new Date(this.getFullYear(), 0, 1)) / 86400000) + 1;
426 };
427 $P.getTimezone = function () {
428 return $D.getTimezoneAbbreviation(this.getUTCOffset());
429 };
430 $P.setTimezoneOffset = function (offset) {
431 var here = this.getTimezoneOffset(),
432 there = Number(offset) * -6 / 10;
433 return this.addMinutes(there - here);
434 };
435 $P.setTimezone = function (offset) {
436 return this.setTimezoneOffset($D.getTimezoneOffset(offset));
437 };
438 $P.hasDaylightSavingTime = function () {
439 return (Date.today().set({
440 month: 0,
441 day: 1
442 }).getTimezoneOffset() !== Date.today().set({
443 month: 6,
444 day: 1
445 }).getTimezoneOffset());
446 };
447 $P.isDaylightSavingTime = function () {
448 return (this.hasDaylightSavingTime() && new Date().getTimezoneOffset() === Date.today().set({
449 month: 6,
450 day: 1
451 }).getTimezoneOffset());
452 };
453 $P.getUTCOffset = function () {
454 var n = this.getTimezoneOffset() * -10 / 6,
455 r;
456 if (n < 0) {
457 r = (n - 10000).toString();
458 return r.charAt(0) + r.substr(2);
459 } else {
460 r = (n + 10000).toString();
461 return "+" + r.substr(1);
462 }
463 };
464 $P.getElapsed = function (date) {
465 return (date || new Date()) - this;
466 };
467 if (!$P.toISOString) {
468 $P.toISOString = function () {
469 function f(n) {
470 return n < 10 ? '0' + n : n;
471 }
472 return '"' + this.getUTCFullYear() + '-' +
473 f(this.getUTCMonth() + 1) + '-' +
474 f(this.getUTCDate()) + 'T' +
475 f(this.getUTCHours()) + ':' +
476 f(this.getUTCMinutes()) + ':' +
477 f(this.getUTCSeconds()) + 'Z"';
478 };
479 }
480 $P._toString = $P.toString;
481 $P.toString = function (format) {
482 var x = this;
483 if (format && format.length == 1) {
484 var c = $C.formatPatterns;
485 x.t = x.toString;
486 switch (format) {
487 case "d":
488 return x.t(c.shortDate);
489 case "D":
490 return x.t(c.longDate);
491 case "F":
492 return x.t(c.fullDateTime);
493 case "m":
494 return x.t(c.monthDay);
495 case "r":
496 return x.t(c.rfc1123);
497 case "s":
498 return x.t(c.sortableDateTime);
499 case "t":
500 return x.t(c.shortTime);
501 case "T":
502 return x.t(c.longTime);
503 case "u":
504 return x.t(c.universalSortableDateTime);
505 case "y":
506 return x.t(c.yearMonth);
507 }
508 }
509 var ord = function (n) {
510 switch (n * 1) {
511 case 1:
512 case 21:
513 case 31:
514 return "st";
515 case 2:
516 case 22:
517 return "nd";
518 case 3:
519 case 23:
520 return "rd";
521 default:
522 return "th";
523 }
524 };
525 return format ? format.replace(/(\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S)/g, function (m) {
526 if (m.charAt(0) === "\\") {
527 return m.replace("\\", "");
528 }
529 x.h = x.getHours;
530 switch (m) {
531 case "hh":
532 return p(x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12));
533 case "h":
534 return x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12);
535 case "HH":
536 return p(x.h());
537 case "H":
538 return x.h();
539 case "mm":
540 return p(x.getMinutes());
541 case "m":
542 return x.getMinutes();
543 case "ss":
544 return p(x.getSeconds());
545 case "s":
546 return x.getSeconds();
547 case "yyyy":
548 return p(x.getFullYear(), 4);
549 case "yy":
550 return p(x.getFullYear());
551 case "dddd":
552 return $C.dayNames[x.getDay()];
553 case "ddd":
554 return $C.abbreviatedDayNames[x.getDay()];
555 case "dd":
556 return p(x.getDate());
557 case "d":
558 return x.getDate();
559 case "MMMM":
560 return $C.monthNames[x.getMonth()];
561 case "MMM":
562 return $C.abbreviatedMonthNames[x.getMonth()];
563 case "MM":
564 return p((x.getMonth() + 1));
565 case "M":
566 return x.getMonth() + 1;
567 case "t":
568 return x.h() < 12 ? $C.amDesignator.substring(0, 1) : $C.pmDesignator.substring(0, 1);
569 case "tt":
570 return x.h() < 12 ? $C.amDesignator : $C.pmDesignator;
571 case "S":
572 return ord(x.getDate());
573 default:
574 return m;
575 }
576 }) : this._toString();
577 };
578 }());
579 (function () {
580 var $D = Date,
581 $P = $D.prototype,
582 $C = $D.CultureInfo,
583 $N = Number.prototype;
584 $P._orient = +1;
585 $P._nth = null;
586 $P._is = false;
587 $P._same = false;
588 $P._isSecond = false;
589 $N._dateElement = "day";
590 $P.next = function () {
591 this._orient = +1;
592 return this;
593 };
594 $D.next = function () {
595 return $D.today().next();
596 };
597 $P.last = $P.prev = $P.previous = function () {
598 this._orient = -1;
599 return this;
600 };
601 $D.last = $D.prev = $D.previous = function () {
602 return $D.today().last();
603 };
604 $P.is = function () {
605 this._is = true;
606 return this;
607 };
608 $P.same = function () {
609 this._same = true;
610 this._isSecond = false;
611 return this;
612 };
613 $P.today = function () {
614 return this.same().day();
615 };
616 $P.weekday = function () {
617 if (this._is) {
618 this._is = false;
619 return (!this.is().sat() && !this.is().sun());
620 }
621 return false;
622 };
623 $P.at = function (time) {
624 return (typeof time === "string") ? $D.parse(this.toString("d") + " " + time) : this.set(time);
625 };
626 $N.fromNow = $N.after = function (date) {
627 var c = {};
628 c[this._dateElement] = this;
629 return ((!date) ? new Date() : date.clone()).add(c);
630 };
631 $N.ago = $N.before = function (date) {
632 var c = {};
633 c[this._dateElement] = this * -1;
634 return ((!date) ? new Date() : date.clone()).add(c);
635 };
636 var dx = ("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),
637 mx = ("january february march april may june july august september october november december").split(/\s/),
638 px = ("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),
639 pxf = ("Milliseconds Seconds Minutes Hours Date Week Month FullYear").split(/\s/),
640 nth = ("final first second third fourth fifth").split(/\s/),
641 de;
642 $P.toObject = function () {
643 var o = {};
644 for (var i = 0; i < px.length; i++) {
645 o[px[i].toLowerCase()] = this["get" + pxf[i]]();
646 }
647 return o;
648 };
649 $D.fromObject = function (config) {
650 config.week = null;
651 return Date.today().set(config);
652 };
653 var df = function (n) {
654 return function () {
655 if (this._is) {
656 this._is = false;
657 return this.getDay() == n;
658 }
659 if (this._nth !== null) {
660 if (this._isSecond) {
661 this.addSeconds(this._orient * -1);
662 }
663 this._isSecond = false;
664 var ntemp = this._nth;
665 this._nth = null;
666 var temp = this.clone().moveToLastDayOfMonth();
667 this.moveToNthOccurrence(n, ntemp);
668 if (this > temp) {
669 throw new RangeError($D.getDayName(n) + " does not occur " + ntemp + " times in the month of " + $D.getMonthName(temp.getMonth()) + " " + temp.getFullYear() + ".");
670 }
671 return this;
672 }
673 return this.moveToDayOfWeek(n, this._orient);
674 };
675 };
676 var sdf = function (n) {
677 return function () {
678 var t = $D.today(),
679 shift = n - t.getDay();
680 if (n === 0 && $C.firstDayOfWeek === 1 && t.getDay() !== 0) {
681 shift = shift + 7;
682 }
683 return t.addDays(shift);
684 };
685 };
686 for (var i = 0; i < dx.length; i++) {
687 $D[dx[i].toUpperCase()] = $D[dx[i].toUpperCase().substring(0, 3)] = i;
688 $D[dx[i]] = $D[dx[i].substring(0, 3)] = sdf(i);
689 $P[dx[i]] = $P[dx[i].substring(0, 3)] = df(i);
690 }
691 var mf = function (n) {
692 return function () {
693 if (this._is) {
694 this._is = false;
695 return this.getMonth() === n;
696 }
697 return this.moveToMonth(n, this._orient);
698 };
699 };
700 var smf = function (n) {
701 return function () {
702 return $D.today().set({
703 month: n,
704 day: 1
705 });
706 };
707 };
708 for (var j = 0; j < mx.length; j++) {
709 $D[mx[j].toUpperCase()] = $D[mx[j].toUpperCase().substring(0, 3)] = j;
710 $D[mx[j]] = $D[mx[j].substring(0, 3)] = smf(j);
711 $P[mx[j]] = $P[mx[j].substring(0, 3)] = mf(j);
712 }
713 var ef = function (j) {
714 return function () {
715 if (this._isSecond) {
716 this._isSecond = false;
717 return this;
718 }
719 if (this._same) {
720 this._same = this._is = false;
721 var o1 = this.toObject(),
722 o2 = (arguments[0] || new Date()).toObject(),
723 v = "",
724 k = j.toLowerCase();
725 for (var m = (px.length - 1); m > -1; m--) {
726 v = px[m].toLowerCase();
727 if (o1[v] != o2[v]) {
728 return false;
729 }
730 if (k == v) {
731 break;
732 }
733 }
734 return true;
735 }
736 if (j.substring(j.length - 1) != "s") {
737 j += "s";
738 }
739 return this["add" + j](this._orient);
740 };
741 };
742 var nf = function (n) {
743 return function () {
744 this._dateElement = n;
745 return this;
746 };
747 };
748 for (var k = 0; k < px.length; k++) {
749 de = px[k].toLowerCase();
750 $P[de] = $P[de + "s"] = ef(px[k]);
751 $N[de] = $N[de + "s"] = nf(de);
752 }
753 $P._ss = ef("Second");
754 var nthfn = function (n) {
755 return function (dayOfWeek) {
756 if (this._same) {
757 return this._ss(arguments[0]);
758 }
759 if (dayOfWeek || dayOfWeek === 0) {
760 return this.moveToNthOccurrence(dayOfWeek, n);
761 }
762 this._nth = n;
763 if (n === 2 && (dayOfWeek === undefined || dayOfWeek === null)) {
764 this._isSecond = true;
765 return this.addSeconds(this._orient);
766 }
767 return this;
768 };
769 };
770 for (var l = 0; l < nth.length; l++) {
771 $P[nth[l]] = (l === 0) ? nthfn(-1) : nthfn(l);
772 }
773 }());
774 (function () {
775 Date.Parsing = {
776 Exception: function (s) {
777 this.message = "Parse error at '" + s.substring(0, 10) + " ...'";
778 }
779 };
780 var $P = Date.Parsing;
781 var _ = $P.Operators = {
782 rtoken: function (r) {
783 return function (s) {
784 var mx = s.match(r);
785 if (mx) {
786 return ([mx[0], s.substring(mx[0].length)]);
787 } else {
788 throw new $P.Exception(s);
789 }
790 };
791 },
792 token: function (s) {
793 return function (s) {
794 return _.rtoken(new RegExp("^\s*" + s + "\s*"))(s);
795 };
796 },
797 stoken: function (s) {
798 return _.rtoken(new RegExp("^" + s));
799 },
800 until: function (p) {
801 return function (s) {
802 var qx = [],
803 rx = null;
804 while (s.length) {
805 try {
806 rx = p.call(this, s);
807 } catch (e) {
808 qx.push(rx[0]);
809 s = rx[1];
810 continue;
811 }
812 break;
813 }
814 return [qx, s];
815 };
816 },
817 many: function (p) {
818 return function (s) {
819 var rx = [],
820 r = null;
821 while (s.length) {
822 try {
823 r = p.call(this, s);
824 } catch (e) {
825 return [rx, s];
826 }
827 rx.push(r[0]);
828 s = r[1];
829 }
830 return [rx, s];
831 };
832 },
833 optional: function (p) {
834 return function (s) {
835 var r = null;
836 try {
837 r = p.call(this, s);
838 } catch (e) {
839 return [null, s];
840 }
841 return [r[0], r[1]];
842 };
843 },
844 not: function (p) {
845 return function (s) {
846 try {
847 p.call(this, s);
848 } catch (e) {
849 return [null, s];
850 }
851 throw new $P.Exception(s);
852 };
853 },
854 ignore: function (p) {
855 return p ? function (s) {
856 var r = null;
857 r = p.call(this, s);
858 return [null, r[1]];
859 } : null;
860 },
861 product: function () {
862 var px = arguments[0],
863 qx = Array.prototype.slice.call(arguments, 1),
864 rx = [];
865 for (var i = 0; i < px.length; i++) {
866 rx.push(_.each(px[i], qx));
867 }
868 return rx;
869 },
870 cache: function (rule) {
871 var cache = {},
872 r = null;
873 return function (s) {
874 try {
875 r = cache[s] = (cache[s] || rule.call(this, s));
876 } catch (e) {
877 r = cache[s] = e;
878 }
879 if (r instanceof $P.Exception) {
880 throw r;
881 } else {
882 return r;
883 }
884 };
885 },
886 any: function () {
887 var px = arguments;
888 return function (s) {
889 var r = null;
890 for (var i = 0; i < px.length; i++) {
891 if (px[i] == null) {
892 continue;
893 }
894 try {
895 r = (px[i].call(this, s));
896 } catch (e) {
897 r = null;
898 }
899 if (r) {
900 return r;
901 }
902 }
903 throw new $P.Exception(s);
904 };
905 },
906 each: function () {
907 var px = arguments;
908 return function (s) {
909 var rx = [],
910 r = null;
911 for (var i = 0; i < px.length; i++) {
912 if (px[i] == null) {
913 continue;
914 }
915 try {
916 r = (px[i].call(this, s));
917 } catch (e) {
918 throw new $P.Exception(s);
919 }
920 rx.push(r[0]);
921 s = r[1];
922 }
923 return [rx, s];
924 };
925 },
926 all: function () {
927 var px = arguments,
928 _ = _;
929 return _.each(_.optional(px));
930 },
931 sequence: function (px, d, c) {
932 d = d || _.rtoken(/^\s*/);
933 c = c || null;
934 if (px.length == 1) {
935 return px[0];
936 }
937 return function (s) {
938 var r = null,
939 q = null;
940 var rx = [];
941 for (var i = 0; i < px.length; i++) {
942 try {
943 r = px[i].call(this, s);
944 } catch (e) {
945 break;
946 }
947 rx.push(r[0]);
948 try {
949 q = d.call(this, r[1]);
950 } catch (ex) {
951 q = null;
952 break;
953 }
954 s = q[1];
955 }
956 if (!r) {
957 throw new $P.Exception(s);
958 }
959 if (q) {
960 throw new $P.Exception(q[1]);
961 }
962 if (c) {
963 try {
964 r = c.call(this, r[1]);
965 } catch (ey) {
966 throw new $P.Exception(r[1]);
967 }
968 }
969 return [rx, (r ? r[1] : s)];
970 };
971 },
972 between: function (d1, p, d2) {
973 d2 = d2 || d1;
974 var _fn = _.each(_.ignore(d1), p, _.ignore(d2));
975 return function (s) {
976 var rx = _fn.call(this, s);
977 return [
978 [rx[0][0], r[0][2]], rx[1]
979 ];
980 };
981 },
982 list: function (p, d, c) {
983 d = d || _.rtoken(/^\s*/);
984 c = c || null;
985 return (p instanceof Array ? _.each(_.product(p.slice(0, -1), _.ignore(d)), p.slice(-1), _.ignore(c)) : _.each(_.many(_.each(p, _.ignore(d))), px, _.ignore(c)));
986 },
987 set: function (px, d, c) {
988 d = d || _.rtoken(/^\s*/);
989 c = c || null;
990 return function (s) {
991 var r = null,
992 p = null,
993 q = null,
994 rx = null,
995 best = [
996 [], s
997 ],
998 last = false;
999 for (var i = 0; i < px.length; i++) {
1000 q = null;
1001 p = null;
1002 r = null;
1003 last = (px.length == 1);
1004 try {
1005 r = px[i].call(this, s);
1006 } catch (e) {
1007 continue;
1008 }
1009 rx = [
1010 [r[0]], r[1]
1011 ];
1012 if (r[1].length > 0 && !last) {
1013 try {
1014 q = d.call(this, r[1]);
1015 } catch (ex) {
1016 last = true;
1017 }
1018 } else {
1019 last = true;
1020 }
1021 if (!last && q[1].length === 0) {
1022 last = true;
1023 }
1024 if (!last) {
1025 var qx = [];
1026 for (var j = 0; j < px.length; j++) {
1027 if (i != j) {
1028 qx.push(px[j]);
1029 }
1030 }
1031 p = _.set(qx, d).call(this, q[1]);
1032 if (p[0].length > 0) {
1033 rx[0] = rx[0].concat(p[0]);
1034 rx[1] = p[1];
1035 }
1036 }
1037 if (rx[1].length < best[1].length) {
1038 best = rx;
1039 }
1040 if (best[1].length === 0) {
1041 break;
1042 }
1043 }
1044 if (best[0].length === 0) {
1045 return best;
1046 }
1047 if (c) {
1048 try {
1049 q = c.call(this, best[1]);
1050 } catch (ey) {
1051 throw new $P.Exception(best[1]);
1052 }
1053 best[1] = q[1];
1054 }
1055 return best;
1056 };
1057 },
1058 forward: function (gr, fname) {
1059 return function (s) {
1060 return gr[fname].call(this, s);
1061 };
1062 },
1063 replace: function (rule, repl) {
1064 return function (s) {
1065 var r = rule.call(this, s);
1066 return [repl, r[1]];
1067 };
1068 },
1069 process: function (rule, fn) {
1070 return function (s) {
1071 var r = rule.call(this, s);
1072 return [fn.call(this, r[0]), r[1]];
1073 };
1074 },
1075 min: function (min, rule) {
1076 return function (s) {
1077 var rx = rule.call(this, s);
1078 if (rx[0].length < min) {
1079 throw new $P.Exception(s);
1080 }
1081 return rx;
1082 };
1083 }
1084 };
1085 var _generator = function (op) {
1086 return function () {
1087 var args = null,
1088 rx = [];
1089 if (arguments.length > 1) {
1090 args = Array.prototype.slice.call(arguments);
1091 } else if (arguments[0] instanceof Array) {
1092 args = arguments[0];
1093 }
1094 if (args) {
1095 for (var i = 0, px = args.shift(); i < px.length; i++) {
1096 args.unshift(px[i]);
1097 rx.push(op.apply(null, args));
1098 args.shift();
1099 return rx;
1100 }
1101 } else {
1102 return op.apply(null, arguments);
1103 }
1104 };
1105 };
1106 var gx = "optional not ignore cache".split(/\s/);
1107 for (var i = 0; i < gx.length; i++) {
1108 _[gx[i]] = _generator(_[gx[i]]);
1109 }
1110 var _vector = function (op) {
1111 return function () {
1112 if (arguments[0] instanceof Array) {
1113 return op.apply(null, arguments[0]);
1114 } else {
1115 return op.apply(null, arguments);
1116 }
1117 };
1118 };
1119 var vx = "each any all".split(/\s/);
1120 for (var j = 0; j < vx.length; j++) {
1121 _[vx[j]] = _vector(_[vx[j]]);
1122 }
1123 }());
1124 (function () {
1125 var $D = Date,
1126 $P = $D.prototype,
1127 $C = $D.CultureInfo;
1128 var flattenAndCompact = function (ax) {
1129 var rx = [];
1130 for (var i = 0; i < ax.length; i++) {
1131 if (ax[i] instanceof Array) {
1132 rx = rx.concat(flattenAndCompact(ax[i]));
1133 } else {
1134 if (ax[i]) {
1135 rx.push(ax[i]);
1136 }
1137 }
1138 }
1139 return rx;
1140 };
1141 $D.Grammar = {};
1142 $D.Translator = {
1143 hour: function (s) {
1144 return function () {
1145 this.hour = Number(s);
1146 };
1147 },
1148 minute: function (s) {
1149 return function () {
1150 this.minute = Number(s);
1151 };
1152 },
1153 second: function (s) {
1154 return function () {
1155 this.second = Number(s);
1156 };
1157 },
1158 meridian: function (s) {
1159 return function () {
1160 this.meridian = s.slice(0, 1).toLowerCase();
1161 };
1162 },
1163 timezone: function (s) {
1164 return function () {
1165 var n = s.replace(/[^\d\+\-]/g, "");
1166 if (n.length) {
1167 this.timezoneOffset = Number(n);
1168 } else {
1169 this.timezone = s.toLowerCase();
1170 }
1171 };
1172 },
1173 day: function (x) {
1174 var s = x[0];
1175 return function () {
1176 this.day = Number(s.match(/\d+/)[0]);
1177 };
1178 },
1179 month: function (s) {
1180 return function () {
1181 this.month = (s.length == 3) ? "jan feb mar apr may jun jul aug sep oct nov dec".indexOf(s) / 4 : Number(s) - 1;
1182 };
1183 },
1184 year: function (s) {
1185 return function () {
1186 var n = Number(s);
1187 this.year = ((s.length > 2) ? n : (n + (((n + 2000) < $C.twoDigitYearMax) ? 2000 : 1900)));
1188 };
1189 },
1190 rday: function (s) {
1191 return function () {
1192 switch (s) {
1193 case "yesterday":
1194 this.days = -1;
1195 break;
1196 case "tomorrow":
1197 this.days = 1;
1198 break;
1199 case "today":
1200 this.days = 0;
1201 break;
1202 case "now":
1203 this.days = 0;
1204 this.now = true;
1205 break;
1206 }
1207 };
1208 },
1209 finishExact: function (x) {
1210 x = (x instanceof Array) ? x : [x];
1211 for (var i = 0; i < x.length; i++) {
1212 if (x[i]) {
1213 x[i].call(this);
1214 }
1215 }
1216 var now = new Date();
1217 if ((this.hour || this.minute) && (!this.month && !this.year && !this.day)) {
1218 this.day = now.getDate();
1219 }
1220 if (!this.year) {
1221 this.year = now.getFullYear();
1222 }
1223 if (!this.month && this.month !== 0) {
1224 this.month = now.getMonth();
1225 }
1226 if (!this.day) {
1227 this.day = 1;
1228 }
1229 if (!this.hour) {
1230 this.hour = 0;
1231 }
1232 if (!this.minute) {
1233 this.minute = 0;
1234 }
1235 if (!this.second) {
1236 this.second = 0;
1237 }
1238 if (this.meridian && this.hour) {
1239 if (this.meridian == "p" && this.hour < 12) {
1240 this.hour = this.hour + 12;
1241 } else if (this.meridian == "a" && this.hour == 12) {
1242 this.hour = 0;
1243 }
1244 }
1245 if (this.day > $D.getDaysInMonth(this.year, this.month)) {
1246 throw new RangeError(this.day + " is not a valid value for days.");
1247 }
1248 var r = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second);
1249 if (this.timezone) {
1250 r.set({
1251 timezone: this.timezone
1252 });
1253 } else if (this.timezoneOffset) {
1254 r.set({
1255 timezoneOffset: this.timezoneOffset
1256 });
1257 }
1258 return r;
1259 },
1260 finish: function (x) {
1261 x = (x instanceof Array) ? flattenAndCompact(x) : [x];
1262 if (x.length === 0) {
1263 return null;
1264 }
1265 for (var i = 0; i < x.length; i++) {
1266 if (typeof x[i] == "function") {
1267 x[i].call(this);
1268 }
1269 }
1270 var today = $D.today();
1271 if (this.now && !this.unit && !this.operator) {
1272 return new Date();
1273 } else if (this.now) {
1274 today = new Date();
1275 }
1276 var expression = !!(this.days && this.days !== null || this.orient || this.operator);
1277 var gap, mod, orient;
1278 orient = ((this.orient == "past" || this.operator == "subtract") ? -1 : 1);
1279 if (!this.now && "hour minute second".indexOf(this.unit) != -1) {
1280 today.setTimeToNow();
1281 }
1282 if (this.month || this.month === 0) {
1283 if ("year day hour minute second".indexOf(this.unit) != -1) {
1284 this.value = this.month + 1;
1285 this.month = null;
1286 expression = true;
1287 }
1288 }
1289 if (!expression && this.weekday && !this.day && !this.days) {
1290 var temp = Date[this.weekday]();
1291 this.day = temp.getDate();
1292 if (!this.month) {
1293 this.month = temp.getMonth();
1294 }
1295 this.year = temp.getFullYear();
1296 }
1297 if (expression && this.weekday && this.unit != "month") {
1298 this.unit = "day";
1299 gap = ($D.getDayNumberFromName(this.weekday) - today.getDay());
1300 mod = 7;
1301 this.days = gap ? ((gap + (orient * mod)) % mod) : (orient * mod);
1302 }
1303 if (this.month && this.unit == "day" && this.operator) {
1304 this.value = (this.month + 1);
1305 this.month = null;
1306 }
1307 if (this.value != null && this.month != null && this.year != null) {
1308 this.day = this.value * 1;
1309 }
1310 if (this.month && !this.day && this.value) {
1311 today.set({
1312 day: this.value * 1
1313 });
1314 if (!expression) {
1315 this.day = this.value * 1;
1316 }
1317 }
1318 if (!this.month && this.value && this.unit == "month" && !this.now) {
1319 this.month = this.value;
1320 expression = true;
1321 }
1322 if (expression && (this.month || this.month === 0) && this.unit != "year") {
1323 this.unit = "month";
1324 gap = (this.month - today.getMonth());
1325 mod = 12;
1326 this.months = gap ? ((gap + (orient * mod)) % mod) : (orient * mod);
1327 this.month = null;
1328 }
1329 if (!this.unit) {
1330 this.unit = "day";
1331 }
1332 if (!this.value && this.operator && this.operator !== null && this[this.unit + "s"] && this[this.unit + "s"] !== null) {
1333 this[this.unit + "s"] = this[this.unit + "s"] + ((this.operator == "add") ? 1 : -1) + (this.value || 0) * orient;
1334 } else if (this[this.unit + "s"] == null || this.operator != null) {
1335 if (!this.value) {
1336 this.value = 1;
1337 }
1338 this[this.unit + "s"] = this.value * orient;
1339 }
1340 if (this.meridian && this.hour) {
1341 if (this.meridian == "p" && this.hour < 12) {
1342 this.hour = this.hour + 12;
1343 } else if (this.meridian == "a" && this.hour == 12) {
1344 this.hour = 0;
1345 }
1346 }
1347 if (this.weekday && !this.day && !this.days) {
1348 var temp = Date[this.weekday]();
1349 this.day = temp.getDate();
1350 if (temp.getMonth() !== today.getMonth()) {
1351 this.month = temp.getMonth();
1352 }
1353 }
1354 if ((this.month || this.month === 0) && !this.day) {
1355 this.day = 1;
1356 }
1357 if (!this.orient && !this.operator && this.unit == "week" && this.value && !this.day && !this.month) {
1358 return Date.today().setWeek(this.value);
1359 }
1360 if (expression && this.timezone && this.day && this.days) {
1361 this.day = this.days;
1362 }
1363 return (expression) ? today.add(this) : today.set(this);
1364 }
1365 };
1366 var _ = $D.Parsing.Operators,
1367 g = $D.Grammar,
1368 t = $D.Translator,
1369 _fn;
1370 g.datePartDelimiter = _.rtoken(/^([\s\-\.\,\/\x27]+)/);
1371 g.timePartDelimiter = _.stoken(":");
1372 g.whiteSpace = _.rtoken(/^\s*/);
1373 g.generalDelimiter = _.rtoken(/^(([\s\,]|at|@|on)+)/);
1374 var _C = {};
1375 g.ctoken = function (keys) {
1376 var fn = _C[keys];
1377 if (!fn) {
1378 var c = $C.regexPatterns;
1379 var kx = keys.split(/\s+/),
1380 px = [];
1381 for (var i = 0; i < kx.length; i++) {
1382 px.push(_.replace(_.rtoken(c[kx[i]]), kx[i]));
1383 }
1384 fn = _C[keys] = _.any.apply(null, px);
1385 }
1386 return fn;
1387 };
1388 g.ctoken2 = function (key) {
1389 return _.rtoken($C.regexPatterns[key]);
1390 };
1391 g.h = _.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/), t.hour));
1392 g.hh = _.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/), t.hour));
1393 g.H = _.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/), t.hour));
1394 g.HH = _.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/), t.hour));
1395 g.m = _.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/), t.minute));
1396 g.mm = _.cache(_.process(_.rtoken(/^[0-5][0-9]/), t.minute));
1397 g.s = _.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/), t.second));
1398 g.ss = _.cache(_.process(_.rtoken(/^[0-5][0-9]/), t.second));
1399 g.hms = _.cache(_.sequence([g.H, g.m, g.s], g.timePartDelimiter));
1400 g.t = _.cache(_.process(g.ctoken2("shortMeridian"), t.meridian));
1401 g.tt = _.cache(_.process(g.ctoken2("longMeridian"), t.meridian));
1402 g.z = _.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/), t.timezone));
1403 g.zz = _.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/), t.timezone));
1404 g.zzz = _.cache(_.process(g.ctoken2("timezone"), t.timezone));
1405 g.timeSuffix = _.each(_.ignore(g.whiteSpace), _.set([g.tt, g.zzz]));
1406 g.time = _.each(_.optional(_.ignore(_.stoken("T"))), g.hms, g.timeSuffix);
1407 g.d = _.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/), _.optional(g.ctoken2("ordinalSuffix"))), t.day));
1408 g.dd = _.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/), _.optional(g.ctoken2("ordinalSuffix"))), t.day));
1409 g.ddd = g.dddd = _.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"), function (s) {
1410 return function () {
1411 this.weekday = s;
1412 };
1413 }));
1414 g.M = _.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/), t.month));
1415 g.MM = _.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/), t.month));
1416 g.MMM = g.MMMM = _.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"), t.month));
1417 g.y = _.cache(_.process(_.rtoken(/^(\d\d?)/), t.year));
1418 g.yy = _.cache(_.process(_.rtoken(/^(\d\d)/), t.year));
1419 g.yyy = _.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/), t.year));
1420 g.yyyy = _.cache(_.process(_.rtoken(/^(\d\d\d\d)/), t.year));
1421 _fn = function () {
1422 return _.each(_.any.apply(null, arguments), _.not(g.ctoken2("timeContext")));
1423 };
1424 g.day = _fn(g.d, g.dd);
1425 g.month = _fn(g.M, g.MMM);
1426 g.year = _fn(g.yyyy, g.yy);
1427 g.orientation = _.process(g.ctoken("past future"), function (s) {
1428 return function () {
1429 this.orient = s;
1430 };
1431 });
1432 g.operator = _.process(g.ctoken("add subtract"), function (s) {
1433 return function () {
1434 this.operator = s;
1435 };
1436 });
1437 g.rday = _.process(g.ctoken("yesterday tomorrow today now"), t.rday);
1438 g.unit = _.process(g.ctoken("second minute hour day week month year"), function (s) {
1439 return function () {
1440 this.unit = s;
1441 };
1442 });
1443 g.value = _.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/), function (s) {
1444 return function () {
1445 this.value = s.replace(/\D/g, "");
1446 };
1447 });
1448 g.expression = _.set([g.rday, g.operator, g.value, g.unit, g.orientation, g.ddd, g.MMM]);
1449 _fn = function () {
1450 return _.set(arguments, g.datePartDelimiter);
1451 };
1452 g.mdy = _fn(g.ddd, g.month, g.day, g.year);
1453 g.ymd = _fn(g.ddd, g.year, g.month, g.day);
1454 g.dmy = _fn(g.ddd, g.day, g.month, g.year);
1455 g.date = function (s) {
1456 return ((g[$C.dateElementOrder] || g.mdy).call(this, s));
1457 };
1458 g.format = _.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/), function (fmt) {
1459 if (g[fmt]) {
1460 return g[fmt];
1461 } else {
1462 throw $D.Parsing.Exception(fmt);
1463 }
1464 }), _.process(_.rtoken(/^[^dMyhHmstz]+/), function (s) {
1465 return _.ignore(_.stoken(s));
1466 }))), function (rules) {
1467 return _.process(_.each.apply(null, rules), t.finishExact);
1468 });
1469 var _F = {};
1470 var _get = function (f) {
1471 return _F[f] = (_F[f] || g.format(f)[0]);
1472 };
1473 g.formats = function (fx) {
1474 if (fx instanceof Array) {
1475 var rx = [];
1476 for (var i = 0; i < fx.length; i++) {
1477 rx.push(_get(fx[i]));
1478 }
1479 return _.any.apply(null, rx);
1480 } else {
1481 return _get(fx);
1482 }
1483 };
1484 g._formats = g.formats(["\"yyyy-MM-ddTHH:mm:ssZ\"", "yyyy-MM-ddTHH:mm:ssZ", "yyyy-MM-ddTHH:mm:ssz", "yyyy-MM-ddTHH:mm:ss", "yyyy-MM-ddTHH:mmZ", "yyyy-MM-ddTHH:mmz", "yyyy-MM-ddTHH:mm", "ddd, MMM dd, yyyy H:mm:ss tt", "ddd MMM d yyyy HH:mm:ss zzz", "MMddyyyy", "ddMMyyyy", "Mddyyyy", "ddMyyyy", "Mdyyyy", "dMyyyy", "yyyy", "Mdyy", "dMyy", "d"]);
1485 g._start = _.process(_.set([g.date, g.time, g.expression], g.generalDelimiter, g.whiteSpace), t.finish);
1486 g.start = function (s) {
1487 try {
1488 var r = g._formats.call({}, s);
1489 if (r[1].length === 0) {
1490 return r;
1491 }
1492 } catch (e) {}
1493 return g._start.call({}, s);
1494 };
1495 $D._parse = $D.parse;
1496 $D.parse = function (s) {
1497 var r = null;
1498 if (!s) {
1499 return null;
1500 }
1501 if (s instanceof Date) {
1502 return s;
1503 }
1504 try {
1505 r = $D.Grammar.start.call({}, s.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1"));
1506 } catch (e) {
1507 return null;
1508 }
1509 return ((r[1].length === 0) ? r[0] : null);
1510 };
1511 $D.getParseFunction = function (fx) {
1512 var fn = $D.Grammar.formats(fx);
1513 return function (s) {
1514 var r = null;
1515 try {
1516 r = fn.call({}, s);
1517 } catch (e) {
1518 return null;
1519 }
1520 return ((r[1].length === 0) ? r[0] : null);
1521 };
1522 };
1523 $D.parseExact = function (s, fx) {
1524 return $D.getParseFunction(fx)(s);
1525 };
1526 }());
1527
1528 // module.exports = {
1529 // Date:Date
1530 // }
1531
1532 module.exports = Date;
...\ No newline at end of file ...\ No newline at end of file
This diff could not be displayed because it is too large.
1 var __request = wx.request;
2 var Mock = require("./mock.js");
3 // console.log('Mock', Mock)
4 Object.defineProperty(wx, "request", { writable: true }); wx.request = function (config) { if (typeof Mock._mocked[config.url] == "undefined") { __request(config); return } var resTemplate = Mock._mocked[config.url].template; var response = Mock.mock(resTemplate); if (typeof config.success == "function") { config.success(response) } if (typeof config.complete == "function") { config.complete(response) } }; module.exports = Mock;
1 !(function () {
2
3 // alignment pattern
4 var adelta = [
5 0, 11, 15, 19, 23, 27, 31,
6 16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24,
7 26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28
8 ];
9
10 // version block
11 var vpat = [
12 0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d,
13 0x928, 0xb78, 0x45d, 0xa17, 0x532, 0x9a6, 0x683, 0x8c9,
14 0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75,
15 0x250, 0x9d5, 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64,
16 0x541, 0xc69
17 ];
18
19 // final format bits with mask: level << 3 | mask
20 var fmtword = [
21 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, //L
22 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, //M
23 0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, //Q
24 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b //H
25 ];
26
27 // 4 per version: number of blocks 1,2; data width; ecc width
28 var eccblocks = [
29 1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17,
30 1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28,
31 1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22,
32 1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16,
33 1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22,
34 2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28,
35 2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26,
36 2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26,
37 2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24,
38 2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28,
39 4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24,
40 2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28,
41 4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22,
42 3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24,
43 5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24,
44 5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30,
45 1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28,
46 5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28,
47 3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26,
48 3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28,
49 4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30,
50 2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24,
51 4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30,
52 6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30,
53 8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30,
54 10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30,
55 8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30,
56 3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30,
57 7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30,
58 5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30,
59 13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30,
60 17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30,
61 17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30,
62 13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30,
63 12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30,
64 6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30,
65 17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30,
66 4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30,
67 20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30,
68 19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30
69 ];
70
71 // Galois field log table
72 var glog = [
73 0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
74 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
75 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
76 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
77 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
78 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
79 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
80 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
81 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
82 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
83 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
84 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
85 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
86 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
87 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
88 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
89 ];
90
91 // Galios field exponent table
92 var gexp = [
93 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
94 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
95 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
96 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
97 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
98 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
99 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
100 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
101 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
102 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
103 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
104 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
105 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
106 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
107 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
108 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00
109 ];
110
111 // Working buffers:
112 // data input and ecc append, image working buffer, fixed part of image, run lengths for badness
113 var strinbuf = [], eccbuf = [], qrframe = [], framask = [], rlens = [];
114 // Control values - width is based on version, last 4 are from table.
115 var version, width, neccblk1, neccblk2, datablkw, eccblkwid;
116 var ecclevel = 2;
117 // set bit to indicate cell in qrframe is immutable. symmetric around diagonal
118 function setmask(x, y) {
119 var bt;
120 if (x > y) {
121 bt = x;
122 x = y;
123 y = bt;
124 }
125 // y*y = 1+3+5...
126 bt = y;
127 bt *= y;
128 bt += y;
129 bt >>= 1;
130 bt += x;
131 framask[bt] = 1;
132 }
133
134 // enter alignment pattern - black to qrframe, white to mask (later black frame merged to mask)
135 function putalign(x, y) {
136 var j;
137
138 qrframe[x + width * y] = 1;
139 for (j = -2; j < 2; j++) {
140 qrframe[(x + j) + width * (y - 2)] = 1;
141 qrframe[(x - 2) + width * (y + j + 1)] = 1;
142 qrframe[(x + 2) + width * (y + j)] = 1;
143 qrframe[(x + j + 1) + width * (y + 2)] = 1;
144 }
145 for (j = 0; j < 2; j++) {
146 setmask(x - 1, y + j);
147 setmask(x + 1, y - j);
148 setmask(x - j, y - 1);
149 setmask(x + j, y + 1);
150 }
151 }
152
153 //========================================================================
154 // Reed Solomon error correction
155 // exponentiation mod N
156 function modnn(x) {
157 while (x >= 255) {
158 x -= 255;
159 x = (x >> 8) + (x & 255);
160 }
161 return x;
162 }
163
164 var genpoly = [];
165
166 // Calculate and append ECC data to data block. Block is in strinbuf, indexes to buffers given.
167 function appendrs(data, dlen, ecbuf, eclen) {
168 var i, j, fb;
169
170 for (i = 0; i < eclen; i++)
171 strinbuf[ecbuf + i] = 0;
172 for (i = 0; i < dlen; i++) {
173 fb = glog[strinbuf[data + i] ^ strinbuf[ecbuf]];
174 if (fb != 255) /* fb term is non-zero */
175 for (j = 1; j < eclen; j++)
176 strinbuf[ecbuf + j - 1] = strinbuf[ecbuf + j] ^ gexp[modnn(fb + genpoly[eclen - j])];
177 else
178 for (j = ecbuf; j < ecbuf + eclen; j++)
179 strinbuf[j] = strinbuf[j + 1];
180 strinbuf[ecbuf + eclen - 1] = fb == 255 ? 0 : gexp[modnn(fb + genpoly[0])];
181 }
182 }
183
184 //========================================================================
185 // Frame data insert following the path rules
186
187 // check mask - since symmetrical use half.
188 function ismasked(x, y) {
189 var bt;
190 if (x > y) {
191 bt = x;
192 x = y;
193 y = bt;
194 }
195 bt = y;
196 bt += y * y;
197 bt >>= 1;
198 bt += x;
199 return framask[bt];
200 }
201
202 //========================================================================
203 // Apply the selected mask out of the 8.
204 function applymask(m) {
205 var x, y, r3x, r3y;
206
207 switch (m) {
208 case 0:
209 for (y = 0; y < width; y++)
210 for (x = 0; x < width; x++)
211 if (!((x + y) & 1) && !ismasked(x, y))
212 qrframe[x + y * width] ^= 1;
213 break;
214 case 1:
215 for (y = 0; y < width; y++)
216 for (x = 0; x < width; x++)
217 if (!(y & 1) && !ismasked(x, y))
218 qrframe[x + y * width] ^= 1;
219 break;
220 case 2:
221 for (y = 0; y < width; y++)
222 for (r3x = 0, x = 0; x < width; x++ , r3x++) {
223 if (r3x == 3)
224 r3x = 0;
225 if (!r3x && !ismasked(x, y))
226 qrframe[x + y * width] ^= 1;
227 }
228 break;
229 case 3:
230 for (r3y = 0, y = 0; y < width; y++ , r3y++) {
231 if (r3y == 3)
232 r3y = 0;
233 for (r3x = r3y, x = 0; x < width; x++ , r3x++) {
234 if (r3x == 3)
235 r3x = 0;
236 if (!r3x && !ismasked(x, y))
237 qrframe[x + y * width] ^= 1;
238 }
239 }
240 break;
241 case 4:
242 for (y = 0; y < width; y++)
243 for (r3x = 0, r3y = ((y >> 1) & 1), x = 0; x < width; x++ , r3x++) {
244 if (r3x == 3) {
245 r3x = 0;
246 r3y = !r3y;
247 }
248 if (!r3y && !ismasked(x, y))
249 qrframe[x + y * width] ^= 1;
250 }
251 break;
252 case 5:
253 for (r3y = 0, y = 0; y < width; y++ , r3y++) {
254 if (r3y == 3)
255 r3y = 0;
256 for (r3x = 0, x = 0; x < width; x++ , r3x++) {
257 if (r3x == 3)
258 r3x = 0;
259 if (!((x & y & 1) + !(!r3x | !r3y)) && !ismasked(x, y))
260 qrframe[x + y * width] ^= 1;
261 }
262 }
263 break;
264 case 6:
265 for (r3y = 0, y = 0; y < width; y++ , r3y++) {
266 if (r3y == 3)
267 r3y = 0;
268 for (r3x = 0, x = 0; x < width; x++ , r3x++) {
269 if (r3x == 3)
270 r3x = 0;
271 if (!(((x & y & 1) + (r3x && (r3x == r3y))) & 1) && !ismasked(x, y))
272 qrframe[x + y * width] ^= 1;
273 }
274 }
275 break;
276 case 7:
277 for (r3y = 0, y = 0; y < width; y++ , r3y++) {
278 if (r3y == 3)
279 r3y = 0;
280 for (r3x = 0, x = 0; x < width; x++ , r3x++) {
281 if (r3x == 3)
282 r3x = 0;
283 if (!(((r3x && (r3x == r3y)) + ((x + y) & 1)) & 1) && !ismasked(x, y))
284 qrframe[x + y * width] ^= 1;
285 }
286 }
287 break;
288 }
289 return;
290 }
291
292 // Badness coefficients.
293 var N1 = 3, N2 = 3, N3 = 40, N4 = 10;
294
295 // Using the table of the length of each run, calculate the amount of bad image
296 // - long runs or those that look like finders; called twice, once each for X and Y
297 function badruns(length) {
298 var i;
299 var runsbad = 0;
300 for (i = 0; i <= length; i++)
301 if (rlens[i] >= 5)
302 runsbad += N1 + rlens[i] - 5;
303 // BwBBBwB as in finder
304 for (i = 3; i < length - 1; i += 2)
305 if (rlens[i - 2] == rlens[i + 2]
306 && rlens[i + 2] == rlens[i - 1]
307 && rlens[i - 1] == rlens[i + 1]
308 && rlens[i - 1] * 3 == rlens[i]
309 // white around the black pattern? Not part of spec
310 && (rlens[i - 3] == 0 // beginning
311 || i + 3 > length // end
312 || rlens[i - 3] * 3 >= rlens[i] * 4 || rlens[i + 3] * 3 >= rlens[i] * 4)
313 )
314 runsbad += N3;
315 return runsbad;
316 }
317
318 // Calculate how bad the masked image is - blocks, imbalance, runs, or finders.
319 function badcheck() {
320 var x, y, h, b, b1;
321 var thisbad = 0;
322 var bw = 0;
323
324 // blocks of same color.
325 for (y = 0; y < width - 1; y++)
326 for (x = 0; x < width - 1; x++)
327 if ((qrframe[x + width * y] && qrframe[(x + 1) + width * y]
328 && qrframe[x + width * (y + 1)] && qrframe[(x + 1) + width * (y + 1)]) // all black
329 || !(qrframe[x + width * y] || qrframe[(x + 1) + width * y]
330 || qrframe[x + width * (y + 1)] || qrframe[(x + 1) + width * (y + 1)])) // all white
331 thisbad += N2;
332
333 // X runs
334 for (y = 0; y < width; y++) {
335 rlens[0] = 0;
336 for (h = b = x = 0; x < width; x++) {
337 if ((b1 = qrframe[x + width * y]) == b)
338 rlens[h]++;
339 else
340 rlens[++h] = 1;
341 b = b1;
342 bw += b ? 1 : -1;
343 }
344 thisbad += badruns(h);
345 }
346
347 // black/white imbalance
348 if (bw < 0)
349 bw = -bw;
350
351 var big = bw;
352 var count = 0;
353 big += big << 2;
354 big <<= 1;
355 while (big > width * width)
356 big -= width * width, count++;
357 thisbad += count * N4;
358
359 // Y runs
360 for (x = 0; x < width; x++) {
361 rlens[0] = 0;
362 for (h = b = y = 0; y < width; y++) {
363 if ((b1 = qrframe[x + width * y]) == b)
364 rlens[h]++;
365 else
366 rlens[++h] = 1;
367 b = b1;
368 }
369 thisbad += badruns(h);
370 }
371 return thisbad;
372 }
373
374 function genframe(instring) {
375 var x, y, k, t, v, i, j, m;
376
377 // find the smallest version that fits the string
378 t = instring.length;
379 version = 0;
380 do {
381 version++;
382 k = (ecclevel - 1) * 4 + (version - 1) * 16;
383 neccblk1 = eccblocks[k++];
384 neccblk2 = eccblocks[k++];
385 datablkw = eccblocks[k++];
386 eccblkwid = eccblocks[k];
387 k = datablkw * (neccblk1 + neccblk2) + neccblk2 - 3 + (version <= 9);
388 if (t <= k)
389 break;
390 } while (version < 40);
391
392 // FIXME - insure that it fits insted of being truncated
393 width = 17 + 4 * version;
394
395 // allocate, clear and setup data structures
396 v = datablkw + (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
397 for (t = 0; t < v; t++)
398 eccbuf[t] = 0;
399 strinbuf = instring.slice(0);
400
401 for (t = 0; t < width * width; t++)
402 qrframe[t] = 0;
403
404 for (t = 0; t < (width * (width + 1) + 1) / 2; t++)
405 framask[t] = 0;
406
407 // insert finders - black to frame, white to mask
408 for (t = 0; t < 3; t++) {
409 k = 0;
410 y = 0;
411 if (t == 1)
412 k = (width - 7);
413 if (t == 2)
414 y = (width - 7);
415 qrframe[(y + 3) + width * (k + 3)] = 1;
416 for (x = 0; x < 6; x++) {
417 qrframe[(y + x) + width * k] = 1;
418 qrframe[y + width * (k + x + 1)] = 1;
419 qrframe[(y + 6) + width * (k + x)] = 1;
420 qrframe[(y + x + 1) + width * (k + 6)] = 1;
421 }
422 for (x = 1; x < 5; x++) {
423 setmask(y + x, k + 1);
424 setmask(y + 1, k + x + 1);
425 setmask(y + 5, k + x);
426 setmask(y + x + 1, k + 5);
427 }
428 for (x = 2; x < 4; x++) {
429 qrframe[(y + x) + width * (k + 2)] = 1;
430 qrframe[(y + 2) + width * (k + x + 1)] = 1;
431 qrframe[(y + 4) + width * (k + x)] = 1;
432 qrframe[(y + x + 1) + width * (k + 4)] = 1;
433 }
434 }
435
436 // alignment blocks
437 if (version > 1) {
438 t = adelta[version];
439 y = width - 7;
440 for (; ;) {
441 x = width - 7;
442 while (x > t - 3) {
443 putalign(x, y);
444 if (x < t)
445 break;
446 x -= t;
447 }
448 if (y <= t + 9)
449 break;
450 y -= t;
451 putalign(6, y);
452 putalign(y, 6);
453 }
454 }
455
456 // single black
457 qrframe[8 + width * (width - 8)] = 1;
458
459 // timing gap - mask only
460 for (y = 0; y < 7; y++) {
461 setmask(7, y);
462 setmask(width - 8, y);
463 setmask(7, y + width - 7);
464 }
465 for (x = 0; x < 8; x++) {
466 setmask(x, 7);
467 setmask(x + width - 8, 7);
468 setmask(x, width - 8);
469 }
470
471 // reserve mask-format area
472 for (x = 0; x < 9; x++)
473 setmask(x, 8);
474 for (x = 0; x < 8; x++) {
475 setmask(x + width - 8, 8);
476 setmask(8, x);
477 }
478 for (y = 0; y < 7; y++)
479 setmask(8, y + width - 7);
480
481 // timing row/col
482 for (x = 0; x < width - 14; x++)
483 if (x & 1) {
484 setmask(8 + x, 6);
485 setmask(6, 8 + x);
486 }
487 else {
488 qrframe[(8 + x) + width * 6] = 1;
489 qrframe[6 + width * (8 + x)] = 1;
490 }
491
492 // version block
493 if (version > 6) {
494 t = vpat[version - 7];
495 k = 17;
496 for (x = 0; x < 6; x++)
497 for (y = 0; y < 3; y++ , k--)
498 if (1 & (k > 11 ? version >> (k - 12) : t >> k)) {
499 qrframe[(5 - x) + width * (2 - y + width - 11)] = 1;
500 qrframe[(2 - y + width - 11) + width * (5 - x)] = 1;
501 }
502 else {
503 setmask(5 - x, 2 - y + width - 11);
504 setmask(2 - y + width - 11, 5 - x);
505 }
506 }
507
508 // sync mask bits - only set above for white spaces, so add in black bits
509 for (y = 0; y < width; y++)
510 for (x = 0; x <= y; x++)
511 if (qrframe[x + width * y])
512 setmask(x, y);
513
514 // convert string to bitstream
515 // 8 bit data to QR-coded 8 bit data (numeric or alphanum, or kanji not supported)
516 v = strinbuf.length;
517
518 // string to array
519 for (i = 0; i < v; i++)
520 eccbuf[i] = strinbuf.charCodeAt(i);
521 strinbuf = eccbuf.slice(0);
522
523 // calculate max string length
524 x = datablkw * (neccblk1 + neccblk2) + neccblk2;
525 if (v >= x - 2) {
526 v = x - 2;
527 if (version > 9)
528 v--;
529 }
530
531 // shift and repack to insert length prefix
532 i = v;
533 if (version > 9) {
534 strinbuf[i + 2] = 0;
535 strinbuf[i + 3] = 0;
536 while (i--) {
537 t = strinbuf[i];
538 strinbuf[i + 3] |= 255 & (t << 4);
539 strinbuf[i + 2] = t >> 4;
540 }
541 strinbuf[2] |= 255 & (v << 4);
542 strinbuf[1] = v >> 4;
543 strinbuf[0] = 0x40 | (v >> 12);
544 }
545 else {
546 strinbuf[i + 1] = 0;
547 strinbuf[i + 2] = 0;
548 while (i--) {
549 t = strinbuf[i];
550 strinbuf[i + 2] |= 255 & (t << 4);
551 strinbuf[i + 1] = t >> 4;
552 }
553 strinbuf[1] |= 255 & (v << 4);
554 strinbuf[0] = 0x40 | (v >> 4);
555 }
556 // fill to end with pad pattern
557 i = v + 3 - (version < 10);
558 while (i < x) {
559 strinbuf[i++] = 0xec;
560 // buffer has room if (i == x) break;
561 strinbuf[i++] = 0x11;
562 }
563
564 // calculate and append ECC
565
566 // calculate generator polynomial
567 genpoly[0] = 1;
568 for (i = 0; i < eccblkwid; i++) {
569 genpoly[i + 1] = 1;
570 for (j = i; j > 0; j--)
571 genpoly[j] = genpoly[j]
572 ? genpoly[j - 1] ^ gexp[modnn(glog[genpoly[j]] + i)] : genpoly[j - 1];
573 genpoly[0] = gexp[modnn(glog[genpoly[0]] + i)];
574 }
575 for (i = 0; i <= eccblkwid; i++)
576 genpoly[i] = glog[genpoly[i]]; // use logs for genpoly[] to save calc step
577
578 // append ecc to data buffer
579 k = x;
580 y = 0;
581 for (i = 0; i < neccblk1; i++) {
582 appendrs(y, datablkw, k, eccblkwid);
583 y += datablkw;
584 k += eccblkwid;
585 }
586 for (i = 0; i < neccblk2; i++) {
587 appendrs(y, datablkw + 1, k, eccblkwid);
588 y += datablkw + 1;
589 k += eccblkwid;
590 }
591 // interleave blocks
592 y = 0;
593 for (i = 0; i < datablkw; i++) {
594 for (j = 0; j < neccblk1; j++)
595 eccbuf[y++] = strinbuf[i + j * datablkw];
596 for (j = 0; j < neccblk2; j++)
597 eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
598 }
599 for (j = 0; j < neccblk2; j++)
600 eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
601 for (i = 0; i < eccblkwid; i++)
602 for (j = 0; j < neccblk1 + neccblk2; j++)
603 eccbuf[y++] = strinbuf[x + i + j * eccblkwid];
604 strinbuf = eccbuf;
605
606 // pack bits into frame avoiding masked area.
607 x = y = width - 1;
608 k = v = 1; // up, minus
609 /* inteleaved data and ecc codes */
610 m = (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
611 for (i = 0; i < m; i++) {
612 t = strinbuf[i];
613 for (j = 0; j < 8; j++ , t <<= 1) {
614 if (0x80 & t)
615 qrframe[x + width * y] = 1;
616 do { // find next fill position
617 if (v)
618 x--;
619 else {
620 x++;
621 if (k) {
622 if (y != 0)
623 y--;
624 else {
625 x -= 2;
626 k = !k;
627 if (x == 6) {
628 x--;
629 y = 9;
630 }
631 }
632 }
633 else {
634 if (y != width - 1)
635 y++;
636 else {
637 x -= 2;
638 k = !k;
639 if (x == 6) {
640 x--;
641 y -= 8;
642 }
643 }
644 }
645 }
646 v = !v;
647 } while (ismasked(x, y));
648 }
649 }
650
651 // save pre-mask copy of frame
652 strinbuf = qrframe.slice(0);
653 t = 0; // best
654 y = 30000; // demerit
655 // for instead of while since in original arduino code
656 // if an early mask was "good enough" it wouldn't try for a better one
657 // since they get more complex and take longer.
658 for (k = 0; k < 8; k++) {
659 applymask(k); // returns black-white imbalance
660 x = badcheck();
661 if (x < y) { // current mask better than previous best?
662 y = x;
663 t = k;
664 }
665 if (t == 7)
666 break; // don't increment i to a void redoing mask
667 qrframe = strinbuf.slice(0); // reset for next pass
668 }
669 if (t != k) // redo best mask - none good enough, last wasn't t
670 applymask(t);
671
672 // add in final mask/ecclevel bytes
673 y = fmtword[t + ((ecclevel - 1) << 3)];
674 // low byte
675 for (k = 0; k < 8; k++ , y >>= 1)
676 if (y & 1) {
677 qrframe[(width - 1 - k) + width * 8] = 1;
678 if (k < 6)
679 qrframe[8 + width * k] = 1;
680 else
681 qrframe[8 + width * (k + 1)] = 1;
682 }
683 // high byte
684 for (k = 0; k < 7; k++ , y >>= 1)
685 if (y & 1) {
686 qrframe[8 + width * (width - 7 + k)] = 1;
687 if (k)
688 qrframe[(6 - k) + width * 8] = 1;
689 else
690 qrframe[7 + width * 8] = 1;
691 }
692 return qrframe;
693 }
694
695
696
697
698 var _canvas = null;
699
700 var api = {
701
702 get ecclevel() {
703 return ecclevel;
704 },
705
706 set ecclevel(val) {
707 ecclevel = val;
708 },
709
710 get size() {
711 return _size;
712 },
713
714 set size(val) {
715 _size = val
716 },
717
718 get canvas() {
719 return _canvas;
720 },
721
722 set canvas(el) {
723 _canvas = el;
724 },
725
726 getFrame: function (string) {
727 return genframe(string);
728 },
729 //这里的utf16to8(str)是对Text中的字符串进行转码,让其支持中文
730 utf16to8: function (str) {
731 var out, i, len, c;
732
733 out = "";
734 len = str.length;
735 for (i = 0; i < len; i++) {
736 c = str.charCodeAt(i);
737 if ((c >= 0x0001) && (c <= 0x007F)) {
738 out += str.charAt(i);
739 } else if (c > 0x07FF) {
740 out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
741 out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
742 out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
743 } else {
744 out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
745 out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
746 }
747 }
748 return out;
749 },
750 /**
751 * 新增$this参数,传入组件的this,兼容在组件中生成
752 */
753 draw: function (str, canvas, cavW, cavH, $this, ecc) {
754 var that = this;
755 ecclevel = ecc || ecclevel;
756 canvas = canvas || _canvas;
757 if (!canvas) {
758 console.warn('No canvas provided to draw QR code in!')
759 return;
760 }
761
762 var size = Math.min(cavW, cavH);
763 str = that.utf16to8(str);//增加中文显示
764
765 var frame = that.getFrame(str),
766 // 组件中生成qrcode需要绑定this
767 ctx = wx.createCanvasContext(canvas,$this),
768 px = Math.round(size / (width + 8));
769 var roundedSize = px * (width + 8),
770 offset = Math.floor((size - roundedSize) / 2);
771 size = roundedSize;
772 //ctx.clearRect(0, 0, cavW, cavW);
773 ctx.setFillStyle('#ffffff')
774 ctx.fillRect(0, 0, cavW, cavW);
775 ctx.setFillStyle('#000000');
776 for (var i = 0; i < width; i++) {
777 for (var j = 0; j < width; j++) {
778 if (frame[j * width + i]) {
779 ctx.fillRect(px * (4 + i) + offset, px * (4 + j) + offset, px, px);
780 }
781 }
782 }
783 ctx.draw();
784 }
785 }
786 module.exports = { api }
787 // exports.draw = api;
788
789 })();
...\ No newline at end of file ...\ No newline at end of file
1 function setItem(key, value, module_name) {
2 if (module_name) {
3 let module_name_info = getItem(module_name) || {};
4 module_name_info[key] = value;
5 try {
6 wx.setStorageSync(module_name, module_name_info);
7 } catch (e) {
8 wx.setStorage({
9 key: module_name,
10 data: module_name_info
11 })
12 }
13 } else {
14 try {
15 wx.setStorageSync(key, value);
16 } catch (e) {
17 wx.setStorage({
18 key: key,
19 data: value
20 })
21 }
22 }
23 }
24
25 function getItem(key, module_name) {
26 if (module_name) {
27 let val = getItem(module_name);
28 if (val) return val[key];
29 return '';
30 }
31 return wx.getStorageSync(key)
32 }
33
34 function clear(name) {
35 name ? wx.removeStorageSync(name) : wx.clearStorageSync()
36 }
37
38 module.exports = {
39 setItem,
40 getItem,
41 clear
42 }
1 // 手机正则
2 const REGEXPS = {
3 "mobile": /^1\d{10}$/
4 }
5 // 验证手机
6 function checkMobile(str) {
7 return REGEXPS.mobile.test(str);
8 }
9
10
11 /**
12 * 链接参数转换为obj
13 * 入参 完整链接
14 * @param {*} url
15 */
16 function param2Obj(url) {
17 const search = url.split('?')[1]
18 if (!search) {
19 return {}
20 }
21 return JSON.parse(
22 '{"' +
23 decodeURIComponent(search)
24 .replace(/"/g, '\\"')
25 .replace(/&/g, '","')
26 .replace(/=/g, '":"') +
27 '"}'
28 )
29 }
30
31 /**
32 * 格式化日期常规日期
33 * 格式yyyy-MM-dd hh:mm:ss
34 * @param {*} date
35 */
36 function formatTime(date) {
37 var year = date.getFullYear()
38 var month = date.getMonth() + 1
39 var day = date.getDate()
40
41 var hour = date.getHours()
42 var minute = date.getMinutes()
43 var second = date.getSeconds()
44
45 return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
46 }
47
48 /**
49 * 格式化数字,不足一位补充0
50 * @param {*} n
51 */
52 function formatNumber(n) {
53 n = n.toString()
54 return n[1] ? n : '0' + n
55 }
56
57 /**
58 * 获取屏幕剩余高度
59 * useHeight 单位是rpx
60 * 默认返回单位是rpx 可通过unit参数改为 px
61 */
62 function getLastScreenHeight(useHeight = 0, unit = 'rpx') {
63 let sysInfo = wx.getSystemInfoSync();
64 let clientHeight = sysInfo.windowHeight;
65 // 获取可使用窗口高度
66 let clientWidth = sysInfo.windowWidth;
67 // 算出比例
68 let ratio = 750 / clientWidth;
69 // 算出屏幕高度(单位rpx)
70 let height = clientHeight * ratio;
71 // 计算剩余高度
72 let lastHeight = height - useHeight;
73 // 可转换成px
74 if (unit == 'px') {
75 lastHeight = lastHeight / 750 * clientWidth
76 }
77 return lastHeight;
78 }
79
80
81 /**
82 * px转rpx
83 * @param {*} value
84 */
85 function pxToRpx(value) {
86 let sysInfo = wx.getSystemInfoSync();
87 let clientWidth = sysInfo.windowWidth;
88 let result = value / 750 * clientWidth
89 return result;
90 }
91
92
93 // 格式化星期几
94 function formatWeek(week) {
95 let result = "";
96 switch (week) {
97 case 1:
98 result = "一";
99 break;
100 case 2:
101 result = "二";
102 break;
103 case 3:
104 result = "三";
105 break;
106 case 4:
107 result = "四";
108 break;
109 case 5:
110 result = "五";
111 break;
112 case 6:
113 result = "六";
114 break;
115 case 0:
116 result = "日";
117 break;
118
119 default:
120 break;
121 }
122 return result;
123 }
124
125 /**
126 * 获取点击传值
127 * @param {*} evt
128 * @param {*} key
129 */
130 function getBindtapData(evt, key = "data") {
131 let keyStr = key || "data";
132 return evt.currentTarget.dataset[keyStr];
133 }
134
135 /**
136 * 从数组中获取 key未value的对象
137 * @param {*} value
138 * @param {*} key
139 * @param {*} list
140 */
141 function getObjByListKeyValue(value, key, list) {
142 let result = null;
143 list.forEach(element => {
144 if (element[key + ""] == value) {
145 result = element;
146 }
147 });
148 return result;
149 }
150
151 /**
152 * 获取小程序码
153 * path = "/pages/index/index?pa=1"
154 * @param {*} path
155 */
156 function wxacodeGet(path) {
157 return " https://api.k.wxpai.cn/bizproxy/mzcfsapi/qrcode/create?path=" + encodeURIComponent(path);
158 }
159
160 /**
161 * 根据url获取参数
162 * @param {*} name
163 */
164 function getQueryByUrl(name, url) {
165 return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(url) || [, ""])[1].replace(/\+/g, '%20')) || null;
166 }
167
168
169 /**
170 * @desc 函数防抖
171 * @param func 函数
172 * @param wait 延迟执行毫秒数
173 * @param immediate true 表立即执行,false 表非立即执行
174 */
175 function debounce(func, wait, immediate) {
176 let timeout;
177
178 return function () {
179 let context = this;
180 let args = arguments;
181
182 if (timeout) clearTimeout(timeout);
183 if (immediate) {
184 var callNow = !timeout;
185 timeout = setTimeout(() => {
186 timeout = null;
187 }, wait)
188 if (callNow) func.apply(context, args)
189 } else {
190 timeout = setTimeout(function () {
191 func.apply(context, args)
192 }, wait);
193 }
194 }
195 }
196
197 /**
198 * @desc 函数节流
199 * @param func 函数
200 * @param wait 延迟执行毫秒数
201 * @param type 1 表时间戳版,2 表定时器版
202 * 时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候。
203 */
204 function throttle(func, wait, type) {
205 if (type === 1) {
206 var previous = 0;
207 } else if (type === 2) {
208 var timeout;
209 }
210 return function () {
211 let context = this;
212 let args = arguments;
213 if (type === 1) {
214 let now = Date.now();
215
216 if (now - previous > wait) {
217 func.apply(context, args);
218 previous = now;
219 }
220 } else if (type === 2) {
221 if (!timeout) {
222 timeout = setTimeout(() => {
223 timeout = null;
224 func.apply(context, args)
225 }, wait)
226 }
227 }
228 }
229 }
230
231 module.exports = {
232 formatTime: formatTime,
233 checkMobile: checkMobile,
234 getLastScreenHeight: getLastScreenHeight,
235 debounce: debounce,
236 throttle: throttle,
237 param2Obj: param2Obj,
238 pxToRpx: pxToRpx,
239 formatWeek: formatWeek,
240 getBindtapData: getBindtapData,
241 wxacodeGet: wxacodeGet,
242 getObjByListKeyValue: getObjByListKeyValue,
243 getQueryByUrl: getQueryByUrl,
244 }
1 var wxTimer = function (initObj){
2 initObj = initObj || {};
3 this.beginTime = initObj.beginTime || "00:00:00"; //开始时间
4 this.interval = initObj.interval || 0; //间隔时间
5 this.complete = initObj.complete; //结束任务
6 this.intervalFn = initObj.intervalFn; //间隔任务
7 this.name = initObj.name; //当前计时器在计时器数组对象中的名字
8
9 this.intervarID; //计时ID
10 this.endTime; //结束时间
11 this.endSystemTime; //结束的系统时间
12 }
13
14 wxTimer.prototype = {
15 //开始
16 start:function(self){
17 this.endTime = new Date("1970/01/01 "+this.beginTime).getTime();//1970年1月1日的00:00:00的字符串日期
18 this.endSystemTime = new Date(Date.now() + this.endTime);
19 var that = this;
20 //开始倒计时
21 var count = 0;//这个count在这里应该是表示s数,js中获得时间是ms,所以下面*1000都换成ms
22 function begin(){
23 var tmpTime = new Date(that.endTime - 1000 * count++);
24 //把2011年1月1日日 00:00:00换成数字型,这样就可以直接1s,1s的减,就变成了倒计时,为了看的更明确,又用new date把字符串换回来了
25 var tmpTimeStr = tmpTime.toString().substr(16,8);//去掉前面的年月日就剩时分秒了
26 var wxTimerSecond = (tmpTime.getTime() - new Date("1970/01/01 00:00:00").getTime()) / 1000;
27 var wxTimerList = self.data.wxTimerList;
28
29 //更新计时器数组
30 wxTimerList[that.name] = {
31 wxTimer:tmpTimeStr,
32 wxTimerSecond:wxTimerSecond,
33 }
34
35 self.setData({
36 wxTimer:tmpTimeStr,
37 wxTimerSecond:wxTimerSecond,
38 wxTimerList:wxTimerList
39 });
40 //时间间隔执行函数
41 if( 0 == (count-1) % that.interval && that.intervalFn){
42 that.intervalFn();
43 }
44 //结束执行函数
45 if(wxTimerSecond <= 0){
46 if(that.complete){
47 that.complete();
48 }
49 that.stop();
50 }
51 }
52 begin();
53 this.intervarID = setInterval(begin,1000);
54 },
55 //结束
56 stop:function(){
57 clearInterval(this.intervarID);
58 },
59 //校准
60 calibration:function(){
61 this.endTime = this.endSystemTime - Date.now();
62 }
63 }
64
65 module.exports = wxTimer;