hookehuyr

🎉 init: 项目初始化

Showing 485 changed files with 11484 additions and 0 deletions
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
// ESLint 检查 .vue 文件需要单独配置编辑器:
// https://eslint.vuejs.org/user-guide/#editor-integrations
{
"extends": ["taro/vue3"]
}
dist/
deploy_versions/
.temp/
.rn_temp/
node_modules/
.DS_Store
doc
.history
// babel-preset-taro 更多选项和默认值:
// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
module.exports = {
presets: [
['taro', {
framework: 'vue3',
ts: false
}]
]
}
module.exports = {
env: {
NODE_ENV: '"development"',
// 添加SERVICES_BASE_URL变量
SERVICES_BASE_URL: '"http://xxx"',
},
defineConstants: {
},
mini: {},
h5: {}
}
const path = require('path')
const fs = require('fs')
const vantComponentNames = require("../vantComponentConf")
const handleGetPatterns = (keyArr) => {
// 这些为公共组件
const defaultArr = [
{
from: "src/components/vant-weapp/wxs",
to: "dist/components/vant-weapp/wxs",
},
{
from: "src/components/vant-weapp/common",
to: "dist/components/vant-weapp/common",
},
];
const componentArr = keyArr
.map((componentName) => {
// 同步检测这个文件是否存在
// 因为vant weapp部分组件文件下的不存在 wxs 文件
const componentPath = path.resolve(
__dirname,
`../src/components/vant-weapp/${componentName}/index.wxs`
);
const isState = fs.statSync(componentPath, { throwIfNoEntry: false });
return [
{
from: `src/components/vant-weapp/${componentName}/index.${isState ? "wxs" : "wxss"
}`,
to: `dist/components/vant-weapp/${componentName}/index.${isState ? "wxs" : "wxss"
}`,
},
{
from:
"src/components/vant-weapp/" + componentName + "/index.wxml",
to:
"dist/components/vant-weapp/" + componentName + "/index.wxml",
},
];
})
.flat(Infinity);
return [...defaultArr, ...componentArr];
};
const config = {
projectName: 'tswj-weapp',
date: '2022-5-27',
designWidth: 750,
deviceRatio: {
640: 2.34 / 2,
750: 1,
828: 1.81 / 2
},
alias: {
"@/utils": path.resolve(__dirname, "../src/utils"),
"@/vant": path.resolve(__dirname, "../src/components/vant-weapp"),
},
sourceRoot: 'src',
outputRoot: 'dist',
// outputRoot: `dist/${process.env.TARO_ENV}`,
plugins: [
'taro-plugin-pinia',
"tarojs-plugin-platform-miniprogram", // 自定义 wxml 支持
['@tarojs/plugin-framework-vue3', {
mini: {
compilerOptions: {
isCustomElement: tag => ["van-tab", "van-tabs"].includes(tag),
whitespace: 'preserve'
}
}
}],
'@tarojs/plugin-html'
],
defineConstants: {
},
copy: {
patterns: handleGetPatterns(vantComponentNames),
// patterns: [
// // 前面2个是基础的
// {
// from: "src/components/vant-weapp/wxs",
// to: "dist/components/vant-weapp/wxs",
// },
// {
// from: "src/components/vant-weapp/common",
// to: "dist/components/vant-weapp/common",
// },
// // 需要用到vant哪个组件就引入
// {
// from: "src/components/vant-weapp/button",
// to: "dist/components/vant-weapp/button",
// },
// {
// from: "src/components/vant-weapp/info",
// to: "dist/components/vant-weapp/info",
// },
// {
// from: "src/components/vant-weapp/icon",
// to: "dist/components/vant-weapp/icon",
// },
// {
// from: "src/components/vant-weapp/loading",
// to: "dist/components/vant-weapp/loading",
// },
// {
// from: "src/components/vant-weapp/tab",
// to: "dist/components/vant-weapp/tab",
// },
// {
// from: "src/components/vant-weapp/tabs",
// to: "dist/components/vant-weapp/tabs",
// },
// {
// from: "src/components/vant-weapp/sticky",
// to: "dist/components/vant-weapp/sticky",
// },
// ],
options: {
}
},
framework: 'vue3',
mini: {
optimizeMainPackage: {
enable: true
},
webpackChain(chain) {
chain.merge({
module: {
rule: {
mjsScript: {
test: /\.mjs$/,
include: [/pinia/],
use: {
babelLoader: {
loader: require.resolve('babel-loader')
}
}
}
}
}
})
},
postcss: {
pxtransform: {
enable: true,
config: {
// 过滤 vant 组件库的前缀:van-
selectorBlackList: [/van-/],
}
},
url: {
enable: true,
config: {
limit: 1024 // 设定转换尺寸上限
}
},
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
}
},
h5: {
publicPath: '/',
staticDirectory: 'static',
postcss: {
autoprefixer: {
enable: true,
config: {
}
},
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
}
}
}
module.exports = function (merge) {
if (process.env.NODE_ENV === 'development') {
return merge({}, config, require('./dev'))
}
return merge({}, config, require('./prod'))
}
module.exports = {
env: {
NODE_ENV: '"production"',
// 这里添加的 DEV_MODE_ENV 就起作用了,进行生产、开发区分,不用每次手动去改了
SERVICES_BASE_URL:
process.env.DEV_MODE_ENV === "true" ? "http://xxx" : "https://xxx",
// 代码里访问`process.env.SERVICES_BASE_URL`是可以正常获取到的
},
defineConstants: {
},
mini: {},
h5: {
/**
* 如果h5端编译后体积过大,可以使用webpack-bundle-analyzer插件对打包体积进行分析。
* 参考代码如下:
* webpackChain (chain) {
* chain.plugin('analyzer')
* .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, [])
* }
*/
}
}
{
"name": "swx-weapp",
"version": "1.0.0",
"private": true,
"description": "胜文轩小程序",
"templateInfo": {
"name": "vue3-pinia",
"typescript": false,
"css": "less"
},
"scripts": {
"build:weapp": "cross-env DEV_MODE_ENV=false taro build --type weapp",
"build:swan": "taro build --type swan",
"build:alipay": "taro build --type alipay",
"build:tt": "taro build --type tt",
"build:h5": "taro build --type h5",
"build:rn": "taro build --type rn",
"build:qq": "taro build --type qq",
"build:quickapp": "taro build --type quickapp",
"dev:weapp": "cross-env NODE_ENV=production DEV_MODE_ENV=true taro build --type weapp --watch",
"dev:swan": "npm run build:swan -- --watch",
"dev:alipay": "npm run build:alipay -- --watch",
"dev:tt": "npm run build:tt -- --watch",
"dev:h5": "npm run build:h5 -- --watch",
"dev:rn": "npm run build:rn -- --watch",
"dev:qq": "npm run build:qq -- --watch",
"dev:quickapp": "npm run build:quickapp -- --watch"
},
"browserslist": [
"last 3 versions",
"Android >= 4.1",
"ios >= 8"
],
"author": "",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.7.7",
"@tarojs/components": "3.4.10",
"@tarojs/plugin-framework-react": "^3.4.10",
"@tarojs/plugin-framework-vue3": "3.4.10",
"@tarojs/plugin-html": "^3.4.10",
"@tarojs/plugin-platform-weapp": "^3.4.10",
"@tarojs/runtime": "3.4.10",
"@tarojs/taro": "3.4.10",
"@vant/weapp": "^1.10.3",
"axios": "^0.27.2",
"axios-miniprogram": "^2.0.0-rc-2",
"pinia": "^2.0.6",
"taro-plugin-pinia": "^1.0.0",
"vant": "^4.0.0-alpha.3",
"vue": "^3.2.24"
},
"devDependencies": {
"@babel/core": "^7.8.0",
"@tarojs/mini-runner": "3.4.10",
"@tarojs/webpack-runner": "3.4.10",
"@types/webpack-env": "^1.13.6",
"babel-preset-taro": "3.4.10",
"cross-env": "^7.0.3",
"eslint": "^8.12.0",
"eslint-config-taro": "3.4.10",
"eslint-plugin-vue": "^8.0.0",
"stylelint": "9.3.0",
"tarojs-plugin-platform-miniprogram": "^0.1.1",
"vue-loader": "^16.8.3"
}
}
{
"miniprogramRoot": "./dist",
"projectname": "swx-weapp",
"description": "胜文轩小程序",
"appid": "touristappid",
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false,
"checkSiteMap": false
},
"compileType": "miniprogram"
}
{
"miniprogramRoot": "./",
"projectname": "swx-weapp",
"description": "胜文轩小程序",
"appid": "touristappid",
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false
},
"compileType": "miniprogram"
}
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-27 15:57:59
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-06 14:47:04
* @FilePath: /taro-vant-weapp/src/app.config.js
* @Description:
*/
const vantComponentNames = require("../vantComponentConf");
const getVantComponentConf = (arr) => {
const result = {};
arr.forEach((key) => {
result[`van-${key}`] = `./components/vant-weapp/${key}/index`;
});
return result;
};
export default {
pages: [
'pages/index/index',
'pages/foo/index',
],
subpackages: [ // 配置在tabBar中的页面不能分包写到subpackages中去
{
root: "pages/demo",
pages: ["index"],
},
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black'
},
usingComponents: {
...getVantComponentConf(vantComponentNames),
// "van-button": "./components/vant-weapp/button/index",
// "van-tab": "./components/vant-weapp/tab/index",
// "van-tabs": "./components/vant-weapp/tabs/index"
},
}
/*
* @Date: 2022-09-19 14:11:05
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-09-19 14:18:43
* @FilePath: /swx/src/app.js
* @Description: 文件描述
*/
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import './app.less'
const App = createApp({
// 可以使用所有的 Vue 生命周期方法
mounted () {},
// 对应 onLaunch
onLaunch () {},
// 对应 onShow
onShow (options) {},
// 对应 onHide
onHide () {},
// 入口组件不需要实现 render 方法,即使实现了也会被 taro 所覆盖
})
App.use(createPinia())
export default App
File mode changed
<template>
<view>
<text class="title">{{ counter.count }}</text>
<view class="button" @tap="onAdd">ADD</view>
</view>
</template>
<script>
import { useCounterStore } from '../stores/counter'
export default {
setup() {
const counter = useCounterStore()
const onAdd = () => {
counter.count++
// with autocompletion ✨
// counter.$patch({count: counter.count + 1})
// or using an action instead
// counter.increment()
}
return {
counter,
onAdd
}
}
}
</script>
<style>
.title {
font-size: 32px;
}
.button {
border: 1px solid lightgray;
padding: 5px 10px;
}
</style>
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
VantComponent({
mixins: [button],
props: {
show: Boolean,
title: String,
cancelText: String,
description: String,
round: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 100,
},
actions: {
type: Array,
value: [],
},
overlay: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
closeOnClickAction: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
methods: {
onSelect(event) {
const { index } = event.currentTarget.dataset;
const { actions, closeOnClickAction, canIUseGetUserProfile } = this.data;
const item = actions[index];
if (item) {
this.$emit('select', item);
if (closeOnClickAction) {
this.onClose();
}
if (item.openType === 'getUserInfo' && canIUseGetUserProfile) {
wx.getUserProfile({
desc: item.getUserProfileDesc || ' ',
complete: (userProfile) => {
this.$emit('getuserinfo', userProfile);
},
});
}
}
},
onCancel() {
this.$emit('cancel');
},
onClose() {
this.$emit('close');
},
onClickOverlay() {
this.$emit('click-overlay');
this.onClose();
},
},
});
{
"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"
round="{{ round }}"
z-index="{{ zIndex }}"
overlay="{{ overlay }}"
custom-class="van-action-sheet"
safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:close="onClickOverlay"
>
<view wx:if="{{ title }}" class="van-action-sheet__header">
{{ title }}
<van-icon
name="cross"
custom-class="van-action-sheet__close"
bind:click="onClose"
/>
</view>
<view wx:if="{{ description }}" class="van-action-sheet__description van-hairline--bottom">
{{ description }}
</view>
<view wx:if="{{ actions && actions.length }}">
<!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
<button
wx:for="{{ actions }}"
wx:key="index"
open-type="{{ item.disabled || item.loading || (canIUseGetUserProfile && item.openType === 'getUserInfo') ? '' : item.openType }}"
style="{{ item.color ? 'color: ' + item.color : '' }}"
class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} {{ item.className || '' }}"
hover-class="van-action-sheet__item--hover"
data-index="{{ index }}"
bindtap="{{ item.disabled || item.loading ? '' : 'onSelect' }}"
bindgetuserinfo="onGetUserInfo"
bindcontact="onContact"
bindgetphonenumber="onGetPhoneNumber"
binderror="onError"
bindlaunchapp="onLaunchApp"
bindopensetting="onOpenSetting"
lang="{{ lang }}"
session-from="{{ sessionFrom }}"
send-message-title="{{ sendMessageTitle }}"
send-message-path="{{ sendMessagePath }}"
send-message-img="{{ sendMessageImg }}"
show-message-card="{{ showMessageCard }}"
app-parameter="{{ appParameter }}"
>
<block wx:if="{{ !item.loading }}">
{{ item.name }}
<view wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</view>
</block>
<van-loading wx:else custom-class="van-action-sheet__loading" size="22px" />
</button>
</view>
<slot />
<block wx:if="{{ cancelText }}">
<view class="van-action-sheet__gap" />
<view
class="van-action-sheet__cancel"
hover-class="van-action-sheet__cancel--hover"
hover-stay-time="70"
bind:tap="onCancel"
>
{{ cancelText }}
</view>
</block>
</van-popup>
@import '../common/index.wxss';.van-action-sheet{color:var(--action-sheet-item-text-color,#323233);max-height:var(--action-sheet-max-height,90%)!important}.van-action-sheet__cancel,.van-action-sheet__item{background-color:var(--action-sheet-item-background,#fff);font-size:var(--action-sheet-item-font-size,16px);line-height:var(--action-sheet-item-line-height,22px);padding:14px 16px;text-align:center}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5}.van-action-sheet__cancel:after,.van-action-sheet__item:after{border-width:0}.van-action-sheet__cancel{color:var(--action-sheet-cancel-text-color,#646566)}.van-action-sheet__gap{background-color:var(--action-sheet-cancel-padding-color,#f7f8fa);display:block;height:var(--action-sheet-cancel-padding-top,8px)}.van-action-sheet__item--disabled{color:var(--action-sheet-item-disabled-text-color,#c8c9cc)}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__subname{color:var(--action-sheet-subname-color,#969799);font-size:var(--action-sheet-subname-font-size,12px);line-height:var(--action-sheet-subname-line-height,20px);margin-top:var(--padding-xs,8px)}.van-action-sheet__header{font-size:var(--action-sheet-header-font-size,16px);font-weight:var(--font-weight-bold,500);line-height:var(--action-sheet-header-height,48px);text-align:center}.van-action-sheet__description{color:var(--action-sheet-description-color,#969799);font-size:var(--action-sheet-description-font-size,14px);line-height:var(--action-sheet-description-line-height,20px);padding:20px var(--padding-md,16px);text-align:center}.van-action-sheet__close{color:var(--action-sheet-close-icon-color,#c8c9cc);font-size:var(--action-sheet-close-icon-size,22px)!important;line-height:inherit!important;padding:var(--action-sheet-close-icon-padding,0 16px);position:absolute!important;right:0;top:0}.van-action-sheet__loading{display:flex!important}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { pickerProps } from '../picker/shared';
import { requestAnimationFrame } from '../common/utils';
const EMPTY_CODE = '000000';
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: Object.assign(Object.assign({}, pickerProps), { showToolbar: {
type: Boolean,
value: true,
}, value: {
type: String,
observer(value) {
this.code = value;
this.setValues();
},
}, areaList: {
type: Object,
value: {},
observer: 'setValues',
}, columnsNum: {
type: null,
value: 3,
}, columnsPlaceholder: {
type: Array,
observer(val) {
this.setData({
typeToColumnsPlaceholder: {
province: val[0] || '',
city: val[1] || '',
county: val[2] || '',
},
});
},
} }),
data: {
columns: [{ values: [] }, { values: [] }, { values: [] }],
typeToColumnsPlaceholder: {},
},
mounted() {
requestAnimationFrame(() => {
this.setValues();
});
},
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) {
const { index } = event.detail;
let { value } = event.detail;
value = this.parseValues(value);
this.emit('confirm', { value, index });
},
emit(type, detail) {
detail.values = detail.value;
delete detail.value;
this.$emit(type, detail);
},
parseValues(values) {
const { columnsPlaceholder } = this.data;
return values.map((value, index) => {
if (value &&
(!value.code || value.name === columnsPlaceholder[index])) {
return Object.assign(Object.assign({}, value), { code: '', name: '' });
}
return value;
});
},
onChange(event) {
var _a;
const { index, picker, value } = event.detail;
this.code = value[index].code;
(_a = this.setValues()) === null || _a === void 0 ? void 0 : _a.then(() => {
this.$emit('change', {
picker,
values: this.parseValues(picker.getValues()),
index,
});
});
},
getConfig(type) {
const { areaList } = this.data;
return (areaList && areaList[`${type}_list`]) || {};
},
getList(type, code) {
if (type !== 'province' && !code) {
return [];
}
const { typeToColumnsPlaceholder } = this.data;
const list = this.getConfig(type);
let result = Object.keys(list).map((code) => ({
code,
name: list[code],
}));
if (code != null) {
// oversea code
if (code[0] === '9' && type === 'city') {
code = '9';
}
result = result.filter((item) => item.code.indexOf(code) === 0);
}
if (typeToColumnsPlaceholder[type] && result.length) {
// set columns placeholder
const codeFill = type === 'province'
? ''
: type === 'city'
? EMPTY_CODE.slice(2, 4)
: EMPTY_CODE.slice(4, 6);
result.unshift({
code: `${code}${codeFill}`,
name: typeToColumnsPlaceholder[type],
});
}
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 picker = this.getPicker();
if (!picker) {
return;
}
let code = this.code || this.getDefaultCode();
const provinceList = this.getList('province');
const cityList = this.getList('city', code.slice(0, 2));
const stack = [];
const indexes = [];
const { columnsNum } = this.data;
if (columnsNum >= 1) {
stack.push(picker.setColumnValues(0, provinceList, false));
indexes.push(this.getIndex('province', code));
}
if (columnsNum >= 2) {
stack.push(picker.setColumnValues(1, cityList, false));
indexes.push(this.getIndex('city', code));
if (cityList.length && code.slice(2, 4) === '00') {
[{ code }] = cityList;
}
}
if (columnsNum === 3) {
stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
indexes.push(this.getIndex('county', code));
}
return Promise.all(stack)
.catch(() => { })
.then(() => picker.setIndexes(indexes))
.catch(() => { });
},
getDefaultCode() {
const { columnsPlaceholder } = this.data;
if (columnsPlaceholder.length) {
return EMPTY_CODE;
}
const countyCodes = Object.keys(this.getConfig('county'));
if (countyCodes[0]) {
return countyCodes[0];
}
const cityCodes = Object.keys(this.getConfig('city'));
if (cityCodes[0]) {
return cityCodes[0];
}
return '';
},
getValues() {
const picker = this.getPicker();
if (!picker) {
return [];
}
return this.parseValues(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(code) {
this.code = code || '';
return this.setValues();
},
},
});
{
"component": true,
"usingComponents": {
"van-picker": "../picker/index"
}
}
<wxs src="./index.wxs" module="computed" />
<van-picker
class="van-area__picker"
active-class="active-class"
toolbar-class="toolbar-class"
column-class="column-class"
show-toolbar="{{ showToolbar }}"
value-key="name"
title="{{ title }}"
loading="{{ loading }}"
columns="{{ computed.displayColumns(columns, columnsNum) }}"
item-height="{{ itemHeight }}"
visible-item-count="{{ visibleItemCount }}"
cancel-button-text="{{ cancelButtonText }}"
confirm-button-text="{{ confirmButtonText }}"
bind:change="onChange"
bind:confirm="onConfirm"
bind:cancel="onCancel"
/>
/* eslint-disable */
function displayColumns(columns, columnsNum) {
return columns.slice(0, +columnsNum);
}
module.exports = {
displayColumns: displayColumns,
};
@import '../common/index.wxss';
\ No newline at end of file
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { canIUseFormFieldButton } from '../common/version';
const mixins = [button];
if (canIUseFormFieldButton()) {
mixins.push('wx://form-field-button');
}
VantComponent({
mixins,
classes: ['hover-class', 'loading-class'],
data: {
baseStyle: '',
},
props: {
formType: String,
icon: String,
classPrefix: {
type: String,
value: 'van-icon',
},
plain: Boolean,
block: Boolean,
round: Boolean,
square: Boolean,
loading: Boolean,
hairline: Boolean,
disabled: Boolean,
loadingText: String,
customStyle: String,
loadingType: {
type: String,
value: 'circular',
},
type: {
type: String,
value: 'default',
},
dataset: null,
size: {
type: String,
value: 'normal',
},
loadingSize: {
type: String,
value: '20px',
},
color: String,
},
methods: {
onClick(event) {
this.$emit('click', event);
const { canIUseGetUserProfile, openType, getUserProfileDesc, lang, } = this.data;
if (openType === 'getUserInfo' && canIUseGetUserProfile) {
wx.getUserProfile({
desc: getUserProfileDesc || ' ',
lang: lang || 'en',
complete: (userProfile) => {
this.$emit('getuserinfo', userProfile);
},
});
}
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<button
id="{{ id }}"
data-detail="{{ dataset }}"
class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
hover-class="van-button--active hover-class"
lang="{{ lang }}"
form-type="{{ formType }}"
style="{{ computed.rootStyle({ plain, color, customStyle }) }}"
open-type="{{ disabled || loading || (canIUseGetUserProfile && openType === 'getUserInfo') ? '' : openType }}"
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="{{ disabled || loading ? '' : 'onClick' }}"
bindgetuserinfo="onGetUserInfo"
bindcontact="onContact"
bindgetphonenumber="onGetPhoneNumber"
binderror="onError"
bindlaunchapp="onLaunchApp"
bindopensetting="onOpenSetting"
>
<block wx:if="{{ loading }}">
<van-loading
custom-class="loading-class"
size="{{ loadingSize }}"
type="{{ loadingType }}"
color="{{ computed.loadingColor({ type, color, plain }) }}"
/>
<view wx:if="{{ loadingText }}" class="van-button__loading-text">
{{ loadingText }}
</view>
</block>
<block wx:else>
<van-icon
wx:if="{{ icon }}"
size="1.2em"
name="{{ icon }}"
class-prefix="{{ classPrefix }}"
class="van-button__icon"
custom-style="line-height: inherit;"
/>
<view class="van-button__text">
<slot />
</view>
</block>
</button>
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
if (!data.color) {
return data.customStyle;
}
var properties = {
color: data.plain ? data.color : '#fff',
background: data.plain ? null : data.color,
};
// hide border when color is linear-gradient
if (data.color.indexOf('gradient') !== -1) {
properties.border = 0;
} else {
properties['border-color'] = data.color;
}
return style([properties, data.customStyle]);
}
function loadingColor(data) {
if (data.plain) {
return data.color ? data.color : '#c9c9c9';
}
if (data.type === 'default') {
return '#c9c9c9';
}
return '#fff';
}
module.exports = {
rootStyle: rootStyle,
loadingColor: loadingColor,
};
@import '../common/index.wxss';.van-button{-webkit-text-size-adjust:100%;align-items:center;-webkit-appearance:none;border-radius:var(--button-border-radius,2px);box-sizing:border-box;display:inline-flex;font-size:var(--button-default-font-size,16px);height:var(--button-default-height,44px);justify-content:center;line-height:var(--button-line-height,20px);padding:0;position:relative;text-align:center;transition:opacity .2s;vertical-align:middle}.van-button:before{background-color:#000;border:inherit;border-color:#000;border-radius:inherit;content:" ";height:100%;left:50%;opacity:0;position:absolute;top:50%;transform:translate(-50%,-50%);width:100%}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{background:var(--button-default-background-color,#fff);border:var(--button-border-width,1px) solid var(--button-default-border-color,#ebedf0);color:var(--button-default-color,#323233)}.van-button--primary{background:var(--button-primary-background-color,#07c160);border:var(--button-border-width,1px) solid var(--button-primary-border-color,#07c160);color:var(--button-primary-color,#fff)}.van-button--info{background:var(--button-info-background-color,#1989fa);border:var(--button-border-width,1px) solid var(--button-info-border-color,#1989fa);color:var(--button-info-color,#fff)}.van-button--danger{background:var(--button-danger-background-color,#ee0a24);border:var(--button-border-width,1px) solid var(--button-danger-border-color,#ee0a24);color:var(--button-danger-color,#fff)}.van-button--warning{background:var(--button-warning-background-color,#ff976a);border:var(--button-border-width,1px) solid var(--button-warning-border-color,#ff976a);color:var(--button-warning-color,#fff)}.van-button--plain{background:var(--button-plain-background-color,#fff)}.van-button--plain.van-button--primary{color:var(--button-primary-background-color,#07c160)}.van-button--plain.van-button--info{color:var(--button-info-background-color,#1989fa)}.van-button--plain.van-button--danger{color:var(--button-danger-background-color,#ee0a24)}.van-button--plain.van-button--warning{color:var(--button-warning-background-color,#ff976a)}.van-button--large{height:var(--button-large-height,50px);width:100%}.van-button--normal{font-size:var(--button-normal-font-size,14px);padding:0 15px}.van-button--small{font-size:var(--button-small-font-size,12px);height:var(--button-small-height,30px);min-width:var(--button-small-min-width,60px);padding:0 var(--padding-xs,8px)}.van-button--mini{display:inline-block;font-size:var(--button-mini-font-size,10px);height:var(--button-mini-height,22px);min-width:var(--button-mini-min-width,50px)}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:flex;width:100%}.van-button--round{border-radius:var(--button-round-border-radius,999px)}.van-button--square{border-radius:0}.van-button--disabled{opacity:var(--button-disabled-opacity,.5)}.van-button__text{display:inline}.van-button__icon+.van-button__text:not(:empty),.van-button__loading-text{margin-left:4px}.van-button__icon{line-height:inherit!important;min-width:1em;vertical-align:top}.van-button--hairline{border-width:0;padding-top:1px}.van-button--hairline:after{border-color:inherit;border-radius:calc(var(--button-border-radius, 2px)*2);border-width:1px}.van-button--hairline.van-button--round:after{border-radius:var(--button-round-border-radius,999px)}.van-button--hairline.van-button--square:after{border-radius:0}
\ No newline at end of file
<view class="van-calendar">
<header
title="{{ title }}"
showTitle="{{ showTitle }}"
subtitle="{{ subtitle }}"
showSubtitle="{{ showSubtitle }}"
firstDayOfWeek="{{ firstDayOfWeek }}"
bind:click-subtitle="onClickSubtitle"
>
<slot name="title" slot="title"></slot>
</header>
<scroll-view
class="van-calendar__body"
scroll-y
scroll-into-view="{{ scrollIntoView }}"
>
<month
wx:for="{{ computed.getMonths(minDate, maxDate) }}"
wx:key="index"
id="month{{ index }}"
class="month"
data-date="{{ item }}"
date="{{ item }}"
type="{{ type }}"
color="{{ color }}"
minDate="{{ minDate }}"
maxDate="{{ maxDate }}"
showMark="{{ showMark }}"
formatter="{{ formatter }}"
rowHeight="{{ rowHeight }}"
currentDate="{{ currentDate }}"
showSubtitle="{{ showSubtitle }}"
allowSameDay="{{ allowSameDay }}"
showMonthTitle="{{ index !== 0 || !showSubtitle }}"
firstDayOfWeek="{{ firstDayOfWeek }}"
bind:click="onClickDay"
/>
</scroll-view>
<view
class="{{ utils.bem('calendar__footer', { safeAreaInsetBottom }) }}"
>
<slot name="footer"></slot>
</view>
<view
class="{{ utils.bem('calendar__footer', { safeAreaInsetBottom }) }}"
>
<van-button
wx:if="{{ showConfirm }}"
round
block
type="danger"
color="{{ color }}"
custom-class="van-calendar__confirm"
disabled="{{ computed.getButtonDisabled(type, currentDate) }}"
nativeType="text"
bind:click="onConfirm"
>
{{
computed.getButtonDisabled(type, currentDate)
? confirmDisabledText
: confirmText
}}
</van-button>
</view>
</view>
import { VantComponent } from '../../../common/component';
VantComponent({
props: {
title: {
type: String,
value: '日期选择',
},
subtitle: String,
showTitle: Boolean,
showSubtitle: Boolean,
firstDayOfWeek: {
type: Number,
observer: 'initWeekDay',
},
},
data: {
weekdays: [],
},
created() {
this.initWeekDay();
},
methods: {
initWeekDay() {
const defaultWeeks = ['日', '一', '二', '三', '四', '五', '六'];
const firstDayOfWeek = this.data.firstDayOfWeek || 0;
this.setData({
weekdays: [
...defaultWeeks.slice(firstDayOfWeek, 7),
...defaultWeeks.slice(0, firstDayOfWeek),
],
});
},
onClickSubtitle(event) {
this.$emit('click-subtitle', event);
},
},
});
<view class="van-calendar__header">
<block wx:if="{{ showTitle }}">
<view class="van-calendar__header-title"><slot name="title"></slot></view>
<view class="van-calendar__header-title">{{ title }}</view>
</block>
<view wx:if="{{ showSubtitle }}" class="van-calendar__header-subtitle" bind:tap="onClickSubtitle">
{{ subtitle }}
</view>
<view class="van-calendar__weekdays">
<view wx:for="{{ weekdays }}" wx:key="index" class="van-calendar__weekday">
{{ item }}
</view>
</view>
</view>
@import '../../../common/index.wxss';.van-calendar__header{box-shadow:var(--calendar-header-box-shadow,0 2px 10px hsla(220,1%,50%,.16));flex-shrink:0}.van-calendar__header-subtitle,.van-calendar__header-title{font-weight:var(--font-weight-bold,500);height:var(--calendar-header-title-height,44px);line-height:var(--calendar-header-title-height,44px);text-align:center}.van-calendar__header-title+.van-calendar__header-title,.van-calendar__header-title:empty{display:none}.van-calendar__header-title:empty+.van-calendar__header-title{display:block!important}.van-calendar__weekdays{display:flex}.van-calendar__weekday{flex:1;font-size:var(--calendar-weekdays-font-size,12px);line-height:var(--calendar-weekdays-height,30px);text-align:center}
\ No newline at end of file
export interface Day {
date: Date;
type: string;
text: number;
bottomInfo?: string;
}
import { VantComponent } from '../../../common/component';
import { getMonthEndDay, compareDay, getPrevDay, getNextDay, } from '../../utils';
VantComponent({
props: {
date: {
type: null,
observer: 'setDays',
},
type: {
type: String,
observer: 'setDays',
},
color: String,
minDate: {
type: null,
observer: 'setDays',
},
maxDate: {
type: null,
observer: 'setDays',
},
showMark: Boolean,
rowHeight: null,
formatter: {
type: null,
observer: 'setDays',
},
currentDate: {
type: null,
observer: 'setDays',
},
firstDayOfWeek: {
type: Number,
observer: 'setDays',
},
allowSameDay: Boolean,
showSubtitle: Boolean,
showMonthTitle: Boolean,
},
data: {
visible: true,
days: [],
},
methods: {
onClick(event) {
const { index } = event.currentTarget.dataset;
const item = this.data.days[index];
if (item.type !== 'disabled') {
this.$emit('click', item);
}
},
setDays() {
const days = [];
const startDate = new Date(this.data.date);
const year = startDate.getFullYear();
const month = startDate.getMonth();
const totalDay = getMonthEndDay(startDate.getFullYear(), startDate.getMonth() + 1);
for (let day = 1; day <= totalDay; day++) {
const date = new Date(year, month, day);
const type = this.getDayType(date);
let config = {
date,
type,
text: day,
bottomInfo: this.getBottomInfo(type),
};
if (this.data.formatter) {
config = this.data.formatter(config);
}
days.push(config);
}
this.setData({ days });
},
getMultipleDayType(day) {
const { currentDate } = this.data;
if (!Array.isArray(currentDate)) {
return '';
}
const isSelected = (date) => currentDate.some((item) => compareDay(item, date) === 0);
if (isSelected(day)) {
const prevDay = getPrevDay(day);
const nextDay = getNextDay(day);
const prevSelected = isSelected(prevDay);
const nextSelected = isSelected(nextDay);
if (prevSelected && nextSelected) {
return 'multiple-middle';
}
if (prevSelected) {
return 'end';
}
return nextSelected ? 'start' : 'multiple-selected';
}
return '';
},
getRangeDayType(day) {
const { currentDate, allowSameDay } = this.data;
if (!Array.isArray(currentDate)) {
return '';
}
const [startDay, endDay] = currentDate;
if (!startDay) {
return '';
}
const compareToStart = compareDay(day, startDay);
if (!endDay) {
return compareToStart === 0 ? 'start' : '';
}
const compareToEnd = compareDay(day, endDay);
if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) {
return 'start-end';
}
if (compareToStart === 0) {
return 'start';
}
if (compareToEnd === 0) {
return 'end';
}
if (compareToStart > 0 && compareToEnd < 0) {
return 'middle';
}
return '';
},
getDayType(day) {
const { type, minDate, maxDate, currentDate } = this.data;
if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
return 'disabled';
}
if (type === 'single') {
return compareDay(day, currentDate) === 0 ? 'selected' : '';
}
if (type === 'multiple') {
return this.getMultipleDayType(day);
}
/* istanbul ignore else */
if (type === 'range') {
return this.getRangeDayType(day);
}
return '';
},
getBottomInfo(type) {
if (this.data.type === 'range') {
if (type === 'start') {
return '开始';
}
if (type === 'end') {
return '结束';
}
if (type === 'start-end') {
return '开始/结束';
}
}
},
},
});
<wxs src="./index.wxs" module="computed"></wxs>
<wxs src="../../../wxs/utils.wxs" module="utils" />
<view class="van-calendar__month" style="{{ computed.getMonthStyle(visible, date, rowHeight) }}">
<view wx:if="{{ showMonthTitle }}" class="van-calendar__month-title">
{{ computed.formatMonthTitle(date) }}
</view>
<view wx:if="{{ visible }}" class="van-calendar__days">
<view wx:if="{{ showMark }}" class="van-calendar__month-mark">
{{ computed.getMark(date) }}
</view>
<view
wx:for="{{ days }}"
wx:key="index"
style="{{ computed.getDayStyle(item.type, index, date, rowHeight, color, firstDayOfWeek) }}"
class="{{ utils.bem('calendar__day', [item.type]) }} {{ item.className }}"
data-index="{{ index }}"
bindtap="onClick"
>
<view wx:if="{{ item.type === 'selected' }}" class="van-calendar__selected-day" style="width: {{ rowHeight }}px; height: {{ rowHeight }}px; background: {{ color }}">
<view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
{{ item.text }}
<view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
{{ item.bottomInfo }}
</view>
</view>
<view wx:else>
<view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
{{ item.text }}
<view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
{{ item.bottomInfo }}
</view>
</view>
</view>
</view>
</view>
/* eslint-disable */
var utils = require('../../utils.wxs');
function getMark(date) {
return getDate(date).getMonth() + 1;
}
var ROW_HEIGHT = 64;
function getDayStyle(type, index, date, rowHeight, color, firstDayOfWeek) {
var style = [];
var current = getDate(date).getDay() || 7;
var offset = current < firstDayOfWeek ? (7 - firstDayOfWeek + current) :
current === 7 && firstDayOfWeek === 0 ? 0 :
(current - firstDayOfWeek);
if (index === 0) {
style.push(['margin-left', (100 * offset) / 7 + '%']);
}
if (rowHeight !== ROW_HEIGHT) {
style.push(['height', rowHeight + 'px']);
}
if (color) {
if (
type === 'start' ||
type === 'end' ||
type === 'start-end' ||
type === 'multiple-selected' ||
type === 'multiple-middle'
) {
style.push(['background', color]);
} else if (type === 'middle') {
style.push(['color', color]);
}
}
return style
.map(function(item) {
return item.join(':');
})
.join(';');
}
function formatMonthTitle(date) {
date = getDate(date);
return date.getFullYear() + '年' + (date.getMonth() + 1) + '月';
}
function getMonthStyle(visible, date, rowHeight) {
if (!visible) {
date = getDate(date);
var totalDay = utils.getMonthEndDay(
date.getFullYear(),
date.getMonth() + 1
);
var offset = getDate(date).getDay();
var padding = Math.ceil((totalDay + offset) / 7) * rowHeight;
return 'padding-bottom:' + padding + 'px';
}
}
module.exports = {
getMark: getMark,
getDayStyle: getDayStyle,
formatMonthTitle: formatMonthTitle,
getMonthStyle: getMonthStyle
};
@import '../../../common/index.wxss';.van-calendar{background-color:var(--calendar-background-color,#fff);display:flex;flex-direction:column;height:100%}.van-calendar__month-title{font-size:var(--calendar-month-title-font-size,14px);font-weight:var(--font-weight-bold,500);height:var(--calendar-header-title-height,44px);line-height:var(--calendar-header-title-height,44px);text-align:center}.van-calendar__days{display:flex;flex-wrap:wrap;position:relative;-webkit-user-select:none;user-select:none}.van-calendar__month-mark{color:var(--calendar-month-mark-color,rgba(242,243,245,.8));font-size:var(--calendar-month-mark-font-size,160px);left:50%;pointer-events:none;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:0}.van-calendar__day,.van-calendar__selected-day{align-items:center;display:flex;justify-content:center;text-align:center}.van-calendar__day{font-size:var(--calendar-day-font-size,16px);height:var(--calendar-day-height,64px);position:relative;width:14.285%}.van-calendar__day--end,.van-calendar__day--multiple-middle,.van-calendar__day--multiple-selected,.van-calendar__day--start,.van-calendar__day--start-end{background-color:var(--calendar-range-edge-background-color,#ee0a24);color:var(--calendar-range-edge-color,#fff)}.van-calendar__day--start{border-radius:4px 0 0 4px}.van-calendar__day--end{border-radius:0 4px 4px 0}.van-calendar__day--multiple-selected,.van-calendar__day--start-end{border-radius:4px}.van-calendar__day--middle{color:var(--calendar-range-middle-color,#ee0a24)}.van-calendar__day--middle:after{background-color:currentColor;bottom:0;content:"";left:0;opacity:var(--calendar-range-middle-background-opacity,.1);position:absolute;right:0;top:0}.van-calendar__day--disabled{color:var(--calendar-day-disabled-color,#c8c9cc);cursor:default}.van-calendar__bottom-info,.van-calendar__top-info{font-size:var(--calendar-info-font-size,10px);left:0;line-height:var(--calendar-info-line-height,14px);position:absolute;right:0}@media (max-width:350px){.van-calendar__bottom-info,.van-calendar__top-info{font-size:9px}}.van-calendar__top-info{top:6px}.van-calendar__bottom-info{bottom:6px}.van-calendar__selected-day{background-color:var(--calendar-selected-day-background-color,#ee0a24);border-radius:4px;color:var(--calendar-selected-day-color,#fff);height:var(--calendar-selected-day-size,54px);width:var(--calendar-selected-day-size,54px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { ROW_HEIGHT, getPrevDay, getNextDay, getToday, compareDay, copyDates, calcDateNum, formatMonthTitle, compareMonth, getMonths, getDayByOffset, } from './utils';
import Toast from '../toast/toast';
import { requestAnimationFrame } from '../common/utils';
const initialMinDate = getToday().getTime();
const initialMaxDate = (() => {
const now = getToday();
return new Date(now.getFullYear(), now.getMonth() + 6, now.getDate()).getTime();
})();
const getTime = (date) => date instanceof Date ? date.getTime() : date;
VantComponent({
props: {
title: {
type: String,
value: '日期选择',
},
color: String,
show: {
type: Boolean,
observer(val) {
if (val) {
this.initRect();
this.scrollIntoView();
}
},
},
formatter: null,
confirmText: {
type: String,
value: '确定',
},
confirmDisabledText: {
type: String,
value: '确定',
},
rangePrompt: String,
showRangePrompt: {
type: Boolean,
value: true,
},
defaultDate: {
type: null,
observer(val) {
this.setData({ currentDate: val });
this.scrollIntoView();
},
},
allowSameDay: Boolean,
type: {
type: String,
value: 'single',
observer: 'reset',
},
minDate: {
type: Number,
value: initialMinDate,
},
maxDate: {
type: Number,
value: initialMaxDate,
},
position: {
type: String,
value: 'bottom',
},
rowHeight: {
type: null,
value: ROW_HEIGHT,
},
round: {
type: Boolean,
value: true,
},
poppable: {
type: Boolean,
value: true,
},
showMark: {
type: Boolean,
value: true,
},
showTitle: {
type: Boolean,
value: true,
},
showConfirm: {
type: Boolean,
value: true,
},
showSubtitle: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
maxRange: {
type: null,
value: null,
},
firstDayOfWeek: {
type: Number,
value: 0,
},
readonly: Boolean,
},
data: {
subtitle: '',
currentDate: null,
scrollIntoView: '',
},
created() {
this.setData({
currentDate: this.getInitialDate(this.data.defaultDate),
});
},
mounted() {
if (this.data.show || !this.data.poppable) {
this.initRect();
this.scrollIntoView();
}
},
methods: {
reset() {
this.setData({ currentDate: this.getInitialDate() });
this.scrollIntoView();
},
initRect() {
if (this.contentObserver != null) {
this.contentObserver.disconnect();
}
const contentObserver = this.createIntersectionObserver({
thresholds: [0, 0.1, 0.9, 1],
observeAll: true,
});
this.contentObserver = contentObserver;
contentObserver.relativeTo('.van-calendar__body');
contentObserver.observe('.month', (res) => {
if (res.boundingClientRect.top <= res.relativeRect.top) {
// @ts-ignore
this.setData({ subtitle: formatMonthTitle(res.dataset.date) });
}
});
},
limitDateRange(date, minDate = null, maxDate = null) {
minDate = minDate || this.data.minDate;
maxDate = maxDate || this.data.maxDate;
if (compareDay(date, minDate) === -1) {
return minDate;
}
if (compareDay(date, maxDate) === 1) {
return maxDate;
}
return date;
},
getInitialDate(defaultDate = null) {
const { type, minDate, maxDate } = this.data;
const now = getToday().getTime();
if (type === 'range') {
if (!Array.isArray(defaultDate)) {
defaultDate = [];
}
const [startDay, endDay] = defaultDate || [];
const start = this.limitDateRange(startDay || now, minDate, getPrevDay(new Date(maxDate)).getTime());
const end = this.limitDateRange(endDay || now, getNextDay(new Date(minDate)).getTime());
return [start, end];
}
if (type === 'multiple') {
if (Array.isArray(defaultDate)) {
return defaultDate.map((date) => this.limitDateRange(date));
}
return [this.limitDateRange(now)];
}
if (!defaultDate || Array.isArray(defaultDate)) {
defaultDate = now;
}
return this.limitDateRange(defaultDate);
},
scrollIntoView() {
requestAnimationFrame(() => {
const { currentDate, type, show, poppable, minDate, maxDate } = this.data;
// @ts-ignore
const targetDate = type === 'single' ? currentDate : currentDate[0];
const displayed = show || !poppable;
if (!targetDate || !displayed) {
return;
}
const months = getMonths(minDate, maxDate);
months.some((month, index) => {
if (compareMonth(month, targetDate) === 0) {
this.setData({ scrollIntoView: `month${index}` });
return true;
}
return false;
});
});
},
onOpen() {
this.$emit('open');
},
onOpened() {
this.$emit('opened');
},
onClose() {
this.$emit('close');
},
onClosed() {
this.$emit('closed');
},
onClickDay(event) {
if (this.data.readonly) {
return;
}
let { date } = event.detail;
const { type, currentDate, allowSameDay } = this.data;
if (type === 'range') {
// @ts-ignore
const [startDay, endDay] = currentDate;
if (startDay && !endDay) {
const compareToStart = compareDay(date, startDay);
if (compareToStart === 1) {
const { days } = this.selectComponent('.month').data;
days.some((day, index) => {
const isDisabled = day.type === 'disabled' &&
getTime(startDay) < getTime(day.date) &&
getTime(day.date) < getTime(date);
if (isDisabled) {
({ date } = days[index - 1]);
}
return isDisabled;
});
this.select([startDay, date], true);
}
else if (compareToStart === -1) {
this.select([date, null]);
}
else if (allowSameDay) {
this.select([date, date]);
}
}
else {
this.select([date, null]);
}
}
else if (type === 'multiple') {
let selectedIndex;
// @ts-ignore
const selected = currentDate.some((dateItem, index) => {
const equal = compareDay(dateItem, date) === 0;
if (equal) {
selectedIndex = index;
}
return equal;
});
if (selected) {
// @ts-ignore
const cancelDate = currentDate.splice(selectedIndex, 1);
this.setData({ currentDate });
this.unselect(cancelDate);
}
else {
// @ts-ignore
this.select([...currentDate, date]);
}
}
else {
this.select(date, true);
}
},
unselect(dateArray) {
const date = dateArray[0];
if (date) {
this.$emit('unselect', copyDates(date));
}
},
select(date, complete) {
if (complete && this.data.type === 'range') {
const valid = this.checkRange(date);
if (!valid) {
// auto selected to max range if showConfirm
if (this.data.showConfirm) {
this.emit([
date[0],
getDayByOffset(date[0], this.data.maxRange - 1),
]);
}
else {
this.emit(date);
}
return;
}
}
this.emit(date);
if (complete && !this.data.showConfirm) {
this.onConfirm();
}
},
emit(date) {
this.setData({
currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date),
});
this.$emit('select', copyDates(date));
},
checkRange(date) {
const { maxRange, rangePrompt, showRangePrompt } = this.data;
if (maxRange && calcDateNum(date) > maxRange) {
if (showRangePrompt) {
Toast({
context: this,
message: rangePrompt || `选择天数不能超过 ${maxRange} 天`,
});
}
this.$emit('over-range');
return false;
}
return true;
},
onConfirm() {
if (this.data.type === 'range' &&
!this.checkRange(this.data.currentDate)) {
return;
}
wx.nextTick(() => {
// @ts-ignore
this.$emit('confirm', copyDates(this.data.currentDate));
});
},
onClickSubtitle(event) {
this.$emit('click-subtitle', event);
},
},
});
{
"component": true,
"usingComponents": {
"header": "./components/header/index",
"month": "./components/month/index",
"van-button": "../button/index",
"van-popup": "../popup/index",
"van-toast": "../toast/index"
}
}
<wxs src="./index.wxs" module="computed" />
<wxs src="../wxs/utils.wxs" module="utils" />
<import src="./calendar.wxml" />
<van-popup
wx:if="{{ poppable }}"
custom-class="van-calendar__popup--{{ position }}"
close-icon-class="van-calendar__close-icon"
show="{{ show }}"
round="{{ round }}"
position="{{ position }}"
closeable="{{ showTitle || showSubtitle }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:enter="onOpen"
bind:close="onClose"
bind:after-enter="onOpened"
bind:after-leave="onClosed"
>
<include src="./calendar.wxml" />
</van-popup>
<include wx:else src="./calendar.wxml" />
<van-toast id="van-toast" />
/* eslint-disable */
var utils = require('./utils.wxs');
function getMonths(minDate, maxDate) {
var months = [];
var cursor = getDate(minDate);
cursor.setDate(1);
do {
months.push(cursor.getTime());
cursor.setMonth(cursor.getMonth() + 1);
} while (utils.compareMonth(cursor, getDate(maxDate)) !== 1);
return months;
}
function getButtonDisabled(type, currentDate) {
if (currentDate == null) {
return true;
}
if (type === 'range') {
return !currentDate[0] || !currentDate[1];
}
if (type === 'multiple') {
return !currentDate.length;
}
return !currentDate;
}
module.exports = {
getMonths: getMonths,
getButtonDisabled: getButtonDisabled
};
@import '../common/index.wxss';.van-calendar{background-color:var(--calendar-background-color,#fff);display:flex;flex-direction:column;height:var(--calendar-height,100%)}.van-calendar__close-icon{top:11px}.van-calendar__popup--bottom,.van-calendar__popup--top{height:var(--calendar-popup-height,80%)}.van-calendar__popup--left,.van-calendar__popup--right{height:100%}.van-calendar__body{-webkit-overflow-scrolling:touch;flex:1;overflow:auto}.van-calendar__footer{flex-shrink:0;padding:0 var(--padding-md,16px)}.van-calendar__footer--safe-area-inset-bottom{padding-bottom:env(safe-area-inset-bottom)}.van-calendar__footer+.van-calendar__footer,.van-calendar__footer:empty{display:none}.van-calendar__footer:empty+.van-calendar__footer{display:block!important}.van-calendar__confirm{height:var(--calendar-confirm-button-height,36px)!important;line-height:var(--calendar-confirm-button-line-height,34px)!important;margin:var(--calendar-confirm-button-margin,7px 0)!important}
\ No newline at end of file
export declare const ROW_HEIGHT = 64;
export declare function formatMonthTitle(date: Date): string;
export declare function compareMonth(date1: Date | number, date2: Date | number): 1 | -1 | 0;
export declare function compareDay(day1: Date | number, day2: Date | number): 1 | -1 | 0;
export declare function getDayByOffset(date: Date, offset: number): Date;
export declare function getPrevDay(date: Date): Date;
export declare function getNextDay(date: Date): Date;
export declare function getToday(): Date;
export declare function calcDateNum(date: [Date, Date]): number;
export declare function copyDates(dates: Date | Date[]): Date | Date[];
export declare function getMonthEndDay(year: number, month: number): number;
export declare function getMonths(minDate: number, maxDate: number): number[];
export const ROW_HEIGHT = 64;
export function formatMonthTitle(date) {
if (!(date instanceof Date)) {
date = new Date(date);
}
return `${date.getFullYear()}${date.getMonth() + 1}月`;
}
export function compareMonth(date1, date2) {
if (!(date1 instanceof Date)) {
date1 = new Date(date1);
}
if (!(date2 instanceof Date)) {
date2 = new Date(date2);
}
const year1 = date1.getFullYear();
const year2 = date2.getFullYear();
const month1 = date1.getMonth();
const month2 = date2.getMonth();
if (year1 === year2) {
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
}
return year1 > year2 ? 1 : -1;
}
export function compareDay(day1, day2) {
if (!(day1 instanceof Date)) {
day1 = new Date(day1);
}
if (!(day2 instanceof Date)) {
day2 = new Date(day2);
}
const compareMonthResult = compareMonth(day1, day2);
if (compareMonthResult === 0) {
const date1 = day1.getDate();
const date2 = day2.getDate();
return date1 === date2 ? 0 : date1 > date2 ? 1 : -1;
}
return compareMonthResult;
}
export function getDayByOffset(date, offset) {
date = new Date(date);
date.setDate(date.getDate() + offset);
return date;
}
export function getPrevDay(date) {
return getDayByOffset(date, -1);
}
export function getNextDay(date) {
return getDayByOffset(date, 1);
}
export function getToday() {
const today = new Date();
today.setHours(0, 0, 0, 0);
return today;
}
export function calcDateNum(date) {
const day1 = new Date(date[0]).getTime();
const day2 = new Date(date[1]).getTime();
return (day2 - day1) / (1000 * 60 * 60 * 24) + 1;
}
export function copyDates(dates) {
if (Array.isArray(dates)) {
return dates.map((date) => {
if (date === null) {
return date;
}
return new Date(date);
});
}
return new Date(dates);
}
export function getMonthEndDay(year, month) {
return 32 - new Date(year, month - 1, 32).getDate();
}
export function getMonths(minDate, maxDate) {
const months = [];
const cursor = new Date(minDate);
cursor.setDate(1);
do {
months.push(cursor.getTime());
cursor.setMonth(cursor.getMonth() + 1);
} while (compareMonth(cursor, maxDate) !== 1);
return months;
}
/* eslint-disable */
function getMonthEndDay(year, month) {
return 32 - getDate(year, month - 1, 32).getDate();
}
function compareMonth(date1, date2) {
date1 = getDate(date1);
date2 = getDate(date2);
var year1 = date1.getFullYear();
var year2 = date2.getFullYear();
var month1 = date1.getMonth();
var month2 = date2.getMonth();
if (year1 === year2) {
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
}
return year1 > year2 ? 1 : -1;
}
module.exports = {
getMonthEndDay: getMonthEndDay,
compareMonth: compareMonth
};
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: {
type: String,
observer: 'updatePrice',
},
centered: Boolean,
lazyLoad: Boolean,
thumbLink: String,
originPrice: String,
thumbMode: {
type: String,
value: 'aspectFit',
},
currency: {
type: String,
value: '¥',
},
},
methods: {
updatePrice() {
const { price } = this.data;
const priceArr = price.toString().split('.');
this.setData({
integerStr: priceArr[0],
decimalStr: priceArr[1] ? `.${priceArr[1]}` : '',
});
},
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 wx:else name="thumb" />
<van-tag
wx:if="{{ tag }}"
mark
type="danger"
custom-class="van-card__tag"
>
{{ tag }}
</van-tag>
<slot wx:else name="tag" />
</view>
<view class="van-card__content {{ utils.bem('card__content', { center: centered }) }}">
<view>
<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>
<view class="van-card__bottom">
<slot name="price-top" />
<view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">
<text>{{ currency }}</text>
<text class="van-card__price-integer">{{ integerStr }}</text>
<text class="van-card__price-decimal">{{ decimalStr }}</text>
</view>
<slot wx:else name="price" />
<view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
<slot wx:else name="origin-price" />
<view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
<slot wx:else name="num" />
<slot name="bottom" />
</view>
</view>
</view>
<view class="van-card__footer">
<slot name="footer" />
</view>
</view>
@import '../common/index.wxss';.van-card{background-color:var(--card-background-color,#fafafa);box-sizing:border-box;color:var(--card-text-color,#323233);font-size:var(--card-font-size,12px);padding:var(--card-padding,8px 16px);position:relative}.van-card__header{display:flex}.van-card__header--center{align-items:center;justify-content:center}.van-card__thumb{flex:none;height:var(--card-thumb-size,88px);margin-right:var(--padding-xs,8px);position:relative;width:var(--card-thumb-size,88px)}.van-card__thumb:empty{display:none}.van-card__img{border-radius:8px;height:100%;width:100%}.van-card__content{display:flex;flex:1;flex-direction:column;justify-content:space-between;min-height:var(--card-thumb-size,88px);min-width:0;position:relative}.van-card__content--center{justify-content:center}.van-card__desc,.van-card__title{word-wrap:break-word}.van-card__title{font-weight:700;line-height:var(--card-title-line-height,16px)}.van-card__desc{color:var(--card-desc-color,#646566);line-height:var(--card-desc-line-height,20px)}.van-card__bottom{line-height:20px}.van-card__price{color:var(--card-price-color,#ee0a24);display:inline-block;font-size:var(--card-price-font-size,12px);font-weight:700}.van-card__price-integer{font-size:var(--card-price-integer-font-size,16px)}.van-card__price-decimal,.van-card__price-integer{font-family:var(--card-price-font-family,Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif)}.van-card__origin-price{color:var(--card-origin-price-color,#646566);display:inline-block;font-size:var(--card-origin-price-font-size,10px);margin-left:5px;text-decoration:line-through}.van-card__num{float:right}.van-card__tag{left:0;position:absolute!important;top:2px}.van-card__footer{flex:none;text-align:right;width:100%}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
props: {
title: String,
border: {
type: Boolean,
value: true,
},
inset: Boolean,
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view
wx:if="{{ title }}"
class="{{ utils.bem('cell-group__title', { inset }) }}"
>
{{ title }}
</view>
<view class="custom-class {{ utils.bem('cell-group', { inset }) }} {{ border ? 'van-hairline--top-bottom' : '' }}">
<slot />
</view>
@import '../common/index.wxss';.van-cell-group--inset{border-radius:var(--cell-group-inset-border-radius,8px);margin:var(--cell-group-inset-padding,0 16px);overflow:hidden}.van-cell-group__title{color:var(--cell-group-title-color,#969799);font-size:var(--cell-group-title-font-size,14px);line-height:var(--cell-group-title-line-height,16px);padding:var(--cell-group-title-padding,16px 16px 8px)}.van-cell-group__title--inset{padding:var(--cell-group-inset-title-padding,16px 16px 8px 32px)}
\ 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,
useLabelSlot: Boolean,
border: {
type: Boolean,
value: true,
},
titleStyle: String,
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
this.jumpLink();
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<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="{{ computed.titleStyle({ titleWidth, titleStyle }) }}"
class="van-cell__title title-class"
>
<block wx:if="{{ title }}">{{ title }}</block>
<slot wx:else name="title" />
<view wx:if="{{ label || useLabelSlot }}" class="van-cell__label label-class">
<slot wx:if="{{ useLabelSlot }}" name="label" />
<block wx:elif="{{ label }}">{{ label }}</block>
</view>
</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>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function titleStyle(data) {
return style([
{
'max-width': addUnit(data.titleWidth),
'min-width': addUnit(data.titleWidth),
},
data.titleStyle,
]);
}
module.exports = {
titleStyle: titleStyle,
};
@import '../common/index.wxss';.van-cell{background-color:var(--cell-background-color,#fff);box-sizing:border-box;color:var(--cell-text-color,#323233);display:flex;font-size:var(--cell-font-size,14px);line-height:var(--cell-line-height,24px);padding:var(--cell-vertical-padding,10px) var(--cell-horizontal-padding,16px);position:relative;width:100%}.van-cell:after{border-bottom:1px solid #ebedf0;bottom:0;box-sizing:border-box;content:" ";left:16px;pointer-events:none;position:absolute;right:16px;transform:scaleY(.5);transform-origin:center}.van-cell--borderless:after{display:none}.van-cell-group{background-color:var(--cell-background-color,#fff)}.van-cell__label{color:var(--cell-label-color,#969799);font-size:var(--cell-label-font-size,12px);line-height:var(--cell-label-line-height,18px);margin-top:var(--cell-label-margin-top,3px)}.van-cell__value{color:var(--cell-value-color,#969799);overflow:hidden;text-align:right;vertical-align:middle}.van-cell__title,.van-cell__value{flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{align-items:center;display:flex;font-size:var(--cell-icon-size,16px);height:var(--cell-line-height,24px)}.van-cell__left-icon-wrap{margin-right:var(--padding-base,4px)}.van-cell__right-icon-wrap{color:var(--cell-right-icon-color,#969799);margin-left:var(--padding-base,4px)}.van-cell__left-icon{vertical-align:middle}.van-cell__left-icon,.van-cell__right-icon{line-height:var(--cell-line-height,24px)}.van-cell--clickable.van-cell--hover{background-color:var(--cell-active-color,#f2f3f5)}.van-cell--required{overflow:visible}.van-cell--required:before{color:var(--cell-required-color,#ee0a24);content:"*";font-size:var(--cell-font-size,14px);left:var(--padding-xs,8px);position:absolute}.van-cell--center{align-items:center}.van-cell--large{padding-bottom:var(--cell-large-vertical-padding,12px);padding-top:var(--cell-large-vertical-padding,12px)}.van-cell--large .van-cell__title{font-size:var(--cell-large-title-font-size,16px)}.van-cell--large .van-cell__value{font-size:var(--cell-large-value-font-size,16px)}.van-cell--large .van-cell__label{font-size:var(--cell-large-label-font-size,14px)}
\ No newline at end of file
import { useChildren } from '../common/relation';
import { VantComponent } from '../common/component';
VantComponent({
field: true,
relation: useChildren('checkbox', function (target) {
this.updateChild(target);
}),
props: {
max: Number,
value: {
type: Array,
observer: 'updateChildren',
},
disabled: {
type: Boolean,
observer: 'updateChildren',
},
direction: {
type: String,
value: 'vertical',
},
},
methods: {
updateChildren() {
this.children.forEach((child) => this.updateChild(child));
},
updateChild(child) {
const { value, disabled, direction } = this.data;
child.setData({
value: value.indexOf(child.data.name) !== -1,
parentDisabled: disabled,
direction,
});
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="{{ utils.bem('checkbox-group', [{ horizontal: direction === 'horizontal' }]) }}">
<slot />
</view>
@import '../common/index.wxss';.van-checkbox-group--horizontal{display:flex;flex-wrap:wrap}
\ No newline at end of file
import { useParent } from '../common/relation';
import { VantComponent } from '../common/component';
function emit(target, value) {
target.$emit('input', value);
target.$emit('change', value);
}
VantComponent({
field: true,
relation: useParent('checkbox-group'),
classes: ['icon-class', 'label-class'],
props: {
value: Boolean,
disabled: Boolean,
useIconSlot: Boolean,
checkedColor: String,
labelPosition: {
type: String,
value: 'right',
},
labelDisabled: Boolean,
shape: {
type: String,
value: 'round',
},
iconSize: {
type: null,
value: 20,
},
},
data: {
parentDisabled: false,
direction: 'vertical',
},
methods: {
emitChange(value) {
if (this.parent) {
this.setParentValue(this.parent, value);
}
else {
emit(this, value);
}
},
toggle() {
const { parentDisabled, disabled, value } = this.data;
if (!disabled && !parentDisabled) {
this.emitChange(!value);
}
},
onClickLabel() {
const { labelDisabled, parentDisabled, disabled, value } = this.data;
if (!disabled && !labelDisabled && !parentDisabled) {
this.emitChange(!value);
}
},
setParentValue(parent, value) {
const parentValue = parent.data.value.slice();
const { name } = this.data;
const { max } = parent.data;
if (value) {
if (max && parentValue.length >= max) {
return;
}
if (parentValue.indexOf(name) === -1) {
parentValue.push(name);
emit(parent, parentValue);
}
}
else {
const index = parentValue.indexOf(name);
if (index !== -1) {
parentValue.splice(index, 1);
emit(parent, parentValue);
}
}
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="{{ utils.bem('checkbox', [{ horizontal: direction === 'horizontal' }]) }} custom-class">
<view
wx:if="{{ labelPosition === 'left' }}"
class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}"
bindtap="onClickLabel"
>
<slot />
</view>
<view class="van-checkbox__icon-wrap" bindtap="toggle">
<slot wx:if="{{ useIconSlot }}" name="icon" />
<van-icon
wx:else
name="success"
size="0.8em"
class="{{ utils.bem('checkbox__icon', [shape, { disabled: disabled || parentDisabled, checked: value }]) }}"
style="{{ computed.iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) }}"
custom-class="icon-class"
custom-style="line-height: 1.25em;"
/>
</view>
<view
wx:if="{{ labelPosition === 'right' }}"
class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}"
bindtap="onClickLabel"
>
<slot />
</view>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) {
var styles = {
'font-size': addUnit(iconSize),
};
if (checkedColor && value && !disabled && !parentDisabled) {
styles['border-color'] = checkedColor;
styles['background-color'] = checkedColor;
}
return style(styles);
}
module.exports = {
iconStyle: iconStyle,
};
@import '../common/index.wxss';.van-checkbox{align-items:center;display:flex;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox--horizontal{margin-right:12px}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{flex:none}.van-checkbox__icon{align-items:center;border:1px solid var(--checkbox-border-color,#c8c9cc);box-sizing:border-box;color:transparent;display:flex;font-size:var(--checkbox-size,20px);height:1em;justify-content:center;text-align:center;transition-duration:var(--checkbox-transition-duration,.2s);transition-property:color,border-color,background-color;width:1em}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:var(--checkbox-checked-icon-color,#1989fa);color:#fff}.van-checkbox__icon--disabled{background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;color:var(--checkbox-label-color,#323233);padding-left:var(--checkbox-label-margin,10px)}.van-checkbox__label--left{float:left;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0}
\ No newline at end of file
/// <reference types="miniprogram-api-typings" />
declare type CanvasContext = WechatMiniprogram.CanvasContext;
export declare function adaptor(ctx: CanvasContext & Record<string, unknown>): CanvasContext;
export {};
export function adaptor(ctx) {
// @ts-ignore
return Object.assign(ctx, {
setStrokeStyle(val) {
ctx.strokeStyle = val;
},
setLineWidth(val) {
ctx.lineWidth = val;
},
setLineCap(val) {
ctx.lineCap = val;
},
setFillStyle(val) {
ctx.fillStyle = val;
},
setFontSize(val) {
ctx.font = String(val);
},
setGlobalAlpha(val) {
ctx.globalAlpha = val;
},
setLineJoin(val) {
ctx.lineJoin = val;
},
setTextAlign(val) {
ctx.textAlign = val;
},
setMiterLimit(val) {
ctx.miterLimit = val;
},
setShadow(offsetX, offsetY, blur, color) {
ctx.shadowOffsetX = offsetX;
ctx.shadowOffsetY = offsetY;
ctx.shadowBlur = blur;
ctx.shadowColor = color;
},
setTextBaseline(val) {
ctx.textBaseline = val;
},
createCircularGradient() { },
draw() { },
});
}
import { BLUE, WHITE } from '../common/color';
import { VantComponent } from '../common/component';
import { getSystemInfoSync } from '../common/utils';
import { isObj } from '../common/validator';
import { canIUseCanvas2d } from '../common/version';
import { adaptor } from './canvas';
function format(rate) {
return Math.min(Math.max(rate, 0), 100);
}
const PERIMETER = 2 * Math.PI;
const BEGIN_ANGLE = -Math.PI / 2;
const STEP = 1;
VantComponent({
props: {
text: String,
lineCap: {
type: String,
value: 'round',
},
value: {
type: Number,
value: 0,
observer: 'reRender',
},
speed: {
type: Number,
value: 50,
},
size: {
type: Number,
value: 100,
observer() {
this.drawCircle(this.currentValue);
},
},
fill: String,
layerColor: {
type: String,
value: WHITE,
},
color: {
type: null,
value: BLUE,
observer() {
this.setHoverColor().then(() => {
this.drawCircle(this.currentValue);
});
},
},
type: {
type: String,
value: '',
},
strokeWidth: {
type: Number,
value: 4,
},
clockwise: {
type: Boolean,
value: true,
},
},
data: {
hoverColor: BLUE,
},
methods: {
getContext() {
const { type, size } = this.data;
if (type === '' || !canIUseCanvas2d()) {
const ctx = wx.createCanvasContext('van-circle', this);
return Promise.resolve(ctx);
}
const dpr = getSystemInfoSync().pixelRatio;
return new Promise((resolve) => {
wx.createSelectorQuery()
.in(this)
.select('#van-circle')
.node()
.exec((res) => {
const canvas = res[0].node;
const ctx = canvas.getContext(type);
if (!this.inited) {
this.inited = true;
canvas.width = size * dpr;
canvas.height = size * dpr;
ctx.scale(dpr, dpr);
}
resolve(adaptor(ctx));
});
});
},
setHoverColor() {
const { color, size } = this.data;
if (isObj(color)) {
return this.getContext().then((context) => {
const LinearColor = context.createLinearGradient(size, 0, 0, 0);
Object.keys(color)
.sort((a, b) => parseFloat(a) - parseFloat(b))
.map((key) => LinearColor.addColorStop(parseFloat(key) / 100, color[key]));
this.hoverColor = LinearColor;
});
}
this.hoverColor = color;
return Promise.resolve();
},
presetCanvas(context, strokeStyle, beginAngle, endAngle, fill) {
const { strokeWidth, lineCap, clockwise, size } = this.data;
const position = size / 2;
const radius = position - strokeWidth / 2;
context.setStrokeStyle(strokeStyle);
context.setLineWidth(strokeWidth);
context.setLineCap(lineCap);
context.beginPath();
context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
context.stroke();
if (fill) {
context.setFillStyle(fill);
context.fill();
}
},
renderLayerCircle(context) {
const { layerColor, fill } = this.data;
this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
},
renderHoverCircle(context, formatValue) {
const { clockwise } = this.data;
// 结束角度
const progress = PERIMETER * (formatValue / 100);
const endAngle = clockwise
? BEGIN_ANGLE + progress
: 3 * Math.PI - (BEGIN_ANGLE + progress);
this.presetCanvas(context, this.hoverColor, BEGIN_ANGLE, endAngle);
},
drawCircle(currentValue) {
const { size } = this.data;
this.getContext().then((context) => {
context.clearRect(0, 0, size, size);
this.renderLayerCircle(context);
const formatValue = format(currentValue);
if (formatValue !== 0) {
this.renderHoverCircle(context, formatValue);
}
context.draw();
});
},
reRender() {
// tofector 动画暂时没有想到好的解决方案
const { value, speed } = this.data;
if (speed <= 0 || speed > 1000) {
this.drawCircle(value);
return;
}
this.clearMockInterval();
this.currentValue = this.currentValue || 0;
const run = () => {
this.interval = setTimeout(() => {
if (this.currentValue !== value) {
if (Math.abs(this.currentValue - value) < STEP) {
this.currentValue = value;
}
else if (this.currentValue < value) {
this.currentValue += STEP;
}
else {
this.currentValue -= STEP;
}
this.drawCircle(this.currentValue);
run();
}
else {
this.clearMockInterval();
}
}, 1000 / speed);
};
run();
},
clearMockInterval() {
if (this.interval) {
clearTimeout(this.interval);
this.interval = null;
}
},
},
mounted() {
this.currentValue = this.data.value;
this.setHoverColor().then(() => {
this.drawCircle(this.currentValue);
});
},
destroyed() {
this.clearMockInterval();
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="van-circle">
<canvas class="van-circle__canvas" type="{{ type }}" style="width: {{ utils.addUnit(size) }};height:{{ utils.addUnit(size) }}" id="van-circle" canvas-id="van-circle"></canvas>
<view wx:if="{{ !text }}" class="van-circle__text">
<slot></slot>
</view>
<cover-view wx:else class="van-circle__text">{{ text }}</cover-view>
</view>
@import '../common/index.wxss';.van-circle{display:inline-block;position:relative;text-align:center}.van-circle__text{color:var(--circle-text-color,#323233);left:0;position:absolute;top:50%;transform:translateY(-50%);width:100%}
\ No newline at end of file
import { useParent } from '../common/relation';
import { VantComponent } from '../common/component';
VantComponent({
relation: useParent('row'),
props: {
span: Number,
offset: Number,
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view
class="custom-class {{ utils.bem('col', [span]) }} {{ offset ? 'van-col--offset-' + offset : '' }}"
style="{{ computed.rootStyle({ gutter }) }}"
>
<slot />
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
if (!data.gutter) {
return '';
}
return style({
'padding-right': addUnit(data.gutter / 2),
'padding-left': addUnit(data.gutter / 2),
});
}
module.exports = {
rootStyle: rootStyle,
};
@import '../common/index.wxss';.van-col{box-sizing:border-box;float:left}.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
/// <reference types="miniprogram-api-typings" />
export declare function setContentAnimate(context: WechatMiniprogram.Component.TrivialInstance, expanded: boolean, mounted: boolean): void;
import { getRect } from '../common/utils';
function useAnimation(context, expanded, mounted, height) {
const animation = wx.createAnimation({
duration: 0,
timingFunction: 'ease-in-out',
});
if (expanded) {
if (height === 0) {
animation.height('auto').top(1).step();
}
else {
animation
.height(height)
.top(1)
.step({
duration: mounted ? 300 : 1,
})
.height('auto')
.step();
}
context.setData({
animation: animation.export(),
});
return;
}
animation.height(height).top(0).step({ duration: 1 }).height(0).step({
duration: 300,
});
context.setData({
animation: animation.export(),
});
}
export function setContentAnimate(context, expanded, mounted) {
getRect(context, '.van-collapse-item__content')
.then((rect) => rect.height)
.then((height) => {
useAnimation(context, expanded, mounted, height);
});
}
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
import { setContentAnimate } from './animate';
VantComponent({
classes: ['title-class', 'content-class'],
relation: useParent('collapse'),
props: {
size: String,
name: null,
title: null,
value: null,
icon: String,
label: String,
disabled: Boolean,
clickable: Boolean,
border: {
type: Boolean,
value: true,
},
isLink: {
type: Boolean,
value: true,
},
},
data: {
expanded: false,
},
mounted() {
this.updateExpanded();
this.mounted = true;
},
methods: {
updateExpanded() {
if (!this.parent) {
return;
}
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);
if (expanded !== this.data.expanded) {
setContentAnimate(this, expanded, this.mounted);
}
this.setData({ index, expanded });
},
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);
},
},
});
{
"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
size="{{ size }}"
title="{{ title }}"
title-class="title-class"
icon="{{ icon }}"
value="{{ value }}"
label="{{ label }}"
is-link="{{ isLink }}"
clickable="{{ clickable }}"
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') }}"
style="height: 0;"
animation="{{ animation }}"
>
<view
class="van-collapse-item__content content-class"
>
<slot />
</view>
</view>
</view>
@import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{transform:rotate(90deg);transition:transform var(--collapse-item-transition-duration,.3s)}.van-collapse-item__title--expanded .van-cell__right-icon{transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:var(--collapse-item-title-disabled-color,#c8c9cc)!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__content{background-color:var(--collapse-item-content-background-color,#fff);color:var(--collapse-item-content-text-color,#969799);font-size:var(--collapse-item-content-font-size,13px);line-height:var(--collapse-item-content-line-height,1.5);padding:var(--collapse-item-content-padding,15px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('collapse-item'),
props: {
value: {
type: null,
observer: 'updateExpanded',
},
accordion: {
type: Boolean,
observer: 'updateExpanded',
},
border: {
type: Boolean,
value: true,
},
},
methods: {
updateExpanded() {
this.children.forEach((child) => {
child.updateExpanded();
});
},
switch(name, expanded) {
const { accordion, value } = this.data;
const changeItem = name;
if (!accordion) {
name = expanded
? (value || []).concat(name)
: (value || []).filter((activeName) => activeName !== name);
}
else {
name = expanded ? name : '';
}
if (expanded) {
this.$emit('open', changeItem);
}
else {
this.$emit('close', changeItem);
}
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 = "#ee0a24";
export declare const BLUE = "#1989fa";
export declare const WHITE = "#fff";
export declare const GREEN = "#07c160";
export declare const ORANGE = "#ff976a";
export declare const GRAY = "#323233";
export declare const GRAY_DARK = "#969799";
export const RED = '#ee0a24';
export const BLUE = '#1989fa';
export const WHITE = '#fff';
export const GREEN = '#07c160';
export const ORANGE = '#ff976a';
export const GRAY = '#323233';
export const GRAY_DARK = '#969799';
/// <reference types="miniprogram-api-typings" />
import { VantComponentOptions } from 'definitions/index';
declare function VantComponent<Data extends WechatMiniprogram.Component.DataOption, Props extends WechatMiniprogram.Component.PropertyOption, Methods extends WechatMiniprogram.Component.MethodOption>(vantOptions: VantComponentOptions<Data, Props, Methods>): void;
export { VantComponent };
import { basic } from '../mixins/basic';
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',
destroyed: 'detached',
classes: 'externalClasses',
});
// add default externalClasses
options.externalClasses = options.externalClasses || [];
options.externalClasses.push('custom-class');
// add default behaviors
options.behaviors = options.behaviors || [];
options.behaviors.push(basic);
// add relations
const { relation } = vantOptions;
if (relation) {
options.relations = relation.relations;
options.behaviors.push(relation.mixin);
}
// map field to form-field behavior
if (vantOptions.field) {
options.behaviors.push('wx://form-field');
}
// add default options
options.options = {
multipleSlots: true,
addGlobalClass: true,
};
Component(options);
}
export { VantComponent };
.van-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{clear:both;content:"";display:table}.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{border:0 solid #ebedf0;bottom:-50%;box-sizing:border-box;content:" ";left:-50%;pointer-events:none;position:absolute;right:-50%;top:-50%;transform:scale(.5);transform-origin:center}.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
/// <reference types="miniprogram-api-typings" />
declare type TrivialInstance = WechatMiniprogram.Component.TrivialInstance;
export declare function useParent(name: string, onEffect?: (this: TrivialInstance) => void): {
relations: {
[x: string]: WechatMiniprogram.Component.RelationOption;
};
mixin: string;
};
export declare function useChildren(name: string, onEffect?: (this: TrivialInstance, target: TrivialInstance) => void): {
relations: {
[x: string]: WechatMiniprogram.Component.RelationOption;
};
mixin: string;
};
export {};
export function useParent(name, onEffect) {
const path = `../${name}/index`;
return {
relations: {
[path]: {
type: 'ancestor',
linked() {
onEffect && onEffect.call(this);
},
linkChanged() {
onEffect && onEffect.call(this);
},
unlinked() {
onEffect && onEffect.call(this);
},
},
},
mixin: Behavior({
created() {
Object.defineProperty(this, 'parent', {
get: () => this.getRelationNodes(path)[0],
});
Object.defineProperty(this, 'index', {
// @ts-ignore
get: () => { var _a, _b; return (_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b.indexOf(this); },
});
},
}),
};
}
export function useChildren(name, onEffect) {
const path = `../${name}/index`;
return {
relations: {
[path]: {
type: 'descendant',
linked(target) {
onEffect && onEffect.call(this, target);
},
linkChanged(target) {
onEffect && onEffect.call(this, target);
},
unlinked(target) {
onEffect && onEffect.call(this, target);
},
},
},
mixin: Behavior({
created() {
Object.defineProperty(this, 'children', {
get: () => this.getRelationNodes(path) || [],
});
},
}),
};
}
.van-clearfix:after{clear:both;content:"";display:table}
\ No newline at end of file
.van-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.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{border:0 solid #ebedf0;bottom:-50%;box-sizing:border-box;content:" ";left:-50%;pointer-events:none;position:absolute;right:-50%;top:-50%;transform:scale(.5);transform-origin:center}.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
/// <reference types="miniprogram-api-typings" />
/// <reference types="node" />
export { isDef } from './validator';
export declare function range(num: number, min: number, max: number): number;
export declare function nextTick(cb: (...args: any[]) => void): void;
export declare function getSystemInfoSync(): WechatMiniprogram.SystemInfo;
export declare function addUnit(value?: string | number): string | undefined;
export declare function requestAnimationFrame(cb: () => void): NodeJS.Timeout | WechatMiniprogram.NodesRef;
export declare function pickExclude(obj: unknown, keys: string[]): {};
export declare function getRect(context: WechatMiniprogram.Component.TrivialInstance, selector: string): Promise<WechatMiniprogram.BoundingClientRectCallbackResult>;
export declare function getAllRect(context: WechatMiniprogram.Component.TrivialInstance, selector: string): Promise<WechatMiniprogram.BoundingClientRectCallbackResult[]>;
export declare function groupSetData(context: WechatMiniprogram.Component.TrivialInstance, cb: () => void): void;
export declare function toPromise(promiseLike: Promise<unknown> | unknown): Promise<unknown>;
export declare function getCurrentPage<T>(): T & WechatMiniprogram.OptionalInterface<WechatMiniprogram.Page.ILifetime> & WechatMiniprogram.Page.InstanceProperties & WechatMiniprogram.Page.InstanceMethods<WechatMiniprogram.IAnyObject> & WechatMiniprogram.Page.Data<WechatMiniprogram.IAnyObject> & WechatMiniprogram.IAnyObject;
import { isDef, isNumber, isPlainObject, isPromise } from './validator';
import { canIUseGroupSetData, canIUseNextTick } from './version';
export { isDef } from './validator';
export function range(num, min, max) {
return Math.min(Math.max(num, min), max);
}
export function nextTick(cb) {
if (canIUseNextTick()) {
wx.nextTick(cb);
}
else {
setTimeout(() => {
cb();
}, 1000 / 30);
}
}
let systemInfo;
export function getSystemInfoSync() {
if (systemInfo == null) {
systemInfo = wx.getSystemInfoSync();
}
return systemInfo;
}
export function addUnit(value) {
if (!isDef(value)) {
return undefined;
}
value = String(value);
return isNumber(value) ? `${value}px` : value;
}
export function requestAnimationFrame(cb) {
const systemInfo = getSystemInfoSync();
if (systemInfo.platform === 'devtools') {
return setTimeout(() => {
cb();
}, 1000 / 30);
}
return wx
.createSelectorQuery()
.selectViewport()
.boundingClientRect()
.exec(() => {
cb();
});
}
export function pickExclude(obj, keys) {
if (!isPlainObject(obj)) {
return {};
}
return Object.keys(obj).reduce((prev, key) => {
if (!keys.includes(key)) {
prev[key] = obj[key];
}
return prev;
}, {});
}
export function getRect(context, selector) {
return new Promise((resolve) => {
wx.createSelectorQuery()
.in(context)
.select(selector)
.boundingClientRect()
.exec((rect = []) => resolve(rect[0]));
});
}
export function getAllRect(context, selector) {
return new Promise((resolve) => {
wx.createSelectorQuery()
.in(context)
.selectAll(selector)
.boundingClientRect()
.exec((rect = []) => resolve(rect[0]));
});
}
export function groupSetData(context, cb) {
if (canIUseGroupSetData()) {
context.groupSetData(cb);
}
else {
cb();
}
}
export function toPromise(promiseLike) {
if (isPromise(promiseLike)) {
return promiseLike;
}
return Promise.resolve(promiseLike);
}
export function getCurrentPage() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
export declare function isFunction(val: unknown): val is Function;
export declare function isPlainObject(val: unknown): val is Record<string, unknown>;
export declare function isPromise<T = unknown>(val: unknown): val is Promise<T>;
export declare function isDef(value: unknown): boolean;
export declare function isObj(x: unknown): x is Record<string, unknown>;
export declare function isNumber(value: string): boolean;
export declare function isBoolean(value: unknown): value is boolean;
export declare function isImageUrl(url: string): boolean;
export declare function isVideoUrl(url: string): boolean;
// eslint-disable-next-line @typescript-eslint/ban-types
export function isFunction(val) {
return typeof val === 'function';
}
export function isPlainObject(val) {
return val !== null && typeof val === 'object' && !Array.isArray(val);
}
export function isPromise(val) {
return isPlainObject(val) && isFunction(val.then) && isFunction(val.catch);
}
export function isDef(value) {
return value !== undefined && value !== null;
}
export function isObj(x) {
const type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
export function isNumber(value) {
return /^\d+(\.\d+)?$/.test(value);
}
export function isBoolean(value) {
return typeof value === 'boolean';
}
const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i;
export function isImageUrl(url) {
return IMAGE_REGEXP.test(url);
}
export function isVideoUrl(url) {
return VIDEO_REGEXP.test(url);
}
export declare function canIUseModel(): boolean;
export declare function canIUseFormFieldButton(): boolean;
export declare function canIUseAnimate(): boolean;
export declare function canIUseGroupSetData(): boolean;
export declare function canIUseNextTick(): boolean;
export declare function canIUseCanvas2d(): boolean;
export declare function canIUseGetUserProfile(): boolean;
import { getSystemInfoSync } from './utils';
function compareVersion(v1, v2) {
v1 = v1.split('.');
v2 = v2.split('.');
const len = Math.max(v1.length, v2.length);
while (v1.length < len) {
v1.push('0');
}
while (v2.length < len) {
v2.push('0');
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i], 10);
const num2 = parseInt(v2[i], 10);
if (num1 > num2) {
return 1;
}
if (num1 < num2) {
return -1;
}
}
return 0;
}
function gte(version) {
const system = getSystemInfoSync();
return compareVersion(system.SDKVersion, version) >= 0;
}
export function canIUseModel() {
return gte('2.9.3');
}
export function canIUseFormFieldButton() {
return gte('2.10.3');
}
export function canIUseAnimate() {
return gte('2.9.0');
}
export function canIUseGroupSetData() {
return gte('2.4.0');
}
export function canIUseNextTick() {
return wx.canIUse('nextTick');
}
export function canIUseCanvas2d() {
return gte('2.9.0');
}
export function canIUseGetUserProfile() {
return !!wx.getUserProfile;
}
import { VantComponent } from '../common/component';
VantComponent({
props: {
themeVars: {
type: Object,
value: {},
},
},
});
<wxs src="./index.wxs" module="computed" />
<view class="van-config-provider" style="{{ computed.mapThemeVarsToCSSVars(themeVars) }}">
<slot />
</view>
/* eslint-disable */
var object = require('../wxs/object.wxs');
var style = require('../wxs/style.wxs');
function kebabCase(word) {
var newWord = word
.replace(getRegExp("[A-Z]", 'g'), function (i) {
return '-' + i;
})
.toLowerCase()
.replace(getRegExp("^-"), '');
return newWord;
}
function mapThemeVarsToCSSVars(themeVars) {
var cssVars = {};
object.keys(themeVars).forEach(function (key) {
var cssVarsKey = '--' + kebabCase(key);
cssVars[cssVarsKey] = themeVars[key];
});
return style(cssVars);
}
module.exports = {
kebabCase: kebabCase,
mapThemeVarsToCSSVars: mapThemeVarsToCSSVars,
};
import { VantComponent } from '../common/component';
import { isSameSecond, parseFormat, parseTimeData } from './utils';
function simpleTick(fn) {
return setTimeout(fn, 30);
}
VantComponent({
props: {
useSlot: Boolean,
millisecond: Boolean,
time: {
type: Number,
observer: 'reset',
},
format: {
type: String,
value: 'HH:mm:ss',
},
autoStart: {
type: Boolean,
value: true,
},
},
data: {
timeData: parseTimeData(0),
formattedTime: '0',
},
destroyed() {
clearTimeout(this.tid);
this.tid = null;
},
methods: {
// 开始
start() {
if (this.counting) {
return;
}
this.counting = true;
this.endTime = Date.now() + this.remain;
this.tick();
},
// 暂停
pause() {
this.counting = false;
clearTimeout(this.tid);
},
// 重置
reset() {
this.pause();
this.remain = this.data.time;
this.setRemain(this.remain);
if (this.data.autoStart) {
this.start();
}
},
tick() {
if (this.data.millisecond) {
this.microTick();
}
else {
this.macroTick();
}
},
microTick() {
this.tid = simpleTick(() => {
this.setRemain(this.getRemain());
if (this.remain !== 0) {
this.microTick();
}
});
},
macroTick() {
this.tid = simpleTick(() => {
const remain = this.getRemain();
if (!isSameSecond(remain, this.remain) || remain === 0) {
this.setRemain(remain);
}
if (this.remain !== 0) {
this.macroTick();
}
});
},
getRemain() {
return Math.max(this.endTime - Date.now(), 0);
},
setRemain(remain) {
this.remain = remain;
const timeData = parseTimeData(remain);
if (this.data.useSlot) {
this.$emit('change', timeData);
}
this.setData({
formattedTime: parseFormat(this.data.format, timeData),
});
if (remain === 0) {
this.pause();
this.$emit('finish');
}
},
},
});
<view class="van-count-down">
<slot wx:if="{{ useSlot }}"/>
<block wx:else>{{ formattedTime }}</block>
</view>
@import '../common/index.wxss';.van-count-down{color:var(--count-down-text-color,#323233);font-size:var(--count-down-font-size,14px);line-height:var(--count-down-line-height,20px)}
\ No newline at end of file
export declare type TimeData = {
days: number;
hours: number;
minutes: number;
seconds: number;
milliseconds: number;
};
export declare function parseTimeData(time: number): TimeData;
export declare function parseFormat(format: string, timeData: TimeData): string;
export declare function isSameSecond(time1: number, time2: number): boolean;
function padZero(num, targetLength = 2) {
let str = num + '';
while (str.length < targetLength) {
str = '0' + str;
}
return str;
}
const SECOND = 1000;
const MINUTE = 60 * SECOND;
const HOUR = 60 * MINUTE;
const DAY = 24 * HOUR;
export function parseTimeData(time) {
const days = Math.floor(time / DAY);
const hours = Math.floor((time % DAY) / HOUR);
const minutes = Math.floor((time % HOUR) / MINUTE);
const seconds = Math.floor((time % MINUTE) / SECOND);
const milliseconds = Math.floor(time % SECOND);
return {
days,
hours,
minutes,
seconds,
milliseconds,
};
}
export function parseFormat(format, timeData) {
const { days } = timeData;
let { hours, minutes, seconds, milliseconds } = timeData;
if (format.indexOf('DD') === -1) {
hours += days * 24;
}
else {
format = format.replace('DD', padZero(days));
}
if (format.indexOf('HH') === -1) {
minutes += hours * 60;
}
else {
format = format.replace('HH', padZero(hours));
}
if (format.indexOf('mm') === -1) {
seconds += minutes * 60;
}
else {
format = format.replace('mm', padZero(minutes));
}
if (format.indexOf('ss') === -1) {
milliseconds += seconds * 1000;
}
else {
format = format.replace('ss', padZero(seconds));
}
return format.replace('SSS', padZero(milliseconds, 3));
}
export function isSameSecond(time1, time2) {
return Math.floor(time1 / 1000) === Math.floor(time2 / 1000);
}
import { VantComponent } from '../common/component';
import { isDef } from '../common/validator';
import { pickerProps } from '../picker/shared';
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 < 0 ? 0 : n);
while (++index < n) {
result[index] = iteratee(index);
}
return result;
}
function getTrueValue(formattedValue) {
if (formattedValue === undefined) {
formattedValue = '1';
}
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();
}
const defaultFormatter = (type, value) => value;
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: Object.assign(Object.assign({}, pickerProps), { value: {
type: null,
observer: 'updateValue',
}, filter: null, type: {
type: String,
value: 'datetime',
observer: 'updateValue',
}, showToolbar: {
type: Boolean,
value: true,
}, formatter: {
type: null,
value: defaultFormatter,
}, minDate: {
type: Number,
value: new Date(currentYear - 10, 0, 1).getTime(),
observer: 'updateValue',
}, maxDate: {
type: Number,
value: new Date(currentYear + 10, 11, 31).getTime(),
observer: 'updateValue',
}, minHour: {
type: Number,
value: 0,
observer: 'updateValue',
}, maxHour: {
type: Number,
value: 23,
observer: 'updateValue',
}, minMinute: {
type: Number,
value: 0,
observer: 'updateValue',
}, maxMinute: {
type: Number,
value: 59,
observer: 'updateValue',
} }),
data: {
innerValue: Date.now(),
columns: [],
},
methods: {
updateValue() {
const { data } = this;
const val = this.correctValue(data.value);
const isEqual = val === data.innerValue;
this.updateColumnValue(val).then(() => {
if (!isEqual) {
this.$emit('input', val);
}
});
},
getPicker() {
if (this.picker == null) {
this.picker = this.selectComponent('.van-datetime-picker');
const { picker } = this;
const { setColumnValues } = picker;
picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]);
}
return this.picker;
},
updateColumns() {
const { formatter = defaultFormatter } = this.data;
const results = this.getOriginColumns().map((column) => ({
values: column.values.map((value) => formatter(column.type, value)),
}));
return this.set({ columns: results });
},
getOriginColumns() {
const { filter } = this.data;
const results = this.getRanges().map(({ type, range }) => {
let values = times(range[1] - range[0] + 1, (index) => {
const value = range[0] + index;
return type === 'year' ? `${value}` : padZero(value);
});
if (filter) {
values = filter(type, values);
}
return { type, values };
});
return 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();
const originColumns = this.getOriginColumns();
if (data.type === 'time') {
const indexes = picker.getIndexes();
value = `${+originColumns[0].values[indexes[0]]}:${+originColumns[1]
.values[indexes[1]]}`;
}
else {
const indexes = picker.getIndexes();
const values = indexes.map((value, index) => originColumns[index].values[value]);
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 { type } = this.data;
const formatter = this.data.formatter || defaultFormatter;
const picker = this.getPicker();
if (type === 'time') {
const pair = value.split(':');
values = [formatter('hour', pair[0]), formatter('minute', pair[1])];
}
else {
const date = new Date(value);
values = [
formatter('year', `${date.getFullYear()}`),
formatter('month', padZero(date.getMonth() + 1)),
];
if (type === 'date') {
values.push(formatter('day', padZero(date.getDate())));
}
if (type === 'datetime') {
values.push(formatter('day', padZero(date.getDate())), formatter('hour', padZero(date.getHours())), formatter('minute', 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"
active-class="active-class"
toolbar-class="toolbar-class"
column-class="column-class"
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
/// <reference types="miniprogram-api-typings" />
interface VantComponentInstance {
parent: WechatMiniprogram.Component.TrivialInstance;
children: WechatMiniprogram.Component.TrivialInstance[];
index: number;
$emit: (name: string, detail?: unknown, options?: WechatMiniprogram.Component.TriggerEventOption) => void;
}
export declare type VantComponentOptions<Data extends WechatMiniprogram.Component.DataOption, Props extends WechatMiniprogram.Component.PropertyOption, Methods extends WechatMiniprogram.Component.MethodOption> = {
data?: Data;
field?: boolean;
classes?: string[];
mixins?: string[];
props?: Props;
relation?: {
relations: Record<string, WechatMiniprogram.Component.RelationOption>;
mixin: string;
};
methods?: Methods;
beforeCreate?: () => void;
created?: () => void;
mounted?: () => void;
destroyed?: () => void;
} & ThisType<VantComponentInstance & WechatMiniprogram.Component.Instance<Data & {
name: string;
value: any;
} & Record<string, any>, Props, Methods> & Record<string, any>>;
export {};
/// <reference types="miniprogram-api-typings" />
export declare type Action = 'confirm' | 'cancel' | 'overlay';
interface DialogOptions {
lang?: string;
show?: boolean;
title?: string;
width?: string | number | null;
zIndex?: number;
theme?: string;
context?: WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance;
message?: string;
overlay?: boolean;
selector?: string;
ariaLabel?: string;
className?: string;
customStyle?: string;
transition?: string;
/**
* @deprecated use beforeClose instead
*/
asyncClose?: boolean;
beforeClose?: null | ((action: Action) => Promise<void | boolean> | void);
businessId?: number;
sessionFrom?: string;
overlayStyle?: 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;
}
declare const Dialog: {
(options: DialogOptions): Promise<WechatMiniprogram.Component.TrivialInstance>;
alert(options: DialogOptions): Promise<WechatMiniprogram.Component.TrivialInstance>;
confirm(options: DialogOptions): Promise<WechatMiniprogram.Component.TrivialInstance>;
close(): void;
stopLoading(): void;
currentOptions: DialogOptions;
defaultOptions: DialogOptions;
setDefaultOptions(options: DialogOptions): void;
resetDefaultOptions(): void;
};
export default Dialog;
let queue = [];
const defaultOptions = {
show: false,
title: '',
width: null,
theme: 'default',
message: '',
zIndex: 100,
overlay: true,
selector: '#van-dialog',
className: '',
asyncClose: false,
beforeClose: null,
transition: 'scale',
customStyle: '',
messageAlign: '',
overlayStyle: '',
confirmButtonText: '确认',
cancelButtonText: '取消',
showConfirmButton: true,
showCancelButton: false,
closeOnClickOverlay: false,
confirmButtonOpenType: '',
};
let currentOptions = Object.assign({}, defaultOptions);
function getContext() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
const Dialog = (options) => {
options = Object.assign(Object.assign({}, currentOptions), options);
return new Promise((resolve, reject) => {
const context = options.context || getContext();
const dialog = context.selectComponent(options.selector);
delete options.context;
delete options.selector;
if (dialog) {
dialog.setData(Object.assign({ callback: (action, instance) => {
action === 'confirm' ? resolve(instance) : reject(instance);
} }, options));
wx.nextTick(() => {
dialog.setData({ show: true });
});
queue.push(dialog);
}
else {
console.warn('未找到 van-dialog 节点,请确认 selector 及 context 是否正确');
}
});
};
Dialog.alert = (options) => Dialog(options);
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.currentOptions = currentOptions;
Dialog.defaultOptions = defaultOptions;
Dialog.setDefaultOptions = (options) => {
currentOptions = Object.assign(Object.assign({}, currentOptions), options);
Dialog.currentOptions = currentOptions;
};
Dialog.resetDefaultOptions = () => {
currentOptions = Object.assign({}, defaultOptions);
Dialog.currentOptions = currentOptions;
};
Dialog.resetDefaultOptions();
export default Dialog;
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { GRAY, RED } from '../common/color';
import { toPromise } from '../common/utils';
VantComponent({
mixins: [button],
props: {
show: {
type: Boolean,
observer(show) {
!show && this.stopLoading();
},
},
title: String,
message: String,
theme: {
type: String,
value: 'default',
},
useSlot: Boolean,
className: String,
customStyle: String,
asyncClose: Boolean,
messageAlign: String,
beforeClose: null,
overlayStyle: String,
useTitleSlot: Boolean,
showCancelButton: Boolean,
closeOnClickOverlay: Boolean,
confirmButtonOpenType: String,
width: null,
zIndex: {
type: Number,
value: 2000,
},
confirmButtonText: {
type: String,
value: '确认',
},
cancelButtonText: {
type: String,
value: '取消',
},
confirmButtonColor: {
type: String,
value: RED,
},
cancelButtonColor: {
type: String,
value: GRAY,
},
showConfirmButton: {
type: Boolean,
value: true,
},
overlay: {
type: Boolean,
value: true,
},
transition: {
type: String,
value: 'scale',
},
},
data: {
loading: {
confirm: false,
cancel: false,
},
callback: (() => { }),
},
methods: {
onConfirm() {
this.handleAction('confirm');
},
onCancel() {
this.handleAction('cancel');
},
onClickOverlay() {
this.close('overlay');
},
close(action) {
this.setData({ show: false });
wx.nextTick(() => {
this.$emit('close', action);
const { callback } = this.data;
if (callback) {
callback(action, this);
}
});
},
stopLoading() {
this.setData({
loading: {
confirm: false,
cancel: false,
},
});
},
handleAction(action) {
this.$emit(action, { dialog: this });
const { asyncClose, beforeClose } = this.data;
if (!asyncClose && !beforeClose) {
this.close(action);
return;
}
this.setData({
[`loading.${action}`]: true,
});
if (beforeClose) {
toPromise(beforeClose(action)).then((value) => {
if (value) {
this.close(action);
}
else {
this.stopLoading();
}
});
}
},
},
});
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"van-button": "../button/index",
"van-goods-action": "../goods-action/index",
"van-goods-action-button": "../goods-action-button/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<van-popup
show="{{ show }}"
z-index="{{ zIndex }}"
overlay="{{ overlay }}"
transition="{{ transition }}"
custom-class="van-dialog van-dialog--{{ theme }} {{ className }}"
custom-style="width: {{ utils.addUnit(width) }};{{ customStyle }}"
overlay-style="{{ overlayStyle }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:close="onClickOverlay"
>
<view
wx:if="{{ title || useTitleSlot }}"
class="{{ utils.bem('dialog__header', { isolated: !(message || useSlot) }) }}"
>
<slot wx:if="{{ useTitleSlot }}" name="title" />
<block wx:elif="{{ title }}">{{ title }}</block>
</view>
<slot wx:if="{{ useSlot }}" />
<view
wx:elif="{{ message }}"
class="{{ utils.bem('dialog__message', [theme, messageAlign, { hasTitle: title }]) }}"
>
<text class="van-dialog__message-text">{{ message }}</text>
</view>
<van-goods-action wx:if="{{ theme === 'round-button' }}" custom-class="van-dialog__footer--round-button">
<van-goods-action-button
wx:if="{{ showCancelButton }}"
size="large"
loading="{{ loading.cancel }}"
class="van-dialog__button van-hairline--right"
custom-class="van-dialog__cancel"
custom-style="color: {{ cancelButtonColor }}"
bind:click="onCancel"
>
{{ cancelButtonText }}
</van-goods-action-button>
<van-goods-action-button
wx:if="{{ showConfirmButton }}"
size="large"
class="van-dialog__button"
loading="{{ loading.confirm }}"
custom-class="van-dialog__confirm"
custom-style="color: {{ confirmButtonColor }}"
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="onGetUserInfo"
bindcontact="onContact"
bindgetphonenumber="onGetPhoneNumber"
binderror="onError"
bindlaunchapp="onLaunchApp"
bindopensetting="onOpenSetting"
>
{{ confirmButtonText }}
</van-goods-action-button>
</van-goods-action>
<view wx:else 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"
custom-style="color: {{ cancelButtonColor }}"
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"
custom-style="color: {{ confirmButtonColor }}"
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="onGetUserInfo"
bindcontact="onContact"
bindgetphonenumber="onGetPhoneNumber"
binderror="onError"
bindlaunchapp="onLaunchApp"
bindopensetting="onOpenSetting"
>
{{ confirmButtonText }}
</van-button>
</view>
</van-popup>
@import '../common/index.wxss';.van-dialog{background-color:var(--dialog-background-color,#fff);border-radius:var(--dialog-border-radius,16px);font-size:var(--dialog-font-size,16px);overflow:hidden;top:45%!important;width:var(--dialog-width,320px)}@media (max-width:321px){.van-dialog{width:var(--dialog-small-screen-width,90%)}}.van-dialog__header{font-weight:var(--dialog-header-font-weight,500);line-height:var(--dialog-header-line-height,24px);padding-top:var(--dialog-header-padding-top,24px);text-align:center}.van-dialog__header--isolated{padding:var(--dialog-header-isolated-padding,24px 0)}.van-dialog__message{-webkit-overflow-scrolling:touch;font-size:var(--dialog-message-font-size,14px);line-height:var(--dialog-message-line-height,20px);max-height:var(--dialog-message-max-height,60vh);overflow-y:auto;padding:var(--dialog-message-padding,24px);text-align:center}.van-dialog__message-text{word-wrap:break-word}.van-dialog__message--hasTitle{color:var(--dialog-has-title-message-text-color,#646566);padding-top:var(--dialog-has-title-message-padding-top,8px)}.van-dialog__message--round-button{color:#323233;padding-bottom:16px}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__footer{display:flex}.van-dialog__footer--round-button{padding:8px 24px 16px!important;position:relative!important}.van-dialog__button{flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog-bounce-enter{opacity:0;transform:translate3d(-50%,-50%,0) scale(.7)}.van-dialog-bounce-leave-active{opacity:0;transform:translate3d(-50%,-50%,0) scale(.9)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
props: {
dashed: Boolean,
hairline: Boolean,
contentPosition: String,
fontSize: String,
borderColor: String,
textColor: String,
customStyle: String,
},
});
{
"component": true,
"usingComponents": {}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view
class="custom-class {{ utils.bem('divider', [{ dashed, hairline }, contentPosition]) }}"
style="{{ computed.rootStyle({ borderColor, textColor, fontSize, customStyle }) }}"
>
<slot />
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style([
{
'border-color': data.borderColor,
color: data.textColor,
'font-size': addUnit(data.fontSize),
},
data.customStyle,
]);
}
module.exports = {
rootStyle: rootStyle,
};
@import '../common/index.wxss';.van-divider{align-items:center;border:0 solid var(--divider-border-color,#ebedf0);color:var(--divider-text-color,#969799);display:flex;font-size:var(--divider-font-size,14px);line-height:var(--divider-line-height,24px);margin:var(--divider-margin,16px 0)}.van-divider:after,.van-divider:before{border-color:inherit;border-style:inherit;border-width:1px 0 0;box-sizing:border-box;display:block;flex:1;height:1px}.van-divider:before{content:""}.van-divider--hairline:after,.van-divider--hairline:before{transform:scaleY(.5)}.van-divider--dashed{border-style:dashed}.van-divider--center:before,.van-divider--left:before,.van-divider--right:before{margin-right:var(--divider-content-padding,16px)}.van-divider--center:after,.van-divider--left:after,.van-divider--right:after{content:"";margin-left:var(--divider-content-padding,16px)}.van-divider--left:before{max-width:var(--divider-content-left-width,10%)}.van-divider--right:after{max-width:var(--divider-content-right-width,10%)}
\ No newline at end of file
import { useParent } from '../common/relation';
import { VantComponent } from '../common/component';
VantComponent({
field: true,
relation: useParent('dropdown-menu', function () {
this.updateDataFromParent();
}),
props: {
value: {
type: null,
observer: 'rerender',
},
title: {
type: String,
observer: 'rerender',
},
disabled: Boolean,
titleClass: {
type: String,
observer: 'rerender',
},
options: {
type: Array,
value: [],
observer: 'rerender',
},
popupStyle: String,
},
data: {
transition: true,
showPopup: false,
showWrapper: false,
displayTitle: '',
},
methods: {
rerender() {
wx.nextTick(() => {
var _a;
(_a = this.parent) === null || _a === void 0 ? void 0 : _a.updateItemListData();
});
},
updateDataFromParent() {
if (this.parent) {
const { overlay, duration, activeColor, closeOnClickOverlay, direction, } = this.parent.data;
this.setData({
overlay,
duration,
activeColor,
closeOnClickOverlay,
direction,
});
}
},
onOpen() {
this.$emit('open');
},
onOpened() {
this.$emit('opened');
},
onClose() {
this.$emit('close');
},
onClosed() {
this.$emit('closed');
this.setData({ showWrapper: false });
},
onOptionTap(event) {
const { option } = event.currentTarget.dataset;
const { value } = option;
const shouldEmitChange = this.data.value !== value;
this.setData({ showPopup: false, value });
this.$emit('close');
this.rerender();
if (shouldEmitChange) {
this.$emit('change', value);
}
},
toggle(show, options = {}) {
var _a;
const { showPopup } = this.data;
if (typeof show !== 'boolean') {
show = !showPopup;
}
if (show === showPopup) {
return;
}
this.setData({
transition: !options.immediate,
showPopup: show,
});
if (show) {
(_a = this.parent) === null || _a === void 0 ? void 0 : _a.getChildWrapperStyle().then((wrapperStyle) => {
this.setData({ wrapperStyle, showWrapper: true });
this.rerender();
});
}
else {
this.rerender();
}
},
},
});
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"van-cell": "../cell/index",
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
wx:if="{{ showWrapper }}"
class="{{ utils.bem('dropdown-item', direction) }}"
style="{{ wrapperStyle }}"
>
<van-popup
show="{{ showPopup }}"
custom-style="position: absolute;{{ popupStyle }}"
overlay-style="position: absolute;"
overlay="{{ overlay }}"
position="{{ direction === 'down' ? 'top' : 'bottom' }}"
duration="{{ transition ? duration : 0 }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:enter="onOpen"
bind:leave="onClose"
bind:close="toggle"
bind:after-enter="onOpened"
bind:after-leave="onClosed"
>
<van-cell
wx:for="{{ options }}"
wx:key="value"
data-option="{{ item }}"
class="{{ utils.bem('dropdown-item__option', { active: item.value === value } ) }}"
clickable
icon="{{ item.icon }}"
bind:tap="onOptionTap"
>
<view
slot="title"
class="van-dropdown-item__title"
style="{{ item.value === value ? 'color:' + activeColor : '' }}"
>
{{ item.text }}
</view>
<van-icon
wx:if="{{ item.value === value }}"
name="success"
class="van-dropdown-item__icon"
color="{{ activeColor }}"
/>
</van-cell>
<slot />
</van-popup>
</view>
@import '../common/index.wxss';.van-dropdown-item{left:0;overflow:hidden;position:fixed;right:0}.van-dropdown-item__option{text-align:left}.van-dropdown-item__option--active .van-dropdown-item__icon,.van-dropdown-item__option--active .van-dropdown-item__title{color:var(--dropdown-menu-option-active-color,#ee0a24)}.van-dropdown-item--up{top:0}.van-dropdown-item--down{bottom:0}.van-dropdown-item__icon{display:block;line-height:inherit}
\ No newline at end of file
export interface Option {
text: string;
value: string | number;
icon: string;
}
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
import { addUnit, getRect, getSystemInfoSync } from '../common/utils';
let ARRAY = [];
VantComponent({
field: true,
relation: useChildren('dropdown-item', function () {
this.updateItemListData();
}),
props: {
activeColor: {
type: String,
observer: 'updateChildrenData',
},
overlay: {
type: Boolean,
value: true,
observer: 'updateChildrenData',
},
zIndex: {
type: Number,
value: 10,
},
duration: {
type: Number,
value: 200,
observer: 'updateChildrenData',
},
direction: {
type: String,
value: 'down',
observer: 'updateChildrenData',
},
closeOnClickOverlay: {
type: Boolean,
value: true,
observer: 'updateChildrenData',
},
closeOnClickOutside: {
type: Boolean,
value: true,
},
},
data: {
itemListData: [],
},
beforeCreate() {
const { windowHeight } = getSystemInfoSync();
this.windowHeight = windowHeight;
ARRAY.push(this);
},
destroyed() {
ARRAY = ARRAY.filter((item) => item !== this);
},
methods: {
updateItemListData() {
this.setData({
itemListData: this.children.map((child) => child.data),
});
},
updateChildrenData() {
this.children.forEach((child) => {
child.updateDataFromParent();
});
},
toggleItem(active) {
this.children.forEach((item, index) => {
const { showPopup } = item.data;
if (index === active) {
item.toggle();
}
else if (showPopup) {
item.toggle(false, { immediate: true });
}
});
},
close() {
this.children.forEach((child) => {
child.toggle(false, { immediate: true });
});
},
getChildWrapperStyle() {
const { zIndex, direction } = this.data;
return getRect(this, '.van-dropdown-menu').then((rect) => {
const { top = 0, bottom = 0 } = rect;
const offset = direction === 'down' ? bottom : this.windowHeight - top;
let wrapperStyle = `z-index: ${zIndex};`;
if (direction === 'down') {
wrapperStyle += `top: ${addUnit(offset)};`;
}
else {
wrapperStyle += `bottom: ${addUnit(offset)};`;
}
return wrapperStyle;
});
},
onTitleTap(event) {
const { index } = event.currentTarget.dataset;
const child = this.children[index];
if (!child.data.disabled) {
ARRAY.forEach((menuItem) => {
if (menuItem &&
menuItem.data.closeOnClickOutside &&
menuItem !== this) {
menuItem.close();
}
});
this.toggleItem(index);
}
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="van-dropdown-menu van-dropdown-menu--top-bottom custom-class">
<view
wx:for="{{ itemListData }}"
wx:key="index"
data-index="{{ index }}"
class="{{ utils.bem('dropdown-menu__item', { disabled: item.disabled }) }}"
bind:tap="onTitleTap"
>
<view
class="{{ item.titleClass }} {{ utils.bem('dropdown-menu__title', { active: item.showPopup, down: item.showPopup === (direction === 'down') }) }}"
style="{{ item.showPopup ? 'color:' + activeColor : '' }}"
>
<view class="van-ellipsis">
{{ computed.displayTitle(item) }}
</view>
</view>
</view>
<slot />
</view>
/* eslint-disable */
function displayTitle(item) {
if (item.title) {
return item.title;
}
var match = item.options.filter(function(option) {
return option.value === item.value;
});
var displayTitle = match.length ? match[0].text : '';
return displayTitle;
}
module.exports = {
displayTitle: displayTitle
};
@import '../common/index.wxss';.van-dropdown-menu{background-color:var(--dropdown-menu-background-color,#fff);box-shadow:var(--dropdown-menu-box-shadow,0 2px 12px hsla(210,1%,40%,.12));display:flex;height:var(--dropdown-menu-height,50px);-webkit-user-select:none;user-select:none}.van-dropdown-menu__item{align-items:center;display:flex;flex:1;justify-content:center;min-width:0}.van-dropdown-menu__item:active{opacity:.7}.van-dropdown-menu__item--disabled:active{opacity:1}.van-dropdown-menu__item--disabled .van-dropdown-menu__title{color:var(--dropdown-menu-title-disabled-text-color,#969799)}.van-dropdown-menu__title{box-sizing:border-box;color:var(--dropdown-menu-title-text-color,#323233);font-size:var(--dropdown-menu-title-font-size,15px);line-height:var(--dropdown-menu-title-line-height,18px);max-width:100%;padding:var(--dropdown-menu-title-padding,0 8px);position:relative}.van-dropdown-menu__title:after{border-color:transparent transparent currentcolor currentcolor;border-style:solid;border-width:3px;content:"";margin-top:-5px;opacity:.8;position:absolute;right:-4px;top:50%;transform:rotate(-45deg)}.van-dropdown-menu__title--active{color:var(--dropdown-menu-title-active-text-color,#ee0a24)}.van-dropdown-menu__title--down:after{margin-top:-1px;transform:rotate(135deg)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
props: {
description: String,
image: {
type: String,
value: 'default',
},
},
});
{
"component": true,
"usingComponents": {}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="custom-class van-empty">
<view class="van-empty__image">
<slot name="image"></slot>
</view>
<view class="van-empty__image">
<image wx:if="{{ image }}" class="van-empty__image__img" src="{{ computed.imageUrl(image) }}" />
</view>
<view class="van-empty__description">
<slot name="description"></slot>
</view>
<view class="van-empty__description">
{{ description }}
</view>
<view class="van-empty__bottom">
<slot></slot>
</view>
</view>
/* eslint-disable */
var PRESETS = ['error', 'search', 'default', 'network'];
function imageUrl(image) {
if (PRESETS.indexOf(image) !== -1) {
return 'https://img.yzcdn.cn/vant/empty-image-' + image + '.png';
}
return image;
}
module.exports = {
imageUrl: imageUrl,
};
@import '../common/index.wxss';.van-empty{align-items:center;box-sizing:border-box;display:flex;flex-direction:column;justify-content:center;padding:32px 0}.van-empty__image{height:160px;width:160px}.van-empty__image:empty{display:none}.van-empty__image__img{height:100%;width:100%}.van-empty__image:not(:empty)+.van-empty__image{display:none}.van-empty__description{color:#969799;font-size:14px;line-height:20px;margin-top:16px;padding:0 60px}.van-empty__description:empty,.van-empty__description:not(:empty)+.van-empty__description{display:none}.van-empty__bottom{margin-top:24px}
\ No newline at end of file
import { nextTick } from '../common/utils';
import { VantComponent } from '../common/component';
import { commonProps, inputProps, textareaProps } from './props';
VantComponent({
field: true,
classes: ['input-class', 'right-icon-class', 'label-class'],
props: Object.assign(Object.assign(Object.assign(Object.assign({}, commonProps), inputProps), textareaProps), { size: String, icon: String, label: String, error: Boolean, center: Boolean, isLink: Boolean, leftIcon: String, rightIcon: String, autosize: null, required: Boolean, iconClass: String, clickable: Boolean, inputAlign: String, customStyle: String, errorMessage: String, arrowDirection: String, showWordLimit: Boolean, errorMessageAlign: String, readonly: {
type: Boolean,
observer: 'setShowClear',
}, clearable: {
type: Boolean,
observer: 'setShowClear',
}, clearTrigger: {
type: String,
value: 'focus',
}, border: {
type: Boolean,
value: true,
}, titleWidth: {
type: String,
value: '6.2em',
}, clearIcon: {
type: String,
value: 'clear',
} }),
data: {
focused: false,
innerValue: '',
showClear: false,
},
created() {
this.value = this.data.value;
this.setData({ innerValue: this.value });
},
methods: {
onInput(event) {
const { value = '' } = event.detail || {};
this.value = value;
this.setShowClear();
this.emitChange();
},
onFocus(event) {
this.focused = true;
this.setShowClear();
this.$emit('focus', event.detail);
},
onBlur(event) {
this.focused = false;
this.setShowClear();
this.$emit('blur', event.detail);
},
onClickIcon() {
this.$emit('click-icon');
},
onClickInput(event) {
this.$emit('click-input', event.detail);
},
onClear() {
this.setData({ innerValue: '' });
this.value = '';
this.setShowClear();
nextTick(() => {
this.emitChange();
this.$emit('clear', '');
});
},
onConfirm(event) {
const { value = '' } = event.detail || {};
this.value = value;
this.setShowClear();
this.$emit('confirm', value);
},
setValue(value) {
this.value = value;
this.setShowClear();
if (value === '') {
this.setData({ innerValue: '' });
}
this.emitChange();
},
onLineChange(event) {
this.$emit('linechange', event.detail);
},
onKeyboardHeightChange(event) {
this.$emit('keyboardheightchange', event.detail);
},
emitChange() {
this.setData({ value: this.value });
nextTick(() => {
this.$emit('input', this.value);
this.$emit('change', this.value);
});
},
setShowClear() {
const { clearable, readonly, clearTrigger } = this.data;
const { focused, value } = this;
let showClear = false;
if (clearable && !readonly) {
const hasValue = !!value;
const trigger = clearTrigger === 'always' || (clearTrigger === 'focus' && focused);
showClear = hasValue && trigger;
}
this.setData({ showClear });
},
noop() { },
},
});
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index",
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<van-cell
size="{{ size }}"
icon="{{ leftIcon }}"
center="{{ center }}"
border="{{ border }}"
is-link="{{ isLink }}"
required="{{ required }}"
clickable="{{ clickable }}"
title-width="{{ titleWidth }}"
title-style="margin-right: 12px;"
custom-style="{{ customStyle }}"
arrow-direction="{{ arrowDirection }}"
custom-class="van-field"
>
<slot name="left-icon" slot="icon" />
<view wx:if="{{ label }}" class="label-class {{ utils.bem('field__label', { disabled }) }}" slot="title">
{{ label }}
</view>
<slot wx:else name="label" slot="title" />
<view class="{{ utils.bem('field__body', [type]) }}">
<view class="{{ utils.bem('field__control', [inputAlign, 'custom']) }}" bindtap="onClickInput">
<slot name="input" />
</view>
<include wx:if="{{ type === 'textarea' }}" src="./textarea.wxml" />
<include wx:else src="./input.wxml" />
<van-icon
wx:if="{{ showClear }}"
name="{{ clearIcon }}"
class="van-field__clear-root van-field__icon-root"
catch:touchstart="onClear"
/>
<view class="van-field__icon-container" bind:tap="onClickIcon">
<van-icon
wx:if="{{ rightIcon || icon }}"
name="{{ rightIcon || icon }}"
class="van-field__icon-root {{ iconClass }}"
custom-class="right-icon-class"
/>
<slot name="right-icon" />
<slot name="icon" />
</view>
<view class="van-field__button">
<slot name="button" />
</view>
</view>
<view wx:if="{{ showWordLimit && maxlength }}" class="van-field__word-limit">
<view class="{{ utils.bem('field__word-num', { full: value.length >= maxlength }) }}">{{ value.length >= maxlength ? maxlength : value.length }}</view>/{{ maxlength }}
</view>
<view wx:if="{{ errorMessage }}" class="{{ utils.bem('field__error-message', [errorMessageAlign, { disabled, error }]) }}">
{{ errorMessage }}
</view>
</van-cell>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function inputStyle(autosize) {
if (autosize && autosize.constructor === 'Object') {
return style({
'min-height': addUnit(autosize.minHeight),
'max-height': addUnit(autosize.maxHeight),
});
}
return '';
}
module.exports = {
inputStyle: inputStyle,
};
@import '../common/index.wxss';.van-field{--cell-icon-size:var(--field-icon-size,16px)}.van-field__label{color:var(--field-label-color,#646566)}.van-field__label--disabled{color:var(--field-disabled-text-color,#c8c9cc)}.van-field__body{align-items:center;display:flex}.van-field__body--textarea{box-sizing:border-box;line-height:1.2em;min-height:var(--cell-line-height,24px);padding:3.6px 0}.van-field__control:empty+.van-field__control{display:block}.van-field__control{background-color:initial;border:0;box-sizing:border-box;color:var(--field-input-text-color,#323233);display:none;height:var(--cell-line-height,24px);line-height:inherit;margin:0;min-height:var(--cell-line-height,24px);padding:0;position:relative;resize:none;text-align:left;width:100%}.van-field__control:empty{display:none}.van-field__control--textarea{height:var(--field-text-area-min-height,18px);min-height:var(--field-text-area-min-height,18px)}.van-field__control--error{color:var(--field-input-error-text-color,#ee0a24)}.van-field__control--disabled{background-color:initial;color:var(--field-input-disabled-text-color,#c8c9cc);opacity:1}.van-field__control--center{text-align:center}.van-field__control--right{text-align:right}.van-field__control--custom{align-items:center;display:flex;min-height:var(--cell-line-height,24px)}.van-field__placeholder{color:var(--field-placeholder-text-color,#c8c9cc);left:0;pointer-events:none;position:absolute;right:0;top:0}.van-field__placeholder--error{color:var(--field-error-message-color,#ee0a24)}.van-field__icon-root{align-items:center;display:flex;min-height:var(--cell-line-height,24px)}.van-field__clear-root,.van-field__icon-container{line-height:inherit;margin-right:calc(var(--padding-xs, 8px)*-1);padding:0 var(--padding-xs,8px);vertical-align:middle}.van-field__button,.van-field__clear-root,.van-field__icon-container{flex-shrink:0}.van-field__clear-root{color:var(--field-clear-icon-color,#c8c9cc);font-size:var(--field-clear-icon-size,16px)}.van-field__icon-container{color:var(--field-icon-container-color,#969799);font-size:var(--field-icon-size,16px)}.van-field__icon-container:empty{display:none}.van-field__button{padding-left:var(--padding-xs,8px)}.van-field__button:empty{display:none}.van-field__error-message{color:var(--field-error-message-color,#ee0a24);font-size:var(--field-error-message-text-font-size,12px);text-align:left}.van-field__error-message--center{text-align:center}.van-field__error-message--right{text-align:right}.van-field__word-limit{color:var(--field-word-limit-color,#646566);font-size:var(--field-word-limit-font-size,12px);line-height:var(--field-word-limit-line-height,16px);margin-top:var(--padding-base,4px);text-align:right}.van-field__word-num{display:inline}.van-field__word-num--full{color:var(--field-word-num-full-color,#ee0a24)}
\ No newline at end of file
<input
class="{{ utils.bem('field__control', [inputAlign, { disabled, error }]) }} input-class"
type="{{ type }}"
focus="{{ focus }}"
cursor="{{ cursor }}"
value="{{ innerValue }}"
auto-focus="{{ autoFocus }}"
disabled="{{ disabled || readonly }}"
maxlength="{{ maxlength }}"
placeholder="{{ placeholder }}"
placeholder-style="{{ placeholderStyle }}"
placeholder-class="{{ utils.bem('field__placeholder', { error }) }}"
confirm-type="{{ confirmType }}"
confirm-hold="{{ confirmHold }}"
hold-keyboard="{{ holdKeyboard }}"
cursor-spacing="{{ cursorSpacing }}"
adjust-position="{{ adjustPosition }}"
selection-end="{{ selectionEnd }}"
selection-start="{{ selectionStart }}"
always-embed="{{ alwaysEmbed }}"
password="{{ password || type === 'password' }}"
bindinput="onInput"
bindtap="onClickInput"
bindblur="onBlur"
bindfocus="onFocus"
bindconfirm="onConfirm"
bindkeyboardheightchange="onKeyboardHeightChange"
/>
/// <reference types="miniprogram-api-typings" />
export declare const commonProps: WechatMiniprogram.Component.PropertyOption;
export declare const inputProps: WechatMiniprogram.Component.PropertyOption;
export declare const textareaProps: WechatMiniprogram.Component.PropertyOption;
export const commonProps = {
value: {
type: String,
observer(value) {
if (value !== this.value) {
this.setData({ innerValue: value });
this.value = value;
}
},
},
placeholder: String,
placeholderStyle: String,
placeholderClass: String,
disabled: Boolean,
maxlength: {
type: Number,
value: -1,
},
cursorSpacing: {
type: Number,
value: 50,
},
autoFocus: Boolean,
focus: Boolean,
cursor: {
type: Number,
value: -1,
},
selectionStart: {
type: Number,
value: -1,
},
selectionEnd: {
type: Number,
value: -1,
},
adjustPosition: {
type: Boolean,
value: true,
},
holdKeyboard: Boolean,
};
export const inputProps = {
type: {
type: String,
value: 'text',
},
password: Boolean,
confirmType: String,
confirmHold: Boolean,
alwaysEmbed: Boolean,
};
export const textareaProps = {
autoHeight: Boolean,
fixed: Boolean,
showConfirmBar: {
type: Boolean,
value: true,
},
disableDefaultPadding: {
type: Boolean,
value: true,
},
};
<textarea
class="{{ utils.bem('field__control', [inputAlign, type, { disabled, error }]) }} input-class"
fixed="{{ fixed }}"
focus="{{ focus }}"
cursor="{{ cursor }}"
value="{{ innerValue }}"
auto-focus="{{ autoFocus }}"
disabled="{{ disabled || readonly }}"
maxlength="{{ maxlength }}"
placeholder="{{ placeholder }}"
placeholder-style="{{ placeholderStyle }}"
placeholder-class="{{ utils.bem('field__placeholder', { error, disabled }) }}"
auto-height="{{ !!autosize }}"
style="{{ computed.inputStyle(autosize) }}"
cursor-spacing="{{ cursorSpacing }}"
adjust-position="{{ adjustPosition }}"
show-confirm-bar="{{ showConfirmBar }}"
hold-keyboard="{{ holdKeyboard }}"
selection-end="{{ selectionEnd }}"
selection-start="{{ selectionStart }}"
disable-default-padding="{{ disableDefaultPadding }}"
bindinput="onInput"
bindtap="onClickInput"
bindblur="onBlur"
bindfocus="onFocus"
bindconfirm="onConfirm"
bindlinechange="onLineChange"
bindkeyboardheightchange="onKeyboardHeightChange"
/>
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
import { button } from '../mixins/button';
import { link } from '../mixins/link';
VantComponent({
mixins: [link, button],
relation: useParent('goods-action'),
props: {
text: String,
color: String,
loading: Boolean,
disabled: Boolean,
plain: Boolean,
type: {
type: String,
value: 'danger',
},
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
this.jumpLink();
},
updateStyle() {
if (this.parent == null) {
return;
}
const { index } = this;
const { children = [] } = this.parent;
this.setData({
isFirst: index === 0,
isLast: index === children.length - 1,
});
},
},
});
{
"component": true,
"usingComponents": {
"van-button": "../button/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<van-button
id="{{ id }}"
lang="{{ lang }}"
type="{{ type }}"
color="{{ color }}"
plain="{{ plain }}"
loading="{{ loading }}"
disabled="{{ disabled }}"
open-type="{{ openType }}"
class="{{ utils.bem('goods-action-button', [type, { first: isFirst, last: isLast, plain: plain }])}}"
custom-class="van-goods-action-button__inner"
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="onError"
bindcontact="onContact"
bindopensetting="onOpenSetting"
bindgetuserinfo="onGetUserInfo"
bindgetphonenumber="onGetPhoneNumber"
bindlaunchapp="onLaunchApp"
>
{{ text }}
<slot></slot>
</van-button>
@import '../common/index.wxss';:host{flex:1}.van-goods-action-button{--button-warning-background-color:var(--goods-action-button-warning-color,linear-gradient(to right,#ffd01e,#ff8917));--button-danger-background-color:var(--goods-action-button-danger-color,linear-gradient(to right,#ff6034,#ee0a24));--button-default-height:var(--goods-action-button-height,40px);--button-line-height:var(--goods-action-button-line-height,20px);--button-plain-background-color:var(--goods-action-button-plain-color,#fff);--button-border-width:0;display:block}.van-goods-action-button--first{--button-border-radius:999px 0 0 var(--goods-action-button-border-radius,999px);margin-left:5px}.van-goods-action-button--last{--button-border-radius:0 999px var(--goods-action-button-border-radius,999px) 0;margin-right:5px}.van-goods-action-button--first.van-goods-action-button--last{--button-border-radius:var(--goods-action-button-border-radius,999px)}.van-goods-action-button--plain{--button-border-width:1px}.van-goods-action-button__inner{font-weight:var(--font-weight-bold,500)!important;width:100%}@media (max-width:321px){.van-goods-action-button{font-size:13px}}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { link } from '../mixins/link';
VantComponent({
classes: ['icon-class', 'text-class'],
mixins: [link, button],
props: {
text: String,
dot: Boolean,
info: String,
icon: String,
classPrefix: {
type: String,
value: 'van-icon',
},
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="onError"
bindcontact="onContact"
bindopensetting="onOpenSetting"
bindgetuserinfo="onGetUserInfo"
bindgetphonenumber="onGetPhoneNumber"
bindlaunchapp="onLaunchApp"
>
<van-icon
wx:if="{{ icon }}"
name="{{ icon }}"
dot="{{ dot }}"
info="{{ info }}"
class-prefix="{{ classPrefix }}"
class="van-goods-action-icon__icon"
custom-class="icon-class"
/>
<slot wx:else name="icon" />
<text class="text-class">{{ text }}</text>
</van-button>
@import '../common/index.wxss';.van-goods-action-icon{border:none!important;color:var(--goods-action-icon-text-color,#646566)!important;display:flex!important;flex-direction:column;font-size:var(--goods-action-icon-font-size,10px)!important;height:var(--goods-action-icon-height,50px)!important;justify-content:center!important;line-height:1!important;min-width:var(--goods-action-icon-width,48px)}.van-goods-action-icon__icon{color:var(--goods-action-icon-color,#323233);display:flex;font-size:var(--goods-action-icon-size,18px);margin:0 auto 5px}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('goods-action-button', function () {
this.children.forEach((item) => {
item.updateStyle();
});
}),
props: {
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="custom-class {{ utils.bem('goods-action', { safe: safeAreaInsetBottom }) }}">
<slot />
</view>
@import '../common/index.wxss';.van-goods-action{align-items:center;background-color:var(--goods-action-background-color,#fff);bottom:0;box-sizing:initial;display:flex;height:var(--goods-action-height,50px);left:0;position:fixed;right:0}.van-goods-action--safe{padding-bottom:env(safe-area-inset-bottom)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
import { link } from '../mixins/link';
VantComponent({
relation: useParent('grid'),
classes: ['content-class', 'icon-class', 'text-class'],
mixins: [link],
props: {
icon: String,
iconColor: String,
iconPrefix: {
type: String,
value: 'van-icon',
},
dot: Boolean,
info: null,
badge: null,
text: String,
useSlot: Boolean,
},
data: {
viewStyle: '',
},
mounted() {
this.updateStyle();
},
methods: {
updateStyle() {
if (!this.parent) {
return;
}
const { data, children } = this.parent;
const { columnNum, border, square, gutter, clickable, center, direction, reverse, iconSize, } = data;
this.setData({
center,
border,
square,
gutter,
clickable,
direction,
reverse,
iconSize,
index: children.indexOf(this),
columnNum,
});
},
onClick() {
this.$emit('click');
this.jumpLink();
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view
class="custom-class {{ utils.bem('grid-item', { square }) }}"
style="{{ computed.wrapperStyle({ square, gutter, columnNum, index }) }}"
bindtap="onClick"
>
<view
class="content-class {{ utils.bem('grid-item__content', [direction, { center, square, reverse, clickable, surround: border && gutter }]) }} {{ border ? 'van-hairline--surround' : '' }}"
style="{{ computed.contentStyle({ square, gutter }) }}"
>
<block wx:if="{{ useSlot }}">
<slot />
</block>
<block wx:else>
<view class="van-grid-item__icon icon-class">
<van-icon wx:if="{{ icon }}" name="{{ icon }}" color="{{ iconColor }}" class-prefix="{{ iconPrefix }}" dot="{{ dot }}" info="{{ badge || info }}" size="{{ iconSize }}" />
<slot wx:else name="icon"></slot>
</view>
<view class="van-grid-item__text text-class">
<text wx:if="{{ text }}">{{ text }}</text>
<slot wx:else name="text"></slot>
</view>
</block>
</view>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function wrapperStyle(data) {
var width = 100 / data.columnNum + '%';
return style({
width: width,
'padding-top': data.square ? width : null,
'padding-right': addUnit(data.gutter),
'margin-top':
data.index >= data.columnNum && !data.square
? addUnit(data.gutter)
: null,
});
}
function contentStyle(data) {
return data.square
? style({
right: addUnit(data.gutter),
bottom: addUnit(data.gutter),
height: 'auto',
})
: '';
}
module.exports = {
wrapperStyle: wrapperStyle,
contentStyle: contentStyle,
};
@import '../common/index.wxss';.van-grid-item{box-sizing:border-box;float:left;position:relative}.van-grid-item--square{height:0}.van-grid-item__content{background-color:var(--grid-item-content-background-color,#fff);box-sizing:border-box;display:flex;flex-direction:column;height:100%;padding:var(--grid-item-content-padding,16px 8px)}.van-grid-item__content:after{border-width:0 1px 1px 0;z-index:1}.van-grid-item__content--surround:after{border-width:1px}.van-grid-item__content--center{align-items:center;justify-content:center}.van-grid-item__content--square{left:0;position:absolute;right:0;top:0}.van-grid-item__content--horizontal{flex-direction:row}.van-grid-item__content--horizontal .van-grid-item__text{margin:0 0 0 8px}.van-grid-item__content--reverse{flex-direction:column-reverse}.van-grid-item__content--reverse .van-grid-item__text{margin:0 0 8px}.van-grid-item__content--horizontal.van-grid-item__content--reverse{flex-direction:row-reverse}.van-grid-item__content--horizontal.van-grid-item__content--reverse .van-grid-item__text{margin:0 8px 0 0}.van-grid-item__content--clickable:active{background-color:var(--grid-item-content-active-color,#f2f3f5)}.van-grid-item__icon{align-items:center;display:flex;font-size:var(--grid-item-icon-size,26px);height:var(--grid-item-icon-size,26px)}.van-grid-item__text{word-wrap:break-word;color:var(--grid-item-text-color,#646566);font-size:var(--grid-item-text-font-size,12px)}.van-grid-item__icon+.van-grid-item__text{margin-top:8px}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('grid-item'),
props: {
square: {
type: Boolean,
observer: 'updateChildren',
},
gutter: {
type: null,
value: 0,
observer: 'updateChildren',
},
clickable: {
type: Boolean,
observer: 'updateChildren',
},
columnNum: {
type: Number,
value: 4,
observer: 'updateChildren',
},
center: {
type: Boolean,
value: true,
observer: 'updateChildren',
},
border: {
type: Boolean,
value: true,
observer: 'updateChildren',
},
direction: {
type: String,
observer: 'updateChildren',
},
iconSize: {
type: String,
observer: 'updateChildren',
},
reverse: {
type: Boolean,
value: false,
observer: 'updateChildren',
},
},
methods: {
updateChildren() {
this.children.forEach((child) => {
child.updateStyle();
});
},
},
});
<wxs src="./index.wxs" module="computed" />
<view
class="van-grid custom-class {{ border && !gutter ? 'van-hairline--top' : '' }}"
style="{{ computed.rootStyle({ gutter }) }}"
>
<slot />
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style({
'padding-left': addUnit(data.gutter),
});
}
module.exports = {
rootStyle: rootStyle,
};
@import '../common/index.wxss';.van-grid{box-sizing:border-box;overflow:hidden;position:relative}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
props: {
dot: Boolean,
info: null,
size: null,
color: String,
customStyle: String,
classPrefix: {
type: String,
value: 'van-icon',
},
name: String,
},
methods: {
onClick() {
this.$emit('click');
},
},
});
{
"component": true,
"usingComponents": {
"van-info": "../info/index"
}
}
<wxs src="./index.wxs" module="computed" />
<view
class="{{ computed.rootClass({ classPrefix, name }) }}"
style="{{ computed.rootStyle({ customStyle, color, size }) }}"
bindtap="onClick"
>
<van-info
wx:if="{{ info !== null || dot }}"
dot="{{ dot }}"
info="{{ info }}"
custom-class="van-icon__info"
/>
<image
wx:if="{{ computed.isImage(name) }}"
src="{{ name }}"
mode="aspectFit"
class="van-icon__image"
/>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function isImage(name) {
return name.indexOf('/') !== -1;
}
function rootClass(data) {
var classes = ['custom-class'];
if (data.classPrefix != null) {
classes.push(data.classPrefix);
}
if (isImage(data.name)) {
classes.push('van-icon--image');
} else if (data.classPrefix != null) {
classes.push(data.classPrefix + '-' + data.name);
}
return classes.join(' ');
}
function rootStyle(data) {
return style([
{
color: data.color,
'font-size': addUnit(data.size),
},
data.customStyle,
]);
}
module.exports = {
isImage: isImage,
rootClass: rootClass,
rootStyle: rootStyle,
};
@import '../common/index.wxss';.van-icon{text-rendering:auto;-webkit-font-smoothing:antialiased;font:normal normal normal 14px/1 vant-icon;font-size:inherit;position:relative}.van-icon,.van-icon:before{display:inline-block}.van-icon-exchange:before{content:"\e6af"}.van-icon-eye:before{content:"\e6b0"}.van-icon-enlarge:before{content:"\e6b1"}.van-icon-expand-o:before{content:"\e6b2"}.van-icon-eye-o:before{content:"\e6b3"}.van-icon-expand:before{content:"\e6b4"}.van-icon-filter-o:before{content:"\e6b5"}.van-icon-fire:before{content:"\e6b6"}.van-icon-fail:before{content:"\e6b7"}.van-icon-failure:before{content:"\e6b8"}.van-icon-fire-o:before{content:"\e6b9"}.van-icon-flag-o:before{content:"\e6ba"}.van-icon-font:before{content:"\e6bb"}.van-icon-font-o:before{content:"\e6bc"}.van-icon-gem-o:before{content:"\e6bd"}.van-icon-flower-o:before{content:"\e6be"}.van-icon-gem:before{content:"\e6bf"}.van-icon-gift-card:before{content:"\e6c0"}.van-icon-friends:before{content:"\e6c1"}.van-icon-friends-o:before{content:"\e6c2"}.van-icon-gold-coin:before{content:"\e6c3"}.van-icon-gold-coin-o:before{content:"\e6c4"}.van-icon-good-job-o:before{content:"\e6c5"}.van-icon-gift:before{content:"\e6c6"}.van-icon-gift-o:before{content:"\e6c7"}.van-icon-gift-card-o:before{content:"\e6c8"}.van-icon-good-job:before{content:"\e6c9"}.van-icon-home-o:before{content:"\e6ca"}.van-icon-goods-collect:before{content:"\e6cb"}.van-icon-graphic:before{content:"\e6cc"}.van-icon-goods-collect-o:before{content:"\e6cd"}.van-icon-hot-o:before{content:"\e6ce"}.van-icon-info:before{content:"\e6cf"}.van-icon-hotel-o:before{content:"\e6d0"}.van-icon-info-o:before{content:"\e6d1"}.van-icon-hot-sale-o:before{content:"\e6d2"}.van-icon-hot:before{content:"\e6d3"}.van-icon-like:before{content:"\e6d4"}.van-icon-idcard:before{content:"\e6d5"}.van-icon-invitation:before{content:"\e6d6"}.van-icon-like-o:before{content:"\e6d7"}.van-icon-hot-sale:before{content:"\e6d8"}.van-icon-location-o:before{content:"\e6d9"}.van-icon-location:before{content:"\e6da"}.van-icon-label:before{content:"\e6db"}.van-icon-lock:before{content:"\e6dc"}.van-icon-label-o:before{content:"\e6dd"}.van-icon-map-marked:before{content:"\e6de"}.van-icon-logistics:before{content:"\e6df"}.van-icon-manager:before{content:"\e6e0"}.van-icon-more:before{content:"\e6e1"}.van-icon-live:before{content:"\e6e2"}.van-icon-manager-o:before{content:"\e6e3"}.van-icon-medal:before{content:"\e6e4"}.van-icon-more-o:before{content:"\e6e5"}.van-icon-music-o:before{content:"\e6e6"}.van-icon-music:before{content:"\e6e7"}.van-icon-new-arrival-o:before{content:"\e6e8"}.van-icon-medal-o:before{content:"\e6e9"}.van-icon-new-o:before{content:"\e6ea"}.van-icon-free-postage:before{content:"\e6eb"}.van-icon-newspaper-o:before{content:"\e6ec"}.van-icon-new-arrival:before{content:"\e6ed"}.van-icon-minus:before{content:"\e6ee"}.van-icon-orders-o:before{content:"\e6ef"}.van-icon-new:before{content:"\e6f0"}.van-icon-paid:before{content:"\e6f1"}.van-icon-notes-o:before{content:"\e6f2"}.van-icon-other-pay:before{content:"\e6f3"}.van-icon-pause-circle:before{content:"\e6f4"}.van-icon-pause:before{content:"\e6f5"}.van-icon-pause-circle-o:before{content:"\e6f6"}.van-icon-peer-pay:before{content:"\e6f7"}.van-icon-pending-payment:before{content:"\e6f8"}.van-icon-passed:before{content:"\e6f9"}.van-icon-plus:before{content:"\e6fa"}.van-icon-phone-circle-o:before{content:"\e6fb"}.van-icon-phone-o:before{content:"\e6fc"}.van-icon-printer:before{content:"\e6fd"}.van-icon-photo-fail:before{content:"\e6fe"}.van-icon-phone:before{content:"\e6ff"}.van-icon-photo-o:before{content:"\e700"}.van-icon-play-circle:before{content:"\e701"}.van-icon-play:before{content:"\e702"}.van-icon-phone-circle:before{content:"\e703"}.van-icon-point-gift-o:before{content:"\e704"}.van-icon-point-gift:before{content:"\e705"}.van-icon-play-circle-o:before{content:"\e706"}.van-icon-shrink:before{content:"\e707"}.van-icon-photo:before{content:"\e708"}.van-icon-qr:before{content:"\e709"}.van-icon-qr-invalid:before{content:"\e70a"}.van-icon-question-o:before{content:"\e70b"}.van-icon-revoke:before{content:"\e70c"}.van-icon-replay:before{content:"\e70d"}.van-icon-service:before{content:"\e70e"}.van-icon-question:before{content:"\e70f"}.van-icon-search:before{content:"\e710"}.van-icon-refund-o:before{content:"\e711"}.van-icon-service-o:before{content:"\e712"}.van-icon-scan:before{content:"\e713"}.van-icon-share:before{content:"\e714"}.van-icon-send-gift-o:before{content:"\e715"}.van-icon-share-o:before{content:"\e716"}.van-icon-setting:before{content:"\e717"}.van-icon-points:before{content:"\e718"}.van-icon-photograph:before{content:"\e719"}.van-icon-shop:before{content:"\e71a"}.van-icon-shop-o:before{content:"\e71b"}.van-icon-shop-collect-o:before{content:"\e71c"}.van-icon-shop-collect:before{content:"\e71d"}.van-icon-smile:before{content:"\e71e"}.van-icon-shopping-cart-o:before{content:"\e71f"}.van-icon-sign:before{content:"\e720"}.van-icon-sort:before{content:"\e721"}.van-icon-star-o:before{content:"\e722"}.van-icon-smile-comment-o:before{content:"\e723"}.van-icon-stop:before{content:"\e724"}.van-icon-stop-circle-o:before{content:"\e725"}.van-icon-smile-o:before{content:"\e726"}.van-icon-star:before{content:"\e727"}.van-icon-success:before{content:"\e728"}.van-icon-stop-circle:before{content:"\e729"}.van-icon-records:before{content:"\e72a"}.van-icon-shopping-cart:before{content:"\e72b"}.van-icon-tosend:before{content:"\e72c"}.van-icon-todo-list:before{content:"\e72d"}.van-icon-thumb-circle-o:before{content:"\e72e"}.van-icon-thumb-circle:before{content:"\e72f"}.van-icon-umbrella-circle:before{content:"\e730"}.van-icon-underway:before{content:"\e731"}.van-icon-upgrade:before{content:"\e732"}.van-icon-todo-list-o:before{content:"\e733"}.van-icon-tv-o:before{content:"\e734"}.van-icon-underway-o:before{content:"\e735"}.van-icon-user-o:before{content:"\e736"}.van-icon-vip-card-o:before{content:"\e737"}.van-icon-vip-card:before{content:"\e738"}.van-icon-send-gift:before{content:"\e739"}.van-icon-wap-home:before{content:"\e73a"}.van-icon-wap-nav:before{content:"\e73b"}.van-icon-volume-o:before{content:"\e73c"}.van-icon-video:before{content:"\e73d"}.van-icon-wap-home-o:before{content:"\e73e"}.van-icon-volume:before{content:"\e73f"}.van-icon-warning:before{content:"\e740"}.van-icon-weapp-nav:before{content:"\e741"}.van-icon-wechat-pay:before{content:"\e742"}.van-icon-warning-o:before{content:"\e743"}.van-icon-wechat:before{content:"\e744"}.van-icon-setting-o:before{content:"\e745"}.van-icon-youzan-shield:before{content:"\e746"}.van-icon-warn-o:before{content:"\e747"}.van-icon-smile-comment:before{content:"\e748"}.van-icon-user-circle-o:before{content:"\e749"}.van-icon-video-o:before{content:"\e74a"}.van-icon-add-square:before{content:"\e65c"}.van-icon-add:before{content:"\e65d"}.van-icon-arrow-down:before{content:"\e65e"}.van-icon-arrow-up:before{content:"\e65f"}.van-icon-arrow:before{content:"\e660"}.van-icon-after-sale:before{content:"\e661"}.van-icon-add-o:before{content:"\e662"}.van-icon-alipay:before{content:"\e663"}.van-icon-ascending:before{content:"\e664"}.van-icon-apps-o:before{content:"\e665"}.van-icon-aim:before{content:"\e666"}.van-icon-award:before{content:"\e667"}.van-icon-arrow-left:before{content:"\e668"}.van-icon-award-o:before{content:"\e669"}.van-icon-audio:before{content:"\e66a"}.van-icon-bag-o:before{content:"\e66b"}.van-icon-balance-list:before{content:"\e66c"}.van-icon-back-top:before{content:"\e66d"}.van-icon-bag:before{content:"\e66e"}.van-icon-balance-pay:before{content:"\e66f"}.van-icon-balance-o:before{content:"\e670"}.van-icon-bar-chart-o:before{content:"\e671"}.van-icon-bars:before{content:"\e672"}.van-icon-balance-list-o:before{content:"\e673"}.van-icon-birthday-cake-o:before{content:"\e674"}.van-icon-bookmark:before{content:"\e675"}.van-icon-bill:before{content:"\e676"}.van-icon-bell:before{content:"\e677"}.van-icon-browsing-history-o:before{content:"\e678"}.van-icon-browsing-history:before{content:"\e679"}.van-icon-bookmark-o:before{content:"\e67a"}.van-icon-bulb-o:before{content:"\e67b"}.van-icon-bullhorn-o:before{content:"\e67c"}.van-icon-bill-o:before{content:"\e67d"}.van-icon-calendar-o:before{content:"\e67e"}.van-icon-brush-o:before{content:"\e67f"}.van-icon-card:before{content:"\e680"}.van-icon-cart-o:before{content:"\e681"}.van-icon-cart-circle:before{content:"\e682"}.van-icon-cart-circle-o:before{content:"\e683"}.van-icon-cart:before{content:"\e684"}.van-icon-cash-on-deliver:before{content:"\e685"}.van-icon-cash-back-record:before{content:"\e686"}.van-icon-cashier-o:before{content:"\e687"}.van-icon-chart-trending-o:before{content:"\e688"}.van-icon-certificate:before{content:"\e689"}.van-icon-chat:before{content:"\e68a"}.van-icon-clear:before{content:"\e68b"}.van-icon-chat-o:before{content:"\e68c"}.van-icon-checked:before{content:"\e68d"}.van-icon-clock:before{content:"\e68e"}.van-icon-clock-o:before{content:"\e68f"}.van-icon-close:before{content:"\e690"}.van-icon-closed-eye:before{content:"\e691"}.van-icon-circle:before{content:"\e692"}.van-icon-cluster-o:before{content:"\e693"}.van-icon-column:before{content:"\e694"}.van-icon-comment-circle-o:before{content:"\e695"}.van-icon-cluster:before{content:"\e696"}.van-icon-comment:before{content:"\e697"}.van-icon-comment-o:before{content:"\e698"}.van-icon-comment-circle:before{content:"\e699"}.van-icon-completed:before{content:"\e69a"}.van-icon-credit-pay:before{content:"\e69b"}.van-icon-coupon:before{content:"\e69c"}.van-icon-debit-pay:before{content:"\e69d"}.van-icon-coupon-o:before{content:"\e69e"}.van-icon-contact:before{content:"\e69f"}.van-icon-descending:before{content:"\e6a0"}.van-icon-desktop-o:before{content:"\e6a1"}.van-icon-diamond-o:before{content:"\e6a2"}.van-icon-description:before{content:"\e6a3"}.van-icon-delete:before{content:"\e6a4"}.van-icon-diamond:before{content:"\e6a5"}.van-icon-delete-o:before{content:"\e6a6"}.van-icon-cross:before{content:"\e6a7"}.van-icon-edit:before{content:"\e6a8"}.van-icon-ellipsis:before{content:"\e6a9"}.van-icon-down:before{content:"\e6aa"}.van-icon-discount:before{content:"\e6ab"}.van-icon-ecard-pay:before{content:"\e6ac"}.van-icon-envelop-o:before{content:"\e6ae"}.van-icon-shield-o:before{content:"\e74b"}.van-icon-guide-o:before{content:"\e74c"}.van-icon-cash-o:before{content:"\e74d"}.van-icon-qq:before{content:"\e74e"}.van-icon-wechat-moments:before{content:"\e74f"}.van-icon-weibo:before{content:"\e750"}.van-icon-link-o:before{content:"\e751"}.van-icon-miniprogram-o:before{content:"\e752"}@font-face{font-display:auto;font-family:vant-icon;font-style:normal;font-weight:400;src:url(https://at.alicdn.com/t/font_2553510_iv4v8nulyz.woff2?t=1649083952952) format("woff2"),url(https://at.alicdn.com/t/font_2553510_iv4v8nulyz.woff?t=1649083952952) format("woff"),url(https://at.alicdn.com/t/font_2553510_iv4v8nulyz.ttf?t=1649083952952) format("truetype")}:host{align-items:center;display:inline-flex;justify-content:center}.van-icon--image{height:1em;width:1em}.van-icon__image{height:100%;width:100%}.van-icon__info{z-index:1}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
VantComponent({
mixins: [button],
classes: ['custom-class', 'loading-class', 'error-class', 'image-class'],
props: {
src: {
type: String,
observer() {
this.setData({
error: false,
loading: true,
});
},
},
round: Boolean,
width: null,
height: null,
radius: null,
lazyLoad: Boolean,
useErrorSlot: Boolean,
useLoadingSlot: Boolean,
showMenuByLongpress: Boolean,
fit: {
type: String,
value: 'fill',
},
showError: {
type: Boolean,
value: true,
},
showLoading: {
type: Boolean,
value: true,
},
},
data: {
error: false,
loading: true,
viewStyle: '',
},
methods: {
onLoad(event) {
this.setData({
loading: false,
});
this.$emit('load', event.detail);
},
onError(event) {
this.setData({
loading: false,
error: true,
});
this.$emit('error', event.detail);
},
onClick(event) {
this.$emit('click', event.detail);
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view
style="{{ computed.rootStyle({ width, height, radius }) }}"
class="custom-class {{ utils.bem('image', { round })}}"
bind:tap="onClick"
>
<image
wx:if="{{ !error }}"
src="{{ src }}"
mode="{{ computed.mode(fit) }}"
lazy-load="{{ lazyLoad }}"
class="image-class van-image__img"
show-menu-by-longpress="{{ showMenuByLongpress }}"
bind:load="onLoad"
bind:error="onError"
/>
<view
wx:if="{{ loading && showLoading }}"
class="loading-class van-image__loading"
>
<slot wx:if="{{ useLoadingSlot }}" name="loading" />
<van-icon wx:else name="photo" custom-class="van-image__loading-icon" />
</view>
<view
wx:if="{{ error && showError }}"
class="error-class van-image__error"
>
<slot wx:if="{{ useErrorSlot }}" name="error" />
<van-icon wx:else name="photo-fail" custom-class="van-image__error-icon" />
</view>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style([
{
width: addUnit(data.width),
height: addUnit(data.height),
'border-radius': addUnit(data.radius),
},
data.radius ? 'overflow: hidden' : null,
]);
}
var FIT_MODE_MAP = {
none: 'center',
fill: 'scaleToFill',
cover: 'aspectFill',
contain: 'aspectFit',
widthFix: 'widthFix',
heightFix: 'heightFix',
};
function mode(fit) {
return FIT_MODE_MAP[fit];
}
module.exports = {
rootStyle: rootStyle,
mode: mode,
};
@import '../common/index.wxss';.van-image{display:inline-block;position:relative}.van-image--round{border-radius:50%;overflow:hidden}.van-image--round .van-image__img{border-radius:inherit}.van-image__error,.van-image__img,.van-image__loading{display:block;height:100%;width:100%}.van-image__error,.van-image__loading{align-items:center;background-color:var(--image-placeholder-background-color,#f7f8fa);color:var(--image-placeholder-text-color,#969799);display:flex;flex-direction:column;font-size:var(--image-placeholder-font-size,14px);justify-content:center;left:0;position:absolute;top:0}.van-image__loading-icon{color:var(--image-loading-icon-color,#dcdee0);font-size:var(--image-loading-icon-size,32px)!important}.van-image__error-icon{color:var(--image-error-icon-color,#dcdee0);font-size:var(--image-error-icon-size,32px)!important}
\ No newline at end of file
import { getRect } from '../common/utils';
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
VantComponent({
relation: useParent('index-bar'),
props: {
useSlot: Boolean,
index: null,
},
data: {
active: false,
wrapperStyle: '',
anchorStyle: '',
},
methods: {
scrollIntoView(scrollTop) {
getRect(this, '.van-index-anchor-wrapper').then((rect) => {
wx.pageScrollTo({
duration: 0,
scrollTop: scrollTop + rect.top - this.parent.data.stickyOffsetTop,
});
});
},
},
});
<view
class="van-index-anchor-wrapper"
style="{{ wrapperStyle }}"
>
<view
class="van-index-anchor {{ active ? 'van-index-anchor--active van-hairline--bottom' : '' }}"
style="{{ anchorStyle }}"
>
<slot wx:if="{{ useSlot }}"/>
<block wx:else>
<text>{{ index }}</text>
</block>
</view>
</view>
@import '../common/index.wxss';.van-index-anchor{background-color:var(--index-anchor-background-color,transparent);color:var(--index-anchor-text-color,#323233);font-size:var(--index-anchor-font-size,14px);font-weight:var(--index-anchor-font-weight,500);line-height:var(--index-anchor-line-height,32px);padding:var(--index-anchor-padding,0 16px)}.van-index-anchor--active{background-color:var(--index-anchor-active-background-color,#fff);color:var(--index-anchor-active-text-color,#07c160);left:0;right:0}
\ No newline at end of file
import { GREEN } from '../common/color';
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
import { getRect, isDef } from '../common/utils';
import { pageScrollMixin } from '../mixins/page-scroll';
const indexList = () => {
const indexList = [];
const charCodeOfA = 'A'.charCodeAt(0);
for (let i = 0; i < 26; i++) {
indexList.push(String.fromCharCode(charCodeOfA + i));
}
return indexList;
};
VantComponent({
relation: useChildren('index-anchor', function () {
this.updateData();
}),
props: {
sticky: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 1,
},
highlightColor: {
type: String,
value: GREEN,
},
stickyOffsetTop: {
type: Number,
value: 0,
},
indexList: {
type: Array,
value: indexList(),
},
},
mixins: [
pageScrollMixin(function (event) {
this.scrollTop = (event === null || event === void 0 ? void 0 : event.scrollTop) || 0;
this.onScroll();
}),
],
data: {
activeAnchorIndex: null,
showSidebar: false,
},
created() {
this.scrollTop = 0;
},
methods: {
updateData() {
wx.nextTick(() => {
if (this.timer != null) {
clearTimeout(this.timer);
}
this.timer = setTimeout(() => {
this.setData({
showSidebar: !!this.children.length,
});
this.setRect().then(() => {
this.onScroll();
});
}, 0);
});
},
setRect() {
return Promise.all([
this.setAnchorsRect(),
this.setListRect(),
this.setSiderbarRect(),
]);
},
setAnchorsRect() {
return Promise.all(this.children.map((anchor) => getRect(anchor, '.van-index-anchor-wrapper').then((rect) => {
Object.assign(anchor, {
height: rect.height,
top: rect.top + this.scrollTop,
});
})));
},
setListRect() {
return getRect(this, '.van-index-bar').then((rect) => {
if (!isDef(rect)) {
return;
}
Object.assign(this, {
height: rect.height,
top: rect.top + this.scrollTop,
});
});
},
setSiderbarRect() {
return getRect(this, '.van-index-bar__sidebar').then((res) => {
if (!isDef(res)) {
return;
}
this.sidebar = {
height: res.height,
top: res.top,
};
});
},
setDiffData({ target, data }) {
const diffData = {};
Object.keys(data).forEach((key) => {
if (target.data[key] !== data[key]) {
diffData[key] = data[key];
}
});
if (Object.keys(diffData).length) {
target.setData(diffData);
}
},
getAnchorRect(anchor) {
return getRect(anchor, '.van-index-anchor-wrapper').then((rect) => ({
height: rect.height,
top: rect.top,
}));
},
getActiveAnchorIndex() {
const { children, scrollTop } = this;
const { sticky, stickyOffsetTop } = this.data;
for (let i = this.children.length - 1; i >= 0; i--) {
const preAnchorHeight = i > 0 ? children[i - 1].height : 0;
const reachTop = sticky ? preAnchorHeight + stickyOffsetTop : 0;
if (reachTop + scrollTop >= children[i].top) {
return i;
}
}
return -1;
},
onScroll() {
const { children = [], scrollTop } = this;
if (!children.length) {
return;
}
const { sticky, stickyOffsetTop, zIndex, highlightColor } = this.data;
const active = this.getActiveAnchorIndex();
this.setDiffData({
target: this,
data: {
activeAnchorIndex: active,
},
});
if (sticky) {
let isActiveAnchorSticky = false;
if (active !== -1) {
isActiveAnchorSticky =
children[active].top <= stickyOffsetTop + scrollTop;
}
children.forEach((item, index) => {
if (index === active) {
let wrapperStyle = '';
let anchorStyle = `
color: ${highlightColor};
`;
if (isActiveAnchorSticky) {
wrapperStyle = `
height: ${children[index].height}px;
`;
anchorStyle = `
position: fixed;
top: ${stickyOffsetTop}px;
z-index: ${zIndex};
color: ${highlightColor};
`;
}
this.setDiffData({
target: item,
data: {
active: true,
anchorStyle,
wrapperStyle,
},
});
}
else if (index === active - 1) {
const currentAnchor = children[index];
const currentOffsetTop = currentAnchor.top;
const targetOffsetTop = index === children.length - 1
? this.top
: children[index + 1].top;
const parentOffsetHeight = targetOffsetTop - currentOffsetTop;
const translateY = parentOffsetHeight - currentAnchor.height;
const anchorStyle = `
position: relative;
transform: translate3d(0, ${translateY}px, 0);
z-index: ${zIndex};
color: ${highlightColor};
`;
this.setDiffData({
target: item,
data: {
active: true,
anchorStyle,
},
});
}
else {
this.setDiffData({
target: item,
data: {
active: false,
anchorStyle: '',
wrapperStyle: '',
},
});
}
});
}
},
onClick(event) {
this.scrollToAnchor(event.target.dataset.index);
},
onTouchMove(event) {
const sidebarLength = this.children.length;
const touch = event.touches[0];
const itemHeight = this.sidebar.height / sidebarLength;
let index = Math.floor((touch.clientY - this.sidebar.top) / itemHeight);
if (index < 0) {
index = 0;
}
else if (index > sidebarLength - 1) {
index = sidebarLength - 1;
}
this.scrollToAnchor(index);
},
onTouchStop() {
this.scrollToAnchorIndex = null;
},
scrollToAnchor(index) {
if (typeof index !== 'number' || this.scrollToAnchorIndex === index) {
return;
}
this.scrollToAnchorIndex = index;
const anchor = this.children.find((item) => item.data.index === this.data.indexList[index]);
if (anchor) {
anchor.scrollIntoView(this.scrollTop);
this.$emit('select', anchor.data.index);
}
},
},
});
<view class="van-index-bar">
<slot />
<view
wx:if="{{ showSidebar }}"
class="van-index-bar__sidebar"
catch:tap="onClick"
catch:touchmove="onTouchMove"
catch:touchend="onTouchStop"
catch:touchcancel="onTouchStop"
>
<view
wx:for="{{ indexList }}"
wx:key="index"
class="van-index-bar__index"
style="z-index: {{ zIndex + 1 }}; color: {{ activeAnchorIndex === index ? highlightColor : '' }}"
data-index="{{ index }}"
>
{{ item }}
</view>
</view>
</view>
@import '../common/index.wxss';.van-index-bar{position:relative}.van-index-bar__sidebar{display:flex;flex-direction:column;position:fixed;right:0;text-align:center;top:50%;transform:translateY(-50%);-webkit-user-select:none;user-select:none}.van-index-bar__index{font-size:var(--index-bar-index-font-size,10px);font-weight:500;line-height:var(--index-bar-index-line-height,14px);padding:0 var(--padding-base,4px) 0 var(--padding-md,16px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
props: {
dot: Boolean,
info: null,
customStyle: String,
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view
wx:if="{{ info !== null && info !== '' || dot }}"
class="van-info {{ utils.bem('info', { dot }) }} custom-class"
style="{{ customStyle }}"
>{{ dot ? '' : info }}</view>
@import '../common/index.wxss';.van-info{align-items:center;background-color:var(--info-background-color,#ee0a24);border:var(--info-border-width,1px) solid #fff;border-radius:var(--info-size,16px);box-sizing:border-box;color:var(--info-color,#fff);display:inline-flex;font-family:var(--info-font-family,-apple-system-font,Helvetica Neue,Arial,sans-serif);font-size:var(--info-font-size,12px);font-weight:var(--info-font-weight,500);height:var(--info-size,16px);justify-content:center;min-width:var(--info-size,16px);padding:var(--info-padding,0 3px);position:absolute;right:0;top:0;transform:translate(50%,-50%);transform-origin:100%;white-space:nowrap}.van-info--dot{background-color:var(--info-dot-color,#ee0a24);border-radius:100%;height:var(--info-dot-size,8px);min-width:0;width:var(--info-dot-size,8px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
props: {
color: String,
vertical: Boolean,
type: {
type: String,
value: 'circular',
},
size: String,
textSize: String,
},
data: {
array12: Array.from({ length: 12 }),
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="custom-class {{ utils.bem('loading', { vertical }) }}">
<view
class="van-loading__spinner van-loading__spinner--{{ type }}"
style="{{ computed.spinnerStyle({ color, size }) }}"
>
<view
wx:if="{{ type === 'spinner' }}"
wx:for="{{ array12 }}"
wx:key="index"
class="van-loading__dot"
/>
</view>
<view class="van-loading__text" style="{{ computed.textStyle({ textSize }) }}">
<slot />
</view>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function spinnerStyle(data) {
return style({
color: data.color,
width: addUnit(data.size),
height: addUnit(data.size),
});
}
function textStyle(data) {
return style({
'font-size': addUnit(data.textSize),
});
}
module.exports = {
spinnerStyle: spinnerStyle,
textStyle: textStyle,
};
@import '../common/index.wxss';:host{font-size:0;line-height:1}.van-loading{align-items:center;color:var(--loading-spinner-color,#c8c9cc);display:inline-flex;justify-content:center}.van-loading__spinner{animation:van-rotate var(--loading-spinner-animation-duration,.8s) linear infinite;box-sizing:border-box;height:var(--loading-spinner-size,30px);max-height:100%;max-width:100%;position:relative;width:var(--loading-spinner-size,30px)}.van-loading__spinner--spinner{animation-timing-function:steps(12)}.van-loading__spinner--circular{border:1px solid transparent;border-radius:100%;border-top-color:initial}.van-loading__text{color:var(--loading-text-color,#969799);font-size:var(--loading-text-font-size,14px);line-height:var(--loading-text-line-height,20px);margin-left:var(--padding-xs,8px)}.van-loading__text:empty{display:none}.van-loading--vertical{flex-direction:column}.van-loading--vertical .van-loading__text{margin:var(--padding-xs,8px) 0 0}.van-loading__dot{height:100%;left:0;position:absolute;top:0;width:100%}.van-loading__dot:before{background-color:currentColor;border-radius:40%;content:" ";display:block;height:25%;margin:0 auto;width:2px}.van-loading__dot:first-of-type{opacity:1;transform:rotate(30deg)}.van-loading__dot:nth-of-type(2){opacity:.9375;transform:rotate(60deg)}.van-loading__dot:nth-of-type(3){opacity:.875;transform:rotate(90deg)}.van-loading__dot:nth-of-type(4){opacity:.8125;transform:rotate(120deg)}.van-loading__dot:nth-of-type(5){opacity:.75;transform:rotate(150deg)}.van-loading__dot:nth-of-type(6){opacity:.6875;transform:rotate(180deg)}.van-loading__dot:nth-of-type(7){opacity:.625;transform:rotate(210deg)}.van-loading__dot:nth-of-type(8){opacity:.5625;transform:rotate(240deg)}.van-loading__dot:nth-of-type(9){opacity:.5;transform:rotate(270deg)}.van-loading__dot:nth-of-type(10){opacity:.4375;transform:rotate(300deg)}.van-loading__dot:nth-of-type(11){opacity:.375;transform:rotate(330deg)}.van-loading__dot:nth-of-type(12){opacity:.3125;transform:rotate(1turn)}@keyframes van-rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
\ No newline at end of file
export declare const basic: string;
export const basic = Behavior({
methods: {
$emit(name, detail, options) {
this.triggerEvent(name, detail, options);
},
set(data) {
this.setData(data);
return new Promise((resolve) => wx.nextTick(resolve));
},
},
});
export declare const button: string;
import { canIUseGetUserProfile } from '../common/version';
export const button = Behavior({
externalClasses: ['hover-class'],
properties: {
id: String,
lang: String,
businessId: Number,
sessionFrom: String,
sendMessageTitle: String,
sendMessagePath: String,
sendMessageImg: String,
showMessageCard: Boolean,
appParameter: String,
ariaLabel: String,
openType: String,
getUserProfileDesc: String,
},
data: {
canIUseGetUserProfile: canIUseGetUserProfile(),
},
methods: {
onGetUserInfo(event) {
this.triggerEvent('getuserinfo', event.detail);
},
onContact(event) {
this.triggerEvent('contact', event.detail);
},
onGetPhoneNumber(event) {
this.triggerEvent('getphonenumber', event.detail);
},
onError(event) {
this.triggerEvent('error', event.detail);
},
onLaunchApp(event) {
this.triggerEvent('launchapp', event.detail);
},
onOpenSetting(event) {
this.triggerEvent('opensetting', event.detail);
},
},
});
export declare const link: string;
export const link = Behavior({
properties: {
url: String,
linkType: {
type: String,
value: 'navigateTo',
},
},
methods: {
jumpLink(urlKey = 'url') {
const url = this.data[urlKey];
if (url) {
if (this.data.linkType === 'navigateTo' &&
getCurrentPages().length > 9) {
wx.redirectTo({ url });
}
else {
wx[this.data.linkType]({ url });
}
}
},
},
});
/// <reference types="miniprogram-api-typings" />
declare type IPageScrollOption = WechatMiniprogram.Page.IPageScrollOption;
declare type Scroller = (this: WechatMiniprogram.Component.TrivialInstance, event?: IPageScrollOption) => void;
export declare const pageScrollMixin: (scroller: Scroller) => string;
export {};
import { getCurrentPage, isDef } from '../common/utils';
function onPageScroll(event) {
const { vanPageScroller = [] } = getCurrentPage();
vanPageScroller.forEach((scroller) => {
if (typeof scroller === 'function') {
// @ts-ignore
scroller(event);
}
});
}
export const pageScrollMixin = (scroller) => Behavior({
attached() {
const page = getCurrentPage();
if (!isDef(page)) {
return;
}
if (Array.isArray(page.vanPageScroller)) {
page.vanPageScroller.push(scroller.bind(this));
}
else {
page.vanPageScroller =
typeof page.onPageScroll === 'function'
? [page.onPageScroll.bind(page), scroller.bind(this)]
: [scroller.bind(this)];
}
page.onPageScroll = onPageScroll;
},
detached() {
var _a;
const page = getCurrentPage();
if (isDef(page)) {
page.vanPageScroller =
((_a = page.vanPageScroller) === null || _a === void 0 ? void 0 : _a.filter((item) => item !== scroller)) || [];
}
},
});
export declare const touch: string;
// @ts-nocheck
const MIN_DISTANCE = 10;
function getDirection(x, y) {
if (x > y && x > MIN_DISTANCE) {
return 'horizontal';
}
if (y > x && y > MIN_DISTANCE) {
return 'vertical';
}
return '';
}
export const touch = Behavior({
methods: {
resetTouchStatus() {
this.direction = '';
this.deltaX = 0;
this.deltaY = 0;
this.offsetX = 0;
this.offsetY = 0;
},
touchStart(event) {
this.resetTouchStatus();
const touch = event.touches[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.direction || getDirection(this.offsetX, this.offsetY);
},
},
});
export declare function transition(showDefaultValue: boolean): string;
// @ts-nocheck
import { requestAnimationFrame } from '../common/utils';
import { isObj } from '../common/validator';
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`,
});
export function transition(showDefaultValue) {
return Behavior({
properties: {
customStyle: String,
// @ts-ignore
show: {
type: Boolean,
value: showDefaultValue,
observer: 'observeShow',
},
// @ts-ignore
duration: {
type: null,
value: 300,
observer: 'observeDuration',
},
name: {
type: String,
value: 'fade',
},
},
data: {
type: '',
inited: false,
display: false,
},
ready() {
if (this.data.show === true) {
this.observeShow(true, false);
}
},
methods: {
observeShow(value, old) {
if (value === old) {
return;
}
value ? this.enter() : this.leave();
},
enter() {
const { duration, name } = this.data;
const classNames = getClassNames(name);
const currentDuration = isObj(duration) ? duration.enter : duration;
this.status = 'enter';
this.$emit('before-enter');
requestAnimationFrame(() => {
if (this.status !== 'enter') {
return;
}
this.$emit('enter');
this.setData({
inited: true,
display: true,
classes: classNames.enter,
currentDuration,
});
requestAnimationFrame(() => {
if (this.status !== 'enter') {
return;
}
this.transitionEnded = false;
this.setData({ classes: classNames['enter-to'] });
});
});
},
leave() {
if (!this.data.display) {
return;
}
const { duration, name } = this.data;
const classNames = getClassNames(name);
const currentDuration = isObj(duration) ? duration.leave : duration;
this.status = 'leave';
this.$emit('before-leave');
requestAnimationFrame(() => {
if (this.status !== 'leave') {
return;
}
this.$emit('leave');
this.setData({
classes: classNames.leave,
currentDuration,
});
requestAnimationFrame(() => {
if (this.status !== 'leave') {
return;
}
this.transitionEnded = false;
setTimeout(() => this.onTransitionEnd(), currentDuration);
this.setData({ classes: classNames['leave-to'] });
});
});
},
onTransitionEnd() {
if (this.transitionEnded) {
return;
}
this.transitionEnded = true;
this.$emit(`after-${this.status}`);
const { show, display } = this.data;
if (!show && display) {
this.setData({ display: false });
}
},
},
});
}
import { VantComponent } from '../common/component';
import { getRect, getSystemInfoSync } from '../common/utils';
VantComponent({
classes: ['title-class'],
props: {
title: String,
fixed: {
type: Boolean,
observer: 'setHeight',
},
placeholder: {
type: Boolean,
observer: 'setHeight',
},
leftText: String,
rightText: String,
customStyle: String,
leftArrow: Boolean,
border: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 1,
},
safeAreaInsetTop: {
type: Boolean,
value: true,
},
},
data: {
height: 46,
},
created() {
const { statusBarHeight } = getSystemInfoSync();
this.setData({
statusBarHeight,
height: 46 + statusBarHeight,
});
},
mounted() {
this.setHeight();
},
methods: {
onClickLeft() {
this.$emit('click-left');
},
onClickRight() {
this.$emit('click-right');
},
setHeight() {
if (!this.data.fixed || !this.data.placeholder) {
return;
}
wx.nextTick(() => {
getRect(this, '.van-nav-bar').then((res) => {
if (res && 'height' in res) {
this.setData({ height: res.height });
}
});
});
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view wx:if="{{ fixed && placeholder }}" style="height: {{ height }}px;" />
<view
class="{{ utils.bem('nav-bar', { fixed }) }} custom-class {{ border ? 'van-hairline--bottom' : '' }}"
style="{{ computed.barStyle({ zIndex, statusBarHeight, safeAreaInsetTop }) }}; {{ customStyle }}"
>
<view class="van-nav-bar__content">
<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>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
function barStyle(data) {
return style({
'z-index': data.zIndex,
'padding-top': data.safeAreaInsetTop ? data.statusBarHeight + 'px' : 0,
});
}
module.exports = {
barStyle: barStyle,
};
@import '../common/index.wxss';.van-nav-bar{background-color:var(--nav-bar-background-color,#fff);height:var(--nav-bar-height,46px);line-height:var(--nav-bar-height,46px);position:relative;text-align:center;-webkit-user-select:none;user-select:none}.van-nav-bar__content{height:100%;position:relative}.van-nav-bar__text{color:var(--nav-bar-text-color,#1989fa);display:inline-block;margin:0 calc(var(--padding-md, 16px)*-1);padding:0 var(--padding-md,16px);vertical-align:middle}.van-nav-bar__text--hover{background-color:#f2f3f5}.van-nav-bar__arrow{color:var(--nav-bar-icon-color,#1989fa)!important;font-size:var(--nav-bar-arrow-size,16px)!important;vertical-align:middle}.van-nav-bar__arrow+.van-nav-bar__text{margin-left:-20px;padding-left:25px}.van-nav-bar--fixed{left:0;position:fixed;top:0;width:100%}.van-nav-bar__title{color:var(--nav-bar-title-text-color,#323233);font-size:var(--nav-bar-title-font-size,16px);font-weight:var(--font-weight-bold,500);margin:0 auto;max-width:60%}.van-nav-bar__left,.van-nav-bar__right{align-items:center;bottom:0;display:flex;font-size:var(--font-size-md,14px);position:absolute;top:0}.van-nav-bar__left{left:var(--padding-md,16px)}.van-nav-bar__right{right:var(--padding-md,16px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { getRect, requestAnimationFrame } from '../common/utils';
VantComponent({
props: {
text: {
type: String,
value: '',
observer: 'init',
},
mode: {
type: String,
value: '',
},
url: {
type: String,
value: '',
},
openType: {
type: String,
value: 'navigate',
},
delay: {
type: Number,
value: 1,
},
speed: {
type: Number,
value: 60,
observer: 'init',
},
scrollable: null,
leftIcon: {
type: String,
value: '',
},
color: String,
backgroundColor: String,
background: String,
wrapable: Boolean,
},
data: {
show: true,
},
created() {
this.resetAnimation = wx.createAnimation({
duration: 0,
timingFunction: 'linear',
});
},
destroyed() {
this.timer && clearTimeout(this.timer);
},
mounted() {
this.init();
},
methods: {
init() {
requestAnimationFrame(() => {
Promise.all([
getRect(this, '.van-notice-bar__content'),
getRect(this, '.van-notice-bar__wrap'),
]).then((rects) => {
const [contentRect, wrapRect] = rects;
const { speed, scrollable, delay } = this.data;
if (contentRect == null ||
wrapRect == null ||
!contentRect.width ||
!wrapRect.width ||
scrollable === false) {
return;
}
if (scrollable || wrapRect.width < contentRect.width) {
const duration = ((wrapRect.width + 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(true);
}
});
});
},
scroll(isInit = false) {
this.timer && clearTimeout(this.timer);
this.timer = null;
this.setData({
animationData: this.resetAnimation
.translateX(isInit ? 0 : this.wrapWidth)
.step()
.export(),
});
requestAnimationFrame(() => {
this.setData({
animationData: this.animation
.translateX(-this.contentWidth)
.step()
.export(),
});
});
this.timer = setTimeout(() => {
this.scroll();
}, this.duration);
},
onClickIcon(event) {
if (this.data.mode === 'closeable') {
this.timer && clearTimeout(this.timer);
this.timer = null;
this.setData({ show: false });
this.$emit('close', event.detail);
}
},
onClick(event) {
this.$emit('click', event);
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view
wx:if="{{ show }}"
class="custom-class {{ utils.bem('notice-bar', { withicon: mode, wrapable }) }}"
style="{{ computed.rootStyle({ color, backgroundColor, background }) }}"
bind:tap="onClick"
>
<van-icon
wx:if="{{ leftIcon }}"
name="{{ leftIcon }}"
class="van-notice-bar__left-icon"
/>
<slot wx:else name="left-icon" />
<view class="van-notice-bar__wrap">
<view class="van-notice-bar__content {{ scrollable === false && !wrapable ? 'van-ellipsis' : '' }}" animation="{{ animationData }}">
{{ text }}
<slot wx:if="{{ !text }}"></slot>
</view>
</view>
<van-icon
wx:if="{{ mode === 'closeable' }}"
class="van-notice-bar__right-icon"
name="cross"
catch:tap="onClickIcon"
/>
<navigator
wx:elif="{{ mode === 'link' }}"
url="{{ url }}"
open-type="{{ openType }}"
>
<van-icon class="van-notice-bar__right-icon" name="arrow" />
</navigator>
<slot wx:else name="right-icon" />
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style({
color: data.color,
'background-color': data.backgroundColor,
background: data.background,
});
}
module.exports = {
rootStyle: rootStyle,
};
@import '../common/index.wxss';.van-notice-bar{align-items:center;background-color:var(--notice-bar-background-color,#fffbe8);color:var(--notice-bar-text-color,#ed6a0c);display:flex;font-size:var(--notice-bar-font-size,14px);height:var(--notice-bar-height,40px);line-height:var(--notice-bar-line-height,24px);padding:var(--notice-bar-padding,0 16px)}.van-notice-bar--withicon{padding-right:40px;position:relative}.van-notice-bar--wrapable{height:auto;padding:var(--notice-bar-wrapable-padding,8px 16px)}.van-notice-bar--wrapable .van-notice-bar__wrap{height:auto}.van-notice-bar--wrapable .van-notice-bar__content{position:relative;white-space:normal}.van-notice-bar__left-icon{align-items:center;display:flex;margin-right:4px;vertical-align:middle}.van-notice-bar__left-icon,.van-notice-bar__right-icon{font-size:var(--notice-bar-icon-size,16px);min-width:var(--notice-bar-icon-min-width,22px)}.van-notice-bar__right-icon{position:absolute;right:15px;top:10px}.van-notice-bar__wrap{flex:1;height:var(--notice-bar-line-height,24px);overflow:hidden;position:relative}.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 { WHITE } from '../common/color';
import { getSystemInfoSync } from '../common/utils';
VantComponent({
props: {
message: String,
background: String,
type: {
type: String,
value: 'danger',
},
color: {
type: String,
value: WHITE,
},
duration: {
type: Number,
value: 3000,
},
zIndex: {
type: Number,
value: 110,
},
safeAreaInsetTop: {
type: Boolean,
value: false,
},
top: null,
},
data: {
show: false,
onOpened: null,
onClose: null,
onClick: null,
},
created() {
const { statusBarHeight } = getSystemInfoSync();
this.setData({ statusBarHeight });
},
methods: {
show() {
const { duration, onOpened } = this.data;
clearTimeout(this.timer);
this.setData({ show: true });
wx.nextTick(onOpened);
if (duration > 0 && duration !== Infinity) {
this.timer = setTimeout(() => {
this.hide();
}, duration);
}
},
hide() {
const { onClose } = this.data;
clearTimeout(this.timer);
this.setData({ show: false });
wx.nextTick(onClose);
},
onTap(event) {
const { onClick } = this.data;
if (onClick) {
onClick(event.detail);
}
},
},
});
{
"component": true,
"usingComponents": {
"van-transition": "../transition/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<van-transition
name="slide-down"
show="{{ show }}"
custom-class="van-notify__container"
custom-style="{{ computed.rootStyle({ zIndex, top }) }}"
bind:tap="onTap"
>
<view
class="van-notify van-notify--{{ type }}"
style="{{ computed.notifyStyle({ background, color }) }}"
>
<view
wx:if="{{ safeAreaInsetTop }}"
style="height: {{ statusBarHeight }}px"
/>
<text>{{ message }}</text>
</view>
</van-transition>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
return style({
'z-index': data.zIndex,
top: addUnit(data.top),
});
}
function notifyStyle(data) {
return style({
background: data.background,
color: data.color,
});
}
module.exports = {
rootStyle: rootStyle,
notifyStyle: notifyStyle,
};
@import '../common/index.wxss';.van-notify{word-wrap:break-word;font-size:var(--notify-font-size,14px);line-height:var(--notify-line-height,20px);padding:var(--notify-padding,6px 15px);text-align:center}.van-notify__container{box-sizing:border-box;left:0;position:fixed;top:0;width:100%}.van-notify--primary{background-color:var(--notify-primary-background-color,#1989fa)}.van-notify--success{background-color:var(--notify-success-background-color,#07c160)}.van-notify--danger{background-color:var(--notify-danger-background-color,#ee0a24)}.van-notify--warning{background-color:var(--notify-warning-background-color,#ff976a)}
\ No newline at end of file
interface NotifyOptions {
type?: 'primary' | 'success' | 'danger' | 'warning';
color?: string;
zIndex?: number;
top?: number;
message: string;
context?: any;
duration?: number;
selector?: string;
background?: string;
safeAreaInsetTop?: boolean;
onClick?: () => void;
onOpened?: () => void;
onClose?: () => void;
}
declare function Notify(options: NotifyOptions | string): any;
declare namespace Notify {
var clear: (options?: NotifyOptions | undefined) => void;
}
export default Notify;
import { WHITE } from '../common/color';
const defaultOptions = {
selector: '#van-notify',
type: 'danger',
message: '',
background: '',
duration: 3000,
zIndex: 110,
top: 0,
color: WHITE,
safeAreaInsetTop: false,
onClick: () => { },
onOpened: () => { },
onClose: () => { },
};
function parseOptions(message) {
if (message == null) {
return {};
}
return typeof message === 'string' ? { message } : message;
}
function getContext() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
export default function Notify(options) {
options = Object.assign(Object.assign({}, defaultOptions), parseOptions(options));
const context = options.context || getContext();
const notify = context.selectComponent(options.selector);
delete options.context;
delete options.selector;
if (notify) {
notify.setData(options);
notify.show();
return notify;
}
console.warn('未找到 van-notify 节点,请确认 selector 及 context 是否正确');
}
Notify.clear = function (options) {
options = Object.assign(Object.assign({}, defaultOptions), parseOptions(options));
const context = options.context || getContext();
const notify = context.selectComponent(options.selector);
if (notify) {
notify.hide();
}
};
import { VantComponent } from '../common/component';
VantComponent({
props: {
show: Boolean,
customStyle: String,
duration: {
type: null,
value: 300,
},
zIndex: {
type: Number,
value: 1,
},
lockScroll: {
type: Boolean,
value: true,
},
},
methods: {
onClick() {
this.$emit('click');
},
// for prevent touchmove
noop() { },
},
});
{
"component": true,
"usingComponents": {
"van-transition": "../transition/index"
}
}
<van-transition
wx:if="{{ lockScroll }}"
show="{{ show }}"
custom-class="van-overlay"
custom-style="z-index: {{ zIndex }}; {{ customStyle }}"
duration="{{ duration }}"
bind:tap="onClick"
catch:touchmove="noop"
>
<slot></slot>
</van-transition>
<van-transition
wx:else
show="{{ show }}"
custom-class="van-overlay"
custom-style="z-index: {{ zIndex }}; {{ customStyle }}"
duration="{{ duration }}"
bind:tap="onClick"
>
<slot></slot>
</van-transition>
@import '../common/index.wxss';.van-overlay{background-color:var(--overlay-background-color,rgba(0,0,0,.7));height:100%;left:0;position:fixed;top:0;width:100%}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
classes: ['header-class', 'footer-class'],
props: {
desc: String,
title: String,
status: String,
},
});
{
"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 class="van-panel__footer van-hairline--top footer-class">
<slot name="footer" />
</view>
</view>
@import '../common/index.wxss';.van-panel{background:var(--panel-background-color,#fff)}.van-panel__header-value{color:var(--panel-header-value-color,#ee0a24)}.van-panel__footer{padding:var(--panel-footer-padding,8px 16px)}.van-panel__footer:empty{display:none}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { range } from '../common/utils';
import { isObj } from '../common/validator';
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,
observer(value) {
this.setIndex(value);
},
},
},
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);
});
},
methods: {
getCount() {
return this.data.options.length;
},
onTouchStart(event) {
this.setData({
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.setData({
offset: range(data.startOffset + deltaY, -(this.getCount() * data.itemHeight), data.itemHeight),
});
},
onTouchEnd() {
const { data } = this;
if (data.offset !== data.startOffset) {
this.setData({ duration: DEFAULT_DURATION });
const index = range(Math.round(-data.offset / data.itemHeight), 0, this.getCount() - 1);
this.setIndex(index, true);
}
},
onClickItem(event) {
const { index } = event.currentTarget.dataset;
this.setIndex(index, true);
},
adjustIndex(index) {
const { data } = this;
const count = this.getCount();
index = range(index, 0, count);
for (let i = index; i < 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);
});
}
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];
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view
class="van-picker-column custom-class"
style="{{ computed.rootStyle({ itemHeight, visibleItemCount }) }}"
bind:touchstart="onTouchStart"
catch:touchmove="onTouchMove"
bind:touchend="onTouchEnd"
bind:touchcancel="onTouchEnd"
>
<view style="{{ computed.wrapperStyle({ offset, itemHeight, visibleItemCount, duration }) }}">
<view
wx:for="{{ options }}"
wx:for-item="option"
wx:key="index"
data-index="{{ index }}"
style="height: {{ itemHeight }}px"
class="van-ellipsis {{ utils.bem('picker-column__item', { disabled: option && option.disabled, selected: index === currentIndex }) }} {{ index === currentIndex ? 'active-class' : '' }}"
bindtap="onClickItem"
>{{ computed.optionText(option, valueKey) }}</view>
</view>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function isObj(x) {
var type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
function optionText(option, valueKey) {
return isObj(option) && option[valueKey] != null ? option[valueKey] : option;
}
function rootStyle(data) {
return style({
height: addUnit(data.itemHeight * data.visibleItemCount),
});
}
function wrapperStyle(data) {
var offset = addUnit(
data.offset + (data.itemHeight * (data.visibleItemCount - 1)) / 2
);
return style({
transition: 'transform ' + data.duration + 'ms',
'line-height': addUnit(data.itemHeight),
transform: 'translate3d(0, ' + offset + ', 0)',
});
}
module.exports = {
optionText: optionText,
rootStyle: rootStyle,
wrapperStyle: wrapperStyle,
};
@import '../common/index.wxss';.van-picker-column{color:var(--picker-option-text-color,#000);font-size:var(--picker-option-font-size,16px);overflow:hidden;text-align:center}.van-picker-column__item{padding:0 5px}.van-picker-column__item--selected{color:var(--picker-option-selected-text-color,#323233);font-weight:var(--font-weight-bold,500)}.van-picker-column__item--disabled{opacity:var(--picker-option-disabled-opacity,.3)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { pickerProps } from './shared';
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: Object.assign(Object.assign({}, pickerProps), { valueKey: {
type: String,
value: 'text',
}, toolbarPosition: {
type: String,
value: 'top',
}, defaultIndex: {
type: Number,
value: 0,
}, columns: {
type: Array,
value: [],
observer(columns = []) {
this.simple = columns.length && !columns[0].values;
if (Array.isArray(this.children) && this.children.length) {
this.setColumns().catch(() => { });
}
},
} }),
beforeCreate() {
Object.defineProperty(this, 'children', {
get: () => this.selectAllComponents('.van-picker__column') || [],
});
},
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(new Error('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(new Error('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(new Error('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"
}
}
<wxs src="./index.wxs" module="computed" />
<view class="van-picker custom-class">
<include wx:if="{{ toolbarPosition === 'top' }}" src="./toolbar.wxml" />
<view wx:if="{{ loading }}" class="van-picker__loading">
<loading color="#1989fa"/>
</view>
<view
class="van-picker__columns"
style="{{ computed.columnsStyle({ itemHeight, visibleItemCount }) }}"
catch:touchmove="noop"
>
<picker-column
class="van-picker__column"
wx:for="{{ computed.columns(columns) }}"
wx:key="index"
data-index="{{ index }}"
custom-class="column-class"
value-key="{{ valueKey }}"
initial-options="{{ item.values }}"
default-index="{{ item.defaultIndex || defaultIndex }}"
item-height="{{ itemHeight }}"
visible-item-count="{{ visibleItemCount }}"
active-class="active-class"
bind:change="onChange"
/>
<view class="van-picker__mask" style="{{ computed.maskStyle({ itemHeight, visibleItemCount }) }}" />
<view
class="van-picker__frame van-hairline--top-bottom"
style="{{ computed.frameStyle({ itemHeight }) }}"
/>
</view>
<include wx:if="{{ toolbarPosition === 'bottom' }}" src="./toolbar.wxml" />
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
var array = require('../wxs/array.wxs');
function columnsStyle(data) {
return style({
height: addUnit(data.itemHeight * data.visibleItemCount),
});
}
function maskStyle(data) {
return style({
'background-size':
'100% ' + addUnit((data.itemHeight * (data.visibleItemCount - 1)) / 2),
});
}
function frameStyle(data) {
return style({
height: addUnit(data.itemHeight),
});
}
function columns(columns) {
if (!array.isArray(columns)) {
return [];
}
if (columns.length && !columns[0].values) {
return [{ values: columns }];
}
return columns;
}
module.exports = {
columnsStyle: columnsStyle,
frameStyle: frameStyle,
maskStyle: maskStyle,
columns: columns,
};
@import '../common/index.wxss';.van-picker{-webkit-text-size-adjust:100%;background-color:var(--picker-background-color,#fff);overflow:hidden;position:relative;-webkit-user-select:none;user-select:none}.van-picker__toolbar{display:flex;height:var(--picker-toolbar-height,44px);justify-content:space-between;line-height:var(--picker-toolbar-height,44px)}.van-picker__cancel,.van-picker__confirm{font-size:var(--picker-action-font-size,14px);padding:var(--picker-action-padding,0 16px)}.van-picker__cancel--hover,.van-picker__confirm--hover{opacity:.7}.van-picker__confirm{color:var(--picker-confirm-action-color,#576b95)}.van-picker__cancel{color:var(--picker-cancel-action-color,#969799)}.van-picker__title{font-size:var(--picker-option-font-size,16px);font-weight:var(--font-weight-bold,500);max-width:50%;text-align:center}.van-picker__columns{display:flex;position:relative}.van-picker__column{flex:1 1;width:0}.van-picker__loading{align-items:center;background-color:var(--picker-loading-mask-color,hsla(0,0%,100%,.9));bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0;z-index:4}.van-picker__mask{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-image:linear-gradient(180deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4)),linear-gradient(0deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4));background-position:top,bottom;background-repeat:no-repeat;height:100%;left:0;top:0;width:100%;z-index:2}.van-picker__frame,.van-picker__mask{pointer-events:none;position:absolute}.van-picker__frame{left:16px;right:16px;top:50%;transform:translateY(-50%);z-index:1}
\ No newline at end of file
export declare const pickerProps: {
title: StringConstructor;
loading: BooleanConstructor;
showToolbar: BooleanConstructor;
cancelButtonText: {
type: StringConstructor;
value: string;
};
confirmButtonText: {
type: StringConstructor;
value: string;
};
visibleItemCount: {
type: NumberConstructor;
value: number;
};
itemHeight: {
type: NumberConstructor;
value: number;
};
};
export const pickerProps = {
title: String,
loading: Boolean,
showToolbar: Boolean,
cancelButtonText: {
type: String,
value: '取消',
},
confirmButtonText: {
type: String,
value: '确认',
},
visibleItemCount: {
type: Number,
value: 6,
},
itemHeight: {
type: Number,
value: 44,
},
};
<view wx:if="{{ showToolbar }}" class="van-picker__toolbar 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>
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',
'close-icon-class',
],
mixins: [transition(false)],
props: {
round: Boolean,
closeable: Boolean,
customStyle: String,
overlayStyle: String,
transition: {
type: String,
observer: 'observeClass',
},
zIndex: {
type: Number,
value: 100,
},
overlay: {
type: Boolean,
value: true,
},
closeIcon: {
type: String,
value: 'cross',
},
closeIconPosition: {
type: String,
value: 'top-right',
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
position: {
type: String,
value: 'center',
observer: 'observeClass',
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
safeAreaInsetTop: {
type: Boolean,
value: false,
},
lockScroll: {
type: Boolean,
value: true,
},
},
created() {
this.observeClass();
},
methods: {
onClickCloseIcon() {
this.$emit('close');
},
onClickOverlay() {
this.$emit('click-overlay');
if (this.data.closeOnClickOverlay) {
this.$emit('close');
}
},
observeClass() {
const { transition, position, duration } = this.data;
const updateData = {
name: transition || position,
};
if (transition === 'none') {
updateData.duration = 0;
this.originDuration = duration;
}
else if (this.originDuration != null) {
updateData.duration = this.originDuration;
}
this.setData(updateData);
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-overlay": "../overlay/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<van-overlay
wx:if="{{ overlay }}"
show="{{ show }}"
z-index="{{ zIndex }}"
custom-style="{{ overlayStyle }}"
duration="{{ duration }}"
bind:click="onClickOverlay"
lock-scroll="{{ lockScroll }}"
/>
<view
wx:if="{{ inited }}"
class="custom-class {{ classes }} {{ utils.bem('popup', [position, { round, safe: safeAreaInsetBottom, safeTop: safeAreaInsetTop }]) }}"
style="{{ computed.popupStyle({ zIndex, currentDuration, display, customStyle }) }}"
bind:transitionend="onTransitionEnd"
>
<slot />
<van-icon
wx:if="{{ closeable }}"
name="{{ closeIcon }}"
class="close-icon-class van-popup__close-icon van-popup__close-icon--{{ closeIconPosition }}"
bind:tap="onClickCloseIcon"
/>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
function popupStyle(data) {
return style([
{
'z-index': data.zIndex,
'-webkit-transition-duration': data.currentDuration + 'ms',
'transition-duration': data.currentDuration + 'ms',
},
data.display ? null : 'display: none',
data.customStyle,
]);
}
module.exports = {
popupStyle: popupStyle,
};
@import '../common/index.wxss';.van-popup{-webkit-overflow-scrolling:touch;animation:ease both;background-color:var(--popup-background-color,#fff);box-sizing:border-box;max-height:100%;overflow-y:auto;position:fixed;transition-timing-function:ease}.van-popup--center{left:50%;top:50%;transform:translate3d(-50%,-50%,0)}.van-popup--center.van-popup--round{border-radius:var(--popup-round-border-radius,16px)}.van-popup--top{left:0;top:0;width:100%}.van-popup--top.van-popup--round{border-radius:0 0 var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) var(--popup-round-border-radius,var(--popup-round-border-radius,16px))}.van-popup--right{right:0;top:50%;transform:translate3d(0,-50%,0)}.van-popup--right.van-popup--round{border-radius:var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) 0 0 var(--popup-round-border-radius,var(--popup-round-border-radius,16px))}.van-popup--bottom{bottom:0;left:0;width:100%}.van-popup--bottom.van-popup--round{border-radius:var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) 0 0}.van-popup--left{left:0;top:50%;transform:translate3d(0,-50%,0)}.van-popup--left.van-popup--round{border-radius:0 var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) var(--popup-round-border-radius,var(--popup-round-border-radius,16px)) 0}.van-popup--bottom.van-popup--safe{padding-bottom:env(safe-area-inset-bottom)}.van-popup--safeTop{padding-top:env(safe-area-inset-top)}.van-popup__close-icon{color:var(--popup-close-icon-color,#969799);font-size:var(--popup-close-icon-size,18px);position:absolute;z-index:var(--popup-close-icon-z-index,1)}.van-popup__close-icon--top-left{left:var(--popup-close-icon-margin,16px);top:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--top-right{right:var(--popup-close-icon-margin,16px);top:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-left{bottom:var(--popup-close-icon-margin,16px);left:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-right{bottom:var(--popup-close-icon-margin,16px);right:var(--popup-close-icon-margin,16px)}.van-popup__close-icon:active{opacity:.6}.van-scale-enter-active,.van-scale-leave-active{transition-property:opacity,transform}.van-scale-enter,.van-scale-leave-to{opacity:0;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:transform}.van-bottom-enter,.van-bottom-leave-to{transform:translate3d(0,100%,0)}.van-top-enter,.van-top-leave-to{transform:translate3d(0,-100%,0)}.van-left-enter,.van-left-leave-to{transform:translate3d(-100%,-50%,0)}.van-right-enter,.van-right-leave-to{transform:translate3d(100%,-50%,0)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { BLUE } from '../common/color';
import { getRect } from '../common/utils';
VantComponent({
props: {
inactive: Boolean,
percentage: {
type: Number,
observer: 'setLeft',
},
pivotText: String,
pivotColor: String,
trackColor: String,
showPivot: {
type: Boolean,
value: true,
},
color: {
type: String,
value: BLUE,
},
textColor: {
type: String,
value: '#fff',
},
strokeWidth: {
type: null,
value: 4,
},
},
data: {
right: 0,
},
mounted() {
this.setLeft();
},
methods: {
setLeft() {
Promise.all([
getRect(this, '.van-progress'),
getRect(this, '.van-progress__pivot'),
]).then(([portion, pivot]) => {
if (portion && pivot) {
this.setData({
right: (pivot.width * (this.data.percentage - 100)) / 100,
});
}
});
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view
class="van-progress custom-class"
style="{{ computed.rootStyle({ strokeWidth, trackColor }) }}"
>
<view
class="van-progress__portion"
style="{{ computed.portionStyle({ percentage, inactive, color }) }}"
>
<view
wx:if="{{ showPivot && computed.pivotText(pivotText, percentage) }}"
style="{{ computed.pivotStyle({ textColor, pivotColor, inactive, color, right }) }}"
class="van-progress__pivot"
>
{{ computed.pivotText(pivotText, percentage) }}
</view>
</view>
</view>
/* eslint-disable */
var utils = require('../wxs/utils.wxs');
var style = require('../wxs/style.wxs');
function pivotText(pivotText, percentage) {
return pivotText || percentage + '%';
}
function rootStyle(data) {
return style({
'height': data.strokeWidth ? utils.addUnit(data.strokeWidth) : '',
'background': data.trackColor,
});
}
function portionStyle(data) {
return style({
background: data.inactive ? '#cacaca' : data.color,
width: data.percentage ? data.percentage + '%' : '',
});
}
function pivotStyle(data) {
return style({
color: data.textColor,
right: data.right + 'px',
background: data.pivotColor ? data.pivotColor : data.inactive ? '#cacaca' : data.color,
});
}
module.exports = {
pivotText: pivotText,
rootStyle: rootStyle,
portionStyle: portionStyle,
pivotStyle: pivotStyle,
};
@import '../common/index.wxss';.van-progress{background:var(--progress-background-color,#ebedf0);border-radius:var(--progress-height,4px);height:var(--progress-height,4px);position:relative}.van-progress__portion{background:var(--progress-color,#1989fa);border-radius:inherit;height:100%;left:0;position:absolute}.van-progress__pivot{background-color:var(--progress-pivot-background-color,#1989fa);border-radius:1em;box-sizing:border-box;color:var(--progress-pivot-text-color,#fff);font-size:var(--progress-pivot-font-size,10px);line-height:var(--progress-pivot-line-height,1.6);min-width:3.6em;padding:var(--progress-pivot-padding,0 5px);position:absolute;text-align:center;top:50%;transform:translateY(-50%);word-break:keep-all}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
field: true,
relation: useChildren('radio'),
props: {
value: {
type: null,
observer: 'updateChildren',
},
direction: String,
disabled: {
type: Boolean,
observer: 'updateChildren',
},
},
methods: {
updateChildren() {
this.children.forEach((child) => child.updateFromParent());
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="{{ utils.bem('radio-group', [direction]) }}">
<slot></slot>
</view>
@import '../common/index.wxss';.van-radio-group--horizontal{display:flex;flex-wrap:wrap}
\ No newline at end of file
import { canIUseModel } from '../common/version';
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
VantComponent({
field: true,
relation: useParent('radio-group', function () {
this.updateFromParent();
}),
classes: ['icon-class', 'label-class'],
props: {
name: null,
value: null,
disabled: Boolean,
useIconSlot: Boolean,
checkedColor: String,
labelPosition: {
type: String,
value: 'right',
},
labelDisabled: Boolean,
shape: {
type: String,
value: 'round',
},
iconSize: {
type: null,
value: 20,
},
},
data: {
direction: '',
parentDisabled: false,
},
methods: {
updateFromParent() {
if (!this.parent) {
return;
}
const { value, disabled: parentDisabled, direction } = this.parent.data;
this.setData({
value,
direction,
parentDisabled,
});
},
emitChange(value) {
const instance = this.parent || this;
instance.$emit('input', value);
instance.$emit('change', value);
if (canIUseModel()) {
instance.setData({ value });
}
},
onChange() {
if (!this.data.disabled && !this.data.parentDisabled) {
this.emitChange(this.data.name);
}
},
onClickLabel() {
const { disabled, parentDisabled, labelDisabled, name } = this.data;
if (!(disabled || parentDisabled) && !labelDisabled) {
this.emitChange(name);
}
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="{{ utils.bem('radio', [direction]) }} custom-class">
<view
wx:if="{{ labelPosition === 'left' }}"
class="{{ utils.bem('radio__label', [labelPosition, { disabled: disabled || parentDisabled }]) }} label-class"
bindtap="onClickLabel"
>
<slot />
</view>
<view class="van-radio__icon-wrap" style="font-size: {{ utils.addUnit(iconSize) }}" bindtap="onChange">
<slot wx:if="{{ useIconSlot }}" name="icon" />
<van-icon
wx:else
name="success"
class="{{ utils.bem('radio__icon', [shape, { disabled: disabled || parentDisabled, checked: value === name }]) }}"
style="{{ computed.iconStyle({ iconSize, checkedColor, disabled, parentDisabled, value, name }) }}"
custom-class="icon-class"
custom-style="{{ computed.iconCustomStyle({ iconSize }) }}"
/>
</view>
<view
wx:if="{{ labelPosition === 'right' }}"
class="label-class {{ utils.bem('radio__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}"
bindtap="onClickLabel"
>
<slot />
</view>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function iconStyle(data) {
var styles = {
'font-size': addUnit(data.iconSize),
};
if (
data.checkedColor &&
!(data.disabled || data.parentDisabled) &&
data.value === data.name
) {
styles['border-color'] = data.checkedColor;
styles['background-color'] = data.checkedColor;
}
return style(styles);
}
function iconCustomStyle(data) {
return style({
'line-height': addUnit(data.iconSize),
'font-size': '.8em',
display: 'block',
});
}
module.exports = {
iconStyle: iconStyle,
iconCustomStyle: iconCustomStyle,
};
@import '../common/index.wxss';.van-radio{align-items:center;display:flex;overflow:hidden;-webkit-user-select:none;user-select:none}.van-radio__icon-wrap{flex:none}.van-radio--horizontal{margin-right:var(--padding-sm,12px)}.van-radio__icon{align-items:center;border:1px solid var(--radio-border-color,#c8c9cc);box-sizing:border-box;color:transparent;display:flex;font-size:var(--radio-size,20px);height:1em;justify-content:center;text-align:center;transition-duration:var(--radio-transition-duration,.2s);transition-property:color,border-color,background-color;width:1em}.van-radio__icon--round{border-radius:100%}.van-radio__icon--checked{background-color:var(--radio-checked-icon-color,#1989fa);border-color:var(--radio-checked-icon-color,#1989fa);color:#fff}.van-radio__icon--disabled{background-color:var(--radio-disabled-background-color,#ebedf0);border-color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__icon--disabled.van-radio__icon--checked{color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__label{word-wrap:break-word;color:var(--radio-label-color,#323233);line-height:var(--radio-size,20px);padding-left:var(--radio-label-margin,10px)}.van-radio__label--left{float:left;margin:0 var(--radio-label-margin,10px) 0 0}.van-radio__label--disabled{color:var(--radio-disabled-label-color,#c8c9cc)}.van-radio__label:empty{margin:0}
\ No newline at end of file
import { getAllRect } from '../common/utils';
import { VantComponent } from '../common/component';
import { canIUseModel } from '../common/version';
VantComponent({
field: true,
classes: ['icon-class'],
props: {
value: {
type: Number,
observer(value) {
if (value !== this.data.innerValue) {
this.setData({ innerValue: value });
}
},
},
readonly: Boolean,
disabled: Boolean,
allowHalf: Boolean,
size: null,
icon: {
type: String,
value: 'star',
},
voidIcon: {
type: String,
value: 'star-o',
},
color: String,
voidColor: String,
disabledColor: String,
count: {
type: Number,
value: 5,
observer(value) {
this.setData({ innerCountArray: Array.from({ length: value }) });
},
},
gutter: null,
touchable: {
type: Boolean,
value: true,
},
},
data: {
innerValue: 0,
innerCountArray: Array.from({ length: 5 }),
},
methods: {
onSelect(event) {
const { data } = this;
const { score } = event.currentTarget.dataset;
if (!data.disabled && !data.readonly) {
this.setData({ innerValue: score + 1 });
if (canIUseModel()) {
this.setData({ value: score + 1 });
}
wx.nextTick(() => {
this.$emit('input', score + 1);
this.$emit('change', score + 1);
});
}
},
onTouchMove(event) {
const { touchable } = this.data;
if (!touchable)
return;
const { clientX } = event.touches[0];
getAllRect(this, '.van-rate__icon').then((list) => {
const target = list
.sort((cur, next) => cur.dataset.score - next.dataset.score)
.find((item) => clientX >= item.left && clientX <= item.right);
if (target != null) {
this.onSelect(Object.assign(Object.assign({}, event), { currentTarget: target }));
}
});
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="../wxs/style.wxs" module="style" />
<view
class="{{ utils.bem('rate') }} custom-class"
bind:touchmove="onTouchMove"
>
<view
class="{{ utils.bem('rate__item') }}"
wx:for="{{ innerCountArray }}"
wx:key="index"
style="{{ style({ paddingRight: index !== count - 1 ? utils.addUnit(gutter) : null }) }}"
>
<van-icon
name="{{ index + 1 <= innerValue ? icon : voidIcon }}"
class="{{ utils.bem('rate__icon', [{ disabled, full: index + 1 <= innerValue }])}}"
style="{{ style({ fontSize: utils.addUnit(size) }) }}"
custom-class="icon-class"
data-score="{{ index }}"
color="{{ disabled ? disabledColor : index + 1 <= innerValue ? color : voidColor }}"
bind:click="onSelect"
/>
<van-icon
wx:if="{{ allowHalf }}"
name="{{ index + 0.5 <= innerValue ? icon : voidIcon }}"
class="{{ utils.bem('rate__icon', ['half', { disabled, full: index + 0.5 <= innerValue }]) }}"
style="{{ style({ fontSize: utils.addUnit(size) }) }}"
custom-class="icon-class"
data-score="{{ index - 0.5 }}"
color="{{ disabled ? disabledColor : index + 0.5 <= innerValue ? color : voidColor }}"
bind:click="onSelect"
/>
</view>
</view>
@import '../common/index.wxss';.van-rate{display:inline-flex;-webkit-user-select:none;user-select:none}.van-rate__item{padding:0 var(--rate-horizontal-padding,2px);position:relative}.van-rate__item:not(:last-child){padding-right:var(--rate-icon-gutter,4px)}.van-rate__icon{color:var(--rate-icon-void-color,#c8c9cc);display:block;font-size:var(--rate-icon-size,20px);height:1em}.van-rate__icon--half{left:var(--rate-horizontal-padding,2px);overflow:hidden;position:absolute;top:0;width:.5em}.van-rate__icon--full,.van-rate__icon--half{color:var(--rate-icon-full-color,#ee0a24)}.van-rate__icon--disabled{color:var(--rate-icon-disabled-color,#c8c9cc)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('col', function (target) {
const { gutter } = this.data;
if (gutter) {
target.setData({ gutter });
}
}),
props: {
gutter: {
type: Number,
observer: 'setGutter',
},
},
methods: {
setGutter() {
this.children.forEach((col) => {
col.setData(this.data);
});
},
},
});
<wxs src="./index.wxs" module="computed" />
<view class="van-row custom-class" style="{{ computed.rootStyle({ gutter }) }}">
<slot />
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
if (!data.gutter) {
return '';
}
return style({
'margin-right': addUnit(-data.gutter / 2),
'margin-left': addUnit(-data.gutter / 2),
});
}
module.exports = {
rootStyle: rootStyle,
};
@import '../common/index.wxss';.van-row:after{clear:both;content:"";display:table}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { canIUseModel } from '../common/version';
VantComponent({
field: true,
classes: ['field-class', 'input-class', 'cancel-class'],
props: {
label: String,
focus: Boolean,
error: Boolean,
disabled: Boolean,
readonly: Boolean,
inputAlign: String,
showAction: Boolean,
useActionSlot: Boolean,
useLeftIconSlot: Boolean,
useRightIconSlot: Boolean,
leftIcon: {
type: String,
value: 'search',
},
rightIcon: String,
placeholder: String,
placeholderStyle: String,
actionText: {
type: String,
value: '取消',
},
background: {
type: String,
value: '#ffffff',
},
maxlength: {
type: Number,
value: -1,
},
shape: {
type: String,
value: 'square',
},
clearable: {
type: Boolean,
value: true,
},
clearTrigger: {
type: String,
value: 'focus',
},
clearIcon: {
type: String,
value: 'clear',
},
},
methods: {
onChange(event) {
if (canIUseModel()) {
this.setData({ value: event.detail });
}
this.$emit('change', event.detail);
},
onCancel() {
/**
* 修复修改输入框值时,输入框失焦和赋值同时触发,赋值失效
* https://github.com/youzan/@vant/weapp/issues/1768
*/
setTimeout(() => {
if (canIUseModel()) {
this.setData({ value: '' });
}
this.$emit('cancel');
this.$emit('change', '');
}, 200);
},
onSearch(event) {
this.$emit('search', event.detail);
},
onFocus(event) {
this.$emit('focus', event.detail);
},
onBlur(event) {
this.$emit('blur', event.detail);
},
onClear(event) {
this.$emit('clear', event.detail);
},
onClickInput(event) {
this.$emit('click-input', event.detail);
},
},
});
{
"component": true,
"usingComponents": {
"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
type="search"
left-icon="{{ !useLeftIconSlot ? leftIcon : '' }}"
right-icon="{{ !useRightIconSlot ? rightIcon : '' }}"
focus="{{ focus }}"
error="{{ error }}"
border="{{ false }}"
confirm-type="search"
class="van-search__field field-class"
value="{{ value }}"
disabled="{{ disabled }}"
readonly="{{ readonly }}"
clearable="{{ clearable }}"
clear-trigger="{{ clearTrigger }}"
clear-icon="{{ clearIcon }}"
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"
bind:click-input="onClickInput"
>
<slot wx:if="{{ useLeftIconSlot }}" name="left-icon" slot="left-icon" />
<slot wx:if="{{ useRightIconSlot }}" name="right-icon" slot="right-icon" />
</van-field>
</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">{{ actionText }}</view>
</view>
</view>
@import '../common/index.wxss';.van-search{align-items:center;box-sizing:border-box;display:flex;padding:var(--search-padding,10px 12px)}.van-search__content{background-color:var(--search-background-color,#f7f8fa);border-radius:2px;display:flex;flex:1;padding-left:var(--padding-sm,12px)}.van-search__content--round{border-radius:999px}.van-search__label{color:var(--search-label-color,#323233);font-size:var(--search-label-font-size,14px);line-height:var(--search-input-height,34px);padding:var(--search-label-padding,0 5px)}.van-search__field{flex:1}.van-search__field__left-icon{color:var(--search-left-icon-color,#969799)}.van-search--withaction{padding-right:0}.van-search__action{color:var(--search-action-text-color,#323233);font-size:var(--search-action-font-size,14px);line-height:var(--search-input-height,34px);padding:var(--search-action-padding,0 8px)}.van-search__action--hover{background-color:#f2f3f5}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
props: {
// whether to show popup
show: Boolean,
// overlay custom style
overlayStyle: String,
// z-index
zIndex: {
type: Number,
value: 100,
},
title: String,
cancelText: {
type: String,
value: '取消',
},
description: String,
options: {
type: Array,
value: [],
},
overlay: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
duration: {
type: null,
value: 300,
},
},
methods: {
onClickOverlay() {
this.$emit('click-overlay');
},
onCancel() {
this.onClose();
this.$emit('cancel');
},
onSelect(event) {
this.$emit('select', event.detail);
},
onClose() {
this.$emit('close');
},
},
});
{
"component": true,
"usingComponents": {
"van-popup": "../popup/index",
"options": "./options"
}
}
<wxs src="./index.wxs" module="computed" />
<van-popup
round
class="van-share-sheet"
show="{{ show }}"
position="bottom"
overlay="{{ overlay }}"
duration="{{ duration }}"
z-index="{{ zIndex }}"
overlay-style="{{ overlayStyle }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
bind:close="onClose"
bind:click-overlay="onClickOverlay"
>
<view class="van-share-sheet__header">
<view class="van-share-sheet__title">
<slot name="title" />
</view>
<view wx:if="{{ title }}" class="van-share-sheet__title">{{ title }}</view>
<view class="van-share-sheet__description">
<slot name="description" />
</view>
<view wx:if="{{ description }}" class="van-share-sheet__description">
{{ description }}
</view>
</view>
<block wx:if="{{ computed.isMulti(options) }}">
<options
wx:for="{{ options }}"
show-border="{{ index !== 0 }}"
wx:key="index"
options="{{ item }}"
bind:select="onSelect"
/>
</block>
<options wx:else options="{{ options }}" bind:select="onSelect" />
<button type="button" class="van-share-sheet__cancel" bindtap="onCancel">
{{ cancelText }}
</button>
</van-popup>
/* eslint-disable */
function isMulti(options) {
if (options == null || options[0] == null) {
return false;
}
return "Array" === options.constructor && "Array" === options[0].constructor;
}
module.exports = {
isMulti: isMulti
};
@import '../common/index.wxss';.van-share-sheet__header{padding:12px 16px 4px;text-align:center}.van-share-sheet__title{color:#323233;font-size:14px;font-weight:400;line-height:20px;margin-top:8px}.van-share-sheet__title:empty,.van-share-sheet__title:not(:empty)+.van-share-sheet__title{display:none}.van-share-sheet__description{color:#969799;display:block;font-size:12px;line-height:16px;margin-top:8px}.van-share-sheet__description:empty,.van-share-sheet__description:not(:empty)+.van-share-sheet__description{display:none}.van-share-sheet__cancel{background:#fff;border:none;box-sizing:initial;display:block;font-size:16px;height:auto;line-height:48px;padding:0;text-align:center;width:100%}.van-share-sheet__cancel:before{background-color:#f7f8fa;content:" ";display:block;height:8px}.van-share-sheet__cancel:after{display:none}.van-share-sheet__cancel:active{background-color:#f2f3f5}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
props: {
options: Array,
showBorder: Boolean,
},
methods: {
onSelect(event) {
const { index } = event.currentTarget.dataset;
const option = this.data.options[index];
this.$emit('select', Object.assign(Object.assign({}, option), { index }));
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./options.wxs" module="computed" />
<view class="{{ utils.bem('share-sheet__options', { border: showBorder }) }}">
<view
wx:for="{{ options }}"
wx:key="index"
class="van-share-sheet__option"
data-index="{{ index }}"
bindtap="onSelect"
>
<button class="van-share-sheet__button" open-type="{{ item.openType }}">
<image src="{{ computed.getIconURL(item.icon) }}" class="van-share-sheet__icon" />
<view wx:if="{{ item.name }}" class="van-share-sheet__name">{{ item.name }}</view>
<view wx:if="{{ item.description }}" class="van-share-sheet__option-description">
{{ item.description }}
</view>
</button>
</view>
</view>
/* eslint-disable */
var PRESET_ICONS = ['qq', 'link', 'weibo', 'wechat', 'poster', 'qrcode', 'weapp-qrcode', 'wechat-moments'];
function getIconURL(icon) {
if (PRESET_ICONS.indexOf(icon) !== -1) {
return 'https://img.yzcdn.cn/vant/share-sheet-' + icon + '.png';
}
return icon;
}
module.exports = {
getIconURL: getIconURL,
};
@import '../common/index.wxss';.van-share-sheet__options{-webkit-overflow-scrolling:touch;display:flex;overflow-x:auto;overflow-y:visible;padding:16px 0 16px 8px;position:relative}.van-share-sheet__options--border:before{border-top:1px solid #ebedf0;box-sizing:border-box;content:" ";left:16px;pointer-events:none;position:absolute;right:0;top:0;transform:scaleY(.5);transform-origin:center}.van-share-sheet__options::-webkit-scrollbar{height:0}.van-share-sheet__option{align-items:center;display:flex;flex-direction:column;-webkit-user-select:none;user-select:none}.van-share-sheet__option:active{opacity:.7}.van-share-sheet__button{background-color:initial;border:0;height:auto;line-height:inherit;padding:0}.van-share-sheet__button:after{border:0}.van-share-sheet__icon{height:48px;margin:0 16px;width:48px}.van-share-sheet__name{color:#646566;font-size:12px;margin-top:8px;padding:0 4px}.van-share-sheet__option-description{color:#c8c9cc;font-size:12px;padding:0 4px}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
VantComponent({
classes: ['active-class', 'disabled-class'],
relation: useParent('sidebar'),
props: {
dot: Boolean,
badge: null,
info: null,
title: String,
disabled: Boolean,
},
methods: {
onClick() {
const { parent } = this;
if (!parent || this.data.disabled) {
return;
}
const index = parent.children.indexOf(this);
parent.setActive(index).then(() => {
this.$emit('click', index);
parent.$emit('change', index);
});
},
setActive(selected) {
return this.setData({ selected });
},
},
});
{
"component": true,
"usingComponents": {
"van-info": "../info/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="{{ utils.bem('sidebar-item', { selected, disabled }) }} {{ selected ? 'active-class' : '' }} {{ disabled ? 'disabled-class' : '' }} custom-class"
hover-class="van-sidebar-item--hover"
hover-stay-time="70"
bind:tap="onClick"
>
<view class="van-sidebar-item__text">
<van-info
wx:if="{{ badge != null || info !== null || dot }}"
dot="{{ dot }}"
info="{{ badge != null ? badge : info }}"
/>
<view wx:if="{{ title }}">{{ title }}</view>
<slot wx:else name="title" />
</view>
</view>
@import '../common/index.wxss';.van-sidebar-item{background-color:var(--sidebar-background-color,#f7f8fa);border-left:3px solid transparent;box-sizing:border-box;color:var(--sidebar-text-color,#323233);display:block;font-size:var(--sidebar-font-size,14px);line-height:var(--sidebar-line-height,20px);overflow:hidden;padding:var(--sidebar-padding,20px 12px 20px 8px);-webkit-user-select:none;user-select:none}.van-sidebar-item__text{display:inline-block;position:relative;word-break:break-all}.van-sidebar-item--hover:not(.van-sidebar-item--disabled){background-color:var(--sidebar-active-color,#f2f3f5)}.van-sidebar-item:after{border-bottom-width:1px}.van-sidebar-item--selected{border-color:var(--sidebar-selected-border-color,#ee0a24);color:var(--sidebar-selected-text-color,#323233);font-weight:var(--sidebar-selected-font-weight,500)}.van-sidebar-item--selected:after{border-right-width:1px}.van-sidebar-item--selected,.van-sidebar-item--selected.van-sidebar-item--hover{background-color:var(--sidebar-selected-background-color,#fff)}.van-sidebar-item--disabled{color:var(--sidebar-disabled-text-color,#c8c9cc)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('sidebar-item', function () {
this.setActive(this.data.activeKey);
}),
props: {
activeKey: {
type: Number,
value: 0,
observer: 'setActive',
},
},
beforeCreate() {
this.currentActive = -1;
},
methods: {
setActive(activeKey) {
const { children, currentActive } = this;
if (!children.length) {
return Promise.resolve();
}
this.currentActive = activeKey;
const stack = [];
if (currentActive !== activeKey && children[currentActive]) {
stack.push(children[currentActive].setActive(false));
}
if (children[activeKey]) {
stack.push(children[activeKey].setActive(true));
}
return Promise.all(stack);
},
},
});
<view class="van-sidebar custom-class">
<slot />
</view>
@import '../common/index.wxss';.van-sidebar{width:var(--sidebar-width,80px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
classes: ['avatar-class', 'title-class', 'row-class'],
props: {
row: {
type: Number,
value: 0,
observer(value) {
this.setData({ rowArray: Array.from({ length: value }) });
},
},
title: Boolean,
avatar: Boolean,
loading: {
type: Boolean,
value: true,
},
animate: {
type: Boolean,
value: true,
},
avatarSize: {
type: String,
value: '32px',
},
avatarShape: {
type: String,
value: 'round',
},
titleWidth: {
type: String,
value: '40%',
},
rowWidth: {
type: null,
value: '100%',
observer(val) {
this.setData({ isArray: val instanceof Array });
},
},
},
data: {
isArray: false,
rowArray: [],
},
});
{
"component": true,
"usingComponents": {}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
wx:if="{{ loading }}"
class="custom-class {{ utils.bem('skeleton', [{animate}]) }}"
>
<view
wx:if="{{ avatar }}"
class="avatar-class {{ utils.bem('skeleton__avatar', [avatarShape])}}"
style="{{ 'width:' + avatarSize + ';height:' + avatarSize }}"
/>
<view class="{{ utils.bem('skeleton__content')}}">
<view
wx:if="{{ title }}"
class="title-class {{ utils.bem('skeleton__title') }}"
style="{{ 'width:' + titleWidth }}"
/>
<view
wx:for="{{ rowArray }}"
wx:key="index"
wx:for-index="index"
class="row-class {{ utils.bem('skeleton__row') }}"
style="{{ 'width:' + (isArray ? rowWidth[index] : rowWidth) }}"
/>
</view>
</view>
<view wx:else class="{{ utils.bem('skeleton__content')}}">
<slot />
</view>
@import '../common/index.wxss';.van-skeleton{box-sizing:border-box;display:flex;padding:var(--skeleton-padding,0 16px);width:100%}.van-skeleton__avatar{background-color:var(--skeleton-avatar-background-color,#f2f3f5);flex-shrink:0;margin-right:var(--padding-md,16px)}.van-skeleton__avatar--round{border-radius:100%}.van-skeleton__content{flex:1}.van-skeleton__avatar+.van-skeleton__content{padding-top:var(--padding-xs,8px)}.van-skeleton__row,.van-skeleton__title{background-color:var(--skeleton-row-background-color,#f2f3f5);height:var(--skeleton-row-height,16px)}.van-skeleton__title{margin:0}.van-skeleton__row:not(:first-child){margin-top:var(--skeleton-row-margin-top,12px)}.van-skeleton__title+.van-skeleton__row{margin-top:20px}.van-skeleton--animate{animation:van-skeleton-blink 1.2s ease-in-out infinite}@keyframes van-skeleton-blink{50%{opacity:.6}}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
import { canIUseModel } from '../common/version';
import { getRect, addUnit } from '../common/utils';
VantComponent({
mixins: [touch],
props: {
range: Boolean,
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: null,
value: 0,
observer(val) {
if (val !== this.value) {
this.updateValue(val);
}
},
},
vertical: Boolean,
barHeight: null,
},
created() {
this.updateValue(this.data.value);
},
methods: {
onTouchStart(event) {
if (this.data.disabled)
return;
const { index } = event.currentTarget.dataset;
if (typeof index === 'number') {
this.buttonIndex = index;
}
this.touchStart(event);
this.startValue = this.format(this.value);
this.newValue = this.value;
if (this.isRange(this.newValue)) {
this.startValue = this.newValue.map((val) => this.format(val));
}
else {
this.startValue = this.format(this.newValue);
}
this.dragStatus = 'start';
},
onTouchMove(event) {
if (this.data.disabled)
return;
if (this.dragStatus === 'start') {
this.$emit('drag-start');
}
this.touchMove(event);
this.dragStatus = 'draging';
getRect(this, '.van-slider').then((rect) => {
const { vertical } = this.data;
const delta = vertical ? this.deltaY : this.deltaX;
const total = vertical ? rect.height : rect.width;
const diff = (delta / total) * this.getRange();
if (this.isRange(this.startValue)) {
this.newValue[this.buttonIndex] =
this.startValue[this.buttonIndex] + diff;
}
else {
this.newValue = this.startValue + diff;
}
this.updateValue(this.newValue, false, true);
});
},
onTouchEnd() {
if (this.data.disabled)
return;
if (this.dragStatus === 'draging') {
this.updateValue(this.newValue, true);
this.$emit('drag-end');
}
},
onClick(event) {
if (this.data.disabled)
return;
const { min } = this.data;
getRect(this, '.van-slider').then((rect) => {
const { vertical } = this.data;
const touch = event.touches[0];
const delta = vertical
? touch.clientY - rect.top
: touch.clientX - rect.left;
const total = vertical ? rect.height : rect.width;
const value = Number(min) + (delta / total) * this.getRange();
if (this.isRange(this.value)) {
const [left, right] = this.value;
const middle = (left + right) / 2;
if (value <= middle) {
this.updateValue([value, right], true);
}
else {
this.updateValue([left, value], true);
}
}
else {
this.updateValue(value, true);
}
});
},
isRange(val) {
const { range } = this.data;
return range && Array.isArray(val);
},
handleOverlap(value) {
if (value[0] > value[1]) {
return value.slice(0).reverse();
}
return value;
},
updateValue(value, end, drag) {
if (this.isRange(value)) {
value = this.handleOverlap(value).map((val) => this.format(val));
}
else {
value = this.format(value);
}
this.value = value;
const { vertical } = this.data;
const mainAxis = vertical ? 'height' : 'width';
this.setData({
wrapperStyle: `
background: ${this.data.inactiveColor || ''};
${vertical ? 'width' : 'height'}: ${addUnit(this.data.barHeight) || ''};
`,
barStyle: `
${mainAxis}: ${this.calcMainAxis()};
left: ${vertical ? 0 : this.calcOffset()};
top: ${vertical ? this.calcOffset() : 0};
${drag ? 'transition: none;' : ''}
`,
});
if (drag) {
this.$emit('drag', { value });
}
if (end) {
this.$emit('change', value);
}
if ((drag || end) && canIUseModel()) {
this.setData({ value });
}
},
getScope() {
return Number(this.data.max) - Number(this.data.min);
},
getRange() {
const { max, min } = this.data;
return max - min;
},
// 计算选中条的长度百分比
calcMainAxis() {
const { value } = this;
const { min } = this.data;
const scope = this.getScope();
if (this.isRange(value)) {
return `${((value[1] - value[0]) * 100) / scope}%`;
}
return `${((value - Number(min)) * 100) / scope}%`;
},
// 计算选中条的开始位置的偏移量
calcOffset() {
const { value } = this;
const { min } = this.data;
const scope = this.getScope();
if (this.isRange(value)) {
return `${((value[0] - Number(min)) * 100) / scope}%`;
}
return '0%';
},
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" />
<wxs src="../wxs/style.wxs" module="style" />
<view
class="custom-class {{ utils.bem('slider', { disabled, vertical }) }}"
style="{{ wrapperStyle }}"
bind:tap="onClick"
>
<view
class="{{ utils.bem('slider__bar') }}"
style="{{ barStyle }}; {{ style({ backgroundColor: activeColor }) }}"
>
<view
wx:if="{{ range }}"
class="{{ utils.bem('slider__button-wrapper-left') }}"
data-index="{{ 0 }}"
bind:touchstart="onTouchStart"
catch:touchmove="onTouchMove"
bind:touchend="onTouchEnd"
bind:touchcancel="onTouchEnd"
>
<slot
wx:if="{{ useButtonSlot }}"
name="left-button"
/>
<view
wx:else
class="{{ utils.bem('slider__button') }}"
/>
</view>
<view
wx:if="{{ range }}"
class="{{ utils.bem('slider__button-wrapper-right') }}"
data-index="{{ 1 }}"
bind:touchstart="onTouchStart"
catch:touchmove="onTouchMove"
bind:touchend="onTouchEnd"
bind:touchcancel="onTouchEnd"
>
<slot
wx:if="{{ useButtonSlot }}"
name="right-button"
/>
<view
wx:else
class="{{ utils.bem('slider__button') }}"
/>
</view>
<view
wx:if="{{ !range }}"
class="{{ utils.bem('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="{{ utils.bem('slider__button') }}"
/>
</view>
</view>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function barStyle(barHeight, activeColor) {
return style({
height: addUnit(barHeight),
background: activeColor,
});
}
module.exports = {
barStyle: barStyle,
};
@import '../common/index.wxss';.van-slider{background-color:var(--slider-inactive-background-color,#ebedf0);border-radius:999px;height:var(--slider-bar-height,2px);position:relative}.van-slider:before{bottom:calc(var(--padding-xs, 8px)*-1);content:"";left:0;position:absolute;right:0;top:calc(var(--padding-xs, 8px)*-1)}.van-slider__bar{background-color:var(--slider-active-background-color,#1989fa);border-radius:inherit;height:100%;position:relative;transition:all .2s;width:100%}.van-slider__button{background-color:var(--slider-button-background-color,#fff);border-radius:var(--slider-button-border-radius,50%);box-shadow:var(--slider-button-box-shadow,0 1px 2px rgba(0,0,0,.5));height:var(--slider-button-height,24px);width:var(--slider-button-width,24px)}.van-slider__button-wrapper,.van-slider__button-wrapper-right{position:absolute;right:0;top:50%;transform:translate3d(50%,-50%,0)}.van-slider__button-wrapper-left{left:0;position:absolute;top:50%;transform:translate3d(-50%,-50%,0)}.van-slider--disabled{opacity:var(--slider-disabled-opacity,.5)}.van-slider--vertical{display:inline-block;height:100%;width:var(--slider-bar-height,2px)}.van-slider--vertical .van-slider__button-wrapper,.van-slider--vertical .van-slider__button-wrapper-right{bottom:0;right:50%;top:auto;transform:translate3d(50%,50%,0)}.van-slider--vertical .van-slider__button-wrapper-left{left:auto;right:50%;top:0;transform:translate3d(50%,-50%,0)}.van-slider--vertical:before{bottom:0;left:-8px;right:-8px;top:0}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { isDef } from '../common/validator';
const LONG_PRESS_START_TIME = 600;
const LONG_PRESS_INTERVAL = 200;
// add num and avoid float number
function add(num1, num2) {
const cardinal = Math.pow(10, 10);
return Math.round((num1 + num2) * cardinal) / cardinal;
}
function equal(value1, value2) {
return String(value1) === String(value2);
}
VantComponent({
field: true,
classes: ['input-class', 'plus-class', 'minus-class'],
props: {
value: {
type: null,
observer: 'observeValue',
},
integer: {
type: Boolean,
observer: 'check',
},
disabled: Boolean,
inputWidth: String,
buttonSize: String,
asyncChange: Boolean,
disableInput: Boolean,
decimalLength: {
type: Number,
value: null,
observer: 'check',
},
min: {
type: null,
value: 1,
observer: 'check',
},
max: {
type: null,
value: Number.MAX_SAFE_INTEGER,
observer: 'check',
},
step: {
type: null,
value: 1,
},
showPlus: {
type: Boolean,
value: true,
},
showMinus: {
type: Boolean,
value: true,
},
disablePlus: Boolean,
disableMinus: Boolean,
longPress: {
type: Boolean,
value: true,
},
theme: String,
alwaysEmbed: Boolean,
},
data: {
currentValue: '',
},
created() {
this.setData({
currentValue: this.format(this.data.value),
});
},
methods: {
observeValue() {
const { value, currentValue } = this.data;
if (!equal(value, currentValue)) {
this.setData({ currentValue: this.format(value) });
}
},
check() {
const val = this.format(this.data.currentValue);
if (!equal(val, this.data.currentValue)) {
this.setData({ currentValue: val });
}
},
isDisabled(type) {
const { disabled, disablePlus, disableMinus, currentValue, max, min, } = this.data;
if (type === 'plus') {
return disabled || disablePlus || currentValue >= max;
}
return disabled || disableMinus || currentValue <= min;
},
onFocus(event) {
this.$emit('focus', event.detail);
},
onBlur(event) {
const value = this.format(event.detail.value);
this.emitChange(value);
this.$emit('blur', Object.assign(Object.assign({}, event.detail), { value }));
},
// filter illegal characters
filter(value) {
value = String(value).replace(/[^0-9.-]/g, '');
if (this.data.integer && value.indexOf('.') !== -1) {
value = value.split('.')[0];
}
return value;
},
// limit value range
format(value) {
value = this.filter(value);
// format range
value = value === '' ? 0 : +value;
value = Math.max(Math.min(this.data.max, value), this.data.min);
// format decimal
if (isDef(this.data.decimalLength)) {
value = value.toFixed(this.data.decimalLength);
}
return value;
},
onInput(event) {
const { value = '' } = event.detail || {};
// allow input to be empty
if (value === '') {
return;
}
let formatted = this.filter(value);
// limit max decimal length
if (isDef(this.data.decimalLength) && formatted.indexOf('.') !== -1) {
const pair = formatted.split('.');
formatted = `${pair[0]}.${pair[1].slice(0, this.data.decimalLength)}`;
}
this.emitChange(formatted);
},
emitChange(value) {
if (!this.data.asyncChange) {
this.setData({ currentValue: value });
}
this.$emit('change', value);
},
onChange() {
const { type } = this;
if (this.isDisabled(type)) {
this.$emit('overlimit', type);
return;
}
const diff = type === 'minus' ? -this.data.step : +this.data.step;
const value = this.format(add(+this.data.currentValue, diff));
this.emitChange(value);
this.$emit(type);
},
longPressStep() {
this.longPressTimer = setTimeout(() => {
this.onChange();
this.longPressStep();
}, LONG_PRESS_INTERVAL);
},
onTap(event) {
const { type } = event.currentTarget.dataset;
this.type = type;
this.onChange();
},
onTouchStart(event) {
if (!this.data.longPress) {
return;
}
clearTimeout(this.longPressTimer);
const { type } = event.currentTarget.dataset;
this.type = type;
this.isLongPress = false;
this.longPressTimer = setTimeout(() => {
this.isLongPress = true;
this.onChange();
this.longPressStep();
}, LONG_PRESS_START_TIME);
},
onTouchEnd() {
if (!this.data.longPress) {
return;
}
clearTimeout(this.longPressTimer);
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="{{ utils.bem('stepper', [theme]) }} custom-class">
<view
wx:if="{{ showMinus }}"
data-type="minus"
style="{{ computed.buttonStyle({ buttonSize }) }}"
class="minus-class {{ utils.bem('stepper__minus', { disabled: disabled || disableMinus || currentValue <= min }) }}"
hover-class="van-stepper__minus--hover"
hover-stay-time="70"
bind:tap="onTap"
bind:touchstart="onTouchStart"
bind:touchend="onTouchEnd"
>
<slot name="minus" />
</view>
<input
always-embed="{{ false }}"
type="{{ integer ? 'number' : 'digit' }}"
class="input-class {{ utils.bem('stepper__input', { disabled: disabled || disableInput }) }}"
style="{{ computed.inputStyle({ buttonSize, inputWidth }) }}"
value="{{ currentValue }}"
focus="{{ focus }}"
disabled="{{ disabled || disableInput }}"
always-embed="{{ alwaysEmbed }}"
bindinput="onInput"
bind:focus="onFocus"
bind:blur="onBlur"
/>
<view
wx:if="{{ showPlus }}"
data-type="plus"
style="{{ computed.buttonStyle({ buttonSize }) }}"
class="plus-class {{ utils.bem('stepper__plus', { disabled: disabled || disablePlus || currentValue >= max }) }}"
hover-class="van-stepper__plus--hover"
hover-stay-time="70"
bind:tap="onTap"
bind:touchstart="onTouchStart"
bind:touchend="onTouchEnd"
>
<slot name="plus" />
</view>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function buttonStyle(data) {
return style({
width: addUnit(data.buttonSize),
height: addUnit(data.buttonSize),
});
}
function inputStyle(data) {
return style({
width: addUnit(data.inputWidth),
height: addUnit(data.buttonSize),
});
}
module.exports = {
buttonStyle: buttonStyle,
inputStyle: inputStyle,
};
@import '../common/index.wxss';.van-stepper{font-size:0}.van-stepper__minus,.van-stepper__plus{background-color:var(--stepper-background-color,#f2f3f5);border:0;box-sizing:border-box;color:var(--stepper-button-icon-color,#323233);display:inline-block;height:var(--stepper-input-height,28px);margin:1px;padding:var(--padding-base,4px);position:relative;vertical-align:middle;width:var(--stepper-input-height,28px)}.van-stepper__minus:before,.van-stepper__plus:before{height:1px;width:9px}.van-stepper__minus:after,.van-stepper__plus:after{height:9px;width:1px}.van-stepper__minus:empty.van-stepper__minus:after,.van-stepper__minus:empty.van-stepper__minus:before,.van-stepper__minus:empty.van-stepper__plus:after,.van-stepper__minus:empty.van-stepper__plus:before,.van-stepper__plus:empty.van-stepper__minus:after,.van-stepper__plus:empty.van-stepper__minus:before,.van-stepper__plus:empty.van-stepper__plus:after,.van-stepper__plus:empty.van-stepper__plus:before{background-color:currentColor;bottom:0;content:"";left:0;margin:auto;position:absolute;right:0;top:0}.van-stepper__minus--hover,.van-stepper__plus--hover{background-color:var(--stepper-active-color,#e8e8e8)}.van-stepper__minus--disabled,.van-stepper__plus--disabled{color:var(--stepper-button-disabled-icon-color,#c8c9cc)}.van-stepper__minus--disabled,.van-stepper__minus--disabled.van-stepper__minus--hover,.van-stepper__minus--disabled.van-stepper__plus--hover,.van-stepper__plus--disabled,.van-stepper__plus--disabled.van-stepper__minus--hover,.van-stepper__plus--disabled.van-stepper__plus--hover{background-color:var(--stepper-button-disabled-color,#f7f8fa)}.van-stepper__minus{border-radius:var(--stepper-border-radius,var(--stepper-border-radius,4px)) 0 0 var(--stepper-border-radius,var(--stepper-border-radius,4px))}.van-stepper__minus:after{display:none}.van-stepper__plus{border-radius:0 var(--stepper-border-radius,var(--stepper-border-radius,4px)) var(--stepper-border-radius,var(--stepper-border-radius,4px)) 0}.van-stepper--round .van-stepper__input{background-color:initial!important}.van-stepper--round .van-stepper__minus,.van-stepper--round .van-stepper__plus{border-radius:100%}.van-stepper--round .van-stepper__minus:active,.van-stepper--round .van-stepper__plus:active{opacity:.7}.van-stepper--round .van-stepper__minus--disabled,.van-stepper--round .van-stepper__minus--disabled:active,.van-stepper--round .van-stepper__plus--disabled,.van-stepper--round .van-stepper__plus--disabled:active{opacity:.3}.van-stepper--round .van-stepper__plus{background-color:#ee0a24;color:#fff}.van-stepper--round .van-stepper__minus{background-color:#fff;border:1px solid #ee0a24;color:#ee0a24}.van-stepper__input{-webkit-appearance:none;background-color:var(--stepper-background-color,#f2f3f5);border:0;border-radius:0;border-width:1px 0;box-sizing:border-box;color:var(--stepper-input-text-color,#323233);display:inline-block;font-size:var(--stepper-input-font-size,14px);height:var(--stepper-input-height,28px);margin:1px;min-height:0;padding:1px;text-align:center;vertical-align:middle;width:var(--stepper-input-width,32px)}.van-stepper__input--disabled{background-color:var(--stepper-input-disabled-background-color,#f2f3f5);color:var(--stepper-input-disabled-text-color,#c8c9cc)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { GREEN, GRAY_DARK } from '../common/color';
VantComponent({
classes: ['desc-class'],
props: {
icon: String,
steps: Array,
active: Number,
direction: {
type: String,
value: 'horizontal',
},
activeColor: {
type: String,
value: GREEN,
},
inactiveColor: {
type: String,
value: GRAY_DARK,
},
activeIcon: {
type: String,
value: 'checked',
},
inactiveIcon: String,
},
methods: {
onClick(event) {
const { index } = event.currentTarget.dataset;
this.$emit('click-step', index);
},
},
});
{
"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"
bindtap="onClick"
data-index="{{ index }}"
class="{{ utils.bem('step', [direction, status(index, active)]) }} van-hairline"
style="{{ status(index, active) === 'inactive' ? 'color: ' + inactiveColor: '' }}"
>
<view class="van-step__title" style="{{ index === active ? 'color: ' + activeColor : '' }}">
<view>{{ item.text }}</view>
<view class="desc-class">{{ item.desc }}</view>
</view>
<view class="van-step__circle-container">
<block wx:if="{{ index !== active }}">
<van-icon
wx:if="{{ item.inactiveIcon || inactiveIcon }}"
color="{{ status(index, active) === 'inactive' ? inactiveColor: activeColor }}"
name="{{ item.inactiveIcon || inactiveIcon }}"
custom-class="van-step__icon"
/>
<view
wx:else
class="van-step__circle"
style="{{ 'background-color: ' + (index < active ? activeColor : inactiveColor) }}"
/>
</block>
<van-icon wx:else name="{{ item.activeIcon || activeIcon }}" color="{{ activeColor }}" custom-class="van-step__icon" />
</view>
<view
wx:if="{{ index !== steps.length - 1 }}"
class="van-step__line" style="{{ 'background-color: ' + (index < active ? activeColor : inactiveColor) }}"
/>
</view>
</view>
</view>
<wxs module="status">
function get(index, active) {
if (index < active) {
return 'finish';
} else if (index === active) {
return 'process';
}
return 'inactive';
}
module.exports = get;
</wxs>
@import '../common/index.wxss';.van-steps{background-color:var(--steps-background-color,#fff);overflow:hidden}.van-steps--horizontal{padding:10px}.van-steps--horizontal .van-step__wrapper{display:flex;overflow:hidden;position:relative}.van-steps--vertical{padding-left:10px}.van-steps--vertical .van-step__wrapper{padding:0 0 0 20px}.van-step{color:var(--step-text-color,#969799);flex:1;font-size:var(--step-font-size,14px);position:relative}.van-step--finish{color:var(--step-finish-text-color,#323233)}.van-step__circle{background-color:var(--step-circle-color,#969799);border-radius:50%;height:var(--step-circle-size,5px);width:var(--step-circle-size,5px)}.van-step--horizontal{padding-bottom:14px}.van-step--horizontal:first-child .van-step__title{transform:none}.van-step--horizontal:first-child .van-step__circle-container{padding:0 8px 0 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;transform:none}.van-step--horizontal:last-child .van-step__circle-container{padding:0 0 0 8px;right:0;transform:translate3d(0,50%,0)}.van-step--horizontal .van-step__circle-container{background-color:#fff;bottom:6px;padding:0 var(--padding-xs,8px);position:absolute;transform:translate3d(-50%,50%,0);z-index:1}.van-step--horizontal .van-step__title{display:inline-block;font-size:var(--step-horizontal-title-font-size,12px);transform:translate3d(-50%,0,0)}.van-step--horizontal .van-step__line{background-color:var(--step-line-color,#ebedf0);bottom:6px;height:1px;left:0;position:absolute;right:0;transform:translate3d(0,50%,0)}.van-step--horizontal.van-step--process{color:var(--step-process-text-color,#323233)}.van-step--horizontal.van-step--process .van-step__icon{display:block;font-size:var(--step-icon-size,12px);line-height:1}.van-step--vertical{line-height:18px;padding:10px 10px 10px 0}.van-step--vertical:after{border-bottom-width:1px}.van-step--vertical:last-child:after{border-bottom-width:none}.van-step--vertical:first-child:before{background-color:#fff;content:"";height:20px;left:-15px;position:absolute;top:0;width:1px;z-index:1}.van-step--vertical .van-step__circle,.van-step--vertical .van-step__icon,.van-step--vertical .van-step__line{left:-14px;position:absolute;top:19px;transform:translate3d(-50%,-50%,0);z-index:2}.van-step--vertical .van-step__icon{font-size:var(--step-icon-size,12px);line-height:1}.van-step--vertical .van-step__line{background-color:var(--step-line-color,#ebedf0);height:100%;transform:translate3d(-50%,0,0);width:1px;z-index:1}
\ No newline at end of file
import { getRect } from '../common/utils';
import { VantComponent } from '../common/component';
import { isDef } from '../common/validator';
import { pageScrollMixin } from '../mixins/page-scroll';
const ROOT_ELEMENT = '.van-sticky';
VantComponent({
props: {
zIndex: {
type: Number,
value: 99,
},
offsetTop: {
type: Number,
value: 0,
observer: 'onScroll',
},
disabled: {
type: Boolean,
observer: 'onScroll',
},
container: {
type: null,
observer: 'onScroll',
},
scrollTop: {
type: null,
observer(val) {
this.onScroll({ scrollTop: val });
},
},
},
mixins: [
pageScrollMixin(function (event) {
if (this.data.scrollTop != null) {
return;
}
this.onScroll(event);
}),
],
data: {
height: 0,
fixed: false,
transform: 0,
},
mounted() {
this.onScroll();
},
methods: {
onScroll({ scrollTop } = {}) {
const { container, offsetTop, disabled } = this.data;
if (disabled) {
this.setDataAfterDiff({
fixed: false,
transform: 0,
});
return;
}
this.scrollTop = scrollTop || this.scrollTop;
if (typeof container === 'function') {
Promise.all([
getRect(this, ROOT_ELEMENT),
this.getContainerRect(),
]).then(([root, container]) => {
if (offsetTop + root.height > container.height + container.top) {
this.setDataAfterDiff({
fixed: false,
transform: container.height - root.height,
});
}
else if (offsetTop >= root.top) {
this.setDataAfterDiff({
fixed: true,
height: root.height,
transform: 0,
});
}
else {
this.setDataAfterDiff({ fixed: false, transform: 0 });
}
});
return;
}
getRect(this, ROOT_ELEMENT).then((root) => {
if (!isDef(root)) {
return;
}
if (offsetTop >= root.top) {
this.setDataAfterDiff({ fixed: true, height: root.height });
this.transform = 0;
}
else {
this.setDataAfterDiff({ fixed: false });
}
});
},
setDataAfterDiff(data) {
wx.nextTick(() => {
const diff = Object.keys(data).reduce((prev, key) => {
if (data[key] !== this.data[key]) {
prev[key] = data[key];
}
return prev;
}, {});
if (Object.keys(diff).length > 0) {
this.setData(diff);
}
this.$emit('scroll', {
scrollTop: this.scrollTop,
isFixed: data.fixed || this.data.fixed,
});
});
},
getContainerRect() {
const nodesRef = this.data.container();
return new Promise((resolve) => nodesRef.boundingClientRect(resolve).exec());
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="custom-class van-sticky" style="{{ computed.containerStyle({ fixed, height, zIndex }) }}">
<view class="{{ utils.bem('sticky-wrap', { fixed }) }}" style="{{ computed.wrapStyle({ fixed, offsetTop, transform, zIndex }) }}">
<slot />
</view>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function wrapStyle(data) {
return style({
transform: data.transform
? 'translate3d(0, ' + data.transform + 'px, 0)'
: '',
top: data.fixed ? addUnit(data.offsetTop) : '',
'z-index': data.zIndex,
});
}
function containerStyle(data) {
return style({
height: data.fixed ? addUnit(data.height) : '',
'z-index': data.zIndex,
});
}
module.exports = {
wrapStyle: wrapStyle,
containerStyle: containerStyle,
};
@import '../common/index.wxss';.van-sticky{position:relative}.van-sticky-wrap--fixed{left:0;position:fixed;right:0}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
classes: ['bar-class', 'price-class', 'button-class'],
props: {
tip: {
type: null,
observer: 'updateTip',
},
tipIcon: String,
type: Number,
price: {
type: null,
observer: 'updatePrice',
},
label: String,
loading: Boolean,
disabled: Boolean,
buttonText: String,
currency: {
type: String,
value: '¥',
},
buttonType: {
type: String,
value: 'danger',
},
decimalLength: {
type: Number,
value: 2,
observer: 'updatePrice',
},
suffixLabel: String,
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
methods: {
updatePrice() {
const { price, decimalLength } = this.data;
const priceStrArr = typeof price === 'number' &&
(price / 100).toFixed(decimalLength).split('.');
this.setData({
hasPrice: typeof price === 'number',
integerStr: priceStrArr && priceStrArr[0],
decimalStr: decimalLength && priceStrArr ? `.${priceStrArr[1]}` : '',
});
},
updateTip() {
this.setData({ hasTip: typeof this.data.tip === 'string' });
},
onSubmit(event) {
this.$emit('submit', event.detail);
},
},
});
{
"component": true,
"usingComponents": {
"van-button": "../button/index",
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="van-submit-bar custom-class">
<slot name="top" />
<view class="van-submit-bar__tip">
<van-icon
wx:if="{{ tipIcon }}"
size="12px"
name="{{ tipIcon }}"
custom-class="van-submit-bar__tip-icon"
/>
<view wx:if="{{ hasTip }}" class="van-submit-bar__tip-text">
{{ tip }}
</view>
<slot name="tip" />
</view>
<view class="bar-class van-submit-bar__bar">
<slot />
<view wx:if="{{ hasPrice }}" class="van-submit-bar__text">
<text>{{ label || '合计:' }}</text>
<text class="van-submit-bar__price price-class">
<text class="van-submit-bar__currency">{{ currency }} </text>
<text class="van-submit-bar__price-integer">{{ integerStr }}</text><text>{{decimalStr}}</text>
</text>
<text class="van-submit-bar__suffix-label">{{ suffixLabel }}</text>
</view>
<van-button
round
type="{{ buttonType }}"
loading="{{ loading }}"
disabled="{{ disabled }}"
class="van-submit-bar__button"
custom-class="button-class"
custom-style="width: 100%;"
bind:click="onSubmit"
>
{{ loading ? '' : buttonText }}
</van-button>
</view>
<view wx:if="{{ safeAreaInsetBottom }}" class="van-submit-bar__safe" />
</view>
@import '../common/index.wxss';.van-submit-bar{background-color:var(--submit-bar-background-color,#fff);bottom:0;left:0;position:fixed;-webkit-user-select:none;user-select:none;width:100%;z-index:var(--submit-bar-z-index,100)}.van-submit-bar__tip{background-color:var(--submit-bar-tip-background-color,#fff7cc);color:var(--submit-bar-tip-color,#f56723);font-size:var(--submit-bar-tip-font-size,12px);line-height:var(--submit-bar-tip-line-height,1.5);padding:var(--submit-bar-tip-padding,10px)}.van-submit-bar__tip:empty{display:none}.van-submit-bar__tip-icon{margin-right:4px;vertical-align:middle}.van-submit-bar__tip-text{display:inline;vertical-align:middle}.van-submit-bar__bar{align-items:center;background-color:var(--submit-bar-background-color,#fff);display:flex;font-size:var(--submit-bar-text-font-size,14px);height:var(--submit-bar-height,50px);justify-content:flex-end;padding:var(--submit-bar-padding,0 16px)}.van-submit-bar__safe{height:constant(safe-area-inset-bottom);height:env(safe-area-inset-bottom)}.van-submit-bar__text{color:var(--submit-bar-text-color,#323233);flex:1;font-weight:var(--font-weight-bold,500);padding-right:var(--padding-sm,12px);text-align:right}.van-submit-bar__price{color:var(--submit-bar-price-color,#ee0a24);font-size:var(--submit-bar-price-font-size,12px);font-weight:var(--font-weight-bold,500)}.van-submit-bar__price-integer{font-family:Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif;font-size:20px}.van-submit-bar__currency{font-size:var(--submit-bar-currency-font-size,12px)}.van-submit-bar__suffix-label{margin-left:5px}.van-submit-bar__button{--button-default-height:var(--submit-bar-button-height,40px)!important;--button-line-height:var(--submit-bar-button-height,40px)!important;font-weight:var(--font-weight-bold,500);width:var(--submit-bar-button-width,110px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
import { range } from '../common/utils';
const THRESHOLD = 0.3;
let ARRAY = [];
VantComponent({
props: {
disabled: Boolean,
leftWidth: {
type: Number,
value: 0,
observer(leftWidth = 0) {
if (this.offset > 0) {
this.swipeMove(leftWidth);
}
},
},
rightWidth: {
type: Number,
value: 0,
observer(rightWidth = 0) {
if (this.offset < 0) {
this.swipeMove(-rightWidth);
}
},
},
asyncClose: Boolean,
name: {
type: null,
value: '',
},
},
mixins: [touch],
data: {
catchMove: false,
wrapperStyle: '',
},
created() {
this.offset = 0;
ARRAY.push(this);
},
destroyed() {
ARRAY = ARRAY.filter((item) => item !== this);
},
methods: {
open(position) {
const { leftWidth, rightWidth } = this.data;
const offset = position === 'left' ? leftWidth : -rightWidth;
this.swipeMove(offset);
this.$emit('open', {
position,
name: this.data.name,
});
},
close() {
this.swipeMove(0);
},
swipeMove(offset = 0) {
this.offset = range(offset, -this.data.rightWidth, this.data.leftWidth);
const transform = `translate3d(${this.offset}px, 0, 0)`;
const transition = this.dragging
? 'none'
: 'transform .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
this.setData({
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);
}
this.setData({ catchMove: false });
},
startDrag(event) {
if (this.data.disabled) {
return;
}
this.startOffset = this.offset;
this.touchStart(event);
},
noop() { },
onDrag(event) {
if (this.data.disabled) {
return;
}
this.touchMove(event);
if (this.direction !== 'horizontal') {
return;
}
this.dragging = true;
ARRAY.filter((item) => item !== this && item.offset !== 0).forEach((item) => item.close());
this.setData({ catchMove: true });
this.swipeMove(this.startOffset + this.deltaX);
},
endDrag() {
if (this.data.disabled) {
return;
}
this.dragging = 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,
name: this.data.name,
});
}
else {
this.swipeMove(0);
}
},
},
});
<view
class="van-swipe-cell custom-class"
data-key="cell"
catchtap="onClick"
bindtouchstart="startDrag"
catchtouchmove="{{ catchMove ? 'noop' : '' }}"
capture-bind:touchmove="onDrag"
bindtouchend="endDrag"
bindtouchcancel="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{overflow:hidden;position:relative}.van-swipe-cell__left,.van-swipe-cell__right{height:100%;position:absolute;top:0}.van-swipe-cell__left{left:0;transform:translate3d(-100%,0,0)}.van-swipe-cell__right{right:0;transform:translate3d(100%,0,0)}
\ 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: '30',
},
activeValue: {
type: null,
value: true,
},
inactiveValue: {
type: null,
value: false,
},
},
methods: {
onClick() {
const { activeValue, inactiveValue, disabled, loading } = this.data;
if (disabled || loading) {
return;
}
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" />
<wxs src="./index.wxs" module="computed" />
<view
class="{{ utils.bem('switch', { on: checked === activeValue, disabled }) }} custom-class"
style="{{ computed.rootStyle({ size, checked, activeColor, inactiveColor, activeValue }) }}"
bind:tap="onClick"
>
<view class="van-switch__node node-class">
<van-loading
wx:if="{{ loading }}"
color="{{ computed.loadingColor({ checked, activeColor, inactiveColor, activeValue }) }}"
custom-class="van-switch__loading"
/>
</view>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
var currentColor = data.checked === data.activeValue ? data.activeColor : data.inactiveColor;
return style({
'font-size': addUnit(data.size),
'background-color': currentColor,
});
}
var BLUE = '#1989fa';
var GRAY_DARK = '#969799';
function loadingColor(data) {
return data.checked === data.activeValue
? data.activeColor || BLUE
: data.inactiveColor || GRAY_DARK;
}
module.exports = {
rootStyle: rootStyle,
loadingColor: loadingColor,
};
@import '../common/index.wxss';.van-switch{background-color:var(--switch-background-color,#fff);border:var(--switch-border,1px solid rgba(0,0,0,.1));border-radius:var(--switch-node-size,1em);box-sizing:initial;display:inline-block;height:var(--switch-height,1em);position:relative;transition:background-color var(--switch-transition-duration,.3s);width:var(--switch-width,2em)}.van-switch__node{background-color:var(--switch-node-background-color,#fff);border-radius:100%;box-shadow:var(--switch-node-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));height:var(--switch-node-size,1em);left:0;position:absolute;top:0;transition:var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05);width:var(--switch-node-size,1em);z-index:var(--switch-node-z-index,1)}.van-switch__loading{height:50%;left:25%;position:absolute!important;top:25%;width:50%}.van-switch--on{background-color:var(--switch-on-background-color,#1989fa)}.van-switch--on .van-switch__node{transform:translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)))}.van-switch--disabled{opacity:var(--switch-disabled-opacity,.4)}
\ No newline at end of file
import { useParent } from '../common/relation';
import { VantComponent } from '../common/component';
VantComponent({
relation: useParent('tabs'),
props: {
dot: {
type: Boolean,
observer: 'update',
},
info: {
type: null,
observer: 'update',
},
title: {
type: String,
observer: 'update',
},
disabled: {
type: Boolean,
observer: 'update',
},
titleStyle: {
type: String,
observer: 'update',
},
name: {
type: null,
value: '',
},
},
data: {
active: false,
},
methods: {
getComputedName() {
if (this.data.name !== '') {
return this.data.name;
}
return this.index;
},
updateRender(active, parent) {
const { data: parentData } = parent;
this.inited = this.inited || active;
this.setData({
active,
shouldRender: this.inited || !parentData.lazyRender,
shouldShow: active || parentData.animated,
});
},
update() {
if (this.parent) {
this.parent.updateTabs();
}
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ utils.bem('tab__pane', { active, inactive: !active }) }}"
style="{{ shouldShow ? '' : 'display: none;' }}"
>
<slot wx:if="{{ shouldRender }}" />
</view>
@import '../common/index.wxss';:host{box-sizing:border-box;flex-shrink:0;width:100%}.van-tab__pane{-webkit-overflow-scrolling:touch;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';
import { useParent } from '../common/relation';
VantComponent({
props: {
info: null,
name: null,
icon: String,
dot: Boolean,
iconPrefix: {
type: String,
value: 'van-icon',
},
},
relation: useParent('tabbar'),
data: {
active: false,
activeColor: '',
inactiveColor: '',
},
methods: {
onClick() {
const { parent } = this;
if (parent) {
const index = parent.children.indexOf(this);
const active = this.data.name || index;
if (active !== this.data.active) {
parent.$emit('change', active);
}
}
this.$emit('click');
},
updateFromParent() {
const { parent } = this;
if (!parent) {
return;
}
const index = parent.children.indexOf(this);
const parentData = parent.data;
const { data } = this;
const active = (data.name || index) === parentData.active;
const patch = {};
if (active !== data.active) {
patch.active = active;
}
if (parentData.activeColor !== data.activeColor) {
patch.activeColor = parentData.activeColor;
}
if (parentData.inactiveColor !== data.inactiveColor) {
patch.inactiveColor = parentData.inactiveColor;
}
if (Object.keys(patch).length > 0) {
this.setData(patch);
}
},
},
});
{
"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="color: {{ active ? activeColor : inactiveColor }}"
bindtap="onClick"
>
<view class="van-tabbar-item__icon">
<van-icon
wx:if="{{ icon }}"
name="{{ icon }}"
class-prefix="{{ iconPrefix }}"
custom-class="van-tabbar-item__icon__inner"
/>
<block wx:else>
<slot wx:if="{{ active }}" name="icon-active" />
<slot wx:else name="icon" />
</block>
<van-info
dot="{{ dot }}"
info="{{ info }}"
custom-class="van-tabbar-item__info"
/>
</view>
<view class="van-tabbar-item__text">
<slot />
</view>
</view>
@import '../common/index.wxss';:host{flex:1}.van-tabbar-item{align-items:center;color:var(--tabbar-item-text-color,#646566);display:flex;flex-direction:column;font-size:var(--tabbar-item-font-size,12px);height:100%;justify-content:center;line-height:var(--tabbar-item-line-height,1)}.van-tabbar-item__icon{font-size:var(--tabbar-item-icon-size,22px);margin-bottom:var(--tabbar-item-margin-bottom,4px);position:relative}.van-tabbar-item__icon__inner{display:block;min-width:1em}.van-tabbar-item--active{color:var(--tabbar-item-active-color,#1989fa)}.van-tabbar-item__info{margin-top:2px}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
import { getRect } from '../common/utils';
VantComponent({
relation: useChildren('tabbar-item', function () {
this.updateChildren();
}),
props: {
active: {
type: null,
observer: 'updateChildren',
},
activeColor: {
type: String,
observer: 'updateChildren',
},
inactiveColor: {
type: String,
observer: 'updateChildren',
},
fixed: {
type: Boolean,
value: true,
observer: 'setHeight',
},
placeholder: {
type: Boolean,
observer: 'setHeight',
},
border: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 1,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
data: {
height: 50,
},
methods: {
updateChildren() {
const { children } = this;
if (!Array.isArray(children) || !children.length) {
return;
}
children.forEach((child) => child.updateFromParent());
},
setHeight() {
if (!this.data.fixed || !this.data.placeholder) {
return;
}
wx.nextTick(() => {
getRect(this, '.van-tabbar').then((res) => {
this.setData({ height: res.height });
});
});
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="{{ border ? 'van-hairline--top-bottom' : '' }} {{ utils.bem('tabbar', { fixed, safe: safeAreaInsetBottom }) }} custom-class"
style="{{ zIndex ? 'z-index: ' + zIndex : '' }}"
>
<slot />
</view>
<view wx:if="{{ fixed && placeholder }}" style="height: {{ height }}px;"></view>
@import '../common/index.wxss';.van-tabbar{background-color:var(--tabbar-background-color,#fff);box-sizing:initial;display:flex;height:var(--tabbar-height,50px);width:100%}.van-tabbar--fixed{bottom:0;left:0;position:fixed}.van-tabbar--safe{padding-bottom:env(safe-area-inset-bottom)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
import { getAllRect, getRect, groupSetData, nextTick, requestAnimationFrame, } from '../common/utils';
import { isDef } from '../common/validator';
import { useChildren } from '../common/relation';
VantComponent({
mixins: [touch],
classes: ['nav-class', 'tab-class', 'tab-active-class', 'line-class'],
relation: useChildren('tab', function () {
this.updateTabs();
}),
props: {
sticky: Boolean,
border: Boolean,
swipeable: Boolean,
titleActiveColor: String,
titleInactiveColor: String,
color: String,
animated: {
type: Boolean,
observer() {
this.children.forEach((child, index) => child.updateRender(index === this.data.currentIndex, this));
},
},
lineWidth: {
type: null,
value: 40,
observer: 'resize',
},
lineHeight: {
type: null,
value: -1,
},
active: {
type: null,
value: 0,
observer(name) {
if (name !== this.getCurrentName()) {
this.setCurrentIndexByName(name);
}
},
},
type: {
type: String,
value: 'line',
},
ellipsis: {
type: Boolean,
value: true,
},
duration: {
type: Number,
value: 0.3,
},
zIndex: {
type: Number,
value: 1,
},
swipeThreshold: {
type: Number,
value: 5,
observer(value) {
this.setData({
scrollable: this.children.length > value || !this.data.ellipsis,
});
},
},
offsetTop: {
type: Number,
value: 0,
},
lazyRender: {
type: Boolean,
value: true,
},
},
data: {
tabs: [],
scrollLeft: 0,
scrollable: false,
currentIndex: 0,
container: null,
skipTransition: true,
scrollWithAnimation: false,
lineOffsetLeft: 0,
},
mounted() {
requestAnimationFrame(() => {
this.swiping = true;
this.setData({
container: () => this.createSelectorQuery().select('.van-tabs'),
});
this.resize();
this.scrollIntoView();
});
},
methods: {
updateTabs() {
const { children = [], data } = this;
this.setData({
tabs: children.map((child) => child.data),
scrollable: this.children.length > data.swipeThreshold || !data.ellipsis,
});
this.setCurrentIndexByName(data.active || this.getCurrentName());
},
trigger(eventName, child) {
const { currentIndex } = this.data;
const currentChild = child || this.children[currentIndex];
if (!isDef(currentChild)) {
return;
}
this.$emit(eventName, {
index: currentChild.index,
name: currentChild.getComputedName(),
title: currentChild.data.title,
});
},
onTap(event) {
const { index } = event.currentTarget.dataset;
const child = this.children[index];
if (child.data.disabled) {
this.trigger('disabled', child);
}
else {
this.setCurrentIndex(index);
nextTick(() => {
this.trigger('click');
});
}
},
// correct the index of active tab
setCurrentIndexByName(name) {
const { children = [] } = this;
const matched = children.filter((child) => child.getComputedName() === name);
if (matched.length) {
this.setCurrentIndex(matched[0].index);
}
},
setCurrentIndex(currentIndex) {
const { data, children = [] } = this;
if (!isDef(currentIndex) ||
currentIndex >= children.length ||
currentIndex < 0) {
return;
}
groupSetData(this, () => {
children.forEach((item, index) => {
const active = index === currentIndex;
if (active !== item.data.active || !item.inited) {
item.updateRender(active, this);
}
});
});
if (currentIndex === data.currentIndex) {
return;
}
const shouldEmitChange = data.currentIndex !== null;
this.setData({ currentIndex });
requestAnimationFrame(() => {
this.resize();
this.scrollIntoView();
});
nextTick(() => {
this.trigger('input');
if (shouldEmitChange) {
this.trigger('change');
}
});
},
getCurrentName() {
const activeTab = this.children[this.data.currentIndex];
if (activeTab) {
return activeTab.getComputedName();
}
},
resize() {
if (this.data.type !== 'line') {
return;
}
const { currentIndex, ellipsis, skipTransition } = this.data;
Promise.all([
getAllRect(this, '.van-tab'),
getRect(this, '.van-tabs__line'),
]).then(([rects = [], lineRect]) => {
const rect = rects[currentIndex];
if (rect == null) {
return;
}
let lineOffsetLeft = rects
.slice(0, currentIndex)
.reduce((prev, curr) => prev + curr.width, 0);
lineOffsetLeft +=
(rect.width - lineRect.width) / 2 + (ellipsis ? 0 : 8);
this.setData({ lineOffsetLeft });
this.swiping = true;
if (skipTransition) {
nextTick(() => {
this.setData({ skipTransition: false });
});
}
});
},
// scroll active tab into view
scrollIntoView() {
const { currentIndex, scrollable, scrollWithAnimation } = this.data;
if (!scrollable) {
return;
}
Promise.all([
getAllRect(this, '.van-tab'),
getRect(this, '.van-tabs__nav'),
]).then(([tabRects, navRect]) => {
const tabRect = tabRects[currentIndex];
const offsetLeft = tabRects
.slice(0, currentIndex)
.reduce((prev, curr) => prev + curr.width, 0);
this.setData({
scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2,
});
if (!scrollWithAnimation) {
nextTick(() => {
this.setData({ scrollWithAnimation: true });
});
}
});
},
onTouchScroll(event) {
this.$emit('scroll', event.detail);
},
onTouchStart(event) {
if (!this.data.swipeable)
return;
this.swiping = true;
this.touchStart(event);
},
onTouchMove(event) {
if (!this.data.swipeable || !this.swiping)
return;
this.touchMove(event);
},
// watch swipe touch end
onTouchEnd() {
if (!this.data.swipeable || !this.swiping)
return;
const { direction, deltaX, offsetX } = this;
const minSwipeDistance = 50;
if (direction === 'horizontal' && offsetX >= minSwipeDistance) {
const index = this.getAvaiableTab(deltaX);
if (index !== -1) {
this.setCurrentIndex(index);
}
}
this.swiping = false;
},
getAvaiableTab(direction) {
const { tabs, currentIndex } = this.data;
const step = direction > 0 ? -1 : 1;
for (let i = step; currentIndex + i < tabs.length && currentIndex + i >= 0; i += step) {
const index = currentIndex + i;
if (index >= 0 &&
index < tabs.length &&
tabs[index] &&
!tabs[index].disabled) {
return index;
}
}
return -1;
},
},
});
{
"component": true,
"usingComponents": {
"van-info": "../info/index",
"van-sticky": "../sticky/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="custom-class {{ utils.bem('tabs', [type]) }}">
<van-sticky
disabled="{{ !sticky }}"
z-index="{{ zIndex }}"
offset-top="{{ offsetTop }}"
container="{{ container }}"
bind:scroll="onTouchScroll"
>
<view 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="{{ scrollWithAnimation }}"
scroll-left="{{ scrollLeft }}"
class="{{ utils.bem('tabs__scroll', [type]) }}"
style="{{ color ? 'border-color: ' + color : '' }}"
>
<view class="{{ utils.bem('tabs__nav', [type, { complete: !ellipsis }]) }} nav-class" style="{{ computed.navStyle(color, type) }}">
<view wx:if="{{ type === 'line' }}" class="van-tabs__line" style="{{ computed.lineStyle({ color, lineOffsetLeft, lineHeight, skipTransition, duration, lineWidth }) }}" />
<view
wx:for="{{ tabs }}"
wx:key="index"
data-index="{{ index }}"
class="{{ computed.tabClass(index === currentIndex, ellipsis) }} {{ utils.bem('tab', { active: index === currentIndex, disabled: item.disabled, complete: !ellipsis }) }}"
style="{{ computed.tabStyle({ active: index === currentIndex, ellipsis, color, type, disabled: item.disabled, titleActiveColor, titleInactiveColor, swipeThreshold, scrollable }) }}"
bind:tap="onTap"
>
<view class="{{ ellipsis ? 'van-ellipsis' : '' }}" style="{{ item.titleStyle }}">
{{ item.title }}
<van-info
wx:if="{{ item.info !== null || item.dot }}"
info="{{ item.info }}"
dot="{{ item.dot }}"
custom-class="van-tab__title__info"
/>
</view>
</view>
</view>
</scroll-view>
<slot name="nav-right" />
</view>
</van-sticky>
<view
class="van-tabs__content"
bind:touchstart="onTouchStart"
bind:touchmove="onTouchMove"
bind:touchend="onTouchEnd"
bind:touchcancel="onTouchEnd"
>
<view
class="{{ utils.bem('tabs__track', [{ animated }]) }} van-tabs__track"
style="{{ computed.trackStyle({ duration, currentIndex, animated }) }}"
>
<slot />
</view>
</view>
</view>
/* eslint-disable */
var utils = require('../wxs/utils.wxs');
var style = require('../wxs/style.wxs');
function tabClass(active, ellipsis) {
var classes = ['tab-class'];
if (active) {
classes.push('tab-active-class');
}
if (ellipsis) {
classes.push('van-ellipsis');
}
return classes.join(' ');
}
function tabStyle(data) {
var titleColor = data.active
? data.titleActiveColor
: data.titleInactiveColor;
var ellipsis = data.scrollable && data.ellipsis;
// card theme color
if (data.type === 'card') {
return style({
'border-color': data.color,
'background-color': !data.disabled && data.active ? data.color : null,
color: titleColor || (!data.disabled && !data.active ? data.color : null),
'flex-basis': ellipsis ? 88 / data.swipeThreshold + '%' : null,
});
}
return style({
color: titleColor,
'flex-basis': ellipsis ? 88 / data.swipeThreshold + '%' : null,
});
}
function navStyle(color, type) {
return style({
'border-color': type === 'card' && color ? color : null,
});
}
function trackStyle(data) {
if (!data.animated) {
return '';
}
return style({
left: -100 * data.currentIndex + '%',
'transition-duration': data.duration + 's',
'-webkit-transition-duration': data.duration + 's',
});
}
function lineStyle(data) {
return style({
width: utils.addUnit(data.lineWidth),
transform: 'translateX(' + data.lineOffsetLeft + 'px)',
'-webkit-transform': 'translateX(' + data.lineOffsetLeft + 'px)',
'background-color': data.color,
height: data.lineHeight !== -1 ? utils.addUnit(data.lineHeight) : null,
'border-radius':
data.lineHeight !== -1 ? utils.addUnit(data.lineHeight) : null,
'transition-duration': !data.skipTransition ? data.duration + 's' : null,
'-webkit-transition-duration': !data.skipTransition
? data.duration + 's'
: null,
});
}
module.exports = {
tabClass: tabClass,
tabStyle: tabStyle,
trackStyle: trackStyle,
lineStyle: lineStyle,
navStyle: navStyle,
};
@import '../common/index.wxss';.van-tabs{-webkit-tap-highlight-color:transparent;position:relative}.van-tabs__wrap{display:flex;overflow:hidden}.van-tabs__wrap--scrollable .van-tab{flex:0 0 22%}.van-tabs__wrap--scrollable .van-tab--complete{flex:1 0 auto!important;padding:0 12px}.van-tabs__wrap--scrollable .van-tabs__nav--complete{padding-left:8px;padding-right:8px}.van-tabs__scroll{background-color:var(--tabs-nav-background-color,#fff)}.van-tabs__scroll--line{box-sizing:initial;height:calc(100% + 15px)}.van-tabs__scroll--card{border:1px solid var(--tabs-default-color,#ee0a24);border-radius:2px;box-sizing:border-box;margin:0 var(--padding-md,16px);width:calc(100% - var(--padding-md, 16px)*2)}.van-tabs__scroll::-webkit-scrollbar{display:none}.van-tabs__nav{display:flex;position:relative;-webkit-user-select:none;user-select:none}.van-tabs__nav--card{box-sizing:border-box;height:var(--tabs-card-height,30px)}.van-tabs__nav--card .van-tab{border-right:1px solid var(--tabs-default-color,#ee0a24);color:var(--tabs-default-color,#ee0a24);line-height:calc(var(--tabs-card-height, 30px) - 2px)}.van-tabs__nav--card .van-tab:last-child{border-right:none}.van-tabs__nav--card .van-tab.van-tab--active{background-color:var(--tabs-default-color,#ee0a24);color:#fff}.van-tabs__nav--card .van-tab--disabled{color:var(--tab-disabled-text-color,#c8c9cc)}.van-tabs__line{background-color:var(--tabs-bottom-bar-color,#ee0a24);border-radius:var(--tabs-bottom-bar-height,3px);bottom:0;height:var(--tabs-bottom-bar-height,3px);left:0;position:absolute;z-index:1}.van-tabs__track{height:100%;position:relative;width:100%}.van-tabs__track--animated{display:flex;transition-property:left}.van-tabs__content{overflow:hidden}.van-tabs--line .van-tabs__wrap{height:var(--tabs-line-height,44px)}.van-tabs--card .van-tabs__wrap{height:var(--tabs-card-height,30px)}.van-tab{box-sizing:border-box;color:var(--tab-text-color,#646566);cursor:pointer;flex:1;font-size:var(--tab-font-size,14px);line-height:var(--tabs-line-height,44px);min-width:0;padding:0 5px;position:relative;text-align:center}.van-tab--active{color:var(--tab-active-text-color,#323233);font-weight:var(--font-weight-bold,500)}.van-tab--disabled{color:var(--tab-disabled-text-color,#c8c9cc)}.van-tab__title__info{display:inline-block;position:relative!important;top:-1px!important;transform:translateX(0)!important}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
props: {
size: String,
mark: Boolean,
color: String,
plain: Boolean,
round: Boolean,
textColor: String,
type: {
type: String,
value: 'default',
},
closeable: Boolean,
},
methods: {
onClose() {
this.$emit('close');
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view
class="custom-class {{ utils.bem('tag', [type, size, { mark, plain, round }]) }}"
style="{{ computed.rootStyle({ plain, color, textColor }) }}"
>
<slot />
<van-icon
wx:if="{{ closeable }}"
name="cross"
custom-class="van-tag__close"
bind:click="onClose"
/>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
return style({
'background-color': data.plain ? '' : data.color,
color: data.textColor || data.plain ? data.textColor || data.color : '',
});
}
module.exports = {
rootStyle: rootStyle,
};
@import '../common/index.wxss';.van-tag{align-items:center;border-radius:var(--tag-border-radius,2px);color:var(--tag-text-color,#fff);display:inline-flex;font-size:var(--tag-font-size,12px);line-height:var(--tag-line-height,16px);padding:var(--tag-padding,0 4px);position:relative}.van-tag--default{background-color:var(--tag-default-color,#969799)}.van-tag--default.van-tag--plain{color:var(--tag-default-color,#969799)}.van-tag--danger{background-color:var(--tag-danger-color,#ee0a24)}.van-tag--danger.van-tag--plain{color:var(--tag-danger-color,#ee0a24)}.van-tag--primary{background-color:var(--tag-primary-color,#1989fa)}.van-tag--primary.van-tag--plain{color:var(--tag-primary-color,#1989fa)}.van-tag--success{background-color:var(--tag-success-color,#07c160)}.van-tag--success.van-tag--plain{color:var(--tag-success-color,#07c160)}.van-tag--warning{background-color:var(--tag-warning-color,#ff976a)}.van-tag--warning.van-tag--plain{color:var(--tag-warning-color,#ff976a)}.van-tag--plain{background-color:var(--tag-plain-background-color,#fff)}.van-tag--plain:before{border:1px solid;border-radius:inherit;bottom:0;content:"";left:0;pointer-events:none;position:absolute;right:0;top:0}.van-tag--medium{padding:var(--tag-medium-padding,2px 6px)}.van-tag--large{border-radius:var(--tag-large-border-radius,4px);font-size:var(--tag-large-font-size,14px);padding:var(--tag-large-padding,4px 8px)}.van-tag--mark{border-radius:0 var(--tag-round-border-radius,var(--tag-round-border-radius,999px)) var(--tag-round-border-radius,var(--tag-round-border-radius,999px)) 0}.van-tag--mark:after{content:"";display:block;width:2px}.van-tag--round{border-radius:var(--tag-round-border-radius,999px)}.van-tag__close{margin-left:2px;min-width:1em}
\ 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: {
// 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 }}"
z-index="{{ zIndex }}"
custom-style="{{ mask ? '' : 'background-color: transparent;' }}"
/>
<van-transition
show="{{ show }}"
custom-style="z-index: {{ zIndex }}"
custom-class="van-toast__container"
>
<view
class="van-toast van-toast--{{ (type === 'text' || type === 'html') ? 'text' : 'icon' }} van-toast--{{ position }}"
catch:touchmove="noop"
>
<!-- text only -->
<text wx:if="{{ type === 'text' }}">{{ message }}</text>
<!-- html only -->
<rich-text wx:elif="{{ type === 'html' }}" nodes="{{ message }}"></rich-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>
<slot />
</view>
</van-transition>
@import '../common/index.wxss';.van-toast{word-wrap:break-word;align-items:center;background-color:var(--toast-background-color,rgba(0,0,0,.7));border-radius:var(--toast-border-radius,8px);box-sizing:initial;color:var(--toast-text-color,#fff);display:flex;flex-direction:column;font-size:var(--toast-font-size,14px);justify-content:center;line-height:var(--toast-line-height,20px);white-space:pre-wrap}.van-toast__container{left:50%;max-width:var(--toast-max-width,70%);position:fixed;top:50%;transform:translate(-50%,-50%);width:-webkit-fit-content;width:fit-content}.van-toast--text{min-width:var(--toast-text-min-width,96px);padding:var(--toast-text-padding,8px 12px)}.van-toast--icon{min-height:var(--toast-default-min-height,88px);padding:var(--toast-default-padding,16px);width:var(--toast-default-width,88px)}.van-toast--icon .van-toast__icon{font-size:var(--toast-icon-size,36px)}.van-toast--icon .van-toast__text{padding-top:8px}.van-toast__loading{margin:10px 0}.van-toast--top{transform:translateY(-30vh)}.van-toast--bottom{transform:translateY(30vh)}
\ No newline at end of file
/// <reference types="miniprogram-api-typings" />
declare type ToastMessage = string | number;
interface ToastOptions {
show?: boolean;
type?: string;
mask?: boolean;
zIndex?: number;
context?: WechatMiniprogram.Component.TrivialInstance | WechatMiniprogram.Page.TrivialInstance;
position?: string;
duration?: number;
selector?: string;
forbidClick?: boolean;
loadingType?: string;
message?: ToastMessage;
onClose?: () => void;
}
declare function Toast(toastOptions: ToastOptions | ToastMessage): WechatMiniprogram.Component.TrivialInstance | undefined;
declare namespace Toast {
var loading: (options: ToastMessage | ToastOptions) => WechatMiniprogram.Component.TrivialInstance | undefined;
var success: (options: ToastMessage | ToastOptions) => WechatMiniprogram.Component.TrivialInstance | undefined;
var fail: (options: ToastMessage | ToastOptions) => WechatMiniprogram.Component.TrivialInstance | undefined;
var clear: () => void;
var setDefaultOptions: (options: ToastOptions) => void;
var resetDefaultOptions: () => void;
}
export default Toast;
import { isObj } from '../common/validator';
const defaultOptions = {
type: 'text',
mask: false,
message: '',
show: true,
zIndex: 1000,
duration: 2000,
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];
}
function Toast(toastOptions) {
const options = Object.assign(Object.assign({}, currentOptions), parseOptions(toastOptions));
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;
toast.clear = () => {
toast.setData({ show: false });
if (options.onClose) {
options.onClose();
}
};
queue.push(toast);
toast.setData(options);
clearTimeout(toast.timer);
if (options.duration != null && 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)));
Toast.loading = createMethod('loading');
Toast.success = createMethod('success');
Toast.fail = createMethod('fail');
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)],
});
<wxs src="./index.wxs" module="computed" />
<view
wx:if="{{ inited }}"
class="van-transition custom-class {{ classes }}"
style="{{ computed.rootStyle({ currentDuration, display, customStyle }) }}"
bind:transitionend="onTransitionEnd"
>
<slot />
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
return style([
{
'-webkit-transition-duration': data.currentDuration + 'ms',
'transition-duration': data.currentDuration + 'ms',
},
data.display ? null : 'display: none',
data.customStyle,
]);
}
module.exports = {
rootStyle: rootStyle,
};
@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,transform}.van-fade-up-enter,.van-fade-up-leave-to{opacity:0;transform:translate3d(0,100%,0)}.van-fade-down-enter,.van-fade-down-leave-to{opacity:0;transform:translate3d(0,-100%,0)}.van-fade-left-enter,.van-fade-left-leave-to{opacity:0;transform:translate3d(-100%,0,0)}.van-fade-right-enter,.van-fade-right-leave-to{opacity: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:transform}.van-slide-up-enter,.van-slide-up-leave-to{transform:translate3d(0,100%,0)}.van-slide-down-enter,.van-slide-down-leave-to{transform:translate3d(0,-100%,0)}.van-slide-left-enter,.van-slide-left-leave-to{transform:translate3d(-100%,0,0)}.van-slide-right-enter,.van-slide-right-leave-to{transform:translate3d(100%,0,0)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'main-item-class',
'content-item-class',
'main-active-class',
'content-active-class',
'main-disabled-class',
'content-disabled-class',
],
props: {
items: {
type: Array,
observer: 'updateSubItems',
},
activeId: null,
mainActiveIndex: {
type: Number,
value: 0,
observer: 'updateSubItems',
},
height: {
type: null,
value: 300,
},
max: {
type: Number,
value: Infinity,
},
selectedIcon: {
type: String,
value: 'success',
},
},
data: {
subItems: [],
},
methods: {
// 当一个子项被选择时
onSelectItem(event) {
const { item } = event.currentTarget.dataset;
const isArray = Array.isArray(this.data.activeId);
// 判断有没有超出右侧选择的最大数
const isOverMax = isArray && this.data.activeId.length >= this.data.max;
// 判断该项有没有被选中, 如果有被选中,则忽视是否超出的条件
const isSelected = isArray
? this.data.activeId.indexOf(item.id) > -1
: this.data.activeId === item.id;
if (!item.disabled && (!isOverMax || isSelected)) {
this.$emit('click-item', item);
}
},
// 当一个导航被点击时
onClickNav(event) {
const index = event.detail;
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.setData({ subItems: children });
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-sidebar": "../sidebar/index",
"van-sidebar-item": "../sidebar-item/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="wxs" />
<view
class="van-tree-select"
style="height: {{ utils.addUnit(height) }}"
>
<scroll-view scroll-y class="van-tree-select__nav">
<van-sidebar active-key="{{ mainActiveIndex }}" bind:change="onClickNav" custom-class="van-tree-select__nav__inner">
<van-sidebar-item
wx:for="{{ items }}"
wx:key="index"
custom-class="main-item-class"
active-class="main-active-class"
disabled-class="main-disabled-class"
badge="{{ item.badge }}"
dot="{{ item.dot }}"
title="{{ item.text }}"
disabled="{{ item.disabled }}"
/>
</van-sidebar>
</scroll-view>
<scroll-view scroll-y class="van-tree-select__content">
<slot name="content" />
<view
wx:for="{{ subItems }}"
wx:key="id"
class="van-ellipsis content-item-class {{ utils.bem('tree-select__item', { active: wxs.isActive(activeId, item.id), disabled: item.disabled }) }} {{ wxs.isActive(activeId, item.id) ? 'content-active-class' : '' }} {{ item.disabled ? 'content-disabled-class' : '' }}"
data-item="{{ item }}"
bind:tap="onSelectItem"
>
{{ item.text }}
<van-icon
wx:if="{{ wxs.isActive(activeId, item.id) }}"
name="{{ selectedIcon }}"
size="16px"
class="van-tree-select__selected"
/>
</view>
</scroll-view>
</view>
/* eslint-disable */
var array = require('../wxs/array.wxs');
function isActive (activeList, itemId) {
if (array.isArray(activeList)) {
return activeList.indexOf(itemId) > -1;
}
return activeList === itemId;
}
module.exports.isActive = isActive;
@import '../common/index.wxss';.van-tree-select{display:flex;font-size:var(--tree-select-font-size,14px);position:relative;-webkit-user-select:none;user-select:none}.van-tree-select__nav{--sidebar-padding:12px 8px 12px 12px;background-color:var(--tree-select-nav-background-color,#f7f8fa);flex:1}.van-tree-select__nav__inner{height:100%;width:100%!important}.van-tree-select__content{background-color:var(--tree-select-content-background-color,#fff);flex:2}.van-tree-select__item{font-weight:700;line-height:var(--tree-select-item-height,44px);padding:0 32px 0 var(--padding-md,16px);position:relative}.van-tree-select__item--active{color:var(--tree-select-item-active-color,#ee0a24)}.van-tree-select__item--disabled{color:var(--tree-select-item-disabled-color,#c8c9cc)}.van-tree-select__selected{position:absolute;right:var(--padding-md,16px);top:50%;transform:translateY(-50%)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { isImageFile, chooseFile, isVideoFile } from './utils';
import { chooseImageProps, chooseVideoProps } from './shared';
import { isBoolean, isPromise } from '../common/validator';
VantComponent({
props: Object.assign(Object.assign({ disabled: Boolean, multiple: Boolean, uploadText: String, useBeforeRead: Boolean, afterRead: null, beforeRead: null, previewSize: {
type: null,
value: 80,
}, name: {
type: null,
value: '',
}, accept: {
type: String,
value: 'image',
}, fileList: {
type: Array,
value: [],
observer: 'formatFileList',
}, maxSize: {
type: Number,
value: Number.MAX_VALUE,
}, maxCount: {
type: Number,
value: 100,
}, deletable: {
type: Boolean,
value: true,
}, showUpload: {
type: Boolean,
value: true,
}, previewImage: {
type: Boolean,
value: true,
}, previewFullImage: {
type: Boolean,
value: true,
}, imageFit: {
type: String,
value: 'scaleToFill',
}, uploadIcon: {
type: String,
value: 'photograph',
} }, chooseImageProps), chooseVideoProps),
data: {
lists: [],
isInCount: true,
},
methods: {
formatFileList() {
const { fileList = [], maxCount } = this.data;
const lists = fileList.map((item) => (Object.assign(Object.assign({}, item), { isImage: isImageFile(item), isVideo: isVideoFile(item), deletable: isBoolean(item.deletable) ? item.deletable : true })));
this.setData({ lists, isInCount: lists.length < maxCount });
},
getDetail(index) {
return {
name: this.data.name,
index: index == null ? this.data.fileList.length : index,
};
},
startUpload() {
const { maxCount, multiple, lists, disabled } = this.data;
if (disabled)
return;
chooseFile(Object.assign(Object.assign({}, this.data), { maxCount: maxCount - lists.length }))
.then((res) => {
this.onBeforeRead(multiple ? res : res[0]);
})
.catch((error) => {
this.$emit('error', error);
});
},
onBeforeRead(file) {
const { beforeRead, useBeforeRead } = this.data;
let res = true;
if (typeof beforeRead === 'function') {
res = beforeRead(file, this.getDetail());
}
if (useBeforeRead) {
res = new Promise((resolve, reject) => {
this.$emit('before-read', Object.assign(Object.assign({ file }, this.getDetail()), { callback: (ok) => {
ok ? resolve() : reject();
} }));
});
}
if (!res) {
return;
}
if (isPromise(res)) {
res.then((data) => this.onAfterRead(data || file));
}
else {
this.onAfterRead(file);
}
},
onAfterRead(file) {
const { maxSize, afterRead } = this.data;
const oversize = Array.isArray(file)
? file.some((item) => item.size > maxSize)
: file.size > maxSize;
if (oversize) {
this.$emit('oversize', Object.assign({ file }, this.getDetail()));
return;
}
if (typeof afterRead === 'function') {
afterRead(file, this.getDetail());
}
this.$emit('after-read', Object.assign({ file }, this.getDetail()));
},
deleteItem(event) {
const { index } = event.currentTarget.dataset;
this.$emit('delete', Object.assign(Object.assign({}, this.getDetail(index)), { file: this.data.fileList[index] }));
},
onPreviewImage(event) {
if (!this.data.previewFullImage)
return;
const { index } = event.currentTarget.dataset;
const { lists } = this.data;
const item = lists[index];
wx.previewImage({
urls: lists.filter((item) => isImageFile(item)).map((item) => item.url),
current: item.url,
fail() {
wx.showToast({ title: '预览图片失败', icon: 'none' });
},
});
},
onPreviewVideo(event) {
if (!this.data.previewFullImage)
return;
const { index } = event.currentTarget.dataset;
const { lists } = this.data;
wx.previewMedia({
sources: lists
.filter((item) => isVideoFile(item))
.map((item) => (Object.assign(Object.assign({}, item), { type: 'video' }))),
current: index,
fail() {
wx.showToast({ title: '预览视频失败', icon: 'none' });
},
});
},
onPreviewFile(event) {
const { index } = event.currentTarget.dataset;
wx.openDocument({
filePath: this.data.lists[index].url,
showMenu: true,
});
},
onClickPreview(event) {
const { index } = event.currentTarget.dataset;
const item = this.data.lists[index];
this.$emit('click-preview', Object.assign(Object.assign({}, item), this.getDetail(index)));
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="van-uploader">
<view class="van-uploader__wrapper">
<!-- 预览样式 -->
<view
wx:if="{{ previewImage }}"
wx:for="{{ lists }}"
wx:key="index"
class="van-uploader__preview"
data-index="{{ index }}"
bindtap="onClickPreview"
>
<image
wx:if="{{ item.isImage }}"
mode="{{ imageFit }}"
src="{{ item.thumb || item.url }}"
alt="{{ item.name || ('图片' + index) }}"
class="van-uploader__preview-image"
style="{{ computed.sizeStyle({ previewSize }) }}"
data-index="{{ index }}"
bindtap="onPreviewImage"
/>
<video
wx:elif="{{ item.isVideo }}"
src="{{ item.url }}"
title="{{ item.name || ('视频' + index) }}"
poster="{{ item.thumb }}"
autoplay="{{ item.autoplay }}"
class="van-uploader__preview-image"
style="{{ computed.sizeStyle({ previewSize }) }}"
data-index="{{ index }}"
bindtap="onPreviewVideo"
>
</video>
<view
wx:else
class="van-uploader__file"
style="{{ computed.sizeStyle({ previewSize }) }}"
data-index="{{ index }}"
bindtap="onPreviewFile"
>
<van-icon name="description" class="van-uploader__file-icon" />
<view class="van-uploader__file-name van-ellipsis">{{ item.name || item.url }}</view>
</view>
<view
wx:if="{{ item.status === 'uploading' || item.status === 'failed' }}"
class="van-uploader__mask"
>
<van-icon wx:if="{{ item.status === 'failed' }}" name="close" class="van-uploader__mask-icon" />
<van-loading wx:else custom-class="van-uploader__loading" />
<text wx:if="{{ item.message }}" class="van-uploader__mask-message">{{ item.message }}</text>
</view>
<view
wx:if="{{ deletable && item.deletable }}"
data-index="{{ index }}"
class="van-uploader__preview-delete"
catch:tap="deleteItem"
>
<van-icon name="cross" class="van-uploader__preview-delete-icon" />
</view>
</view>
<!-- 上传样式 -->
<block wx:if="{{ isInCount }}">
<view class="van-uploader__slot" bindtap="startUpload">
<slot />
</view>
<!-- 默认上传样式 -->
<view
wx:if="{{ showUpload }}"
class="van-uploader__upload {{ disabled ? 'van-uploader__upload--disabled': ''}}"
style="{{ computed.sizeStyle({ previewSize }) }}"
bindtap="startUpload"
>
<van-icon name="{{ uploadIcon }}" class="van-uploader__upload-icon" />
<text wx:if="{{ uploadText }}" class="van-uploader__upload-text">{{ uploadText }}</text>
</view>
</block>
</view>
</view>
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function sizeStyle(data) {
return "Array" === data.previewSize.constructor ? style({
width: addUnit(data.previewSize[0]),
height: addUnit(data.previewSize[1]),
}) : style({
width: addUnit(data.previewSize),
height: addUnit(data.previewSize),
});
}
module.exports = {
sizeStyle: sizeStyle,
};
@import '../common/index.wxss';.van-uploader{display:inline-block;position:relative}.van-uploader__wrapper{display:flex;flex-wrap:wrap}.van-uploader__slot:empty{display:none}.van-uploader__slot:not(:empty)+.van-uploader__upload{display:none!important}.van-uploader__upload{align-items:center;background-color:var(--uploader-upload-background-color,#f7f8fa);box-sizing:border-box;display:flex;flex-direction:column;height:var(--uploader-size,80px);justify-content:center;margin:0 8px 8px 0;position:relative;width:var(--uploader-size,80px)}.van-uploader__upload:active{background-color:var(--uploader-upload-active-color,#f2f3f5)}.van-uploader__upload-icon{color:var(--uploader-icon-color,#dcdee0);font-size:var(--uploader-icon-size,24px)}.van-uploader__upload-text{color:var(--uploader-text-color,#969799);font-size:var(--uploader-text-font-size,12px);margin-top:var(--padding-xs,8px)}.van-uploader__upload--disabled{opacity:var(--uploader-disabled-opacity,.5)}.van-uploader__preview{cursor:pointer;margin:0 8px 8px 0;position:relative}.van-uploader__preview-image{display:block;height:var(--uploader-size,80px);overflow:hidden;width:var(--uploader-size,80px)}.van-uploader__preview-delete,.van-uploader__preview-delete:after{height:var(--uploader-delete-icon-size,14px);position:absolute;right:0;top:0;width:var(--uploader-delete-icon-size,14px)}.van-uploader__preview-delete:after{background-color:var(--uploader-delete-background-color,rgba(0,0,0,.7));border-radius:0 0 0 12px;content:""}.van-uploader__preview-delete-icon{color:var(--uploader-delete-color,#fff);font-size:var(--uploader-delete-icon-size,14px);position:absolute;right:0;top:0;transform:scale(.7) translate(10%,-10%);z-index:1}.van-uploader__file{align-items:center;background-color:var(--uploader-file-background-color,#f7f8fa);display:flex;flex-direction:column;height:var(--uploader-size,80px);justify-content:center;width:var(--uploader-size,80px)}.van-uploader__file-icon{color:var(--uploader-file-icon-color,#646566);font-size:var(--uploader-file-icon-size,20px)}.van-uploader__file-name{box-sizing:border-box;color:var(--uploader-file-name-text-color,#646566);font-size:var(--uploader-file-name-font-size,12px);margin-top:var(--uploader-file-name-margin-top,8px);padding:var(--uploader-file-name-padding,0 4px);text-align:center;width:100%}.van-uploader__mask{align-items:center;background-color:var(--uploader-mask-background-color,rgba(50,50,51,.88));bottom:0;color:#fff;display:flex;flex-direction:column;justify-content:center;left:0;position:absolute;right:0;top:0}.van-uploader__mask-icon{font-size:var(--uploader-mask-icon-size,22px)}.van-uploader__mask-message{font-size:var(--uploader-mask-message-font-size,12px);line-height:var(--uploader-mask-message-line-height,14px);margin-top:6px;padding:0 var(--padding-base,4px)}.van-uploader__loading{color:var(--uploader-loading-icon-color,#fff)!important;height:var(--uploader-loading-icon-size,22px);width:var(--uploader-loading-icon-size,22px)}
\ No newline at end of file
export declare const chooseImageProps: {
sizeType: {
type: ArrayConstructor;
value: string[];
};
capture: {
type: ArrayConstructor;
value: string[];
};
};
export declare const chooseVideoProps: {
capture: {
type: ArrayConstructor;
value: string[];
};
compressed: {
type: BooleanConstructor;
value: boolean;
};
maxDuration: {
type: NumberConstructor;
value: number;
};
camera: {
type: StringConstructor;
value: string;
};
};
// props for choose image
export const chooseImageProps = {
sizeType: {
type: Array,
value: ['original', 'compressed'],
},
capture: {
type: Array,
value: ['album', 'camera'],
},
};
// props for choose video
export const chooseVideoProps = {
capture: {
type: Array,
value: ['album', 'camera'],
},
compressed: {
type: Boolean,
value: true,
},
maxDuration: {
type: Number,
value: 60,
},
camera: {
type: String,
value: 'back',
},
};
export interface File {
url: string;
size?: number;
name?: string;
type: string;
duration?: number;
time?: number;
isImage?: boolean;
isVideo?: boolean;
}
export declare function isImageFile(item: File): boolean;
export declare function isVideoFile(item: File): boolean;
export declare function chooseFile({ accept, multiple, capture, compressed, maxDuration, sizeType, camera, maxCount, }: {
accept: any;
multiple: any;
capture: any;
compressed: any;
maxDuration: any;
sizeType: any;
camera: any;
maxCount: any;
}): Promise<File | File[]>;
import { pickExclude } from '../common/utils';
import { isImageUrl, isVideoUrl } from '../common/validator';
export function isImageFile(item) {
if (item.isImage != null) {
return item.isImage;
}
if (item.type) {
return item.type === 'image';
}
if (item.url) {
return isImageUrl(item.url);
}
return false;
}
export function isVideoFile(item) {
if (item.isVideo != null) {
return item.isVideo;
}
if (item.type) {
return item.type === 'video';
}
if (item.url) {
return isVideoUrl(item.url);
}
return false;
}
function formatImage(res) {
return res.tempFiles.map((item) => (Object.assign(Object.assign({}, pickExclude(item, ['path'])), { type: 'image', url: item.path, thumb: item.path })));
}
function formatVideo(res) {
return [
Object.assign(Object.assign({}, pickExclude(res, ['tempFilePath', 'thumbTempFilePath', 'errMsg'])), { type: 'video', url: res.tempFilePath, thumb: res.thumbTempFilePath }),
];
}
function formatMedia(res) {
return res.tempFiles.map((item) => (Object.assign(Object.assign({}, pickExclude(item, ['fileType', 'thumbTempFilePath', 'tempFilePath'])), { type: res.type, url: item.tempFilePath, thumb: res.type === 'video' ? item.thumbTempFilePath : item.tempFilePath })));
}
function formatFile(res) {
return res.tempFiles.map((item) => (Object.assign(Object.assign({}, pickExclude(item, ['path'])), { url: item.path })));
}
export function chooseFile({ accept, multiple, capture, compressed, maxDuration, sizeType, camera, maxCount, }) {
return new Promise((resolve, reject) => {
switch (accept) {
case 'image':
wx.chooseImage({
count: multiple ? Math.min(maxCount, 9) : 1,
sourceType: capture,
sizeType,
success: (res) => resolve(formatImage(res)),
fail: reject,
});
break;
case 'media':
wx.chooseMedia({
count: multiple ? Math.min(maxCount, 9) : 1,
sourceType: capture,
maxDuration,
sizeType,
camera,
success: (res) => resolve(formatMedia(res)),
fail: reject,
});
break;
case 'video':
wx.chooseVideo({
sourceType: capture,
compressed,
maxDuration,
camera,
success: (res) => resolve(formatVideo(res)),
fail: reject,
});
break;
default:
wx.chooseMessageFile({
count: multiple ? maxCount : 1,
type: accept,
success: (res) => resolve(formatFile(res)),
fail: reject,
});
break;
}
});
}
/* eslint-disable */
var REGEXP = getRegExp('^-?\d+(\.\d+)?$');
function addUnit(value) {
if (value == null) {
return undefined;
}
return REGEXP.test('' + value) ? value + 'px' : value;
}
module.exports = addUnit;
function isArray(array) {
return array && array.constructor === 'Array';
}
module.exports.isArray = isArray;
/* eslint-disable */
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;
/**
* Simple memoize
* wxs doesn't support fn.apply, so this memoize only support up to 2 args
*/
/* eslint-disable */
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;
/* 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;
/* eslint-disable */
var object = require('./object.wxs');
var array = require('./array.wxs');
function kebabCase(word) {
var newWord = word
.replace(getRegExp("[A-Z]", 'g'), function (i) {
return '-' + i;
})
.toLowerCase()
return newWord;
}
function style(styles) {
if (array.isArray(styles)) {
return styles
.filter(function (item) {
return item != null && item !== '';
})
.map(function (item) {
return style(item);
})
.join(';');
}
if ('Object' === styles.constructor) {
return object
.keys(styles)
.filter(function (key) {
return styles[key] != null && styles[key] !== '';
})
.map(function (key) {
return [kebabCase(key), [styles[key]]].join(':');
})
.join(';');
}
return styles;
}
module.exports = style;
/* eslint-disable */
var bem = require('./bem.wxs');
var memoize = require('./memoize.wxs');
var addUnit = require('./add-unit.wxs');
module.exports = {
bem: memoize(bem),
memoize: memoize,
addUnit: addUnit
};
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-touch-fullscreen" content="yes">
<meta name="format-detection" content="telephone=no,address=no">
<meta name="apple-mobile-web-app-status-bar-style" content="white">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" >
<title></title>
<script>
!function(x){function w(){var v,u,t,tes,s=x.document,r=s.documentElement,a=r.getBoundingClientRect().width;if(!v&&!u){var n=!!x.navigator.appVersion.match(/AppleWebKit.*Mobile.*/);v=x.devicePixelRatio;tes=x.devicePixelRatio;v=n?v:1,u=1/v}if(a>=640){r.style.fontSize="40px"}else{if(a<=320){r.style.fontSize="20px"}else{r.style.fontSize=a/320*20+"px"}}}x.addEventListener("resize",function(){w()});w()}(window);
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
export default {
navigationBarTitleText: 'demo',
usingComponents: {
},
}
.red {
color: red;
}
<template>
<div class="red">{{ str }}</div>
</template>
<script setup>
import { ref } from "vue";
const str = ref('demo')
</script>
<script>
import "./index.less";
export default {
name: "demoPage",
};
</script>
export default {
navigationBarTitleText: 'demo',
usingComponents: {
},
}
.red {
color: red;
}
<!--
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-06-06 14:45:50
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-06 14:51:51
* @FilePath: /taro-vant-weapp/src/pages/foo/index.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div class="red">{{ str }}</div>
</template>
<script setup>
import { ref } from "vue";
const str = ref('foo')
</script>
<script>
import "./index.less";
export default {
name: "fooPage",
};
</script>
export default {
navigationBarTitleText: '首页',
usingComponents: {
},
}
<!--
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-27 15:57:59
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-06 19:18:14
* @FilePath: /taro-vant-weapp/src/pages/index/index.vue
* @Description:
-->
<template>
<!-- <van-tabs :active="active" bind:change="onChange">
<van-tab title="标签 1">内容 2</van-tab>
<van-tab title="标签 2">内容 2</van-tab>
<van-tab title="标签 3">内容 3</van-tab>
<van-tab title="标签 4">
<van-button type="primary" @click="goTo">主要按钮</van-button>
</van-tab>
</van-tabs> -->
<van-button type="primary" @click="goTo">主要按钮</van-button>
<van-image width="100" height="100" src="https://img.yzcdn.cn/vant/cat.jpeg" />
</template>
<script setup>
import Taro from '@tarojs/taro'
import { ref } from 'vue';
import request from '../../utils/request';
request.get('/srv/?a=kg_list')
.then(res => {
console.warn(res);
})
.catch(err => {
console.error(err);
})
// Taro.request({
// url: 'http://voice.onwall.cn/srv/?f=voice&a=kg_list', //仅为示例,并非真实的接口地址
// data: {
// },
// // header: {
// // 'content-type': 'application/json' // 默认值
// // },
// success: function (res) {
// console.log(res.data)
// }
// })
const active = ref(1);
const goTo = () => {
Taro.navigateTo({
url: '../demo/index?id=1'
})
}
</script>
<script>
import "./index.less";
export default {
name: "indexPage",
onReady() {
if (!Taro.canIUse("getUpdateManager")) {
Taro.showModal({
title: "提示",
content: "当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试",
showCancel: false,
});
return;
}
// https://developers.weixin.qq.com/miniprogram/dev/api/base/update/UpdateManager.html
const updateManager = Taro.getUpdateManager();
updateManager.onCheckForUpdate((res) => {
// 请求完新版本信息的回调
if (res.hasUpdate) {
updateManager.onUpdateReady(function () {
Taro.showModal({
title: "更新提示",
content: "新版本已经准备好,是否重启应用?",
success: function (res) {
if (res.confirm) {
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
updateManager.applyUpdate();
}
},
});
});
updateManager.onUpdateFailed(function () {
// 新版本下载失败
Taro.showModal({
title: "更新提示",
content: "新版本已上线,请删除当前小程序,重新搜索打开",
});
});
}
});
},
};
</script>
// https://pinia.esm.dev/introduction.html
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 }
},
// could also be defined as
// state: () => ({ count: 0 })
actions: {
increment() {
this.count++
},
},
})
// You can even use a function (similar to a component setup()) to define a Store for more advanced use cases:
// export const useCounterStore = defineStore('counter', () => {
// const count = ref(0)
//
// function increment() {
// count.value++
// }
//
// return {count, increment}
// })
\ No newline at end of file
/*
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-09-19 14:19:05
* @FilePath: /swx/src/utils/config.js
* @Description: 文件描述
*/
const BASE_URL = "http://voice.onwall.cn";
export default BASE_URL
/*
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-09-19 14:19:18
* @FilePath: /swx/src/utils/request.js
* @Description: 简单axios封装,后续按实际处理
*/
// import axios from 'axios'
import axios from 'axios-miniprogram';
// import Toast from '../components/vant-weapp/toast/toast';
// import { ProgressStart, ProgressEnd } from '@/components/axios-progress/progress';
// import store from '@/store'
// import { getToken } from '@/utils/auth'
import BASE_URL from './config';
// create an axios instance
const service = axios.create({
baseURL: BASE_URL, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout
})
service.defaults.params = {
f: 'voice',
};
// request interceptor
service.interceptors.request.use(
config => {
console.warn(config)
// console.warn(store)
return config
},
error => {
// do something with request error
console.error(error, 'err') // for debug
return Promise.reject(error)
}
)
// response interceptor
service.interceptors.response.use(
/**
* If you want to get http information such as headers or status
* Please return response => response
*/
/**
* Determine the request status by custom code
* Here is just an example
* You can also judge the status by HTTP Status Code
*/
response => {
// wx.hideLoading();
// const res = response.data
// // Toast.clear();
// // if the custom code is not 20000, it is judged as an error.
// if (res.code !== 100000) {
// // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
// if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// // to re-login
// // Toast.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
// // confirmButtonText: 'Re-Login',
// // cancelButtonText: 'Cancel',
// // type: 'warning'
// // }).then(() => {
// // // store.dispatch('user/resetToken').then(() => {
// // // location.reload()
// // // })
// // })
// } else {
// // Toast.fail({
// // message: res.message,
// // duration: 1.5 * 1000
// // })
// // Tips.error(res.message, false)
// }
// return Promise.reject(new Error(res.message || 'Error'))
// } else {
// return res
// }
return response
},
error => {
// Toast.clear();
console.error('err' + error) // for debug
// Toast.fail({
// message: error.message,
// duration: 1.5 * 1000
// })
return Promise.reject(error)
}
)
export default service
const vantComponentNames = [
"button",
"icon",
"loading",
"info",
"tab",
"tabs",
"sticky",
"field",
"cell",
"image",
"col",
"row",
"field",
"cell-group",
"toast",
"empty",
"overlay",
"popup",
"picker",
"picker-column",
"stepper",
"dialog",
"action-sheet",
"checkbox",
"transition",
];
module.exports = vantComponentNames;
This diff could not be displayed because it is too large.