wedux-ui 0.1.0

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 (231) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +184 -0
  3. package/miniprogram_dist/behaviors/formField.js +35 -0
  4. package/miniprogram_dist/components/avatar/avatar.js +70 -0
  5. package/miniprogram_dist/components/avatar/avatar.json +4 -0
  6. package/miniprogram_dist/components/avatar/avatar.scss +68 -0
  7. package/miniprogram_dist/components/avatar/avatar.wxml +15 -0
  8. package/miniprogram_dist/components/avatar-group/avatar-group.js +45 -0
  9. package/miniprogram_dist/components/avatar-group/avatar-group.json +7 -0
  10. package/miniprogram_dist/components/avatar-group/avatar-group.scss +4 -0
  11. package/miniprogram_dist/components/avatar-group/avatar-group.wxml +3 -0
  12. package/miniprogram_dist/components/back-top/back-top.js +68 -0
  13. package/miniprogram_dist/components/back-top/back-top.json +4 -0
  14. package/miniprogram_dist/components/back-top/back-top.scss +43 -0
  15. package/miniprogram_dist/components/back-top/back-top.wxml +10 -0
  16. package/miniprogram_dist/components/badge/badge.js +100 -0
  17. package/miniprogram_dist/components/badge/badge.json +4 -0
  18. package/miniprogram_dist/components/badge/badge.scss +98 -0
  19. package/miniprogram_dist/components/badge/badge.wxml +11 -0
  20. package/miniprogram_dist/components/button/button.js +152 -0
  21. package/miniprogram_dist/components/button/button.json +4 -0
  22. package/miniprogram_dist/components/button/button.scss +499 -0
  23. package/miniprogram_dist/components/button/button.wxml +21 -0
  24. package/miniprogram_dist/components/button-group/button-group.js +51 -0
  25. package/miniprogram_dist/components/button-group/button-group.json +4 -0
  26. package/miniprogram_dist/components/button-group/button-group.scss +8 -0
  27. package/miniprogram_dist/components/button-group/button-group.wxml +3 -0
  28. package/miniprogram_dist/components/calendar/calendar.js +308 -0
  29. package/miniprogram_dist/components/calendar/calendar.json +4 -0
  30. package/miniprogram_dist/components/calendar/calendar.scss +141 -0
  31. package/miniprogram_dist/components/calendar/calendar.wxml +47 -0
  32. package/miniprogram_dist/components/card/card.js +44 -0
  33. package/miniprogram_dist/components/card/card.json +4 -0
  34. package/miniprogram_dist/components/card/card.scss +143 -0
  35. package/miniprogram_dist/components/card/card.wxml +31 -0
  36. package/miniprogram_dist/components/checkbox/checkbox.js +43 -0
  37. package/miniprogram_dist/components/checkbox/checkbox.json +4 -0
  38. package/miniprogram_dist/components/checkbox/checkbox.scss +77 -0
  39. package/miniprogram_dist/components/checkbox/checkbox.wxml +13 -0
  40. package/miniprogram_dist/components/checkbox-button/checkbox-button.js +43 -0
  41. package/miniprogram_dist/components/checkbox-button/checkbox-button.json +4 -0
  42. package/miniprogram_dist/components/checkbox-button/checkbox-button.scss +39 -0
  43. package/miniprogram_dist/components/checkbox-button/checkbox-button.wxml +8 -0
  44. package/miniprogram_dist/components/checkbox-group/checkbox-group.js +84 -0
  45. package/miniprogram_dist/components/checkbox-group/checkbox-group.json +4 -0
  46. package/miniprogram_dist/components/checkbox-group/checkbox-group.scss +9 -0
  47. package/miniprogram_dist/components/checkbox-group/checkbox-group.wxml +3 -0
  48. package/miniprogram_dist/components/color-picker/color-picker.js +348 -0
  49. package/miniprogram_dist/components/color-picker/color-picker.json +7 -0
  50. package/miniprogram_dist/components/color-picker/color-picker.scss +383 -0
  51. package/miniprogram_dist/components/color-picker/color-picker.wxml +232 -0
  52. package/miniprogram_dist/components/date-picker/date-picker.js +1289 -0
  53. package/miniprogram_dist/components/date-picker/date-picker.json +7 -0
  54. package/miniprogram_dist/components/date-picker/date-picker.scss +468 -0
  55. package/miniprogram_dist/components/date-picker/date-picker.wxml +214 -0
  56. package/miniprogram_dist/components/divider/divider.js +34 -0
  57. package/miniprogram_dist/components/divider/divider.json +4 -0
  58. package/miniprogram_dist/components/divider/divider.scss +75 -0
  59. package/miniprogram_dist/components/divider/divider.wxml +8 -0
  60. package/miniprogram_dist/components/drawer/drawer.js +104 -0
  61. package/miniprogram_dist/components/drawer/drawer.json +4 -0
  62. package/miniprogram_dist/components/drawer/drawer.scss +171 -0
  63. package/miniprogram_dist/components/drawer/drawer.wxml +22 -0
  64. package/miniprogram_dist/components/ellipsis/ellipsis.js +38 -0
  65. package/miniprogram_dist/components/ellipsis/ellipsis.json +4 -0
  66. package/miniprogram_dist/components/ellipsis/ellipsis.scss +22 -0
  67. package/miniprogram_dist/components/ellipsis/ellipsis.wxml +7 -0
  68. package/miniprogram_dist/components/flex/flex.js +81 -0
  69. package/miniprogram_dist/components/flex/flex.json +4 -0
  70. package/miniprogram_dist/components/flex/flex.scss +4 -0
  71. package/miniprogram_dist/components/flex/flex.wxml +3 -0
  72. package/miniprogram_dist/components/float-button/float-button.js +78 -0
  73. package/miniprogram_dist/components/float-button/float-button.json +4 -0
  74. package/miniprogram_dist/components/float-button/float-button.scss +54 -0
  75. package/miniprogram_dist/components/float-button/float-button.wxml +9 -0
  76. package/miniprogram_dist/components/form/form.js +142 -0
  77. package/miniprogram_dist/components/form/form.json +4 -0
  78. package/miniprogram_dist/components/form/form.scss +11 -0
  79. package/miniprogram_dist/components/form/form.wxml +3 -0
  80. package/miniprogram_dist/components/form/validator.js +220 -0
  81. package/miniprogram_dist/components/form-item/form-item.js +240 -0
  82. package/miniprogram_dist/components/form-item/form-item.json +4 -0
  83. package/miniprogram_dist/components/form-item/form-item.scss +59 -0
  84. package/miniprogram_dist/components/form-item/form-item.wxml +33 -0
  85. package/miniprogram_dist/components/gradient-text/gradient-text.js +54 -0
  86. package/miniprogram_dist/components/gradient-text/gradient-text.json +4 -0
  87. package/miniprogram_dist/components/gradient-text/gradient-text.scss +7 -0
  88. package/miniprogram_dist/components/gradient-text/gradient-text.wxml +1 -0
  89. package/miniprogram_dist/components/h/h.js +60 -0
  90. package/miniprogram_dist/components/h/h.json +4 -0
  91. package/miniprogram_dist/components/h/h.scss +53 -0
  92. package/miniprogram_dist/components/h/h.wxml +1 -0
  93. package/miniprogram_dist/components/highlight/highlight.js +77 -0
  94. package/miniprogram_dist/components/highlight/highlight.json +4 -0
  95. package/miniprogram_dist/components/highlight/highlight.scss +8 -0
  96. package/miniprogram_dist/components/highlight/highlight.wxml +12 -0
  97. package/miniprogram_dist/components/infinite-scroll/infinite-scroll.js +31 -0
  98. package/miniprogram_dist/components/infinite-scroll/infinite-scroll.json +4 -0
  99. package/miniprogram_dist/components/infinite-scroll/infinite-scroll.scss +31 -0
  100. package/miniprogram_dist/components/infinite-scroll/infinite-scroll.wxml +12 -0
  101. package/miniprogram_dist/components/input/input.js +59 -0
  102. package/miniprogram_dist/components/input/input.json +4 -0
  103. package/miniprogram_dist/components/input/input.scss +96 -0
  104. package/miniprogram_dist/components/input/input.wxml +34 -0
  105. package/miniprogram_dist/components/input-otp/input-otp.js +106 -0
  106. package/miniprogram_dist/components/input-otp/input-otp.json +4 -0
  107. package/miniprogram_dist/components/input-otp/input-otp.scss +122 -0
  108. package/miniprogram_dist/components/input-otp/input-otp.wxml +38 -0
  109. package/miniprogram_dist/components/layout/layout.js +50 -0
  110. package/miniprogram_dist/components/layout/layout.json +4 -0
  111. package/miniprogram_dist/components/layout/layout.scss +10 -0
  112. package/miniprogram_dist/components/layout/layout.wxml +3 -0
  113. package/miniprogram_dist/components/layout-content/layout-content.js +47 -0
  114. package/miniprogram_dist/components/layout-content/layout-content.json +4 -0
  115. package/miniprogram_dist/components/layout-content/layout-content.scss +5 -0
  116. package/miniprogram_dist/components/layout-content/layout-content.wxml +13 -0
  117. package/miniprogram_dist/components/layout-footer/layout-footer.js +59 -0
  118. package/miniprogram_dist/components/layout-footer/layout-footer.json +4 -0
  119. package/miniprogram_dist/components/layout-footer/layout-footer.scss +23 -0
  120. package/miniprogram_dist/components/layout-footer/layout-footer.wxml +16 -0
  121. package/miniprogram_dist/components/layout-header/layout-header.js +59 -0
  122. package/miniprogram_dist/components/layout-header/layout-header.json +4 -0
  123. package/miniprogram_dist/components/layout-header/layout-header.scss +23 -0
  124. package/miniprogram_dist/components/layout-header/layout-header.wxml +16 -0
  125. package/miniprogram_dist/components/layout-sider/layout-sider.js +48 -0
  126. package/miniprogram_dist/components/layout-sider/layout-sider.json +4 -0
  127. package/miniprogram_dist/components/layout-sider/layout-sider.scss +13 -0
  128. package/miniprogram_dist/components/layout-sider/layout-sider.wxml +5 -0
  129. package/miniprogram_dist/components/list/list.js +55 -0
  130. package/miniprogram_dist/components/list/list.json +4 -0
  131. package/miniprogram_dist/components/list/list.scss +51 -0
  132. package/miniprogram_dist/components/list/list.wxml +9 -0
  133. package/miniprogram_dist/components/list-item/list-item.js +24 -0
  134. package/miniprogram_dist/components/list-item/list-item.json +4 -0
  135. package/miniprogram_dist/components/list-item/list-item.scss +51 -0
  136. package/miniprogram_dist/components/list-item/list-item.wxml +14 -0
  137. package/miniprogram_dist/components/navigation-bar/navigation-bar.js +77 -0
  138. package/miniprogram_dist/components/navigation-bar/navigation-bar.json +4 -0
  139. package/miniprogram_dist/components/navigation-bar/navigation-bar.scss +63 -0
  140. package/miniprogram_dist/components/navigation-bar/navigation-bar.wxml +35 -0
  141. package/miniprogram_dist/components/number-animation/number-animation.js +124 -0
  142. package/miniprogram_dist/components/number-animation/number-animation.json +4 -0
  143. package/miniprogram_dist/components/number-animation/number-animation.scss +3 -0
  144. package/miniprogram_dist/components/number-animation/number-animation.wxml +1 -0
  145. package/miniprogram_dist/components/popover/popover.js +183 -0
  146. package/miniprogram_dist/components/popover/popover.json +4 -0
  147. package/miniprogram_dist/components/popover/popover.scss +69 -0
  148. package/miniprogram_dist/components/popover/popover.wxml +19 -0
  149. package/miniprogram_dist/components/qr-code/qr-code.js +216 -0
  150. package/miniprogram_dist/components/qr-code/qr-code.json +4 -0
  151. package/miniprogram_dist/components/qr-code/qr-code.scss +8 -0
  152. package/miniprogram_dist/components/qr-code/qr-code.wxml +16 -0
  153. package/miniprogram_dist/components/radio/radio.js +38 -0
  154. package/miniprogram_dist/components/radio/radio.json +4 -0
  155. package/miniprogram_dist/components/radio/radio.scss +50 -0
  156. package/miniprogram_dist/components/radio/radio.wxml +12 -0
  157. package/miniprogram_dist/components/radio-button/radio-button.js +39 -0
  158. package/miniprogram_dist/components/radio-button/radio-button.json +4 -0
  159. package/miniprogram_dist/components/radio-button/radio-button.scss +39 -0
  160. package/miniprogram_dist/components/radio-button/radio-button.wxml +8 -0
  161. package/miniprogram_dist/components/radio-group/radio-group.js +72 -0
  162. package/miniprogram_dist/components/radio-group/radio-group.json +4 -0
  163. package/miniprogram_dist/components/radio-group/radio-group.scss +9 -0
  164. package/miniprogram_dist/components/radio-group/radio-group.wxml +3 -0
  165. package/miniprogram_dist/components/rate/rate.js +90 -0
  166. package/miniprogram_dist/components/rate/rate.json +4 -0
  167. package/miniprogram_dist/components/rate/rate.scss +59 -0
  168. package/miniprogram_dist/components/rate/rate.wxml +16 -0
  169. package/miniprogram_dist/components/select/select.js +201 -0
  170. package/miniprogram_dist/components/select/select.json +7 -0
  171. package/miniprogram_dist/components/select/select.scss +235 -0
  172. package/miniprogram_dist/components/select/select.wxml +79 -0
  173. package/miniprogram_dist/components/stepper/stepper.js +113 -0
  174. package/miniprogram_dist/components/stepper/stepper.json +4 -0
  175. package/miniprogram_dist/components/stepper/stepper.scss +73 -0
  176. package/miniprogram_dist/components/stepper/stepper.wxml +23 -0
  177. package/miniprogram_dist/components/switch/switch.js +42 -0
  178. package/miniprogram_dist/components/switch/switch.json +4 -0
  179. package/miniprogram_dist/components/switch/switch.scss +77 -0
  180. package/miniprogram_dist/components/switch/switch.wxml +10 -0
  181. package/miniprogram_dist/components/tab-bar/tab-bar.js +53 -0
  182. package/miniprogram_dist/components/tab-bar/tab-bar.json +4 -0
  183. package/miniprogram_dist/components/tab-bar/tab-bar.scss +53 -0
  184. package/miniprogram_dist/components/tab-bar/tab-bar.wxml +12 -0
  185. package/miniprogram_dist/components/tag/tag.js +87 -0
  186. package/miniprogram_dist/components/tag/tag.json +4 -0
  187. package/miniprogram_dist/components/tag/tag.scss +138 -0
  188. package/miniprogram_dist/components/tag/tag.wxml +12 -0
  189. package/miniprogram_dist/components/textarea/textarea.js +46 -0
  190. package/miniprogram_dist/components/textarea/textarea.json +4 -0
  191. package/miniprogram_dist/components/textarea/textarea.scss +51 -0
  192. package/miniprogram_dist/components/textarea/textarea.wxml +20 -0
  193. package/miniprogram_dist/components/theme-provider/presets.js +101 -0
  194. package/miniprogram_dist/components/theme-provider/theme-provider.js +34 -0
  195. package/miniprogram_dist/components/theme-provider/theme-provider.json +4 -0
  196. package/miniprogram_dist/components/theme-provider/theme-provider.scss +3 -0
  197. package/miniprogram_dist/components/theme-provider/theme-provider.wxml +3 -0
  198. package/miniprogram_dist/components/time-picker/time-picker.js +136 -0
  199. package/miniprogram_dist/components/time-picker/time-picker.json +7 -0
  200. package/miniprogram_dist/components/time-picker/time-picker.scss +135 -0
  201. package/miniprogram_dist/components/time-picker/time-picker.wxml +47 -0
  202. package/miniprogram_dist/components/tooltip/tooltip.js +179 -0
  203. package/miniprogram_dist/components/tooltip/tooltip.json +4 -0
  204. package/miniprogram_dist/components/tooltip/tooltip.scss +66 -0
  205. package/miniprogram_dist/components/tooltip/tooltip.wxml +17 -0
  206. package/miniprogram_dist/components/tree/tree.js +647 -0
  207. package/miniprogram_dist/components/tree/tree.json +4 -0
  208. package/miniprogram_dist/components/tree/tree.scss +178 -0
  209. package/miniprogram_dist/components/tree/tree.wxml +59 -0
  210. package/miniprogram_dist/components/tree-select/tree-select.js +260 -0
  211. package/miniprogram_dist/components/tree-select/tree-select.json +8 -0
  212. package/miniprogram_dist/components/tree-select/tree-select.scss +250 -0
  213. package/miniprogram_dist/components/tree-select/tree-select.wxml +118 -0
  214. package/miniprogram_dist/components/upload/upload.js +387 -0
  215. package/miniprogram_dist/components/upload/upload.json +4 -0
  216. package/miniprogram_dist/components/upload/upload.scss +258 -0
  217. package/miniprogram_dist/components/upload/upload.wxml +142 -0
  218. package/miniprogram_dist/components/watermark/watermark.js +260 -0
  219. package/miniprogram_dist/components/watermark/watermark.json +4 -0
  220. package/miniprogram_dist/components/watermark/watermark.scss +35 -0
  221. package/miniprogram_dist/components/watermark/watermark.wxml +13 -0
  222. package/miniprogram_dist/libs/qrcodegen.js +714 -0
  223. package/miniprogram_dist/libs/seemly.min.js +547 -0
  224. package/miniprogram_dist/libs/tempo_1_0_0.js +1264 -0
  225. package/miniprogram_dist/libs/validator_13_56_26.min.js +5282 -0
  226. package/miniprogram_dist/styles/demo.scss +96 -0
  227. package/miniprogram_dist/styles/iconfont.scss +91 -0
  228. package/miniprogram_dist/styles/theme.scss +126 -0
  229. package/miniprogram_dist/styles/tokens.scss +292 -0
  230. package/miniprogram_dist/utils/relations.js +21 -0
  231. package/package.json +25 -0
@@ -0,0 +1,387 @@
1
+ const formField = require('../../behaviors/formField');
2
+
3
+ let _fileId = 0;
4
+
5
+ Component({
6
+ behaviors: ['wx://form-field', formField],
7
+
8
+ options: {
9
+ multipleSlots: true,
10
+ },
11
+
12
+ relations: {
13
+ '../form-item/form-item': {
14
+ type: 'ancestor',
15
+ },
16
+ },
17
+
18
+ properties: {
19
+ fileList: { type: Array, value: [] },
20
+ mode: { type: String, value: 'grid' },
21
+ accept: { type: String, value: 'image' },
22
+ multiple: { type: Boolean, value: false },
23
+ maxCount: { type: Number, value: 9 },
24
+ maxSize: { type: Number, value: 10 * 1024 * 1024 },
25
+ maxDuration: { type: Number, value: 60 },
26
+ uploadUrl: { type: String, value: '' },
27
+ header: { type: Object, value: {} },
28
+ formData: { type: Object, value: {} },
29
+ fileName: { type: String, value: 'file' },
30
+ sizeType: { type: Array, value: ['original', 'compressed'] },
31
+ sourceType: { type: Array, value: ['album', 'camera'] },
32
+ compressed: { type: Boolean, value: true },
33
+ camera: { type: String, value: 'back' },
34
+ disabled: { type: Boolean, value: false },
35
+ readonly: { type: Boolean, value: false },
36
+ columns: { type: Number, value: 4 },
37
+ size: { type: String, value: '' },
38
+ status: { type: String, value: '' },
39
+ useSlot: { type: Boolean, value: false },
40
+ },
41
+
42
+ data: {
43
+ _showAdd: true,
44
+ _fileSizes: [],
45
+ _itemStyle: '',
46
+ _useSlot: false,
47
+ },
48
+
49
+ observers: {
50
+ 'fileList, maxCount'(fileList, maxCount) {
51
+ const list = fileList || [];
52
+ this.setData({
53
+ _showAdd: maxCount <= 0 || list.length < maxCount,
54
+ _fileSizes: list.map((f) => this._formatSize(f.size)),
55
+ });
56
+ // Sync form value: only completed files
57
+ const doneFiles = list.filter((f) => f.status === 'done' || !f.status);
58
+ this.setData({ value: doneFiles });
59
+ },
60
+ columns(columns) {
61
+ const gaps = columns - 1;
62
+ const style = `width: calc((100% - ${gaps} * var(--spacing-upload-gap)) / ${columns}); height: 0; padding-bottom: calc((100% - ${gaps} * var(--spacing-upload-gap)) / ${columns});`;
63
+ this.setData({ _itemStyle: style });
64
+ },
65
+ useSlot(val) {
66
+ this.setData({ _useSlot: val });
67
+ },
68
+ },
69
+
70
+ lifetimes: {
71
+ attached() {
72
+ this._uploadTasks = {};
73
+ const { columns, useSlot } = this.data;
74
+ const gaps = columns - 1;
75
+ const style = `width: calc((100% - ${gaps} * var(--spacing-upload-gap)) / ${columns}); height: 0; padding-bottom: calc((100% - ${gaps} * var(--spacing-upload-gap)) / ${columns});`;
76
+ this.setData({ _itemStyle: style, _useSlot: useSlot });
77
+ },
78
+ detached() {
79
+ this._abortAll();
80
+ },
81
+ },
82
+
83
+ methods: {
84
+ // ===== File Selection =====
85
+ handleChoose() {
86
+ if (this.data.readonly || this._isDisabled()) return;
87
+
88
+ const { accept } = this.data;
89
+ if (accept === 'file') {
90
+ this._chooseFile();
91
+ } else {
92
+ this._chooseMedia();
93
+ }
94
+ },
95
+
96
+ _chooseMedia() {
97
+ const {
98
+ accept,
99
+ multiple,
100
+ maxCount,
101
+ fileList,
102
+ sizeType,
103
+ sourceType,
104
+ compressed,
105
+ camera,
106
+ maxDuration,
107
+ } = this.data;
108
+ const remaining = maxCount > 0 ? maxCount - fileList.length : 9;
109
+ const count = multiple ? remaining : 1;
110
+
111
+ const mediaType =
112
+ accept === 'video' ? ['video'] : accept === 'media' ? ['image', 'video'] : ['image'];
113
+
114
+ wx.chooseMedia({
115
+ count,
116
+ mediaType,
117
+ sizeType,
118
+ sourceType,
119
+ compressed,
120
+ camera,
121
+ maxDuration,
122
+ success: (res) => {
123
+ const files = res.tempFiles.map((f) => ({
124
+ _id: ++_fileId,
125
+ url: f.tempFilePath,
126
+ name: f.tempFilePath.split('/').pop(),
127
+ size: f.size,
128
+ type: f.fileType || 'image',
129
+ thumb: f.thumbTempFilePath || '',
130
+ status: '',
131
+ progress: 0,
132
+ }));
133
+ this._processFiles(files);
134
+ },
135
+ });
136
+ },
137
+
138
+ _chooseFile() {
139
+ const { multiple, maxCount, fileList } = this.data;
140
+ const remaining = maxCount > 0 ? maxCount - fileList.length : 100;
141
+ const count = multiple ? remaining : 1;
142
+
143
+ wx.chooseMessageFile({
144
+ count,
145
+ type: 'all',
146
+ success: (res) => {
147
+ const files = res.tempFiles.map((f) => ({
148
+ _id: ++_fileId,
149
+ url: f.path,
150
+ name: f.name,
151
+ size: f.size,
152
+ type: 'file',
153
+ thumb: '',
154
+ status: '',
155
+ progress: 0,
156
+ }));
157
+ this._processFiles(files);
158
+ },
159
+ });
160
+ },
161
+
162
+ _processFiles(inFiles) {
163
+ const { maxCount, maxSize, fileList, uploadUrl } = this.data;
164
+ let files = inFiles;
165
+
166
+ // Check count limit
167
+ if (maxCount > 0) {
168
+ const remaining = maxCount - fileList.length;
169
+ if (files.length > remaining) {
170
+ this.triggerEvent('overlimit', { files, maxCount });
171
+ files = files.slice(0, remaining);
172
+ }
173
+ }
174
+
175
+ // Check size limit
176
+ if (maxSize > 0) {
177
+ const oversized = files.filter((f) => f.size > maxSize);
178
+ if (oversized.length > 0) {
179
+ this.triggerEvent('oversize', { files: oversized });
180
+ files = files.filter((f) => f.size <= maxSize);
181
+ }
182
+ }
183
+
184
+ if (files.length === 0) return;
185
+
186
+ this.triggerEvent('choose', { files });
187
+
188
+ if (uploadUrl) {
189
+ files.forEach((f) => {
190
+ f.status = 'uploading';
191
+ });
192
+ }
193
+
194
+ const newList = [...fileList, ...files];
195
+ this._updateFileList(newList);
196
+
197
+ if (uploadUrl) {
198
+ files.forEach((f) => {
199
+ this._uploadFile(f._id);
200
+ });
201
+ } else {
202
+ this.triggerEvent('upload', { files });
203
+ }
204
+ },
205
+
206
+ // ===== Upload Management =====
207
+ _findFileById(id) {
208
+ const { fileList } = this.data;
209
+ for (let i = 0; i < fileList.length; i++) {
210
+ if (fileList[i]._id === id) return { file: fileList[i], index: i };
211
+ }
212
+ return null;
213
+ },
214
+
215
+ _uploadFile(fileId) {
216
+ const { uploadUrl, header, formData, fileName } = this.data;
217
+ const found = this._findFileById(fileId);
218
+ if (!found) return;
219
+
220
+ const task = wx.uploadFile({
221
+ url: uploadUrl,
222
+ filePath: found.file.url,
223
+ name: fileName,
224
+ header,
225
+ formData,
226
+ success: (res) => {
227
+ const cur = this._findFileById(fileId);
228
+ if (!cur) return;
229
+ const list = [...this.data.fileList];
230
+ list[cur.index] = { ...list[cur.index], status: 'done', progress: 100 };
231
+ try {
232
+ const data = JSON.parse(res.data);
233
+ if (data.url) list[cur.index].url = data.url;
234
+ } catch (e) {
235
+ // Keep original url
236
+ }
237
+ this._updateFileList(list);
238
+ this.triggerEvent('success', { file: list[cur.index], response: res, fileList: list });
239
+ },
240
+ fail: (err) => {
241
+ const cur = this._findFileById(fileId);
242
+ if (!cur) return;
243
+ const list = [...this.data.fileList];
244
+ list[cur.index] = { ...list[cur.index], status: 'error' };
245
+ this._updateFileList(list);
246
+ this.triggerEvent('error', { file: list[cur.index], error: err, fileList: list });
247
+ },
248
+ complete: () => {
249
+ delete this._uploadTasks[fileId];
250
+ },
251
+ });
252
+
253
+ task.onProgressUpdate((res) => {
254
+ const cur = this._findFileById(fileId);
255
+ if (!cur) return;
256
+ const list = [...this.data.fileList];
257
+ list[cur.index] = { ...list[cur.index], progress: res.progress };
258
+ this._updateFileList(list);
259
+ this.triggerEvent('progress', { file: list[cur.index], progress: res.progress });
260
+ });
261
+
262
+ this._uploadTasks[fileId] = task;
263
+ },
264
+
265
+ _abortAll() {
266
+ if (!this._uploadTasks) return;
267
+ Object.values(this._uploadTasks).forEach((task) => {
268
+ if (task && task.abort) task.abort();
269
+ });
270
+ this._uploadTasks = {};
271
+ },
272
+
273
+ // ===== Interactions =====
274
+ handleDelete(e) {
275
+ const { index } = e.currentTarget.dataset;
276
+ const list = [...this.data.fileList];
277
+ const file = list[index];
278
+
279
+ // Abort upload if in progress
280
+ if (file._id && this._uploadTasks[file._id]) {
281
+ this._uploadTasks[file._id].abort();
282
+ delete this._uploadTasks[file._id];
283
+ }
284
+
285
+ list.splice(index, 1);
286
+ this.triggerEvent('remove', { file, index, fileList: list });
287
+ this._updateFileList(list);
288
+ },
289
+
290
+ handlePreview(e) {
291
+ const { index } = e.currentTarget.dataset;
292
+ const { fileList } = this.data;
293
+ const file = fileList[index];
294
+ if (!file || file.status === 'error') return;
295
+
296
+ this.triggerEvent('preview', { file, index });
297
+
298
+ // Auto preview for images/videos
299
+ if (file.type === 'image' || file.type === 'video') {
300
+ const sources = fileList
301
+ .filter((f) => f.type === 'image' || f.type === 'video')
302
+ .map((f) => ({
303
+ url: f.url,
304
+ type: f.type,
305
+ }));
306
+ const current = sources.findIndex((s) => s.url === file.url);
307
+ wx.previewMedia({
308
+ sources,
309
+ current: current >= 0 ? current : 0,
310
+ });
311
+ }
312
+ },
313
+
314
+ handleRetry(e) {
315
+ const { index } = e.currentTarget.dataset;
316
+ const { uploadUrl } = this.data;
317
+ if (!uploadUrl) return;
318
+
319
+ const list = [...this.data.fileList];
320
+ const file = list[index];
321
+ if (!file) return;
322
+
323
+ list[index] = { ...file, status: 'uploading', progress: 0 };
324
+ this._updateFileList(list);
325
+ this._uploadFile(file._id);
326
+ },
327
+
328
+ handleListContentTap(e) {
329
+ const { index } = e.currentTarget.dataset;
330
+ const { fileList } = this.data;
331
+ const file = fileList[index];
332
+ if (!file) return;
333
+
334
+ if (file.status === 'error') {
335
+ this.handleRetry(e);
336
+ } else {
337
+ this.handlePreview(e);
338
+ }
339
+ },
340
+
341
+ // ===== Public Methods =====
342
+ chooseFile() {
343
+ this.handleChoose();
344
+ },
345
+
346
+ upload(file) {
347
+ const { uploadUrl } = this.data;
348
+ if (!uploadUrl || !file._id) return;
349
+
350
+ const found = this._findFileById(file._id);
351
+ if (!found) return;
352
+
353
+ const list = [...this.data.fileList];
354
+ list[found.index] = { ...list[found.index], status: 'uploading', progress: 0 };
355
+ this._updateFileList(list);
356
+ this._uploadFile(file._id);
357
+ },
358
+
359
+ abort(fileId) {
360
+ if (this._uploadTasks[fileId]) {
361
+ this._uploadTasks[fileId].abort();
362
+ delete this._uploadTasks[fileId];
363
+
364
+ const found = this._findFileById(fileId);
365
+ if (found) {
366
+ const list = [...this.data.fileList];
367
+ list[found.index] = { ...list[found.index], status: 'error', progress: 0 };
368
+ this._updateFileList(list);
369
+ }
370
+ }
371
+ },
372
+
373
+ // ===== Helpers =====
374
+ _updateFileList(list) {
375
+ this.setData({ fileList: list });
376
+ this.triggerEvent('update:fileList', { fileList: list });
377
+ this._notifyChange();
378
+ },
379
+
380
+ _formatSize(bytes) {
381
+ if (!bytes) return '';
382
+ if (bytes < 1024) return `${bytes}B`;
383
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
384
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
385
+ },
386
+ },
387
+ });
@@ -0,0 +1,4 @@
1
+ {
2
+ "component": true,
3
+ "styleIsolation": "apply-shared"
4
+ }
@@ -0,0 +1,258 @@
1
+ @import '../../styles/iconfont.scss';
2
+
3
+ /* ===== Grid Mode ===== */
4
+ .w-upload--grid {
5
+ display: flex;
6
+ flex-wrap: wrap;
7
+ gap: var(--spacing-upload-gap);
8
+ }
9
+
10
+ .w-upload__grid-item {
11
+ position: relative;
12
+ border-radius: var(--radius-upload);
13
+ overflow: hidden;
14
+ background-color: var(--color-upload-bg);
15
+ }
16
+
17
+ .w-upload__thumb {
18
+ position: absolute;
19
+ top: 0;
20
+ left: 0;
21
+ width: 100%;
22
+ height: 100%;
23
+ }
24
+
25
+ .w-upload__video-icon {
26
+ position: absolute;
27
+ top: 50%;
28
+ left: 50%;
29
+ transform: translate(-50%, -50%);
30
+ font-size: var(--size-upload-icon);
31
+ color: var(--color-upload-overlay-text);
32
+ line-height: 1;
33
+ }
34
+
35
+ .w-upload__file-info {
36
+ position: absolute;
37
+ top: 0;
38
+ left: 0;
39
+ width: 100%;
40
+ height: 100%;
41
+ display: flex;
42
+ flex-direction: column;
43
+ align-items: center;
44
+ justify-content: center;
45
+ padding: var(--spacing-sm);
46
+ box-sizing: border-box;
47
+ }
48
+
49
+ .w-upload__file-icon {
50
+ font-size: var(--size-upload-icon);
51
+ color: var(--color-upload-icon);
52
+ margin-bottom: var(--spacing-xs);
53
+ }
54
+
55
+ .w-upload__file-name {
56
+ font-size: var(--font-size-sm);
57
+ color: var(--color-text-secondary);
58
+ max-width: 100%;
59
+ overflow: hidden;
60
+ text-overflow: ellipsis;
61
+ white-space: nowrap;
62
+ }
63
+
64
+ /* Delete button */
65
+ .w-upload__delete {
66
+ position: absolute;
67
+ top: 0;
68
+ right: 0;
69
+ width: var(--size-upload-delete);
70
+ height: var(--size-upload-delete);
71
+ display: flex;
72
+ align-items: center;
73
+ justify-content: center;
74
+ background-color: var(--color-upload-mask);
75
+ border-radius: 0 0 0 var(--radius-upload);
76
+ z-index: 2;
77
+ }
78
+
79
+ .w-upload__delete-icon {
80
+ font-size: 20rpx;
81
+ color: var(--color-upload-overlay-text);
82
+ line-height: 1;
83
+ }
84
+
85
+ /* Progress bar (grid) */
86
+ .w-upload__progress {
87
+ position: absolute;
88
+ bottom: 0;
89
+ left: 0;
90
+ width: 100%;
91
+ height: var(--size-upload-progress);
92
+ background-color: var(--color-upload-progress-track);
93
+ }
94
+
95
+ .w-upload__progress-bar {
96
+ height: 100%;
97
+ background-color: var(--color-upload-progress);
98
+ transition: width 0.2s;
99
+ }
100
+
101
+ /* Error overlay (grid) */
102
+ .w-upload__error-overlay {
103
+ position: absolute;
104
+ top: 0;
105
+ left: 0;
106
+ width: 100%;
107
+ height: 100%;
108
+ display: flex;
109
+ align-items: center;
110
+ justify-content: center;
111
+ background-color: var(--color-upload-mask);
112
+ z-index: 1;
113
+ }
114
+
115
+ .w-upload__retry-icon {
116
+ font-size: var(--size-upload-icon);
117
+ color: var(--color-upload-overlay-text);
118
+ }
119
+
120
+ /* Add button (grid) */
121
+ .w-upload__add {
122
+ position: relative;
123
+ border-radius: var(--radius-upload);
124
+ background-color: var(--color-upload-bg);
125
+ }
126
+
127
+ .w-upload__add-icon {
128
+ position: absolute;
129
+ top: 50%;
130
+ left: 50%;
131
+ transform: translate(-50%, -50%);
132
+ font-size: var(--size-upload-icon);
133
+ color: var(--color-upload-icon);
134
+ line-height: 1;
135
+ }
136
+
137
+ /* ===== List Mode ===== */
138
+ .w-upload--list {
139
+ display: flex;
140
+ flex-direction: column;
141
+ }
142
+
143
+ .w-upload__list-item {
144
+ display: flex;
145
+ align-items: center;
146
+ padding: var(--spacing-upload-list-gap) 0;
147
+ border-bottom: 1rpx solid var(--color-separator);
148
+ }
149
+
150
+ .w-upload__list-thumb {
151
+ width: var(--size-upload-list-thumb);
152
+ height: var(--size-upload-list-thumb);
153
+ border-radius: var(--radius-upload);
154
+ margin-right: var(--spacing-sm);
155
+ flex-shrink: 0;
156
+ overflow: hidden;
157
+ }
158
+
159
+ .w-upload__list-thumb-img {
160
+ width: 100%;
161
+ height: 100%;
162
+ }
163
+
164
+ .w-upload__list-icon {
165
+ width: var(--size-upload-list-thumb);
166
+ height: var(--size-upload-list-thumb);
167
+ display: flex;
168
+ align-items: center;
169
+ justify-content: center;
170
+ font-size: var(--size-upload-icon);
171
+ color: var(--color-upload-icon);
172
+ margin-right: var(--spacing-sm);
173
+ flex-shrink: 0;
174
+ }
175
+
176
+ .w-upload__list-content {
177
+ flex: 1;
178
+ min-width: 0;
179
+ }
180
+
181
+ .w-upload__list-name {
182
+ font-size: var(--font-size-md);
183
+ color: var(--color-text-primary);
184
+ overflow: hidden;
185
+ text-overflow: ellipsis;
186
+ white-space: nowrap;
187
+ }
188
+
189
+ .w-upload__list-meta {
190
+ display: flex;
191
+ align-items: center;
192
+ margin-top: var(--spacing-xs);
193
+ }
194
+
195
+ .w-upload__list-size {
196
+ font-size: var(--font-size-sm);
197
+ color: var(--color-text-secondary);
198
+ }
199
+
200
+ .w-upload__list-status {
201
+ font-size: var(--font-size-sm);
202
+ margin-left: var(--spacing-sm);
203
+ }
204
+
205
+ .w-upload__list-status--uploading {
206
+ color: var(--color-upload-progress);
207
+ }
208
+
209
+ .w-upload__list-status--error {
210
+ color: var(--color-upload-error);
211
+ }
212
+
213
+ /* List progress */
214
+ .w-upload__list-progress {
215
+ height: var(--size-upload-progress);
216
+ background-color: var(--color-upload-progress-track);
217
+ border-radius: 2rpx;
218
+ margin-top: var(--spacing-xs);
219
+ }
220
+
221
+ .w-upload__list-progress-bar {
222
+ height: 100%;
223
+ border-radius: 2rpx;
224
+ background-color: var(--color-upload-progress);
225
+ transition: width 0.2s;
226
+ }
227
+
228
+ .w-upload__list-progress-bar--error {
229
+ background-color: var(--color-upload-error);
230
+ }
231
+
232
+ .w-upload__list-delete {
233
+ flex-shrink: 0;
234
+ padding: var(--spacing-sm);
235
+ font-size: var(--font-size-md);
236
+ color: var(--color-text-secondary);
237
+ line-height: 1;
238
+ }
239
+
240
+ /* List add button */
241
+ .w-upload__list-add {
242
+ display: flex;
243
+ align-items: center;
244
+ padding: var(--spacing-upload-list-gap) 0;
245
+ color: var(--color-upload-icon);
246
+ font-size: var(--font-size-md);
247
+ }
248
+
249
+ .w-upload__list-add-icon {
250
+ font-size: var(--font-size-lg);
251
+ margin-right: var(--spacing-xs);
252
+ }
253
+
254
+ /* ===== States ===== */
255
+ .w-upload--disabled {
256
+ opacity: 0.4;
257
+ pointer-events: none;
258
+ }