hy-app 0.1.1

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 (206) hide show
  1. package/README.md +42 -0
  2. package/api/http.ts +138 -0
  3. package/api/index.ts +1 -0
  4. package/common/index.ts +1 -0
  5. package/common/versionControl.ts +102 -0
  6. package/components/dialog/TheDialog.vue +128 -0
  7. package/components/dialog/index.ts +38 -0
  8. package/components/hy-address-picker/hy-address-picker.vue +262 -0
  9. package/components/hy-address-picker/props.ts +27 -0
  10. package/components/hy-address-picker/typing.d.ts +98 -0
  11. package/components/hy-avatar/hy-avatar.vue +217 -0
  12. package/components/hy-avatar/props.ts +20 -0
  13. package/components/hy-avatar/typing.d.ts +64 -0
  14. package/components/hy-back-top/hy-back-top.vue +71 -0
  15. package/components/hy-back-top/props.ts +23 -0
  16. package/components/hy-back-top/typing.d.ts +49 -0
  17. package/components/hy-badge/hy-badge.vue +155 -0
  18. package/components/hy-badge/props.ts +19 -0
  19. package/components/hy-badge/typing.d.ts +60 -0
  20. package/components/hy-button/hy-button.vue +394 -0
  21. package/components/hy-button/props.ts +36 -0
  22. package/components/hy-button/typing.d.ts +125 -0
  23. package/components/hy-card/hy-card.vue +198 -0
  24. package/components/hy-card/props.ts +29 -0
  25. package/components/hy-card/typing.d.ts +112 -0
  26. package/components/hy-cell/hy-cell.vue +268 -0
  27. package/components/hy-cell/props.ts +20 -0
  28. package/components/hy-cell/typing.d.ts +98 -0
  29. package/components/hy-check-button/hy-check-button.vue +71 -0
  30. package/components/hy-check-button/props.ts +20 -0
  31. package/components/hy-check-button/typing.d.ts +79 -0
  32. package/components/hy-checkbox/hy-checkbox.vue +299 -0
  33. package/components/hy-checkbox/props.ts +28 -0
  34. package/components/hy-checkbox/typing.d.ts +77 -0
  35. package/components/hy-datetime-picker/hy-datetime-picker.vue +584 -0
  36. package/components/hy-datetime-picker/props.ts +36 -0
  37. package/components/hy-datetime-picker/typing.d.ts +135 -0
  38. package/components/hy-divider/hy-divider.vue +164 -0
  39. package/components/hy-divider/props.ts +21 -0
  40. package/components/hy-divider/typing.d.ts +64 -0
  41. package/components/hy-empty/hy-empty.vue +122 -0
  42. package/components/hy-empty/props.ts +21 -0
  43. package/components/hy-empty/typing.d.ts +68 -0
  44. package/components/hy-folding-panel/hy-folding-panel.vue +94 -0
  45. package/components/hy-folding-panel/props.ts +17 -0
  46. package/components/hy-folding-panel/typing.d.ts +59 -0
  47. package/components/hy-form/hy-form.vue +372 -0
  48. package/components/hy-form/props.ts +15 -0
  49. package/components/hy-form/typing.d.ts +51 -0
  50. package/components/hy-grid/hy-grid.vue +126 -0
  51. package/components/hy-grid/props.ts +16 -0
  52. package/components/hy-grid/typing.d.ts +62 -0
  53. package/components/hy-icon/hy-icon.vue +207 -0
  54. package/components/hy-icon/props.ts +24 -0
  55. package/components/hy-icon/typing.d.ts +80 -0
  56. package/components/hy-input/hy-input.vue +402 -0
  57. package/components/hy-input/props.ts +41 -0
  58. package/components/hy-input/typing.d.ts +148 -0
  59. package/components/hy-line/hy-line.vue +44 -0
  60. package/components/hy-line/props.ts +12 -0
  61. package/components/hy-line/typing.d.ts +32 -0
  62. package/components/hy-line-progress/hy-line-progress.vue +118 -0
  63. package/components/hy-line-progress/props.ts +12 -0
  64. package/components/hy-line-progress/typing.d.ts +28 -0
  65. package/components/hy-list/hy-list.vue +250 -0
  66. package/components/hy-list/props.ts +18 -0
  67. package/components/hy-list/typing.d.ts +50 -0
  68. package/components/hy-login/ThePhoneLogin.vue +106 -0
  69. package/components/hy-login/TheUserLogin.vue +391 -0
  70. package/components/hy-login/hy-login.vue +283 -0
  71. package/components/hy-login/props.ts +32 -0
  72. package/components/hy-login/typing.d.ts +60 -0
  73. package/components/hy-modal/hy-modal.vue +240 -0
  74. package/components/hy-modal/props.ts +24 -0
  75. package/components/hy-modal/typing.d.ts +70 -0
  76. package/components/hy-navbar/hy-navbar.vue +194 -0
  77. package/components/hy-navbar/props.ts +24 -0
  78. package/components/hy-navbar/typing.d.ts +81 -0
  79. package/components/hy-notice-bar/hy-column-notice.vue +130 -0
  80. package/components/hy-notice-bar/hy-notice-bar.vue +82 -0
  81. package/components/hy-notice-bar/hy-row-notice.vue +182 -0
  82. package/components/hy-notice-bar/props.ts +19 -0
  83. package/components/hy-notice-bar/typing.d.ts +56 -0
  84. package/components/hy-number-step/hy-number-step.vue +428 -0
  85. package/components/hy-number-step/props.ts +29 -0
  86. package/components/hy-number-step/typing.d.ts +104 -0
  87. package/components/hy-overlay/hy-overlay.vue +54 -0
  88. package/components/hy-overlay/props.ts +10 -0
  89. package/components/hy-overlay/typing.d.ts +24 -0
  90. package/components/hy-picker/hy-picker.vue +499 -0
  91. package/components/hy-picker/props.ts +30 -0
  92. package/components/hy-picker/typing.d.ts +115 -0
  93. package/components/hy-popup/hy-popup.vue +269 -0
  94. package/components/hy-popup/props.ts +21 -0
  95. package/components/hy-popup/typing.d.ts +68 -0
  96. package/components/hy-price/hy-price.vue +86 -0
  97. package/components/hy-price/props.ts +13 -0
  98. package/components/hy-price/typing.d.ts +36 -0
  99. package/components/hy-qrcode/hy-qrcode.vue +153 -0
  100. package/components/hy-qrcode/props.ts +20 -0
  101. package/components/hy-qrcode/qrcode.js +1364 -0
  102. package/components/hy-qrcode/typing.d.ts +64 -0
  103. package/components/hy-radio/hy-radio.vue +319 -0
  104. package/components/hy-radio/props.ts +28 -0
  105. package/components/hy-radio/typing.d.ts +85 -0
  106. package/components/hy-rate/hy-rate.vue +261 -0
  107. package/components/hy-rate/props.ts +18 -0
  108. package/components/hy-rate/typing.d.ts +60 -0
  109. package/components/hy-read-more/hy-read-more.vue +134 -0
  110. package/components/hy-read-more/props.ts +20 -0
  111. package/components/hy-read-more/typing.d.ts +44 -0
  112. package/components/hy-safe-bottom/hy-safe-bottom.vue +64 -0
  113. package/components/hy-scroll-list/hy-scroll-list.vue +146 -0
  114. package/components/hy-scroll-list/props.ts +12 -0
  115. package/components/hy-scroll-list/typing.d.ts +28 -0
  116. package/components/hy-search/hy-search.vue +294 -0
  117. package/components/hy-search/props.ts +29 -0
  118. package/components/hy-search/typing.d.ts +109 -0
  119. package/components/hy-slider/hy-slider.vue +511 -0
  120. package/components/hy-slider/props.ts +21 -0
  121. package/components/hy-slider/typing.d.ts +68 -0
  122. package/components/hy-steps/hy-steps.vue +352 -0
  123. package/components/hy-steps/props.ts +15 -0
  124. package/components/hy-steps/typing.d.ts +58 -0
  125. package/components/hy-subsection/hy-subsection.vue +272 -0
  126. package/components/hy-subsection/props.ts +16 -0
  127. package/components/hy-subsection/typing.d.ts +44 -0
  128. package/components/hy-swiper/hy-swiper-indicator.vue +105 -0
  129. package/components/hy-swiper/hy-swiper.vue +242 -0
  130. package/components/hy-swiper/props.ts +30 -0
  131. package/components/hy-swiper/typing.d.ts +107 -0
  132. package/components/hy-switch/hy-switch.vue +168 -0
  133. package/components/hy-switch/props.ts +16 -0
  134. package/components/hy-switch/typing.d.ts +48 -0
  135. package/components/hy-tabs/hy-tabs.vue +416 -0
  136. package/components/hy-tabs/props.ts +26 -0
  137. package/components/hy-tabs/typing.d.ts +86 -0
  138. package/components/hy-tag/hy-tag.vue +374 -0
  139. package/components/hy-tag/props.ts +22 -0
  140. package/components/hy-tag/typing.d.ts +76 -0
  141. package/components/hy-textarea/hy-textarea.vue +229 -0
  142. package/components/hy-textarea/props.ts +26 -0
  143. package/components/hy-textarea/typing.d.ts +27 -0
  144. package/components/hy-tooltip/hy-tooltip.vue +332 -0
  145. package/components/hy-tooltip/props.ts +17 -0
  146. package/components/hy-tooltip/typing.d.ts +52 -0
  147. package/components/hy-transition/hy-transition.vue +150 -0
  148. package/components/hy-transition/index.scss +113 -0
  149. package/components/hy-transition/props.ts +10 -0
  150. package/components/hy-transition/typing.d.ts +36 -0
  151. package/components/hy-upload/hy-upload.vue +557 -0
  152. package/components/hy-upload/props.ts +29 -0
  153. package/components/hy-upload/typing.d.ts +147 -0
  154. package/components/hy-warn/hy-warn.vue +228 -0
  155. package/components/hy-warn/props.ts +14 -0
  156. package/components/hy-warn/typing.d.ts +40 -0
  157. package/components/hy-waterfall/hy-waterfall.vue +51 -0
  158. package/components/hy-waterfall/props.ts +10 -0
  159. package/components/hy-waterfall/typing.d.ts +20 -0
  160. package/components/index.ts +162 -0
  161. package/components/message/TheMessage.vue +169 -0
  162. package/components/message/index.ts +54 -0
  163. package/components/u-form/form.js +22 -0
  164. package/components/u-form/hy-form.vue +324 -0
  165. package/components/u-form/props.js +49 -0
  166. package/components/u-form/schema.js +1451 -0
  167. package/components/u-form/u-form.vue +267 -0
  168. package/components/u-form/utils.js +65 -0
  169. package/components/u-form-item/formItem.js +24 -0
  170. package/components/u-form-item/hy-form-item.vue +360 -0
  171. package/components/u-form-item/props.js +57 -0
  172. package/components/u-form-item/u-form-item.vue +294 -0
  173. package/components/yk-dialog/yk-dialog.vue +129 -0
  174. package/components/yk-tabbar/props.ts +49 -0
  175. package/components/yk-tabbar/yk-tabbar.vue +224 -0
  176. package/config/color.ts +6 -0
  177. package/config/icon.ts +366 -0
  178. package/config/index.ts +2 -0
  179. package/global/index.ts +6 -0
  180. package/global/register-properties.ts +37 -0
  181. package/index.ts +8 -0
  182. package/libs/css/common.scss +0 -0
  183. package/libs/css/iconfont.css +379 -0
  184. package/libs/css/iconfont.ttf +0 -0
  185. package/libs/css/mixin.scss +15 -0
  186. package/package.json +42 -0
  187. package/public/icons/error.png +0 -0
  188. package/public/icons/success.png +0 -0
  189. package/public/icons/warning.png +0 -0
  190. package/store/index.ts +1 -0
  191. package/store/userInfo.ts +25 -0
  192. package/theme.scss +94 -0
  193. package/typing/index.ts +7 -0
  194. package/typing/modules/common.d.ts +50 -0
  195. package/typing/modules/dialog.ts +17 -0
  196. package/typing/modules/enum.ts +67 -0
  197. package/typing/modules/form.ts +161 -0
  198. package/typing/modules/http.ts +68 -0
  199. package/typing/modules/icon.d.ts +366 -0
  200. package/typing/modules/img.ts +15 -0
  201. package/typing/modules/rect.ts +10 -0
  202. package/utils/address.json +5890 -0
  203. package/utils/base64.ts +119 -0
  204. package/utils/index.ts +3 -0
  205. package/utils/inside.ts +310 -0
  206. package/utils/utils.ts +446 -0
@@ -0,0 +1,44 @@
1
+ import { CSSProperties } from "vue";
2
+
3
+ export default interface IProps {
4
+ /**
5
+ * @description tab的数据
6
+ * */
7
+ list: (string | Record<string, string>)[];
8
+ /**
9
+ * @description 当前活动的tab的index(默认 0 )
10
+ * */
11
+ current?: number;
12
+ /**
13
+ * @description 激活时的颜色(默认 '#3c9cff' )
14
+ * */
15
+ activeColor?: string;
16
+ /**
17
+ * @description 未激活时的颜色(默认 '#303133' )
18
+ * */
19
+ inactiveColor?: string;
20
+ /**
21
+ * @description 模式选择,mode=button为按钮形式,mode=subsection时为分段模式(默认 'button' )
22
+ * */
23
+ mode?: "button" | "subsection";
24
+ /**
25
+ * @description 字体大小,单位px(默认 12 )
26
+ * */
27
+ fontSize?: number | string;
28
+ /**
29
+ * @description 激活选项的字体是否加粗(默认 true )
30
+ * */
31
+ bold?: boolean;
32
+ /**
33
+ * @description 组件背景颜色,mode为button时有效(默认 '#eeeeef' )
34
+ * */
35
+ bgColor?: string;
36
+ /**
37
+ * @description 从`list`元素对象中读取的键名(默认 'name' )
38
+ * */
39
+ keyName?: string;
40
+ /**
41
+ * @description 定义需要用到的外部样式
42
+ * */
43
+ customStyle?: CSSProperties;
44
+ }
@@ -0,0 +1,105 @@
1
+ <template>
2
+ <view class="hy-swiper-indicator">
3
+ <view
4
+ v-if="indicatorMode === 'line'"
5
+ :class="[
6
+ 'hy-swiper-indicator__wrapper',
7
+ `hy-swiper-indicator__wrapper--${indicatorMode}`
8
+ ]"
9
+ :style="{
10
+ width: addUnit(lineWidth * length),
11
+ backgroundColor: indicatorInactiveColor
12
+ }"
13
+ >
14
+ <view
15
+ class="hy-swiper-indicator__wrapper--line__bar"
16
+ :style="[lineStyle]"
17
+ ></view>
18
+ </view>
19
+ <view class="hy-swiper-indicator__wrapper" v-if="indicatorMode === 'dot'">
20
+ <view
21
+ class="hy-swiper-indicator__wrapper__dot"
22
+ v-for="(item, index) in length"
23
+ :key="index"
24
+ :class="[
25
+ index === current && 'hy-swiper-indicator__wrapper__dot--active'
26
+ ]"
27
+ :style="[dotStyle(index)]"
28
+ >
29
+ </view>
30
+ </view>
31
+ </view>
32
+ </template>
33
+
34
+ <script setup lang="ts">
35
+ // 指示器为线型的样式
36
+ import { computed, type CSSProperties, toRefs, ref } from "vue";
37
+ import { addUnit } from "../../utils";
38
+
39
+ interface IProps {
40
+ length: number;
41
+ current: number | string;
42
+ indicatorActiveColor: string;
43
+ indicatorInactiveColor: string;
44
+ indicatorMode: "line" | "dot";
45
+ }
46
+ const props = withDefaults(defineProps<IProps>(), {});
47
+ const { current, indicatorActiveColor, indicatorInactiveColor } = toRefs(props);
48
+
49
+ const lineWidth = ref<number>(22);
50
+
51
+ const lineStyle = computed<CSSProperties>(() => {
52
+ let style: CSSProperties = {};
53
+ style.width = addUnit(lineWidth.value);
54
+ style.transform = `translateX(${addUnit(
55
+ Number(current.value) * lineWidth.value
56
+ )})`;
57
+ style.backgroundColor = indicatorActiveColor.value;
58
+ return style;
59
+ });
60
+ // 指示器为点型的样式
61
+ const dotStyle = computed(() => {
62
+ return (index: number): CSSProperties => {
63
+ let style: CSSProperties = {};
64
+ style.backgroundColor =
65
+ index === current.value
66
+ ? indicatorActiveColor.value
67
+ : indicatorInactiveColor.value;
68
+ return style;
69
+ };
70
+ });
71
+ </script>
72
+
73
+ <style lang="scss" scoped>
74
+ @import "../../libs/css/mixin.scss";
75
+
76
+ .hy-swiper-indicator {
77
+ &__wrapper {
78
+ @include flex;
79
+
80
+ &--line {
81
+ border-radius: 100px;
82
+ height: 4px;
83
+
84
+ &__bar {
85
+ width: 22px;
86
+ height: 4px;
87
+ border-radius: 100px;
88
+ background-color: #ffffff;
89
+ transition: transform 0.3s;
90
+ }
91
+ }
92
+
93
+ &__dot {
94
+ width: 5px;
95
+ height: 5px;
96
+ border-radius: 100px;
97
+ margin: 0 4px;
98
+
99
+ &--active {
100
+ width: 12px;
101
+ }
102
+ }
103
+ }
104
+ }
105
+ </style>
@@ -0,0 +1,242 @@
1
+ <template>
2
+ <view
3
+ class="hy-swiper"
4
+ :style="{
5
+ backgroundColor: bgColor,
6
+ height: addUnit(height),
7
+ borderRadius: addUnit(radius)
8
+ }"
9
+ >
10
+ <view class="hy-swiper__loading" v-if="loading">
11
+ <HyIcon :is-rotate="loading" :name="IconConfig.LOADING"></HyIcon>
12
+ </view>
13
+ <swiper
14
+ v-else
15
+ class="hy-swiper__wrapper"
16
+ :style="{
17
+ flex: '1',
18
+ height: addUnit(height)
19
+ }"
20
+ @change="change"
21
+ :circular="circular"
22
+ :interval="interval"
23
+ :duration="duration"
24
+ :autoplay="autoplay"
25
+ :current="current"
26
+ :currentItemId="currentItemId"
27
+ :previousMargin="addUnit(previousMargin)"
28
+ :nextMargin="addUnit(nextMargin)"
29
+ :acceleration="acceleration"
30
+ :displayMultipleItems="displayMultipleItems"
31
+ :easingFunction="easingFunction"
32
+ >
33
+ <swiper-item
34
+ class="hy-swiper__wrapper__item"
35
+ v-for="(item, index) in list"
36
+ :key="index"
37
+ >
38
+ <slot :record="item" :index="index">
39
+ <view class="hy-swiper__wrapper__item__wrapper">
40
+ <!-- 在nvue中,image图片的宽度默认为屏幕宽度,需要通过flex:1撑开,另外必须设置高度才能显示图片 -->
41
+ <image
42
+ class="hy-swiper__wrapper__item__wrapper__image"
43
+ v-if="getItemType(item) === 'image'"
44
+ :src="getSource(item)"
45
+ :mode="imgMode"
46
+ @tap="clickHandler(index)"
47
+ :style="{
48
+ height: addUnit(height),
49
+ borderRadius: addUnit(radius)
50
+ }"
51
+ ></image>
52
+ <video
53
+ class="hy-swiper__wrapper__item__wrapper__video"
54
+ v-if="getItemType(item) === 'video'"
55
+ :id="`video-${index}`"
56
+ :enable-progress-gesture="false"
57
+ :src="getSource(item)"
58
+ :poster="getPoster(item)"
59
+ :title="showTitle && hasTitle(item)"
60
+ :style="{
61
+ height: addUnit(height)
62
+ }"
63
+ controls
64
+ @tap="clickHandler(index)"
65
+ ></video>
66
+ <view
67
+ v-if="showTitle && hasTitle(item)"
68
+ class="hy-swiper__wrapper__item__wrapper__title"
69
+ >
70
+ <text class="hy-line-1">{{ hasTitle(item) }}</text>
71
+ </view>
72
+ </view>
73
+ </slot>
74
+ </swiper-item>
75
+ </swiper>
76
+ <view class="hy-swiper__indicator" :style="[indicatorStyle]">
77
+ <slot name="indicator">
78
+ <HySwiperIndicator
79
+ v-if="!loading && indicator && !showTitle"
80
+ :indicatorActiveColor="indicatorActiveColor"
81
+ :indicatorInactiveColor="indicatorInactiveColor"
82
+ :length="list.length"
83
+ :current="currentIndex"
84
+ :indicatorMode="indicatorMode"
85
+ ></HySwiperIndicator>
86
+ </slot>
87
+ </view>
88
+ </view>
89
+ </template>
90
+
91
+ <script setup lang="ts">
92
+ import { computed, toRefs, ref, watch, getCurrentInstance } from "vue";
93
+ import { addUnit, isVideo } from "../../utils";
94
+ import defaultProps from "./props";
95
+ import HyIcon from "../hy-icon/hy-icon.vue";
96
+ import { IconConfig } from "../../config";
97
+ import IProps, { SwiperVo } from "./typing";
98
+ import HySwiperIndicator from "./hy-swiper-indicator.vue";
99
+
100
+ const props = withDefaults(defineProps<IProps>(), defaultProps);
101
+ const { keyName, list, current } = toRefs(props);
102
+ const emit = defineEmits(["click", "update:current", "change"]);
103
+
104
+ const instance = getCurrentInstance();
105
+ const currentIndex = ref<string | number>(0);
106
+
107
+ watch(
108
+ () => current.value,
109
+ (newVal) => {
110
+ currentIndex.value = newVal;
111
+ }
112
+ );
113
+
114
+ const hasTitle = computed(() => {
115
+ return (item: string | Record<string, any>) => {
116
+ if (typeof item === "object") {
117
+ return item.title ?? "";
118
+ } else {
119
+ return "";
120
+ }
121
+ };
122
+ });
123
+ /**
124
+ * @description 获取目标路径,可能数组中为字符串,对象的形式,额外可指定对象的目标属性名keyName
125
+ * */
126
+ const getSource = (item: string | Record<string, any>): string => {
127
+ if (typeof item === "string") return item;
128
+ if (typeof item === "object" && keyName.value) return item[keyName.value];
129
+ return "";
130
+ };
131
+
132
+ /**
133
+ * @description 轮播切换事件
134
+ */
135
+ const change = (e: SwiperVo) => {
136
+ // 当前的激活索引
137
+ const { current } = e.detail;
138
+ pauseVideo(currentIndex.value);
139
+ currentIndex.value = current;
140
+ emit("update:current", currentIndex.value);
141
+ emit("change", e.detail);
142
+ };
143
+
144
+ /**
145
+ * @description 切换轮播时,暂停视频播放
146
+ * */
147
+ const pauseVideo = (index: number | string) => {
148
+ const lastItem = getSource(list.value[Number(index)]);
149
+ if (isVideo(lastItem)) {
150
+ // 当视频隐藏时,暂停播放
151
+ const video = uni.createVideoContext(`video-${index}`, instance);
152
+ video.pause();
153
+ }
154
+ };
155
+
156
+ /**
157
+ * @description 当一个轮播item为视频时,获取它的视频海报
158
+ * */
159
+ const getPoster = (item: string | Record<string, unknown>): string => {
160
+ return typeof item === "object" && item.poster ? item.poster : "";
161
+ };
162
+
163
+ /**
164
+ * @description 点击某个item
165
+ * */
166
+ const clickHandler = (index: number) => {
167
+ emit("click", index);
168
+ };
169
+
170
+ /**
171
+ * @description 判断链接是视频还是图片
172
+ * */
173
+ const getItemType = computed(() => {
174
+ return (item: string | Record<string, unknown>) => {
175
+ if (typeof item === "string") return isVideo(item) ? "video" : "image";
176
+ if (typeof item === "object" && keyName.value) {
177
+ if (!item.type)
178
+ return isVideo(item[keyName.value] as string) ? "video" : "image";
179
+ if (item.type === "image") return "image";
180
+ if (item.type === "video") return "video";
181
+ return "image";
182
+ }
183
+ };
184
+ });
185
+ </script>
186
+
187
+ <style lang="scss" scoped>
188
+ @import "../../libs/css/mixin.scss";
189
+ @import "../../theme.scss";
190
+
191
+ .hy-swiper__wrapper {
192
+ flex: 1;
193
+ }
194
+ .hy-swiper {
195
+ @include flex;
196
+ justify-content: center;
197
+ align-items: center;
198
+ position: relative;
199
+ overflow: hidden;
200
+
201
+ &__wrapper {
202
+ flex: 1;
203
+
204
+ &__item {
205
+ flex: 1;
206
+
207
+ &__wrapper {
208
+ @include flex;
209
+ position: relative;
210
+ overflow: hidden;
211
+ transition: transform 0.3s;
212
+ flex: 1;
213
+
214
+ &__image {
215
+ flex: 1;
216
+ }
217
+
218
+ &__video {
219
+ flex: 1;
220
+ }
221
+
222
+ &__title {
223
+ position: absolute;
224
+ background-color: rgba(0, 0, 0, 0.3);
225
+ bottom: 0;
226
+ left: 0;
227
+ right: 0;
228
+ font-size: 28rpx;
229
+ padding: $hy-border-margin-padding-sm $hy-border-margin-padding-lg;
230
+ color: #ffffff;
231
+ flex: 1;
232
+ }
233
+ }
234
+ }
235
+ }
236
+
237
+ &__indicator {
238
+ position: absolute;
239
+ bottom: $hy-border-margin-padding-sm;
240
+ }
241
+ }
242
+ </style>
@@ -0,0 +1,30 @@
1
+ import IProps from "./typing";
2
+
3
+ const defaultProps: IProps = {
4
+ list: () => [],
5
+ indicator: false,
6
+ indicatorActiveColor: "#FFFFFF",
7
+ indicatorInactiveColor: "rgba(255, 255, 255, 0.35)",
8
+ indicatorStyle: {},
9
+ indicatorMode: "line",
10
+ autoplay: true,
11
+ current: 0,
12
+ currentItemId: "",
13
+ interval: 3000,
14
+ duration: 300,
15
+ circular: false,
16
+ previousMargin: 0,
17
+ nextMargin: 0,
18
+ acceleration: false,
19
+ displayMultipleItems: 1,
20
+ easingFunction: "default",
21
+ keyName: "url",
22
+ imgMode: "aspectFill",
23
+ height: 130,
24
+ bgColor: "#f3f4f6",
25
+ radius: 4,
26
+ loading: false,
27
+ showTitle: false
28
+ };
29
+
30
+ export default defaultProps;
@@ -0,0 +1,107 @@
1
+ import { ImageModeVo } from "../../typing";
2
+ import type { CSSProperties, PropType } from "vue";
3
+
4
+ export default interface IProps {
5
+ /**
6
+ * @description 轮播图数据
7
+ * */
8
+ list: PropType<(string | Record<string, unknown>)[]>;
9
+ /**
10
+ * @description list数组中指定对象的目标属性名(默认 'url' )
11
+ * */
12
+ keyName?: string;
13
+ /**
14
+ * @description 是否显示面板指示器(默认 false )
15
+ * */
16
+ indicator?: boolean;
17
+ /**
18
+ * @description 指示器非激活颜色(默认 '#FFFFFF' )
19
+ * */
20
+ indicatorActiveColor?: string;
21
+ /**
22
+ * @description 指示器的激活颜色(默认 'rgba(255, 255, 255, 0.35)' )
23
+ * */
24
+ indicatorInactiveColor?: string;
25
+ /**
26
+ * @description 指示器样式,可通过bottom,left,right进行定位
27
+ * */
28
+ indicatorStyle?: CSSProperties;
29
+ /**
30
+ * @description 指示器模式(默认 'line' )
31
+ * */
32
+ indicatorMode?: "line" | "dot";
33
+ /**
34
+ * @description 是否自动切换(默认 true )
35
+ * */
36
+ autoplay?: boolean;
37
+ /**
38
+ * @description 当前所在滑块的 index(默认 0 )
39
+ * */
40
+ current?: number | string;
41
+ /**
42
+ * @description 当前所在滑块的 item-id ,不能与 current 被同时指定
43
+ * */
44
+ currentItemId?: string;
45
+ /**
46
+ * @description 滑块自动切换时间间隔(ms)(默认 3000 )
47
+ * */
48
+ interval?: number;
49
+ /**
50
+ * @description 滑块切换过程所需时间(ms)(默认 300 )
51
+ * */
52
+ duration?: number;
53
+ /**
54
+ * @description 播放到末尾后是否重新回到开头(默认 false )
55
+ * */
56
+ circular?: boolean;
57
+ /**
58
+ * @description 前边距,可用于露出前一项的一小部分,nvue和支付宝不支持(默认 0 )
59
+ * */
60
+ previousMargin?: number | string;
61
+ /**
62
+ * @description 后边距,可用于露出后一项的一小部分,nvue和支付宝不支持(默认 0 )
63
+ * */
64
+ nextMargin?: number | string;
65
+ /**
66
+ * @description 当开启时,会根据滑动速度,连续滑动多屏,支付宝不支持(默认 false )
67
+ * */
68
+ acceleration?: boolean;
69
+ /**
70
+ * @description 同时显示的滑块数量,nvue、支付宝小程序不支持(默认 1 )
71
+ * */
72
+ displayMultipleItems?: number;
73
+ /**
74
+ * @description 指定swiper切换缓动动画类型, 只对微信小程序有效(默认 'default' )
75
+ * */
76
+ easingFunction?: string;
77
+ /**
78
+ * @description 图片的裁剪模式(默认 'aspectFill' )
79
+ * */
80
+ imgMode?: ImageModeVo;
81
+ /**
82
+ * @description 组件高度(默认 130 )
83
+ * */
84
+ height?: number;
85
+ /**
86
+ * @description 背景颜色(默认 '#f3f4f6' )
87
+ * */
88
+ bgColor?: string;
89
+ /**
90
+ * @description 组件圆角,数值或带单位的字符串(默认 4 )
91
+ * */
92
+ radius?: number | string;
93
+ /**
94
+ * @description 是否加载中(默认 false )
95
+ * */
96
+ loading?: boolean;
97
+ /**
98
+ * @description 是否显示标题,要求数组对象中有title属性(默认 false )
99
+ * */
100
+ showTitle?: boolean;
101
+ }
102
+
103
+ export interface SwiperVo {
104
+ detail: {
105
+ current: number;
106
+ };
107
+ }
@@ -0,0 +1,168 @@
1
+ <template>
2
+ <view
3
+ class="hy-switch cursor-pointer"
4
+ :class="[disabled && 'hy-switch--disabled']"
5
+ :style="[switchStyle, customStyle]"
6
+ @tap="clickHandler"
7
+ >
8
+ <view class="hy-switch__bg" :style="[bgStyle]"> </view>
9
+ <view
10
+ :class="['hy-switch__node', modelValue && 'hy-switch__node--on']"
11
+ :style="[nodeStyle]"
12
+ ref="hy-switch__node"
13
+ >
14
+ <HyIcon
15
+ v-if="loading"
16
+ :name="IconConfig.LOADING"
17
+ is-rotate
18
+ :color="modelValue ? activeColor : '#AAABAD'"
19
+ :size="size * 0.6"
20
+ ></HyIcon>
21
+ </view>
22
+ </view>
23
+ </template>
24
+
25
+ <script setup lang="ts">
26
+ import { toRefs, watch, ref, nextTick, computed, CSSProperties } from "vue";
27
+ import { IconConfig } from "../../config";
28
+ import { addUnit, error } from "../../utils";
29
+ import defaultProps from "./props";
30
+ import IProps from "./typing";
31
+
32
+ import HyIcon from "../hy-icon/hy-icon.vue";
33
+
34
+ const props = withDefaults(defineProps<IProps>(), defaultProps);
35
+ const {
36
+ modelValue,
37
+ size,
38
+ space,
39
+ inactiveValue,
40
+ activeValue,
41
+ activeColor,
42
+ disabled,
43
+ loading,
44
+ asyncChange,
45
+ inactiveColor
46
+ } = toRefs(props);
47
+ const emit = defineEmits(["update:modelValue", "change"]);
48
+ const bgColor = ref("#ffffff");
49
+
50
+ watch(
51
+ () => modelValue.value,
52
+ (newValue) => {
53
+ if (newValue !== inactiveValue.value && newValue !== activeValue.value) {
54
+ error("v-model绑定的值必须为inactiveValue、activeValue二者之一");
55
+ }
56
+ },
57
+ { immediate: true }
58
+ );
59
+
60
+ const isActive = computed(() => {
61
+ return modelValue.value === activeValue.value;
62
+ });
63
+ const switchStyle = computed<CSSProperties>(() => {
64
+ let style: CSSProperties = {};
65
+ // 这里需要加2,是为了腾出边框的距离,否则圆点node会和外边框紧贴在一起
66
+ style.width = addUnit(size.value * 2 + 2);
67
+ style.height = addUnit(Number(size.value) + 2);
68
+ // style.borderColor = this.value ? 'rgba(0, 0, 0, 0)' : 'rgba(0, 0, 0, 0.12)'
69
+ // 如果自定义了“非激活”演示,name边框颜色设置为透明(跟非激活颜色一致)
70
+ // 这里不能简单的设置为非激活的颜色,否则打开状态时,会有边框,所以需要透明
71
+ if (customInactiveColor.value) {
72
+ style.borderColor = "rgba(0, 0, 0, 0)";
73
+ }
74
+ style.backgroundColor = isActive.value
75
+ ? activeColor.value
76
+ : inactiveColor.value;
77
+ return style;
78
+ });
79
+ const nodeStyle = computed<CSSProperties>(() => {
80
+ let style: CSSProperties = {};
81
+ // 如果自定义非激活颜色,将node圆点的尺寸减少两个像素,让其与外边框距离更大一点
82
+ style.width = addUnit(size.value - space.value);
83
+ style.height = addUnit(size.value - space.value);
84
+ const translateX = isActive.value
85
+ ? addUnit(space.value)
86
+ : addUnit(size.value);
87
+ style.transform = `translateX(-${translateX})`;
88
+ return style;
89
+ });
90
+ const bgStyle = computed<CSSProperties>(() => {
91
+ let style: CSSProperties = {};
92
+ // 这里配置一个多余的元素在HTML中,是为了让switch切换时,有更良好的背景色扩充体验(见实际效果)
93
+ style.width = addUnit(Number(size.value) * 2 - size.value / 2);
94
+ style.height = addUnit(size.value);
95
+ style.backgroundColor = inactiveColor.value;
96
+ // 打开时,让此元素收缩,否则反之
97
+ style.transform = `scale(${isActive.value ? 0 : 1})`;
98
+ return style;
99
+ });
100
+ const customInactiveColor = computed(() => {
101
+ // 之所以需要判断是否自定义了“非激活”颜色,是为了让node圆点离外边框更宽一点的距离
102
+ return inactiveColor.value !== "#fff" && inactiveColor.value !== "#ffffff";
103
+ });
104
+
105
+ const clickHandler = () => {
106
+ if (!disabled.value && !loading.value) {
107
+ const oldValue = isActive.value ? inactiveValue.value : activeValue.value;
108
+ if (!asyncChange.value) {
109
+ emit("update:modelValue", oldValue);
110
+ }
111
+ // 放到下一个生命周期,因为双向绑定的value修改父组件状态需要时间,且是异步的
112
+ nextTick(() => {
113
+ emit("change", oldValue);
114
+ });
115
+ }
116
+ };
117
+ </script>
118
+
119
+ <style lang="scss" scoped>
120
+ @import "../../libs/css/mixin.scss";
121
+
122
+ .hy-switch {
123
+ @include flex(row);
124
+ /* #ifndef APP-NVUE */
125
+ box-sizing: border-box;
126
+ /* #endif */
127
+ position: relative;
128
+ background-color: #fff;
129
+ border-width: 1px;
130
+ border-radius: 100px;
131
+ transition: background-color 0.4s;
132
+ border-color: rgba(0, 0, 0, 0.12);
133
+ border-style: solid;
134
+ justify-content: flex-end;
135
+ align-items: center;
136
+ // 由于weex为阿里逗着玩的KPI项目,导致bug奇多,这必须要写这一行,
137
+ // 否则在iOS上,点击页面任意地方,都会触发switch的点击事件
138
+ overflow: hidden;
139
+
140
+ &__node {
141
+ @include flex(row);
142
+ align-items: center;
143
+ justify-content: center;
144
+ border-radius: 100px;
145
+ background-color: #fff;
146
+ border-radius: 100px;
147
+ box-shadow: 1px 1px 1px 0 rgba(0, 0, 0, 0.25);
148
+ transition-property: transform;
149
+ transition-duration: 0.4s;
150
+ transition-timing-function: cubic-bezier(0.3, 1.05, 0.4, 1.05);
151
+ }
152
+
153
+ &__bg {
154
+ position: absolute;
155
+ border-radius: 100px;
156
+ background-color: #ffffff;
157
+ transition-property: transform;
158
+ transition-duration: 0.4s;
159
+ border-top-left-radius: 0;
160
+ border-bottom-left-radius: 0;
161
+ transition-timing-function: ease;
162
+ }
163
+
164
+ &--disabled {
165
+ opacity: 0.6;
166
+ }
167
+ }
168
+ </style>