hookehuyr

🎉 init: 项目初始化

Showing 485 changed files with 11484 additions and 0 deletions
1 +# http://editorconfig.org
2 +root = true
3 +
4 +[*]
5 +indent_style = space
6 +indent_size = 2
7 +charset = utf-8
8 +trim_trailing_whitespace = true
9 +insert_final_newline = true
10 +
11 +[*.md]
12 +trim_trailing_whitespace = false
1 +// ESLint 检查 .vue 文件需要单独配置编辑器:
2 +// https://eslint.vuejs.org/user-guide/#editor-integrations
3 +{
4 + "extends": ["taro/vue3"]
5 +}
6 +
1 +dist/
2 +deploy_versions/
3 +.temp/
4 +.rn_temp/
5 +node_modules/
6 +.DS_Store
7 +doc
8 +.history
1 +// babel-preset-taro 更多选项和默认值:
2 +// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
3 +module.exports = {
4 + presets: [
5 + ['taro', {
6 + framework: 'vue3',
7 + ts: false
8 + }]
9 + ]
10 +}
1 +module.exports = {
2 + env: {
3 + NODE_ENV: '"development"',
4 + // 添加SERVICES_BASE_URL变量
5 + SERVICES_BASE_URL: '"http://xxx"',
6 + },
7 + defineConstants: {
8 + },
9 + mini: {},
10 + h5: {}
11 +}
1 +const path = require('path')
2 +const fs = require('fs')
3 +const vantComponentNames = require("../vantComponentConf")
4 +
5 +const handleGetPatterns = (keyArr) => {
6 + // 这些为公共组件
7 + const defaultArr = [
8 + {
9 + from: "src/components/vant-weapp/wxs",
10 + to: "dist/components/vant-weapp/wxs",
11 + },
12 + {
13 + from: "src/components/vant-weapp/common",
14 + to: "dist/components/vant-weapp/common",
15 + },
16 + ];
17 +
18 + const componentArr = keyArr
19 + .map((componentName) => {
20 + // 同步检测这个文件是否存在
21 + // 因为vant weapp部分组件文件下的不存在 wxs 文件
22 + const componentPath = path.resolve(
23 + __dirname,
24 + `../src/components/vant-weapp/${componentName}/index.wxs`
25 + );
26 +
27 + const isState = fs.statSync(componentPath, { throwIfNoEntry: false });
28 +
29 + return [
30 + {
31 + from: `src/components/vant-weapp/${componentName}/index.${isState ? "wxs" : "wxss"
32 + }`,
33 + to: `dist/components/vant-weapp/${componentName}/index.${isState ? "wxs" : "wxss"
34 + }`,
35 + },
36 + {
37 + from:
38 + "src/components/vant-weapp/" + componentName + "/index.wxml",
39 + to:
40 + "dist/components/vant-weapp/" + componentName + "/index.wxml",
41 + },
42 + ];
43 + })
44 + .flat(Infinity);
45 +
46 + return [...defaultArr, ...componentArr];
47 +};
48 +
49 +const config = {
50 + projectName: 'tswj-weapp',
51 + date: '2022-5-27',
52 + designWidth: 750,
53 + deviceRatio: {
54 + 640: 2.34 / 2,
55 + 750: 1,
56 + 828: 1.81 / 2
57 + },
58 + alias: {
59 + "@/utils": path.resolve(__dirname, "../src/utils"),
60 + "@/vant": path.resolve(__dirname, "../src/components/vant-weapp"),
61 + },
62 + sourceRoot: 'src',
63 + outputRoot: 'dist',
64 + // outputRoot: `dist/${process.env.TARO_ENV}`,
65 + plugins: [
66 + 'taro-plugin-pinia',
67 + "tarojs-plugin-platform-miniprogram", // 自定义 wxml 支持
68 + ['@tarojs/plugin-framework-vue3', {
69 + mini: {
70 + compilerOptions: {
71 + isCustomElement: tag => ["van-tab", "van-tabs"].includes(tag),
72 + whitespace: 'preserve'
73 + }
74 + }
75 + }],
76 + '@tarojs/plugin-html'
77 + ],
78 + defineConstants: {
79 + },
80 + copy: {
81 + patterns: handleGetPatterns(vantComponentNames),
82 + // patterns: [
83 + // // 前面2个是基础的
84 + // {
85 + // from: "src/components/vant-weapp/wxs",
86 + // to: "dist/components/vant-weapp/wxs",
87 + // },
88 + // {
89 + // from: "src/components/vant-weapp/common",
90 + // to: "dist/components/vant-weapp/common",
91 + // },
92 + // // 需要用到vant哪个组件就引入
93 + // {
94 + // from: "src/components/vant-weapp/button",
95 + // to: "dist/components/vant-weapp/button",
96 + // },
97 + // {
98 + // from: "src/components/vant-weapp/info",
99 + // to: "dist/components/vant-weapp/info",
100 + // },
101 + // {
102 + // from: "src/components/vant-weapp/icon",
103 + // to: "dist/components/vant-weapp/icon",
104 + // },
105 + // {
106 + // from: "src/components/vant-weapp/loading",
107 + // to: "dist/components/vant-weapp/loading",
108 + // },
109 + // {
110 + // from: "src/components/vant-weapp/tab",
111 + // to: "dist/components/vant-weapp/tab",
112 + // },
113 + // {
114 + // from: "src/components/vant-weapp/tabs",
115 + // to: "dist/components/vant-weapp/tabs",
116 + // },
117 + // {
118 + // from: "src/components/vant-weapp/sticky",
119 + // to: "dist/components/vant-weapp/sticky",
120 + // },
121 + // ],
122 + options: {
123 + }
124 + },
125 + framework: 'vue3',
126 + mini: {
127 + optimizeMainPackage: {
128 + enable: true
129 + },
130 + webpackChain(chain) {
131 + chain.merge({
132 + module: {
133 + rule: {
134 + mjsScript: {
135 + test: /\.mjs$/,
136 + include: [/pinia/],
137 + use: {
138 + babelLoader: {
139 + loader: require.resolve('babel-loader')
140 + }
141 + }
142 + }
143 + }
144 + }
145 + })
146 + },
147 + postcss: {
148 + pxtransform: {
149 + enable: true,
150 + config: {
151 + // 过滤 vant 组件库的前缀:van-
152 + selectorBlackList: [/van-/],
153 + }
154 + },
155 + url: {
156 + enable: true,
157 + config: {
158 + limit: 1024 // 设定转换尺寸上限
159 + }
160 + },
161 + cssModules: {
162 + enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
163 + config: {
164 + namingPattern: 'module', // 转换模式,取值为 global/module
165 + generateScopedName: '[name]__[local]___[hash:base64:5]'
166 + }
167 + }
168 + }
169 + },
170 + h5: {
171 + publicPath: '/',
172 + staticDirectory: 'static',
173 + postcss: {
174 + autoprefixer: {
175 + enable: true,
176 + config: {
177 + }
178 + },
179 + cssModules: {
180 + enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
181 + config: {
182 + namingPattern: 'module', // 转换模式,取值为 global/module
183 + generateScopedName: '[name]__[local]___[hash:base64:5]'
184 + }
185 + }
186 + }
187 + }
188 +}
189 +
190 +module.exports = function (merge) {
191 + if (process.env.NODE_ENV === 'development') {
192 + return merge({}, config, require('./dev'))
193 + }
194 + return merge({}, config, require('./prod'))
195 +}
1 +module.exports = {
2 + env: {
3 + NODE_ENV: '"production"',
4 + // 这里添加的 DEV_MODE_ENV 就起作用了,进行生产、开发区分,不用每次手动去改了
5 + SERVICES_BASE_URL:
6 + process.env.DEV_MODE_ENV === "true" ? "http://xxx" : "https://xxx",
7 + // 代码里访问`process.env.SERVICES_BASE_URL`是可以正常获取到的
8 + },
9 + defineConstants: {
10 + },
11 + mini: {},
12 + h5: {
13 + /**
14 + * 如果h5端编译后体积过大,可以使用webpack-bundle-analyzer插件对打包体积进行分析。
15 + * 参考代码如下:
16 + * webpackChain (chain) {
17 + * chain.plugin('analyzer')
18 + * .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, [])
19 + * }
20 + */
21 + }
22 +}
1 +{
2 + "name": "swx-weapp",
3 + "version": "1.0.0",
4 + "private": true,
5 + "description": "胜文轩小程序",
6 + "templateInfo": {
7 + "name": "vue3-pinia",
8 + "typescript": false,
9 + "css": "less"
10 + },
11 + "scripts": {
12 + "build:weapp": "cross-env DEV_MODE_ENV=false taro build --type weapp",
13 + "build:swan": "taro build --type swan",
14 + "build:alipay": "taro build --type alipay",
15 + "build:tt": "taro build --type tt",
16 + "build:h5": "taro build --type h5",
17 + "build:rn": "taro build --type rn",
18 + "build:qq": "taro build --type qq",
19 + "build:quickapp": "taro build --type quickapp",
20 + "dev:weapp": "cross-env NODE_ENV=production DEV_MODE_ENV=true taro build --type weapp --watch",
21 + "dev:swan": "npm run build:swan -- --watch",
22 + "dev:alipay": "npm run build:alipay -- --watch",
23 + "dev:tt": "npm run build:tt -- --watch",
24 + "dev:h5": "npm run build:h5 -- --watch",
25 + "dev:rn": "npm run build:rn -- --watch",
26 + "dev:qq": "npm run build:qq -- --watch",
27 + "dev:quickapp": "npm run build:quickapp -- --watch"
28 + },
29 + "browserslist": [
30 + "last 3 versions",
31 + "Android >= 4.1",
32 + "ios >= 8"
33 + ],
34 + "author": "",
35 + "license": "MIT",
36 + "dependencies": {
37 + "@babel/runtime": "^7.7.7",
38 + "@tarojs/components": "3.4.10",
39 + "@tarojs/plugin-framework-react": "^3.4.10",
40 + "@tarojs/plugin-framework-vue3": "3.4.10",
41 + "@tarojs/plugin-html": "^3.4.10",
42 + "@tarojs/plugin-platform-weapp": "^3.4.10",
43 + "@tarojs/runtime": "3.4.10",
44 + "@tarojs/taro": "3.4.10",
45 + "@vant/weapp": "^1.10.3",
46 + "axios": "^0.27.2",
47 + "axios-miniprogram": "^2.0.0-rc-2",
48 + "pinia": "^2.0.6",
49 + "taro-plugin-pinia": "^1.0.0",
50 + "vant": "^4.0.0-alpha.3",
51 + "vue": "^3.2.24"
52 + },
53 + "devDependencies": {
54 + "@babel/core": "^7.8.0",
55 + "@tarojs/mini-runner": "3.4.10",
56 + "@tarojs/webpack-runner": "3.4.10",
57 + "@types/webpack-env": "^1.13.6",
58 + "babel-preset-taro": "3.4.10",
59 + "cross-env": "^7.0.3",
60 + "eslint": "^8.12.0",
61 + "eslint-config-taro": "3.4.10",
62 + "eslint-plugin-vue": "^8.0.0",
63 + "stylelint": "9.3.0",
64 + "tarojs-plugin-platform-miniprogram": "^0.1.1",
65 + "vue-loader": "^16.8.3"
66 + }
67 +}
1 +{
2 + "miniprogramRoot": "./dist",
3 + "projectname": "swx-weapp",
4 + "description": "胜文轩小程序",
5 + "appid": "touristappid",
6 + "setting": {
7 + "urlCheck": true,
8 + "es6": false,
9 + "postcss": false,
10 + "minified": false,
11 + "checkSiteMap": false
12 + },
13 + "compileType": "miniprogram"
14 +}
1 +{
2 + "miniprogramRoot": "./",
3 + "projectname": "swx-weapp",
4 + "description": "胜文轩小程序",
5 + "appid": "touristappid",
6 + "setting": {
7 + "urlCheck": true,
8 + "es6": false,
9 + "postcss": false,
10 + "minified": false
11 + },
12 + "compileType": "miniprogram"
13 +}
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-27 15:57:59
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-06-06 14:47:04
6 + * @FilePath: /taro-vant-weapp/src/app.config.js
7 + * @Description:
8 + */
9 +const vantComponentNames = require("../vantComponentConf");
10 +
11 +const getVantComponentConf = (arr) => {
12 + const result = {};
13 + arr.forEach((key) => {
14 + result[`van-${key}`] = `./components/vant-weapp/${key}/index`;
15 + });
16 +
17 + return result;
18 +};
19 +
20 +export default {
21 + pages: [
22 + 'pages/index/index',
23 + 'pages/foo/index',
24 + ],
25 + subpackages: [ // 配置在tabBar中的页面不能分包写到subpackages中去
26 + {
27 + root: "pages/demo",
28 + pages: ["index"],
29 + },
30 + ],
31 + window: {
32 + backgroundTextStyle: 'light',
33 + navigationBarBackgroundColor: '#fff',
34 + navigationBarTitleText: 'WeChat',
35 + navigationBarTextStyle: 'black'
36 + },
37 + usingComponents: {
38 + ...getVantComponentConf(vantComponentNames),
39 + // "van-button": "./components/vant-weapp/button/index",
40 + // "van-tab": "./components/vant-weapp/tab/index",
41 + // "van-tabs": "./components/vant-weapp/tabs/index"
42 + },
43 +}
1 +/*
2 + * @Date: 2022-09-19 14:11:05
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-09-19 14:18:43
5 + * @FilePath: /swx/src/app.js
6 + * @Description: 文件描述
7 + */
8 +import { createApp } from 'vue'
9 +import { createPinia } from 'pinia'
10 +
11 +import './app.less'
12 +
13 +const App = createApp({
14 + // 可以使用所有的 Vue 生命周期方法
15 + mounted () {},
16 +
17 + // 对应 onLaunch
18 + onLaunch () {},
19 +
20 + // 对应 onShow
21 + onShow (options) {},
22 +
23 + // 对应 onHide
24 + onHide () {},
25 +
26 + // 入口组件不需要实现 render 方法,即使实现了也会被 taro 所覆盖
27 +})
28 +
29 +App.use(createPinia())
30 +
31 +export default App
File mode changed
1 +<template>
2 + <view>
3 + <text class="title">{{ counter.count }}</text>
4 + <view class="button" @tap="onAdd">ADD</view>
5 + </view>
6 +</template>
7 +
8 +<script>
9 +import { useCounterStore } from '../stores/counter'
10 +
11 +export default {
12 + setup() {
13 + const counter = useCounterStore()
14 +
15 + const onAdd = () => {
16 + counter.count++
17 +
18 + // with autocompletion ✨
19 + // counter.$patch({count: counter.count + 1})
20 +
21 + // or using an action instead
22 + // counter.increment()
23 + }
24 +
25 + return {
26 + counter,
27 + onAdd
28 + }
29 + }
30 +}
31 +</script>
32 +
33 +<style>
34 +.title {
35 + font-size: 32px;
36 +}
37 +.button {
38 + border: 1px solid lightgray;
39 + padding: 5px 10px;
40 +}
41 +</style>
1 +import { VantComponent } from '../common/component';
2 +import { button } from '../mixins/button';
3 +VantComponent({
4 + mixins: [button],
5 + props: {
6 + show: Boolean,
7 + title: String,
8 + cancelText: String,
9 + description: String,
10 + round: {
11 + type: Boolean,
12 + value: true,
13 + },
14 + zIndex: {
15 + type: Number,
16 + value: 100,
17 + },
18 + actions: {
19 + type: Array,
20 + value: [],
21 + },
22 + overlay: {
23 + type: Boolean,
24 + value: true,
25 + },
26 + closeOnClickOverlay: {
27 + type: Boolean,
28 + value: true,
29 + },
30 + closeOnClickAction: {
31 + type: Boolean,
32 + value: true,
33 + },
34 + safeAreaInsetBottom: {
35 + type: Boolean,
36 + value: true,
37 + },
38 + },
39 + methods: {
40 + onSelect(event) {
41 + const { index } = event.currentTarget.dataset;
42 + const { actions, closeOnClickAction, canIUseGetUserProfile } = this.data;
43 + const item = actions[index];
44 + if (item) {
45 + this.$emit('select', item);
46 + if (closeOnClickAction) {
47 + this.onClose();
48 + }
49 + if (item.openType === 'getUserInfo' && canIUseGetUserProfile) {
50 + wx.getUserProfile({
51 + desc: item.getUserProfileDesc || ' ',
52 + complete: (userProfile) => {
53 + this.$emit('getuserinfo', userProfile);
54 + },
55 + });
56 + }
57 + }
58 + },
59 + onCancel() {
60 + this.$emit('cancel');
61 + },
62 + onClose() {
63 + this.$emit('close');
64 + },
65 + onClickOverlay() {
66 + this.$emit('click-overlay');
67 + this.onClose();
68 + },
69 + },
70 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index",
5 + "van-popup": "../popup/index",
6 + "van-loading": "../loading/index"
7 + }
8 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<van-popup
4 + show="{{ show }}"
5 + position="bottom"
6 + round="{{ round }}"
7 + z-index="{{ zIndex }}"
8 + overlay="{{ overlay }}"
9 + custom-class="van-action-sheet"
10 + safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
11 + close-on-click-overlay="{{ closeOnClickOverlay }}"
12 + bind:close="onClickOverlay"
13 +>
14 + <view wx:if="{{ title }}" class="van-action-sheet__header">
15 + {{ title }}
16 + <van-icon
17 + name="cross"
18 + custom-class="van-action-sheet__close"
19 + bind:click="onClose"
20 + />
21 + </view>
22 + <view wx:if="{{ description }}" class="van-action-sheet__description van-hairline--bottom">
23 + {{ description }}
24 + </view>
25 + <view wx:if="{{ actions && actions.length }}">
26 + <!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
27 + <button
28 + wx:for="{{ actions }}"
29 + wx:key="index"
30 + open-type="{{ item.disabled || item.loading || (canIUseGetUserProfile && item.openType === 'getUserInfo') ? '' : item.openType }}"
31 + style="{{ item.color ? 'color: ' + item.color : '' }}"
32 + class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} {{ item.className || '' }}"
33 + hover-class="van-action-sheet__item--hover"
34 + data-index="{{ index }}"
35 + bindtap="{{ item.disabled || item.loading ? '' : 'onSelect' }}"
36 + bindgetuserinfo="onGetUserInfo"
37 + bindcontact="onContact"
38 + bindgetphonenumber="onGetPhoneNumber"
39 + binderror="onError"
40 + bindlaunchapp="onLaunchApp"
41 + bindopensetting="onOpenSetting"
42 + lang="{{ lang }}"
43 + session-from="{{ sessionFrom }}"
44 + send-message-title="{{ sendMessageTitle }}"
45 + send-message-path="{{ sendMessagePath }}"
46 + send-message-img="{{ sendMessageImg }}"
47 + show-message-card="{{ showMessageCard }}"
48 + app-parameter="{{ appParameter }}"
49 + >
50 + <block wx:if="{{ !item.loading }}">
51 + {{ item.name }}
52 + <view wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</view>
53 + </block>
54 + <van-loading wx:else custom-class="van-action-sheet__loading" size="22px" />
55 + </button>
56 + </view>
57 + <slot />
58 + <block wx:if="{{ cancelText }}">
59 + <view class="van-action-sheet__gap" />
60 + <view
61 + class="van-action-sheet__cancel"
62 + hover-class="van-action-sheet__cancel--hover"
63 + hover-stay-time="70"
64 + bind:tap="onCancel"
65 + >
66 + {{ cancelText }}
67 + </view>
68 + </block>
69 +</van-popup>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { pickerProps } from '../picker/shared';
3 +import { requestAnimationFrame } from '../common/utils';
4 +const EMPTY_CODE = '000000';
5 +VantComponent({
6 + classes: ['active-class', 'toolbar-class', 'column-class'],
7 + props: Object.assign(Object.assign({}, pickerProps), { showToolbar: {
8 + type: Boolean,
9 + value: true,
10 + }, value: {
11 + type: String,
12 + observer(value) {
13 + this.code = value;
14 + this.setValues();
15 + },
16 + }, areaList: {
17 + type: Object,
18 + value: {},
19 + observer: 'setValues',
20 + }, columnsNum: {
21 + type: null,
22 + value: 3,
23 + }, columnsPlaceholder: {
24 + type: Array,
25 + observer(val) {
26 + this.setData({
27 + typeToColumnsPlaceholder: {
28 + province: val[0] || '',
29 + city: val[1] || '',
30 + county: val[2] || '',
31 + },
32 + });
33 + },
34 + } }),
35 + data: {
36 + columns: [{ values: [] }, { values: [] }, { values: [] }],
37 + typeToColumnsPlaceholder: {},
38 + },
39 + mounted() {
40 + requestAnimationFrame(() => {
41 + this.setValues();
42 + });
43 + },
44 + methods: {
45 + getPicker() {
46 + if (this.picker == null) {
47 + this.picker = this.selectComponent('.van-area__picker');
48 + }
49 + return this.picker;
50 + },
51 + onCancel(event) {
52 + this.emit('cancel', event.detail);
53 + },
54 + onConfirm(event) {
55 + const { index } = event.detail;
56 + let { value } = event.detail;
57 + value = this.parseValues(value);
58 + this.emit('confirm', { value, index });
59 + },
60 + emit(type, detail) {
61 + detail.values = detail.value;
62 + delete detail.value;
63 + this.$emit(type, detail);
64 + },
65 + parseValues(values) {
66 + const { columnsPlaceholder } = this.data;
67 + return values.map((value, index) => {
68 + if (value &&
69 + (!value.code || value.name === columnsPlaceholder[index])) {
70 + return Object.assign(Object.assign({}, value), { code: '', name: '' });
71 + }
72 + return value;
73 + });
74 + },
75 + onChange(event) {
76 + var _a;
77 + const { index, picker, value } = event.detail;
78 + this.code = value[index].code;
79 + (_a = this.setValues()) === null || _a === void 0 ? void 0 : _a.then(() => {
80 + this.$emit('change', {
81 + picker,
82 + values: this.parseValues(picker.getValues()),
83 + index,
84 + });
85 + });
86 + },
87 + getConfig(type) {
88 + const { areaList } = this.data;
89 + return (areaList && areaList[`${type}_list`]) || {};
90 + },
91 + getList(type, code) {
92 + if (type !== 'province' && !code) {
93 + return [];
94 + }
95 + const { typeToColumnsPlaceholder } = this.data;
96 + const list = this.getConfig(type);
97 + let result = Object.keys(list).map((code) => ({
98 + code,
99 + name: list[code],
100 + }));
101 + if (code != null) {
102 + // oversea code
103 + if (code[0] === '9' && type === 'city') {
104 + code = '9';
105 + }
106 + result = result.filter((item) => item.code.indexOf(code) === 0);
107 + }
108 + if (typeToColumnsPlaceholder[type] && result.length) {
109 + // set columns placeholder
110 + const codeFill = type === 'province'
111 + ? ''
112 + : type === 'city'
113 + ? EMPTY_CODE.slice(2, 4)
114 + : EMPTY_CODE.slice(4, 6);
115 + result.unshift({
116 + code: `${code}${codeFill}`,
117 + name: typeToColumnsPlaceholder[type],
118 + });
119 + }
120 + return result;
121 + },
122 + getIndex(type, code) {
123 + let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
124 + const list = this.getList(type, code.slice(0, compareNum - 2));
125 + // oversea code
126 + if (code[0] === '9' && type === 'province') {
127 + compareNum = 1;
128 + }
129 + code = code.slice(0, compareNum);
130 + for (let i = 0; i < list.length; i++) {
131 + if (list[i].code.slice(0, compareNum) === code) {
132 + return i;
133 + }
134 + }
135 + return 0;
136 + },
137 + setValues() {
138 + const picker = this.getPicker();
139 + if (!picker) {
140 + return;
141 + }
142 + let code = this.code || this.getDefaultCode();
143 + const provinceList = this.getList('province');
144 + const cityList = this.getList('city', code.slice(0, 2));
145 + const stack = [];
146 + const indexes = [];
147 + const { columnsNum } = this.data;
148 + if (columnsNum >= 1) {
149 + stack.push(picker.setColumnValues(0, provinceList, false));
150 + indexes.push(this.getIndex('province', code));
151 + }
152 + if (columnsNum >= 2) {
153 + stack.push(picker.setColumnValues(1, cityList, false));
154 + indexes.push(this.getIndex('city', code));
155 + if (cityList.length && code.slice(2, 4) === '00') {
156 + [{ code }] = cityList;
157 + }
158 + }
159 + if (columnsNum === 3) {
160 + stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
161 + indexes.push(this.getIndex('county', code));
162 + }
163 + return Promise.all(stack)
164 + .catch(() => { })
165 + .then(() => picker.setIndexes(indexes))
166 + .catch(() => { });
167 + },
168 + getDefaultCode() {
169 + const { columnsPlaceholder } = this.data;
170 + if (columnsPlaceholder.length) {
171 + return EMPTY_CODE;
172 + }
173 + const countyCodes = Object.keys(this.getConfig('county'));
174 + if (countyCodes[0]) {
175 + return countyCodes[0];
176 + }
177 + const cityCodes = Object.keys(this.getConfig('city'));
178 + if (cityCodes[0]) {
179 + return cityCodes[0];
180 + }
181 + return '';
182 + },
183 + getValues() {
184 + const picker = this.getPicker();
185 + if (!picker) {
186 + return [];
187 + }
188 + return this.parseValues(picker.getValues().filter((value) => !!value));
189 + },
190 + getDetail() {
191 + const values = this.getValues();
192 + const area = {
193 + code: '',
194 + country: '',
195 + province: '',
196 + city: '',
197 + county: '',
198 + };
199 + if (!values.length) {
200 + return area;
201 + }
202 + const names = values.map((item) => item.name);
203 + area.code = values[values.length - 1].code;
204 + if (area.code[0] === '9') {
205 + area.country = names[1] || '';
206 + area.province = names[2] || '';
207 + }
208 + else {
209 + area.province = names[0] || '';
210 + area.city = names[1] || '';
211 + area.county = names[2] || '';
212 + }
213 + return area;
214 + },
215 + reset(code) {
216 + this.code = code || '';
217 + return this.setValues();
218 + },
219 + },
220 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-picker": "../picker/index"
5 + }
6 +}
1 +<wxs src="./index.wxs" module="computed" />
2 +
3 +<van-picker
4 + class="van-area__picker"
5 + active-class="active-class"
6 + toolbar-class="toolbar-class"
7 + column-class="column-class"
8 + show-toolbar="{{ showToolbar }}"
9 + value-key="name"
10 + title="{{ title }}"
11 + loading="{{ loading }}"
12 + columns="{{ computed.displayColumns(columns, columnsNum) }}"
13 + item-height="{{ itemHeight }}"
14 + visible-item-count="{{ visibleItemCount }}"
15 + cancel-button-text="{{ cancelButtonText }}"
16 + confirm-button-text="{{ confirmButtonText }}"
17 + bind:change="onChange"
18 + bind:confirm="onConfirm"
19 + bind:cancel="onCancel"
20 +/>
1 +/* eslint-disable */
2 +function displayColumns(columns, columnsNum) {
3 + return columns.slice(0, +columnsNum);
4 +}
5 +
6 +module.exports = {
7 + displayColumns: displayColumns,
8 +};
1 +@import '../common/index.wxss';
...\ No newline at end of file ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { button } from '../mixins/button';
3 +import { canIUseFormFieldButton } from '../common/version';
4 +const mixins = [button];
5 +if (canIUseFormFieldButton()) {
6 + mixins.push('wx://form-field-button');
7 +}
8 +VantComponent({
9 + mixins,
10 + classes: ['hover-class', 'loading-class'],
11 + data: {
12 + baseStyle: '',
13 + },
14 + props: {
15 + formType: String,
16 + icon: String,
17 + classPrefix: {
18 + type: String,
19 + value: 'van-icon',
20 + },
21 + plain: Boolean,
22 + block: Boolean,
23 + round: Boolean,
24 + square: Boolean,
25 + loading: Boolean,
26 + hairline: Boolean,
27 + disabled: Boolean,
28 + loadingText: String,
29 + customStyle: String,
30 + loadingType: {
31 + type: String,
32 + value: 'circular',
33 + },
34 + type: {
35 + type: String,
36 + value: 'default',
37 + },
38 + dataset: null,
39 + size: {
40 + type: String,
41 + value: 'normal',
42 + },
43 + loadingSize: {
44 + type: String,
45 + value: '20px',
46 + },
47 + color: String,
48 + },
49 + methods: {
50 + onClick(event) {
51 + this.$emit('click', event);
52 + const { canIUseGetUserProfile, openType, getUserProfileDesc, lang, } = this.data;
53 + if (openType === 'getUserInfo' && canIUseGetUserProfile) {
54 + wx.getUserProfile({
55 + desc: getUserProfileDesc || ' ',
56 + lang: lang || 'en',
57 + complete: (userProfile) => {
58 + this.$emit('getuserinfo', userProfile);
59 + },
60 + });
61 + }
62 + },
63 + },
64 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index",
5 + "van-loading": "../loading/index"
6 + }
7 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<button
5 + id="{{ id }}"
6 + data-detail="{{ dataset }}"
7 + class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
8 + hover-class="van-button--active hover-class"
9 + lang="{{ lang }}"
10 + form-type="{{ formType }}"
11 + style="{{ computed.rootStyle({ plain, color, customStyle }) }}"
12 + open-type="{{ disabled || loading || (canIUseGetUserProfile && openType === 'getUserInfo') ? '' : openType }}"
13 + business-id="{{ businessId }}"
14 + session-from="{{ sessionFrom }}"
15 + send-message-title="{{ sendMessageTitle }}"
16 + send-message-path="{{ sendMessagePath }}"
17 + send-message-img="{{ sendMessageImg }}"
18 + show-message-card="{{ showMessageCard }}"
19 + app-parameter="{{ appParameter }}"
20 + aria-label="{{ ariaLabel }}"
21 + bindtap="{{ disabled || loading ? '' : 'onClick' }}"
22 + bindgetuserinfo="onGetUserInfo"
23 + bindcontact="onContact"
24 + bindgetphonenumber="onGetPhoneNumber"
25 + binderror="onError"
26 + bindlaunchapp="onLaunchApp"
27 + bindopensetting="onOpenSetting"
28 +>
29 + <block wx:if="{{ loading }}">
30 + <van-loading
31 + custom-class="loading-class"
32 + size="{{ loadingSize }}"
33 + type="{{ loadingType }}"
34 + color="{{ computed.loadingColor({ type, color, plain }) }}"
35 + />
36 + <view wx:if="{{ loadingText }}" class="van-button__loading-text">
37 + {{ loadingText }}
38 + </view>
39 + </block>
40 + <block wx:else>
41 + <van-icon
42 + wx:if="{{ icon }}"
43 + size="1.2em"
44 + name="{{ icon }}"
45 + class-prefix="{{ classPrefix }}"
46 + class="van-button__icon"
47 + custom-style="line-height: inherit;"
48 + />
49 + <view class="van-button__text">
50 + <slot />
51 + </view>
52 + </block>
53 +</button>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +
4 +function rootStyle(data) {
5 + if (!data.color) {
6 + return data.customStyle;
7 + }
8 +
9 + var properties = {
10 + color: data.plain ? data.color : '#fff',
11 + background: data.plain ? null : data.color,
12 + };
13 +
14 + // hide border when color is linear-gradient
15 + if (data.color.indexOf('gradient') !== -1) {
16 + properties.border = 0;
17 + } else {
18 + properties['border-color'] = data.color;
19 + }
20 +
21 + return style([properties, data.customStyle]);
22 +}
23 +
24 +function loadingColor(data) {
25 + if (data.plain) {
26 + return data.color ? data.color : '#c9c9c9';
27 + }
28 +
29 + if (data.type === 'default') {
30 + return '#c9c9c9';
31 + }
32 +
33 + return '#fff';
34 +}
35 +
36 +module.exports = {
37 + rootStyle: rootStyle,
38 + loadingColor: loadingColor,
39 +};
1 +@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 ...\ No newline at end of file
1 +<view class="van-calendar">
2 + <header
3 + title="{{ title }}"
4 + showTitle="{{ showTitle }}"
5 + subtitle="{{ subtitle }}"
6 + showSubtitle="{{ showSubtitle }}"
7 + firstDayOfWeek="{{ firstDayOfWeek }}"
8 + bind:click-subtitle="onClickSubtitle"
9 + >
10 + <slot name="title" slot="title"></slot>
11 + </header>
12 +
13 + <scroll-view
14 + class="van-calendar__body"
15 + scroll-y
16 + scroll-into-view="{{ scrollIntoView }}"
17 + >
18 + <month
19 + wx:for="{{ computed.getMonths(minDate, maxDate) }}"
20 + wx:key="index"
21 + id="month{{ index }}"
22 + class="month"
23 + data-date="{{ item }}"
24 + date="{{ item }}"
25 + type="{{ type }}"
26 + color="{{ color }}"
27 + minDate="{{ minDate }}"
28 + maxDate="{{ maxDate }}"
29 + showMark="{{ showMark }}"
30 + formatter="{{ formatter }}"
31 + rowHeight="{{ rowHeight }}"
32 + currentDate="{{ currentDate }}"
33 + showSubtitle="{{ showSubtitle }}"
34 + allowSameDay="{{ allowSameDay }}"
35 + showMonthTitle="{{ index !== 0 || !showSubtitle }}"
36 + firstDayOfWeek="{{ firstDayOfWeek }}"
37 + bind:click="onClickDay"
38 + />
39 + </scroll-view>
40 +
41 + <view
42 + class="{{ utils.bem('calendar__footer', { safeAreaInsetBottom }) }}"
43 + >
44 + <slot name="footer"></slot>
45 + </view>
46 +
47 + <view
48 + class="{{ utils.bem('calendar__footer', { safeAreaInsetBottom }) }}"
49 + >
50 + <van-button
51 + wx:if="{{ showConfirm }}"
52 + round
53 + block
54 + type="danger"
55 + color="{{ color }}"
56 + custom-class="van-calendar__confirm"
57 + disabled="{{ computed.getButtonDisabled(type, currentDate) }}"
58 + nativeType="text"
59 + bind:click="onConfirm"
60 + >
61 + {{
62 + computed.getButtonDisabled(type, currentDate)
63 + ? confirmDisabledText
64 + : confirmText
65 + }}
66 + </van-button>
67 + </view>
68 +</view>
1 +import { VantComponent } from '../../../common/component';
2 +VantComponent({
3 + props: {
4 + title: {
5 + type: String,
6 + value: '日期选择',
7 + },
8 + subtitle: String,
9 + showTitle: Boolean,
10 + showSubtitle: Boolean,
11 + firstDayOfWeek: {
12 + type: Number,
13 + observer: 'initWeekDay',
14 + },
15 + },
16 + data: {
17 + weekdays: [],
18 + },
19 + created() {
20 + this.initWeekDay();
21 + },
22 + methods: {
23 + initWeekDay() {
24 + const defaultWeeks = ['日', '一', '二', '三', '四', '五', '六'];
25 + const firstDayOfWeek = this.data.firstDayOfWeek || 0;
26 + this.setData({
27 + weekdays: [
28 + ...defaultWeeks.slice(firstDayOfWeek, 7),
29 + ...defaultWeeks.slice(0, firstDayOfWeek),
30 + ],
31 + });
32 + },
33 + onClickSubtitle(event) {
34 + this.$emit('click-subtitle', event);
35 + },
36 + },
37 +});
1 +<view class="van-calendar__header">
2 + <block wx:if="{{ showTitle }}">
3 + <view class="van-calendar__header-title"><slot name="title"></slot></view>
4 + <view class="van-calendar__header-title">{{ title }}</view>
5 + </block>
6 +
7 + <view wx:if="{{ showSubtitle }}" class="van-calendar__header-subtitle" bind:tap="onClickSubtitle">
8 + {{ subtitle }}
9 + </view>
10 +
11 + <view class="van-calendar__weekdays">
12 + <view wx:for="{{ weekdays }}" wx:key="index" class="van-calendar__weekday">
13 + {{ item }}
14 + </view>
15 + </view>
16 +</view>
1 +@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 ...\ No newline at end of file
1 +export interface Day {
2 + date: Date;
3 + type: string;
4 + text: number;
5 + bottomInfo?: string;
6 +}
1 +import { VantComponent } from '../../../common/component';
2 +import { getMonthEndDay, compareDay, getPrevDay, getNextDay, } from '../../utils';
3 +VantComponent({
4 + props: {
5 + date: {
6 + type: null,
7 + observer: 'setDays',
8 + },
9 + type: {
10 + type: String,
11 + observer: 'setDays',
12 + },
13 + color: String,
14 + minDate: {
15 + type: null,
16 + observer: 'setDays',
17 + },
18 + maxDate: {
19 + type: null,
20 + observer: 'setDays',
21 + },
22 + showMark: Boolean,
23 + rowHeight: null,
24 + formatter: {
25 + type: null,
26 + observer: 'setDays',
27 + },
28 + currentDate: {
29 + type: null,
30 + observer: 'setDays',
31 + },
32 + firstDayOfWeek: {
33 + type: Number,
34 + observer: 'setDays',
35 + },
36 + allowSameDay: Boolean,
37 + showSubtitle: Boolean,
38 + showMonthTitle: Boolean,
39 + },
40 + data: {
41 + visible: true,
42 + days: [],
43 + },
44 + methods: {
45 + onClick(event) {
46 + const { index } = event.currentTarget.dataset;
47 + const item = this.data.days[index];
48 + if (item.type !== 'disabled') {
49 + this.$emit('click', item);
50 + }
51 + },
52 + setDays() {
53 + const days = [];
54 + const startDate = new Date(this.data.date);
55 + const year = startDate.getFullYear();
56 + const month = startDate.getMonth();
57 + const totalDay = getMonthEndDay(startDate.getFullYear(), startDate.getMonth() + 1);
58 + for (let day = 1; day <= totalDay; day++) {
59 + const date = new Date(year, month, day);
60 + const type = this.getDayType(date);
61 + let config = {
62 + date,
63 + type,
64 + text: day,
65 + bottomInfo: this.getBottomInfo(type),
66 + };
67 + if (this.data.formatter) {
68 + config = this.data.formatter(config);
69 + }
70 + days.push(config);
71 + }
72 + this.setData({ days });
73 + },
74 + getMultipleDayType(day) {
75 + const { currentDate } = this.data;
76 + if (!Array.isArray(currentDate)) {
77 + return '';
78 + }
79 + const isSelected = (date) => currentDate.some((item) => compareDay(item, date) === 0);
80 + if (isSelected(day)) {
81 + const prevDay = getPrevDay(day);
82 + const nextDay = getNextDay(day);
83 + const prevSelected = isSelected(prevDay);
84 + const nextSelected = isSelected(nextDay);
85 + if (prevSelected && nextSelected) {
86 + return 'multiple-middle';
87 + }
88 + if (prevSelected) {
89 + return 'end';
90 + }
91 + return nextSelected ? 'start' : 'multiple-selected';
92 + }
93 + return '';
94 + },
95 + getRangeDayType(day) {
96 + const { currentDate, allowSameDay } = this.data;
97 + if (!Array.isArray(currentDate)) {
98 + return '';
99 + }
100 + const [startDay, endDay] = currentDate;
101 + if (!startDay) {
102 + return '';
103 + }
104 + const compareToStart = compareDay(day, startDay);
105 + if (!endDay) {
106 + return compareToStart === 0 ? 'start' : '';
107 + }
108 + const compareToEnd = compareDay(day, endDay);
109 + if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) {
110 + return 'start-end';
111 + }
112 + if (compareToStart === 0) {
113 + return 'start';
114 + }
115 + if (compareToEnd === 0) {
116 + return 'end';
117 + }
118 + if (compareToStart > 0 && compareToEnd < 0) {
119 + return 'middle';
120 + }
121 + return '';
122 + },
123 + getDayType(day) {
124 + const { type, minDate, maxDate, currentDate } = this.data;
125 + if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
126 + return 'disabled';
127 + }
128 + if (type === 'single') {
129 + return compareDay(day, currentDate) === 0 ? 'selected' : '';
130 + }
131 + if (type === 'multiple') {
132 + return this.getMultipleDayType(day);
133 + }
134 + /* istanbul ignore else */
135 + if (type === 'range') {
136 + return this.getRangeDayType(day);
137 + }
138 + return '';
139 + },
140 + getBottomInfo(type) {
141 + if (this.data.type === 'range') {
142 + if (type === 'start') {
143 + return '开始';
144 + }
145 + if (type === 'end') {
146 + return '结束';
147 + }
148 + if (type === 'start-end') {
149 + return '开始/结束';
150 + }
151 + }
152 + },
153 + },
154 +});
1 +<wxs src="./index.wxs" module="computed"></wxs>
2 +<wxs src="../../../wxs/utils.wxs" module="utils" />
3 +
4 +<view class="van-calendar__month" style="{{ computed.getMonthStyle(visible, date, rowHeight) }}">
5 + <view wx:if="{{ showMonthTitle }}" class="van-calendar__month-title">
6 + {{ computed.formatMonthTitle(date) }}
7 + </view>
8 +
9 + <view wx:if="{{ visible }}" class="van-calendar__days">
10 + <view wx:if="{{ showMark }}" class="van-calendar__month-mark">
11 + {{ computed.getMark(date) }}
12 + </view>
13 +
14 + <view
15 + wx:for="{{ days }}"
16 + wx:key="index"
17 + style="{{ computed.getDayStyle(item.type, index, date, rowHeight, color, firstDayOfWeek) }}"
18 + class="{{ utils.bem('calendar__day', [item.type]) }} {{ item.className }}"
19 + data-index="{{ index }}"
20 + bindtap="onClick"
21 + >
22 + <view wx:if="{{ item.type === 'selected' }}" class="van-calendar__selected-day" style="width: {{ rowHeight }}px; height: {{ rowHeight }}px; background: {{ color }}">
23 + <view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
24 + {{ item.text }}
25 + <view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
26 + {{ item.bottomInfo }}
27 + </view>
28 + </view>
29 +
30 + <view wx:else>
31 + <view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
32 + {{ item.text }}
33 + <view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
34 + {{ item.bottomInfo }}
35 + </view>
36 + </view>
37 + </view>
38 + </view>
39 +</view>
1 +/* eslint-disable */
2 +var utils = require('../../utils.wxs');
3 +
4 +function getMark(date) {
5 + return getDate(date).getMonth() + 1;
6 +}
7 +
8 +var ROW_HEIGHT = 64;
9 +
10 +function getDayStyle(type, index, date, rowHeight, color, firstDayOfWeek) {
11 + var style = [];
12 + var current = getDate(date).getDay() || 7;
13 + var offset = current < firstDayOfWeek ? (7 - firstDayOfWeek + current) :
14 + current === 7 && firstDayOfWeek === 0 ? 0 :
15 + (current - firstDayOfWeek);
16 +
17 + if (index === 0) {
18 + style.push(['margin-left', (100 * offset) / 7 + '%']);
19 + }
20 +
21 + if (rowHeight !== ROW_HEIGHT) {
22 + style.push(['height', rowHeight + 'px']);
23 + }
24 +
25 + if (color) {
26 + if (
27 + type === 'start' ||
28 + type === 'end' ||
29 + type === 'start-end' ||
30 + type === 'multiple-selected' ||
31 + type === 'multiple-middle'
32 + ) {
33 + style.push(['background', color]);
34 + } else if (type === 'middle') {
35 + style.push(['color', color]);
36 + }
37 + }
38 +
39 + return style
40 + .map(function(item) {
41 + return item.join(':');
42 + })
43 + .join(';');
44 +}
45 +
46 +function formatMonthTitle(date) {
47 + date = getDate(date);
48 + return date.getFullYear() + '年' + (date.getMonth() + 1) + '月';
49 +}
50 +
51 +function getMonthStyle(visible, date, rowHeight) {
52 + if (!visible) {
53 + date = getDate(date);
54 +
55 + var totalDay = utils.getMonthEndDay(
56 + date.getFullYear(),
57 + date.getMonth() + 1
58 + );
59 + var offset = getDate(date).getDay();
60 + var padding = Math.ceil((totalDay + offset) / 7) * rowHeight;
61 +
62 + return 'padding-bottom:' + padding + 'px';
63 + }
64 +}
65 +
66 +module.exports = {
67 + getMark: getMark,
68 + getDayStyle: getDayStyle,
69 + formatMonthTitle: formatMonthTitle,
70 + getMonthStyle: getMonthStyle
71 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { ROW_HEIGHT, getPrevDay, getNextDay, getToday, compareDay, copyDates, calcDateNum, formatMonthTitle, compareMonth, getMonths, getDayByOffset, } from './utils';
3 +import Toast from '../toast/toast';
4 +import { requestAnimationFrame } from '../common/utils';
5 +const initialMinDate = getToday().getTime();
6 +const initialMaxDate = (() => {
7 + const now = getToday();
8 + return new Date(now.getFullYear(), now.getMonth() + 6, now.getDate()).getTime();
9 +})();
10 +const getTime = (date) => date instanceof Date ? date.getTime() : date;
11 +VantComponent({
12 + props: {
13 + title: {
14 + type: String,
15 + value: '日期选择',
16 + },
17 + color: String,
18 + show: {
19 + type: Boolean,
20 + observer(val) {
21 + if (val) {
22 + this.initRect();
23 + this.scrollIntoView();
24 + }
25 + },
26 + },
27 + formatter: null,
28 + confirmText: {
29 + type: String,
30 + value: '确定',
31 + },
32 + confirmDisabledText: {
33 + type: String,
34 + value: '确定',
35 + },
36 + rangePrompt: String,
37 + showRangePrompt: {
38 + type: Boolean,
39 + value: true,
40 + },
41 + defaultDate: {
42 + type: null,
43 + observer(val) {
44 + this.setData({ currentDate: val });
45 + this.scrollIntoView();
46 + },
47 + },
48 + allowSameDay: Boolean,
49 + type: {
50 + type: String,
51 + value: 'single',
52 + observer: 'reset',
53 + },
54 + minDate: {
55 + type: Number,
56 + value: initialMinDate,
57 + },
58 + maxDate: {
59 + type: Number,
60 + value: initialMaxDate,
61 + },
62 + position: {
63 + type: String,
64 + value: 'bottom',
65 + },
66 + rowHeight: {
67 + type: null,
68 + value: ROW_HEIGHT,
69 + },
70 + round: {
71 + type: Boolean,
72 + value: true,
73 + },
74 + poppable: {
75 + type: Boolean,
76 + value: true,
77 + },
78 + showMark: {
79 + type: Boolean,
80 + value: true,
81 + },
82 + showTitle: {
83 + type: Boolean,
84 + value: true,
85 + },
86 + showConfirm: {
87 + type: Boolean,
88 + value: true,
89 + },
90 + showSubtitle: {
91 + type: Boolean,
92 + value: true,
93 + },
94 + safeAreaInsetBottom: {
95 + type: Boolean,
96 + value: true,
97 + },
98 + closeOnClickOverlay: {
99 + type: Boolean,
100 + value: true,
101 + },
102 + maxRange: {
103 + type: null,
104 + value: null,
105 + },
106 + firstDayOfWeek: {
107 + type: Number,
108 + value: 0,
109 + },
110 + readonly: Boolean,
111 + },
112 + data: {
113 + subtitle: '',
114 + currentDate: null,
115 + scrollIntoView: '',
116 + },
117 + created() {
118 + this.setData({
119 + currentDate: this.getInitialDate(this.data.defaultDate),
120 + });
121 + },
122 + mounted() {
123 + if (this.data.show || !this.data.poppable) {
124 + this.initRect();
125 + this.scrollIntoView();
126 + }
127 + },
128 + methods: {
129 + reset() {
130 + this.setData({ currentDate: this.getInitialDate() });
131 + this.scrollIntoView();
132 + },
133 + initRect() {
134 + if (this.contentObserver != null) {
135 + this.contentObserver.disconnect();
136 + }
137 + const contentObserver = this.createIntersectionObserver({
138 + thresholds: [0, 0.1, 0.9, 1],
139 + observeAll: true,
140 + });
141 + this.contentObserver = contentObserver;
142 + contentObserver.relativeTo('.van-calendar__body');
143 + contentObserver.observe('.month', (res) => {
144 + if (res.boundingClientRect.top <= res.relativeRect.top) {
145 + // @ts-ignore
146 + this.setData({ subtitle: formatMonthTitle(res.dataset.date) });
147 + }
148 + });
149 + },
150 + limitDateRange(date, minDate = null, maxDate = null) {
151 + minDate = minDate || this.data.minDate;
152 + maxDate = maxDate || this.data.maxDate;
153 + if (compareDay(date, minDate) === -1) {
154 + return minDate;
155 + }
156 + if (compareDay(date, maxDate) === 1) {
157 + return maxDate;
158 + }
159 + return date;
160 + },
161 + getInitialDate(defaultDate = null) {
162 + const { type, minDate, maxDate } = this.data;
163 + const now = getToday().getTime();
164 + if (type === 'range') {
165 + if (!Array.isArray(defaultDate)) {
166 + defaultDate = [];
167 + }
168 + const [startDay, endDay] = defaultDate || [];
169 + const start = this.limitDateRange(startDay || now, minDate, getPrevDay(new Date(maxDate)).getTime());
170 + const end = this.limitDateRange(endDay || now, getNextDay(new Date(minDate)).getTime());
171 + return [start, end];
172 + }
173 + if (type === 'multiple') {
174 + if (Array.isArray(defaultDate)) {
175 + return defaultDate.map((date) => this.limitDateRange(date));
176 + }
177 + return [this.limitDateRange(now)];
178 + }
179 + if (!defaultDate || Array.isArray(defaultDate)) {
180 + defaultDate = now;
181 + }
182 + return this.limitDateRange(defaultDate);
183 + },
184 + scrollIntoView() {
185 + requestAnimationFrame(() => {
186 + const { currentDate, type, show, poppable, minDate, maxDate } = this.data;
187 + // @ts-ignore
188 + const targetDate = type === 'single' ? currentDate : currentDate[0];
189 + const displayed = show || !poppable;
190 + if (!targetDate || !displayed) {
191 + return;
192 + }
193 + const months = getMonths(minDate, maxDate);
194 + months.some((month, index) => {
195 + if (compareMonth(month, targetDate) === 0) {
196 + this.setData({ scrollIntoView: `month${index}` });
197 + return true;
198 + }
199 + return false;
200 + });
201 + });
202 + },
203 + onOpen() {
204 + this.$emit('open');
205 + },
206 + onOpened() {
207 + this.$emit('opened');
208 + },
209 + onClose() {
210 + this.$emit('close');
211 + },
212 + onClosed() {
213 + this.$emit('closed');
214 + },
215 + onClickDay(event) {
216 + if (this.data.readonly) {
217 + return;
218 + }
219 + let { date } = event.detail;
220 + const { type, currentDate, allowSameDay } = this.data;
221 + if (type === 'range') {
222 + // @ts-ignore
223 + const [startDay, endDay] = currentDate;
224 + if (startDay && !endDay) {
225 + const compareToStart = compareDay(date, startDay);
226 + if (compareToStart === 1) {
227 + const { days } = this.selectComponent('.month').data;
228 + days.some((day, index) => {
229 + const isDisabled = day.type === 'disabled' &&
230 + getTime(startDay) < getTime(day.date) &&
231 + getTime(day.date) < getTime(date);
232 + if (isDisabled) {
233 + ({ date } = days[index - 1]);
234 + }
235 + return isDisabled;
236 + });
237 + this.select([startDay, date], true);
238 + }
239 + else if (compareToStart === -1) {
240 + this.select([date, null]);
241 + }
242 + else if (allowSameDay) {
243 + this.select([date, date]);
244 + }
245 + }
246 + else {
247 + this.select([date, null]);
248 + }
249 + }
250 + else if (type === 'multiple') {
251 + let selectedIndex;
252 + // @ts-ignore
253 + const selected = currentDate.some((dateItem, index) => {
254 + const equal = compareDay(dateItem, date) === 0;
255 + if (equal) {
256 + selectedIndex = index;
257 + }
258 + return equal;
259 + });
260 + if (selected) {
261 + // @ts-ignore
262 + const cancelDate = currentDate.splice(selectedIndex, 1);
263 + this.setData({ currentDate });
264 + this.unselect(cancelDate);
265 + }
266 + else {
267 + // @ts-ignore
268 + this.select([...currentDate, date]);
269 + }
270 + }
271 + else {
272 + this.select(date, true);
273 + }
274 + },
275 + unselect(dateArray) {
276 + const date = dateArray[0];
277 + if (date) {
278 + this.$emit('unselect', copyDates(date));
279 + }
280 + },
281 + select(date, complete) {
282 + if (complete && this.data.type === 'range') {
283 + const valid = this.checkRange(date);
284 + if (!valid) {
285 + // auto selected to max range if showConfirm
286 + if (this.data.showConfirm) {
287 + this.emit([
288 + date[0],
289 + getDayByOffset(date[0], this.data.maxRange - 1),
290 + ]);
291 + }
292 + else {
293 + this.emit(date);
294 + }
295 + return;
296 + }
297 + }
298 + this.emit(date);
299 + if (complete && !this.data.showConfirm) {
300 + this.onConfirm();
301 + }
302 + },
303 + emit(date) {
304 + this.setData({
305 + currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date),
306 + });
307 + this.$emit('select', copyDates(date));
308 + },
309 + checkRange(date) {
310 + const { maxRange, rangePrompt, showRangePrompt } = this.data;
311 + if (maxRange && calcDateNum(date) > maxRange) {
312 + if (showRangePrompt) {
313 + Toast({
314 + context: this,
315 + message: rangePrompt || `选择天数不能超过 ${maxRange} 天`,
316 + });
317 + }
318 + this.$emit('over-range');
319 + return false;
320 + }
321 + return true;
322 + },
323 + onConfirm() {
324 + if (this.data.type === 'range' &&
325 + !this.checkRange(this.data.currentDate)) {
326 + return;
327 + }
328 + wx.nextTick(() => {
329 + // @ts-ignore
330 + this.$emit('confirm', copyDates(this.data.currentDate));
331 + });
332 + },
333 + onClickSubtitle(event) {
334 + this.$emit('click-subtitle', event);
335 + },
336 + },
337 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "header": "./components/header/index",
5 + "month": "./components/month/index",
6 + "van-button": "../button/index",
7 + "van-popup": "../popup/index",
8 + "van-toast": "../toast/index"
9 + }
10 +}
1 +<wxs src="./index.wxs" module="computed" />
2 +<wxs src="../wxs/utils.wxs" module="utils" />
3 +
4 +<import src="./calendar.wxml" />
5 +
6 +<van-popup
7 + wx:if="{{ poppable }}"
8 + custom-class="van-calendar__popup--{{ position }}"
9 + close-icon-class="van-calendar__close-icon"
10 + show="{{ show }}"
11 + round="{{ round }}"
12 + position="{{ position }}"
13 + closeable="{{ showTitle || showSubtitle }}"
14 + close-on-click-overlay="{{ closeOnClickOverlay }}"
15 + bind:enter="onOpen"
16 + bind:close="onClose"
17 + bind:after-enter="onOpened"
18 + bind:after-leave="onClosed"
19 +>
20 + <include src="./calendar.wxml" />
21 +</van-popup>
22 +
23 +<include wx:else src="./calendar.wxml" />
24 +
25 +<van-toast id="van-toast" />
1 +/* eslint-disable */
2 +var utils = require('./utils.wxs');
3 +
4 +function getMonths(minDate, maxDate) {
5 + var months = [];
6 + var cursor = getDate(minDate);
7 +
8 + cursor.setDate(1);
9 +
10 + do {
11 + months.push(cursor.getTime());
12 + cursor.setMonth(cursor.getMonth() + 1);
13 + } while (utils.compareMonth(cursor, getDate(maxDate)) !== 1);
14 +
15 + return months;
16 +}
17 +
18 +function getButtonDisabled(type, currentDate) {
19 + if (currentDate == null) {
20 + return true;
21 + }
22 +
23 + if (type === 'range') {
24 + return !currentDate[0] || !currentDate[1];
25 + }
26 +
27 + if (type === 'multiple') {
28 + return !currentDate.length;
29 + }
30 +
31 + return !currentDate;
32 +}
33 +
34 +module.exports = {
35 + getMonths: getMonths,
36 + getButtonDisabled: getButtonDisabled
37 +};
1 +@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 ...\ No newline at end of file
1 +export declare const ROW_HEIGHT = 64;
2 +export declare function formatMonthTitle(date: Date): string;
3 +export declare function compareMonth(date1: Date | number, date2: Date | number): 1 | -1 | 0;
4 +export declare function compareDay(day1: Date | number, day2: Date | number): 1 | -1 | 0;
5 +export declare function getDayByOffset(date: Date, offset: number): Date;
6 +export declare function getPrevDay(date: Date): Date;
7 +export declare function getNextDay(date: Date): Date;
8 +export declare function getToday(): Date;
9 +export declare function calcDateNum(date: [Date, Date]): number;
10 +export declare function copyDates(dates: Date | Date[]): Date | Date[];
11 +export declare function getMonthEndDay(year: number, month: number): number;
12 +export declare function getMonths(minDate: number, maxDate: number): number[];
1 +export const ROW_HEIGHT = 64;
2 +export function formatMonthTitle(date) {
3 + if (!(date instanceof Date)) {
4 + date = new Date(date);
5 + }
6 + return `${date.getFullYear()}${date.getMonth() + 1}月`;
7 +}
8 +export function compareMonth(date1, date2) {
9 + if (!(date1 instanceof Date)) {
10 + date1 = new Date(date1);
11 + }
12 + if (!(date2 instanceof Date)) {
13 + date2 = new Date(date2);
14 + }
15 + const year1 = date1.getFullYear();
16 + const year2 = date2.getFullYear();
17 + const month1 = date1.getMonth();
18 + const month2 = date2.getMonth();
19 + if (year1 === year2) {
20 + return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
21 + }
22 + return year1 > year2 ? 1 : -1;
23 +}
24 +export function compareDay(day1, day2) {
25 + if (!(day1 instanceof Date)) {
26 + day1 = new Date(day1);
27 + }
28 + if (!(day2 instanceof Date)) {
29 + day2 = new Date(day2);
30 + }
31 + const compareMonthResult = compareMonth(day1, day2);
32 + if (compareMonthResult === 0) {
33 + const date1 = day1.getDate();
34 + const date2 = day2.getDate();
35 + return date1 === date2 ? 0 : date1 > date2 ? 1 : -1;
36 + }
37 + return compareMonthResult;
38 +}
39 +export function getDayByOffset(date, offset) {
40 + date = new Date(date);
41 + date.setDate(date.getDate() + offset);
42 + return date;
43 +}
44 +export function getPrevDay(date) {
45 + return getDayByOffset(date, -1);
46 +}
47 +export function getNextDay(date) {
48 + return getDayByOffset(date, 1);
49 +}
50 +export function getToday() {
51 + const today = new Date();
52 + today.setHours(0, 0, 0, 0);
53 + return today;
54 +}
55 +export function calcDateNum(date) {
56 + const day1 = new Date(date[0]).getTime();
57 + const day2 = new Date(date[1]).getTime();
58 + return (day2 - day1) / (1000 * 60 * 60 * 24) + 1;
59 +}
60 +export function copyDates(dates) {
61 + if (Array.isArray(dates)) {
62 + return dates.map((date) => {
63 + if (date === null) {
64 + return date;
65 + }
66 + return new Date(date);
67 + });
68 + }
69 + return new Date(dates);
70 +}
71 +export function getMonthEndDay(year, month) {
72 + return 32 - new Date(year, month - 1, 32).getDate();
73 +}
74 +export function getMonths(minDate, maxDate) {
75 + const months = [];
76 + const cursor = new Date(minDate);
77 + cursor.setDate(1);
78 + do {
79 + months.push(cursor.getTime());
80 + cursor.setMonth(cursor.getMonth() + 1);
81 + } while (compareMonth(cursor, maxDate) !== 1);
82 + return months;
83 +}
1 +/* eslint-disable */
2 +function getMonthEndDay(year, month) {
3 + return 32 - getDate(year, month - 1, 32).getDate();
4 +}
5 +
6 +function compareMonth(date1, date2) {
7 + date1 = getDate(date1);
8 + date2 = getDate(date2);
9 +
10 + var year1 = date1.getFullYear();
11 + var year2 = date2.getFullYear();
12 + var month1 = date1.getMonth();
13 + var month2 = date2.getMonth();
14 +
15 + if (year1 === year2) {
16 + return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
17 + }
18 +
19 + return year1 > year2 ? 1 : -1;
20 +}
21 +
22 +module.exports = {
23 + getMonthEndDay: getMonthEndDay,
24 + compareMonth: compareMonth
25 +};
1 +import { link } from '../mixins/link';
2 +import { VantComponent } from '../common/component';
3 +VantComponent({
4 + classes: [
5 + 'num-class',
6 + 'desc-class',
7 + 'thumb-class',
8 + 'title-class',
9 + 'price-class',
10 + 'origin-price-class',
11 + ],
12 + mixins: [link],
13 + props: {
14 + tag: String,
15 + num: String,
16 + desc: String,
17 + thumb: String,
18 + title: String,
19 + price: {
20 + type: String,
21 + observer: 'updatePrice',
22 + },
23 + centered: Boolean,
24 + lazyLoad: Boolean,
25 + thumbLink: String,
26 + originPrice: String,
27 + thumbMode: {
28 + type: String,
29 + value: 'aspectFit',
30 + },
31 + currency: {
32 + type: String,
33 + value: '¥',
34 + },
35 + },
36 + methods: {
37 + updatePrice() {
38 + const { price } = this.data;
39 + const priceArr = price.toString().split('.');
40 + this.setData({
41 + integerStr: priceArr[0],
42 + decimalStr: priceArr[1] ? `.${priceArr[1]}` : '',
43 + });
44 + },
45 + onClickThumb() {
46 + this.jumpLink('thumbLink');
47 + },
48 + },
49 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-tag": "../tag/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view class="custom-class van-card">
4 + <view class="{{ utils.bem('card__header', { center: centered }) }}">
5 + <view class="van-card__thumb" bind:tap="onClickThumb">
6 + <image
7 + wx:if="{{ thumb }}"
8 + src="{{ thumb }}"
9 + mode="{{ thumbMode }}"
10 + lazy-load="{{ lazyLoad }}"
11 + class="van-card__img thumb-class"
12 + />
13 + <slot wx:else name="thumb" />
14 + <van-tag
15 + wx:if="{{ tag }}"
16 + mark
17 + type="danger"
18 + custom-class="van-card__tag"
19 + >
20 + {{ tag }}
21 + </van-tag>
22 + <slot wx:else name="tag" />
23 + </view>
24 +
25 + <view class="van-card__content {{ utils.bem('card__content', { center: centered }) }}">
26 + <view>
27 + <view wx:if="{{ title }}" class="van-card__title title-class">{{ title }}</view>
28 + <slot wx:else name="title" />
29 +
30 + <view wx:if="{{ desc }}" class="van-card__desc desc-class">{{ desc }}</view>
31 + <slot wx:else name="desc" />
32 +
33 + <slot name="tags" />
34 + </view>
35 +
36 + <view class="van-card__bottom">
37 + <slot name="price-top" />
38 + <view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">
39 + <text>{{ currency }}</text>
40 + <text class="van-card__price-integer">{{ integerStr }}</text>
41 + <text class="van-card__price-decimal">{{ decimalStr }}</text>
42 + </view>
43 + <slot wx:else name="price" />
44 + <view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
45 + <slot wx:else name="origin-price" />
46 + <view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
47 + <slot wx:else name="num" />
48 + <slot name="bottom" />
49 + </view>
50 + </view>
51 + </view>
52 +
53 + <view class="van-card__footer">
54 + <slot name="footer" />
55 + </view>
56 +</view>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + props: {
4 + title: String,
5 + border: {
6 + type: Boolean,
7 + value: true,
8 + },
9 + inset: Boolean,
10 + },
11 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view
4 + wx:if="{{ title }}"
5 + class="{{ utils.bem('cell-group__title', { inset }) }}"
6 +>
7 + {{ title }}
8 +</view>
9 +<view class="custom-class {{ utils.bem('cell-group', { inset }) }} {{ border ? 'van-hairline--top-bottom' : '' }}">
10 + <slot />
11 +</view>
1 +@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 ...\ No newline at end of file
1 +import { link } from '../mixins/link';
2 +import { VantComponent } from '../common/component';
3 +VantComponent({
4 + classes: [
5 + 'title-class',
6 + 'label-class',
7 + 'value-class',
8 + 'right-icon-class',
9 + 'hover-class',
10 + ],
11 + mixins: [link],
12 + props: {
13 + title: null,
14 + value: null,
15 + icon: String,
16 + size: String,
17 + label: String,
18 + center: Boolean,
19 + isLink: Boolean,
20 + required: Boolean,
21 + clickable: Boolean,
22 + titleWidth: String,
23 + customStyle: String,
24 + arrowDirection: String,
25 + useLabelSlot: Boolean,
26 + border: {
27 + type: Boolean,
28 + value: true,
29 + },
30 + titleStyle: String,
31 + },
32 + methods: {
33 + onClick(event) {
34 + this.$emit('click', event.detail);
35 + this.jumpLink();
36 + },
37 + },
38 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view
5 + class="custom-class {{ utils.bem('cell', [size, { center, required, borderless: !border, clickable: isLink || clickable }]) }}"
6 + hover-class="van-cell--hover hover-class"
7 + hover-stay-time="70"
8 + style="{{ customStyle }}"
9 + bind:tap="onClick"
10 +>
11 + <van-icon
12 + wx:if="{{ icon }}"
13 + name="{{ icon }}"
14 + class="van-cell__left-icon-wrap"
15 + custom-class="van-cell__left-icon"
16 + />
17 + <slot wx:else name="icon" />
18 +
19 + <view
20 + style="{{ computed.titleStyle({ titleWidth, titleStyle }) }}"
21 + class="van-cell__title title-class"
22 + >
23 +
24 + <block wx:if="{{ title }}">{{ title }}</block>
25 + <slot wx:else name="title" />
26 +
27 + <view wx:if="{{ label || useLabelSlot }}" class="van-cell__label label-class">
28 + <slot wx:if="{{ useLabelSlot }}" name="label" />
29 + <block wx:elif="{{ label }}">{{ label }}</block>
30 + </view>
31 + </view>
32 +
33 + <view class="van-cell__value value-class">
34 + <block wx:if="{{ value || value === 0 }}">{{ value }}</block>
35 + <slot wx:else />
36 + </view>
37 +
38 + <van-icon
39 + wx:if="{{ isLink }}"
40 + name="{{ arrowDirection ? 'arrow' + '-' + arrowDirection : 'arrow' }}"
41 + class="van-cell__right-icon-wrap right-icon-class"
42 + custom-class="van-cell__right-icon"
43 + />
44 + <slot wx:else name="right-icon" />
45 +
46 + <slot name="extra" />
47 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function titleStyle(data) {
6 + return style([
7 + {
8 + 'max-width': addUnit(data.titleWidth),
9 + 'min-width': addUnit(data.titleWidth),
10 + },
11 + data.titleStyle,
12 + ]);
13 +}
14 +
15 +module.exports = {
16 + titleStyle: titleStyle,
17 +};
1 +@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 ...\ No newline at end of file
1 +import { useChildren } from '../common/relation';
2 +import { VantComponent } from '../common/component';
3 +VantComponent({
4 + field: true,
5 + relation: useChildren('checkbox', function (target) {
6 + this.updateChild(target);
7 + }),
8 + props: {
9 + max: Number,
10 + value: {
11 + type: Array,
12 + observer: 'updateChildren',
13 + },
14 + disabled: {
15 + type: Boolean,
16 + observer: 'updateChildren',
17 + },
18 + direction: {
19 + type: String,
20 + value: 'vertical',
21 + },
22 + },
23 + methods: {
24 + updateChildren() {
25 + this.children.forEach((child) => this.updateChild(child));
26 + },
27 + updateChild(child) {
28 + const { value, disabled, direction } = this.data;
29 + child.setData({
30 + value: value.indexOf(child.data.name) !== -1,
31 + parentDisabled: disabled,
32 + direction,
33 + });
34 + },
35 + },
36 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view class="{{ utils.bem('checkbox-group', [{ horizontal: direction === 'horizontal' }]) }}">
4 + <slot />
5 +</view>
1 +@import '../common/index.wxss';.van-checkbox-group--horizontal{display:flex;flex-wrap:wrap}
...\ No newline at end of file ...\ No newline at end of file
1 +import { useParent } from '../common/relation';
2 +import { VantComponent } from '../common/component';
3 +function emit(target, value) {
4 + target.$emit('input', value);
5 + target.$emit('change', value);
6 +}
7 +VantComponent({
8 + field: true,
9 + relation: useParent('checkbox-group'),
10 + classes: ['icon-class', 'label-class'],
11 + props: {
12 + value: Boolean,
13 + disabled: Boolean,
14 + useIconSlot: Boolean,
15 + checkedColor: String,
16 + labelPosition: {
17 + type: String,
18 + value: 'right',
19 + },
20 + labelDisabled: Boolean,
21 + shape: {
22 + type: String,
23 + value: 'round',
24 + },
25 + iconSize: {
26 + type: null,
27 + value: 20,
28 + },
29 + },
30 + data: {
31 + parentDisabled: false,
32 + direction: 'vertical',
33 + },
34 + methods: {
35 + emitChange(value) {
36 + if (this.parent) {
37 + this.setParentValue(this.parent, value);
38 + }
39 + else {
40 + emit(this, value);
41 + }
42 + },
43 + toggle() {
44 + const { parentDisabled, disabled, value } = this.data;
45 + if (!disabled && !parentDisabled) {
46 + this.emitChange(!value);
47 + }
48 + },
49 + onClickLabel() {
50 + const { labelDisabled, parentDisabled, disabled, value } = this.data;
51 + if (!disabled && !labelDisabled && !parentDisabled) {
52 + this.emitChange(!value);
53 + }
54 + },
55 + setParentValue(parent, value) {
56 + const parentValue = parent.data.value.slice();
57 + const { name } = this.data;
58 + const { max } = parent.data;
59 + if (value) {
60 + if (max && parentValue.length >= max) {
61 + return;
62 + }
63 + if (parentValue.indexOf(name) === -1) {
64 + parentValue.push(name);
65 + emit(parent, parentValue);
66 + }
67 + }
68 + else {
69 + const index = parentValue.indexOf(name);
70 + if (index !== -1) {
71 + parentValue.splice(index, 1);
72 + emit(parent, parentValue);
73 + }
74 + }
75 + },
76 + },
77 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view class="{{ utils.bem('checkbox', [{ horizontal: direction === 'horizontal' }]) }} custom-class">
5 + <view
6 + wx:if="{{ labelPosition === 'left' }}"
7 + class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}"
8 + bindtap="onClickLabel"
9 + >
10 + <slot />
11 + </view>
12 + <view class="van-checkbox__icon-wrap" bindtap="toggle">
13 + <slot wx:if="{{ useIconSlot }}" name="icon" />
14 + <van-icon
15 + wx:else
16 + name="success"
17 + size="0.8em"
18 + class="{{ utils.bem('checkbox__icon', [shape, { disabled: disabled || parentDisabled, checked: value }]) }}"
19 + style="{{ computed.iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) }}"
20 + custom-class="icon-class"
21 + custom-style="line-height: 1.25em;"
22 + />
23 + </view>
24 + <view
25 + wx:if="{{ labelPosition === 'right' }}"
26 + class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}"
27 + bindtap="onClickLabel"
28 + >
29 + <slot />
30 + </view>
31 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) {
6 + var styles = {
7 + 'font-size': addUnit(iconSize),
8 + };
9 +
10 + if (checkedColor && value && !disabled && !parentDisabled) {
11 + styles['border-color'] = checkedColor;
12 + styles['background-color'] = checkedColor;
13 + }
14 +
15 + return style(styles);
16 +}
17 +
18 +module.exports = {
19 + iconStyle: iconStyle,
20 +};
1 +@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 ...\ No newline at end of file
1 +/// <reference types="miniprogram-api-typings" />
2 +declare type CanvasContext = WechatMiniprogram.CanvasContext;
3 +export declare function adaptor(ctx: CanvasContext & Record<string, unknown>): CanvasContext;
4 +export {};
1 +export function adaptor(ctx) {
2 + // @ts-ignore
3 + return Object.assign(ctx, {
4 + setStrokeStyle(val) {
5 + ctx.strokeStyle = val;
6 + },
7 + setLineWidth(val) {
8 + ctx.lineWidth = val;
9 + },
10 + setLineCap(val) {
11 + ctx.lineCap = val;
12 + },
13 + setFillStyle(val) {
14 + ctx.fillStyle = val;
15 + },
16 + setFontSize(val) {
17 + ctx.font = String(val);
18 + },
19 + setGlobalAlpha(val) {
20 + ctx.globalAlpha = val;
21 + },
22 + setLineJoin(val) {
23 + ctx.lineJoin = val;
24 + },
25 + setTextAlign(val) {
26 + ctx.textAlign = val;
27 + },
28 + setMiterLimit(val) {
29 + ctx.miterLimit = val;
30 + },
31 + setShadow(offsetX, offsetY, blur, color) {
32 + ctx.shadowOffsetX = offsetX;
33 + ctx.shadowOffsetY = offsetY;
34 + ctx.shadowBlur = blur;
35 + ctx.shadowColor = color;
36 + },
37 + setTextBaseline(val) {
38 + ctx.textBaseline = val;
39 + },
40 + createCircularGradient() { },
41 + draw() { },
42 + });
43 +}
1 +import { BLUE, WHITE } from '../common/color';
2 +import { VantComponent } from '../common/component';
3 +import { getSystemInfoSync } from '../common/utils';
4 +import { isObj } from '../common/validator';
5 +import { canIUseCanvas2d } from '../common/version';
6 +import { adaptor } from './canvas';
7 +function format(rate) {
8 + return Math.min(Math.max(rate, 0), 100);
9 +}
10 +const PERIMETER = 2 * Math.PI;
11 +const BEGIN_ANGLE = -Math.PI / 2;
12 +const STEP = 1;
13 +VantComponent({
14 + props: {
15 + text: String,
16 + lineCap: {
17 + type: String,
18 + value: 'round',
19 + },
20 + value: {
21 + type: Number,
22 + value: 0,
23 + observer: 'reRender',
24 + },
25 + speed: {
26 + type: Number,
27 + value: 50,
28 + },
29 + size: {
30 + type: Number,
31 + value: 100,
32 + observer() {
33 + this.drawCircle(this.currentValue);
34 + },
35 + },
36 + fill: String,
37 + layerColor: {
38 + type: String,
39 + value: WHITE,
40 + },
41 + color: {
42 + type: null,
43 + value: BLUE,
44 + observer() {
45 + this.setHoverColor().then(() => {
46 + this.drawCircle(this.currentValue);
47 + });
48 + },
49 + },
50 + type: {
51 + type: String,
52 + value: '',
53 + },
54 + strokeWidth: {
55 + type: Number,
56 + value: 4,
57 + },
58 + clockwise: {
59 + type: Boolean,
60 + value: true,
61 + },
62 + },
63 + data: {
64 + hoverColor: BLUE,
65 + },
66 + methods: {
67 + getContext() {
68 + const { type, size } = this.data;
69 + if (type === '' || !canIUseCanvas2d()) {
70 + const ctx = wx.createCanvasContext('van-circle', this);
71 + return Promise.resolve(ctx);
72 + }
73 + const dpr = getSystemInfoSync().pixelRatio;
74 + return new Promise((resolve) => {
75 + wx.createSelectorQuery()
76 + .in(this)
77 + .select('#van-circle')
78 + .node()
79 + .exec((res) => {
80 + const canvas = res[0].node;
81 + const ctx = canvas.getContext(type);
82 + if (!this.inited) {
83 + this.inited = true;
84 + canvas.width = size * dpr;
85 + canvas.height = size * dpr;
86 + ctx.scale(dpr, dpr);
87 + }
88 + resolve(adaptor(ctx));
89 + });
90 + });
91 + },
92 + setHoverColor() {
93 + const { color, size } = this.data;
94 + if (isObj(color)) {
95 + return this.getContext().then((context) => {
96 + const LinearColor = context.createLinearGradient(size, 0, 0, 0);
97 + Object.keys(color)
98 + .sort((a, b) => parseFloat(a) - parseFloat(b))
99 + .map((key) => LinearColor.addColorStop(parseFloat(key) / 100, color[key]));
100 + this.hoverColor = LinearColor;
101 + });
102 + }
103 + this.hoverColor = color;
104 + return Promise.resolve();
105 + },
106 + presetCanvas(context, strokeStyle, beginAngle, endAngle, fill) {
107 + const { strokeWidth, lineCap, clockwise, size } = this.data;
108 + const position = size / 2;
109 + const radius = position - strokeWidth / 2;
110 + context.setStrokeStyle(strokeStyle);
111 + context.setLineWidth(strokeWidth);
112 + context.setLineCap(lineCap);
113 + context.beginPath();
114 + context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
115 + context.stroke();
116 + if (fill) {
117 + context.setFillStyle(fill);
118 + context.fill();
119 + }
120 + },
121 + renderLayerCircle(context) {
122 + const { layerColor, fill } = this.data;
123 + this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
124 + },
125 + renderHoverCircle(context, formatValue) {
126 + const { clockwise } = this.data;
127 + // 结束角度
128 + const progress = PERIMETER * (formatValue / 100);
129 + const endAngle = clockwise
130 + ? BEGIN_ANGLE + progress
131 + : 3 * Math.PI - (BEGIN_ANGLE + progress);
132 + this.presetCanvas(context, this.hoverColor, BEGIN_ANGLE, endAngle);
133 + },
134 + drawCircle(currentValue) {
135 + const { size } = this.data;
136 + this.getContext().then((context) => {
137 + context.clearRect(0, 0, size, size);
138 + this.renderLayerCircle(context);
139 + const formatValue = format(currentValue);
140 + if (formatValue !== 0) {
141 + this.renderHoverCircle(context, formatValue);
142 + }
143 + context.draw();
144 + });
145 + },
146 + reRender() {
147 + // tofector 动画暂时没有想到好的解决方案
148 + const { value, speed } = this.data;
149 + if (speed <= 0 || speed > 1000) {
150 + this.drawCircle(value);
151 + return;
152 + }
153 + this.clearMockInterval();
154 + this.currentValue = this.currentValue || 0;
155 + const run = () => {
156 + this.interval = setTimeout(() => {
157 + if (this.currentValue !== value) {
158 + if (Math.abs(this.currentValue - value) < STEP) {
159 + this.currentValue = value;
160 + }
161 + else if (this.currentValue < value) {
162 + this.currentValue += STEP;
163 + }
164 + else {
165 + this.currentValue -= STEP;
166 + }
167 + this.drawCircle(this.currentValue);
168 + run();
169 + }
170 + else {
171 + this.clearMockInterval();
172 + }
173 + }, 1000 / speed);
174 + };
175 + run();
176 + },
177 + clearMockInterval() {
178 + if (this.interval) {
179 + clearTimeout(this.interval);
180 + this.interval = null;
181 + }
182 + },
183 + },
184 + mounted() {
185 + this.currentValue = this.data.value;
186 + this.setHoverColor().then(() => {
187 + this.drawCircle(this.currentValue);
188 + });
189 + },
190 + destroyed() {
191 + this.clearMockInterval();
192 + },
193 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view class="van-circle">
4 + <canvas class="van-circle__canvas" type="{{ type }}" style="width: {{ utils.addUnit(size) }};height:{{ utils.addUnit(size) }}" id="van-circle" canvas-id="van-circle"></canvas>
5 + <view wx:if="{{ !text }}" class="van-circle__text">
6 + <slot></slot>
7 + </view>
8 + <cover-view wx:else class="van-circle__text">{{ text }}</cover-view>
9 +</view>
1 +@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 ...\ No newline at end of file
1 +import { useParent } from '../common/relation';
2 +import { VantComponent } from '../common/component';
3 +VantComponent({
4 + relation: useParent('row'),
5 + props: {
6 + span: Number,
7 + offset: Number,
8 + },
9 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view
5 + class="custom-class {{ utils.bem('col', [span]) }} {{ offset ? 'van-col--offset-' + offset : '' }}"
6 + style="{{ computed.rootStyle({ gutter }) }}"
7 +>
8 + <slot />
9 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function rootStyle(data) {
6 + if (!data.gutter) {
7 + return '';
8 + }
9 +
10 + return style({
11 + 'padding-right': addUnit(data.gutter / 2),
12 + 'padding-left': addUnit(data.gutter / 2),
13 + });
14 +}
15 +
16 +module.exports = {
17 + rootStyle: rootStyle,
18 +};
1 +@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 ...\ No newline at end of file
1 +/// <reference types="miniprogram-api-typings" />
2 +export declare function setContentAnimate(context: WechatMiniprogram.Component.TrivialInstance, expanded: boolean, mounted: boolean): void;
1 +import { getRect } from '../common/utils';
2 +function useAnimation(context, expanded, mounted, height) {
3 + const animation = wx.createAnimation({
4 + duration: 0,
5 + timingFunction: 'ease-in-out',
6 + });
7 + if (expanded) {
8 + if (height === 0) {
9 + animation.height('auto').top(1).step();
10 + }
11 + else {
12 + animation
13 + .height(height)
14 + .top(1)
15 + .step({
16 + duration: mounted ? 300 : 1,
17 + })
18 + .height('auto')
19 + .step();
20 + }
21 + context.setData({
22 + animation: animation.export(),
23 + });
24 + return;
25 + }
26 + animation.height(height).top(0).step({ duration: 1 }).height(0).step({
27 + duration: 300,
28 + });
29 + context.setData({
30 + animation: animation.export(),
31 + });
32 +}
33 +export function setContentAnimate(context, expanded, mounted) {
34 + getRect(context, '.van-collapse-item__content')
35 + .then((rect) => rect.height)
36 + .then((height) => {
37 + useAnimation(context, expanded, mounted, height);
38 + });
39 +}
1 +import { VantComponent } from '../common/component';
2 +import { useParent } from '../common/relation';
3 +import { setContentAnimate } from './animate';
4 +VantComponent({
5 + classes: ['title-class', 'content-class'],
6 + relation: useParent('collapse'),
7 + props: {
8 + size: String,
9 + name: null,
10 + title: null,
11 + value: null,
12 + icon: String,
13 + label: String,
14 + disabled: Boolean,
15 + clickable: Boolean,
16 + border: {
17 + type: Boolean,
18 + value: true,
19 + },
20 + isLink: {
21 + type: Boolean,
22 + value: true,
23 + },
24 + },
25 + data: {
26 + expanded: false,
27 + },
28 + mounted() {
29 + this.updateExpanded();
30 + this.mounted = true;
31 + },
32 + methods: {
33 + updateExpanded() {
34 + if (!this.parent) {
35 + return;
36 + }
37 + const { value, accordion } = this.parent.data;
38 + const { children = [] } = this.parent;
39 + const { name } = this.data;
40 + const index = children.indexOf(this);
41 + const currentName = name == null ? index : name;
42 + const expanded = accordion
43 + ? value === currentName
44 + : (value || []).some((name) => name === currentName);
45 + if (expanded !== this.data.expanded) {
46 + setContentAnimate(this, expanded, this.mounted);
47 + }
48 + this.setData({ index, expanded });
49 + },
50 + onClick() {
51 + if (this.data.disabled) {
52 + return;
53 + }
54 + const { name, expanded } = this.data;
55 + const index = this.parent.children.indexOf(this);
56 + const currentName = name == null ? index : name;
57 + this.parent.switch(currentName, !expanded);
58 + },
59 + },
60 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-cell": "../cell/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view class="van-collapse-item custom-class {{ index !== 0 ? 'van-hairline--top' : '' }}">
4 + <van-cell
5 + size="{{ size }}"
6 + title="{{ title }}"
7 + title-class="title-class"
8 + icon="{{ icon }}"
9 + value="{{ value }}"
10 + label="{{ label }}"
11 + is-link="{{ isLink }}"
12 + clickable="{{ clickable }}"
13 + border="{{ border && expanded }}"
14 + class="{{ utils.bem('collapse-item__title', { disabled, expanded }) }}"
15 + right-icon-class="van-cell__right-icon"
16 + custom-class="van-cell"
17 + hover-class="van-cell--hover"
18 + bind:click="onClick"
19 + >
20 + <slot
21 + name="title"
22 + slot="title"
23 + />
24 + <slot
25 + name="icon"
26 + slot="icon"
27 + />
28 + <slot name="value" />
29 + <slot
30 + name="right-icon"
31 + slot="right-icon"
32 + />
33 + </van-cell>
34 + <view
35 + class="{{ utils.bem('collapse-item__wrapper') }}"
36 + style="height: 0;"
37 + animation="{{ animation }}"
38 + >
39 + <view
40 + class="van-collapse-item__content content-class"
41 + >
42 + <slot />
43 + </view>
44 + </view>
45 +</view>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { useChildren } from '../common/relation';
3 +VantComponent({
4 + relation: useChildren('collapse-item'),
5 + props: {
6 + value: {
7 + type: null,
8 + observer: 'updateExpanded',
9 + },
10 + accordion: {
11 + type: Boolean,
12 + observer: 'updateExpanded',
13 + },
14 + border: {
15 + type: Boolean,
16 + value: true,
17 + },
18 + },
19 + methods: {
20 + updateExpanded() {
21 + this.children.forEach((child) => {
22 + child.updateExpanded();
23 + });
24 + },
25 + switch(name, expanded) {
26 + const { accordion, value } = this.data;
27 + const changeItem = name;
28 + if (!accordion) {
29 + name = expanded
30 + ? (value || []).concat(name)
31 + : (value || []).filter((activeName) => activeName !== name);
32 + }
33 + else {
34 + name = expanded ? name : '';
35 + }
36 + if (expanded) {
37 + this.$emit('open', changeItem);
38 + }
39 + else {
40 + this.$emit('close', changeItem);
41 + }
42 + this.$emit('change', name);
43 + this.$emit('input', name);
44 + },
45 + },
46 +});
1 +<view class="custom-class van-collapse {{ border ? 'van-hairline--top-bottom' : '' }}">
2 + <slot />
3 +</view>
1 +@import '../common/index.wxss';
...\ No newline at end of file ...\ No newline at end of file
1 +export declare const RED = "#ee0a24";
2 +export declare const BLUE = "#1989fa";
3 +export declare const WHITE = "#fff";
4 +export declare const GREEN = "#07c160";
5 +export declare const ORANGE = "#ff976a";
6 +export declare const GRAY = "#323233";
7 +export declare const GRAY_DARK = "#969799";
1 +export const RED = '#ee0a24';
2 +export const BLUE = '#1989fa';
3 +export const WHITE = '#fff';
4 +export const GREEN = '#07c160';
5 +export const ORANGE = '#ff976a';
6 +export const GRAY = '#323233';
7 +export const GRAY_DARK = '#969799';
1 +/// <reference types="miniprogram-api-typings" />
2 +import { VantComponentOptions } from 'definitions/index';
3 +declare function VantComponent<Data extends WechatMiniprogram.Component.DataOption, Props extends WechatMiniprogram.Component.PropertyOption, Methods extends WechatMiniprogram.Component.MethodOption>(vantOptions: VantComponentOptions<Data, Props, Methods>): void;
4 +export { VantComponent };
1 +import { basic } from '../mixins/basic';
2 +function mapKeys(source, target, map) {
3 + Object.keys(map).forEach((key) => {
4 + if (source[key]) {
5 + target[map[key]] = source[key];
6 + }
7 + });
8 +}
9 +function VantComponent(vantOptions) {
10 + const options = {};
11 + mapKeys(vantOptions, options, {
12 + data: 'data',
13 + props: 'properties',
14 + mixins: 'behaviors',
15 + methods: 'methods',
16 + beforeCreate: 'created',
17 + created: 'attached',
18 + mounted: 'ready',
19 + destroyed: 'detached',
20 + classes: 'externalClasses',
21 + });
22 + // add default externalClasses
23 + options.externalClasses = options.externalClasses || [];
24 + options.externalClasses.push('custom-class');
25 + // add default behaviors
26 + options.behaviors = options.behaviors || [];
27 + options.behaviors.push(basic);
28 + // add relations
29 + const { relation } = vantOptions;
30 + if (relation) {
31 + options.relations = relation.relations;
32 + options.behaviors.push(relation.mixin);
33 + }
34 + // map field to form-field behavior
35 + if (vantOptions.field) {
36 + options.behaviors.push('wx://form-field');
37 + }
38 + // add default options
39 + options.options = {
40 + multipleSlots: true,
41 + addGlobalClass: true,
42 + };
43 + Component(options);
44 +}
45 +export { VantComponent };
1 +.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 ...\ No newline at end of file
1 +/// <reference types="miniprogram-api-typings" />
2 +declare type TrivialInstance = WechatMiniprogram.Component.TrivialInstance;
3 +export declare function useParent(name: string, onEffect?: (this: TrivialInstance) => void): {
4 + relations: {
5 + [x: string]: WechatMiniprogram.Component.RelationOption;
6 + };
7 + mixin: string;
8 +};
9 +export declare function useChildren(name: string, onEffect?: (this: TrivialInstance, target: TrivialInstance) => void): {
10 + relations: {
11 + [x: string]: WechatMiniprogram.Component.RelationOption;
12 + };
13 + mixin: string;
14 +};
15 +export {};
1 +export function useParent(name, onEffect) {
2 + const path = `../${name}/index`;
3 + return {
4 + relations: {
5 + [path]: {
6 + type: 'ancestor',
7 + linked() {
8 + onEffect && onEffect.call(this);
9 + },
10 + linkChanged() {
11 + onEffect && onEffect.call(this);
12 + },
13 + unlinked() {
14 + onEffect && onEffect.call(this);
15 + },
16 + },
17 + },
18 + mixin: Behavior({
19 + created() {
20 + Object.defineProperty(this, 'parent', {
21 + get: () => this.getRelationNodes(path)[0],
22 + });
23 + Object.defineProperty(this, 'index', {
24 + // @ts-ignore
25 + 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); },
26 + });
27 + },
28 + }),
29 + };
30 +}
31 +export function useChildren(name, onEffect) {
32 + const path = `../${name}/index`;
33 + return {
34 + relations: {
35 + [path]: {
36 + type: 'descendant',
37 + linked(target) {
38 + onEffect && onEffect.call(this, target);
39 + },
40 + linkChanged(target) {
41 + onEffect && onEffect.call(this, target);
42 + },
43 + unlinked(target) {
44 + onEffect && onEffect.call(this, target);
45 + },
46 + },
47 + },
48 + mixin: Behavior({
49 + created() {
50 + Object.defineProperty(this, 'children', {
51 + get: () => this.getRelationNodes(path) || [],
52 + });
53 + },
54 + }),
55 + };
56 +}
1 +.van-clearfix:after{clear:both;content:"";display:table}
...\ No newline at end of file ...\ No newline at end of file
1 +.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 ...\ No newline at end of file
1 +.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{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 ...\ No newline at end of file
1 +/// <reference types="miniprogram-api-typings" />
2 +/// <reference types="node" />
3 +export { isDef } from './validator';
4 +export declare function range(num: number, min: number, max: number): number;
5 +export declare function nextTick(cb: (...args: any[]) => void): void;
6 +export declare function getSystemInfoSync(): WechatMiniprogram.SystemInfo;
7 +export declare function addUnit(value?: string | number): string | undefined;
8 +export declare function requestAnimationFrame(cb: () => void): NodeJS.Timeout | WechatMiniprogram.NodesRef;
9 +export declare function pickExclude(obj: unknown, keys: string[]): {};
10 +export declare function getRect(context: WechatMiniprogram.Component.TrivialInstance, selector: string): Promise<WechatMiniprogram.BoundingClientRectCallbackResult>;
11 +export declare function getAllRect(context: WechatMiniprogram.Component.TrivialInstance, selector: string): Promise<WechatMiniprogram.BoundingClientRectCallbackResult[]>;
12 +export declare function groupSetData(context: WechatMiniprogram.Component.TrivialInstance, cb: () => void): void;
13 +export declare function toPromise(promiseLike: Promise<unknown> | unknown): Promise<unknown>;
14 +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;
1 +import { isDef, isNumber, isPlainObject, isPromise } from './validator';
2 +import { canIUseGroupSetData, canIUseNextTick } from './version';
3 +export { isDef } from './validator';
4 +export function range(num, min, max) {
5 + return Math.min(Math.max(num, min), max);
6 +}
7 +export function nextTick(cb) {
8 + if (canIUseNextTick()) {
9 + wx.nextTick(cb);
10 + }
11 + else {
12 + setTimeout(() => {
13 + cb();
14 + }, 1000 / 30);
15 + }
16 +}
17 +let systemInfo;
18 +export function getSystemInfoSync() {
19 + if (systemInfo == null) {
20 + systemInfo = wx.getSystemInfoSync();
21 + }
22 + return systemInfo;
23 +}
24 +export function addUnit(value) {
25 + if (!isDef(value)) {
26 + return undefined;
27 + }
28 + value = String(value);
29 + return isNumber(value) ? `${value}px` : value;
30 +}
31 +export function requestAnimationFrame(cb) {
32 + const systemInfo = getSystemInfoSync();
33 + if (systemInfo.platform === 'devtools') {
34 + return setTimeout(() => {
35 + cb();
36 + }, 1000 / 30);
37 + }
38 + return wx
39 + .createSelectorQuery()
40 + .selectViewport()
41 + .boundingClientRect()
42 + .exec(() => {
43 + cb();
44 + });
45 +}
46 +export function pickExclude(obj, keys) {
47 + if (!isPlainObject(obj)) {
48 + return {};
49 + }
50 + return Object.keys(obj).reduce((prev, key) => {
51 + if (!keys.includes(key)) {
52 + prev[key] = obj[key];
53 + }
54 + return prev;
55 + }, {});
56 +}
57 +export function getRect(context, selector) {
58 + return new Promise((resolve) => {
59 + wx.createSelectorQuery()
60 + .in(context)
61 + .select(selector)
62 + .boundingClientRect()
63 + .exec((rect = []) => resolve(rect[0]));
64 + });
65 +}
66 +export function getAllRect(context, selector) {
67 + return new Promise((resolve) => {
68 + wx.createSelectorQuery()
69 + .in(context)
70 + .selectAll(selector)
71 + .boundingClientRect()
72 + .exec((rect = []) => resolve(rect[0]));
73 + });
74 +}
75 +export function groupSetData(context, cb) {
76 + if (canIUseGroupSetData()) {
77 + context.groupSetData(cb);
78 + }
79 + else {
80 + cb();
81 + }
82 +}
83 +export function toPromise(promiseLike) {
84 + if (isPromise(promiseLike)) {
85 + return promiseLike;
86 + }
87 + return Promise.resolve(promiseLike);
88 +}
89 +export function getCurrentPage() {
90 + const pages = getCurrentPages();
91 + return pages[pages.length - 1];
92 +}
1 +export declare function isFunction(val: unknown): val is Function;
2 +export declare function isPlainObject(val: unknown): val is Record<string, unknown>;
3 +export declare function isPromise<T = unknown>(val: unknown): val is Promise<T>;
4 +export declare function isDef(value: unknown): boolean;
5 +export declare function isObj(x: unknown): x is Record<string, unknown>;
6 +export declare function isNumber(value: string): boolean;
7 +export declare function isBoolean(value: unknown): value is boolean;
8 +export declare function isImageUrl(url: string): boolean;
9 +export declare function isVideoUrl(url: string): boolean;
1 +// eslint-disable-next-line @typescript-eslint/ban-types
2 +export function isFunction(val) {
3 + return typeof val === 'function';
4 +}
5 +export function isPlainObject(val) {
6 + return val !== null && typeof val === 'object' && !Array.isArray(val);
7 +}
8 +export function isPromise(val) {
9 + return isPlainObject(val) && isFunction(val.then) && isFunction(val.catch);
10 +}
11 +export function isDef(value) {
12 + return value !== undefined && value !== null;
13 +}
14 +export function isObj(x) {
15 + const type = typeof x;
16 + return x !== null && (type === 'object' || type === 'function');
17 +}
18 +export function isNumber(value) {
19 + return /^\d+(\.\d+)?$/.test(value);
20 +}
21 +export function isBoolean(value) {
22 + return typeof value === 'boolean';
23 +}
24 +const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
25 +const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i;
26 +export function isImageUrl(url) {
27 + return IMAGE_REGEXP.test(url);
28 +}
29 +export function isVideoUrl(url) {
30 + return VIDEO_REGEXP.test(url);
31 +}
1 +export declare function canIUseModel(): boolean;
2 +export declare function canIUseFormFieldButton(): boolean;
3 +export declare function canIUseAnimate(): boolean;
4 +export declare function canIUseGroupSetData(): boolean;
5 +export declare function canIUseNextTick(): boolean;
6 +export declare function canIUseCanvas2d(): boolean;
7 +export declare function canIUseGetUserProfile(): boolean;
1 +import { getSystemInfoSync } from './utils';
2 +function compareVersion(v1, v2) {
3 + v1 = v1.split('.');
4 + v2 = v2.split('.');
5 + const len = Math.max(v1.length, v2.length);
6 + while (v1.length < len) {
7 + v1.push('0');
8 + }
9 + while (v2.length < len) {
10 + v2.push('0');
11 + }
12 + for (let i = 0; i < len; i++) {
13 + const num1 = parseInt(v1[i], 10);
14 + const num2 = parseInt(v2[i], 10);
15 + if (num1 > num2) {
16 + return 1;
17 + }
18 + if (num1 < num2) {
19 + return -1;
20 + }
21 + }
22 + return 0;
23 +}
24 +function gte(version) {
25 + const system = getSystemInfoSync();
26 + return compareVersion(system.SDKVersion, version) >= 0;
27 +}
28 +export function canIUseModel() {
29 + return gte('2.9.3');
30 +}
31 +export function canIUseFormFieldButton() {
32 + return gte('2.10.3');
33 +}
34 +export function canIUseAnimate() {
35 + return gte('2.9.0');
36 +}
37 +export function canIUseGroupSetData() {
38 + return gte('2.4.0');
39 +}
40 +export function canIUseNextTick() {
41 + return wx.canIUse('nextTick');
42 +}
43 +export function canIUseCanvas2d() {
44 + return gte('2.9.0');
45 +}
46 +export function canIUseGetUserProfile() {
47 + return !!wx.getUserProfile;
48 +}
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + props: {
4 + themeVars: {
5 + type: Object,
6 + value: {},
7 + },
8 + },
9 +});
1 +<wxs src="./index.wxs" module="computed" />
2 +
3 +<view class="van-config-provider" style="{{ computed.mapThemeVarsToCSSVars(themeVars) }}">
4 + <slot />
5 +</view>
1 +/* eslint-disable */
2 +var object = require('../wxs/object.wxs');
3 +var style = require('../wxs/style.wxs');
4 +
5 +function kebabCase(word) {
6 + var newWord = word
7 + .replace(getRegExp("[A-Z]", 'g'), function (i) {
8 + return '-' + i;
9 + })
10 + .toLowerCase()
11 + .replace(getRegExp("^-"), '');
12 +
13 + return newWord;
14 +}
15 +
16 +function mapThemeVarsToCSSVars(themeVars) {
17 + var cssVars = {};
18 + object.keys(themeVars).forEach(function (key) {
19 + var cssVarsKey = '--' + kebabCase(key);
20 + cssVars[cssVarsKey] = themeVars[key];
21 + });
22 +
23 + return style(cssVars);
24 +}
25 +
26 +module.exports = {
27 + kebabCase: kebabCase,
28 + mapThemeVarsToCSSVars: mapThemeVarsToCSSVars,
29 +};
1 +import { VantComponent } from '../common/component';
2 +import { isSameSecond, parseFormat, parseTimeData } from './utils';
3 +function simpleTick(fn) {
4 + return setTimeout(fn, 30);
5 +}
6 +VantComponent({
7 + props: {
8 + useSlot: Boolean,
9 + millisecond: Boolean,
10 + time: {
11 + type: Number,
12 + observer: 'reset',
13 + },
14 + format: {
15 + type: String,
16 + value: 'HH:mm:ss',
17 + },
18 + autoStart: {
19 + type: Boolean,
20 + value: true,
21 + },
22 + },
23 + data: {
24 + timeData: parseTimeData(0),
25 + formattedTime: '0',
26 + },
27 + destroyed() {
28 + clearTimeout(this.tid);
29 + this.tid = null;
30 + },
31 + methods: {
32 + // 开始
33 + start() {
34 + if (this.counting) {
35 + return;
36 + }
37 + this.counting = true;
38 + this.endTime = Date.now() + this.remain;
39 + this.tick();
40 + },
41 + // 暂停
42 + pause() {
43 + this.counting = false;
44 + clearTimeout(this.tid);
45 + },
46 + // 重置
47 + reset() {
48 + this.pause();
49 + this.remain = this.data.time;
50 + this.setRemain(this.remain);
51 + if (this.data.autoStart) {
52 + this.start();
53 + }
54 + },
55 + tick() {
56 + if (this.data.millisecond) {
57 + this.microTick();
58 + }
59 + else {
60 + this.macroTick();
61 + }
62 + },
63 + microTick() {
64 + this.tid = simpleTick(() => {
65 + this.setRemain(this.getRemain());
66 + if (this.remain !== 0) {
67 + this.microTick();
68 + }
69 + });
70 + },
71 + macroTick() {
72 + this.tid = simpleTick(() => {
73 + const remain = this.getRemain();
74 + if (!isSameSecond(remain, this.remain) || remain === 0) {
75 + this.setRemain(remain);
76 + }
77 + if (this.remain !== 0) {
78 + this.macroTick();
79 + }
80 + });
81 + },
82 + getRemain() {
83 + return Math.max(this.endTime - Date.now(), 0);
84 + },
85 + setRemain(remain) {
86 + this.remain = remain;
87 + const timeData = parseTimeData(remain);
88 + if (this.data.useSlot) {
89 + this.$emit('change', timeData);
90 + }
91 + this.setData({
92 + formattedTime: parseFormat(this.data.format, timeData),
93 + });
94 + if (remain === 0) {
95 + this.pause();
96 + this.$emit('finish');
97 + }
98 + },
99 + },
100 +});
1 +<view class="van-count-down">
2 + <slot wx:if="{{ useSlot }}"/>
3 + <block wx:else>{{ formattedTime }}</block>
4 +</view>
1 +@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 ...\ No newline at end of file
1 +export declare type TimeData = {
2 + days: number;
3 + hours: number;
4 + minutes: number;
5 + seconds: number;
6 + milliseconds: number;
7 +};
8 +export declare function parseTimeData(time: number): TimeData;
9 +export declare function parseFormat(format: string, timeData: TimeData): string;
10 +export declare function isSameSecond(time1: number, time2: number): boolean;
1 +function padZero(num, targetLength = 2) {
2 + let str = num + '';
3 + while (str.length < targetLength) {
4 + str = '0' + str;
5 + }
6 + return str;
7 +}
8 +const SECOND = 1000;
9 +const MINUTE = 60 * SECOND;
10 +const HOUR = 60 * MINUTE;
11 +const DAY = 24 * HOUR;
12 +export function parseTimeData(time) {
13 + const days = Math.floor(time / DAY);
14 + const hours = Math.floor((time % DAY) / HOUR);
15 + const minutes = Math.floor((time % HOUR) / MINUTE);
16 + const seconds = Math.floor((time % MINUTE) / SECOND);
17 + const milliseconds = Math.floor(time % SECOND);
18 + return {
19 + days,
20 + hours,
21 + minutes,
22 + seconds,
23 + milliseconds,
24 + };
25 +}
26 +export function parseFormat(format, timeData) {
27 + const { days } = timeData;
28 + let { hours, minutes, seconds, milliseconds } = timeData;
29 + if (format.indexOf('DD') === -1) {
30 + hours += days * 24;
31 + }
32 + else {
33 + format = format.replace('DD', padZero(days));
34 + }
35 + if (format.indexOf('HH') === -1) {
36 + minutes += hours * 60;
37 + }
38 + else {
39 + format = format.replace('HH', padZero(hours));
40 + }
41 + if (format.indexOf('mm') === -1) {
42 + seconds += minutes * 60;
43 + }
44 + else {
45 + format = format.replace('mm', padZero(minutes));
46 + }
47 + if (format.indexOf('ss') === -1) {
48 + milliseconds += seconds * 1000;
49 + }
50 + else {
51 + format = format.replace('ss', padZero(seconds));
52 + }
53 + return format.replace('SSS', padZero(milliseconds, 3));
54 +}
55 +export function isSameSecond(time1, time2) {
56 + return Math.floor(time1 / 1000) === Math.floor(time2 / 1000);
57 +}
1 +import { VantComponent } from '../common/component';
2 +import { isDef } from '../common/validator';
3 +import { pickerProps } from '../picker/shared';
4 +const currentYear = new Date().getFullYear();
5 +function isValidDate(date) {
6 + return isDef(date) && !isNaN(new Date(date).getTime());
7 +}
8 +function range(num, min, max) {
9 + return Math.min(Math.max(num, min), max);
10 +}
11 +function padZero(val) {
12 + return `00${val}`.slice(-2);
13 +}
14 +function times(n, iteratee) {
15 + let index = -1;
16 + const result = Array(n < 0 ? 0 : n);
17 + while (++index < n) {
18 + result[index] = iteratee(index);
19 + }
20 + return result;
21 +}
22 +function getTrueValue(formattedValue) {
23 + if (formattedValue === undefined) {
24 + formattedValue = '1';
25 + }
26 + while (isNaN(parseInt(formattedValue, 10))) {
27 + formattedValue = formattedValue.slice(1);
28 + }
29 + return parseInt(formattedValue, 10);
30 +}
31 +function getMonthEndDay(year, month) {
32 + return 32 - new Date(year, month - 1, 32).getDate();
33 +}
34 +const defaultFormatter = (type, value) => value;
35 +VantComponent({
36 + classes: ['active-class', 'toolbar-class', 'column-class'],
37 + props: Object.assign(Object.assign({}, pickerProps), { value: {
38 + type: null,
39 + observer: 'updateValue',
40 + }, filter: null, type: {
41 + type: String,
42 + value: 'datetime',
43 + observer: 'updateValue',
44 + }, showToolbar: {
45 + type: Boolean,
46 + value: true,
47 + }, formatter: {
48 + type: null,
49 + value: defaultFormatter,
50 + }, minDate: {
51 + type: Number,
52 + value: new Date(currentYear - 10, 0, 1).getTime(),
53 + observer: 'updateValue',
54 + }, maxDate: {
55 + type: Number,
56 + value: new Date(currentYear + 10, 11, 31).getTime(),
57 + observer: 'updateValue',
58 + }, minHour: {
59 + type: Number,
60 + value: 0,
61 + observer: 'updateValue',
62 + }, maxHour: {
63 + type: Number,
64 + value: 23,
65 + observer: 'updateValue',
66 + }, minMinute: {
67 + type: Number,
68 + value: 0,
69 + observer: 'updateValue',
70 + }, maxMinute: {
71 + type: Number,
72 + value: 59,
73 + observer: 'updateValue',
74 + } }),
75 + data: {
76 + innerValue: Date.now(),
77 + columns: [],
78 + },
79 + methods: {
80 + updateValue() {
81 + const { data } = this;
82 + const val = this.correctValue(data.value);
83 + const isEqual = val === data.innerValue;
84 + this.updateColumnValue(val).then(() => {
85 + if (!isEqual) {
86 + this.$emit('input', val);
87 + }
88 + });
89 + },
90 + getPicker() {
91 + if (this.picker == null) {
92 + this.picker = this.selectComponent('.van-datetime-picker');
93 + const { picker } = this;
94 + const { setColumnValues } = picker;
95 + picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]);
96 + }
97 + return this.picker;
98 + },
99 + updateColumns() {
100 + const { formatter = defaultFormatter } = this.data;
101 + const results = this.getOriginColumns().map((column) => ({
102 + values: column.values.map((value) => formatter(column.type, value)),
103 + }));
104 + return this.set({ columns: results });
105 + },
106 + getOriginColumns() {
107 + const { filter } = this.data;
108 + const results = this.getRanges().map(({ type, range }) => {
109 + let values = times(range[1] - range[0] + 1, (index) => {
110 + const value = range[0] + index;
111 + return type === 'year' ? `${value}` : padZero(value);
112 + });
113 + if (filter) {
114 + values = filter(type, values);
115 + }
116 + return { type, values };
117 + });
118 + return results;
119 + },
120 + getRanges() {
121 + const { data } = this;
122 + if (data.type === 'time') {
123 + return [
124 + {
125 + type: 'hour',
126 + range: [data.minHour, data.maxHour],
127 + },
128 + {
129 + type: 'minute',
130 + range: [data.minMinute, data.maxMinute],
131 + },
132 + ];
133 + }
134 + const { maxYear, maxDate, maxMonth, maxHour, maxMinute, } = this.getBoundary('max', data.innerValue);
135 + const { minYear, minDate, minMonth, minHour, minMinute, } = this.getBoundary('min', data.innerValue);
136 + const result = [
137 + {
138 + type: 'year',
139 + range: [minYear, maxYear],
140 + },
141 + {
142 + type: 'month',
143 + range: [minMonth, maxMonth],
144 + },
145 + {
146 + type: 'day',
147 + range: [minDate, maxDate],
148 + },
149 + {
150 + type: 'hour',
151 + range: [minHour, maxHour],
152 + },
153 + {
154 + type: 'minute',
155 + range: [minMinute, maxMinute],
156 + },
157 + ];
158 + if (data.type === 'date')
159 + result.splice(3, 2);
160 + if (data.type === 'year-month')
161 + result.splice(2, 3);
162 + return result;
163 + },
164 + correctValue(value) {
165 + const { data } = this;
166 + // validate value
167 + const isDateType = data.type !== 'time';
168 + if (isDateType && !isValidDate(value)) {
169 + value = data.minDate;
170 + }
171 + else if (!isDateType && !value) {
172 + const { minHour } = data;
173 + value = `${padZero(minHour)}:00`;
174 + }
175 + // time type
176 + if (!isDateType) {
177 + let [hour, minute] = value.split(':');
178 + hour = padZero(range(hour, data.minHour, data.maxHour));
179 + minute = padZero(range(minute, data.minMinute, data.maxMinute));
180 + return `${hour}:${minute}`;
181 + }
182 + // date type
183 + value = Math.max(value, data.minDate);
184 + value = Math.min(value, data.maxDate);
185 + return value;
186 + },
187 + getBoundary(type, innerValue) {
188 + const value = new Date(innerValue);
189 + const boundary = new Date(this.data[`${type}Date`]);
190 + const year = boundary.getFullYear();
191 + let month = 1;
192 + let date = 1;
193 + let hour = 0;
194 + let minute = 0;
195 + if (type === 'max') {
196 + month = 12;
197 + date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1);
198 + hour = 23;
199 + minute = 59;
200 + }
201 + if (value.getFullYear() === year) {
202 + month = boundary.getMonth() + 1;
203 + if (value.getMonth() + 1 === month) {
204 + date = boundary.getDate();
205 + if (value.getDate() === date) {
206 + hour = boundary.getHours();
207 + if (value.getHours() === hour) {
208 + minute = boundary.getMinutes();
209 + }
210 + }
211 + }
212 + }
213 + return {
214 + [`${type}Year`]: year,
215 + [`${type}Month`]: month,
216 + [`${type}Date`]: date,
217 + [`${type}Hour`]: hour,
218 + [`${type}Minute`]: minute,
219 + };
220 + },
221 + onCancel() {
222 + this.$emit('cancel');
223 + },
224 + onConfirm() {
225 + this.$emit('confirm', this.data.innerValue);
226 + },
227 + onChange() {
228 + const { data } = this;
229 + let value;
230 + const picker = this.getPicker();
231 + const originColumns = this.getOriginColumns();
232 + if (data.type === 'time') {
233 + const indexes = picker.getIndexes();
234 + value = `${+originColumns[0].values[indexes[0]]}:${+originColumns[1]
235 + .values[indexes[1]]}`;
236 + }
237 + else {
238 + const indexes = picker.getIndexes();
239 + const values = indexes.map((value, index) => originColumns[index].values[value]);
240 + const year = getTrueValue(values[0]);
241 + const month = getTrueValue(values[1]);
242 + const maxDate = getMonthEndDay(year, month);
243 + let date = getTrueValue(values[2]);
244 + if (data.type === 'year-month') {
245 + date = 1;
246 + }
247 + date = date > maxDate ? maxDate : date;
248 + let hour = 0;
249 + let minute = 0;
250 + if (data.type === 'datetime') {
251 + hour = getTrueValue(values[3]);
252 + minute = getTrueValue(values[4]);
253 + }
254 + value = new Date(year, month - 1, date, hour, minute);
255 + }
256 + value = this.correctValue(value);
257 + this.updateColumnValue(value).then(() => {
258 + this.$emit('input', value);
259 + this.$emit('change', picker);
260 + });
261 + },
262 + updateColumnValue(value) {
263 + let values = [];
264 + const { type } = this.data;
265 + const formatter = this.data.formatter || defaultFormatter;
266 + const picker = this.getPicker();
267 + if (type === 'time') {
268 + const pair = value.split(':');
269 + values = [formatter('hour', pair[0]), formatter('minute', pair[1])];
270 + }
271 + else {
272 + const date = new Date(value);
273 + values = [
274 + formatter('year', `${date.getFullYear()}`),
275 + formatter('month', padZero(date.getMonth() + 1)),
276 + ];
277 + if (type === 'date') {
278 + values.push(formatter('day', padZero(date.getDate())));
279 + }
280 + if (type === 'datetime') {
281 + values.push(formatter('day', padZero(date.getDate())), formatter('hour', padZero(date.getHours())), formatter('minute', padZero(date.getMinutes())));
282 + }
283 + }
284 + return this.set({ innerValue: value })
285 + .then(() => this.updateColumns())
286 + .then(() => picker.setValues(values));
287 + },
288 + },
289 + created() {
290 + const innerValue = this.correctValue(this.data.value);
291 + this.updateColumnValue(innerValue).then(() => {
292 + this.$emit('input', innerValue);
293 + });
294 + },
295 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-picker": "../picker/index"
5 + }
6 +}
1 +<van-picker
2 + class="van-datetime-picker"
3 + active-class="active-class"
4 + toolbar-class="toolbar-class"
5 + column-class="column-class"
6 + title="{{ title }}"
7 + columns="{{ columns }}"
8 + item-height="{{ itemHeight }}"
9 + show-toolbar="{{ showToolbar }}"
10 + visible-item-count="{{ visibleItemCount }}"
11 + confirm-button-text="{{ confirmButtonText }}"
12 + cancel-button-text="{{ cancelButtonText }}"
13 + bind:change="onChange"
14 + bind:confirm="onConfirm"
15 + bind:cancel="onCancel"
16 +/>
1 +@import '../common/index.wxss';
...\ No newline at end of file ...\ No newline at end of file
1 +/// <reference types="miniprogram-api-typings" />
2 +interface VantComponentInstance {
3 + parent: WechatMiniprogram.Component.TrivialInstance;
4 + children: WechatMiniprogram.Component.TrivialInstance[];
5 + index: number;
6 + $emit: (name: string, detail?: unknown, options?: WechatMiniprogram.Component.TriggerEventOption) => void;
7 +}
8 +export declare type VantComponentOptions<Data extends WechatMiniprogram.Component.DataOption, Props extends WechatMiniprogram.Component.PropertyOption, Methods extends WechatMiniprogram.Component.MethodOption> = {
9 + data?: Data;
10 + field?: boolean;
11 + classes?: string[];
12 + mixins?: string[];
13 + props?: Props;
14 + relation?: {
15 + relations: Record<string, WechatMiniprogram.Component.RelationOption>;
16 + mixin: string;
17 + };
18 + methods?: Methods;
19 + beforeCreate?: () => void;
20 + created?: () => void;
21 + mounted?: () => void;
22 + destroyed?: () => void;
23 +} & ThisType<VantComponentInstance & WechatMiniprogram.Component.Instance<Data & {
24 + name: string;
25 + value: any;
26 +} & Record<string, any>, Props, Methods> & Record<string, any>>;
27 +export {};
1 +/// <reference types="miniprogram-api-typings" />
2 +export declare type Action = 'confirm' | 'cancel' | 'overlay';
3 +interface DialogOptions {
4 + lang?: string;
5 + show?: boolean;
6 + title?: string;
7 + width?: string | number | null;
8 + zIndex?: number;
9 + theme?: string;
10 + context?: WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance;
11 + message?: string;
12 + overlay?: boolean;
13 + selector?: string;
14 + ariaLabel?: string;
15 + className?: string;
16 + customStyle?: string;
17 + transition?: string;
18 + /**
19 + * @deprecated use beforeClose instead
20 + */
21 + asyncClose?: boolean;
22 + beforeClose?: null | ((action: Action) => Promise<void | boolean> | void);
23 + businessId?: number;
24 + sessionFrom?: string;
25 + overlayStyle?: string;
26 + appParameter?: string;
27 + messageAlign?: string;
28 + sendMessageImg?: string;
29 + showMessageCard?: boolean;
30 + sendMessagePath?: string;
31 + sendMessageTitle?: string;
32 + confirmButtonText?: string;
33 + cancelButtonText?: string;
34 + showConfirmButton?: boolean;
35 + showCancelButton?: boolean;
36 + closeOnClickOverlay?: boolean;
37 + confirmButtonOpenType?: string;
38 +}
39 +declare const Dialog: {
40 + (options: DialogOptions): Promise<WechatMiniprogram.Component.TrivialInstance>;
41 + alert(options: DialogOptions): Promise<WechatMiniprogram.Component.TrivialInstance>;
42 + confirm(options: DialogOptions): Promise<WechatMiniprogram.Component.TrivialInstance>;
43 + close(): void;
44 + stopLoading(): void;
45 + currentOptions: DialogOptions;
46 + defaultOptions: DialogOptions;
47 + setDefaultOptions(options: DialogOptions): void;
48 + resetDefaultOptions(): void;
49 +};
50 +export default Dialog;
1 +let queue = [];
2 +const defaultOptions = {
3 + show: false,
4 + title: '',
5 + width: null,
6 + theme: 'default',
7 + message: '',
8 + zIndex: 100,
9 + overlay: true,
10 + selector: '#van-dialog',
11 + className: '',
12 + asyncClose: false,
13 + beforeClose: null,
14 + transition: 'scale',
15 + customStyle: '',
16 + messageAlign: '',
17 + overlayStyle: '',
18 + confirmButtonText: '确认',
19 + cancelButtonText: '取消',
20 + showConfirmButton: true,
21 + showCancelButton: false,
22 + closeOnClickOverlay: false,
23 + confirmButtonOpenType: '',
24 +};
25 +let currentOptions = Object.assign({}, defaultOptions);
26 +function getContext() {
27 + const pages = getCurrentPages();
28 + return pages[pages.length - 1];
29 +}
30 +const Dialog = (options) => {
31 + options = Object.assign(Object.assign({}, currentOptions), options);
32 + return new Promise((resolve, reject) => {
33 + const context = options.context || getContext();
34 + const dialog = context.selectComponent(options.selector);
35 + delete options.context;
36 + delete options.selector;
37 + if (dialog) {
38 + dialog.setData(Object.assign({ callback: (action, instance) => {
39 + action === 'confirm' ? resolve(instance) : reject(instance);
40 + } }, options));
41 + wx.nextTick(() => {
42 + dialog.setData({ show: true });
43 + });
44 + queue.push(dialog);
45 + }
46 + else {
47 + console.warn('未找到 van-dialog 节点,请确认 selector 及 context 是否正确');
48 + }
49 + });
50 +};
51 +Dialog.alert = (options) => Dialog(options);
52 +Dialog.confirm = (options) => Dialog(Object.assign({ showCancelButton: true }, options));
53 +Dialog.close = () => {
54 + queue.forEach((dialog) => {
55 + dialog.close();
56 + });
57 + queue = [];
58 +};
59 +Dialog.stopLoading = () => {
60 + queue.forEach((dialog) => {
61 + dialog.stopLoading();
62 + });
63 +};
64 +Dialog.currentOptions = currentOptions;
65 +Dialog.defaultOptions = defaultOptions;
66 +Dialog.setDefaultOptions = (options) => {
67 + currentOptions = Object.assign(Object.assign({}, currentOptions), options);
68 + Dialog.currentOptions = currentOptions;
69 +};
70 +Dialog.resetDefaultOptions = () => {
71 + currentOptions = Object.assign({}, defaultOptions);
72 + Dialog.currentOptions = currentOptions;
73 +};
74 +Dialog.resetDefaultOptions();
75 +export default Dialog;
1 +import { VantComponent } from '../common/component';
2 +import { button } from '../mixins/button';
3 +import { GRAY, RED } from '../common/color';
4 +import { toPromise } from '../common/utils';
5 +VantComponent({
6 + mixins: [button],
7 + props: {
8 + show: {
9 + type: Boolean,
10 + observer(show) {
11 + !show && this.stopLoading();
12 + },
13 + },
14 + title: String,
15 + message: String,
16 + theme: {
17 + type: String,
18 + value: 'default',
19 + },
20 + useSlot: Boolean,
21 + className: String,
22 + customStyle: String,
23 + asyncClose: Boolean,
24 + messageAlign: String,
25 + beforeClose: null,
26 + overlayStyle: String,
27 + useTitleSlot: Boolean,
28 + showCancelButton: Boolean,
29 + closeOnClickOverlay: Boolean,
30 + confirmButtonOpenType: String,
31 + width: null,
32 + zIndex: {
33 + type: Number,
34 + value: 2000,
35 + },
36 + confirmButtonText: {
37 + type: String,
38 + value: '确认',
39 + },
40 + cancelButtonText: {
41 + type: String,
42 + value: '取消',
43 + },
44 + confirmButtonColor: {
45 + type: String,
46 + value: RED,
47 + },
48 + cancelButtonColor: {
49 + type: String,
50 + value: GRAY,
51 + },
52 + showConfirmButton: {
53 + type: Boolean,
54 + value: true,
55 + },
56 + overlay: {
57 + type: Boolean,
58 + value: true,
59 + },
60 + transition: {
61 + type: String,
62 + value: 'scale',
63 + },
64 + },
65 + data: {
66 + loading: {
67 + confirm: false,
68 + cancel: false,
69 + },
70 + callback: (() => { }),
71 + },
72 + methods: {
73 + onConfirm() {
74 + this.handleAction('confirm');
75 + },
76 + onCancel() {
77 + this.handleAction('cancel');
78 + },
79 + onClickOverlay() {
80 + this.close('overlay');
81 + },
82 + close(action) {
83 + this.setData({ show: false });
84 + wx.nextTick(() => {
85 + this.$emit('close', action);
86 + const { callback } = this.data;
87 + if (callback) {
88 + callback(action, this);
89 + }
90 + });
91 + },
92 + stopLoading() {
93 + this.setData({
94 + loading: {
95 + confirm: false,
96 + cancel: false,
97 + },
98 + });
99 + },
100 + handleAction(action) {
101 + this.$emit(action, { dialog: this });
102 + const { asyncClose, beforeClose } = this.data;
103 + if (!asyncClose && !beforeClose) {
104 + this.close(action);
105 + return;
106 + }
107 + this.setData({
108 + [`loading.${action}`]: true,
109 + });
110 + if (beforeClose) {
111 + toPromise(beforeClose(action)).then((value) => {
112 + if (value) {
113 + this.close(action);
114 + }
115 + else {
116 + this.stopLoading();
117 + }
118 + });
119 + }
120 + },
121 + },
122 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-popup": "../popup/index",
5 + "van-button": "../button/index",
6 + "van-goods-action": "../goods-action/index",
7 + "van-goods-action-button": "../goods-action-button/index"
8 + }
9 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<van-popup
4 + show="{{ show }}"
5 + z-index="{{ zIndex }}"
6 + overlay="{{ overlay }}"
7 + transition="{{ transition }}"
8 + custom-class="van-dialog van-dialog--{{ theme }} {{ className }}"
9 + custom-style="width: {{ utils.addUnit(width) }};{{ customStyle }}"
10 + overlay-style="{{ overlayStyle }}"
11 + close-on-click-overlay="{{ closeOnClickOverlay }}"
12 + bind:close="onClickOverlay"
13 +>
14 + <view
15 + wx:if="{{ title || useTitleSlot }}"
16 + class="{{ utils.bem('dialog__header', { isolated: !(message || useSlot) }) }}"
17 + >
18 + <slot wx:if="{{ useTitleSlot }}" name="title" />
19 + <block wx:elif="{{ title }}">{{ title }}</block>
20 + </view>
21 +
22 + <slot wx:if="{{ useSlot }}" />
23 + <view
24 + wx:elif="{{ message }}"
25 + class="{{ utils.bem('dialog__message', [theme, messageAlign, { hasTitle: title }]) }}"
26 + >
27 + <text class="van-dialog__message-text">{{ message }}</text>
28 + </view>
29 +
30 + <van-goods-action wx:if="{{ theme === 'round-button' }}" custom-class="van-dialog__footer--round-button">
31 + <van-goods-action-button
32 + wx:if="{{ showCancelButton }}"
33 + size="large"
34 + loading="{{ loading.cancel }}"
35 + class="van-dialog__button van-hairline--right"
36 + custom-class="van-dialog__cancel"
37 + custom-style="color: {{ cancelButtonColor }}"
38 + bind:click="onCancel"
39 + >
40 + {{ cancelButtonText }}
41 + </van-goods-action-button>
42 + <van-goods-action-button
43 + wx:if="{{ showConfirmButton }}"
44 + size="large"
45 + class="van-dialog__button"
46 + loading="{{ loading.confirm }}"
47 + custom-class="van-dialog__confirm"
48 + custom-style="color: {{ confirmButtonColor }}"
49 +
50 + open-type="{{ confirmButtonOpenType }}"
51 + lang="{{ lang }}"
52 + business-id="{{ businessId }}"
53 + session-from="{{ sessionFrom }}"
54 + send-message-title="{{ sendMessageTitle }}"
55 + send-message-path="{{ sendMessagePath }}"
56 + send-message-img="{{ sendMessageImg }}"
57 + show-message-card="{{ showMessageCard }}"
58 + app-parameter="{{ appParameter }}"
59 +
60 + bind:click="onConfirm"
61 + bindgetuserinfo="onGetUserInfo"
62 + bindcontact="onContact"
63 + bindgetphonenumber="onGetPhoneNumber"
64 + binderror="onError"
65 + bindlaunchapp="onLaunchApp"
66 + bindopensetting="onOpenSetting"
67 + >
68 + {{ confirmButtonText }}
69 + </van-goods-action-button>
70 + </van-goods-action>
71 +
72 + <view wx:else class="van-hairline--top van-dialog__footer">
73 + <van-button
74 + wx:if="{{ showCancelButton }}"
75 + size="large"
76 + loading="{{ loading.cancel }}"
77 + class="van-dialog__button van-hairline--right"
78 + custom-class="van-dialog__cancel"
79 + custom-style="color: {{ cancelButtonColor }}"
80 + bind:click="onCancel"
81 + >
82 + {{ cancelButtonText }}
83 + </van-button>
84 + <van-button
85 + wx:if="{{ showConfirmButton }}"
86 + size="large"
87 + class="van-dialog__button"
88 + loading="{{ loading.confirm }}"
89 + custom-class="van-dialog__confirm"
90 + custom-style="color: {{ confirmButtonColor }}"
91 +
92 + open-type="{{ confirmButtonOpenType }}"
93 + lang="{{ lang }}"
94 + business-id="{{ businessId }}"
95 + session-from="{{ sessionFrom }}"
96 + send-message-title="{{ sendMessageTitle }}"
97 + send-message-path="{{ sendMessagePath }}"
98 + send-message-img="{{ sendMessageImg }}"
99 + show-message-card="{{ showMessageCard }}"
100 + app-parameter="{{ appParameter }}"
101 +
102 + bind:click="onConfirm"
103 + bindgetuserinfo="onGetUserInfo"
104 + bindcontact="onContact"
105 + bindgetphonenumber="onGetPhoneNumber"
106 + binderror="onError"
107 + bindlaunchapp="onLaunchApp"
108 + bindopensetting="onOpenSetting"
109 + >
110 + {{ confirmButtonText }}
111 + </van-button>
112 + </view>
113 +</van-popup>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + props: {
4 + dashed: Boolean,
5 + hairline: Boolean,
6 + contentPosition: String,
7 + fontSize: String,
8 + borderColor: String,
9 + textColor: String,
10 + customStyle: String,
11 + },
12 +});
1 +{
2 + "component": true,
3 + "usingComponents": {}
4 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view
5 + class="custom-class {{ utils.bem('divider', [{ dashed, hairline }, contentPosition]) }}"
6 + style="{{ computed.rootStyle({ borderColor, textColor, fontSize, customStyle }) }}"
7 +>
8 + <slot />
9 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function rootStyle(data) {
6 + return style([
7 + {
8 + 'border-color': data.borderColor,
9 + color: data.textColor,
10 + 'font-size': addUnit(data.fontSize),
11 + },
12 + data.customStyle,
13 + ]);
14 +}
15 +
16 +module.exports = {
17 + rootStyle: rootStyle,
18 +};
1 +@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 ...\ No newline at end of file
1 +import { useParent } from '../common/relation';
2 +import { VantComponent } from '../common/component';
3 +VantComponent({
4 + field: true,
5 + relation: useParent('dropdown-menu', function () {
6 + this.updateDataFromParent();
7 + }),
8 + props: {
9 + value: {
10 + type: null,
11 + observer: 'rerender',
12 + },
13 + title: {
14 + type: String,
15 + observer: 'rerender',
16 + },
17 + disabled: Boolean,
18 + titleClass: {
19 + type: String,
20 + observer: 'rerender',
21 + },
22 + options: {
23 + type: Array,
24 + value: [],
25 + observer: 'rerender',
26 + },
27 + popupStyle: String,
28 + },
29 + data: {
30 + transition: true,
31 + showPopup: false,
32 + showWrapper: false,
33 + displayTitle: '',
34 + },
35 + methods: {
36 + rerender() {
37 + wx.nextTick(() => {
38 + var _a;
39 + (_a = this.parent) === null || _a === void 0 ? void 0 : _a.updateItemListData();
40 + });
41 + },
42 + updateDataFromParent() {
43 + if (this.parent) {
44 + const { overlay, duration, activeColor, closeOnClickOverlay, direction, } = this.parent.data;
45 + this.setData({
46 + overlay,
47 + duration,
48 + activeColor,
49 + closeOnClickOverlay,
50 + direction,
51 + });
52 + }
53 + },
54 + onOpen() {
55 + this.$emit('open');
56 + },
57 + onOpened() {
58 + this.$emit('opened');
59 + },
60 + onClose() {
61 + this.$emit('close');
62 + },
63 + onClosed() {
64 + this.$emit('closed');
65 + this.setData({ showWrapper: false });
66 + },
67 + onOptionTap(event) {
68 + const { option } = event.currentTarget.dataset;
69 + const { value } = option;
70 + const shouldEmitChange = this.data.value !== value;
71 + this.setData({ showPopup: false, value });
72 + this.$emit('close');
73 + this.rerender();
74 + if (shouldEmitChange) {
75 + this.$emit('change', value);
76 + }
77 + },
78 + toggle(show, options = {}) {
79 + var _a;
80 + const { showPopup } = this.data;
81 + if (typeof show !== 'boolean') {
82 + show = !showPopup;
83 + }
84 + if (show === showPopup) {
85 + return;
86 + }
87 + this.setData({
88 + transition: !options.immediate,
89 + showPopup: show,
90 + });
91 + if (show) {
92 + (_a = this.parent) === null || _a === void 0 ? void 0 : _a.getChildWrapperStyle().then((wrapperStyle) => {
93 + this.setData({ wrapperStyle, showWrapper: true });
94 + this.rerender();
95 + });
96 + }
97 + else {
98 + this.rerender();
99 + }
100 + },
101 + },
102 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-popup": "../popup/index",
5 + "van-cell": "../cell/index",
6 + "van-icon": "../icon/index"
7 + }
8 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view
4 + wx:if="{{ showWrapper }}"
5 + class="{{ utils.bem('dropdown-item', direction) }}"
6 + style="{{ wrapperStyle }}"
7 +>
8 + <van-popup
9 + show="{{ showPopup }}"
10 + custom-style="position: absolute;{{ popupStyle }}"
11 + overlay-style="position: absolute;"
12 + overlay="{{ overlay }}"
13 + position="{{ direction === 'down' ? 'top' : 'bottom' }}"
14 + duration="{{ transition ? duration : 0 }}"
15 + close-on-click-overlay="{{ closeOnClickOverlay }}"
16 + bind:enter="onOpen"
17 + bind:leave="onClose"
18 + bind:close="toggle"
19 + bind:after-enter="onOpened"
20 + bind:after-leave="onClosed"
21 + >
22 + <van-cell
23 + wx:for="{{ options }}"
24 + wx:key="value"
25 + data-option="{{ item }}"
26 + class="{{ utils.bem('dropdown-item__option', { active: item.value === value } ) }}"
27 + clickable
28 + icon="{{ item.icon }}"
29 + bind:tap="onOptionTap"
30 + >
31 + <view
32 + slot="title"
33 + class="van-dropdown-item__title"
34 + style="{{ item.value === value ? 'color:' + activeColor : '' }}"
35 + >
36 + {{ item.text }}
37 + </view>
38 + <van-icon
39 + wx:if="{{ item.value === value }}"
40 + name="success"
41 + class="van-dropdown-item__icon"
42 + color="{{ activeColor }}"
43 + />
44 + </van-cell>
45 +
46 + <slot />
47 + </van-popup>
48 +</view>
1 +@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 ...\ No newline at end of file
1 +export interface Option {
2 + text: string;
3 + value: string | number;
4 + icon: string;
5 +}
1 +import { VantComponent } from '../common/component';
2 +import { useChildren } from '../common/relation';
3 +import { addUnit, getRect, getSystemInfoSync } from '../common/utils';
4 +let ARRAY = [];
5 +VantComponent({
6 + field: true,
7 + relation: useChildren('dropdown-item', function () {
8 + this.updateItemListData();
9 + }),
10 + props: {
11 + activeColor: {
12 + type: String,
13 + observer: 'updateChildrenData',
14 + },
15 + overlay: {
16 + type: Boolean,
17 + value: true,
18 + observer: 'updateChildrenData',
19 + },
20 + zIndex: {
21 + type: Number,
22 + value: 10,
23 + },
24 + duration: {
25 + type: Number,
26 + value: 200,
27 + observer: 'updateChildrenData',
28 + },
29 + direction: {
30 + type: String,
31 + value: 'down',
32 + observer: 'updateChildrenData',
33 + },
34 + closeOnClickOverlay: {
35 + type: Boolean,
36 + value: true,
37 + observer: 'updateChildrenData',
38 + },
39 + closeOnClickOutside: {
40 + type: Boolean,
41 + value: true,
42 + },
43 + },
44 + data: {
45 + itemListData: [],
46 + },
47 + beforeCreate() {
48 + const { windowHeight } = getSystemInfoSync();
49 + this.windowHeight = windowHeight;
50 + ARRAY.push(this);
51 + },
52 + destroyed() {
53 + ARRAY = ARRAY.filter((item) => item !== this);
54 + },
55 + methods: {
56 + updateItemListData() {
57 + this.setData({
58 + itemListData: this.children.map((child) => child.data),
59 + });
60 + },
61 + updateChildrenData() {
62 + this.children.forEach((child) => {
63 + child.updateDataFromParent();
64 + });
65 + },
66 + toggleItem(active) {
67 + this.children.forEach((item, index) => {
68 + const { showPopup } = item.data;
69 + if (index === active) {
70 + item.toggle();
71 + }
72 + else if (showPopup) {
73 + item.toggle(false, { immediate: true });
74 + }
75 + });
76 + },
77 + close() {
78 + this.children.forEach((child) => {
79 + child.toggle(false, { immediate: true });
80 + });
81 + },
82 + getChildWrapperStyle() {
83 + const { zIndex, direction } = this.data;
84 + return getRect(this, '.van-dropdown-menu').then((rect) => {
85 + const { top = 0, bottom = 0 } = rect;
86 + const offset = direction === 'down' ? bottom : this.windowHeight - top;
87 + let wrapperStyle = `z-index: ${zIndex};`;
88 + if (direction === 'down') {
89 + wrapperStyle += `top: ${addUnit(offset)};`;
90 + }
91 + else {
92 + wrapperStyle += `bottom: ${addUnit(offset)};`;
93 + }
94 + return wrapperStyle;
95 + });
96 + },
97 + onTitleTap(event) {
98 + const { index } = event.currentTarget.dataset;
99 + const child = this.children[index];
100 + if (!child.data.disabled) {
101 + ARRAY.forEach((menuItem) => {
102 + if (menuItem &&
103 + menuItem.data.closeOnClickOutside &&
104 + menuItem !== this) {
105 + menuItem.close();
106 + }
107 + });
108 + this.toggleItem(index);
109 + }
110 + },
111 + },
112 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view class="van-dropdown-menu van-dropdown-menu--top-bottom custom-class">
5 + <view
6 + wx:for="{{ itemListData }}"
7 + wx:key="index"
8 + data-index="{{ index }}"
9 + class="{{ utils.bem('dropdown-menu__item', { disabled: item.disabled }) }}"
10 + bind:tap="onTitleTap"
11 + >
12 + <view
13 + class="{{ item.titleClass }} {{ utils.bem('dropdown-menu__title', { active: item.showPopup, down: item.showPopup === (direction === 'down') }) }}"
14 + style="{{ item.showPopup ? 'color:' + activeColor : '' }}"
15 + >
16 + <view class="van-ellipsis">
17 + {{ computed.displayTitle(item) }}
18 + </view>
19 + </view>
20 + </view>
21 +
22 + <slot />
23 +</view>
1 +/* eslint-disable */
2 +function displayTitle(item) {
3 + if (item.title) {
4 + return item.title;
5 + }
6 +
7 + var match = item.options.filter(function(option) {
8 + return option.value === item.value;
9 + });
10 + var displayTitle = match.length ? match[0].text : '';
11 + return displayTitle;
12 +}
13 +
14 +module.exports = {
15 + displayTitle: displayTitle
16 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + props: {
4 + description: String,
5 + image: {
6 + type: String,
7 + value: 'default',
8 + },
9 + },
10 +});
1 +{
2 + "component": true,
3 + "usingComponents": {}
4 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view class="custom-class van-empty">
5 + <view class="van-empty__image">
6 + <slot name="image"></slot>
7 + </view>
8 + <view class="van-empty__image">
9 + <image wx:if="{{ image }}" class="van-empty__image__img" src="{{ computed.imageUrl(image) }}" />
10 + </view>
11 +
12 + <view class="van-empty__description">
13 + <slot name="description"></slot>
14 + </view>
15 + <view class="van-empty__description">
16 + {{ description }}
17 + </view>
18 +
19 + <view class="van-empty__bottom">
20 + <slot></slot>
21 + </view>
22 +</view>
1 +/* eslint-disable */
2 +var PRESETS = ['error', 'search', 'default', 'network'];
3 +
4 +function imageUrl(image) {
5 + if (PRESETS.indexOf(image) !== -1) {
6 + return 'https://img.yzcdn.cn/vant/empty-image-' + image + '.png';
7 + }
8 +
9 + return image;
10 +}
11 +
12 +module.exports = {
13 + imageUrl: imageUrl,
14 +};
15 +
1 +@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 ...\ No newline at end of file
1 +import { nextTick } from '../common/utils';
2 +import { VantComponent } from '../common/component';
3 +import { commonProps, inputProps, textareaProps } from './props';
4 +VantComponent({
5 + field: true,
6 + classes: ['input-class', 'right-icon-class', 'label-class'],
7 + 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: {
8 + type: Boolean,
9 + observer: 'setShowClear',
10 + }, clearable: {
11 + type: Boolean,
12 + observer: 'setShowClear',
13 + }, clearTrigger: {
14 + type: String,
15 + value: 'focus',
16 + }, border: {
17 + type: Boolean,
18 + value: true,
19 + }, titleWidth: {
20 + type: String,
21 + value: '6.2em',
22 + }, clearIcon: {
23 + type: String,
24 + value: 'clear',
25 + } }),
26 + data: {
27 + focused: false,
28 + innerValue: '',
29 + showClear: false,
30 + },
31 + created() {
32 + this.value = this.data.value;
33 + this.setData({ innerValue: this.value });
34 + },
35 + methods: {
36 + onInput(event) {
37 + const { value = '' } = event.detail || {};
38 + this.value = value;
39 + this.setShowClear();
40 + this.emitChange();
41 + },
42 + onFocus(event) {
43 + this.focused = true;
44 + this.setShowClear();
45 + this.$emit('focus', event.detail);
46 + },
47 + onBlur(event) {
48 + this.focused = false;
49 + this.setShowClear();
50 + this.$emit('blur', event.detail);
51 + },
52 + onClickIcon() {
53 + this.$emit('click-icon');
54 + },
55 + onClickInput(event) {
56 + this.$emit('click-input', event.detail);
57 + },
58 + onClear() {
59 + this.setData({ innerValue: '' });
60 + this.value = '';
61 + this.setShowClear();
62 + nextTick(() => {
63 + this.emitChange();
64 + this.$emit('clear', '');
65 + });
66 + },
67 + onConfirm(event) {
68 + const { value = '' } = event.detail || {};
69 + this.value = value;
70 + this.setShowClear();
71 + this.$emit('confirm', value);
72 + },
73 + setValue(value) {
74 + this.value = value;
75 + this.setShowClear();
76 + if (value === '') {
77 + this.setData({ innerValue: '' });
78 + }
79 + this.emitChange();
80 + },
81 + onLineChange(event) {
82 + this.$emit('linechange', event.detail);
83 + },
84 + onKeyboardHeightChange(event) {
85 + this.$emit('keyboardheightchange', event.detail);
86 + },
87 + emitChange() {
88 + this.setData({ value: this.value });
89 + nextTick(() => {
90 + this.$emit('input', this.value);
91 + this.$emit('change', this.value);
92 + });
93 + },
94 + setShowClear() {
95 + const { clearable, readonly, clearTrigger } = this.data;
96 + const { focused, value } = this;
97 + let showClear = false;
98 + if (clearable && !readonly) {
99 + const hasValue = !!value;
100 + const trigger = clearTrigger === 'always' || (clearTrigger === 'focus' && focused);
101 + showClear = hasValue && trigger;
102 + }
103 + this.setData({ showClear });
104 + },
105 + noop() { },
106 + },
107 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-cell": "../cell/index",
5 + "van-icon": "../icon/index"
6 + }
7 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<van-cell
5 + size="{{ size }}"
6 + icon="{{ leftIcon }}"
7 + center="{{ center }}"
8 + border="{{ border }}"
9 + is-link="{{ isLink }}"
10 + required="{{ required }}"
11 + clickable="{{ clickable }}"
12 + title-width="{{ titleWidth }}"
13 + title-style="margin-right: 12px;"
14 + custom-style="{{ customStyle }}"
15 + arrow-direction="{{ arrowDirection }}"
16 + custom-class="van-field"
17 +>
18 + <slot name="left-icon" slot="icon" />
19 + <view wx:if="{{ label }}" class="label-class {{ utils.bem('field__label', { disabled }) }}" slot="title">
20 + {{ label }}
21 + </view>
22 + <slot wx:else name="label" slot="title" />
23 + <view class="{{ utils.bem('field__body', [type]) }}">
24 + <view class="{{ utils.bem('field__control', [inputAlign, 'custom']) }}" bindtap="onClickInput">
25 + <slot name="input" />
26 + </view>
27 + <include wx:if="{{ type === 'textarea' }}" src="./textarea.wxml" />
28 + <include wx:else src="./input.wxml" />
29 +
30 + <van-icon
31 + wx:if="{{ showClear }}"
32 + name="{{ clearIcon }}"
33 + class="van-field__clear-root van-field__icon-root"
34 + catch:touchstart="onClear"
35 + />
36 + <view class="van-field__icon-container" bind:tap="onClickIcon">
37 + <van-icon
38 + wx:if="{{ rightIcon || icon }}"
39 + name="{{ rightIcon || icon }}"
40 + class="van-field__icon-root {{ iconClass }}"
41 + custom-class="right-icon-class"
42 + />
43 + <slot name="right-icon" />
44 + <slot name="icon" />
45 + </view>
46 + <view class="van-field__button">
47 + <slot name="button" />
48 + </view>
49 + </view>
50 + <view wx:if="{{ showWordLimit && maxlength }}" class="van-field__word-limit">
51 + <view class="{{ utils.bem('field__word-num', { full: value.length >= maxlength }) }}">{{ value.length >= maxlength ? maxlength : value.length }}</view>/{{ maxlength }}
52 + </view>
53 + <view wx:if="{{ errorMessage }}" class="{{ utils.bem('field__error-message', [errorMessageAlign, { disabled, error }]) }}">
54 + {{ errorMessage }}
55 + </view>
56 +</van-cell>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function inputStyle(autosize) {
6 + if (autosize && autosize.constructor === 'Object') {
7 + return style({
8 + 'min-height': addUnit(autosize.minHeight),
9 + 'max-height': addUnit(autosize.maxHeight),
10 + });
11 + }
12 +
13 + return '';
14 +}
15 +
16 +module.exports = {
17 + inputStyle: inputStyle,
18 +};
1 +@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 ...\ No newline at end of file
1 +<input
2 + class="{{ utils.bem('field__control', [inputAlign, { disabled, error }]) }} input-class"
3 + type="{{ type }}"
4 + focus="{{ focus }}"
5 + cursor="{{ cursor }}"
6 + value="{{ innerValue }}"
7 + auto-focus="{{ autoFocus }}"
8 + disabled="{{ disabled || readonly }}"
9 + maxlength="{{ maxlength }}"
10 + placeholder="{{ placeholder }}"
11 + placeholder-style="{{ placeholderStyle }}"
12 + placeholder-class="{{ utils.bem('field__placeholder', { error }) }}"
13 + confirm-type="{{ confirmType }}"
14 + confirm-hold="{{ confirmHold }}"
15 + hold-keyboard="{{ holdKeyboard }}"
16 + cursor-spacing="{{ cursorSpacing }}"
17 + adjust-position="{{ adjustPosition }}"
18 + selection-end="{{ selectionEnd }}"
19 + selection-start="{{ selectionStart }}"
20 + always-embed="{{ alwaysEmbed }}"
21 + password="{{ password || type === 'password' }}"
22 + bindinput="onInput"
23 + bindtap="onClickInput"
24 + bindblur="onBlur"
25 + bindfocus="onFocus"
26 + bindconfirm="onConfirm"
27 + bindkeyboardheightchange="onKeyboardHeightChange"
28 +/>
1 +/// <reference types="miniprogram-api-typings" />
2 +export declare const commonProps: WechatMiniprogram.Component.PropertyOption;
3 +export declare const inputProps: WechatMiniprogram.Component.PropertyOption;
4 +export declare const textareaProps: WechatMiniprogram.Component.PropertyOption;
1 +export const commonProps = {
2 + value: {
3 + type: String,
4 + observer(value) {
5 + if (value !== this.value) {
6 + this.setData({ innerValue: value });
7 + this.value = value;
8 + }
9 + },
10 + },
11 + placeholder: String,
12 + placeholderStyle: String,
13 + placeholderClass: String,
14 + disabled: Boolean,
15 + maxlength: {
16 + type: Number,
17 + value: -1,
18 + },
19 + cursorSpacing: {
20 + type: Number,
21 + value: 50,
22 + },
23 + autoFocus: Boolean,
24 + focus: Boolean,
25 + cursor: {
26 + type: Number,
27 + value: -1,
28 + },
29 + selectionStart: {
30 + type: Number,
31 + value: -1,
32 + },
33 + selectionEnd: {
34 + type: Number,
35 + value: -1,
36 + },
37 + adjustPosition: {
38 + type: Boolean,
39 + value: true,
40 + },
41 + holdKeyboard: Boolean,
42 +};
43 +export const inputProps = {
44 + type: {
45 + type: String,
46 + value: 'text',
47 + },
48 + password: Boolean,
49 + confirmType: String,
50 + confirmHold: Boolean,
51 + alwaysEmbed: Boolean,
52 +};
53 +export const textareaProps = {
54 + autoHeight: Boolean,
55 + fixed: Boolean,
56 + showConfirmBar: {
57 + type: Boolean,
58 + value: true,
59 + },
60 + disableDefaultPadding: {
61 + type: Boolean,
62 + value: true,
63 + },
64 +};
1 +<textarea
2 + class="{{ utils.bem('field__control', [inputAlign, type, { disabled, error }]) }} input-class"
3 + fixed="{{ fixed }}"
4 + focus="{{ focus }}"
5 + cursor="{{ cursor }}"
6 + value="{{ innerValue }}"
7 + auto-focus="{{ autoFocus }}"
8 + disabled="{{ disabled || readonly }}"
9 + maxlength="{{ maxlength }}"
10 + placeholder="{{ placeholder }}"
11 + placeholder-style="{{ placeholderStyle }}"
12 + placeholder-class="{{ utils.bem('field__placeholder', { error, disabled }) }}"
13 + auto-height="{{ !!autosize }}"
14 + style="{{ computed.inputStyle(autosize) }}"
15 + cursor-spacing="{{ cursorSpacing }}"
16 + adjust-position="{{ adjustPosition }}"
17 + show-confirm-bar="{{ showConfirmBar }}"
18 + hold-keyboard="{{ holdKeyboard }}"
19 + selection-end="{{ selectionEnd }}"
20 + selection-start="{{ selectionStart }}"
21 + disable-default-padding="{{ disableDefaultPadding }}"
22 + bindinput="onInput"
23 + bindtap="onClickInput"
24 + bindblur="onBlur"
25 + bindfocus="onFocus"
26 + bindconfirm="onConfirm"
27 + bindlinechange="onLineChange"
28 + bindkeyboardheightchange="onKeyboardHeightChange"
29 +/>
1 +import { VantComponent } from '../common/component';
2 +import { useParent } from '../common/relation';
3 +import { button } from '../mixins/button';
4 +import { link } from '../mixins/link';
5 +VantComponent({
6 + mixins: [link, button],
7 + relation: useParent('goods-action'),
8 + props: {
9 + text: String,
10 + color: String,
11 + loading: Boolean,
12 + disabled: Boolean,
13 + plain: Boolean,
14 + type: {
15 + type: String,
16 + value: 'danger',
17 + },
18 + },
19 + methods: {
20 + onClick(event) {
21 + this.$emit('click', event.detail);
22 + this.jumpLink();
23 + },
24 + updateStyle() {
25 + if (this.parent == null) {
26 + return;
27 + }
28 + const { index } = this;
29 + const { children = [] } = this.parent;
30 + this.setData({
31 + isFirst: index === 0,
32 + isLast: index === children.length - 1,
33 + });
34 + },
35 + },
36 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-button": "../button/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<van-button
3 + id="{{ id }}"
4 + lang="{{ lang }}"
5 + type="{{ type }}"
6 + color="{{ color }}"
7 + plain="{{ plain }}"
8 + loading="{{ loading }}"
9 + disabled="{{ disabled }}"
10 + open-type="{{ openType }}"
11 + class="{{ utils.bem('goods-action-button', [type, { first: isFirst, last: isLast, plain: plain }])}}"
12 + custom-class="van-goods-action-button__inner"
13 + business-id="{{ businessId }}"
14 + session-from="{{ sessionFrom }}"
15 + app-parameter="{{ appParameter }}"
16 + send-message-img="{{ sendMessageImg }}"
17 + send-message-path="{{ sendMessagePath }}"
18 + show-message-card="{{ showMessageCard }}"
19 + send-message-title="{{ sendMessageTitle }}"
20 + bind:click="onClick"
21 + binderror="onError"
22 + bindcontact="onContact"
23 + bindopensetting="onOpenSetting"
24 + bindgetuserinfo="onGetUserInfo"
25 + bindgetphonenumber="onGetPhoneNumber"
26 + bindlaunchapp="onLaunchApp"
27 +>
28 + {{ text }}
29 + <slot></slot>
30 +</van-button>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { button } from '../mixins/button';
3 +import { link } from '../mixins/link';
4 +VantComponent({
5 + classes: ['icon-class', 'text-class'],
6 + mixins: [link, button],
7 + props: {
8 + text: String,
9 + dot: Boolean,
10 + info: String,
11 + icon: String,
12 + classPrefix: {
13 + type: String,
14 + value: 'van-icon',
15 + },
16 + disabled: Boolean,
17 + loading: Boolean,
18 + },
19 + methods: {
20 + onClick(event) {
21 + this.$emit('click', event.detail);
22 + this.jumpLink();
23 + },
24 + },
25 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index",
5 + "van-button": "../button/index"
6 + }
7 +}
1 +<van-button
2 + square
3 + id="{{ id }}"
4 + size="large"
5 + lang="{{ lang }}"
6 + loading="{{ loading }}"
7 + disabled="{{ disabled }}"
8 + open-type="{{ openType }}"
9 + business-id="{{ businessId }}"
10 + custom-class="van-goods-action-icon"
11 + session-from="{{ sessionFrom }}"
12 + app-parameter="{{ appParameter }}"
13 + send-message-img="{{ sendMessageImg }}"
14 + send-message-path="{{ sendMessagePath }}"
15 + show-message-card="{{ showMessageCard }}"
16 + send-message-title="{{ sendMessageTitle }}"
17 + bind:click="onClick"
18 + binderror="onError"
19 + bindcontact="onContact"
20 + bindopensetting="onOpenSetting"
21 + bindgetuserinfo="onGetUserInfo"
22 + bindgetphonenumber="onGetPhoneNumber"
23 + bindlaunchapp="onLaunchApp"
24 +>
25 + <van-icon
26 + wx:if="{{ icon }}"
27 + name="{{ icon }}"
28 + dot="{{ dot }}"
29 + info="{{ info }}"
30 + class-prefix="{{ classPrefix }}"
31 + class="van-goods-action-icon__icon"
32 + custom-class="icon-class"
33 + />
34 + <slot wx:else name="icon" />
35 + <text class="text-class">{{ text }}</text>
36 +</van-button>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { useChildren } from '../common/relation';
3 +VantComponent({
4 + relation: useChildren('goods-action-button', function () {
5 + this.children.forEach((item) => {
6 + item.updateStyle();
7 + });
8 + }),
9 + props: {
10 + safeAreaInsetBottom: {
11 + type: Boolean,
12 + value: true,
13 + },
14 + },
15 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view class="custom-class {{ utils.bem('goods-action', { safe: safeAreaInsetBottom }) }}">
4 + <slot />
5 +</view>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { useParent } from '../common/relation';
3 +import { link } from '../mixins/link';
4 +VantComponent({
5 + relation: useParent('grid'),
6 + classes: ['content-class', 'icon-class', 'text-class'],
7 + mixins: [link],
8 + props: {
9 + icon: String,
10 + iconColor: String,
11 + iconPrefix: {
12 + type: String,
13 + value: 'van-icon',
14 + },
15 + dot: Boolean,
16 + info: null,
17 + badge: null,
18 + text: String,
19 + useSlot: Boolean,
20 + },
21 + data: {
22 + viewStyle: '',
23 + },
24 + mounted() {
25 + this.updateStyle();
26 + },
27 + methods: {
28 + updateStyle() {
29 + if (!this.parent) {
30 + return;
31 + }
32 + const { data, children } = this.parent;
33 + const { columnNum, border, square, gutter, clickable, center, direction, reverse, iconSize, } = data;
34 + this.setData({
35 + center,
36 + border,
37 + square,
38 + gutter,
39 + clickable,
40 + direction,
41 + reverse,
42 + iconSize,
43 + index: children.indexOf(this),
44 + columnNum,
45 + });
46 + },
47 + onClick() {
48 + this.$emit('click');
49 + this.jumpLink();
50 + },
51 + },
52 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view
5 + class="custom-class {{ utils.bem('grid-item', { square }) }}"
6 + style="{{ computed.wrapperStyle({ square, gutter, columnNum, index }) }}"
7 + bindtap="onClick"
8 +>
9 + <view
10 + class="content-class {{ utils.bem('grid-item__content', [direction, { center, square, reverse, clickable, surround: border && gutter }]) }} {{ border ? 'van-hairline--surround' : '' }}"
11 + style="{{ computed.contentStyle({ square, gutter }) }}"
12 + >
13 + <block wx:if="{{ useSlot }}">
14 + <slot />
15 + </block>
16 + <block wx:else>
17 + <view class="van-grid-item__icon icon-class">
18 + <van-icon wx:if="{{ icon }}" name="{{ icon }}" color="{{ iconColor }}" class-prefix="{{ iconPrefix }}" dot="{{ dot }}" info="{{ badge || info }}" size="{{ iconSize }}" />
19 + <slot wx:else name="icon"></slot>
20 + </view>
21 + <view class="van-grid-item__text text-class">
22 + <text wx:if="{{ text }}">{{ text }}</text>
23 + <slot wx:else name="text"></slot>
24 + </view>
25 + </block>
26 + </view>
27 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function wrapperStyle(data) {
6 + var width = 100 / data.columnNum + '%';
7 +
8 + return style({
9 + width: width,
10 + 'padding-top': data.square ? width : null,
11 + 'padding-right': addUnit(data.gutter),
12 + 'margin-top':
13 + data.index >= data.columnNum && !data.square
14 + ? addUnit(data.gutter)
15 + : null,
16 + });
17 +}
18 +
19 +function contentStyle(data) {
20 + return data.square
21 + ? style({
22 + right: addUnit(data.gutter),
23 + bottom: addUnit(data.gutter),
24 + height: 'auto',
25 + })
26 + : '';
27 +}
28 +
29 +module.exports = {
30 + wrapperStyle: wrapperStyle,
31 + contentStyle: contentStyle,
32 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { useChildren } from '../common/relation';
3 +VantComponent({
4 + relation: useChildren('grid-item'),
5 + props: {
6 + square: {
7 + type: Boolean,
8 + observer: 'updateChildren',
9 + },
10 + gutter: {
11 + type: null,
12 + value: 0,
13 + observer: 'updateChildren',
14 + },
15 + clickable: {
16 + type: Boolean,
17 + observer: 'updateChildren',
18 + },
19 + columnNum: {
20 + type: Number,
21 + value: 4,
22 + observer: 'updateChildren',
23 + },
24 + center: {
25 + type: Boolean,
26 + value: true,
27 + observer: 'updateChildren',
28 + },
29 + border: {
30 + type: Boolean,
31 + value: true,
32 + observer: 'updateChildren',
33 + },
34 + direction: {
35 + type: String,
36 + observer: 'updateChildren',
37 + },
38 + iconSize: {
39 + type: String,
40 + observer: 'updateChildren',
41 + },
42 + reverse: {
43 + type: Boolean,
44 + value: false,
45 + observer: 'updateChildren',
46 + },
47 + },
48 + methods: {
49 + updateChildren() {
50 + this.children.forEach((child) => {
51 + child.updateStyle();
52 + });
53 + },
54 + },
55 +});
1 +<wxs src="./index.wxs" module="computed" />
2 +
3 +<view
4 + class="van-grid custom-class {{ border && !gutter ? 'van-hairline--top' : '' }}"
5 + style="{{ computed.rootStyle({ gutter }) }}"
6 +>
7 + <slot />
8 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function rootStyle(data) {
6 + return style({
7 + 'padding-left': addUnit(data.gutter),
8 + });
9 +}
10 +
11 +module.exports = {
12 + rootStyle: rootStyle,
13 +};
1 +@import '../common/index.wxss';.van-grid{box-sizing:border-box;overflow:hidden;position:relative}
...\ No newline at end of file ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + props: {
4 + dot: Boolean,
5 + info: null,
6 + size: null,
7 + color: String,
8 + customStyle: String,
9 + classPrefix: {
10 + type: String,
11 + value: 'van-icon',
12 + },
13 + name: String,
14 + },
15 + methods: {
16 + onClick() {
17 + this.$emit('click');
18 + },
19 + },
20 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-info": "../info/index"
5 + }
6 +}
1 +<wxs src="./index.wxs" module="computed" />
2 +
3 +<view
4 + class="{{ computed.rootClass({ classPrefix, name }) }}"
5 + style="{{ computed.rootStyle({ customStyle, color, size }) }}"
6 + bindtap="onClick"
7 +>
8 + <van-info
9 + wx:if="{{ info !== null || dot }}"
10 + dot="{{ dot }}"
11 + info="{{ info }}"
12 + custom-class="van-icon__info"
13 + />
14 + <image
15 + wx:if="{{ computed.isImage(name) }}"
16 + src="{{ name }}"
17 + mode="aspectFit"
18 + class="van-icon__image"
19 + />
20 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function isImage(name) {
6 + return name.indexOf('/') !== -1;
7 +}
8 +
9 +function rootClass(data) {
10 + var classes = ['custom-class'];
11 +
12 + if (data.classPrefix != null) {
13 + classes.push(data.classPrefix);
14 + }
15 +
16 + if (isImage(data.name)) {
17 + classes.push('van-icon--image');
18 + } else if (data.classPrefix != null) {
19 + classes.push(data.classPrefix + '-' + data.name);
20 + }
21 +
22 + return classes.join(' ');
23 +}
24 +
25 +function rootStyle(data) {
26 + return style([
27 + {
28 + color: data.color,
29 + 'font-size': addUnit(data.size),
30 + },
31 + data.customStyle,
32 + ]);
33 +}
34 +
35 +module.exports = {
36 + isImage: isImage,
37 + rootClass: rootClass,
38 + rootStyle: rootStyle,
39 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { button } from '../mixins/button';
3 +VantComponent({
4 + mixins: [button],
5 + classes: ['custom-class', 'loading-class', 'error-class', 'image-class'],
6 + props: {
7 + src: {
8 + type: String,
9 + observer() {
10 + this.setData({
11 + error: false,
12 + loading: true,
13 + });
14 + },
15 + },
16 + round: Boolean,
17 + width: null,
18 + height: null,
19 + radius: null,
20 + lazyLoad: Boolean,
21 + useErrorSlot: Boolean,
22 + useLoadingSlot: Boolean,
23 + showMenuByLongpress: Boolean,
24 + fit: {
25 + type: String,
26 + value: 'fill',
27 + },
28 + showError: {
29 + type: Boolean,
30 + value: true,
31 + },
32 + showLoading: {
33 + type: Boolean,
34 + value: true,
35 + },
36 + },
37 + data: {
38 + error: false,
39 + loading: true,
40 + viewStyle: '',
41 + },
42 + methods: {
43 + onLoad(event) {
44 + this.setData({
45 + loading: false,
46 + });
47 + this.$emit('load', event.detail);
48 + },
49 + onError(event) {
50 + this.setData({
51 + loading: false,
52 + error: true,
53 + });
54 + this.$emit('error', event.detail);
55 + },
56 + onClick(event) {
57 + this.$emit('click', event.detail);
58 + },
59 + },
60 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index",
5 + "van-loading": "../loading/index"
6 + }
7 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view
5 + style="{{ computed.rootStyle({ width, height, radius }) }}"
6 + class="custom-class {{ utils.bem('image', { round })}}"
7 + bind:tap="onClick"
8 +>
9 + <image
10 + wx:if="{{ !error }}"
11 + src="{{ src }}"
12 + mode="{{ computed.mode(fit) }}"
13 + lazy-load="{{ lazyLoad }}"
14 + class="image-class van-image__img"
15 + show-menu-by-longpress="{{ showMenuByLongpress }}"
16 + bind:load="onLoad"
17 + bind:error="onError"
18 + />
19 +
20 + <view
21 + wx:if="{{ loading && showLoading }}"
22 + class="loading-class van-image__loading"
23 + >
24 + <slot wx:if="{{ useLoadingSlot }}" name="loading" />
25 + <van-icon wx:else name="photo" custom-class="van-image__loading-icon" />
26 + </view>
27 + <view
28 + wx:if="{{ error && showError }}"
29 + class="error-class van-image__error"
30 + >
31 + <slot wx:if="{{ useErrorSlot }}" name="error" />
32 + <van-icon wx:else name="photo-fail" custom-class="van-image__error-icon" />
33 + </view>
34 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function rootStyle(data) {
6 + return style([
7 + {
8 + width: addUnit(data.width),
9 + height: addUnit(data.height),
10 + 'border-radius': addUnit(data.radius),
11 + },
12 + data.radius ? 'overflow: hidden' : null,
13 + ]);
14 +}
15 +
16 +var FIT_MODE_MAP = {
17 + none: 'center',
18 + fill: 'scaleToFill',
19 + cover: 'aspectFill',
20 + contain: 'aspectFit',
21 + widthFix: 'widthFix',
22 + heightFix: 'heightFix',
23 +};
24 +
25 +function mode(fit) {
26 + return FIT_MODE_MAP[fit];
27 +}
28 +
29 +module.exports = {
30 + rootStyle: rootStyle,
31 + mode: mode,
32 +};
1 +@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 ...\ No newline at end of file
1 +import { getRect } from '../common/utils';
2 +import { VantComponent } from '../common/component';
3 +import { useParent } from '../common/relation';
4 +VantComponent({
5 + relation: useParent('index-bar'),
6 + props: {
7 + useSlot: Boolean,
8 + index: null,
9 + },
10 + data: {
11 + active: false,
12 + wrapperStyle: '',
13 + anchorStyle: '',
14 + },
15 + methods: {
16 + scrollIntoView(scrollTop) {
17 + getRect(this, '.van-index-anchor-wrapper').then((rect) => {
18 + wx.pageScrollTo({
19 + duration: 0,
20 + scrollTop: scrollTop + rect.top - this.parent.data.stickyOffsetTop,
21 + });
22 + });
23 + },
24 + },
25 +});
1 +<view
2 + class="van-index-anchor-wrapper"
3 + style="{{ wrapperStyle }}"
4 +>
5 + <view
6 + class="van-index-anchor {{ active ? 'van-index-anchor--active van-hairline--bottom' : '' }}"
7 + style="{{ anchorStyle }}"
8 + >
9 + <slot wx:if="{{ useSlot }}"/>
10 + <block wx:else>
11 + <text>{{ index }}</text>
12 + </block>
13 + </view>
14 +</view>
1 +@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 ...\ No newline at end of file
1 +import { GREEN } from '../common/color';
2 +import { VantComponent } from '../common/component';
3 +import { useChildren } from '../common/relation';
4 +import { getRect, isDef } from '../common/utils';
5 +import { pageScrollMixin } from '../mixins/page-scroll';
6 +const indexList = () => {
7 + const indexList = [];
8 + const charCodeOfA = 'A'.charCodeAt(0);
9 + for (let i = 0; i < 26; i++) {
10 + indexList.push(String.fromCharCode(charCodeOfA + i));
11 + }
12 + return indexList;
13 +};
14 +VantComponent({
15 + relation: useChildren('index-anchor', function () {
16 + this.updateData();
17 + }),
18 + props: {
19 + sticky: {
20 + type: Boolean,
21 + value: true,
22 + },
23 + zIndex: {
24 + type: Number,
25 + value: 1,
26 + },
27 + highlightColor: {
28 + type: String,
29 + value: GREEN,
30 + },
31 + stickyOffsetTop: {
32 + type: Number,
33 + value: 0,
34 + },
35 + indexList: {
36 + type: Array,
37 + value: indexList(),
38 + },
39 + },
40 + mixins: [
41 + pageScrollMixin(function (event) {
42 + this.scrollTop = (event === null || event === void 0 ? void 0 : event.scrollTop) || 0;
43 + this.onScroll();
44 + }),
45 + ],
46 + data: {
47 + activeAnchorIndex: null,
48 + showSidebar: false,
49 + },
50 + created() {
51 + this.scrollTop = 0;
52 + },
53 + methods: {
54 + updateData() {
55 + wx.nextTick(() => {
56 + if (this.timer != null) {
57 + clearTimeout(this.timer);
58 + }
59 + this.timer = setTimeout(() => {
60 + this.setData({
61 + showSidebar: !!this.children.length,
62 + });
63 + this.setRect().then(() => {
64 + this.onScroll();
65 + });
66 + }, 0);
67 + });
68 + },
69 + setRect() {
70 + return Promise.all([
71 + this.setAnchorsRect(),
72 + this.setListRect(),
73 + this.setSiderbarRect(),
74 + ]);
75 + },
76 + setAnchorsRect() {
77 + return Promise.all(this.children.map((anchor) => getRect(anchor, '.van-index-anchor-wrapper').then((rect) => {
78 + Object.assign(anchor, {
79 + height: rect.height,
80 + top: rect.top + this.scrollTop,
81 + });
82 + })));
83 + },
84 + setListRect() {
85 + return getRect(this, '.van-index-bar').then((rect) => {
86 + if (!isDef(rect)) {
87 + return;
88 + }
89 + Object.assign(this, {
90 + height: rect.height,
91 + top: rect.top + this.scrollTop,
92 + });
93 + });
94 + },
95 + setSiderbarRect() {
96 + return getRect(this, '.van-index-bar__sidebar').then((res) => {
97 + if (!isDef(res)) {
98 + return;
99 + }
100 + this.sidebar = {
101 + height: res.height,
102 + top: res.top,
103 + };
104 + });
105 + },
106 + setDiffData({ target, data }) {
107 + const diffData = {};
108 + Object.keys(data).forEach((key) => {
109 + if (target.data[key] !== data[key]) {
110 + diffData[key] = data[key];
111 + }
112 + });
113 + if (Object.keys(diffData).length) {
114 + target.setData(diffData);
115 + }
116 + },
117 + getAnchorRect(anchor) {
118 + return getRect(anchor, '.van-index-anchor-wrapper').then((rect) => ({
119 + height: rect.height,
120 + top: rect.top,
121 + }));
122 + },
123 + getActiveAnchorIndex() {
124 + const { children, scrollTop } = this;
125 + const { sticky, stickyOffsetTop } = this.data;
126 + for (let i = this.children.length - 1; i >= 0; i--) {
127 + const preAnchorHeight = i > 0 ? children[i - 1].height : 0;
128 + const reachTop = sticky ? preAnchorHeight + stickyOffsetTop : 0;
129 + if (reachTop + scrollTop >= children[i].top) {
130 + return i;
131 + }
132 + }
133 + return -1;
134 + },
135 + onScroll() {
136 + const { children = [], scrollTop } = this;
137 + if (!children.length) {
138 + return;
139 + }
140 + const { sticky, stickyOffsetTop, zIndex, highlightColor } = this.data;
141 + const active = this.getActiveAnchorIndex();
142 + this.setDiffData({
143 + target: this,
144 + data: {
145 + activeAnchorIndex: active,
146 + },
147 + });
148 + if (sticky) {
149 + let isActiveAnchorSticky = false;
150 + if (active !== -1) {
151 + isActiveAnchorSticky =
152 + children[active].top <= stickyOffsetTop + scrollTop;
153 + }
154 + children.forEach((item, index) => {
155 + if (index === active) {
156 + let wrapperStyle = '';
157 + let anchorStyle = `
158 + color: ${highlightColor};
159 + `;
160 + if (isActiveAnchorSticky) {
161 + wrapperStyle = `
162 + height: ${children[index].height}px;
163 + `;
164 + anchorStyle = `
165 + position: fixed;
166 + top: ${stickyOffsetTop}px;
167 + z-index: ${zIndex};
168 + color: ${highlightColor};
169 + `;
170 + }
171 + this.setDiffData({
172 + target: item,
173 + data: {
174 + active: true,
175 + anchorStyle,
176 + wrapperStyle,
177 + },
178 + });
179 + }
180 + else if (index === active - 1) {
181 + const currentAnchor = children[index];
182 + const currentOffsetTop = currentAnchor.top;
183 + const targetOffsetTop = index === children.length - 1
184 + ? this.top
185 + : children[index + 1].top;
186 + const parentOffsetHeight = targetOffsetTop - currentOffsetTop;
187 + const translateY = parentOffsetHeight - currentAnchor.height;
188 + const anchorStyle = `
189 + position: relative;
190 + transform: translate3d(0, ${translateY}px, 0);
191 + z-index: ${zIndex};
192 + color: ${highlightColor};
193 + `;
194 + this.setDiffData({
195 + target: item,
196 + data: {
197 + active: true,
198 + anchorStyle,
199 + },
200 + });
201 + }
202 + else {
203 + this.setDiffData({
204 + target: item,
205 + data: {
206 + active: false,
207 + anchorStyle: '',
208 + wrapperStyle: '',
209 + },
210 + });
211 + }
212 + });
213 + }
214 + },
215 + onClick(event) {
216 + this.scrollToAnchor(event.target.dataset.index);
217 + },
218 + onTouchMove(event) {
219 + const sidebarLength = this.children.length;
220 + const touch = event.touches[0];
221 + const itemHeight = this.sidebar.height / sidebarLength;
222 + let index = Math.floor((touch.clientY - this.sidebar.top) / itemHeight);
223 + if (index < 0) {
224 + index = 0;
225 + }
226 + else if (index > sidebarLength - 1) {
227 + index = sidebarLength - 1;
228 + }
229 + this.scrollToAnchor(index);
230 + },
231 + onTouchStop() {
232 + this.scrollToAnchorIndex = null;
233 + },
234 + scrollToAnchor(index) {
235 + if (typeof index !== 'number' || this.scrollToAnchorIndex === index) {
236 + return;
237 + }
238 + this.scrollToAnchorIndex = index;
239 + const anchor = this.children.find((item) => item.data.index === this.data.indexList[index]);
240 + if (anchor) {
241 + anchor.scrollIntoView(this.scrollTop);
242 + this.$emit('select', anchor.data.index);
243 + }
244 + },
245 + },
246 +});
1 +<view class="van-index-bar">
2 + <slot />
3 +
4 + <view
5 + wx:if="{{ showSidebar }}"
6 + class="van-index-bar__sidebar"
7 + catch:tap="onClick"
8 + catch:touchmove="onTouchMove"
9 + catch:touchend="onTouchStop"
10 + catch:touchcancel="onTouchStop"
11 + >
12 + <view
13 + wx:for="{{ indexList }}"
14 + wx:key="index"
15 + class="van-index-bar__index"
16 + style="z-index: {{ zIndex + 1 }}; color: {{ activeAnchorIndex === index ? highlightColor : '' }}"
17 + data-index="{{ index }}"
18 + >
19 + {{ item }}
20 + </view>
21 + </view>
22 +</view>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + props: {
4 + dot: Boolean,
5 + info: null,
6 + customStyle: String,
7 + },
8 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view
4 + wx:if="{{ info !== null && info !== '' || dot }}"
5 + class="van-info {{ utils.bem('info', { dot }) }} custom-class"
6 + style="{{ customStyle }}"
7 +>{{ dot ? '' : info }}</view>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + props: {
4 + color: String,
5 + vertical: Boolean,
6 + type: {
7 + type: String,
8 + value: 'circular',
9 + },
10 + size: String,
11 + textSize: String,
12 + },
13 + data: {
14 + array12: Array.from({ length: 12 }),
15 + },
16 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view class="custom-class {{ utils.bem('loading', { vertical }) }}">
5 + <view
6 + class="van-loading__spinner van-loading__spinner--{{ type }}"
7 + style="{{ computed.spinnerStyle({ color, size }) }}"
8 + >
9 + <view
10 + wx:if="{{ type === 'spinner' }}"
11 + wx:for="{{ array12 }}"
12 + wx:key="index"
13 + class="van-loading__dot"
14 + />
15 + </view>
16 + <view class="van-loading__text" style="{{ computed.textStyle({ textSize }) }}">
17 + <slot />
18 + </view>
19 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function spinnerStyle(data) {
6 + return style({
7 + color: data.color,
8 + width: addUnit(data.size),
9 + height: addUnit(data.size),
10 + });
11 +}
12 +
13 +function textStyle(data) {
14 + return style({
15 + 'font-size': addUnit(data.textSize),
16 + });
17 +}
18 +
19 +module.exports = {
20 + spinnerStyle: spinnerStyle,
21 + textStyle: textStyle,
22 +};
1 +@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 ...\ No newline at end of file
1 +export declare const basic: string;
1 +export const basic = Behavior({
2 + methods: {
3 + $emit(name, detail, options) {
4 + this.triggerEvent(name, detail, options);
5 + },
6 + set(data) {
7 + this.setData(data);
8 + return new Promise((resolve) => wx.nextTick(resolve));
9 + },
10 + },
11 +});
1 +export declare const button: string;
1 +import { canIUseGetUserProfile } from '../common/version';
2 +export const button = Behavior({
3 + externalClasses: ['hover-class'],
4 + properties: {
5 + id: String,
6 + lang: String,
7 + businessId: Number,
8 + sessionFrom: String,
9 + sendMessageTitle: String,
10 + sendMessagePath: String,
11 + sendMessageImg: String,
12 + showMessageCard: Boolean,
13 + appParameter: String,
14 + ariaLabel: String,
15 + openType: String,
16 + getUserProfileDesc: String,
17 + },
18 + data: {
19 + canIUseGetUserProfile: canIUseGetUserProfile(),
20 + },
21 + methods: {
22 + onGetUserInfo(event) {
23 + this.triggerEvent('getuserinfo', event.detail);
24 + },
25 + onContact(event) {
26 + this.triggerEvent('contact', event.detail);
27 + },
28 + onGetPhoneNumber(event) {
29 + this.triggerEvent('getphonenumber', event.detail);
30 + },
31 + onError(event) {
32 + this.triggerEvent('error', event.detail);
33 + },
34 + onLaunchApp(event) {
35 + this.triggerEvent('launchapp', event.detail);
36 + },
37 + onOpenSetting(event) {
38 + this.triggerEvent('opensetting', event.detail);
39 + },
40 + },
41 +});
1 +export declare const link: string;
1 +export const link = Behavior({
2 + properties: {
3 + url: String,
4 + linkType: {
5 + type: String,
6 + value: 'navigateTo',
7 + },
8 + },
9 + methods: {
10 + jumpLink(urlKey = 'url') {
11 + const url = this.data[urlKey];
12 + if (url) {
13 + if (this.data.linkType === 'navigateTo' &&
14 + getCurrentPages().length > 9) {
15 + wx.redirectTo({ url });
16 + }
17 + else {
18 + wx[this.data.linkType]({ url });
19 + }
20 + }
21 + },
22 + },
23 +});
1 +/// <reference types="miniprogram-api-typings" />
2 +declare type IPageScrollOption = WechatMiniprogram.Page.IPageScrollOption;
3 +declare type Scroller = (this: WechatMiniprogram.Component.TrivialInstance, event?: IPageScrollOption) => void;
4 +export declare const pageScrollMixin: (scroller: Scroller) => string;
5 +export {};
1 +import { getCurrentPage, isDef } from '../common/utils';
2 +function onPageScroll(event) {
3 + const { vanPageScroller = [] } = getCurrentPage();
4 + vanPageScroller.forEach((scroller) => {
5 + if (typeof scroller === 'function') {
6 + // @ts-ignore
7 + scroller(event);
8 + }
9 + });
10 +}
11 +export const pageScrollMixin = (scroller) => Behavior({
12 + attached() {
13 + const page = getCurrentPage();
14 + if (!isDef(page)) {
15 + return;
16 + }
17 + if (Array.isArray(page.vanPageScroller)) {
18 + page.vanPageScroller.push(scroller.bind(this));
19 + }
20 + else {
21 + page.vanPageScroller =
22 + typeof page.onPageScroll === 'function'
23 + ? [page.onPageScroll.bind(page), scroller.bind(this)]
24 + : [scroller.bind(this)];
25 + }
26 + page.onPageScroll = onPageScroll;
27 + },
28 + detached() {
29 + var _a;
30 + const page = getCurrentPage();
31 + if (isDef(page)) {
32 + page.vanPageScroller =
33 + ((_a = page.vanPageScroller) === null || _a === void 0 ? void 0 : _a.filter((item) => item !== scroller)) || [];
34 + }
35 + },
36 +});
1 +export declare const touch: string;
1 +// @ts-nocheck
2 +const MIN_DISTANCE = 10;
3 +function getDirection(x, y) {
4 + if (x > y && x > MIN_DISTANCE) {
5 + return 'horizontal';
6 + }
7 + if (y > x && y > MIN_DISTANCE) {
8 + return 'vertical';
9 + }
10 + return '';
11 +}
12 +export const touch = Behavior({
13 + methods: {
14 + resetTouchStatus() {
15 + this.direction = '';
16 + this.deltaX = 0;
17 + this.deltaY = 0;
18 + this.offsetX = 0;
19 + this.offsetY = 0;
20 + },
21 + touchStart(event) {
22 + this.resetTouchStatus();
23 + const touch = event.touches[0];
24 + this.startX = touch.clientX;
25 + this.startY = touch.clientY;
26 + },
27 + touchMove(event) {
28 + const touch = event.touches[0];
29 + this.deltaX = touch.clientX - this.startX;
30 + this.deltaY = touch.clientY - this.startY;
31 + this.offsetX = Math.abs(this.deltaX);
32 + this.offsetY = Math.abs(this.deltaY);
33 + this.direction =
34 + this.direction || getDirection(this.offsetX, this.offsetY);
35 + },
36 + },
37 +});
1 +export declare function transition(showDefaultValue: boolean): string;
1 +// @ts-nocheck
2 +import { requestAnimationFrame } from '../common/utils';
3 +import { isObj } from '../common/validator';
4 +const getClassNames = (name) => ({
5 + enter: `van-${name}-enter van-${name}-enter-active enter-class enter-active-class`,
6 + 'enter-to': `van-${name}-enter-to van-${name}-enter-active enter-to-class enter-active-class`,
7 + leave: `van-${name}-leave van-${name}-leave-active leave-class leave-active-class`,
8 + 'leave-to': `van-${name}-leave-to van-${name}-leave-active leave-to-class leave-active-class`,
9 +});
10 +export function transition(showDefaultValue) {
11 + return Behavior({
12 + properties: {
13 + customStyle: String,
14 + // @ts-ignore
15 + show: {
16 + type: Boolean,
17 + value: showDefaultValue,
18 + observer: 'observeShow',
19 + },
20 + // @ts-ignore
21 + duration: {
22 + type: null,
23 + value: 300,
24 + observer: 'observeDuration',
25 + },
26 + name: {
27 + type: String,
28 + value: 'fade',
29 + },
30 + },
31 + data: {
32 + type: '',
33 + inited: false,
34 + display: false,
35 + },
36 + ready() {
37 + if (this.data.show === true) {
38 + this.observeShow(true, false);
39 + }
40 + },
41 + methods: {
42 + observeShow(value, old) {
43 + if (value === old) {
44 + return;
45 + }
46 + value ? this.enter() : this.leave();
47 + },
48 + enter() {
49 + const { duration, name } = this.data;
50 + const classNames = getClassNames(name);
51 + const currentDuration = isObj(duration) ? duration.enter : duration;
52 + this.status = 'enter';
53 + this.$emit('before-enter');
54 + requestAnimationFrame(() => {
55 + if (this.status !== 'enter') {
56 + return;
57 + }
58 + this.$emit('enter');
59 + this.setData({
60 + inited: true,
61 + display: true,
62 + classes: classNames.enter,
63 + currentDuration,
64 + });
65 + requestAnimationFrame(() => {
66 + if (this.status !== 'enter') {
67 + return;
68 + }
69 + this.transitionEnded = false;
70 + this.setData({ classes: classNames['enter-to'] });
71 + });
72 + });
73 + },
74 + leave() {
75 + if (!this.data.display) {
76 + return;
77 + }
78 + const { duration, name } = this.data;
79 + const classNames = getClassNames(name);
80 + const currentDuration = isObj(duration) ? duration.leave : duration;
81 + this.status = 'leave';
82 + this.$emit('before-leave');
83 + requestAnimationFrame(() => {
84 + if (this.status !== 'leave') {
85 + return;
86 + }
87 + this.$emit('leave');
88 + this.setData({
89 + classes: classNames.leave,
90 + currentDuration,
91 + });
92 + requestAnimationFrame(() => {
93 + if (this.status !== 'leave') {
94 + return;
95 + }
96 + this.transitionEnded = false;
97 + setTimeout(() => this.onTransitionEnd(), currentDuration);
98 + this.setData({ classes: classNames['leave-to'] });
99 + });
100 + });
101 + },
102 + onTransitionEnd() {
103 + if (this.transitionEnded) {
104 + return;
105 + }
106 + this.transitionEnded = true;
107 + this.$emit(`after-${this.status}`);
108 + const { show, display } = this.data;
109 + if (!show && display) {
110 + this.setData({ display: false });
111 + }
112 + },
113 + },
114 + });
115 +}
1 +import { VantComponent } from '../common/component';
2 +import { getRect, getSystemInfoSync } from '../common/utils';
3 +VantComponent({
4 + classes: ['title-class'],
5 + props: {
6 + title: String,
7 + fixed: {
8 + type: Boolean,
9 + observer: 'setHeight',
10 + },
11 + placeholder: {
12 + type: Boolean,
13 + observer: 'setHeight',
14 + },
15 + leftText: String,
16 + rightText: String,
17 + customStyle: String,
18 + leftArrow: Boolean,
19 + border: {
20 + type: Boolean,
21 + value: true,
22 + },
23 + zIndex: {
24 + type: Number,
25 + value: 1,
26 + },
27 + safeAreaInsetTop: {
28 + type: Boolean,
29 + value: true,
30 + },
31 + },
32 + data: {
33 + height: 46,
34 + },
35 + created() {
36 + const { statusBarHeight } = getSystemInfoSync();
37 + this.setData({
38 + statusBarHeight,
39 + height: 46 + statusBarHeight,
40 + });
41 + },
42 + mounted() {
43 + this.setHeight();
44 + },
45 + methods: {
46 + onClickLeft() {
47 + this.$emit('click-left');
48 + },
49 + onClickRight() {
50 + this.$emit('click-right');
51 + },
52 + setHeight() {
53 + if (!this.data.fixed || !this.data.placeholder) {
54 + return;
55 + }
56 + wx.nextTick(() => {
57 + getRect(this, '.van-nav-bar').then((res) => {
58 + if (res && 'height' in res) {
59 + this.setData({ height: res.height });
60 + }
61 + });
62 + });
63 + },
64 + },
65 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view wx:if="{{ fixed && placeholder }}" style="height: {{ height }}px;" />
5 +
6 +<view
7 + class="{{ utils.bem('nav-bar', { fixed }) }} custom-class {{ border ? 'van-hairline--bottom' : '' }}"
8 + style="{{ computed.barStyle({ zIndex, statusBarHeight, safeAreaInsetTop }) }}; {{ customStyle }}"
9 +>
10 + <view class="van-nav-bar__content">
11 + <view class="van-nav-bar__left" bind:tap="onClickLeft">
12 + <block wx:if="{{ leftArrow || leftText }}">
13 + <van-icon
14 + wx:if="{{ leftArrow }}"
15 + size="16px"
16 + name="arrow-left"
17 + custom-class="van-nav-bar__arrow"
18 + />
19 + <view
20 + wx:if="{{ leftText }}"
21 + class="van-nav-bar__text"
22 + hover-class="van-nav-bar__text--hover"
23 + hover-stay-time="70"
24 + >{{ leftText }}</view>
25 + </block>
26 + <slot wx:else name="left" />
27 + </view>
28 + <view class="van-nav-bar__title title-class van-ellipsis">
29 + <block wx:if="{{ title }}">{{ title }}</block>
30 + <slot wx:else name="title" />
31 + </view>
32 + <view class="van-nav-bar__right" bind:tap="onClickRight">
33 + <view
34 + wx:if="{{ rightText }}"
35 + class="van-nav-bar__text"
36 + hover-class="van-nav-bar__text--hover"
37 + hover-stay-time="70"
38 + >{{ rightText }}</view>
39 + <slot wx:else name="right" />
40 + </view>
41 + </view>
42 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +
4 +function barStyle(data) {
5 + return style({
6 + 'z-index': data.zIndex,
7 + 'padding-top': data.safeAreaInsetTop ? data.statusBarHeight + 'px' : 0,
8 + });
9 +}
10 +
11 +module.exports = {
12 + barStyle: barStyle,
13 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { getRect, requestAnimationFrame } from '../common/utils';
3 +VantComponent({
4 + props: {
5 + text: {
6 + type: String,
7 + value: '',
8 + observer: 'init',
9 + },
10 + mode: {
11 + type: String,
12 + value: '',
13 + },
14 + url: {
15 + type: String,
16 + value: '',
17 + },
18 + openType: {
19 + type: String,
20 + value: 'navigate',
21 + },
22 + delay: {
23 + type: Number,
24 + value: 1,
25 + },
26 + speed: {
27 + type: Number,
28 + value: 60,
29 + observer: 'init',
30 + },
31 + scrollable: null,
32 + leftIcon: {
33 + type: String,
34 + value: '',
35 + },
36 + color: String,
37 + backgroundColor: String,
38 + background: String,
39 + wrapable: Boolean,
40 + },
41 + data: {
42 + show: true,
43 + },
44 + created() {
45 + this.resetAnimation = wx.createAnimation({
46 + duration: 0,
47 + timingFunction: 'linear',
48 + });
49 + },
50 + destroyed() {
51 + this.timer && clearTimeout(this.timer);
52 + },
53 + mounted() {
54 + this.init();
55 + },
56 + methods: {
57 + init() {
58 + requestAnimationFrame(() => {
59 + Promise.all([
60 + getRect(this, '.van-notice-bar__content'),
61 + getRect(this, '.van-notice-bar__wrap'),
62 + ]).then((rects) => {
63 + const [contentRect, wrapRect] = rects;
64 + const { speed, scrollable, delay } = this.data;
65 + if (contentRect == null ||
66 + wrapRect == null ||
67 + !contentRect.width ||
68 + !wrapRect.width ||
69 + scrollable === false) {
70 + return;
71 + }
72 + if (scrollable || wrapRect.width < contentRect.width) {
73 + const duration = ((wrapRect.width + contentRect.width) / speed) * 1000;
74 + this.wrapWidth = wrapRect.width;
75 + this.contentWidth = contentRect.width;
76 + this.duration = duration;
77 + this.animation = wx.createAnimation({
78 + duration,
79 + timingFunction: 'linear',
80 + delay,
81 + });
82 + this.scroll(true);
83 + }
84 + });
85 + });
86 + },
87 + scroll(isInit = false) {
88 + this.timer && clearTimeout(this.timer);
89 + this.timer = null;
90 + this.setData({
91 + animationData: this.resetAnimation
92 + .translateX(isInit ? 0 : this.wrapWidth)
93 + .step()
94 + .export(),
95 + });
96 + requestAnimationFrame(() => {
97 + this.setData({
98 + animationData: this.animation
99 + .translateX(-this.contentWidth)
100 + .step()
101 + .export(),
102 + });
103 + });
104 + this.timer = setTimeout(() => {
105 + this.scroll();
106 + }, this.duration);
107 + },
108 + onClickIcon(event) {
109 + if (this.data.mode === 'closeable') {
110 + this.timer && clearTimeout(this.timer);
111 + this.timer = null;
112 + this.setData({ show: false });
113 + this.$emit('close', event.detail);
114 + }
115 + },
116 + onClick(event) {
117 + this.$emit('click', event);
118 + },
119 + },
120 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view
5 + wx:if="{{ show }}"
6 + class="custom-class {{ utils.bem('notice-bar', { withicon: mode, wrapable }) }}"
7 + style="{{ computed.rootStyle({ color, backgroundColor, background }) }}"
8 + bind:tap="onClick"
9 +>
10 + <van-icon
11 + wx:if="{{ leftIcon }}"
12 + name="{{ leftIcon }}"
13 + class="van-notice-bar__left-icon"
14 + />
15 + <slot wx:else name="left-icon" />
16 +
17 + <view class="van-notice-bar__wrap">
18 + <view class="van-notice-bar__content {{ scrollable === false && !wrapable ? 'van-ellipsis' : '' }}" animation="{{ animationData }}">
19 + {{ text }}
20 + <slot wx:if="{{ !text }}"></slot>
21 + </view>
22 + </view>
23 +
24 + <van-icon
25 + wx:if="{{ mode === 'closeable' }}"
26 + class="van-notice-bar__right-icon"
27 + name="cross"
28 + catch:tap="onClickIcon"
29 + />
30 + <navigator
31 + wx:elif="{{ mode === 'link' }}"
32 + url="{{ url }}"
33 + open-type="{{ openType }}"
34 + >
35 + <van-icon class="van-notice-bar__right-icon" name="arrow" />
36 + </navigator>
37 + <slot wx:else name="right-icon" />
38 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function rootStyle(data) {
6 + return style({
7 + color: data.color,
8 + 'background-color': data.backgroundColor,
9 + background: data.background,
10 + });
11 +}
12 +
13 +module.exports = {
14 + rootStyle: rootStyle,
15 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { WHITE } from '../common/color';
3 +import { getSystemInfoSync } from '../common/utils';
4 +VantComponent({
5 + props: {
6 + message: String,
7 + background: String,
8 + type: {
9 + type: String,
10 + value: 'danger',
11 + },
12 + color: {
13 + type: String,
14 + value: WHITE,
15 + },
16 + duration: {
17 + type: Number,
18 + value: 3000,
19 + },
20 + zIndex: {
21 + type: Number,
22 + value: 110,
23 + },
24 + safeAreaInsetTop: {
25 + type: Boolean,
26 + value: false,
27 + },
28 + top: null,
29 + },
30 + data: {
31 + show: false,
32 + onOpened: null,
33 + onClose: null,
34 + onClick: null,
35 + },
36 + created() {
37 + const { statusBarHeight } = getSystemInfoSync();
38 + this.setData({ statusBarHeight });
39 + },
40 + methods: {
41 + show() {
42 + const { duration, onOpened } = this.data;
43 + clearTimeout(this.timer);
44 + this.setData({ show: true });
45 + wx.nextTick(onOpened);
46 + if (duration > 0 && duration !== Infinity) {
47 + this.timer = setTimeout(() => {
48 + this.hide();
49 + }, duration);
50 + }
51 + },
52 + hide() {
53 + const { onClose } = this.data;
54 + clearTimeout(this.timer);
55 + this.setData({ show: false });
56 + wx.nextTick(onClose);
57 + },
58 + onTap(event) {
59 + const { onClick } = this.data;
60 + if (onClick) {
61 + onClick(event.detail);
62 + }
63 + },
64 + },
65 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-transition": "../transition/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<van-transition
5 + name="slide-down"
6 + show="{{ show }}"
7 + custom-class="van-notify__container"
8 + custom-style="{{ computed.rootStyle({ zIndex, top }) }}"
9 + bind:tap="onTap"
10 +>
11 + <view
12 + class="van-notify van-notify--{{ type }}"
13 + style="{{ computed.notifyStyle({ background, color }) }}"
14 + >
15 + <view
16 + wx:if="{{ safeAreaInsetTop }}"
17 + style="height: {{ statusBarHeight }}px"
18 + />
19 + <text>{{ message }}</text>
20 + </view>
21 +</van-transition>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function rootStyle(data) {
6 + return style({
7 + 'z-index': data.zIndex,
8 + top: addUnit(data.top),
9 + });
10 +}
11 +
12 +function notifyStyle(data) {
13 + return style({
14 + background: data.background,
15 + color: data.color,
16 + });
17 +}
18 +
19 +module.exports = {
20 + rootStyle: rootStyle,
21 + notifyStyle: notifyStyle,
22 +};
1 +@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 ...\ No newline at end of file
1 +interface NotifyOptions {
2 + type?: 'primary' | 'success' | 'danger' | 'warning';
3 + color?: string;
4 + zIndex?: number;
5 + top?: number;
6 + message: string;
7 + context?: any;
8 + duration?: number;
9 + selector?: string;
10 + background?: string;
11 + safeAreaInsetTop?: boolean;
12 + onClick?: () => void;
13 + onOpened?: () => void;
14 + onClose?: () => void;
15 +}
16 +declare function Notify(options: NotifyOptions | string): any;
17 +declare namespace Notify {
18 + var clear: (options?: NotifyOptions | undefined) => void;
19 +}
20 +export default Notify;
1 +import { WHITE } from '../common/color';
2 +const defaultOptions = {
3 + selector: '#van-notify',
4 + type: 'danger',
5 + message: '',
6 + background: '',
7 + duration: 3000,
8 + zIndex: 110,
9 + top: 0,
10 + color: WHITE,
11 + safeAreaInsetTop: false,
12 + onClick: () => { },
13 + onOpened: () => { },
14 + onClose: () => { },
15 +};
16 +function parseOptions(message) {
17 + if (message == null) {
18 + return {};
19 + }
20 + return typeof message === 'string' ? { message } : message;
21 +}
22 +function getContext() {
23 + const pages = getCurrentPages();
24 + return pages[pages.length - 1];
25 +}
26 +export default function Notify(options) {
27 + options = Object.assign(Object.assign({}, defaultOptions), parseOptions(options));
28 + const context = options.context || getContext();
29 + const notify = context.selectComponent(options.selector);
30 + delete options.context;
31 + delete options.selector;
32 + if (notify) {
33 + notify.setData(options);
34 + notify.show();
35 + return notify;
36 + }
37 + console.warn('未找到 van-notify 节点,请确认 selector 及 context 是否正确');
38 +}
39 +Notify.clear = function (options) {
40 + options = Object.assign(Object.assign({}, defaultOptions), parseOptions(options));
41 + const context = options.context || getContext();
42 + const notify = context.selectComponent(options.selector);
43 + if (notify) {
44 + notify.hide();
45 + }
46 +};
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + props: {
4 + show: Boolean,
5 + customStyle: String,
6 + duration: {
7 + type: null,
8 + value: 300,
9 + },
10 + zIndex: {
11 + type: Number,
12 + value: 1,
13 + },
14 + lockScroll: {
15 + type: Boolean,
16 + value: true,
17 + },
18 + },
19 + methods: {
20 + onClick() {
21 + this.$emit('click');
22 + },
23 + // for prevent touchmove
24 + noop() { },
25 + },
26 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-transition": "../transition/index"
5 + }
6 +}
1 +<van-transition
2 + wx:if="{{ lockScroll }}"
3 + show="{{ show }}"
4 + custom-class="van-overlay"
5 + custom-style="z-index: {{ zIndex }}; {{ customStyle }}"
6 + duration="{{ duration }}"
7 + bind:tap="onClick"
8 + catch:touchmove="noop"
9 +>
10 + <slot></slot>
11 +</van-transition>
12 +<van-transition
13 + wx:else
14 + show="{{ show }}"
15 + custom-class="van-overlay"
16 + custom-style="z-index: {{ zIndex }}; {{ customStyle }}"
17 + duration="{{ duration }}"
18 + bind:tap="onClick"
19 +>
20 + <slot></slot>
21 +</van-transition>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + classes: ['header-class', 'footer-class'],
4 + props: {
5 + desc: String,
6 + title: String,
7 + status: String,
8 + },
9 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-cell": "../cell/index"
5 + }
6 +}
1 +<view class="van-panel van-hairline--top-bottom custom-class">
2 + <van-cell
3 + wx:if="{{ title || desc || status }}"
4 + title="{{ title }}"
5 + label="{{ desc }}"
6 + value="{{ status }}"
7 + custom-class="header-class"
8 + value-class="van-panel__header-value"
9 + />
10 + <slot wx:else name="header" />
11 +
12 + <view class="van-panel__content">
13 + <slot />
14 + </view>
15 +
16 + <view class="van-panel__footer van-hairline--top footer-class">
17 + <slot name="footer" />
18 + </view>
19 +</view>
1 +@import '../common/index.wxss';.van-panel{background: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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { range } from '../common/utils';
3 +import { isObj } from '../common/validator';
4 +const DEFAULT_DURATION = 200;
5 +VantComponent({
6 + classes: ['active-class'],
7 + props: {
8 + valueKey: String,
9 + className: String,
10 + itemHeight: Number,
11 + visibleItemCount: Number,
12 + initialOptions: {
13 + type: Array,
14 + value: [],
15 + },
16 + defaultIndex: {
17 + type: Number,
18 + value: 0,
19 + observer(value) {
20 + this.setIndex(value);
21 + },
22 + },
23 + },
24 + data: {
25 + startY: 0,
26 + offset: 0,
27 + duration: 0,
28 + startOffset: 0,
29 + options: [],
30 + currentIndex: 0,
31 + },
32 + created() {
33 + const { defaultIndex, initialOptions } = this.data;
34 + this.set({
35 + currentIndex: defaultIndex,
36 + options: initialOptions,
37 + }).then(() => {
38 + this.setIndex(defaultIndex);
39 + });
40 + },
41 + methods: {
42 + getCount() {
43 + return this.data.options.length;
44 + },
45 + onTouchStart(event) {
46 + this.setData({
47 + startY: event.touches[0].clientY,
48 + startOffset: this.data.offset,
49 + duration: 0,
50 + });
51 + },
52 + onTouchMove(event) {
53 + const { data } = this;
54 + const deltaY = event.touches[0].clientY - data.startY;
55 + this.setData({
56 + offset: range(data.startOffset + deltaY, -(this.getCount() * data.itemHeight), data.itemHeight),
57 + });
58 + },
59 + onTouchEnd() {
60 + const { data } = this;
61 + if (data.offset !== data.startOffset) {
62 + this.setData({ duration: DEFAULT_DURATION });
63 + const index = range(Math.round(-data.offset / data.itemHeight), 0, this.getCount() - 1);
64 + this.setIndex(index, true);
65 + }
66 + },
67 + onClickItem(event) {
68 + const { index } = event.currentTarget.dataset;
69 + this.setIndex(index, true);
70 + },
71 + adjustIndex(index) {
72 + const { data } = this;
73 + const count = this.getCount();
74 + index = range(index, 0, count);
75 + for (let i = index; i < count; i++) {
76 + if (!this.isDisabled(data.options[i]))
77 + return i;
78 + }
79 + for (let i = index - 1; i >= 0; i--) {
80 + if (!this.isDisabled(data.options[i]))
81 + return i;
82 + }
83 + },
84 + isDisabled(option) {
85 + return isObj(option) && option.disabled;
86 + },
87 + getOptionText(option) {
88 + const { data } = this;
89 + return isObj(option) && data.valueKey in option
90 + ? option[data.valueKey]
91 + : option;
92 + },
93 + setIndex(index, userAction) {
94 + const { data } = this;
95 + index = this.adjustIndex(index) || 0;
96 + const offset = -index * data.itemHeight;
97 + if (index !== data.currentIndex) {
98 + return this.set({ offset, currentIndex: index }).then(() => {
99 + userAction && this.$emit('change', index);
100 + });
101 + }
102 + return this.set({ offset });
103 + },
104 + setValue(value) {
105 + const { options } = this.data;
106 + for (let i = 0; i < options.length; i++) {
107 + if (this.getOptionText(options[i]) === value) {
108 + return this.setIndex(i);
109 + }
110 + }
111 + return Promise.resolve();
112 + },
113 + getValue() {
114 + const { data } = this;
115 + return data.options[data.currentIndex];
116 + },
117 + },
118 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view
5 + class="van-picker-column custom-class"
6 + style="{{ computed.rootStyle({ itemHeight, visibleItemCount }) }}"
7 + bind:touchstart="onTouchStart"
8 + catch:touchmove="onTouchMove"
9 + bind:touchend="onTouchEnd"
10 + bind:touchcancel="onTouchEnd"
11 +>
12 + <view style="{{ computed.wrapperStyle({ offset, itemHeight, visibleItemCount, duration }) }}">
13 + <view
14 + wx:for="{{ options }}"
15 + wx:for-item="option"
16 + wx:key="index"
17 + data-index="{{ index }}"
18 + style="height: {{ itemHeight }}px"
19 + class="van-ellipsis {{ utils.bem('picker-column__item', { disabled: option && option.disabled, selected: index === currentIndex }) }} {{ index === currentIndex ? 'active-class' : '' }}"
20 + bindtap="onClickItem"
21 + >{{ computed.optionText(option, valueKey) }}</view>
22 + </view>
23 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function isObj(x) {
6 + var type = typeof x;
7 + return x !== null && (type === 'object' || type === 'function');
8 +}
9 +
10 +function optionText(option, valueKey) {
11 + return isObj(option) && option[valueKey] != null ? option[valueKey] : option;
12 +}
13 +
14 +function rootStyle(data) {
15 + return style({
16 + height: addUnit(data.itemHeight * data.visibleItemCount),
17 + });
18 +}
19 +
20 +function wrapperStyle(data) {
21 + var offset = addUnit(
22 + data.offset + (data.itemHeight * (data.visibleItemCount - 1)) / 2
23 + );
24 +
25 + return style({
26 + transition: 'transform ' + data.duration + 'ms',
27 + 'line-height': addUnit(data.itemHeight),
28 + transform: 'translate3d(0, ' + offset + ', 0)',
29 + });
30 +}
31 +
32 +module.exports = {
33 + optionText: optionText,
34 + rootStyle: rootStyle,
35 + wrapperStyle: wrapperStyle,
36 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { pickerProps } from './shared';
3 +VantComponent({
4 + classes: ['active-class', 'toolbar-class', 'column-class'],
5 + props: Object.assign(Object.assign({}, pickerProps), { valueKey: {
6 + type: String,
7 + value: 'text',
8 + }, toolbarPosition: {
9 + type: String,
10 + value: 'top',
11 + }, defaultIndex: {
12 + type: Number,
13 + value: 0,
14 + }, columns: {
15 + type: Array,
16 + value: [],
17 + observer(columns = []) {
18 + this.simple = columns.length && !columns[0].values;
19 + if (Array.isArray(this.children) && this.children.length) {
20 + this.setColumns().catch(() => { });
21 + }
22 + },
23 + } }),
24 + beforeCreate() {
25 + Object.defineProperty(this, 'children', {
26 + get: () => this.selectAllComponents('.van-picker__column') || [],
27 + });
28 + },
29 + methods: {
30 + noop() { },
31 + setColumns() {
32 + const { data } = this;
33 + const columns = this.simple ? [{ values: data.columns }] : data.columns;
34 + const stack = columns.map((column, index) => this.setColumnValues(index, column.values));
35 + return Promise.all(stack);
36 + },
37 + emit(event) {
38 + const { type } = event.currentTarget.dataset;
39 + if (this.simple) {
40 + this.$emit(type, {
41 + value: this.getColumnValue(0),
42 + index: this.getColumnIndex(0),
43 + });
44 + }
45 + else {
46 + this.$emit(type, {
47 + value: this.getValues(),
48 + index: this.getIndexes(),
49 + });
50 + }
51 + },
52 + onChange(event) {
53 + if (this.simple) {
54 + this.$emit('change', {
55 + picker: this,
56 + value: this.getColumnValue(0),
57 + index: this.getColumnIndex(0),
58 + });
59 + }
60 + else {
61 + this.$emit('change', {
62 + picker: this,
63 + value: this.getValues(),
64 + index: event.currentTarget.dataset.index,
65 + });
66 + }
67 + },
68 + // get column instance by index
69 + getColumn(index) {
70 + return this.children[index];
71 + },
72 + // get column value by index
73 + getColumnValue(index) {
74 + const column = this.getColumn(index);
75 + return column && column.getValue();
76 + },
77 + // set column value by index
78 + setColumnValue(index, value) {
79 + const column = this.getColumn(index);
80 + if (column == null) {
81 + return Promise.reject(new Error('setColumnValue: 对应列不存在'));
82 + }
83 + return column.setValue(value);
84 + },
85 + // get column option index by column index
86 + getColumnIndex(columnIndex) {
87 + return (this.getColumn(columnIndex) || {}).data.currentIndex;
88 + },
89 + // set column option index by column index
90 + setColumnIndex(columnIndex, optionIndex) {
91 + const column = this.getColumn(columnIndex);
92 + if (column == null) {
93 + return Promise.reject(new Error('setColumnIndex: 对应列不存在'));
94 + }
95 + return column.setIndex(optionIndex);
96 + },
97 + // get options of column by index
98 + getColumnValues(index) {
99 + return (this.children[index] || {}).data.options;
100 + },
101 + // set options of column by index
102 + setColumnValues(index, options, needReset = true) {
103 + const column = this.children[index];
104 + if (column == null) {
105 + return Promise.reject(new Error('setColumnValues: 对应列不存在'));
106 + }
107 + const isSame = JSON.stringify(column.data.options) === JSON.stringify(options);
108 + if (isSame) {
109 + return Promise.resolve();
110 + }
111 + return column.set({ options }).then(() => {
112 + if (needReset) {
113 + column.setIndex(0);
114 + }
115 + });
116 + },
117 + // get values of all columns
118 + getValues() {
119 + return this.children.map((child) => child.getValue());
120 + },
121 + // set values of all columns
122 + setValues(values) {
123 + const stack = values.map((value, index) => this.setColumnValue(index, value));
124 + return Promise.all(stack);
125 + },
126 + // get indexes of all columns
127 + getIndexes() {
128 + return this.children.map((child) => child.data.currentIndex);
129 + },
130 + // set indexes of all columns
131 + setIndexes(indexes) {
132 + const stack = indexes.map((optionIndex, columnIndex) => this.setColumnIndex(columnIndex, optionIndex));
133 + return Promise.all(stack);
134 + },
135 + },
136 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "picker-column": "../picker-column/index",
5 + "loading": "../loading/index"
6 + }
7 +}
1 +<wxs src="./index.wxs" module="computed" />
2 +
3 +<view class="van-picker custom-class">
4 + <include wx:if="{{ toolbarPosition === 'top' }}" src="./toolbar.wxml" />
5 +
6 + <view wx:if="{{ loading }}" class="van-picker__loading">
7 + <loading color="#1989fa"/>
8 + </view>
9 +
10 + <view
11 + class="van-picker__columns"
12 + style="{{ computed.columnsStyle({ itemHeight, visibleItemCount }) }}"
13 + catch:touchmove="noop"
14 + >
15 + <picker-column
16 + class="van-picker__column"
17 + wx:for="{{ computed.columns(columns) }}"
18 + wx:key="index"
19 + data-index="{{ index }}"
20 + custom-class="column-class"
21 + value-key="{{ valueKey }}"
22 + initial-options="{{ item.values }}"
23 + default-index="{{ item.defaultIndex || defaultIndex }}"
24 + item-height="{{ itemHeight }}"
25 + visible-item-count="{{ visibleItemCount }}"
26 + active-class="active-class"
27 + bind:change="onChange"
28 + />
29 + <view class="van-picker__mask" style="{{ computed.maskStyle({ itemHeight, visibleItemCount }) }}" />
30 + <view
31 + class="van-picker__frame van-hairline--top-bottom"
32 + style="{{ computed.frameStyle({ itemHeight }) }}"
33 + />
34 + </view>
35 +
36 + <include wx:if="{{ toolbarPosition === 'bottom' }}" src="./toolbar.wxml" />
37 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +var array = require('../wxs/array.wxs');
5 +
6 +function columnsStyle(data) {
7 + return style({
8 + height: addUnit(data.itemHeight * data.visibleItemCount),
9 + });
10 +}
11 +
12 +function maskStyle(data) {
13 + return style({
14 + 'background-size':
15 + '100% ' + addUnit((data.itemHeight * (data.visibleItemCount - 1)) / 2),
16 + });
17 +}
18 +
19 +function frameStyle(data) {
20 + return style({
21 + height: addUnit(data.itemHeight),
22 + });
23 +}
24 +
25 +function columns(columns) {
26 + if (!array.isArray(columns)) {
27 + return [];
28 + }
29 +
30 + if (columns.length && !columns[0].values) {
31 + return [{ values: columns }];
32 + }
33 +
34 + return columns;
35 +}
36 +
37 +module.exports = {
38 + columnsStyle: columnsStyle,
39 + frameStyle: frameStyle,
40 + maskStyle: maskStyle,
41 + columns: columns,
42 +};
1 +@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 ...\ No newline at end of file
1 +export declare const pickerProps: {
2 + title: StringConstructor;
3 + loading: BooleanConstructor;
4 + showToolbar: BooleanConstructor;
5 + cancelButtonText: {
6 + type: StringConstructor;
7 + value: string;
8 + };
9 + confirmButtonText: {
10 + type: StringConstructor;
11 + value: string;
12 + };
13 + visibleItemCount: {
14 + type: NumberConstructor;
15 + value: number;
16 + };
17 + itemHeight: {
18 + type: NumberConstructor;
19 + value: number;
20 + };
21 +};
1 +export const pickerProps = {
2 + title: String,
3 + loading: Boolean,
4 + showToolbar: Boolean,
5 + cancelButtonText: {
6 + type: String,
7 + value: '取消',
8 + },
9 + confirmButtonText: {
10 + type: String,
11 + value: '确认',
12 + },
13 + visibleItemCount: {
14 + type: Number,
15 + value: 6,
16 + },
17 + itemHeight: {
18 + type: Number,
19 + value: 44,
20 + },
21 +};
1 +<view wx:if="{{ showToolbar }}" class="van-picker__toolbar toolbar-class">
2 + <view
3 + class="van-picker__cancel"
4 + hover-class="van-picker__cancel--hover"
5 + hover-stay-time="70"
6 + data-type="cancel"
7 + bindtap="emit"
8 + >
9 + {{ cancelButtonText }}
10 + </view>
11 + <view wx:if="{{ title }}" class="van-picker__title van-ellipsis">{{
12 + title
13 + }}</view>
14 + <view
15 + class="van-picker__confirm"
16 + hover-class="van-picker__confirm--hover"
17 + hover-stay-time="70"
18 + data-type="confirm"
19 + bindtap="emit"
20 + >
21 + {{ confirmButtonText }}
22 + </view>
23 +</view>
1 +import { VantComponent } from '../common/component';
2 +import { transition } from '../mixins/transition';
3 +VantComponent({
4 + classes: [
5 + 'enter-class',
6 + 'enter-active-class',
7 + 'enter-to-class',
8 + 'leave-class',
9 + 'leave-active-class',
10 + 'leave-to-class',
11 + 'close-icon-class',
12 + ],
13 + mixins: [transition(false)],
14 + props: {
15 + round: Boolean,
16 + closeable: Boolean,
17 + customStyle: String,
18 + overlayStyle: String,
19 + transition: {
20 + type: String,
21 + observer: 'observeClass',
22 + },
23 + zIndex: {
24 + type: Number,
25 + value: 100,
26 + },
27 + overlay: {
28 + type: Boolean,
29 + value: true,
30 + },
31 + closeIcon: {
32 + type: String,
33 + value: 'cross',
34 + },
35 + closeIconPosition: {
36 + type: String,
37 + value: 'top-right',
38 + },
39 + closeOnClickOverlay: {
40 + type: Boolean,
41 + value: true,
42 + },
43 + position: {
44 + type: String,
45 + value: 'center',
46 + observer: 'observeClass',
47 + },
48 + safeAreaInsetBottom: {
49 + type: Boolean,
50 + value: true,
51 + },
52 + safeAreaInsetTop: {
53 + type: Boolean,
54 + value: false,
55 + },
56 + lockScroll: {
57 + type: Boolean,
58 + value: true,
59 + },
60 + },
61 + created() {
62 + this.observeClass();
63 + },
64 + methods: {
65 + onClickCloseIcon() {
66 + this.$emit('close');
67 + },
68 + onClickOverlay() {
69 + this.$emit('click-overlay');
70 + if (this.data.closeOnClickOverlay) {
71 + this.$emit('close');
72 + }
73 + },
74 + observeClass() {
75 + const { transition, position, duration } = this.data;
76 + const updateData = {
77 + name: transition || position,
78 + };
79 + if (transition === 'none') {
80 + updateData.duration = 0;
81 + this.originDuration = duration;
82 + }
83 + else if (this.originDuration != null) {
84 + updateData.duration = this.originDuration;
85 + }
86 + this.setData(updateData);
87 + },
88 + },
89 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index",
5 + "van-overlay": "../overlay/index"
6 + }
7 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<van-overlay
5 + wx:if="{{ overlay }}"
6 + show="{{ show }}"
7 + z-index="{{ zIndex }}"
8 + custom-style="{{ overlayStyle }}"
9 + duration="{{ duration }}"
10 + bind:click="onClickOverlay"
11 + lock-scroll="{{ lockScroll }}"
12 +/>
13 +<view
14 + wx:if="{{ inited }}"
15 + class="custom-class {{ classes }} {{ utils.bem('popup', [position, { round, safe: safeAreaInsetBottom, safeTop: safeAreaInsetTop }]) }}"
16 + style="{{ computed.popupStyle({ zIndex, currentDuration, display, customStyle }) }}"
17 + bind:transitionend="onTransitionEnd"
18 +>
19 + <slot />
20 + <van-icon
21 + wx:if="{{ closeable }}"
22 + name="{{ closeIcon }}"
23 + class="close-icon-class van-popup__close-icon van-popup__close-icon--{{ closeIconPosition }}"
24 + bind:tap="onClickCloseIcon"
25 + />
26 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +
4 +function popupStyle(data) {
5 + return style([
6 + {
7 + 'z-index': data.zIndex,
8 + '-webkit-transition-duration': data.currentDuration + 'ms',
9 + 'transition-duration': data.currentDuration + 'ms',
10 + },
11 + data.display ? null : 'display: none',
12 + data.customStyle,
13 + ]);
14 +}
15 +
16 +module.exports = {
17 + popupStyle: popupStyle,
18 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { BLUE } from '../common/color';
3 +import { getRect } from '../common/utils';
4 +VantComponent({
5 + props: {
6 + inactive: Boolean,
7 + percentage: {
8 + type: Number,
9 + observer: 'setLeft',
10 + },
11 + pivotText: String,
12 + pivotColor: String,
13 + trackColor: String,
14 + showPivot: {
15 + type: Boolean,
16 + value: true,
17 + },
18 + color: {
19 + type: String,
20 + value: BLUE,
21 + },
22 + textColor: {
23 + type: String,
24 + value: '#fff',
25 + },
26 + strokeWidth: {
27 + type: null,
28 + value: 4,
29 + },
30 + },
31 + data: {
32 + right: 0,
33 + },
34 + mounted() {
35 + this.setLeft();
36 + },
37 + methods: {
38 + setLeft() {
39 + Promise.all([
40 + getRect(this, '.van-progress'),
41 + getRect(this, '.van-progress__pivot'),
42 + ]).then(([portion, pivot]) => {
43 + if (portion && pivot) {
44 + this.setData({
45 + right: (pivot.width * (this.data.percentage - 100)) / 100,
46 + });
47 + }
48 + });
49 + },
50 + },
51 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view
5 + class="van-progress custom-class"
6 + style="{{ computed.rootStyle({ strokeWidth, trackColor }) }}"
7 +>
8 + <view
9 + class="van-progress__portion"
10 + style="{{ computed.portionStyle({ percentage, inactive, color }) }}"
11 + >
12 + <view
13 + wx:if="{{ showPivot && computed.pivotText(pivotText, percentage) }}"
14 + style="{{ computed.pivotStyle({ textColor, pivotColor, inactive, color, right }) }}"
15 + class="van-progress__pivot"
16 + >
17 + {{ computed.pivotText(pivotText, percentage) }}
18 + </view>
19 + </view>
20 +</view>
1 +/* eslint-disable */
2 +var utils = require('../wxs/utils.wxs');
3 +var style = require('../wxs/style.wxs');
4 +
5 +function pivotText(pivotText, percentage) {
6 + return pivotText || percentage + '%';
7 +}
8 +
9 +function rootStyle(data) {
10 + return style({
11 + 'height': data.strokeWidth ? utils.addUnit(data.strokeWidth) : '',
12 + 'background': data.trackColor,
13 + });
14 +}
15 +
16 +function portionStyle(data) {
17 + return style({
18 + background: data.inactive ? '#cacaca' : data.color,
19 + width: data.percentage ? data.percentage + '%' : '',
20 + });
21 +}
22 +
23 +function pivotStyle(data) {
24 + return style({
25 + color: data.textColor,
26 + right: data.right + 'px',
27 + background: data.pivotColor ? data.pivotColor : data.inactive ? '#cacaca' : data.color,
28 + });
29 +}
30 +
31 +module.exports = {
32 + pivotText: pivotText,
33 + rootStyle: rootStyle,
34 + portionStyle: portionStyle,
35 + pivotStyle: pivotStyle,
36 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { useChildren } from '../common/relation';
3 +VantComponent({
4 + field: true,
5 + relation: useChildren('radio'),
6 + props: {
7 + value: {
8 + type: null,
9 + observer: 'updateChildren',
10 + },
11 + direction: String,
12 + disabled: {
13 + type: Boolean,
14 + observer: 'updateChildren',
15 + },
16 + },
17 + methods: {
18 + updateChildren() {
19 + this.children.forEach((child) => child.updateFromParent());
20 + },
21 + },
22 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view class="{{ utils.bem('radio-group', [direction]) }}">
4 + <slot></slot>
5 +</view>
1 +@import '../common/index.wxss';.van-radio-group--horizontal{display:flex;flex-wrap:wrap}
...\ No newline at end of file ...\ No newline at end of file
1 +import { canIUseModel } from '../common/version';
2 +import { VantComponent } from '../common/component';
3 +import { useParent } from '../common/relation';
4 +VantComponent({
5 + field: true,
6 + relation: useParent('radio-group', function () {
7 + this.updateFromParent();
8 + }),
9 + classes: ['icon-class', 'label-class'],
10 + props: {
11 + name: null,
12 + value: null,
13 + disabled: Boolean,
14 + useIconSlot: Boolean,
15 + checkedColor: String,
16 + labelPosition: {
17 + type: String,
18 + value: 'right',
19 + },
20 + labelDisabled: Boolean,
21 + shape: {
22 + type: String,
23 + value: 'round',
24 + },
25 + iconSize: {
26 + type: null,
27 + value: 20,
28 + },
29 + },
30 + data: {
31 + direction: '',
32 + parentDisabled: false,
33 + },
34 + methods: {
35 + updateFromParent() {
36 + if (!this.parent) {
37 + return;
38 + }
39 + const { value, disabled: parentDisabled, direction } = this.parent.data;
40 + this.setData({
41 + value,
42 + direction,
43 + parentDisabled,
44 + });
45 + },
46 + emitChange(value) {
47 + const instance = this.parent || this;
48 + instance.$emit('input', value);
49 + instance.$emit('change', value);
50 + if (canIUseModel()) {
51 + instance.setData({ value });
52 + }
53 + },
54 + onChange() {
55 + if (!this.data.disabled && !this.data.parentDisabled) {
56 + this.emitChange(this.data.name);
57 + }
58 + },
59 + onClickLabel() {
60 + const { disabled, parentDisabled, labelDisabled, name } = this.data;
61 + if (!(disabled || parentDisabled) && !labelDisabled) {
62 + this.emitChange(name);
63 + }
64 + },
65 + },
66 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view class="{{ utils.bem('radio', [direction]) }} custom-class">
5 + <view
6 + wx:if="{{ labelPosition === 'left' }}"
7 + class="{{ utils.bem('radio__label', [labelPosition, { disabled: disabled || parentDisabled }]) }} label-class"
8 + bindtap="onClickLabel"
9 + >
10 + <slot />
11 + </view>
12 + <view class="van-radio__icon-wrap" style="font-size: {{ utils.addUnit(iconSize) }}" bindtap="onChange">
13 + <slot wx:if="{{ useIconSlot }}" name="icon" />
14 + <van-icon
15 + wx:else
16 + name="success"
17 + class="{{ utils.bem('radio__icon', [shape, { disabled: disabled || parentDisabled, checked: value === name }]) }}"
18 + style="{{ computed.iconStyle({ iconSize, checkedColor, disabled, parentDisabled, value, name }) }}"
19 + custom-class="icon-class"
20 + custom-style="{{ computed.iconCustomStyle({ iconSize }) }}"
21 + />
22 + </view>
23 + <view
24 + wx:if="{{ labelPosition === 'right' }}"
25 + class="label-class {{ utils.bem('radio__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}"
26 + bindtap="onClickLabel"
27 + >
28 + <slot />
29 + </view>
30 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function iconStyle(data) {
6 + var styles = {
7 + 'font-size': addUnit(data.iconSize),
8 + };
9 +
10 + if (
11 + data.checkedColor &&
12 + !(data.disabled || data.parentDisabled) &&
13 + data.value === data.name
14 + ) {
15 + styles['border-color'] = data.checkedColor;
16 + styles['background-color'] = data.checkedColor;
17 + }
18 +
19 + return style(styles);
20 +}
21 +
22 +function iconCustomStyle(data) {
23 + return style({
24 + 'line-height': addUnit(data.iconSize),
25 + 'font-size': '.8em',
26 + display: 'block',
27 + });
28 +}
29 +
30 +module.exports = {
31 + iconStyle: iconStyle,
32 + iconCustomStyle: iconCustomStyle,
33 +};
1 +@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 ...\ No newline at end of file
1 +import { getAllRect } from '../common/utils';
2 +import { VantComponent } from '../common/component';
3 +import { canIUseModel } from '../common/version';
4 +VantComponent({
5 + field: true,
6 + classes: ['icon-class'],
7 + props: {
8 + value: {
9 + type: Number,
10 + observer(value) {
11 + if (value !== this.data.innerValue) {
12 + this.setData({ innerValue: value });
13 + }
14 + },
15 + },
16 + readonly: Boolean,
17 + disabled: Boolean,
18 + allowHalf: Boolean,
19 + size: null,
20 + icon: {
21 + type: String,
22 + value: 'star',
23 + },
24 + voidIcon: {
25 + type: String,
26 + value: 'star-o',
27 + },
28 + color: String,
29 + voidColor: String,
30 + disabledColor: String,
31 + count: {
32 + type: Number,
33 + value: 5,
34 + observer(value) {
35 + this.setData({ innerCountArray: Array.from({ length: value }) });
36 + },
37 + },
38 + gutter: null,
39 + touchable: {
40 + type: Boolean,
41 + value: true,
42 + },
43 + },
44 + data: {
45 + innerValue: 0,
46 + innerCountArray: Array.from({ length: 5 }),
47 + },
48 + methods: {
49 + onSelect(event) {
50 + const { data } = this;
51 + const { score } = event.currentTarget.dataset;
52 + if (!data.disabled && !data.readonly) {
53 + this.setData({ innerValue: score + 1 });
54 + if (canIUseModel()) {
55 + this.setData({ value: score + 1 });
56 + }
57 + wx.nextTick(() => {
58 + this.$emit('input', score + 1);
59 + this.$emit('change', score + 1);
60 + });
61 + }
62 + },
63 + onTouchMove(event) {
64 + const { touchable } = this.data;
65 + if (!touchable)
66 + return;
67 + const { clientX } = event.touches[0];
68 + getAllRect(this, '.van-rate__icon').then((list) => {
69 + const target = list
70 + .sort((cur, next) => cur.dataset.score - next.dataset.score)
71 + .find((item) => clientX >= item.left && clientX <= item.right);
72 + if (target != null) {
73 + this.onSelect(Object.assign(Object.assign({}, event), { currentTarget: target }));
74 + }
75 + });
76 + },
77 + },
78 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="../wxs/style.wxs" module="style" />
3 +
4 +<view
5 + class="{{ utils.bem('rate') }} custom-class"
6 + bind:touchmove="onTouchMove"
7 +>
8 + <view
9 + class="{{ utils.bem('rate__item') }}"
10 + wx:for="{{ innerCountArray }}"
11 + wx:key="index"
12 + style="{{ style({ paddingRight: index !== count - 1 ? utils.addUnit(gutter) : null }) }}"
13 + >
14 + <van-icon
15 + name="{{ index + 1 <= innerValue ? icon : voidIcon }}"
16 + class="{{ utils.bem('rate__icon', [{ disabled, full: index + 1 <= innerValue }])}}"
17 + style="{{ style({ fontSize: utils.addUnit(size) }) }}"
18 + custom-class="icon-class"
19 + data-score="{{ index }}"
20 + color="{{ disabled ? disabledColor : index + 1 <= innerValue ? color : voidColor }}"
21 + bind:click="onSelect"
22 + />
23 +
24 + <van-icon
25 + wx:if="{{ allowHalf }}"
26 + name="{{ index + 0.5 <= innerValue ? icon : voidIcon }}"
27 + class="{{ utils.bem('rate__icon', ['half', { disabled, full: index + 0.5 <= innerValue }]) }}"
28 + style="{{ style({ fontSize: utils.addUnit(size) }) }}"
29 + custom-class="icon-class"
30 + data-score="{{ index - 0.5 }}"
31 + color="{{ disabled ? disabledColor : index + 0.5 <= innerValue ? color : voidColor }}"
32 + bind:click="onSelect"
33 + />
34 + </view>
35 +</view>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { useChildren } from '../common/relation';
3 +VantComponent({
4 + relation: useChildren('col', function (target) {
5 + const { gutter } = this.data;
6 + if (gutter) {
7 + target.setData({ gutter });
8 + }
9 + }),
10 + props: {
11 + gutter: {
12 + type: Number,
13 + observer: 'setGutter',
14 + },
15 + },
16 + methods: {
17 + setGutter() {
18 + this.children.forEach((col) => {
19 + col.setData(this.data);
20 + });
21 + },
22 + },
23 +});
1 +<wxs src="./index.wxs" module="computed" />
2 +
3 +<view class="van-row custom-class" style="{{ computed.rootStyle({ gutter }) }}">
4 + <slot />
5 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function rootStyle(data) {
6 + if (!data.gutter) {
7 + return '';
8 + }
9 +
10 + return style({
11 + 'margin-right': addUnit(-data.gutter / 2),
12 + 'margin-left': addUnit(-data.gutter / 2),
13 + });
14 +}
15 +
16 +module.exports = {
17 + rootStyle: rootStyle,
18 +};
1 +@import '../common/index.wxss';.van-row:after{clear:both;content:"";display:table}
...\ No newline at end of file ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { canIUseModel } from '../common/version';
3 +VantComponent({
4 + field: true,
5 + classes: ['field-class', 'input-class', 'cancel-class'],
6 + props: {
7 + label: String,
8 + focus: Boolean,
9 + error: Boolean,
10 + disabled: Boolean,
11 + readonly: Boolean,
12 + inputAlign: String,
13 + showAction: Boolean,
14 + useActionSlot: Boolean,
15 + useLeftIconSlot: Boolean,
16 + useRightIconSlot: Boolean,
17 + leftIcon: {
18 + type: String,
19 + value: 'search',
20 + },
21 + rightIcon: String,
22 + placeholder: String,
23 + placeholderStyle: String,
24 + actionText: {
25 + type: String,
26 + value: '取消',
27 + },
28 + background: {
29 + type: String,
30 + value: '#ffffff',
31 + },
32 + maxlength: {
33 + type: Number,
34 + value: -1,
35 + },
36 + shape: {
37 + type: String,
38 + value: 'square',
39 + },
40 + clearable: {
41 + type: Boolean,
42 + value: true,
43 + },
44 + clearTrigger: {
45 + type: String,
46 + value: 'focus',
47 + },
48 + clearIcon: {
49 + type: String,
50 + value: 'clear',
51 + },
52 + },
53 + methods: {
54 + onChange(event) {
55 + if (canIUseModel()) {
56 + this.setData({ value: event.detail });
57 + }
58 + this.$emit('change', event.detail);
59 + },
60 + onCancel() {
61 + /**
62 + * 修复修改输入框值时,输入框失焦和赋值同时触发,赋值失效
63 + * https://github.com/youzan/@vant/weapp/issues/1768
64 + */
65 + setTimeout(() => {
66 + if (canIUseModel()) {
67 + this.setData({ value: '' });
68 + }
69 + this.$emit('cancel');
70 + this.$emit('change', '');
71 + }, 200);
72 + },
73 + onSearch(event) {
74 + this.$emit('search', event.detail);
75 + },
76 + onFocus(event) {
77 + this.$emit('focus', event.detail);
78 + },
79 + onBlur(event) {
80 + this.$emit('blur', event.detail);
81 + },
82 + onClear(event) {
83 + this.$emit('clear', event.detail);
84 + },
85 + onClickInput(event) {
86 + this.$emit('click-input', event.detail);
87 + },
88 + },
89 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-field": "../field/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view
4 + class="{{ utils.bem('search', { withaction: showAction || useActionSlot }) }} custom-class"
5 + style="background: {{ background }}"
6 +>
7 + <view class="{{ utils.bem('search__content', [shape]) }}">
8 + <view class="van-search__label" wx:if="{{ label }}">{{ label }}</view>
9 + <slot wx:else name="label" />
10 +
11 + <van-field
12 + type="search"
13 + left-icon="{{ !useLeftIconSlot ? leftIcon : '' }}"
14 + right-icon="{{ !useRightIconSlot ? rightIcon : '' }}"
15 + focus="{{ focus }}"
16 + error="{{ error }}"
17 + border="{{ false }}"
18 + confirm-type="search"
19 + class="van-search__field field-class"
20 + value="{{ value }}"
21 + disabled="{{ disabled }}"
22 + readonly="{{ readonly }}"
23 + clearable="{{ clearable }}"
24 + clear-trigger="{{ clearTrigger }}"
25 + clear-icon="{{ clearIcon }}"
26 + maxlength="{{ maxlength }}"
27 + input-align="{{ inputAlign }}"
28 + input-class="input-class"
29 + placeholder="{{ placeholder }}"
30 + placeholder-style="{{ placeholderStyle }}"
31 + custom-style="padding: 5px 10px 5px 0; background-color: transparent;"
32 + bind:blur="onBlur"
33 + bind:focus="onFocus"
34 + bind:change="onChange"
35 + bind:confirm="onSearch"
36 + bind:clear="onClear"
37 + bind:click-input="onClickInput"
38 + >
39 + <slot wx:if="{{ useLeftIconSlot }}" name="left-icon" slot="left-icon" />
40 + <slot wx:if="{{ useRightIconSlot }}" name="right-icon" slot="right-icon" />
41 + </van-field>
42 + </view>
43 +
44 + <view
45 + wx:if="{{ showAction || useActionSlot }}"
46 + class="van-search__action"
47 + hover-class="van-search__action--hover"
48 + hover-stay-time="70"
49 + >
50 + <slot wx:if="{{ useActionSlot }}" name="action" />
51 + <view wx:else bind:tap="onCancel" class="cancel-class">{{ actionText }}</view>
52 + </view>
53 +</view>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + props: {
4 + // whether to show popup
5 + show: Boolean,
6 + // overlay custom style
7 + overlayStyle: String,
8 + // z-index
9 + zIndex: {
10 + type: Number,
11 + value: 100,
12 + },
13 + title: String,
14 + cancelText: {
15 + type: String,
16 + value: '取消',
17 + },
18 + description: String,
19 + options: {
20 + type: Array,
21 + value: [],
22 + },
23 + overlay: {
24 + type: Boolean,
25 + value: true,
26 + },
27 + safeAreaInsetBottom: {
28 + type: Boolean,
29 + value: true,
30 + },
31 + closeOnClickOverlay: {
32 + type: Boolean,
33 + value: true,
34 + },
35 + duration: {
36 + type: null,
37 + value: 300,
38 + },
39 + },
40 + methods: {
41 + onClickOverlay() {
42 + this.$emit('click-overlay');
43 + },
44 + onCancel() {
45 + this.onClose();
46 + this.$emit('cancel');
47 + },
48 + onSelect(event) {
49 + this.$emit('select', event.detail);
50 + },
51 + onClose() {
52 + this.$emit('close');
53 + },
54 + },
55 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-popup": "../popup/index",
5 + "options": "./options"
6 + }
7 +}
1 +<wxs src="./index.wxs" module="computed" />
2 +
3 +<van-popup
4 + round
5 + class="van-share-sheet"
6 + show="{{ show }}"
7 + position="bottom"
8 + overlay="{{ overlay }}"
9 + duration="{{ duration }}"
10 + z-index="{{ zIndex }}"
11 + overlay-style="{{ overlayStyle }}"
12 + close-on-click-overlay="{{ closeOnClickOverlay }}"
13 + safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
14 + bind:close="onClose"
15 + bind:click-overlay="onClickOverlay"
16 +>
17 + <view class="van-share-sheet__header">
18 + <view class="van-share-sheet__title">
19 + <slot name="title" />
20 + </view>
21 + <view wx:if="{{ title }}" class="van-share-sheet__title">{{ title }}</view>
22 +
23 + <view class="van-share-sheet__description">
24 + <slot name="description" />
25 + </view>
26 + <view wx:if="{{ description }}" class="van-share-sheet__description">
27 + {{ description }}
28 + </view>
29 + </view>
30 +
31 + <block wx:if="{{ computed.isMulti(options) }}">
32 + <options
33 + wx:for="{{ options }}"
34 + show-border="{{ index !== 0 }}"
35 + wx:key="index"
36 + options="{{ item }}"
37 + bind:select="onSelect"
38 + />
39 + </block>
40 +
41 + <options wx:else options="{{ options }}" bind:select="onSelect" />
42 +
43 + <button type="button" class="van-share-sheet__cancel" bindtap="onCancel">
44 + {{ cancelText }}
45 + </button>
46 +</van-popup>
1 +/* eslint-disable */
2 +function isMulti(options) {
3 + if (options == null || options[0] == null) {
4 + return false;
5 + }
6 +
7 + return "Array" === options.constructor && "Array" === options[0].constructor;
8 +}
9 +
10 +module.exports = {
11 + isMulti: isMulti
12 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + props: {
4 + options: Array,
5 + showBorder: Boolean,
6 + },
7 + methods: {
8 + onSelect(event) {
9 + const { index } = event.currentTarget.dataset;
10 + const option = this.data.options[index];
11 + this.$emit('select', Object.assign(Object.assign({}, option), { index }));
12 + },
13 + },
14 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./options.wxs" module="computed" />
3 +
4 +<view class="{{ utils.bem('share-sheet__options', { border: showBorder }) }}">
5 + <view
6 + wx:for="{{ options }}"
7 + wx:key="index"
8 + class="van-share-sheet__option"
9 + data-index="{{ index }}"
10 + bindtap="onSelect"
11 + >
12 + <button class="van-share-sheet__button" open-type="{{ item.openType }}">
13 + <image src="{{ computed.getIconURL(item.icon) }}" class="van-share-sheet__icon" />
14 + <view wx:if="{{ item.name }}" class="van-share-sheet__name">{{ item.name }}</view>
15 + <view wx:if="{{ item.description }}" class="van-share-sheet__option-description">
16 + {{ item.description }}
17 + </view>
18 + </button>
19 + </view>
20 +</view>
1 +/* eslint-disable */
2 +var PRESET_ICONS = ['qq', 'link', 'weibo', 'wechat', 'poster', 'qrcode', 'weapp-qrcode', 'wechat-moments'];
3 +
4 +function getIconURL(icon) {
5 + if (PRESET_ICONS.indexOf(icon) !== -1) {
6 + return 'https://img.yzcdn.cn/vant/share-sheet-' + icon + '.png';
7 + }
8 +
9 + return icon;
10 +}
11 +
12 +module.exports = {
13 + getIconURL: getIconURL,
14 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { useParent } from '../common/relation';
3 +VantComponent({
4 + classes: ['active-class', 'disabled-class'],
5 + relation: useParent('sidebar'),
6 + props: {
7 + dot: Boolean,
8 + badge: null,
9 + info: null,
10 + title: String,
11 + disabled: Boolean,
12 + },
13 + methods: {
14 + onClick() {
15 + const { parent } = this;
16 + if (!parent || this.data.disabled) {
17 + return;
18 + }
19 + const index = parent.children.indexOf(this);
20 + parent.setActive(index).then(() => {
21 + this.$emit('click', index);
22 + parent.$emit('change', index);
23 + });
24 + },
25 + setActive(selected) {
26 + return this.setData({ selected });
27 + },
28 + },
29 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-info": "../info/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view
4 + class="{{ utils.bem('sidebar-item', { selected, disabled }) }} {{ selected ? 'active-class' : '' }} {{ disabled ? 'disabled-class' : '' }} custom-class"
5 + hover-class="van-sidebar-item--hover"
6 + hover-stay-time="70"
7 + bind:tap="onClick"
8 +>
9 + <view class="van-sidebar-item__text">
10 + <van-info
11 + wx:if="{{ badge != null || info !== null || dot }}"
12 + dot="{{ dot }}"
13 + info="{{ badge != null ? badge : info }}"
14 + />
15 + <view wx:if="{{ title }}">{{ title }}</view>
16 + <slot wx:else name="title" />
17 + </view>
18 +</view>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { useChildren } from '../common/relation';
3 +VantComponent({
4 + relation: useChildren('sidebar-item', function () {
5 + this.setActive(this.data.activeKey);
6 + }),
7 + props: {
8 + activeKey: {
9 + type: Number,
10 + value: 0,
11 + observer: 'setActive',
12 + },
13 + },
14 + beforeCreate() {
15 + this.currentActive = -1;
16 + },
17 + methods: {
18 + setActive(activeKey) {
19 + const { children, currentActive } = this;
20 + if (!children.length) {
21 + return Promise.resolve();
22 + }
23 + this.currentActive = activeKey;
24 + const stack = [];
25 + if (currentActive !== activeKey && children[currentActive]) {
26 + stack.push(children[currentActive].setActive(false));
27 + }
28 + if (children[activeKey]) {
29 + stack.push(children[activeKey].setActive(true));
30 + }
31 + return Promise.all(stack);
32 + },
33 + },
34 +});
1 +<view class="van-sidebar custom-class">
2 + <slot />
3 +</view>
1 +@import '../common/index.wxss';.van-sidebar{width:var(--sidebar-width,80px)}
...\ No newline at end of file ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + classes: ['avatar-class', 'title-class', 'row-class'],
4 + props: {
5 + row: {
6 + type: Number,
7 + value: 0,
8 + observer(value) {
9 + this.setData({ rowArray: Array.from({ length: value }) });
10 + },
11 + },
12 + title: Boolean,
13 + avatar: Boolean,
14 + loading: {
15 + type: Boolean,
16 + value: true,
17 + },
18 + animate: {
19 + type: Boolean,
20 + value: true,
21 + },
22 + avatarSize: {
23 + type: String,
24 + value: '32px',
25 + },
26 + avatarShape: {
27 + type: String,
28 + value: 'round',
29 + },
30 + titleWidth: {
31 + type: String,
32 + value: '40%',
33 + },
34 + rowWidth: {
35 + type: null,
36 + value: '100%',
37 + observer(val) {
38 + this.setData({ isArray: val instanceof Array });
39 + },
40 + },
41 + },
42 + data: {
43 + isArray: false,
44 + rowArray: [],
45 + },
46 +});
1 +{
2 + "component": true,
3 + "usingComponents": {}
4 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view
4 + wx:if="{{ loading }}"
5 + class="custom-class {{ utils.bem('skeleton', [{animate}]) }}"
6 +>
7 + <view
8 + wx:if="{{ avatar }}"
9 + class="avatar-class {{ utils.bem('skeleton__avatar', [avatarShape])}}"
10 + style="{{ 'width:' + avatarSize + ';height:' + avatarSize }}"
11 + />
12 + <view class="{{ utils.bem('skeleton__content')}}">
13 + <view
14 + wx:if="{{ title }}"
15 + class="title-class {{ utils.bem('skeleton__title') }}"
16 + style="{{ 'width:' + titleWidth }}"
17 + />
18 + <view
19 + wx:for="{{ rowArray }}"
20 + wx:key="index"
21 + wx:for-index="index"
22 + class="row-class {{ utils.bem('skeleton__row') }}"
23 + style="{{ 'width:' + (isArray ? rowWidth[index] : rowWidth) }}"
24 + />
25 + </view>
26 +</view>
27 +<view wx:else class="{{ utils.bem('skeleton__content')}}">
28 + <slot />
29 +</view>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { touch } from '../mixins/touch';
3 +import { canIUseModel } from '../common/version';
4 +import { getRect, addUnit } from '../common/utils';
5 +VantComponent({
6 + mixins: [touch],
7 + props: {
8 + range: Boolean,
9 + disabled: Boolean,
10 + useButtonSlot: Boolean,
11 + activeColor: String,
12 + inactiveColor: String,
13 + max: {
14 + type: Number,
15 + value: 100,
16 + },
17 + min: {
18 + type: Number,
19 + value: 0,
20 + },
21 + step: {
22 + type: Number,
23 + value: 1,
24 + },
25 + value: {
26 + type: null,
27 + value: 0,
28 + observer(val) {
29 + if (val !== this.value) {
30 + this.updateValue(val);
31 + }
32 + },
33 + },
34 + vertical: Boolean,
35 + barHeight: null,
36 + },
37 + created() {
38 + this.updateValue(this.data.value);
39 + },
40 + methods: {
41 + onTouchStart(event) {
42 + if (this.data.disabled)
43 + return;
44 + const { index } = event.currentTarget.dataset;
45 + if (typeof index === 'number') {
46 + this.buttonIndex = index;
47 + }
48 + this.touchStart(event);
49 + this.startValue = this.format(this.value);
50 + this.newValue = this.value;
51 + if (this.isRange(this.newValue)) {
52 + this.startValue = this.newValue.map((val) => this.format(val));
53 + }
54 + else {
55 + this.startValue = this.format(this.newValue);
56 + }
57 + this.dragStatus = 'start';
58 + },
59 + onTouchMove(event) {
60 + if (this.data.disabled)
61 + return;
62 + if (this.dragStatus === 'start') {
63 + this.$emit('drag-start');
64 + }
65 + this.touchMove(event);
66 + this.dragStatus = 'draging';
67 + getRect(this, '.van-slider').then((rect) => {
68 + const { vertical } = this.data;
69 + const delta = vertical ? this.deltaY : this.deltaX;
70 + const total = vertical ? rect.height : rect.width;
71 + const diff = (delta / total) * this.getRange();
72 + if (this.isRange(this.startValue)) {
73 + this.newValue[this.buttonIndex] =
74 + this.startValue[this.buttonIndex] + diff;
75 + }
76 + else {
77 + this.newValue = this.startValue + diff;
78 + }
79 + this.updateValue(this.newValue, false, true);
80 + });
81 + },
82 + onTouchEnd() {
83 + if (this.data.disabled)
84 + return;
85 + if (this.dragStatus === 'draging') {
86 + this.updateValue(this.newValue, true);
87 + this.$emit('drag-end');
88 + }
89 + },
90 + onClick(event) {
91 + if (this.data.disabled)
92 + return;
93 + const { min } = this.data;
94 + getRect(this, '.van-slider').then((rect) => {
95 + const { vertical } = this.data;
96 + const touch = event.touches[0];
97 + const delta = vertical
98 + ? touch.clientY - rect.top
99 + : touch.clientX - rect.left;
100 + const total = vertical ? rect.height : rect.width;
101 + const value = Number(min) + (delta / total) * this.getRange();
102 + if (this.isRange(this.value)) {
103 + const [left, right] = this.value;
104 + const middle = (left + right) / 2;
105 + if (value <= middle) {
106 + this.updateValue([value, right], true);
107 + }
108 + else {
109 + this.updateValue([left, value], true);
110 + }
111 + }
112 + else {
113 + this.updateValue(value, true);
114 + }
115 + });
116 + },
117 + isRange(val) {
118 + const { range } = this.data;
119 + return range && Array.isArray(val);
120 + },
121 + handleOverlap(value) {
122 + if (value[0] > value[1]) {
123 + return value.slice(0).reverse();
124 + }
125 + return value;
126 + },
127 + updateValue(value, end, drag) {
128 + if (this.isRange(value)) {
129 + value = this.handleOverlap(value).map((val) => this.format(val));
130 + }
131 + else {
132 + value = this.format(value);
133 + }
134 + this.value = value;
135 + const { vertical } = this.data;
136 + const mainAxis = vertical ? 'height' : 'width';
137 + this.setData({
138 + wrapperStyle: `
139 + background: ${this.data.inactiveColor || ''};
140 + ${vertical ? 'width' : 'height'}: ${addUnit(this.data.barHeight) || ''};
141 + `,
142 + barStyle: `
143 + ${mainAxis}: ${this.calcMainAxis()};
144 + left: ${vertical ? 0 : this.calcOffset()};
145 + top: ${vertical ? this.calcOffset() : 0};
146 + ${drag ? 'transition: none;' : ''}
147 + `,
148 + });
149 + if (drag) {
150 + this.$emit('drag', { value });
151 + }
152 + if (end) {
153 + this.$emit('change', value);
154 + }
155 + if ((drag || end) && canIUseModel()) {
156 + this.setData({ value });
157 + }
158 + },
159 + getScope() {
160 + return Number(this.data.max) - Number(this.data.min);
161 + },
162 + getRange() {
163 + const { max, min } = this.data;
164 + return max - min;
165 + },
166 + // 计算选中条的长度百分比
167 + calcMainAxis() {
168 + const { value } = this;
169 + const { min } = this.data;
170 + const scope = this.getScope();
171 + if (this.isRange(value)) {
172 + return `${((value[1] - value[0]) * 100) / scope}%`;
173 + }
174 + return `${((value - Number(min)) * 100) / scope}%`;
175 + },
176 + // 计算选中条的开始位置的偏移量
177 + calcOffset() {
178 + const { value } = this;
179 + const { min } = this.data;
180 + const scope = this.getScope();
181 + if (this.isRange(value)) {
182 + return `${((value[0] - Number(min)) * 100) / scope}%`;
183 + }
184 + return '0%';
185 + },
186 + format(value) {
187 + const { max, min, step } = this.data;
188 + return Math.round(Math.max(min, Math.min(value, max)) / step) * step;
189 + },
190 + },
191 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="../wxs/style.wxs" module="style" />
3 +
4 +<view
5 + class="custom-class {{ utils.bem('slider', { disabled, vertical }) }}"
6 + style="{{ wrapperStyle }}"
7 + bind:tap="onClick"
8 +>
9 + <view
10 + class="{{ utils.bem('slider__bar') }}"
11 + style="{{ barStyle }}; {{ style({ backgroundColor: activeColor }) }}"
12 + >
13 + <view
14 + wx:if="{{ range }}"
15 + class="{{ utils.bem('slider__button-wrapper-left') }}"
16 + data-index="{{ 0 }}"
17 + bind:touchstart="onTouchStart"
18 + catch:touchmove="onTouchMove"
19 + bind:touchend="onTouchEnd"
20 + bind:touchcancel="onTouchEnd"
21 + >
22 + <slot
23 + wx:if="{{ useButtonSlot }}"
24 + name="left-button"
25 + />
26 + <view
27 + wx:else
28 + class="{{ utils.bem('slider__button') }}"
29 + />
30 + </view>
31 + <view
32 + wx:if="{{ range }}"
33 + class="{{ utils.bem('slider__button-wrapper-right') }}"
34 + data-index="{{ 1 }}"
35 + bind:touchstart="onTouchStart"
36 + catch:touchmove="onTouchMove"
37 + bind:touchend="onTouchEnd"
38 + bind:touchcancel="onTouchEnd"
39 + >
40 + <slot
41 + wx:if="{{ useButtonSlot }}"
42 + name="right-button"
43 + />
44 + <view
45 + wx:else
46 + class="{{ utils.bem('slider__button') }}"
47 + />
48 + </view>
49 +
50 + <view
51 + wx:if="{{ !range }}"
52 + class="{{ utils.bem('slider__button-wrapper') }}"
53 + bind:touchstart="onTouchStart"
54 + catch:touchmove="onTouchMove"
55 + bind:touchend="onTouchEnd"
56 + bind:touchcancel="onTouchEnd"
57 + >
58 + <slot
59 + wx:if="{{ useButtonSlot }}"
60 + name="button"
61 + />
62 + <view
63 + wx:else
64 + class="{{ utils.bem('slider__button') }}"
65 + />
66 + </view>
67 + </view>
68 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function barStyle(barHeight, activeColor) {
6 + return style({
7 + height: addUnit(barHeight),
8 + background: activeColor,
9 + });
10 +}
11 +
12 +module.exports = {
13 + barStyle: barStyle,
14 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { isDef } from '../common/validator';
3 +const LONG_PRESS_START_TIME = 600;
4 +const LONG_PRESS_INTERVAL = 200;
5 +// add num and avoid float number
6 +function add(num1, num2) {
7 + const cardinal = Math.pow(10, 10);
8 + return Math.round((num1 + num2) * cardinal) / cardinal;
9 +}
10 +function equal(value1, value2) {
11 + return String(value1) === String(value2);
12 +}
13 +VantComponent({
14 + field: true,
15 + classes: ['input-class', 'plus-class', 'minus-class'],
16 + props: {
17 + value: {
18 + type: null,
19 + observer: 'observeValue',
20 + },
21 + integer: {
22 + type: Boolean,
23 + observer: 'check',
24 + },
25 + disabled: Boolean,
26 + inputWidth: String,
27 + buttonSize: String,
28 + asyncChange: Boolean,
29 + disableInput: Boolean,
30 + decimalLength: {
31 + type: Number,
32 + value: null,
33 + observer: 'check',
34 + },
35 + min: {
36 + type: null,
37 + value: 1,
38 + observer: 'check',
39 + },
40 + max: {
41 + type: null,
42 + value: Number.MAX_SAFE_INTEGER,
43 + observer: 'check',
44 + },
45 + step: {
46 + type: null,
47 + value: 1,
48 + },
49 + showPlus: {
50 + type: Boolean,
51 + value: true,
52 + },
53 + showMinus: {
54 + type: Boolean,
55 + value: true,
56 + },
57 + disablePlus: Boolean,
58 + disableMinus: Boolean,
59 + longPress: {
60 + type: Boolean,
61 + value: true,
62 + },
63 + theme: String,
64 + alwaysEmbed: Boolean,
65 + },
66 + data: {
67 + currentValue: '',
68 + },
69 + created() {
70 + this.setData({
71 + currentValue: this.format(this.data.value),
72 + });
73 + },
74 + methods: {
75 + observeValue() {
76 + const { value, currentValue } = this.data;
77 + if (!equal(value, currentValue)) {
78 + this.setData({ currentValue: this.format(value) });
79 + }
80 + },
81 + check() {
82 + const val = this.format(this.data.currentValue);
83 + if (!equal(val, this.data.currentValue)) {
84 + this.setData({ currentValue: val });
85 + }
86 + },
87 + isDisabled(type) {
88 + const { disabled, disablePlus, disableMinus, currentValue, max, min, } = this.data;
89 + if (type === 'plus') {
90 + return disabled || disablePlus || currentValue >= max;
91 + }
92 + return disabled || disableMinus || currentValue <= min;
93 + },
94 + onFocus(event) {
95 + this.$emit('focus', event.detail);
96 + },
97 + onBlur(event) {
98 + const value = this.format(event.detail.value);
99 + this.emitChange(value);
100 + this.$emit('blur', Object.assign(Object.assign({}, event.detail), { value }));
101 + },
102 + // filter illegal characters
103 + filter(value) {
104 + value = String(value).replace(/[^0-9.-]/g, '');
105 + if (this.data.integer && value.indexOf('.') !== -1) {
106 + value = value.split('.')[0];
107 + }
108 + return value;
109 + },
110 + // limit value range
111 + format(value) {
112 + value = this.filter(value);
113 + // format range
114 + value = value === '' ? 0 : +value;
115 + value = Math.max(Math.min(this.data.max, value), this.data.min);
116 + // format decimal
117 + if (isDef(this.data.decimalLength)) {
118 + value = value.toFixed(this.data.decimalLength);
119 + }
120 + return value;
121 + },
122 + onInput(event) {
123 + const { value = '' } = event.detail || {};
124 + // allow input to be empty
125 + if (value === '') {
126 + return;
127 + }
128 + let formatted = this.filter(value);
129 + // limit max decimal length
130 + if (isDef(this.data.decimalLength) && formatted.indexOf('.') !== -1) {
131 + const pair = formatted.split('.');
132 + formatted = `${pair[0]}.${pair[1].slice(0, this.data.decimalLength)}`;
133 + }
134 + this.emitChange(formatted);
135 + },
136 + emitChange(value) {
137 + if (!this.data.asyncChange) {
138 + this.setData({ currentValue: value });
139 + }
140 + this.$emit('change', value);
141 + },
142 + onChange() {
143 + const { type } = this;
144 + if (this.isDisabled(type)) {
145 + this.$emit('overlimit', type);
146 + return;
147 + }
148 + const diff = type === 'minus' ? -this.data.step : +this.data.step;
149 + const value = this.format(add(+this.data.currentValue, diff));
150 + this.emitChange(value);
151 + this.$emit(type);
152 + },
153 + longPressStep() {
154 + this.longPressTimer = setTimeout(() => {
155 + this.onChange();
156 + this.longPressStep();
157 + }, LONG_PRESS_INTERVAL);
158 + },
159 + onTap(event) {
160 + const { type } = event.currentTarget.dataset;
161 + this.type = type;
162 + this.onChange();
163 + },
164 + onTouchStart(event) {
165 + if (!this.data.longPress) {
166 + return;
167 + }
168 + clearTimeout(this.longPressTimer);
169 + const { type } = event.currentTarget.dataset;
170 + this.type = type;
171 + this.isLongPress = false;
172 + this.longPressTimer = setTimeout(() => {
173 + this.isLongPress = true;
174 + this.onChange();
175 + this.longPressStep();
176 + }, LONG_PRESS_START_TIME);
177 + },
178 + onTouchEnd() {
179 + if (!this.data.longPress) {
180 + return;
181 + }
182 + clearTimeout(this.longPressTimer);
183 + },
184 + },
185 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view class="{{ utils.bem('stepper', [theme]) }} custom-class">
5 + <view
6 + wx:if="{{ showMinus }}"
7 + data-type="minus"
8 + style="{{ computed.buttonStyle({ buttonSize }) }}"
9 + class="minus-class {{ utils.bem('stepper__minus', { disabled: disabled || disableMinus || currentValue <= min }) }}"
10 + hover-class="van-stepper__minus--hover"
11 + hover-stay-time="70"
12 + bind:tap="onTap"
13 + bind:touchstart="onTouchStart"
14 + bind:touchend="onTouchEnd"
15 + >
16 + <slot name="minus" />
17 + </view>
18 + <input
19 + always-embed="{{ false }}"
20 + type="{{ integer ? 'number' : 'digit' }}"
21 + class="input-class {{ utils.bem('stepper__input', { disabled: disabled || disableInput }) }}"
22 + style="{{ computed.inputStyle({ buttonSize, inputWidth }) }}"
23 + value="{{ currentValue }}"
24 + focus="{{ focus }}"
25 + disabled="{{ disabled || disableInput }}"
26 + always-embed="{{ alwaysEmbed }}"
27 + bindinput="onInput"
28 + bind:focus="onFocus"
29 + bind:blur="onBlur"
30 + />
31 + <view
32 + wx:if="{{ showPlus }}"
33 + data-type="plus"
34 + style="{{ computed.buttonStyle({ buttonSize }) }}"
35 + class="plus-class {{ utils.bem('stepper__plus', { disabled: disabled || disablePlus || currentValue >= max }) }}"
36 + hover-class="van-stepper__plus--hover"
37 + hover-stay-time="70"
38 + bind:tap="onTap"
39 + bind:touchstart="onTouchStart"
40 + bind:touchend="onTouchEnd"
41 + >
42 + <slot name="plus" />
43 + </view>
44 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function buttonStyle(data) {
6 + return style({
7 + width: addUnit(data.buttonSize),
8 + height: addUnit(data.buttonSize),
9 + });
10 +}
11 +
12 +function inputStyle(data) {
13 + return style({
14 + width: addUnit(data.inputWidth),
15 + height: addUnit(data.buttonSize),
16 + });
17 +}
18 +
19 +module.exports = {
20 + buttonStyle: buttonStyle,
21 + inputStyle: inputStyle,
22 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { GREEN, GRAY_DARK } from '../common/color';
3 +VantComponent({
4 + classes: ['desc-class'],
5 + props: {
6 + icon: String,
7 + steps: Array,
8 + active: Number,
9 + direction: {
10 + type: String,
11 + value: 'horizontal',
12 + },
13 + activeColor: {
14 + type: String,
15 + value: GREEN,
16 + },
17 + inactiveColor: {
18 + type: String,
19 + value: GRAY_DARK,
20 + },
21 + activeIcon: {
22 + type: String,
23 + value: 'checked',
24 + },
25 + inactiveIcon: String,
26 + },
27 + methods: {
28 + onClick(event) {
29 + const { index } = event.currentTarget.dataset;
30 + this.$emit('click-step', index);
31 + },
32 + },
33 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view class="custom-class {{ utils.bem('steps', [direction]) }}">
4 + <view class="van-step__wrapper">
5 + <view
6 + wx:for="{{ steps }}"
7 + wx:key="index"
8 + bindtap="onClick"
9 + data-index="{{ index }}"
10 + class="{{ utils.bem('step', [direction, status(index, active)]) }} van-hairline"
11 + style="{{ status(index, active) === 'inactive' ? 'color: ' + inactiveColor: '' }}"
12 + >
13 + <view class="van-step__title" style="{{ index === active ? 'color: ' + activeColor : '' }}">
14 + <view>{{ item.text }}</view>
15 + <view class="desc-class">{{ item.desc }}</view>
16 + </view>
17 + <view class="van-step__circle-container">
18 + <block wx:if="{{ index !== active }}">
19 + <van-icon
20 + wx:if="{{ item.inactiveIcon || inactiveIcon }}"
21 + color="{{ status(index, active) === 'inactive' ? inactiveColor: activeColor }}"
22 + name="{{ item.inactiveIcon || inactiveIcon }}"
23 + custom-class="van-step__icon"
24 + />
25 + <view
26 + wx:else
27 + class="van-step__circle"
28 + style="{{ 'background-color: ' + (index < active ? activeColor : inactiveColor) }}"
29 + />
30 + </block>
31 +
32 + <van-icon wx:else name="{{ item.activeIcon || activeIcon }}" color="{{ activeColor }}" custom-class="van-step__icon" />
33 + </view>
34 + <view
35 + wx:if="{{ index !== steps.length - 1 }}"
36 + class="van-step__line" style="{{ 'background-color: ' + (index < active ? activeColor : inactiveColor) }}"
37 + />
38 + </view>
39 + </view>
40 +</view>
41 +
42 +<wxs module="status">
43 +function get(index, active) {
44 + if (index < active) {
45 + return 'finish';
46 + } else if (index === active) {
47 + return 'process';
48 + }
49 +
50 + return 'inactive';
51 +}
52 +
53 +module.exports = get;
54 +</wxs>
1 +@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 ...\ No newline at end of file
1 +import { getRect } from '../common/utils';
2 +import { VantComponent } from '../common/component';
3 +import { isDef } from '../common/validator';
4 +import { pageScrollMixin } from '../mixins/page-scroll';
5 +const ROOT_ELEMENT = '.van-sticky';
6 +VantComponent({
7 + props: {
8 + zIndex: {
9 + type: Number,
10 + value: 99,
11 + },
12 + offsetTop: {
13 + type: Number,
14 + value: 0,
15 + observer: 'onScroll',
16 + },
17 + disabled: {
18 + type: Boolean,
19 + observer: 'onScroll',
20 + },
21 + container: {
22 + type: null,
23 + observer: 'onScroll',
24 + },
25 + scrollTop: {
26 + type: null,
27 + observer(val) {
28 + this.onScroll({ scrollTop: val });
29 + },
30 + },
31 + },
32 + mixins: [
33 + pageScrollMixin(function (event) {
34 + if (this.data.scrollTop != null) {
35 + return;
36 + }
37 + this.onScroll(event);
38 + }),
39 + ],
40 + data: {
41 + height: 0,
42 + fixed: false,
43 + transform: 0,
44 + },
45 + mounted() {
46 + this.onScroll();
47 + },
48 + methods: {
49 + onScroll({ scrollTop } = {}) {
50 + const { container, offsetTop, disabled } = this.data;
51 + if (disabled) {
52 + this.setDataAfterDiff({
53 + fixed: false,
54 + transform: 0,
55 + });
56 + return;
57 + }
58 + this.scrollTop = scrollTop || this.scrollTop;
59 + if (typeof container === 'function') {
60 + Promise.all([
61 + getRect(this, ROOT_ELEMENT),
62 + this.getContainerRect(),
63 + ]).then(([root, container]) => {
64 + if (offsetTop + root.height > container.height + container.top) {
65 + this.setDataAfterDiff({
66 + fixed: false,
67 + transform: container.height - root.height,
68 + });
69 + }
70 + else if (offsetTop >= root.top) {
71 + this.setDataAfterDiff({
72 + fixed: true,
73 + height: root.height,
74 + transform: 0,
75 + });
76 + }
77 + else {
78 + this.setDataAfterDiff({ fixed: false, transform: 0 });
79 + }
80 + });
81 + return;
82 + }
83 + getRect(this, ROOT_ELEMENT).then((root) => {
84 + if (!isDef(root)) {
85 + return;
86 + }
87 + if (offsetTop >= root.top) {
88 + this.setDataAfterDiff({ fixed: true, height: root.height });
89 + this.transform = 0;
90 + }
91 + else {
92 + this.setDataAfterDiff({ fixed: false });
93 + }
94 + });
95 + },
96 + setDataAfterDiff(data) {
97 + wx.nextTick(() => {
98 + const diff = Object.keys(data).reduce((prev, key) => {
99 + if (data[key] !== this.data[key]) {
100 + prev[key] = data[key];
101 + }
102 + return prev;
103 + }, {});
104 + if (Object.keys(diff).length > 0) {
105 + this.setData(diff);
106 + }
107 + this.$emit('scroll', {
108 + scrollTop: this.scrollTop,
109 + isFixed: data.fixed || this.data.fixed,
110 + });
111 + });
112 + },
113 + getContainerRect() {
114 + const nodesRef = this.data.container();
115 + return new Promise((resolve) => nodesRef.boundingClientRect(resolve).exec());
116 + },
117 + },
118 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view class="custom-class van-sticky" style="{{ computed.containerStyle({ fixed, height, zIndex }) }}">
5 + <view class="{{ utils.bem('sticky-wrap', { fixed }) }}" style="{{ computed.wrapStyle({ fixed, offsetTop, transform, zIndex }) }}">
6 + <slot />
7 + </view>
8 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function wrapStyle(data) {
6 + return style({
7 + transform: data.transform
8 + ? 'translate3d(0, ' + data.transform + 'px, 0)'
9 + : '',
10 + top: data.fixed ? addUnit(data.offsetTop) : '',
11 + 'z-index': data.zIndex,
12 + });
13 +}
14 +
15 +function containerStyle(data) {
16 + return style({
17 + height: data.fixed ? addUnit(data.height) : '',
18 + 'z-index': data.zIndex,
19 + });
20 +}
21 +
22 +module.exports = {
23 + wrapStyle: wrapStyle,
24 + containerStyle: containerStyle,
25 +};
1 +@import '../common/index.wxss';.van-sticky{position:relative}.van-sticky-wrap--fixed{left:0;position:fixed;right:0}
...\ No newline at end of file ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + classes: ['bar-class', 'price-class', 'button-class'],
4 + props: {
5 + tip: {
6 + type: null,
7 + observer: 'updateTip',
8 + },
9 + tipIcon: String,
10 + type: Number,
11 + price: {
12 + type: null,
13 + observer: 'updatePrice',
14 + },
15 + label: String,
16 + loading: Boolean,
17 + disabled: Boolean,
18 + buttonText: String,
19 + currency: {
20 + type: String,
21 + value: '¥',
22 + },
23 + buttonType: {
24 + type: String,
25 + value: 'danger',
26 + },
27 + decimalLength: {
28 + type: Number,
29 + value: 2,
30 + observer: 'updatePrice',
31 + },
32 + suffixLabel: String,
33 + safeAreaInsetBottom: {
34 + type: Boolean,
35 + value: true,
36 + },
37 + },
38 + methods: {
39 + updatePrice() {
40 + const { price, decimalLength } = this.data;
41 + const priceStrArr = typeof price === 'number' &&
42 + (price / 100).toFixed(decimalLength).split('.');
43 + this.setData({
44 + hasPrice: typeof price === 'number',
45 + integerStr: priceStrArr && priceStrArr[0],
46 + decimalStr: decimalLength && priceStrArr ? `.${priceStrArr[1]}` : '',
47 + });
48 + },
49 + updateTip() {
50 + this.setData({ hasTip: typeof this.data.tip === 'string' });
51 + },
52 + onSubmit(event) {
53 + this.$emit('submit', event.detail);
54 + },
55 + },
56 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-button": "../button/index",
5 + "van-icon": "../icon/index"
6 + }
7 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view class="van-submit-bar custom-class">
4 + <slot name="top" />
5 +
6 + <view class="van-submit-bar__tip">
7 + <van-icon
8 + wx:if="{{ tipIcon }}"
9 + size="12px"
10 + name="{{ tipIcon }}"
11 + custom-class="van-submit-bar__tip-icon"
12 + />
13 + <view wx:if="{{ hasTip }}" class="van-submit-bar__tip-text">
14 + {{ tip }}
15 + </view>
16 + <slot name="tip" />
17 + </view>
18 +
19 + <view class="bar-class van-submit-bar__bar">
20 + <slot />
21 + <view wx:if="{{ hasPrice }}" class="van-submit-bar__text">
22 + <text>{{ label || '合计:' }}</text>
23 + <text class="van-submit-bar__price price-class">
24 + <text class="van-submit-bar__currency">{{ currency }} </text>
25 + <text class="van-submit-bar__price-integer">{{ integerStr }}</text><text>{{decimalStr}}</text>
26 + </text>
27 + <text class="van-submit-bar__suffix-label">{{ suffixLabel }}</text>
28 + </view>
29 + <van-button
30 + round
31 + type="{{ buttonType }}"
32 + loading="{{ loading }}"
33 + disabled="{{ disabled }}"
34 + class="van-submit-bar__button"
35 + custom-class="button-class"
36 + custom-style="width: 100%;"
37 + bind:click="onSubmit"
38 + >
39 + {{ loading ? '' : buttonText }}
40 + </van-button>
41 + </view>
42 +
43 + <view wx:if="{{ safeAreaInsetBottom }}" class="van-submit-bar__safe" />
44 +</view>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { touch } from '../mixins/touch';
3 +import { range } from '../common/utils';
4 +const THRESHOLD = 0.3;
5 +let ARRAY = [];
6 +VantComponent({
7 + props: {
8 + disabled: Boolean,
9 + leftWidth: {
10 + type: Number,
11 + value: 0,
12 + observer(leftWidth = 0) {
13 + if (this.offset > 0) {
14 + this.swipeMove(leftWidth);
15 + }
16 + },
17 + },
18 + rightWidth: {
19 + type: Number,
20 + value: 0,
21 + observer(rightWidth = 0) {
22 + if (this.offset < 0) {
23 + this.swipeMove(-rightWidth);
24 + }
25 + },
26 + },
27 + asyncClose: Boolean,
28 + name: {
29 + type: null,
30 + value: '',
31 + },
32 + },
33 + mixins: [touch],
34 + data: {
35 + catchMove: false,
36 + wrapperStyle: '',
37 + },
38 + created() {
39 + this.offset = 0;
40 + ARRAY.push(this);
41 + },
42 + destroyed() {
43 + ARRAY = ARRAY.filter((item) => item !== this);
44 + },
45 + methods: {
46 + open(position) {
47 + const { leftWidth, rightWidth } = this.data;
48 + const offset = position === 'left' ? leftWidth : -rightWidth;
49 + this.swipeMove(offset);
50 + this.$emit('open', {
51 + position,
52 + name: this.data.name,
53 + });
54 + },
55 + close() {
56 + this.swipeMove(0);
57 + },
58 + swipeMove(offset = 0) {
59 + this.offset = range(offset, -this.data.rightWidth, this.data.leftWidth);
60 + const transform = `translate3d(${this.offset}px, 0, 0)`;
61 + const transition = this.dragging
62 + ? 'none'
63 + : 'transform .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
64 + this.setData({
65 + wrapperStyle: `
66 + -webkit-transform: ${transform};
67 + -webkit-transition: ${transition};
68 + transform: ${transform};
69 + transition: ${transition};
70 + `,
71 + });
72 + },
73 + swipeLeaveTransition() {
74 + const { leftWidth, rightWidth } = this.data;
75 + const { offset } = this;
76 + if (rightWidth > 0 && -offset > rightWidth * THRESHOLD) {
77 + this.open('right');
78 + }
79 + else if (leftWidth > 0 && offset > leftWidth * THRESHOLD) {
80 + this.open('left');
81 + }
82 + else {
83 + this.swipeMove(0);
84 + }
85 + this.setData({ catchMove: false });
86 + },
87 + startDrag(event) {
88 + if (this.data.disabled) {
89 + return;
90 + }
91 + this.startOffset = this.offset;
92 + this.touchStart(event);
93 + },
94 + noop() { },
95 + onDrag(event) {
96 + if (this.data.disabled) {
97 + return;
98 + }
99 + this.touchMove(event);
100 + if (this.direction !== 'horizontal') {
101 + return;
102 + }
103 + this.dragging = true;
104 + ARRAY.filter((item) => item !== this && item.offset !== 0).forEach((item) => item.close());
105 + this.setData({ catchMove: true });
106 + this.swipeMove(this.startOffset + this.deltaX);
107 + },
108 + endDrag() {
109 + if (this.data.disabled) {
110 + return;
111 + }
112 + this.dragging = false;
113 + this.swipeLeaveTransition();
114 + },
115 + onClick(event) {
116 + const { key: position = 'outside' } = event.currentTarget.dataset;
117 + this.$emit('click', position);
118 + if (!this.offset) {
119 + return;
120 + }
121 + if (this.data.asyncClose) {
122 + this.$emit('close', {
123 + position,
124 + instance: this,
125 + name: this.data.name,
126 + });
127 + }
128 + else {
129 + this.swipeMove(0);
130 + }
131 + },
132 + },
133 +});
1 +<view
2 + class="van-swipe-cell custom-class"
3 + data-key="cell"
4 + catchtap="onClick"
5 + bindtouchstart="startDrag"
6 + catchtouchmove="{{ catchMove ? 'noop' : '' }}"
7 + capture-bind:touchmove="onDrag"
8 + bindtouchend="endDrag"
9 + bindtouchcancel="endDrag"
10 +>
11 + <view style="{{ wrapperStyle }}">
12 + <view wx:if="{{ leftWidth }}" class="van-swipe-cell__left" data-key="left" catch:tap="onClick">
13 + <slot name="left" />
14 + </view>
15 + <slot />
16 + <view wx:if="{{ rightWidth }}" class="van-swipe-cell__right" data-key="right" catch:tap="onClick">
17 + <slot name="right" />
18 + </view>
19 + </view>
20 +</view>
1 +@import '../common/index.wxss';.van-swipe-cell{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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + field: true,
4 + classes: ['node-class'],
5 + props: {
6 + checked: null,
7 + loading: Boolean,
8 + disabled: Boolean,
9 + activeColor: String,
10 + inactiveColor: String,
11 + size: {
12 + type: String,
13 + value: '30',
14 + },
15 + activeValue: {
16 + type: null,
17 + value: true,
18 + },
19 + inactiveValue: {
20 + type: null,
21 + value: false,
22 + },
23 + },
24 + methods: {
25 + onClick() {
26 + const { activeValue, inactiveValue, disabled, loading } = this.data;
27 + if (disabled || loading) {
28 + return;
29 + }
30 + const checked = this.data.checked === activeValue;
31 + const value = checked ? inactiveValue : activeValue;
32 + this.$emit('input', value);
33 + this.$emit('change', value);
34 + },
35 + },
36 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-loading": "../loading/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view
5 + class="{{ utils.bem('switch', { on: checked === activeValue, disabled }) }} custom-class"
6 + style="{{ computed.rootStyle({ size, checked, activeColor, inactiveColor, activeValue }) }}"
7 + bind:tap="onClick"
8 +>
9 + <view class="van-switch__node node-class">
10 + <van-loading
11 + wx:if="{{ loading }}"
12 + color="{{ computed.loadingColor({ checked, activeColor, inactiveColor, activeValue }) }}"
13 + custom-class="van-switch__loading"
14 + />
15 + </view>
16 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function rootStyle(data) {
6 + var currentColor = data.checked === data.activeValue ? data.activeColor : data.inactiveColor;
7 +
8 + return style({
9 + 'font-size': addUnit(data.size),
10 + 'background-color': currentColor,
11 + });
12 +}
13 +
14 +var BLUE = '#1989fa';
15 +var GRAY_DARK = '#969799';
16 +
17 +function loadingColor(data) {
18 + return data.checked === data.activeValue
19 + ? data.activeColor || BLUE
20 + : data.inactiveColor || GRAY_DARK;
21 +}
22 +
23 +module.exports = {
24 + rootStyle: rootStyle,
25 + loadingColor: loadingColor,
26 +};
1 +@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 ...\ No newline at end of file
1 +import { useParent } from '../common/relation';
2 +import { VantComponent } from '../common/component';
3 +VantComponent({
4 + relation: useParent('tabs'),
5 + props: {
6 + dot: {
7 + type: Boolean,
8 + observer: 'update',
9 + },
10 + info: {
11 + type: null,
12 + observer: 'update',
13 + },
14 + title: {
15 + type: String,
16 + observer: 'update',
17 + },
18 + disabled: {
19 + type: Boolean,
20 + observer: 'update',
21 + },
22 + titleStyle: {
23 + type: String,
24 + observer: 'update',
25 + },
26 + name: {
27 + type: null,
28 + value: '',
29 + },
30 + },
31 + data: {
32 + active: false,
33 + },
34 + methods: {
35 + getComputedName() {
36 + if (this.data.name !== '') {
37 + return this.data.name;
38 + }
39 + return this.index;
40 + },
41 + updateRender(active, parent) {
42 + const { data: parentData } = parent;
43 + this.inited = this.inited || active;
44 + this.setData({
45 + active,
46 + shouldRender: this.inited || !parentData.lazyRender,
47 + shouldShow: active || parentData.animated,
48 + });
49 + },
50 + update() {
51 + if (this.parent) {
52 + this.parent.updateTabs();
53 + }
54 + },
55 + },
56 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view
4 + class="custom-class {{ utils.bem('tab__pane', { active, inactive: !active }) }}"
5 + style="{{ shouldShow ? '' : 'display: none;' }}"
6 +>
7 + <slot wx:if="{{ shouldRender }}" />
8 +</view>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { useParent } from '../common/relation';
3 +VantComponent({
4 + props: {
5 + info: null,
6 + name: null,
7 + icon: String,
8 + dot: Boolean,
9 + iconPrefix: {
10 + type: String,
11 + value: 'van-icon',
12 + },
13 + },
14 + relation: useParent('tabbar'),
15 + data: {
16 + active: false,
17 + activeColor: '',
18 + inactiveColor: '',
19 + },
20 + methods: {
21 + onClick() {
22 + const { parent } = this;
23 + if (parent) {
24 + const index = parent.children.indexOf(this);
25 + const active = this.data.name || index;
26 + if (active !== this.data.active) {
27 + parent.$emit('change', active);
28 + }
29 + }
30 + this.$emit('click');
31 + },
32 + updateFromParent() {
33 + const { parent } = this;
34 + if (!parent) {
35 + return;
36 + }
37 + const index = parent.children.indexOf(this);
38 + const parentData = parent.data;
39 + const { data } = this;
40 + const active = (data.name || index) === parentData.active;
41 + const patch = {};
42 + if (active !== data.active) {
43 + patch.active = active;
44 + }
45 + if (parentData.activeColor !== data.activeColor) {
46 + patch.activeColor = parentData.activeColor;
47 + }
48 + if (parentData.inactiveColor !== data.inactiveColor) {
49 + patch.inactiveColor = parentData.inactiveColor;
50 + }
51 + if (Object.keys(patch).length > 0) {
52 + this.setData(patch);
53 + }
54 + },
55 + },
56 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index",
5 + "van-info": "../info/index"
6 + }
7 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view
4 + class="{{ utils.bem('tabbar-item', { active }) }} custom-class"
5 + style="color: {{ active ? activeColor : inactiveColor }}"
6 + bindtap="onClick"
7 +>
8 + <view class="van-tabbar-item__icon">
9 + <van-icon
10 + wx:if="{{ icon }}"
11 + name="{{ icon }}"
12 + class-prefix="{{ iconPrefix }}"
13 + custom-class="van-tabbar-item__icon__inner"
14 + />
15 + <block wx:else>
16 + <slot wx:if="{{ active }}" name="icon-active" />
17 + <slot wx:else name="icon" />
18 + </block>
19 + <van-info
20 + dot="{{ dot }}"
21 + info="{{ info }}"
22 + custom-class="van-tabbar-item__info"
23 + />
24 + </view>
25 + <view class="van-tabbar-item__text">
26 + <slot />
27 + </view>
28 +</view>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { useChildren } from '../common/relation';
3 +import { getRect } from '../common/utils';
4 +VantComponent({
5 + relation: useChildren('tabbar-item', function () {
6 + this.updateChildren();
7 + }),
8 + props: {
9 + active: {
10 + type: null,
11 + observer: 'updateChildren',
12 + },
13 + activeColor: {
14 + type: String,
15 + observer: 'updateChildren',
16 + },
17 + inactiveColor: {
18 + type: String,
19 + observer: 'updateChildren',
20 + },
21 + fixed: {
22 + type: Boolean,
23 + value: true,
24 + observer: 'setHeight',
25 + },
26 + placeholder: {
27 + type: Boolean,
28 + observer: 'setHeight',
29 + },
30 + border: {
31 + type: Boolean,
32 + value: true,
33 + },
34 + zIndex: {
35 + type: Number,
36 + value: 1,
37 + },
38 + safeAreaInsetBottom: {
39 + type: Boolean,
40 + value: true,
41 + },
42 + },
43 + data: {
44 + height: 50,
45 + },
46 + methods: {
47 + updateChildren() {
48 + const { children } = this;
49 + if (!Array.isArray(children) || !children.length) {
50 + return;
51 + }
52 + children.forEach((child) => child.updateFromParent());
53 + },
54 + setHeight() {
55 + if (!this.data.fixed || !this.data.placeholder) {
56 + return;
57 + }
58 + wx.nextTick(() => {
59 + getRect(this, '.van-tabbar').then((res) => {
60 + this.setData({ height: res.height });
61 + });
62 + });
63 + },
64 + },
65 +});
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +
3 +<view
4 + class="{{ border ? 'van-hairline--top-bottom' : '' }} {{ utils.bem('tabbar', { fixed, safe: safeAreaInsetBottom }) }} custom-class"
5 + style="{{ zIndex ? 'z-index: ' + zIndex : '' }}"
6 +>
7 + <slot />
8 +</view>
9 +
10 +<view wx:if="{{ fixed && placeholder }}" style="height: {{ height }}px;"></view>
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { touch } from '../mixins/touch';
3 +import { getAllRect, getRect, groupSetData, nextTick, requestAnimationFrame, } from '../common/utils';
4 +import { isDef } from '../common/validator';
5 +import { useChildren } from '../common/relation';
6 +VantComponent({
7 + mixins: [touch],
8 + classes: ['nav-class', 'tab-class', 'tab-active-class', 'line-class'],
9 + relation: useChildren('tab', function () {
10 + this.updateTabs();
11 + }),
12 + props: {
13 + sticky: Boolean,
14 + border: Boolean,
15 + swipeable: Boolean,
16 + titleActiveColor: String,
17 + titleInactiveColor: String,
18 + color: String,
19 + animated: {
20 + type: Boolean,
21 + observer() {
22 + this.children.forEach((child, index) => child.updateRender(index === this.data.currentIndex, this));
23 + },
24 + },
25 + lineWidth: {
26 + type: null,
27 + value: 40,
28 + observer: 'resize',
29 + },
30 + lineHeight: {
31 + type: null,
32 + value: -1,
33 + },
34 + active: {
35 + type: null,
36 + value: 0,
37 + observer(name) {
38 + if (name !== this.getCurrentName()) {
39 + this.setCurrentIndexByName(name);
40 + }
41 + },
42 + },
43 + type: {
44 + type: String,
45 + value: 'line',
46 + },
47 + ellipsis: {
48 + type: Boolean,
49 + value: true,
50 + },
51 + duration: {
52 + type: Number,
53 + value: 0.3,
54 + },
55 + zIndex: {
56 + type: Number,
57 + value: 1,
58 + },
59 + swipeThreshold: {
60 + type: Number,
61 + value: 5,
62 + observer(value) {
63 + this.setData({
64 + scrollable: this.children.length > value || !this.data.ellipsis,
65 + });
66 + },
67 + },
68 + offsetTop: {
69 + type: Number,
70 + value: 0,
71 + },
72 + lazyRender: {
73 + type: Boolean,
74 + value: true,
75 + },
76 + },
77 + data: {
78 + tabs: [],
79 + scrollLeft: 0,
80 + scrollable: false,
81 + currentIndex: 0,
82 + container: null,
83 + skipTransition: true,
84 + scrollWithAnimation: false,
85 + lineOffsetLeft: 0,
86 + },
87 + mounted() {
88 + requestAnimationFrame(() => {
89 + this.swiping = true;
90 + this.setData({
91 + container: () => this.createSelectorQuery().select('.van-tabs'),
92 + });
93 + this.resize();
94 + this.scrollIntoView();
95 + });
96 + },
97 + methods: {
98 + updateTabs() {
99 + const { children = [], data } = this;
100 + this.setData({
101 + tabs: children.map((child) => child.data),
102 + scrollable: this.children.length > data.swipeThreshold || !data.ellipsis,
103 + });
104 + this.setCurrentIndexByName(data.active || this.getCurrentName());
105 + },
106 + trigger(eventName, child) {
107 + const { currentIndex } = this.data;
108 + const currentChild = child || this.children[currentIndex];
109 + if (!isDef(currentChild)) {
110 + return;
111 + }
112 + this.$emit(eventName, {
113 + index: currentChild.index,
114 + name: currentChild.getComputedName(),
115 + title: currentChild.data.title,
116 + });
117 + },
118 + onTap(event) {
119 + const { index } = event.currentTarget.dataset;
120 + const child = this.children[index];
121 + if (child.data.disabled) {
122 + this.trigger('disabled', child);
123 + }
124 + else {
125 + this.setCurrentIndex(index);
126 + nextTick(() => {
127 + this.trigger('click');
128 + });
129 + }
130 + },
131 + // correct the index of active tab
132 + setCurrentIndexByName(name) {
133 + const { children = [] } = this;
134 + const matched = children.filter((child) => child.getComputedName() === name);
135 + if (matched.length) {
136 + this.setCurrentIndex(matched[0].index);
137 + }
138 + },
139 + setCurrentIndex(currentIndex) {
140 + const { data, children = [] } = this;
141 + if (!isDef(currentIndex) ||
142 + currentIndex >= children.length ||
143 + currentIndex < 0) {
144 + return;
145 + }
146 + groupSetData(this, () => {
147 + children.forEach((item, index) => {
148 + const active = index === currentIndex;
149 + if (active !== item.data.active || !item.inited) {
150 + item.updateRender(active, this);
151 + }
152 + });
153 + });
154 + if (currentIndex === data.currentIndex) {
155 + return;
156 + }
157 + const shouldEmitChange = data.currentIndex !== null;
158 + this.setData({ currentIndex });
159 + requestAnimationFrame(() => {
160 + this.resize();
161 + this.scrollIntoView();
162 + });
163 + nextTick(() => {
164 + this.trigger('input');
165 + if (shouldEmitChange) {
166 + this.trigger('change');
167 + }
168 + });
169 + },
170 + getCurrentName() {
171 + const activeTab = this.children[this.data.currentIndex];
172 + if (activeTab) {
173 + return activeTab.getComputedName();
174 + }
175 + },
176 + resize() {
177 + if (this.data.type !== 'line') {
178 + return;
179 + }
180 + const { currentIndex, ellipsis, skipTransition } = this.data;
181 + Promise.all([
182 + getAllRect(this, '.van-tab'),
183 + getRect(this, '.van-tabs__line'),
184 + ]).then(([rects = [], lineRect]) => {
185 + const rect = rects[currentIndex];
186 + if (rect == null) {
187 + return;
188 + }
189 + let lineOffsetLeft = rects
190 + .slice(0, currentIndex)
191 + .reduce((prev, curr) => prev + curr.width, 0);
192 + lineOffsetLeft +=
193 + (rect.width - lineRect.width) / 2 + (ellipsis ? 0 : 8);
194 + this.setData({ lineOffsetLeft });
195 + this.swiping = true;
196 + if (skipTransition) {
197 + nextTick(() => {
198 + this.setData({ skipTransition: false });
199 + });
200 + }
201 + });
202 + },
203 + // scroll active tab into view
204 + scrollIntoView() {
205 + const { currentIndex, scrollable, scrollWithAnimation } = this.data;
206 + if (!scrollable) {
207 + return;
208 + }
209 + Promise.all([
210 + getAllRect(this, '.van-tab'),
211 + getRect(this, '.van-tabs__nav'),
212 + ]).then(([tabRects, navRect]) => {
213 + const tabRect = tabRects[currentIndex];
214 + const offsetLeft = tabRects
215 + .slice(0, currentIndex)
216 + .reduce((prev, curr) => prev + curr.width, 0);
217 + this.setData({
218 + scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2,
219 + });
220 + if (!scrollWithAnimation) {
221 + nextTick(() => {
222 + this.setData({ scrollWithAnimation: true });
223 + });
224 + }
225 + });
226 + },
227 + onTouchScroll(event) {
228 + this.$emit('scroll', event.detail);
229 + },
230 + onTouchStart(event) {
231 + if (!this.data.swipeable)
232 + return;
233 + this.swiping = true;
234 + this.touchStart(event);
235 + },
236 + onTouchMove(event) {
237 + if (!this.data.swipeable || !this.swiping)
238 + return;
239 + this.touchMove(event);
240 + },
241 + // watch swipe touch end
242 + onTouchEnd() {
243 + if (!this.data.swipeable || !this.swiping)
244 + return;
245 + const { direction, deltaX, offsetX } = this;
246 + const minSwipeDistance = 50;
247 + if (direction === 'horizontal' && offsetX >= minSwipeDistance) {
248 + const index = this.getAvaiableTab(deltaX);
249 + if (index !== -1) {
250 + this.setCurrentIndex(index);
251 + }
252 + }
253 + this.swiping = false;
254 + },
255 + getAvaiableTab(direction) {
256 + const { tabs, currentIndex } = this.data;
257 + const step = direction > 0 ? -1 : 1;
258 + for (let i = step; currentIndex + i < tabs.length && currentIndex + i >= 0; i += step) {
259 + const index = currentIndex + i;
260 + if (index >= 0 &&
261 + index < tabs.length &&
262 + tabs[index] &&
263 + !tabs[index].disabled) {
264 + return index;
265 + }
266 + }
267 + return -1;
268 + },
269 + },
270 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-info": "../info/index",
5 + "van-sticky": "../sticky/index"
6 + }
7 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view class="custom-class {{ utils.bem('tabs', [type]) }}">
5 + <van-sticky
6 + disabled="{{ !sticky }}"
7 + z-index="{{ zIndex }}"
8 + offset-top="{{ offsetTop }}"
9 + container="{{ container }}"
10 + bind:scroll="onTouchScroll"
11 + >
12 + <view class="{{ utils.bem('tabs__wrap', { scrollable }) }} {{ type === 'line' && border ? 'van-hairline--top-bottom' : '' }}">
13 + <slot name="nav-left" />
14 +
15 + <scroll-view
16 + scroll-x="{{ scrollable }}"
17 + scroll-with-animation="{{ scrollWithAnimation }}"
18 + scroll-left="{{ scrollLeft }}"
19 + class="{{ utils.bem('tabs__scroll', [type]) }}"
20 + style="{{ color ? 'border-color: ' + color : '' }}"
21 + >
22 + <view class="{{ utils.bem('tabs__nav', [type, { complete: !ellipsis }]) }} nav-class" style="{{ computed.navStyle(color, type) }}">
23 + <view wx:if="{{ type === 'line' }}" class="van-tabs__line" style="{{ computed.lineStyle({ color, lineOffsetLeft, lineHeight, skipTransition, duration, lineWidth }) }}" />
24 + <view
25 + wx:for="{{ tabs }}"
26 + wx:key="index"
27 + data-index="{{ index }}"
28 + class="{{ computed.tabClass(index === currentIndex, ellipsis) }} {{ utils.bem('tab', { active: index === currentIndex, disabled: item.disabled, complete: !ellipsis }) }}"
29 + style="{{ computed.tabStyle({ active: index === currentIndex, ellipsis, color, type, disabled: item.disabled, titleActiveColor, titleInactiveColor, swipeThreshold, scrollable }) }}"
30 + bind:tap="onTap"
31 + >
32 + <view class="{{ ellipsis ? 'van-ellipsis' : '' }}" style="{{ item.titleStyle }}">
33 + {{ item.title }}
34 + <van-info
35 + wx:if="{{ item.info !== null || item.dot }}"
36 + info="{{ item.info }}"
37 + dot="{{ item.dot }}"
38 + custom-class="van-tab__title__info"
39 + />
40 + </view>
41 + </view>
42 + </view>
43 + </scroll-view>
44 +
45 + <slot name="nav-right" />
46 + </view>
47 + </van-sticky>
48 +
49 + <view
50 + class="van-tabs__content"
51 + bind:touchstart="onTouchStart"
52 + bind:touchmove="onTouchMove"
53 + bind:touchend="onTouchEnd"
54 + bind:touchcancel="onTouchEnd"
55 + >
56 + <view
57 + class="{{ utils.bem('tabs__track', [{ animated }]) }} van-tabs__track"
58 + style="{{ computed.trackStyle({ duration, currentIndex, animated }) }}"
59 + >
60 + <slot />
61 + </view>
62 + </view>
63 +</view>
1 +/* eslint-disable */
2 +var utils = require('../wxs/utils.wxs');
3 +var style = require('../wxs/style.wxs');
4 +
5 +function tabClass(active, ellipsis) {
6 + var classes = ['tab-class'];
7 +
8 + if (active) {
9 + classes.push('tab-active-class');
10 + }
11 +
12 + if (ellipsis) {
13 + classes.push('van-ellipsis');
14 + }
15 +
16 + return classes.join(' ');
17 +}
18 +
19 +function tabStyle(data) {
20 + var titleColor = data.active
21 + ? data.titleActiveColor
22 + : data.titleInactiveColor;
23 +
24 + var ellipsis = data.scrollable && data.ellipsis;
25 +
26 + // card theme color
27 + if (data.type === 'card') {
28 + return style({
29 + 'border-color': data.color,
30 + 'background-color': !data.disabled && data.active ? data.color : null,
31 + color: titleColor || (!data.disabled && !data.active ? data.color : null),
32 + 'flex-basis': ellipsis ? 88 / data.swipeThreshold + '%' : null,
33 + });
34 + }
35 +
36 + return style({
37 + color: titleColor,
38 + 'flex-basis': ellipsis ? 88 / data.swipeThreshold + '%' : null,
39 + });
40 +}
41 +
42 +function navStyle(color, type) {
43 + return style({
44 + 'border-color': type === 'card' && color ? color : null,
45 + });
46 +}
47 +
48 +function trackStyle(data) {
49 + if (!data.animated) {
50 + return '';
51 + }
52 +
53 + return style({
54 + left: -100 * data.currentIndex + '%',
55 + 'transition-duration': data.duration + 's',
56 + '-webkit-transition-duration': data.duration + 's',
57 + });
58 +}
59 +
60 +function lineStyle(data) {
61 + return style({
62 + width: utils.addUnit(data.lineWidth),
63 + transform: 'translateX(' + data.lineOffsetLeft + 'px)',
64 + '-webkit-transform': 'translateX(' + data.lineOffsetLeft + 'px)',
65 + 'background-color': data.color,
66 + height: data.lineHeight !== -1 ? utils.addUnit(data.lineHeight) : null,
67 + 'border-radius':
68 + data.lineHeight !== -1 ? utils.addUnit(data.lineHeight) : null,
69 + 'transition-duration': !data.skipTransition ? data.duration + 's' : null,
70 + '-webkit-transition-duration': !data.skipTransition
71 + ? data.duration + 's'
72 + : null,
73 + });
74 +}
75 +
76 +module.exports = {
77 + tabClass: tabClass,
78 + tabStyle: tabStyle,
79 + trackStyle: trackStyle,
80 + lineStyle: lineStyle,
81 + navStyle: navStyle,
82 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + props: {
4 + size: String,
5 + mark: Boolean,
6 + color: String,
7 + plain: Boolean,
8 + round: Boolean,
9 + textColor: String,
10 + type: {
11 + type: String,
12 + value: 'default',
13 + },
14 + closeable: Boolean,
15 + },
16 + methods: {
17 + onClose() {
18 + this.$emit('close');
19 + },
20 + },
21 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index"
5 + }
6 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view
5 + class="custom-class {{ utils.bem('tag', [type, size, { mark, plain, round }]) }}"
6 + style="{{ computed.rootStyle({ plain, color, textColor }) }}"
7 +>
8 + <slot />
9 + <van-icon
10 + wx:if="{{ closeable }}"
11 + name="cross"
12 + custom-class="van-tag__close"
13 + bind:click="onClose"
14 + />
15 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +
4 +function rootStyle(data) {
5 + return style({
6 + 'background-color': data.plain ? '' : data.color,
7 + color: data.textColor || data.plain ? data.textColor || data.color : '',
8 + });
9 +}
10 +
11 +module.exports = {
12 + rootStyle: rootStyle,
13 +};
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + props: {
4 + show: Boolean,
5 + mask: Boolean,
6 + message: String,
7 + forbidClick: Boolean,
8 + zIndex: {
9 + type: Number,
10 + value: 1000,
11 + },
12 + type: {
13 + type: String,
14 + value: 'text',
15 + },
16 + loadingType: {
17 + type: String,
18 + value: 'circular',
19 + },
20 + position: {
21 + type: String,
22 + value: 'middle',
23 + },
24 + },
25 + methods: {
26 + // for prevent touchmove
27 + noop() { },
28 + },
29 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index",
5 + "van-loading": "../loading/index",
6 + "van-overlay": "../overlay/index",
7 + "van-transition": "../transition/index"
8 + }
9 +}
1 +<van-overlay
2 + wx:if="{{ mask || forbidClick }}"
3 + show="{{ show }}"
4 + z-index="{{ zIndex }}"
5 + custom-style="{{ mask ? '' : 'background-color: transparent;' }}"
6 +/>
7 +<van-transition
8 + show="{{ show }}"
9 + custom-style="z-index: {{ zIndex }}"
10 + custom-class="van-toast__container"
11 +>
12 + <view
13 + class="van-toast van-toast--{{ (type === 'text' || type === 'html') ? 'text' : 'icon' }} van-toast--{{ position }}"
14 + catch:touchmove="noop"
15 + >
16 + <!-- text only -->
17 + <text wx:if="{{ type === 'text' }}">{{ message }}</text>
18 +
19 + <!-- html only -->
20 + <rich-text wx:elif="{{ type === 'html' }}" nodes="{{ message }}"></rich-text>
21 +
22 + <!-- with icon -->
23 + <block wx:else>
24 + <van-loading
25 + wx:if="{{ type === 'loading' }}"
26 + color="white"
27 + type="{{ loadingType }}"
28 + custom-class="van-toast__loading"
29 + />
30 + <van-icon wx:else class="van-toast__icon" name="{{ type }}" />
31 + <text wx:if="{{ message }}" class="van-toast__text">{{ message }}</text>
32 + </block>
33 +
34 + <slot />
35 + </view>
36 +</van-transition>
1 +@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 ...\ No newline at end of file
1 +/// <reference types="miniprogram-api-typings" />
2 +declare type ToastMessage = string | number;
3 +interface ToastOptions {
4 + show?: boolean;
5 + type?: string;
6 + mask?: boolean;
7 + zIndex?: number;
8 + context?: WechatMiniprogram.Component.TrivialInstance | WechatMiniprogram.Page.TrivialInstance;
9 + position?: string;
10 + duration?: number;
11 + selector?: string;
12 + forbidClick?: boolean;
13 + loadingType?: string;
14 + message?: ToastMessage;
15 + onClose?: () => void;
16 +}
17 +declare function Toast(toastOptions: ToastOptions | ToastMessage): WechatMiniprogram.Component.TrivialInstance | undefined;
18 +declare namespace Toast {
19 + var loading: (options: ToastMessage | ToastOptions) => WechatMiniprogram.Component.TrivialInstance | undefined;
20 + var success: (options: ToastMessage | ToastOptions) => WechatMiniprogram.Component.TrivialInstance | undefined;
21 + var fail: (options: ToastMessage | ToastOptions) => WechatMiniprogram.Component.TrivialInstance | undefined;
22 + var clear: () => void;
23 + var setDefaultOptions: (options: ToastOptions) => void;
24 + var resetDefaultOptions: () => void;
25 +}
26 +export default Toast;
1 +import { isObj } from '../common/validator';
2 +const defaultOptions = {
3 + type: 'text',
4 + mask: false,
5 + message: '',
6 + show: true,
7 + zIndex: 1000,
8 + duration: 2000,
9 + position: 'middle',
10 + forbidClick: false,
11 + loadingType: 'circular',
12 + selector: '#van-toast',
13 +};
14 +let queue = [];
15 +let currentOptions = Object.assign({}, defaultOptions);
16 +function parseOptions(message) {
17 + return isObj(message) ? message : { message };
18 +}
19 +function getContext() {
20 + const pages = getCurrentPages();
21 + return pages[pages.length - 1];
22 +}
23 +function Toast(toastOptions) {
24 + const options = Object.assign(Object.assign({}, currentOptions), parseOptions(toastOptions));
25 + const context = options.context || getContext();
26 + const toast = context.selectComponent(options.selector);
27 + if (!toast) {
28 + console.warn('未找到 van-toast 节点,请确认 selector 及 context 是否正确');
29 + return;
30 + }
31 + delete options.context;
32 + delete options.selector;
33 + toast.clear = () => {
34 + toast.setData({ show: false });
35 + if (options.onClose) {
36 + options.onClose();
37 + }
38 + };
39 + queue.push(toast);
40 + toast.setData(options);
41 + clearTimeout(toast.timer);
42 + if (options.duration != null && options.duration > 0) {
43 + toast.timer = setTimeout(() => {
44 + toast.clear();
45 + queue = queue.filter((item) => item !== toast);
46 + }, options.duration);
47 + }
48 + return toast;
49 +}
50 +const createMethod = (type) => (options) => Toast(Object.assign({ type }, parseOptions(options)));
51 +Toast.loading = createMethod('loading');
52 +Toast.success = createMethod('success');
53 +Toast.fail = createMethod('fail');
54 +Toast.clear = () => {
55 + queue.forEach((toast) => {
56 + toast.clear();
57 + });
58 + queue = [];
59 +};
60 +Toast.setDefaultOptions = (options) => {
61 + Object.assign(currentOptions, options);
62 +};
63 +Toast.resetDefaultOptions = () => {
64 + currentOptions = Object.assign({}, defaultOptions);
65 +};
66 +export default Toast;
1 +import { VantComponent } from '../common/component';
2 +import { transition } from '../mixins/transition';
3 +VantComponent({
4 + classes: [
5 + 'enter-class',
6 + 'enter-active-class',
7 + 'enter-to-class',
8 + 'leave-class',
9 + 'leave-active-class',
10 + 'leave-to-class',
11 + ],
12 + mixins: [transition(true)],
13 +});
1 +<wxs src="./index.wxs" module="computed" />
2 +
3 +<view
4 + wx:if="{{ inited }}"
5 + class="van-transition custom-class {{ classes }}"
6 + style="{{ computed.rootStyle({ currentDuration, display, customStyle }) }}"
7 + bind:transitionend="onTransitionEnd"
8 +>
9 + <slot />
10 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +
4 +function rootStyle(data) {
5 + return style([
6 + {
7 + '-webkit-transition-duration': data.currentDuration + 'ms',
8 + 'transition-duration': data.currentDuration + 'ms',
9 + },
10 + data.display ? null : 'display: none',
11 + data.customStyle,
12 + ]);
13 +}
14 +
15 +module.exports = {
16 + rootStyle: rootStyle,
17 +};
1 +@import '../common/index.wxss';.van-transition{transition-timing-function:ease}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-fade-down-enter-active,.van-fade-down-leave-active,.van-fade-left-enter-active,.van-fade-left-leave-active,.van-fade-right-enter-active,.van-fade-right-leave-active,.van-fade-up-enter-active,.van-fade-up-leave-active{transition-property:opacity,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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +VantComponent({
3 + classes: [
4 + 'main-item-class',
5 + 'content-item-class',
6 + 'main-active-class',
7 + 'content-active-class',
8 + 'main-disabled-class',
9 + 'content-disabled-class',
10 + ],
11 + props: {
12 + items: {
13 + type: Array,
14 + observer: 'updateSubItems',
15 + },
16 + activeId: null,
17 + mainActiveIndex: {
18 + type: Number,
19 + value: 0,
20 + observer: 'updateSubItems',
21 + },
22 + height: {
23 + type: null,
24 + value: 300,
25 + },
26 + max: {
27 + type: Number,
28 + value: Infinity,
29 + },
30 + selectedIcon: {
31 + type: String,
32 + value: 'success',
33 + },
34 + },
35 + data: {
36 + subItems: [],
37 + },
38 + methods: {
39 + // 当一个子项被选择时
40 + onSelectItem(event) {
41 + const { item } = event.currentTarget.dataset;
42 + const isArray = Array.isArray(this.data.activeId);
43 + // 判断有没有超出右侧选择的最大数
44 + const isOverMax = isArray && this.data.activeId.length >= this.data.max;
45 + // 判断该项有没有被选中, 如果有被选中,则忽视是否超出的条件
46 + const isSelected = isArray
47 + ? this.data.activeId.indexOf(item.id) > -1
48 + : this.data.activeId === item.id;
49 + if (!item.disabled && (!isOverMax || isSelected)) {
50 + this.$emit('click-item', item);
51 + }
52 + },
53 + // 当一个导航被点击时
54 + onClickNav(event) {
55 + const index = event.detail;
56 + const item = this.data.items[index];
57 + if (!item.disabled) {
58 + this.$emit('click-nav', { index });
59 + }
60 + },
61 + // 更新子项列表
62 + updateSubItems() {
63 + const { items, mainActiveIndex } = this.data;
64 + const { children = [] } = items[mainActiveIndex] || {};
65 + this.setData({ subItems: children });
66 + },
67 + },
68 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index",
5 + "van-sidebar": "../sidebar/index",
6 + "van-sidebar-item": "../sidebar-item/index"
7 + }
8 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="wxs" />
3 +
4 +<view
5 + class="van-tree-select"
6 + style="height: {{ utils.addUnit(height) }}"
7 +>
8 + <scroll-view scroll-y class="van-tree-select__nav">
9 + <van-sidebar active-key="{{ mainActiveIndex }}" bind:change="onClickNav" custom-class="van-tree-select__nav__inner">
10 + <van-sidebar-item
11 + wx:for="{{ items }}"
12 + wx:key="index"
13 + custom-class="main-item-class"
14 + active-class="main-active-class"
15 + disabled-class="main-disabled-class"
16 + badge="{{ item.badge }}"
17 + dot="{{ item.dot }}"
18 + title="{{ item.text }}"
19 + disabled="{{ item.disabled }}"
20 + />
21 + </van-sidebar>
22 + </scroll-view>
23 + <scroll-view scroll-y class="van-tree-select__content">
24 + <slot name="content" />
25 + <view
26 + wx:for="{{ subItems }}"
27 + wx:key="id"
28 + 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' : '' }}"
29 + data-item="{{ item }}"
30 + bind:tap="onSelectItem"
31 + >
32 + {{ item.text }}
33 + <van-icon
34 + wx:if="{{ wxs.isActive(activeId, item.id) }}"
35 + name="{{ selectedIcon }}"
36 + size="16px"
37 + class="van-tree-select__selected"
38 + />
39 + </view>
40 + </scroll-view>
41 +</view>
1 +/* eslint-disable */
2 +var array = require('../wxs/array.wxs');
3 +
4 +function isActive (activeList, itemId) {
5 + if (array.isArray(activeList)) {
6 + return activeList.indexOf(itemId) > -1;
7 + }
8 +
9 + return activeList === itemId;
10 +}
11 +
12 +module.exports.isActive = isActive;
1 +@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 ...\ No newline at end of file
1 +import { VantComponent } from '../common/component';
2 +import { isImageFile, chooseFile, isVideoFile } from './utils';
3 +import { chooseImageProps, chooseVideoProps } from './shared';
4 +import { isBoolean, isPromise } from '../common/validator';
5 +VantComponent({
6 + props: Object.assign(Object.assign({ disabled: Boolean, multiple: Boolean, uploadText: String, useBeforeRead: Boolean, afterRead: null, beforeRead: null, previewSize: {
7 + type: null,
8 + value: 80,
9 + }, name: {
10 + type: null,
11 + value: '',
12 + }, accept: {
13 + type: String,
14 + value: 'image',
15 + }, fileList: {
16 + type: Array,
17 + value: [],
18 + observer: 'formatFileList',
19 + }, maxSize: {
20 + type: Number,
21 + value: Number.MAX_VALUE,
22 + }, maxCount: {
23 + type: Number,
24 + value: 100,
25 + }, deletable: {
26 + type: Boolean,
27 + value: true,
28 + }, showUpload: {
29 + type: Boolean,
30 + value: true,
31 + }, previewImage: {
32 + type: Boolean,
33 + value: true,
34 + }, previewFullImage: {
35 + type: Boolean,
36 + value: true,
37 + }, imageFit: {
38 + type: String,
39 + value: 'scaleToFill',
40 + }, uploadIcon: {
41 + type: String,
42 + value: 'photograph',
43 + } }, chooseImageProps), chooseVideoProps),
44 + data: {
45 + lists: [],
46 + isInCount: true,
47 + },
48 + methods: {
49 + formatFileList() {
50 + const { fileList = [], maxCount } = this.data;
51 + const lists = fileList.map((item) => (Object.assign(Object.assign({}, item), { isImage: isImageFile(item), isVideo: isVideoFile(item), deletable: isBoolean(item.deletable) ? item.deletable : true })));
52 + this.setData({ lists, isInCount: lists.length < maxCount });
53 + },
54 + getDetail(index) {
55 + return {
56 + name: this.data.name,
57 + index: index == null ? this.data.fileList.length : index,
58 + };
59 + },
60 + startUpload() {
61 + const { maxCount, multiple, lists, disabled } = this.data;
62 + if (disabled)
63 + return;
64 + chooseFile(Object.assign(Object.assign({}, this.data), { maxCount: maxCount - lists.length }))
65 + .then((res) => {
66 + this.onBeforeRead(multiple ? res : res[0]);
67 + })
68 + .catch((error) => {
69 + this.$emit('error', error);
70 + });
71 + },
72 + onBeforeRead(file) {
73 + const { beforeRead, useBeforeRead } = this.data;
74 + let res = true;
75 + if (typeof beforeRead === 'function') {
76 + res = beforeRead(file, this.getDetail());
77 + }
78 + if (useBeforeRead) {
79 + res = new Promise((resolve, reject) => {
80 + this.$emit('before-read', Object.assign(Object.assign({ file }, this.getDetail()), { callback: (ok) => {
81 + ok ? resolve() : reject();
82 + } }));
83 + });
84 + }
85 + if (!res) {
86 + return;
87 + }
88 + if (isPromise(res)) {
89 + res.then((data) => this.onAfterRead(data || file));
90 + }
91 + else {
92 + this.onAfterRead(file);
93 + }
94 + },
95 + onAfterRead(file) {
96 + const { maxSize, afterRead } = this.data;
97 + const oversize = Array.isArray(file)
98 + ? file.some((item) => item.size > maxSize)
99 + : file.size > maxSize;
100 + if (oversize) {
101 + this.$emit('oversize', Object.assign({ file }, this.getDetail()));
102 + return;
103 + }
104 + if (typeof afterRead === 'function') {
105 + afterRead(file, this.getDetail());
106 + }
107 + this.$emit('after-read', Object.assign({ file }, this.getDetail()));
108 + },
109 + deleteItem(event) {
110 + const { index } = event.currentTarget.dataset;
111 + this.$emit('delete', Object.assign(Object.assign({}, this.getDetail(index)), { file: this.data.fileList[index] }));
112 + },
113 + onPreviewImage(event) {
114 + if (!this.data.previewFullImage)
115 + return;
116 + const { index } = event.currentTarget.dataset;
117 + const { lists } = this.data;
118 + const item = lists[index];
119 + wx.previewImage({
120 + urls: lists.filter((item) => isImageFile(item)).map((item) => item.url),
121 + current: item.url,
122 + fail() {
123 + wx.showToast({ title: '预览图片失败', icon: 'none' });
124 + },
125 + });
126 + },
127 + onPreviewVideo(event) {
128 + if (!this.data.previewFullImage)
129 + return;
130 + const { index } = event.currentTarget.dataset;
131 + const { lists } = this.data;
132 + wx.previewMedia({
133 + sources: lists
134 + .filter((item) => isVideoFile(item))
135 + .map((item) => (Object.assign(Object.assign({}, item), { type: 'video' }))),
136 + current: index,
137 + fail() {
138 + wx.showToast({ title: '预览视频失败', icon: 'none' });
139 + },
140 + });
141 + },
142 + onPreviewFile(event) {
143 + const { index } = event.currentTarget.dataset;
144 + wx.openDocument({
145 + filePath: this.data.lists[index].url,
146 + showMenu: true,
147 + });
148 + },
149 + onClickPreview(event) {
150 + const { index } = event.currentTarget.dataset;
151 + const item = this.data.lists[index];
152 + this.$emit('click-preview', Object.assign(Object.assign({}, item), this.getDetail(index)));
153 + },
154 + },
155 +});
1 +{
2 + "component": true,
3 + "usingComponents": {
4 + "van-icon": "../icon/index",
5 + "van-loading": "../loading/index"
6 + }
7 +}
1 +<wxs src="../wxs/utils.wxs" module="utils" />
2 +<wxs src="./index.wxs" module="computed" />
3 +
4 +<view class="van-uploader">
5 + <view class="van-uploader__wrapper">
6 + <!-- 预览样式 -->
7 + <view
8 + wx:if="{{ previewImage }}"
9 + wx:for="{{ lists }}"
10 + wx:key="index"
11 + class="van-uploader__preview"
12 + data-index="{{ index }}"
13 + bindtap="onClickPreview"
14 + >
15 + <image
16 + wx:if="{{ item.isImage }}"
17 + mode="{{ imageFit }}"
18 + src="{{ item.thumb || item.url }}"
19 + alt="{{ item.name || ('图片' + index) }}"
20 + class="van-uploader__preview-image"
21 + style="{{ computed.sizeStyle({ previewSize }) }}"
22 + data-index="{{ index }}"
23 + bindtap="onPreviewImage"
24 + />
25 + <video
26 + wx:elif="{{ item.isVideo }}"
27 + src="{{ item.url }}"
28 + title="{{ item.name || ('视频' + index) }}"
29 + poster="{{ item.thumb }}"
30 + autoplay="{{ item.autoplay }}"
31 + class="van-uploader__preview-image"
32 + style="{{ computed.sizeStyle({ previewSize }) }}"
33 + data-index="{{ index }}"
34 + bindtap="onPreviewVideo"
35 + >
36 + </video>
37 + <view
38 + wx:else
39 + class="van-uploader__file"
40 + style="{{ computed.sizeStyle({ previewSize }) }}"
41 + data-index="{{ index }}"
42 + bindtap="onPreviewFile"
43 + >
44 + <van-icon name="description" class="van-uploader__file-icon" />
45 + <view class="van-uploader__file-name van-ellipsis">{{ item.name || item.url }}</view>
46 + </view>
47 + <view
48 + wx:if="{{ item.status === 'uploading' || item.status === 'failed' }}"
49 + class="van-uploader__mask"
50 + >
51 + <van-icon wx:if="{{ item.status === 'failed' }}" name="close" class="van-uploader__mask-icon" />
52 + <van-loading wx:else custom-class="van-uploader__loading" />
53 + <text wx:if="{{ item.message }}" class="van-uploader__mask-message">{{ item.message }}</text>
54 + </view>
55 + <view
56 + wx:if="{{ deletable && item.deletable }}"
57 + data-index="{{ index }}"
58 + class="van-uploader__preview-delete"
59 + catch:tap="deleteItem"
60 + >
61 + <van-icon name="cross" class="van-uploader__preview-delete-icon" />
62 + </view>
63 + </view>
64 +
65 + <!-- 上传样式 -->
66 + <block wx:if="{{ isInCount }}">
67 + <view class="van-uploader__slot" bindtap="startUpload">
68 + <slot />
69 + </view>
70 +
71 + <!-- 默认上传样式 -->
72 + <view
73 + wx:if="{{ showUpload }}"
74 + class="van-uploader__upload {{ disabled ? 'van-uploader__upload--disabled': ''}}"
75 + style="{{ computed.sizeStyle({ previewSize }) }}"
76 + bindtap="startUpload"
77 + >
78 + <van-icon name="{{ uploadIcon }}" class="van-uploader__upload-icon" />
79 + <text wx:if="{{ uploadText }}" class="van-uploader__upload-text">{{ uploadText }}</text>
80 + </view>
81 + </block>
82 + </view>
83 +</view>
1 +/* eslint-disable */
2 +var style = require('../wxs/style.wxs');
3 +var addUnit = require('../wxs/add-unit.wxs');
4 +
5 +function sizeStyle(data) {
6 + return "Array" === data.previewSize.constructor ? style({
7 + width: addUnit(data.previewSize[0]),
8 + height: addUnit(data.previewSize[1]),
9 + }) : style({
10 + width: addUnit(data.previewSize),
11 + height: addUnit(data.previewSize),
12 + });
13 +}
14 +
15 +module.exports = {
16 + sizeStyle: sizeStyle,
17 +};
1 +@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 ...\ No newline at end of file
1 +export declare const chooseImageProps: {
2 + sizeType: {
3 + type: ArrayConstructor;
4 + value: string[];
5 + };
6 + capture: {
7 + type: ArrayConstructor;
8 + value: string[];
9 + };
10 +};
11 +export declare const chooseVideoProps: {
12 + capture: {
13 + type: ArrayConstructor;
14 + value: string[];
15 + };
16 + compressed: {
17 + type: BooleanConstructor;
18 + value: boolean;
19 + };
20 + maxDuration: {
21 + type: NumberConstructor;
22 + value: number;
23 + };
24 + camera: {
25 + type: StringConstructor;
26 + value: string;
27 + };
28 +};
1 +// props for choose image
2 +export const chooseImageProps = {
3 + sizeType: {
4 + type: Array,
5 + value: ['original', 'compressed'],
6 + },
7 + capture: {
8 + type: Array,
9 + value: ['album', 'camera'],
10 + },
11 +};
12 +// props for choose video
13 +export const chooseVideoProps = {
14 + capture: {
15 + type: Array,
16 + value: ['album', 'camera'],
17 + },
18 + compressed: {
19 + type: Boolean,
20 + value: true,
21 + },
22 + maxDuration: {
23 + type: Number,
24 + value: 60,
25 + },
26 + camera: {
27 + type: String,
28 + value: 'back',
29 + },
30 +};
1 +export interface File {
2 + url: string;
3 + size?: number;
4 + name?: string;
5 + type: string;
6 + duration?: number;
7 + time?: number;
8 + isImage?: boolean;
9 + isVideo?: boolean;
10 +}
11 +export declare function isImageFile(item: File): boolean;
12 +export declare function isVideoFile(item: File): boolean;
13 +export declare function chooseFile({ accept, multiple, capture, compressed, maxDuration, sizeType, camera, maxCount, }: {
14 + accept: any;
15 + multiple: any;
16 + capture: any;
17 + compressed: any;
18 + maxDuration: any;
19 + sizeType: any;
20 + camera: any;
21 + maxCount: any;
22 +}): Promise<File | File[]>;
1 +import { pickExclude } from '../common/utils';
2 +import { isImageUrl, isVideoUrl } from '../common/validator';
3 +export function isImageFile(item) {
4 + if (item.isImage != null) {
5 + return item.isImage;
6 + }
7 + if (item.type) {
8 + return item.type === 'image';
9 + }
10 + if (item.url) {
11 + return isImageUrl(item.url);
12 + }
13 + return false;
14 +}
15 +export function isVideoFile(item) {
16 + if (item.isVideo != null) {
17 + return item.isVideo;
18 + }
19 + if (item.type) {
20 + return item.type === 'video';
21 + }
22 + if (item.url) {
23 + return isVideoUrl(item.url);
24 + }
25 + return false;
26 +}
27 +function formatImage(res) {
28 + return res.tempFiles.map((item) => (Object.assign(Object.assign({}, pickExclude(item, ['path'])), { type: 'image', url: item.path, thumb: item.path })));
29 +}
30 +function formatVideo(res) {
31 + return [
32 + Object.assign(Object.assign({}, pickExclude(res, ['tempFilePath', 'thumbTempFilePath', 'errMsg'])), { type: 'video', url: res.tempFilePath, thumb: res.thumbTempFilePath }),
33 + ];
34 +}
35 +function formatMedia(res) {
36 + 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 })));
37 +}
38 +function formatFile(res) {
39 + return res.tempFiles.map((item) => (Object.assign(Object.assign({}, pickExclude(item, ['path'])), { url: item.path })));
40 +}
41 +export function chooseFile({ accept, multiple, capture, compressed, maxDuration, sizeType, camera, maxCount, }) {
42 + return new Promise((resolve, reject) => {
43 + switch (accept) {
44 + case 'image':
45 + wx.chooseImage({
46 + count: multiple ? Math.min(maxCount, 9) : 1,
47 + sourceType: capture,
48 + sizeType,
49 + success: (res) => resolve(formatImage(res)),
50 + fail: reject,
51 + });
52 + break;
53 + case 'media':
54 + wx.chooseMedia({
55 + count: multiple ? Math.min(maxCount, 9) : 1,
56 + sourceType: capture,
57 + maxDuration,
58 + sizeType,
59 + camera,
60 + success: (res) => resolve(formatMedia(res)),
61 + fail: reject,
62 + });
63 + break;
64 + case 'video':
65 + wx.chooseVideo({
66 + sourceType: capture,
67 + compressed,
68 + maxDuration,
69 + camera,
70 + success: (res) => resolve(formatVideo(res)),
71 + fail: reject,
72 + });
73 + break;
74 + default:
75 + wx.chooseMessageFile({
76 + count: multiple ? maxCount : 1,
77 + type: accept,
78 + success: (res) => resolve(formatFile(res)),
79 + fail: reject,
80 + });
81 + break;
82 + }
83 + });
84 +}
1 +/* eslint-disable */
2 +var REGEXP = getRegExp('^-?\d+(\.\d+)?$');
3 +
4 +function addUnit(value) {
5 + if (value == null) {
6 + return undefined;
7 + }
8 +
9 + return REGEXP.test('' + value) ? value + 'px' : value;
10 +}
11 +
12 +module.exports = addUnit;
1 +function isArray(array) {
2 + return array && array.constructor === 'Array';
3 +}
4 +
5 +module.exports.isArray = isArray;
1 +/* eslint-disable */
2 +var array = require('./array.wxs');
3 +var object = require('./object.wxs');
4 +var PREFIX = 'van-';
5 +
6 +function join(name, mods) {
7 + name = PREFIX + name;
8 + mods = mods.map(function(mod) {
9 + return name + '--' + mod;
10 + });
11 + mods.unshift(name);
12 + return mods.join(' ');
13 +}
14 +
15 +function traversing(mods, conf) {
16 + if (!conf) {
17 + return;
18 + }
19 +
20 + if (typeof conf === 'string' || typeof conf === 'number') {
21 + mods.push(conf);
22 + } else if (array.isArray(conf)) {
23 + conf.forEach(function(item) {
24 + traversing(mods, item);
25 + });
26 + } else if (typeof conf === 'object') {
27 + object.keys(conf).forEach(function(key) {
28 + conf[key] && mods.push(key);
29 + });
30 + }
31 +}
32 +
33 +function bem(name, conf) {
34 + var mods = [];
35 + traversing(mods, conf);
36 + return join(name, mods);
37 +}
38 +
39 +module.exports = bem;
1 +/**
2 + * Simple memoize
3 + * wxs doesn't support fn.apply, so this memoize only support up to 2 args
4 + */
5 +/* eslint-disable */
6 +
7 +function isPrimitive(value) {
8 + var type = typeof value;
9 + return (
10 + type === 'boolean' ||
11 + type === 'number' ||
12 + type === 'string' ||
13 + type === 'undefined' ||
14 + value === null
15 + );
16 +}
17 +
18 +// mock simple fn.call in wxs
19 +function call(fn, args) {
20 + if (args.length === 2) {
21 + return fn(args[0], args[1]);
22 + }
23 +
24 + if (args.length === 1) {
25 + return fn(args[0]);
26 + }
27 +
28 + return fn();
29 +}
30 +
31 +function serializer(args) {
32 + if (args.length === 1 && isPrimitive(args[0])) {
33 + return args[0];
34 + }
35 + var obj = {};
36 + for (var i = 0; i < args.length; i++) {
37 + obj['key' + i] = args[i];
38 + }
39 + return JSON.stringify(obj);
40 +}
41 +
42 +function memoize(fn) {
43 + var cache = {};
44 +
45 + return function() {
46 + var key = serializer(arguments);
47 + if (cache[key] === undefined) {
48 + cache[key] = call(fn, arguments);
49 + }
50 +
51 + return cache[key];
52 + };
53 +}
54 +
55 +module.exports = memoize;
1 +/* eslint-disable */
2 +var REGEXP = getRegExp('{|}|"', 'g');
3 +
4 +function keys(obj) {
5 + return JSON.stringify(obj)
6 + .replace(REGEXP, '')
7 + .split(',')
8 + .map(function(item) {
9 + return item.split(':')[0];
10 + });
11 +}
12 +
13 +module.exports.keys = keys;
1 +/* eslint-disable */
2 +var object = require('./object.wxs');
3 +var array = require('./array.wxs');
4 +
5 +function kebabCase(word) {
6 + var newWord = word
7 + .replace(getRegExp("[A-Z]", 'g'), function (i) {
8 + return '-' + i;
9 + })
10 + .toLowerCase()
11 +
12 + return newWord;
13 +}
14 +
15 +function style(styles) {
16 + if (array.isArray(styles)) {
17 + return styles
18 + .filter(function (item) {
19 + return item != null && item !== '';
20 + })
21 + .map(function (item) {
22 + return style(item);
23 + })
24 + .join(';');
25 + }
26 +
27 + if ('Object' === styles.constructor) {
28 + return object
29 + .keys(styles)
30 + .filter(function (key) {
31 + return styles[key] != null && styles[key] !== '';
32 + })
33 + .map(function (key) {
34 + return [kebabCase(key), [styles[key]]].join(':');
35 + })
36 + .join(';');
37 + }
38 +
39 + return styles;
40 +}
41 +
42 +module.exports = style;
1 +/* eslint-disable */
2 +var bem = require('./bem.wxs');
3 +var memoize = require('./memoize.wxs');
4 +var addUnit = require('./add-unit.wxs');
5 +
6 +module.exports = {
7 + bem: memoize(bem),
8 + memoize: memoize,
9 + addUnit: addUnit
10 +};
1 +<!DOCTYPE html>
2 +<html>
3 +<head>
4 + <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
5 + <meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport">
6 + <meta name="apple-mobile-web-app-capable" content="yes">
7 + <meta name="apple-touch-fullscreen" content="yes">
8 + <meta name="format-detection" content="telephone=no,address=no">
9 + <meta name="apple-mobile-web-app-status-bar-style" content="white">
10 + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" >
11 + <title></title>
12 + <script>
13 + !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);
14 + </script>
15 +</head>
16 +<body>
17 + <div id="app"></div>
18 +</body>
19 +</html>
1 +export default {
2 + navigationBarTitleText: 'demo',
3 + usingComponents: {
4 + },
5 +}
1 +.red {
2 + color: red;
3 +}
1 +<template>
2 + <div class="red">{{ str }}</div>
3 +</template>
4 +
5 +<script setup>
6 + import { ref } from "vue";
7 + const str = ref('demo')
8 +</script>
9 +
10 +<script>
11 +import "./index.less";
12 +export default {
13 + name: "demoPage",
14 +};
15 +</script>
1 +export default {
2 + navigationBarTitleText: 'demo',
3 + usingComponents: {
4 + },
5 +}
1 +.red {
2 + color: red;
3 +}
1 +<!--
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-06-06 14:45:50
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-06-06 14:51:51
6 + * @FilePath: /taro-vant-weapp/src/pages/foo/index.vue
7 + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
8 +-->
9 +<template>
10 + <div class="red">{{ str }}</div>
11 +</template>
12 +
13 +<script setup>
14 + import { ref } from "vue";
15 + const str = ref('foo')
16 +</script>
17 +
18 +<script>
19 +import "./index.less";
20 +export default {
21 + name: "fooPage",
22 +};
23 +</script>
1 +export default {
2 + navigationBarTitleText: '首页',
3 + usingComponents: {
4 + },
5 +}
1 +<!--
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-27 15:57:59
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-06-06 19:18:14
6 + * @FilePath: /taro-vant-weapp/src/pages/index/index.vue
7 + * @Description:
8 +-->
9 +<template>
10 + <!-- <van-tabs :active="active" bind:change="onChange">
11 + <van-tab title="标签 1">内容 2</van-tab>
12 + <van-tab title="标签 2">内容 2</van-tab>
13 + <van-tab title="标签 3">内容 3</van-tab>
14 + <van-tab title="标签 4">
15 + <van-button type="primary" @click="goTo">主要按钮</van-button>
16 + </van-tab>
17 + </van-tabs> -->
18 + <van-button type="primary" @click="goTo">主要按钮</van-button>
19 + <van-image width="100" height="100" src="https://img.yzcdn.cn/vant/cat.jpeg" />
20 +</template>
21 +
22 +<script setup>
23 +import Taro from '@tarojs/taro'
24 +import { ref } from 'vue';
25 +import request from '../../utils/request';
26 +
27 +request.get('/srv/?a=kg_list')
28 +.then(res => {
29 + console.warn(res);
30 +})
31 +.catch(err => {
32 + console.error(err);
33 +})
34 +// Taro.request({
35 +// url: 'http://voice.onwall.cn/srv/?f=voice&a=kg_list', //仅为示例,并非真实的接口地址
36 +// data: {
37 +// },
38 +// // header: {
39 +// // 'content-type': 'application/json' // 默认值
40 +// // },
41 +// success: function (res) {
42 +// console.log(res.data)
43 +// }
44 +// })
45 +const active = ref(1);
46 +
47 +const goTo = () => {
48 + Taro.navigateTo({
49 + url: '../demo/index?id=1'
50 + })
51 +}
52 +</script>
53 +
54 +<script>
55 +import "./index.less";
56 +export default {
57 + name: "indexPage",
58 + onReady() {
59 + if (!Taro.canIUse("getUpdateManager")) {
60 + Taro.showModal({
61 + title: "提示",
62 + content: "当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试",
63 + showCancel: false,
64 + });
65 + return;
66 + }
67 +
68 + // https://developers.weixin.qq.com/miniprogram/dev/api/base/update/UpdateManager.html
69 + const updateManager = Taro.getUpdateManager();
70 +
71 + updateManager.onCheckForUpdate((res) => {
72 + // 请求完新版本信息的回调
73 + if (res.hasUpdate) {
74 + updateManager.onUpdateReady(function () {
75 + Taro.showModal({
76 + title: "更新提示",
77 + content: "新版本已经准备好,是否重启应用?",
78 + success: function (res) {
79 + if (res.confirm) {
80 + // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
81 + updateManager.applyUpdate();
82 + }
83 + },
84 + });
85 + });
86 +
87 + updateManager.onUpdateFailed(function () {
88 + // 新版本下载失败
89 + Taro.showModal({
90 + title: "更新提示",
91 + content: "新版本已上线,请删除当前小程序,重新搜索打开",
92 + });
93 + });
94 + }
95 + });
96 + },
97 +};
98 +</script>
1 +// https://pinia.esm.dev/introduction.html
2 +import { defineStore } from 'pinia'
3 +
4 +export const useCounterStore = defineStore('counter', {
5 + state: () => {
6 + return { count: 0 }
7 + },
8 + // could also be defined as
9 + // state: () => ({ count: 0 })
10 + actions: {
11 + increment() {
12 + this.count++
13 + },
14 + },
15 +})
16 +
17 +// You can even use a function (similar to a component setup()) to define a Store for more advanced use cases:
18 +// export const useCounterStore = defineStore('counter', () => {
19 +// const count = ref(0)
20 +//
21 +// function increment() {
22 +// count.value++
23 +// }
24 +//
25 +// return {count, increment}
26 +// })
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * @Date: 2022-09-19 14:11:06
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-09-19 14:19:05
5 + * @FilePath: /swx/src/utils/config.js
6 + * @Description: 文件描述
7 + */
8 +const BASE_URL = "http://voice.onwall.cn";
9 +
10 +export default BASE_URL
1 +/*
2 + * @Date: 2022-09-19 14:11:06
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-09-19 14:19:18
5 + * @FilePath: /swx/src/utils/request.js
6 + * @Description: 简单axios封装,后续按实际处理
7 + */
8 +// import axios from 'axios'
9 +import axios from 'axios-miniprogram';
10 +// import Toast from '../components/vant-weapp/toast/toast';
11 +// import { ProgressStart, ProgressEnd } from '@/components/axios-progress/progress';
12 +// import store from '@/store'
13 +// import { getToken } from '@/utils/auth'
14 +import BASE_URL from './config';
15 +// create an axios instance
16 +const service = axios.create({
17 + baseURL: BASE_URL, // url = base url + request url
18 + // withCredentials: true, // send cookies when cross-domain requests
19 + timeout: 5000 // request timeout
20 +})
21 +
22 +service.defaults.params = {
23 + f: 'voice',
24 +};
25 +
26 +// request interceptor
27 +service.interceptors.request.use(
28 + config => {
29 + console.warn(config)
30 + // console.warn(store)
31 +
32 + return config
33 + },
34 + error => {
35 + // do something with request error
36 + console.error(error, 'err') // for debug
37 + return Promise.reject(error)
38 + }
39 +)
40 +
41 +// response interceptor
42 +service.interceptors.response.use(
43 + /**
44 + * If you want to get http information such as headers or status
45 + * Please return response => response
46 + */
47 +
48 + /**
49 + * Determine the request status by custom code
50 + * Here is just an example
51 + * You can also judge the status by HTTP Status Code
52 + */
53 + response => {
54 +
55 + // wx.hideLoading();
56 + // const res = response.data
57 + // // Toast.clear();
58 + // // if the custom code is not 20000, it is judged as an error.
59 + // if (res.code !== 100000) {
60 + // // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
61 + // if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
62 + // // to re-login
63 + // // Toast.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
64 + // // confirmButtonText: 'Re-Login',
65 + // // cancelButtonText: 'Cancel',
66 + // // type: 'warning'
67 + // // }).then(() => {
68 + // // // store.dispatch('user/resetToken').then(() => {
69 + // // // location.reload()
70 + // // // })
71 + // // })
72 + // } else {
73 + // // Toast.fail({
74 + // // message: res.message,
75 + // // duration: 1.5 * 1000
76 + // // })
77 + // // Tips.error(res.message, false)
78 + // }
79 + // return Promise.reject(new Error(res.message || 'Error'))
80 + // } else {
81 + // return res
82 + // }
83 + return response
84 + },
85 + error => {
86 + // Toast.clear();
87 + console.error('err' + error) // for debug
88 + // Toast.fail({
89 + // message: error.message,
90 + // duration: 1.5 * 1000
91 + // })
92 + return Promise.reject(error)
93 + }
94 +)
95 +
96 +export default service
1 +const vantComponentNames = [
2 + "button",
3 + "icon",
4 + "loading",
5 + "info",
6 + "tab",
7 + "tabs",
8 + "sticky",
9 + "field",
10 + "cell",
11 + "image",
12 + "col",
13 + "row",
14 + "field",
15 + "cell-group",
16 + "toast",
17 + "empty",
18 + "overlay",
19 + "popup",
20 + "picker",
21 + "picker-column",
22 + "stepper",
23 + "dialog",
24 + "action-sheet",
25 + "checkbox",
26 + "transition",
27 +];
28 +
29 +module.exports = vantComponentNames;
This diff could not be displayed because it is too large.