@puresnake/snake-ui 0.0.0-stage → 0.0.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 (279) hide show
  1. package/LICENSE +21 -0
  2. package/changelog.md +1 -0
  3. package/components/snake-activity-list/snake-activity-list.vue +365 -0
  4. package/components/snake-activity-list/types.ts +29 -0
  5. package/components/snake-auxiliary-segmentation/snake-auxiliary-segmentation.vue +44 -0
  6. package/components/snake-auxiliary-segmentation/types.ts +5 -0
  7. package/components/snake-button/snake-button.vue +357 -0
  8. package/components/snake-button/types.ts +103 -0
  9. package/components/snake-button-sort/snake-button-sort.vue +72 -0
  10. package/components/snake-button-sort/types.ts +22 -0
  11. package/components/snake-calendar/snake-calendar.vue +998 -0
  12. package/components/snake-calendar/types.ts +189 -0
  13. package/components/snake-cell-group/snake-cell-group.vue +55 -0
  14. package/components/snake-cell-group/types.ts +19 -0
  15. package/components/snake-cell-item/snake-cell-item.vue +159 -0
  16. package/components/snake-cell-item/types.ts +66 -0
  17. package/components/snake-checkbox/snake-checkbox.vue +264 -0
  18. package/components/snake-checkbox/types.ts +70 -0
  19. package/components/snake-checkbox-group/snake-checkbox-group.vue +154 -0
  20. package/components/snake-checkbox-group/types.ts +52 -0
  21. package/components/snake-cms/blocks/v2/cms-v2-carousel.vue +87 -0
  22. package/components/snake-cms/blocks/v2/cms-v2-coupon.vue +25 -0
  23. package/components/snake-cms/blocks/v2/cms-v2-custom.vue +12 -0
  24. package/components/snake-cms/blocks/v2/cms-v2-divider.vue +33 -0
  25. package/components/snake-cms/blocks/v2/cms-v2-floatbutton.vue +28 -0
  26. package/components/snake-cms/blocks/v2/cms-v2-goods-list.vue +150 -0
  27. package/components/snake-cms/blocks/v2/cms-v2-hotzone.vue +41 -0
  28. package/components/snake-cms/blocks/v2/cms-v2-images.vue +41 -0
  29. package/components/snake-cms/blocks/v2/cms-v2-magiccube.vue +93 -0
  30. package/components/snake-cms/blocks/v2/cms-v2-notice.vue +80 -0
  31. package/components/snake-cms/blocks/v2/cms-v2-popup.vue +46 -0
  32. package/components/snake-cms/blocks/v2/cms-v2-richtext.vue +18 -0
  33. package/components/snake-cms/blocks/v2/cms-v2-search.vue +115 -0
  34. package/components/snake-cms/blocks/v2/cms-v2-video.vue +25 -0
  35. package/components/snake-cms/blocks/v2/shared.ts +84 -0
  36. package/components/snake-cms/snake-cms.vue +409 -0
  37. package/components/snake-cms/types.ts +50 -0
  38. package/components/snake-commodity-search/snake-commodity-search.vue +234 -0
  39. package/components/snake-commodity-search/types.ts +11 -0
  40. package/components/snake-config-provider/snake-config-provider.vue +61 -0
  41. package/components/snake-config-provider/types.ts +22 -0
  42. package/components/snake-count-down/snake-count-down.vue +231 -0
  43. package/components/snake-count-down/types.ts +103 -0
  44. package/components/snake-coupon/snake-coupon.vue +209 -0
  45. package/components/snake-coupon/types.ts +21 -0
  46. package/components/snake-custom-module/snake-custom-module.vue +25 -0
  47. package/components/snake-custom-module/types.ts +11 -0
  48. package/components/snake-drop-menu/snake-drop-menu.vue +123 -0
  49. package/components/snake-drop-menu/types.ts +95 -0
  50. package/components/snake-drop-menu-item/snake-drop-menu-item.vue +181 -0
  51. package/components/snake-drop-menu-item/types.ts +48 -0
  52. package/components/snake-empty/snake-empty.vue +100 -0
  53. package/components/snake-empty/types.ts +48 -0
  54. package/components/snake-filter-sorts/filter-page.vue +695 -0
  55. package/components/snake-filter-sorts/snake-filter-sorts.vue +185 -0
  56. package/components/snake-filter-sorts/types.ts +57 -0
  57. package/components/snake-floating-bubble/snake-floating-bubble.vue +157 -0
  58. package/components/snake-floating-bubble/types.ts +43 -0
  59. package/components/snake-follow/snake-follow.vue +18 -0
  60. package/components/snake-follow/types.ts +2 -0
  61. package/components/snake-form/snake-form.vue +124 -0
  62. package/components/snake-form/types.ts +96 -0
  63. package/components/snake-form-item/snake-form-item.vue +331 -0
  64. package/components/snake-form-item/types.ts +70 -0
  65. package/components/snake-goods-list/snake-goods-list.vue +792 -0
  66. package/components/snake-goods-list/types.ts +55 -0
  67. package/components/snake-graphic-navigation/snake-graphic-navigation.vue +198 -0
  68. package/components/snake-graphic-navigation/types.ts +43 -0
  69. package/components/snake-icon/icon-names.ts +222 -0
  70. package/components/snake-icon/snake-icon.vue +220 -0
  71. package/components/snake-icon/types.ts +45 -0
  72. package/components/snake-image/snake-image.vue +230 -0
  73. package/components/snake-image/types.ts +70 -0
  74. package/components/snake-images/snake-images.vue +80 -0
  75. package/components/snake-images/types.ts +5 -0
  76. package/components/snake-index-anchor/snake-index-anchor.vue +83 -0
  77. package/components/snake-index-anchor/types.ts +14 -0
  78. package/components/snake-index-list/anchor-registry.ts +80 -0
  79. package/components/snake-index-list/snake-index-list.vue +259 -0
  80. package/components/snake-index-list/types.ts +115 -0
  81. package/components/snake-index-list-panel/snake-index-list-panel.vue +277 -0
  82. package/components/snake-index-list-panel/types.ts +10 -0
  83. package/components/snake-input/snake-input.vue +225 -0
  84. package/components/snake-input/types.ts +99 -0
  85. package/components/snake-jump-applet/snake-jump-applet.vue +99 -0
  86. package/components/snake-jump-applet/types.ts +17 -0
  87. package/components/snake-line/snake-line.vue +42 -0
  88. package/components/snake-line/types.ts +30 -0
  89. package/components/snake-line-progress/snake-line-progress.vue +105 -0
  90. package/components/snake-line-progress/types.ts +26 -0
  91. package/components/snake-link/snake-link.vue +74 -0
  92. package/components/snake-link/types.ts +30 -0
  93. package/components/snake-list-switching/components/tree-select/index.vue +156 -0
  94. package/components/snake-list-switching/snake-list-switching.vue +1285 -0
  95. package/components/snake-list-switching/types.ts +11 -0
  96. package/components/snake-loading/snake-loading.vue +241 -0
  97. package/components/snake-loading/types.ts +34 -0
  98. package/components/snake-loadmore/snake-loadmore.vue +103 -0
  99. package/components/snake-loadmore/types.ts +56 -0
  100. package/components/snake-magic-cube/snake-magic-cube.vue +622 -0
  101. package/components/snake-magic-cube/types.ts +5 -0
  102. package/components/snake-modal/snake-modal.vue +434 -0
  103. package/components/snake-modal/types.ts +71 -0
  104. package/components/snake-navbar/snake-navbar.vue +194 -0
  105. package/components/snake-navbar/types.ts +54 -0
  106. package/components/snake-no-network/snake-no-network.vue +125 -0
  107. package/components/snake-no-network/types.ts +27 -0
  108. package/components/snake-notice/snake-notice.vue +44 -0
  109. package/components/snake-notice/types.ts +5 -0
  110. package/components/snake-notice-bar/snake-notice-bar.vue +336 -0
  111. package/components/snake-notice-bar/types.ts +82 -0
  112. package/components/snake-overlay/snake-overlay.vue +73 -0
  113. package/components/snake-overlay/types.ts +35 -0
  114. package/components/snake-page-popup/snake-page-popup.vue +146 -0
  115. package/components/snake-page-popup/types.ts +28 -0
  116. package/components/snake-parse/audio/audio.vue +286 -0
  117. package/components/snake-parse/audio/context.js +11 -0
  118. package/components/snake-parse/audio/index.js +34 -0
  119. package/components/snake-parse/node/node.vue +830 -0
  120. package/components/snake-parse/parser.js +1480 -0
  121. package/components/snake-parse/snake-parse.vue +548 -0
  122. package/components/snake-parse/static/app-plus/snake-parse/js/handler.js +109 -0
  123. package/components/snake-parse/static/app-plus/snake-parse/js/uni.webview.js +0 -0
  124. package/components/snake-parse/static/app-plus/snake-parse/js/uni.webview.min.js +1 -0
  125. package/components/snake-parse/static/app-plus/snake-parse/local.html +3 -0
  126. package/components/snake-parse/style/index.js +132 -0
  127. package/components/snake-parse/style/parser.js +175 -0
  128. package/components/snake-parse/types.ts +49 -0
  129. package/components/snake-picture-ads/snake-picture-ads.vue +292 -0
  130. package/components/snake-picture-ads/types.ts +5 -0
  131. package/components/snake-popup/snake-popup.vue +348 -0
  132. package/components/snake-popup/types.ts +88 -0
  133. package/components/snake-qr-code/qrcode.ts +1214 -0
  134. package/components/snake-qr-code/snake-qr-code.vue +408 -0
  135. package/components/snake-qr-code/types.ts +78 -0
  136. package/components/snake-radio/snake-radio.vue +271 -0
  137. package/components/snake-radio/types.ts +64 -0
  138. package/components/snake-radio-group/snake-radio-group.vue +98 -0
  139. package/components/snake-radio-group/types.ts +48 -0
  140. package/components/snake-read-more/snake-read-more.vue +140 -0
  141. package/components/snake-read-more/types.ts +53 -0
  142. package/components/snake-rich-text/snake-rich-text.vue +24 -0
  143. package/components/snake-rich-text/types.ts +5 -0
  144. package/components/snake-root-portal/snake-root-portal.vue +92 -0
  145. package/components/snake-root-portal/types.ts +9 -0
  146. package/components/snake-search/snake-search.vue +202 -0
  147. package/components/snake-search/types.ts +84 -0
  148. package/components/snake-select/snake-select.vue +371 -0
  149. package/components/snake-select/types.ts +75 -0
  150. package/components/snake-skeleton/snake-skeleton.vue +104 -0
  151. package/components/snake-skeleton/types.ts +32 -0
  152. package/components/snake-skeleton-item/snake-skeleton-item.vue +90 -0
  153. package/components/snake-skeleton-item/types.ts +30 -0
  154. package/components/snake-slider/snake-slider.vue +249 -0
  155. package/components/snake-slider/types.ts +59 -0
  156. package/components/snake-sticky/snake-sticky.vue +178 -0
  157. package/components/snake-sticky/types.ts +48 -0
  158. package/components/snake-subsection/snake-subsection.vue +188 -0
  159. package/components/snake-subsection/types.ts +54 -0
  160. package/components/snake-swiper/snake-swiper.vue +229 -0
  161. package/components/snake-swiper/types.ts +79 -0
  162. package/components/snake-switch/snake-switch.vue +100 -0
  163. package/components/snake-switch/types.ts +41 -0
  164. package/components/snake-tabbar/snake-tabbar.vue +306 -0
  165. package/components/snake-tabbar/types.ts +93 -0
  166. package/components/snake-tabs/snake-tabs.vue +305 -0
  167. package/components/snake-tabs/types.ts +79 -0
  168. package/components/snake-text/snake-text.vue +292 -0
  169. package/components/snake-text/types.ts +100 -0
  170. package/components/snake-textarea/snake-textarea.vue +171 -0
  171. package/components/snake-textarea/types.ts +79 -0
  172. package/components/snake-toast/snake-toast.vue +330 -0
  173. package/components/snake-toast/types.ts +55 -0
  174. package/components/snake-tooltip/position.ts +33 -0
  175. package/components/snake-tooltip/snake-tooltip.vue +339 -0
  176. package/components/snake-tooltip/types.ts +80 -0
  177. package/components/snake-transition/snake-transition.vue +315 -0
  178. package/components/snake-transition/types.ts +65 -0
  179. package/components/snake-upload/snake-upload.vue +1801 -0
  180. package/components/snake-upload/types.ts +256 -0
  181. package/components/snake-videos/snake-videos.vue +122 -0
  182. package/components/snake-videos/types.ts +7 -0
  183. package/iconfont.css +881 -0
  184. package/index.d.ts +7 -0
  185. package/index.scss +26 -0
  186. package/index.ts +94 -0
  187. package/libs/cms/blocks.ts +103 -0
  188. package/libs/cms/config.ts +25 -0
  189. package/libs/cms/index.ts +7 -0
  190. package/libs/cms/normalize.ts +135 -0
  191. package/libs/cms/resolve.ts +12 -0
  192. package/libs/cms/types.ts +164 -0
  193. package/libs/cms/use-commerce.ts +385 -0
  194. package/libs/cms/v2.ts +193 -0
  195. package/libs/config/index.ts +4 -0
  196. package/libs/config/modal.ts +93 -0
  197. package/libs/config/state.ts +33 -0
  198. package/libs/config/theme.ts +351 -0
  199. package/libs/config/toast.ts +71 -0
  200. package/libs/config/types.ts +135 -0
  201. package/libs/config/zIndex.ts +44 -0
  202. package/libs/css/color.scss +105 -0
  203. package/libs/css/common.scss +171 -0
  204. package/libs/css/style.h5.scss +7 -0
  205. package/libs/css/style.mp.scss +7 -0
  206. package/libs/css/style.theme.scss +70 -0
  207. package/libs/css/style.vue.scss +140 -0
  208. package/libs/form/async-validator.min.d.ts +75 -0
  209. package/libs/form/async-validator.min.js +3 -0
  210. package/libs/form/index.ts +3 -0
  211. package/libs/form/path.ts +40 -0
  212. package/libs/form/types.ts +51 -0
  213. package/libs/form/validate.ts +149 -0
  214. package/libs/foundation.ts +96 -0
  215. package/libs/function/$parent.ts +33 -0
  216. package/libs/function/clipboard.ts +13 -0
  217. package/libs/function/color.ts +55 -0
  218. package/libs/function/debounce.ts +34 -0
  219. package/libs/function/deepClone.ts +30 -0
  220. package/libs/function/deepMerge.ts +25 -0
  221. package/libs/function/emitter.ts +30 -0
  222. package/libs/function/format.ts +27 -0
  223. package/libs/function/getParent.ts +53 -0
  224. package/libs/function/getRect.ts +29 -0
  225. package/libs/function/guid.ts +11 -0
  226. package/libs/function/index.ts +31 -0
  227. package/libs/function/queryParams.ts +73 -0
  228. package/libs/function/random.ts +6 -0
  229. package/libs/function/randomArray.ts +14 -0
  230. package/libs/function/route.ts +155 -0
  231. package/libs/function/sleep.ts +7 -0
  232. package/libs/function/style.ts +58 -0
  233. package/libs/function/styleUtils.ts +83 -0
  234. package/libs/function/system.ts +14 -0
  235. package/libs/function/test.ts +202 -0
  236. package/libs/function/throttle.ts +36 -0
  237. package/libs/function/timeFormat.ts +27 -0
  238. package/libs/function/timeFrom.ts +27 -0
  239. package/libs/function/toast.ts +10 -0
  240. package/libs/function/trim.ts +11 -0
  241. package/libs/function/type2icon.ts +11 -0
  242. package/libs/function/unit.ts +45 -0
  243. package/libs/hooks/index.ts +11 -0
  244. package/libs/hooks/useChildren.ts +125 -0
  245. package/libs/hooks/useColor.ts +5 -0
  246. package/libs/hooks/useDebounce.ts +5 -0
  247. package/libs/hooks/useLocale.ts +13 -0
  248. package/libs/hooks/useModal.ts +131 -0
  249. package/libs/hooks/useParent.ts +62 -0
  250. package/libs/hooks/useRect.ts +44 -0
  251. package/libs/hooks/useRouter.ts +5 -0
  252. package/libs/hooks/useTheme.ts +31 -0
  253. package/libs/hooks/useThrottle.ts +5 -0
  254. package/libs/hooks/useToast.ts +116 -0
  255. package/libs/index.ts +18 -0
  256. package/libs/request/auto-http.ts +1 -0
  257. package/libs/request/index.ts +343 -0
  258. package/libs/runtime/accessors.ts +55 -0
  259. package/libs/runtime/context.ts +40 -0
  260. package/libs/runtime/index.ts +18 -0
  261. package/libs/runtime/types.ts +49 -0
  262. package/libs/util/calendar.ts +6 -0
  263. package/locale/index.ts +130 -0
  264. package/locale/lang/en-US.ts +67 -0
  265. package/locale/lang/zh-CN.ts +67 -0
  266. package/package.json +130 -5
  267. package/plugins/index.ts +1 -0
  268. package/plugins/root/README.md +86 -0
  269. package/plugins/root/index.ts +123 -0
  270. package/plugins/root/page.ts +77 -0
  271. package/plugins/root/root.ts +53 -0
  272. package/plugins/root/utils.ts +137 -0
  273. package/readme.md +79 -0
  274. package/theme.scss +118 -0
  275. package/types/components.d.ts +236 -0
  276. package/types/global.d.ts +21 -0
  277. package/types/index.d.ts +6 -0
  278. package/types/uni-app.d.ts +16 -0
  279. package/README.md +0 -3
@@ -0,0 +1,234 @@
1
+ <template>
2
+ <!-- 外层添加高度 防止高度塌陷 -->
3
+ <view :style="{ height: height }">
4
+ <view :class="{ 'search-fixed': datas.position === 1 }">
5
+ <!-- 搜索 -->
6
+ <view class="search" :style="{ background: datas.backgroundColor, padding: `0 ${datas.pageMargin}rpx` }">
7
+ <!-- 搜索框 -->
8
+ <view
9
+ class="center"
10
+ :style="{
11
+ height: datas.heights + 'rpx',
12
+ background: datas.borderBgColor,
13
+ borderRadius: datas.borderRadius + 'rpx',
14
+ border: datas.showBorder ? `${datas.borderSize}rpx solid ${datas.borderColor}` : 'none'
15
+ }"
16
+ >
17
+ <view class="search-left">
18
+ <snake-icon name="search" size="44rpx" :color="datas.textColor"></snake-icon>
19
+ <!-- 占位符 -->
20
+ <view v-if="!datas.textList.length" class="input-search" @click="toPage(datas.url)">
21
+ <input
22
+ v-if="datas.isSearch"
23
+ class="input"
24
+ :type="datas.inputType"
25
+ :disabled="!datas.isSearch"
26
+ :placeholder="datas.searchText"
27
+ @confirm="confirm"
28
+ />
29
+ <text class="text" v-else :style="{ color: datas.textColor }">{{ datas.searchText }}</text>
30
+ </view>
31
+ <!-- 热词竖向滚动 -->
32
+ <view :style="{ width: hotordsWidth + 'px' }" v-else>
33
+ <snake-notice-bar
34
+ :datas="datas"
35
+ direction="column"
36
+ :icon="null"
37
+ :text="hotordsList"
38
+ :bgColor="datas.borderBgColor"
39
+ :color="datas.textColor"
40
+ :duration="3000"
41
+ :customStyle="{ padding: '9rpx 12rpx' }"
42
+ @click="hotordsClick"
43
+ ></snake-notice-bar>
44
+ </view>
45
+ </view>
46
+ <view
47
+ class="search-right"
48
+ :style="{ paddingRight: datas.rightImage.marginRight + 'rpx' }"
49
+ v-if="datas.rightImage.show"
50
+ >
51
+ <image
52
+ class="search-right-image"
53
+ :src="datas.rightImage.src"
54
+ :style="{
55
+ borderRadius: datas.rightImage.borderRadius + 'rpx',
56
+ width: datas.rightImage.width + 'rpx',
57
+ height: datas.rightImage.height + 'rpx'
58
+ }"
59
+ />
60
+ </view>
61
+ </view>
62
+ <!-- 右侧icon图片 最多两个 -->
63
+ <template v-if="datas.iconImgList.length !== 0">
64
+ <view
65
+ :id="item.id"
66
+ class="right"
67
+ v-for="(item, index) in datas.iconImgList"
68
+ :key="index"
69
+ @click="uni.$snake.navTo(item.url)"
70
+ >
71
+ <image
72
+ class="right-image"
73
+ :src="item.src"
74
+ :style="{ width: item.width + 'rpx', height: item.height + 'rpx' }"
75
+ />
76
+ </view>
77
+ </template>
78
+ </view>
79
+ </view>
80
+ </view>
81
+ </template>
82
+
83
+ <script>
84
+ /**
85
+ * @component CommoditySearch
86
+ * @description 提供可吸顶的商城搜索栏,支持输入搜索、热词轮播、右侧图片和快捷图标。
87
+ */
88
+
89
+ import { getCurrentInstance } from 'vue';
90
+ export default {
91
+ name: 'commoditysearch',
92
+ options: { virtualHost: true, styleIsolation: 'shared' },
93
+ props: { datas: Object },
94
+ emits: ['search'],
95
+ setup() {
96
+ const instance = getCurrentInstance();
97
+ return { instance };
98
+ },
99
+ data() {
100
+ return {
101
+ hotordsWidth: 0, // 热词滚动的宽度
102
+ height: 0 // 容器高度
103
+ };
104
+ },
105
+ computed: {
106
+ // 热词列表
107
+ hotordsList() {
108
+ let list = [];
109
+ if (this.datas.textList.length) {
110
+ list = this.datas.textList.map(item => item.text);
111
+ }
112
+ return list;
113
+ }
114
+ },
115
+ async mounted() {
116
+ await uni.$snake.sleep(100);
117
+ if (this.datas.position === 1) {
118
+ // 组件吸顶 获取占位的高度
119
+ uni.$snake.getRect('.search-fixed', this.instance).then(size => {
120
+ this.height = `${size.height}px`;
121
+ });
122
+ } else {
123
+ this.height = 'auto';
124
+ }
125
+ // 获取搜索框的占位文本,用于热词滚动的宽度
126
+ this.hotordsWidth = (await uni.$snake.getRect('.search-left', this.instance)).width;
127
+ if (this.datas.rightImage.show) {
128
+ this.hotordsWidth -= (await uni.$snake.getRect('.search-right', this.instance)).width;
129
+ }
130
+ },
131
+ methods: {
132
+ // 点击热词跳转
133
+ hotordsClick(index) {
134
+ uni.$snake.navTo(this.datas.textList[index].url);
135
+ },
136
+ toPage() {
137
+ // 如果可以回车搜索 则不能跳转
138
+ if (this.datas.isSearch) {
139
+ return false;
140
+ }
141
+ uni.$snake.navTo(this.datas.url);
142
+ },
143
+ confirm(e) {
144
+ const keyword = e.detail.value;
145
+ this.$emit('search', keyword);
146
+ if (this.datas.url) uni.$snake.navTo(this.datas.url + keyword);
147
+ }
148
+ }
149
+ };
150
+ </script>
151
+
152
+ <style scoped lang="scss">
153
+ .search-fixed {
154
+ position: fixed;
155
+ /* #ifndef MP-WEIXIN */
156
+ top: 0;
157
+ /* #endif */
158
+ /* #ifdef H5 */
159
+ top: 44px;
160
+ /* #endif */
161
+ left: 50%;
162
+ z-index: 9;
163
+ box-sizing: border-box;
164
+ width: 100%;
165
+ transform: translateX(-50%);
166
+ }
167
+
168
+ .search {
169
+ display: flex;
170
+ flex: 1;
171
+ align-items: center;
172
+
173
+ /* 搜索框 */
174
+ .center {
175
+ display: flex;
176
+ align-items: center;
177
+ justify-content: space-between;
178
+ width: 100%;
179
+ padding-left: 20rpx;
180
+ overflow: hidden;
181
+ font-size: 24rpx;
182
+
183
+ .search-left {
184
+ display: flex;
185
+ flex: 1;
186
+ align-items: center;
187
+
188
+ text:nth-child(2) {
189
+ width: 100%;
190
+ padding-left: 5rpx;
191
+ overflow: hidden; //超出的文本隐藏
192
+ text-overflow: ellipsis; //用省略号显示
193
+ font-size: 24rpx;
194
+ white-space: nowrap; //不换行
195
+ }
196
+
197
+ .input-search {
198
+ width: 100%;
199
+ padding-left: 10rpx;
200
+
201
+ .input {
202
+ width: 100%;
203
+ font-size: 24rpx;
204
+ }
205
+ .text {
206
+ font-size: 26rpx;
207
+ }
208
+ }
209
+ }
210
+
211
+ .search-right {
212
+ display: flex;
213
+ align-items: center;
214
+ justify-content: center;
215
+
216
+ .search-right-image {
217
+ width: 100%;
218
+ height: 100%;
219
+ }
220
+ }
221
+ }
222
+
223
+ .right {
224
+ display: flex;
225
+ flex: 1;
226
+ flex-direction: column;
227
+
228
+ .right-image {
229
+ width: 100%;
230
+ height: 100%;
231
+ }
232
+ }
233
+ }
234
+ </style>
@@ -0,0 +1,11 @@
1
+ /** CommoditySearch 组件的公开属性。 */
2
+ export interface CommoditySearchProps<Data extends Record<string, any> = Record<string, any>> {
3
+ /** CMS 装修组件配置数据。 */
4
+ datas?: Data;
5
+ }
6
+
7
+ /** 输入框确认搜索时发出的事件。 */
8
+ export interface CommoditySearchEmits {
9
+ /** 用户确认搜索时输入的关键词。 */
10
+ search: [keyword: string];
11
+ }
@@ -0,0 +1,61 @@
1
+ <template>
2
+ <view
3
+ :class="['snake-config-provider', `snake-theme-${mode}`, customClass]"
4
+ :data-snake-theme-mode="mode"
5
+ :style="[$themeStyle, customStyle]"
6
+ >
7
+ <slot />
8
+ </view>
9
+ </template>
10
+
11
+ <script setup lang="ts">
12
+ /**
13
+ * @component ConfigProvider
14
+ * @description `snake-config-provider` 是 Snake UI 主题系统的页面入口组件,负责把当前主题的 CSS 变量注入页面,并根据主题模式附加明亮或暗黑类名。将它与 `Root` 插件配合使用,可以让主题配置自动作用于每个页面,无需逐页添加组件。
15
+ * @see /components/config-provider
16
+ */
17
+
18
+ /**
19
+ * snake-config-provider 全局主题配置入口
20
+ *
21
+ * 把主题引擎的 CSS 变量内联到页面根部并携带暗色 class:
22
+ * - uni-app H5 会把 `page` 选择器编译为 uni-page-body,自定义属性在声明处
23
+ * 完成 var() 代换后按字面值继承,仅挂在 html 上的暗色覆写无法穿透页面内容;
24
+ * - 本组件经 vite-plugin-snake-root 包裹到每个页面根部后,主题变量对全页生效,
25
+ * 小程序端(无 document)同样可用。
26
+ *
27
+ * 可选 bootstrap:传入 currentTheme / darkMode 时,挂载及变化时同步到主题引擎
28
+ * (含 storage 持久化),便于在 App.root.vue 中声明式固定初始主题。
29
+ */
30
+ import { computed, onMounted, watch } from 'vue';
31
+ import { currentTheme, setDarkMode, setTheme, darkMode, systemDark } from '../../libs/config/theme';
32
+ import type { ConfigProviderEmits, ConfigProviderProps } from './types';
33
+
34
+ defineOptions({ name: 'ConfigProvider', options: { virtualHost: true, styleIsolation: 'shared' } });
35
+ const props = withDefaults(defineProps<ConfigProviderProps>(), {
36
+ darkMode: undefined,
37
+ currentTheme: '',
38
+ customClass: '',
39
+ customStyle: ''
40
+ });
41
+ const emit = defineEmits<ConfigProviderEmits>();
42
+
43
+ const mode = computed<'light' | 'dark'>(() =>
44
+ darkMode.value === 'auto' ? (systemDark.value ? 'dark' : 'light') : darkMode.value
45
+ );
46
+
47
+ function bootstrap() {
48
+ if (props.currentTheme && props.currentTheme !== currentTheme.value.name) {
49
+ if (setTheme(props.currentTheme)) emit('theme-change', props.currentTheme);
50
+ }
51
+ if (props.darkMode && props.darkMode !== darkMode.value) {
52
+ setDarkMode(props.darkMode);
53
+ emit('mode-change', mode.value);
54
+ }
55
+ }
56
+
57
+ onMounted(bootstrap);
58
+ watch(() => [props.currentTheme, props.darkMode], bootstrap);
59
+ </script>
60
+
61
+ <style lang="scss" scoped></style>
@@ -0,0 +1,22 @@
1
+ import type { DarkMode } from '../../libs/config/types';
2
+ import type { StyleValue } from '../../types/global';
3
+
4
+ /** ConfigProvider 组件的公开属性。 */
5
+ export interface ConfigProviderProps {
6
+ /** 初始化/切换暗黑模式(light | dark | auto),不传则沿用当前引擎状态 */
7
+ darkMode?: DarkMode;
8
+ /** 初始化/切换主题名(需已通过 app.use 注册主题),不传则沿用当前主题 */
9
+ currentTheme?: string;
10
+ /** 根节点自定义类名。 */
11
+ customClass?: string;
12
+ /** 根节点自定义样式。 */
13
+ customStyle?: StyleValue;
14
+ }
15
+
16
+ /** ConfigProvider 组件的事件契约。 */
17
+ export type ConfigProviderEmits = {
18
+ /** theme-change 事件携带的参数。 */
19
+ 'theme-change': [themeName: string];
20
+ /** mode-change 事件携带的参数。 */
21
+ 'mode-change': [mode: 'light' | 'dark'];
22
+ };
@@ -0,0 +1,231 @@
1
+ <template>
2
+ <view class="snake-countdown" :class="customClass" :style="customStyle">
3
+ <view class="snake-countdown__item" :style="itemStyle" v-if="showDays && (!hideZeroDay || d !== '00')">
4
+ <view class="snake-countdown__time" :style="letterStyle">
5
+ {{ d }}
6
+ </view>
7
+ </view>
8
+ <view
9
+ class="snake-countdown__colon"
10
+ :style="{
11
+ fontSize: separatorSize + 'rpx',
12
+ color: separatorColor,
13
+ paddingBottom: separator === 'colon' ? '4rpx' : 0
14
+ }"
15
+ v-if="showDays && (!hideZeroDay || d !== '00')"
16
+ >
17
+ {{ separator === 'colon' && showHours ? ':' : t('day') }}
18
+ </view>
19
+ <view class="snake-countdown__item" :style="itemStyle" v-if="showHours">
20
+ <view class="snake-countdown__time" :style="{ fontSize: fontSize + 'rpx', color: color }">
21
+ {{ h }}
22
+ </view>
23
+ </view>
24
+ <view
25
+ class="snake-countdown__colon"
26
+ :style="{
27
+ fontSize: separatorSize + 'rpx',
28
+ color: separatorColor,
29
+ paddingBottom: separator === 'colon' ? '4rpx' : 0
30
+ }"
31
+ v-if="showHours"
32
+ >
33
+ {{ separator === 'colon' && showMinutes ? ':' : t('hour') }}
34
+ </view>
35
+ <view class="snake-countdown__item" :style="itemStyle" v-if="showMinutes">
36
+ <view class="snake-countdown__time" :style="{ fontSize: fontSize + 'rpx', color: color }">
37
+ {{ i }}
38
+ </view>
39
+ </view>
40
+ <view
41
+ class="snake-countdown__colon"
42
+ :style="{
43
+ fontSize: separatorSize + 'rpx',
44
+ color: separatorColor,
45
+ paddingBottom: separator === 'colon' ? '4rpx' : 0
46
+ }"
47
+ v-if="showMinutes"
48
+ >
49
+ {{ separator === 'colon' && showSeconds ? ':' : t('minute') }}
50
+ </view>
51
+ <view class="snake-countdown__item" :style="itemStyle" v-if="showSeconds">
52
+ <view class="snake-countdown__time" :style="{ fontSize: fontSize + 'rpx', color: color }">
53
+ {{ s }}
54
+ </view>
55
+ </view>
56
+ <view
57
+ class="snake-countdown__colon"
58
+ :style="{ fontSize: separatorSize + 'rpx', color: separatorColor, paddingBottom: 0 }"
59
+ v-if="showSeconds && separator === 'zh'"
60
+ >
61
+ {{ t('second') }}
62
+ </view>
63
+ </view>
64
+ </template>
65
+
66
+ <script setup lang="ts">
67
+ /**
68
+ * @component CountDown
69
+ * @description 倒计时组件,用于活动截止等场景,通过数字变化给用户明确的时间感受;支持时分秒显示开关、分隔符形态与样式定制。
70
+ * @see /components/count-down
71
+ */
72
+
73
+ import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
74
+ import { useLocale } from '../../libs/hooks/useLocale';
75
+ import { countDownProps } from './types';
76
+ import type { CountDownEmits, CountDownExpose } from './types';
77
+
78
+ defineOptions({ name: 'CountDown', options: { virtualHost: true, styleIsolation: 'shared' } });
79
+
80
+ const props = defineProps(countDownProps);
81
+ const emit = defineEmits<CountDownEmits>();
82
+ const { t } = useLocale('countDown');
83
+
84
+ const d = ref('00'); // 天
85
+ const h = ref('00'); // 小时
86
+ const i = ref('00'); // 分钟
87
+ const s = ref('00'); // 秒
88
+ const timer = ref<ReturnType<typeof setInterval> | null>(null); // 定时器
89
+ const seconds = ref(0);
90
+
91
+ /** 数字块(时分秒部分)的样式。 */
92
+ const itemStyle = computed(() => {
93
+ const style: Record<string, string> = {};
94
+ if (props.height) {
95
+ style.height = props.height + 'rpx';
96
+ style.width = props.height + 'rpx';
97
+ }
98
+ if (props.showBorder) {
99
+ style.borderStyle = 'solid';
100
+ style.borderColor = props.borderColor;
101
+ style.borderWidth = '1px';
102
+ }
103
+ if (props.bgColor) {
104
+ style.backgroundColor = props.bgColor;
105
+ }
106
+ return style;
107
+ });
108
+
109
+ /** 数字文字的样式。 */
110
+ const letterStyle = computed(() => {
111
+ const style: Record<string, string> = {};
112
+ if (props.fontSize) style.fontSize = props.fontSize + 'rpx';
113
+ if (props.color) style.color = props.color;
114
+ return style;
115
+ });
116
+
117
+ // 时间戳变化时重新开始倒计时
118
+ watch(
119
+ () => props.timestamp,
120
+ () => {
121
+ clearTimer();
122
+ start();
123
+ }
124
+ );
125
+
126
+ onMounted(() => {
127
+ if (props.autoplay && props.timestamp) {
128
+ start();
129
+ }
130
+ });
131
+ onBeforeUnmount(clearTimer);
132
+
133
+ /** 开始倒计时。 */
134
+ function start() {
135
+ // 避免可能出现的倒计时重叠
136
+ clearTimer();
137
+ if (Number(props.timestamp) <= 0) return;
138
+ seconds.value = Number(props.timestamp);
139
+ formatTime(seconds.value);
140
+ timer.value = setInterval(() => {
141
+ seconds.value--;
142
+ emit('change', seconds.value);
143
+ if (seconds.value < 0) {
144
+ end();
145
+ return;
146
+ }
147
+ formatTime(seconds.value);
148
+ }, 1000);
149
+ }
150
+
151
+ /** 将剩余秒数格式化到 d/h/i/s。 */
152
+ function formatTime(sec: number) {
153
+ if (sec <= 0) end();
154
+ const dayNum = Math.floor(sec / (60 * 60 * 24));
155
+ const hourNum = Math.floor(sec / (60 * 60)) - dayNum * 24;
156
+ // 不显示天时,把天的部分折算进小时
157
+ let showHour: string;
158
+ if (props.showDays) {
159
+ showHour = hourNum < 10 ? `0${hourNum}` : String(hourNum);
160
+ } else {
161
+ const hourTotal = Math.floor(sec / (60 * 60));
162
+ showHour = hourTotal < 10 ? `0${hourTotal}` : String(hourTotal);
163
+ }
164
+ const minuteNum = Math.floor(sec / 60) - hourNum * 60 - dayNum * 24 * 60;
165
+ const secondNum = Math.floor(sec) - dayNum * 24 * 60 * 60 - hourNum * 60 * 60 - minuteNum * 60;
166
+ const minute = minuteNum < 10 ? `0${minuteNum}` : String(minuteNum);
167
+ const second = secondNum < 10 ? `0${secondNum}` : String(secondNum);
168
+ const day = dayNum < 10 ? `0${dayNum}` : String(dayNum);
169
+ d.value = day;
170
+ h.value = showHour;
171
+ i.value = minute;
172
+ s.value = second;
173
+ }
174
+
175
+ /** 结束倒计时。 */
176
+ function end() {
177
+ clearTimer();
178
+ emit('end');
179
+ }
180
+
181
+ /**
182
+ * 主动停止倒计时,不触发 end 事件。
183
+ * 适用于父组件切换场景或业务主动销毁计时任务。
184
+ */
185
+ function destroy() {
186
+ clearTimer();
187
+ }
188
+
189
+ /** 清除定时器。 */
190
+ function clearTimer() {
191
+ if (timer.value) {
192
+ clearInterval(timer.value);
193
+ timer.value = null;
194
+ }
195
+ }
196
+
197
+ defineExpose<CountDownExpose>({
198
+ start,
199
+ end,
200
+ destroy
201
+ });
202
+ </script>
203
+
204
+ <style scoped>
205
+ .snake-countdown {
206
+ display: inline-flex;
207
+ align-items: center;
208
+ }
209
+ .snake-countdown__item {
210
+ display: flex;
211
+ align-items: center;
212
+ justify-content: center;
213
+ padding: 2rpx;
214
+ border-radius: 6rpx;
215
+ white-space: nowrap;
216
+ transform: translateZ(0);
217
+ }
218
+ .snake-countdown__time {
219
+ margin: 0;
220
+ padding: 0;
221
+ line-height: 1;
222
+ }
223
+ .snake-countdown__colon {
224
+ display: flex;
225
+ align-items: center;
226
+ justify-content: center;
227
+ padding: 0 5rpx;
228
+ padding-bottom: 4rpx;
229
+ line-height: 1;
230
+ }
231
+ </style>
@@ -0,0 +1,103 @@
1
+ import type { ExtractPropTypes, PropType } from 'vue';
2
+ import type { StyleValue } from '../../types/global';
3
+
4
+ /** countDownProps 运行时属性及默认值。 */
5
+ export const countDownProps = {
6
+ /** 根节点自定义类名。 */
7
+ customClass: { type: String, default: '' },
8
+ /** 根节点自定义样式。 */
9
+ customStyle: { type: [String, Object, Array] as PropType<StyleValue>, default: '' },
10
+ /** 倒计时剩余秒数。 */
11
+ timestamp: { type: [Number, String] as PropType<number | string>, default: 0 },
12
+ /** 是否挂载后自动开始倒计时。 */
13
+ autoplay: { type: Boolean, default: true },
14
+ /** 分隔符形态,colon 为英文冒号,zh 为中文单位。 */
15
+ separator: { type: String as PropType<'colon' | 'zh'>, default: 'colon' },
16
+ /** 分隔符大小,单位 rpx。 */
17
+ separatorSize: { type: [Number, String] as PropType<number | string>, default: 30 },
18
+ /** 分隔符颜色。 */
19
+ separatorColor: { type: String, default: 'var(--snake-color-text, #22292f)' },
20
+ /** 倒计时数字颜色。 */
21
+ color: { type: String, default: 'var(--snake-color-text, #22292f)' },
22
+ /** 倒计时数字大小,单位 rpx。 */
23
+ fontSize: { type: [Number, String] as PropType<number | string>, default: 30 },
24
+ /** 倒计时数字背景颜色。 */
25
+ bgColor: { type: String, default: 'var(--snake-color-surface, #fff)' },
26
+ /** 数字块高度(宽度同值),单位 rpx。 */
27
+ height: { type: [Number, String] as PropType<number | string>, default: 'auto' },
28
+ /** 是否显示数字边框。 */
29
+ showBorder: { type: Boolean, default: false },
30
+ /** 数字边框颜色。 */
31
+ borderColor: { type: String, default: 'var(--snake-color-text, #22292f)' },
32
+ /** 是否显示秒。 */
33
+ showSeconds: { type: Boolean, default: true },
34
+ /** 是否显示分钟。 */
35
+ showMinutes: { type: Boolean, default: true },
36
+ /** 是否显示小时。 */
37
+ showHours: { type: Boolean, default: true },
38
+ /** 是否显示天。 */
39
+ showDays: { type: Boolean, default: true },
40
+ /** 天数为 0 时是否隐藏天部分。 */
41
+ hideZeroDay: { type: Boolean, default: false }
42
+ } as const;
43
+
44
+ /** CountDownResolved 组件的解析属性。 */
45
+ export type CountDownResolvedProps = ExtractPropTypes<typeof countDownProps>;
46
+
47
+ /** CountDown 组件的公开属性。 */
48
+ export interface CountDownProps {
49
+ /** 根节点自定义类名。 */
50
+ customClass?: string;
51
+ /** 根节点自定义样式。 */
52
+ customStyle?: StyleValue;
53
+ /** 倒计时剩余秒数。 */
54
+ timestamp?: number | string;
55
+ /** 是否挂载后自动开始倒计时。 */
56
+ autoplay?: boolean;
57
+ /** 分隔符形态,colon 为英文冒号,zh 为中文单位。 */
58
+ separator?: 'colon' | 'zh';
59
+ /** 分隔符大小,单位 rpx。 */
60
+ separatorSize?: number | string;
61
+ /** 分隔符颜色。 */
62
+ separatorColor?: string;
63
+ /** 倒计时数字颜色。 */
64
+ color?: string;
65
+ /** 倒计时数字大小,单位 rpx。 */
66
+ fontSize?: number | string;
67
+ /** 倒计时数字背景颜色。 */
68
+ bgColor?: string;
69
+ /** 数字块高度(宽度同值),单位 rpx。 */
70
+ height?: number | string;
71
+ /** 是否显示数字边框。 */
72
+ showBorder?: boolean;
73
+ /** 数字边框颜色。 */
74
+ borderColor?: string;
75
+ /** 是否显示秒。 */
76
+ showSeconds?: boolean;
77
+ /** 是否显示分钟。 */
78
+ showMinutes?: boolean;
79
+ /** 是否显示小时。 */
80
+ showHours?: boolean;
81
+ /** 是否显示天。 */
82
+ showDays?: boolean;
83
+ /** 天数为 0 时是否隐藏天部分。 */
84
+ hideZeroDay?: boolean;
85
+ }
86
+
87
+ /** CountDown 组件的事件契约。 */
88
+ export type CountDownEmits = {
89
+ /** 倒计时结束时触发。 */
90
+ end: [];
91
+ /** 每秒触发一次,参数为剩余秒数。 */
92
+ change: [seconds: number];
93
+ };
94
+
95
+ /** CountDown 组件暴露的方法。 */
96
+ export interface CountDownExpose {
97
+ /** 开始倒计时。 */
98
+ start: () => void;
99
+ /** 结束倒计时。 */
100
+ end: () => void;
101
+ /** 主动停止倒计时,不触发 end 事件。 */
102
+ destroy: () => void;
103
+ }