papayaui 0.3.5 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/components/date-range-picker/date-range-picker.scss +79 -0
  2. package/components/date-range-picker/date-range-picker.vue +245 -0
  3. package/components/date-range-picker/index.ts +6 -0
  4. package/components/date-range-picker/props.ts +139 -0
  5. package/components/index.ts +2 -0
  6. package/components/picker-popup/picker-popup.vue +3 -1
  7. package/components/picker-popup/props.ts +7 -0
  8. package/components/tour/index.ts +6 -0
  9. package/components/tour/props.ts +105 -0
  10. package/components/tour/tour.scss +148 -0
  11. package/components/tour/tour.vue +376 -0
  12. package/core/useCascader/index.ts +3 -1
  13. package/core/useForm/useFormValidate.ts +10 -8
  14. package/coverage/base.css +224 -0
  15. package/coverage/block-navigation.js +87 -0
  16. package/coverage/clover.xml +859 -0
  17. package/coverage/core/useSelect/index.html +116 -0
  18. package/coverage/core/useSelect/index.ts.html +649 -0
  19. package/coverage/coverage-final.json +9 -0
  20. package/coverage/favicon.png +0 -0
  21. package/coverage/index.html +131 -0
  22. package/coverage/prettify.css +1 -0
  23. package/coverage/prettify.js +2 -0
  24. package/coverage/sort-arrow-sprite.png +0 -0
  25. package/coverage/sorter.js +210 -0
  26. package/coverage/utils/common.ts.html +382 -0
  27. package/coverage/utils/cos.ts.html +1030 -0
  28. package/coverage/utils/format.ts.html +121 -0
  29. package/coverage/utils/function.ts.html +307 -0
  30. package/coverage/utils/index.html +206 -0
  31. package/coverage/utils/index.ts.html +103 -0
  32. package/coverage/utils/lang.ts.html +328 -0
  33. package/coverage/utils/object.ts.html +229 -0
  34. package/package.json +1 -1
  35. package/tsconfig.json +9 -0
@@ -0,0 +1,79 @@
1
+ @import '../../styles/vars.scss';
2
+
3
+ .#{$prefix}-date-range-picker {
4
+ display: block;
5
+
6
+ &-inputs {
7
+ display: flex;
8
+ align-items: center;
9
+ padding: 0;
10
+ background-color: _var(date-range-picker-background, #fff);
11
+ border-radius: _var(date-range-picker-border-radius, 12rpx);
12
+ border: 1rpx solid _var(date-range-picker-border-color, _var(color-border));
13
+ overflow: hidden;
14
+ }
15
+
16
+ &-input {
17
+ flex: 1;
18
+ display: flex;
19
+ flex-direction: column;
20
+ padding: _var(date-range-picker-padding-y, 16rpx) _var(date-range-picker-padding-x, 20rpx);
21
+ min-width: 0;
22
+ }
23
+
24
+ &-label {
25
+ font-size: _var(date-range-picker-label-font-size, 24rpx);
26
+ color: _var(date-range-picker-label-color, _var(color-black));
27
+ margin-bottom: _var(date-range-picker-label-margin-bottom, 8rpx);
28
+ }
29
+
30
+ &-value {
31
+ font-size: _var(date-range-picker-value-font-size, 26rpx);
32
+ color: _var(date-range-picker-value-color, _var(color-text));
33
+ }
34
+
35
+ &--placeholder {
36
+ color: _var(date-range-picker-placeholder-color, _var(color-disabled));
37
+ }
38
+
39
+ &-separator {
40
+ margin: 0 _var(date-range-picker-separator-margin, 12rpx);
41
+ color: _var(date-range-picker-separator-color, _var(color-text-secondary));
42
+ }
43
+
44
+ &-clear {
45
+ flex-shrink: 0;
46
+ font-size: _var(date-range-picker-clear-font-size, 32rpx);
47
+ color: _var(date-range-picker-clear-color, _var(color-disabled));
48
+ padding-right: _var(date-range-picker-clear-padding-right, 20rpx);
49
+ }
50
+
51
+ &--readonly &-inputs {
52
+ background-color: _var(date-range-picker-readonly-background, #fff);
53
+ }
54
+
55
+ &--disabled &-inputs {
56
+ background-color: _var(
57
+ date-range-picker-disabled-background,
58
+ _var(color-background-disabled, #f7f8fa)
59
+ );
60
+ border-color: _var(date-range-picker-disabled-border-color, _var(color-border));
61
+ }
62
+
63
+ &--readonly &-value,
64
+ &--readonly &-label,
65
+ &--readonly &-separator {
66
+ color: _var(date-range-picker-readonly-color, _var(color-text-secondary));
67
+ }
68
+
69
+ &--disabled &-value,
70
+ &--disabled &-label,
71
+ &--disabled &-separator {
72
+ color: _var(date-range-picker-disabled-color, _var(color-disabled));
73
+ }
74
+ }
75
+
76
+ .btn-hover {
77
+ opacity: 0.7;
78
+ }
79
+
@@ -0,0 +1,245 @@
1
+ <template>
2
+ <view :class="[ns.b(), ns.is('readonly', readonly), ns.is('disabled', disabled)]">
3
+ <view :class="ns.b('inputs')">
4
+ <view :class="ns.b('input')" @click="openStart">
5
+ <view v-if="startLabel" :class="ns.b('label')">
6
+ {{ startLabel }}
7
+ </view>
8
+ <view :class="[ns.b('value'), ns.is('placeholder', !startText)]">
9
+ {{ startText || startPlaceholder }}
10
+ </view>
11
+ </view>
12
+ <view :class="ns.b('separator')">-</view>
13
+ <view :class="ns.b('input')" @click="openEnd">
14
+ <view v-if="endLabel" :class="ns.b('label')">
15
+ {{ endLabel }}
16
+ </view>
17
+ <view :class="[ns.b('value'), ns.is('placeholder', !endText)]">
18
+ {{ endText || endPlaceholder }}
19
+ </view>
20
+ </view>
21
+ <pa-icon
22
+ v-if="showClear"
23
+ name="round-close-fill"
24
+ :class="ns.b('clear')"
25
+ @tap.stop="onClear"
26
+ />
27
+ </view>
28
+
29
+ <!-- 开始时间选择 -->
30
+ <pa-bottom-popup v-model:show="showStartPopup" :title="title" height="auto">
31
+ <pa-date-picker
32
+ v-model="innerStart"
33
+ :columns-type="columnsType"
34
+ :show-toolbar="showToolbar"
35
+ :show-columns-header="true"
36
+ :min-date="minDate"
37
+ :max-date="maxDate"
38
+ :option-height="optionHeight"
39
+ :visible-option-num="visibleOptionNum"
40
+ :confirm-button-text="confirmButtonText"
41
+ :cancel-button-text="cancelButtonText"
42
+ :formatter="formatter"
43
+ :filter="filter"
44
+ @change="onStartChange"
45
+ @confirm="onStartConfirm"
46
+ @cancel="onStartCancel"
47
+ />
48
+ </pa-bottom-popup>
49
+
50
+ <!-- 结束时间选择 -->
51
+ <pa-bottom-popup v-model:show="showEndPopup" :title="title" height="auto">
52
+ <pa-date-picker
53
+ v-model="innerEnd"
54
+ :columns-type="columnsType"
55
+ :show-toolbar="showToolbar"
56
+ :show-columns-header="true"
57
+ :min-date="endMinDate"
58
+ :max-date="maxDate"
59
+ :option-height="optionHeight"
60
+ :visible-option-num="visibleOptionNum"
61
+ :confirm-button-text="confirmButtonText"
62
+ :cancel-button-text="cancelButtonText"
63
+ :formatter="formatter"
64
+ :filter="filter"
65
+ @change="onEndChange"
66
+ @confirm="onEndConfirm"
67
+ @cancel="onEndCancel"
68
+ />
69
+ </pa-bottom-popup>
70
+ </view>
71
+ </template>
72
+
73
+ <script lang="ts" setup>
74
+ import dayjs from 'dayjs'
75
+ import { computed, ref, toRefs, watch } from 'vue'
76
+ import useNamespace from '../../core/useNamespace'
77
+ import { dateRangePickerEmits, dateRangePickerProps } from './props'
78
+
79
+ const ns = useNamespace('date-range-picker')
80
+
81
+ const props = defineProps(dateRangePickerProps)
82
+ const emit = defineEmits(dateRangePickerEmits)
83
+
84
+ const { columnsType, minDate, maxDate, formatter, filter } = toRefs(props)
85
+
86
+ const showStartPopup = ref(false)
87
+ const showEndPopup = ref(false)
88
+
89
+ const innerStart = ref<Date | undefined>(props.start)
90
+ const innerEnd = ref<Date | undefined>(props.end)
91
+
92
+ /** 是否允许打开弹窗 */
93
+ const canOpenPopup = computed(() => !props.disabled && !props.readonly)
94
+
95
+ /** 是否显示清空按钮 */
96
+ const showClear = computed(() => {
97
+ return !props.disabled && !props.readonly && props.clearable && (!!props.start || !!props.end)
98
+ })
99
+
100
+ watch(
101
+ () => props.start,
102
+ (val) => {
103
+ innerStart.value = val
104
+ },
105
+ )
106
+
107
+ watch(
108
+ () => props.end,
109
+ (val) => {
110
+ innerEnd.value = val
111
+ },
112
+ )
113
+
114
+ const endMinDate = computed(() => {
115
+ const base = minDate?.value || innerStart.value || props.start
116
+ if (!base) return undefined
117
+ if (props.allowReverse) {
118
+ return base
119
+ }
120
+ const startTime = dayjs(innerStart.value || base)
121
+ const minTime = dayjs(minDate?.value || base)
122
+ return startTime.isAfter(minTime) ? startTime.toDate() : minTime.toDate()
123
+ })
124
+
125
+ const getFormatByColumnsType = () => {
126
+ if (!columnsType.value || !columnsType.value.length) {
127
+ return 'YYYY-MM-DD HH:mm'
128
+ }
129
+ const dateParts: string[] = []
130
+ const timeParts: string[] = []
131
+
132
+ columnsType.value.forEach((type) => {
133
+ if (type === 'year') dateParts.push('YYYY')
134
+ if (type === 'month') dateParts.push('MM')
135
+ if (type === 'day') dateParts.push('DD')
136
+ if (type === 'hour') timeParts.push('HH')
137
+ if (type === 'minute') timeParts.push('mm')
138
+ })
139
+
140
+ let format = ''
141
+ if (dateParts.length) {
142
+ format += dateParts.join('-')
143
+ }
144
+ if (timeParts.length) {
145
+ format += format ? ' ' : ''
146
+ format += timeParts.join(':')
147
+ }
148
+
149
+ return format || 'YYYY-MM-DD HH:mm'
150
+ }
151
+
152
+ const startText = computed(() =>
153
+ props.start ? dayjs(props.start).format(getFormatByColumnsType()) : '',
154
+ )
155
+ const endText = computed(() =>
156
+ props.end ? dayjs(props.end).format(getFormatByColumnsType()) : '',
157
+ )
158
+
159
+ /** 触发区间变更事件 */
160
+ const emitRangeChange = (start?: Date, end?: Date) => {
161
+ if (start && end) {
162
+ emit('change', { start, end })
163
+ }
164
+ }
165
+
166
+ /** 触发区间确认事件 */
167
+ const emitRangeConfirm = (start?: Date, end?: Date) => {
168
+ if (start && end) {
169
+ emit('confirm', { start, end })
170
+ }
171
+ }
172
+
173
+ const openStart = () => {
174
+ if (!canOpenPopup.value) return
175
+ showStartPopup.value = true
176
+ }
177
+
178
+ const openEnd = () => {
179
+ if (!canOpenPopup.value) return
180
+ showEndPopup.value = true
181
+ }
182
+
183
+ /** 清空当前区间值 */
184
+ const onClear = () => {
185
+ showStartPopup.value = false
186
+ showEndPopup.value = false
187
+ emit('update:start', undefined)
188
+ emit('update:end', undefined)
189
+ emit('clear')
190
+ }
191
+
192
+ /** 处理开始时间变更 */
193
+ const onStartChange = (val: Date) => {
194
+ if (!props.showToolbar) {
195
+ onStartConfirm(val)
196
+ }
197
+ }
198
+
199
+ const onStartConfirm = (val: Date) => {
200
+ const finalStart = val
201
+ const finalEnd =
202
+ !props.allowReverse && props.end && dayjs(val).isAfter(props.end) ? val : props.end
203
+
204
+ emit('update:start', val)
205
+ showStartPopup.value = false
206
+ if (finalEnd !== props.end) {
207
+ emit('update:end', finalEnd)
208
+ }
209
+ emitRangeChange(finalStart, finalEnd)
210
+ emitRangeConfirm(finalStart, finalEnd)
211
+ }
212
+
213
+ const onStartCancel = () => {
214
+ showStartPopup.value = false
215
+ emit('cancel')
216
+ }
217
+
218
+ const onEndConfirm = (val: Date) => {
219
+ let finalEnd = val
220
+ if (!props.allowReverse && props.start && dayjs(val).isBefore(props.start)) {
221
+ finalEnd = props.start
222
+ }
223
+ const finalStart = props.start
224
+ emit('update:end', finalEnd)
225
+ showEndPopup.value = false
226
+ emitRangeChange(finalStart, finalEnd)
227
+ emitRangeConfirm(finalStart, finalEnd)
228
+ }
229
+
230
+ /** 处理结束时间变更 */
231
+ const onEndChange = (val: Date) => {
232
+ if (!props.showToolbar) {
233
+ onEndConfirm(val)
234
+ }
235
+ }
236
+
237
+ const onEndCancel = () => {
238
+ showEndPopup.value = false
239
+ emit('cancel')
240
+ }
241
+ </script>
242
+
243
+ <style lang="scss">
244
+ @import './date-range-picker.scss';
245
+ </style>
@@ -0,0 +1,6 @@
1
+ import DateRangePicker from './date-range-picker.vue'
2
+
3
+ export type DateRangePickerInstance = InstanceType<typeof DateRangePicker>
4
+ export * from './props'
5
+
6
+ export default DateRangePicker
@@ -0,0 +1,139 @@
1
+ import type { ExtractPropTypes, ExtractPublicPropTypes, PropType } from 'vue'
2
+ import type {
3
+ DatePickerColumnType,
4
+ DatePickerFilter,
5
+ DatePickerFormatter,
6
+ } from '../../core/useDatePicker'
7
+ import { isDate, isUndefined } from '../../utils'
8
+
9
+ export const dateRangePickerProps = {
10
+ /**
11
+ * 开始时间
12
+ */
13
+ start: Date,
14
+ /**
15
+ * 结束时间
16
+ */
17
+ end: Date,
18
+ /**
19
+ * 选项类型
20
+ */
21
+ columnsType: {
22
+ type: Array as PropType<DatePickerColumnType[]>,
23
+ default: () => ['year', 'month', 'day'],
24
+ },
25
+ /**
26
+ * 可选的最小时间,精确到分
27
+ */
28
+ minDate: Date,
29
+ /**
30
+ * 可选的最大时间,精确到分
31
+ */
32
+ maxDate: Date,
33
+ /**
34
+ * 顶部栏标题
35
+ */
36
+ title: {
37
+ type: String,
38
+ default: '选择时间区间',
39
+ },
40
+ /**
41
+ * 是否显示顶部栏
42
+ * @description 启用时只有 confirm 会触发值更新,禁用时 change 会触发更新
43
+ */
44
+ showToolbar: {
45
+ type: Boolean,
46
+ default: true,
47
+ },
48
+ /**
49
+ * 选项高度
50
+ */
51
+ optionHeight: {
52
+ type: Number,
53
+ default: 44,
54
+ },
55
+ /**
56
+ * 可见选项个数
57
+ */
58
+ visibleOptionNum: {
59
+ type: Number,
60
+ default: 6,
61
+ },
62
+ /**
63
+ * 选项格式化函数
64
+ */
65
+ formatter: Function as PropType<DatePickerFormatter>,
66
+ /**
67
+ * 选项过滤函数
68
+ */
69
+ filter: Function as PropType<DatePickerFilter>,
70
+ /**
71
+ * 是否允许结束时间早于开始时间
72
+ */
73
+ allowReverse: {
74
+ type: Boolean,
75
+ default: false,
76
+ },
77
+ /**
78
+ * 是否禁用
79
+ */
80
+ disabled: Boolean,
81
+ /**
82
+ * 是否只读
83
+ */
84
+ readonly: Boolean,
85
+ /**
86
+ * 是否显示清空控件
87
+ */
88
+ clearable: Boolean,
89
+ /**
90
+ * 开始时间标签
91
+ */
92
+ startLabel: String,
93
+ /**
94
+ * 结束时间标签
95
+ */
96
+ endLabel: String,
97
+ /**
98
+ * 开始时间占位文字
99
+ */
100
+ startPlaceholder: {
101
+ type: String,
102
+ default: '开始时间',
103
+ },
104
+ /**
105
+ * 结束时间占位文字
106
+ */
107
+ endPlaceholder: {
108
+ type: String,
109
+ default: '结束时间',
110
+ },
111
+ /**
112
+ * 确认按钮文字
113
+ */
114
+ confirmButtonText: {
115
+ type: String,
116
+ default: '确认',
117
+ },
118
+ /**
119
+ * 取消按钮文字
120
+ */
121
+ cancelButtonText: {
122
+ type: String,
123
+ default: '取消',
124
+ },
125
+ } as const
126
+
127
+ export const dateRangePickerEmits = {
128
+ 'update:start': (value?: Date) => isDate(value) || isUndefined(value),
129
+ 'update:end': (value?: Date) => isDate(value) || isUndefined(value),
130
+ change: (value: { start: Date; end: Date }) => isDate(value.start) && isDate(value.end),
131
+ confirm: (value: { start: Date; end: Date }) => isDate(value.start) && isDate(value.end),
132
+ cancel: () => true,
133
+ clear: () => true,
134
+ }
135
+
136
+ export type DateRangePickerProps = ExtractPropTypes<typeof dateRangePickerProps>
137
+ export type DateRangePickerPropsPublic = ExtractPublicPropTypes<typeof dateRangePickerProps>
138
+
139
+ export type DateRangePickerEmits = typeof dateRangePickerEmits
@@ -65,3 +65,5 @@ export * from './tooltip'
65
65
  export * from './transition'
66
66
  export * from './uploader'
67
67
  export * from './watermark'
68
+ export * from './date-range-picker'
69
+ export * from './tour'
@@ -136,7 +136,9 @@ const filterOptions = computed(() => {
136
136
  if (props.remote) return text ? options.value : fullOptions
137
137
  // 本地数据情况,直接做过滤
138
138
  if (!text) return fullOptions
139
- return fullOptions.filter((item) => item[labelKey.value]?.indexOf(text) !== -1)
139
+ // 优先使用 searchKey,未指定时回退到 labelKey
140
+ const key = props.searchKey ?? labelKey.value
141
+ return fullOptions.filter((item) => item[key]?.indexOf(text) !== -1)
140
142
  })
141
143
 
142
144
  const showView = computed(() => {
@@ -34,6 +34,13 @@ export const pickerPopupProps = {
34
34
  type: String,
35
35
  default: 'value',
36
36
  },
37
+ /**
38
+ * 搜索时使用的字段名,不传则默认使用 labelKey 字段进行搜索
39
+ */
40
+ searchKey: {
41
+ type: String,
42
+ default: undefined,
43
+ },
37
44
  /**
38
45
  * 是否显示搜索
39
46
  */
@@ -0,0 +1,6 @@
1
+ import Tour from './tour.vue'
2
+
3
+ export type TourInstance = InstanceType<typeof Tour>
4
+ export * from './props'
5
+
6
+ export default Tour
@@ -0,0 +1,105 @@
1
+ import type {
2
+ ComponentInternalInstance,
3
+ ExtractPropTypes,
4
+ ExtractPublicPropTypes,
5
+ PropType,
6
+ } from 'vue'
7
+
8
+ /** 气泡弹出方向 */
9
+ export type TourPlacement = 'top' | 'bottom' | 'left' | 'right'
10
+
11
+ /** 单步引导配置 */
12
+ export interface TourStep {
13
+ /** 目标元素的 CSS 选择器,不传时气泡居中展示 */
14
+ target?: string
15
+ /** 步骤标题 */
16
+ title?: string
17
+ /** 步骤描述内容 */
18
+ content: string
19
+ /** 气泡弹出位置,不传时根据目标位置自动判断 */
20
+ placement?: TourPlacement
21
+ }
22
+
23
+ export const tourProps = {
24
+ /** 是否显示引导 */
25
+ show: {
26
+ type: Boolean,
27
+ default: false,
28
+ },
29
+ /** 引导步骤列表 */
30
+ steps: {
31
+ type: Array as PropType<TourStep[]>,
32
+ default: () => [],
33
+ },
34
+ /** 当前步骤索引,支持 v-model:current */
35
+ current: {
36
+ type: Number,
37
+ default: 0,
38
+ },
39
+ /** 点击遮罩是否关闭引导 */
40
+ maskClosable: {
41
+ type: Boolean,
42
+ default: false,
43
+ },
44
+ /** 是否显示关闭按钮 */
45
+ showClose: {
46
+ type: Boolean,
47
+ default: true,
48
+ },
49
+ /** 高亮区域内边距,单位 px */
50
+ padding: {
51
+ type: Number,
52
+ default: 8,
53
+ },
54
+ /** 上一步按钮文字 */
55
+ prevText: {
56
+ type: String,
57
+ default: '上一步',
58
+ },
59
+ /** 下一步按钮文字 */
60
+ nextText: {
61
+ type: String,
62
+ default: '下一步',
63
+ },
64
+ /** 完成按钮文字 */
65
+ finishText: {
66
+ type: String,
67
+ default: '完成',
68
+ },
69
+ /** 遮罩颜色 */
70
+ maskColor: {
71
+ type: String,
72
+ default: 'rgba(0, 0, 0, 0.5)',
73
+ },
74
+ /** z-index 层级 */
75
+ zIndex: {
76
+ type: Number,
77
+ default: 9999,
78
+ },
79
+ /**
80
+ * 包含目标元素的组件实例,传入调用方的 getCurrentInstance()。
81
+ * 在微信小程序中,createSelectorQuery 的查询范围由组件实例决定,
82
+ * 必须传入实际持有目标元素的那个组件实例才能正确获取元素位置。
83
+ */
84
+ scope: {
85
+ type: Object as PropType<ComponentInternalInstance>,
86
+ default: null,
87
+ },
88
+ } as const
89
+
90
+ export const tourEmits = {
91
+ /** 更新 show 状态 */
92
+ 'update:show': (value: boolean) => typeof value === 'boolean',
93
+ /** 更新当前步骤索引 */
94
+ 'update:current': (value: number) => typeof value === 'number',
95
+ /** 步骤切换时触发,参数为切换后的步骤索引 */
96
+ change: (current: number) => typeof current === 'number',
97
+ /** 点击关闭按钮或遮罩关闭时触发 */
98
+ close: () => true,
99
+ /** 点击完成按钮时触发 */
100
+ finish: () => true,
101
+ }
102
+
103
+ export type TourProps = ExtractPropTypes<typeof tourProps>
104
+ export type TourPropsPublic = ExtractPublicPropTypes<typeof tourProps>
105
+ export type TourEmits = typeof tourEmits