@rao2126340634/yt-ui 1.2.20

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 (120) hide show
  1. package/package.json +43 -0
  2. package/src/components/yt-avatar/yt-avatar.vue +108 -0
  3. package/src/components/yt-badge/yt-badge.vue +65 -0
  4. package/src/components/yt-button/yt-button.vue +79 -0
  5. package/src/components/yt-calendar/yt-calendar.vue +327 -0
  6. package/src/components/yt-card/yt-card.vue +93 -0
  7. package/src/components/yt-checkbox-group/yt-checkbox-group.vue +80 -0
  8. package/src/components/yt-collapse/yt-collapse.vue +115 -0
  9. package/src/components/yt-divider/yt-divider.vue +110 -0
  10. package/src/components/yt-dots/yt-dots.vue +83 -0
  11. package/src/components/yt-empty/yt-empty.vue +43 -0
  12. package/src/components/yt-fab/yt-fab.vue +132 -0
  13. package/src/components/yt-form/yt-form.vue +86 -0
  14. package/src/components/yt-icon/icon-map.ts +52 -0
  15. package/src/components/yt-icon/yt-icon.vue +67 -0
  16. package/src/components/yt-input/yt-input.vue +162 -0
  17. package/src/components/yt-line/yt-line.vue +71 -0
  18. package/src/components/yt-loading/yt-loading.vue +66 -0
  19. package/src/components/yt-movable-view/yt-movable-view.vue +121 -0
  20. package/src/components/yt-notice-bar/yt-notice-bar.vue +91 -0
  21. package/src/components/yt-overlay/yt-overlay.vue +59 -0
  22. package/src/components/yt-picker/yt-picker.vue +111 -0
  23. package/src/components/yt-popup/yt-popup.vue +222 -0
  24. package/src/components/yt-radio-group/yt-radio-group.vue +89 -0
  25. package/src/components/yt-result/yt-result.vue +52 -0
  26. package/src/components/yt-schedule/yt-schedule.vue +737 -0
  27. package/src/components/yt-search/yt-search.vue +127 -0
  28. package/src/components/yt-segment/yt-segment.vue +65 -0
  29. package/src/components/yt-slider/yt-slider.vue +87 -0
  30. package/src/components/yt-steps/yt-steps.vue +90 -0
  31. package/src/components/yt-swiper/yt-swiper.vue +553 -0
  32. package/src/components/yt-switch/yt-switch.vue +76 -0
  33. package/src/components/yt-switch/yt-tabbar/yt-tabbar.vue +198 -0
  34. package/src/components/yt-tabbar/yt-tabbar.vue +198 -0
  35. package/src/components/yt-tag/yt-tag.vue +68 -0
  36. package/src/components/yt-textarea/yt-textarea.vue +172 -0
  37. package/src/components/yt-top-tabbar/yt-top-tabbar.vue +87 -0
  38. package/src/components/yt-virtual-list/yt-virtual-list.vue +140 -0
  39. package/src/configs/scheduleConfig.ts +31 -0
  40. package/src/hooks/useCalendar.ts +79 -0
  41. package/src/hooks/useInterval.ts +28 -0
  42. package/src/hooks/useSchedule.ts +83 -0
  43. package/src/shims.d.ts +4 -0
  44. package/src/static/icons/QRcode.png +0 -0
  45. package/src/static/icons/arrow_down.png +0 -0
  46. package/src/static/icons/arrow_down_white.png +0 -0
  47. package/src/static/icons/arrow_left.png +0 -0
  48. package/src/static/icons/arrow_left_white.png +0 -0
  49. package/src/static/icons/arrow_right.png +0 -0
  50. package/src/static/icons/arrow_right_white.png +0 -0
  51. package/src/static/icons/arrow_up.png +0 -0
  52. package/src/static/icons/arrow_up_white.png +0 -0
  53. package/src/static/icons/calendar.png +0 -0
  54. package/src/static/icons/champion.png +0 -0
  55. package/src/static/icons/close.png +0 -0
  56. package/src/static/icons/community.png +0 -0
  57. package/src/static/icons/community_active.png +0 -0
  58. package/src/static/icons/course.png +0 -0
  59. package/src/static/icons/course_active.png +0 -0
  60. package/src/static/icons/default_avatar.png +0 -0
  61. package/src/static/icons/done.png +0 -0
  62. package/src/static/icons/door_enter.png +0 -0
  63. package/src/static/icons/door_exit.png +0 -0
  64. package/src/static/icons/edit.png +0 -0
  65. package/src/static/icons/empty.png +0 -0
  66. package/src/static/icons/error.png +0 -0
  67. package/src/static/icons/fail.png +0 -0
  68. package/src/static/icons/fail_result.png +0 -0
  69. package/src/static/icons/first_place.png +0 -0
  70. package/src/static/icons/home.png +0 -0
  71. package/src/static/icons/home_active.png +0 -0
  72. package/src/static/icons/hot_topic.png +0 -0
  73. package/src/static/icons/identity.png +0 -0
  74. package/src/static/icons/info_result.png +0 -0
  75. package/src/static/icons/me.png +0 -0
  76. package/src/static/icons/me_active.png +0 -0
  77. package/src/static/icons/official.png +0 -0
  78. package/src/static/icons/passed.png +0 -0
  79. package/src/static/icons/plus.png +0 -0
  80. package/src/static/icons/read.png +0 -0
  81. package/src/static/icons/search.png +0 -0
  82. package/src/static/icons/second_place.png +0 -0
  83. package/src/static/icons/slider.png +0 -0
  84. package/src/static/icons/success_result.png +0 -0
  85. package/src/static/icons/third_place.png +0 -0
  86. package/src/static/icons/time.png +0 -0
  87. package/src/static/icons/unpassed.png +0 -0
  88. package/src/static/icons/winner.png +0 -0
  89. package/src/styles/_anim.scss +130 -0
  90. package/src/styles/_mixins.scss +6 -0
  91. package/src/styles/_theme-utils.scss +11 -0
  92. package/src/styles/_themes.scss +392 -0
  93. package/src/styles/_var.scss +65 -0
  94. package/src/styles/components/_avatar.scss +21 -0
  95. package/src/styles/components/_badge.scss +35 -0
  96. package/src/styles/components/_button.scss +131 -0
  97. package/src/styles/components/_calendar.scss +145 -0
  98. package/src/styles/components/_card.scss +34 -0
  99. package/src/styles/components/_collapse.scss +58 -0
  100. package/src/styles/components/_divider.scss +57 -0
  101. package/src/styles/components/_dots.scss +42 -0
  102. package/src/styles/components/_fab.scss +104 -0
  103. package/src/styles/components/_icon.scss +6 -0
  104. package/src/styles/components/_line.scss +66 -0
  105. package/src/styles/components/_loading.scss +36 -0
  106. package/src/styles/components/_notice-bar.scss +39 -0
  107. package/src/styles/components/_overlay.scss +17 -0
  108. package/src/styles/components/_popup.scss +118 -0
  109. package/src/styles/components/_schedule.scss +324 -0
  110. package/src/styles/components/_search.scss +35 -0
  111. package/src/styles/components/_segment.scss +40 -0
  112. package/src/styles/components/_steps.scss +97 -0
  113. package/src/styles/components/_swiper.scss +122 -0
  114. package/src/styles/components/_tabbar.scss +106 -0
  115. package/src/styles/components/_tag.scss +84 -0
  116. package/src/styles/components/_top-tabbar.scss +40 -0
  117. package/src/types/prop-types.ts +47 -0
  118. package/src/types/theme-types.ts +16 -0
  119. package/src/utils/date.ts +31 -0
  120. package/src/utils/util.ts +72 -0
@@ -0,0 +1,91 @@
1
+ <script setup lang="ts">
2
+ import { computed, useSlots } from 'vue'
3
+ import { ThemeColor } from '../../types/theme-types'
4
+
5
+ const slots = useSlots()
6
+
7
+ interface Props {
8
+ theme?: ThemeColor | 'none'
9
+ width?: number | string
10
+ height?: number | string
11
+ textSize?: number
12
+ animation?: boolean
13
+ duration?: number
14
+ prefixFlex?: number // 0-1
15
+ suffixFlex?: number // 0-1
16
+ }
17
+
18
+ const props = withDefaults(defineProps<Props>(), {
19
+ theme: 'none',
20
+ width: '100%',
21
+ height: 45,
22
+ textSize: 12,
23
+ animation: true,
24
+ duration: 12000,
25
+ prefixFlex: 0.3,
26
+ suffixFlex: 0.3
27
+ })
28
+
29
+ const noticeBarClass = computed(() => {
30
+ return ['yt-notice-bar', `yt-notice-bar--theme-${props.theme}`]
31
+ })
32
+ const noticeBarStyle = computed(() => {
33
+ return {
34
+ width: typeof props.width === 'number' ? `${props.width}px` : props.width,
35
+ height: typeof props.height === 'number' ? `${props.height}px` : props.height
36
+ }
37
+ })
38
+ const noticeTextStyle = computed(() => {
39
+ return {
40
+ fontSize: `${props.textSize}px`,
41
+ animationPlayState: props.animation ? 'running' : 'paused',
42
+ animationDuration: `${props.duration}ms`
43
+ }
44
+ })
45
+
46
+ const hasSlots = computed(() => {
47
+ return {
48
+ hasPrefix: !!slots.prefix,
49
+ hasSuffix: !!slots.suffix
50
+ }
51
+ })
52
+
53
+ defineOptions({
54
+ name: 'YtNoticeBar'
55
+ })
56
+ </script>
57
+
58
+ <template>
59
+ <view
60
+ :class="noticeBarClass"
61
+ :style="noticeBarStyle"
62
+ >
63
+ <view
64
+ v-if="hasSlots.hasPrefix"
65
+ class="yt-notice-bar--prefix"
66
+ :style="{ flex: prefixFlex }"
67
+ >
68
+ <slot name="prefix" />
69
+ </view>
70
+ <view class="yt-notice-bar--text-container">
71
+ <span
72
+ class="yt-notice-bar--text"
73
+ :style="noticeTextStyle"
74
+ >
75
+ <slot />
76
+ </span>
77
+ </view>
78
+ <view
79
+ v-if="hasSlots.hasSuffix"
80
+ class="yt-notice-bar--suffix"
81
+ :style="{ flex: suffixFlex }"
82
+ >
83
+ <slot name="suffix" />
84
+ </view>
85
+ </view>
86
+ </template>
87
+
88
+ <style lang="scss" scoped>
89
+ @use '../../styles/components/_notice-bar.scss';
90
+ @use '../../styles/themes';
91
+ </style>
@@ -0,0 +1,59 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+
4
+ interface Props {
5
+ visible?: boolean
6
+ duration?: number
7
+ zIndex?: number
8
+ bgColor?: string
9
+ width?: number | string
10
+ height?: number | string
11
+ }
12
+ const props = withDefaults(defineProps<Props>(), {
13
+ visible: false,
14
+ duration: 200,
15
+ zIndex: 500,
16
+ bgColor: '#00000080',
17
+ width: '100%',
18
+ height: '100%'
19
+ })
20
+
21
+ const emit = defineEmits<{
22
+ click: [e: Event]
23
+ }>()
24
+
25
+ const overlayStyle = computed(() => {
26
+ return {
27
+ width: typeof props.width === 'number' ? `${props.width}px` : props.width,
28
+ height: typeof props.height === 'number' ? `${props.height}px` : props.height,
29
+ '--overlay-background-color': props.bgColor,
30
+ '--overlay-transition': `opacity ${props.duration}ms ease-out, visibility ${props.duration}ms linear`,
31
+ '--overlay-z-index': props.zIndex
32
+ }
33
+ })
34
+ const overlayClass = computed(() => ({
35
+ 'yt-overlay': true,
36
+ 'yt-overlay--visible': props.visible
37
+ }))
38
+
39
+ function handleClick(e: Event) {
40
+ emit('click', e)
41
+ }
42
+
43
+ defineOptions({
44
+ name: 'YtOverlay'
45
+ })
46
+ </script>
47
+
48
+ <template>
49
+ <view
50
+ @click="handleClick"
51
+ :class="overlayClass"
52
+ :style="overlayStyle"
53
+ @touchmove.stop
54
+ />
55
+ </template>
56
+
57
+ <style lang="scss" scoped>
58
+ @use '../../styles/components/_overlay.scss';
59
+ </style>
@@ -0,0 +1,111 @@
1
+ <script setup lang="ts">
2
+ import { inject, onMounted, onUnmounted, ref } from 'vue'
3
+
4
+ interface Props {
5
+ name?: string
6
+ type?: 'single' | 'multi' | 'date' | 'region'
7
+ items?: any[]
8
+ itemKey?: string
9
+ start?: string
10
+ end?: string
11
+ disabled?: boolean
12
+ fields?: 'year' | 'month' | 'day'
13
+ }
14
+
15
+ const props = withDefaults(defineProps<Props>(), {
16
+ name: '',
17
+ type: 'single',
18
+ items: () => [],
19
+ itemKey: '',
20
+ start: '',
21
+ end: '',
22
+ disabled: false,
23
+ fields: 'day'
24
+ })
25
+
26
+ if (
27
+ props.items.some(item => typeof item === 'object' && item !== null && !Array.isArray(item)) &&
28
+ !props.itemKey
29
+ ) {
30
+ console.warn('[yt-picker] 使用对象数组的选择器时,请设置itemKey以作为显示内容')
31
+ }
32
+ if (props.items.length && (props.type === 'date' || props.type === 'region')) {
33
+ console.warn('[yt-picker] 请使用正确的选择器类型')
34
+ }
35
+ if (props.type === 'multi' && props.items.some(item => !Array.isArray(item))) {
36
+ console.warn('[yt-picker] 使用多列选择器时,请传入二维数组items')
37
+ }
38
+
39
+ // 映射为uniapp selector的mode name
40
+ const typeMap = {
41
+ single: 'selector',
42
+ multi: 'multiSelector',
43
+ date: 'date',
44
+ region: 'region'
45
+ }
46
+
47
+ // 初始化传入的值
48
+ const currentValue = ref<any>()
49
+
50
+ const emit = defineEmits<{
51
+ change: [value: any]
52
+ cancel: []
53
+ columnChange: [{ column: number; value: any }]
54
+ }>()
55
+
56
+ // normal selector value changed
57
+ function handleChange(e: any) {
58
+ currentValue.value = e.detail.value
59
+ emit('change', e.detail.value)
60
+ }
61
+
62
+ // cancel event
63
+ function handleCancel() {
64
+ emit('cancel')
65
+ }
66
+
67
+ // multiselector value changed => return { columnIndex, index }
68
+ function handleColumnChange(e: any) {
69
+ emit('columnChange', e.detail)
70
+ }
71
+
72
+ defineOptions({
73
+ name: 'YtPicker'
74
+ })
75
+
76
+ const registerField: any = inject('registerField', () => {})
77
+ const unregisterField: any = inject('unregisterField', () => {})
78
+ const getValue = () => {
79
+ return currentValue.value
80
+ }
81
+ const setValue = (value: any) => {
82
+ currentValue.value = value
83
+ }
84
+ onMounted(() => {
85
+ if (registerField && props.name) {
86
+ registerField(props.name, getValue, setValue)
87
+ }
88
+ })
89
+ onUnmounted(() => {
90
+ if (unregisterField && props.name) {
91
+ unregisterField(props.name)
92
+ }
93
+ })
94
+ </script>
95
+
96
+ <template>
97
+ <picker
98
+ :mode="typeMap[type]"
99
+ :start="start"
100
+ :end="end"
101
+ @change="handleChange"
102
+ @cancel="handleCancel"
103
+ @columnchange="handleColumnChange"
104
+ :range="items"
105
+ :range-key="itemKey"
106
+ :disabled="disabled"
107
+ :fields="fields"
108
+ >
109
+ <slot />
110
+ </picker>
111
+ </template>
@@ -0,0 +1,222 @@
1
+ <script setup lang="ts">
2
+ import { computed, CSSProperties, onUnmounted, watch } from 'vue'
3
+ interface HeaderProps {
4
+ title?: string
5
+ cancelName?: string
6
+ confirmName?: string
7
+ cancelFn?: () => void
8
+ confirmFn?: () => void
9
+ closeSide?: 'left' | 'right'
10
+ }
11
+ interface Props {
12
+ width?: number | string
13
+ height?: number | string
14
+ maxWidth?: number | string
15
+ maxHeight?: number | string
16
+ bgColor?: string
17
+ overlayColor?: string
18
+ visible?: boolean
19
+ zIndex?: number
20
+ placement?: 'top' | 'bottom' | 'left' | 'right' | 'center'
21
+ borderRadius?: number | string
22
+ duration?: number
23
+ closeOnOverlayClick?: boolean
24
+ destroyOnClose?: boolean
25
+ headerType?: 'close-only' | 'cancel-confirm' | 'none'
26
+ headerProps?: HeaderProps
27
+ }
28
+ const props = withDefaults(defineProps<Props>(), {
29
+ width: '70vw',
30
+ height: '70vh',
31
+ maxWidth: 'none',
32
+ maxHeight: 'none',
33
+ bgColor: '#ffffff',
34
+ overlayColor: '#00000080',
35
+ visible: false,
36
+ zIndex: 1000,
37
+ placement: 'bottom',
38
+ borderRadius: 10,
39
+ duration: 200,
40
+ closeOnOverlayClick: true,
41
+ destroyOnClose: false,
42
+ headerType: 'none',
43
+ headerProps: () => ({
44
+ title: '',
45
+ cancelName: '取消',
46
+ confirmName: '确定',
47
+ cancelFn: () => {},
48
+ confirmFn: () => {},
49
+ closeSide: 'right'
50
+ })
51
+ })
52
+ const emit = defineEmits<{
53
+ overlayClick: [e: Event]
54
+ 'update:visible': [value: boolean]
55
+ open: []
56
+ opened: []
57
+ close: []
58
+ closed: []
59
+ }>()
60
+
61
+ const shouldRender = computed(() => {
62
+ return props.visible || !props.destroyOnClose
63
+ })
64
+ const popupBorderRadius = computed(() => {
65
+ const borderRadius =
66
+ typeof props.borderRadius === 'number' ? `${props.borderRadius}px` : props.borderRadius
67
+ let tl = '0'
68
+ let tr = '0'
69
+ let bl = '0'
70
+ let br = '0'
71
+ if (props.placement === 'top') {
72
+ bl = borderRadius
73
+ br = borderRadius
74
+ }
75
+ if (props.placement === 'bottom') {
76
+ tl = borderRadius
77
+ tr = borderRadius
78
+ }
79
+ if (props.placement === 'center') {
80
+ tl = borderRadius
81
+ tr = borderRadius
82
+ bl = borderRadius
83
+ br = borderRadius
84
+ }
85
+ return {
86
+ '--popup-borderTopLeftRadius': tl,
87
+ '--popup-borderTopRightRadius': tr,
88
+ '--popup-borderBottomLeftRadius': bl,
89
+ '--popup-borderBottomRightRadius': br
90
+ }
91
+ })
92
+ const popupClass = computed(() => {
93
+ return [
94
+ 'yt-popup',
95
+ `yt-popup--${props.placement}`,
96
+ {
97
+ 'yt-popup--visible': props.visible
98
+ }
99
+ ]
100
+ })
101
+ const popupStyle = computed(() => {
102
+ const width = typeof props.width === 'number' ? `${props.width}px` : props.width
103
+ const height = typeof props.height === 'number' ? `${props.height}px` : props.height
104
+ const maxWidth = typeof props.maxWidth === 'number' ? `${props.maxWidth}px` : props.maxWidth
105
+ const maxHeight = typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight
106
+ return {
107
+ ...popupBorderRadius.value,
108
+ width: isCenter.value ? width : isHorizontal.value ? width : '100vw',
109
+ height: isCenter.value ? height : isHorizontal.value ? '100vh' : height,
110
+ '--popup-max-width': maxWidth,
111
+ '--popup-max-height': maxHeight,
112
+ '--popup-z-index': props.zIndex,
113
+ '--popup-transition': `transform ${props.duration}ms ease-out, opacity ${props.duration}ms ease-out`,
114
+ '--popup-background-color': props.bgColor,
115
+ '--popup-header-close-justify-content':
116
+ props.headerProps.closeSide === 'left' ? 'flex-start' : 'flex-end'
117
+ } as CSSProperties
118
+ })
119
+ const isHorizontal = computed(() => {
120
+ return props.placement === 'left' || props.placement === 'right'
121
+ })
122
+ const isCenter = computed(() => {
123
+ return props.placement === 'center'
124
+ })
125
+
126
+ function handleOverlayClick(e: Event) {
127
+ emit('overlayClick', e)
128
+ if (props.closeOnOverlayClick) {
129
+ emit('update:visible', false)
130
+ }
131
+ }
132
+
133
+ let stateTime: NodeJS.Timeout | null = null
134
+ watch(
135
+ () => props.visible,
136
+ newVal => {
137
+ if (stateTime) {
138
+ clearTimeout(stateTime)
139
+ stateTime = null
140
+ }
141
+ if (newVal) {
142
+ emit('open')
143
+ stateTime = setTimeout(() => emit('opened'), props.duration)
144
+ } else {
145
+ emit('close')
146
+ stateTime = setTimeout(() => emit('closed'), props.duration)
147
+ }
148
+ },
149
+ { immediate: true }
150
+ )
151
+
152
+ onUnmounted(() => {
153
+ if (stateTime) {
154
+ clearTimeout(stateTime)
155
+ stateTime = null
156
+ }
157
+ })
158
+
159
+ defineOptions({
160
+ name: 'YtPopup'
161
+ })
162
+ </script>
163
+
164
+ <template>
165
+ <view
166
+ v-if="shouldRender"
167
+ :class="popupClass"
168
+ :style="popupStyle"
169
+ >
170
+ <view
171
+ class="yt-popup--header"
172
+ v-if="headerType !== 'none'"
173
+ >
174
+ <view
175
+ v-if="headerType === 'cancel-confirm'"
176
+ class="yt-popup--header-cancel-confirm"
177
+ >
178
+ <span
179
+ class="yt-popup--text yt-popup--text-cancel"
180
+ @click="props.headerProps.cancelFn"
181
+ >
182
+ {{ props.headerProps.cancelName }}
183
+ </span>
184
+ <span class="yt-popup--text yt-popup--text-title">{{ props.headerProps.title }}</span>
185
+ <span
186
+ class="yt-popup--text yt-popup--text-confirm"
187
+ @click="props.headerProps.confirmFn"
188
+ >
189
+ {{ props.headerProps.confirmName }}
190
+ </span>
191
+ </view>
192
+
193
+ <view
194
+ v-if="headerType === 'close-only'"
195
+ class="yt-popup--header-close-only"
196
+ >
197
+ <span class="yt-popup--text yt-popup--text-title">{{ props.headerProps.title }}</span>
198
+ <yt-icon
199
+ name="Close"
200
+ :width="12"
201
+ :height="12"
202
+ :size="38"
203
+ @click="() => emit('update:visible', false)"
204
+ ></yt-icon>
205
+ </view>
206
+ </view>
207
+
208
+ <slot />
209
+ </view>
210
+
211
+ <yt-overlay
212
+ :visible="visible"
213
+ :zIndex="zIndex - 1"
214
+ :bgColor="overlayColor"
215
+ @click="handleOverlayClick"
216
+ />
217
+ </template>
218
+
219
+ <style lang="scss" scoped>
220
+ @use '../../styles/components/_popup.scss';
221
+ @use '../../styles/_themes.scss';
222
+ </style>
@@ -0,0 +1,89 @@
1
+ <script setup lang="ts">
2
+ import { inject, onMounted, onUnmounted, ref, watch } from 'vue'
3
+
4
+ interface Props {
5
+ name?: string // form-name
6
+ list: {
7
+ label?: string | number
8
+ value?: string | number
9
+ checked?: boolean
10
+ disabled?: boolean
11
+ }[]
12
+ }
13
+ const props = withDefaults(defineProps<Props>(), {
14
+ name: '',
15
+ list: () => []
16
+ })
17
+
18
+ const currentValue = ref<any>(null)
19
+
20
+ const emit = defineEmits<{
21
+ change: [value: any]
22
+ }>()
23
+
24
+ function handleChange(e: any) {
25
+ currentValue.value = e.detail.value
26
+ emit('change', e.detail.value)
27
+ }
28
+
29
+ watch(
30
+ () => props.list,
31
+ newList => {
32
+ const defaultItem = newList.find(item => item.checked)
33
+ if (defaultItem) {
34
+ currentValue.value = defaultItem.value
35
+ }
36
+ },
37
+ {
38
+ immediate: true,
39
+ deep: true
40
+ }
41
+ )
42
+
43
+ defineOptions({
44
+ name: 'YtRadioGroup'
45
+ })
46
+
47
+ const registerField: any = inject('registerField', () => {})
48
+ const unregisterField: any = inject('unregisterField', () => {})
49
+ const getValue = () => {
50
+ return currentValue.value
51
+ }
52
+ const setValue = (value: any) => {
53
+ currentValue.value = value
54
+ }
55
+ onMounted(() => {
56
+ if (registerField && props.name) {
57
+ registerField(props.name, getValue, setValue)
58
+ }
59
+ })
60
+ onUnmounted(() => {
61
+ if (unregisterField && props.name) {
62
+ unregisterField(props.name)
63
+ }
64
+ })
65
+ </script>
66
+
67
+ <template>
68
+ <radio-group @change="handleChange">
69
+ <label
70
+ v-for="item in list"
71
+ :key="item.value"
72
+ class="radio-label"
73
+ >
74
+ <radio
75
+ :value="item.value"
76
+ :checked="currentValue === item.value"
77
+ :disabled="item.disabled"
78
+ >
79
+ {{ item.label }}
80
+ </radio>
81
+ </label>
82
+ </radio-group>
83
+ </template>
84
+
85
+ <style lang="scss" scoped>
86
+ .radio-label {
87
+ margin: 8px;
88
+ }
89
+ </style>
@@ -0,0 +1,52 @@
1
+ <script setup lang="ts">
2
+ interface Props {
3
+ type?: 'success' | 'fail' | 'info'
4
+ size?: number
5
+ }
6
+
7
+ const props = withDefaults(defineProps<Props>(), {
8
+ type: 'success',
9
+ size: 24
10
+ })
11
+
12
+ const typeMap = {
13
+ success: 'SuccessResult',
14
+ fail: 'FailResult',
15
+ info: 'InfoResult'
16
+ }
17
+
18
+ defineOptions({
19
+ name: 'YtResult'
20
+ })
21
+ </script>
22
+
23
+ <template>
24
+ <view class="yt-result">
25
+ <yt-icon
26
+ :name="typeMap[props.type]"
27
+ :size="size"
28
+ :width="120"
29
+ :height="120"
30
+ />
31
+ <span class="yt-result--text"><slot /></span>
32
+ </view>
33
+ </template>
34
+
35
+ <style lang="scss" scoped>
36
+ .yt-result {
37
+ width: fit-content;
38
+ height: fit-content;
39
+ position: absolute;
40
+ top: 50%;
41
+ left: 50%;
42
+ transform: translate(-50%, -50%);
43
+ display: inline-flex;
44
+ flex-direction: column;
45
+ gap: 8px;
46
+ align-items: center;
47
+
48
+ &--text {
49
+ color: #999;
50
+ }
51
+ }
52
+ </style>