2632c460 by simon

默认提交

0 parents
Showing 397 changed files with 15366 additions and 0 deletions
root = true;
[*]
# indent_style = tab
indent_style = space
# indent_size = 4
indent_size = 2
tab_width = 2
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
# [*.{json,yml,wxml,html}]
# indent_style = tab
# indent_size = 4
# tab_width = 2
[README.md]
trim_trailing_whitespace = ignore
.idea
.DS_Store
dist
tmp
node_modules
_old
config.custom.js
src/assets/images/filetype.png
src/assets/images/filetype@2x.png
.gitignore
.editorconfig
.eslintrc
.idea
node_modules/
npm-debug.log
CHANGELOG.md
test
examples
gulpfile.js
.travis.yml
appveyor.yml
.DS_Store
dist
tmp
_old
config.custom.js
src/assets/images/filetype.png
src/assets/images/filetype@2x.png
sudo: false
language: node_js
node_js:
- "6"
- "7"
- "8"
- "stable"
before_script:
- npm install -g gulp@next
MIT License
Copyright (c) 2017 Jeff Ma
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
## 介绍
mp-gulp-framework 是一个专门为开发微信小程序打造的前端开发工作流,基于Gulp 4 开发,旨在通过工作流的方式解决微信小程序开发过程中写前端代码的痛点。
借鉴于:[https://github.com/Jeff2Ma/WeApp-Workflow](https://github.com/Jeff2Ma/WeApp-Workflow)
在此基础上作修改。
## 功能
### SCSS 实时编译为 WXSS
使用Sass 预处理器,让写CSS 更加顺畅。`.scss`文件会实时编译为微信小程序支持的`.wxss`文件。
### WXSS(CSS) 中px 单位转小程序单位rpx
以官方推荐的iPhone 6 为标准设计格式,开发中直接写`px` 即可自动转换为`rpx`
其中屏幕铺满为750px。
```css
// Input: src/pages/index/index.scss
.index__header {
font-size: 14px;
margin-top: 20PX; /* 如果为大写的`PX`单位则不会转换 */
}
// Output: dist/pages/index/index.wxss
.index__header {
font-size: 28rpx;
margin-top: 20PX; /* 如果为大写的`PX`单位则不会转换 */
}
```
### 图片压缩
实时压缩图片并采用增量方式防止被重复压缩。
### 自动上传图片到CDN 并更新路径为https 绝对路径
小程序不支持相对路径的图片引用,仅支持带`https`协议头的绝对路径。本工作流可以将WXML 以及WXSS 文件中引用的相对路径图片上传到云存储CDN 或通过FTP/SFTP 协议上传到个人服务器空间。目前支持腾讯云,七牛云。
```html
// Input: src/pages/index/index.wxml
<image src="%ASSETS_IMG%/t.png"></image>
// Output: dist/pages/index/index.wxml
<image src="https://cdn.devework.com/weapp/devework/t.png"></image>
```
### Font 文件转为base64 编码
小程序不支持相对路径的字体文件,本工作流可将CSS 中引用到的Font 文件转码为base64 并替换原路径。
```
// Input: src/pages/index/index.scss
@font-face {
font-family: 'fontello';
src: url("assets/fonts/fontello.ttf") format('truetype');
}
// Output: dist/pages/index/index.wxss
@font-face {
font-family: 'fontello';
src: url(data:application/font-sfnt;charset=utf-8;base64,AAEAAAAPAIAA....FsASNsQIARAAA) format("truetype");
}
```
### 全自动构建雪碧图及生成相应CSS
本功能由[postcss-lazysprite](https://github.com/Jeff2Ma/postcss-lazysprite) 插件驱动。开发中准备好图片后仅仅写一句类似`@lazysprite "xxxx"`的代码,即可全自动构建雪碧图及生成相应CSS。
```css
// Input: src/app.scss
@lazysprite "filetype";
// Output: dist/app.wxss
.icon-filetype-doc {
background-image: url(../sprites/filetype.png);
background-position: 0 0;
width: 80px;
height: 80px;
}
.icon-filetype-pdf {
background-image: url(../sprites/filetype.png);
background-position: -90px 0;
width: 80px;
height: 80px;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio:2) {
.icon-filetype-doc {
background-image: url(../sprites/filetype@2x.png);
background-position: 0 0;
background-size: 170px 170px;
}
.icon-filetype-pdf {
background-image: url(../sprites/filetype@2x.png);
background-position: -90px 0;
background-size: 170px 170px;
}
}
```
## 项目结构
```
.
├── config.custom.js // gulp自定义配置,会覆盖config.js
├── config.js // gulp 配置文件
├── gulpfile.js
├── package.json
├── src // 开发目录
│   ├── app.js
│   ├── app.json
│   ├── app.scss
│   ├── assets // 开发相关的静态文件原始资源
│  │   ├── fonts //字体文件
│  │   ├── images // 图片文件,可被上传到CDN
│  │   ├── scss // 一般放置SCSS 的minxins 等被import 的SCSS 文件
│  │   └── sprites // 生成雪碧图小图的目录
│   ├── image // 小程序专用的图片资源(如tabbar icon)目录
│   ├── pages
│   └── utils
├── tmp // 通过src 目录编译后生成的缓存目录
└── dist // 通过src 目录编译后生成的文件目录,也是小程序开发的项目目录
```
# Notes:
# - Minimal appveyor.yml file is an empty file. All sections are optional.
# - Indent each level of configuration with 2 spaces. Do not use tabs!
# - All section names are case-sensitive.
# - Section names should be unique on each level.
#---------------------------------#
# general configuration #
#---------------------------------#
# branches to build
#branches:
# # whitelist
# only:
# - master
# - test
# Do not build on tags (GitHub and BitBucket)
skip_tags: true
# Do not build feature branch with open Pull Requests
skip_branch_with_pr: true
# Build worker image (VM template)
image: Visual Studio 2015
environment:
matrix:
- nodejs_version: 4.7.0
# scripts that run after cloning repository
install:
# to run script as a PowerShell command prepend it with ps:
- ps: Install-Product node $env:nodejs_version
# batch commands start from cmd:
- npm cache clean
- npm i
- npm install -g gulp@next
# to run your custom scripts instead of automatic tests
test_script:
# Output useful info for debugging.
- node --version && npm --version
- npm i
- pwd
- gulp test
# Don't actually build.
build: off
matrix:
fast_finish: true
cache:
# local npm modules
- C:\Users\appveyor\AppData\Roaming\npm-cache -> package.json # npm cache
- node_modules -> package.json
/**
* ------------------------------------------------------------------
* 配置文件
*
* 建议复制一份并重命名为 config.custom.js ,即可在config.custom.js 上根据需求进行配置
* ------------------------------------------------------------------
*
*/
module.exports = {
"enabledQcloud": false, //是否开启腾讯云COS 上传功能
// 腾讯云COS 上传功能配置表
"qcloud": {
"appid": "1111111",
"secretId": "xxx",
"secretKey": "xxxxx",
"bucket": "xxxx",
"region": "sh",
"prefix": "what-ever/you-want",
"overWrite": true,
"headers": {
"Cache-Control": "max-age=5184000"
}
},
// 静态资源CDN 域名,配合CDN 功能实用,线上请确保在mp管理端已经注册域名
"assetsCDN": "https://res.jianhui.org/"
};
# chmod u+x git.sh
unset msg
read -p "请输入commit提交的描述: " msg
if [[ $msg == "" ]]; then
msg="默认提交"
fi
git add -A
git commit -m $msg
git push
git status
/**
* ------------------------------------------------------------------
* gulpfile 文件
* ------------------------------------------------------------------
*/
var path = require('path');
var gulp = require('gulp');
var changed = require('gulp-changed');
var sass = require('gulp-sass');
var rename = require('gulp-rename');
var imagemin = require('gulp-imagemin');
var sftp = require('gulp-sftp');
var del = require('del');
var replace = require('gulp-replace');
var postcss = require('gulp-postcss');
var qcloudUpload = require('gulp-qcloud-upload');
var gulpif = require('gulp-if');
var gutil = require('gulp-util');
var newer = require('gulp-newer');
var cache = require('gulp-cached');
var debug = require('gulp-debug');
var pxtorpx = require('postcss-px2rpx');
// var base64 = require('postcss-font-base64');
// var lazysprite = require('postcss-lazysprite');
var argv = require('yargs').argv;
var config = null;
// 获取用户配置
try {
config = require('./config.custom.js');
} catch (e) {
try {
config = require('./config.js');
} catch (e) {
log(gutil.colors.red('丢失配置文件(config.js/config.custom.js)'));
}
}
// 相关路径配置
var paths = {
src: {
baseDir: 'src',
imgDir: 'src/image',
spriteDir: 'src/assets/sprites',
scssDir: 'src/assets/scss',
imgFiles: 'src/image/**/*',
scssFiles: 'src/**/*.scss',
baseFiles: ['src/**/*.{png,js,json,wxml,wxss,wxs,ts,woff2}', '!src/assets/**/*', '!src/image/**/*'],
busFiles: ['src/**/*.{js,json}', '!src/assets/**/*', '!src/image/**/*', '!src/ui/**/*'],
assetsDir: 'src/assets',
assetsImgFiles: 'src/assets/images/**/*.{png,jpg,jpeg,svg,gif}',
wxmlFiles: ['src/**/*.wxml'],
jsFiles: 'src/**/*.js'
},
dist: {
baseDir: 'dist',
imgDir: 'dist/image',
wxssFiles: 'dist/**/*.wxss',
},
tmp: {
baseDir: 'tmp',
imgDir: 'tmp/assets/images',
imgFiles: 'tmp/assets/images/**/*.{png,jpg,jpeg,svg,gif}'
}
};
// 雪碧图的配置
var lazyspriteConfig = {
imagePath: paths.src.spriteDir,
stylesheetInput: paths.src.scssDir,
stylesheetRelative: paths.src.assetsDir,
spritePath: paths.src.assetsDir + '/images',
smartUpdate: false,
cssSeparator: '-',
outputExtralCSS: true,
nameSpace: 'icon-'
};
// Log for output msg.
function log() {
var data = Array.prototype.slice.call(arguments);
gutil.log.apply(false, data);
}
// 压缩图片
function imageMin() {
// return gulp.src(paths.src.imgFiles, {si≤nce: gulp.lastRun(imageMin)})
return gulp.src(paths.src.imgFiles)
.pipe(newer(paths.dist.imgDir))
.pipe(imagemin({
progressive: true,
svgoPlugins: [{
removeViewBox: false
}]
}))
.pipe(gulp.dest(paths.dist.imgDir));
}
// assets 文件夹下的图片处理
function assetsImgMin() {
return gulp.src(paths.src.assetsImgFiles)
.pipe(newer(paths.tmp.imgDir))
.pipe(imagemin({
progressive: true,
svgoPlugins: [{
removeViewBox: false
}]
}))
.pipe(gulp.dest(paths.tmp.imgDir))
}
// Sass 编译
function sassCompile() {
var res = config.assetsCDN + config.qcloud.prefix + '/';
// 缩放比例 1为750
var pxtorpxOpts = {
times: 1
};
return gulp.src(paths.src.scssFiles)
.pipe(sass({
errLogToConsole: true,
outputStyle: 'expanded'
})
.on('error', sass.logError))
.pipe(gulpif(Boolean(argv.debug), debug({
title: '`sassCompile` Debug:'
})))
// .pipe(postcss([lazysprite(lazyspriteConfig), pxtorpx(pxtorpxOpts), base64()]))
.pipe(postcss([pxtorpx(pxtorpxOpts)]))
.pipe(rename({
'extname': '.wxss'
}))
.pipe(replace('.scss', '.wxss'))
// .pipe(replace('%ASSETS_IMG%/', res))
// .pipe(replace('src/assets/images', res)) // 雪碧图CSS RUL 中的图片路径
.pipe(gulp.dest(paths.dist.baseDir))
}
// 复制业务文件 只复制修改过的文件
function copyModifyFiles() {
return gulp.src(paths.src.busFiles)
.pipe(changed(paths.dist.baseDir))
.pipe(gulp.dest(paths.dist.baseDir));
}
// 复制基础文件
function copyBasicFiles() {
return gulp.src(paths.src.baseFiles, {})
.pipe(gulp.dest(paths.dist.baseDir));
}
// 复制 WXML
function copyWXML() {
return gulp.src(paths.src.wxmlFiles, {})
.pipe(gulp.dest(paths.dist.baseDir));
}
// 重写WXML 中 image 标签中的图片路径
function wxmlImgRewrite() {
var res = config.assetsCDN + config.qcloud.prefix + '/';
return gulp.src(paths.src.wxmlFiles)
// .pipe(replace('%ASSETS_IMG%/', res))
.pipe(gulp.dest(paths.dist.baseDir))
}
// clean 任务, dist 目录
function cleanDist() {
return del(paths.dist.baseDir);
}
// clean tmp 目录
function cleanTmp() {
return del(paths.tmp.baseDir);
}
// 腾讯云上传任务
function qcloudCDN(cb) {
if (config.enabledQcloud) {
// return gulp.src(paths.src.assetsImgFiles, {since: gulp.lastRun(qcloudCDN)})
return gulp.src(paths.tmp.imgFiles)
.pipe(cache('qcloudCache'))
.pipe(qcloudUpload({
appid: config.qcloud.appid,
secretId: config.qcloud.secretId,
secretKey: config.qcloud.secretKey,
bucket: config.qcloud.bucket,
region: config.qcloud.region,
prefix: config.qcloud.prefix,
overWrite: config.qcloud.overWrite,
headers: config.qcloud.headers
}));
}
cb();
}
var watchHandler = function (type, file) {
var extname = path.extname(file);
// SCSS 文件
if (extname === '.scss') {
if (type === 'removed') {
var tmp = file.replace('src/', 'dist/').replace(extname, '.wxss');
del([tmp]);
} else {
sassCompile();
}
}
// 图片文件
else if (extname === '.png' || extname === '.jpg' || extname === '.jpeg' || extname === '.svg' || extname === '.gif') {
if (type === 'removed') {
if (file.indexOf('assets') > -1) {
del([file.replace('src/', 'tmp/')]);
} else {
del([file.replace('src/', 'dist/')]);
}
} else {
imageMin();
// assetsImgMin();
// qcloudCDN();
wxmlImgRewrite();
}
}
// wxml
else if (extname === '.wxml') {
if (type === 'removed') {
var tmp = file.replace('src/', 'dist/')
del([tmp]);
} else {
copyWXML();
wxmlImgRewrite();
}
}
// 其余文件
else {
if (type === 'removed') {
var tmp = file.replace('src/', 'dist/');
del([tmp]);
} else {
// copyBasicFiles();
copyModifyFiles(); // 复制修改过的业务文件
// copyWXML();
wxmlImgRewrite();
}
}
};
//监听文件
function watch(cb) {
var watcher = gulp.watch([
paths.src.baseDir,
paths.tmp.imgDir
], {
ignored: /[\/\\]\./
});
watcher
.on('change', function (file) {
log(gutil.colors.yellow(file) + ' is changed');
watchHandler('changed', file);
})
.on('add', function (file) {
log(gutil.colors.yellow(file) + ' is added');
watchHandler('add', file);
})
.on('unlink', function (file) {
log(gutil.colors.yellow(file) + ' is deleted');
watchHandler('removed', file);
});
cb();
}
//注册默认任务
gulp.task('default', gulp.series(
cleanTmp,
copyBasicFiles,
gulp.parallel(
sassCompile,
imageMin,
copyWXML
),
wxmlImgRewrite,
// assetsImgMin,
// qcloudCDN,
watch
));
//注册测试任务
gulp.task('test', gulp.series(
cleanTmp,
copyBasicFiles,
gulp.parallel(
sassCompile,
imageMin,
copyWXML
),
wxmlImgRewrite,
// assetsImgMin,
// qcloudCDN
));
// 删除任务
gulp.task('clean', gulp.parallel(
cleanTmp,
cleanDist
));
This diff could not be displayed because it is too large.
{
"name": "mp-gulp-frame-work",
"version": "0.0.5",
"description": "A workflow for better weapp developing.",
"main": "index.js",
"scripts": {
"test": "gulp test",
"dev": "gulp"
},
"repository": {
"type": "git",
"url": "http://admin@www.simonfungc.com:10086/r/mp/mp-gulp-framework.git"
},
"keywords": [
"gulp",
"gulpjs",
"workflow",
"weapp",
"wexin",
"wechat",
"css",
"wxml",
"wxss"
],
"author": "SimonFungc",
"license": "MIT",
"bugs": {
"url": "https://www.simonfungc.com/"
},
"homepage": "https://www.simonfungc.com/",
"devDependencies": {
"del": "^4.0.0",
"gulp": "^4.0.0",
"gulp-changed": "^4.0.2",
"gulp-cached": "^1.1.1",
"gulp-debug": "^4.0.0",
"gulp-if": "^2.0.2",
"gulp-imagemin": "^5.0.0",
"gulp-newer": "^1.3.0",
"gulp-postcss": "^8.0.0",
"gulp-qcloud-upload": "^2.2.0",
"gulp-rename": "^1.2.2",
"gulp-replace": "^1.0.0",
"gulp-sass": "^4.0.0",
"gulp-sftp": "^0.1.5",
"gulp-util": "^3.0.8",
"postcss-font-base64": "^1.0.4",
"postcss-lazysprite": "^2.0.0",
"postcss-px2rpx": "0.0.4",
"yargs": "^13.1.0"
}
}
{
"client": "./dist",
"svr": "./server",
"setting": {
"urlCheck": false,
"es6": true,
"postcss": true,
"minified": true,
"newFeature": true
},
"appid": "wxc57ed87f2569f701",
"projectname": "gulp-example",
"condition": {}
}
//app.js
let fetchApi = require('./http/fetch-api.js');
let api = require('./http/api');
let config = require('./config');
let router = require('./router/index');
let store = require('./utils/stroage');
require('./http/mock-data');
App({
get: fetchApi.fetch,
post: (params) => {
params.method = 'post';
return fetchApi.fetch(params);
},
api: api,
config: config,
router: router,
store: store,
onLaunch(options) {
let scene = options.scene;
// 根据场景值判断分享入口
// https://developers.weixin.qq.com/miniprogram/dev/reference/scene-list.html
// 小程序由分享进入
// if (scene == 1007 || scene == 1008 || scene == 1011 || scene == 1012 || scene == 1013) {
// this.globalData.share = true
// } else {
// this.globalData.share = false
// };
const MenuRect = wx.getMenuButtonBoundingClientRect();
const statusBarHeight = wx.getSystemInfoSync().statusBarHeight;
const height = (MenuRect.top - statusBarHeight) * 2 + MenuRect.height + MenuRect.top;
this.globalData.statusBarHeight = wx.getSystemInfoSync().statusBarHeight;
this.globalData.barHeight = height;
this.share();
},
globalData: {
share: false,
indexInfo: null,
userInfo: null,
wxcode: store.getItem("wxcode"),
tlMemberCode: "",
},
//重写分享方法
share: function () {
//监听路由切换
//间接实现全局设置分享内容
wx.onAppRoute(function (res) {
//获取加载的页面
let pages = getCurrentPages();
//获取当前页面的对象
let view = pages[pages.length - 1];
let data;
if (view) {
data = view.data;
if (!data.isOverShare) {
data.isOverShare = true;
view.onShareAppMessage = function (res) {
//分享配置
return {
title: '模板标题',
path: 'pages/index/index',
// imageUrl: ''
};
};
}
}
})
},
})
{
"pages": [
"pages/index/index",
"pages/more/more",
"pages/poster-example/poster-example",
"pages/authorize/authorize",
"pages/demo/demo"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "mp-gulp-framework",
"navigationBarTextStyle": "black"
},
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#CF4646",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/index/index",
"iconPath": "image/tabbar/home_D.png",
"selectedIconPath": "image/tabbar/home.png",
"text": "介绍"
},
{
"pagePath": "pages/more/more",
"iconPath": "image/tabbar/set_D.png",
"selectedIconPath": "image/tabbar/set.png",
"text": "更多"
}
]
},
"usingComponents": {
"authorize-comp": "../../component/authorize-comp/authorize-comp",
"empty-tips": "../../component/empty-tips/empty-tips",
"van-popup": "../../ui/vant-weapp/popup/index"
}
}
/**
* ------------------------------------------------------------------
* app.scss 入口文件
*
* ------------------------------------------------------------------
*
*/
// 支持文件
@import "assets/scss/support";
// 原子类
@import "assets/scss/utils";
// 图标
// @import 'styles/iconfont.wxss';
// 雪碧图
// @lazysprite "filetype";
// .test {
// background-image: url(%ASSETS_IMG%/qr-r.jpg);
// }
.app {
height: 100%;
justify-content: space-between;
// text-align: center;
box-sizing: border-box;
font-family: -apple-system-font, Helvetica Neue, Helvetica, sans-serif, FZY3JW-GB1-0;
}
.app__width {
width: 750px;
}
.app__width {
width: 750px;
}
.app__inner {
margin: 20px;
}
.app__title {
font-size: $fontSize;
line-height: $fontSize + 4px;
font-weight: bold;
padding-bottom: 10px;
margin-bottom: 20px;
border-bottom: .5px solid #EEEEEE;
}
.app__desc {
font-size: $fontSizeSmaller;
line-height: $fontSizeSmaller +2px;
margin-bottom: 20px;
color: $colorGray;
}
.app__bgc {
position: fixed;
background-color: #ffffff;
width: 100%;
height: 100%;
}
.app__bg {
position: absolute;
width: 100%;
height: 100%;
}
.app__top-shadow {
position: fixed;
width: 750px;
height: 1px;
box-shadow: 0px 4px 0.9px 0.1px rgba(6, 0, 1, 0.07);
background-color: #ffffff;
}
.app__content {
position: relative;
}
// web font icon
@font-face {
font-family: "iconfont";
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'),
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.iconrefresh:before {
content: "\e874";
}
.iconempty:before {
content: "\e6a6";
}
.drop-down-item :last-child {
border-bottom: none;
}
@charset "UTF-8";
/*!
* animate.css -http://daneden.me/animate
* Version - 3.6.0
* Licensed under the MIT license - http://opensource.org/licenses/MIT
*
* Copyright (c) 2018 Daniel Eden
*/
.animated {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
.animated.infinite {
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@-webkit-keyframes bounce {
from,
20%,
53%,
80%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
40%,
43% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
-webkit-transform: translate3d(0, -30px, 0);
transform: translate3d(0, -30px, 0);
}
70% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
-webkit-transform: translate3d(0, -15px, 0);
transform: translate3d(0, -15px, 0);
}
90% {
-webkit-transform: translate3d(0, -4px, 0);
transform: translate3d(0, -4px, 0);
}
}
@keyframes bounce {
from,
20%,
53%,
80%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
40%,
43% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
-webkit-transform: translate3d(0, -30px, 0);
transform: translate3d(0, -30px, 0);
}
70% {
-webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
-webkit-transform: translate3d(0, -15px, 0);
transform: translate3d(0, -15px, 0);
}
90% {
-webkit-transform: translate3d(0, -4px, 0);
transform: translate3d(0, -4px, 0);
}
}
.bounce {
-webkit-animation-name: bounce;
animation-name: bounce;
-webkit-transform-origin: center bottom;
transform-origin: center bottom;
}
@-webkit-keyframes flash {
from,
50%,
to {
opacity: 1;
}
25%,
75% {
opacity: 0;
}
}
@keyframes flash {
from,
50%,
to {
opacity: 1;
}
25%,
75% {
opacity: 0;
}
}
.flash {
-webkit-animation-name: flash;
animation-name: flash;
}
@-webkit-keyframes pulse {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
50% {
-webkit-transform: scale3d(1.05, 1.05, 1.05);
transform: scale3d(1.05, 1.05, 1.05);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
@keyframes pulse {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
50% {
-webkit-transform: scale3d(1.05, 1.05, 1.05);
transform: scale3d(1.05, 1.05, 1.05);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
.pulse {
-webkit-animation-name: pulse;
animation-name: pulse;
}
@-webkit-keyframes rubberBand {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
30% {
-webkit-transform: scale3d(1.25, 0.75, 1);
transform: scale3d(1.25, 0.75, 1);
}
40% {
-webkit-transform: scale3d(0.75, 1.25, 1);
transform: scale3d(0.75, 1.25, 1);
}
50% {
-webkit-transform: scale3d(1.15, 0.85, 1);
transform: scale3d(1.15, 0.85, 1);
}
65% {
-webkit-transform: scale3d(0.95, 1.05, 1);
transform: scale3d(0.95, 1.05, 1);
}
75% {
-webkit-transform: scale3d(1.05, 0.95, 1);
transform: scale3d(1.05, 0.95, 1);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
@keyframes rubberBand {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
30% {
-webkit-transform: scale3d(1.25, 0.75, 1);
transform: scale3d(1.25, 0.75, 1);
}
40% {
-webkit-transform: scale3d(0.75, 1.25, 1);
transform: scale3d(0.75, 1.25, 1);
}
50% {
-webkit-transform: scale3d(1.15, 0.85, 1);
transform: scale3d(1.15, 0.85, 1);
}
65% {
-webkit-transform: scale3d(0.95, 1.05, 1);
transform: scale3d(0.95, 1.05, 1);
}
75% {
-webkit-transform: scale3d(1.05, 0.95, 1);
transform: scale3d(1.05, 0.95, 1);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
.rubberBand {
-webkit-animation-name: rubberBand;
animation-name: rubberBand;
}
@-webkit-keyframes shake {
from,
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
10%,
30%,
50%,
70%,
90% {
-webkit-transform: translate3d(-10px, 0, 0);
transform: translate3d(-10px, 0, 0);
}
20%,
40%,
60%,
80% {
-webkit-transform: translate3d(10px, 0, 0);
transform: translate3d(10px, 0, 0);
}
}
@keyframes shake {
from,
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
10%,
30%,
50%,
70%,
90% {
-webkit-transform: translate3d(-10px, 0, 0);
transform: translate3d(-10px, 0, 0);
}
20%,
40%,
60%,
80% {
-webkit-transform: translate3d(10px, 0, 0);
transform: translate3d(10px, 0, 0);
}
}
.shake {
-webkit-animation-name: shake;
animation-name: shake;
}
@-webkit-keyframes headShake {
0% {
-webkit-transform: translateX(0);
transform: translateX(0);
}
6.5% {
-webkit-transform: translateX(-6px) rotateY(-9deg);
transform: translateX(-6px) rotateY(-9deg);
}
18.5% {
-webkit-transform: translateX(5px) rotateY(7deg);
transform: translateX(5px) rotateY(7deg);
}
31.5% {
-webkit-transform: translateX(-3px) rotateY(-5deg);
transform: translateX(-3px) rotateY(-5deg);
}
43.5% {
-webkit-transform: translateX(2px) rotateY(3deg);
transform: translateX(2px) rotateY(3deg);
}
50% {
-webkit-transform: translateX(0);
transform: translateX(0);
}
}
@keyframes headShake {
0% {
-webkit-transform: translateX(0);
transform: translateX(0);
}
6.5% {
-webkit-transform: translateX(-6px) rotateY(-9deg);
transform: translateX(-6px) rotateY(-9deg);
}
18.5% {
-webkit-transform: translateX(5px) rotateY(7deg);
transform: translateX(5px) rotateY(7deg);
}
31.5% {
-webkit-transform: translateX(-3px) rotateY(-5deg);
transform: translateX(-3px) rotateY(-5deg);
}
43.5% {
-webkit-transform: translateX(2px) rotateY(3deg);
transform: translateX(2px) rotateY(3deg);
}
50% {
-webkit-transform: translateX(0);
transform: translateX(0);
}
}
.headShake {
-webkit-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
-webkit-animation-name: headShake;
animation-name: headShake;
}
@-webkit-keyframes swing {
20% {
-webkit-transform: rotate3d(0, 0, 1, 15deg);
transform: rotate3d(0, 0, 1, 15deg);
}
40% {
-webkit-transform: rotate3d(0, 0, 1, -10deg);
transform: rotate3d(0, 0, 1, -10deg);
}
60% {
-webkit-transform: rotate3d(0, 0, 1, 5deg);
transform: rotate3d(0, 0, 1, 5deg);
}
80% {
-webkit-transform: rotate3d(0, 0, 1, -5deg);
transform: rotate3d(0, 0, 1, -5deg);
}
to {
-webkit-transform: rotate3d(0, 0, 1, 0deg);
transform: rotate3d(0, 0, 1, 0deg);
}
}
@keyframes swing {
20% {
-webkit-transform: rotate3d(0, 0, 1, 15deg);
transform: rotate3d(0, 0, 1, 15deg);
}
40% {
-webkit-transform: rotate3d(0, 0, 1, -10deg);
transform: rotate3d(0, 0, 1, -10deg);
}
60% {
-webkit-transform: rotate3d(0, 0, 1, 5deg);
transform: rotate3d(0, 0, 1, 5deg);
}
80% {
-webkit-transform: rotate3d(0, 0, 1, -5deg);
transform: rotate3d(0, 0, 1, -5deg);
}
to {
-webkit-transform: rotate3d(0, 0, 1, 0deg);
transform: rotate3d(0, 0, 1, 0deg);
}
}
.swing {
-webkit-transform-origin: top center;
transform-origin: top center;
-webkit-animation-name: swing;
animation-name: swing;
}
@-webkit-keyframes tada {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
10%,
20% {
-webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
}
30%,
50%,
70%,
90% {
-webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
}
40%,
60%,
80% {
-webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
@keyframes tada {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
10%,
20% {
-webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
}
30%,
50%,
70%,
90% {
-webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
}
40%,
60%,
80% {
-webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
.tada {
-webkit-animation-name: tada;
animation-name: tada;
}
@-webkit-keyframes wobble {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
15% {
-webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
}
30% {
-webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
}
45% {
-webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
}
60% {
-webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
}
75% {
-webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes wobble {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
15% {
-webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
}
30% {
-webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
}
45% {
-webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
}
60% {
-webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
}
75% {
-webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.wobble {
-webkit-animation-name: wobble;
animation-name: wobble;
}
@-webkit-keyframes jello {
from,
11.1%,
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
22.2% {
-webkit-transform: skewX(-12.5deg) skewY(-12.5deg);
transform: skewX(-12.5deg) skewY(-12.5deg);
}
33.3% {
-webkit-transform: skewX(6.25deg) skewY(6.25deg);
transform: skewX(6.25deg) skewY(6.25deg);
}
44.4% {
-webkit-transform: skewX(-3.125deg) skewY(-3.125deg);
transform: skewX(-3.125deg) skewY(-3.125deg);
}
55.5% {
-webkit-transform: skewX(1.5625deg) skewY(1.5625deg);
transform: skewX(1.5625deg) skewY(1.5625deg);
}
66.6% {
-webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg);
transform: skewX(-0.78125deg) skewY(-0.78125deg);
}
77.7% {
-webkit-transform: skewX(0.390625deg) skewY(0.390625deg);
transform: skewX(0.390625deg) skewY(0.390625deg);
}
88.8% {
-webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
}
}
@keyframes jello {
from,
11.1%,
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
22.2% {
-webkit-transform: skewX(-12.5deg) skewY(-12.5deg);
transform: skewX(-12.5deg) skewY(-12.5deg);
}
33.3% {
-webkit-transform: skewX(6.25deg) skewY(6.25deg);
transform: skewX(6.25deg) skewY(6.25deg);
}
44.4% {
-webkit-transform: skewX(-3.125deg) skewY(-3.125deg);
transform: skewX(-3.125deg) skewY(-3.125deg);
}
55.5% {
-webkit-transform: skewX(1.5625deg) skewY(1.5625deg);
transform: skewX(1.5625deg) skewY(1.5625deg);
}
66.6% {
-webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg);
transform: skewX(-0.78125deg) skewY(-0.78125deg);
}
77.7% {
-webkit-transform: skewX(0.390625deg) skewY(0.390625deg);
transform: skewX(0.390625deg) skewY(0.390625deg);
}
88.8% {
-webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
}
}
.jello {
-webkit-animation-name: jello;
animation-name: jello;
-webkit-transform-origin: center;
transform-origin: center;
}
@-webkit-keyframes bounceIn {
from,
20%,
40%,
60%,
80%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
0% {
opacity: 0;
-webkit-transform: scale3d(0.3, 0.3, 0.3);
transform: scale3d(0.3, 0.3, 0.3);
}
20% {
-webkit-transform: scale3d(1.1, 1.1, 1.1);
transform: scale3d(1.1, 1.1, 1.1);
}
40% {
-webkit-transform: scale3d(0.9, 0.9, 0.9);
transform: scale3d(0.9, 0.9, 0.9);
}
60% {
opacity: 1;
-webkit-transform: scale3d(1.03, 1.03, 1.03);
transform: scale3d(1.03, 1.03, 1.03);
}
80% {
-webkit-transform: scale3d(0.97, 0.97, 0.97);
transform: scale3d(0.97, 0.97, 0.97);
}
to {
opacity: 1;
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
@keyframes bounceIn {
from,
20%,
40%,
60%,
80%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
0% {
opacity: 0;
-webkit-transform: scale3d(0.3, 0.3, 0.3);
transform: scale3d(0.3, 0.3, 0.3);
}
20% {
-webkit-transform: scale3d(1.1, 1.1, 1.1);
transform: scale3d(1.1, 1.1, 1.1);
}
40% {
-webkit-transform: scale3d(0.9, 0.9, 0.9);
transform: scale3d(0.9, 0.9, 0.9);
}
60% {
opacity: 1;
-webkit-transform: scale3d(1.03, 1.03, 1.03);
transform: scale3d(1.03, 1.03, 1.03);
}
80% {
-webkit-transform: scale3d(0.97, 0.97, 0.97);
transform: scale3d(0.97, 0.97, 0.97);
}
to {
opacity: 1;
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
.bounceIn {
-webkit-animation-duration: 0.75s;
animation-duration: 0.75s;
-webkit-animation-name: bounceIn;
animation-name: bounceIn;
}
@-webkit-keyframes bounceInDown {
from,
60%,
75%,
90%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
0% {
opacity: 0;
-webkit-transform: translate3d(0, -3000px, 0);
transform: translate3d(0, -3000px, 0);
}
60% {
opacity: 1;
-webkit-transform: translate3d(0, 25px, 0);
transform: translate3d(0, 25px, 0);
}
75% {
-webkit-transform: translate3d(0, -10px, 0);
transform: translate3d(0, -10px, 0);
}
90% {
-webkit-transform: translate3d(0, 5px, 0);
transform: translate3d(0, 5px, 0);
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes bounceInDown {
from,
60%,
75%,
90%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
0% {
opacity: 0;
-webkit-transform: translate3d(0, -3000px, 0);
transform: translate3d(0, -3000px, 0);
}
60% {
opacity: 1;
-webkit-transform: translate3d(0, 25px, 0);
transform: translate3d(0, 25px, 0);
}
75% {
-webkit-transform: translate3d(0, -10px, 0);
transform: translate3d(0, -10px, 0);
}
90% {
-webkit-transform: translate3d(0, 5px, 0);
transform: translate3d(0, 5px, 0);
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.bounceInDown {
-webkit-animation-name: bounceInDown;
animation-name: bounceInDown;
}
@-webkit-keyframes bounceInLeft {
from,
60%,
75%,
90%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
0% {
opacity: 0;
-webkit-transform: translate3d(-3000px, 0, 0);
transform: translate3d(-3000px, 0, 0);
}
60% {
opacity: 1;
-webkit-transform: translate3d(25px, 0, 0);
transform: translate3d(25px, 0, 0);
}
75% {
-webkit-transform: translate3d(-10px, 0, 0);
transform: translate3d(-10px, 0, 0);
}
90% {
-webkit-transform: translate3d(5px, 0, 0);
transform: translate3d(5px, 0, 0);
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes bounceInLeft {
from,
60%,
75%,
90%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
0% {
opacity: 0;
-webkit-transform: translate3d(-3000px, 0, 0);
transform: translate3d(-3000px, 0, 0);
}
60% {
opacity: 1;
-webkit-transform: translate3d(25px, 0, 0);
transform: translate3d(25px, 0, 0);
}
75% {
-webkit-transform: translate3d(-10px, 0, 0);
transform: translate3d(-10px, 0, 0);
}
90% {
-webkit-transform: translate3d(5px, 0, 0);
transform: translate3d(5px, 0, 0);
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.bounceInLeft {
-webkit-animation-name: bounceInLeft;
animation-name: bounceInLeft;
}
@-webkit-keyframes bounceInRight {
from,
60%,
75%,
90%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
from {
opacity: 0;
-webkit-transform: translate3d(3000px, 0, 0);
transform: translate3d(3000px, 0, 0);
}
60% {
opacity: 1;
-webkit-transform: translate3d(-25px, 0, 0);
transform: translate3d(-25px, 0, 0);
}
75% {
-webkit-transform: translate3d(10px, 0, 0);
transform: translate3d(10px, 0, 0);
}
90% {
-webkit-transform: translate3d(-5px, 0, 0);
transform: translate3d(-5px, 0, 0);
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes bounceInRight {
from,
60%,
75%,
90%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
from {
opacity: 0;
-webkit-transform: translate3d(3000px, 0, 0);
transform: translate3d(3000px, 0, 0);
}
60% {
opacity: 1;
-webkit-transform: translate3d(-25px, 0, 0);
transform: translate3d(-25px, 0, 0);
}
75% {
-webkit-transform: translate3d(10px, 0, 0);
transform: translate3d(10px, 0, 0);
}
90% {
-webkit-transform: translate3d(-5px, 0, 0);
transform: translate3d(-5px, 0, 0);
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.bounceInRight {
-webkit-animation-name: bounceInRight;
animation-name: bounceInRight;
}
@-webkit-keyframes bounceInUp {
from,
60%,
75%,
90%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
from {
opacity: 0;
-webkit-transform: translate3d(0, 3000px, 0);
transform: translate3d(0, 3000px, 0);
}
60% {
opacity: 1;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}
75% {
-webkit-transform: translate3d(0, 10px, 0);
transform: translate3d(0, 10px, 0);
}
90% {
-webkit-transform: translate3d(0, -5px, 0);
transform: translate3d(0, -5px, 0);
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes bounceInUp {
from,
60%,
75%,
90%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
from {
opacity: 0;
-webkit-transform: translate3d(0, 3000px, 0);
transform: translate3d(0, 3000px, 0);
}
60% {
opacity: 1;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}
75% {
-webkit-transform: translate3d(0, 10px, 0);
transform: translate3d(0, 10px, 0);
}
90% {
-webkit-transform: translate3d(0, -5px, 0);
transform: translate3d(0, -5px, 0);
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.bounceInUp {
-webkit-animation-name: bounceInUp;
animation-name: bounceInUp;
}
@-webkit-keyframes bounceOut {
20% {
-webkit-transform: scale3d(0.9, 0.9, 0.9);
transform: scale3d(0.9, 0.9, 0.9);
}
50%,
55% {
opacity: 1;
-webkit-transform: scale3d(1.1, 1.1, 1.1);
transform: scale3d(1.1, 1.1, 1.1);
}
to {
opacity: 0;
-webkit-transform: scale3d(0.3, 0.3, 0.3);
transform: scale3d(0.3, 0.3, 0.3);
}
}
@keyframes bounceOut {
20% {
-webkit-transform: scale3d(0.9, 0.9, 0.9);
transform: scale3d(0.9, 0.9, 0.9);
}
50%,
55% {
opacity: 1;
-webkit-transform: scale3d(1.1, 1.1, 1.1);
transform: scale3d(1.1, 1.1, 1.1);
}
to {
opacity: 0;
-webkit-transform: scale3d(0.3, 0.3, 0.3);
transform: scale3d(0.3, 0.3, 0.3);
}
}
.bounceOut {
-webkit-animation-duration: 0.75s;
animation-duration: 0.75s;
-webkit-animation-name: bounceOut;
animation-name: bounceOut;
}
@-webkit-keyframes bounceOutDown {
20% {
-webkit-transform: translate3d(0, 10px, 0);
transform: translate3d(0, 10px, 0);
}
40%,
45% {
opacity: 1;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}
to {
opacity: 0;
-webkit-transform: translate3d(0, 2000px, 0);
transform: translate3d(0, 2000px, 0);
}
}
@keyframes bounceOutDown {
20% {
-webkit-transform: translate3d(0, 10px, 0);
transform: translate3d(0, 10px, 0);
}
40%,
45% {
opacity: 1;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}
to {
opacity: 0;
-webkit-transform: translate3d(0, 2000px, 0);
transform: translate3d(0, 2000px, 0);
}
}
.bounceOutDown {
-webkit-animation-name: bounceOutDown;
animation-name: bounceOutDown;
}
@-webkit-keyframes bounceOutLeft {
20% {
opacity: 1;
-webkit-transform: translate3d(20px, 0, 0);
transform: translate3d(20px, 0, 0);
}
to {
opacity: 0;
-webkit-transform: translate3d(-2000px, 0, 0);
transform: translate3d(-2000px, 0, 0);
}
}
@keyframes bounceOutLeft {
20% {
opacity: 1;
-webkit-transform: translate3d(20px, 0, 0);
transform: translate3d(20px, 0, 0);
}
to {
opacity: 0;
-webkit-transform: translate3d(-2000px, 0, 0);
transform: translate3d(-2000px, 0, 0);
}
}
.bounceOutLeft {
-webkit-animation-name: bounceOutLeft;
animation-name: bounceOutLeft;
}
@-webkit-keyframes bounceOutRight {
20% {
opacity: 1;
-webkit-transform: translate3d(-20px, 0, 0);
transform: translate3d(-20px, 0, 0);
}
to {
opacity: 0;
-webkit-transform: translate3d(2000px, 0, 0);
transform: translate3d(2000px, 0, 0);
}
}
@keyframes bounceOutRight {
20% {
opacity: 1;
-webkit-transform: translate3d(-20px, 0, 0);
transform: translate3d(-20px, 0, 0);
}
to {
opacity: 0;
-webkit-transform: translate3d(2000px, 0, 0);
transform: translate3d(2000px, 0, 0);
}
}
.bounceOutRight {
-webkit-animation-name: bounceOutRight;
animation-name: bounceOutRight;
}
@-webkit-keyframes bounceOutUp {
20% {
-webkit-transform: translate3d(0, -10px, 0);
transform: translate3d(0, -10px, 0);
}
40%,
45% {
opacity: 1;
-webkit-transform: translate3d(0, 20px, 0);
transform: translate3d(0, 20px, 0);
}
to {
opacity: 0;
-webkit-transform: translate3d(0, -2000px, 0);
transform: translate3d(0, -2000px, 0);
}
}
@keyframes bounceOutUp {
20% {
-webkit-transform: translate3d(0, -10px, 0);
transform: translate3d(0, -10px, 0);
}
40%,
45% {
opacity: 1;
-webkit-transform: translate3d(0, 20px, 0);
transform: translate3d(0, 20px, 0);
}
to {
opacity: 0;
-webkit-transform: translate3d(0, -2000px, 0);
transform: translate3d(0, -2000px, 0);
}
}
.bounceOutUp {
-webkit-animation-name: bounceOutUp;
animation-name: bounceOutUp;
}
@-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fadeIn {
-webkit-animation-name: fadeIn;
animation-name: fadeIn;
}
@-webkit-keyframes fadeInDown {
from {
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes fadeInDown {
from {
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.fadeInDown {
-webkit-animation-name: fadeInDown;
animation-name: fadeInDown;
}
@-webkit-keyframes fadeInDownBig {
from {
opacity: 0;
-webkit-transform: translate3d(0, -2000px, 0);
transform: translate3d(0, -2000px, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes fadeInDownBig {
from {
opacity: 0;
-webkit-transform: translate3d(0, -2000px, 0);
transform: translate3d(0, -2000px, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.fadeInDownBig {
-webkit-animation-name: fadeInDownBig;
animation-name: fadeInDownBig;
}
@-webkit-keyframes fadeInLeft {
from {
opacity: 0;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes fadeInLeft {
from {
opacity: 0;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.fadeInLeft {
-webkit-animation-name: fadeInLeft;
animation-name: fadeInLeft;
}
@-webkit-keyframes fadeInLeftBig {
from {
opacity: 0;
-webkit-transform: translate3d(-2000px, 0, 0);
transform: translate3d(-2000px, 0, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes fadeInLeftBig {
from {
opacity: 0;
-webkit-transform: translate3d(-2000px, 0, 0);
transform: translate3d(-2000px, 0, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.fadeInLeftBig {
-webkit-animation-name: fadeInLeftBig;
animation-name: fadeInLeftBig;
}
@-webkit-keyframes fadeInRight {
from {
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes fadeInRight {
from {
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.fadeInRight {
-webkit-animation-name: fadeInRight;
animation-name: fadeInRight;
}
@-webkit-keyframes fadeInRightBig {
from {
opacity: 0;
-webkit-transform: translate3d(2000px, 0, 0);
transform: translate3d(2000px, 0, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes fadeInRightBig {
from {
opacity: 0;
-webkit-transform: translate3d(2000px, 0, 0);
transform: translate3d(2000px, 0, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.fadeInRightBig {
-webkit-animation-name: fadeInRightBig;
animation-name: fadeInRightBig;
}
@-webkit-keyframes fadeInUp {
from {
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes fadeInUp {
from {
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.fadeInUp {
-webkit-animation-name: fadeInUp;
animation-name: fadeInUp;
}
@-webkit-keyframes fadeInUpBig {
from {
opacity: 0;
-webkit-transform: translate3d(0, 2000px, 0);
transform: translate3d(0, 2000px, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes fadeInUpBig {
from {
opacity: 0;
-webkit-transform: translate3d(0, 2000px, 0);
transform: translate3d(0, 2000px, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.fadeInUpBig {
-webkit-animation-name: fadeInUpBig;
animation-name: fadeInUpBig;
}
@-webkit-keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.fadeOut {
-webkit-animation-name: fadeOut;
animation-name: fadeOut;
}
@-webkit-keyframes fadeOutDown {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
}
@keyframes fadeOutDown {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
}
.fadeOutDown {
-webkit-animation-name: fadeOutDown;
animation-name: fadeOutDown;
}
@-webkit-keyframes fadeOutDownBig {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(0, 2000px, 0);
transform: translate3d(0, 2000px, 0);
}
}
@keyframes fadeOutDownBig {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(0, 2000px, 0);
transform: translate3d(0, 2000px, 0);
}
}
.fadeOutDownBig {
-webkit-animation-name: fadeOutDownBig;
animation-name: fadeOutDownBig;
}
@-webkit-keyframes fadeOutLeft {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
}
@keyframes fadeOutLeft {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
}
.fadeOutLeft {
-webkit-animation-name: fadeOutLeft;
animation-name: fadeOutLeft;
}
@-webkit-keyframes fadeOutLeftBig {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(-2000px, 0, 0);
transform: translate3d(-2000px, 0, 0);
}
}
@keyframes fadeOutLeftBig {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(-2000px, 0, 0);
transform: translate3d(-2000px, 0, 0);
}
}
.fadeOutLeftBig {
-webkit-animation-name: fadeOutLeftBig;
animation-name: fadeOutLeftBig;
}
@-webkit-keyframes fadeOutRight {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
}
@keyframes fadeOutRight {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
}
.fadeOutRight {
-webkit-animation-name: fadeOutRight;
animation-name: fadeOutRight;
}
@-webkit-keyframes fadeOutRightBig {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(2000px, 0, 0);
transform: translate3d(2000px, 0, 0);
}
}
@keyframes fadeOutRightBig {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(2000px, 0, 0);
transform: translate3d(2000px, 0, 0);
}
}
.fadeOutRightBig {
-webkit-animation-name: fadeOutRightBig;
animation-name: fadeOutRightBig;
}
@-webkit-keyframes fadeOutUp {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
}
@keyframes fadeOutUp {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
}
.fadeOutUp {
-webkit-animation-name: fadeOutUp;
animation-name: fadeOutUp;
}
@-webkit-keyframes fadeOutUpBig {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(0, -2000px, 0);
transform: translate3d(0, -2000px, 0);
}
}
@keyframes fadeOutUpBig {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(0, -2000px, 0);
transform: translate3d(0, -2000px, 0);
}
}
.fadeOutUpBig {
-webkit-animation-name: fadeOutUpBig;
animation-name: fadeOutUpBig;
}
@-webkit-keyframes flip {
from {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
40% {
-webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
50% {
-webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
80% {
-webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95);
transform: perspective(400px) scale3d(0.95, 0.95, 0.95);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
to {
-webkit-transform: perspective(400px);
transform: perspective(400px);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
}
@keyframes flip {
from {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
40% {
-webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
50% {
-webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
80% {
-webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95);
transform: perspective(400px) scale3d(0.95, 0.95, 0.95);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
to {
-webkit-transform: perspective(400px);
transform: perspective(400px);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
}
.animated.flip {
-webkit-backface-visibility: visible;
backface-visibility: visible;
-webkit-animation-name: flip;
animation-name: flip;
}
@-webkit-keyframes flipInX {
from {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
opacity: 0;
}
40% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
60% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
opacity: 1;
}
80% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
}
to {
-webkit-transform: perspective(400px);
transform: perspective(400px);
}
}
@keyframes flipInX {
from {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
opacity: 0;
}
40% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
60% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
opacity: 1;
}
80% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
}
to {
-webkit-transform: perspective(400px);
transform: perspective(400px);
}
}
.flipInX {
-webkit-backface-visibility: visible !important;
backface-visibility: visible !important;
-webkit-animation-name: flipInX;
animation-name: flipInX;
}
@-webkit-keyframes flipInY {
from {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
opacity: 0;
}
40% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
60% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
opacity: 1;
}
80% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
}
to {
-webkit-transform: perspective(400px);
transform: perspective(400px);
}
}
@keyframes flipInY {
from {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
opacity: 0;
}
40% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
60% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
opacity: 1;
}
80% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
}
to {
-webkit-transform: perspective(400px);
transform: perspective(400px);
}
}
.flipInY {
-webkit-backface-visibility: visible !important;
backface-visibility: visible !important;
-webkit-animation-name: flipInY;
animation-name: flipInY;
}
@-webkit-keyframes flipOutX {
from {
-webkit-transform: perspective(400px);
transform: perspective(400px);
}
30% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
opacity: 1;
}
to {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
opacity: 0;
}
}
@keyframes flipOutX {
from {
-webkit-transform: perspective(400px);
transform: perspective(400px);
}
30% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
opacity: 1;
}
to {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
opacity: 0;
}
}
.flipOutX {
-webkit-animation-duration: 0.75s;
animation-duration: 0.75s;
-webkit-animation-name: flipOutX;
animation-name: flipOutX;
-webkit-backface-visibility: visible !important;
backface-visibility: visible !important;
}
@-webkit-keyframes flipOutY {
from {
-webkit-transform: perspective(400px);
transform: perspective(400px);
}
30% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
opacity: 1;
}
to {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
opacity: 0;
}
}
@keyframes flipOutY {
from {
-webkit-transform: perspective(400px);
transform: perspective(400px);
}
30% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
opacity: 1;
}
to {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
opacity: 0;
}
}
.flipOutY {
-webkit-animation-duration: 0.75s;
animation-duration: 0.75s;
-webkit-backface-visibility: visible !important;
backface-visibility: visible !important;
-webkit-animation-name: flipOutY;
animation-name: flipOutY;
}
@-webkit-keyframes lightSpeedIn {
from {
-webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
transform: translate3d(100%, 0, 0) skewX(-30deg);
opacity: 0;
}
60% {
-webkit-transform: skewX(20deg);
transform: skewX(20deg);
opacity: 1;
}
80% {
-webkit-transform: skewX(-5deg);
transform: skewX(-5deg);
opacity: 1;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
@keyframes lightSpeedIn {
from {
-webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
transform: translate3d(100%, 0, 0) skewX(-30deg);
opacity: 0;
}
60% {
-webkit-transform: skewX(20deg);
transform: skewX(20deg);
opacity: 1;
}
80% {
-webkit-transform: skewX(-5deg);
transform: skewX(-5deg);
opacity: 1;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
.lightSpeedIn {
-webkit-animation-name: lightSpeedIn;
animation-name: lightSpeedIn;
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
@-webkit-keyframes lightSpeedOut {
from {
opacity: 1;
}
to {
-webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
transform: translate3d(100%, 0, 0) skewX(30deg);
opacity: 0;
}
}
@keyframes lightSpeedOut {
from {
opacity: 1;
}
to {
-webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
transform: translate3d(100%, 0, 0) skewX(30deg);
opacity: 0;
}
}
.lightSpeedOut {
-webkit-animation-name: lightSpeedOut;
animation-name: lightSpeedOut;
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
@-webkit-keyframes rotateIn {
from {
-webkit-transform-origin: center;
transform-origin: center;
-webkit-transform: rotate3d(0, 0, 1, -200deg);
transform: rotate3d(0, 0, 1, -200deg);
opacity: 0;
}
to {
-webkit-transform-origin: center;
transform-origin: center;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
@keyframes rotateIn {
from {
-webkit-transform-origin: center;
transform-origin: center;
-webkit-transform: rotate3d(0, 0, 1, -200deg);
transform: rotate3d(0, 0, 1, -200deg);
opacity: 0;
}
to {
-webkit-transform-origin: center;
transform-origin: center;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
.rotateIn {
-webkit-animation-name: rotateIn;
animation-name: rotateIn;
}
@-webkit-keyframes rotateInDownLeft {
from {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
-webkit-transform: rotate3d(0, 0, 1, -45deg);
transform: rotate3d(0, 0, 1, -45deg);
opacity: 0;
}
to {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
@keyframes rotateInDownLeft {
from {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
-webkit-transform: rotate3d(0, 0, 1, -45deg);
transform: rotate3d(0, 0, 1, -45deg);
opacity: 0;
}
to {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
.rotateInDownLeft {
-webkit-animation-name: rotateInDownLeft;
animation-name: rotateInDownLeft;
}
@-webkit-keyframes rotateInDownRight {
from {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
-webkit-transform: rotate3d(0, 0, 1, 45deg);
transform: rotate3d(0, 0, 1, 45deg);
opacity: 0;
}
to {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
@keyframes rotateInDownRight {
from {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
-webkit-transform: rotate3d(0, 0, 1, 45deg);
transform: rotate3d(0, 0, 1, 45deg);
opacity: 0;
}
to {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
.rotateInDownRight {
-webkit-animation-name: rotateInDownRight;
animation-name: rotateInDownRight;
}
@-webkit-keyframes rotateInUpLeft {
from {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
-webkit-transform: rotate3d(0, 0, 1, 45deg);
transform: rotate3d(0, 0, 1, 45deg);
opacity: 0;
}
to {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
@keyframes rotateInUpLeft {
from {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
-webkit-transform: rotate3d(0, 0, 1, 45deg);
transform: rotate3d(0, 0, 1, 45deg);
opacity: 0;
}
to {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
.rotateInUpLeft {
-webkit-animation-name: rotateInUpLeft;
animation-name: rotateInUpLeft;
}
@-webkit-keyframes rotateInUpRight {
from {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
-webkit-transform: rotate3d(0, 0, 1, -90deg);
transform: rotate3d(0, 0, 1, -90deg);
opacity: 0;
}
to {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
@keyframes rotateInUpRight {
from {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
-webkit-transform: rotate3d(0, 0, 1, -90deg);
transform: rotate3d(0, 0, 1, -90deg);
opacity: 0;
}
to {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
.rotateInUpRight {
-webkit-animation-name: rotateInUpRight;
animation-name: rotateInUpRight;
}
@-webkit-keyframes rotateOut {
from {
-webkit-transform-origin: center;
transform-origin: center;
opacity: 1;
}
to {
-webkit-transform-origin: center;
transform-origin: center;
-webkit-transform: rotate3d(0, 0, 1, 200deg);
transform: rotate3d(0, 0, 1, 200deg);
opacity: 0;
}
}
@keyframes rotateOut {
from {
-webkit-transform-origin: center;
transform-origin: center;
opacity: 1;
}
to {
-webkit-transform-origin: center;
transform-origin: center;
-webkit-transform: rotate3d(0, 0, 1, 200deg);
transform: rotate3d(0, 0, 1, 200deg);
opacity: 0;
}
}
.rotateOut {
-webkit-animation-name: rotateOut;
animation-name: rotateOut;
}
@-webkit-keyframes rotateOutDownLeft {
from {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
opacity: 1;
}
to {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
-webkit-transform: rotate3d(0, 0, 1, 45deg);
transform: rotate3d(0, 0, 1, 45deg);
opacity: 0;
}
}
@keyframes rotateOutDownLeft {
from {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
opacity: 1;
}
to {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
-webkit-transform: rotate3d(0, 0, 1, 45deg);
transform: rotate3d(0, 0, 1, 45deg);
opacity: 0;
}
}
.rotateOutDownLeft {
-webkit-animation-name: rotateOutDownLeft;
animation-name: rotateOutDownLeft;
}
@-webkit-keyframes rotateOutDownRight {
from {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
opacity: 1;
}
to {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
-webkit-transform: rotate3d(0, 0, 1, -45deg);
transform: rotate3d(0, 0, 1, -45deg);
opacity: 0;
}
}
@keyframes rotateOutDownRight {
from {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
opacity: 1;
}
to {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
-webkit-transform: rotate3d(0, 0, 1, -45deg);
transform: rotate3d(0, 0, 1, -45deg);
opacity: 0;
}
}
.rotateOutDownRight {
-webkit-animation-name: rotateOutDownRight;
animation-name: rotateOutDownRight;
}
@-webkit-keyframes rotateOutUpLeft {
from {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
opacity: 1;
}
to {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
-webkit-transform: rotate3d(0, 0, 1, -45deg);
transform: rotate3d(0, 0, 1, -45deg);
opacity: 0;
}
}
@keyframes rotateOutUpLeft {
from {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
opacity: 1;
}
to {
-webkit-transform-origin: left bottom;
transform-origin: left bottom;
-webkit-transform: rotate3d(0, 0, 1, -45deg);
transform: rotate3d(0, 0, 1, -45deg);
opacity: 0;
}
}
.rotateOutUpLeft {
-webkit-animation-name: rotateOutUpLeft;
animation-name: rotateOutUpLeft;
}
@-webkit-keyframes rotateOutUpRight {
from {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
opacity: 1;
}
to {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
-webkit-transform: rotate3d(0, 0, 1, 90deg);
transform: rotate3d(0, 0, 1, 90deg);
opacity: 0;
}
}
@keyframes rotateOutUpRight {
from {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
opacity: 1;
}
to {
-webkit-transform-origin: right bottom;
transform-origin: right bottom;
-webkit-transform: rotate3d(0, 0, 1, 90deg);
transform: rotate3d(0, 0, 1, 90deg);
opacity: 0;
}
}
.rotateOutUpRight {
-webkit-animation-name: rotateOutUpRight;
animation-name: rotateOutUpRight;
}
@-webkit-keyframes hinge {
0% {
-webkit-transform-origin: top left;
transform-origin: top left;
-webkit-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
}
20%,
60% {
-webkit-transform: rotate3d(0, 0, 1, 80deg);
transform: rotate3d(0, 0, 1, 80deg);
-webkit-transform-origin: top left;
transform-origin: top left;
-webkit-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
}
40%,
80% {
-webkit-transform: rotate3d(0, 0, 1, 60deg);
transform: rotate3d(0, 0, 1, 60deg);
-webkit-transform-origin: top left;
transform-origin: top left;
-webkit-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
opacity: 1;
}
to {
-webkit-transform: translate3d(0, 700px, 0);
transform: translate3d(0, 700px, 0);
opacity: 0;
}
}
@keyframes hinge {
0% {
-webkit-transform-origin: top left;
transform-origin: top left;
-webkit-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
}
20%,
60% {
-webkit-transform: rotate3d(0, 0, 1, 80deg);
transform: rotate3d(0, 0, 1, 80deg);
-webkit-transform-origin: top left;
transform-origin: top left;
-webkit-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
}
40%,
80% {
-webkit-transform: rotate3d(0, 0, 1, 60deg);
transform: rotate3d(0, 0, 1, 60deg);
-webkit-transform-origin: top left;
transform-origin: top left;
-webkit-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
opacity: 1;
}
to {
-webkit-transform: translate3d(0, 700px, 0);
transform: translate3d(0, 700px, 0);
opacity: 0;
}
}
.hinge {
-webkit-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-name: hinge;
animation-name: hinge;
}
@-webkit-keyframes jackInTheBox {
from {
opacity: 0;
-webkit-transform: scale(0.1) rotate(30deg);
transform: scale(0.1) rotate(30deg);
-webkit-transform-origin: center bottom;
transform-origin: center bottom;
}
50% {
-webkit-transform: rotate(-10deg);
transform: rotate(-10deg);
}
70% {
-webkit-transform: rotate(3deg);
transform: rotate(3deg);
}
to {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1);
}
}
@keyframes jackInTheBox {
from {
opacity: 0;
-webkit-transform: scale(0.1) rotate(30deg);
transform: scale(0.1) rotate(30deg);
-webkit-transform-origin: center bottom;
transform-origin: center bottom;
}
50% {
-webkit-transform: rotate(-10deg);
transform: rotate(-10deg);
}
70% {
-webkit-transform: rotate(3deg);
transform: rotate(3deg);
}
to {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1);
}
}
.jackInTheBox {
-webkit-animation-name: jackInTheBox;
animation-name: jackInTheBox;
}
@-webkit-keyframes rollIn {
from {
opacity: 0;
-webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes rollIn {
from {
opacity: 0;
-webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.rollIn {
-webkit-animation-name: rollIn;
animation-name: rollIn;
}
@-webkit-keyframes rollOut {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
}
}
@keyframes rollOut {
from {
opacity: 1;
}
to {
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
}
}
.rollOut {
-webkit-animation-name: rollOut;
animation-name: rollOut;
}
@-webkit-keyframes zoomIn {
from {
opacity: 0;
-webkit-transform: scale3d(0.3, 0.3, 0.3);
transform: scale3d(0.3, 0.3, 0.3);
}
50% {
opacity: 1;
}
}
@keyframes zoomIn {
from {
opacity: 0;
-webkit-transform: scale3d(0.3, 0.3, 0.3);
transform: scale3d(0.3, 0.3, 0.3);
}
50% {
opacity: 1;
}
}
.zoomIn {
-webkit-animation-name: zoomIn;
animation-name: zoomIn;
}
@-webkit-keyframes zoomInDown {
from {
opacity: 0;
-webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
-webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
60% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
}
}
@keyframes zoomInDown {
from {
opacity: 0;
-webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0);
-webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
60% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
}
}
.zoomInDown {
-webkit-animation-name: zoomInDown;
animation-name: zoomInDown;
}
@-webkit-keyframes zoomInLeft {
from {
opacity: 0;
-webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
-webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
60% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
}
}
@keyframes zoomInLeft {
from {
opacity: 0;
-webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
transform: scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0);
-webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
60% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0);
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
}
}
.zoomInLeft {
-webkit-animation-name: zoomInLeft;
animation-name: zoomInLeft;
}
@-webkit-keyframes zoomInRight {
from {
opacity: 0;
-webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
-webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
60% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
}
}
@keyframes zoomInRight {
from {
opacity: 0;
-webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
transform: scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0);
-webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
60% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0);
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
}
}
.zoomInRight {
-webkit-animation-name: zoomInRight;
animation-name: zoomInRight;
}
@-webkit-keyframes zoomInUp {
from {
opacity: 0;
-webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
-webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
60% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
}
}
@keyframes zoomInUp {
from {
opacity: 0;
-webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0);
-webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
60% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
}
}
.zoomInUp {
-webkit-animation-name: zoomInUp;
animation-name: zoomInUp;
}
@-webkit-keyframes zoomOut {
from {
opacity: 1;
}
50% {
opacity: 0;
-webkit-transform: scale3d(0.3, 0.3, 0.3);
transform: scale3d(0.3, 0.3, 0.3);
}
to {
opacity: 0;
}
}
@keyframes zoomOut {
from {
opacity: 1;
}
50% {
opacity: 0;
-webkit-transform: scale3d(0.3, 0.3, 0.3);
transform: scale3d(0.3, 0.3, 0.3);
}
to {
opacity: 0;
}
}
.zoomOut {
-webkit-animation-name: zoomOut;
animation-name: zoomOut;
}
@-webkit-keyframes zoomOutDown {
40% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
-webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
to {
opacity: 0;
-webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
-webkit-transform-origin: center bottom;
transform-origin: center bottom;
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
}
}
@keyframes zoomOutDown {
40% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0);
-webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
to {
opacity: 0;
-webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
transform: scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0);
-webkit-transform-origin: center bottom;
transform-origin: center bottom;
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
}
}
.zoomOutDown {
-webkit-animation-name: zoomOutDown;
animation-name: zoomOutDown;
}
@-webkit-keyframes zoomOutLeft {
40% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
}
to {
opacity: 0;
-webkit-transform: scale(0.1) translate3d(-2000px, 0, 0);
transform: scale(0.1) translate3d(-2000px, 0, 0);
-webkit-transform-origin: left center;
transform-origin: left center;
}
}
@keyframes zoomOutLeft {
40% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0);
}
to {
opacity: 0;
-webkit-transform: scale(0.1) translate3d(-2000px, 0, 0);
transform: scale(0.1) translate3d(-2000px, 0, 0);
-webkit-transform-origin: left center;
transform-origin: left center;
}
}
.zoomOutLeft {
-webkit-animation-name: zoomOutLeft;
animation-name: zoomOutLeft;
}
@-webkit-keyframes zoomOutRight {
40% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
}
to {
opacity: 0;
-webkit-transform: scale(0.1) translate3d(2000px, 0, 0);
transform: scale(0.1) translate3d(2000px, 0, 0);
-webkit-transform-origin: right center;
transform-origin: right center;
}
}
@keyframes zoomOutRight {
40% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0);
}
to {
opacity: 0;
-webkit-transform: scale(0.1) translate3d(2000px, 0, 0);
transform: scale(0.1) translate3d(2000px, 0, 0);
-webkit-transform-origin: right center;
transform-origin: right center;
}
}
.zoomOutRight {
-webkit-animation-name: zoomOutRight;
animation-name: zoomOutRight;
}
@-webkit-keyframes zoomOutUp {
40% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
-webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
to {
opacity: 0;
-webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
-webkit-transform-origin: center bottom;
transform-origin: center bottom;
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
}
}
@keyframes zoomOutUp {
40% {
opacity: 1;
-webkit-transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
transform: scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0);
-webkit-animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
to {
opacity: 0;
-webkit-transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
transform: scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0);
-webkit-transform-origin: center bottom;
transform-origin: center bottom;
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
}
}
.zoomOutUp {
-webkit-animation-name: zoomOutUp;
animation-name: zoomOutUp;
}
@-webkit-keyframes slideInDown {
from {
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
visibility: visible;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes slideInDown {
from {
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
visibility: visible;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.slideInDown {
-webkit-animation-name: slideInDown;
animation-name: slideInDown;
}
@-webkit-keyframes slideInLeft {
from {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
visibility: visible;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes slideInLeft {
from {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
visibility: visible;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.slideInLeft {
-webkit-animation-name: slideInLeft;
animation-name: slideInLeft;
}
@-webkit-keyframes slideInRight {
from {
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
visibility: visible;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes slideInRight {
from {
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
visibility: visible;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.slideInRight {
-webkit-animation-name: slideInRight;
animation-name: slideInRight;
}
@-webkit-keyframes slideInUp {
from {
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
visibility: visible;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes slideInUp {
from {
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
visibility: visible;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.slideInUp {
-webkit-animation-name: slideInUp;
animation-name: slideInUp;
}
@-webkit-keyframes slideOutDown {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
to {
visibility: hidden;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
}
@keyframes slideOutDown {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
to {
visibility: hidden;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
}
.slideOutDown {
-webkit-animation-name: slideOutDown;
animation-name: slideOutDown;
}
@-webkit-keyframes slideOutLeft {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
to {
visibility: hidden;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
}
@keyframes slideOutLeft {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
to {
visibility: hidden;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
}
.slideOutLeft {
-webkit-animation-name: slideOutLeft;
animation-name: slideOutLeft;
}
@-webkit-keyframes slideOutRight {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
to {
visibility: hidden;
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
}
@keyframes slideOutRight {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
to {
visibility: hidden;
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
}
.slideOutRight {
-webkit-animation-name: slideOutRight;
animation-name: slideOutRight;
}
@-webkit-keyframes slideOutUp {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
to {
visibility: hidden;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
}
@keyframes slideOutUp {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
to {
visibility: hidden;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
}
.slideOutUp {
-webkit-animation-name: slideOutUp;
animation-name: slideOutUp;
}
// 居中按钮样式
@mixin btn-center($width, $height) {
width: $width;
height: $height;
line-height: $height;
text-align: center;
}
// 超过多少行自动省略 默认一行
@mixin ellipsis($line:1) {
display: -webkit-box;
word-break: break-all;
-webkit-box-orient: vertical;
-webkit-line-clamp: $line;
overflow: hidden;
text-overflow: ellipsis;
}
// 文字截取
@mixin text-overflow() {
overflow: hidden;
white-space: normal;
text-overflow: ellipsis;
word-break: break-all;
word-wrap: normal;
}
@mixin word-break() {
word-break: break-all;
word-wrap: break-word;
white-space: normal;
}
// No wrap
@mixin no-wrap() {
word-break: normal;
word-wrap: normal;
white-space: nowrap;
}
// 清除浮动
@mixin clearfix() {
&:before,
&:after {
content: " "; // 1
display: table; // 2
}
&:after {
clear: both;
}
}
// Single side border-radius
@mixin border-top-radius($radius) {
border-top-right-radius: $radius;
border-top-left-radius: $radius;
}
@mixin border-right-radius($radius) {
border-bottom-right-radius: $radius;
border-top-right-radius: $radius;
}
@mixin border-bottom-radius($radius) {
border-bottom-right-radius: $radius;
border-bottom-left-radius: $radius;
}
@mixin border-left-radius($radius) {
border-bottom-left-radius: $radius;
border-top-left-radius: $radius;
}
// Center-align a block level element
@mixin center-block() {
display: block;
margin-left: auto;
margin-right: auto;
}
// CSS image replacement
// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757
@mixin hide-text() {
font-size: 0;
line-height: 0;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
// 居中按钮样式
@mixin btc($width, $height) {
width: $width;
height: $height;
line-height: $height;
text-align: center;
}
// 通用按钮
@mixin cb($width:320px, $height:84px, $fontSize:32px) {
color: #FFFFFF;
position: relative;
width: $width;
height: $height;
line-height: $height;
text-align: center;
font-size: $fontSize;
border-radius: 8px;
background-color: #3680EB;
}
// 通用按钮
@mixin cb2($width:320px, $height:84px, $fontSize:32px) {
position: relative;
width: $width;
height: $height;
line-height: $height;
text-align: center;
font-size: $fontSize;
border-radius: 8px;
color: #3680EB;
border: solid 1PX #3680EB;
}
@mixin app-width() {
width: 750px;
}
@import "mixins";
@import "var";
@import "support";
// // Margin
// .u-mt-smaller {
// margin-top: $marginTopSmaller;
// }
// .u-mt-small {
// margin-top: $marginTopSmall;
// }
// .u-mt-medium {
// margin-top: $marginTopMedium;
// }
// .u-mt-large {
// margin-top: $marginTopLarge;
// }
// .u-mt-larger {
// margin-top: $marginTopLarger;
// }
// .u-mb-smaller {
// margin-bottom: $marginTopSmaller;
// }
// .u-mb-small {
// margin-bottom: $marginTopSmall;
// }
// .u-mb-medium {
// margin-bottom: $marginTopMedium;
// }
// .u-mb-large {
// margin-bottom: $marginTopLarge;
// }
// .u-mb-larger {
// margin-bottom: $marginTopLarger;
// }
// // Padding
// .u-pt-smaller {
// padding-top: $paddingTopSmaller;
// }
// .u-pt-small {
// padding-top: $paddingTopSmall;
// }
// .u-pt-medium {
// padding-top: $paddingTopMedium;
// }
// .u-pt-large {
// padding-top: $paddingTopLarge;
// }
// .u-pt-larger {
// padding-top: $paddingTopLarger;
// }
// .u-pb-smaller {
// padding-bottom: $paddingTopSmaller;
// }
// .u-pb-small {
// padding-bottom: $paddingTopSmall;
// }
// .u-pb-medium {
// padding-bottom: $paddingTopMedium;
// }
// .u-pb-large {
// padding-bottom: $paddingTopLarge;
// }
// .u-pb-larger {
// padding-bottom: $paddingTopLarger;
// }
// // 布局方位
// .u-ta-c {
// text-align: center !important;
// }
// .u-ta-l {
// text-align: left !important;
// }
// .u-ta-r {
// text-align: right !important;
// }
// .u-fl-l {
// float: left;
// }
// .u-fl-n {
// float: none;
// }
// .u-fl-r {
// float: right;
// }
// .u-d-b {
// display: block;
// }
// .u-d-i {
// display: inline !important;
// }
// .u-d-ib {
// display: inline-block !important;
// }
// .u-d-n {
// display: none !important;
// }
// .u-d-t {
// display: table;
// table-layout: fixed;
// }
// .u-d-tc {
// display: table-cell;
// }
// .u-va-b {
// vertical-align: bottom;
// }
// .u-va-m {
// vertical-align: middle;
// }
// .u-va-t {
// vertical-align: top;
// }
// // clearfix
// .u-clearfix {
// @include clearfix;
// }
// // 虚拟格式
// .u-cur-d {
// cursor: default;
// }
// .u-cur-p {
// cursor: pointer;
// }
// // flex
// .u-flex {
// display: -webkit-box;
// display: -webkit-flex;
// display: flex;
// }
// .u-flex-item {
// -webkit-box-flex: 1;
// -webkit-flex: 1;
// flex: 1;
// }
// // 小程序中模拟ul、li
// .u-ul {
// padding-left: 30px;
// text-align: left;
// display: block;
// }
// .u-li {
// position: relative;
// font-size: $fontSizeSmall;
// line-height: $fontSizeSmall + 4px;
// margin-bottom: $marginTopSmall;
// &:before {
// position: absolute;
// content: " ";
// top: 14px;
// left: -20px;
// width: 8px;
// height: 8px;
// border-radius: 8px;
// background-color: $colorBlack;
// }
// }
.bis {
background-repeat: no-repeat;
background-size: 100% 100%;
}
//flex 布局和 子元素 对其方式
.fl {
display: flex;
}
.fj {
display: flex;
justify-content: space-between;
}
.fje {
display: flex;
justify-content: flex-end;
}
//水平和垂直居中
.fcc {
display: flex;
justify-content: center;
align-items: center;
}
// 为元素设定的宽度和高度决定了元素的边框盒。
.bb {
box-sizing: border-box;
}
// 满屏
.fullp {
width: 100%;
height: 100%;
}
.shadow {
box-shadow: 0 6px 18px 0 rgba(0, 0, 0, 0.10);
border-radius: 8px;
}
.linear {
background-image: linear-gradient(to right, #1bade8, #3680EB);
}
// // Margin
// $marginTopSmaller: 20px;
// $marginTopSmall: 30px;
// $marginTopMedium: 40px;
// $marginTopLarge: 60px;
// $marginTopLarger: 80px;
// // Padding
// $paddingTopSmaller: 20px;
// $paddingTopSmall: 30px;
// $paddingTopMedium: 40px;
// $paddingTopLarge: 60px;
// $paddingTopLarger: 80px;
// // Color
$colorBlue: #20A0FF;
$colorGreen: #13CE66;
$colorGray: #475669;
$colorBlack: #000;
$colorRed: #FF4949;
$colorYellow: #F7BA2A;
$color: #787878;
// $colorLink: #1D8CE0;
// $backGroundColor: #fff;
// // Font
$fontSize: 32px;
$fontSizeSmall: 28px;
$fontSizeSmaller: 24px;
$fontSizeLarge: 36px;
$fontSizeLarger: 44px;
// // 主题颜色
$colorMain:#3680EB;
$pageBottom:80px;
let app = getApp();
Component({
properties: {
// 这里定义了innerText属性,属性值可以在组件使用时指定
innerText: {
type: String,
value: 'default value',
},
// 用户拒绝授权后是否后退页面
cancelBack: {
type: Boolean,
value: false,
},
// 用户拒绝授权后描述
cancelDesc: {
type: String,
value: "同意授权才能获得更多体验哦~",
}
},
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod() {
this.triggerEvent('evtcomp', {
name: "_evt_custom"
})
},
// 隐藏蒙层
hideMask() {
this.triggerEvent('evtcomp', {
name: "_evt_hide_mask"
});
},
// 授权成功事件
authComplete() {
this.triggerEvent('evtcomp', {
name: "_evt_auth_complete"
});
},
// 点击暂不授权按钮
cancelAuth(e) {
this.hideMask();
// this.triggerEvent('evtcomp', {
// name: "_evt_auth_cancel"
// });
// if (this.properties.cancelBack) {
// wx.navigateBack({
// delta: 1
// });
// }
},
// 点击确认授权按钮
bindGetUserInfo(e) {
wx.showLoading();
this.getUserInfo(e.detail);
},
// 授权操作
getUserInfo(e) {
let _this = this;
if (e.encryptedData && e.iv) {
// 同意授权
app.post({
url: app.api.register,
sid: false,
data: {
encryptedData: e.encryptedData,
iv: e.iv,
code: app.store.getItem("wxcode"),
tlMemberCode: app.globalData.tlMemberCode
}
}).then((res2) => {
wx.hideLoading();
if (res2 && res2.sessionId) {
app.store.setItem('sessionId', res2.sessionId);
}
_this.hideMask();
_this.authComplete();
_this.initPage();
}).catch((err) => {})
} else {
// 取消授权
if (_this.properties.cancelBack) {
wx.navigateBack({
delta: 1
});
} else {
if (_this.properties.cancelDesc) {
wx.showToast({
title: _this.properties.cancelDesc,
icon: "none"
})
}
}
}
},
/**
* 尝试重拉信息
*/
initPage() {
let pages = getCurrentPages();
let view = pages[pages.length - 1];
console.log("@authorize-comp view:", view);
if (view) {
try {
view.hideMask();
console.log("@authorize-comp || hideMask");
} catch (error) {}
try {
view.initData();
console.log("@authorize-comp || initData");
} catch (error) {}
}
}
}
})
@import '../../assets/scss/mixins';
@import '../../assets/scss/utils';
.comp-item {
width: 650px;
min-height: 496px;
border-radius: 10px;
background-color: #ffffff;
.cspace {
height: 80px;
}
.cont {
text-align: center;
width: 520px;
margin: 0 auto;
.logo {
margin: 0 auto;
width: 200px;
height: 153px;
image {
width: 200px;
height: 153px;
}
}
.tit {
font-size: 40px;
color: #333333;
}
.tips {
margin-top: 28px;
font-size: 32px;
color: #333333;
padding-bottom: 244px;
}
}
.btn-wrap {
position: absolute;
left: 0;
right: 0;
bottom: 80px;
margin: 0 auto;
display: flex;
justify-content: center;
}
.btn {
@include cb(240px, 80px);
margin: 0 24px;
}
.btn2 {
@include cb2(240px, 80px);
}
}
<view class="comp-item">
<view class="cspace"></view>
<view class="cont">
<!-- <view class="logo">
<image mode="widthFix" src="../../image/logo.png" />
</view> -->
<view class="tit">深士照明</view>
<view class="tips">
<text>需要获取您的微信昵称等信息才可以获取积分和兑换奖品哦</text>
</view>
</view>
<view class="btn-wrap">
<button class="btn btn2" bindtap="cancelAuth">暂不授权</button>
<button class="btn" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">确认授权</button>
</view>
</view>
Component({
properties: {
// 这里定义了innerText属性,属性值可以在组件使用时指定
innerText: {
type: String,
value: 'default value',
},
bottomVisible: {
type: Boolean,
value: false
}
},
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod() {}
}
})
// 底线
.bottom-tips {
position: relative;
padding: 40px 0;
width: 100%;
text-align: center;
color: #666666;
.line {
border-bottom: dashed 1px #cccccc;
width: 80%;
position: absolute;
top: 50%;
left: 0;
right: 0;
margin: 0 auto;
}
.tips-wrap {
position: relative;
font-size: 28px;
.tips {
padding: 0 20px;
background-color: #ffffff;
}
}
}
<view class="bottom-tips" wx:if="{{bottomVisible}}">
<view class="line"></view>
<view class="tips-wrap">
<text class="tips">我是有底线的</text>
</view>
</view>
let app = getApp();
Component({
// 样式隔离
// 详见 https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html
// isolated 表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(一般情况下的默认值);
// apply-shared 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面;
// shared 表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置了 apply-shared 或 shared 的自定义组件。(这个选项在插件中不可用。)
options: {
styleIsolation: 'isolated'
},
properties: {
// 这里定义了innerText属性,属性值可以在组件使用时指定
innerText: {
type: String,
value: 'default value',
}
},
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod() {
this.triggerEvent('evtcomp', {
name: "_evt_custom"
})
},
// 隐藏蒙层
hideMask() {
this.triggerEvent('evtcomp', {
name: "_evt_hide_product_detail_mask"
});
}
}
})
<view class="demo-item">demo-item</view>
Component({
options: {
styleIsolation: 'apply-shared' // 接受外部样式
},
properties: {
// 这里定义了innerText属性,属性值可以在组件使用时指定
innerText: {
type: String,
value: 'default value',
},
emptyVisible: {
type: Boolean,
value: false
}
},
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod() {}
}
})
//用的fixed 请确保 内容为空
.empty-tips {
position: fixed;
text-align: center;
color: #666666;
font-size: 32px;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
top:35%;
.iconfont{
font-size: 100px;
}
.tips {
padding: 20px;
}
}
<view class="empty-tips" wx:if="{{emptyVisible}}">
<view class="tips">
<span class="iconfont iconempty"></span>
<view class="tips">这里空空如也~</view>
</view>
</view>
const app = getApp()
Component({
options: {
styleIsolation: 'apply-shared'
},
properties: {
navbarData: { //navbarData 由父页面传递的数据,变量名字自命名
type: Object,
value: {},
// observer: function (newVal, oldVal) {}
},
share: {
type: Boolean,
value: false
}
},
data: {
height: '',
barHeight: app.globalData.barHeight,
//默认值 默认显示左上角
// navbarData: {
// showCapsule: 1,
// }
},
attached: function () {
// 获取是否是通过分享进入的小程序
// this.setData({
// share: app.globalData.share
// })
// 定义导航栏的高度 方便对齐
this.setData({
statusBarHeight: app.globalData.statusBarHeight,
height: app.globalData.barHeight
})
},
methods: {
// 返回上一页面
_navback() {
wx.navigateBack()
},
//返回到首页
_backhome() {
app.router.push({
path: "index",
openType: "reLaunch"
})
// wx.navigateBack({
// delta: 999999
// })
}
},
ready() {
// console.log("navbarData.title}:", this.properties.navbarData.title);
}
})
{
"component": true
}
/* 顶部要固定定位 标题要居中 自定义按钮和标题要和右边微信原生的胶囊上下对齐 */
.nav-wrap {
position: fixed;
width: 100%;
top: 0;
background: #fff;
color: #000;
z-index: 999999;
}
/* 标题要居中 */
.nav-title {
position: absolute;
text-align: center;
max-width: 400px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
font-size: 32px;
color: #2c2b2b;
font-weight: 600;
}
.nav-capsule {
display: flex;
align-items: center;
margin-left: 30px;
width: 120px;
justify-content: space-between;
height: 100%;
}
.navbar-v-line {
width: 1px;
height: 32px;
background-color: #e5e5e5;
}
.back-pre,
.back-home {
width: 32px;
height: 36px;
line-height: 36px;
margin-top: 4px;
padding: 10px;
}
.nav-capsule .back-home {
width: 36px;
height: 40px;
margin-top: 3px;
}
.iconfont {
font-size: 40px;
}
<view class='nav-wrap' style='height: {{height}}px;'>
<view class='nav-title' style='line-height: {{height+statusBarHeight}}px;'>{{navbarData.title}}</view>
<view style='display: flex; justify-content: space-around;flex-direction: column'>
<view class='nav-capsule' style='height: {{height+statusBarHeight}}px;' wx:if='{{navbarData.showCapsule}}'>
<view bindtap='_navback' wx:if='{{!share}}'>
<span class="iconfont iconbackicon1"></span>
</view>
<view class='navbar-v-line' wx:if='{{!share}}'></view>
<view bindtap='_backhome'>
<span class="iconfont iconhome"></span>
</view>
</view>
</view>
</view>
let ENV_CONFIG = require('./env/index');
const APPID = ''
/** ====每次发布版本记得修改此环境配置==== */
const ENV = 'dev'; // Dev Prod
const NET_CONFIG = ENV_CONFIG[ENV];
const MOCKAPI = ENV_CONFIG.mockApi;
module.exports = {
APPID,
ENV,
NET_CONFIG,
MOCKAPI
}
module.exports = {
mockApi: 'http://mock.simonfungc.com',
Dev: {
baseApi: 'https://ow.go.qudone.com/xxx',
commonApi: 'https://api.k.wxpai.cn/bizproxy'
},
Test: {
baseApi: 'https://test-api.xxx.com'
},
Slave: {
baseApi: 'https://slave-api.xxx.com'
},
Prod: {
baseApi: 'https://api.k.wxpai.cn/bizproxy/xxx',
commonApi: 'https://api.k.wxpai.cn/bizproxy'
}
}
# chmod u+x git.sh
unset msg
read -p "请输入commit提交的描述: " msg
if [[ $msg == "" ]]; then
msg="默认提交"
fi
git add -A
git commit -m $msg
git push
git status
module.exports = {
login: "/login", // post 通过wxcode换取sessionId
register: '/register', // post 注册(用户授权)
dataList: '/dataList', // 测试接口
/**
* 通用接口
* 请求时 "mode"传"custom"
*/
areaQuery: 'https://api.k.wxpai.cn/bizproxy/kdapi/area', // post 区域查询
}
let config = require('./../config');
let Store = require('./../utils/stroage');
let Router = require('./../router/index');
const errMsg = '服务异常,请稍后重试';
// let isWxLogin = false;
function wxLogin() {
return new Promise((resolve, reject) => {
wx.login({
success: function (res) {
// isWxLogin = true;
Store.setItem('wxcode', res.code);
resolve();
}
});
});
}
// 检查并获取sessionid
function checkSessionId(sid) {
return new Promise((resolve, reject) => {
if (!sid) {
resolve();
return;
}
let sessionId = Store.getItem('sessionId');
if (sessionId) {
resolve();
} else {
// 没有sessionId则获取并埋值
login().then((result) => {
resolve();
}).catch((err) => {
reject();
});
}
});
}
// session丢失
function login() {
return new Promise((resolve, reject) => {
wxLogin().then((result) => {
let baseUrl = config.NET_CONFIG.baseApi;
wx.request({
url: baseUrl + '/login',
sid: false,
data: {
code: Store.getItem('wxcode')
},
method: 'POST',
success: function (res2) {
let {
code,
content
} = res2.data;
if (code == 200 && content.sessionId) {
Store.setItem('sessionId', content.sessionId);
resolve();
} else {
wx.hideLoading();
let pages = getCurrentPages();
let view = pages[pages.length - 1];
if (view) {
try {
wx.login({
success: function (res) {
Store.setItem('wxcode', res.code);
view.showAuth();
}
});
} catch (error) {}
}
reject();
}
}
})
})
});
}
const fetch = function ({
loading = true,
toast = true,
sid = true,
auth = true,
mode,
isMock,
url,
data,
method
}) {
if (loading && mode != 'log') wx.showLoading();
// 新建promise对象
let promise = new Promise((resolve, reject) => {
/**
* isMock设置单个接口Mock开启
* mode:目前针对不同业务的接口进行处理,log标识本地埋点上传
*/
let baseUrl = config.NET_CONFIG.baseApi;
if (isMock && mode != 'log') {
baseUrl = config.MOCKAPI; //环境配置
}
// 使用通用接口前缀
if (mode == "common") {
baseUrl = config.NET_CONFIG.commonApi
}
// 自定义前缀,即不使用前缀
if (mode == "custom") {
baseUrl = ""
}
checkSessionId(sid).then((result) => {
wx.request({
url: baseUrl + url, //请求地址
data: data, //自定义参数
method: method || 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
header: {
sessionId: Store.getItem("sessionId")
},
success: function (result) {
// 日志上传不需要处理结果
if (mode == 'log') return;
let res = result.data;
// 登陆失效拦截,根据项目需要添加自己的配置
if (res.code == 404) {
//登陆失效的回调
Store.clear("sessionId");
// wx.reLaunch({
// url: '/pages/index/index'
// })
// 404后拉取登陆后再做一次
login().then((resultLogin) => {
wx.request({
url: baseUrl + url, //请求地址
data: data, //自定义参数
method: method || 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
header: {
sessionId: Store.getItem("sessionId")
},
success: function (result) {
// 日志上传不需要处理结果
if (mode == 'log') return;
let res = result.data;
if (res.code === 200) {
if (loading) {
wx.hideLoading();
}
resolve(res.content);
} else {
// 有些特殊状况不需要toast 需要弹窗
if (toast) {
wx.showToast({
title: res.errMsg || errMsg,
icon: 'none'
})
} else {
wx.hideLoading();
}
// 返回错误信息
reject(res);
}
}
});
})
return;
}
// 内部统一的成功code拦截码
if (res.code === 200) {
if (loading) {
wx.hideLoading();
}
resolve(res.content);
} else {
// 有些特殊状况不需要toast 需要弹窗
if (toast) {
wx.showToast({
title: res.errMsg || errMsg,
icon: 'none'
})
} else {
wx.hideLoading();
}
// 返回错误信息
reject(res);
}
},
fail: function (e = {
CODE: -1,
msg: errMsg,
errMsg
}) {
let msg = e.errMsg;
if (e.errMsg == 'request:fail timeout') {
msg = '服务请求超时,请稍后重试'
}
wx.showToast({
title: msg,
icon: 'none'
});
reject(e)
},
complete: function () {
// complete
}
})
})
});
return promise;
}
module.exports = {
fetch
}
// https://github.com/webx32/WxMock
let Mock = require('../utils/mockSdk.js');
let config = require('../config')
let env = config.MOCKAPI;
Mock.mock(env + '/eatClassifyService', {
data: {
resultCode: 0,
content: function () {
return Mock.Random.ip();
}
}
});
let app = getApp();
Page({
data: {
barHeight: app.globalData.barHeight,
navbarData: {
showCapsule: 0, //是否显示左上角图标 1表示显示 0表示不显示
title: '微信授权' //导航栏 中间的标题
},
loginData: null,
authorized: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
parentMemberCode: "",
},
onLoad(options) {},
onReady() {
app.store.clear("sessionId");
let _this = this;
wx.login({
success: function (res) {
_this.data.loginData = res;
}
});
},
bindGetUserInfo(e) {
wx.showLoading();
this.getUserInfo(e.detail);
},
getUserInfo(e) {
let _this = this;
app.globalData.userInfo = e.userInfo;
// console.log("loginData:",_this.data.loginData);
app.post({
url: app.api.register,
sid: false,
data: {
encryptedData: e.encryptedData,
iv: e.iv,
code: _this.data.loginData.code,
parentMemberCode: _this.data.parentMemberCode,
}
}).then((res2) => {
app.store.setItem('sessionId', res2.sessionId);
_this.setData({
authorized: true
})
_this.toIndex();
}).catch((err) => {
console.log("@authorize || err:", err);
})
},
toIndex() {
console.log("@authorize || toIndex ");
setTimeout(() => {
app.router.push({
path: "index",
query: {},
openType: "redirect"
})
wx.hideLoading();
}, 2000);
}
})
{
"usingComponents": {
"navbar": "../../component/navbar/index"
},
"navigationStyle": "custom"
}
@import '../../assets/scss/mixins';
.page {
position: relative;
overflow: hidden;
.bgc {
// background-color: transparent;
// background-color: black;
background-color: #fafafc;
}
.main {
position: relative;
.top-space {
height: 60px;
}
.login {
position: relative;
width: 650px;
margin: 0 auto;
text-align: center;
&-logo {
width: 140px;
height: 140px;
}
&-name {
margin-top: 32px;
font-size: 32px;
color: #333333;
}
&-line {
margin-top: 70px;
width: 650px;
height: 2px;
background-color: #eaeaec;
}
&-title {
margin-top: 40px;
font-size: 32px;
text-align: left;
color: #333333;
}
&-tips {
margin-top: 28px;
font-size: 26px;
text-align: left;
color: #666666;
}
&-btn {
margin-top: 102px;
width: 650px;
height: 90px;
line-height: 90px;
border-radius: 8px;
background-color: #00c200;
font-size: 32px;
color: #ffffff;
}
}
}
}
<navbar navbar-data='{{navbarData}}'></navbar>
<view style='height: {{barHeight}}px'></view>
<view class="page-authorize page">
<view class="app__bgc bgc"></view>
<view class="app__bg bg"></view>
<!-- <view class="app__top-shadow"></view> -->
<view class="app__content main">
<view class="top-space"></view>
<view class="login">
<image class="login-logo" src="../../image/logo.png" mode="aspectFit" />
<view class="login-name">美赞臣</view>
<view class="login-line"></view>
<view class="login-title">完整体验小程序功能,需要您的微信授权哦</view>
<view class="login-tips">· 获取您的公开信息(昵称、头像等)</view>
<button type="default" class="login-btn" wx:if="{{!authorized}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">
确认授权
</button>
</view>
</view>
</view>
let app = getApp();
Page({
data: {
barHeight: app.globalData.barHeight,
navbarData: {
showCapsule: 0, //是否显示左上角图标 1表示显示 0表示不显示
title: '微信授权' //导航栏 中间的标题
},
loginData: null,
authorized: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
parentMemberCode: "",
},
onLoad(options) {},
onReady() {
app.store.clear("sessionId");
let _this = this;
wx.login({
success: function (res) {
_this.data.loginData = res;
}
});
},
bindGetUserInfo(e) {
wx.showLoading();
this.getUserInfo(e.detail);
},
getUserInfo(e) {
let _this = this;
app.globalData.userInfo = e.userInfo;
// console.log("loginData:",_this.data.loginData);
app.post({
url: app.api.register,
sid: false,
data: {
encryptedData: e.encryptedData,
iv: e.iv,
code: _this.data.loginData.code,
parentMemberCode: _this.data.parentMemberCode,
}
}).then((res2) => {
app.store.setItem('sessionId', res2.sessionId);
_this.setData({
authorized: true
})
_this.toIndex();
}).catch((err) => {
console.log("@authorize || err:", err);
})
},
toIndex() {
console.log("@authorize || toIndex ");
setTimeout(() => {
app.router.push({
path: "index",
query: {},
openType: "redirect"
})
wx.hideLoading();
}, 2000);
}
})
{
"navigationStyle": "custom"
}
@import '../../assets/scss/mixins';
@import '../../assets/scss/utils';
.page {
position: relative;
overflow: hidden;
.bgc {}
.bg {
@include app-width;
image {
@include app-width;
}
}
// 右下角图标背景内容补充
.br-wrap {
$brWidth: 168px;
$brHeight: 172px;
width: $brWidth;
height: $brHeight;
position: fixed;
bottom: 0;
right: 0;
background-color: transparent;
image {
width: $brWidth;
height: $brHeight;
}
}
.main {
position: relative;
min-height: 1206px;
.content {
position: relative;
}
.login-wrap {
padding-top: 886px;
.terms-wrap {
margin-top: 24px;
display: flex;
justify-content: center;
margin-bottom: 16px;
font-size: 28px;
color: #333333;
.terms {
text-align: center;
padding: 0 12px;
.t1 {
color: #4bc2ed;
display: inline-block;
}
}
}
.login-btn {
width: 340px;
height: 80px;
line-height: 80px;
border-radius: 40px;
border: solid 3px #4bc2ed;
margin: 0 auto;
font-size: 36px;
color: #4bc2ed;
text-align: center;
background-color: transparent;
}
.gray {
color: #8f8f8f;
border-color: #8f8f8f;
}
}
}
}
.space1 {
height: 116px;
}
.terms-cont {
width: 690px;
height: 1000px;
position: relative;
background-color: #fff;
.cont {
position: relative;
width: 690px;
height: 900px;
overflow: auto;
padding: 28px;
@extend .bb;
font-size: 24px;
.tit {
text-align: center;
font-size: 32px;
font-weight: bold;
}
.desc {}
.t1 {
color: #4bc2ed;
display: inline-block;
margin-top: 16px;
}
}
.btn {
position: absolute;
bottom: 0;
left: 0;
right: 0;
}
}
<view class="page-authorize page">
<view class="app__bgc bgc"></view>
<view class="app__bg bg"></view>
<!-- <view class="app__top-shadow"></view> -->
<view class="app__content main">
<view class="top-space"></view>
<view class="login">
<image class="login-logo" src="../../image/logo.png" mode="aspectFit" />
<view class="login-name">小程序</view>
<view class="login-line"></view>
<view class="login-title">完整体验小程序功能,需要您的微信授权哦</view>
<view class="login-tips">· 获取您的公开信息(昵称、头像等)</view>
<button type="default" class="login-btn" wx:if="{{!authorized}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">
确认授权
</button>
</view>
</view>
</view>
import {
getBindtapData
} from '../../utils/util';
let app = getApp();
Page({
data: {
authorizeVisible: false,
total: 0,
page: 1,
size: 10,
productList: [], // 产品列表
indexInfo: {},
userInfo: {},
},
onShareAppMessage() {},
showAuth() {
this.setData({
authorizeVisible: true
})
},
onLoad(options) {},
/**
* 基础方法
* 授权完毕重拉数据用
*/
initData() {
},
/**
* 到达底部
* 做加载更多操作
*/
onReachBottom() {
if (this.data.dataList.length < this.data.total) {
this.setData({
page: this.data.page + 1
});
this.queryDataList();
}
},
// 重置页面列表 点击搜索条件时需要
resetPage() {
this.setData({
page: 1,
dataList: []
})
},
/**
* 请求DataList
*/
queryDataList() {
return;
return new Promise((resolve, reject) => {
app.post({
sid: false,
url: app.api.dataList,
data: {
page: this.data.page,
size: this.data.size,
},
}).then((result) => {
let dataList = result.list;
dataList = this.data.dataList.concat(dataList);
this.setData({
dataList: dataList,
total: result.total
})
resolve();
})
});
},
/**
* 隐藏蒙层
*/
hideMask() {
this.setData({
productDetailVisible: false,
authorizeVisible: false,
})
},
/**
* 子组件事件
* @param {*} evt
*/
evtcomp(evt) {
let {
name,
data
} = evt.detail;
switch (name) {
// 隐藏蒙层
case "_evt_hide_mask":
this.hideMask();
break;
/**
* 重拉数据已在
*/
case "_evt_auth_complete":
// this.initData();
this.hideMask();
break;
default:
break;
}
},
})
{
"navigationBarTitleText": ""
}
@import '../../assets/scss/mixins';
@import '../../assets/scss/utils';
.page {
.bgc {}
.bg {}
.main {
.top-space {
height: 0px;
}
.content {
position: relative;
}
}
}
<view class="page">
<view class="app__bgc bgc"></view>
<view class="app__bg bg"></view>
<view class="app__content main">
<view class="top-space"></view>
<view class="content"></view>
</view>
</view>
let app = getApp();
Page({
data: {},
onLoad(options) {
}
})
{
"navigationBarTitleText": "首页"
}
@import '../../assets/scss/mixins';
@import '../../assets/scss/utils';
.page {
.bgc {}
.bg {}
.main {
.top-space {
height: 0px;
}
.content {
position: relative;
}
}
}
<view class="page">
<view class="app__bgc bgc"></view>
<view class="app__bg bg"></view>
<!-- <view class="app__top-shadow"></view> -->
<view class="app__content main">
<view class="top-space"></view>
<view class="content">index</view>
</view>
</view>
let app = getApp();
Page({
data: {},
onLoad(options) {}
})
{
"navigationBarTitleText": "demo"
}
@import '../../assets/scss/mixins';
@import '../../assets/scss/utils';
.page {
.bgc {}
.bg {}
.main {
.top-space {
height: 0px;
}
.content {
position: relative;
}
}
}
<view class="page">
<view class="app__bgc bgc"></view>
<view class="app__bg bg"></view>
<!-- <view class="app__top-shadow"></view> -->
<view class="app__content main">
<view class="top-space"></view>
<view class="content"></view>
</view>
</view>
import {
getBindtapData
} from '../../utils/util';
// 二维码
import QR from '../../utils/qrcode'
// 海报
import Poster from '../../plugin/poster/poster/poster';
let app = getApp();
Page({
data: {
authorizeVisible: false,
},
onShareAppMessage() {},
showAuth() {
this.setData({
authorizeVisible: true
})
},
onLoad(options) {},
initData() {
this.initPoster();
this.initQrcode();
},
// 创建海报
initPoster() {
// 获取海报数据
let posterData = this.getPosterConfig();
// 绘制设置海报
this.onCreatePoster(posterData);
},
// 创建二维码
initQrcode() {
createQrCode('wxapp-qrcode', 'qrcode', 300, 300)
},
// ---- START 海报合成 ----
// 详情见: https://github.com/jasondu/wxa-plugin-canvas
// 海报合成成功
onPosterSuccess(e) {
wx.hideLoading();
const {
detail
} = e;
this.setData({
imageUrl: detail
})
},
// 合成失败
onPosterFail(err) {
wx.hideLoading();
console.error(err);
},
// 异步生成海报
onCreatePoster(posterConfig) {
this.setData({
posterConfig: posterConfig
}, () => {
Poster.create(true); // 入参:true为抹掉重新生成
});
},
// 获取海报数据
getPosterConfig() {
let blocks = [{
x: 0,
y: 0,
width: 690,
height: 900,
backgroundColor: "#ffffff",
borderRadius: 10,
}];
let images = [];
let lines = [];
let texts = [{
x: 690 / 2,
y: 192,
width: 690,
fontSize: 36,
color: "#3680EB",
textAlign: "center",
zIndex: 11,
text: "nickname",
}];
let posterData = {
width: 690,
height: 900,
debug: false,
blocks: blocks,
images: images,
lines: lines,
texts: texts,
}
return posterData;
},
// ---- END 海报合成 ----
/**
---------------- 分界线 ----------------
*/
// ---- START 二维码生成 ----
// 详情见: https://github.com/demi520/wxapp-qrcode
// 创建二维码
createQrCode(content, canvasId, cavW, cavH) {
//调用插件中的draw方法,绘制二维码图片
QR.api.draw(content, canvasId, cavW, cavH);
this.canvasToTempImage(canvasId);
},
//获取临时缓存图片路径,存入data中
canvasToTempImage(canvasId) {
let that = this;
wx.canvasToTempFilePath({
canvasId, // 这里canvasId即之前创建的canvas-id
success: function (res) {
let tempFilePath = res.tempFilePath;
console.log(tempFilePath);
that.setData({ // 如果采用mpvue,即 this.imagePath = tempFilePath
qrImagePath: tempFilePath,
});
},
fail: function (res) {
console.log(res);
}
});
},
//适配不同屏幕大小的canvas
setCanvasSize(sz) {
var size = {};
try {
var res = wx.getSystemInfoSync();
var scale = 750 / sz; //不同屏幕下canvas的适配比例;设计稿是750宽
var width = res.windowWidth / scale;
var height = width; //canvas画布为正方形
size.w = width;
size.h = height;
} catch (e) {
// Do something when catch error
console.log("获取设备信息失败" + e);
}
return size;
},
// ---- END 二维码生成 ----
})
{
"navigationBarTitleText": "海报合成/二维码示例",
"usingComponents": {
"poster": "/plugin/poster/poster/index"
}
}
@import '../../assets/scss/mixins';
@import '../../assets/scss/utils';
.page {
.bgc {}
.bg {}
.main {
.top-space {
height: 0px;
}
.content {
position: relative;
}
}
}
<poster id="poster" hide-loading="{{true}}" preload="{{false}}" config="{{posterConfig}}" bind:success="onPosterSuccess" bind:fail="onPosterFail"></poster>
<canvas canvas-id="qrcode" style="width: 200rpx;height: 200rpx;background:#0f0f0f;" />
<view class="page">
<view class="app__bgc bgc"></view>
<view class="app__bg bg"></view>
<view class="app__content main">
<view class="top-space"></view>
<view class="content">poster</view>
</view>
</view>
let app = getApp();
Page({
data: {
isShow: false, // 控制组件显示隐藏
url: ''
},
onLoad: function (options = {}) {
let url = options.url;
if (url) {
this.setData({
url: url,
isShow: true
})
} else {
wx.showToast({
title: '未找到页面地址',
title: 'none',
});
}
}
})
{
"navigationBarTitleText": "webview"
}
<view class="loading-wrap">
<view class="loading">
<view class="icon"></view>
<view class="text">加载中...</view>
</view>
</view>
<web-view wx:if="{{isShow}}" src="{{url}}" bindload="loadSucc"/>
const main = {
/**
* 渲染块
* @param {Object} params
*/
drawBlock({ text, width = 0, height, x, y, paddingLeft = 0, paddingRight = 0, borderWidth, backgroundColor, borderColor, borderRadius = 0, opacity = 1 }) {
// 判断是否块内有文字
let blockWidth = 0; // 块的宽度
let textX = 0;
let textY = 0;
if (typeof text !== 'undefined') {
// 如果有文字并且块的宽度小于文字宽度,块的宽度为 文字的宽度 + 内边距
const textWidth = this._getTextWidth(typeof text.text === 'string' ? text : text.text);
blockWidth = textWidth > width ? textWidth : width;
blockWidth += paddingLeft + paddingLeft;
const { textAlign = 'left', text: textCon } = text;
textY = height / 2 + y; // 文字的y轴坐标在块中线
if (textAlign === 'left') {
// 如果是右对齐,那x轴在块的最左边
textX = x + paddingLeft;
} else if (textAlign === 'center') {
textX = blockWidth / 2 + x;
} else {
textX = x + blockWidth - paddingRight;
}
} else {
blockWidth = width;
}
if (backgroundColor) {
// 画面
this.ctx.save();
this.ctx.setGlobalAlpha(opacity);
this.ctx.setFillStyle(backgroundColor);
if (borderRadius > 0) {
// 画圆角矩形
this._drawRadiusRect(x, y, blockWidth, height, borderRadius);
this.ctx.fill();
} else {
this.ctx.fillRect(this.toPx(x), this.toPx(y), this.toPx(blockWidth), this.toPx(height));
}
this.ctx.restore();
}
if (borderWidth) {
// 画线
this.ctx.save();
this.ctx.setGlobalAlpha(opacity);
this.ctx.setStrokeStyle(borderColor);
this.ctx.setLineWidth(this.toPx(borderWidth));
if (borderRadius > 0) {
// 画圆角矩形边框
this._drawRadiusRect(x, y, blockWidth, height, borderRadius);
this.ctx.stroke();
} else {
this.ctx.strokeRect(this.toPx(x), this.toPx(y), this.toPx(blockWidth), this.toPx(height));
}
this.ctx.restore();
}
if (text) {
this.drawText(Object.assign(text, { x: textX, y: textY }))
}
},
/**
* 渲染文字
* @param {Object} params
*/
drawText(params) {
const { x, y, fontSize, color, baseLine, textAlign, text, opacity = 1, width, lineNum, lineHeight } = params;
if (Object.prototype.toString.call(text) === '[object Array]') {
let preText = { x, y, baseLine };
text.forEach(item => {
preText.x += item.marginLeft || 0;
const textWidth = this._drawSingleText(Object.assign(item, {
...preText,
}));
preText.x += textWidth + (item.marginRight || 0); // 下一段字的x轴为上一段字x + 上一段字宽度
})
} else {
this._drawSingleText(params);
}
},
/**
* 渲染图片
*/
drawImage(data) {
const { imgPath, x, y, w, h, sx, sy, sw, sh, borderRadius = 0, borderWidth = 0, borderColor } = data;
this.ctx.save();
if (borderRadius > 0) {
this._drawRadiusRect(x, y, w, h, borderRadius);
this.ctx.strokeStyle = 'rgba(255,255,255,0)';
this.ctx.stroke();
this.ctx.clip();
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));
if (borderWidth > 0) {
this.ctx.setStrokeStyle(borderColor);
this.ctx.setLineWidth(this.toPx(borderWidth));
this.ctx.stroke();
}
} else {
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));
}
this.ctx.restore();
},
/**
* 渲染线
* @param {*} param0
*/
drawLine({ startX, startY, endX, endY, color, width }) {
this.ctx.save();
this.ctx.beginPath();
this.ctx.setStrokeStyle(color);
this.ctx.setLineWidth(this.toPx(width));
this.ctx.moveTo(this.toPx(startX), this.toPx(startY));
this.ctx.lineTo(this.toPx(endX), this.toPx(endY));
this.ctx.stroke();
this.ctx.closePath();
this.ctx.restore();
},
downloadResource(images = []) {
const drawList = [];
this.drawArr = [];
images.forEach((image, index) => drawList.push(this._downloadImageAndInfo(image, index)));
return Promise.all(drawList);
},
initCanvas(w, h, debug) {
return new Promise((resolve) => {
this.setData({
pxWidth: this.toPx(w),
pxHeight: this.toPx(h),
debug,
}, resolve);
});
}
}
const handle = {
/**
* 画圆角矩形
*/
_drawRadiusRect(x, y, w, h, r) {
const br = r / 2;
this.ctx.beginPath();
this.ctx.moveTo(this.toPx(x + br), this.toPx(y)); // 移动到左上角的点
this.ctx.lineTo(this.toPx(x + w - br), this.toPx(y));
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))
this.ctx.lineTo(this.toPx(x + w), this.toPx(y + h - br));
this.ctx.arc(this.toPx(x + w - br), this.toPx(y + h - br), this.toPx(br), 0, 2 * Math.PI * (1 / 4))
this.ctx.lineTo(this.toPx(x + br), this.toPx(y + h));
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))
this.ctx.lineTo(this.toPx(x), this.toPx(y + br));
this.ctx.arc(this.toPx(x + br), this.toPx(y + br), this.toPx(br), 2 * Math.PI * (2 / 4), 2 * Math.PI * (3 / 4))
},
/**
* 计算文本长度
* @param {Array|Object}} text 数组 或者 对象
*/
_getTextWidth(text) {
let texts = [];
if (Object.prototype.toString.call(text) === '[object Object]') {
texts.push(text);
} else {
texts = text;
}
let width = 0;
texts.forEach(({ fontSize, text, marginLeft = 0, marginRight = 0 }) => {
this.ctx.setFontSize(this.toPx(fontSize));
width += this.ctx.measureText(text).width + marginLeft + marginRight;
})
return this.toRpx(width);
},
/**
* 渲染一段文字
*/
_drawSingleText({ x, y, fontSize, color, baseLine, textAlign = 'left', text, opacity = 1, textDecoration = 'none',
width, lineNum = 1, lineHeight = 0, fontWeight = 'normal', fontStyle = 'normal', fontFamily = "sans-serif"}) {
this.ctx.save();
this.ctx.beginPath();
this.ctx.font = fontStyle + " " + fontWeight + " " + this.toPx(fontSize, true) + "px " + fontFamily
this.ctx.setGlobalAlpha(opacity);
// this.ctx.setFontSize(this.toPx(fontSize));
this.ctx.setFillStyle(color);
this.ctx.setTextBaseline(baseLine);
this.ctx.setTextAlign(textAlign);
let textWidth = this.toRpx(this.ctx.measureText(text).width);
const textArr = [];
if (textWidth > width) {
// 文本宽度 大于 渲染宽度
let fillText = '';
let line = 1;
for (let i = 0; i <= text.length - 1 ; i++) { // 将文字转为数组,一行文字一个元素
fillText = fillText + text[i];
if (this.toRpx(this.ctx.measureText(fillText).width) >= width) {
if (line === lineNum) {
if (i !== text.length - 1) {
fillText = fillText.substring(0, fillText.length - 1) + '...';
}
}
if(line <= lineNum) {
textArr.push(fillText);
}
fillText = '';
line++;
} else {
if(line <= lineNum) {
if(i === text.length -1){
textArr.push(fillText);
}
}
}
}
textWidth = width;
} else {
textArr.push(text);
}
textArr.forEach((item, index) => {
this.ctx.fillText(item, this.toPx(x), this.toPx(y + (lineHeight || fontSize) * index));
})
this.ctx.restore();
// textDecoration
if (textDecoration !== 'none') {
let lineY = y;
if (textDecoration === 'line-through') {
// 目前只支持贯穿线
lineY = y;
}
this.ctx.save();
this.ctx.moveTo(this.toPx(x), this.toPx(lineY));
this.ctx.lineTo(this.toPx(x) + this.toPx(textWidth), this.toPx(lineY));
this.ctx.setStrokeStyle(color);
this.ctx.stroke();
this.ctx.restore();
}
return textWidth;
},
}
const helper = {
/**
* 下载图片并获取图片信息
*/
_downloadImageAndInfo(image, index) {
return new Promise((resolve, reject) => {
const { x, y, url, zIndex } = image;
const imageUrl = url;
// 下载图片
this._downImage(imageUrl, index)
// 获取图片信息
.then(imgPath => this._getImageInfo(imgPath, index))
.then(({ imgPath, imgInfo }) => {
// 根据画布的宽高计算出图片绘制的大小,这里会保证图片绘制不变形
let sx;
let sy;
const borderRadius = image.borderRadius || 0;
const setWidth = image.width;
const setHeight = image.height;
const width = this.toRpx(imgInfo.width);
const height = this.toRpx(imgInfo.height);
if (width / height <= setWidth / setHeight) {
sx = 0;
sy = (height - ((width / setWidth) * setHeight)) / 2;
} else {
sy = 0;
sx = (width - ((height / setHeight) * setWidth)) / 2;
}
this.drawArr.push({
type: 'image',
borderRadius,
borderWidth: image.borderWidth,
borderColor: image.borderColor,
zIndex: typeof zIndex !== 'undefined' ? zIndex : index,
imgPath,
sx,
sy,
sw: (width - (sx * 2)),
sh: (height - (sy * 2)),
x,
y,
w: setWidth,
h: setHeight,
});
resolve();
})
.catch(err => reject(err));
});
},
/**
* 下载图片资源
* @param {*} imageUrl
*/
_downImage(imageUrl) {
return new Promise((resolve, reject) => {
if (/^http/.test(imageUrl) && !new RegExp(wx.env.USER_DATA_PATH).test(imageUrl)) {
wx.downloadFile({
url: this._mapHttpToHttps(imageUrl),
success: (res) => {
if (res.statusCode === 200) {
resolve(res.tempFilePath);
} else {
reject(res.errMsg);
}
},
fail(err) {
reject(err);
},
});
} else {
// 支持本地地址
resolve(imageUrl);
}
});
},
/**
* 获取图片信息
* @param {*} imgPath
* @param {*} index
*/
_getImageInfo(imgPath, index) {
return new Promise((resolve, reject) => {
wx.getImageInfo({
src: imgPath,
success(res) {
resolve({ imgPath, imgInfo: res, index });
},
fail(err) {
reject(err);
},
});
});
},
toPx(rpx, int) {
if (int) {
return parseInt(rpx * this.factor);
}
return rpx * this.factor;
},
toRpx(px, int) {
if (int) {
return parseInt(px / this.factor);
}
return px / this.factor;
},
/**
* 将http转为https
* @param {String}} rawUrl 图片资源url
*/
_mapHttpToHttps(rawUrl) {
if (rawUrl.indexOf(':') < 0) {
return rawUrl;
}
const urlComponent = rawUrl.split(':');
if (urlComponent.length === 2) {
if (urlComponent[0] === 'http') {
urlComponent[0] = 'https';
return `${urlComponent[0]}:${urlComponent[1]}`;
}
}
return rawUrl;
},
}
Component({
properties: {
},
created() {
const sysInfo = wx.getSystemInfoSync();
const screenWidth = sysInfo.screenWidth;
this.factor = screenWidth / 750;
},
methods: Object.assign({
/**
* 计算画布的高度
* @param {*} config
*/
getHeight(config) {
const getTextHeight = (text) => {
let fontHeight = text.lineHeight || text.fontSize;
let height = 0;
if (text.baseLine === 'top') {
height = fontHeight;
} else if (text.baseLine === 'middle') {
height = fontHeight / 2;
} else {
height = 0;
}
return height;
}
const heightArr = [];
(config.blocks || []).forEach((item) => {
heightArr.push(item.y + item.height);
});
(config.texts || []).forEach((item) => {
let height;
if (Object.prototype.toString.call(item.text) === '[object Array]') {
item.text.forEach((i) => {
height = getTextHeight({...i, baseLine: item.baseLine});
heightArr.push(item.y + height);
});
} else {
height = getTextHeight(item);
heightArr.push(item.y + height);
}
});
(config.images || []).forEach((item) => {
heightArr.push(item.y + item.height);
});
(config.lines || []).forEach((item) => {
heightArr.push(item.startY);
heightArr.push(item.endY);
});
const sortRes = heightArr.sort((a, b) => b - a);
let canvasHeight = 0;
if (sortRes.length > 0) {
canvasHeight = sortRes[0];
}
if (config.height < canvasHeight || !config.height) {
return canvasHeight;
} else {
return config.height;
}
},
create(config) {
this.ctx = wx.createCanvasContext('canvasid', this);
const height = this.getHeight(config);
this.initCanvas(config.width, height, config.debug)
.then(() => {
// 设置画布底色
if (config.backgroundColor) {
this.ctx.save();
this.ctx.setFillStyle(config.backgroundColor);
this.ctx.fillRect(0, 0, this.toPx(config.width), this.toPx(height));
this.ctx.restore();
}
const { texts = [], images = [], blocks = [], lines = [] } = config;
const queue = this.drawArr
.concat(texts.map((item) => {
item.type = 'text';
item.zIndex = item.zIndex || 0;
return item;
}))
.concat(blocks.map((item) => {
item.type = 'block';
item.zIndex = item.zIndex || 0;
return item;
}))
.concat(lines.map((item) => {
item.type = 'line';
item.zIndex = item.zIndex || 0;
return item;
}));
// 按照顺序排序
queue.sort((a, b) => a.zIndex - b.zIndex);
queue.forEach((item) => {
if (item.type === 'image') {
this.drawImage(item)
} else if (item.type === 'text') {
this.drawText(item)
} else if (item.type === 'block') {
this.drawBlock(item)
} else if (item.type === 'line') {
this.drawLine(item)
}
});
const res = wx.getSystemInfoSync();
const platform = res.platform;
let time = 0;
if (platform === 'android') {
// 在安卓平台,经测试发现如果海报过于复杂在转换时需要做延时,要不然样式会错乱
time = 300;
}
this.ctx.draw(false, () => {
setTimeout(() => {
wx.canvasToTempFilePath({
canvasId: 'canvasid',
success: (res) => {
this.triggerEvent('success', res.tempFilePath);
},
fail: (err) => {
this.triggerEvent('fail', err);
},
}, this);
}, time);
});
})
.catch((err) => {
wx.showToast({ icon: 'none', title: err.errMsg || '生成失败' });
console.error(err);
});
},
}, main, handle, helper),
});
{
"component": true
}
\ No newline at end of file
<!--index.wxml-->
<view class="container">
<canvas canvas-id='canvasid' class="canvas {{debug ? 'debug' : 'pro'}}" style='width: {{pxWidth}}px; height: {{pxHeight}}px;'></canvas>
</view>
.canvas {
width: 750rpx;
height: 750rpx;
}
.canvas.pro {
position: absolute;
bottom: 0;
left: 0;
transform: translate3d(-9999rpx, 0, 0);
}
.canvas.debug {
position: absolute;
bottom: 0;
left: 0;
border: 1rpx solid #ccc;
}
\ No newline at end of file
Component({
properties: {
config: {
type: Object,
value: {},
},
preload: { // 是否预下载图片资源
type: Boolean,
value: false,
},
hideLoading: { // 是否隐藏loading
type: Boolean,
value: false,
}
},
ready() {
if (this.data.preload) {
const poster = this.selectComponent('#poster');
this.downloadStatus = 'doing';
poster.downloadResource(this.data.config.images).then(() => {
this.downloadStatus = 'success';
this.trigger('downloadSuccess');
}).catch((e) => {
this.downloadStatus = 'fail';
this.trigger('downloadFail', e);
});
}
},
methods: {
trigger(event, data) {
if (this.listener && typeof this.listener[event] === 'function') {
this.listener[event](data);
}
},
once(event, fun) {
if (typeof this.listener === 'undefined') {
this.listener = {};
}
this.listener[event] = fun;
},
downloadResource(reset) {
return new Promise((resolve, reject) => {
if (reset) {
this.downloadStatus = null;
}
const poster = this.selectComponent('#poster');
if (this.downloadStatus && this.downloadStatus !== 'fail') {
if (this.downloadStatus === 'success') {
resolve();
} else {
this.once('downloadSuccess', () => resolve());
this.once('downloadFail', (e) => reject(e));
}
} else {
poster.downloadResource(this.data.config.images)
.then(() => {
this.downloadStatus = 'success';
resolve();
})
.catch((e) => reject(e));
}
})
},
onCreate(reset = false) {
!this.data.hideLoading && wx.showLoading({ mask: true, title: '生成中' });
return this.downloadResource(typeof reset === 'boolean' && reset).then(() => {
!this.data.hideLoading && wx.hideLoading();
const poster = this.selectComponent('#poster');
poster.create(this.data.config);
})
.catch((err) => {
!this.data.hideLoading && wx.hideLoading();
wx.showToast({ icon: 'none', title: err.errMsg || '生成失败' });
console.error(err);
this.triggerEvent('fail', err);
})
},
onCreateSuccess(e) {
const { detail } = e;
this.triggerEvent('success', detail);
},
onCreateFail(err) {
console.error(err);
this.triggerEvent('fail', err);
}
}
})
\ No newline at end of file
{
"component": true,
"usingComponents": {
"we-canvas": "../index/index"
}
}
\ No newline at end of file
<view bindtap='onCreate'>
<slot/>
</view>
<we-canvas id="poster" bind:success="onCreateSuccess" bind:fail="onCreateFail"/>
\ No newline at end of file
const defaultOptions = {
selector: '#poster'
};
function Poster(options = {}) {
options = {
...defaultOptions,
...options,
};
const pages = getCurrentPages();
const ctx = pages[pages.length - 1];
const poster = ctx.selectComponent(options.selector);
delete options.selector;
return poster;
};
Poster.create = (reset = false) => {
const poster = Poster();
if (!poster) {
console.error('请设置组件的id="poster"!!!');
} else {
return Poster().onCreate(reset);
}
}
export default Poster;
\ No newline at end of file
const routerPath = {
index: '/pages/index/index',
authorize: '/pages/authorize/authorize', // 授权
example: '/pages/example/example',
more: '/pages/more/more',
}
function parse(data) {
let tempArr = [];
for (let key in data) {
tempArr.push(key + '=' + encodeURIComponent(data[key]));
}
return tempArr.join('&');
}
function push(path, option = {}) {
if (typeof path == 'string') {
option.path = path; //兼容无参数路径
} else {
option = path;
}
// console.log("option:", option);
// 配置key值找到对应path
let url = routerPath[option.path] || routerPath['index'];
// console.log("url:", url);
// 读取传入的配置参数
let {
query = {}, openType = 'navigate', duration = 0
} = option;
// json 转换为 字符串拼接参数
let params = parse(query)
// console.log("params:", params);
if (params) {
url = url + '?' + params;
}
// 是否需要延时跳转
duration ? setTimeout(() => {
to(openType, url);
}, duration) : to(openType, url);
}
function to(openType, url) {
let obj = {
url
};
if (openType == 'redirect') {
wx.redirectTo(obj);
} else if (openType == 'reLaunch') {
wx.reLaunch(obj);
} else if (openType == 'switchTab') {
wx.switchTab(obj);
} else if (openType == 'back') {
wx.navigateBack({
delta: 1
});
} else {
wx.navigateTo(obj);
}
}
module.exports = {
parse,
push,
to
}
import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({
mixins: [safeArea()],
props: {
show: Boolean,
title: String,
cancelText: String,
zIndex: {
type: Number,
value: 100
},
actions: {
type: Array,
value: []
},
overlay: {
type: Boolean,
value: true
},
closeOnClickOverlay: {
type: Boolean,
value: true
}
},
methods: {
onSelect(event) {
const { index } = event.currentTarget.dataset;
const item = this.data.actions[index];
if (item && !item.disabled && !item.loading) {
this.$emit('select', item);
}
},
onCancel() {
this.$emit('cancel');
},
onClose() {
this.$emit('close');
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-popup": "../popup/index",
"van-loading": "../loading/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<van-popup
show="{{ show }}"
position="bottom"
z-index="{{ zIndex }}"
overlay="{{ overlay }}"
custom-class="van-action-sheet"
safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:close="onClose"
>
<view wx:if="{{ title }}" class="van-hairline--bottom van-action-sheet__header">
{{ title }}
<van-icon
name="close"
custom-class="van-action-sheet__close"
bind:click="onClose"
/>
</view>
<view wx:if="{{ actions && actions.length }}">
<!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
<button
wx:for="{{ actions }}"
wx:key="index"
open-type="{{ item.openType }}"
class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} van-hairline--top {{ item.className || '' }}"
hover-class="van-action-sheet__item--hover"
data-index="{{ index }}"
bind:tap="onSelect"
>
<block wx:if="{{ !item.loading }}">
{{ item.name }}
<text wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</text>
</block>
<van-loading wx:else size="20px" />
</button>
</view>
<slot />
<view
wx:if="{{ cancelText }}"
class="van-action-sheet__cancel"
hover-class="van-action-sheet__cancel--hover"
hover-stay-time="70"
bind:tap="onCancel"
>
{{ cancelText }}
</view>
</van-popup>
@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
import { VantComponent } from '../common/component';
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: {
title: String,
value: String,
loading: Boolean,
cancelButtonText: String,
confirmButtonText: String,
itemHeight: {
type: Number,
value: 44
},
visibleItemCount: {
type: Number,
value: 5
},
columnsNum: {
type: [String, Number],
value: 3
},
areaList: {
type: Object,
value: {}
}
},
data: {
columns: [{ values: [] }, { values: [] }, { values: [] }],
displayColumns: [{ values: [] }, { values: [] }, { values: [] }]
},
watch: {
value(value) {
this.code = value;
this.setValues();
},
areaList: 'setValues',
columnsNum(value) {
this.set({
displayColumns: this.data.columns.slice(0, +value)
});
}
},
methods: {
getPicker() {
if (this.picker == null) {
this.picker = this.selectComponent('.van-area__picker');
}
return this.picker;
},
onCancel(event) {
this.emit('cancel', event.detail);
},
onConfirm(event) {
this.emit('confirm', event.detail);
},
emit(type, detail) {
detail.values = detail.value;
delete detail.value;
this.$emit(type, detail);
},
onChange(event) {
const { index, picker, value } = event.detail;
this.code = value[index].code;
this.setValues().then(() => {
this.$emit('change', {
picker,
values: picker.getValues(),
index
});
});
},
getConfig(type) {
const { areaList } = this.data;
return (areaList && areaList[`${type}_list`]) || {};
},
getList(type, code) {
let result = [];
if (type !== 'province' && !code) {
return result;
}
const list = this.getConfig(type);
result = Object.keys(list).map(code => ({
code,
name: list[code]
}));
if (code) {
// oversea code
if (code[0] === '9' && type === 'city') {
code = '9';
}
result = result.filter(item => item.code.indexOf(code) === 0);
}
return result;
},
getIndex(type, code) {
let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
const list = this.getList(type, code.slice(0, compareNum - 2));
// oversea code
if (code[0] === '9' && type === 'province') {
compareNum = 1;
}
code = code.slice(0, compareNum);
for (let i = 0; i < list.length; i++) {
if (list[i].code.slice(0, compareNum) === code) {
return i;
}
}
return 0;
},
setValues() {
const county = this.getConfig('county');
let code = this.code || Object.keys(county)[0] || '';
const province = this.getList('province');
const city = this.getList('city', code.slice(0, 2));
const picker = this.getPicker();
if (!picker) {
return;
}
const stack = [];
stack.push(picker.setColumnValues(0, province, false));
stack.push(picker.setColumnValues(1, city, false));
if (city.length && code.slice(2, 4) === '00') {
;
[{ code }] = city;
}
stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
return Promise.all(stack)
.catch(() => { })
.then(() => picker.setIndexes([
this.getIndex('province', code),
this.getIndex('city', code),
this.getIndex('county', code)
]))
.catch(() => { });
},
getValues() {
const picker = this.getPicker();
return picker ? picker.getValues().filter(value => !!value) : [];
},
getDetail() {
const values = this.getValues();
const area = {
code: '',
country: '',
province: '',
city: '',
county: ''
};
if (!values.length) {
return area;
}
const names = values.map((item) => item.name);
area.code = values[values.length - 1].code;
if (area.code[0] === '9') {
area.country = names[1] || '';
area.province = names[2] || '';
}
else {
area.province = names[0] || '';
area.city = names[1] || '';
area.county = names[2] || '';
}
return area;
},
reset() {
this.code = '';
return this.setValues();
}
}
});
{
"component": true,
"usingComponents": {
"van-picker": "../picker/index"
}
}
<van-picker
class="van-area__picker"
active-class="active-class"
toolbar-class="toolbar-class"
column-class="column-class"
show-toolbar
value-key="name"
title="{{ title }}"
loading="{{ loading }}"
columns="{{ displayColumns }}"
item-height="{{ itemHeight }}"
visible-item-count="{{ visibleItemCount }}"
cancel-button-text="{{ cancelButtonText }}"
confirm-button-text="{{ confirmButtonText }}"
bind:change="onChange"
bind:confirm="onConfirm"
bind:cancel="onCancel"
/>
@import '../common/index.wxss';
\ No newline at end of file
import { VantComponent } from '../common/component';
import { isNumber } from '../common/utils';
VantComponent({
relation: {
name: 'badge',
type: 'descendant',
linked(target) {
this.badges.push(target);
this.setActive();
},
unlinked(target) {
this.badges = this.badges.filter(item => item !== target);
this.setActive();
}
},
props: {
active: {
type: Number,
value: 0
}
},
watch: {
active: 'setActive'
},
beforeCreate() {
this.badges = [];
this.currentActive = -1;
},
methods: {
setActive(badge) {
let { active } = this.data;
const { badges } = this;
if (badge && !isNumber(badge)) {
active = badges.indexOf(badge);
}
if (active === this.currentActive) {
return;
}
if (this.currentActive !== -1 && badges[this.currentActive]) {
this.$emit('change', active);
badges[this.currentActive].setActive(false);
}
if (badges[active]) {
badges[active].setActive(true);
this.currentActive = active;
}
}
}
});
<view class="van-badge-group van-hairline--top-bottom custom-class">
<slot />
</view>
@import '../common/index.wxss';.van-badge-group{width:85px}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
relation: {
type: 'ancestor',
name: 'badge-group'
},
props: {
info: null,
title: String
},
methods: {
onClick() {
const group = this.getRelationNodes('../badge-group/index')[0];
if (group) {
group.setActive(this);
}
},
setActive(active) {
this.set({ active });
}
}
});
{
"component": true,
"usingComponents": {
"van-info": "../info/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="{{ utils.bem('badge', { active }) }} van-hairline custom-class"
hover-class="van-badge--hover"
hover-stay-time="70"
bind:tap="onClick"
>
<view class="van-badge__text">
<van-info
wx:if="{{ info !== null }}"
info="{{ info }}"
custom-style="right: 4px"
/>
{{ title }}
</view>
</view>
@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
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
VantComponent({
mixins: [button, openType],
classes: ['hover-class', 'loading-class'],
props: {
plain: Boolean,
block: Boolean,
round: Boolean,
square: Boolean,
loading: Boolean,
hairline: Boolean,
disabled: Boolean,
loadingText: String,
type: {
type: String,
value: 'default'
},
size: {
type: String,
value: 'normal'
},
loadingSize: {
type: String,
value: '20px'
}
},
methods: {
onClick() {
if (!this.data.disabled && !this.data.loading) {
this.$emit('click');
}
}
}
});
{
"component": true,
"usingComponents": {
"van-loading": "../loading/index"
}
}
\ No newline at end of file
<wxs src="../wxs/utils.wxs" module="utils" />
<button
id="{{ id }}"
class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
open-type="{{ openType }}"
hover-class="van-button--active hover-class"
lang="{{ lang }}"
business-id="{{ businessId }}"
session-from="{{ sessionFrom }}"
send-message-title="{{ sendMessageTitle }}"
send-message-path="{{ sendMessagePath }}"
send-message-img="{{ sendMessageImg }}"
show-message-card="{{ showMessageCard }}"
app-parameter="{{ appParameter }}"
aria-label="{{ ariaLabel }}"
bindtap="onClick"
bindgetuserinfo="bindGetUserInfo"
bindcontact="bindContact"
bindgetphonenumber="bindGetPhoneNumber"
binderror="bindError"
bindlaunchapp="bindLaunchApp"
bindopensetting="bindOpenSetting"
>
<block wx:if="{{ loading }}">
<van-loading
custom-class="loading-class"
size="{{ loadingSize }}"
color="{{ type === 'default' ? '#c9c9c9' : '' }}"
/>
<view
wx:if="{{ loadingText }}"
class="van-button__loading-text"
>
{{ loadingText }}
</view>
</block>
<slot wx:else />
</button>
@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
import { link } from '../mixins/link';
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'num-class',
'desc-class',
'thumb-class',
'title-class',
'price-class',
'origin-price-class',
],
mixins: [link],
props: {
tag: String,
num: String,
desc: String,
thumb: String,
title: String,
price: String,
centered: Boolean,
lazyLoad: Boolean,
thumbLink: String,
originPrice: String,
thumbMode: {
type: String,
value: 'aspectFit'
},
currency: {
type: String,
value: '¥'
}
},
methods: {
onClickThumb() {
this.jumpLink('thumbLink');
}
}
});
{
"component": true,
"usingComponents": {
"van-tag": "../tag/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="custom-class van-card">
<view class="{{ utils.bem('card__header', { center: centered }) }}">
<view class="van-card__thumb" bind:tap="onClickThumb">
<image
wx:if="{{ thumb }}"
src="{{ thumb }}"
mode="{{ thumbMode }}"
lazy-load="{{ lazyLoad }}"
class="van-card__img thumb-class"
/>
<slot name="thumb" />
<van-tag
wx:if="{{ tag }}"
mark
type="danger"
custom-class="van-card__tag"
>
{{ tag }}
</van-tag>
</view>
<view class="van-card__content">
<view wx:if="{{ title }}" class="van-card__title title-class">{{ title }}</view>
<slot wx:else name="title" />
<view wx:if="{{ desc }}" class="van-card__desc desc-class">{{ desc }}</view>
<slot wx:else name="desc" />
<slot name="tags" />
<view class="van-card__bottom">
<view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">{{ currency }} {{ price }}</view>
<view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
<view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
</view>
</view>
</view>
<view class="van-card__footer">
<slot name="footer" />
</view>
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
props: {
title: String,
border: {
type: Boolean,
value: true
}
}
});
{
"component": true
}
\ No newline at end of file
<view
wx:if="{{ title }}"
class="van-cell-group__title"
>
{{ title }}
</view>
<view class="custom-class van-cell-group {{ border ? 'van-hairline--top-bottom' : '' }}">
<slot />
</view>
@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
import { link } from '../mixins/link';
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'title-class',
'label-class',
'value-class',
'right-icon-class',
'hover-class'
],
mixins: [link],
props: {
title: null,
value: null,
icon: String,
size: String,
label: String,
center: Boolean,
isLink: Boolean,
required: Boolean,
clickable: Boolean,
titleWidth: String,
customStyle: String,
arrowDirection: String,
border: {
type: Boolean,
value: true
}
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
this.jumpLink();
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
\ No newline at end of file
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ utils.bem('cell', [size, { center, required, borderless: !border, clickable: isLink || clickable }]) }}"
hover-class="van-cell--hover hover-class"
hover-stay-time="70"
style="{{ customStyle }}"
bind:tap="onClick"
>
<van-icon
wx:if="{{ icon }}"
name="{{ icon }}"
class="van-cell__left-icon-wrap"
custom-class="van-cell__left-icon"
/>
<slot wx:else name="icon" />
<view
style="{{ titleWidth ? 'max-width:' + titleWidth + ';min-width:' + titleWidth : '' }}"
class="van-cell__title title-class"
>
<block wx:if="{{ title }}">
{{ title }}
<view wx:if="{{ label }}" class="van-cell__label label-class">{{ label }}</view>
</block>
<slot wx:else name="title" />
</view>
<view class="van-cell__value value-class">
<block wx:if="{{ value || value === 0 }}">{{ value }}</block>
<slot wx:else />
</view>
<van-icon
wx:if="{{ isLink }}"
name="{{ arrowDirection ? 'arrow' + '-' + arrowDirection : 'arrow' }}"
class="van-cell__right-icon-wrap right-icon-class"
custom-class="van-cell__right-icon"
/>
<slot wx:else name="right-icon" />
<slot name="extra" />
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
field: true,
relation: {
name: 'checkbox',
type: 'descendant',
linked(target) {
const { value, disabled } = this.data;
target.set({
value: value.indexOf(target.data.name) !== -1,
disabled: disabled || target.data.disabled
});
}
},
props: {
max: Number,
value: Array,
disabled: Boolean
},
watch: {
value(value) {
const children = this.getRelationNodes('../checkbox/index');
children.forEach(child => {
child.set({ value: value.indexOf(child.data.name) !== -1 });
});
},
disabled(disabled) {
const children = this.getRelationNodes('../checkbox/index');
children.forEach(child => {
child.set({ disabled: disabled || child.data.disabled });
});
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
@import '../common/index.wxss';
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
field: true,
relation: {
name: 'checkbox-group',
type: 'ancestor'
},
classes: ['icon-class', 'label-class'],
props: {
value: null,
disabled: Boolean,
useIconSlot: Boolean,
checkedColor: String,
labelPosition: String,
labelDisabled: Boolean,
shape: {
type: String,
value: 'round'
}
},
methods: {
emitChange(value) {
const parent = this.getRelationNodes('../checkbox-group/index')[0];
if (parent) {
this.setParentValue(parent, value);
}
else {
this.$emit('input', value);
this.$emit('change', value);
}
},
toggle() {
if (!this.data.disabled) {
this.emitChange(!this.data.value);
}
},
onClickLabel() {
if (!this.data.disabled && !this.data.labelDisabled) {
this.emitChange(!this.data.value);
}
},
setParentValue(parent, value) {
const parentValue = parent.data.value.slice();
const { name } = this.data;
if (value) {
if (parent.data.max && parentValue.length >= parent.data.max) {
return;
}
/* istanbul ignore else */
if (parentValue.indexOf(name) === -1) {
parentValue.push(name);
parent.$emit('input', parentValue);
parent.$emit('change', parentValue);
}
}
else {
const index = parentValue.indexOf(name);
/* istanbul ignore else */
if (index !== -1) {
parentValue.splice(index, 1);
parent.$emit('input', parentValue);
parent.$emit('change', parentValue);
}
}
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="van-checkbox custom-class">
<view class="van-checkbox__icon-wrap" bindtap="toggle">
<slot wx:if="{{ useIconSlot }}" name="icon" />
<van-icon
wx:else
name="success"
class="{{ utils.bem('checkbox__icon', [shape, { disabled, checked: value }]) }}"
style="{{ checkedColor && value && !disabled ? 'border-color:' + checkedColor + '; background-color:' + checkedColor : '' }}"
custom-class="icon-class"
custom-style="line-height: 20px;"
/>
</view>
<view class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled }]) }}" bindtap="onClickLabel">
<slot />
</view>
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'row',
type: 'ancestor'
},
props: {
span: Number,
offset: Number
},
data: {
style: ''
},
methods: {
setGutter(gutter) {
const padding = `${gutter / 2}px`;
const style = gutter ? `padding-left: ${padding}; padding-right: ${padding};` : '';
if (style !== this.data.style) {
this.set({ style });
}
}
}
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ utils.bem('col', [span]) }} {{ offset ? 'van-col--offset-' + offset : '' }}"
style="{{ style }}"
>
<slot />
</view>
@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
import { VantComponent } from '../common/component';
const nextTick = () => new Promise(resolve => setTimeout(resolve, 20));
VantComponent({
classes: ['title-class', 'content-class'],
relation: {
name: 'collapse',
type: 'ancestor',
linked(parent) {
this.parent = parent;
}
},
props: {
name: null,
title: null,
value: null,
icon: String,
label: String,
disabled: Boolean,
border: {
type: Boolean,
value: true
},
isLink: {
type: Boolean,
value: true
}
},
data: {
contentHeight: 0,
expanded: false,
transition: false
},
mounted() {
this.updateExpanded()
.then(nextTick)
.then(() => {
this.set({ transition: true });
});
},
methods: {
updateExpanded() {
if (!this.parent) {
return Promise.resolve();
}
const { value, accordion } = this.parent.data;
const { children = [] } = this.parent;
const { name } = this.data;
const index = children.indexOf(this);
const currentName = name == null ? index : name;
const expanded = accordion
? value === currentName
: (value || []).some((name) => name === currentName);
const stack = [];
if (expanded !== this.data.expanded) {
stack.push(this.updateStyle(expanded));
}
stack.push(this.set({ index, expanded }));
return Promise.all(stack);
},
updateStyle(expanded) {
return this.getRect('.van-collapse-item__content')
.then((rect) => rect.height)
.then((height) => {
if (expanded) {
return this.set({
contentHeight: height ? `${height}px` : 'auto'
});
}
else {
return this.set({ contentHeight: `${height}px` })
.then(nextTick)
.then(() => this.set({ contentHeight: 0 }));
}
});
},
onClick() {
if (this.data.disabled) {
return;
}
const { name, expanded } = this.data;
const index = this.parent.children.indexOf(this);
const currentName = name == null ? index : name;
this.parent.switch(currentName, !expanded);
},
onTransitionEnd() {
if (this.data.expanded) {
this.set({
contentHeight: 'auto'
});
}
}
}
});
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="van-collapse-item custom-class {{ index !== 0 ? 'van-hairline--top' : '' }}">
<van-cell
title="{{ title }}"
title-class="title-class"
icon="{{ icon }}"
is-link="{{ isLink }}"
value="{{ value }}"
label="{{ label }}"
border="{{ border && expanded }}"
class="{{ utils.bem('collapse-item__title', { disabled, expanded }) }}"
right-icon-class="van-cell__right-icon"
custom-class="van-cell"
hover-class="van-cell--hover"
bind:click="onClick"
>
<slot
name="title"
slot="title"
/>
<slot
name="icon"
slot="icon"
/>
<slot name="value" />
<slot
name="right-icon"
slot="right-icon"
/>
</van-cell>
<view
class="{{ utils.bem('collapse-item__wrapper', { transition }) }}"
style="height: {{ contentHeight }};"
bind:transitionend="onTransitionEnd"
>
<view
class="van-collapse-item__content content-class"
>
<slot />
</view>
</view>
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'collapse-item',
type: 'descendant',
linked(child) {
this.children.push(child);
}
},
props: {
value: {
type: null,
observer: 'updateExpanded'
},
accordion: {
type: Boolean,
observer: 'updateExpanded'
},
border: {
type: Boolean,
value: true
}
},
beforeCreate() {
this.children = [];
},
methods: {
updateExpanded() {
this.children.forEach((child) => {
child.updateExpanded();
});
},
switch(name, expanded) {
const { accordion, value } = this.data;
if (!accordion) {
name = expanded
? (value || []).concat(name)
: (value || []).filter((activeName) => activeName !== name);
}
else {
name = expanded ? name : '';
}
this.$emit('change', name);
this.$emit('input', name);
}
}
});
<view class="custom-class van-collapse {{ border ? 'van-hairline--top-bottom' : '' }}">
<slot />
</view>
@import '../common/index.wxss';
\ No newline at end of file
export declare const RED = "#f44";
export declare const BLUE = "#1989fa";
export declare const GREEN = "#07c160";
export const RED = '#f44';
export const BLUE = '#1989fa';
export const GREEN = '#07c160';
declare function VantComponent<Data, Props, Watch, Methods, Computed>(vantOptions?: VantComponentOptions<Data, Props, Watch, Methods, Computed, CombinedComponentInstance<Data, Props, Watch, Methods, Computed>>): void;
export { VantComponent };
import { basic } from '../mixins/basic';
import { observe } from '../mixins/observer/index';
function mapKeys(source, target, map) {
Object.keys(map).forEach(key => {
if (source[key]) {
target[map[key]] = source[key];
}
});
}
function VantComponent(vantOptions = {}) {
const options = {};
mapKeys(vantOptions, options, {
data: 'data',
props: 'properties',
mixins: 'behaviors',
methods: 'methods',
beforeCreate: 'created',
created: 'attached',
mounted: 'ready',
relations: 'relations',
destroyed: 'detached',
classes: 'externalClasses'
});
const { relation } = vantOptions;
if (relation) {
options.relations = Object.assign(options.relations || {}, {
[`../${relation.name}/index`]: relation
});
}
// add default externalClasses
options.externalClasses = options.externalClasses || [];
options.externalClasses.push('custom-class');
// add default behaviors
options.behaviors = options.behaviors || [];
options.behaviors.push(basic);
// map field to form-field behavior
if (vantOptions.field) {
options.behaviors.push('wx://form-field');
}
// add default options
options.options = {
multipleSlots: true,
addGlobalClass: true
};
observe(vantOptions, options);
Component(options);
}
export { VantComponent };
.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
.van-clearfix:after{content:"";display:table;clear:both}
\ No newline at end of file
.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
.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
declare function isDef(value: any): boolean;
declare function isObj(x: any): boolean;
declare function isNumber(value: any): boolean;
declare function range(num: number, min: number, max: number): number;
export { isObj, isDef, isNumber, range };
function isDef(value) {
return value !== undefined && value !== null;
}
function isObj(x) {
const type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
function isNumber(value) {
return /^\d+$/.test(value);
}
function range(num, min, max) {
return Math.min(Math.max(num, min), max);
}
export { isObj, isDef, isNumber, range };
import { VantComponent } from '../common/component';
import { isDef } from '../common/utils';
const currentYear = new Date().getFullYear();
function isValidDate(date) {
return isDef(date) && !isNaN(new Date(date).getTime());
}
function range(num, min, max) {
return Math.min(Math.max(num, min), max);
}
function padZero(val) {
return `00${val}`.slice(-2);
}
function times(n, iteratee) {
let index = -1;
const result = Array(n);
while (++index < n) {
result[index] = iteratee(index);
}
return result;
}
function getTrueValue(formattedValue) {
if (!formattedValue)
return;
while (isNaN(parseInt(formattedValue, 10))) {
formattedValue = formattedValue.slice(1);
}
return parseInt(formattedValue, 10);
}
function getMonthEndDay(year, month) {
return 32 - new Date(year, month - 1, 32).getDate();
}
VantComponent({
props: {
value: null,
title: String,
loading: Boolean,
itemHeight: {
type: Number,
value: 44
},
visibleItemCount: {
type: Number,
value: 5
},
confirmButtonText: {
type: String,
value: '确认'
},
cancelButtonText: {
type: String,
value: '取消'
},
type: {
type: String,
value: 'datetime'
},
showToolbar: {
type: Boolean,
value: true
},
minDate: {
type: Number,
value: new Date(currentYear - 10, 0, 1).getTime()
},
maxDate: {
type: Number,
value: new Date(currentYear + 10, 11, 31).getTime()
},
minHour: {
type: Number,
value: 0
},
maxHour: {
type: Number,
value: 23
},
minMinute: {
type: Number,
value: 0
},
maxMinute: {
type: Number,
value: 59
}
},
data: {
innerValue: Date.now(),
columns: []
},
watch: {
value(val) {
const { data } = this;
val = this.correctValue(val);
const isEqual = val === data.innerValue;
if (!isEqual) {
this.updateColumnValue(val).then(() => {
this.$emit('input', val);
});
}
},
type: 'updateColumns',
minHour: 'updateColumns',
maxHour: 'updateColumns',
minMinute: 'updateColumns',
maxMinute: 'updateColumns'
},
methods: {
getPicker() {
if (this.picker == null) {
const picker = this.picker = this.selectComponent('.van-datetime-picker');
const { setColumnValues } = picker;
picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]);
}
return this.picker;
},
updateColumns() {
const results = this.getRanges().map(({ type, range }, index) => {
const values = times(range[1] - range[0] + 1, index => {
let value = range[0] + index;
value = type === 'year' ? `${value}` : padZero(value);
return value;
});
return { values };
});
return this.set({ columns: results });
},
getRanges() {
const { data } = this;
if (data.type === 'time') {
return [
{
type: 'hour',
range: [data.minHour, data.maxHour]
},
{
type: 'minute',
range: [data.minMinute, data.maxMinute]
}
];
}
const { maxYear, maxDate, maxMonth, maxHour, maxMinute } = this.getBoundary('max', data.innerValue);
const { minYear, minDate, minMonth, minHour, minMinute } = this.getBoundary('min', data.innerValue);
const result = [
{
type: 'year',
range: [minYear, maxYear]
},
{
type: 'month',
range: [minMonth, maxMonth]
},
{
type: 'day',
range: [minDate, maxDate]
},
{
type: 'hour',
range: [minHour, maxHour]
},
{
type: 'minute',
range: [minMinute, maxMinute]
}
];
if (data.type === 'date')
result.splice(3, 2);
if (data.type === 'year-month')
result.splice(2, 3);
return result;
},
correctValue(value) {
const { data } = this;
// validate value
const isDateType = data.type !== 'time';
if (isDateType && !isValidDate(value)) {
value = data.minDate;
}
else if (!isDateType && !value) {
const { minHour } = data;
value = `${padZero(minHour)}:00`;
}
// time type
if (!isDateType) {
let [hour, minute] = value.split(':');
hour = padZero(range(hour, data.minHour, data.maxHour));
minute = padZero(range(minute, data.minMinute, data.maxMinute));
return `${hour}:${minute}`;
}
// date type
value = Math.max(value, data.minDate);
value = Math.min(value, data.maxDate);
return value;
},
getBoundary(type, innerValue) {
const value = new Date(innerValue);
const boundary = new Date(this.data[`${type}Date`]);
const year = boundary.getFullYear();
let month = 1;
let date = 1;
let hour = 0;
let minute = 0;
if (type === 'max') {
month = 12;
date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1);
hour = 23;
minute = 59;
}
if (value.getFullYear() === year) {
month = boundary.getMonth() + 1;
if (value.getMonth() + 1 === month) {
date = boundary.getDate();
if (value.getDate() === date) {
hour = boundary.getHours();
if (value.getHours() === hour) {
minute = boundary.getMinutes();
}
}
}
}
return {
[`${type}Year`]: year,
[`${type}Month`]: month,
[`${type}Date`]: date,
[`${type}Hour`]: hour,
[`${type}Minute`]: minute
};
},
onCancel() {
this.$emit('cancel');
},
onConfirm() {
this.$emit('confirm', this.data.innerValue);
},
onChange() {
const { data } = this;
let value;
const picker = this.getPicker();
if (data.type === 'time') {
const indexes = picker.getIndexes();
value = `${indexes[0] + data.minHour}:${indexes[1] + data.minMinute}`;
}
else {
const values = picker.getValues();
const year = getTrueValue(values[0]);
const month = getTrueValue(values[1]);
const maxDate = getMonthEndDay(year, month);
let date = getTrueValue(values[2]);
if (data.type === 'year-month') {
date = 1;
}
date = date > maxDate ? maxDate : date;
let hour = 0;
let minute = 0;
if (data.type === 'datetime') {
hour = getTrueValue(values[3]);
minute = getTrueValue(values[4]);
}
value = new Date(year, month - 1, date, hour, minute);
}
value = this.correctValue(value);
this.updateColumnValue(value).then(() => {
this.$emit('input', value);
this.$emit('change', picker);
});
},
updateColumnValue(value) {
let values = [];
const { data } = this;
const picker = this.getPicker();
if (data.type === 'time') {
const pair = value.split(':');
values = [pair[0], pair[1]];
}
else {
const date = new Date(value);
values = [`${date.getFullYear()}`, padZero(date.getMonth() + 1)];
if (data.type === 'date') {
values.push(padZero(date.getDate()));
}
if (data.type === 'datetime') {
values.push(padZero(date.getDate()), padZero(date.getHours()), padZero(date.getMinutes()));
}
}
return this.set({ innerValue: value })
.then(() => this.updateColumns())
.then(() => picker.setValues(values));
}
},
created() {
const innerValue = this.correctValue(this.data.value);
this.updateColumnValue(innerValue).then(() => {
this.$emit('input', innerValue);
});
}
});
{
"component": true,
"usingComponents": {
"van-picker": "../picker/index"
}
}
<van-picker
class="van-datetime-picker"
title="{{ title }}"
columns="{{ columns }}"
item-height="{{ itemHeight }}"
show-toolbar="{{ showToolbar }}"
visible-item-count="{{ visibleItemCount }}"
confirm-button-text="{{ confirmButtonText }}"
cancel-button-text="{{ cancelButtonText }}"
bind:change="onChange"
bind:confirm="onConfirm"
bind:cancel="onCancel"
/>
@import '../common/index.wxss';
\ No newline at end of file
declare type DialogAction = 'confirm' | 'cancel';
declare type DialogOptions = {
lang?: string;
show?: boolean;
title?: string;
zIndex?: number;
context?: any;
message?: string;
overlay?: boolean;
selector?: string;
ariaLabel?: string;
transition?: string;
asyncClose?: boolean;
businessId?: number;
sessionFrom?: string;
appParameter?: string;
messageAlign?: string;
sendMessageImg?: string;
showMessageCard?: boolean;
sendMessagePath?: string;
sendMessageTitle?: string;
confirmButtonText?: string;
cancelButtonText?: string;
showConfirmButton?: boolean;
showCancelButton?: boolean;
closeOnClickOverlay?: boolean;
confirmButtonOpenType?: string;
};
interface Dialog {
(options: DialogOptions): Promise<DialogAction>;
alert?: (options: DialogOptions) => Promise<DialogAction>;
confirm?: (options: DialogOptions) => Promise<DialogAction>;
close?: () => void;
stopLoading?: () => void;
install?: () => void;
setDefaultOptions?: (options: DialogOptions) => void;
resetDefaultOptions?: () => void;
defaultOptions?: DialogOptions;
currentOptions?: DialogOptions;
}
declare const Dialog: Dialog;
export default Dialog;
let queue = [];
function getContext() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
const Dialog = options => {
options = Object.assign({}, Dialog.currentOptions, options);
return new Promise((resolve, reject) => {
const context = options.context || getContext();
const dialog = context.selectComponent(options.selector);
delete options.selector;
if (dialog) {
dialog.set(Object.assign({ onCancel: reject, onConfirm: resolve }, options));
queue.push(dialog);
}
else {
console.warn('未找到 van-dialog 节点,请确认 selector 及 context 是否正确');
}
});
};
Dialog.defaultOptions = {
show: true,
title: '',
message: '',
zIndex: 100,
overlay: true,
asyncClose: false,
messageAlign: '',
transition: 'scale',
selector: '#van-dialog',
confirmButtonText: '确认',
cancelButtonText: '取消',
showConfirmButton: true,
showCancelButton: false,
closeOnClickOverlay: false,
confirmButtonOpenType: ''
};
Dialog.alert = Dialog;
Dialog.confirm = options => Dialog(Object.assign({ showCancelButton: true }, options));
Dialog.close = () => {
queue.forEach(dialog => {
dialog.close();
});
queue = [];
};
Dialog.stopLoading = () => {
queue.forEach(dialog => {
dialog.stopLoading();
});
};
Dialog.setDefaultOptions = options => {
Object.assign(Dialog.currentOptions, options);
};
Dialog.resetDefaultOptions = () => {
Dialog.currentOptions = Object.assign({}, Dialog.defaultOptions);
};
Dialog.resetDefaultOptions();
export default Dialog;
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
VantComponent({
mixins: [button, openType],
props: {
show: Boolean,
title: String,
message: String,
useSlot: Boolean,
asyncClose: Boolean,
messageAlign: String,
showCancelButton: Boolean,
closeOnClickOverlay: Boolean,
confirmButtonOpenType: String,
zIndex: {
type: Number,
value: 2000
},
confirmButtonText: {
type: String,
value: '确认'
},
cancelButtonText: {
type: String,
value: '取消'
},
showConfirmButton: {
type: Boolean,
value: true
},
overlay: {
type: Boolean,
value: true
},
transition: {
type: String,
value: 'scale'
}
},
data: {
loading: {
confirm: false,
cancel: false
}
},
watch: {
show(show) {
!show && this.stopLoading();
}
},
methods: {
onConfirm() {
this.handleAction('confirm');
},
onCancel() {
this.handleAction('cancel');
},
onClickOverlay() {
this.onClose('overlay');
},
handleAction(action) {
if (this.data.asyncClose) {
this.set({
[`loading.${action}`]: true
});
}
this.onClose(action);
},
close() {
this.set({
show: false
});
},
stopLoading() {
this.set({
loading: {
confirm: false,
cancel: false
}
});
},
onClose(action) {
if (!this.data.asyncClose) {
this.close();
}
this.$emit('close', action);
//把 dialog 实例传递出去,可以通过 stopLoading() 在外部关闭按钮的 loading
this.$emit(action, { dialog: this });
const callback = this.data[action === 'confirm' ? 'onConfirm' : 'onCancel'];
if (callback) {
callback(this);
}
}
}
});
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"van-button": "../button/index"
}
}
<van-popup
show="{{ show }}"
z-index="{{ zIndex }}"
overlay="{{ overlay }}"
custom-class="van-dialog"
transition="{{ transition }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:close="onClickOverlay"
>
<view
wx:if="{{ title }}"
class="van-dialog__header {{ message || useSlot ? '' : 'van-dialog--isolated' }}"
>
{{ title }}
</view>
<slot wx:if="{{ useSlot }}" />
<view
wx:elif="{{ message }}"
class="van-dialog__message {{ title ? 'van-dialog__message--has-title' : '' }} {{ messageAlign ? 'van-dialog__message--' + messageAlign : '' }}"
>
<text>{{ message }}</text>
</view>
<view class="van-hairline--top van-dialog__footer">
<van-button
wx:if="{{ showCancelButton }}"
size="large"
loading="{{ loading.cancel }}"
class="van-dialog__button van-hairline--right"
custom-class="van-dialog__cancel"
bind:click="onCancel"
>
{{ cancelButtonText }}
</van-button>
<van-button
wx:if="{{ showConfirmButton }}"
size="large"
class="van-dialog__button"
loading="{{ loading.confirm }}"
custom-class="van-dialog__confirm"
open-type="{{ confirmButtonOpenType }}"
lang="{{ lang }}"
business-id="{{ businessId }}"
session-from="{{ sessionFrom }}"
send-message-title="{{ sendMessageTitle }}"
send-message-path="{{ sendMessagePath }}"
send-message-img="{{ sendMessageImg }}"
show-message-card="{{ showMessageCard }}"
app-parameter="{{ appParameter }}"
bind:click="onConfirm"
bindgetuserinfo="bindGetUserInfo"
bindcontact="bindContact"
bindgetphonenumber="bindGetPhoneNumber"
binderror="bindError"
bindlaunchapp="bindLaunchApp"
bindopensetting="bindOpenSetting"
>
{{ confirmButtonText }}
</van-button>
</view>
</van-popup>
@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
import { VantComponent } from '../common/component';
VantComponent({
field: true,
classes: ['input-class'],
props: {
size: String,
icon: String,
label: String,
error: Boolean,
fixed: Boolean,
focus: Boolean,
center: Boolean,
isLink: Boolean,
leftIcon: String,
disabled: Boolean,
autosize: Boolean,
readonly: Boolean,
required: Boolean,
iconClass: String,
clearable: Boolean,
inputAlign: String,
errorMessageAlign: String,
customClass: String,
confirmType: String,
confirmHold: Boolean,
errorMessage: String,
placeholder: String,
customStyle: String,
useIconSlot: Boolean,
useButtonSlot: Boolean,
showConfirmBar: {
type: Boolean,
value: true
},
placeholderStyle: String,
adjustPosition: {
type: Boolean,
value: true
},
cursorSpacing: {
type: Number,
value: 50
},
maxlength: {
type: Number,
value: -1
},
type: {
type: String,
value: 'text'
},
border: {
type: Boolean,
value: true
},
titleWidth: {
type: String,
value: '90px'
}
},
data: {
showClear: false
},
beforeCreate() {
this.focused = false;
},
methods: {
onInput(event) {
const { value = '' } = event.detail || {};
this.set({
value,
showClear: this.getShowClear(value)
}, () => {
this.emitChange(value);
});
},
onFocus(event) {
const { value = '', height = 0 } = event.detail || {};
this.$emit('focus', { value, height });
this.focused = true;
this.blurFromClear = false;
this.set({
showClear: this.getShowClear()
});
},
onBlur(event) {
const { value = '', cursor = 0 } = event.detail || {};
this.$emit('blur', { value, cursor });
this.focused = false;
const showClear = this.getShowClear();
if (this.data.value === value) {
this.set({
showClear
});
}
else if (!this.blurFromClear) {
// fix: the handwritten keyboard does not trigger input change
this.set({
value,
showClear
}, () => {
this.emitChange(value);
});
}
},
onClickIcon() {
this.$emit('click-icon');
},
getShowClear(value) {
value = value === undefined ? this.data.value : value;
return (this.data.clearable && this.focused && value && !this.data.readonly);
},
onClear() {
this.blurFromClear = true;
this.set({
value: '',
showClear: this.getShowClear('')
}, () => {
this.emitChange('');
this.$emit('clear', '');
});
},
onConfirm() {
this.$emit('confirm', this.data.value);
},
emitChange(value) {
this.$emit('input', value);
this.$emit('change', value);
}
}
});
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index",
"van-icon": "../icon/index"
}
}
\ No newline at end of file
<wxs src="../wxs/utils.wxs" module="utils" />
<van-cell
icon="{{ leftIcon }}"
title="{{ label }}"
center="{{ center }}"
border="{{ border }}"
is-link="{{ isLink }}"
required="{{ required }}"
custom-style="{{ customStyle }}"
title-width="{{ titleWidth }}"
custom-class="van-field"
size="{{ size }}"
>
<slot name="left-icon" slot="icon" />
<slot name="label" slot="title" />
<view class="van-field__body {{ type === 'textarea' ? 'van-field__body--textarea' : '' }}">
<textarea
wx:if="{{ type === 'textarea' }}"
class="input-class {{ utils.bem('field__input', [inputAlign, { disabled, error }]) }}"
fixed="{{ fixed }}"
focus="{{ focus }}"
value="{{ value }}"
disabled="{{ disabled || readonly }}"
maxlength="{{ maxlength }}"
auto-height="{{ autosize }}"
placeholder="{{ placeholder }}"
placeholder-style="{{ placeholderStyle }}"
placeholder-class="{{ error ? 'van-field__input--error' : 'van-field__placeholder' }}"
cursor-spacing="{{ cursorSpacing }}"
adjust-position="{{ adjustPosition }}"
show-confirm-bar="{{ showConfirmBar }}"
bindinput="onInput"
bind:blur="onBlur"
bind:focus="onFocus"
bind:confirm="onConfirm"
/>
<input
wx:else
class="input-class {{ utils.bem('field__input', [inputAlign, { disabled, error }]) }}"
type="{{ type }}"
focus="{{ focus }}"
value="{{ value }}"
disabled="{{ disabled || readonly }}"
maxlength="{{ maxlength }}"
placeholder="{{ placeholder }}"
placeholder-style="{{ placeholderStyle }}"
placeholder-class="{{ error ? 'van-field__input--error' : 'van-field__placeholder' }}"
confirm-type="{{ confirmType }}"
confirm-hold="{{ confirmHold }}"
cursor-spacing="{{ cursorSpacing }}"
adjust-position="{{ adjustPosition }}"
bindinput="onInput"
bind:blur="onBlur"
bind:focus="onFocus"
bind:confirm="onConfirm"
/>
<van-icon
wx:if="{{ showClear }}"
size="16px"
name="clear"
class="van-field__clear-root"
custom-class="van-field__clear"
bind:touchstart="onClear"
/>
<view class="van-field__icon-container" wx:if="{{ icon || useIconSlot }}" bind:tap="onClickIcon">
<van-icon
wx:if="{{ icon }}"
size="16px"
name="{{ icon }}"
custom-class="van-field__icon {{ iconClass }}"
/>
<slot wx:else name="icon" />
</view>
<view wx:if="{{ useButtonSlot }}" class="van-field__button">
<slot name="button" />
</view>
</view>
<view wx:if="{{ errorMessage }}" class="van-field__error-message {{ utils.bem('field__error', [errorMessageAlign, { disabled, error }]) }}">
{{ errorMessage }}
</view>
</van-cell>
@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
import { VantComponent } from '../common/component';
import { link } from '../mixins/link';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
VantComponent({
mixins: [link, button, openType],
props: {
text: String,
loading: Boolean,
disabled: Boolean,
type: {
type: String,
value: 'danger'
}
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
this.jumpLink();
}
}
});
{
"component": true,
"usingComponents": {
"van-button": "../button/index"
}
}
<van-button
square
id="{{ id }}"
size="large"
lang="{{ lang }}"
type="{{ type }}"
loading="{{ loading }}"
disabled="{{ disabled }}"
open-type="{{ openType }}"
custom-class="custom-class"
business-id="{{ businessId }}"
session-from="{{ sessionFrom }}"
app-parameter="{{ appParameter }}"
send-message-img="{{ sendMessageImg }}"
send-message-path="{{ sendMessagePath }}"
show-message-card="{{ showMessageCard }}"
send-message-title="{{ sendMessageTitle }}"
bind:click="onClick"
binderror="bindError"
bindcontact="bindContact"
bindopensetting="bindOpenSetting"
bindgetuserinfo="bindGetUserInfo"
bindgetphonenumber="bindGetPhoneNumber"
bindlaunchapp="bindLaunchApp"
>
{{ text }}
</van-button>
@import '../common/index.wxss';:host{-webkit-flex:1;flex:1}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { link } from '../mixins/link';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
VantComponent({
classes: ['icon-class', 'text-class'],
mixins: [link, button, openType],
props: {
text: String,
info: String,
icon: String,
disabled: Boolean,
loading: Boolean
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
this.jumpLink();
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-button": "../button/index"
}
}
<van-button
square
id="{{ id }}"
size="large"
lang="{{ lang }}"
loading="{{ loading }}"
disabled="{{ disabled }}"
open-type="{{ openType }}"
business-id="{{ businessId }}"
custom-class="van-goods-action-icon"
session-from="{{ sessionFrom }}"
app-parameter="{{ appParameter }}"
send-message-img="{{ sendMessageImg }}"
send-message-path="{{ sendMessagePath }}"
show-message-card="{{ showMessageCard }}"
send-message-title="{{ sendMessageTitle }}"
bind:click="onClick"
binderror="bindError"
bindcontact="bindContact"
bindopensetting="bindOpenSetting"
bindgetuserinfo="bindGetUserInfo"
bindgetphonenumber="bindGetPhoneNumber"
bindlaunchapp="bindLaunchApp"
>
<view class="van-goods-action-icon__content van-hairline--right">
<van-icon
size="20px"
name="{{ icon }}"
info="{{ info }}"
class="van-goods-action-icon__icon"
custom-class="icon-class"
/>
<text class="text-class">{{ text }}</text>
</view>
</van-button>
@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
import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({
mixins: [safeArea()]
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="custom-class {{ utils.bem('goods-action', { safe: isIPhoneX && safeAreaInsetBottom }) }}">
<slot />
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
props: {
info: null,
name: String,
size: String,
color: String,
customStyle: String,
classPrefix: {
type: String,
value: 'van-icon'
}
},
methods: {
onClick() {
this.$emit('click');
}
}
});
{
"component": true,
"usingComponents": {
"van-info": "../info/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ classPrefix }} {{ utils.isSrc(name) ? 'van-icon--image' : classPrefix + '-' + name }}"
style="{{ color ? 'color: ' + color + ';' : '' }}{{ size ? 'font-size: ' + size + ';' : '' }}{{ customStyle }}"
bind:tap="onClick"
>
<van-info
wx:if="{{ info !== null }}"
info="{{ info }}"
custom-class="van-icon__info"
/>
<image
wx:if="{{ utils.isSrc(name) }}"
src="{{ name }}"
class="van-icon__image"
/>
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
props: {
info: null,
customStyle: String
}
});
<view
wx:if="{{ info !== null }}"
class="custom-class van-info"
style="{{ customStyle }}"
>{{ info }}</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
props: {
size: {
type: String,
value: '30px'
},
type: {
type: String,
value: 'circular'
},
color: {
type: String,
value: '#c9c9c9'
}
}
});
{
"component": true
}
\ No newline at end of file
<view
class="van-loading custom-class"
style="width: {{ size }}; height: {{ size }}"
>
<view
class="van-loading__spinner van-loading__spinner--{{ type }}"
style="color: {{ color }};"
>
<view
wx:if="{{ type === 'spinner' }}"
wx:for="item in 12"
wx:key="index"
class="van-loading__dot"
/>
</view>
</view>
@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
export declare const basic: void;
export const basic = Behavior({
methods: {
$emit() {
this.triggerEvent.apply(this, arguments);
},
getRect(selector, all) {
return new Promise(resolve => {
wx.createSelectorQuery()
.in(this)[all ? 'selectAll' : 'select'](selector)
.boundingClientRect(rect => {
if (all && Array.isArray(rect) && rect.length) {
resolve(rect);
}
if (!all && rect) {
resolve(rect);
}
})
.exec();
});
}
}
});
export declare const button: void;
export const button = Behavior({
externalClasses: ['hover-class'],
properties: {
id: String,
lang: {
type: String,
value: 'en'
},
businessId: Number,
sessionFrom: String,
sendMessageTitle: String,
sendMessagePath: String,
sendMessageImg: String,
showMessageCard: Boolean,
appParameter: String,
ariaLabel: String
}
});
export declare const link: void;
export const link = Behavior({
properties: {
url: String,
linkType: {
type: String,
value: 'navigateTo'
}
},
methods: {
jumpLink(urlKey = 'url') {
const url = this.data[urlKey];
if (url) {
wx[this.data.linkType]({ url });
}
}
}
});
export declare const behavior: void;
function setAsync(context, data) {
return new Promise(resolve => {
context.setData(data, resolve);
});
}
;
export const behavior = Behavior({
created() {
if (!this.$options) {
return;
}
const cache = {};
const { computed } = this.$options();
const keys = Object.keys(computed);
this.calcComputed = () => {
const needUpdate = {};
keys.forEach(key => {
const value = computed[key].call(this);
if (cache[key] !== value) {
cache[key] = needUpdate[key] = value;
}
});
return needUpdate;
};
},
attached() {
this.set();
},
methods: {
// set data and set computed data
set(data, callback) {
const stack = [];
if (data) {
stack.push(setAsync(this, data));
}
if (this.calcComputed) {
stack.push(setAsync(this, this.calcComputed()));
}
return Promise.all(stack).then(res => {
if (callback && typeof callback === 'function') {
callback.call(this);
}
return res;
});
}
}
});
export declare function observe(vantOptions: any, options: any): void;
import { behavior } from './behavior';
import { observeProps } from './props';
export function observe(vantOptions, options) {
const { watch, computed } = vantOptions;
options.behaviors.push(behavior);
if (watch) {
const props = options.properties || {};
Object.keys(watch).forEach(key => {
if (key in props) {
let prop = props[key];
if (prop === null || !('type' in prop)) {
prop = { type: prop };
}
prop.observer = watch[key];
props[key] = prop;
}
});
options.properties = props;
}
if (computed) {
options.methods = options.methods || {};
options.methods.$options = () => vantOptions;
if (options.properties) {
observeProps(options.properties);
}
}
}
export declare function observeProps(props: any): void;
export function observeProps(props) {
if (!props) {
return;
}
Object.keys(props).forEach(key => {
let prop = props[key];
if (prop === null || !('type' in prop)) {
prop = { type: prop };
}
let { observer } = prop;
prop.observer = function () {
if (observer) {
if (typeof observer === 'string') {
observer = this[observer];
}
observer.apply(this, arguments);
}
this.set();
};
props[key] = prop;
});
}
export declare const openType: void;
export const openType = Behavior({
properties: {
openType: String
},
methods: {
bindGetUserInfo(event) {
this.$emit('getuserinfo', event.detail);
},
bindContact(event) {
this.$emit('contact', event.detail);
},
bindGetPhoneNumber(event) {
this.$emit('getphonenumber', event.detail);
},
bindError(event) {
this.$emit('error', event.detail);
},
bindLaunchApp(event) {
this.$emit('launchapp', event.detail);
},
bindOpenSetting(event) {
this.$emit('opensetting', event.detail);
},
}
});
export declare const safeArea: ({ safeAreaInsetBottom, safeAreaInsetTop }?: {
safeAreaInsetBottom?: boolean;
safeAreaInsetTop?: boolean;
}) => void;
let cache = null;
function getSafeArea() {
return new Promise((resolve, reject) => {
if (cache != null) {
resolve(cache);
}
else {
wx.getSystemInfo({
success: ({ model, screenHeight, statusBarHeight }) => {
const iphoneX = /iphone x/i.test(model);
const iphoneNew = /iPhone11/i.test(model) && screenHeight === 812;
cache = {
isIPhoneX: iphoneX || iphoneNew,
statusBarHeight
};
resolve(cache);
},
fail: reject
});
}
});
}
export const safeArea = ({ safeAreaInsetBottom = true, safeAreaInsetTop = false } = {}) => Behavior({
properties: {
safeAreaInsetTop: {
type: Boolean,
value: safeAreaInsetTop
},
safeAreaInsetBottom: {
type: Boolean,
value: safeAreaInsetBottom
}
},
created() {
getSafeArea().then(({ isIPhoneX, statusBarHeight }) => {
this.set({ isIPhoneX, statusBarHeight });
});
}
});
export declare const touch: void;
export const touch = Behavior({
methods: {
touchStart(event) {
const touch = event.touches[0];
this.direction = '';
this.deltaX = 0;
this.deltaY = 0;
this.offsetX = 0;
this.offsetY = 0;
this.startX = touch.clientX;
this.startY = touch.clientY;
},
touchMove(event) {
const touch = event.touches[0];
this.deltaX = touch.clientX - this.startX;
this.deltaY = touch.clientY - this.startY;
this.offsetX = Math.abs(this.deltaX);
this.offsetY = Math.abs(this.deltaY);
this.direction =
this.offsetX > this.offsetY
? 'horizontal'
: this.offsetX < this.offsetY
? 'vertical'
: '';
}
}
});
export declare const transition: (showDefaultValue: boolean) => void;
import { isObj } from '../common/utils';
const getClassNames = (name) => ({
enter: `van-${name}-enter van-${name}-enter-active enter-class enter-active-class`,
'enter-to': `van-${name}-enter-to van-${name}-enter-active enter-to-class enter-active-class`,
leave: `van-${name}-leave van-${name}-leave-active leave-class leave-active-class`,
'leave-to': `van-${name}-leave-to van-${name}-leave-active leave-to-class leave-active-class`
});
const nextTick = () => new Promise(resolve => setTimeout(resolve, 1000 / 30));
export const transition = function (showDefaultValue) {
return Behavior({
properties: {
customStyle: String,
show: {
type: Boolean,
value: showDefaultValue,
observer: 'observeShow'
},
duration: {
type: [Number, Object],
value: 300,
observer: 'observeDuration'
},
name: {
type: String,
value: 'fade',
observer: 'updateClasses'
}
},
data: {
type: '',
inited: false,
display: false,
classNames: getClassNames('fade')
},
attached() {
if (this.data.show) {
this.show();
}
},
methods: {
observeShow(value) {
if (value) {
this.show();
}
else {
this.leave();
}
},
updateClasses(name) {
this.set({
classNames: getClassNames(name)
});
},
show() {
const { classNames, duration } = this.data;
const currentDuration = isObj(duration) ? duration.leave : duration;
Promise.resolve()
.then(nextTick)
.then(() => this.set({
inited: true,
display: true,
classes: classNames.enter,
currentDuration
}))
.then(nextTick)
.then(() => this.set({
classes: classNames['enter-to']
}));
},
leave() {
const { classNames, duration } = this.data;
const currentDuration = isObj(duration) ? duration.leave : duration;
if (+currentDuration === 0) {
this.onTransitionEnd();
return;
}
Promise.resolve()
.then(nextTick)
.then(() => this.set({
classes: classNames.leave,
currentDuration
}))
.then(nextTick)
.then(() => this.set({
classes: classNames['leave-to']
}));
},
onTransitionEnd() {
if (!this.data.show) {
this.set({ display: false });
this.$emit('transitionEnd');
}
}
}
});
};
import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({
mixins: [safeArea({ safeAreaInsetTop: true })],
classes: ['title-class'],
props: {
title: String,
fixed: Boolean,
leftText: String,
rightText: String,
leftArrow: Boolean,
border: {
type: Boolean,
value: true
},
zIndex: {
type: Number,
value: 120
}
},
methods: {
onClickLeft() {
this.$emit('click-left');
},
onClickRight() {
this.$emit('click-right');
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="{{ utils.bem('nav-bar', { fixed }) }} custom-class {{ border ? 'van-hairline--bottom' : '' }}"
style="z-index: {{ zIndex }}; {{ safeAreaInsetTop ? 'padding-top: ' + statusBarHeight + 'px;' : '' }}"
>
<view class="van-nav-bar__left" bind:tap="onClickLeft">
<block wx:if="{{ leftArrow || leftText }}">
<van-icon
wx:if="{{ leftArrow }}"
size="16px"
name="arrow-left"
custom-class="van-nav-bar__arrow"
/>
<view
wx:if="{{ leftText }}"
class="van-nav-bar__text"
hover-class="van-nav-bar__text--hover"
hover-stay-time="70"
>{{ leftText }}</view>
</block>
<slot wx:else name="left" />
</view>
<view class="van-nav-bar__title title-class van-ellipsis">
<block wx:if="{{ title }}">{{ title }}</block>
<slot wx:else name="title" />
</view>
<view class="van-nav-bar__right" bind:tap="onClickRight">
<view
wx:if="{{ rightText }}"
class="van-nav-bar__text"
hover-class="van-nav-bar__text--hover"
hover-stay-time="70"
>{{ rightText }}</view>
<slot wx:else name="right" />
</view>
</view>
@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
import { VantComponent } from '../common/component';
const FONT_COLOR = '#ed6a0c';
const BG_COLOR = '#fffbe8';
VantComponent({
props: {
text: {
type: String,
value: ''
},
mode: {
type: String,
value: ''
},
url: {
type: String,
value: ''
},
openType: {
type: String,
value: 'navigate'
},
delay: {
type: Number,
value: 0
},
speed: {
type: Number,
value: 50
},
scrollable: {
type: Boolean,
value: true
},
leftIcon: {
type: String,
value: ''
},
color: {
type: String,
value: FONT_COLOR
},
backgroundColor: {
type: String,
value: BG_COLOR
}
},
data: {
show: true,
hasRightIcon: false
},
watch: {
text() {
this.set({}, this.init);
}
},
created() {
if (this.data.mode) {
this.set({
hasRightIcon: true
});
}
this.resetAnimation = wx.createAnimation({
duration: 0,
timingFunction: 'linear'
});
},
destroyed() {
this.timer && clearTimeout(this.timer);
},
methods: {
init() {
Promise.all([
this.getRect('.van-notice-bar__content'),
this.getRect('.van-notice-bar__content-wrap')
]).then((rects) => {
const [contentRect, wrapRect] = rects;
if (contentRect == null ||
wrapRect == null ||
!contentRect.width ||
!wrapRect.width) {
return;
}
const { speed, scrollable, delay } = this.data;
if (scrollable && wrapRect.width < contentRect.width) {
const duration = (contentRect.width / speed) * 1000;
this.wrapWidth = wrapRect.width;
this.contentWidth = contentRect.width;
this.duration = duration;
this.animation = wx.createAnimation({
duration,
timingFunction: 'linear',
delay
});
this.scroll();
}
});
},
scroll() {
this.timer && clearTimeout(this.timer);
this.timer = null;
this.set({
animationData: this.resetAnimation
.translateX(this.wrapWidth)
.step()
.export()
});
setTimeout(() => {
this.set({
animationData: this.animation
.translateX(-this.contentWidth)
.step()
.export()
});
}, 20);
this.timer = setTimeout(() => {
this.scroll();
}, this.duration);
},
onClickIcon() {
this.timer && clearTimeout(this.timer);
this.timer = null;
this.set({ show: false });
},
onClick(event) {
this.$emit('click', event);
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
\ No newline at end of file
<view
wx:if="{{ show }}"
class="custom-class van-notice-bar {{ hasRightIcon ? 'van-notice-bar--within-icon' : '' }}"
style="color: {{ color }}; background-color: {{ backgroundColor }};"
bind:tap="onClick"
>
<view wx:if="{{ leftIcon }}" class="van-notice-bar__left-icon">
<image src="{{ leftIcon }}" />
</view>
<view class="van-notice-bar__content-wrap">
<view class="van-notice-bar__content {{ scrollable ? '' : 'van-ellipsis' }}" animation="{{ animationData }}">
{{ text }}
</view>
</view>
<van-icon
wx:if="{{ mode === 'closeable' }}"
class="van-notice-bar__right-icon"
name="cross"
bind:tap="onClickIcon"
/>
<navigator
wx:if="{{ mode === 'link' }}"
url="{{ url }}"
open-type="{{ openType }}"
>
<van-icon class="van-notice-bar__right-icon" name="arrow" />
</navigator>
</view>
@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
import { VantComponent } from '../common/component';
import { RED } from '../common/color';
import { safeArea } from '../mixins/safe-area';
VantComponent({
mixins: [safeArea()],
props: {
text: String,
color: {
type: String,
value: '#fff'
},
backgroundColor: {
type: String,
value: RED
},
duration: {
type: Number,
value: 3000
}
},
methods: {
show() {
const { duration } = this.data;
clearTimeout(this.timer);
this.set({
show: true
});
if (duration > 0 && duration !== Infinity) {
this.timer = setTimeout(() => {
this.hide();
}, duration);
}
},
hide() {
clearTimeout(this.timer);
this.set({
show: false
});
}
}
});
{
"component": true,
"usingComponents": {
"van-transition": "../transition/index"
}
}
<van-transition
name="slide-down"
show="{{ show }}"
custom-class="van-notify"
custom-style="background-color:{{ backgroundColor }}; color: {{ color }};"
>
<view wx:if="{{ safeAreaInsetTop }}" class="van-notify__safe-top" style="padding-top: {{ statusBarHeight }}px"></view>
{{ text }}
</van-transition>
@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
declare type NotifyOptions = {
text: string;
color?: string;
backgroundColor?: string;
duration?: number;
selector?: string;
context?: any;
safeAreaInsetTop?: boolean;
};
export default function Notify(options: NotifyOptions | string): void;
export {};
import { isObj } from '../common/utils';
const defaultOptions = {
selector: '#van-notify',
duration: 3000
};
function parseOptions(text) {
return isObj(text) ? text : { text };
}
function getContext() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
export default function Notify(options) {
options = Object.assign({}, defaultOptions, parseOptions(options));
const context = options.context || getContext();
const notify = context.selectComponent(options.selector);
delete options.selector;
if (notify) {
notify.set(options);
notify.show();
}
else {
console.warn('未找到 van-notify 节点,请确认 selector 及 context 是否正确');
}
}
import { VantComponent } from '../common/component';
VantComponent({
props: {
show: Boolean,
mask: Boolean,
customStyle: String,
duration: {
type: [Number, Object],
value: 300
},
zIndex: {
type: Number,
value: 1
}
},
methods: {
onClick() {
this.$emit('click');
},
// for prevent touchmove
noop() { }
}
});
{
"component": true,
"usingComponents": {
"van-transition": "../transition/index"
}
}
<van-transition
show="{{ show }}"
custom-class="van-overlay"
custom-style="z-index: {{ zIndex }}; {{ mask ? 'background-color: rgba(0, 0, 0, .7);' : '' }}; {{ customStyle }}"
duration="{{ duration }}"
bind:tap="onClick"
catch:touchmove="noop"
/>
@import '../common/index.wxss';.van-overlay{position:fixed;top:0;right:0;bottom:0;left:0}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
classes: ['header-class', 'footer-class'],
props: {
desc: String,
title: String,
status: String,
useFooterSlot: Boolean
}
});
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index"
}
}
<view class="van-panel van-hairline--top-bottom custom-class">
<van-cell
wx:if="{{ title || desc || status }}"
title="{{ title }}"
label="{{ desc }}"
value="{{ status }}"
custom-class="header-class"
value-class="van-panel__header-value"
/>
<slot wx:else name="header" />
<view class="van-panel__content">
<slot />
</view>
<view wx:if="{{ useFooterSlot }}" class="van-panel__footer van-hairline--top footer-class">
<slot name="footer" />
</view>
</view>
@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
import { VantComponent } from '../common/component';
import { isObj, range } from '../common/utils';
const DEFAULT_DURATION = 200;
VantComponent({
classes: ['active-class'],
props: {
valueKey: String,
className: String,
itemHeight: Number,
visibleItemCount: Number,
initialOptions: {
type: Array,
value: []
},
defaultIndex: {
type: Number,
value: 0
}
},
data: {
startY: 0,
offset: 0,
duration: 0,
startOffset: 0,
options: [],
currentIndex: 0
},
created() {
const { defaultIndex, initialOptions } = this.data;
this.set({
currentIndex: defaultIndex,
options: initialOptions
}).then(() => {
this.setIndex(defaultIndex);
});
},
computed: {
count() {
return this.data.options.length;
},
baseOffset() {
const { data } = this;
return (data.itemHeight * (data.visibleItemCount - 1)) / 2;
},
wrapperStyle() {
const { data } = this;
return [
`transition: ${data.duration}ms`,
`transform: translate3d(0, ${data.offset + data.baseOffset}px, 0)`,
`line-height: ${data.itemHeight}px`
].join('; ');
}
},
watch: {
defaultIndex(value) {
this.setIndex(value);
}
},
methods: {
onTouchStart(event) {
this.set({
startY: event.touches[0].clientY,
startOffset: this.data.offset,
duration: 0
});
},
onTouchMove(event) {
const { data } = this;
const deltaY = event.touches[0].clientY - data.startY;
this.set({
offset: range(data.startOffset + deltaY, -(data.count * data.itemHeight), data.itemHeight)
});
},
onTouchEnd() {
const { data } = this;
if (data.offset !== data.startOffset) {
this.set({
duration: DEFAULT_DURATION
});
const index = range(Math.round(-data.offset / data.itemHeight), 0, data.count - 1);
this.setIndex(index, true);
}
},
onClickItem(event) {
const { index } = event.currentTarget.dataset;
this.setIndex(index, true);
},
adjustIndex(index) {
const { data } = this;
index = range(index, 0, data.count);
for (let i = index; i < data.count; i++) {
if (!this.isDisabled(data.options[i]))
return i;
}
for (let i = index - 1; i >= 0; i--) {
if (!this.isDisabled(data.options[i]))
return i;
}
},
isDisabled(option) {
return isObj(option) && option.disabled;
},
getOptionText(option) {
const { data } = this;
return isObj(option) && data.valueKey in option
? option[data.valueKey]
: option;
},
setIndex(index, userAction) {
const { data } = this;
index = this.adjustIndex(index) || 0;
const offset = -index * data.itemHeight;
if (index !== data.currentIndex) {
return this.set({ offset, currentIndex: index }).then(() => {
userAction && this.$emit('change', index);
});
}
else {
return this.set({ offset });
}
},
setValue(value) {
const { options } = this.data;
for (let i = 0; i < options.length; i++) {
if (this.getOptionText(options[i]) === value) {
return this.setIndex(i);
}
}
return Promise.resolve();
},
getValue() {
const { data } = this;
return data.options[data.currentIndex];
}
}
});
{
"component": true
}
\ No newline at end of file
<view
class="van-picker-column custom-class"
style="height: {{ itemHeight * visibleItemCount }}px"
bind:touchstart="onTouchStart"
catch:touchmove="onTouchMove"
bind:touchend="onTouchEnd"
bind:touchcancel="onTouchEnd"
>
<view style="{{ wrapperStyle }}">
<view
wx:for="{{ options }}"
wx:for-item="option"
wx:key="index"
data-index="{{ index }}"
style="height: {{ itemHeight }}px"
class="van-ellipsis van-picker-column__item {{ option && option.disabled ? 'van-picker-column__item--disabled' : '' }} {{ index === currentIndex ? 'van-picker-column__item--selected active-class' : '' }}"
bindtap="onClickItem"
>{{ getOptionText(option, valueKey) }}</view>
</view>
</view>
<wxs module="getOptionText">
function isObj(x) {
var type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
module.exports = function (option, valueKey) {
return isObj(option) && option[valueKey] ? option[valueKey] : option;
}
</wxs>
@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
import { VantComponent } from '../common/component';
function isSimple(columns) {
return columns.length && !columns[0].values;
}
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: {
title: String,
loading: Boolean,
showToolbar: Boolean,
confirmButtonText: String,
cancelButtonText: String,
visibleItemCount: {
type: Number,
value: 5
},
valueKey: {
type: String,
value: 'text'
},
itemHeight: {
type: Number,
value: 44
},
columns: {
type: Array,
value: [],
observer(columns = []) {
this.simple = isSimple(columns);
this.children = this.selectAllComponents('.van-picker__column');
if (Array.isArray(this.children) && this.children.length) {
this.setColumns().catch(() => { });
}
}
}
},
beforeCreate() {
this.children = [];
},
methods: {
noop() { },
setColumns() {
const { data } = this;
const columns = this.simple ? [{ values: data.columns }] : data.columns;
const stack = columns.map((column, index) => this.setColumnValues(index, column.values));
return Promise.all(stack);
},
emit(event) {
const { type } = event.currentTarget.dataset;
if (this.simple) {
this.$emit(type, {
value: this.getColumnValue(0),
index: this.getColumnIndex(0)
});
}
else {
this.$emit(type, {
value: this.getValues(),
index: this.getIndexes()
});
}
},
onChange(event) {
if (this.simple) {
this.$emit('change', {
picker: this,
value: this.getColumnValue(0),
index: this.getColumnIndex(0)
});
}
else {
this.$emit('change', {
picker: this,
value: this.getValues(),
index: event.currentTarget.dataset.index
});
}
},
// get column instance by index
getColumn(index) {
return this.children[index];
},
// get column value by index
getColumnValue(index) {
const column = this.getColumn(index);
return column && column.getValue();
},
// set column value by index
setColumnValue(index, value) {
const column = this.getColumn(index);
if (column == null) {
return Promise.reject('setColumnValue: 对应列不存在');
}
return column.setValue(value);
},
// get column option index by column index
getColumnIndex(columnIndex) {
return (this.getColumn(columnIndex) || {}).data.currentIndex;
},
// set column option index by column index
setColumnIndex(columnIndex, optionIndex) {
const column = this.getColumn(columnIndex);
if (column == null) {
return Promise.reject('setColumnIndex: 对应列不存在');
}
return column.setIndex(optionIndex);
},
// get options of column by index
getColumnValues(index) {
return (this.children[index] || {}).data.options;
},
// set options of column by index
setColumnValues(index, options, needReset = true) {
const column = this.children[index];
if (column == null) {
return Promise.reject('setColumnValues: 对应列不存在');
}
const isSame = JSON.stringify(column.data.options) === JSON.stringify(options);
if (isSame) {
return Promise.resolve();
}
return column.set({ options }).then(() => {
if (needReset) {
column.setIndex(0);
}
});
},
// get values of all columns
getValues() {
return this.children.map((child) => child.getValue());
},
// set values of all columns
setValues(values) {
const stack = values.map((value, index) => this.setColumnValue(index, value));
return Promise.all(stack);
},
// get indexes of all columns
getIndexes() {
return this.children.map((child) => child.data.currentIndex);
},
// set indexes of all columns
setIndexes(indexes) {
const stack = indexes.map((optionIndex, columnIndex) => this.setColumnIndex(columnIndex, optionIndex));
return Promise.all(stack);
}
}
});
{
"component": true,
"usingComponents": {
"picker-column": "../picker-column/index",
"loading": "../loading/index"
}
}
<view class="van-picker custom-class">
<view
wx:if="{{ showToolbar }}"
class="van-picker__toolbar van-hairline--top-bottom toolbar-class"
>
<view
class="van-picker__cancel"
hover-class="van-picker__cancel--hover"
hover-stay-time="70"
data-type="cancel"
bindtap="emit"
>
{{ cancelButtonText || '取消' }}
</view>
<view wx:if="{{ title }}" class="van-picker__title van-ellipsis">{{ title }}</view>
<view
class="van-picker__confirm"
hover-class="van-picker__confirm--hover"
hover-stay-time="70"
data-type="confirm"
bindtap="emit"
>
{{ confirmButtonText || '确认' }}
</view>
</view>
<view wx:if="{{ loading }}" class="van-picker__loading">
<loading color="#1989fa"/>
</view>
<view
class="van-picker__columns"
style="height: {{ itemHeight * visibleItemCount }}px"
catch:touchmove="noop"
>
<picker-column
class="van-picker__column"
wx:for="{{ isSimple(columns) ? [columns] : columns }}"
wx:key="{{ index }}"
data-index="{{ index }}"
custom-class="column-class"
value-key="{{ valueKey }}"
initial-options="{{ isSimple(columns) ? item : item.values }}"
default-index="{{ item.defaultIndex }}"
item-height="{{ itemHeight }}"
visible-item-count="{{ visibleItemCount }}"
active-class="active-class"
bind:change="onChange"
/>
<view
class="van-picker__frame van-hairline--top-bottom"
style="height: {{ itemHeight }}px"
/>
</view>
</view>
<wxs module="isSimple">
function isSimple(columns) {
return columns.length && !columns[0].values;
}
module.exports = isSimple;
</wxs>
@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
import { VantComponent } from '../common/component';
import { transition } from '../mixins/transition';
import { safeArea } from '../mixins/safe-area';
VantComponent({
classes: [
'enter-class',
'enter-active-class',
'enter-to-class',
'leave-class',
'leave-active-class',
'leave-to-class'
],
mixins: [transition(false), safeArea()],
props: {
transition: {
type: String,
observer: 'observeClass'
},
customStyle: String,
overlayStyle: String,
zIndex: {
type: Number,
value: 100
},
overlay: {
type: Boolean,
value: true
},
closeOnClickOverlay: {
type: Boolean,
value: true
},
position: {
type: String,
value: 'center',
observer: 'observeClass'
}
},
created() {
this.observeClass();
},
methods: {
onClickOverlay() {
this.$emit('click-overlay');
if (this.data.closeOnClickOverlay) {
this.$emit('close');
}
},
observeClass() {
const { transition, position } = this.data;
this.updateClasses(transition || position);
if (transition === 'none') {
this.set({ duration: 0 });
}
}
}
});
{
"component": true,
"usingComponents": {
"van-overlay": "../overlay/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<van-overlay
wx:if="{{ inited && overlay }}"
mask
show="{{ show }}"
z-index="{{ zIndex }}"
custom-style="{{ overlayStyle }}"
duration="{{ duration }}"
bind:click="onClickOverlay"
/>
<view
wx:if="{{ inited }}"
class="custom-class {{ classes }} {{ utils.bem('popup', [position, { safe: isIPhoneX && safeAreaInsetBottom }]) }}"
style="z-index: {{ zIndex }}; -webkit-transition-duration:{{ currentDuration }}ms; transition-duration:{{ currentDuration }}ms; {{ display ? '' : 'display: none;' }} {{ customStyle }}"
bind:transitionend="onTransitionEnd"
>
<view wx:if="{{ safeAreaInsetTop }}" class="van-popup__safe-top" style="padding-top: {{ statusBarHeight }}px;"></view>
<slot />
</view>
@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
import { VantComponent } from '../common/component';
import { BLUE } from '../common/color';
VantComponent({
props: {
inactive: Boolean,
percentage: Number,
pivotText: String,
pivotColor: String,
showPivot: {
type: Boolean,
value: true
},
color: {
type: String,
value: BLUE
},
textColor: {
type: String,
value: '#fff'
}
},
data: {
pivotWidth: 0,
progressWidth: 0
},
watch: {
pivotText: 'getWidth',
showPivot: 'getWidth'
},
computed: {
portionStyle() {
const width = (this.data.progressWidth - this.data.pivotWidth) * this.data.percentage / 100 + 'px';
const background = this.getCurrentColor();
return `width: ${width}; background: ${background}; `;
},
pivotStyle() {
const color = this.data.textColor;
const background = this.data.pivotColor || this.getCurrentColor();
return `color: ${color}; background: ${background}`;
},
text() {
return this.data.pivotText || this.data.percentage + '%';
}
},
mounted() {
this.getWidth();
},
methods: {
getCurrentColor() {
return this.data.inactive ? '#cacaca' : this.data.color;
},
getWidth() {
this.getRect('.van-progress').then(rect => {
this.set({
progressWidth: rect.width
});
});
this.getRect('.van-progress__pivot').then(rect => {
this.set({
pivotWidth: rect.width || 0
});
});
}
}
});
<view class="van-progress custom-class">
<view
class="van-progress__portion {{ showPivot && text ? 'van-progress__portion--with-pivot' : '' }}"
style="{{ portionStyle }}"
>
<view
wx:if="{{ showPivot && text }}"
style="{{ pivotStyle }}"
class="van-progress__pivot"
>
{{ text }}
</view>
</view>
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
field: true,
relation: {
name: 'radio',
type: 'descendant',
linked(target) {
const { value, disabled } = this.data;
target.set({
value: value,
disabled: disabled || target.data.disabled
});
}
},
props: {
value: null,
disabled: Boolean
},
watch: {
value(value) {
const children = this.getRelationNodes('../radio/index');
children.forEach(child => {
child.set({ value });
});
},
disabled(disabled) {
const children = this.getRelationNodes('../radio/index');
children.forEach(child => {
child.set({ disabled: disabled || child.data.disabled });
});
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
@import '../common/index.wxss';
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
field: true,
relation: {
name: 'radio-group',
type: 'ancestor'
},
classes: ['icon-class', 'label-class'],
props: {
name: null,
value: null,
disabled: Boolean,
labelDisabled: Boolean,
labelPosition: String,
checkedColor: String
},
methods: {
emitChange(value) {
const instance = this.getRelationNodes('../radio-group/index')[0] || this;
instance.$emit('input', value);
instance.$emit('change', value);
},
onChange(event) {
this.emitChange(event.detail.value);
},
onClickLabel() {
if (!this.data.disabled && !this.data.labelDisabled) {
this.emitChange(this.data.name);
}
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="van-radio custom-class">
<view class="van-radio__input">
<radio-group bindchange="onChange">
<radio
value="{{ name }}"
checked="{{ value === name }}"
disabled="{{ disabled }}"
class="van-radio__control"
/>
</radio-group>
<van-icon
class="{{ utils.bem('radio__icon', { disabled, checked: !disabled && name === value, check: !disabled && name !== value }) }}"
custom-class="icon-class"
color="{{ value === name ? checkedColor : '' }}"
name="{{ value === name ? 'checked' : 'circle' }}"
/>
</view>
<view class="van-radio__label van-radio__label--{{ labelPosition }} label-class" bindtap="onClickLabel">
<slot />
</view>
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
field: true,
classes: ['icon-class'],
props: {
readonly: Boolean,
disabled: Boolean,
size: {
type: Number,
value: 20
},
icon: {
type: String,
value: 'star'
},
voidIcon: {
type: String,
value: 'star-o'
},
color: {
type: String,
value: '#ffd21e'
},
voidColor: {
type: String,
value: '#c7c7c7'
},
disabledColor: {
type: String,
value: '#bdbdbd'
},
count: {
type: Number,
value: 5
},
value: {
type: Number,
value: 0
}
},
data: {
innerValue: 0
},
watch: {
value(value) {
if (value !== this.data.innerValue) {
this.set({ innerValue: value });
}
}
},
computed: {
list() {
const { count, innerValue } = this.data;
return Array.from({ length: count }, (_, index) => index < innerValue);
}
},
methods: {
onSelect(event) {
const { data } = this;
const { index } = event.currentTarget.dataset;
if (!data.disabled && !data.readonly) {
this.set({ innerValue: index + 1 });
this.$emit('input', index + 1);
this.$emit('change', index + 1);
}
},
onTouchMove(event) {
const { clientX, clientY } = event.touches[0];
this.getRect('.van-rate__item', true).then(list => {
const target = list.find(item => clientX >= item.left &&
clientX <= item.right &&
clientY >= item.top &&
clientY <= item.bottom);
if (target != null) {
this.onSelect(Object.assign({}, event, { currentTarget: target }));
}
});
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<view
class="van-rate custom-class"
bind:touchmove="onTouchMove"
>
<van-icon
wx:for="{{ list }}"
wx:key="index"
class="van-rate__item"
custom-class="icon-class"
size="{{ size }}px"
data-index="{{ index }}"
name="{{ item ? icon : voidIcon }}"
color="{{ disabled ? disabledColor : item ? color : voidColor }}"
bind:click="onSelect"
/>
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'col',
type: 'descendant',
linked(target) {
if (this.data.gutter) {
target.setGutter(this.data.gutter);
}
}
},
props: {
gutter: Number
},
watch: {
gutter: 'setGutter'
},
mounted() {
if (this.data.gutter) {
this.setGutter();
}
},
methods: {
setGutter() {
const { gutter } = this.data;
const margin = `-${Number(gutter) / 2}px`;
const style = gutter
? `margin-right: ${margin}; margin-left: ${margin};`
: '';
this.set({ style });
this.getRelationNodes('../col/index').forEach(col => {
col.setGutter(this.data.gutter);
});
}
}
});
<view class="custom-class van-row" style="{{ style }}">
<slot />
</view>
@import '../common/index.wxss';.van-row:after{content:"";display:table;clear:both}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
field: true,
classes: ['field-class', 'input-class', 'cancel-class'],
props: {
focus: Boolean,
error: Boolean,
disabled: Boolean,
readonly: Boolean,
inputAlign: String,
showAction: Boolean,
useActionSlot: Boolean,
placeholder: String,
placeholderStyle: String,
background: {
type: String,
value: '#ffffff'
},
maxlength: {
type: Number,
value: -1
},
shape: {
type: String,
value: 'square'
},
label: String
},
methods: {
onChange(event) {
this.set({ value: event.detail });
this.$emit('change', event.detail);
},
onCancel() {
this.set({ value: '' });
this.$emit('cancel');
this.$emit('change', '');
},
onSearch() {
this.$emit('search', this.data.value);
},
onFocus() {
this.$emit('focus');
},
onBlur() {
this.$emit('blur');
},
onClear() {
this.$emit('clear');
},
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-field": "../field/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="{{ utils.bem('search', { withaction: showAction || useActionSlot }) }} custom-class"
style="background: {{ background }}"
>
<view class="{{ utils.bem('search__content', [shape]) }}">
<view class="van-search__label" wx:if="{{ label }}">{{ label }}</view>
<slot wx:else name="label" />
<van-field
clearable
type="search"
left-icon="search"
focus="{{ focus }}"
error="{{ error }}"
border="{{ false }}"
confirm-type="search"
class="van-search__field field-class"
value="{{ value }}"
disabled="{{ disabled }}"
readonly="{{ readonly }}"
maxlength="{{ maxlength }}"
input-align="{{ inputAlign }}"
input-class="input-class"
placeholder="{{ placeholder }}"
placeholder-style="{{ placeholderStyle }}"
custom-style="padding: 5px 10px 5px 0; background-color: transparent;"
bind:blur="onBlur"
bind:focus="onFocus"
bind:change="onChange"
bind:confirm="onSearch"
bind:clear="onClear"
/>
</view>
<view
wx:if="{{ showAction || useActionSlot }}"
class="van-search__action"
hover-class="van-search__action--hover"
hover-stay-time="70"
>
<slot wx:if="{{ useActionSlot }}" name="action" />
<view wx:else bind:tap="onCancel" class="cancel-class">取消</view>
</view>
</view>
@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
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
VantComponent({
mixins: [touch],
props: {
disabled: Boolean,
useButtonSlot: Boolean,
activeColor: String,
inactiveColor: String,
max: {
type: Number,
value: 100
},
min: {
type: Number,
value: 0
},
step: {
type: Number,
value: 1
},
value: {
type: Number,
value: 0
},
barHeight: {
type: String,
value: '2px'
}
},
watch: {
value(value) {
this.updateValue(value, false);
}
},
created() {
this.updateValue(this.data.value);
},
methods: {
onTouchStart(event) {
if (this.data.disabled)
return;
this.touchStart(event);
this.startValue = this.format(this.data.value);
},
onTouchMove(event) {
if (this.data.disabled)
return;
this.touchMove(event);
this.getRect('.van-slider').then((rect) => {
const diff = this.deltaX / rect.width * 100;
this.updateValue(this.startValue + diff, false, true);
});
},
onTouchEnd() {
if (this.data.disabled)
return;
this.updateValue(this.data.value, true);
},
onClick(event) {
if (this.data.disabled)
return;
this.getRect('.van-slider').then((rect) => {
const value = (event.detail.x - rect.left) / rect.width * 100;
this.updateValue(value, true);
});
},
updateValue(value, end, drag) {
value = this.format(value);
this.set({
value,
barStyle: `width: ${value}%; height: ${this.data.barHeight};`
});
if (drag) {
this.$emit('drag', { value });
}
if (end) {
this.$emit('change', value);
}
},
format(value) {
const { max, min, step } = this.data;
return Math.round(Math.max(min, Math.min(value, max)) / step) * step;
}
}
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ utils.bem('slider', { disabled }) }}"
style="{{ inactiveColor ? 'background:' + inactiveColor : '' }}"
bind:tap="onClick"
>
<view
class="van-slider__bar"
style="{{ barStyle }}; {{ activeColor ? 'background:' + activeColor : '' }}"
>
<view
class="van-slider__button-wrapper"
bind:touchstart="onTouchStart"
catch:touchmove="onTouchMove"
bind:touchend="onTouchEnd"
bind:touchcancel="onTouchEnd"
>
<slot
wx:if="{{ useButtonSlot }}"
name="button"
/>
<view
wx:else
class="van-slider__button"
/>
</view>
</view>
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
field: true,
classes: [
'input-class',
'plus-class',
'minus-class'
],
props: {
value: null,
integer: Boolean,
disabled: Boolean,
inputWidth: String,
asyncChange: Boolean,
disableInput: Boolean,
min: {
type: null,
value: 1
},
max: {
type: null,
value: Number.MAX_SAFE_INTEGER
},
step: {
type: null,
value: 1
}
},
computed: {
minusDisabled() {
return this.data.disabled || this.data.value <= this.data.min;
},
plusDisabled() {
return this.data.disabled || this.data.value >= this.data.max;
}
},
watch: {
value(value) {
if (value === '') {
return;
}
const newValue = this.range(value);
if (typeof newValue === 'number' && value !== newValue) {
this.set({ value: newValue });
}
}
},
data: {
focus: false
},
created() {
this.set({
value: this.range(this.data.value)
});
},
methods: {
onFocus(event) {
this.$emit('focus', event.detail);
},
onBlur(event) {
const value = this.range(this.data.value);
this.triggerInput(value);
this.$emit('blur', event.detail);
},
// limit value range
range(value) {
return Math.max(Math.min(this.data.max, value), this.data.min);
},
onInput(event) {
const { value = '' } = event.detail || {};
this.triggerInput(value);
},
onChange(type) {
if (this.data[`${type}Disabled`]) {
this.$emit('overlimit', type);
return;
}
const diff = type === 'minus' ? -this.data.step : +this.data.step;
const value = Math.round((this.data.value + diff) * 100) / 100;
this.triggerInput(this.range(value));
this.$emit(type);
},
onMinus() {
this.onChange('minus');
},
onPlus() {
this.onChange('plus');
},
triggerInput(value) {
this.set({
value: this.data.asyncChange ? this.data.value : value
});
this.$emit('change', value);
}
}
});
{
"component": true
}
\ No newline at end of file
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="van-stepper custom-class">
<view
class="minus-class {{ utils.bem('stepper__minus', { disabled: minusDisabled }) }}"
hover-class="van-stepper__minus--hover"
hover-stay-time="70"
bind:tap="onMinus"
/>
<input
type="{{ integer ? 'number' : 'digit' }}"
class="input-class {{ utils.bem('stepper__input', { disabled: disabled || disableInput }) }}"
style="{{ inputWidth ? 'width: ' + inputWidth : '' }}"
value="{{ value }}"
focus="{{ focus }}"
disabled="{{ disabled || disableInput }}"
bindinput="onInput"
bind:focus="onFocus"
bind:blur="onBlur"
/>
<view
class="plus-class {{ utils.bem('stepper__plus', { disabled: plusDisabled }) }}"
hover-class="van-stepper__plus--hover"
hover-stay-time="70"
bind:tap="onPlus"
/>
</view>
@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
import { VantComponent } from '../common/component';
import { GREEN } from '../common/color';
VantComponent({
props: {
icon: String,
steps: Array,
active: Number,
direction: {
type: String,
value: 'horizontal'
},
activeColor: {
type: String,
value: GREEN
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="custom-class {{ utils.bem('steps', [direction]) }}">
<view class="van-step__wrapper">
<view
wx:for="{{ steps }}"
wx:key="index"
class="{{ utils.bem('step', [direction, status(index, active)]) }} van-hairline"
>
<view class="van-step__title" style="{{ index === active ? 'color: ' + activeColor : '' }}">
<view>{{ item.text }}</view>
<view>{{ item.desc }}</view>
</view>
<view class="van-step__circle-container">
<view class="van-step__circle" wx:if="{{ index !== active }}" style="{{ index < active ? 'background-color: ' + activeColor : '' }}" />
<van-icon wx:else name="checked" color="{{ activeColor }}" custom-class="van-step__active" />
</view>
<view wx:if="{{ index !== steps.length - 1 }}" class="van-step__line" style="{{ index < active ? 'background-color: ' + activeColor : '' }}" />
</view>
</view>
</view>
<wxs module="status">
function get(index, active) {
if (index < active) {
return 'finish';
} else if (index === active) {
return 'process';
}
return '';
}
module.exports = get;
</wxs>
@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
import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({
mixins: [safeArea()],
classes: [
'bar-class',
'price-class',
'button-class'
],
props: {
tip: null,
type: Number,
price: null,
label: String,
loading: Boolean,
disabled: Boolean,
buttonText: String,
currency: {
type: String,
value: '¥'
},
buttonType: {
type: String,
value: 'danger'
}
},
computed: {
hasPrice() {
return typeof this.data.price === 'number';
},
priceStr() {
return (this.data.price / 100).toFixed(2);
},
tipStr() {
const { tip } = this.data;
return typeof tip === 'string' ? tip : '';
}
},
methods: {
onSubmit(event) {
this.$emit('submit', event.detail);
}
}
});
{
"component": true,
"usingComponents": {
"van-button": "../button/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="van-submit-bar custom-class">
<slot name="top" />
<view wx:if="{{ tip }}" class="van-submit-bar__tip">
{{ tipStr }}<slot name="tip" />
</view>
<view class="bar-class {{ utils.bem('submit-bar__bar', { safe: safeAreaInsetBottom && isIPhoneX }) }}">
<slot />
<view class="van-submit-bar__text">
<block wx:if="{{ hasPrice }}">
<text>{{ label || '合计:' }}</text>
<text class="van-submit-bar__price price-class">
<text class="van-submit-bar__currency">{{ currency }}</text> {{ priceStr }}
</text>
</block>
</view>
<van-button
square
size="large"
type="{{ buttonType }}"
loading="{{ loading }}"
disabled="{{ disabled }}"
class="van-submit-bar__button"
custom-class="button-class"
bind:click="onSubmit"
>
{{ loading ? '' : buttonText }}
</van-button>
</view>
</view>
@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
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
const THRESHOLD = 0.3;
VantComponent({
props: {
disabled: Boolean,
leftWidth: {
type: Number,
value: 0
},
rightWidth: {
type: Number,
value: 0
},
asyncClose: Boolean
},
mixins: [touch],
data: {
catchMove: true
},
created() {
this.offset = 0;
},
methods: {
open(position) {
const { leftWidth, rightWidth } = this.data;
const offset = position === 'left' ? leftWidth : -rightWidth;
this.swipeMove(offset);
},
close() {
this.swipeMove(0);
},
swipeMove(offset = 0) {
this.offset = offset;
const transform = `translate3d(${offset}px, 0, 0)`;
const transition = this.draging
? 'none'
: '.6s cubic-bezier(0.18, 0.89, 0.32, 1)';
this.set({
wrapperStyle: `
-webkit-transform: ${transform};
-webkit-transition: ${transition};
transform: ${transform};
transition: ${transition};
`
});
},
swipeLeaveTransition() {
const { leftWidth, rightWidth } = this.data;
const { offset } = this;
if (rightWidth > 0 && -offset > rightWidth * THRESHOLD) {
this.open('right');
}
else if (leftWidth > 0 && offset > leftWidth * THRESHOLD) {
this.open('left');
}
else {
this.swipeMove(0);
}
},
startDrag(event) {
if (this.data.disabled) {
return;
}
this.draging = true;
this.startOffset = this.offset;
this.firstDirection = '';
this.touchStart(event);
},
noop() { },
onDrag(event) {
if (this.data.disabled) {
return;
}
this.touchMove(event);
if (!this.firstDirection) {
this.firstDirection = this.direction;
this.set({ catchMove: this.firstDirection === 'horizontal' });
}
if (this.firstDirection === 'vertical') {
return;
}
const { leftWidth, rightWidth } = this.data;
const offset = this.startOffset + this.deltaX;
if ((rightWidth > 0 && -offset > rightWidth) ||
(leftWidth > 0 && offset > leftWidth)) {
return;
}
this.swipeMove(offset);
},
endDrag() {
if (this.data.disabled) {
return;
}
this.draging = false;
this.swipeLeaveTransition();
},
onClick(event) {
const { key: position = 'outside' } = event.currentTarget.dataset;
this.$emit('click', position);
if (!this.offset) {
return;
}
if (this.data.asyncClose) {
this.$emit('close', { position, instance: this });
}
else {
this.swipeMove(0);
}
}
}
});
<view
class="van-swipe-cell"
data-key="cell"
catchtap="onClick"
bindtouchstart="startDrag"
catchtouchmove="{{ catchMove ? 'noop' : '' }}"
capture-bind:touchmove="onDrag"
catchtouchend="endDrag"
catchtouchcancel="endDrag"
>
<view style="{{ wrapperStyle }}">
<view wx:if="{{ leftWidth }}" class="van-swipe-cell__left" data-key="left" catch:tap="onClick">
<slot name="left" />
</view>
<slot />
<view wx:if="{{ rightWidth }}" class="van-swipe-cell__right" data-key="right" catch:tap="onClick">
<slot name="right" />
</view>
</view>
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
field: true,
props: {
value: null,
title: String,
border: Boolean,
checked: Boolean,
loading: Boolean,
disabled: Boolean,
activeColor: String,
inactiveColor: String,
size: {
type: String,
value: '24px'
},
activeValue: {
type: null,
value: true
},
inactiveValue: {
type: null,
value: false
}
},
watch: {
checked(value) {
this.set({ value });
}
},
created() {
this.set({ value: this.data.checked });
},
methods: {
onChange(event) {
this.$emit('change', event.detail);
}
}
});
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index",
"van-switch": "../switch/index"
}
}
<van-cell
center
title="{{ title }}"
border="{{ border }}"
custom-class="van-switch-cell"
>
<van-switch
size="{{ size }}"
checked="{{ checked }}"
loading="{{ loading }}"
disabled="{{ disabled }}"
active-color="{{ activeColor }}"
inactive-color="{{ inactiveColor }}"
active-value="{{ activeValue }}"
inactive-value="{{ inactiveValue }}"
custom-class="van-switch-cell__switch"
bind:change="onChange"
/>
</van-cell>
@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
import { VantComponent } from '../common/component';
VantComponent({
field: true,
classes: ['node-class'],
props: {
checked: null,
loading: Boolean,
disabled: Boolean,
activeColor: String,
inactiveColor: String,
size: {
type: String,
value: '30px'
},
activeValue: {
type: null,
value: true
},
inactiveValue: {
type: null,
value: false
}
},
watch: {
checked(value) {
this.set({ value });
}
},
created() {
this.set({ value: this.data.checked });
},
methods: {
onClick() {
const { activeValue, inactiveValue } = this.data;
if (!this.data.disabled && !this.data.loading) {
const checked = this.data.checked === activeValue;
const value = checked ? inactiveValue : activeValue;
this.$emit('input', value);
this.$emit('change', value);
}
}
}
});
{
"component": true,
"usingComponents": {
"van-loading": "../loading/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ utils.bem('switch', { on: value === activeValue, disabled }) }}"
style="font-size: {{ size }}; {{ (checked ? activeColor : inactiveColor) ? 'background-color: ' + (checked ? activeColor : inactiveColor ) : '' }}"
bind:tap="onClick"
>
<view class="van-switch__node node-class">
<van-loading wx:if="{{ loading }}" size="50%" custom-class="van-switch__loading" />
</view>
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'tabs',
type: 'ancestor'
},
props: {
dot: Boolean,
info: null,
title: String,
disabled: Boolean,
titleStyle: String
},
data: {
width: null,
inited: false,
active: false,
animated: false
},
watch: {
title: 'update',
disabled: 'update',
dot: 'update',
info: 'update',
titleStyle: 'update'
},
methods: {
update() {
const parent = this.getRelationNodes('../tabs/index')[0];
if (parent) {
parent.updateTabs();
}
}
}
});
{
"component": true
}
\ No newline at end of file
<wxs src="../wxs/utils.wxs" module="utils" />
<view
wx:if="{{ animated || inited }}"
class="custom-class {{ utils.bem('tab__pane', { active, inactive: !active }) }}"
style="{{ animated || active ? '' : 'display: none;' }} {{ width ? 'width:' + width + 'px;' : '' }}"
>
<slot />
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
props: {
info: null,
icon: String,
dot: Boolean
},
relation: {
name: 'tabbar',
type: 'ancestor',
linked(target) {
this.parent = target;
}
},
data: {
active: false
},
methods: {
onClick() {
if (this.parent) {
this.parent.onChange(this);
}
this.$emit('click');
},
setActive({ active, color }) {
if (this.data.active !== active) {
return this.set({ active, color });
}
return Promise.resolve();
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-info": "../info/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="{{ utils.bem('tabbar-item', { active }) }} custom-class"
style="{{ active && color ? 'color: ' + color : '' }}"
bind:tap="onClick"
>
<view class="{{ utils.bem('tabbar-item__icon', { dot }) }}">
<van-icon
wx:if="{{ icon }}"
name="{{ icon }}"
customStyle="display: block"
/>
<block wx:else>
<slot
wx:if="{{ active }}"
name="icon-active"
/>
<slot wx:else name="icon" />
</block>
<van-info
wx:if="{{ info !== null }}"
info="{{ info }}"
custom-style="margin-top: 2px"
/>
</view>
<view class="van-tabbar-item__text">
<slot />
</view>
</view>
@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
import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({
mixins: [safeArea()],
relation: {
name: 'tabbar-item',
type: 'descendant',
linked(target) {
this.children = this.children || [];
this.children.push(target);
this.setActiveItem();
},
unlinked(target) {
this.children = this.children || [];
this.children = this.children.filter(item => item !== target);
this.setActiveItem();
}
},
props: {
active: Number,
activeColor: String,
fixed: {
type: Boolean,
value: true
},
zIndex: {
type: Number,
value: 1
}
},
watch: {
active(active) {
this.currentActive = active;
this.setActiveItem();
}
},
created() {
this.currentActive = this.data.active;
},
methods: {
setActiveItem() {
if (!Array.isArray(this.children) || !this.children.length) {
return Promise.resolve();
}
return Promise.all(this.children.map((item, index) => item.setActive({
active: index === this.currentActive,
color: this.data.activeColor
})));
},
onChange(child) {
const active = (this.children || []).indexOf(child);
if (active !== this.currentActive && active !== -1) {
this.currentActive = active;
this.setActiveItem().then(() => {
this.$emit('change', active);
});
}
}
}
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class van-hairline--top-bottom {{ utils.bem('tabbar', { fixed, safe: isIPhoneX && safeAreaInsetBottom }) }}"
style="{{ zIndex ? 'z-index: ' + zIndex : '' }}"
>
<slot />
</view>
@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
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
VantComponent({
mixins: [touch],
classes: ['nav-class', 'tab-class', 'tab-active-class', 'line-class'],
relation: {
name: 'tab',
type: 'descendant',
linked(child) {
this.child.push(child);
this.updateTabs(this.data.tabs.concat(child.data));
},
unlinked(child) {
const index = this.child.indexOf(child);
const { tabs } = this.data;
tabs.splice(index, 1);
this.child.splice(index, 1);
this.updateTabs(tabs);
}
},
props: {
color: String,
sticky: Boolean,
animated: Boolean,
swipeable: Boolean,
lineWidth: {
type: Number,
value: -1
},
lineHeight: {
type: Number,
value: -1
},
active: {
type: Number,
value: 0
},
type: {
type: String,
value: 'line'
},
border: {
type: Boolean,
value: true
},
duration: {
type: Number,
value: 0.3
},
zIndex: {
type: Number,
value: 1
},
swipeThreshold: {
type: Number,
value: 4
},
offsetTop: {
type: Number,
value: 0
}
},
data: {
tabs: [],
lineStyle: '',
scrollLeft: 0,
scrollable: false,
trackStyle: '',
wrapStyle: '',
position: ''
},
watch: {
swipeThreshold() {
this.set({
scrollable: this.child.length > this.data.swipeThreshold
});
},
color: 'setLine',
lineWidth: 'setLine',
lineHeight: 'setLine',
active: 'setActiveTab',
animated: 'setTrack',
offsetTop: 'setWrapStyle'
},
beforeCreate() {
this.child = [];
},
mounted() {
this.setLine(true);
this.setTrack();
this.scrollIntoView();
this.getRect('.van-tabs__wrap').then((rect) => {
this.navHeight = rect.height;
this.observerContentScroll();
});
},
destroyed() {
this.createIntersectionObserver().disconnect();
},
methods: {
updateTabs(tabs) {
tabs = tabs || this.data.tabs;
this.set({
tabs,
scrollable: tabs.length > this.data.swipeThreshold
});
this.setActiveTab();
},
trigger(eventName, index) {
this.$emit(eventName, {
index,
title: this.data.tabs[index].title
});
},
onTap(event) {
const { index } = event.currentTarget.dataset;
if (this.data.tabs[index].disabled) {
this.trigger('disabled', index);
}
else {
this.trigger('click', index);
this.setActive(index);
}
},
setActive(active) {
if (active !== this.data.active) {
this.trigger('change', active);
this.set({ active });
this.setActiveTab();
}
},
setLine(skipTransition) {
if (this.data.type !== 'line') {
return;
}
const { color, active, duration, lineWidth, lineHeight } = this.data;
this.getRect('.van-tab', true).then((rects) => {
const rect = rects[active];
const width = lineWidth !== -1 ? lineWidth : rect.width / 2;
const height = lineHeight !== -1 ? `height: ${lineHeight}px;` : '';
let left = rects
.slice(0, active)
.reduce((prev, curr) => prev + curr.width, 0);
left += (rect.width - width) / 2;
const transition = skipTransition
? ''
: `transition-duration: ${duration}s; -webkit-transition-duration: ${duration}s;`;
this.set({
lineStyle: `
${height}
width: ${width}px;
background-color: ${color};
-webkit-transform: translateX(${left}px);
transform: translateX(${left}px);
${transition}
`
});
});
},
setTrack() {
const { animated, active, duration } = this.data;
if (!animated)
return '';
this.getRect('.van-tabs__content').then((rect) => {
const { width } = rect;
this.set({
trackStyle: `
width: ${width * this.child.length}px;
left: ${-1 * active * width}px;
transition: left ${duration}s;
display: -webkit-box;
display: flex;
`
});
const props = { width, animated };
this.child.forEach((item) => {
item.set(props);
});
});
},
setActiveTab() {
this.child.forEach((item, index) => {
const data = {
active: index === this.data.active
};
if (data.active) {
data.inited = true;
}
if (data.active !== item.data.active) {
item.set(data);
}
});
this.set({}, () => {
this.setLine();
this.setTrack();
this.scrollIntoView();
});
},
// scroll active tab into view
scrollIntoView() {
const { active, scrollable } = this.data;
if (!scrollable) {
return;
}
Promise.all([
this.getRect('.van-tab', true),
this.getRect('.van-tabs__nav')
]).then(([tabRects, navRect]) => {
const tabRect = tabRects[active];
const offsetLeft = tabRects
.slice(0, active)
.reduce((prev, curr) => prev + curr.width, 0);
this.set({
scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2
});
});
},
onTouchStart(event) {
if (!this.data.swipeable)
return;
this.touchStart(event);
},
onTouchMove(event) {
if (!this.data.swipeable)
return;
this.touchMove(event);
},
// watch swipe touch end
onTouchEnd() {
if (!this.data.swipeable)
return;
const { active, tabs } = this.data;
const { direction, deltaX, offsetX } = this;
const minSwipeDistance = 50;
if (direction === 'horizontal' && offsetX >= minSwipeDistance) {
if (deltaX > 0 && active !== 0) {
this.setActive(active - 1);
}
else if (deltaX < 0 && active !== tabs.length - 1) {
this.setActive(active + 1);
}
}
},
setWrapStyle() {
const { offsetTop, position } = this.data;
let wrapStyle;
switch (position) {
case 'top':
wrapStyle = `
top: ${offsetTop}px;
position: fixed;
`;
break;
case 'bottom':
wrapStyle = `
top: auto;
bottom: 0;
`;
break;
default:
wrapStyle = '';
}
// cut down `set`
if (wrapStyle === this.data.wrapStyle)
return;
this.set({ wrapStyle });
},
observerContentScroll() {
if (!this.data.sticky) {
return;
}
const { offsetTop } = this.data;
const { windowHeight } = wx.getSystemInfoSync();
this.createIntersectionObserver().disconnect();
this.createIntersectionObserver()
.relativeToViewport({ top: -(this.navHeight + offsetTop) })
.observe('.van-tabs', (res) => {
const { top } = res.boundingClientRect;
if (top > offsetTop) {
return;
}
const position = res.intersectionRatio > 0 ? 'top' : 'bottom';
this.$emit('scroll', {
scrollTop: top + offsetTop,
isFixed: position === 'top'
});
this.setPosition(position);
});
this.createIntersectionObserver()
.relativeToViewport({ bottom: -(windowHeight - 1 - offsetTop) })
.observe('.van-tabs', (res) => {
const { top, bottom } = res.boundingClientRect;
if (bottom < this.navHeight) {
return;
}
const position = res.intersectionRatio > 0 ? 'top' : '';
this.$emit('scroll', {
scrollTop: top + offsetTop,
isFixed: position === 'top'
});
this.setPosition(position);
});
},
setPosition(position) {
if (position !== this.data.position) {
this.set({ position }).then(() => {
this.setWrapStyle();
});
}
}
}
});
{
"component": true,
"usingComponents": {
"van-info": "../info/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="custom-class {{ utils.bem('tabs', [type]) }}">
<view style="z-index: {{ zIndex }}; {{ wrapStyle }}" class="{{ utils.bem('tabs__wrap', { scrollable }) }} {{ type === 'line' && border ? 'van-hairline--top-bottom' : '' }}">
<slot name="nav-left" />
<scroll-view
scroll-x="{{ scrollable }}"
scroll-with-animation
scroll-left="{{ scrollLeft }}"
class="van-tabs__scroll--{{ type }}"
style="{{ color ? 'border-color: ' + color : '' }}"
>
<view class="{{ utils.bem('tabs__nav', [type]) }} nav-class">
<view wx:if="{{ type === 'line' }}" class="van-tabs__line" style="{{ lineStyle }}" />
<view
wx:for="{{ tabs }}"
wx:key="index"
data-index="{{ index }}"
class="van-ellipsis tab-class {{ index === active ? 'tab-active-class' : '' }} {{ utils.bem('tab', { active: index === active, disabled: item.disabled }) }}"
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) + '%' : '' }}"
bind:tap="onTap"
>
<view class="van-ellipsis {{ utils.bem('tab__title', { dot: item.dot }) }}" style="{{ item.titleStyle }}">
{{ item.title }}
<van-info
wx:if="{{ item.info !== null }}"
info="{{ item.info }}"
custom-class="van-tab__title__info"
/>
</view>
</view>
</view>
</scroll-view>
<slot name="nav-right" />
</view>
<view
class="van-tabs__content"
bind:touchstart="onTouchStart"
bind:touchmove="onTouchMove"
bind:touchend="onTouchEnd"
bind:touchcancel="onTouchEnd"
>
<view class="van-tabs__track" style="{{ trackStyle }}">
<slot />
</view>
</view>
</view>
@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
import { VantComponent } from '../common/component';
import { RED, BLUE, GREEN } from '../common/color';
const DEFAULT_COLOR = '#999';
const COLOR_MAP = {
danger: RED,
primary: BLUE,
success: GREEN
};
VantComponent({
props: {
size: String,
type: String,
mark: Boolean,
color: String,
plain: Boolean,
round: Boolean,
textColor: String
},
computed: {
style() {
const color = this.data.color || COLOR_MAP[this.data.type] || DEFAULT_COLOR;
const key = this.data.plain ? 'color' : 'background-color';
const style = { [key]: color };
if (this.data.textColor) {
style.color = this.data.textColor;
}
return Object.keys(style).map(key => `${key}: ${style[key]}`).join(';');
}
}
});
{
"component": true
}
\ No newline at end of file
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ utils.bem('tag', [size, { mark, plain, round }]) }} {{ plain ? 'van-hairline--surround' : '' }}"
style="{{ style }}"
>
<slot />
</view>
@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
import { VantComponent } from '../common/component';
VantComponent({
props: {
show: Boolean,
mask: Boolean,
message: String,
forbidClick: Boolean,
zIndex: {
type: Number,
value: 1000
},
type: {
type: String,
value: 'text'
},
loadingType: {
type: String,
value: 'circular'
},
position: {
type: String,
value: 'middle'
}
},
methods: {
clear() {
this.set({
show: false
});
},
// for prevent touchmove
noop() { }
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index",
"van-overlay": "../overlay/index",
"van-transition": "../transition/index"
}
}
<van-overlay
wx:if="{{ mask || forbidClick }}"
show="{{ show }}"
mask="{{ mask }}"
z-index="{{ zIndex }}"
/>
<van-transition
show="{{ show }}"
custom-style="z-index: {{ zIndex }}"
custom-class="van-toast__container"
>
<view
class="van-toast van-toast--{{ type === 'text' ? 'text' : 'icon' }} van-toast--{{ position }}"
catch:touchmove="noop"
>
<!-- text only -->
<text wx:if="{{ type === 'text' }}">{{ message }}</text>
<!-- with icon -->
<block wx:else>
<van-loading
wx:if="{{ type === 'loading' }}"
color="white"
type="{{ loadingType }}"
custom-class="van-toast__loading"
/>
<van-icon wx:else class="van-toast__icon" name="{{ type }}" />
<text wx:if="{{ message }}" class="van-toast__text">{{ message }}</text>
</block>
</view>
</van-transition>
@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
declare type ToastMessage = string | number;
export declare type ToastOptions = {
show?: boolean;
type?: string;
mask?: boolean;
zIndex?: number;
context?: any;
position?: string;
duration?: number;
selector?: string;
forbidClick?: boolean;
loadingType?: string;
message?: ToastMessage;
};
export interface Toast {
(message: ToastOptions | ToastMessage, options?: ToastOptions): Weapp.Component;
loading?(options?: ToastOptions | ToastMessage): Weapp.Component;
success?(options?: ToastOptions | ToastMessage): Weapp.Component;
fail?(options?: ToastOptions | ToastMessage): Weapp.Component;
clear?(): void;
setDefaultOptions?(options: ToastOptions): void;
resetDefaultOptions?(): void;
}
declare const Toast: Toast;
export default Toast;
import { isObj } from '../common/utils';
const defaultOptions = {
type: 'text',
mask: false,
message: '',
show: true,
zIndex: 1000,
duration: 3000,
position: 'middle',
forbidClick: false,
loadingType: 'circular',
selector: '#van-toast'
};
let queue = [];
let currentOptions = Object.assign({}, defaultOptions);
function parseOptions(message) {
return isObj(message) ? message : { message };
}
function getContext() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
const Toast = (options = {}) => {
options = Object.assign({}, currentOptions, parseOptions(options));
const context = options.context || getContext();
const toast = context.selectComponent(options.selector);
if (!toast) {
console.warn('未找到 van-toast 节点,请确认 selector 及 context 是否正确');
return;
}
delete options.context;
delete options.selector;
queue.push(toast);
toast.set(options);
clearTimeout(toast.timer);
if (options.duration > 0) {
toast.timer = setTimeout(() => {
toast.clear();
queue = queue.filter(item => item !== toast);
}, options.duration);
}
return toast;
};
const createMethod = type => options => Toast(Object.assign({ type }, parseOptions(options)));
['loading', 'success', 'fail'].forEach(method => {
Toast[method] = createMethod(method);
});
Toast.clear = () => {
queue.forEach(toast => {
toast.clear();
});
queue = [];
};
Toast.setDefaultOptions = options => {
Object.assign(currentOptions, options);
};
Toast.resetDefaultOptions = () => {
currentOptions = Object.assign({}, defaultOptions);
};
export default Toast;
import { VantComponent } from '../common/component';
import { transition } from '../mixins/transition';
VantComponent({
classes: [
'enter-class',
'enter-active-class',
'enter-to-class',
'leave-class',
'leave-active-class',
'leave-to-class'
],
mixins: [transition(true)]
});
{
"component": true
}
\ No newline at end of file
<view
wx:if="{{ inited }}"
class="van-transition custom-class {{ classes }}"
style="-webkit-transition-duration:{{ currentDuration }}ms; transition-duration:{{ currentDuration }}ms; {{ display ? '' : 'display: none;' }} {{ customStyle }}"
bind:transitionend="onTransitionEnd"
>
<slot />
</view>
@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
import { VantComponent } from '../common/component';
const ITEM_HEIGHT = 44;
VantComponent({
classes: [
'main-item-class',
'content-item-class',
'main-active-class',
'content-active-class',
'main-disabled-class',
'content-disabled-class'
],
props: {
items: Array,
mainActiveIndex: {
type: Number,
value: 0
},
activeId: {
type: [Number, String]
},
maxHeight: {
type: Number,
value: 300
}
},
data: {
subItems: [],
mainHeight: 0,
itemHeight: 0
},
watch: {
items() {
this.updateSubItems().then(() => {
this.updateMainHeight();
});
},
maxHeight() {
this.updateItemHeight(this.data.subItems);
this.updateMainHeight();
},
mainActiveIndex: 'updateSubItems'
},
methods: {
// 当一个子项被选择时
onSelectItem(event) {
const { item } = event.currentTarget.dataset;
if (!item.disabled) {
this.$emit('click-item', item);
}
},
// 当一个导航被点击时
onClickNav(event) {
const { index } = event.currentTarget.dataset;
const item = this.data.items[index];
if (!item.disabled) {
this.$emit('click-nav', { index });
}
},
// 更新子项列表
updateSubItems() {
const { items, mainActiveIndex } = this.data;
const { children = [] } = items[mainActiveIndex] || {};
this.updateItemHeight(children);
return this.set({ subItems: children });
},
// 更新组件整体高度,根据最大高度和当前组件需要展示的高度来决定
updateMainHeight() {
const { items = [], subItems = [] } = this.data;
const maxHeight = Math.max(items.length * ITEM_HEIGHT, subItems.length * ITEM_HEIGHT);
this.set({ mainHeight: Math.min(maxHeight, this.data.maxHeight) });
},
// 更新子项列表高度,根据可展示的最大高度和当前子项列表的高度决定
updateItemHeight(subItems) {
const itemHeight = Math.min(subItems.length * ITEM_HEIGHT, this.data.maxHeight);
return this.set({ itemHeight });
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-cell": "../cell/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="van-tree-select"
style="height: {{ mainHeight }}px"
>
<scroll-view scroll-y class="van-tree-select__nav">
<view
wx:for="{{ items }}"
wx:key="index"
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' : '' }}"
data-index="{{ index }}"
bind:tap="onClickNav"
>
{{ item.text }}
</view>
</scroll-view>
<scroll-view
scroll-y
class="van-tree-select__content"
style="height: {{ itemHeight }}px"
>
<view
wx:for="{{ subItems }}"
wx:key="id"
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' : '' }}"
data-item="{{ item }}"
bind:tap="onSelectItem"
>
{{ item.text }}
<van-icon
wx:if="{{ activeId === item.id }}"
name="checked"
size="16px"
class="van-tree-select__selected"
/>
</view>
</scroll-view>
</view>
@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
function isArray(array) {
return array && array.constructor === 'Array';
}
module.exports.isArray = isArray;
var array = require('./array.wxs');
var object = require('./object.wxs');
var PREFIX = 'van-';
function join(name, mods) {
name = PREFIX + name;
mods = mods.map(function(mod) {
return name + '--' + mod;
});
mods.unshift(name);
return mods.join(' ');
}
function traversing(mods, conf) {
if (!conf) {
return;
}
if (typeof conf === 'string' || typeof conf === 'number') {
mods.push(conf);
} else if (array.isArray(conf)) {
conf.forEach(function(item) {
traversing(mods, item);
});
} else if (typeof conf === 'object') {
object.keys(conf).forEach(function(key) {
conf[key] && mods.push(key);
});
}
}
function bem(name, conf) {
var mods = [];
traversing(mods, conf);
return join(name, mods);
}
module.exports.bem = bem;
/**
* Simple memoize
* wxs doesn't support fn.apply, so this memoize only support up to 2 args
*/
function isPrimitive(value) {
var type = typeof value;
return (
type === 'boolean' ||
type === 'number' ||
type === 'string' ||
type === 'undefined' ||
value === null
);
}
// mock simple fn.call in wxs
function call(fn, args) {
if (args.length === 2) {
return fn(args[0], args[1]);
}
if (args.length === 1) {
return fn(args[0]);
}
return fn();
}
function serializer(args) {
if (args.length === 1 && isPrimitive(args[0])) {
return args[0];
}
var obj = {};
for (var i = 0; i < args.length; i++) {
obj['key' + i] = args[i];
}
return JSON.stringify(obj);
}
function memoize(fn) {
var cache = {};
return function() {
var key = serializer(arguments);
if (cache[key] === undefined) {
cache[key] = call(fn, arguments);
}
return cache[key];
};
}
module.exports.memoize = memoize;
/* eslint-disable */
var REGEXP = getRegExp('{|}|"', 'g');
function keys(obj) {
return JSON.stringify(obj)
.replace(REGEXP, '')
.split(',')
.map(function(item) {
return item.split(':')[0];
});
}
module.exports.keys = keys;
var bem = require('./bem.wxs').bem;
var memoize = require('./memoize.wxs').memoize;
function isSrc(url) {
return url.indexOf('http') === 0 || url.indexOf('data:image') === 0 || url.indexOf('//') === 0;
}
module.exports = {
bem: memoize(bem),
isSrc: isSrc,
memoize: memoize
};
/**
* @version: 1.0 Alpha-1
* @author: Coolite Inc. http://www.coolite.com/
* @date: 2008-05-13
* @copyright: Copyright (c) 2006-2008, Coolite Inc. (http://www.coolite.com/). All rights reserved.
* @license: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
* @website: http://www.datejs.com/
*/
Date.CultureInfo = {
name: "en-US",
englishName: "English (United States)",
nativeName: "English (United States)",
dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
abbreviatedDayNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
shortestDayNames: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
firstLetterDayNames: ["S", "M", "T", "W", "T", "F", "S"],
monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
abbreviatedMonthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
amDesignator: "AM",
pmDesignator: "PM",
firstDayOfWeek: 0,
twoDigitYearMax: 2029,
dateElementOrder: "mdy",
formatPatterns: {
shortDate: "M/d/yyyy",
longDate: "dddd, MMMM dd, yyyy",
shortTime: "h:mm tt",
longTime: "h:mm:ss tt",
fullDateTime: "dddd, MMMM dd, yyyy h:mm:ss tt",
sortableDateTime: "yyyy-MM-ddTHH:mm:ss",
universalSortableDateTime: "yyyy-MM-dd HH:mm:ssZ",
rfc1123: "ddd, dd MMM yyyy HH:mm:ss GMT",
monthDay: "MMMM dd",
yearMonth: "MMMM, yyyy"
},
regexPatterns: {
jan: /^jan(uary)?/i,
feb: /^feb(ruary)?/i,
mar: /^mar(ch)?/i,
apr: /^apr(il)?/i,
may: /^may/i,
jun: /^jun(e)?/i,
jul: /^jul(y)?/i,
aug: /^aug(ust)?/i,
sep: /^sep(t(ember)?)?/i,
oct: /^oct(ober)?/i,
nov: /^nov(ember)?/i,
dec: /^dec(ember)?/i,
sun: /^su(n(day)?)?/i,
mon: /^mo(n(day)?)?/i,
tue: /^tu(e(s(day)?)?)?/i,
wed: /^we(d(nesday)?)?/i,
thu: /^th(u(r(s(day)?)?)?)?/i,
fri: /^fr(i(day)?)?/i,
sat: /^sa(t(urday)?)?/i,
future: /^next/i,
past: /^last|past|prev(ious)?/i,
add: /^(\+|aft(er)?|from|hence)/i,
subtract: /^(\-|bef(ore)?|ago)/i,
yesterday: /^yes(terday)?/i,
today: /^t(od(ay)?)?/i,
tomorrow: /^tom(orrow)?/i,
now: /^n(ow)?/i,
millisecond: /^ms|milli(second)?s?/i,
second: /^sec(ond)?s?/i,
minute: /^mn|min(ute)?s?/i,
hour: /^h(our)?s?/i,
week: /^w(eek)?s?/i,
month: /^m(onth)?s?/i,
day: /^d(ay)?s?/i,
year: /^y(ear)?s?/i,
shortMeridian: /^(a|p)/i,
longMeridian: /^(a\.?m?\.?|p\.?m?\.?)/i,
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,
ordinalSuffix: /^\s*(st|nd|rd|th)/i,
timeContext: /^\s*(\:|a(?!u|p)|p)/i
},
timezones: [{
name: "UTC",
offset: "-000"
}, {
name: "GMT",
offset: "-000"
}, {
name: "EST",
offset: "-0500"
}, {
name: "EDT",
offset: "-0400"
}, {
name: "CST",
offset: "-0600"
}, {
name: "CDT",
offset: "-0500"
}, {
name: "MST",
offset: "-0700"
}, {
name: "MDT",
offset: "-0600"
}, {
name: "PST",
offset: "-0800"
}, {
name: "PDT",
offset: "-0700"
}]
};
(function () {
var $D = Date,
$P = $D.prototype,
$C = $D.CultureInfo,
p = function (s, l) {
if (!l) {
l = 2;
}
return ("000" + s).slice(l * -1);
};
$P.clearTime = function () {
this.setHours(0);
this.setMinutes(0);
this.setSeconds(0);
this.setMilliseconds(0);
return this;
};
$P.setTimeToNow = function () {
var n = new Date();
this.setHours(n.getHours());
this.setMinutes(n.getMinutes());
this.setSeconds(n.getSeconds());
this.setMilliseconds(n.getMilliseconds());
return this;
};
$D.today = function () {
return new Date().clearTime();
};
$D.compare = function (date1, date2) {
if (isNaN(date1) || isNaN(date2)) {
throw new Error(date1 + " - " + date2);
} else if (date1 instanceof Date && date2 instanceof Date) {
return (date1 < date2) ? -1 : (date1 > date2) ? 1 : 0;
} else {
throw new TypeError(date1 + " - " + date2);
}
};
$D.equals = function (date1, date2) {
return (date1.compareTo(date2) === 0);
};
$D.getDayNumberFromName = function (name) {
var n = $C.dayNames,
m = $C.abbreviatedDayNames,
o = $C.shortestDayNames,
s = name.toLowerCase();
for (var i = 0; i < n.length; i++) {
if (n[i].toLowerCase() == s || m[i].toLowerCase() == s || o[i].toLowerCase() == s) {
return i;
}
}
return -1;
};
$D.getMonthNumberFromName = function (name) {
var n = $C.monthNames,
m = $C.abbreviatedMonthNames,
s = name.toLowerCase();
for (var i = 0; i < n.length; i++) {
if (n[i].toLowerCase() == s || m[i].toLowerCase() == s) {
return i;
}
}
return -1;
};
$D.isLeapYear = function (year) {
return ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);
};
$D.getDaysInMonth = function (year, month) {
return [31, ($D.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
};
$D.getTimezoneAbbreviation = function (offset) {
var z = $C.timezones,
p;
for (var i = 0; i < z.length; i++) {
if (z[i].offset === offset) {
return z[i].name;
}
}
return null;
};
$D.getTimezoneOffset = function (name) {
var z = $C.timezones,
p;
for (var i = 0; i < z.length; i++) {
if (z[i].name === name.toUpperCase()) {
return z[i].offset;
}
}
return null;
};
$P.clone = function () {
return new Date(this.getTime());
};
$P.compareTo = function (date) {
return Date.compare(this, date);
};
$P.equals = function (date) {
return Date.equals(this, date || new Date());
};
$P.between = function (start, end) {
return this.getTime() >= start.getTime() && this.getTime() <= end.getTime();
};
$P.isAfter = function (date) {
return this.compareTo(date || new Date()) === 1;
};
$P.isBefore = function (date) {
return (this.compareTo(date || new Date()) === -1);
};
$P.isToday = function () {
return this.isSameDay(new Date());
};
$P.isSameDay = function (date) {
return this.clone().clearTime().equals(date.clone().clearTime());
};
$P.addMilliseconds = function (value) {
this.setMilliseconds(this.getMilliseconds() + value);
return this;
};
$P.addSeconds = function (value) {
return this.addMilliseconds(value * 1000);
};
$P.addMinutes = function (value) {
return this.addMilliseconds(value * 60000);
};
$P.addHours = function (value) {
return this.addMilliseconds(value * 3600000);
};
$P.addDays = function (value) {
this.setDate(this.getDate() + value);
return this;
};
$P.addWeeks = function (value) {
return this.addDays(value * 7);
};
$P.addMonths = function (value) {
var n = this.getDate();
this.setDate(1);
this.setMonth(this.getMonth() + value);
this.setDate(Math.min(n, $D.getDaysInMonth(this.getFullYear(), this.getMonth())));
return this;
};
$P.addYears = function (value) {
return this.addMonths(value * 12);
};
$P.add = function (config) {
if (typeof config == "number") {
this._orient = config;
return this;
}
var x = config;
if (x.milliseconds) {
this.addMilliseconds(x.milliseconds);
}
if (x.seconds) {
this.addSeconds(x.seconds);
}
if (x.minutes) {
this.addMinutes(x.minutes);
}
if (x.hours) {
this.addHours(x.hours);
}
if (x.weeks) {
this.addWeeks(x.weeks);
}
if (x.months) {
this.addMonths(x.months);
}
if (x.years) {
this.addYears(x.years);
}
if (x.days) {
this.addDays(x.days);
}
return this;
};
var $y, $m, $d;
$P.getWeek = function () {
var a, b, c, d, e, f, g, n, s, w;
$y = (!$y) ? this.getFullYear() : $y;
$m = (!$m) ? this.getMonth() + 1 : $m;
$d = (!$d) ? this.getDate() : $d;
if ($m <= 2) {
a = $y - 1;
b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0);
c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0);
s = b - c;
e = 0;
f = $d - 1 + (31 * ($m - 1));
} else {
a = $y;
b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0);
c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0);
s = b - c;
e = s + 1;
f = $d + ((153 * ($m - 3) + 2) / 5) + 58 + s;
}
g = (a + b) % 7;
d = (f + g - e) % 7;
n = (f + 3 - d) | 0;
if (n < 0) {
w = 53 - ((g - s) / 5 | 0);
} else if (n > 364 + s) {
w = 1;
} else {
w = (n / 7 | 0) + 1;
}
$y = $m = $d = null;
return w;
};
$P.getISOWeek = function () {
$y = this.getUTCFullYear();
$m = this.getUTCMonth() + 1;
$d = this.getUTCDate();
return p(this.getWeek());
};
$P.setWeek = function (n) {
return this.moveToDayOfWeek(1).addWeeks(n - this.getWeek());
};
$D._validate = function (n, min, max, name) {
if (typeof n == "undefined") {
return false;
} else if (typeof n != "number") {
throw new TypeError(n + " is not a Number.");
} else if (n < min || n > max) {
throw new RangeError(n + " is not a valid value for " + name + ".");
}
return true;
};
$D.validateMillisecond = function (value) {
return $D._validate(value, 0, 999, "millisecond");
};
$D.validateSecond = function (value) {
return $D._validate(value, 0, 59, "second");
};
$D.validateMinute = function (value) {
return $D._validate(value, 0, 59, "minute");
};
$D.validateHour = function (value) {
return $D._validate(value, 0, 23, "hour");
};
$D.validateDay = function (value, year, month) {
return $D._validate(value, 1, $D.getDaysInMonth(year, month), "day");
};
$D.validateMonth = function (value) {
return $D._validate(value, 0, 11, "month");
};
$D.validateYear = function (value) {
return $D._validate(value, 0, 9999, "year");
};
$P.set = function (config) {
if ($D.validateMillisecond(config.millisecond)) {
this.addMilliseconds(config.millisecond - this.getMilliseconds());
}
if ($D.validateSecond(config.second)) {
this.addSeconds(config.second - this.getSeconds());
}
if ($D.validateMinute(config.minute)) {
this.addMinutes(config.minute - this.getMinutes());
}
if ($D.validateHour(config.hour)) {
this.addHours(config.hour - this.getHours());
}
if ($D.validateMonth(config.month)) {
this.addMonths(config.month - this.getMonth());
}
if ($D.validateYear(config.year)) {
this.addYears(config.year - this.getFullYear());
}
if ($D.validateDay(config.day, this.getFullYear(), this.getMonth())) {
this.addDays(config.day - this.getDate());
}
if (config.timezone) {
this.setTimezone(config.timezone);
}
if (config.timezoneOffset) {
this.setTimezoneOffset(config.timezoneOffset);
}
if (config.week && $D._validate(config.week, 0, 53, "week")) {
this.setWeek(config.week);
}
return this;
};
$P.moveToFirstDayOfMonth = function () {
return this.set({
day: 1
});
};
$P.moveToLastDayOfMonth = function () {
return this.set({
day: $D.getDaysInMonth(this.getFullYear(), this.getMonth())
});
};
$P.moveToNthOccurrence = function (dayOfWeek, occurrence) {
var shift = 0;
if (occurrence > 0) {
shift = occurrence - 1;
} else if (occurrence === -1) {
this.moveToLastDayOfMonth();
if (this.getDay() !== dayOfWeek) {
this.moveToDayOfWeek(dayOfWeek, -1);
}
return this;
}
return this.moveToFirstDayOfMonth().addDays(-1).moveToDayOfWeek(dayOfWeek, +1).addWeeks(shift);
};
$P.moveToDayOfWeek = function (dayOfWeek, orient) {
var diff = (dayOfWeek - this.getDay() + 7 * (orient || +1)) % 7;
return this.addDays((diff === 0) ? diff += 7 * (orient || +1) : diff);
};
$P.moveToMonth = function (month, orient) {
var diff = (month - this.getMonth() + 12 * (orient || +1)) % 12;
return this.addMonths((diff === 0) ? diff += 12 * (orient || +1) : diff);
};
$P.getOrdinalNumber = function () {
return Math.ceil((this.clone().clearTime() - new Date(this.getFullYear(), 0, 1)) / 86400000) + 1;
};
$P.getTimezone = function () {
return $D.getTimezoneAbbreviation(this.getUTCOffset());
};
$P.setTimezoneOffset = function (offset) {
var here = this.getTimezoneOffset(),
there = Number(offset) * -6 / 10;
return this.addMinutes(there - here);
};
$P.setTimezone = function (offset) {
return this.setTimezoneOffset($D.getTimezoneOffset(offset));
};
$P.hasDaylightSavingTime = function () {
return (Date.today().set({
month: 0,
day: 1
}).getTimezoneOffset() !== Date.today().set({
month: 6,
day: 1
}).getTimezoneOffset());
};
$P.isDaylightSavingTime = function () {
return (this.hasDaylightSavingTime() && new Date().getTimezoneOffset() === Date.today().set({
month: 6,
day: 1
}).getTimezoneOffset());
};
$P.getUTCOffset = function () {
var n = this.getTimezoneOffset() * -10 / 6,
r;
if (n < 0) {
r = (n - 10000).toString();
return r.charAt(0) + r.substr(2);
} else {
r = (n + 10000).toString();
return "+" + r.substr(1);
}
};
$P.getElapsed = function (date) {
return (date || new Date()) - this;
};
if (!$P.toISOString) {
$P.toISOString = function () {
function f(n) {
return n < 10 ? '0' + n : n;
}
return '"' + this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z"';
};
}
$P._toString = $P.toString;
$P.toString = function (format) {
var x = this;
if (format && format.length == 1) {
var c = $C.formatPatterns;
x.t = x.toString;
switch (format) {
case "d":
return x.t(c.shortDate);
case "D":
return x.t(c.longDate);
case "F":
return x.t(c.fullDateTime);
case "m":
return x.t(c.monthDay);
case "r":
return x.t(c.rfc1123);
case "s":
return x.t(c.sortableDateTime);
case "t":
return x.t(c.shortTime);
case "T":
return x.t(c.longTime);
case "u":
return x.t(c.universalSortableDateTime);
case "y":
return x.t(c.yearMonth);
}
}
var ord = function (n) {
switch (n * 1) {
case 1:
case 21:
case 31:
return "st";
case 2:
case 22:
return "nd";
case 3:
case 23:
return "rd";
default:
return "th";
}
};
return format ? format.replace(/(\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S)/g, function (m) {
if (m.charAt(0) === "\\") {
return m.replace("\\", "");
}
x.h = x.getHours;
switch (m) {
case "hh":
return p(x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12));
case "h":
return x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12);
case "HH":
return p(x.h());
case "H":
return x.h();
case "mm":
return p(x.getMinutes());
case "m":
return x.getMinutes();
case "ss":
return p(x.getSeconds());
case "s":
return x.getSeconds();
case "yyyy":
return p(x.getFullYear(), 4);
case "yy":
return p(x.getFullYear());
case "dddd":
return $C.dayNames[x.getDay()];
case "ddd":
return $C.abbreviatedDayNames[x.getDay()];
case "dd":
return p(x.getDate());
case "d":
return x.getDate();
case "MMMM":
return $C.monthNames[x.getMonth()];
case "MMM":
return $C.abbreviatedMonthNames[x.getMonth()];
case "MM":
return p((x.getMonth() + 1));
case "M":
return x.getMonth() + 1;
case "t":
return x.h() < 12 ? $C.amDesignator.substring(0, 1) : $C.pmDesignator.substring(0, 1);
case "tt":
return x.h() < 12 ? $C.amDesignator : $C.pmDesignator;
case "S":
return ord(x.getDate());
default:
return m;
}
}) : this._toString();
};
}());
(function () {
var $D = Date,
$P = $D.prototype,
$C = $D.CultureInfo,
$N = Number.prototype;
$P._orient = +1;
$P._nth = null;
$P._is = false;
$P._same = false;
$P._isSecond = false;
$N._dateElement = "day";
$P.next = function () {
this._orient = +1;
return this;
};
$D.next = function () {
return $D.today().next();
};
$P.last = $P.prev = $P.previous = function () {
this._orient = -1;
return this;
};
$D.last = $D.prev = $D.previous = function () {
return $D.today().last();
};
$P.is = function () {
this._is = true;
return this;
};
$P.same = function () {
this._same = true;
this._isSecond = false;
return this;
};
$P.today = function () {
return this.same().day();
};
$P.weekday = function () {
if (this._is) {
this._is = false;
return (!this.is().sat() && !this.is().sun());
}
return false;
};
$P.at = function (time) {
return (typeof time === "string") ? $D.parse(this.toString("d") + " " + time) : this.set(time);
};
$N.fromNow = $N.after = function (date) {
var c = {};
c[this._dateElement] = this;
return ((!date) ? new Date() : date.clone()).add(c);
};
$N.ago = $N.before = function (date) {
var c = {};
c[this._dateElement] = this * -1;
return ((!date) ? new Date() : date.clone()).add(c);
};
var dx = ("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),
mx = ("january february march april may june july august september october november december").split(/\s/),
px = ("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),
pxf = ("Milliseconds Seconds Minutes Hours Date Week Month FullYear").split(/\s/),
nth = ("final first second third fourth fifth").split(/\s/),
de;
$P.toObject = function () {
var o = {};
for (var i = 0; i < px.length; i++) {
o[px[i].toLowerCase()] = this["get" + pxf[i]]();
}
return o;
};
$D.fromObject = function (config) {
config.week = null;
return Date.today().set(config);
};
var df = function (n) {
return function () {
if (this._is) {
this._is = false;
return this.getDay() == n;
}
if (this._nth !== null) {
if (this._isSecond) {
this.addSeconds(this._orient * -1);
}
this._isSecond = false;
var ntemp = this._nth;
this._nth = null;
var temp = this.clone().moveToLastDayOfMonth();
this.moveToNthOccurrence(n, ntemp);
if (this > temp) {
throw new RangeError($D.getDayName(n) + " does not occur " + ntemp + " times in the month of " + $D.getMonthName(temp.getMonth()) + " " + temp.getFullYear() + ".");
}
return this;
}
return this.moveToDayOfWeek(n, this._orient);
};
};
var sdf = function (n) {
return function () {
var t = $D.today(),
shift = n - t.getDay();
if (n === 0 && $C.firstDayOfWeek === 1 && t.getDay() !== 0) {
shift = shift + 7;
}
return t.addDays(shift);
};
};
for (var i = 0; i < dx.length; i++) {
$D[dx[i].toUpperCase()] = $D[dx[i].toUpperCase().substring(0, 3)] = i;
$D[dx[i]] = $D[dx[i].substring(0, 3)] = sdf(i);
$P[dx[i]] = $P[dx[i].substring(0, 3)] = df(i);
}
var mf = function (n) {
return function () {
if (this._is) {
this._is = false;
return this.getMonth() === n;
}
return this.moveToMonth(n, this._orient);
};
};
var smf = function (n) {
return function () {
return $D.today().set({
month: n,
day: 1
});
};
};
for (var j = 0; j < mx.length; j++) {
$D[mx[j].toUpperCase()] = $D[mx[j].toUpperCase().substring(0, 3)] = j;
$D[mx[j]] = $D[mx[j].substring(0, 3)] = smf(j);
$P[mx[j]] = $P[mx[j].substring(0, 3)] = mf(j);
}
var ef = function (j) {
return function () {
if (this._isSecond) {
this._isSecond = false;
return this;
}
if (this._same) {
this._same = this._is = false;
var o1 = this.toObject(),
o2 = (arguments[0] || new Date()).toObject(),
v = "",
k = j.toLowerCase();
for (var m = (px.length - 1); m > -1; m--) {
v = px[m].toLowerCase();
if (o1[v] != o2[v]) {
return false;
}
if (k == v) {
break;
}
}
return true;
}
if (j.substring(j.length - 1) != "s") {
j += "s";
}
return this["add" + j](this._orient);
};
};
var nf = function (n) {
return function () {
this._dateElement = n;
return this;
};
};
for (var k = 0; k < px.length; k++) {
de = px[k].toLowerCase();
$P[de] = $P[de + "s"] = ef(px[k]);
$N[de] = $N[de + "s"] = nf(de);
}
$P._ss = ef("Second");
var nthfn = function (n) {
return function (dayOfWeek) {
if (this._same) {
return this._ss(arguments[0]);
}
if (dayOfWeek || dayOfWeek === 0) {
return this.moveToNthOccurrence(dayOfWeek, n);
}
this._nth = n;
if (n === 2 && (dayOfWeek === undefined || dayOfWeek === null)) {
this._isSecond = true;
return this.addSeconds(this._orient);
}
return this;
};
};
for (var l = 0; l < nth.length; l++) {
$P[nth[l]] = (l === 0) ? nthfn(-1) : nthfn(l);
}
}());
(function () {
Date.Parsing = {
Exception: function (s) {
this.message = "Parse error at '" + s.substring(0, 10) + " ...'";
}
};
var $P = Date.Parsing;
var _ = $P.Operators = {
rtoken: function (r) {
return function (s) {
var mx = s.match(r);
if (mx) {
return ([mx[0], s.substring(mx[0].length)]);
} else {
throw new $P.Exception(s);
}
};
},
token: function (s) {
return function (s) {
return _.rtoken(new RegExp("^\s*" + s + "\s*"))(s);
};
},
stoken: function (s) {
return _.rtoken(new RegExp("^" + s));
},
until: function (p) {
return function (s) {
var qx = [],
rx = null;
while (s.length) {
try {
rx = p.call(this, s);
} catch (e) {
qx.push(rx[0]);
s = rx[1];
continue;
}
break;
}
return [qx, s];
};
},
many: function (p) {
return function (s) {
var rx = [],
r = null;
while (s.length) {
try {
r = p.call(this, s);
} catch (e) {
return [rx, s];
}
rx.push(r[0]);
s = r[1];
}
return [rx, s];
};
},
optional: function (p) {
return function (s) {
var r = null;
try {
r = p.call(this, s);
} catch (e) {
return [null, s];
}
return [r[0], r[1]];
};
},
not: function (p) {
return function (s) {
try {
p.call(this, s);
} catch (e) {
return [null, s];
}
throw new $P.Exception(s);
};
},
ignore: function (p) {
return p ? function (s) {
var r = null;
r = p.call(this, s);
return [null, r[1]];
} : null;
},
product: function () {
var px = arguments[0],
qx = Array.prototype.slice.call(arguments, 1),
rx = [];
for (var i = 0; i < px.length; i++) {
rx.push(_.each(px[i], qx));
}
return rx;
},
cache: function (rule) {
var cache = {},
r = null;
return function (s) {
try {
r = cache[s] = (cache[s] || rule.call(this, s));
} catch (e) {
r = cache[s] = e;
}
if (r instanceof $P.Exception) {
throw r;
} else {
return r;
}
};
},
any: function () {
var px = arguments;
return function (s) {
var r = null;
for (var i = 0; i < px.length; i++) {
if (px[i] == null) {
continue;
}
try {
r = (px[i].call(this, s));
} catch (e) {
r = null;
}
if (r) {
return r;
}
}
throw new $P.Exception(s);
};
},
each: function () {
var px = arguments;
return function (s) {
var rx = [],
r = null;
for (var i = 0; i < px.length; i++) {
if (px[i] == null) {
continue;
}
try {
r = (px[i].call(this, s));
} catch (e) {
throw new $P.Exception(s);
}
rx.push(r[0]);
s = r[1];
}
return [rx, s];
};
},
all: function () {
var px = arguments,
_ = _;
return _.each(_.optional(px));
},
sequence: function (px, d, c) {
d = d || _.rtoken(/^\s*/);
c = c || null;
if (px.length == 1) {
return px[0];
}
return function (s) {
var r = null,
q = null;
var rx = [];
for (var i = 0; i < px.length; i++) {
try {
r = px[i].call(this, s);
} catch (e) {
break;
}
rx.push(r[0]);
try {
q = d.call(this, r[1]);
} catch (ex) {
q = null;
break;
}
s = q[1];
}
if (!r) {
throw new $P.Exception(s);
}
if (q) {
throw new $P.Exception(q[1]);
}
if (c) {
try {
r = c.call(this, r[1]);
} catch (ey) {
throw new $P.Exception(r[1]);
}
}
return [rx, (r ? r[1] : s)];
};
},
between: function (d1, p, d2) {
d2 = d2 || d1;
var _fn = _.each(_.ignore(d1), p, _.ignore(d2));
return function (s) {
var rx = _fn.call(this, s);
return [
[rx[0][0], r[0][2]], rx[1]
];
};
},
list: function (p, d, c) {
d = d || _.rtoken(/^\s*/);
c = c || null;
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)));
},
set: function (px, d, c) {
d = d || _.rtoken(/^\s*/);
c = c || null;
return function (s) {
var r = null,
p = null,
q = null,
rx = null,
best = [
[], s
],
last = false;
for (var i = 0; i < px.length; i++) {
q = null;
p = null;
r = null;
last = (px.length == 1);
try {
r = px[i].call(this, s);
} catch (e) {
continue;
}
rx = [
[r[0]], r[1]
];
if (r[1].length > 0 && !last) {
try {
q = d.call(this, r[1]);
} catch (ex) {
last = true;
}
} else {
last = true;
}
if (!last && q[1].length === 0) {
last = true;
}
if (!last) {
var qx = [];
for (var j = 0; j < px.length; j++) {
if (i != j) {
qx.push(px[j]);
}
}
p = _.set(qx, d).call(this, q[1]);
if (p[0].length > 0) {
rx[0] = rx[0].concat(p[0]);
rx[1] = p[1];
}
}
if (rx[1].length < best[1].length) {
best = rx;
}
if (best[1].length === 0) {
break;
}
}
if (best[0].length === 0) {
return best;
}
if (c) {
try {
q = c.call(this, best[1]);
} catch (ey) {
throw new $P.Exception(best[1]);
}
best[1] = q[1];
}
return best;
};
},
forward: function (gr, fname) {
return function (s) {
return gr[fname].call(this, s);
};
},
replace: function (rule, repl) {
return function (s) {
var r = rule.call(this, s);
return [repl, r[1]];
};
},
process: function (rule, fn) {
return function (s) {
var r = rule.call(this, s);
return [fn.call(this, r[0]), r[1]];
};
},
min: function (min, rule) {
return function (s) {
var rx = rule.call(this, s);
if (rx[0].length < min) {
throw new $P.Exception(s);
}
return rx;
};
}
};
var _generator = function (op) {
return function () {
var args = null,
rx = [];
if (arguments.length > 1) {
args = Array.prototype.slice.call(arguments);
} else if (arguments[0] instanceof Array) {
args = arguments[0];
}
if (args) {
for (var i = 0, px = args.shift(); i < px.length; i++) {
args.unshift(px[i]);
rx.push(op.apply(null, args));
args.shift();
return rx;
}
} else {
return op.apply(null, arguments);
}
};
};
var gx = "optional not ignore cache".split(/\s/);
for (var i = 0; i < gx.length; i++) {
_[gx[i]] = _generator(_[gx[i]]);
}
var _vector = function (op) {
return function () {
if (arguments[0] instanceof Array) {
return op.apply(null, arguments[0]);
} else {
return op.apply(null, arguments);
}
};
};
var vx = "each any all".split(/\s/);
for (var j = 0; j < vx.length; j++) {
_[vx[j]] = _vector(_[vx[j]]);
}
}());
(function () {
var $D = Date,
$P = $D.prototype,
$C = $D.CultureInfo;
var flattenAndCompact = function (ax) {
var rx = [];
for (var i = 0; i < ax.length; i++) {
if (ax[i] instanceof Array) {
rx = rx.concat(flattenAndCompact(ax[i]));
} else {
if (ax[i]) {
rx.push(ax[i]);
}
}
}
return rx;
};
$D.Grammar = {};
$D.Translator = {
hour: function (s) {
return function () {
this.hour = Number(s);
};
},
minute: function (s) {
return function () {
this.minute = Number(s);
};
},
second: function (s) {
return function () {
this.second = Number(s);
};
},
meridian: function (s) {
return function () {
this.meridian = s.slice(0, 1).toLowerCase();
};
},
timezone: function (s) {
return function () {
var n = s.replace(/[^\d\+\-]/g, "");
if (n.length) {
this.timezoneOffset = Number(n);
} else {
this.timezone = s.toLowerCase();
}
};
},
day: function (x) {
var s = x[0];
return function () {
this.day = Number(s.match(/\d+/)[0]);
};
},
month: function (s) {
return function () {
this.month = (s.length == 3) ? "jan feb mar apr may jun jul aug sep oct nov dec".indexOf(s) / 4 : Number(s) - 1;
};
},
year: function (s) {
return function () {
var n = Number(s);
this.year = ((s.length > 2) ? n : (n + (((n + 2000) < $C.twoDigitYearMax) ? 2000 : 1900)));
};
},
rday: function (s) {
return function () {
switch (s) {
case "yesterday":
this.days = -1;
break;
case "tomorrow":
this.days = 1;
break;
case "today":
this.days = 0;
break;
case "now":
this.days = 0;
this.now = true;
break;
}
};
},
finishExact: function (x) {
x = (x instanceof Array) ? x : [x];
for (var i = 0; i < x.length; i++) {
if (x[i]) {
x[i].call(this);
}
}
var now = new Date();
if ((this.hour || this.minute) && (!this.month && !this.year && !this.day)) {
this.day = now.getDate();
}
if (!this.year) {
this.year = now.getFullYear();
}
if (!this.month && this.month !== 0) {
this.month = now.getMonth();
}
if (!this.day) {
this.day = 1;
}
if (!this.hour) {
this.hour = 0;
}
if (!this.minute) {
this.minute = 0;
}
if (!this.second) {
this.second = 0;
}
if (this.meridian && this.hour) {
if (this.meridian == "p" && this.hour < 12) {
this.hour = this.hour + 12;
} else if (this.meridian == "a" && this.hour == 12) {
this.hour = 0;
}
}
if (this.day > $D.getDaysInMonth(this.year, this.month)) {
throw new RangeError(this.day + " is not a valid value for days.");
}
var r = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second);
if (this.timezone) {
r.set({
timezone: this.timezone
});
} else if (this.timezoneOffset) {
r.set({
timezoneOffset: this.timezoneOffset
});
}
return r;
},
finish: function (x) {
x = (x instanceof Array) ? flattenAndCompact(x) : [x];
if (x.length === 0) {
return null;
}
for (var i = 0; i < x.length; i++) {
if (typeof x[i] == "function") {
x[i].call(this);
}
}
var today = $D.today();
if (this.now && !this.unit && !this.operator) {
return new Date();
} else if (this.now) {
today = new Date();
}
var expression = !!(this.days && this.days !== null || this.orient || this.operator);
var gap, mod, orient;
orient = ((this.orient == "past" || this.operator == "subtract") ? -1 : 1);
if (!this.now && "hour minute second".indexOf(this.unit) != -1) {
today.setTimeToNow();
}
if (this.month || this.month === 0) {
if ("year day hour minute second".indexOf(this.unit) != -1) {
this.value = this.month + 1;
this.month = null;
expression = true;
}
}
if (!expression && this.weekday && !this.day && !this.days) {
var temp = Date[this.weekday]();
this.day = temp.getDate();
if (!this.month) {
this.month = temp.getMonth();
}
this.year = temp.getFullYear();
}
if (expression && this.weekday && this.unit != "month") {
this.unit = "day";
gap = ($D.getDayNumberFromName(this.weekday) - today.getDay());
mod = 7;
this.days = gap ? ((gap + (orient * mod)) % mod) : (orient * mod);
}
if (this.month && this.unit == "day" && this.operator) {
this.value = (this.month + 1);
this.month = null;
}
if (this.value != null && this.month != null && this.year != null) {
this.day = this.value * 1;
}
if (this.month && !this.day && this.value) {
today.set({
day: this.value * 1
});
if (!expression) {
this.day = this.value * 1;
}
}
if (!this.month && this.value && this.unit == "month" && !this.now) {
this.month = this.value;
expression = true;
}
if (expression && (this.month || this.month === 0) && this.unit != "year") {
this.unit = "month";
gap = (this.month - today.getMonth());
mod = 12;
this.months = gap ? ((gap + (orient * mod)) % mod) : (orient * mod);
this.month = null;
}
if (!this.unit) {
this.unit = "day";
}
if (!this.value && this.operator && this.operator !== null && this[this.unit + "s"] && this[this.unit + "s"] !== null) {
this[this.unit + "s"] = this[this.unit + "s"] + ((this.operator == "add") ? 1 : -1) + (this.value || 0) * orient;
} else if (this[this.unit + "s"] == null || this.operator != null) {
if (!this.value) {
this.value = 1;
}
this[this.unit + "s"] = this.value * orient;
}
if (this.meridian && this.hour) {
if (this.meridian == "p" && this.hour < 12) {
this.hour = this.hour + 12;
} else if (this.meridian == "a" && this.hour == 12) {
this.hour = 0;
}
}
if (this.weekday && !this.day && !this.days) {
var temp = Date[this.weekday]();
this.day = temp.getDate();
if (temp.getMonth() !== today.getMonth()) {
this.month = temp.getMonth();
}
}
if ((this.month || this.month === 0) && !this.day) {
this.day = 1;
}
if (!this.orient && !this.operator && this.unit == "week" && this.value && !this.day && !this.month) {
return Date.today().setWeek(this.value);
}
if (expression && this.timezone && this.day && this.days) {
this.day = this.days;
}
return (expression) ? today.add(this) : today.set(this);
}
};
var _ = $D.Parsing.Operators,
g = $D.Grammar,
t = $D.Translator,
_fn;
g.datePartDelimiter = _.rtoken(/^([\s\-\.\,\/\x27]+)/);
g.timePartDelimiter = _.stoken(":");
g.whiteSpace = _.rtoken(/^\s*/);
g.generalDelimiter = _.rtoken(/^(([\s\,]|at|@|on)+)/);
var _C = {};
g.ctoken = function (keys) {
var fn = _C[keys];
if (!fn) {
var c = $C.regexPatterns;
var kx = keys.split(/\s+/),
px = [];
for (var i = 0; i < kx.length; i++) {
px.push(_.replace(_.rtoken(c[kx[i]]), kx[i]));
}
fn = _C[keys] = _.any.apply(null, px);
}
return fn;
};
g.ctoken2 = function (key) {
return _.rtoken($C.regexPatterns[key]);
};
g.h = _.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/), t.hour));
g.hh = _.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/), t.hour));
g.H = _.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/), t.hour));
g.HH = _.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/), t.hour));
g.m = _.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/), t.minute));
g.mm = _.cache(_.process(_.rtoken(/^[0-5][0-9]/), t.minute));
g.s = _.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/), t.second));
g.ss = _.cache(_.process(_.rtoken(/^[0-5][0-9]/), t.second));
g.hms = _.cache(_.sequence([g.H, g.m, g.s], g.timePartDelimiter));
g.t = _.cache(_.process(g.ctoken2("shortMeridian"), t.meridian));
g.tt = _.cache(_.process(g.ctoken2("longMeridian"), t.meridian));
g.z = _.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/), t.timezone));
g.zz = _.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/), t.timezone));
g.zzz = _.cache(_.process(g.ctoken2("timezone"), t.timezone));
g.timeSuffix = _.each(_.ignore(g.whiteSpace), _.set([g.tt, g.zzz]));
g.time = _.each(_.optional(_.ignore(_.stoken("T"))), g.hms, g.timeSuffix);
g.d = _.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/), _.optional(g.ctoken2("ordinalSuffix"))), t.day));
g.dd = _.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/), _.optional(g.ctoken2("ordinalSuffix"))), t.day));
g.ddd = g.dddd = _.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"), function (s) {
return function () {
this.weekday = s;
};
}));
g.M = _.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/), t.month));
g.MM = _.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/), t.month));
g.MMM = g.MMMM = _.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"), t.month));
g.y = _.cache(_.process(_.rtoken(/^(\d\d?)/), t.year));
g.yy = _.cache(_.process(_.rtoken(/^(\d\d)/), t.year));
g.yyy = _.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/), t.year));
g.yyyy = _.cache(_.process(_.rtoken(/^(\d\d\d\d)/), t.year));
_fn = function () {
return _.each(_.any.apply(null, arguments), _.not(g.ctoken2("timeContext")));
};
g.day = _fn(g.d, g.dd);
g.month = _fn(g.M, g.MMM);
g.year = _fn(g.yyyy, g.yy);
g.orientation = _.process(g.ctoken("past future"), function (s) {
return function () {
this.orient = s;
};
});
g.operator = _.process(g.ctoken("add subtract"), function (s) {
return function () {
this.operator = s;
};
});
g.rday = _.process(g.ctoken("yesterday tomorrow today now"), t.rday);
g.unit = _.process(g.ctoken("second minute hour day week month year"), function (s) {
return function () {
this.unit = s;
};
});
g.value = _.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/), function (s) {
return function () {
this.value = s.replace(/\D/g, "");
};
});
g.expression = _.set([g.rday, g.operator, g.value, g.unit, g.orientation, g.ddd, g.MMM]);
_fn = function () {
return _.set(arguments, g.datePartDelimiter);
};
g.mdy = _fn(g.ddd, g.month, g.day, g.year);
g.ymd = _fn(g.ddd, g.year, g.month, g.day);
g.dmy = _fn(g.ddd, g.day, g.month, g.year);
g.date = function (s) {
return ((g[$C.dateElementOrder] || g.mdy).call(this, s));
};
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) {
if (g[fmt]) {
return g[fmt];
} else {
throw $D.Parsing.Exception(fmt);
}
}), _.process(_.rtoken(/^[^dMyhHmstz]+/), function (s) {
return _.ignore(_.stoken(s));
}))), function (rules) {
return _.process(_.each.apply(null, rules), t.finishExact);
});
var _F = {};
var _get = function (f) {
return _F[f] = (_F[f] || g.format(f)[0]);
};
g.formats = function (fx) {
if (fx instanceof Array) {
var rx = [];
for (var i = 0; i < fx.length; i++) {
rx.push(_get(fx[i]));
}
return _.any.apply(null, rx);
} else {
return _get(fx);
}
};
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"]);
g._start = _.process(_.set([g.date, g.time, g.expression], g.generalDelimiter, g.whiteSpace), t.finish);
g.start = function (s) {
try {
var r = g._formats.call({}, s);
if (r[1].length === 0) {
return r;
}
} catch (e) {}
return g._start.call({}, s);
};
$D._parse = $D.parse;
$D.parse = function (s) {
var r = null;
if (!s) {
return null;
}
if (s instanceof Date) {
return s;
}
try {
r = $D.Grammar.start.call({}, s.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1"));
} catch (e) {
return null;
}
return ((r[1].length === 0) ? r[0] : null);
};
$D.getParseFunction = function (fx) {
var fn = $D.Grammar.formats(fx);
return function (s) {
var r = null;
try {
r = fn.call({}, s);
} catch (e) {
return null;
}
return ((r[1].length === 0) ? r[0] : null);
};
};
$D.parseExact = function (s, fx) {
return $D.getParseFunction(fx)(s);
};
}());
// module.exports = {
// Date:Date
// }
module.exports = Date;
\ No newline at end of file
This diff could not be displayed because it is too large.
var __request = wx.request;
var Mock = require("./mock.js");
// console.log('Mock', Mock)
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;
!(function () {
// alignment pattern
var adelta = [
0, 11, 15, 19, 23, 27, 31,
16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24,
26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28
];
// version block
var vpat = [
0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d,
0x928, 0xb78, 0x45d, 0xa17, 0x532, 0x9a6, 0x683, 0x8c9,
0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75,
0x250, 0x9d5, 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64,
0x541, 0xc69
];
// final format bits with mask: level << 3 | mask
var fmtword = [
0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, //L
0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, //M
0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, //Q
0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b //H
];
// 4 per version: number of blocks 1,2; data width; ecc width
var eccblocks = [
1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17,
1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28,
1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22,
1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16,
1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22,
2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28,
2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26,
2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26,
2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24,
2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28,
4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24,
2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28,
4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22,
3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24,
5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24,
5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30,
1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28,
5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28,
3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26,
3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28,
4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30,
2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24,
4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30,
6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30,
8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30,
10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30,
8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30,
3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30,
7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30,
5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30,
13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30,
17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30,
17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30,
13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30,
12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30,
6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30,
17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30,
4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30,
20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30,
19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30
];
// Galois field log table
var glog = [
0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
];
// Galios field exponent table
var gexp = [
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00
];
// Working buffers:
// data input and ecc append, image working buffer, fixed part of image, run lengths for badness
var strinbuf = [], eccbuf = [], qrframe = [], framask = [], rlens = [];
// Control values - width is based on version, last 4 are from table.
var version, width, neccblk1, neccblk2, datablkw, eccblkwid;
var ecclevel = 2;
// set bit to indicate cell in qrframe is immutable. symmetric around diagonal
function setmask(x, y) {
var bt;
if (x > y) {
bt = x;
x = y;
y = bt;
}
// y*y = 1+3+5...
bt = y;
bt *= y;
bt += y;
bt >>= 1;
bt += x;
framask[bt] = 1;
}
// enter alignment pattern - black to qrframe, white to mask (later black frame merged to mask)
function putalign(x, y) {
var j;
qrframe[x + width * y] = 1;
for (j = -2; j < 2; j++) {
qrframe[(x + j) + width * (y - 2)] = 1;
qrframe[(x - 2) + width * (y + j + 1)] = 1;
qrframe[(x + 2) + width * (y + j)] = 1;
qrframe[(x + j + 1) + width * (y + 2)] = 1;
}
for (j = 0; j < 2; j++) {
setmask(x - 1, y + j);
setmask(x + 1, y - j);
setmask(x - j, y - 1);
setmask(x + j, y + 1);
}
}
//========================================================================
// Reed Solomon error correction
// exponentiation mod N
function modnn(x) {
while (x >= 255) {
x -= 255;
x = (x >> 8) + (x & 255);
}
return x;
}
var genpoly = [];
// Calculate and append ECC data to data block. Block is in strinbuf, indexes to buffers given.
function appendrs(data, dlen, ecbuf, eclen) {
var i, j, fb;
for (i = 0; i < eclen; i++)
strinbuf[ecbuf + i] = 0;
for (i = 0; i < dlen; i++) {
fb = glog[strinbuf[data + i] ^ strinbuf[ecbuf]];
if (fb != 255) /* fb term is non-zero */
for (j = 1; j < eclen; j++)
strinbuf[ecbuf + j - 1] = strinbuf[ecbuf + j] ^ gexp[modnn(fb + genpoly[eclen - j])];
else
for (j = ecbuf; j < ecbuf + eclen; j++)
strinbuf[j] = strinbuf[j + 1];
strinbuf[ecbuf + eclen - 1] = fb == 255 ? 0 : gexp[modnn(fb + genpoly[0])];
}
}
//========================================================================
// Frame data insert following the path rules
// check mask - since symmetrical use half.
function ismasked(x, y) {
var bt;
if (x > y) {
bt = x;
x = y;
y = bt;
}
bt = y;
bt += y * y;
bt >>= 1;
bt += x;
return framask[bt];
}
//========================================================================
// Apply the selected mask out of the 8.
function applymask(m) {
var x, y, r3x, r3y;
switch (m) {
case 0:
for (y = 0; y < width; y++)
for (x = 0; x < width; x++)
if (!((x + y) & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
break;
case 1:
for (y = 0; y < width; y++)
for (x = 0; x < width; x++)
if (!(y & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
break;
case 2:
for (y = 0; y < width; y++)
for (r3x = 0, x = 0; x < width; x++ , r3x++) {
if (r3x == 3)
r3x = 0;
if (!r3x && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
break;
case 3:
for (r3y = 0, y = 0; y < width; y++ , r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = r3y, x = 0; x < width; x++ , r3x++) {
if (r3x == 3)
r3x = 0;
if (!r3x && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
case 4:
for (y = 0; y < width; y++)
for (r3x = 0, r3y = ((y >> 1) & 1), x = 0; x < width; x++ , r3x++) {
if (r3x == 3) {
r3x = 0;
r3y = !r3y;
}
if (!r3y && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
break;
case 5:
for (r3y = 0, y = 0; y < width; y++ , r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = 0, x = 0; x < width; x++ , r3x++) {
if (r3x == 3)
r3x = 0;
if (!((x & y & 1) + !(!r3x | !r3y)) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
case 6:
for (r3y = 0, y = 0; y < width; y++ , r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = 0, x = 0; x < width; x++ , r3x++) {
if (r3x == 3)
r3x = 0;
if (!(((x & y & 1) + (r3x && (r3x == r3y))) & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
case 7:
for (r3y = 0, y = 0; y < width; y++ , r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = 0, x = 0; x < width; x++ , r3x++) {
if (r3x == 3)
r3x = 0;
if (!(((r3x && (r3x == r3y)) + ((x + y) & 1)) & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
}
return;
}
// Badness coefficients.
var N1 = 3, N2 = 3, N3 = 40, N4 = 10;
// Using the table of the length of each run, calculate the amount of bad image
// - long runs or those that look like finders; called twice, once each for X and Y
function badruns(length) {
var i;
var runsbad = 0;
for (i = 0; i <= length; i++)
if (rlens[i] >= 5)
runsbad += N1 + rlens[i] - 5;
// BwBBBwB as in finder
for (i = 3; i < length - 1; i += 2)
if (rlens[i - 2] == rlens[i + 2]
&& rlens[i + 2] == rlens[i - 1]
&& rlens[i - 1] == rlens[i + 1]
&& rlens[i - 1] * 3 == rlens[i]
// white around the black pattern? Not part of spec
&& (rlens[i - 3] == 0 // beginning
|| i + 3 > length // end
|| rlens[i - 3] * 3 >= rlens[i] * 4 || rlens[i + 3] * 3 >= rlens[i] * 4)
)
runsbad += N3;
return runsbad;
}
// Calculate how bad the masked image is - blocks, imbalance, runs, or finders.
function badcheck() {
var x, y, h, b, b1;
var thisbad = 0;
var bw = 0;
// blocks of same color.
for (y = 0; y < width - 1; y++)
for (x = 0; x < width - 1; x++)
if ((qrframe[x + width * y] && qrframe[(x + 1) + width * y]
&& qrframe[x + width * (y + 1)] && qrframe[(x + 1) + width * (y + 1)]) // all black
|| !(qrframe[x + width * y] || qrframe[(x + 1) + width * y]
|| qrframe[x + width * (y + 1)] || qrframe[(x + 1) + width * (y + 1)])) // all white
thisbad += N2;
// X runs
for (y = 0; y < width; y++) {
rlens[0] = 0;
for (h = b = x = 0; x < width; x++) {
if ((b1 = qrframe[x + width * y]) == b)
rlens[h]++;
else
rlens[++h] = 1;
b = b1;
bw += b ? 1 : -1;
}
thisbad += badruns(h);
}
// black/white imbalance
if (bw < 0)
bw = -bw;
var big = bw;
var count = 0;
big += big << 2;
big <<= 1;
while (big > width * width)
big -= width * width, count++;
thisbad += count * N4;
// Y runs
for (x = 0; x < width; x++) {
rlens[0] = 0;
for (h = b = y = 0; y < width; y++) {
if ((b1 = qrframe[x + width * y]) == b)
rlens[h]++;
else
rlens[++h] = 1;
b = b1;
}
thisbad += badruns(h);
}
return thisbad;
}
function genframe(instring) {
var x, y, k, t, v, i, j, m;
// find the smallest version that fits the string
t = instring.length;
version = 0;
do {
version++;
k = (ecclevel - 1) * 4 + (version - 1) * 16;
neccblk1 = eccblocks[k++];
neccblk2 = eccblocks[k++];
datablkw = eccblocks[k++];
eccblkwid = eccblocks[k];
k = datablkw * (neccblk1 + neccblk2) + neccblk2 - 3 + (version <= 9);
if (t <= k)
break;
} while (version < 40);
// FIXME - insure that it fits insted of being truncated
width = 17 + 4 * version;
// allocate, clear and setup data structures
v = datablkw + (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
for (t = 0; t < v; t++)
eccbuf[t] = 0;
strinbuf = instring.slice(0);
for (t = 0; t < width * width; t++)
qrframe[t] = 0;
for (t = 0; t < (width * (width + 1) + 1) / 2; t++)
framask[t] = 0;
// insert finders - black to frame, white to mask
for (t = 0; t < 3; t++) {
k = 0;
y = 0;
if (t == 1)
k = (width - 7);
if (t == 2)
y = (width - 7);
qrframe[(y + 3) + width * (k + 3)] = 1;
for (x = 0; x < 6; x++) {
qrframe[(y + x) + width * k] = 1;
qrframe[y + width * (k + x + 1)] = 1;
qrframe[(y + 6) + width * (k + x)] = 1;
qrframe[(y + x + 1) + width * (k + 6)] = 1;
}
for (x = 1; x < 5; x++) {
setmask(y + x, k + 1);
setmask(y + 1, k + x + 1);
setmask(y + 5, k + x);
setmask(y + x + 1, k + 5);
}
for (x = 2; x < 4; x++) {
qrframe[(y + x) + width * (k + 2)] = 1;
qrframe[(y + 2) + width * (k + x + 1)] = 1;
qrframe[(y + 4) + width * (k + x)] = 1;
qrframe[(y + x + 1) + width * (k + 4)] = 1;
}
}
// alignment blocks
if (version > 1) {
t = adelta[version];
y = width - 7;
for (; ;) {
x = width - 7;
while (x > t - 3) {
putalign(x, y);
if (x < t)
break;
x -= t;
}
if (y <= t + 9)
break;
y -= t;
putalign(6, y);
putalign(y, 6);
}
}
// single black
qrframe[8 + width * (width - 8)] = 1;
// timing gap - mask only
for (y = 0; y < 7; y++) {
setmask(7, y);
setmask(width - 8, y);
setmask(7, y + width - 7);
}
for (x = 0; x < 8; x++) {
setmask(x, 7);
setmask(x + width - 8, 7);
setmask(x, width - 8);
}
// reserve mask-format area
for (x = 0; x < 9; x++)
setmask(x, 8);
for (x = 0; x < 8; x++) {
setmask(x + width - 8, 8);
setmask(8, x);
}
for (y = 0; y < 7; y++)
setmask(8, y + width - 7);
// timing row/col
for (x = 0; x < width - 14; x++)
if (x & 1) {
setmask(8 + x, 6);
setmask(6, 8 + x);
}
else {
qrframe[(8 + x) + width * 6] = 1;
qrframe[6 + width * (8 + x)] = 1;
}
// version block
if (version > 6) {
t = vpat[version - 7];
k = 17;
for (x = 0; x < 6; x++)
for (y = 0; y < 3; y++ , k--)
if (1 & (k > 11 ? version >> (k - 12) : t >> k)) {
qrframe[(5 - x) + width * (2 - y + width - 11)] = 1;
qrframe[(2 - y + width - 11) + width * (5 - x)] = 1;
}
else {
setmask(5 - x, 2 - y + width - 11);
setmask(2 - y + width - 11, 5 - x);
}
}
// sync mask bits - only set above for white spaces, so add in black bits
for (y = 0; y < width; y++)
for (x = 0; x <= y; x++)
if (qrframe[x + width * y])
setmask(x, y);
// convert string to bitstream
// 8 bit data to QR-coded 8 bit data (numeric or alphanum, or kanji not supported)
v = strinbuf.length;
// string to array
for (i = 0; i < v; i++)
eccbuf[i] = strinbuf.charCodeAt(i);
strinbuf = eccbuf.slice(0);
// calculate max string length
x = datablkw * (neccblk1 + neccblk2) + neccblk2;
if (v >= x - 2) {
v = x - 2;
if (version > 9)
v--;
}
// shift and repack to insert length prefix
i = v;
if (version > 9) {
strinbuf[i + 2] = 0;
strinbuf[i + 3] = 0;
while (i--) {
t = strinbuf[i];
strinbuf[i + 3] |= 255 & (t << 4);
strinbuf[i + 2] = t >> 4;
}
strinbuf[2] |= 255 & (v << 4);
strinbuf[1] = v >> 4;
strinbuf[0] = 0x40 | (v >> 12);
}
else {
strinbuf[i + 1] = 0;
strinbuf[i + 2] = 0;
while (i--) {
t = strinbuf[i];
strinbuf[i + 2] |= 255 & (t << 4);
strinbuf[i + 1] = t >> 4;
}
strinbuf[1] |= 255 & (v << 4);
strinbuf[0] = 0x40 | (v >> 4);
}
// fill to end with pad pattern
i = v + 3 - (version < 10);
while (i < x) {
strinbuf[i++] = 0xec;
// buffer has room if (i == x) break;
strinbuf[i++] = 0x11;
}
// calculate and append ECC
// calculate generator polynomial
genpoly[0] = 1;
for (i = 0; i < eccblkwid; i++) {
genpoly[i + 1] = 1;
for (j = i; j > 0; j--)
genpoly[j] = genpoly[j]
? genpoly[j - 1] ^ gexp[modnn(glog[genpoly[j]] + i)] : genpoly[j - 1];
genpoly[0] = gexp[modnn(glog[genpoly[0]] + i)];
}
for (i = 0; i <= eccblkwid; i++)
genpoly[i] = glog[genpoly[i]]; // use logs for genpoly[] to save calc step
// append ecc to data buffer
k = x;
y = 0;
for (i = 0; i < neccblk1; i++) {
appendrs(y, datablkw, k, eccblkwid);
y += datablkw;
k += eccblkwid;
}
for (i = 0; i < neccblk2; i++) {
appendrs(y, datablkw + 1, k, eccblkwid);
y += datablkw + 1;
k += eccblkwid;
}
// interleave blocks
y = 0;
for (i = 0; i < datablkw; i++) {
for (j = 0; j < neccblk1; j++)
eccbuf[y++] = strinbuf[i + j * datablkw];
for (j = 0; j < neccblk2; j++)
eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
}
for (j = 0; j < neccblk2; j++)
eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
for (i = 0; i < eccblkwid; i++)
for (j = 0; j < neccblk1 + neccblk2; j++)
eccbuf[y++] = strinbuf[x + i + j * eccblkwid];
strinbuf = eccbuf;
// pack bits into frame avoiding masked area.
x = y = width - 1;
k = v = 1; // up, minus
/* inteleaved data and ecc codes */
m = (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
for (i = 0; i < m; i++) {
t = strinbuf[i];
for (j = 0; j < 8; j++ , t <<= 1) {
if (0x80 & t)
qrframe[x + width * y] = 1;
do { // find next fill position
if (v)
x--;
else {
x++;
if (k) {
if (y != 0)
y--;
else {
x -= 2;
k = !k;
if (x == 6) {
x--;
y = 9;
}
}
}
else {
if (y != width - 1)
y++;
else {
x -= 2;
k = !k;
if (x == 6) {
x--;
y -= 8;
}
}
}
}
v = !v;
} while (ismasked(x, y));
}
}
// save pre-mask copy of frame
strinbuf = qrframe.slice(0);
t = 0; // best
y = 30000; // demerit
// for instead of while since in original arduino code
// if an early mask was "good enough" it wouldn't try for a better one
// since they get more complex and take longer.
for (k = 0; k < 8; k++) {
applymask(k); // returns black-white imbalance
x = badcheck();
if (x < y) { // current mask better than previous best?
y = x;
t = k;
}
if (t == 7)
break; // don't increment i to a void redoing mask
qrframe = strinbuf.slice(0); // reset for next pass
}
if (t != k) // redo best mask - none good enough, last wasn't t
applymask(t);
// add in final mask/ecclevel bytes
y = fmtword[t + ((ecclevel - 1) << 3)];
// low byte
for (k = 0; k < 8; k++ , y >>= 1)
if (y & 1) {
qrframe[(width - 1 - k) + width * 8] = 1;
if (k < 6)
qrframe[8 + width * k] = 1;
else
qrframe[8 + width * (k + 1)] = 1;
}
// high byte
for (k = 0; k < 7; k++ , y >>= 1)
if (y & 1) {
qrframe[8 + width * (width - 7 + k)] = 1;
if (k)
qrframe[(6 - k) + width * 8] = 1;
else
qrframe[7 + width * 8] = 1;
}
return qrframe;
}
var _canvas = null;
var api = {
get ecclevel() {
return ecclevel;
},
set ecclevel(val) {
ecclevel = val;
},
get size() {
return _size;
},
set size(val) {
_size = val
},
get canvas() {
return _canvas;
},
set canvas(el) {
_canvas = el;
},
getFrame: function (string) {
return genframe(string);
},
//这里的utf16to8(str)是对Text中的字符串进行转码,让其支持中文
utf16to8: function (str) {
var out, i, len, c;
out = "";
len = str.length;
for (i = 0; i < len; i++) {
c = str.charCodeAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out += str.charAt(i);
} else if (c > 0x07FF) {
out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
} else {
out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
}
}
return out;
},
/**
* 新增$this参数,传入组件的this,兼容在组件中生成
*/
draw: function (str, canvas, cavW, cavH, $this, ecc) {
var that = this;
ecclevel = ecc || ecclevel;
canvas = canvas || _canvas;
if (!canvas) {
console.warn('No canvas provided to draw QR code in!')
return;
}
var size = Math.min(cavW, cavH);
str = that.utf16to8(str);//增加中文显示
var frame = that.getFrame(str),
// 组件中生成qrcode需要绑定this
ctx = wx.createCanvasContext(canvas,$this),
px = Math.round(size / (width + 8));
var roundedSize = px * (width + 8),
offset = Math.floor((size - roundedSize) / 2);
size = roundedSize;
//ctx.clearRect(0, 0, cavW, cavW);
ctx.setFillStyle('#ffffff')
ctx.fillRect(0, 0, cavW, cavW);
ctx.setFillStyle('#000000');
for (var i = 0; i < width; i++) {
for (var j = 0; j < width; j++) {
if (frame[j * width + i]) {
ctx.fillRect(px * (4 + i) + offset, px * (4 + j) + offset, px, px);
}
}
}
ctx.draw();
}
}
module.exports = { api }
// exports.draw = api;
})();
\ No newline at end of file
function setItem(key, value, module_name) {
if (module_name) {
let module_name_info = getItem(module_name) || {};
module_name_info[key] = value;
try {
wx.setStorageSync(module_name, module_name_info);
} catch (e) {
wx.setStorage({
key: module_name,
data: module_name_info
})
}
} else {
try {
wx.setStorageSync(key, value);
} catch (e) {
wx.setStorage({
key: key,
data: value
})
}
}
}
function getItem(key, module_name) {
if (module_name) {
let val = getItem(module_name);
if (val) return val[key];
return '';
}
return wx.getStorageSync(key)
}
function clear(name) {
name ? wx.removeStorageSync(name) : wx.clearStorageSync()
}
module.exports = {
setItem,
getItem,
clear
}
// 手机正则
const REGEXPS = {
"mobile": /^1\d{10}$/
}
// 验证手机
function checkMobile(str) {
return REGEXPS.mobile.test(str);
}
/**
* 链接参数转换为obj
* 入参 完整链接
* @param {*} url
*/
function param2Obj(url) {
const search = url.split('?')[1]
if (!search) {
return {}
}
return JSON.parse(
'{"' +
decodeURIComponent(search)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"') +
'"}'
)
}
/**
* 格式化日期常规日期
* 格式yyyy-MM-dd hh:mm:ss
* @param {*} date
*/
function formatTime(date) {
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
var hour = date.getHours()
var minute = date.getMinutes()
var second = date.getSeconds()
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
/**
* 格式化数字,不足一位补充0
* @param {*} n
*/
function formatNumber(n) {
n = n.toString()
return n[1] ? n : '0' + n
}
/**
* 获取屏幕剩余高度
* useHeight 单位是rpx
* 默认返回单位是rpx 可通过unit参数改为 px
*/
function getLastScreenHeight(useHeight = 0, unit = 'rpx') {
let sysInfo = wx.getSystemInfoSync();
let clientHeight = sysInfo.windowHeight;
// 获取可使用窗口高度
let clientWidth = sysInfo.windowWidth;
// 算出比例
let ratio = 750 / clientWidth;
// 算出屏幕高度(单位rpx)
let height = clientHeight * ratio;
// 计算剩余高度
let lastHeight = height - useHeight;
// 可转换成px
if (unit == 'px') {
lastHeight = lastHeight / 750 * clientWidth
}
return lastHeight;
}
/**
* px转rpx
* @param {*} value
*/
function pxToRpx(value) {
let sysInfo = wx.getSystemInfoSync();
let clientWidth = sysInfo.windowWidth;
let result = value / 750 * clientWidth
return result;
}
// 格式化星期几
function formatWeek(week) {
let result = "";
switch (week) {
case 1:
result = "一";
break;
case 2:
result = "二";
break;
case 3:
result = "三";
break;
case 4:
result = "四";
break;
case 5:
result = "五";
break;
case 6:
result = "六";
break;
case 0:
result = "日";
break;
default:
break;
}
return result;
}
/**
* 获取点击传值
* @param {*} evt
* @param {*} key
*/
function getBindtapData(evt, key = "data") {
let keyStr = key || "data";
return evt.currentTarget.dataset[keyStr];
}
/**
* 从数组中获取 key未value的对象
* @param {*} value
* @param {*} key
* @param {*} list
*/
function getObjByListKeyValue(value, key, list) {
let result = null;
list.forEach(element => {
if (element[key + ""] == value) {
result = element;
}
});
return result;
}
/**
* 获取小程序码
* path = "/pages/index/index?pa=1"
* @param {*} path
*/
function wxacodeGet(path) {
return " https://api.k.wxpai.cn/bizproxy/mzcfsapi/qrcode/create?path=" + encodeURIComponent(path);
}
/**
* 根据url获取参数
* @param {*} name
*/
function getQueryByUrl(name, url) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(url) || [, ""])[1].replace(/\+/g, '%20')) || null;
}
/**
* @desc 函数防抖
* @param func 函数
* @param wait 延迟执行毫秒数
* @param immediate true 表立即执行,false 表非立即执行
*/
function debounce(func, wait, immediate) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
} else {
timeout = setTimeout(function () {
func.apply(context, args)
}, wait);
}
}
}
/**
* @desc 函数节流
* @param func 函数
* @param wait 延迟执行毫秒数
* @param type 1 表时间戳版,2 表定时器版
* 时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候。
*/
function throttle(func, wait, type) {
if (type === 1) {
var previous = 0;
} else if (type === 2) {
var timeout;
}
return function () {
let context = this;
let args = arguments;
if (type === 1) {
let now = Date.now();
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
} else if (type === 2) {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
}
module.exports = {
formatTime: formatTime,
checkMobile: checkMobile,
getLastScreenHeight: getLastScreenHeight,
debounce: debounce,
throttle: throttle,
param2Obj: param2Obj,
pxToRpx: pxToRpx,
formatWeek: formatWeek,
getBindtapData: getBindtapData,
wxacodeGet: wxacodeGet,
getObjByListKeyValue: getObjByListKeyValue,
getQueryByUrl: getQueryByUrl,
}
var wxTimer = function (initObj){
initObj = initObj || {};
this.beginTime = initObj.beginTime || "00:00:00"; //开始时间
this.interval = initObj.interval || 0; //间隔时间
this.complete = initObj.complete; //结束任务
this.intervalFn = initObj.intervalFn; //间隔任务
this.name = initObj.name; //当前计时器在计时器数组对象中的名字
this.intervarID; //计时ID
this.endTime; //结束时间
this.endSystemTime; //结束的系统时间
}
wxTimer.prototype = {
//开始
start:function(self){
this.endTime = new Date("1970/01/01 "+this.beginTime).getTime();//1970年1月1日的00:00:00的字符串日期
this.endSystemTime = new Date(Date.now() + this.endTime);
var that = this;
//开始倒计时
var count = 0;//这个count在这里应该是表示s数,js中获得时间是ms,所以下面*1000都换成ms
function begin(){
var tmpTime = new Date(that.endTime - 1000 * count++);
//把2011年1月1日日 00:00:00换成数字型,这样就可以直接1s,1s的减,就变成了倒计时,为了看的更明确,又用new date把字符串换回来了
var tmpTimeStr = tmpTime.toString().substr(16,8);//去掉前面的年月日就剩时分秒了
var wxTimerSecond = (tmpTime.getTime() - new Date("1970/01/01 00:00:00").getTime()) / 1000;
var wxTimerList = self.data.wxTimerList;
//更新计时器数组
wxTimerList[that.name] = {
wxTimer:tmpTimeStr,
wxTimerSecond:wxTimerSecond,
}
self.setData({
wxTimer:tmpTimeStr,
wxTimerSecond:wxTimerSecond,
wxTimerList:wxTimerList
});
//时间间隔执行函数
if( 0 == (count-1) % that.interval && that.intervalFn){
that.intervalFn();
}
//结束执行函数
if(wxTimerSecond <= 0){
if(that.complete){
that.complete();
}
that.stop();
}
}
begin();
this.intervarID = setInterval(begin,1000);
},
//结束
stop:function(){
clearInterval(this.intervarID);
},
//校准
calibration:function(){
this.endTime = this.endSystemTime - Date.now();
}
}
module.exports = wxTimer;