mirror of
https://gitee.com/wot-design-uni/wot-design-uni.git
synced 2025-12-06 17:18:40 +08:00
feat: ✨ Picker组件优化性能
This commit is contained in:
parent
09c75d4878
commit
24dd43f3a0
@ -222,7 +222,7 @@ function handleChange({ value }) {
|
|||||||
|
|
||||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
|
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
|
||||||
| ----------------- | ---------------------------------------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------- | --------------------- | -------- |
|
| ----------------- | ---------------------------------------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------- | --------------------- | -------- |
|
||||||
| v-model | 选中值,为 13 位时间戳或时间戳数组 | null / number / array | - | - | - |
|
| v-model | 选中值,为 13 位时间戳或时间戳数组 | null / number / array | - | - | - |
|
||||||
| type | 日期类型 | string | date / dates / datetime / week / month / daterange / datetimerange / weekrange / monthrange | date | - |
|
| type | 日期类型 | string | date / dates / datetime / week / month / daterange / datetimerange / weekrange / monthrange | date | - |
|
||||||
| min-date | 最小日期,为 13 位时间戳 | number | - | 当前日期往前推 6 个月 | - |
|
| min-date | 最小日期,为 13 位时间戳 | number | - | 当前日期往前推 6 个月 | - |
|
||||||
| max-date | 最大日期,为 13 位时间戳 | number | - | 当前日期往后推 6 个月 | - |
|
| max-date | 最大日期,为 13 位时间戳 | number | - | 当前日期往后推 6 个月 | - |
|
||||||
@ -239,15 +239,15 @@ function handleChange({ value }) {
|
|||||||
|
|
||||||
## Events
|
## Events
|
||||||
|
|
||||||
| 事件名称 | 说明 | 参数 | 最低版本 |
|
| 事件名称 | 说明 | 参数 | 最低版本 |
|
||||||
| -------- | ---------------- | ------------------------ | -------- |
|
| -------- | ---------------- | ----------- | -------- |
|
||||||
| change | 绑定值变化时触发 | `{ value }` | - |
|
| change | 绑定值变化时触发 | `{ value }` | - |
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
|
|
||||||
| 方法名称 | 说明 | 参数 | 最低版本 |
|
| 方法名称 | 说明 | 参数 | 最低版本 |
|
||||||
| -------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | -------- |
|
| -------------- | ------------------------------------------------------------------------------------------------------------ | ---- | -------- |
|
||||||
| scrollIntoView | 使当前日期或者选中日期滚动到可视区域,并监听滚动,在面板从 隐藏状态(如 display: none) 切换为展示状态时调用 | thresholds,数字数组,具体使用见 [Intersection Observer](https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver) | - |
|
| scrollIntoView | 使当前日期或者选中日期滚动到可视区域,并监听滚动,在面板从 隐藏状态(如 display: none) 切换为展示状态时调用 | - |
|
||||||
|
|
||||||
## 外部样式类
|
## 外部样式类
|
||||||
|
|
||||||
|
|||||||
35
package.json
35
package.json
@ -52,19 +52,20 @@
|
|||||||
"upload:mp-dingtalk": "uni build -p mp-dingtalk && minici --platform dd"
|
"upload:mp-dingtalk": "uni build -p mp-dingtalk && minici --platform dd"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dcloudio/uni-app": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-app": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-app-plus": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-app-plus": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-components": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-components": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-h5": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-h5": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-mp-alipay": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-mp-alipay": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-mp-baidu": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-mp-baidu": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-mp-jd": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-mp-jd": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-mp-kuaishou": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-mp-kuaishou": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-mp-lark": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-mp-lark": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-mp-qq": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-mp-qq": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-mp-toutiao": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-mp-toutiao": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-mp-weixin": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-mp-weixin": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-quickapp-webview": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-mp-xhs": "3.0.0-alpha-3081220230802001",
|
||||||
|
"@dcloudio/uni-quickapp-webview": "3.0.0-alpha-3081220230802001",
|
||||||
"vitepress": "^1.0.0-beta.6",
|
"vitepress": "^1.0.0-beta.6",
|
||||||
"vue": "^3.2.45",
|
"vue": "^3.2.45",
|
||||||
"vue-i18n": "^9.1.9"
|
"vue-i18n": "^9.1.9"
|
||||||
@ -73,10 +74,10 @@
|
|||||||
"@commitlint/cli": "^17.4.4",
|
"@commitlint/cli": "^17.4.4",
|
||||||
"@commitlint/config-conventional": "^17.4.4",
|
"@commitlint/config-conventional": "^17.4.4",
|
||||||
"@dcloudio/types": "^3.3.2",
|
"@dcloudio/types": "^3.3.2",
|
||||||
"@dcloudio/uni-automator": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-automator": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-cli-shared": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-cli-shared": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-stacktracey": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/uni-stacktracey": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/vite-plugin-uni": "3.0.0-alpha-3080220230511001",
|
"@dcloudio/vite-plugin-uni": "3.0.0-alpha-3081220230802001",
|
||||||
"@types/node": "^18.14.6",
|
"@types/node": "^18.14.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.55.0",
|
"@typescript-eslint/eslint-plugin": "^5.55.0",
|
||||||
"@typescript-eslint/parser": "^5.55.0",
|
"@typescript-eslint/parser": "^5.55.0",
|
||||||
|
|||||||
@ -358,7 +358,7 @@
|
|||||||
"mp-alipay": {
|
"mp-alipay": {
|
||||||
"allowsBounceVertical": "NO"
|
"allowsBounceVertical": "NO"
|
||||||
},
|
},
|
||||||
"navigationBarTitleText": "Picker 选择器视图"
|
"navigationBarTitleText": "Picker 选择器"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
<wd-calendar label="日期时间选择" type="datetime" v-model="value4" />
|
<wd-calendar label="日期时间选择" type="datetime" v-model="value4" />
|
||||||
<wd-calendar label="日期时间范围选择" type="datetimerange" v-model="value5" />
|
<wd-calendar label="日期时间范围选择" type="datetimerange" v-model="value5" />
|
||||||
<wd-calendar label="周选择" type="week" v-model="value6" />
|
<wd-calendar label="周选择" type="week" v-model="value6" />
|
||||||
<wd-calendar label="月选择" type="month" v-model="value7" />
|
<wd-calendar label="月选择" type="month" :min-date="minDate" v-model="value7" />
|
||||||
<wd-calendar label="周范围选择" :first-day-of-week="1" type="weekrange" v-model="value8" />
|
<wd-calendar label="周范围选择" :first-day-of-week="1" type="weekrange" v-model="value8" />
|
||||||
<wd-calendar label="月范围选择" type="monthrange" v-model="value9" />
|
<wd-calendar label="月范围选择" type="monthrange" v-model="value9" />
|
||||||
<wd-calendar label="日周月切换" :first-day-of-week="1" show-type-switch v-model="value10" />
|
<wd-calendar label="日周月切换" :first-day-of-week="1" show-type-switch v-model="value10" />
|
||||||
@ -51,6 +51,8 @@ import { useToast } from '@/uni_modules/wot-design-uni'
|
|||||||
import { dayjs } from '@/uni_modules/wot-design-uni'
|
import { dayjs } from '@/uni_modules/wot-design-uni'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const minDate = ref<number>(new Date(new Date().getFullYear() - 20, new Date().getMonth() - 6, new Date().getDate()).getTime())
|
||||||
|
|
||||||
const value1 = ref<number>(Date.now())
|
const value1 = ref<number>(Date.now())
|
||||||
const value2 = ref<number[]>([Date.now() - 24 * 60 * 60 * 1000 * 3, Date.now()])
|
const value2 = ref<number[]>([Date.now() - 24 * 60 * 60 * 1000 * 3, Date.now()])
|
||||||
const value3 = ref<number[]>([])
|
const value3 = ref<number[]>([])
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
</demo-block>
|
</demo-block>
|
||||||
<demo-block title="自定义菜单选项" transparent>
|
<demo-block title="自定义菜单选项" transparent>
|
||||||
<view class="custom-menu">
|
<view class="custom-menu">
|
||||||
<wd-drop-menu style="flex: 1; min-width: 0">
|
<wd-drop-menu custom-style="flex: 1; min-width: 0">
|
||||||
<wd-drop-menu-item v-model="value4" :options="option1" @change="handleChange4" />
|
<wd-drop-menu-item v-model="value4" :options="option1" @change="handleChange4" />
|
||||||
</wd-drop-menu>
|
</wd-drop-menu>
|
||||||
<view style="flex: 1">
|
<view style="flex: 1">
|
||||||
|
|||||||
@ -69,6 +69,7 @@ onReady(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
function handleResize(detail: Record<string, string | number>) {
|
function handleResize(detail: Record<string, string | number>) {
|
||||||
|
console.log(detail)
|
||||||
const { height, width, top, right, bottom, left } = detail
|
const { height, width, top, right, bottom, left } = detail
|
||||||
lastHeight.value = sizeHeight.value
|
lastHeight.value = sizeHeight.value
|
||||||
lastTop.value = sizeTop.value
|
lastTop.value = sizeTop.value
|
||||||
|
|||||||
@ -42,6 +42,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.wd-action-sheet__popup){
|
||||||
|
border-radius: $-action-sheet-radius $-action-sheet-radius 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
@include b(action-sheet) {
|
@include b(action-sheet) {
|
||||||
background-color: $-color-white;
|
background-color: $-color-white;
|
||||||
padding-bottom: 1px;
|
padding-bottom: 1px;
|
||||||
|
|||||||
@ -1,57 +1,59 @@
|
|||||||
<template>
|
<template>
|
||||||
<wd-popup
|
<view>
|
||||||
custom-class="wd-action-sheet__popup"
|
<wd-popup
|
||||||
:custom-style="`${(actions && actions.length) || (panels && panels.length) ? 'background: transparent;' : ''}`"
|
custom-class="wd-action-sheet__popup"
|
||||||
v-model="showPopup"
|
:custom-style="`${(actions && actions.length) || (panels && panels.length) ? 'background: transparent;' : ''}`"
|
||||||
:duration="duration"
|
v-model="showPopup"
|
||||||
position="bottom"
|
:duration="duration"
|
||||||
:close-on-click-modal="closeOnClickModal"
|
position="bottom"
|
||||||
:safe-area-inset-bottom="safeAreaInsetBottom"
|
:close-on-click-modal="closeOnClickModal"
|
||||||
:lazy-render="lazyRender"
|
:safe-area-inset-bottom="safeAreaInsetBottom"
|
||||||
@enter="handleOpen"
|
:lazy-render="lazyRender"
|
||||||
@close="close"
|
@enter="handleOpen"
|
||||||
@after-enter="handleOpened"
|
@close="close"
|
||||||
@after-leave="handleClosed"
|
@after-enter="handleOpened"
|
||||||
@clickmodal="handleClickModal"
|
@after-leave="handleClosed"
|
||||||
:z-index="zIndex"
|
@clickmodal="handleClickModal"
|
||||||
>
|
:z-index="zIndex"
|
||||||
<view
|
|
||||||
class="wd-action-sheet"
|
|
||||||
:style="`${(actions && actions.length) || (panels && panels.length) ? 'margin: 0 10px 10px; border-radius: 16px;' : ''}`"
|
|
||||||
>
|
>
|
||||||
<view v-if="title" :class="`wd-action-sheet__header ${customHeaderClass}`">
|
<view
|
||||||
{{ title }}
|
class="wd-action-sheet"
|
||||||
<wd-icon custom-class="wd-action-sheet__close" name="add" @click="close" />
|
:style="`${(actions && actions.length) || (panels && panels.length) ? 'margin: 0 10px 10px; border-radius: 16px;' : ''}`"
|
||||||
</view>
|
>
|
||||||
<view class="wd-action-sheet__actions" v-if="actions && actions.length">
|
<view v-if="title" :class="`wd-action-sheet__header ${customHeaderClass}`">
|
||||||
<button
|
{{ title }}
|
||||||
v-for="(action, rowIndex) in actions"
|
<wd-icon custom-class="wd-action-sheet__close" name="add" @click="close" />
|
||||||
:key="rowIndex"
|
</view>
|
||||||
:class="`wd-action-sheet__action ${action.disabled ? 'wd-action-sheet__action--disabled' : ''} ${
|
<view class="wd-action-sheet__actions" v-if="actions && actions.length">
|
||||||
action.loading ? 'wd-action-sheet__action--loading' : ''
|
<button
|
||||||
}`"
|
v-for="(action, rowIndex) in actions"
|
||||||
:style="`color: ${action.color}`"
|
:key="rowIndex"
|
||||||
@click="select(rowIndex, 'action')"
|
:class="`wd-action-sheet__action ${action.disabled ? 'wd-action-sheet__action--disabled' : ''} ${
|
||||||
>
|
action.loading ? 'wd-action-sheet__action--loading' : ''
|
||||||
<wd-loading v-if="action.loading" size="20px" />
|
}`"
|
||||||
<view v-else class="wd-action-sheet__name">{{ action.name }}</view>
|
:style="`color: ${action.color}`"
|
||||||
<view v-if="!action.loading && action.subname" class="wd-action-sheet__subname">{{ action.subname }}</view>
|
@click="select(rowIndex, 'action')"
|
||||||
</button>
|
>
|
||||||
</view>
|
<wd-loading v-if="action.loading" size="20px" />
|
||||||
<view v-if="formatPanels && formatPanels.length">
|
<view v-else class="wd-action-sheet__name">{{ action.name }}</view>
|
||||||
<view v-for="(panel, rowIndex) in formatPanels" :key="rowIndex" class="wd-action-sheet__panels">
|
<view v-if="!action.loading && action.subname" class="wd-action-sheet__subname">{{ action.subname }}</view>
|
||||||
<view class="wd-action-sheet__panels-content">
|
</button>
|
||||||
<view v-for="(col, colIndex) in panel" :key="colIndex" class="wd-action-sheet__panel" @click="select(rowIndex, 'panels', colIndex)">
|
</view>
|
||||||
<image class="wd-action-sheet__panel-img" :src="(col as any).iconUrl" />
|
<view v-if="formatPanels && formatPanels.length">
|
||||||
<view class="wd-action-sheet__panel-title">{{ (col as any).title }}</view>
|
<view v-for="(panel, rowIndex) in formatPanels" :key="rowIndex" class="wd-action-sheet__panels">
|
||||||
|
<view class="wd-action-sheet__panels-content">
|
||||||
|
<view v-for="(col, colIndex) in panel" :key="colIndex" class="wd-action-sheet__panel" @click="select(rowIndex, 'panels', colIndex)">
|
||||||
|
<image class="wd-action-sheet__panel-img" :src="(col as any).iconUrl" />
|
||||||
|
<view class="wd-action-sheet__panel-title">{{ (col as any).title }}</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<slot />
|
||||||
|
<button v-if="cancelText" class="wd-action-sheet__cancel" @click="handleCancel">{{ cancelText }}</button>
|
||||||
</view>
|
</view>
|
||||||
<slot />
|
</wd-popup>
|
||||||
<button v-if="cancelText" class="wd-action-sheet__cancel" @click="handleCancel">{{ cancelText }}</button>
|
</view>
|
||||||
</view>
|
|
||||||
</wd-popup>
|
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
@ -114,7 +116,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
closeOnClickModal: true,
|
closeOnClickModal: true,
|
||||||
duration: 200,
|
duration: 200,
|
||||||
zIndex: 10,
|
zIndex: 10,
|
||||||
lazyRender: false,
|
lazyRender: true,
|
||||||
safeAreaInsetBottom: true
|
safeAreaInsetBottom: true
|
||||||
})
|
})
|
||||||
const formatPanels = ref<Array<Panel> | Array<Array<Panel>>>([])
|
const formatPanels = ref<Array<Panel> | Array<Array<Panel>>>([])
|
||||||
|
|||||||
@ -23,8 +23,10 @@
|
|||||||
|
|
||||||
@include b(month) {
|
@include b(month) {
|
||||||
@include e(title) {
|
@include e(title) {
|
||||||
padding: 13px 0;
|
display: flex;
|
||||||
text-align: center;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 45px;
|
||||||
font-size: $-calendar-panel-title-fs;
|
font-size: $-calendar-panel-title-fs;
|
||||||
color: $-calendar-panel-title-color;
|
color: $-calendar-panel-title-color;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,7 +82,7 @@ const monthTitle = computed(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
const firstDayStyle = computed(() => {
|
const firstDayStyle = computed(() => {
|
||||||
return (index, date, firstDayOfWeek) => {
|
return (index: number, date: number, firstDayOfWeek: number) => {
|
||||||
return getFirstDayStyle(index, date, firstDayOfWeek)
|
return getFirstDayStyle(index, date, firstDayOfWeek)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -8,16 +8,17 @@
|
|||||||
</view>
|
</view>
|
||||||
<scroll-view
|
<scroll-view
|
||||||
:class="`wd-month-panel__container ${!!timeType ? 'wd-month-panel__container--time' : ''}`"
|
:class="`wd-month-panel__container ${!!timeType ? 'wd-month-panel__container--time' : ''}`"
|
||||||
:style="`height: ${!!timeType ? (panelHeight || 378) - 125 : panelHeight || 378}px`"
|
:style="`height: ${scrollHeight}px`"
|
||||||
scroll-y
|
scroll-y
|
||||||
:scroll-into-view="scrollIntoViewValue"
|
@scroll="monthScroll"
|
||||||
|
:scroll-top="scrollTop"
|
||||||
>
|
>
|
||||||
<view v-for="(item, index) in months(minDate, maxDate)" :key="index" :id="`month${index}`">
|
<view v-for="(item, index) in months(minDate, maxDate)" :key="index" :id="`month${index}`">
|
||||||
<month
|
<month
|
||||||
class="month"
|
class="month"
|
||||||
:type="type"
|
:type="type"
|
||||||
:date="item"
|
:date="item.date"
|
||||||
:data-date="item"
|
:data-date="item.date"
|
||||||
:value="value"
|
:value="value"
|
||||||
:min-date="minDate"
|
:min-date="minDate"
|
||||||
:max-date="maxDate"
|
:max-date="maxDate"
|
||||||
@ -41,7 +42,6 @@
|
|||||||
v-model="timeValue"
|
v-model="timeValue"
|
||||||
:columns="timeData"
|
:columns="timeData"
|
||||||
:columns-height="125"
|
:columns-height="125"
|
||||||
:show-picker="showPicker"
|
|
||||||
@change="handleTimeChange"
|
@change="handleTimeChange"
|
||||||
@pickstart="handlePickStart"
|
@pickstart="handlePickStart"
|
||||||
@pickend="handlePickEnd"
|
@pickend="handlePickEnd"
|
||||||
@ -64,8 +64,9 @@ export default {
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, getCurrentInstance, nextTick, onMounted, ref, watch } from 'vue'
|
import { computed, getCurrentInstance, nextTick, onMounted, ref, watch } from 'vue'
|
||||||
import { debounce, getType, isEqual } from '../../common/util'
|
import { debounce, getType, isEqual } from '../../common/util'
|
||||||
import { compareMonth, formatMonthTitle, getMonths, getTimeData, getWeekLabel } from '../utils'
|
import { compareMonth, formatMonthTitle, getMonthEndDay, getMonths, getTimeData, getWeekLabel } from '../utils'
|
||||||
import Month from '../month/month.vue'
|
import Month from '../month/month.vue'
|
||||||
|
import { MonthInfo } from './type'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
type: string
|
type: string
|
||||||
@ -84,35 +85,44 @@ interface Props {
|
|||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
timeFilter?: Function
|
timeFilter?: Function
|
||||||
hideSecond: boolean
|
hideSecond: boolean
|
||||||
// 是否展示picker(兼容支付宝和钉钉)
|
|
||||||
showPicker: boolean
|
|
||||||
}
|
}
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
showPicker: true,
|
|
||||||
allowSameDay: false,
|
allowSameDay: false,
|
||||||
showPanelTitle: false,
|
showPanelTitle: false,
|
||||||
hideSecond: false
|
hideSecond: false
|
||||||
})
|
})
|
||||||
|
|
||||||
const title = ref<string>('')
|
const title = ref<string>('')
|
||||||
const scrollIntoViewValue = ref<string>('')
|
const scrollTop = ref<number>(0) // 滚动位置
|
||||||
const timeValue = ref<Array<string>>([])
|
const timeValue = ref<Array<string>>([])
|
||||||
const timeData = ref<Array<string | string[]>>([])
|
const timeData = ref<Array<string | string[]>>([])
|
||||||
const timeType = ref<string>('') // 当前时间类型,是开始还是结束
|
const timeType = ref<string>('') // 当前时间类型,是开始还是结束
|
||||||
const innerValue = ref<string | number[]>('') // 内部保存一个值,用于判断新老值,避免监听器触发
|
const innerValue = ref<string | number[]>('') // 内部保存一个值,用于判断新老值,避免监听器触发
|
||||||
|
|
||||||
let contentObserver: null | UniApp.IntersectionObserver = null
|
|
||||||
const instance = getCurrentInstance() as any
|
|
||||||
|
|
||||||
const weekLabel = computed(() => {
|
const weekLabel = computed(() => {
|
||||||
return (index: number) => {
|
return (index: number) => {
|
||||||
return getWeekLabel(index)
|
return getWeekLabel(index - 1)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 滚动区域的高度
|
||||||
|
const scrollHeight = computed(() => {
|
||||||
|
const scrollHeight: number = timeType.value ? (props.panelHeight || 378) - 125 : props.panelHeight || 378
|
||||||
|
return scrollHeight
|
||||||
|
})
|
||||||
|
|
||||||
|
// 月份日期和月份高度
|
||||||
const months = computed(() => {
|
const months = computed(() => {
|
||||||
return (minDate, maxDate) => {
|
return (minDate: number, maxDate: number): MonthInfo[] => {
|
||||||
return getMonths(minDate, maxDate)
|
let months = getMonths(minDate, maxDate).map((month) => {
|
||||||
|
const offset = (7 + new Date(month).getDay() - props.firstDayOfWeek) % 7
|
||||||
|
const totalDay = getMonthEndDay(new Date(month).getFullYear(), new Date(month).getMonth() + 1)
|
||||||
|
return {
|
||||||
|
height: (offset + totalDay > 35 ? 64 * 6 : 64 * 5) + 45,
|
||||||
|
date: month
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return months
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -148,7 +158,6 @@ watch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initRect()
|
|
||||||
scrollIntoView()
|
scrollIntoView()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -160,26 +169,6 @@ const handleChange = debounce((value) => {
|
|||||||
})
|
})
|
||||||
}, 50)
|
}, 50)
|
||||||
|
|
||||||
function initRect(thresholds = [0, 0.7, 0.8, 0.9, 1]) {
|
|
||||||
if (!props.showPanelTitle) return
|
|
||||||
|
|
||||||
if (contentObserver != null) {
|
|
||||||
contentObserver.disconnect()
|
|
||||||
}
|
|
||||||
|
|
||||||
contentObserver = uni.createIntersectionObserver(instance, {
|
|
||||||
thresholds,
|
|
||||||
observeAll: true,
|
|
||||||
dataset: true
|
|
||||||
} as any)
|
|
||||||
|
|
||||||
contentObserver.relativeTo('.wd-month-panel__container')
|
|
||||||
contentObserver.observe('.month', (res: any) => {
|
|
||||||
if (res.boundingClientRect.top <= res.relativeRect.top) {
|
|
||||||
title.value = formatMonthTitle(res.dataset.date)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
function scrollIntoView() {
|
function scrollIntoView() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
let activeDate
|
let activeDate
|
||||||
@ -194,17 +183,18 @@ function scrollIntoView() {
|
|||||||
activeDate = Date.now()
|
activeDate = Date.now()
|
||||||
}
|
}
|
||||||
|
|
||||||
const months = getMonths(props.minDate, props.maxDate)
|
const monthsInfo = months.value(props.minDate, props.maxDate)
|
||||||
|
|
||||||
months.some((month, index) => {
|
let top: number = 0
|
||||||
if (compareMonth(month, activeDate) === 0) {
|
for (let index = 0; index < monthsInfo.length; index++) {
|
||||||
scrollIntoViewValue.value = ''
|
if (compareMonth(monthsInfo[index].date, activeDate) === 0) {
|
||||||
nextTick(() => {
|
break
|
||||||
scrollIntoViewValue.value = `month${index}`
|
|
||||||
})
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
return false
|
top += monthsInfo[index] ? Number(monthsInfo[index].height) : 0
|
||||||
|
}
|
||||||
|
scrollTop.value = 0
|
||||||
|
nextTick(() => {
|
||||||
|
scrollTop.value = top
|
||||||
})
|
})
|
||||||
}, 50)
|
}, 50)
|
||||||
}
|
}
|
||||||
@ -275,10 +265,6 @@ function setTime(value, type) {
|
|||||||
timeData.value = getTime(value, type) || []
|
timeData.value = getTime(value, type) || []
|
||||||
timeValue.value = getTimeValue(value, type)
|
timeValue.value = getTimeValue(value, type)
|
||||||
timeType.value = type
|
timeType.value = type
|
||||||
|
|
||||||
nextTick(() => {
|
|
||||||
initRect([0, 0.58, 0.69, 0.83, 1])
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
function handleDateChange({ value, type }) {
|
function handleDateChange({ value, type }) {
|
||||||
if (!isEqual(value, props.value)) {
|
if (!isEqual(value, props.value)) {
|
||||||
@ -335,8 +321,31 @@ function handlePickEnd() {
|
|||||||
emit('pickend')
|
emit('pickend')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const monthScroll = (event: { detail: { scrollTop: number } }) => {
|
||||||
|
const monthsInfo = months.value(props.minDate, props.maxDate)
|
||||||
|
if (monthsInfo.length <= 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const scrollTop = Math.max(0, event.detail.scrollTop)
|
||||||
|
doSetSubtitle(scrollTop, monthsInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置小标题
|
||||||
|
* scrollTop 滚动条位置
|
||||||
|
*/
|
||||||
|
function doSetSubtitle(scrollTop: number, monthsInfo: MonthInfo[]) {
|
||||||
|
let height: number = 0 // 月份高度和
|
||||||
|
for (let index = 0; index < monthsInfo.length; index++) {
|
||||||
|
height = height + monthsInfo[index].height
|
||||||
|
if (scrollTop < height + 45) {
|
||||||
|
title.value = formatMonthTitle(monthsInfo[index].date)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
initRect,
|
|
||||||
scrollIntoView
|
scrollIntoView
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* 月份信息
|
||||||
|
*/
|
||||||
|
export interface MonthInfo {
|
||||||
|
date: number
|
||||||
|
height: number
|
||||||
|
}
|
||||||
@ -112,15 +112,14 @@ export function getWeekLabel(index) {
|
|||||||
* @param {timestamp} date
|
* @param {timestamp} date
|
||||||
* @param {number} firstDayOfWeek
|
* @param {number} firstDayOfWeek
|
||||||
*/
|
*/
|
||||||
export function getFirstDayStyle(index, date, firstDayOfWeek) {
|
export function getFirstDayStyle(index: number, date: number, firstDayOfWeek: number) {
|
||||||
if (firstDayOfWeek >= 7) {
|
if (firstDayOfWeek >= 7) {
|
||||||
firstDayOfWeek = firstDayOfWeek % 7
|
firstDayOfWeek = firstDayOfWeek % 7
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index !== 0) return ''
|
if (index !== 0) return ''
|
||||||
|
|
||||||
date = new Date(date)
|
const offset = (7 + new Date(date).getDay() - firstDayOfWeek) % 7
|
||||||
const offset = (7 + date.getDay() - firstDayOfWeek) % 7
|
|
||||||
|
|
||||||
return 'margin-left: ' + (100 / 7) * offset + '%'
|
return 'margin-left: ' + (100 / 7) * offset + '%'
|
||||||
}
|
}
|
||||||
@ -129,10 +128,8 @@ export function getFirstDayStyle(index, date, firstDayOfWeek) {
|
|||||||
* 格式化年份
|
* 格式化年份
|
||||||
* @param {timestamp} date
|
* @param {timestamp} date
|
||||||
*/
|
*/
|
||||||
export function formatYearTitle(date) {
|
export function formatYearTitle(date: number) {
|
||||||
date = new Date(date)
|
const year = new Date(date).getFullYear()
|
||||||
|
|
||||||
const year = date.getFullYear()
|
|
||||||
|
|
||||||
return year + '年'
|
return year + '年'
|
||||||
}
|
}
|
||||||
@ -160,7 +157,7 @@ export function getMonths(minDate, maxDate) {
|
|||||||
* @param {timestamp} minDate
|
* @param {timestamp} minDate
|
||||||
* @param {timestamp} maxDate
|
* @param {timestamp} maxDate
|
||||||
*/
|
*/
|
||||||
export function getYears(minDate, maxDate) {
|
export function getYears(minDate: number, maxDate: number) {
|
||||||
const years: number[] = []
|
const years: number[] = []
|
||||||
const year = new Date(minDate)
|
const year = new Date(minDate)
|
||||||
year.setMonth(0)
|
year.setMonth(0)
|
||||||
|
|||||||
@ -33,7 +33,6 @@
|
|||||||
:panel-height="panelHeight"
|
:panel-height="panelHeight"
|
||||||
:time-filter="timeFilter"
|
:time-filter="timeFilter"
|
||||||
:hide-second="hideSecond"
|
:hide-second="hideSecond"
|
||||||
:show-picker="showPicker"
|
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
@pickstart="handlePickStart"
|
@pickstart="handlePickStart"
|
||||||
@pickend="handlePickEnd"
|
@pickend="handlePickEnd"
|
||||||
@ -43,7 +42,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-calendar-view',
|
name: 'wd-calendar-view',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
@ -92,8 +90,6 @@ interface Props {
|
|||||||
timeFilter?: Function
|
timeFilter?: Function
|
||||||
// type 为 'datetime' 或 'datetimerange' 时有效,是否不展示秒修改
|
// type 为 'datetime' 或 'datetimerange' 时有效,是否不展示秒修改
|
||||||
hideSecond: boolean
|
hideSecond: boolean
|
||||||
// 是否展示picker(兼容支付宝和钉钉)
|
|
||||||
showPicker: boolean
|
|
||||||
}
|
}
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
customClass: '',
|
customClass: '',
|
||||||
@ -105,8 +101,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
showPanelTitle: true,
|
showPanelTitle: true,
|
||||||
defaultTime: '00:00:00',
|
defaultTime: '00:00:00',
|
||||||
panelHeight: 378,
|
panelHeight: 378,
|
||||||
hideSecond: false,
|
hideSecond: false
|
||||||
showPicker: true
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const formatDefauleTime = ref<number[]>([])
|
const formatDefauleTime = ref<number[]>([])
|
||||||
@ -128,9 +123,8 @@ watch(
|
|||||||
const emit = defineEmits(['change', 'update:modelValue', 'pickstart', 'pickend'])
|
const emit = defineEmits(['change', 'update:modelValue', 'pickstart', 'pickend'])
|
||||||
|
|
||||||
// 对外暴露方法
|
// 对外暴露方法
|
||||||
function scrollIntoView(thresholds) {
|
function scrollIntoView() {
|
||||||
const panel = getPanel()
|
const panel = getPanel()
|
||||||
panel.initRect && panel.initRect(thresholds)
|
|
||||||
panel.scrollIntoView && panel.scrollIntoView()
|
panel.scrollIntoView && panel.scrollIntoView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,8 +24,10 @@
|
|||||||
|
|
||||||
@include b(year) {
|
@include b(year) {
|
||||||
@include e(title) {
|
@include e(title) {
|
||||||
padding: 13px 0;
|
display: flex;
|
||||||
text-align: center;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 45px;
|
||||||
font-size: $-calendar-panel-title-fs;
|
font-size: $-calendar-panel-title-fs;
|
||||||
color: $-calendar-panel-title-color;
|
color: $-calendar-panel-title-color;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* 月份信息
|
||||||
|
*/
|
||||||
|
export interface YearInfo {
|
||||||
|
date: number
|
||||||
|
height: number
|
||||||
|
}
|
||||||
@ -1,18 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="wd-year-panel">
|
<view class="wd-year-panel">
|
||||||
<view v-if="showPanelTitle" class="wd-year-panel__title">{{ title }}</view>
|
<view v-if="showPanelTitle" class="wd-year-panel__title">{{ title }}</view>
|
||||||
<scroll-view
|
<scroll-view class="wd-year-panel__container" :style="`height: ${scrollHeight}px`" scroll-y @scroll="yearScroll" :scroll-top="scrollTop">
|
||||||
class="wd-year-panel__container"
|
|
||||||
:style="`height: ${(panelHeight || 378) + (showPanelTitle ? 26 : 16)}px`"
|
|
||||||
scroll-y
|
|
||||||
:scroll-into-view="scrollIntoViewValue"
|
|
||||||
>
|
|
||||||
<view v-for="(item, index) in years(minDate, maxDate)" :key="index" :id="`year${index}`">
|
<view v-for="(item, index) in years(minDate, maxDate)" :key="index" :id="`year${index}`">
|
||||||
<year
|
<year
|
||||||
class="year"
|
class="year"
|
||||||
:type="type"
|
:type="type"
|
||||||
:date="item"
|
:date="item.date"
|
||||||
:data-date="item"
|
:data-date="item.date"
|
||||||
:value="value"
|
:value="value"
|
||||||
:min-date="minDate"
|
:min-date="minDate"
|
||||||
:max-date="maxDate"
|
:max-date="maxDate"
|
||||||
@ -42,6 +37,7 @@ import { computed, getCurrentInstance, onMounted, ref, nextTick } from 'vue'
|
|||||||
import { compareYear, formatYearTitle, getYears } from '../utils'
|
import { compareYear, formatYearTitle, getYears } from '../utils'
|
||||||
import { getType } from '../../common/util'
|
import { getType } from '../../common/util'
|
||||||
import Year from '../year/year.vue'
|
import Year from '../year/year.vue'
|
||||||
|
import { YearInfo } from './type'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
type: string
|
type: string
|
||||||
@ -63,21 +59,34 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const title = ref<string>('')
|
const title = ref<string>('')
|
||||||
|
const scrollTop = ref<number>(0) // 滚动位置
|
||||||
|
|
||||||
const scrollIntoViewValue = ref<string>('')
|
const scrollIntoViewValue = ref<string>('')
|
||||||
|
|
||||||
let contentObserver: null | UniApp.IntersectionObserver = null
|
let contentObserver: null | UniApp.IntersectionObserver = null
|
||||||
const instance = getCurrentInstance() as any
|
const instance = getCurrentInstance() as any
|
||||||
|
|
||||||
|
// 滚动区域的高度
|
||||||
|
const scrollHeight = computed(() => {
|
||||||
|
const scrollHeight: number = (props.panelHeight || 378) + (props.showPanelTitle ? 26 : 16)
|
||||||
|
return scrollHeight
|
||||||
|
})
|
||||||
|
|
||||||
const years = computed(() => {
|
const years = computed(() => {
|
||||||
return (minDate, maxDate) => {
|
return (minDate: number, maxDate: number): YearInfo[] => {
|
||||||
return getYears(minDate, maxDate)
|
let years = getYears(minDate, maxDate).map((year) => {
|
||||||
|
return {
|
||||||
|
date: year,
|
||||||
|
height: 237
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return years
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['change'])
|
const emit = defineEmits(['change'])
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initRect()
|
|
||||||
scrollIntoView()
|
scrollIntoView()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -94,25 +103,6 @@ const requestAnimationFrame = (cb = () => void 0) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function initRect(thresholds = [0, 0.15, 0.7, 0.8, 0.9, 1]) {
|
|
||||||
if (!props.showPanelTitle) return
|
|
||||||
|
|
||||||
if (contentObserver != null) {
|
|
||||||
contentObserver.disconnect()
|
|
||||||
}
|
|
||||||
|
|
||||||
contentObserver = uni.createIntersectionObserver(instance, {
|
|
||||||
thresholds,
|
|
||||||
observeAll: true
|
|
||||||
})
|
|
||||||
|
|
||||||
contentObserver.relativeTo('.wd-year-panel__container')
|
|
||||||
contentObserver.observe('.year', (res: any) => {
|
|
||||||
if (res.boundingClientRect.top <= res.relativeRect.top) {
|
|
||||||
title.value = formatYearTitle(res.dataset.date)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
function scrollIntoView() {
|
function scrollIntoView() {
|
||||||
requestAnimationFrame().then(() => {
|
requestAnimationFrame().then(() => {
|
||||||
let activeDate
|
let activeDate
|
||||||
@ -127,21 +117,46 @@ function scrollIntoView() {
|
|||||||
activeDate = Date.now()
|
activeDate = Date.now()
|
||||||
}
|
}
|
||||||
|
|
||||||
const years = getYears(props.minDate, props.maxDate)
|
const yearsInfo = years.value(props.minDate, props.maxDate)
|
||||||
|
|
||||||
years.some((year, index) => {
|
let top: number = 0
|
||||||
if (compareYear(year, activeDate) === 0) {
|
for (let index = 0; index < yearsInfo.length; index++) {
|
||||||
scrollIntoViewValue.value = ''
|
if (compareYear(yearsInfo[index].date, activeDate) === 0) {
|
||||||
nextTick(() => {
|
break
|
||||||
scrollIntoViewValue.value = `year${index}`
|
|
||||||
})
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
top += yearsInfo[index] ? Number(yearsInfo[index].height) : 0
|
||||||
return false
|
}
|
||||||
|
scrollTop.value = 0
|
||||||
|
nextTick(() => {
|
||||||
|
scrollTop.value = top
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const yearScroll = (e: Event) => {
|
||||||
|
const yearsInfo = years.value(props.minDate, props.maxDate)
|
||||||
|
if (yearsInfo.length <= 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const scrollTop = Math.max(0, (e.target as Element).scrollTop)
|
||||||
|
doSetSubtitle(scrollTop, yearsInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置小标题
|
||||||
|
* scrollTop 滚动条位置
|
||||||
|
*/
|
||||||
|
function doSetSubtitle(scrollTop: number, yearsInfo: YearInfo[]) {
|
||||||
|
let height: number = 0 // 月份高度和
|
||||||
|
for (let index = 0; index < yearsInfo.length; index++) {
|
||||||
|
height = height + yearsInfo[index].height
|
||||||
|
if (scrollTop < height + 45) {
|
||||||
|
title.value = formatYearTitle(yearsInfo[index].date)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleDateChange({ value }) {
|
function handleDateChange({ value }) {
|
||||||
emit('change', {
|
emit('change', {
|
||||||
value
|
value
|
||||||
@ -149,7 +164,6 @@ function handleDateChange({ value }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
initRect,
|
|
||||||
scrollIntoView
|
scrollIntoView
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -31,8 +31,6 @@
|
|||||||
:safe-area-inset-bottom="safeAreaInsetBottom"
|
:safe-area-inset-bottom="safeAreaInsetBottom"
|
||||||
:z-index="zIndex"
|
:z-index="zIndex"
|
||||||
@close="close"
|
@close="close"
|
||||||
@opened="setShowPicker(true)"
|
|
||||||
@closed="setShowPicker(false)"
|
|
||||||
>
|
>
|
||||||
<view class="wd-calendar__header">
|
<view class="wd-calendar__header">
|
||||||
<view v-if="!showTypeSwitch && shortcuts.length === 0" class="wd-calendar__title">{{ title || '选择日期' }}</view>
|
<view v-if="!showTypeSwitch && shortcuts.length === 0" class="wd-calendar__title">{{ title || '选择日期' }}</view>
|
||||||
@ -86,7 +84,6 @@
|
|||||||
:default-time="defaultTime"
|
:default-time="defaultTime"
|
||||||
:time-filter="timeFilter"
|
:time-filter="timeFilter"
|
||||||
:hide-second="hideSecond"
|
:hide-second="hideSecond"
|
||||||
:show-picker="showPicker"
|
|
||||||
:show-panel-title="!range(type)"
|
:show-panel-title="!range(type)"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
/>
|
/>
|
||||||
@ -101,7 +98,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-calendar',
|
name: 'wd-calendar',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
@ -274,7 +270,6 @@ const currentType = ref<CalendarType>('date')
|
|||||||
const lastCurrentType = ref<CalendarType>('date')
|
const lastCurrentType = ref<CalendarType>('date')
|
||||||
const inited = ref<boolean>(false)
|
const inited = ref<boolean>(false)
|
||||||
const rangeLabel = ref<Array<string>>([])
|
const rangeLabel = ref<Array<string>>([])
|
||||||
const showPicker = ref<boolean>(false)
|
|
||||||
|
|
||||||
const cell = useCell()
|
const cell = useCell()
|
||||||
|
|
||||||
@ -342,10 +337,6 @@ const range = computed(() => {
|
|||||||
|
|
||||||
const emit = defineEmits(['cancel', 'change', 'update:modelValue', 'confirm'])
|
const emit = defineEmits(['cancel', 'change', 'update:modelValue', 'confirm'])
|
||||||
|
|
||||||
const setShowPicker = debounce(function (show: boolean) {
|
|
||||||
showPicker.value = show
|
|
||||||
}, 100)
|
|
||||||
|
|
||||||
function scrollIntoView() {
|
function scrollIntoView() {
|
||||||
calendarView.value && calendarView.value && calendarView.value.$.exposed.scrollIntoView()
|
calendarView.value && calendarView.value && calendarView.value.$.exposed.scrollIntoView()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-checkbox-group',
|
name: 'wd-checkbox-group',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
|
|||||||
@ -33,7 +33,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-checkbox',
|
name: 'wd-checkbox',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
|
|||||||
@ -80,7 +80,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-col-picker',
|
name: 'wd-col-picker',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
@ -217,8 +216,6 @@ watch(
|
|||||||
selectShowList.value = pickerColSelected.value.map((item, colIndex) => {
|
selectShowList.value = pickerColSelected.value.map((item, colIndex) => {
|
||||||
return getSelectedItem(item, colIndex, newSelectedList)[props.labelKey]
|
return getSelectedItem(item, colIndex, newSelectedList)[props.labelKey]
|
||||||
})
|
})
|
||||||
console.log(selectShowList.value, 'watch props.columns')
|
|
||||||
|
|
||||||
lastSelectList.value = newSelectedList
|
lastSelectList.value = newSelectedList
|
||||||
|
|
||||||
if (newSelectedList.length > 0) {
|
if (newSelectedList.length > 0) {
|
||||||
@ -372,8 +369,6 @@ function handleColChange(colIndex, item, index, callback?) {
|
|||||||
selectShowList.value = pickerColSelected.value.map((item, colIndex) => {
|
selectShowList.value = pickerColSelected.value.map((item, colIndex) => {
|
||||||
return getSelectedItem(item, colIndex, selectList.value)[props.labelKey]
|
return getSelectedItem(item, colIndex, selectList.value)[props.labelKey]
|
||||||
})
|
})
|
||||||
console.log(selectShowList.value, 'handleColChange')
|
|
||||||
|
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -509,6 +504,11 @@ function handleAutoComplete() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
close,
|
||||||
|
open
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@ -0,0 +1,24 @@
|
|||||||
|
export type DateTimeType = 'date' | 'year-month' | 'time' | 'datetime'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据传入的值和类型,获取当前的选项数组,便于传入 pickerView
|
||||||
|
* @param value
|
||||||
|
* @param type picker类型
|
||||||
|
* @return {Array} pickerValue
|
||||||
|
*/
|
||||||
|
export function getPickerValue(value, type) {
|
||||||
|
const values: number[] = []
|
||||||
|
const date = new Date(value)
|
||||||
|
if (type === 'time') {
|
||||||
|
const pair = value.split(':')
|
||||||
|
values.push(parseInt(pair[0]), parseInt(pair[1]))
|
||||||
|
} else {
|
||||||
|
values.push(date.getFullYear(), date.getMonth() + 1)
|
||||||
|
if (type === 'date') {
|
||||||
|
values.push(date.getDate())
|
||||||
|
} else if (type === 'datetime') {
|
||||||
|
values.push(date.getDate(), date.getHours(), date.getMinutes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
@ -9,7 +9,6 @@
|
|||||||
:columnChange="columnChange"
|
:columnChange="columnChange"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:loading-color="loadingColor"
|
:loading-color="loadingColor"
|
||||||
:show-picker="showPicker"
|
|
||||||
@change="onChange"
|
@change="onChange"
|
||||||
@pickstart="onPickStart"
|
@pickstart="onPickStart"
|
||||||
@pickend="onPickEnd"
|
@pickend="onPickEnd"
|
||||||
@ -19,7 +18,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-datetime-picker-view',
|
name: 'wd-datetime-picker-view',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
styleIsolation: 'shared'
|
styleIsolation: 'shared'
|
||||||
@ -29,6 +27,7 @@ export default {
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getCurrentInstance, onBeforeMount, onMounted, ref, watch } from 'vue'
|
import { getCurrentInstance, onBeforeMount, onMounted, ref, watch } from 'vue'
|
||||||
import { debounce, getType, isDef, padZero, range } from '../common/util'
|
import { debounce, getType, isDef, padZero, range } from '../common/util'
|
||||||
|
import { DateTimeType, getPickerValue } from './type'
|
||||||
|
|
||||||
// 本地时间戳
|
// 本地时间戳
|
||||||
/** @description 判断时间戳是否合法 */
|
/** @description 判断时间戳是否合法 */
|
||||||
@ -58,15 +57,11 @@ const getMonthEndDay = (year, month) => {
|
|||||||
return 32 - new Date(year, month - 1, 32).getDate()
|
return 32 - new Date(year, month - 1, 32).getDate()
|
||||||
}
|
}
|
||||||
|
|
||||||
type DateTimeType = 'date' | 'year-month' | 'time' | 'datetime'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
customClass?: string
|
customClass?: string
|
||||||
// 选中项,当 type 为 time 时,类型为字符串,否则为 Date
|
// 选中项,当 type 为 time 时,类型为字符串,否则为 Date
|
||||||
modelValue: string | number | Date
|
modelValue: string | number | Date
|
||||||
// PickerView的Props 开始
|
// PickerView的Props 开始
|
||||||
// 是否展示picker(兼容支付宝和钉钉)
|
|
||||||
showPicker: boolean
|
|
||||||
// 加载中
|
// 加载中
|
||||||
loading: boolean
|
loading: boolean
|
||||||
loadingColor: string
|
loadingColor: string
|
||||||
@ -106,7 +101,6 @@ interface Props {
|
|||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
customClass: '',
|
customClass: '',
|
||||||
// PickerView的Props 开始
|
// PickerView的Props 开始
|
||||||
showPicker: true,
|
|
||||||
// 加载中
|
// 加载中
|
||||||
loading: false,
|
loading: false,
|
||||||
loadingColor: '#4D80F0',
|
loadingColor: '#4D80F0',
|
||||||
@ -131,7 +125,7 @@ const datePickerview = ref()
|
|||||||
// 内部保持时间戳的
|
// 内部保持时间戳的
|
||||||
const innerValue = ref<null | number>(null)
|
const innerValue = ref<null | number>(null)
|
||||||
// 传递给pickerView的columns的数据
|
// 传递给pickerView的columns的数据
|
||||||
const columns = ref<Array<string | string[]>>([])
|
const columns = ref<Array<string | number>>([])
|
||||||
// 传递给pickerView的value的数据
|
// 传递给pickerView的value的数据
|
||||||
const pickerValue = ref<string | number | boolean | Array<string | number | boolean>>([])
|
const pickerValue = ref<string | number | boolean | Array<string | number | boolean>>([])
|
||||||
// 自定义组件是否已经调用created hook
|
// 自定义组件是否已经调用created hook
|
||||||
@ -432,29 +426,6 @@ function getBoundary(type, innerValue) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 根据传入的值和类型,获取当前的选项数组,便于传入 pickerView
|
|
||||||
* @param value
|
|
||||||
* @param type picker类型
|
|
||||||
* @return {Array} pickerValue
|
|
||||||
*/
|
|
||||||
function getPickerValue(value, type) {
|
|
||||||
const values: number[] = []
|
|
||||||
const date = new Date(value)
|
|
||||||
if (type === 'time') {
|
|
||||||
const pair = value.split(':')
|
|
||||||
values.push(parseInt(pair[0]), parseInt(pair[1]))
|
|
||||||
} else {
|
|
||||||
values.push(date.getFullYear(), date.getMonth() + 1)
|
|
||||||
if (type === 'date') {
|
|
||||||
values.push(date.getDate())
|
|
||||||
} else if (type === 'datetime') {
|
|
||||||
values.push(date.getDate(), date.getHours(), date.getMinutes())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return values
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 根据传入的value以及type,初始化innerValue,期间会使用format格式化数据
|
* @description 根据传入的value以及type,初始化innerValue,期间会使用format格式化数据
|
||||||
* @param value
|
* @param value
|
||||||
@ -571,7 +542,7 @@ function onPickEnd() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSelects() {
|
function getSelects() {
|
||||||
return datePickerview.value.getSelects()
|
return datePickerview.value && datePickerview.value.getSelects ? datePickerview.value.getSelects() : undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
|
|||||||
@ -33,14 +33,11 @@
|
|||||||
<wd-popup
|
<wd-popup
|
||||||
v-model="popupShow"
|
v-model="popupShow"
|
||||||
position="bottom"
|
position="bottom"
|
||||||
:lazyRender="false"
|
:hide-when-close="false"
|
||||||
:hide-when-close="true"
|
|
||||||
:close-on-click-modal="closeOnClickModal"
|
:close-on-click-modal="closeOnClickModal"
|
||||||
:safe-area-inset-bottom="safeAreaInsetBottom"
|
:safe-area-inset-bottom="safeAreaInsetBottom"
|
||||||
:z-index="zIndex"
|
:z-index="zIndex"
|
||||||
@close="onCancel"
|
@close="onCancel"
|
||||||
@enter="setShowPicker(true)"
|
|
||||||
@leave="setShowPicker(false)"
|
|
||||||
custom-class="wd-picker__popup"
|
custom-class="wd-picker__popup"
|
||||||
>
|
>
|
||||||
<!--toolBar-->
|
<!--toolBar-->
|
||||||
@ -89,7 +86,6 @@
|
|||||||
:max-minute="maxMinute"
|
:max-minute="maxMinute"
|
||||||
:min-minute="minMinute"
|
:min-minute="minMinute"
|
||||||
:start-symbol="true"
|
:start-symbol="true"
|
||||||
:show-picker="showPicker"
|
|
||||||
@change="onChangeStart"
|
@change="onChangeStart"
|
||||||
@pickstart="onPickStart"
|
@pickstart="onPickStart"
|
||||||
@pickend="onPickEnd"
|
@pickend="onPickEnd"
|
||||||
@ -116,7 +112,6 @@
|
|||||||
:max-minute="maxMinute"
|
:max-minute="maxMinute"
|
||||||
:min-minute="minMinute"
|
:min-minute="minMinute"
|
||||||
:start-symbol="false"
|
:start-symbol="false"
|
||||||
:show-picker="showPicker"
|
|
||||||
@change="onChangeEnd"
|
@change="onChangeEnd"
|
||||||
@pickstart="onPickStart"
|
@pickstart="onPickStart"
|
||||||
@pickend="onPickEnd"
|
@pickend="onPickEnd"
|
||||||
@ -129,7 +124,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-datetime-picker',
|
name: 'wd-datetime-picker',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
@ -140,14 +134,14 @@ export default {
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getCurrentInstance, onBeforeMount, onMounted, ref, watch, nextTick } from 'vue'
|
import { getCurrentInstance, onBeforeMount, onMounted, ref, watch, nextTick } from 'vue'
|
||||||
import { debounce, deepClone, getType, isArray, isDef, isEqual, padZero } from '../common/util'
|
import { deepClone, getType, isArray, isDef, isEqual, padZero } from '../common/util'
|
||||||
import { useCell } from '../mixins/useCell'
|
import { useCell } from '../mixins/useCell'
|
||||||
type DateTimeType = 'date' | 'year-month' | 'time' | 'datetime'
|
import { DateTimeType, getPickerValue } from '../wd-datetime-picker-view/type'
|
||||||
interface Props {
|
interface Props {
|
||||||
customClass?: string
|
customClass: string
|
||||||
customViewClass?: string
|
customViewClass: string
|
||||||
customLabelClass?: string
|
customLabelClass: string
|
||||||
customValueClass?: string
|
customValueClass: string
|
||||||
// 选择器左侧文案
|
// 选择器左侧文案
|
||||||
label?: string
|
label?: string
|
||||||
// 选择器占位符
|
// 选择器占位符
|
||||||
@ -220,7 +214,7 @@ interface Props {
|
|||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
customClass: '',
|
customClass: '',
|
||||||
customViewClass: '',
|
customViewClass: '',
|
||||||
customLabelVlass: '',
|
customLabelClass: '',
|
||||||
customValueClass: '',
|
customValueClass: '',
|
||||||
// 选择器占位符
|
// 选择器占位符
|
||||||
placeholder: '请选择',
|
placeholder: '请选择',
|
||||||
@ -273,7 +267,6 @@ const datetimePickerView1 = ref()
|
|||||||
|
|
||||||
const showValue = ref<string | Date | Array<string | Date>>([])
|
const showValue = ref<string | Date | Array<string | Date>>([])
|
||||||
const popupShow = ref<boolean>(false)
|
const popupShow = ref<boolean>(false)
|
||||||
const showPicker = ref<boolean>(false)
|
|
||||||
const showStart = ref<boolean>(true)
|
const showStart = ref<boolean>(true)
|
||||||
const region = ref<boolean>(false)
|
const region = ref<boolean>(false)
|
||||||
const showTabLabel = ref<string[]>([])
|
const showTabLabel = ref<string[]>([])
|
||||||
@ -288,10 +281,6 @@ const { proxy } = getCurrentInstance() as any
|
|||||||
|
|
||||||
const cell = useCell()
|
const cell = useCell()
|
||||||
|
|
||||||
const setShowPicker = debounce(function (show: boolean) {
|
|
||||||
showPicker.value = show
|
|
||||||
}, 100)
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.modelValue,
|
() => props.modelValue,
|
||||||
(val, oldVal) => {
|
(val, oldVal) => {
|
||||||
@ -377,7 +366,7 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
() => props.defaultValue,
|
() => props.defaultValue,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (getType(val) === 'array') {
|
if (getType(val) === 'array' || region.value) {
|
||||||
innerValue.value = deepClone(getDefaultInnerValue(true))
|
innerValue.value = deepClone(getDefaultInnerValue(true))
|
||||||
endInnerValue.value = deepClone(getDefaultInnerValue(true, true))
|
endInnerValue.value = deepClone(getDefaultInnerValue(true, true))
|
||||||
} else {
|
} else {
|
||||||
@ -428,14 +417,11 @@ const customColumnFormatter = (picker) => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
console.log(mapColumns(columns))
|
|
||||||
|
|
||||||
return mapColumns(columns)
|
return mapColumns(columns)
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
const { modelValue: value } = props
|
const { modelValue: value } = props
|
||||||
|
|
||||||
if (getType(value) === 'array') {
|
if (getType(value) === 'array') {
|
||||||
region.value = true
|
region.value = true
|
||||||
innerValue.value = deepClone(getDefaultInnerValue(true))
|
innerValue.value = deepClone(getDefaultInnerValue(true))
|
||||||
@ -446,9 +432,28 @@ onBeforeMount(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setShowValue()
|
setShowValue(false, false, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据传入的picker,picker组件获取当前cell展示值。
|
||||||
|
*/
|
||||||
|
function getSelects(picker: 'before' | 'after') {
|
||||||
|
let value = picker === 'before' ? innerValue.value : endInnerValue.value
|
||||||
|
let selected: number[] = []
|
||||||
|
if (value) {
|
||||||
|
selected = getPickerValue(value, props.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
let selects = selected.map((value) => {
|
||||||
|
return {
|
||||||
|
[props.labelKey]: padZero(value),
|
||||||
|
[props.valueKey]: value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return selects
|
||||||
|
}
|
||||||
|
|
||||||
function noop() {}
|
function noop() {}
|
||||||
|
|
||||||
function getDefaultInnerValue(isRegion?: boolean, isEnd?: boolean) {
|
function getDefaultInnerValue(isRegion?: boolean, isEnd?: boolean) {
|
||||||
@ -491,7 +496,7 @@ function showPopup() {
|
|||||||
popupShow.value = true
|
popupShow.value = true
|
||||||
innerValue.value = deepClone(getDefaultInnerValue())
|
innerValue.value = deepClone(getDefaultInnerValue())
|
||||||
}
|
}
|
||||||
setShowValue(true, false)
|
setShowValue(true, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -531,6 +536,7 @@ function onChangeStart({ value }) {
|
|||||||
*/
|
*/
|
||||||
function onChangeEnd({ value }) {
|
function onChangeEnd({ value }) {
|
||||||
endInnerValue.value = deepClone(value)
|
endInnerValue.value = deepClone(value)
|
||||||
|
|
||||||
showTabLabel.value = [deepClone(showTabLabel.value[0]), setTabLabel(1)]
|
showTabLabel.value = [deepClone(showTabLabel.value[0]), setTabLabel(1)]
|
||||||
// emit('update:modelValue', [innerValue.value, value])
|
// emit('update:modelValue', [innerValue.value, value])
|
||||||
emit('change', {
|
emit('change', {
|
||||||
@ -620,9 +626,13 @@ function setTabLabel(index: number = 0) {
|
|||||||
if (region.value) {
|
if (region.value) {
|
||||||
let items = []
|
let items = []
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
items = (datetimePickerView.value && datetimePickerView.value.getSelects()) || []
|
items =
|
||||||
|
(datetimePickerView.value && datetimePickerView.value.getSelects && datetimePickerView.value.getSelects()) ||
|
||||||
|
(innerValue.value && getSelects('before'))
|
||||||
} else {
|
} else {
|
||||||
items = (datetimePickerView1.value && datetimePickerView1.value.getSelects()) || []
|
items =
|
||||||
|
(datetimePickerView1.value && datetimePickerView1.value.getSelects && datetimePickerView1.value.getSelects()) ||
|
||||||
|
(endInnerValue.value && getSelects('after'))
|
||||||
}
|
}
|
||||||
return defaultDisplayFormat(items, true)
|
return defaultDisplayFormat(items, true)
|
||||||
}
|
}
|
||||||
@ -633,16 +643,25 @@ function setTabLabel(index: number = 0) {
|
|||||||
* @param {Boolean} tab 是否修改tab展示值(尽在区域选择情况下生效)
|
* @param {Boolean} tab 是否修改tab展示值(尽在区域选择情况下生效)
|
||||||
* @param {Boolean} isConfirm 是否提交当前修改
|
* @param {Boolean} isConfirm 是否提交当前修改
|
||||||
*/
|
*/
|
||||||
function setShowValue(tab = false, isConfirm = false) {
|
function setShowValue(tab: boolean = false, isConfirm: boolean = false, beforeMount: boolean = false) {
|
||||||
if (region.value) {
|
if (region.value) {
|
||||||
const items = (datetimePickerView.value && datetimePickerView.value.getSelects()) || []
|
const items = beforeMount
|
||||||
const endItems = (datetimePickerView1.value && datetimePickerView1.value.getSelects()) || []
|
? (innerValue.value && getSelects('before')) || []
|
||||||
|
: (datetimePickerView.value && datetimePickerView.value.getSelects && datetimePickerView.value.getSelects()) || []
|
||||||
|
|
||||||
|
const endItems = beforeMount
|
||||||
|
? (endInnerValue.value && getSelects('after')) || []
|
||||||
|
: (datetimePickerView1.value && datetimePickerView1.value.getSelects && datetimePickerView1.value.getSelects()) || []
|
||||||
|
|
||||||
showValue.value = tab
|
showValue.value = tab
|
||||||
? showValue.value
|
? showValue.value
|
||||||
: [props.modelValue[0] || isConfirm ? defaultDisplayFormat(items) : '', props.modelValue[1] || isConfirm ? defaultDisplayFormat(endItems) : '']
|
: [props.modelValue[0] || isConfirm ? defaultDisplayFormat(items) : '', props.modelValue[1] || isConfirm ? defaultDisplayFormat(endItems) : '']
|
||||||
showTabLabel.value = [defaultDisplayFormat(items, true), defaultDisplayFormat(endItems, true)]
|
showTabLabel.value = [defaultDisplayFormat(items, true), defaultDisplayFormat(endItems, true)]
|
||||||
} else {
|
} else {
|
||||||
const items = (datetimePickerView.value && datetimePickerView.value.getSelects()) || []
|
const items = beforeMount
|
||||||
|
? (innerValue.value && getSelects('before')) || []
|
||||||
|
: (datetimePickerView.value && datetimePickerView.value.getSelects && datetimePickerView.value.getSelects()) || []
|
||||||
|
|
||||||
showValue.value = deepClone(props.modelValue || isConfirm ? defaultDisplayFormat(items) : '')
|
showValue.value = deepClone(props.modelValue || isConfirm ? defaultDisplayFormat(items) : '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<view :class="`wd-drop-menu ${customClass}`" @click.stop="noop">
|
<view :style="customStyle" :class="`wd-drop-menu ${customClass}`" @click.stop="noop">
|
||||||
<view class="wd-drop-menu__list">
|
<view class="wd-drop-menu__list">
|
||||||
<view
|
<view
|
||||||
v-for="(item, index) in titleList"
|
v-for="(item, index) in titleList"
|
||||||
@ -34,7 +34,8 @@ import { getRect } from '../common/util'
|
|||||||
|
|
||||||
type DropDirction = 'up' | 'down'
|
type DropDirction = 'up' | 'down'
|
||||||
interface Props {
|
interface Props {
|
||||||
customClass?: string
|
customClass: string
|
||||||
|
customStyle: string
|
||||||
zIndex: number
|
zIndex: number
|
||||||
direction: DropDirction
|
direction: DropDirction
|
||||||
modal: boolean
|
modal: boolean
|
||||||
@ -44,6 +45,7 @@ interface Props {
|
|||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
customClass: '',
|
customClass: '',
|
||||||
|
customStyle: '',
|
||||||
zIndex: 12,
|
zIndex: 12,
|
||||||
direction: 'down',
|
direction: 'down',
|
||||||
modal: true,
|
modal: true,
|
||||||
@ -126,7 +128,7 @@ function fold(child?: any) {
|
|||||||
const { top, bottom } = rect
|
const { top, bottom } = rect
|
||||||
|
|
||||||
if (props.direction === 'down') {
|
if (props.direction === 'down') {
|
||||||
offset.value = bottom + 44
|
offset.value = bottom
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
// H5端,导航栏为普通元素,需要将组件移动到导航栏的下边沿
|
// H5端,导航栏为普通元素,需要将组件移动到导航栏的下边沿
|
||||||
// H5的导航栏高度为44px
|
// H5的导航栏高度为44px
|
||||||
|
|||||||
@ -26,7 +26,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-input-number',
|
name: 'wd-input-number',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
|
|||||||
@ -127,7 +127,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-input',
|
name: 'wd-input',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
|
|||||||
@ -21,6 +21,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.wd-message-box){
|
||||||
|
border-radius: $-message-box-radius;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
@include bdeep(message-box) {
|
@include bdeep(message-box) {
|
||||||
border-radius: $-message-box-radius;
|
border-radius: $-message-box-radius;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@ -1,49 +1,51 @@
|
|||||||
<template>
|
<template>
|
||||||
<wd-popup
|
<view>
|
||||||
transition="zoom-in"
|
<wd-popup
|
||||||
v-model="show"
|
transition="zoom-in"
|
||||||
:close-on-click-modal="closeOnClickModal"
|
v-model="show"
|
||||||
:lazy-render="lazyRender"
|
:close-on-click-modal="closeOnClickModal"
|
||||||
custom-class="wd-message-box"
|
:lazy-render="lazyRender"
|
||||||
@clickmodal="toggleModal('modal')"
|
custom-class="wd-message-box"
|
||||||
:z-index="zIndex"
|
@clickmodal="toggleModal('modal')"
|
||||||
:duration="200"
|
:z-index="zIndex"
|
||||||
>
|
:duration="200"
|
||||||
<view :class="rootClass">
|
>
|
||||||
<!--内容部分-->
|
<view :class="rootClass">
|
||||||
<view :class="bodyClass">
|
<!--内容部分-->
|
||||||
<!--公共title-->
|
<view :class="bodyClass">
|
||||||
<view v-if="title" class="wd-message-box__title">
|
<!--公共title-->
|
||||||
{{ title }}
|
<view v-if="title" class="wd-message-box__title">
|
||||||
|
{{ title }}
|
||||||
|
</view>
|
||||||
|
<!--其它类型-->
|
||||||
|
<view class="wd-message-box__content">
|
||||||
|
<!--prompt类型-->
|
||||||
|
<block v-if="type === 'prompt'">
|
||||||
|
<!--输入框-->
|
||||||
|
<wd-input v-model="inputValue" :type="inputType" size="large" :placeholder="inputPlaceholder || '请输入'" @input="inputValChange" />
|
||||||
|
<!--错误提示-->
|
||||||
|
<view v-if="showErr" class="wd-message-box__input-error">
|
||||||
|
{{ inputError || '输入的数据不合法' }}
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<!--使用插槽-->
|
||||||
|
<slot v-if="useSlot"></slot>
|
||||||
|
<!--使用文本-->
|
||||||
|
<block v-else>{{ msg }}</block>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!--其它类型-->
|
<!--action按钮组合-->
|
||||||
<view class="wd-message-box__content">
|
<view :class="`wd-message-box__actions ${showCancelButton ? 'wd-message-box__flex' : 'wd-message-box__block'}`">
|
||||||
<!--prompt类型-->
|
<wd-button type="info" block v-if="showCancelButton" custom-style="margin-right: 16px;" @click="toggleModal('cancel')">
|
||||||
<block v-if="type === 'prompt'">
|
{{ cancelButtonText || '取消' }}
|
||||||
<!--输入框-->
|
</wd-button>
|
||||||
<wd-input v-model="inputValue" :type="inputType" size="large" :placeholder="inputPlaceholder || '请输入'" @input="inputValChange" />
|
<wd-button block @click="toggleModal('confirm')">
|
||||||
<!--错误提示-->
|
{{ confirmButtonText || '确定' }}
|
||||||
<view v-if="showErr" class="wd-message-box__input-error">
|
</wd-button>
|
||||||
{{ inputError || '输入的数据不合法' }}
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
<!--使用插槽-->
|
|
||||||
<slot v-if="useSlot"></slot>
|
|
||||||
<!--使用文本-->
|
|
||||||
<block v-else>{{ msg }}</block>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!--action按钮组合-->
|
</wd-popup>
|
||||||
<view :class="`wd-message-box__actions ${showCancelButton ? 'wd-message-box__flex' : 'wd-message-box__block'}`">
|
</view>
|
||||||
<wd-button type="info" block v-if="showCancelButton" custom-style="margin-right: 16px;" @click="toggleModal('cancel')">
|
|
||||||
{{ cancelButtonText || '取消' }}
|
|
||||||
</wd-button>
|
|
||||||
<wd-button block @click="toggleModal('confirm')">
|
|
||||||
{{ confirmButtonText || '确定' }}
|
|
||||||
</wd-button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</wd-popup>
|
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* @Author: weisheng
|
||||||
|
* @Date: 2023-08-21 13:03:42
|
||||||
|
* @LastEditTime: 2023-08-21 17:24:57
|
||||||
|
* @LastEditors: weisheng
|
||||||
|
* @Description:
|
||||||
|
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-picker-view\type.ts
|
||||||
|
* 记得注释
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { getType } from '../common/util'
|
||||||
|
|
||||||
|
export type ColumnItem = {
|
||||||
|
value?: string | number | boolean
|
||||||
|
label?: string
|
||||||
|
disabled?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 为props的value为array类型时提供format
|
||||||
|
* @param {Array<String|Number|Object>} array 列数组
|
||||||
|
* @param {string} valueKey valueKey
|
||||||
|
* @param {string} labelKey labelKey
|
||||||
|
*/
|
||||||
|
export function formatArray(array: Array<string | number | ColumnItem | Array<string | number | ColumnItem>>, valueKey: string, labelKey: string) {
|
||||||
|
let tempArray: Array<string | number | ColumnItem | Array<string | number | ColumnItem>> = array instanceof Array ? array : [array]
|
||||||
|
// 检测第一层的type
|
||||||
|
const firstLevelTypeList = new Set(array.map(getType))
|
||||||
|
/**
|
||||||
|
* 存在三种类型的合法数据
|
||||||
|
* 1.数组是一维元素,所有元素都是原始值
|
||||||
|
* 2.数组是一维元素,所有元素都是object
|
||||||
|
* 3.数组是二维元素,二维元素可以是任意内容
|
||||||
|
*/
|
||||||
|
if (firstLevelTypeList.size !== 1 && firstLevelTypeList.has('object')) {
|
||||||
|
// 原始值和引用类型不用混用
|
||||||
|
throw Error('The columns are correct')
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 数组的所有一维子元素都不是array,说明是它是一个一维数组
|
||||||
|
* 所以需要把一维的转成二维,这样方便统一处理
|
||||||
|
*/
|
||||||
|
if (!(array[0] instanceof Array)) {
|
||||||
|
tempArray = [tempArray as Array<string | number | ColumnItem>]
|
||||||
|
}
|
||||||
|
// 经过上述处理,都已经变成了二维数组,再把每一项二维元素包装成object
|
||||||
|
const result: Array<Array<ColumnItem>> = (tempArray as Array<Array<string | number | ColumnItem>>).map((col) => {
|
||||||
|
return col.map((row) => {
|
||||||
|
const isObj = getType(row)
|
||||||
|
/* 针对原始值,包装成{valueKey,labelKey} */
|
||||||
|
if (isObj !== 'object') {
|
||||||
|
return {
|
||||||
|
[valueKey]: row,
|
||||||
|
[labelKey]: row
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 针对已经是object的,修补成{valueKey,labelKey}
|
||||||
|
* 如果没有labelKey,用valueKey代替
|
||||||
|
* 如果没有valueKey,用labelKey代替
|
||||||
|
* valueKey,labelKey都没有,直接抛错
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line no-prototype-builtins
|
||||||
|
if (!row.hasOwnProperty(valueKey) && !row.hasOwnProperty(labelKey)) {
|
||||||
|
// eslint-disable-next-line prettier/prettier
|
||||||
|
throw Error('Can\'t find valueKey and labelKey in columns')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-prototype-builtins
|
||||||
|
if (!row.hasOwnProperty(labelKey)) {
|
||||||
|
row[labelKey] = row[valueKey]
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-prototype-builtins
|
||||||
|
if (!row.hasOwnProperty(valueKey)) {
|
||||||
|
row[valueKey] = row[labelKey]
|
||||||
|
}
|
||||||
|
return row as ColumnItem
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
@ -5,7 +5,6 @@
|
|||||||
</view>
|
</view>
|
||||||
<view :style="`height: ${columnsHeight - 20}px;`">
|
<view :style="`height: ${columnsHeight - 20}px;`">
|
||||||
<picker-view
|
<picker-view
|
||||||
v-if="showPicker"
|
|
||||||
mask-class="wd-picker-view__mask"
|
mask-class="wd-picker-view__mask"
|
||||||
indicator-class="wd-picker-view__roller"
|
indicator-class="wd-picker-view__roller"
|
||||||
:indicator-style="`height: ${itemHeight}px;`"
|
:indicator-style="`height: ${itemHeight}px;`"
|
||||||
@ -45,17 +44,10 @@ export default {
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getCurrentInstance, ref, watch, nextTick } from 'vue'
|
import { getCurrentInstance, ref, watch, nextTick } from 'vue'
|
||||||
import { deepClone, getType, isEqual, range } from '../common/util'
|
import { deepClone, getType, isEqual, range } from '../common/util'
|
||||||
|
import { ColumnItem, formatArray } from './type'
|
||||||
type ColumnItem = {
|
|
||||||
value?: string | number | boolean
|
|
||||||
label: string
|
|
||||||
disabled?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
customClass?: string
|
customClass?: string
|
||||||
// 是否展示picker(兼容支付宝和钉钉)
|
|
||||||
showPicker: boolean
|
|
||||||
// 加载中
|
// 加载中
|
||||||
loading: boolean
|
loading: boolean
|
||||||
loadingColor: string
|
loadingColor: string
|
||||||
@ -68,7 +60,7 @@ interface Props {
|
|||||||
// 初始值
|
// 初始值
|
||||||
modelValue: string | number | boolean | Array<string | number | boolean>
|
modelValue: string | number | boolean | Array<string | number | boolean>
|
||||||
// 选择器数据
|
// 选择器数据
|
||||||
columns: Array<string | string[] | ColumnItem>
|
columns: Array<string | number | ColumnItem | Array<string | number | ColumnItem>>
|
||||||
// 多级联动
|
// 多级联动
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
columnChange?: Function
|
columnChange?: Function
|
||||||
@ -77,7 +69,6 @@ interface Props {
|
|||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
customClass: '',
|
customClass: '',
|
||||||
loading: false,
|
loading: false,
|
||||||
showPicker: true,
|
|
||||||
loadingColor: '#4D80F0',
|
loadingColor: '#4D80F0',
|
||||||
columnsHeight: 217,
|
columnsHeight: 217,
|
||||||
valueKey: 'value',
|
valueKey: 'value',
|
||||||
@ -86,7 +77,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 格式化之后,用于render 列表的数据
|
// 格式化之后,用于render 列表的数据
|
||||||
const formatColumns = ref<Array<Record<string, any>[]>>([])
|
const formatColumns = ref<Array<Array<Record<string, any>>>>([])
|
||||||
const itemHeight = ref<number>(35)
|
const itemHeight = ref<number>(35)
|
||||||
const selectedIndex = ref<Array<number>>([]) // 格式化之后,每列选中的下标集合
|
const selectedIndex = ref<Array<number>>([]) // 格式化之后,每列选中的下标集合
|
||||||
const preSelectedIndex = ref<Array<number>>([])
|
const preSelectedIndex = ref<Array<number>>([])
|
||||||
@ -108,7 +99,7 @@ watch(
|
|||||||
() => props.columns,
|
() => props.columns,
|
||||||
(newValue) => {
|
(newValue) => {
|
||||||
// props初始化的时候格式化formatColumns交给value的observer来做
|
// props初始化的时候格式化formatColumns交给value的observer来做
|
||||||
formatColumns.value = formatArray(newValue)
|
formatColumns.value = formatArray(newValue, props.valueKey, props.labelKey)
|
||||||
/**
|
/**
|
||||||
* 每次改变都要重置选中项
|
* 每次改变都要重置选中项
|
||||||
* 1.选中每列的第一个
|
* 1.选中每列的第一个
|
||||||
@ -172,7 +163,7 @@ function selectWithValue(value) {
|
|||||||
if (type.indexOf(valueType) === -1) throw Error(`value must be one of ${type.toString()}`)
|
if (type.indexOf(valueType) === -1) throw Error(`value must be one of ${type.toString()}`)
|
||||||
// 在props初始化的时候有可能会调用此函数,此时需要保证formatColumns已经被设置,关于此问题更多详情参考/ISSUE.md。
|
// 在props初始化的时候有可能会调用此函数,此时需要保证formatColumns已经被设置,关于此问题更多详情参考/ISSUE.md。
|
||||||
if (formatColumns.value.length === 0) {
|
if (formatColumns.value.length === 0) {
|
||||||
formatColumns.value = formatArray(props.columns)
|
formatColumns.value = formatArray(props.columns, props.valueKey, props.labelKey)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 1.单key转为Array<key>
|
* 1.单key转为Array<key>
|
||||||
@ -234,67 +225,6 @@ function selectWithIndex(columnIndex, rowIndex) {
|
|||||||
return selectedIndex.value
|
return selectedIndex.value
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 为props的value为array类型时提供format
|
|
||||||
* @param {Array<String|Number|Boolean|Object>} array
|
|
||||||
*/
|
|
||||||
function formatArray(array) {
|
|
||||||
array = array instanceof Array ? array : [array]
|
|
||||||
// 检测第一层的type
|
|
||||||
const firstLevelTypeList = new Set(array.map(getType))
|
|
||||||
/**
|
|
||||||
* 存在三种类型的合法数据
|
|
||||||
* 1.数组是一维元素,所有元素都是原始值
|
|
||||||
* 2.数组是一维元素,所有元素都是object
|
|
||||||
* 3.数组是二维元素,二维元素可以是任意内容
|
|
||||||
*/
|
|
||||||
if (firstLevelTypeList.size !== 1 && firstLevelTypeList.has('object')) {
|
|
||||||
// 原始值和引用类型不用混用
|
|
||||||
throw Error('The columns are correct')
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 数组的所有一维子元素都不是array,说明是它是一个一维数组
|
|
||||||
* 所以需要把一维的转成二维,这样方便统一处理
|
|
||||||
*/
|
|
||||||
if (!(array[0] instanceof Array)) {
|
|
||||||
array = [array]
|
|
||||||
}
|
|
||||||
// 经过上述处理,都已经变成了二维数组,再把每一项二维元素包装成object
|
|
||||||
return array.map((col) =>
|
|
||||||
col.map((row) => {
|
|
||||||
const isObj = getType(row)
|
|
||||||
const { valueKey, labelKey } = props
|
|
||||||
/* 针对原始值,包装成{valueKey,labelKey} */
|
|
||||||
if (isObj !== 'object') {
|
|
||||||
return {
|
|
||||||
[valueKey]: row,
|
|
||||||
[labelKey]: row
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 针对已经是object的,修补成{valueKey,labelKey}
|
|
||||||
* 如果没有labelKey,用valueKey代替
|
|
||||||
* 如果没有valueKey,用labelKey代替
|
|
||||||
* valueKey,labelKey都没有,直接抛错
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line no-prototype-builtins
|
|
||||||
if (!row.hasOwnProperty(valueKey) && !row.hasOwnProperty(labelKey)) {
|
|
||||||
// eslint-disable-next-line prettier/prettier
|
|
||||||
throw Error('Can\'t find valueKey and labelKey in columns')
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line no-prototype-builtins
|
|
||||||
if (!row.hasOwnProperty(labelKey)) {
|
|
||||||
row[labelKey] = row[valueKey]
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line no-prototype-builtins
|
|
||||||
if (!row.hasOwnProperty(valueKey)) {
|
|
||||||
row[valueKey] = row[labelKey]
|
|
||||||
}
|
|
||||||
return row
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 滚动选中时更新选中的索引、触发change事件
|
* @description 滚动选中时更新选中的索引、触发change事件
|
||||||
* @return {Number|Array<Number>}选中项的下标或者集合
|
* @return {Number|Array<Number>}选中项的下标或者集合
|
||||||
@ -389,7 +319,6 @@ function getSelects() {
|
|||||||
if (selects.length === 1) {
|
if (selects.length === 1) {
|
||||||
return selects[0]
|
return selects[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
return selects
|
return selects
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,7 +378,7 @@ function setColumnData(columnIndex, data, jumpTo = 0) {
|
|||||||
selectedIndex.value = selectWithIndex(columnIndex, jumpTo)
|
selectedIndex.value = selectWithIndex(columnIndex, jumpTo)
|
||||||
// 经过formatArray处理的数据会变成二维数组,一定要拍成一维的。
|
// 经过formatArray处理的数据会变成二维数组,一定要拍成一维的。
|
||||||
// ps 小程序基础库v2.9.3才可以用flat
|
// ps 小程序基础库v2.9.3才可以用flat
|
||||||
formatColumns.value[columnIndex] = formatArray(data).reduce((acc, val) => acc.concat(val), [])
|
formatColumns.value[columnIndex] = formatArray(data, props.valueKey, props.labelKey).reduce((acc, val) => acc.concat(val), [])
|
||||||
}
|
}
|
||||||
|
|
||||||
function getColumnsData() {
|
function getColumnsData() {
|
||||||
|
|||||||
@ -69,7 +69,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-picker',
|
name: 'wd-picker',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
@ -80,8 +79,9 @@ export default {
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getCurrentInstance, onBeforeMount, ref, watch, computed, onMounted } from 'vue'
|
import { getCurrentInstance, onBeforeMount, ref, watch, computed, onMounted } from 'vue'
|
||||||
import { deepClone, defaultDisplayFormat, getType } from '../common/util'
|
import { deepClone, defaultDisplayFormat, getType, isArray } from '../common/util'
|
||||||
import { useCell } from '../mixins/useCell'
|
import { useCell } from '../mixins/useCell'
|
||||||
|
import { ColumnItem, formatArray } from '../wd-picker-view/type'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
customClass?: string
|
customClass?: string
|
||||||
@ -126,9 +126,9 @@ interface Props {
|
|||||||
// 选项对象中,展示的文本对应的 key
|
// 选项对象中,展示的文本对应的 key
|
||||||
labelKey: string
|
labelKey: string
|
||||||
// 初始值
|
// 初始值
|
||||||
modelValue: string | number | boolean | Array<string | number | boolean>
|
modelValue: string | number | Array<string | number>
|
||||||
// 选择器数据
|
// 选择器数据
|
||||||
columns: Array<string | string[]>
|
columns: Array<string | number | ColumnItem | Array<string | number | ColumnItem>>
|
||||||
// 多级联动
|
// 多级联动
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
columnChange?: Function
|
columnChange?: Function
|
||||||
@ -182,8 +182,8 @@ const popupShow = ref<boolean>(false)
|
|||||||
// 选定后展示的选中项
|
// 选定后展示的选中项
|
||||||
const showValue = ref<string>('')
|
const showValue = ref<string>('')
|
||||||
const pickerValue = ref<string | number | boolean | (string | number | boolean)[]>('')
|
const pickerValue = ref<string | number | boolean | (string | number | boolean)[]>('')
|
||||||
const displayColumns = ref<Array<string | string[]>>([]) // 传入 pickerView 的columns
|
const displayColumns = ref<Array<string | number | ColumnItem | Array<string | number | ColumnItem>>>([]) // 传入 pickerView 的columns
|
||||||
const resetColumns = ref<Array<string | string[]>>([]) // 保存之前的 columns,当取消时,将数据源回滚,避免多级联动数据源不正确的情况
|
const resetColumns = ref<Array<string | number | ColumnItem | Array<string | number | ColumnItem>>>([]) // 保存之前的 columns,当取消时,将数据源回滚,避免多级联动数据源不正确的情况
|
||||||
const isPicking = ref<boolean>(false) // 判断pickview是否还在滑动中
|
const isPicking = ref<boolean>(false) // 判断pickview是否还在滑动中
|
||||||
const hasConfirmed = ref<boolean>(false) // 判断用户是否点击了确认按钮
|
const hasConfirmed = ref<boolean>(false) // 判断用户是否点击了确认按钮
|
||||||
|
|
||||||
@ -264,6 +264,7 @@ const { proxy } = getCurrentInstance() as any
|
|||||||
const emit = defineEmits(['confirm', 'open', 'cancel', 'update:modelValue'])
|
const emit = defineEmits(['confirm', 'open', 'cancel', 'update:modelValue'])
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
props.modelValue && setShowValue(getSelects(props.modelValue))
|
||||||
if (props.modelValue && pickerViewWd.value && pickerViewWd.value.getSelects) {
|
if (props.modelValue && pickerViewWd.value && pickerViewWd.value.getSelects) {
|
||||||
setShowValue(pickerViewWd.value!.getSelects())
|
setShowValue(pickerViewWd.value!.getSelects())
|
||||||
}
|
}
|
||||||
@ -274,6 +275,51 @@ onBeforeMount(() => {
|
|||||||
resetColumns.value = deepClone(props.columns)
|
resetColumns.value = deepClone(props.columns)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据传入的value,picker组件获取当前cell展示值。
|
||||||
|
* @param {String|Number|Array<String|Number|Array<any>>}value
|
||||||
|
*/
|
||||||
|
function getSelects(value) {
|
||||||
|
const formatColumns = formatArray(props.columns, props.valueKey, props.labelKey)
|
||||||
|
if (props.columns.length === 0) return
|
||||||
|
|
||||||
|
// 使其默认选中首项
|
||||||
|
if (value === '' || value === null || value === undefined || (getType(value) === 'array' && value.length === 0)) {
|
||||||
|
value = formatColumns.map((col) => {
|
||||||
|
return col[0][props.valueKey]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const valueType = getType(value)
|
||||||
|
const type = ['string', 'number', 'boolean', 'array']
|
||||||
|
if (type.indexOf(valueType) === -1) return []
|
||||||
|
/**
|
||||||
|
* 1.单key转为Array<key>
|
||||||
|
* 2.根据formatColumns的长度截取Array<String>,保证下面的遍历不溢出
|
||||||
|
* 3.根据每列的key值找到选项中value为此key的下标并记录
|
||||||
|
*/
|
||||||
|
value = value instanceof Array ? value : [value]
|
||||||
|
value = value.slice(0, formatColumns.length)
|
||||||
|
|
||||||
|
if (value.length === 0) {
|
||||||
|
value = formatColumns.map(() => 0)
|
||||||
|
}
|
||||||
|
let selected: number[] = []
|
||||||
|
value.forEach((target, col) => {
|
||||||
|
let row = formatColumns[col].findIndex((row) => {
|
||||||
|
return row[props.valueKey].toString() === target.toString()
|
||||||
|
})
|
||||||
|
row = row === -1 ? 0 : row
|
||||||
|
selected.push(row)
|
||||||
|
})
|
||||||
|
|
||||||
|
const selects = selected.map((row, col) => formatColumns[col][row])
|
||||||
|
// 单列选择器,则返回单项
|
||||||
|
if (selects.length === 1) {
|
||||||
|
return selects[0]
|
||||||
|
}
|
||||||
|
return selects
|
||||||
|
}
|
||||||
|
|
||||||
// 对外暴露方法,打开弹框
|
// 对外暴露方法,打开弹框
|
||||||
function open() {
|
function open() {
|
||||||
showPopup()
|
showPopup()
|
||||||
|
|||||||
@ -38,16 +38,18 @@ interface Props {
|
|||||||
modal: boolean
|
modal: boolean
|
||||||
zIndex: number
|
zIndex: number
|
||||||
hideWhenClose: boolean
|
hideWhenClose: boolean
|
||||||
modalStyle?: string
|
modalStyle: string
|
||||||
safeAreaInsetBottom: boolean
|
safeAreaInsetBottom: boolean
|
||||||
modelValue: boolean
|
modelValue: boolean
|
||||||
customStyle?: string
|
customStyle: string
|
||||||
lazyRender: boolean
|
lazyRender: boolean
|
||||||
customClass?: string
|
customClass: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
customClass: '',
|
customClass: '',
|
||||||
|
customStyle: '',
|
||||||
|
modalStyle: '',
|
||||||
position: 'center',
|
position: 'center',
|
||||||
closeOnClickModal: true,
|
closeOnClickModal: true,
|
||||||
modal: true,
|
modal: true,
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-radio-group',
|
name: 'wd-radio-group',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
|
|||||||
@ -21,7 +21,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-rate',
|
name: 'wd-rate',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
|
|||||||
@ -94,6 +94,13 @@ onMounted(() => {
|
|||||||
width.value = lastWidth
|
width.value = lastWidth
|
||||||
// 监听滚动事件
|
// 监听滚动事件
|
||||||
onScrollHandler = () => {
|
onScrollHandler = () => {
|
||||||
|
const query = uni
|
||||||
|
.createSelectorQuery()
|
||||||
|
// #ifndef MP-ALIPAY
|
||||||
|
.in(proxy)
|
||||||
|
// #endif
|
||||||
|
.select('.wd-resize__container')
|
||||||
|
.boundingClientRect()
|
||||||
query.exec(([res]) => {
|
query.exec(([res]) => {
|
||||||
// 前两次滚动事件被触发,说明 created 的修改已渲染,通知用户代码当前容器大小
|
// 前两次滚动事件被触发,说明 created 的修改已渲染,通知用户代码当前容器大小
|
||||||
if (scrollEventCount.value++ === 0) {
|
if (scrollEventCount.value++ === 0) {
|
||||||
|
|||||||
@ -50,7 +50,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-search',
|
name: 'wd-search',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
|
|||||||
@ -88,7 +88,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-select-picker',
|
name: 'wd-select-picker',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
|
|||||||
@ -44,7 +44,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-slider',
|
name: 'wd-slider',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
|
|||||||
@ -67,7 +67,9 @@
|
|||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
|
||||||
@include when(active) {
|
@include when(active) {
|
||||||
:deep(.wd-sort-button__icon-up, .wd-sort-button__icon-down) {
|
|
||||||
|
:deep(.wd-sort-button__icon-up),
|
||||||
|
:deep(.wd-sort-button__icon-down) {
|
||||||
transform: scale(calc((10 / 14)));
|
transform: scale(calc((10 / 14)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,9 +3,9 @@
|
|||||||
<view
|
<view
|
||||||
:class="`wd-swipe-action ${customClass}`"
|
:class="`wd-swipe-action ${customClass}`"
|
||||||
@click.stop="onClick()"
|
@click.stop="onClick()"
|
||||||
@touchstart="startDrag"
|
|
||||||
@touchmove="stopPropagation ? nothing : ''"
|
@touchmove="stopPropagation ? nothing : ''"
|
||||||
@touchmove.capture="onDrag"
|
@touchstart="startDrag"
|
||||||
|
@touchmove.prevent="onDrag"
|
||||||
@touchend="endDrag"
|
@touchend="endDrag"
|
||||||
@touchcancel="endDrag"
|
@touchcancel="endDrag"
|
||||||
>
|
>
|
||||||
@ -43,7 +43,7 @@ import { getRect } from '../common/util'
|
|||||||
interface Props {
|
interface Props {
|
||||||
customClass?: string
|
customClass?: string
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
beforeClose: Function
|
beforeClose?: Function
|
||||||
disabled: boolean
|
disabled: boolean
|
||||||
modelValue: string
|
modelValue: string
|
||||||
}
|
}
|
||||||
@ -51,8 +51,7 @@ interface Props {
|
|||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
customStyle: '',
|
customStyle: '',
|
||||||
modelValue: 'close',
|
modelValue: 'close',
|
||||||
disabled: false,
|
disabled: false
|
||||||
beforeClose: (v) => v
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const wrapperStyle = ref<string>('')
|
const wrapperStyle = ref<string>('')
|
||||||
@ -280,7 +279,7 @@ function close(reason, position?: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (reason && position) {
|
if (reason && position) {
|
||||||
props.beforeClose(reason, position)
|
props.beforeClose && props.beforeClose(reason, position)
|
||||||
}
|
}
|
||||||
|
|
||||||
swipeMove(0)
|
swipeMove(0)
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-switch',
|
name: 'wd-switch',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
|
|||||||
@ -42,7 +42,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'wd-upload',
|
name: 'wd-upload',
|
||||||
behaviors: ['uni://form-field'],
|
|
||||||
options: {
|
options: {
|
||||||
addGlobalClass: true,
|
addGlobalClass: true,
|
||||||
virtualHost: true,
|
virtualHost: true,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user