Commit 0d1a4181c6991053de88ab8db1b92e3f971e10da

Authored by 刘淇
1 parent 8ee2a923

个人中心

Showing 545 changed files with 491 additions and 71128 deletions

Too many changes.

To preserve performance only 100 of 545 files are displayed.

manifest.json
... ... @@ -48,6 +48,10 @@
48 48 },
49 49 /* 快应用特有相关 */
50 50 "quickapp" : {},
  51 + "uni-app": {
  52 + "vue3": true,
  53 + "compilerOptions": {}
  54 + },
51 55 /* 小程序特有相关 */
52 56 "mp-weixin" : {
53 57 "appid" : "wxcb4cd34066b97d82",
... ...
package-lock.json
... ... @@ -7,165 +7,12 @@
7 7 "dependencies": {
8 8 "clipboard": "^2.0.11",
9 9 "dayjs": "^1.11.19",
10   - "pinia-plugin-persistedstate": "^4.7.1",
11   - "vue": "^3.5.25"
  10 + "pinia-plugin-persistedstate": "^4.7.1"
12 11 },
13 12 "devDependencies": {
14 13 "rollup-plugin-visualizer": "^6.0.5"
15 14 }
16 15 },
17   - "node_modules/@babel/helper-string-parser": {
18   - "version": "7.27.1",
19   - "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
20   - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
21   - "license": "MIT",
22   - "engines": {
23   - "node": ">=6.9.0"
24   - }
25   - },
26   - "node_modules/@babel/helper-validator-identifier": {
27   - "version": "7.28.5",
28   - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
29   - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
30   - "license": "MIT",
31   - "engines": {
32   - "node": ">=6.9.0"
33   - }
34   - },
35   - "node_modules/@babel/parser": {
36   - "version": "7.28.5",
37   - "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.5.tgz",
38   - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
39   - "license": "MIT",
40   - "dependencies": {
41   - "@babel/types": "^7.28.5"
42   - },
43   - "bin": {
44   - "parser": "bin/babel-parser.js"
45   - },
46   - "engines": {
47   - "node": ">=6.0.0"
48   - }
49   - },
50   - "node_modules/@babel/types": {
51   - "version": "7.28.5",
52   - "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.28.5.tgz",
53   - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
54   - "license": "MIT",
55   - "dependencies": {
56   - "@babel/helper-string-parser": "^7.27.1",
57   - "@babel/helper-validator-identifier": "^7.28.5"
58   - },
59   - "engines": {
60   - "node": ">=6.9.0"
61   - }
62   - },
63   - "node_modules/@jridgewell/sourcemap-codec": {
64   - "version": "1.5.5",
65   - "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
66   - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
67   - "license": "MIT"
68   - },
69   - "node_modules/@vue/compiler-core": {
70   - "version": "3.5.25",
71   - "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.25.tgz",
72   - "integrity": "sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==",
73   - "license": "MIT",
74   - "dependencies": {
75   - "@babel/parser": "^7.28.5",
76   - "@vue/shared": "3.5.25",
77   - "entities": "^4.5.0",
78   - "estree-walker": "^2.0.2",
79   - "source-map-js": "^1.2.1"
80   - }
81   - },
82   - "node_modules/@vue/compiler-dom": {
83   - "version": "3.5.25",
84   - "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.25.tgz",
85   - "integrity": "sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==",
86   - "license": "MIT",
87   - "dependencies": {
88   - "@vue/compiler-core": "3.5.25",
89   - "@vue/shared": "3.5.25"
90   - }
91   - },
92   - "node_modules/@vue/compiler-sfc": {
93   - "version": "3.5.25",
94   - "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.25.tgz",
95   - "integrity": "sha512-PUgKp2rn8fFsI++lF2sO7gwO2d9Yj57Utr5yEsDf3GNaQcowCLKL7sf+LvVFvtJDXUp/03+dC6f2+LCv5aK1ag==",
96   - "license": "MIT",
97   - "dependencies": {
98   - "@babel/parser": "^7.28.5",
99   - "@vue/compiler-core": "3.5.25",
100   - "@vue/compiler-dom": "3.5.25",
101   - "@vue/compiler-ssr": "3.5.25",
102   - "@vue/shared": "3.5.25",
103   - "estree-walker": "^2.0.2",
104   - "magic-string": "^0.30.21",
105   - "postcss": "^8.5.6",
106   - "source-map-js": "^1.2.1"
107   - }
108   - },
109   - "node_modules/@vue/compiler-ssr": {
110   - "version": "3.5.25",
111   - "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.25.tgz",
112   - "integrity": "sha512-ritPSKLBcParnsKYi+GNtbdbrIE1mtuFEJ4U1sWeuOMlIziK5GtOL85t5RhsNy4uWIXPgk+OUdpnXiTdzn8o3A==",
113   - "license": "MIT",
114   - "dependencies": {
115   - "@vue/compiler-dom": "3.5.25",
116   - "@vue/shared": "3.5.25"
117   - }
118   - },
119   - "node_modules/@vue/reactivity": {
120   - "version": "3.5.25",
121   - "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.25.tgz",
122   - "integrity": "sha512-5xfAypCQepv4Jog1U4zn8cZIcbKKFka3AgWHEFQeK65OW+Ys4XybP6z2kKgws4YB43KGpqp5D/K3go2UPPunLA==",
123   - "license": "MIT",
124   - "dependencies": {
125   - "@vue/shared": "3.5.25"
126   - }
127   - },
128   - "node_modules/@vue/runtime-core": {
129   - "version": "3.5.25",
130   - "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.25.tgz",
131   - "integrity": "sha512-Z751v203YWwYzy460bzsYQISDfPjHTl+6Zzwo/a3CsAf+0ccEjQ8c+0CdX1WsumRTHeywvyUFtW6KvNukT/smA==",
132   - "license": "MIT",
133   - "dependencies": {
134   - "@vue/reactivity": "3.5.25",
135   - "@vue/shared": "3.5.25"
136   - }
137   - },
138   - "node_modules/@vue/runtime-dom": {
139   - "version": "3.5.25",
140   - "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.25.tgz",
141   - "integrity": "sha512-a4WrkYFbb19i9pjkz38zJBg8wa/rboNERq3+hRRb0dHiJh13c+6kAbgqCPfMaJ2gg4weWD3APZswASOfmKwamA==",
142   - "license": "MIT",
143   - "dependencies": {
144   - "@vue/reactivity": "3.5.25",
145   - "@vue/runtime-core": "3.5.25",
146   - "@vue/shared": "3.5.25",
147   - "csstype": "^3.1.3"
148   - }
149   - },
150   - "node_modules/@vue/server-renderer": {
151   - "version": "3.5.25",
152   - "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.25.tgz",
153   - "integrity": "sha512-UJaXR54vMG61i8XNIzTSf2Q7MOqZHpp8+x3XLGtE3+fL+nQd+k7O5+X3D/uWrnQXOdMw5VPih+Uremcw+u1woQ==",
154   - "license": "MIT",
155   - "dependencies": {
156   - "@vue/compiler-ssr": "3.5.25",
157   - "@vue/shared": "3.5.25"
158   - },
159   - "peerDependencies": {
160   - "vue": "3.5.25"
161   - }
162   - },
163   - "node_modules/@vue/shared": {
164   - "version": "3.5.25",
165   - "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.25.tgz",
166   - "integrity": "sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==",
167   - "license": "MIT"
168   - },
169 16 "node_modules/ansi-regex": {
170 17 "version": "5.0.1",
171 18 "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
... ... @@ -238,12 +85,6 @@
238 85 "dev": true,
239 86 "license": "MIT"
240 87 },
241   - "node_modules/csstype": {
242   - "version": "3.2.3",
243   - "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz",
244   - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
245   - "license": "MIT"
246   - },
247 88 "node_modules/dayjs": {
248 89 "version": "1.11.19",
249 90 "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.19.tgz",
... ... @@ -279,18 +120,6 @@
279 120 "dev": true,
280 121 "license": "MIT"
281 122 },
282   - "node_modules/entities": {
283   - "version": "4.5.0",
284   - "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
285   - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
286   - "license": "BSD-2-Clause",
287   - "engines": {
288   - "node": ">=0.12"
289   - },
290   - "funding": {
291   - "url": "https://github.com/fb55/entities?sponsor=1"
292   - }
293   - },
294 123 "node_modules/escalade": {
295 124 "version": "3.2.0",
296 125 "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz",
... ... @@ -301,12 +130,6 @@
301 130 "node": ">=6"
302 131 }
303 132 },
304   - "node_modules/estree-walker": {
305   - "version": "2.0.2",
306   - "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
307   - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
308   - "license": "MIT"
309   - },
310 133 "node_modules/get-caller-file": {
311 134 "version": "2.0.5",
312 135 "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz",
... ... @@ -365,33 +188,6 @@
365 188 "node": ">=8"
366 189 }
367 190 },
368   - "node_modules/magic-string": {
369   - "version": "0.30.21",
370   - "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz",
371   - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
372   - "license": "MIT",
373   - "dependencies": {
374   - "@jridgewell/sourcemap-codec": "^1.5.5"
375   - }
376   - },
377   - "node_modules/nanoid": {
378   - "version": "3.3.11",
379   - "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
380   - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
381   - "funding": [
382   - {
383   - "type": "github",
384   - "url": "https://github.com/sponsors/ai"
385   - }
386   - ],
387   - "license": "MIT",
388   - "bin": {
389   - "nanoid": "bin/nanoid.cjs"
390   - },
391   - "engines": {
392   - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
393   - }
394   - },
395 191 "node_modules/open": {
396 192 "version": "8.4.2",
397 193 "resolved": "https://registry.npmmirror.com/open/-/open-8.4.2.tgz",
... ... @@ -410,12 +206,6 @@
410 206 "url": "https://github.com/sponsors/sindresorhus"
411 207 }
412 208 },
413   - "node_modules/picocolors": {
414   - "version": "1.1.1",
415   - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
416   - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
417   - "license": "ISC"
418   - },
419 209 "node_modules/picomatch": {
420 210 "version": "4.0.3",
421 211 "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz",
... ... @@ -454,34 +244,6 @@
454 244 }
455 245 }
456 246 },
457   - "node_modules/postcss": {
458   - "version": "8.5.6",
459   - "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz",
460   - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
461   - "funding": [
462   - {
463   - "type": "opencollective",
464   - "url": "https://opencollective.com/postcss/"
465   - },
466   - {
467   - "type": "tidelift",
468   - "url": "https://tidelift.com/funding/github/npm/postcss"
469   - },
470   - {
471   - "type": "github",
472   - "url": "https://github.com/sponsors/ai"
473   - }
474   - ],
475   - "license": "MIT",
476   - "dependencies": {
477   - "nanoid": "^3.3.11",
478   - "picocolors": "^1.1.1",
479   - "source-map-js": "^1.2.1"
480   - },
481   - "engines": {
482   - "node": "^10 || ^12 || >=14"
483   - }
484   - },
485 247 "node_modules/require-directory": {
486 248 "version": "2.1.1",
487 249 "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz",
... ... @@ -539,15 +301,6 @@
539 301 "node": ">= 12"
540 302 }
541 303 },
542   - "node_modules/source-map-js": {
543   - "version": "1.2.1",
544   - "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
545   - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
546   - "license": "BSD-3-Clause",
547   - "engines": {
548   - "node": ">=0.10.0"
549   - }
550   - },
551 304 "node_modules/string-width": {
552 305 "version": "4.2.3",
553 306 "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
... ... @@ -582,27 +335,6 @@
582 335 "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
583 336 "license": "MIT"
584 337 },
585   - "node_modules/vue": {
586   - "version": "3.5.25",
587   - "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.25.tgz",
588   - "integrity": "sha512-YLVdgv2K13WJ6n+kD5owehKtEXwdwXuj2TTyJMsO7pSeKw2bfRNZGjhB7YzrpbMYj5b5QsUebHpOqR3R3ziy/g==",
589   - "license": "MIT",
590   - "dependencies": {
591   - "@vue/compiler-dom": "3.5.25",
592   - "@vue/compiler-sfc": "3.5.25",
593   - "@vue/runtime-dom": "3.5.25",
594   - "@vue/server-renderer": "3.5.25",
595   - "@vue/shared": "3.5.25"
596   - },
597   - "peerDependencies": {
598   - "typescript": "*"
599   - },
600   - "peerDependenciesMeta": {
601   - "typescript": {
602   - "optional": true
603   - }
604   - }
605   - },
606 338 "node_modules/wrap-ansi": {
607 339 "version": "7.0.0",
608 340 "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
... ...
package.json
... ... @@ -2,8 +2,7 @@
2 2 "dependencies": {
3 3 "clipboard": "^2.0.11",
4 4 "dayjs": "^1.11.19",
5   - "pinia-plugin-persistedstate": "^4.7.1",
6   - "vue": "^3.5.25"
  5 + "pinia-plugin-persistedstate": "^4.7.1"
7 6 },
8 7 "devDependencies": {
9 8 "rollup-plugin-visualizer": "^6.0.5"
... ...
pages-sub/daily/quick-order/add-order.vue
1 1 <template>
2 2 <view class="u-page">
3 3 <!-- 核心:将所有 up-form-item 包裹在同一个 up-form 内 -->
4   - <up-form
5   - label-position="left"
6   - :model="workOrderForm"
7   - ref="workOrderFormRef"
8   - labelWidth="220rpx"
9   - :rules="workOrderFormRules"
10   - :error-type="['message', 'border']"
11   - class="work-order-form-container"
12   - >
13   - <!-- 工单表单容器 -->
14   - <view class="work-order-form-content commonPageLRpadding">
  4 + <view class="work-order-form-content commonPageLRpadding">
  5 + <up-form
  6 + label-position="left"
  7 + :model="workOrderForm"
  8 + ref="workOrderFormRef"
  9 + labelWidth="160rpx"
  10 + >
15 11 <!-- 1. 工单位置(地图选择) -->
16 12 <up-form-item
17 13 label="工单位置"
... ... @@ -77,18 +73,16 @@
77 73 required
78 74 >
79 75 <up-textarea
80   - placeholder="请输入情况描述(最多150字)"
  76 + placeholder="请输入情况描述(最多200字)"
81 77 v-model="workOrderForm.problemDesc"
82 78 count
83   - maxlength="150"
  79 + maxlength="200"
84 80 rows="4"
85   - @blur="() => workOrderFormRef.value?.validateField('problemDesc')"
  81 + @blur="() => $refs.workOrderFormRef.validateField('problemDesc')"
86 82 ></up-textarea>
87 83 </up-form-item>
88   - </view>
89 84  
90   - <!-- 问题照片:独立一行显示(移入 up-form 内) -->
91   - <view class="img-upload-wrap">
  85 + <!-- 问题照片 -->
92 86 <up-form-item label="问题照片" prop="problemImgs" required>
93 87 <up-upload
94 88 :file-list="problemImgsList"
... ... @@ -99,11 +93,9 @@
99 93 upload-text="选择问题照片"
100 94 ></up-upload>
101 95 </up-form-item>
102   - </view>
103 96  
104   - <!-- 完成照片:独立一行显示(移入 up-form 内) -->
105   - <view class="img-upload-wrap">
106   - <up-form-item label="完成照片" prop="completeImgs" required>
  97 + <!-- 完成照片 -->
  98 + <up-form-item label="完成照片" prop="completeImgs" required class="mt-20">
107 99 <up-upload
108 100 :file-list="completeImgsList"
109 101 @after-read="(event) => uploadImgs(event, 'completeImgsList')"
... ... @@ -114,35 +106,27 @@
114 106 upload-text="选择完成照片"
115 107 ></up-upload>
116 108 </up-form-item>
117   - </view>
118 109  
119   - <!-- 处理结果描述(独立显示,移入 up-form 内) -->
120   - <view class="handle-result-wrap">
121   - <up-form-item
122   - label="处理结果"
123   - prop="handleResultDesc"
124   - required
125   - >
  110 + <!-- 处理结果(不必填) -->
  111 + <up-form-item label="处理结果" prop="handleResultDesc" class="mt-20">
126 112 <up-textarea
127   - placeholder="请输入处理结果描述(最多200字)"
  113 + placeholder="请输入处理结果描述(最多200字,选填)"
128 114 v-model="workOrderForm.handleResultDesc"
129 115 count
130 116 maxlength="200"
131 117 rows="4"
132   - @blur="() => workOrderFormRef.value?.validateField('handleResultDesc')"
  118 + @blur="() => $refs.workOrderFormRef.validateField('handleResultDesc')"
133 119 ></up-textarea>
134 120 </up-form-item>
135   - </view>
136   - </up-form>
137 121  
138   - <!-- 底部提交按钮 -->
  122 + </up-form>
  123 + </view>
  124 + <!-- 底部提交按钮(移除loading和disabled属性) -->
139 125 <view class="fixed-bottom-btn-wrap">
140 126 <up-button
141 127 type="primary"
142 128 text="提交工单"
143 129 @click="submitWorkOrder"
144   - :loading="isSubmitting"
145   - :disabled="isSubmitting"
146 130 ></up-button>
147 131 </view>
148 132  
... ... @@ -167,176 +151,220 @@
167 151 </template>
168 152  
169 153 <script setup lang="ts">
170   -import { ref, reactive, onMounted } from 'vue'
171   -import type { UniFormRef, UniActionSheetSelectEvent, UploadFile, UploadDeleteEvent } from '@/uni_modules/uview-plus/types'
172   -// 导入接口
173   -import { getRoadListByLatLng } from '@/api/common'
174   -// 导入统一的多文件上传方法
175   -import { uploadImages } from '@/common/utils/upload';
176   -import { createQuick } from '@/api/quick-order/quick-order'
177   -
178   -// ========== 基础变量定义 ==========
179   -// 问题照片列表
180   -const problemImgsList = ref<UploadFile[]>([])
181   -// 完成照片列表
182   -const completeImgsList = ref<UploadFile[]>([])
183   -// 表单Ref
  154 +import {ref} from 'vue'
  155 +import type {UniFormRef} from '@/uni_modules/uview-plus/types'
  156 +// 定义ref供选项式API使用
184 157 const workOrderFormRef = ref<UniFormRef>(null)
185   -// 提交加载状态
186   -const isSubmitting = ref(false)
187   -// 弹窗显隐控制
188   -const showRoadName = ref(false)
189   -const showOrderName = ref(false)
190   -// 下拉列表数据
191   -const roadNameList = ref<any[]>([])
192   -const orderNameList = ref([
193   - { name: '绿地卫生', code: 'ORDER001' },
194   - { name: '设施维修', code: 'ORDER002' },
195   - { name: '垃圾清理', code: 'ORDER003' }
196   -])
197   -
198   -// ========== 工单表单数据 ==========
199   -const workOrderForm = reactive({
200   - roadId: 0, // 道路ID
201   - roadName: '', // 道路名称
202   - workLocation: '', // 工单位置
203   - orderName: '', // 工单名称
204   - problemDesc: '', // 情况描述
205   - handleResultDesc: '', // 处理结果描述
206   - lat: 0, // 纬度
207   - lon: 0 // 经度
208   -})
209   -
210   -// ========== 表单校验规则 ==========
211   -const workOrderFormRules = reactive({
212   - workLocation: [
213   - { type: 'string', required: true, message: '请选择工单位置', trigger: ['change', 'blur'] }
214   - ],
215   - roadName: [
216   - { type: 'string', required: true, message: '请选择道路名称', trigger: ['change', 'blur'] }
217   - ],
218   - orderName: [
219   - { type: 'string', required: true, message: '请选择工单名称', trigger: ['change', 'blur'] }
220   - ],
221   - problemDesc: [
222   - { type: 'string', required: true, message: '请输入情况描述', trigger: ['change', 'blur'] },
223   - { type: 'string', min: 3, max: 150, message: '情况描述需3-150字', trigger: ['change', 'blur'] }
224   - ],
225   - problemImgs: [
226   - { required: true, message: '请上传问题照片', trigger: 'change' }
227   - ],
228   - completeImgs: [
229   - { required: true, message: '请上传完成照片', trigger: 'change' }
230   - ],
231   - handleResultDesc: [
232   - { type: 'string', required: true, message: '请输入处理结果描述', trigger: ['change', 'blur'] },
233   - { type: 'string', min: 3, max: 200, message: '处理结果需3-200字', trigger: ['change', 'blur'] }
234   - ]
235   -})
236   -
237   -// ========== 方法定义 ==========
238   -/**
239   - * 删除图片
240   - */
241   -const deleteImg = (event: UploadDeleteEvent, type: string) => {
242   - console.log('删除图片事件:', event, '类型:', type)
243   - if (type === 'problemImgsList') {
244   - problemImgsList.value.splice(event.index, 1)
245   - } else if (type === 'completeImgsList') {
246   - completeImgsList.value.splice(event.index, 1)
247   - }
248   - uni.showToast({ title: '图片删除成功', icon: 'success' })
249   -}
  158 +</script>
250 159  
251   -/**
252   - * 上传图片
253   - */
254   -const uploadImgs = async (event: { file: UploadFile | UploadFile[] }, type: string) => {
255   - console.log('上传图片事件:', event, '类型:', type)
256   - const fileList = Array.isArray(event.file) ? event.file : [event.file]
257   - const targetImgList = type === 'problemImgsList' ? problemImgsList : completeImgsList
258   -
259   - const filePaths = fileList.map(item => item.url)
260   - const tempItems: UploadFile[] = fileList.map(item => ({
261   - ...item,
262   - status: 'uploading' as const,
263   - message: '上传中'
264   - }))
265   - const startIndex = targetImgList.value.length
266   - targetImgList.value.push(...tempItems)
267   -
268   - try {
269   - const uploadResultUrls = await uploadImages({
270   - filePaths: filePaths,
271   - ignoreError: true
272   - })
273   - console.log('上传成功的URL列表:', uploadResultUrls)
274   -
275   - uploadResultUrls.forEach((url, index) => {
276   - if (targetImgList.value[startIndex + index]) {
277   - targetImgList.value.splice(startIndex + index, 1, {
278   - ...fileList[index],
279   - status: 'success' as const,
280   - message: '',
281   - url: url
282   - })
283   - }
284   - })
285   -
286   - if (uploadResultUrls.length < fileList.length) {
287   - const failCount = fileList.length - uploadResultUrls.length
288   - for (let i = uploadResultUrls.length; i < fileList.length; i++) {
289   - if (targetImgList.value[startIndex + i]) {
290   - targetImgList.value.splice(startIndex + i, 1, {
291   - ...fileList[i],
292   - status: 'failed' as const,
293   - message: '上传失败'
294   - })
295   - }
  160 +<script lang="ts">
  161 +import {getRoadListByLatLng} from '@/api/common'
  162 +import {uploadImages} from '@/common/utils/upload';
  163 +import {createQuick} from '@/api/quick-order/quick-order'
  164 +import {toast} from '@/uni_modules/uview-plus'
  165 +
  166 +export default {
  167 + data() {
  168 + return {
  169 + // 问题照片列表
  170 + problemImgsList: [],
  171 + // 完成照片列表
  172 + completeImgsList: [],
  173 + // 弹窗显隐控制
  174 + showRoadName: false,
  175 + showOrderName: false,
  176 + // 下拉列表数据
  177 + roadNameList: [],
  178 + orderNameList: [
  179 + {name: '绿地卫生', code: 'ORDER001'},
  180 + {name: '设施维修', code: 'ORDER002'},
  181 + {name: '垃圾清理', code: 'ORDER003'}
  182 + ],
  183 + // 工单表单数据
  184 + workOrderForm: {
  185 + roadId: 0, // 道路ID
  186 + roadName: '', // 道路名称
  187 + workLocation: '', // 工单位置
  188 + orderName: '', // 工单名称
  189 + problemDesc: '', // 情况描述
  190 + handleResultDesc: '', // 处理结果描述(不必填)
  191 + lat: 0, // 纬度
  192 + lon: 0 // 经度
  193 + },
  194 + // 表单校验规则
  195 + workOrderFormRules: {
  196 + workLocation: [
  197 + {type: 'string', required: true, message: '请选择工单位置', trigger: ['change', 'blur']}
  198 + ],
  199 + roadName: [
  200 + {type: 'string', required: true, message: '请选择道路名称', trigger: ['change', 'blur']}
  201 + ],
  202 + orderName: [
  203 + {type: 'string', required: true, message: '请选择工单名称', trigger: ['change', 'blur']}
  204 + ],
  205 + problemDesc: [
  206 + {type: 'string', required: true, message: '请输入情况描述', trigger: ['change', 'blur']},
  207 + {type: 'string', min: 3, max: 200, message: '情况描述需3-150字', trigger: ['change', 'blur']}
  208 + ],
  209 + problemImgs: [
  210 + {
  211 + required: true,
  212 + message: '请上传问题照片',
  213 + trigger: 'change',
  214 + validator: (rule, value, callback) => {
  215 + // 自定义校验规则:检查是否有成功上传的图片
  216 + const hasSuccessImg = this.problemImgsList.some(item => item.status === 'success')
  217 + hasSuccessImg ? callback() : callback(new Error('请上传至少1张问题照片'))
  218 + }
  219 + }
  220 + ],
  221 + completeImgs: [
  222 + {
  223 + required: true,
  224 + message: '请上传完成照片',
  225 + trigger: 'change',
  226 + validator: (rule, value, callback) => {
  227 + // 自定义校验规则:检查是否有成功上传的图片
  228 + const hasSuccessImg = this.completeImgsList.some(item => item.status === 'success')
  229 + hasSuccessImg ? callback() : callback(new Error('请上传至少1张完成照片'))
  230 + }
  231 + }
  232 + ],
  233 + handleResultDesc: [
  234 + // 移除required,改为可选字段
  235 + {type: 'string', min: 3, max: 200, message: '处理结果需3-200字', trigger: ['change', 'blur']}
  236 + ]
296 237 }
297   - uni.showToast({ title: `成功上传${uploadResultUrls.length}张,失败${failCount}张`, icon: 'none' })
298   - } else {
299   - uni.showToast({ title: `成功上传${fileList.length}张图片`, icon: 'success' })
300 238 }
301   - } catch (err) {
302   - console.error('图片上传失败:', err)
303   - for (let i = 0; i < fileList.length; i++) {
304   - if (targetImgList.value[startIndex + i]) {
305   - targetImgList.value.splice(startIndex + i, 1, {
306   - ...fileList[i],
307   - status: 'failed' as const,
308   - message: '上传失败'
309   - })
  239 + },
  240 + onReady() {
  241 + // 兼容微信小程序,通过setRules设置校验规则
  242 + this.$refs.workOrderFormRef.setRules(this.workOrderFormRules)
  243 + console.log('工单表单规则初始化完成')
  244 + },
  245 + methods: {
  246 + /**
  247 + * 返回上一页
  248 + */
  249 + navigateBack() {
  250 + uni.navigateBack()
  251 + },
  252 + /**
  253 + * 删除图片
  254 + */
  255 + deleteImg(event, type) {
  256 + console.log('删除图片事件:', event, '类型:', type)
  257 + if (type === 'problemImgsList') {
  258 + this.problemImgsList.splice(event.index, 1)
  259 + } else if (type === 'completeImgsList') {
  260 + this.completeImgsList.splice(event.index, 1)
310 261 }
311   - }
312   - uni.showToast({ title: '图片上传失败,请重试', icon: 'none' })
313   - }
314   -}
  262 + // 删除图片后重新校验图片字段
  263 + if (type === 'problemImgsList') {
  264 + this.$refs.workOrderFormRef.validateField('problemImgs')
  265 + } else if (type === 'completeImgsList') {
  266 + this.$refs.workOrderFormRef.validateField('completeImgs')
  267 + }
  268 + uni.showToast({title: '图片删除成功', icon: 'success'})
  269 + },
  270 + /**
  271 + * 上传图片
  272 + */
  273 + async uploadImgs(event, type) {
  274 + console.log('上传图片事件:', event, '类型:', type)
  275 + const fileList = Array.isArray(event.file) ? event.file : [event.file]
  276 + const targetImgList = type === 'problemImgsList' ? this.problemImgsList : this.completeImgsList
  277 +
  278 + const filePaths = fileList.map(item => item.url)
  279 + const tempItems = fileList.map(item => ({
  280 + ...item,
  281 + status: 'uploading',
  282 + message: '上传中'
  283 + }))
  284 + const startIndex = targetImgList.length
  285 + targetImgList.push(...tempItems)
  286 +
  287 + try {
  288 + const uploadResultUrls = await uploadImages({
  289 + filePaths: filePaths,
  290 + ignoreError: true
  291 + })
  292 + console.log('上传成功的URL列表:', uploadResultUrls)
  293 +
  294 + uploadResultUrls.forEach((url, index) => {
  295 + if (targetImgList[startIndex + index]) {
  296 + targetImgList.splice(startIndex + index, 1, {
  297 + ...fileList[index],
  298 + status: 'success',
  299 + message: '',
  300 + url: url
  301 + })
  302 + }
  303 + })
315 304  
316   -/**
317   - * 选择工单位置
318   - */
319   -const chooseWorkLocation = () => {
320   - if (isSubmitting.value) return
  305 + if (uploadResultUrls.length < fileList.length) {
  306 + const failCount = fileList.length - uploadResultUrls.length
  307 + for (let i = uploadResultUrls.length; i < fileList.length; i++) {
  308 + if (targetImgList[startIndex + i]) {
  309 + targetImgList.splice(startIndex + i, 1, {
  310 + ...fileList[i],
  311 + status: 'failed',
  312 + message: '上传失败'
  313 + })
  314 + }
  315 + }
  316 + uni.showToast({title: `成功上传${uploadResultUrls.length}张,失败${failCount}张`, icon: 'none'})
  317 + } else {
  318 + uni.showToast({title: `成功上传${fileList.length}张图片`, icon: 'success'})
  319 + }
  320 +
  321 + // 上传完成后重新校验图片字段
  322 + if (type === 'problemImgsList') {
  323 + this.$refs.workOrderFormRef.validateField('problemImgs')
  324 + } else if (type === 'completeImgsList') {
  325 + this.$refs.workOrderFormRef.validateField('completeImgs')
  326 + }
  327 + } catch (err) {
  328 + console.error('图片上传失败:', err)
  329 + for (let i = 0; i < fileList.length; i++) {
  330 + if (targetImgList[startIndex + i]) {
  331 + targetImgList.splice(startIndex + i, 1, {
  332 + ...fileList[i],
  333 + status: 'failed',
  334 + message: '上传失败'
  335 + })
  336 + }
  337 + }
  338 + uni.showToast({title: '图片上传失败,请重试', icon: 'none'})
321 339  
322   - uni.authorize({
323   - scope: 'scope.userLocation',
324   - success: () => {
  340 + // 上传失败后重新校验图片字段
  341 + if (type === 'problemImgsList') {
  342 + this.$refs.workOrderFormRef.validateField('problemImgs')
  343 + } else if (type === 'completeImgsList') {
  344 + this.$refs.workOrderFormRef.validateField('completeImgs')
  345 + }
  346 + }
  347 + },
  348 + /**
  349 + * 选择工单位置(移除isSubmitting判断)
  350 + */
  351 + chooseWorkLocation() {
  352 + let that = this
325 353 uni.chooseLocation({
326 354 success: async (res) => {
327   - workOrderForm.roadName = ''
328   - workOrderForm.roadId = 0
329   - roadNameList.value = []
  355 + that.workOrderForm.roadName = ''
  356 + that.workOrderForm.roadId = 0
  357 + that.roadNameList = []
330 358  
331   - workOrderForm.workLocation = res.name
332   - workOrderForm.lat = res.latitude
333   - workOrderForm.lon = res.longitude
  359 + that.workOrderForm.workLocation = res.name
  360 + that.workOrderForm.lat = res.latitude
  361 + that.workOrderForm.lon = res.longitude
334 362  
335   - workOrderFormRef.value?.validateField('workLocation')
336   - workOrderFormRef.value?.validateField('roadName')
  363 + that.$refs.workOrderFormRef.validateField('workLocation')
  364 + that.$refs.workOrderFormRef.validateField('roadName')
337 365  
338 366 try {
339   - uni.showLoading({ title: '获取道路名称中...' })
  367 + uni.showLoading({title: '获取道路名称中...'})
340 368 const roadRes = await getRoadListByLatLng({
341 369 companyCode: 'sls',
342 370 latitude: res.latitude,
... ... @@ -345,291 +373,143 @@ const chooseWorkLocation = () =&gt; {
345 373 uni.hideLoading()
346 374  
347 375 if (Array.isArray(roadRes)) {
348   - roadNameList.value = roadRes.map((item: any) => ({
  376 + that.roadNameList = roadRes.map((item) => ({
349 377 name: item.roadName || '',
350 378 code: item.roadCode || '',
351 379 id: item.roadId || 0
352 380 }))
353 381 } else {
354   - roadNameList.value = [{ name: '未查询到道路名称', code: '', id: 0 }]
355   - uni.showToast({ title: '未查询到该位置的道路信息', icon: 'none' })
  382 + that.roadNameList = [{name: '未查询到道路名称', code: '', id: 0}]
  383 + uni.showToast({title: '未查询到该位置的道路信息', icon: 'none'})
356 384 }
357 385 } catch (err) {
358 386 uni.hideLoading()
359 387 console.error('获取道路名称失败:', err)
360   - uni.showToast({ title: '获取道路名称失败,请重试', icon: 'none' })
361   - roadNameList.value = [{ name: '获取失败,请重新选择位置', code: '', id: 0 }]
  388 + uni.showToast({title: '获取道路名称失败,请重试', icon: 'none'})
  389 + that.roadNameList = [{name: '获取失败,请重新选择位置', code: '', id: 0}]
362 390 }
363 391 },
364 392 fail: (err) => {
365 393 console.error('选择位置失败:', err)
366   - uni.showToast({ title: '选择位置失败:' + err.errMsg, icon: 'none' })
  394 + uni.showToast({title: '选择位置失败:' + err.errMsg, icon: 'none'})
367 395 }
368 396 })
369 397 },
370   - fail: (err) => {
371   - console.error('位置授权失败:', err)
372   - uni.showModal({
373   - title: '权限提示',
374   - content: '需要获取您的位置权限才能选择工单位置,请前往设置开启',
375   - confirmText: '去设置',
376   - cancelText: '取消',
377   - success: (res) => {
378   - if (res.confirm) {
379   - uni.openSetting({
380   - success: (settingRes) => {
381   - if (settingRes.authSetting['scope.userLocation']) {
382   - uni.showToast({ title: '权限已开启,请重新选择位置', icon: 'none' })
383   - }
384   - }
385   - })
386   - }
  398 + /**
  399 + * 选择道路名称
  400 + */
  401 + handleRoadNameSelect(e) {
  402 + console.log('选择道路名称:', e)
  403 + this.workOrderForm.roadName = e.name
  404 + this.workOrderForm.roadId = e.code
  405 + this.showRoadName = false
  406 + this.$refs.workOrderFormRef.validateField('roadName')
  407 + },
  408 + /**
  409 + * 选择工单名称
  410 + */
  411 + handleOrderNameSelect(e) {
  412 + this.workOrderForm.orderName = e.name
  413 + this.showOrderName = false
  414 + this.$refs.workOrderFormRef.validateField('orderName')
  415 + },
  416 + /**
  417 + * 隐藏键盘
  418 + */
  419 + hideKeyboard() {
  420 + uni.hideKeyboard()
  421 + },
  422 + /**
  423 + * 提取图片URL数组
  424 + */
  425 + getImgUrlList(imgList) {
  426 + return imgList.filter(item => item.status === 'success').map(item => item.url)
  427 + },
  428 + /**
  429 + * 提交工单(添加成功跳转逻辑)
  430 + */
  431 + /**
  432 + * 提交工单(添加成功跳转逻辑)
  433 + */
  434 + async submitWorkOrder() {
  435 + try {
  436 + // 先执行表单校验(改用async/await写法,更易维护)
  437 + await this.$refs.workOrderFormRef.validate()
  438 +
  439 + const submitData = {
  440 + roadId: this.workOrderForm.roadId,
  441 + roadName: this.workOrderForm.roadName,
  442 + imgs: this.getImgUrlList(this.problemImgsList),
  443 + longRangeImgList: this.getImgUrlList(this.completeImgsList),
  444 + remark: this.workOrderForm.problemDesc,
  445 + handleResultDesc: this.workOrderForm.handleResultDesc,
  446 + latLonType: 2,
  447 + lat: this.workOrderForm.lat,
  448 + lon: this.workOrderForm.lon,
  449 + lonLatAddress: this.workOrderForm.workLocation,
  450 + pressingType: 2,
  451 + orderName: this.workOrderForm.orderName,
  452 + sourceId: 1,
  453 + sourceName: '园林',
  454 + thirdWorkNo: ''
387 455 }
388   - })
389   - }
390   - })
391   -}
392 456  
393   -/**
394   - * 选择道路名称
395   - */
396   -const handleRoadNameSelect = (e: UniActionSheetSelectEvent) => {
397   - console.log('选择道路名称:', e)
398   - workOrderForm.roadName = e.name
399   - workOrderForm.roadId = e.code
400   - showRoadName.value = false
401   - workOrderFormRef.value?.validateField('roadName')
402   -}
  457 + // 显示加载中
  458 + uni.showLoading({title: '提交中...'})
403 459  
404   -/**
405   - * 选择工单名称
406   - */
407   -const handleOrderNameSelect = (e: UniActionSheetSelectEvent) => {
408   - workOrderForm.orderName = e.name
409   - showOrderName.value = false
410   - workOrderFormRef.value?.validateField('orderName')
411   -}
412   -
413   -/**
414   - * 隐藏键盘
415   - */
416   -const hideKeyboard = () => {
417   - uni.hideKeyboard()
418   -}
  460 + // 调用提交接口(await需要async函数支持)
  461 + const res = await createQuick(submitData)
419 462  
420   -/**
421   - * 提取图片URL数组
422   - */
423   -const getImgUrlList = (imgList: UploadFile[]) => {
424   - console.log('提取图片URL:', imgList)
425   - return imgList.filter(item => item.status === 'success').map(item => item.url)
426   -}
427   -
428   -/**
429   - * 校验上传图片
430   - */
431   -const validateUploadImgs = () => {
432   - const hasValidProblemImgs = problemImgsList.value.some(item => item.status === 'success')
433   - if (!hasValidProblemImgs) {
434   - uni.showToast({ title: '请上传至少1张问题照片', icon: 'none' })
435   - workOrderFormRef.value?.validateField('problemImgs')
436   - return false
437   - }
438   -
439   - const hasValidCompleteImgs = completeImgsList.value.some(item => item.status === 'success')
440   - if (!hasValidCompleteImgs) {
441   - uni.showToast({ title: '请上传至少1张完成照片', icon: 'none' })
442   - workOrderFormRef.value?.validateField('completeImgs')
443   - return false
444   - }
445   -
446   - return true
447   -}
448   -
449   -/**
450   - * 提交工单
451   - */
452   -const submitWorkOrder = async () => {
453   - if (isSubmitting.value) {
454   - uni.showToast({ title: '提交中,请稍候', icon: 'none' })
455   - return
456   - }
457   -
458   - try {
459   - isSubmitting.value = true
460   -
461   - if (!validateUploadImgs()) {
462   - isSubmitting.value = false
463   - return
464   - }
465   -
466   - const valid = await new Promise<boolean>((resolve) => {
467   - workOrderFormRef.value?.validate((isValid, invalidFields) => {
468   - console.log('校验失败的字段:', invalidFields)
469   - resolve(isValid)
470   - })
471   - })
  463 + uni.hideLoading()
  464 + uni.showToast({
  465 + title: '工单提交成功',
  466 + icon: 'success',
  467 + duration: 1500
  468 + })
472 469  
473   - if (!valid) {
474   - const firstInvalidField = Object.keys(workOrderFormRef.value?.invalidFields || {})[0]
475   - if (firstInvalidField) {
476   - const el = document.querySelector(`[prop="${firstInvalidField}"]`)
477   - el?.scrollIntoView({ behavior: 'smooth', block: 'center' })
  470 + // 延迟跳转(等待提示框显示完成)
  471 + setTimeout(() => {
  472 + uni.redirectTo({
  473 + url: '/pages-sub/daily/quick-order/index'
  474 + })
  475 + }, 1500)
  476 + } catch (error) {
  477 + // 隐藏加载框
  478 + uni.hideLoading()
  479 +
  480 + // 区分是表单校验失败还是接口调用失败
  481 + if (Array.isArray(error)) {
  482 + // 表单校验失败
  483 + // uni.showToast({
  484 + // title: '表单填写不完整,请检查',
  485 + // icon: 'none',
  486 + // duration: 2000
  487 + // })
  488 + } else {
  489 + // 接口调用失败
  490 + console.error('工单提交失败:', error)
  491 + uni.showToast({
  492 + title: '提交失败,请重试',
  493 + icon: 'none',
  494 + duration: 2000
  495 + })
  496 + }
478 497 }
479   - uni.showToast({ title: '表单填写不完整,请检查', icon: 'none' })
480   - isSubmitting.value = false
481   - return
482   - }
483   -
484   - const submitData = {
485   - roadId: workOrderForm.roadId,
486   - roadName: workOrderForm.roadName,
487   - imgs: getImgUrlList(problemImgsList.value),
488   - longRangeImgList: getImgUrlList(completeImgsList.value),
489   - remark: workOrderForm.problemDesc,
490   - handleResultDesc: workOrderForm.handleResultDesc,
491   - latLonType: 2,
492   - lat: workOrderForm.lat,
493   - lon: workOrderForm.lon,
494   - lonLatAddress: workOrderForm.workLocation,
495   - pressingType: 2,
496   - orderName: workOrderForm.orderName,
497   - sourceId: 1,
498   - sourceName: '园林',
499   - thirdWorkNo: ''
500 498 }
501   -
502   - console.log('提交工单数据:', submitData)
503   - await createQuick(submitData)
504   - uni.showToast({ title: '工单提交成功', icon: 'success' })
505   -
506   - } catch (error) {
507   - console.error('提交工单失败:', error)
508   - uni.showToast({ title: '提交失败,请重试', icon: 'none' })
509   - } finally {
510   - isSubmitting.value = false
511 499 }
512 500 }
513   -
514   -// ========== 页面挂载初始化 ==========
515   -onMounted(() => {
516   - if (workOrderFormRef.value && !workOrderFormRef.value.rules) {
517   - workOrderFormRef.value.setRules(workOrderFormRules)
518   - console.log('工单表单规则初始化完成')
519   - }
520   -})
521 501 </script>
522 502  
523 503 <style lang="scss" scoped>
524 504 // 全局页面样式
525 505 .u-page {
526   - background-color: #f5f5f5;
527 506 min-height: 100vh;
528   - padding-bottom: 100rpx;
529   -}
530   -
531   -// 表单容器(新增:包裹整个表单)
532   -.work-order-form-container {
533   - width: 100%;
534 507 }
535 508  
536 509 // 工单表单内容容器
537 510 .work-order-form-content {
538 511 background: #fff;
539   - padding: 20rpx;
540   - box-sizing: border-box;
541   - margin-bottom: 20rpx;
542   -}
543   -
544   -// 图片上传区域
545   -.img-upload-wrap {
546   - background: #fff;
547   - padding: 20rpx;
548   - margin-bottom: 20rpx;
549   -
550   - :deep(.u-upload) {
551   - --u-upload-item-width: 200rpx;
552   - --u-upload-item-height: 200rpx;
553   - }
554   -
555   - :deep(.u-form-item) {
556   - margin-bottom: 0;
557   - }
558   -}
559   -
560   -// 处理结果描述区域
561   -.handle-result-wrap {
562   - background: #fff;
563   - padding: 0 20rpx 20rpx;
564   - margin-bottom: 20rpx;
565   - border-top: 1px solid #f0f0f0;
566   -
567   - :deep(.u-form-item) {
568   - --u-form-item-label-font-size: 28rpx;
569   - --u-form-item-content-font-size: 28rpx;
570   - }
571   -
572   - :deep(.u-textarea) {
573   - --u-textarea-font-size: 28rpx;
574   - padding: 10rpx 0;
575   - }
576 512 }
577 513  
578   -// 提交按钮区域
579   -.fixed-bottom-btn-wrap {
580   - position: fixed;
581   - bottom: 0;
582   - left: 0;
583   - right: 0;
584   - padding: 20rpx;
585   - background: #fff;
586   - box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
587   -
588   - :deep(.u-button) {
589   - width: 100%;
590   - height: 80rpx;
591   - line-height: 80rpx;
592   - font-size: 32rpx;
593   - border-radius: 8rpx;
594   - }
595   -}
596 514  
597   -// Label样式
598   -:deep(.u-form-item__label) {
599   - white-space: nowrap;
600   - text-overflow: ellipsis;
601   - overflow: hidden;
602   - line-height: 1.4;
603   -}
604   -
605   -// 表单基础样式
606   -:deep(.u-form-item) {
607   - --u-form-item-label-font-size: 28rpx;
608   - --u-form-item-content-font-size: 28rpx;
609   - margin-bottom: 10rpx;
610   -}
611   -
612   -:deep(.u-input) {
613   - --u-input-font-size: 28rpx;
614   -}
615   -
616   -:deep(.u-textarea) {
617   - --u-textarea-font-size: 28rpx;
618   - padding: 10rpx 0;
619   -}
620   -
621   -:deep(.u-action-sheet) {
622   - z-index: 9999 !important;
623   -}
624   -
625   -// 错误提示样式
626   -:deep(.u-form-item__error-message) {
627   - font-size: 24rpx !important;
628   - color: #f56c6c !important;
629   - margin-top: 5rpx !important;
630   -}
631   -
632   -:deep(.u-form-item--error .u-input__wrap) {
633   - border-color: #f56c6c !important;
634   -}
635 515 </style>
636 516 \ No newline at end of file
... ...
pages/mine/index.vue
  1 +<template>
  2 + <view class="user-center-page">
  3 + <!-- 顶部用户信息栏 -->
  4 + <view class="user-info-header">
  5 + <!-- 渐变背景层 -->
  6 + <view class="header-bg"></view>
  7 + <!-- 用户信息主体 -->
  8 + <view class="user-info-wrap">
  9 + <!-- 头像 -->
  10 + <up-avatar
  11 + :src="'/static/imgs/default-avatar.png'"
  12 + size="100rpx"
  13 + shape="circle"
  14 + class="user-avatar"
  15 + ></up-avatar>
  16 +
  17 + <!-- 用户名+手机号+角色 -->
  18 + <view class="user-info-content">
  19 + <view class="user-name">{{ userInfo.username || '未登录' }}</view>
  20 + <view class="user-phone">{{ userInfo.nickname || '--------' }}</view>
  21 + </view>
  22 +
  23 + <!-- 登录/编辑入口 -->
  24 + <up-button
  25 + v-if="!userStore.isLogin"
  26 + type="primary"
  27 + size="mini"
  28 + @click="handleLogin"
  29 + >
  30 + 立即登录
  31 + </up-button>
  32 + </view>
  33 + </view>
  34 +
  35 +
  36 + <!-- 退出登录按钮 (仅登录状态显示) -->
  37 + <view v-if="userStore.isLogin" class="logout-btn-wrap ">
  38 + <up-button
  39 + type="primary"
  40 + size="large"
  41 + @click="confirmLogout"
  42 + >
  43 + 退出登录
  44 + </up-button>
  45 + </view>
  46 +
  47 +
  48 + </view>
  49 +</template>
  50 +
1 51 <script setup lang="ts">
  52 +import { ref } from 'vue'
  53 +import { useUserStore } from '@/pinia/user' // 匹配你的 Pinia 路径
  54 +import { onShow } from '@dcloudio/uni-app'
  55 +
  56 +// 初始化Pinia仓库
  57 +const userStore = useUserStore()
  58 +const userInfo = userStore.userInfo.user
  59 +console.log(userInfo.nickname)
  60 +
  61 +
  62 +
  63 +// 页面显示时检查登录状态(同步缓存)
  64 +onShow(() => {
  65 + // 触发登录状态检查,确保缓存和Pinia同步
  66 + userStore.checkLogin()
  67 +})
  68 +
  69 +// 处理登录(跳转到登录页)
  70 +const handleLogin = () => {
  71 + navigateTo({
  72 + url: '/pages/login/index' // 替换为你的实际登录页路径
  73 + })
  74 +}
  75 +
  76 +
  77 +
  78 +// 确认退出登录
  79 +const confirmLogout = async () => {
  80 + try {
  81 + // 调用Pinia自带的logout方法(你的仓库已实现清空状态+跳转)
  82 + await userStore.logout()
  83 +
  84 + } catch (error) {
  85 + console.error('退出登录失败:', error)
  86 + uni.showToast({
  87 + title: '退出登录失败,请重试',
  88 + type: 'error'
  89 + })
  90 +
  91 + }
  92 +}
2 93  
3 94 </script>
4 95  
5   -<template>
  96 +<script lang="ts">
  97 +export default {
  98 + name: 'UserCenter'
  99 +}
  100 +</script>
  101 +
  102 +<style lang="scss" scoped>
  103 +.user-center-page {
  104 + min-height: 100vh;
  105 + background-color: #f5f7fa;
  106 +}
  107 +
  108 +// 顶部用户信息栏
  109 +.user-info-header {
  110 + position: relative;
  111 + padding-bottom: 40rpx;
  112 +
  113 + .header-bg {
  114 + position: absolute;
  115 + top: 0;
  116 + left: 0;
  117 + width: 100%;
  118 + height: 320rpx;
  119 + background: linear-gradient(135deg, #409eff, #67c23a);
  120 + border-radius: 0 0 20rpx 20rpx;
  121 + z-index: 1;
  122 + }
  123 +
  124 + .user-info-wrap {
  125 + position: relative;
  126 + z-index: 2;
  127 + display: flex;
  128 + align-items: center;
  129 + padding: 60rpx 30rpx 0;
  130 +
  131 + .user-avatar {
  132 + border: 4rpx solid #ffffff;
  133 + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
  134 + }
  135 +
  136 + .user-info-content {
  137 + margin-left: 30rpx;
  138 + flex: 1;
  139 +
  140 + .user-name {
  141 + font-size: 32rpx;
  142 + font-weight: 600;
  143 + color: #ffffff;
  144 + margin-bottom: 10rpx;
  145 + text-shadow: 0 1rpx 3rpx rgba(0, 0, 0, 0.1);
  146 + }
  147 +
  148 + .user-phone {
  149 + font-size: 26rpx;
  150 + color: rgba(255, 255, 255, 0.9);
  151 + margin-bottom: 10rpx;
  152 + }
  153 +
  154 + .user-role-tag {
  155 + background-color: rgba(255, 255, 255, 0.2);
  156 + color: #ffffff;
  157 + border: none;
  158 + }
  159 + }
  160 + }
  161 +}
  162 +
  163 +
  164 +// 退出登录按钮
  165 +.logout-btn-wrap {
  166 + margin: 200rpx 20rpx 20rpx;
  167 + padding: 20rpx;
6 168  
7   -</template>
8 169  
9   -<style scoped>
  170 +}
10 171  
11 172 </style>
12 173 \ No newline at end of file
... ...
static/imgs/default-avatar.png 0 → 100644

1.81 MB

static/imgs/logo.png

3.93 KB | W: | H:

7.55 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
uni_modules/uview-plus/LICENSE deleted
1   -MIT License
2   -
3   -Copyright (c) 2024 https://uiadmin.net/uview-plus
4   -
5   -Permission is hereby granted, free of charge, to any person obtaining a copy
6   -of this software and associated documentation files (the "Software"), to deal
7   -in the Software without restriction, including without limitation the rights
8   -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9   -copies of the Software, and to permit persons to whom the Software is
10   -furnished to do so, subject to the following conditions:
11   -
12   -The above copyright notice and this permission notice shall be included in all
13   -copies or substantial portions of the Software.
14   -
15   -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16   -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17   -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18   -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19   -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20   -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21   -SOFTWARE.
22 0 \ No newline at end of file
uni_modules/uview-plus/README.md deleted
1   -<p align="center">
2   - <img alt="logo" src="https://uiadmin.net/uview-plus/common/logo.png" width="120" height="120" style="margin-bottom: 10px;">
3   -</p>
4   -<h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uview-plus 3.0</h3>
5   -<h3 align="center">多平台快速开发的UI框架</h3>
6   -
7   -[![stars](https://img.shields.io/github/stars/ijry/uview-plus?style=flat-square&logo=GitHub)](https://github.com/ijry/uview-plus)
8   -[![forks](https://img.shields.io/github/forks/ijry/uview-plus?style=flat-square&logo=GitHub)](https://github.com/ijry/uview-plus)
9   -[![issues](https://img.shields.io/github/issues/ijry/uview-plus?style=flat-square&logo=GitHub)](https://github.com/ijry/uview-plus/issues)
10   -[![release](https://img.shields.io/github/v/release/ijry/uview-plus?style=flat-square)](https://gitee.com/jry/uview-plus/releases)
11   -[![license](https://img.shields.io/github/license/ijry/uview-plus?style=flat-square)](https://en.wikipedia.org/wiki/MIT_License)
12   -
13   -## 说明
14   -
15   -uview-plus,是uni-app全面兼容vue3/nvue/鸿蒙/uni-app-x(即将发布)的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水。uview-plus是基于uView2.x移植的支持vue3的版本,感谢uView。
16   -
17   -## 可视化设计
18   -
19   -uview-plus现已推出免费可视化设计,可以方便的进行页面可视化设计,导出源码即可使用。极大提高前端页面开发效率;如产品经理设计师直接使用更可作为高保真高可用原型制作工具,让设计稿即代码,无需传统的设计稿开发还原步骤。
20   -
21   -<img src="https://s3.bmp.ovh/imgs/2024/11/24/fd58d00071e6e5df.png" width="900" height="auto" >
22   -<img src="https://s3.bmp.ovh/imgs/2024/11/24/8e85a519fe627fb1.png" width="900" height="auto" >
23   -
24   -
25   -## 文档
26   -[官方文档:https://uview-plus.jiangruyi.com](https://uview-plus.jiangruyi.com)
27   -[备用文档:https://uiadmin.net/uview-plus](https://uiadmin.net/uview-plus)
28   -
29   -
30   -## 预览
31   -
32   -您可以通过**微信**扫码,查看最佳的演示效果。
33   -<br>
34   -<br>
35   -<img src="https://uview-plus.jiangruyi.com/common/h5_qrcode.png" width="220" height="220" >
36   -
37   -## 链接
38   -
39   -- [官方文档](https://uview-plus.jiangruyi.com)
40   -- [更新日志](https://uview-plus.jiangruyi.com/components/changelog.html)
41   -- [升级指南](https://uview-plus.jiangruyi.com/components/changeGuide.html)
42   -- [关于我们](https://uview-plus.jiangruyi.com/cooperation/about.html)
43   -
44   -## 交流反馈
45   -
46   -欢迎加入我们的QQ群交流反馈:[点此跳转](https://uview-plus.jiangruyi.com/components/addQQGroup.html)
47   -
48   -## 关于PR
49   -
50   -> 我们非常乐意接受各位的优质PR,但在此之前我希望您了解uview-plus是一个需要兼容多个平台的(小程序、h5、ios app、android app)包括nvue页面、vue页面。
51   -> 所以希望在您修复bug并提交之前尽可能的去这些平台测试一下兼容性。最好能携带测试截图以方便审核。非常感谢!
52   -
53   -## 安装
54   -
55   -#### **uni-app插件市场链接** —— [https://ext.dcloud.net.cn/plugin?name=uview-plus](https://ext.dcloud.net.cn/plugin?name=uview-plus)
56   -
57   -请通过[官网安装文档](https://uview-plus.jiangruyi.com/components/install.html)了解更详细的内容
58   -
59   -## 快速上手
60   -
61   -请通过[快速上手](https://uview-plus.jiangruyi.com/components/quickstart.html)了解更详细的内容
62   -
63   -## 使用方法
64   -配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。
65   -
66   -```html
67   -<template>
68   - <u-button text="按钮"></u-button>
69   -</template>
70   -```
71   -
72   -## 版权信息
73   -uview-plus遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uview-plus应用到您的产品中。
74   -
uni_modules/uview-plus/changelog.md deleted
1   -## 3.6.20(2025-12-08)
2   -improvment: 优化form组件语法普适性
3   -
4   -## 3.6.19(2025-12-01)
5   -fix: 修复商品SKU组件i18n
6   -
7   -fix: Choose组件会有width警告提示 #915
8   -
9   -## 3.6.18(2025-11-30)
10   -feature: upload组件file模式支持微信小程序chooseMessageFile的extension属性 #913
11   -
12   -## 3.6.17(2025-11-18)
13   -add: picker-data支持表单验证
14   -
15   -## 3.6.16(2025-11-18)
16   -improvment: 优化下拉菜单示例
17   -
18   -## 3.6.15(2025-11-10)
19   -fix: 修复tabs添加activeStyle切换后滑块无法居中
20   -
21   -## 3.6.14(2025-11-07)
22   -fix: 修复引用拼写
23   -
24   -## 3.6.13(2025-11-06)
25   -improvment: 组合式API升级之gap示例改造
26   -
27   -## 3.6.12(2025-11-05)
28   -improvment: empty示例改为组合式API
29   -
30   -## 3.6.11(2025-11-05)
31   -improvment: divider示例改为组合式API
32   -
33   -## 3.6.10(2025-11-04)
34   -improvment: checkbox示例改为组合式API
35   -
36   -## 3.6.9(2025-10-21)
37   -improvment: cell示例改为组合式API
38   -
39   -## 3.6.8(2025-10-20)
40   -imporvment: button示例改为组合式API
41   -
42   -## 3.6.7(2025-10-17)
43   -fix: 优化picker当前列判断
44   -
45   -## 3.6.6(2025-10-13)
46   -fix: 修复getWindowInfo微信小程序下报警告
47   -
48   -## 3.6.5(2025-10-11)
49   -🐛fix: 修复picker双向绑定 #753
50   -
51   -## 3.6.4(2025-10-09)
52   -🐛fix: import rpx2px function and add to exports in index.js
53   -
54   -## 3.6.3(2025-10-09)
55   -fix: 修复getWindowInfo微信小程序下报警告
56   -
57   -## 3.6.2(2025-10-05)
58   -fix: 修复picker双向绑定 #753
59   -
60   -## 3.6.1(2025-10-01)
61   -fix: 修复poster海报组件微信小程序图片绘制失败
62   -
63   -## 3.6.0(2025-09-30)
64   -fix: 修复parse事件报错及统一事件名称小写
65   -
66   -## 3.5.57(2025-09-30)
67   -improvment: 更换部分资源域名提升访问速度
68   -
69   -## 3.5.56(2025-09-29)
70   -fix: 修复picker和datetime-picker在部分原生渲染时hasInput触发键盘弹起
71   -
72   -## 3.5.55(2025-09-29)
73   -feat: waterfall新增after-add-one和after-add-all事件
74   -
75   -## 3.5.54(2025-09-25)
76   -🐞 fix: 解决索引列表初始化时获取不到高度导致的字母列表异常
77   -
78   -## 3.5.53(2025-09-19)
79   -improvment: back-top示例组合式API改造
80   -
81   -## 3.5.52(2025-09-19)
82   -fix: 优化tabbar的borderColor优先级
83   -
84   -## 3.5.51(2025-09-19)
85   -fix: 微信小程序下u-transition包裹的内容因为没有默认flex column而出现布局错误
86   -
87   -## 3.5.50(2025-09-18)
88   -fix: 修复tabbar组件borderColor类型
89   -
90   -## 3.5.49(2025-09-18)
91   -fix: 修复action-sheet列表中第一个item的hover style
92   -
93   -## 3.5.48(2025-09-17)
94   -fix: 修复table2的fixedHeader参数生效
95   -
96   -## 3.5.47(2025-09-16)
97   -fix: 修复modelValue类型
98   -
99   -## 3.5.46(2025-09-15)
100   -feat: table2新增支持span-method合并单元格
101   -
102   -## 3.5.45(2025-09-13)
103   -fix: 修复数据分配时未等待获取元素后再执行下一次循环导致数据插入错误,addTime属性未使用修改。
104   -
105   -## 3.5.44(2025-09-12)
106   -fix: 单选快捷组件作为受控组件,当modelValue清除选择时,组件状态未被清除。
107   -
108   -## 3.5.43(2025-09-10)
109   -fix: 增加subsection兼容性索引转为数字
110   -
111   -## 3.5.42(2025-09-09)
112   -feat: index-list增加下边距高度
113   -
114   -## 3.5.41(2025-09-08)
115   -fix: 修复cascader方法引用位置
116   -
117   -## 3.5.40(2025-09-08)
118   -feat: goods-sku组件支持多语言
119   -
120   -## 3.5.39(2025-09-07)
121   -fix: 修复cascader多语言问题
122   -
123   -## 3.5.38(2025-09-07)
124   -improvment: 完善演示图标
125   -
126   -## 3.5.37(2025-09-05)
127   -feat: cascader支持多语言
128   -
129   -## 3.5.36(2025-09-04)
130   -improvment: 补充图标
131   -
132   -## 3.5.35(2025-09-04)
133   -feat: cascader级联组件增加垂直头部与单列选项支持
134   -
135   -## 3.5.34(2025-09-03)
136   -improvement: 优化steps-item
137   -
138   -## 3.5.33(2025-09-02)
139   -升级uni-app至最新版
140   -## 3.5.32(2025-09-01)
141   -feat: cate-tab支持非联动跟随的单一切换模式
142   -
143   -feat: choose组件示例使用cate-tab的单一切换模式
144   -
145   -
146   -## 3.5.31(2025-09-01)
147   -feat: 新增choose通用选项选择器组件
148   -
149   -## 3.5.30(2025-08-31)
150   -fix: 修复缺失cascader级联选择器
151   -
152   -## 3.5.29(2025-08-30)
153   -feat: 新增cascader级联选择器
154   -
155   -## 3.5.28(2025-08-29)
156   -feat: 多语言增加泰语
157   -
158   -## 3.5.27(2025-08-29)
159   -feat: 新增基于tooltip的popover组件
160   -
161   -## 3.5.26(2025-08-29)
162   -improvment: 增强多语言兼容性
163   -
164   -## 3.5.25(2025-08-28)
165   -fix: 修复左侧与右侧弹出时页面打开闪现问题
166   -
167   -## 3.5.24(2025-08-28)
168   -feat: 优化tooltip弹窗定位
169   -
170   -feat: tooltip组件新增forcePosition支持强制精确定位
171   -
172   -## 3.5.23(2025-08-28)
173   -improvment: 调整pdf阅读器默认高度
174   -
175   -## 3.5.22(2025-08-28)
176   -feat: 新增goods-sku商品SKU选购组件
177   -
178   -## 3.5.21(2025-08-27)
179   -fix: 修复popup组件手势控制参数注释
180   -
181   -## 3.5.20(2025-08-27)
182   -improvement: 提升checkbox条件编译兼容性
183   -
184   -## 3.5.19(2025-08-27)
185   -feat: popup新增iOS风格手势控制上下高度及下滑关闭
186   -
187   -## 3.5.18(2025-08-26)
188   -feat: 新增coupon优惠券组件
189   -
190   -## 3.5.17(2025-08-26)
191   -fix: 分支合并冲突修复
192   -
193   -feat: picker-data组件新增cancel/close/confirm事件支持
194   -
195   -## 3.5.16(2025-08-26)
196   -feat: tabbar新增支持中间凸起按钮
197   -
198   -## 3.5.15(2025-08-25)
199   -feat: 之前的color-picker颜色选择器按计划上线
200   -
201   -## 3.5.14(2025-08-25)
202   -feat: 新增PDF阅读器组件
203   -
204   -## 3.5.13(2025-08-24)
205   -fix: 修复短视频示例https
206   -
207   -## 3.5.12(2025-08-23)
208   -feat: short-video短视频组件增加视频播放示例
209   -
210   -## 3.5.11(2025-08-23)
211   -feat: 新增short-video短视频切换组件
212   -
213   -feat: tabbar支持backgroundColor和borderColor属性
214   -
215   -feat: slider支持innerStyle样式属性
216   -
217   -## 3.5.10(2025-08-22)
218   -feat: 新增poster海报生成组件
219   -
220   -
221   -## 3.5.9(2025-08-22)
222   -feat: 优化qrcode组件支持toTempFilePath方法
223   -
224   -## 3.5.8(2025-08-22)
225   -fix: 优化rpx下calendar高度计算强制px
226   -
227   -## 3.5.7(2025-08-22)
228   -feat: input和search新增onlyClearableOnFocused参数支持控制是否仅聚焦时显示清除按钮
229   -
230   -## 3.5.6(2025-08-21)
231   -feat: picker弹窗及datetime-picker组件支持页面内模式
232   -
233   -## 3.5.5(2025-08-21)
234   -feat: popup弹窗及canlendar组件支持页面内插入无弹窗模式
235   -
236   -## 3.5.4(2025-08-21)
237   -feat: popup弹窗及canlendar组件支持页面内插入无弹窗模式
238   -
239   -## 3.5.3(2025-08-21)
240   -fix: 修复下拉刷新多语言key
241   -
242   -## 3.5.2(2025-08-20)
243   -fix: 修复非cli模式下引入的三方库报An error occurred while trying to read the map file错误
244   -
245   -fix: 去除i18n多语言多余console
246   -
247   -## 3.5.1(2025-08-20)
248   -feat: calendar组件月份标题自动适配多语言
249   -
250   -## 3.5.0(2025-08-20)
251   -feat: 组件库新增多语言支持且无侵入无依赖内置八种语言
252   -
253   -## 3.4.107(2025-08-20)
254   -feat: input组件支持密码显示切换
255   -
256   -## 3.4.106(2025-08-20)
257   -feat: tooltip组件支持左右方向弹窗
258   -
259   -## 3.4.105(2025-08-19)
260   -feat: 增加markdown解析器组件AI对话流式响应示例
261   -
262   -## 3.4.104(2025-08-19)
263   -feat: tooltip支持自定义触发器
264   -
265   -feat: tooltip支持插槽自定义内容
266   -
267   -feat: tooltip支持单击触发
268   -
269   -feat: tooltip支持设置弹窗背景色
270   -
271   -## 3.4.103(2025-08-19)
272   -feat: 内置一份dayjs库
273   -
274   -fix: 删除个别组件多余重复方法
275   -
276   -fix: 修复marked库App打包时报错
277   -
278   -## 3.4.102(2025-08-19)
279   -fix: 小程序下cate-tab动态加载数据后尺寸获取及联动异常
280   -
281   -## 3.4.101(2025-08-18)
282   -improvment: 增加一些涉及触摸组件PC端需要仿真模式提示
283   -
284   -## 3.4.100(2025-08-18)
285   -feat: 新增markdown解析器组件
286   -
287   -## 3.4.99(2025-08-18)
288   -fix: 修复parse富文本组件可能导致无限循环的问题
289   -
290   -## 3.4.98(2025-08-17)
291   -feat: alert组件新增transitionMode/icon/duration/modelValue等参数
292   -
293   -improvment: 完善alert组件注释
294   -
295   -## 3.4.97(2025-08-16)
296   -improvment: 完善album组件注释
297   -
298   -## 3.4.96(2025-08-16)
299   -improvment: 完善action-sheet注释
300   -
301   -## 3.4.95(2025-08-16)
302   -del: 去除不再需要的重复组件
303   -
304   -## 3.4.94(2025-08-15)
305   -improvment: 组件库内部icon前缀统一
306   -
307   -## 3.4.93(2025-08-15)
308   -fix: 修复dropdown组件在打开下拉菜单时content高度为NANpx的问题
309   -
310   -## 3.4.92(2025-08-14)
311   -fix: 修复多余空格导致cropper编译出错 #830
312   -
313   -## 3.4.91(2025-08-14)
314   -feat: 新增agreement弹窗协议组件
315   -
316   -## 3.4.90(2025-08-13)
317   -feat: datetimepicker新增datehour类型
318   -
319   -## 3.4.89(2025-08-13)
320   -fix: 修复u-form-item组件缺少对labelPosition的判断
321   -
322   -## 3.4.88(2025-08-13)
323   -fix: subsection组件的disabled属性应为Boolean类型
324   -
325   -## 3.4.87(2025-08-12)
326   -improvment: 签名组件示例前缀改为up
327   -
328   -## 3.4.86(2025-08-12)
329   -feat: 新增signature签名签字组件
330   -
331   -## 3.4.85(2025-08-11)
332   -feat: 完善图片裁剪功能支持props及JS两种方式
333   -
334   -fix: 修复H5下裁剪后图片黑屏
335   -
336   -## 3.4.84(2025-08-11)
337   -feat: 新增cropper图片裁剪组件
338   -
339   -## 3.4.83(2025-08-11)
340   -feat: 新增barcode无三方依赖条码组
341   -
342   -## 3.4.82(2025-08-11)
343   -improvment: 优化table2递归组件逻辑
344   -
345   -feat: 支持树状列表复选框
346   -
347   -## 3.4.81(2025-08-10)
348   -feat: table2新增树状结构递归支持
349   -
350   -## 3.4.80(2025-08-10)
351   -feat: 新增table2固定列对树状支持
352   -
353   -## 3.4.79(2025-08-09)
354   -feat: table2组件支持左侧固定列功能
355   -
356   -## 3.4.78(2025-08-09)
357   -fix: 修复table2在popup弹窗中无法横向滚动
358   -
359   -## 3.4.77(2025-08-08)
360   -feat: 优化waterfall瀑布流组件逻辑
361   -
362   -feat: waterfall瀑布流组件支持多列
363   -
364   -feat: waterfall瀑布流组件支持响应式列数
365   -
366   -## 3.4.76(2025-08-08)
367   -feat: 取消props中tabs组件默认颜色影响主题色生效
368   -
369   -fix: 修复parse富文本组件报错$options
370   -
371   -feat: timeFormat时间格式化方法支持UTC格式时间 #596
372   -
373   -## 3.4.75(2025-08-07)
374   -feat: 新增loadFontOnce参数控制是否全局只加载一次字体图标
375   -
376   -## 3.4.74(2025-08-07)
377   -feat: input组件新增cursorColor属性
378   -
379   -## 3.4.73(2025-08-05)
380   -improvment: 优化下拉刷新默认图标
381   -
382   -## 3.4.72(2025-08-05)
383   -improvment: 优化virtual-list虚拟列表样式
384   -
385   -feat: 新增virtual-list虚拟列表演示
386   -
387   -## 3.4.71(2025-08-05)
388   -feat: 新增virtual-list虚拟列表组件
389   -
390   -feat: 新增pull-refresh下拉刷新结合虚拟列表使用
391   -
392   -## 3.4.70(2025-08-05)
393   -fix: 修复qrcode组件长按事件传入错误cid导致的报错
394   -
395   -fix: 修复index-list组件key为undefined导致的索引报错消失
396   -
397   -## 3.4.69(2025-08-04)
398   -feat: pull-refresh下拉刷新新增上拉加载特性
399   -
400   -## 3.4.68(2025-08-03)
401   -feat: 新增pull-refresh下拉刷新组件
402   -
403   -## 3.4.67(2025-08-02)
404   -feat: number-box支持disabledBgColor参数
405   -
406   -## 3.4.66(2025-08-01)
407   -improvment: 增加组件图标
408   -
409   -feat: table2组件新增列排序插槽
410   -
411   -fix: 分段器组件onWindowResize使用条件编译
412   -
413   -fix: 修复u-line-1单行省略样式
414   -
415   -## 3.4.65(2025-07-26)
416   -fix: 修复部分环境下字体图标全局加载问题
417   -
418   -## 3.4.64(2025-07-25)
419   -feat: 新增dragsort拖动排序组件
420   -
421   -## 3.4.63(2025-07-24)
422   -feat: count-down支持slot传递时间参数
423   -
424   -## 3.4.62(2025-07-24)
425   -feat: divider支持默认插槽
426   -
427   -## 3.4.61(2025-07-24)
428   -feat: divider支持默认插槽
429   -
430   -## 3.4.60(2025-07-23)
431   -fix: 修复use阶段全局加载图标引起App端不明$page报错
432   -
433   -## 3.4.59(2025-07-23)
434   -fix: 修复album组件和CateTab组件watch和emits重复
435   -
436   -fix: 修复样式优先级导致form表单labelPosition属性top失效
437   -
438   -## 3.4.58(2025-07-22)
439   -fix: 修复样式优先级影响grid宫格组件布局
440   -
441   -## 3.4.57(2025-07-22)
442   -feat: 新增title标题组件
443   -
444   -## 3.4.56(2025-07-21)
445   -fix: 去除多余hotCity参数
446   -
447   -## 3.4.55(2025-07-21)
448   -feat: 新增city-locate城市定位选择组件
449   -
450   -feat: 优化index-list组件索引
451   -
452   -## 3.4.54(2025-07-18)
453   -feat: dropdown组件的highlight方法支持同时高亮多个菜单项
454   -
455   -feat: 支持一次性全局加载icon字体
456   -
457   -## 3.4.53(2025-07-18)
458   -feat: dropdown组件的highlight方法支持同时高亮多个菜单项 感谢@keeplearning66
459   -
460   -## 3.4.52(2025-07-16)
461   -fix: 修复底部安全区域组件兼容性
462   -
463   -## 3.4.51(2025-07-14)
464   -fix: 修复u-slider在click后没有触发change事件
465   -
466   -## 3.4.50(2025-07-13)
467   -feat: subsection分段器添加禁用参数
468   -
469   -## 3.4.49(2025-07-11)
470   -feat: picker支持bgColor、round、duration和overlayOpacity属性
471   -
472   -## 3.4.48(2025-07-10)
473   -fix: 官方文档Card示例组件多行显示省略号样式异常
474   -
475   -feat: album组件支持自定义preview事件
476   -
477   -## 3.4.47(2025-07-09)
478   -fix: 修复datetime-picker打开时,数值可能出现对不上的问题
479   -
480   -feat: Subsection 分段器添加支持从 list中读取激活文字颜色和未激活文字颜色
481   -
482   -fix: 修复modal定义confirmButton
483   -
484   -fix: safe-bottom底部安全距离在小程序优先用JS计算
485   -
486   -feat: 新增tree树形组件
487   -
488   -## 3.4.46(2025-07-08)
489   -feat: 上传组件预览视频支持videoPreviewObjectFit参数
490   -
491   -feat: td增加多个样式props
492   -
493   -fix: 修复noticeBar字号增大时文字遮挡
494   -
495   -feat: 项目工程增加pinia
496   -
497   -## 3.4.45(2025-07-01)
498   -fix: 修复picker-data组件缺少name
499   -
500   -fix: 优化picker高度单位
501   -
502   -## 3.4.44(2025-06-30)
503   -fix: 修复indexList中stikcy属性写死的问题(always true)
504   -
505   -feat: 搜索框添加新的右侧插槽
506   -
507   -fix: 修复indexList中丢失的select event
508   -
509   -fix: 解决因为层级问题导致点击picker选择器无法正常弹出
510   -
511   -## 3.4.43(2025-06-16)
512   -feat: table2支持header插槽
513   -
514   -## 3.4.42(2025-06-12)
515   -fix: 修复qrcode中默认id问题及canvas2时App无法绘制二维码 感谢@jiaruiyan
516   -
517   -## 3.4.41(2025-06-11)
518   -feat: qrcode支持 新参数useRootHeightAndWidth 是否使用根节点的宽高 感谢@YJR
519   -
520   -feat: toast支持设置zIndex层级
521   -
522   -
523   -
524   -## 3.4.40(2025-06-06)
525   -fix: 升级二维码 canvas -> canvas2 感谢@yjr
526   -
527   -## 3.4.39(2025-05-31)
528   -fix: 修改步骤条微信小程序下的布局 感谢@jiaruiyan
529   -
530   -fix: u-tabs在屏幕尺寸发生变化时滑块位置没有发生变化 感谢@aqzhft
531   -
532   -fix: 鸿蒙平台不支持plus.runtime.openWeb 感谢@aqzhft
533   -
534   -## 3.4.38(2025-05-30)
535   -fix: 修复picker-data快捷组件缺少index
536   -
537   -fix: 修复picker组件双向绑定初始化及取消后复原再次打开后的当前项目
538   -
539   -## 3.4.37(2025-05-29)
540   -feat: modal支持设置动画时间
541   -
542   -fix: DatetimePicker v-model 绑定异步设置无效 (#803)
543   -
544   -## 3.4.36(2025-05-28)
545   -fix: lazy-load图片为空时显示错误
546   -
547   -## 3.4.35(2025-05-28)
548   -feat: 进度条支持从右往左加载
549   -
550   -## 3.4.34(2025-05-28)
551   -feat: table2支持自定义标题和单元格样式
552   -
553   -## 3.4.33(2025-05-27)
554   -fix: 修复小程序cate-tab第一次切换时没反应 感谢@jiaruiyan
555   -
556   -fix: 修复datetimepicker传入空字符串时导致组件崩溃 感谢@jiaruiyan
557   -
558   -fix: 修复album带单位的字符串参与计算导致的计算数据错误 感谢@jiaruiyan
559   -
560   -## 3.4.32(2025-05-26)
561   -feat: 增加状态栏独立颜色配置支持支付宝小程序状态栏对背景色识别的不友好的情况
562   -
563   -fix: 抖音二维码兼容修复
564   -
565   -feat: cate-tab组件增加rightTop插槽 #715
566   -
567   -fix: 修改 test.promise(res) 预期结果不一致
568   -
569   -## 3.4.31(2025-05-17)
570   -fix: 修复parse富文本组件导致鸿蒙运行白屏
571   -
572   -fix: 去除演示项目中uni.$u用法便于兼容鸿蒙
573   -
574   -feat: modal新增popupBottom插槽适用类似关闭按钮与内容区域分离的场景
575   -
576   -## 3.4.30(2025-05-16)
577   -feat: 新增pagination分页器组件
578   -
579   -feat: popup新增bottom插槽适用类似关闭按钮与内容区域分离的场景
580   -
581   -## 3.4.29(2025-05-15)
582   -fix: 修复table2横向滚动样式
583   -
584   -fix: 修复table2组件宽度兼容
585   -
586   -fix: 修复image显示png图片时默认背景色问题
587   -
588   -feat: cate-tab新增height参数便于设置组件高度
589   -
590   -feat: 在index.js种导出digit.js便于使用
591   -
592   -fix: 修复tag组件缺失iconColor属性
593   -
594   -fix: 优化index-list的setValueForTouch方法逻辑 #708
595   -
596   -feat: number-box支持change事件返回变动是点击了增加还是减少按钮
597   -
598   -fix: 修复table2在小程序下部分情形不显示表格
599   -
600   -## 3.4.28(2025-05-12)
601   -feat: 新增table表格组件
602   -
603   -feat: 新增element-plus风格的table2组件
604   -
605   -## 3.4.27(2025-05-06)
606   -fix: 修复card组件props
607   -
608   -## 3.4.26(2025-05-06)
609   -fix: 修复test工具引入
610   -
611   -feat: card组件支持全局设置props默认值
612   -
613   -fix: 修复image在加载错误情况下高度和宽度不正确问题
614   -
615   -fix: 修复picker-data快捷组件默认picker选中
616   -
617   -fix: 修复日历month子组件缺失emits定义
618   -
619   -## 3.4.25(2025-04-27)
620   -fix: up-form编译在微信小程序里样式缺失 #640
621   -
622   -fix: number-box输入为空时自动设为最小值
623   -
624   -feat: picker与datetimepicke组件hasInput模式支持inputProps属性
625   -
626   -## 3.4.24(2025-04-25)
627   -fix: 修复upload上传逻辑(感谢@semdy)
628   -
629   -## 3.4.23(2025-04-24)
630   -chore: 补全chooseFile TS类型(感谢@semdy)
631   -
632   -feat: u-search组件的图标支持显示在右边(感谢@semdy)
633   -
634   -chore: 修正chooseFile返回的数据TS类型(感谢@semdy)
635   -
636   -fix: PR导致缺失name影响uplad自动上传扩展名
637   -
638   -
639   -## 3.4.22(2025-04-22)
640   -fix: 修复自动上传偶发的success被覆盖为uploading
641   -
642   -fix: float-button缺少key #677
643   -
644   -fix: upload组件完善优化(感谢@semdy)
645   -
646   -fix: toolbar组件confirmColor属性默认改为空,以便默认使用主题色、标题字体加粗(感谢@semdy)
647   -
648   -## 3.4.21(2025-04-21)
649   -feat: subsection分段器支持双向绑定current
650   -
651   -feat: select组件支持maxHeight属性
652   -
653   -feat: datetime-picker支持inputBorder属性
654   -
655   -## 3.4.20(2025-04-17)
656   -fix: 修复navbar-mini提示border不存在
657   -
658   -feat: status-bar支持对外暴露状态栏高度值
659   -
660   -feat: upload支持自定义自动上传后处理逻辑便于对接不同规范后端
661   -
662   -feat: 优化tag组件插槽
663   -
664   -
665   -## 3.4.19(2025-04-14)
666   -fix: 修复model组件增加contentStyle带来的语法问题
667   -
668   -## 3.4.18(2025-04-14)
669   -fix: upload组件支持所有文件类型的onClickPreview事件
670   -
671   -## 3.4.17(2025-04-11)
672   -feat: select组件text插槽增加scope传递currentLabel
673   -
674   -## 3.4.16(2025-04-10)
675   -fix: 修复安卓新加载字体方式导致Cannot read property '$page' of undefined
676   -
677   -## 3.4.15(2025-04-10)
678   -improvment: 优化移步加载数据时swiper组件displayMultipleItems报错
679   -
680   -feat: modal增加contentStyle属性
681   -
682   -fix: 修复下拉菜单收起动画缺失
683   -
684   -fix: 修复sticky的offset属性值为响应式数据时失效 #237
685   -
686   -
687   -## 3.4.14(2025-04-09)
688   -feat: 支持自托管内置图标及扩展自定义图标
689   -
690   -## 3.4.13(2025-04-08)
691   -fix: tabs点击当前tab触发change事件
692   -
693   -## 3.4.12(2025-04-02)
694   -fix: dropdown关闭后遮挡页面内容 #653
695   -
696   -fix u-sticky.vue Uncaught TypeError: e.querySelector is not a function at uni-app-view.umd.js
697   -
698   -## 3.4.11(2025-03-31)
699   -fix: 优化upload组件预览视频的弹窗占位
700   -
701   -## 3.4.10(2025-03-28)
702   -feat: select组件新增多个props属性及优化
703   -
704   -fix: 修复cate-tab报错index is not defined #661
705   -
706   -
707   -## 3.4.9(2025-03-27)
708   -fix: 修复upload组件split报错
709   -
710   -fix: 修复float-button缺少flex样式
711   -
712   -## 3.4.8(2025-03-27)
713   -fix: 修复upload组件split报错
714   -
715   -fix: 移除mapState
716   -
717   -## 3.4.7(2025-03-26)
718   -fix: 修复action-sheet-data和picker-data数据回显
719   -
720   -fix: 优化upload组件视频封面兼容
721   -
722   -## 3.4.6(2025-03-25)
723   -feat: checkbox触发change时携带name参数
724   -
725   -feat: upload组件支持服务器本机和阿里云OSS自动上传功能及上传进度条
726   -
727   -feat: upload组件支持视频预览及oss上传时获取视频封面图
728   -
729   -feat: 新增up-action-sheet-data快捷组件
730   -
731   -feat: 新增up-picker-data快捷组件
732   -
733   -## 3.4.5(2025-03-24)
734   -feat: tag组件新增textSize/height/padding/borderRadius属性
735   -
736   -feat: 新增genLightColor自动计算浅色方法及tag组件支持autoBgColor自动计算背景色
737   -
738   -## 3.4.4(2025-03-13)
739   -feat: modal增加异步操作进行中点击取消弹出提示特性防止操作被中断
740   -
741   -fix: 修复toast组件show方法类型声明
742   -
743   -## 3.4.3(2025-03-12)
744   -fix: 修复textarea自动增高时在输入时高度异常
745   -
746   -## 3.4.2(2025-03-11)
747   -feat: step组件增加title插槽及增加辅助class便于自定义样式
748   -
749   -## 3.4.1(2025-03-11)
750   -feat: 新机制确保setConfig与http在nvue等环境下生效
751   -
752   -## 3.3.74(2025-03-06)
753   -fix: CateTab语法问题
754   -
755   -## 3.3.73(2025-03-06)
756   -feat: CateTab新增v-model:current属性
757   -
758   -## 3.3.72(2025-02-28)
759   -feat: tabs组件支持icon图标及插槽
760   -
761   -## 3.3.71(2025-02-27)
762   -feat: 折叠面板collapse增加titileStyle/iconStyle/rightIconStyle属性
763   -
764   -feat: 折叠面板组件新增cellCustomStyle/cellCustomClass属性
765   -
766   -fix: select组件盒模型
767   -
768   -## 3.3.70(2025-02-24)
769   -fix: 修改u-checkbox-group组件changes事件发生位置
770   -
771   -## 3.3.69(2025-02-19)
772   -picker允许传递禁用颜色props
773   -
774   -slider组件isRange状态下增加min max插槽分开显示内容
775   -
776   -feat: 新增经典下拉框组件up-select
777   -
778   -## 3.3.68(2025-02-12)
779   -fix: 修复weekText类型
780   -
781   -feat: 日历增加单选与多选指定禁止选中的日期功能
782   -
783   -fix: NumberBox删除数字时取值有误 #613
784   -
785   -## 3.3.67(2025-02-11)
786   -feat: navbar支持返回全局拦截器配置
787   -
788   -feat: 表单-校验-支持无提示-得到校验结果
789   -
790   -feat: picker传递hasInput属性时候,可以禁用输入框点击
791   -
792   -## 3.3.66(2025-02-09)
793   -feat: steps-item增加content插槽
794   -
795   -## 3.3.65(2025-02-05)
796   -feat: number-box组件新增按钮圆角/按钮宽度/数据框背景色/迷你模式
797   -## 3.3.64(2025-01-18)
798   -feat: 日历组件支持自定义星期文案
799   -
800   -## 3.3.63(2025-01-13)
801   -fix: cate-tab支持支付宝小程序
802   -
803   -fix: textarea 修复 placeholder-style
804   -
805   -fix: 修复在图片加载及加载失败时容器宽度
806   -
807   -fix: waterfall组件报错Maximum recursive updates
808   -
809   -## 3.3.62(2025-01-10)
810   -feat: sleder滑动选择器双滑块增加外层触发值的变动功能
811   -
812   -fix: picker支持hasInput优化
813   -
814   -## 3.3.61(2024-12-31)
815   -fix: 修复微信getSystemInfoSync接口废弃警告
816   -
817   -fix: 'u-status-bar' symbol missing
818   -
819   -## 3.3.60(2024-12-30)
820   -feat: 日期组件支持禁用
821   -
822   -fix: ts定义修复 #600
823   -
824   -feat: Tabs组件选中时增加一个active的class #595
825   -
826   -## 3.3.59(2024-12-30)
827   -fix: Property "isH5" was accessed during render
828   -
829   -## 3.3.58(2024-12-26)
830   -fix: slider组件change事件传参
831   -
832   -## 3.3.57(2024-12-23)
833   -fix: slider组件change事件传参
834   -
835   -feat: 更新u-picker组件增加当前选中class类名
836   -
837   -## 3.3.56(2024-12-18)
838   -feat: 在u-alert组件中添加关闭事件
839   -
840   -## 3.3.55(2024-12-17)
841   -add: swiper增加双向绑定
842   -
843   -## 3.3.54(2024-12-11)
844   -add: qrcode支持props控制是否开启点击预览
845   -
846   -add: 新增cate-tab垂直分类组件
847   -
848   -## 3.3.53(2024-12-10)
849   -fix: 修复popup居中模式点击内容区域触发关闭
850   -
851   -## 3.3.52(2024-12-09)
852   -add: notice-bar支持justifyContent属性
853   -
854   -## 3.3.51(2024-12-09)
855   -add: radio增加label插槽
856   -
857   -## 3.3.50(2024-12-05)
858   -fix: 优化popup等对禁止背景滚动机制
859   -
860   -add: slider在弹窗使用示例
861   -
862   -fix: card组件类名问题
863   -
864   -## 3.3.49(2024-12-02)
865   -fix: 去除album多余的$u引用
866   -
867   -fix: 优化图片组件兼容性
868   -
869   -add: picker组件增加zIndex属性
870   -
871   -add: text增加是否占满剩余空间属性
872   -
873   -add: input颜色示例
874   -
875   -## 3.3.48(2024-11-29)
876   -add: 文本行数限制样式提高到10行
877   -
878   -del: 去除不跨端的inputmode
879   -## 3.3.47(2024-11-28)
880   -fix: 时间选择器在hasInput模式下部分机型键盘弹出
881   -
882   -## 3.3.46(2024-11-26)
883   -fix: 修复text传递事件参数
884   -
885   -## 3.3.45(2024-11-24)
886   -add: navbar组件支持配置标题颜色
887   -
888   -fix: 边框按钮警告类型下颜色变量使用错误
889   -
890   -## 3.3.43(2024-11-18)
891   -fix: 支持瀑布流组件v-model置为[]
892   -
893   -add: 新增字符串路径访问工具方法getValueByPath
894   -
895   -add: 新增float-button悬浮按钮组件
896   -
897   -## 3.3.42(2024-11-15)
898   -add: button组件支持stop参数阻止冒泡
899   -
900   -## 3.3.41(2024-11-13)
901   -fix: u-radio-group invalid import
902   -
903   -improvement: 优化图片组件宽高及修复事件event传递
904   -
905   -## 3.3.40(2024-11-11)
906   -add: 组件radioGroup增加gap属性用于设置item间隔
907   -
908   -fix: 修复H5全局导入
909   -
910   -## 3.3.39(2024-11-04)
911   -fix: 修复相册组件
912   -
913   -## 3.3.38(2024-11-04)
914   -fix: 修复视频预览报错 #510
915   -
916   -add: album组件增加stop参数支持阻止事件冒泡
917   -
918   -## 3.3.37(2024-10-21)
919   -fix: 修复因为修改组件名称前缀,导致h5打包后$parent方法内找不到父组件的问题
920   -
921   -fix: 修复datetime-picker选择2000年以前日期出错
922   -
923   -## 3.3.36(2024-10-09)
924   -fix: toast 自动关闭
925   -
926   -feat: 增加微信小程序用户昵称审核完毕回调及修改 ts 定义文件
927   -
928   -## 3.3.35(2024-10-08)
929   -feat: modal和picker支持v-model:show双向绑定
930   -
931   -feat: 支持checkbox使用slot自定义label后自带点击事件 #522
932   -
933   -feat: swipe-action支持自动关闭特性及初始化打开状态
934   -
935   -## 3.3.34(2024-09-23)
936   -feat: 支持toast设置duration值为-1时不自动关闭
937   -
938   -## 3.3.33(2024-09-18)
939   -fix: 修复test.date('008')等验证结果不准确
940   -
941   -## 3.3.32(2024-09-09)
942   -fix: u-keyboard名称冲突warning
943   -
944   -## 3.3.31(2024-08-31)
945   -feat: qrcode初步支持nvue
946   -
947   -## 3.3.30(2024-08-30)
948   -fix: slider兼容step为字符串类型
949   -
950   -## 3.3.29(2024-08-30)
951   -fix: 修复tabs组件current参数为字符串处理逻辑
952   -
953   -## 3.3.28(2024-08-26)
954   -fix: list组件滑动偏移量不一样取绝对值导致iOS下拉偏移量计算错误
955   -
956   -## 3.3.27(2024-08-22)
957   -fix: 修复up-datetime-picker组件toolbarRightSlot定义缺失
958   -
959   -fix: 修复FormItem的rules更新错误的问题
960   -
961   -## 3.3.26(2024-08-22)
962   -fix: 批量注册全局组件优化
963   -
964   -## 3.3.25(2024-08-21)
965   -fix: 修复slider在app-vue下样式问题
966   -
967   -## 3.3.24(2024-08-19)
968   -fix: 修复时间选择器hasInput模式小程序不生效
969   -
970   -feat: 支持H5导入所有组件
971   -
972   -## 3.3.23(2024-08-17)
973   -feat: swipe-action增加closeAll方法
974   -
975   -fix: 兼容tabs在某些场景下index小于0时自动设置为0
976   -
977   -add: 通用mixin新增navTo页面跳转方法
978   -
979   -## 3.3.21(2024-08-15)
980   -improvement: 优化二维码组件loading及支持预览与长按事件 #351
981   -
982   -fix: 修复swipe-action自动关闭其它功能及组件卸载自动关闭
983   -
984   -## 3.3.20(2024-08-15)
985   -refactor: props默认值文件移至组件文件夹内便于查找
986   -## 3.3.19(2024-08-14)
987   -fix: 修复2被rpx兼容处理只在数字值生效
988   -
989   -add: 增加swiper自定义插槽示例
990   -
991   -## 3.3.18(2024-08-13)
992   -feat: 新增支持datetime-picker工具栏插槽及picker插槽支持修复
993   -## 3.3.17(2024-08-12)
994   -feat: swiper组件增加默认slot便于自定义
995   -
996   -feat: grid新增间隔参数
997   -
998   -feat: picker新增toolbar-right和toolbar-bottom插槽
999   -
1000   -## 3.3.16(2024-08-12)
1001   -fix: 解决swiper中title换行后多余的内容未被遮挡问题
1002   -
1003   -fix: 修复迷你导航适配异形屏
1004   -
1005   -## 3.3.15(2024-08-09)
1006   -fix: 修复默认单位设置为rpx时一些组件高度间距异常
1007   -
1008   -fix: 修复日历在rpx单位下布局异常
1009   -
1010   -feat: code-input支持App端展示输入光标
1011   -
1012   -## 3.3.14(2024-08-09)
1013   -add: 增加box组件
1014   -
1015   -add: 增加card卡片组件
1016   -
1017   -
1018   -## 3.3.13(2024-08-08)
1019   -feat: input支持调用原生组件的focus和blur方法
1020   -
1021   -improvement: grid-item条件编译优化
1022   -
1023   -add: 新增迷你导航组件
1024   -
1025   -## 3.3.12(2024-08-06)
1026   -improvement: $u挂载时机调整便于打包分离chunk
1027   -
1028   -fix: steps新增itemStyle属性名称冲突
1029   -
1030   -## 3.3.11(2024-08-05)
1031   -feat: 新增支持upload组件的deletable/maxCount/accept变更监听 #333
1032   -
1033   -feat: 新增支持tabs在swiper中使用
1034   -
1035   -feat: 新增FormItem支持独立设置验证规则rules
1036   -
1037   -fix: 修复index-list未设置$slots.header时索引高亮失效
1038   -
1039   -## 3.3.10(2024-08-02)
1040   -fix: 修复index-list偶发的滑动最后一个索引报错top不存在
1041   -
1042   -fix: 修复gird在QQ、抖音小程序下布局
1043   -
1044   -feat: 优化step支持自定义样式prop
1045   -
1046   -feat: action-sheet组件支持v-model:show双向绑定
1047   -
1048   -fix: 小程序下steps和grid都统一采用grid布局
1049   -
1050   -fix: 修复支付宝小程序下input类型为数字时双向绑定失效
1051   -
1052   -feat : form 表单 validate 校验不通过后 error增加字段prop信息 #304
1053   -
1054   -fix: form组件异步校异常验问题 #393
1055   -
1056   -## 3.3.9(2024-08-01)
1057   -fix: 优化获取nvue元素
1058   -
1059   -feat: modal新增contentTextAlign设置文案对齐方式
1060   -
1061   -fix: 修复NVUE下tabbar文字不显示 #458
1062   -
1063   -feat: loading-page增加zIndex属性
1064   -
1065   -fix: 相册在宽度较小时换行问题
1066   -
1067   -feat: album相册增加自适应自动换行模式
1068   -
1069   -feat: album相册增加图片尺寸单位prop
1070   -
1071   -fix: 修复calendar日历月份居中
1072   -
1073   -## 3.3.8(2024-07-31)
1074   -feat: slider支持进度条任意位置触发按钮拖动
1075   -
1076   -fix: 修复app-vue下modal标题不居中
1077   -
1078   -fix: #459 TS setConfig 声明异常
1079   -
1080   -feat: tabs组件增加longPress长按事件
1081   -
1082   -feat: 新增showRight属性控制collapse右侧图标显隐
1083   -
1084   -fix: 优化nvue下css警告
1085   -
1086   -## 3.3.7(2024-07-29)
1087   -feat: 支持IndexList组件支持在弹窗等场景下使用及联动优化
1088   -
1089   -feat: popup组件支持v-model:show双向绑定
1090   -
1091   -feat: 优化tabs的current双向绑定
1092   -
1093   -fix: checkbox独立使用时checked赋初始值可以,但是手动切换时值没有做双向绑定! #455
1094   -
1095   -feat: slider组件支持区间双滑块
1096   -
1097   -fix: toast 支持自定义图标?可传入了决对路径的 icon也没有用 #409
1098   -
1099   -feat: form-item校验失败时 增加class方便自定义显示错误的展示方式 #394
1100   -
1101   -fix: up-cell的required配置不生效 #395
1102   -
1103   -fix: 横向滚动组件,微信小程序编译后会有警告 #415
1104   -
1105   -fix: u-picker内部对默认值defaultIndex的监听 #425
1106   -
1107   -feat: toast 组件支持遮掩层穿透 #417
1108   -
1109   -fix: 兼容vue的slot编译bug #423
1110   -
1111   -fix: upload 微信小程序 点击预览视频报错 #424
1112   -
1113   -fix: u-number-box 组件修改【integer, decimalLength, min, max 】props时没有触发绑定值更新 #429
1114   -
1115   -feat: Tabs组件能否支持自定义插槽 #439
1116   -
1117   -feat: ActionSheet 可以配置最大高度吗, 我当做select使用了。 #445
1118   -
1119   -fix: cursor-pointer优化
1120   -
1121   -feat: 新版slider组件兼容NVUE改造
1122   -
1123   -feat: 新增slider组件手动实现以支持样式自定义
1124   -
1125   -perf:补充TS声明提示信息
1126   -
1127   -修复:ActionSheet 操作菜单cancelText属性为空DOM节点还存在并且可以点击问题
1128   -
1129   -fix: 去除预留的beforeDestroy兼容容易在某些sdk下不识别条件编译
1130   -
1131   -## 3.3.6(2024-07-23)
1132   -feat: u-album组件添加radius,shape参数,定义参考当前u-image参数
1133   -
1134   -fix: 修复了calendar组件title和日期title未垂直居中的问题
1135   -
1136   -fix: update:modelValue缺失emit定义
1137   -
1138   -## 3.3.5(2024-07-10)
1139   -picker组件支持hasInput模式
1140   -
1141   -## 3.3.4(2024-07-07)
1142   -fix: input组件双向绑定问题 #419
1143   -
1144   -lazy-load完善emit
1145   -
1146   -优化通用小程序分享
1147   -
1148   -## 3.3.2(2024-06-27)
1149   -fix: 在Nvue环境中编译,出现大量警告 #406
1150   -## 3.3.1(2024-06-27)
1151   -u-button组件报错,找不到button mixins #407
1152   -## 3.3.0(2024-06-27)
1153   -feat: checkbox支持label设置slot
1154   -
1155   -feat: modal增加customClass
1156   -
1157   -feat: navbar、popup、tabs、text支持customClass
1158   -
1159   -fix: cell组建缺少flex布局
1160   -
1161   -fix: 修复微信小程序真机调试时快速输入出现文本回退问题
1162   -
1163   -feat: tag增加默认slot
1164   -
1165   -公共mixin改造为按需导入语法
1166   -
1167   -refactor: 组件props混入mixin改造为按需导入语法
1168   -
1169   -fix: u-tabbar 安卓手机点击按钮变蓝问题 #396
1170   -
1171   -feat: upload组建增加extension属性
1172   -
1173   -fix: upload组件参数mode添加left
1174   -
1175   -fix: 修复阴影在非nvue时白色背景色不显示
1176   -
1177   -## 3.2.24(2024-06-11)
1178   -fix: 修复时间选择器confirm事件触发时机导致2次才会触发v-model更新
1179   -## 3.2.23(2024-05-30)
1180   -fix: #378 H5 u-input 在表单中初始值为空也会触发一次 formValidate(this,"change")事件导致进入页面直接校验了一次
1181   -
1182   -fix: #373 搜索组件up-search的@clear事件无效
1183   -
1184   -fix: #372 ActionSheet 组件的取消按钮触发区域太小
1185   -
1186   -## 3.2.22(2024-05-13)
1187   -上传组件支持微信小程序预览视频
1188   -
1189   -修复折叠面板右侧箭头不显示
1190   -
1191   -修复uxp2px
1192   -
1193   -## 3.2.21(2024-05-10)
1194   -fix: loading-icon修复flex布局
1195   -## 3.2.20(2024-05-10)
1196   -修复瀑布流大小写#355
1197   -## 3.2.19(2024-05-10)
1198   -去除意外的文件引入
1199   -## 3.2.18(2024-05-09)
1200   -fix: 349 popup 组件设置 zIndex 属性后,组件渲染异常#
1201   -feat: 搜索框增加adjustPosition属性
1202   -fix: #331增加u-action-sheet__cancel
1203   -优化mixin兼容性
1204   -feat: #326 up-list增加下拉刷新功能
1205   -fix: #319 优化up-tabs参数与定义匹配
1206   -fix: index-list组件微信小程序端使用自定义导航栏异常
1207   -fix: #285 pickerimmediateChange 写死为true
1208   -fix: #111 u-scroll-list组件,隐藏指示器后报错, 提示找不到ref
1209   -list增加微信小程序防抖配置
1210   -
1211   -## 3.2.17(2024-05-08)
1212   -fix: 支付宝小程序二维码渲染
1213   -## 3.2.16(2024-05-06)
1214   -修复tabs中,当前激活样式的undefined bug
1215   -
1216   -fix: #341u-code 倒计时没结束前退出,再次进入结束后退出界面,再次进入重新开始倒计时bug
1217   -
1218   -受到uni-app内置text样式影响修复
1219   -
1220   -## 3.2.15(2024-04-28)
1221   -优化时间选择器hasInput模式初始化值
1222   -## 3.2.14(2024-04-24)
1223   -去除pleaseSetTranspileDependencies
1224   -
1225   -http采用useStore
1226   -
1227   -## 3.2.13(2024-04-22)
1228   -修复modal标题样式
1229   -
1230   -优化日期选择器hasInput模式宽度
1231   -
1232   -## 3.2.12(2024-04-22)
1233   -修复color应用
1234   -## 3.2.11(2024-04-18)
1235   -修复import化带来的问题
1236   -## 3.2.10(2024-04-17)
1237   -完善input清空事件App端失效的兼容性
1238   -
1239   -修复日历组件二次打开后当前月份显示不正确
1240   -
1241   -## 3.2.9(2024-04-16)
1242   -组件内uni.$u用法改为import引入
1243   -
1244   -规范化及兼容性增强
1245   -
1246   -## 3.2.8(2024-04-15)
1247   -修复up-tag语法错
1248   -## 3.2.7(2024-04-15)
1249   -修复下拉菜单背景色在支付宝小程序无效
1250   -
1251   -setConfig改为浅拷贝解决无法用import导入代替uni.$u.props设置
1252   -
1253   -## 3.2.6(2024-04-14)
1254   -修复某些情况下滑动单元格默认右侧按钮是展开的问题
1255   -## 3.2.5(2024-04-13)
1256   -调整分段器尺寸及修复窗口大小改变时重新计算尺寸
1257   -
1258   -多个组件支持cursor-pointer增强PC端体验
1259   -
1260   -## 3.2.4(2024-04-12)
1261   -初步支持typescript
1262   -## 3.2.3(2024-04-12)
1263   -fix: 修复square属性在小程序下无效问题
1264   -
1265   -fix:修复lastIndex异常导致的column异常问题
1266   -
1267   -fix: alipayapp picker style
1268   -
1269   -feat(button): 添加用户同意隐私协议事件回调
1270   -
1271   -fix: input switch password
1272   -
1273   -fix: 修复u-code组件keepRuning失效问题
1274   -
1275   -feat: form-item添加labelPosition属性
1276   -
1277   -新增dropdown组件
1278   -
1279   -分段器支持内部current值
1280   -
1281   -优化cell和action-sheet视觉大小
1282   -
1283   -修复tabs文字换行
1284   -
1285   -## 3.2.2(2024-04-11)
1286   -修复换行符问题
1287   -## 3.2.1(2024-04-11)
1288   -修复演示H5二维码
1289   -
1290   -fix: #270 ReadMore 展开阅读更多内容变化兼容
1291   -
1292   -fix: #238Calendar组件maxDate修改为不能小于minDate
1293   -
1294   -checkbox支持独立使用
1295   -
1296   -修复popup中在微信小程序中真机调试滚动失效
1297   -
1298   -## 3.2.0(2024-04-10)
1299   -修复轮播图在nvue显示
1300   -修复疑似u-slider名称被占用导致slider在App下不显示
1301   -解决微信小程序提示 Some selectors are not allowed in component wxss
1302   -示例中u-前缀统一为up-
1303   -增加瀑布流与图片懒加载组件
1304   -fix: #308修复tag组件缺失iconColor参数
1305   -fix: #297使用grid布局解决目前编译为抖音小程序无法开启virtualHost
1306   -## 3.1.52(2024-04-07)
1307   -工具类方法调用import化改造
1308   -新增up-copy复制组件
1309   -## 3.1.51(2024-04-07)
1310   -优化时间选择器自带输入框格式化显示
1311   -防止按钮文字换行
1312   -修复订单列表模板滑动
1313   -增加u-qrcode二维码组件
1314   -## 3.1.49(2024-03-27)
1315   -日期时间组件支持自带输入框
1316   -fix: popup弹窗滚动穿透问题
1317   -fix: 修复小程序numberbox bug
1318   -## 3.1.48(2024-03-18)
1319   -fix:[plugin:uni:pre-css] Unbalanced delimiter found in string
1320   -## 3.1.47(2024-03-18)
1321   -fix: setConfig设置组件默认参数无效问题
1322   -fix: 修复自定义图标无效问题
1323   -feat: 增加u-form-item单独设置规则变量
1324   -fix:#293小程序是自定义导航栏的时候即传了customNavHeight的时候会出现跳转偏移的情况
1325   -
1326   -## 3.1.46(2024-01-29)
1327   -beforeUnmount
1328   -## 3.1.45(2024-01-24)
1329   -fix: #262ext组件为超链接的情况下size属性不生效
1330   -fix: #263最新版本3.1.42中微信小程序u-swipe-action-item报错
1331   -fix: #224最新版本3.1.42中微信小程序u-swipe-action-item报错
1332   -fix: #263支持支付宝小程序
1333   -fix: #261u-input在直接修改v-model的绑定值时,每隔一次会无法出发change事件
1334   -优化折叠面板兼容微信小程序
1335   -## 3.1.42(2024-01-15)
1336   -修复u-number-box默认值0时在小程序不显示值
1337   -优化u-code的timer判断
1338   -优化支付宝小程序下textarea字数统计兼容
1339   -优化u-calendar
1340   -## 3.1.41(2023-11-18)
1341   -#215优化u-cell图标容器间距问题
1342   -## 3.1.40(2023-11-16)
1343   -修复u-slider双向绑定
1344   -## 3.1.39(2023-11-10)
1345   -修复头条小程序不支持env(safe-area-inset-bottom)
1346   -优化#201u-grid 指定列数导致闪烁
1347   -#193IndexList 索引列表 高度错误
1348   -其他优化
1349   -## 3.1.38(2023-10-08)
1350   -修复u-slider
1351   -## 3.1.37(2023-09-13)
1352   -完善emits定义及修复code-input双向数据绑定
1353   -## 3.1.36(2023-08-08)
1354   -修复富文本事件名称大小写
1355   -## 3.1.35(2023-08-02)
1356   -修复编译到支付宝小程序u-form报错
1357   -## 3.1.34(2023-07-27)
1358   -修复App打包uni.$u.mpMixin方式sdk暂时不支持导致报错
1359   -## 3.1.33(2023-07-13)
1360   -修复弹窗进入动画、模板页面样式等
1361   -## 3.1.31(2023-07-11)
1362   -修复dayjs引用
1363   -## 3.0.8(2022-07-12)
1364   -修复u-tag默认宽度撑满容器
1365   -## 3.0.7(2022-07-12)
1366   -修复u-navbar自定义插槽演示示例
1367   -## 3.0.6(2022-07-11)
1368   -修复u-image缺少emits申明
1369   -## 3.0.5(2022-07-11)
1370   -修复u-upload缺少emits申明
1371   -## 3.0.4(2022-07-10)
1372   -修复u-textarea/u-input/u-datetime-picker/u-number-box/u-radio-group/u-switch/u-rate在vue3下数据绑定
1373   -## 3.0.3(2022-07-09)
1374   -启用自建演示二维码
1375   -## 3.0.2(2022-07-09)
1376   -修复dayjs/clipboard等导致打包报错
1377   -## 3.0.1(2022-07-09)
1378   -增加插件市场地址
1379   -## 3.0.0(2022-07-09)
1380   -# uview-plus(vue3)初步发布
uni_modules/uview-plus/components/u-action-sheet-data/u-action-sheet-data.vue deleted
1   -<template>
2   - <view class="u-action-sheet-data">
3   - <view class="u-action-sheet-data__trigger">
4   - <slot name="trigger"></slot>
5   - <up-input
6   - v-if="!$slots['trigger']"
7   - :modelValue="current"
8   - disabled
9   - disabledColor="#ffffff"
10   - :placeholder="title"
11   - border="none"
12   - ></up-input>
13   - <view @click="show = true"
14   - class="u-action-sheet-data__trigger__cover"></view>
15   - </view>
16   - <up-action-sheet
17   - :show="show"
18   - :actions="options"
19   - :title="title"
20   - safeAreaInsetBottom
21   - :description="description"
22   - @close="show = false"
23   - @select="select"
24   - >
25   - </up-action-sheet>
26   - </view>
27   -</template>
28   -
29   -<script>
30   -export default {
31   - props: {
32   - modelValue: {
33   - type: [String, Number],
34   - default: ''
35   - },
36   - title: {
37   - type: String,
38   - default: ''
39   - },
40   - description: {
41   - type: String,
42   - default: ''
43   - },
44   - options: {
45   - type: Array,
46   - default: () => {
47   - return []
48   - }
49   - },
50   - valueKey: {
51   - type: String,
52   - default: 'value'
53   - },
54   - labelKey: {
55   - type: String,
56   - default: 'name'
57   - }
58   - },
59   - data() {
60   - return {
61   - show: false,
62   - current: '',
63   - }
64   - },
65   - created() {
66   - if (this.modelValue) {
67   - this.options.forEach((ele) => {
68   - if (ele[this.valueKey] == this.modelValue) {
69   - this.current = ele[this.labelKey]
70   - }
71   - })
72   - }
73   - },
74   - emits: ['update:modelValue'],
75   - watch: {
76   - modelValue() {
77   - this.options.forEach((ele) => {
78   - if (ele[this.valueKey] == this.modelValue) {
79   - this.current = ele[this.labelKey]
80   - }
81   - })
82   - }
83   - },
84   - methods: {
85   - hideKeyboard() {
86   - uni.hideKeyboard()
87   - },
88   - select(e) {
89   - this.$emit('update:modelValue', e[this.valueKey])
90   - this.current = e[this.labelKey]
91   - },
92   - }
93   -}
94   -</script>
95   -
96   -<style lang="scss" scoped>
97   - .u-action-sheet-data {
98   - &__trigger {
99   - position: relative;
100   - &__cover {
101   - position: absolute;
102   - top: 0;
103   - left: 0;
104   - right: 0;
105   - bottom: 0;
106   - }
107   - }
108   - }
109   -</style>
110 0 \ No newline at end of file
uni_modules/uview-plus/components/u-action-sheet/actionSheet.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 3.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : jry
7   - * @lastTime : 2025-08-16 10:52:35
8   - * @FilePath : /uview-plus/libs/config/props/actionSheet.js
9   - */
10   -export default {
11   - // action-sheet组件
12   - actionSheet: {
13   - show: false,
14   - title: '',
15   - description: '',
16   - actions: [],
17   - index: '',
18   - cancelText: '',
19   - closeOnClickAction: true,
20   - safeAreaInsetBottom: true,
21   - openType: '',
22   - closeOnClickOverlay: true,
23   - round: 0,
24   - wrapMaxHeight: '600px'
25   - }
26   -}
uni_modules/uview-plus/components/u-action-sheet/props.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 3.0
5   - * @LastAuthor : jry
6   - * @lastTime : 2025-08-16 10:52:35
7   - * @FilePath : /uview-plus/libs/config/props/props.js
8   - */
9   -import { defineMixin } from '../../libs/vue'
10   -import defProps from '../../libs/config/props.js'
11   -
12   -export const props = defineMixin({
13   - props: {
14   - // 操作菜单是否展示 (默认false)
15   - show: {
16   - type: Boolean,
17   - default: () => defProps.actionSheet.show
18   - },
19   - // 标题
20   - title: {
21   - type: String,
22   - default: () => defProps.actionSheet.title
23   - },
24   - // 选项上方的描述信息
25   - description: {
26   - type: String,
27   - default: () => defProps.actionSheet.description
28   - },
29   - // 数据
30   - actions: {
31   - type: Array,
32   - default: () => defProps.actionSheet.actions
33   - },
34   - // 取消按钮的文字,不为空时显示按钮
35   - cancelText: {
36   - type: String,
37   - default: () => defProps.actionSheet.cancelText
38   - },
39   - // 点击某个菜单项时是否关闭弹窗
40   - closeOnClickAction: {
41   - type: Boolean,
42   - default: () => defProps.actionSheet.closeOnClickAction
43   - },
44   - // 处理底部安全区(默认true)
45   - safeAreaInsetBottom: {
46   - type: Boolean,
47   - default: () => defProps.actionSheet.safeAreaInsetBottom
48   - },
49   - // 小程序的打开方式
50   - openType: {
51   - type: String,
52   - default: () => defProps.actionSheet.openType
53   - },
54   - // 点击遮罩是否允许关闭 (默认true)
55   - closeOnClickOverlay: {
56   - type: Boolean,
57   - default: () => defProps.actionSheet.closeOnClickOverlay
58   - },
59   - // 圆角值
60   - round: {
61   - type: [Boolean, String, Number],
62   - default: () => defProps.actionSheet.round
63   - },
64   - // 选项区域最大高度
65   - wrapMaxHeight: {
66   - type: [String],
67   - default: () => defProps.actionSheet.wrapMaxHeight
68   - },
69   - }
70   -})
uni_modules/uview-plus/components/u-action-sheet/u-action-sheet.vue deleted
1   -<template>
2   - <u-popup
3   - :show="show"
4   - mode="bottom"
5   - @close="closeHandler"
6   - :safeAreaInsetBottom="safeAreaInsetBottom"
7   - :round="round"
8   - >
9   - <view class="u-action-sheet">
10   - <!-- 顶部标题区域 -->
11   - <view
12   - class="u-action-sheet__header"
13   - v-if="title"
14   - >
15   - <text class="u-action-sheet__header__title u-line-1">{{title}}</text>
16   - <view
17   - class="u-action-sheet__header__icon-wrap"
18   - @tap.stop="cancel"
19   - >
20   - <up-icon
21   - name="close"
22   - size="17"
23   - color="#c8c9cc"
24   - bold
25   - ></up-icon>
26   - </view>
27   - </view>
28   - <!-- 描述信息 -->
29   - <text
30   - class="u-action-sheet__description"
31   - :style="[{
32   - marginTop: `${title && description ? 0 : '18px'}`
33   - }]"
34   - v-if="description"
35   - >{{description}}</text>
36   - <slot>
37   - <!-- 分割线 -->
38   - <u-line v-if="description"></u-line>
39   - <!-- 操作项列表 -->
40   - <scroll-view scroll-y class="u-action-sheet__item-wrap" :style="{maxHeight: wrapMaxHeight}">
41   - <view :key="index" v-for="(item, index) in actions">
42   - <!-- #ifdef MP -->
43   - <button
44   - class="u-reset-button"
45   - :openType="item.openType"
46   - @getuserinfo="onGetUserInfo"
47   - @contact="onContact"
48   - @getphonenumber="onGetPhoneNumber"
49   - @error="onError"
50   - @launchapp="onLaunchApp"
51   - @opensetting="onOpenSetting"
52   - :lang="lang"
53   - :session-from="sessionFrom"
54   - :send-message-title="sendMessageTitle"
55   - :send-message-path="sendMessagePath"
56   - :send-message-img="sendMessageImg"
57   - :show-message-card="showMessageCard"
58   - :app-parameter="appParameter"
59   - @tap="selectHandler(index)"
60   - :hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"
61   - >
62   - <!-- #endif -->
63   - <view
64   - class="u-action-sheet__item-wrap__item"
65   - @tap.stop="selectHandler(index)"
66   - :hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"
67   - :hover-stay-time="150"
68   - :style="getItemHoverStyle(index)"
69   - >
70   - <template v-if="!item.loading">
71   - <text
72   - class="u-action-sheet__item-wrap__item__name"
73   - :style="[itemStyle(index)]"
74   - >{{ item.name }}</text>
75   - <text
76   - v-if="item.subname"
77   - class="u-action-sheet__item-wrap__item__subname"
78   - >{{ item.subname }}</text>
79   - </template>
80   - <!-- 加载状态图标 -->
81   - <u-loading-icon
82   - v-else
83   - custom-class="van-action-sheet__loading"
84   - size="18"
85   - mode="circle"
86   - />
87   - </view>
88   - <!-- #ifdef MP -->
89   - </button>
90   - <!-- #endif -->
91   - <!-- 选项间分割线 -->
92   - <u-line v-if="index !== actions.length - 1"></u-line>
93   - </view>
94   - </scroll-view>
95   - </slot>
96   - <!-- 取消按钮前的分割区域 -->
97   - <u-gap
98   - bgColor="#eaeaec"
99   - height="6"
100   - v-if="cancelText"
101   - ></u-gap>
102   - <!-- 取消按钮 -->
103   - <view class="u-action-sheet__item-wrap__item u-action-sheet__cancel"
104   - hover-class="u-action-sheet--hover" @tap="cancel" v-if="cancelText">
105   - <text
106   - @touchmove.stop.prevent
107   - :hover-stay-time="150"
108   - class="u-action-sheet__cancel-text"
109   - >{{cancelText}}</text>
110   - </view>
111   - </view>
112   - </u-popup>
113   -</template>
114   -
115   -<script>
116   - import { openType } from '../../libs/mixin/openType'
117   - import { buttonMixin } from '../../libs/mixin/button'
118   - import { props } from './props';
119   - import { mpMixin } from '../../libs/mixin/mpMixin';
120   - import { mixin } from '../../libs/mixin/mixin';
121   - import { addUnit } from '../../libs/function/index';
122   - /**
123   - * ActionSheet 操作菜单
124   - * @description 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI,配置更加灵活,所有平台都表现一致。
125   - * @tutorial https://uview-plus.jiangruyi.com/components/actionSheet.html
126   - *
127   - * @property {Boolean} show 操作菜单是否展示 (默认 false )
128   - * @property {String} title 操作菜单标题
129   - * @property {String} description 选项上方的描述信息
130   - * @property {Array<Object>} actions 按钮的文字数组,见官方文档示例
131   - * @property {String} cancelText 取消按钮的提示文字,不为空时显示按钮
132   - * @property {Boolean} closeOnClickAction 点击某个菜单项时是否关闭弹窗 (默认 true )
133   - * @property {Boolean} safeAreaInsetBottom 处理底部安全区 (默认 true )
134   - * @property {String} openType 小程序的打开方式 (contact | launchApp | getUserInfo | openSetting |getPhoneNumber |error )
135   - * @property {Boolean} closeOnClickOverlay 点击遮罩是否允许关闭 (默认 true )
136   - * @property {Number|String} round 圆角值,默认无圆角 (默认 0 )
137   - * @property {String} lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文
138   - * @property {String} sessionFrom 会话来源,openType="contact"时有效
139   - * @property {String} sendMessageTitle 会话内消息卡片标题,openType="contact"时有效
140   - * @property {String} sendMessagePath 会话内消息卡片点击跳转小程序路径,openType="contact"时有效
141   - * @property {String} sendMessageImg 会话内消息卡片图片,openType="contact"时有效
142   - * @property {Boolean} showMessageCard 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,openType="contact"时有效 (默认 false )
143   - * @property {String} appParameter 打开 APP 时,向 APP 传递的参数,openType=launchApp 时有效
144   - *
145   - * @event {Function} select 点击ActionSheet列表项时触发
146   - * @event {Function} close 点击取消按钮时触发
147   - * @event {Function} getuserinfo 用户点击该按钮时,会返回获取到的用户信息,回调的 detail 数据与 wx.getUserInfo 返回的一致,openType="getUserInfo"时有效
148   - * @event {Function} contact 客服消息回调,openType="contact"时有效
149   - * @event {Function} getphonenumber 获取用户手机号回调,openType="getPhoneNumber"时有效
150   - * @event {Function} error 当使用开放能力时,发生错误的回调,openType="error"时有效
151   - * @event {Function} launchapp 打开 APP 成功的回调,openType="launchApp"时有效
152   - * @event {Function} opensetting 在打开授权设置页后回调,openType="openSetting"时有效
153   - * @example <u-action-sheet :actions="list" :title="title" :show="show"></u-action-sheet>
154   - */
155   - export default {
156   - name: "u-action-sheet",
157   - // 一些props参数和methods方法,通过mixin混入,因为其他文件也会用到
158   - mixins: [openType, buttonMixin, mixin, props],
159   - data() {
160   - return {
161   -
162   - }
163   - },
164   - computed: {
165   - // 操作项目的样式
166   - itemStyle() {
167   - return (index) => {
168   - let style = {};
169   - if (this.actions[index].color) style.color = this.actions[index].color
170   - if (this.actions[index].fontSize) style.fontSize = addUnit(this.actions[index].fontSize)
171   - // 选项被禁用的样式
172   - if (this.actions[index].disabled) style.color = '#c0c4cc'
173   - return style;
174   - }
175   - },
176   - },
177   - emits: ["close", "select", "update:show"],
178   - methods: {
179   - // 关闭操作菜单事件处理
180   - closeHandler() {
181   - // 允许点击遮罩关闭时,才发出close事件
182   - if(this.closeOnClickOverlay) {
183   - this.$emit('update:show', false)
184   - this.$emit('close')
185   - }
186   - },
187   - // 点击取消按钮
188   - cancel() {
189   - this.$emit('update:show', false)
190   - this.$emit('close')
191   - },
192   - // 选择操作项处理
193   - selectHandler(index) {
194   - const item = this.actions[index]
195   - if (item && !item.disabled && !item.loading) {
196   - this.$emit('select', item)
197   - if (this.closeOnClickAction) {
198   - this.$emit('update:show', false)
199   - this.$emit('close')
200   - }
201   - }
202   - },
203   - // 动态处理Hover时候第一个item的圆角
204   - getItemHoverStyle(index) {
205   - if (index === 0 && this.round && !this.title && !this.description) {
206   - return {
207   - borderTopLeftRadius: `${this.round}px`,
208   - borderTopRightRadius: `${this.round}px`,
209   - }
210   - }
211   - return {}
212   - },
213   - }
214   - }
215   -</script>
216   -
217   -<style lang="scss" scoped>
218   - $u-action-sheet-reset-button-width:100% !default;
219   - $u-action-sheet-title-font-size: 16px !default;
220   - $u-action-sheet-title-padding: 12px 30px !default;
221   - $u-action-sheet-title-color: $u-main-color !default;
222   - $u-action-sheet-header-icon-wrap-right:15px !default;
223   - $u-action-sheet-header-icon-wrap-top:15px !default;
224   - $u-action-sheet-description-font-size:13px !default;
225   - $u-action-sheet-description-color:14px !default;
226   - $u-action-sheet-description-margin: 18px 15px !default;
227   - $u-action-sheet-item-wrap-item-padding:17px !default;
228   - $u-action-sheet-item-wrap-name-font-size:16px !default;
229   - $u-action-sheet-item-wrap-subname-font-size:13px !default;
230   - $u-action-sheet-item-wrap-subname-color: #c0c4cc !default;
231   - $u-action-sheet-item-wrap-subname-margin-top:10px !default;
232   - $u-action-sheet-cancel-text-font-size:16px !default;
233   - $u-action-sheet-cancel-text-color:$u-content-color !default;
234   - $u-action-sheet-cancel-text-font-size:15px !default;
235   - $u-action-sheet-cancel-text-hover-background-color:rgb(242, 243, 245) !default;
236   -
237   - .u-reset-button {
238   - width: $u-action-sheet-reset-button-width;
239   - }
240   -
241   - .u-action-sheet {
242   - text-align: center;
243   - &__header {
244   - position: relative;
245   - padding: $u-action-sheet-title-padding;
246   - &__title {
247   - font-size: $u-action-sheet-title-font-size;
248   - color: $u-action-sheet-title-color;
249   - font-weight: bold;
250   - text-align: center;
251   - }
252   -
253   - &__icon-wrap {
254   - position: absolute;
255   - right: $u-action-sheet-header-icon-wrap-right;
256   - top: $u-action-sheet-header-icon-wrap-top;
257   - }
258   - }
259   -
260   - &__description {
261   - font-size: $u-action-sheet-description-font-size;
262   - color: $u-tips-color;
263   - margin: $u-action-sheet-description-margin;
264   - text-align: center;
265   - }
266   -
267   - &__item-wrap {
268   -
269   - &__item {
270   - padding: $u-action-sheet-item-wrap-item-padding;
271   - @include flex;
272   - align-items: center;
273   - justify-content: center;
274   - flex-direction: column;
275   -
276   - &__name {
277   - font-size: $u-action-sheet-item-wrap-name-font-size;
278   - color: $u-main-color;
279   - text-align: center;
280   - }
281   -
282   - &__subname {
283   - font-size: $u-action-sheet-item-wrap-subname-font-size;
284   - color: $u-action-sheet-item-wrap-subname-color;
285   - margin-top: $u-action-sheet-item-wrap-subname-margin-top;
286   - text-align: center;
287   - }
288   - }
289   - }
290   -
291   - &__cancel-text {
292   - font-size: $u-action-sheet-cancel-text-font-size;
293   - color: $u-action-sheet-cancel-text-color;
294   - text-align: center;
295   - // padding: $u-action-sheet-cancel-text-font-size;
296   - }
297   -
298   - &--hover {
299   - background-color: $u-action-sheet-cancel-text-hover-background-color;
300   - }
301   - }
302   -</style>
303 0 \ No newline at end of file
uni_modules/uview-plus/components/u-agreement/u-agreement.vue deleted
1   -<style scoped lang="scss">
2   - .agreement-content {
3   - width: 100%;;
4   - display: inline-block;
5   - flex-direction: column;
6   - .agreement-url {
7   - display: inline-block;
8   - color: blue;
9   - // #ifdef H5
10   - cursor: pointer;
11   - // #endif
12   - }
13   - }
14   -</style>
15   -
16   -<template>
17   - <view class="up-agreement">
18   - <up-modal v-model:show="show" showCancelButton @confirm="confirm" @cancel="close" confirmText="阅读并同意">
19   - <view class="agreement-content">
20   - <slot>
21   - 我们非常重视您的个人信息和隐私保护。为了更好地保障您的个人权益,在您使用我们的产品前,
22   - 请务必审慎阅读《<text class="agreement-url" @click="urlClick('urlProtocol')">用户协议</text>》
23   - 和《<text class="agreement-url" @click="urlClick('urlPrivacy')">隐私政策</text>》内的所有条款,
24   - 尤其是:1.我们对您的个人信息的收集/保存/使用/对外提供/保护等规则条款,以及您的用户权利等条款;2. 约定我们的限制责任、免责
25   - 条款;3.其他以颜色或加粗进行标识的重要条款。如您对以上协议有任何疑问,请先不要同意,您点击“同意并继续”的行为即表示您已阅读
26   - 完毕并同意以上协议的全部内容。
27   - </slot>
28   - </view>
29   - </up-modal>
30   - </view>
31   -</template>
32   -
33   -<script>
34   - export default {
35   - name: 'up-agreement',
36   - props: {
37   - urlProtocol: {
38   - type: String,
39   - default: '/pages/user_agreement/agreement/info?title=用户协议'
40   - },
41   - urlPrivacy: {
42   - type: String,
43   - default: '/pages/user_agreement/agreement/info?title=隐私政策'
44   - },
45   - },
46   - emits: ['confirm'],
47   - data() {
48   - return {
49   - show: false
50   - }
51   - },
52   - methods: {
53   - close() {
54   - // #ifdef H5
55   - window.opener = null;
56   - window.close();
57   - // #endif
58   - // #ifdef APP-PLUS
59   - plus.runtime.quit();
60   - // #endif
61   - },
62   - confirm() {
63   - this.show = false;
64   - this.$emit('confirm', 1);
65   - },
66   - showModal() {
67   - this.show = true;
68   - },
69   - urlClick(type) {
70   - uni.navigateTo({
71   - url: this[type]
72   - });
73   - }
74   - }
75   - }
76   -</script>
uni_modules/uview-plus/components/u-album/album.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : jry
7   - * @lastTime : 2025-08-16 16:32:24
8   - * @FilePath : /uview-plus/libs/config/props/album.js
9   - */
10   -export default {
11   - // album 组件
12   - album: {
13   - urls: [],
14   - keyName: '',
15   - singleSize: 180,
16   - multipleSize: 70,
17   - space: 6,
18   - singleMode: 'scaleToFill',
19   - multipleMode: 'aspectFill',
20   - maxCount: 9,
21   - previewFullImage: true,
22   - rowCount: 3,
23   - showMore: true,
24   - autoWrap: false,
25   - unit: 'px',
26   - stop: true,
27   - }
28   -}
uni_modules/uview-plus/components/u-album/props.js deleted
1   -/*
2   - * @Author : jry
3   - * @Description :
4   - * @version : 3.0
5   - * @LastAuthor : jry
6   - * @lastTime : 2025-08-16 16:35:24
7   - * @FilePath : /uview-plus/components/u-album/props.js
8   - */
9   -import { defineMixin } from '../../libs/vue'
10   -import defProps from '../../libs/config/props.js'
11   -
12   -export const props = defineMixin({
13   - props: {
14   - // 图片地址,Array<String>|Array<Object>形式
15   - urls: {
16   - type: Array,
17   - default: () => defProps.album.urls
18   - },
19   - // 指定从数组的对象元素中读取哪个属性作为图片地址
20   - keyName: {
21   - type: String,
22   - default: () => defProps.album.keyName
23   - },
24   - // 单图时,图片长边的长度
25   - singleSize: {
26   - type: [String, Number],
27   - default: () => defProps.album.singleSize
28   - },
29   - // 多图时,图片边长
30   - multipleSize: {
31   - type: [String, Number],
32   - default: () => defProps.album.multipleSize
33   - },
34   - // 多图时,图片水平和垂直之间的间隔
35   - space: {
36   - type: [String, Number],
37   - default: () => defProps.album.space
38   - },
39   - // 单图时,图片缩放裁剪的模式
40   - singleMode: {
41   - type: String,
42   - default: () => defProps.album.singleMode
43   - },
44   - // 多图时,图片缩放裁剪的模式
45   - multipleMode: {
46   - type: String,
47   - default: () => defProps.album.multipleMode
48   - },
49   - // 最多展示的图片数量,超出时最后一个位置将会显示剩余图片数量
50   - maxCount: {
51   - type: [String, Number],
52   - default: () => defProps.album.maxCount
53   - },
54   - // 是否可以预览图片
55   - previewFullImage: {
56   - type: Boolean,
57   - default: () => defProps.album.previewFullImage
58   - },
59   - // 每行展示图片数量,如设置,singleSize和multipleSize将会无效
60   - rowCount: {
61   - type: [String, Number],
62   - default: () => defProps.album.rowCount
63   - },
64   - // 超出maxCount时是否显示查看更多的提示
65   - showMore: {
66   - type: Boolean,
67   - default: () => defProps.album.showMore
68   - },
69   - // 图片形状,circle-圆形,square-方形
70   - shape: {
71   - type: String,
72   - default: () => defProps.image.shape
73   - },
74   - // 圆角,单位任意
75   - radius: {
76   - type: [String, Number],
77   - default: () => defProps.image.radius
78   - },
79   - // 自适应换行
80   - autoWrap: {
81   - type: Boolean,
82   - default: () => defProps.album.autoWrap
83   - },
84   - // 单位
85   - unit: {
86   - type: [String],
87   - default: () => defProps.album.unit
88   - },
89   - // 阻止点击冒泡
90   - stop: {
91   - type: Boolean,
92   - default: () => defProps.album.stop
93   - }
94   - }
95   -})
uni_modules/uview-plus/components/u-album/u-album.vue deleted
1   -<template>
2   - <view class="u-album">
3   - <!-- 相册行容器,每行显示 rowCount 个图片 -->
4   - <view
5   - class="u-album__row"
6   - ref="u-album__row"
7   - v-for="(arr, index) in showUrls"
8   - :forComputedUse="albumWidth"
9   - :key="index"
10   - :style="{flexWrap: autoWrap ? 'wrap' : 'nowrap'}"
11   - >
12   - <!-- 图片包装容器 -->
13   - <view
14   - class="u-album__row__wrapper"
15   - v-for="(item, index1) in arr"
16   - :key="index1"
17   - :style="[imageStyle(index + 1, index1 + 1)]"
18   - @tap="onPreviewTap($event, getSrc(item))"
19   - >
20   - <!-- 图片显示 -->
21   - <image
22   - :src="getSrc(item)"
23   - :mode="
24   - urls.length === 1
25   - ? imageHeight > 0
26   - ? singleMode
27   - : 'widthFix'
28   - : multipleMode
29   - "
30   - :style="[
31   - {
32   - width: imageWidth,
33   - height: imageHeight,
34   - borderRadius: shape == 'circle' ? '10000px' : addUnit(radius)
35   - }
36   - ]"
37   - ></image>
38   - <!-- 超出最大显示数量时的更多提示 -->
39   - <view
40   - v-if="
41   - showMore &&
42   - urls.length > rowCount * showUrls.length &&
43   - index === showUrls.length - 1 &&
44   - index1 === showUrls[showUrls.length - 1].length - 1
45   - "
46   - class="u-album__row__wrapper__text"
47   - :style="{
48   - borderRadius: shape == 'circle' ? '50%' : addUnit(radius),
49   - }"
50   - >
51   - <up-text
52   - :text="`+${urls.length - maxCount}`"
53   - color="#fff"
54   - :size="multipleSize * 0.3"
55   - align="center"
56   - customStyle="justify-content: center"
57   - ></up-text>
58   - </view>
59   - </view>
60   - </view>
61   - </view>
62   -</template>
63   -
64   -<script>
65   -import { props } from './props';
66   -import { mpMixin } from '../../libs/mixin/mpMixin';
67   -import { mixin } from '../../libs/mixin/mixin';
68   -import { addUnit, sleep } from '../../libs/function/index';
69   -import test from '../../libs/function/test';
70   -// #ifdef APP-NVUE
71   -// 不支持百分比单位,这里需要通过dom查询组件的宽度
72   -const dom = uni.requireNativePlugin('dom')
73   -// #endif
74   -
75   -/**
76   - * Album 相册
77   - * @description 本组件提供一个类似相册的功能,让开发者开发起来更加得心应手。减少重复的模板代码
78   - * @tutorial https://uview-plus.jiangruyi.com/components/album.html
79   - *
80   - * @property {Array} urls 图片地址列表 Array<String>|Array<Object>形式
81   - * @property {String} keyName 指定从数组的对象元素中读取哪个属性作为图片地址
82   - * @property {String | Number} singleSize 单图时,图片长边的长度 (默认 180 )
83   - * @property {String | Number} multipleSize 多图时,图片边长 (默认 70 )
84   - * @property {String | Number} space 多图时,图片水平和垂直之间的间隔 (默认 6 )
85   - * @property {String} singleMode 单图时,图片缩放裁剪的模式 (默认 'scaleToFill' )
86   - * @property {String} multipleMode 多图时,图片缩放裁剪的模式 (默认 'aspectFill' )
87   - * @property {String | Number} maxCount 取消按钮的提示文字 (默认 9 )
88   - * @property {Boolean} previewFullImage 是否可以预览图片 (默认 true )
89   - * @property {String | Number} rowCount 每行展示图片数量,如设置,singleSize和multipleSize将会无效 (默认 3 )
90   - * @property {Boolean} showMore 超出maxCount时是否显示查看更多的提示 (默认 true )
91   - * @property {String} shape 图片形状,circle-圆形,square-方形 (默认 'square' )
92   - * @property {String | Number} radius 圆角值,单位任意,如果为数值,则为px单位 (默认 0 )
93   - * @property {Boolean} autoWrap 自适应换行模式,不受rowCount限制,图片会自动换行 (默认 false )
94   - * @property {String} unit 图片单位 (默认 px )
95   - * @event {Function} albumWidth 某些特殊的情况下,需要让文字与相册的宽度相等,这里事件的形式对外发送 (回调参数 width )
96   - * @example <u-album :urls="urls2" @albumWidth="width => albumWidth = width" multipleSize="68" ></u-album>
97   - */
98   -export default {
99   - name: 'u-album',
100   - mixins: [mpMixin, mixin, props],
101   - data() {
102   - return {
103   - // 单图的宽度
104   - singleWidth: 0,
105   - // 单图的高度
106   - singleHeight: 0,
107   - // 单图时,如果无法获取图片的尺寸信息,让图片宽度默认为容器的一定百分比
108   - singlePercent: 0.6
109   - }
110   - },
111   - watch: {
112   - urls: {
113   - immediate: true,
114   - handler(newVal) {
115   - // 当只有一张图片时,获取图片尺寸信息
116   - if (newVal.length === 1) {
117   - this.getImageRect()
118   - }
119   - }
120   - }
121   - },
122   - computed: {
123   - /**
124   - * 计算图片样式
125   - * @param {Number} index1 - 行索引
126   - * @param {Number} index2 - 列索引
127   - * @returns {Object} 图片样式对象
128   - */
129   - imageStyle() {
130   - return (index1, index2) => {
131   - const { space, rowCount, multipleSize, urls } = this,
132   - rowLen = this.showUrls.length,
133   - allLen = this.urls.length
134   - const style = {
135   - marginRight: addUnit(space),
136   - marginBottom: addUnit(space)
137   - }
138   - // 如果为最后一行,则每个图片都无需下边框
139   - if (index1 === rowLen && !this.autoWrap) style.marginBottom = 0
140   - // 每行的最右边一张和总长度的最后一张无需右边框
141   - if (!this.autoWrap) {
142   - if (
143   - index2 === rowCount ||
144   - (index1 === rowLen &&
145   - index2 === this.showUrls[index1 - 1].length)
146   - )
147   - style.marginRight = 0
148   - }
149   - return style
150   - }
151   - },
152   - /**
153   - * 将图片地址数组划分为二维数组,用于按行显示
154   - * @returns {Array} 二维数组,每个子数组代表一行图片
155   - */
156   - showUrls() {
157   - if (this.autoWrap) {
158   - // 自动换行模式下,所有图片放在一行中显示
159   - return [ this.urls.slice(0, this.maxCount) ];
160   - } else {
161   - // 固定行数模式下,按 rowCount 分割图片
162   - const arr = []
163   - this.urls.map((item, index) => {
164   - // 限制最大展示数量
165   - if (index + 1 <= this.maxCount) {
166   - // 计算该元素为第几个素组内
167   - const itemIndex = Math.floor(index / this.rowCount)
168   - // 判断对应的索引是否存在
169   - if (!arr[itemIndex]) {
170   - arr[itemIndex] = []
171   - }
172   - arr[itemIndex].push(item)
173   - }
174   - })
175   - return arr
176   - }
177   - },
178   - /**
179   - * 计算图片宽度
180   - * @returns {String} 图片宽度样式值
181   - */
182   - imageWidth() {
183   - return addUnit(
184   - this.urls.length === 1 ? this.singleWidth : this.multipleSize, this.unit
185   - )
186   - },
187   - /**
188   - * 计算图片高度
189   - * @returns {String} 图片高度样式值
190   - */
191   - imageHeight() {
192   - return addUnit(
193   - this.urls.length === 1 ? this.singleHeight : this.multipleSize, this.unit
194   - )
195   - },
196   - /**
197   - * 计算相册总宽度,用于外部组件对齐
198   - * 此变量无实际用途,仅仅是为了利用computed特性,让其在urls长度等变化时,重新计算图片的宽度
199   - * @returns {Number} 相册宽度
200   - */
201   - albumWidth() {
202   - let width = 0
203   - if (this.urls.length === 1) {
204   - width = this.singleWidth
205   - } else {
206   - width =
207   - this.showUrls[0].length * this.multipleSize +
208   - this.space * (this.showUrls[0].length - 1)
209   - }
210   - this.$emit('albumWidth', width)
211   - return width
212   - }
213   - },
214   - emits: ['preview', 'albumWidth'],
215   - methods: {
216   - addUnit,
217   - /**
218   - * 点击图片预览
219   - * @param {Event} e - 点击事件对象
220   - * @param {String} url - 当前点击图片的地址
221   - */
222   - onPreviewTap(e, url) {
223   - // 获取所有图片地址
224   - const urls = this.urls.map((item) => {
225   - return this.getSrc(item)
226   - })
227   - if (this.previewFullImage) {
228   - // 使用系统默认预览图片功能
229   - uni.previewImage({
230   - current: url,
231   - urls
232   - })
233   - // 是否阻止事件传播
234   - this.stop && this.preventEvent(e)
235   - } else {
236   - // 发送自定义预览事件
237   - this.$emit('preview', {
238   - urls,
239   - currentIndex: urls.indexOf(url)
240   - })
241   - }
242   - },
243   - /**
244   - * 获取图片地址
245   - * @param {String|Object} item - 图片项,可以是字符串或对象
246   - * @returns {String} 图片地址
247   - */
248   - getSrc(item) {
249   - return test.object(item)
250   - ? (this.keyName && item[this.keyName]) || item.src
251   - : item
252   - },
253   - /**
254   - * 单图时,获取图片的尺寸
255   - * 在小程序中,需要将网络图片的的域名添加到小程序的download域名才可能获取尺寸
256   - * 在没有添加的情况下,让单图宽度默认为盒子的一定宽度(singlePercent)
257   - */
258   - getImageRect() {
259   - const src = this.getSrc(this.urls[0])
260   - uni.getImageInfo({
261   - src,
262   - success: (res) => {
263   - let singleSize = this.singleSize;
264   - // 单位
265   - let unit = '';
266   - if (Number.isNaN(Number(this.singleSize))) {
267   - // 大小中有字符 则记录字符
268   - unit = this.singleSize.replace(/\d+/g, ''); // 单位
269   - singleSize = Number(this.singleSize.replace(/\D+/g, ''), 10); // 具体值
270   - }
271   -
272   - // 判断图片横向还是竖向展示方式
273   - const isHorizotal = res.width >= res.height
274   - this.singleWidth = isHorizotal
275   - ? singleSize
276   - : (res.width / res.height) * singleSize
277   - this.singleHeight = !isHorizotal
278   - ? singleSize
279   - : (res.height / res.width) * this.singleWidth
280   -
281   - // 如果有单位统一设置单位
282   - if(unit != null && unit !== ''){
283   - this.singleWidth = this.singleWidth + unit
284   - this.singleHeight = this.singleHeight + unit
285   - }
286   - },
287   - fail: () => {
288   - // 获取图片信息失败时,通过组件宽度计算
289   - this.getComponentWidth()
290   - }
291   - })
292   - },
293   - /**
294   - * 获取组件的宽度,用于计算单图显示尺寸
295   - */
296   - async getComponentWidth() {
297   - // 延时一定时间,以获取dom尺寸
298   - await sleep(30)
299   - // #ifndef APP-NVUE
300   - // H5、小程序等平台通过 $uGetRect 获取组件宽度
301   - this.$uGetRect('.u-album__row').then((size) => {
302   - this.singleWidth = size.width * this.singlePercent
303   - })
304   - // #endif
305   -
306   - // #ifdef APP-NVUE
307   - // NVUE 平台通过 dom 插件获取组件宽度
308   - // 这里ref="u-album__row"所在的标签为通过for循环出来,导致this.$refs['u-album__row']是一个数组
309   - const ref = this.$refs['u-album__row'][0]
310   - ref &&
311   - dom.getComponentRect(ref, (res) => {
312   - this.singleWidth = res.size.width * this.singlePercent
313   - })
314   - // #endif
315   - }
316   - }
317   -}
318   -</script>
319   -
320   -<style lang="scss" scoped>
321   -.u-album {
322   - @include flex(column);
323   -
324   - &__row {
325   - @include flex(row);
326   -
327   - &__wrapper {
328   - position: relative;
329   -
330   - &__text {
331   - position: absolute;
332   - top: 0;
333   - left: 0;
334   - right: 0;
335   - bottom: 0;
336   - background-color: rgba(0, 0, 0, 0.3);
337   - @include flex(row);
338   - justify-content: center;
339   - align-items: center;
340   - }
341   - }
342   - }
343   -}
344   -</style>
345 0 \ No newline at end of file
uni_modules/uview-plus/components/u-alert/alert.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 3.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : jry
7   - * @lastTime : 2025-08-17 17:23:53
8   - * @FilePath : /uview-plus/libs/config/props/alert.js
9   - */
10   -export default {
11   - // alert警告组件
12   - alert: {
13   - title: '',
14   - type: 'warning',
15   - description: '',
16   - closable: false,
17   - showIcon: false,
18   - effect: 'light',
19   - center: false,
20   - fontSize: 14,
21   - transitionMode: 'fade',
22   - duration: 0,
23   - icon: '',
24   - value: true
25   - }
26   -}
uni_modules/uview-plus/components/u-alert/props.js deleted
1   -/*
2   - * @Author : jry
3   - * @Description :
4   - * @version : 3.0
5   - * @LastAuthor : jry
6   - * @lastTime : 2025-08-17 17:23:53
7   - * @FilePath : /uview-plus/libs/config/props/props.js
8   - */
9   -import { defineMixin } from '../../libs/vue'
10   -import defProps from '../../libs/config/props.js'
11   -
12   -export const props = defineMixin({
13   - props: {
14   - // 显示文字
15   - title: {
16   - type: String,
17   - default: () => defProps.alert.title
18   - },
19   - // 主题,success/warning/info/error
20   - type: {
21   - type: String,
22   - default: () => defProps.alert.type
23   - },
24   - // 辅助性文字
25   - description: {
26   - type: String,
27   - default: () => defProps.alert.description
28   - },
29   - // 是否可关闭
30   - closable: {
31   - type: Boolean,
32   - default: () => defProps.alert.closable
33   - },
34   - // 是否显示图标
35   - showIcon: {
36   - type: Boolean,
37   - default: () => defProps.alert.showIcon
38   - },
39   - // 浅或深色调,light-浅色,dark-深色
40   - effect: {
41   - type: String,
42   - default: () => defProps.alert.effect
43   - },
44   - // 文字是否居中
45   - center: {
46   - type: Boolean,
47   - default: () => defProps.alert.center
48   - },
49   - // 字体大小
50   - fontSize: {
51   - type: [String, Number],
52   - default: () => defProps.alert.fontSize
53   - },
54   - // 动画类型
55   - transitionMode: {
56   - type: [String],
57   - default: () => defProps.alert.transitionMode
58   - },
59   - // 自动定时关闭毫秒
60   - duration: {
61   - type: [Number],
62   - default: () => defProps.alert.duration
63   - },
64   - // 自定义图标
65   - icon: {
66   - type: [String],
67   - default: () => defProps.alert.icon
68   - },
69   - // 是否显示
70   - modelValue: {
71   - type: [Boolean],
72   - default: () => defProps.alert.value
73   - }
74   - }
75   -})
uni_modules/uview-plus/components/u-alert/u-alert.vue deleted
1   -<template>
2   - <up-transition
3   - :mode="transitionMode"
4   - :show="show"
5   - >
6   - <view
7   - class="u-alert"
8   - :class="[`u-alert--${type}--${effect}`]"
9   - @tap.stop="clickHandler"
10   - :style="[addStyle(customStyle)]"
11   - >
12   - <!-- 左侧图标 -->
13   - <view
14   - class="u-alert__icon"
15   - v-if="showIcon"
16   - >
17   - <up-icon
18   - :name="iconName"
19   - size="18"
20   - :color="iconColor"
21   - ></up-icon>
22   - </view>
23   - <!-- 内容区域 -->
24   - <view
25   - class="u-alert__content"
26   - :style="[{
27   - paddingRight: closable ? '20px' : 0
28   - }]"
29   - >
30   - <!-- 标题 -->
31   - <text
32   - class="u-alert__content__title"
33   - v-if="title"
34   - :style="[{
35   - fontSize: addUnit(fontSize),
36   - textAlign: center ? 'center' : 'left'
37   - }]"
38   - :class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
39   - >{{ title }}</text>
40   - <!-- 描述信息 -->
41   - <text
42   - class="u-alert__content__desc"
43   - v-if="description"
44   - :style="[{
45   - fontSize: addUnit(fontSize),
46   - textAlign: center ? 'center' : 'left'
47   - }]"
48   - :class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
49   - >{{ description }}</text>
50   - </view>
51   - <!-- 关闭按钮 -->
52   - <view
53   - class="u-alert__close"
54   - v-if="closable"
55   - @tap.stop="closeHandler"
56   - >
57   - <slot name="close">
58   - <up-icon
59   - name="close"
60   - :color="iconColor"
61   - size="15"
62   - ></up-icon>
63   - </slot>
64   - </view>
65   - </view>
66   - </up-transition>
67   -</template>
68   -
69   -<script>
70   - import { props } from './props';
71   - import { mpMixin } from '../../libs/mixin/mpMixin';
72   - import { mixin } from '../../libs/mixin/mixin';
73   - import { addUnit, addStyle } from '../../libs/function/index';
74   - /**
75   - * Alert 警告提示
76   - * @description 警告提示,展现需要关注的信息。
77   - * @tutorial https://uview-plus.jiangruyi.com/components/alertTips.html
78   - *
79   - * @property {String} title 显示的文字
80   - * @property {String} type 使用预设的颜色 (默认 'warning' )
81   - * @property {String} description 辅助性文字,颜色比title浅一点,字号也小一点,可选
82   - * @property {Boolean} closable 关闭按钮(默认为叉号icon图标) (默认 false )
83   - * @property {Boolean} showIcon 是否显示左边的辅助图标 ( 默认 false )
84   - * @property {String} effect 多图时,图片缩放裁剪的模式 (默认 'light' )
85   - * @property {Boolean} center 文字是否居中 (默认 false )
86   - * @property {String | Number} fontSize 字体大小 (默认 14 )
87   - * @property {Object} customStyle 定义需要用到的外部样式
88   - * @property {String} transitionMode 过渡动画模式 (默认 'fade' )
89   - * @property {String | Number} duration 自动关闭延时(毫秒),设置为0或负数则不自动关闭 (默认 0 )
90   - * @property {String} icon 自定义图标名称,优先级高于type默认图标
91   - * @property {Boolean} modelValue/v-model 绑定值,控制是否显示 (默认 true )
92   - * @event {Function} click 点击组件时触发
93   - * @event {Function} close 点击关闭按钮时触发
94   - * @event {Function} closed 关闭动画结束时触发
95   - * @example <up-alert :title="title" type = "warning" :closable="closable" :description = "description"></up-alert>
96   - */
97   - export default {
98   - name: 'u-alert',
99   - mixins: [mpMixin, mixin, props],
100   - data() {
101   - return {
102   - // 控制组件显示隐藏
103   - show: true
104   - }
105   - },
106   - computed: {
107   - // 根据不同的主题类型返回对应的图标颜色
108   - iconColor() {
109   - return this.effect === 'light' ? this.type : '#fff'
110   - },
111   - // 不同主题对应不同的图标
112   - iconName() {
113   - // 如果用户自定义了图标,则优先使用自定义图标
114   - if (this.icon) return this.icon;
115   -
116   - switch (this.type) {
117   - case 'success':
118   - return 'checkmark-circle-fill';
119   - break;
120   - case 'error':
121   - return 'close-circle-fill';
122   - break;
123   - case 'warning':
124   - return 'error-circle-fill';
125   - break;
126   - case 'info':
127   - return 'info-circle-fill';
128   - break;
129   - case 'primary':
130   - return 'more-circle-fill';
131   - break;
132   - default:
133   - return 'error-circle-fill';
134   - }
135   - }
136   - },
137   - emits: ["click","close", "closed", "update:modelValue"],
138   - watch: {
139   - modelValue: {
140   - handler(newVal) {
141   - this.show = newVal;
142   - },
143   - immediate: true
144   - },
145   - show: {
146   - handler(newVal) {
147   - this.$emit('update:modelValue', newVal);
148   -
149   - // 如果是从显示到隐藏,且启用了自动关闭功能
150   - if (!newVal && this.duration > 0) {
151   - this.$emit('closed');
152   - }
153   - }
154   - }
155   - },
156   - mounted() {
157   - // 如果设置了自动关闭时间,则在指定时间后自动关闭
158   - if (this.duration > 0) {
159   - setTimeout(() => {
160   - this.closeHandler();
161   - }, this.duration);
162   - }
163   - },
164   - methods: {
165   - addUnit,
166   - addStyle,
167   - // 点击内容区域触发click事件
168   - clickHandler() {
169   - this.$emit('click')
170   - },
171   - // 点击关闭按钮触发close事件并隐藏组件
172   - closeHandler() {
173   - this.show = false
174   - this.$emit('close');
175   - }
176   - }
177   - }
178   -</script>
179   -
180   -<style lang="scss" scoped>
181   -
182   - .u-alert {
183   - position: relative;
184   - background-color: $u-primary;
185   - padding: 8px 10px;
186   - @include flex(row);
187   - align-items: center;
188   - border-top-left-radius: 4px;
189   - border-top-right-radius: 4px;
190   - border-bottom-left-radius: 4px;
191   - border-bottom-right-radius: 4px;
192   -
193   - &--primary--dark {
194   - background-color: $u-primary;
195   - }
196   -
197   - &--primary--light {
198   - background-color: #ecf5ff;
199   - }
200   -
201   - &--error--dark {
202   - background-color: $u-error;
203   - }
204   -
205   - &--error--light {
206   - background-color: #FEF0F0;
207   - }
208   -
209   - &--success--dark {
210   - background-color: $u-success;
211   - }
212   -
213   - &--success--light {
214   - background-color: #f5fff0;
215   - }
216   -
217   - &--warning--dark {
218   - background-color: $u-warning;
219   - }
220   -
221   - &--warning--light {
222   - background-color: #FDF6EC;
223   - }
224   -
225   - &--info--dark {
226   - background-color: $u-info;
227   - }
228   -
229   - &--info--light {
230   - background-color: #f4f4f5;
231   - }
232   -
233   - &__icon {
234   - margin-right: 5px;
235   - }
236   -
237   - &__content {
238   - @include flex(column);
239   - flex: 1;
240   -
241   - &__title {
242   - color: $u-main-color;
243   - font-size: 14px;
244   - font-weight: bold;
245   - color: #fff;
246   - margin-bottom: 2px;
247   - }
248   -
249   - &__desc {
250   - color: $u-main-color;
251   - font-size: 14px;
252   - flex-wrap: wrap;
253   - color: #fff;
254   - }
255   - }
256   -
257   - &__title--dark,
258   - &__desc--dark {
259   - color: #FFFFFF;
260   - }
261   -
262   - &__text--primary--light,
263   - &__text--primary--light {
264   - color: $u-primary;
265   - }
266   -
267   - &__text--success--light,
268   - &__text--success--light {
269   - color: $u-success;
270   - }
271   -
272   - &__text--warning--light,
273   - &__text--warning--light {
274   - color: $u-warning;
275   - }
276   -
277   - &__text--error--light,
278   - &__text--error--light {
279   - color: $u-error;
280   - }
281   -
282   - &__text--info--light,
283   - &__text--info--light {
284   - color: $u-info;
285   - }
286   -
287   - &__close {
288   - position: absolute;
289   - top: 11px;
290   - right: 10px;
291   - }
292   - }
293   -</style>
uni_modules/uview-plus/components/u-avatar-group/avatarGroup.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:49:55
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/avatarGroup.js
9   - */
10   -export default {
11   - // avatarGroup 组件
12   - avatarGroup: {
13   - urls: [],
14   - maxCount: 5,
15   - shape: 'circle',
16   - mode: 'scaleToFill',
17   - showMore: true,
18   - size: 40,
19   - keyName: '',
20   - gap: 0.5,
21   - extraValue: 0
22   - }
23   -}
uni_modules/uview-plus/components/u-avatar-group/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 头像图片组
6   - urls: {
7   - type: Array,
8   - default: () => defProps.avatarGroup.urls
9   - },
10   - // 最多展示的头像数量
11   - maxCount: {
12   - type: [String, Number],
13   - default: () => defProps.avatarGroup.maxCount
14   - },
15   - // 头像形状
16   - shape: {
17   - type: String,
18   - default: () => defProps.avatarGroup.shape
19   - },
20   - // 图片裁剪模式
21   - mode: {
22   - type: String,
23   - default: () => defProps.avatarGroup.mode
24   - },
25   - // 超出maxCount时是否显示查看更多的提示
26   - showMore: {
27   - type: Boolean,
28   - default: () => defProps.avatarGroup.showMore
29   - },
30   - // 头像大小
31   - size: {
32   - type: [String, Number],
33   - default: () => defProps.avatarGroup.size
34   - },
35   - // 指定从数组的对象元素中读取哪个属性作为图片地址
36   - keyName: {
37   - type: String,
38   - default: () => defProps.avatarGroup.keyName
39   - },
40   - // 头像之间的遮挡比例
41   - gap: {
42   - type: [String, Number],
43   - validator(value) {
44   - return value >= 0 && value <= 1
45   - },
46   - default: () => defProps.avatarGroup.gap
47   - },
48   - // 需额外显示的值
49   - extraValue: {
50   - type: [Number, String],
51   - default: () => defProps.avatarGroup.extraValue
52   - }
53   - }
54   -})
uni_modules/uview-plus/components/u-avatar-group/u-avatar-group.vue deleted
1   -<template>
2   - <view class="u-avatar-group">
3   - <view
4   - class="u-avatar-group__item"
5   - v-for="(item, index) in showUrl"
6   - :key="index"
7   - :style="{
8   - marginLeft: index === 0 ? 0 : addUnit(-size * gap)
9   - }"
10   - >
11   - <u-avatar
12   - :size="size"
13   - :shape="shape"
14   - :mode="mode"
15   - :src="testObject(item) ? keyName && item[keyName] || item.url : item"
16   - ></u-avatar>
17   - <view
18   - class="u-avatar-group__item__show-more"
19   - v-if="showMore && index === showUrl.length - 1 && (urls.length > maxCount || extraValue > 0)"
20   - @tap="clickHandler"
21   - >
22   - <up-text
23   - color="#ffffff"
24   - :size="size * 0.4"
25   - :text="`+${extraValue || urls.length - showUrl.length}`"
26   - align="center"
27   - customStyle="justify-content: center"
28   - ></up-text>
29   - </view>
30   - </view>
31   - </view>
32   -</template>
33   -
34   -<script>
35   - import { props } from './props';
36   - import { mpMixin } from '../../libs/mixin/mpMixin';
37   - import { mixin } from '../../libs/mixin/mixin';
38   - import { addUnit } from '../../libs/function/index';
39   - import test from '../../libs/function/test';
40   - /**
41   - * AvatarGroup 头像组
42   - * @description 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。
43   - * @tutorial https://uview-plus.jiangruyi.com/components/avatar.html
44   - *
45   - * @property {Array} urls 头像图片组 (默认 [] )
46   - * @property {String | Number} maxCount 最多展示的头像数量 ( 默认 5 )
47   - * @property {String} shape 头像形状( 'circle' (默认) | 'square' )
48   - * @property {String} mode 图片裁剪模式(默认 'scaleToFill' )
49   - * @property {Boolean} showMore 超出maxCount时是否显示查看更多的提示 (默认 true )
50   - * @property {String | Number} size 头像大小 (默认 40 )
51   - * @property {String} keyName 指定从数组的对象元素中读取哪个属性作为图片地址
52   - * @property {String | Number} gap 头像之间的遮挡比例(0.4代表遮挡40%) (默认 0.5 )
53   - * @property {String | Number} extraValue 需额外显示的值
54   - * @event {Function} showMore 头像组更多点击
55   - * @example <u-avatar-group:urls="urls" size="35" gap="0.4" ></u-avatar-group:urls=>
56   - */
57   - export default {
58   - name: 'u-avatar-group',
59   - mixins: [mpMixin, mixin, props],
60   - data() {
61   - return {
62   -
63   - }
64   - },
65   - computed: {
66   - showUrl() {
67   - return this.urls.slice(0, this.maxCount)
68   - }
69   - },
70   - emits: ["showMore"],
71   - methods: {
72   - addUnit,
73   - testObject: test.object,
74   - clickHandler() {
75   - this.$emit('showMore')
76   - }
77   - },
78   - }
79   -</script>
80   -
81   -<style lang="scss" scoped>
82   -
83   - .u-avatar-group {
84   - @include flex;
85   -
86   - &__item {
87   - margin-left: -10px;
88   - position: relative;
89   -
90   - &--no-indent {
91   - // 如果你想质疑作者不会使用:first-child,说明你太年轻,因为nvue不支持
92   - margin-left: 0;
93   - }
94   -
95   - &__show-more {
96   - position: absolute;
97   - top: 0;
98   - bottom: 0;
99   - left: 0;
100   - right: 0;
101   - background-color: rgba(0, 0, 0, 0.3);
102   - @include flex;
103   - align-items: center;
104   - justify-content: center;
105   - border-radius: 100px;
106   - }
107   - }
108   - }
109   -</style>
uni_modules/uview-plus/components/u-avatar/avatar.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:49:22
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/avatar.js
9   - */
10   -export default {
11   - // avatar 组件
12   - avatar: {
13   - src: '',
14   - shape: 'circle',
15   - size: 40,
16   - mode: 'scaleToFill',
17   - text: '',
18   - bgColor: '#c0c4cc',
19   - color: '#ffffff',
20   - fontSize: 18,
21   - icon: '',
22   - mpAvatar: false,
23   - randomBgColor: false,
24   - defaultUrl: '',
25   - colorIndex: '',
26   - name: ''
27   - }
28   -}
uni_modules/uview-plus/components/u-avatar/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -import test from '../../libs/function/test';
4   -export const props = defineMixin({
5   - props: {
6   - // 头像图片路径(不能为相对路径)
7   - src: {
8   - type: String,
9   - default: () => defProps.avatar.src
10   - },
11   - // 头像形状,circle-圆形,square-方形
12   - shape: {
13   - type: String,
14   - default: () => defProps.avatar.shape
15   - },
16   - // 头像尺寸
17   - size: {
18   - type: [String, Number],
19   - default: () => defProps.avatar.size
20   - },
21   - // 裁剪模式
22   - mode: {
23   - type: String,
24   - default: () => defProps.avatar.mode
25   - },
26   - // 显示的文字
27   - text: {
28   - type: String,
29   - default: () => defProps.avatar.text
30   - },
31   - // 背景色
32   - bgColor: {
33   - type: String,
34   - default: () => defProps.avatar.bgColor
35   - },
36   - // 文字颜色
37   - color: {
38   - type: String,
39   - default: () => defProps.avatar.color
40   - },
41   - // 文字大小
42   - fontSize: {
43   - type: [String, Number],
44   - default: () => defProps.avatar.fontSize
45   - },
46   - // 显示的图标
47   - icon: {
48   - type: String,
49   - default: () => defProps.avatar.icon
50   - },
51   - // 显示小程序头像,只对百度,微信,QQ小程序有效
52   - mpAvatar: {
53   - type: Boolean,
54   - default: () => defProps.avatar.mpAvatar
55   - },
56   - // 是否使用随机背景色
57   - randomBgColor: {
58   - type: Boolean,
59   - default: () => defProps.avatar.randomBgColor
60   - },
61   - // 加载失败的默认头像(组件有内置默认图片)
62   - defaultUrl: {
63   - type: String,
64   - default: () => defProps.avatar.defaultUrl
65   - },
66   - // 如果配置了randomBgColor为true,且配置了此值,则从默认的背景色数组中取出对应索引的颜色值,取值0-19之间
67   - colorIndex: {
68   - type: [String, Number],
69   - // 校验参数规则,索引在0-19之间
70   - validator(n) {
71   - return test.range(n, [0, 19]) || n === ''
72   - },
73   - default: () => defProps.avatar.colorIndex
74   - },
75   - // 组件标识符
76   - name: {
77   - type: String,
78   - default: () => defProps.avatar.name
79   - }
80   - }
81   -})
uni_modules/uview-plus/components/u-avatar/u-avatar.vue deleted
1   -<template>
2   - <view
3   - class="u-avatar"
4   - :class="[`u-avatar--${shape}`]"
5   - :style="[{
6   - backgroundColor: (text || icon) ? (randomBgColor ? colors[colorIndex !== '' ? colorIndex : random(0, 19)] : bgColor) : 'transparent',
7   - width: addUnit(size),
8   - height: addUnit(size),
9   - }, addStyle(customStyle)]"
10   - @tap="clickHandler"
11   - >
12   - <slot>
13   - <!-- #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU -->
14   - <open-data
15   - v-if="mpAvatar && allowMp"
16   - type="userAvatarUrl"
17   - :style="[{
18   - width: addUnit(size),
19   - height: addUnit(size)
20   - }]"
21   - />
22   - <!-- #endif -->
23   - <!-- #ifndef MP-WEIXIN && MP-QQ && MP-BAIDU -->
24   - <template v-if="mpAvatar && allowMp"></template>
25   - <!-- #endif -->
26   - <up-icon
27   - v-else-if="icon"
28   - :name="icon"
29   - :size="fontSize"
30   - :color="color"
31   - ></up-icon>
32   - <up-text
33   - v-else-if="text"
34   - :text="text"
35   - :size="fontSize"
36   - :color="color"
37   - align="center"
38   - customStyle="justify-content: center"
39   - ></up-text>
40   - <image
41   - class="u-avatar__image"
42   - v-else
43   - :class="[`u-avatar__image--${shape}`]"
44   - :src="avatarUrl || defaultUrl"
45   - :mode="mode"
46   - @error="errorHandler"
47   - :style="[{
48   - width: addUnit(size),
49   - height: addUnit(size)
50   - }]"
51   - ></image>
52   - </slot>
53   - </view>
54   -</template>
55   -
56   -<script>
57   - import { props } from './props';
58   - import { mpMixin } from '../../libs/mixin/mpMixin';
59   - import { mixin } from '../../libs/mixin/mixin';
60   - import { addStyle, addUnit, random } from '../../libs/function/index';
61   - const base64Avatar =
62   - "data:image/jpg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/4QMraHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjMtYzAxMSA2Ni4xNDU2NjEsIDIwMTIvMDIvMDYtMTQ6NTY6MjcgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzYgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjREMEQwRkY0RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjREMEQwRkY1RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NEQwRDBGRjJGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NEQwRDBGRjNGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAGBAQEBQQGBQUGCQYFBgkLCAYGCAsMCgoLCgoMEAwMDAwMDBAMDg8QDw4MExMUFBMTHBsbGxwfHx8fHx8fHx8fAQcHBw0MDRgQEBgaFREVGh8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx//wAARCADIAMgDAREAAhEBAxEB/8QAcQABAQEAAwEBAAAAAAAAAAAAAAUEAQMGAgcBAQAAAAAAAAAAAAAAAAAAAAAQAAIBAwICBgkDBQAAAAAAAAABAhEDBCEFMVFBYXGREiKBscHRMkJSEyOh4XLxYjNDFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8A/fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHbHFyZ/Dam+yLA+Z2L0Pjtyj2poD4AAAAAAAAAAAAAAAAAAAAAAAAKWFs9y6lcvvwQeqj8z9wFaziY1n/HbUX9XF97A7QAGXI23EvJ1goyfzR0YEfN269jeZ+a03pNe0DIAAAAAAAAAAAAAAAAAAAACvtO3RcVkXlWutuL9YFYAAAAAOJRjKLjJVi9GmB5/csH/mu1h/in8PU+QGMAAAAAAAAAAAAAAAAAAaMDG/6MmMH8C80+xAelSSVFolwQAAAAAAAHVlWI37ErUulaPk+hgeYnCUJuElSUXRrrQHAAAAAAAAAAAAAAAAABa2Oz4bM7r4zdF2ICmAAAAAAAAAg7zZ8GX41wuJP0rRgYAAAAAAAAAAAAAAAAAD0m2R8ODaXU33tsDSAAAAAAAAAlb9HyWZcnJd9PcBHAAAAAAAAAAAAAAAAAPS7e64Vn+KA0AAAAAAAAAJm+v8Ftf3ewCKAAAAAAAAAAAAAAAAAX9muqeGo9NttP06+0DcAAAAAAAAAjb7dTu2ra+VOT9P8AQCWAAAAAAAAAAAAAAAAAUNmyPt5Ltv4bui/kuAF0AAAAAAADiUlGLlJ0SVW+oDzOXfd/Ind6JPRdS0QHSAAAAAAAAAAAAAAAAAE2nVaNcGB6Lbs6OTao9LsF51z60BrAAAAAABJ3jOVHjW3r/sa9QEgAAAAAAAAAAAAAAAAAAAPu1duWriuW34ZR4MC9hbnZyEoy8l36XwfYBsAAADaSq9EuLAlZ+7xSdrGdW9Hc5dgEdtt1erfFgAAAAAAAAAAAAAAAAADVjbblX6NR8MH80tEBRs7HYivyzlN8lovaBPzduvY0m6eK10TXtAyAarO55lpJK54orolr+4GqO/Xaea1FvqbXvA+Z77kNeW3GPbV+4DJfzcm/pcm3H6Vou5AdAFLC2ed2Pjv1txa8sV8T6wOL+yZEKu1JXFy4MDBOE4ScZxcZLinoB8gAAAAAAAAAAAB242LeyJ+C3GvN9C7QLmJtePYpKS+5c+p8F2IDYAANJqj1T4oCfk7Nj3G5Wn9qXJax7gJ93Z82D8sVNc4v30A6Xg5i42Z+iLfqARwcyT0sz9MWvWBps7LlTf5Grce9/oBTxdtxseklHxT+uWr9AGoAB138ezfj4bsFJdD6V2MCPm7RdtJzs1uW1xXzL3gTgAAAAAAAAADRhYc8q74I6RWs5ckB6GxYtWLat21SK731sDsAAAAAAAAAAAAAAAASt021NO/YjrxuQXT1oCOAAAAAAABzGLlJRSq26JAelwsWONYjbXxcZvmwO8AAAAAAAAAAAAAAAAAAef3TEWPkVivx3NY9T6UBiAAAAAABo2+VmGXblddIJ8eivRUD0oAAAAAAAAAAAAAAAAAAAYt4tKeFKVNYNSXfRgefAAAAAAAAr7VuSSWPedKaW5v1MCsAAAAAAAAAAAAAAAAAAIe6bj96Ts2n+JPzSXzP3ATgAAAAAAAAFbbt1UUrOQ9FpC4/UwK6aaqtU+DAAAAAAAAAAAAAAA4lKMIuUmoxWrb4ARNx3R3q2rLpa4Sl0y/YCcAAAAAAAAAAANmFud7G8r89r6X0dgFvGzLGRGtuWvTF6NAdwAAAAAAAAAAAy5W442PVN+K59EePp5ARMvOv5MvO6QXCC4AZwAAAAAAAAAAAAAcxlKLUotprg1owN+PvORborq+7Hnwl3gUbO74VzRydt8pKn68ANcJwmqwkpLmnUDkAAAAfNy9atqtyagut0AxXt5xIV8Fbj6lRd7Am5G65V6qUvtwfyx94GMAAAAAAAAAAAAAAAAAAAOU2nVOj5gdsc3LiqRvTpyqwOxbnnrhdfpSfrQB7pnv/AGvuS9gHXPMy5/Fem1yq0v0A6W29XqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//Z";
63   - /**
64   - * Avatar 头像
65   - * @description 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。
66   - * @tutorial https://uview-plus.jiangruyi.com/components/avatar.html
67   - *
68   - * @property {String} src 头像路径,如加载失败,将会显示默认头像(不能为相对路径)
69   - * @property {String} shape 头像形状 ( circle (默认) | square)
70   - * @property {String | Number} size 头像尺寸,可以为指定字符串(large, default, mini),或者数值 (默认 40 )
71   - * @property {String} mode 头像图片的裁剪类型,与uni的image组件的mode参数一致,如效果达不到需求,可尝试传widthFix值 (默认 'scaleToFill' )
72   - * @property {String} text 用文字替代图片,级别优先于src
73   - * @property {String} bgColor 背景颜色,一般显示文字时用 (默认 '#c0c4cc' )
74   - * @property {String} color 文字颜色 (默认 '#ffffff' )
75   - * @property {String | Number} fontSize 文字大小 (默认 18 )
76   - * @property {String} icon 显示的图标
77   - * @property {Boolean} mpAvatar 显示小程序头像,只对百度,微信,QQ小程序有效 (默认 false )
78   - * @property {Boolean} randomBgColor 是否使用随机背景色 (默认 false )
79   - * @property {String} defaultUrl 加载失败的默认头像(组件有内置默认图片)
80   - * @property {String | Number} colorIndex 如果配置了randomBgColor为true,且配置了此值,则从默认的背景色数组中取出对应索引的颜色值,取值0-19之间
81   - * @property {String} name 组件标识符 (默认 'level' )
82   - * @property {Object} customStyle 定义需要用到的外部样式
83   - *
84   - * @event {Function} click 点击组件时触发 index: 用户传递的标识符
85   - * @example <u-avatar :src="src" mode="square"></u-avatar>
86   - */
87   - export default {
88   - name: 'u-avatar',
89   - mixins: [mpMixin, mixin, props],
90   - data() {
91   - return {
92   - // 如果配置randomBgColor参数为true,在图标或者文字的模式下,会随机从中取出一个颜色值当做背景色
93   - colors: ['#ffb34b', '#f2bba9', '#f7a196', '#f18080', '#88a867', '#bfbf39', '#89c152', '#94d554', '#f19ec2',
94   - '#afaae4', '#e1b0df', '#c38cc1', '#72dcdc', '#9acdcb', '#77b1cc', '#448aca', '#86cefa', '#98d1ee',
95   - '#73d1f1',
96   - '#80a7dc'
97   - ],
98   - avatarUrl: this.src,
99   - allowMp: false
100   - }
101   - },
102   - watch: {
103   - // 监听头像src的变化,赋值给内部的avatarUrl变量,因为图片加载失败时,需要修改图片的src为默认值
104   - // 而组件内部不能直接修改props的值,所以需要一个中间变量
105   - src: {
106   - immediate: true,
107   - handler(newVal) {
108   - this.avatarUrl = newVal
109   - // 如果没有传src,则主动触发error事件,用于显示默认的头像,否则src为''空字符等的时候,会无内容展示
110   - if(!newVal) {
111   - this.errorHandler()
112   - }
113   - }
114   - }
115   - },
116   - computed: {
117   - imageStyle() {
118   - const style = {}
119   - return style
120   - }
121   - },
122   - created() {
123   - this.init()
124   - },
125   - emits: ["click"],
126   - methods: {
127   - addStyle,
128   - addUnit,
129   - random,
130   - init() {
131   - // 目前只有这几个小程序平台具有open-data标签
132   - // 其他平台可以通过uni.getUserInfo类似接口获取信息,但是需要弹窗授权(首次),不合符组件逻辑
133   - // 故目前自动获取小程序头像只支持这几个平台
134   - // #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU
135   - this.allowMp = true
136   - // #endif
137   - },
138   - // 判断传入的name属性,是否图片路径,只要带有"/"均认为是图片形式
139   - isImg() {
140   - return this.src.indexOf('/') !== -1
141   - },
142   - // 图片加载时失败时触发
143   - errorHandler() {
144   - this.avatarUrl = this.defaultUrl || base64Avatar
145   - },
146   - clickHandler(e) {
147   - this.$emit('click', this.name, e)
148   - }
149   - }
150   - }
151   -</script>
152   -
153   -<style lang="scss" scoped>
154   -
155   - .u-avatar {
156   - @include flex;
157   - align-items: center;
158   - justify-content: center;
159   -
160   - &--circle {
161   - border-radius: 100px;
162   - }
163   -
164   - &--square {
165   - border-radius: 4px;
166   - }
167   -
168   - &__image {
169   - &--circle {
170   - border-radius: 100px;
171   - overflow: hidden;
172   - }
173   -
174   - &--square {
175   - border-radius: 4px;
176   - }
177   - }
178   - }
179   -</style>
uni_modules/uview-plus/components/u-back-top/backtop.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:50:18
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/backtop.js
9   - */
10   -export default {
11   - // backtop组件
12   - backtop: {
13   - mode: 'circle',
14   - icon: 'arrow-upward',
15   - text: '',
16   - duration: 100,
17   - scrollTop: 0,
18   - top: 400,
19   - bottom: 100,
20   - right: 20,
21   - zIndex: 9,
22   - iconStyle: {
23   - color: '#909399',
24   - fontSize: '19px'
25   - }
26   - }
27   -}
uni_modules/uview-plus/components/u-back-top/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 返回顶部的形状,circle-圆形,square-方形
6   - mode: {
7   - type: String,
8   - default: () => defProps.backtop.mode
9   - },
10   - // 自定义图标
11   - icon: {
12   - type: String,
13   - default: () => defProps.backtop.icon
14   - },
15   - // 提示文字
16   - text: {
17   - type: String,
18   - default: () => defProps.backtop.text
19   - },
20   - // 返回顶部滚动时间
21   - duration: {
22   - type: [String, Number],
23   - default: () => defProps.backtop.duration
24   - },
25   - // 滚动距离
26   - scrollTop: {
27   - type: [String, Number],
28   - default: () => defProps.backtop.scrollTop
29   - },
30   - // 距离顶部多少距离显示,单位px
31   - top: {
32   - type: [String, Number],
33   - default: () => defProps.backtop.top
34   - },
35   - // 返回顶部按钮到底部的距离,单位px
36   - bottom: {
37   - type: [String, Number],
38   - default: () => defProps.backtop.bottom
39   - },
40   - // 返回顶部按钮到右边的距离,单位px
41   - right: {
42   - type: [String, Number],
43   - default: () => defProps.backtop.right
44   - },
45   - // 层级
46   - zIndex: {
47   - type: [String, Number],
48   - default: () => defProps.backtop.zIndex
49   - },
50   - // 图标的样式,对象形式
51   - iconStyle: {
52   - type: Object,
53   - default: () => defProps.backtop.iconStyle
54   - }
55   - }
56   -})
uni_modules/uview-plus/components/u-back-top/u-back-top.vue deleted
1   -<template>
2   - <u-transition
3   - mode="fade"
4   - :customStyle="backTopStyle"
5   - :show="show"
6   - >
7   - <view
8   - class="u-back-top"
9   - :style="[contentStyle]"
10   - v-if="!$slots.default && !$slots.$default"
11   - @click="backToTop"
12   - >
13   - <up-icon
14   - :name="icon"
15   - :custom-style="iconStyle"
16   - ></up-icon>
17   - <text
18   - v-if="text"
19   - class="u-back-top__text"
20   - >{{text}}</text>
21   - </view>
22   - <slot v-else />
23   - </u-transition>
24   -</template>
25   -
26   -<script>
27   - import { props } from './props';
28   - import { mpMixin } from '../../libs/mixin/mpMixin';
29   - import { mixin } from '../../libs/mixin/mixin';
30   - import { addUnit, addStyle, getPx, deepMerge, error } from '../../libs/function/index';
31   - // #ifdef APP-NVUE
32   - const dom = weex.requireModule('dom')
33   - // #endif
34   - /**
35   - * backTop 返回顶部
36   - * @description 本组件一个用于长页面,滑动一定距离后,出现返回顶部按钮,方便快速返回顶部的场景。
37   - * @tutorial https://uview-plus.jiangruyi.com/components/backTop.html
38   - *
39   - * @property {String} mode 返回顶部的形状,circle-圆形,square-方形 (默认 'circle' )
40   - * @property {String} icon 自定义图标 (默认 'arrow-upward' ) 见官方文档示例
41   - * @property {String} text 提示文字
42   - * @property {String | Number} duration 返回顶部滚动时间 (默认 100)
43   - * @property {String | Number} scrollTop 滚动距离 (默认 0 )
44   - * @property {String | Number} top 距离顶部多少距离显示,单位px (默认 400 )
45   - * @property {String | Number} bottom 返回顶部按钮到底部的距离,单位px (默认 100 )
46   - * @property {String | Number} right 返回顶部按钮到右边的距离,单位px (默认 20 )
47   - * @property {String | Number} zIndex 层级 (默认 9 )
48   - * @property {Object<Object>} iconStyle 图标的样式,对象形式 (默认 {color: '#909399',fontSize: '19px'})
49   - * @property {Object} customStyle 定义需要用到的外部样式
50   - *
51   - * @example <u-back-top :scrollTop="scrollTop"></u-back-top>
52   - */
53   - export default {
54   - name: 'u-back-top',
55   - mixins: [mpMixin, mixin, props],
56   - computed: {
57   - backTopStyle() {
58   - // 动画组件样式
59   - const style = {
60   - bottom: addUnit(this.bottom),
61   - right: addUnit(this.right),
62   - width: '40px',
63   - height: '40px',
64   - position: 'fixed',
65   - zIndex: 10,
66   - }
67   - return style
68   - },
69   - show() {
70   - return getPx(this.scrollTop) > getPx(this.top)
71   - },
72   - contentStyle() {
73   - const style = {}
74   - let radius = 0
75   - // 是否圆形
76   - if(this.mode === 'circle') {
77   - radius = '100px'
78   - } else {
79   - radius = '4px'
80   - }
81   - // 为了兼容安卓nvue,只能这么分开写
82   - style.borderTopLeftRadius = radius
83   - style.borderTopRightRadius = radius
84   - style.borderBottomLeftRadius = radius
85   - style.borderBottomRightRadius = radius
86   - return deepMerge(style, addStyle(this.customStyle))
87   - }
88   - },
89   - emits: ["click"],
90   - methods: {
91   - backToTop() {
92   - // #ifdef APP-NVUE
93   - if (!this.$parent.$refs['u-back-top']) {
94   - error(`nvue页面需要给页面最外层元素设置"ref='u-back-top'`)
95   - }
96   - dom.scrollToElement(this.$parent.$refs['u-back-top'], {
97   - offset: 0
98   - })
99   - // #endif
100   -
101   - // #ifndef APP-NVUE
102   - uni.pageScrollTo({
103   - scrollTop: 0,
104   - duration: this.duration
105   - });
106   - // #endif
107   - this.$emit('click')
108   - }
109   - }
110   - }
111   -</script>
112   -
113   -<style lang="scss" scoped>
114   - $u-back-top-flex:1 !default;
115   - $u-back-top-height:100% !default;
116   - $u-back-top-background-color:#E1E1E1 !default;
117   - $u-back-top-tips-font-size:12px !default;
118   - .u-back-top {
119   - @include flex;
120   - flex-direction: column;
121   - align-items: center;
122   - flex:$u-back-top-flex;
123   - height: $u-back-top-height;
124   - justify-content: center;
125   - background-color: $u-back-top-background-color;
126   -
127   - &__tips {
128   - font-size:$u-back-top-tips-font-size;
129   - transform: scale(0.8);
130   - }
131   - }
132   -</style>
uni_modules/uview-plus/components/u-badge/badge.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-23 19:51:50
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/badge.js
9   - */
10   -export default {
11   - // 徽标数组件
12   - badge: {
13   - isDot: false,
14   - value: '',
15   - show: true,
16   - max: 999,
17   - type: 'error',
18   - showZero: false,
19   - bgColor: null,
20   - color: null,
21   - shape: 'circle',
22   - numberType: 'overflow',
23   - offset: [],
24   - inverted: false,
25   - absolute: false
26   - }
27   -}
uni_modules/uview-plus/components/u-badge/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 是否显示圆点
6   - isDot: {
7   - type: Boolean,
8   - default: () => defProps.badge.isDot
9   - },
10   - // 显示的内容
11   - value: {
12   - type: [Number, String],
13   - default: () => defProps.badge.value
14   - },
15   - // 显示的内容
16   - modelValue: {
17   - type: [Number, String],
18   - default: () => defProps.badge.modelValue
19   - },
20   - // 是否显示
21   - show: {
22   - type: Boolean,
23   - default: () => defProps.badge.show
24   - },
25   - // 最大值,超过最大值会显示 '{max}+'
26   - max: {
27   - type: [Number, String],
28   - default: () => defProps.badge.max
29   - },
30   - // 主题类型,error|warning|success|primary
31   - type: {
32   - type: String,
33   - default: () => defProps.badge.type
34   - },
35   - // 当数值为 0 时,是否展示 Badge
36   - showZero: {
37   - type: Boolean,
38   - default: () => defProps.badge.showZero
39   - },
40   - // 背景颜色,优先级比type高,如设置,type参数会失效
41   - bgColor: {
42   - type: [String, null],
43   - default: () => defProps.badge.bgColor
44   - },
45   - // 字体颜色
46   - color: {
47   - type: [String, null],
48   - default: () => defProps.badge.color
49   - },
50   - // 徽标形状,circle-四角均为圆角,horn-左下角为直角
51   - shape: {
52   - type: String,
53   - default: () => defProps.badge.shape
54   - },
55   - // 设置数字的显示方式,overflow|ellipsis|limit
56   - // overflow会根据max字段判断,超出显示`${max}+`
57   - // ellipsis会根据max判断,超出显示`${max}...`
58   - // limit会依据1000作为判断条件,超出1000,显示`${value/1000}K`,比如2.2k、3.34w,最多保留2位小数
59   - numberType: {
60   - type: String,
61   - default: () => defProps.badge.numberType
62   - },
63   - // 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效
64   - offset: {
65   - type: Array,
66   - default: () => defProps.badge.offset
67   - },
68   - // 是否反转背景和字体颜色
69   - inverted: {
70   - type: Boolean,
71   - default: () => defProps.badge.inverted
72   - },
73   - // 是否绝对定位
74   - absolute: {
75   - type: Boolean,
76   - default: () => defProps.badge.absolute
77   - }
78   - }
79   -})
uni_modules/uview-plus/components/u-badge/u-badge.vue deleted
1   -<template>
2   - <text
3   - v-if="show && ((Number(value) === 0 ? showZero : true) || isDot)"
4   - :class="[isDot ? 'u-badge--dot' : 'u-badge--not-dot', inverted && 'u-badge--inverted', shape === 'horn' && 'u-badge--horn', `u-badge--${type}${inverted ? '--inverted' : ''}`]"
5   - :style="[addStyle(customStyle), badgeStyle]"
6   - class="u-badge"
7   - >{{ isDot ? '' :showValue }}</text>
8   -</template>
9   -
10   -<script>
11   - import { props } from './props';
12   - import { mpMixin } from '../../libs/mixin/mpMixin';
13   - import { mixin } from '../../libs/mixin/mixin';
14   - import { addStyle, addUnit } from '../../libs/function/index';
15   - /**
16   - * badge 徽标数
17   - * @description 该组件一般用于图标右上角显示未读的消息数量,提示用户点击,有圆点和圆包含文字两种形式。
18   - * @tutorial https://uview-plus.jiangruyi.com/components/badge.html
19   - *
20   - * @property {Boolean} isDot 是否显示圆点 (默认 false )
21   - * @property {String | Number} value 显示的内容
22   - * @property {Boolean} show 是否显示 (默认 true )
23   - * @property {String | Number} max 最大值,超过最大值会显示 '{max}+' (默认999)
24   - * @property {String} type 主题类型,error|warning|success|primary (默认 'error' )
25   - * @property {Boolean} showZero 当数值为 0 时,是否展示 Badge (默认 false )
26   - * @property {String} bgColor 背景颜色,优先级比type高,如设置,type参数会失效
27   - * @property {String} color 字体颜色 (默认 '#ffffff' )
28   - * @property {String} shape 徽标形状,circle-四角均为圆角,horn-左下角为直角 (默认 'circle' )
29   - * @property {String} numberType 设置数字的显示方式,overflow|ellipsis|limit (默认 'overflow' )
30   - * @property {Array}} offset 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效
31   - * @property {Boolean} inverted 是否反转背景和字体颜色(默认 false )
32   - * @property {Boolean} absolute 是否绝对定位(默认 false )
33   - * @property {Object} customStyle 定义需要用到的外部样式
34   - * @example <u-badge :type="type" :count="count"></u-badge>
35   - */
36   - export default {
37   - name: 'u-badge',
38   - mixins: [mpMixin, props, mixin],
39   - computed: {
40   - // 是否将badge中心与父组件右上角重合
41   - boxStyle() {
42   - let style = {};
43   - return style;
44   - },
45   - // 整个组件的样式
46   - badgeStyle() {
47   - const style = {}
48   - if(this.color) {
49   - style.color = this.color
50   - }
51   - if (this.bgColor && !this.inverted) {
52   - style.backgroundColor = this.bgColor
53   - }
54   - if (this.absolute) {
55   - style.position = 'absolute'
56   - // 如果有设置offset参数
57   - if(this.offset.length) {
58   - // top和right分为为offset的第一个和第二个值,如果没有第二个值,则right等于top
59   - const top = this.offset[0]
60   - const right = this.offset[1] || top
61   - style.top = addUnit(top)
62   - style.right = addUnit(right)
63   - }
64   - }
65   - return style
66   - },
67   - showValue() {
68   - switch (this.numberType) {
69   - case "overflow":
70   - return Number(this.value) > Number(this.max) ? this.max + "+" : this.value
71   - break;
72   - case "ellipsis":
73   - return Number(this.value) > Number(this.max) ? "..." : this.value
74   - break;
75   - case "limit":
76   - return Number(this.value) > 999 ? Number(this.value) >= 9999 ?
77   - Math.floor(this.value / 1e4 * 100) / 100 + "w" : Math.floor(this.value /
78   - 1e3 * 100) / 100 + "k" : this.value
79   - break;
80   - default:
81   - return Number(this.value)
82   - }
83   - },
84   - },
85   - methods: {
86   - addStyle
87   - }
88   - }
89   -</script>
90   -
91   -<style lang="scss" scoped>
92   -
93   - $u-badge-primary: $u-primary !default;
94   - $u-badge-error: $u-error !default;
95   - $u-badge-success: $u-success !default;
96   - $u-badge-info: $u-info !default;
97   - $u-badge-warning: $u-warning !default;
98   - $u-badge-dot-radius: 100px !default;
99   - $u-badge-dot-size: 8px !default;
100   - $u-badge-dot-right: 4px !default;
101   - $u-badge-dot-top: 0 !default;
102   - $u-badge-text-font-size: 11px !default;
103   - $u-badge-text-right: 10px !default;
104   - $u-badge-text-padding: 2px 5px !default;
105   - $u-badge-text-align: center !default;
106   - $u-badge-text-color: #FFFFFF !default;
107   -
108   - .u-badge {
109   - border-top-right-radius: $u-badge-dot-radius;
110   - border-top-left-radius: $u-badge-dot-radius;
111   - border-bottom-left-radius: $u-badge-dot-radius;
112   - border-bottom-right-radius: $u-badge-dot-radius;
113   - @include flex;
114   - line-height: $u-badge-text-font-size;
115   - text-align: $u-badge-text-align;
116   - font-size: $u-badge-text-font-size;
117   - color: $u-badge-text-color;
118   -
119   - &--dot {
120   - height: $u-badge-dot-size;
121   - width: $u-badge-dot-size;
122   - }
123   -
124   - &--inverted {
125   - font-size: 13px;
126   - }
127   -
128   - &--not-dot {
129   - padding: $u-badge-text-padding;
130   - }
131   -
132   - &--horn {
133   - border-bottom-left-radius: 0;
134   - }
135   -
136   - &--primary {
137   - background-color: $u-badge-primary;
138   - }
139   -
140   - &--primary--inverted {
141   - color: $u-badge-primary;
142   - }
143   -
144   - &--error {
145   - background-color: $u-badge-error;
146   - }
147   -
148   - &--error--inverted {
149   - color: $u-badge-error;
150   - }
151   -
152   - &--success {
153   - background-color: $u-badge-success;
154   - }
155   -
156   - &--success--inverted {
157   - color: $u-badge-success;
158   - }
159   -
160   - &--info {
161   - background-color: $u-badge-info;
162   - }
163   -
164   - &--info--inverted {
165   - color: $u-badge-info;
166   - }
167   -
168   - &--warning {
169   - background-color: $u-badge-warning;
170   - }
171   -
172   - &--warning--inverted {
173   - color: $u-badge-warning;
174   - }
175   - }
176   -</style>
uni_modules/uview-plus/components/u-barcode/u-barcode.vue deleted
1   -<template>
2   - <view class="u-barcode" v-if="calcSizeDone">
3   - <canvas
4   - v-if="showCanvas && !error"
5   - :id="canvasId"
6   - :canvas-id="canvasId"
7   - :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
8   - ></canvas>
9   - <image
10   - v-else-if="!showCanvas && !error"
11   - :src="barcodeImage"
12   - :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
13   - mode="aspectFit"
14   - />
15   - <view
16   - v-else
17   - class="error-container"
18   - :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
19   - >
20   - <text class="error-text">{{ error }}</text>
21   - </view>
22   - </view>
23   -</template>
24   -
25   -<script>
26   -import { nextTick } from 'vue'
27   -import { t } from '../../libs/i18n'
28   -
29   -export default {
30   - name: 'u-barcode',
31   - props: {
32   - // 条码值
33   - value: {
34   - type: [String, Number],
35   - required: true
36   - },
37   - // 条码格式
38   - format: {
39   - type: String,
40   - default: 'auto',
41   - validator: function (value) {
42   - return [
43   - 'auto',
44   - 'CODE128', 'CODE128A', 'CODE128B', 'CODE128C',
45   - 'EAN13', 'EAN8', 'EAN5', 'EAN2',
46   - 'UPC', 'UPCA', 'UPCE',
47   - 'CODE39',
48   - 'ITF', 'ITF14',
49   - 'MSI', 'MSI10', 'MSI11', 'MSI1010', 'MSI1110',
50   - 'pharmacode',
51   - 'codabar'
52   - ].includes(value)
53   - }
54   - },
55   - // 宽度
56   - width: {
57   - type: Number,
58   - default: 200
59   - },
60   - // 高度
61   - height: {
62   - type: Number,
63   - default: 80
64   - },
65   - // 是否显示文本
66   - displayValue: {
67   - type: Boolean,
68   - default: true
69   - },
70   - // 文本内容
71   - text: {
72   - type: String,
73   - default: undefined
74   - },
75   - // 字体选项
76   - fontOptions: {
77   - type: String,
78   - default: ''
79   - },
80   - // 字体
81   - font: {
82   - type: String,
83   - default: 'monospace'
84   - },
85   - // 文本对齐方式
86   - textAlign: {
87   - type: String,
88   - default: 'center'
89   - },
90   - // 文本位置
91   - textPosition: {
92   - type: String,
93   - default: 'bottom'
94   - },
95   - // 文本边距
96   - textMargin: {
97   - type: Number,
98   - default: 2
99   - },
100   - // 字体大小
101   - fontSize: {
102   - type: Number,
103   - default: 14
104   - },
105   - // 背景色
106   - background: {
107   - type: String,
108   - default: '#ffffff'
109   - },
110   - // 条码颜色
111   - lineColor: {
112   - type: String,
113   - default: '#000000'
114   - },
115   - // 边距
116   - margin: {
117   - type: Number,
118   - default: 10
119   - },
120   - // 上边距
121   - marginTop: {
122   - type: Number,
123   - default: undefined
124   - },
125   - // 下边距
126   - marginBottom: {
127   - type: Number,
128   - default: undefined
129   - },
130   - // 左边距
131   - marginLeft: {
132   - type: Number,
133   - default: undefined
134   - },
135   - // 右边距
136   - marginRight: {
137   - type: Number,
138   - default: undefined
139   - },
140   - // 使用canvas还是生成图片
141   - useCanvas: {
142   - type: Boolean,
143   - default: true
144   - }
145   - },
146   - data() {
147   - return {
148   - canvasId: 'barcode-' + Math.random().toString(36).substr(2, 9),
149   - barcodeImage: '',
150   - showCanvas: false,
151   - canvasWidth: 0,
152   - canvasHeight: 0,
153   - calcSizeDone: false,
154   - error: ''
155   - }
156   - },
157   - watch: {
158   - value() {
159   - this.generateBarcode()
160   - },
161   - format() {
162   - this.generateBarcode()
163   - },
164   - width() {
165   - this.generateBarcode()
166   - },
167   - height() {
168   - this.generateBarcode()
169   - },
170   - displayValue() {
171   - this.generateBarcode()
172   - },
173   - text() {
174   - this.generateBarcode()
175   - },
176   - font() {
177   - this.generateBarcode()
178   - },
179   - textAlign() {
180   - this.generateBarcode()
181   - },
182   - textPosition() {
183   - this.generateBarcode()
184   - },
185   - textMargin() {
186   - this.generateBarcode()
187   - },
188   - fontSize() {
189   - this.generateBarcode()
190   - },
191   - background() {
192   - this.generateBarcode()
193   - },
194   - lineColor() {
195   - this.generateBarcode()
196   - },
197   - margin() {
198   - this.generateBarcode()
199   - }
200   - },
201   - mounted() {
202   - /**
203   - * @author jry <ijry@qq.com>
204   - */
205   - this.$nextTick(() => {
206   - this.generateBarcode()
207   - })
208   - },
209   - methods: {
210   - /**
211   - * 生成条形码
212   - * @author jry <ijry@qq.com>
213   - * @param {String|Number} value - 条码值
214   - * @param {Object} options - 条码配置选项
215   - */
216   - generateBarcode() {
217   - // 统一处理默认值
218   - const margin = this.margin
219   - const options = {
220   - format: this.format || 'auto',
221   - width: this.width,
222   - height: this.height,
223   - displayValue: this.displayValue,
224   - text: this.text,
225   - fontOptions: this.fontOptions || '',
226   - font: this.font || 'monospace',
227   - textAlign: this.textAlign || 'center',
228   - textPosition: this.textPosition || 'bottom',
229   - textMargin: this.textMargin !== undefined ? this.textMargin : 2,
230   - fontSize: this.fontSize || 20,
231   - background: this.background || '#ffffff',
232   - lineColor: this.lineColor || '#000000',
233   - margin: margin,
234   - marginTop: this.marginTop !== undefined ? this.marginTop : margin,
235   - marginBottom: this.marginBottom !== undefined ? this.marginBottom : margin,
236   - marginLeft: this.marginLeft !== undefined ? this.marginLeft : margin,
237   - marginRight: this.marginRight !== undefined ? this.marginRight : margin
238   - }
239   -
240   - // 清理未定义的选项
241   - Object.keys(options).forEach(key => {
242   - if (options[key] === undefined) {
243   - delete options[key]
244   - }
245   - })
246   -
247   - if (this.useCanvas) {
248   - // 使用canvas渲染
249   - this.showCanvas = true
250   - this.$nextTick(() => {
251   - this.renderToCanvas(options)
252   - })
253   - } else {
254   - // 生成图片
255   - this.showCanvas = false
256   - this.renderToImage(options)
257   - }
258   - },
259   -
260   - /**
261   - * 渲染条形码到canvas
262   - * @author jry <ijry@qq.com>
263   - * @param {Object} options - 条码配置选项
264   - */
265   - async renderToCanvas(options) {
266   - try {
267   - // 计算canvas尺寸
268   - this.calculateCanvasSize(options)
269   -
270   - await nextTick()
271   -
272   - // 获取canvas上下文
273   - const ctx = uni.createCanvasContext(this.canvasId, this)
274   -
275   - // 清空画布
276   - ctx.setFillStyle(options.background)
277   - ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight)
278   -
279   - // 生成条形码数据
280   - const barcodeData = this.encodeBarcode(this.value, options.format)
281   -
282   - if (barcodeData) {
283   - // 绘制条形码
284   - this.drawBarcode(ctx, barcodeData, options)
285   - }
286   -
287   - // 绘制到canvas
288   - ctx.draw(false, () => {
289   - // 绘制完成回调
290   - this.$emit('rendered', { type: 'canvas', id: this.canvasId })
291   - })
292   - } catch (error) {
293   - console.error('生成条码失败:', error)
294   - this.error = error.message || t('up.barcode.error')
295   - this.$emit('error', error)
296   - }
297   - },
298   -
299   - /**
300   - * 渲染条形码为图片
301   - * @author jry <ijry@qq.com>
302   - * @param {Object} options - 条码配置选项
303   - */
304   - renderToImage(options) {
305   - try {
306   - // 计算canvas尺寸
307   - this.calculateCanvasSize(options)
308   -
309   - // 创建临时canvas用于生成图片
310   - const tempCanvasId = 'temp-' + this.canvasId
311   - const ctx = uni.createCanvasContext(tempCanvasId, this)
312   -
313   - // 清空画布
314   - ctx.setFillStyle(options.background)
315   - ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight)
316   -
317   - // 生成条形码数据
318   - const barcodeData = this.encodeBarcode(this.value, options.format)
319   -
320   - if (barcodeData) {
321   - // 绘制条形码
322   - this.drawBarcode(ctx, barcodeData, options)
323   - }
324   -
325   - // 绘制到临时canvas并生成图片
326   - ctx.draw(false, () => {
327   - // 延迟一小段时间确保canvas绘制完成
328   - setTimeout(() => {
329   - // 将canvas转换为图片
330   - uni.canvasToTempFilePath({
331   - canvasId: tempCanvasId,
332   - success: (res) => {
333   - this.barcodeImage = res.tempFilePath
334   - this.$emit('rendered', { type: 'image', value: this.value, path: res.tempFilePath })
335   - },
336   - fail: (error) => {
337   - console.error('生成条码图片失败:', error)
338   - this.$emit('error', error)
339   - }
340   - }, this)
341   - }, 100)
342   - })
343   - } catch (error) {
344   - console.error('生成条码图片失败:', error)
345   - this.$emit('error', error)
346   - }
347   - },
348   -
349   - /**
350   - * 计算canvas尺寸
351   - * @author jry <ijry@qq.com>
352   - * @param {Object} options - 条码配置选项
353   - */
354   - calculateCanvasSize(options) {
355   - // 基础宽度计算
356   - let width = options.width
357   - let height = options.height
358   -
359   - // 考虑边距
360   - const marginLeft = options.marginLeft
361   - const marginRight = options.marginRight
362   - const marginTop = options.marginTop
363   - const marginBottom = options.marginBottom
364   -
365   - // 考虑文本高度
366   - let textHeight = 0
367   - if (options.displayValue !== false) {
368   - textHeight = options.fontSize + options.textMargin
369   - }
370   -
371   - // 根据文本位置调整高度
372   - if (options.textPosition === 'top' || options.textPosition === 'bottom') {
373   - height += textHeight
374   - }
375   -
376   - // 添加边距
377   - width += marginLeft + marginRight
378   - height += marginTop + marginBottom
379   -
380   - this.canvasWidth = Math.max(width, 100)
381   - this.canvasHeight = Math.max(height, 60 + textHeight)
382   -
383   - this.calcSizeDone = true
384   - },
385   -
386   - /**
387   - * 编码条形码数据
388   - * @author jry <ijry@qq.com>
389   - * @param {String|Number} value - 条码值
390   - * @param {String} format - 条码格式
391   - * @returns {String|null} 条形码编码数据
392   - */
393   - encodeBarcode(value, format) {
394   - try {
395   - switch (format) {
396   - case 'CODE128':
397   - case 'auto':
398   - return this.encodeCode128(value)
399   - case 'CODE39':
400   - return this.encodeCode39(value)
401   - case 'EAN13':
402   - return this.encodeEAN13(value)
403   - case 'EAN8':
404   - return this.encodeEAN8(value)
405   - case 'EAN5':
406   - case 'EAN2':
407   - return this.encodeEAN52(value, format)
408   - case 'UPC':
409   - case 'UPCA':
410   - return this.encodeUPCA(value)
411   - case 'UPCE':
412   - return this.encodeUPCE(value)
413   - default:
414   - // 默认使用CODE128
415   - return this.encodeCode128(value)
416   - }
417   - } catch (error) {
418   - console.error('条码编码失败:', error)
419   - throw error
420   - }
421   - },
422   -
423   - /**
424   - * 添加右侧安静区(至少2个模块宽度的空白)
425   - * @author jry <ijry@qq.com>
426   - * @param {String} data - 要编码的数据
427   - * @returns {String|null} 编码后的条形码数据
428   - */
429   - encodeCode128(data) {
430   - const CODE128_START_CODE_B = 104
431   - const CODE128_STOP = 106
432   -
433   - // CODE128 Code B 字符集
434   - const CODE128_CODE_B_CHARS = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'
435   -
436   - // 条形码模式 (B 模式)
437   - const codes = []
438   - let checksum = CODE128_START_CODE_B
439   -
440   - // 添加起始字符
441   - codes.push(CODE128_START_CODE_B)
442   -
443   - // 编码每个字符
444   - for (let i = 0; i < data.length; i++) {
445   - const char = data[i]
446   - const code = CODE128_CODE_B_CHARS.indexOf(char)
447   -
448   - if (code === -1) {
449   - throw new Error('Invalid character in CODE128: ' + char)
450   - }
451   -
452   - codes.push(code)
453   - checksum += code * (i + 1)
454   - }
455   -
456   - // 添加校验字符
457   - codes.push(checksum % 103)
458   -
459   - // 添加结束字符
460   - codes.push(CODE128_STOP)
461   -
462   - // 转换为条形码模式 (1 = 黑条, 0 = 白条)
463   - let barcode = ''
464   - for (let i = 0; i < codes.length; i++) {
465   - const code = codes[i]
466   - barcode += this.getCode128Pattern(code)
467   - }
468   -
469   - // 添加右侧安静区(至少2个模块宽度的空白)
470   - barcode += '00000'
471   -
472   - return barcode
473   - },
474   -
475   - /**
476   - * 获取CODE128编码模式
477   - * @author jry <ijry@qq.com>
478   - * @param {Number} code - 字符编码
479   - * @returns {String} 条形码二进制模式
480   - */
481   - getCode128Pattern(code) {
482   - // CODE128编码表
483   - const patterns = [
484   - "11011001100", "11001101100", "11001100110", "10010011000",
485   - "10010001100", "10001001100", "10011001000", "10011000100",
486   - "10001100100", "11001001000", "11001000100", "11000100100",
487   - "10110011100", "10011011100", "10011001110", "10111001100",
488   - "10011101100", "10011100110", "11001110010", "11001011100",
489   - "11001001110", "11011100100", "11001110100", "11101101110",
490   - "11101001100", "11100101100", "11100100110", "11101100100",
491   - "11100110100", "11100110010", "11011011000", "11011000110",
492   - "11000110110", "10100011000", "10001011000", "10001000110",
493   - "10110001000", "10001101000", "10001100010", "11010001000",
494   - "11000101000", "11000100010", "10110111000", "10110001110",
495   - "10001101110", "10111011000", "10111000110", "10001110110",
496   - "11101110110", "11010001110", "11000101110", "11011101000",
497   - "11011100010", "11011101110", "11101011000", "11101000110",
498   - "11100010110", "11101101000", "11101100010", "11100011010",
499   - "11101111010", "11001000010", "11110001010", "10100110000",
500   - "10100001100", "10010110000", "10010000110", "10000101100",
501   - "10000100110", "10110010000", "10110000100", "10011010000",
502   - "10011000010", "10000110100", "10000110010", "11000010010",
503   - "11001010000", "11110111010", "11000010100", "10001111010",
504   - "10100111100", "10010111100", "10010011110", "10111100100",
505   - "10011110100", "10011110010", "11110100100", "11110010100",
506   - "11110010010", "11011011110", "11011110110", "11110110110",
507   - "10101111000", "10100011110", "10001011110", "10111101000",
508   - "10111100010", "11110101000", "11110100010", "10111011110",
509   - "10111101110", "11101011110", "11110101110", "11010000100",
510   - "11010010000", "11010011100", "11000111010"
511   - ];
512   -
513   - return patterns[code] || "";
514   - },
515   -
516   - /**
517   - * CODE39编码实现
518   - * @author jry <ijry@qq.com>
519   - * @param {String} data - 要编码的数据
520   - * @returns {String|null} 编码后的条形码数据
521   - */
522   - encodeCode39(data) {
523   - const codes = {
524   - '0': '101000111011101',
525   - '1': '111010001010111',
526   - '2': '101110001010111',
527   - '3': '111011100010101',
528   - '4': '101000111010111',
529   - '5': '111010001110101',
530   - '6': '101110001110101',
531   - '7': '101000101110111',
532   - '8': '111010001011101',
533   - '9': '101110001011101',
534   - 'A': '111010100010111',
535   - 'B': '101110100010111',
536   - 'C': '111011101000101',
537   - 'D': '101011100010111',
538   - 'E': '111010111000101',
539   - 'F': '101110111000101',
540   - 'G': '101010001110111',
541   - 'H': '111010100011101',
542   - 'I': '101110100011101',
543   - 'J': '101011100011101',
544   - 'K': '111010101000111',
545   - 'L': '101110101000111',
546   - 'M': '111011101010001',
547   - 'N': '101011101000111',
548   - 'O': '111010111010001',
549   - 'P': '101110111010001',
550   - 'Q': '101010111000111',
551   - 'R': '111010101110001',
552   - 'S': '101110101110001',
553   - 'T': '101011101110001',
554   - 'U': '111000101010111',
555   - 'V': '100011101010111',
556   - 'W': '111000111010101',
557   - 'X': '100010111010111',
558   - 'Y': '111000101110101',
559   - 'Z': '100011101110101',
560   - '-': '100010101110111',
561   - '.': '111000101011101',
562   - ' ': '100011101011101',
563   - '*': '100010111011101', // 起始和终止字符
564   - '$': '100010001000101',
565   - '/': '100010001010001',
566   - '+': '100010100010001',
567   - '%': '101000100010001'
568   - }
569   -
570   - // 转为大写
571   - data = data.toUpperCase()
572   -
573   - // 添加起始和终止字符
574   - let barcode = codes['*']
575   -
576   - // 添加数据字符
577   - for (let i = 0; i < data.length; i++) {
578   - const char = data[i]
579   - if (codes[char]) {
580   - barcode += '0' // 字符间隔
581   - barcode += codes[char]
582   - } else {
583   - throw new Error('Invalid character in CODE39: ' + char)
584   - }
585   - }
586   -
587   - // 添加终止字符
588   - barcode += '0' // 字符间隔
589   - barcode += codes['*']
590   -
591   - return barcode
592   - },
593   -
594   - /**
595   - * EAN13编码实现
596   - * @author jry <ijry@qq.com>
597   - * @param {String} data - 13位数字字符串
598   - * @returns {String|null} 编码后的条形码数据
599   - */
600   - encodeEAN13(data) {
601   - // 确保数据是13位数字
602   - if (!/^\d{13}$/.test(data)) {
603   - throw new Error('EAN13 must be 13 digits')
604   - }
605   -
606   - // 验证校验位
607   - let sum = 0
608   - for (let i = 0; i < 12; i++) {
609   - const digit = parseInt(data[i])
610   - sum += (i % 2 === 0) ? digit : digit * 3
611   - }
612   - const checkDigit = (10 - (sum % 10)) % 10
613   - if (parseInt(data[12]) !== checkDigit) {
614   - throw new Error('Invalid EAN13 check digit')
615   - }
616   -
617   - // 左侧数据
618   - const leftData = data.substring(1, 7)
619   - const rightData = data.substring(7, 13)
620   -
621   - // 起始符
622   - let barcode = '101'
623   -
624   - // 左侧数据编码 (根据第一位数字决定编码方式)
625   - const firstDigit = parseInt(data[0])
626   - const leftPatterns = [
627   - ['LLLLLL', 'LLGLGG', 'LLGGLG', 'LLGGGL', 'LGLLGG',
628   - 'LGGLLG', 'LGGGLL', 'LGLGLG', 'LGLGGL', 'LGGLGL']
629   - ]
630   -
631   - const pattern = leftPatterns[0][firstDigit]
632   -
633   - // 左侧奇偶编码模式
634   - const leftOdd = [
635   - '0001101', '0011001', '0010011', '0111101', '0100011',
636   - '0110001', '0101111', '0111011', '0110111', '0001011'
637   - ]
638   -
639   - const leftEven = [
640   - '0100111', '0110011', '0011011', '0100001', '0011101',
641   - '0111001', '0000101', '0010001', '0001001', '0010111'
642   - ]
643   -
644   - // 编码左侧数据
645   - for (let i = 0; i < leftData.length; i++) {
646   - const digit = parseInt(leftData[i])
647   - if (pattern[i] === 'L') {
648   - barcode += leftOdd[digit]
649   - } else {
650   - barcode += leftEven[digit]
651   - }
652   - }
653   -
654   - // 中间分隔符
655   - barcode += '01010'
656   -
657   - // 右侧数据编码 (始终使用右编码)
658   - const rightCodes = [
659   - '1110010', '1100110', '1101100', '1000010', '1011100',
660   - '1001110', '1010000', '1000100', '1001000', '1110100'
661   - ]
662   -
663   - for (let i = 0; i < rightData.length; i++) {
664   - const digit = parseInt(rightData[i])
665   - barcode += rightCodes[digit]
666   - }
667   -
668   - // 结束符
669   - barcode += '101'
670   -
671   - return barcode
672   - },
673   -
674   - /**
675   - * EAN8编码实现
676   - * @author jry <ijry@qq.com>
677   - * @param {String} data - 8位数字字符串
678   - * @returns {String|null} 编码后的条形码数据
679   - */
680   - encodeEAN8(data) {
681   - // 确保数据是8位数字
682   - if (!/^\d{8}$/.test(data)) {
683   - throw new Error('EAN8 must be 8 digits')
684   - }
685   -
686   - // 验证校验位
687   - let sum = 0
688   - for (let i = 0; i < 7; i++) {
689   - const digit = parseInt(data[i])
690   - sum += digit * (i % 2 === 0 ? 3 : 1)
691   - }
692   - const checkDigit = (10 - (sum % 10)) % 10
693   - if (parseInt(data[7]) !== checkDigit) {
694   - throw new Error('Invalid EAN8 check digit')
695   - }
696   -
697   - // 左侧数据(4位)
698   - const leftData = data.substring(0, 4)
699   - // 右侧数据(4位)
700   - const rightData = data.substring(4, 8)
701   -
702   - // 起始符
703   - let barcode = '101'
704   -
705   - // 左侧奇偶编码模式
706   - const leftOdd = [
707   - '0001101', '0011001', '0010011', '0111101', '0100011',
708   - '0110001', '0101111', '0111011', '0110111', '0001011'
709   - ]
710   -
711   - // 编码左侧数据
712   - for (let i = 0; i < leftData.length; i++) {
713   - const digit = parseInt(leftData[i])
714   - barcode += leftOdd[digit]
715   - }
716   -
717   - // 中间分隔符
718   - barcode += '01010'
719   -
720   - // 右侧数据编码 (始终使用右编码)
721   - const rightCodes = [
722   - '1110010', '1100110', '1101100', '1000010', '1011100',
723   - '1001110', '1010000', '1000100', '1001000', '1110100'
724   - ]
725   -
726   - // 编码右侧数据
727   - for (let i = 0; i < rightData.length; i++) {
728   - const digit = parseInt(rightData[i])
729   - barcode += rightCodes[digit]
730   - }
731   -
732   - // 结束符
733   - barcode += '101'
734   -
735   - return barcode
736   - },
737   -
738   - /**
739   - * EAN5/EAN2编码实现
740   - * @author jry <ijry@qq.com>
741   - * @param {String} data - 2位或5位数字字符串
742   - * @param {String} format - 格式类型(EAN5或EAN2)
743   - * @returns {String|null} 编码后的条形码数据
744   - */
745   - encodeEAN52(data, format) {
746   - const length = format === 'EAN5' ? 5 : 2
747   - // 确保数据是相应位数的数字
748   - if (!new RegExp(`^\\d{${length}}$`).test(data)) {
749   - throw new Error(`${format} must be ${length} digits`)
750   - }
751   -
752   - // EAN5/2编码表
753   - const codes = [
754   - '0001101', '0011001', '0010011', '0111101', '0100011',
755   - '0110001', '0101111', '0111011', '0110111', '0001011'
756   - ]
757   -
758   - // 计算校验和
759   - let checksum = 0
760   - for (let i = 0; i < data.length; i++) {
761   - checksum += parseInt(data[i]) * (i % 2 === 0 ? 3 : 1)
762   - }
763   -
764   - // 根据校验和确定编码模式
765   - const patterns = format === 'EAN5' ?
766   - ['00001', '00010', '00100', '01000', '10000', // 0-4
767   - '00000', '00011', '00101', '00110', '01001', // 5-9
768   - '01010', '01100', '10001', '10010', '10100', // 10-14
769   - '11000', '11001', '11010', '11100'] : // 15-18
770   - ['00', '01', '10', '11'] // EAN2只有4种模式
771   -
772   - const pattern = format === 'EAN5' ?
773   - patterns[checksum % 10] :
774   - patterns[parseInt(data) % 4]
775   -
776   - // 起始符
777   - let barcode = '1011'
778   -
779   - // 编码数据
780   - for (let i = 0; i < data.length; i++) {
781   - // 添加分隔符(除了第一个字符)
782   - if (i > 0) {
783   - barcode += '01' // 字符间分隔符
784   - }
785   -
786   - // 根据模式确定编码方式
787   - const digit = parseInt(data[i])
788   - const code = codes[digit]
789   -
790   - barcode += code
791   - }
792   -
793   - return barcode
794   - },
795   -
796   - /**
797   - * UPCA编码实现
798   - * @author jry <ijry@qq.com>
799   - * @param {String} data - 11位或12位数字字符串
800   - * @returns {String|null} 编码后的条形码数据
801   - */
802   - encodeUPCA(data) {
803   - // 如果是11位,计算校验位
804   - if (/^\d{11}$/.test(data)) {
805   - let sum = 0
806   - for (let i = 0; i < 11; i++) {
807   - const digit = parseInt(data[i])
808   - sum += (i % 2 === 0) ? digit * 3 : digit
809   - }
810   - const checkDigit = (10 - (sum % 10)) % 10
811   - data += checkDigit
812   - }
813   -
814   - // 确保数据是12位数字
815   - if (!/^\d{12}$/.test(data)) {
816   - throw new Error('UPC-A must be 11 or 12 digits')
817   - }
818   -
819   - // UPCA实际上是EAN13的第一个数字为0的特殊情况
820   - return this.encodeEAN13('0' + data)
821   - },
822   -
823   - /**
824   - * UPCE编码实现
825   - * @author jry <ijry@qq.com>
826   - * @param {String} data - 6位或8位数字字符串
827   - * @returns {String|null} 编码后的条形码数据
828   - */
829   - encodeUPCE(data) {
830   - // 如果是7位,计算校验位
831   - if (/^\d{7}$/.test(data)) {
832   - let sum = 0
833   - for (let i = 0; i < 7; i++) {
834   - const digit = parseInt(data[i])
835   - sum += (i % 2 === 0) ? digit * 3 : digit
836   - }
837   - const checkDigit = (10 - (sum % 10)) % 10
838   - data += checkDigit
839   - }
840   -
841   - // 确保数据是8位数字
842   - if (!/^\d{8}$/.test(data)) {
843   - throw new Error('UPC-E must be 7 or 8 digits')
844   - }
845   -
846   - // 检查是否是有效的UPC-E格式
847   - if (data[0] !== '0' && data[0] !== '1') {
848   - throw new Error('UPC-E must start with 0 or 1')
849   - }
850   -
851   - // UPCE编码表
852   - const leftOdd = [
853   - '0001101', '0011001', '0010011', '0111101', '0100011',
854   - '0110001', '0101111', '0111011', '0110111', '0001011'
855   - ]
856   -
857   - const leftEven = [
858   - '0100111', '0110011', '0011011', '0100001', '0011101',
859   - '0111001', '0000101', '0010001', '0001001', '0010111'
860   - ]
861   -
862   - // 根据系统数字确定编码模式
863   - const systemDigit = data[0]
864   - const checkDigit = data[7]
865   -
866   - // 提取中间6位
867   - const middleData = data.substring(1, 7)
868   -
869   - // 确定编码模式
870   - let pattern
871   - if (checkDigit === '0' || checkDigit === '1' || checkDigit === '2') {
872   - pattern = 'EEEEOO' // 0,1,2
873   - } else if (checkDigit === '3') {
874   - pattern = 'EEEEOO' // 3
875   - } else if (checkDigit === '4') {
876   - pattern = 'EEEOOO' // 4
877   - } else {
878   - pattern = 'EEOOOO' // 5,6,7,8,9
879   - }
880   -
881   - // 起始符
882   - let barcode = '101'
883   -
884   - // 编码中间6位数据
885   - for (let i = 0; i < middleData.length; i++) {
886   - const digit = parseInt(middleData[i])
887   - if (pattern[i] === 'E') {
888   - barcode += leftEven[digit]
889   - } else {
890   - barcode += leftOdd[digit]
891   - }
892   - }
893   -
894   - // 中间分隔符
895   - barcode += '010101'
896   -
897   - // 结束符
898   - barcode += '101'
899   -
900   - return barcode
901   - },
902   -
903   - /**
904   - * 绘制条形码
905   - * @author jry <ijry@qq.com>
906   - * @param {Object} ctx - canvas上下文
907   - * @param {String} barcodeData - 条形码数据
908   - * @param {Object} options - 条码配置选项
909   - */
910   - drawBarcode(ctx, barcodeData, options) {
911   - if (!barcodeData) return
912   -
913   - const marginLeft = options.marginLeft
914   - const marginTop = options.marginTop
915   - const marginBottom = options.marginBottom
916   - const textHeight = options.displayValue !== false ? options.fontSize + options.textMargin : 0
917   - const height = options.height
918   - // 恢复: 根据总长度计算模块宽度
919   - const moduleWidth = Math.max(1, (this.canvasWidth - marginLeft - (options.marginRight || 10)) / barcodeData.length)
920   -
921   - ctx.setFillStyle(options.lineColor)
922   -
923   - // 计算条形码绘制的Y坐标
924   - let barcodeY = marginTop
925   - // 如果文本在顶部,需要调整条形码绘制位置
926   - if (options.displayValue !== false && options.textPosition === 'top') {
927   - barcodeY += textHeight
928   - }
929   -
930   - // 恢复: 使用计算出的模块宽度绘制条形码
931   - let x = marginLeft
932   - for (let i = 0; i < barcodeData.length; i++) {
933   - if (barcodeData[i] === '1') {
934   - // 使用计算的模块宽度绘制每个条
935   - ctx.fillRect(x, barcodeY, moduleWidth, height)
936   - }
937   - // 每个条/空都占用一个模块宽度
938   - x += moduleWidth
939   - }
940   -
941   - // 绘制文本
942   - if (options.displayValue !== false) {
943   - const text = options.text || this.value
944   - let textY
945   -
946   - ctx.setFillStyle(options.lineColor)
947   - ctx.setFontSize(options.fontSize)
948   - ctx.setTextAlign(options.textAlign)
949   -
950   - let textX
951   - switch (options.textAlign) {
952   - case 'left':
953   - textX = marginLeft
954   - break
955   - case 'right':
956   - textX = this.canvasWidth - options.marginRight
957   - break
958   - default: // center
959   - textX = this.canvasWidth / 2
960   - }
961   -
962   - // 根据文本位置确定Y坐标
963   - if (options.textPosition === 'top') {
964   - textY = marginTop + options.fontSize - 3
965   - } else { // bottom
966   - // 修复:正确计算底部文本位置,确保文本完全显示
967   - textY = barcodeY + height + options.textMargin + options.fontSize
968   - // 确保文本不会超出画布边界
969   - if (textY > this.canvasHeight - marginBottom) {
970   - textY = this.canvasHeight - marginBottom - 2
971   - }
972   - }
973   -
974   - ctx.fillText(text, textX, textY)
975   - }
976   - }
977   - }
978   -}
979   -</script>
980   -
981   -<style scoped>
982   -.u-barcode {
983   - display: flex;
984   - flex-direction: row;
985   - justify-content: center;
986   - align-items: center;
987   -}
988   -
989   -.error-container {
990   - display: flex;
991   - justify-content: center;
992   - align-items: center;
993   - background-color: #f0f0f0;
994   - color: #ff0000;
995   -}
996   -
997   -.error-text {
998   - font-size: 14px;
999   -}
1000   -</style>
uni_modules/uview-plus/components/u-box/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -
4   -export const propsBox = defineMixin({
5   - props: {
6   - // 背景色
7   - bgColors: {
8   - type: [Array],
9   - default: ['#EEFCFF', '#FCF8FF', '#FDF8F2']
10   - },
11   - // 高度
12   - height: {
13   - type: [String],
14   - default: "160px"
15   - },
16   - // 圆角
17   - borderRadius: {
18   - type: [String],
19   - default: "6px"
20   - },
21   - // 间隔
22   - gap: {
23   - type: [String],
24   - default: "15px"
25   - },
26   - }
27   -})
uni_modules/uview-plus/components/u-box/u-box.vue deleted
1   -<template>
2   - <view class="u-box" :style="[{height: height}, addStyle(customStyle)]">
3   - <view class="u-box__left" :style="{borderRadius: borderRadius, backgroundColor: bgColors[0]}">
4   - <slot name="left">左</slot>
5   - </view>
6   - <view class="u-box__gap" :style="{width: gap, height: height}"></view>
7   - <view class="u-box__right">
8   - <view class="u-box__right-top" :style="{borderRadius: borderRadius, backgroundColor: bgColors[1]}">
9   - <slot name="rightTop">右上</slot>
10   - </view>
11   - <view class="u-box__right-gap" :style="{height: gap}"></view>
12   - <view class="u-box__right-bottom" :style="{borderRadius: borderRadius, backgroundColor: bgColors[2]}">
13   - <slot name="rightBottom">右下</slot>
14   - </view>
15   - </view>
16   - </view>
17   -</template>
18   -
19   -<script>
20   - import { propsBox } from './props';
21   - import { mpMixin } from '../../libs/mixin/mpMixin';
22   - import { mixin } from '../../libs/mixin/mixin';
23   - import { addStyle } from '../../libs/function/index';
24   - import test from '../../libs/function/test';
25   - /**
26   - * box 盒子
27   - * @description box盒子一般为左边一个盒子,右侧两个等高的半盒组成,常用于App首页座位重点突出。
28   - * @tutorial https://uview-plus.jiangruyi.com/components/box.html
29   - * @property {Array} bgColors 背景色
30   - * @property {String} height 高度
31   - * @property {String} borderRadius 圆角
32   - * @property {Object} customStyle 定义需要用到的外部样式
33   - *
34   - * @event {Function} click 点击cell列表时触发
35   - * @example <up-box colors=['blue', 'red', 'yellow'] height="200px"></up-box>
36   - */
37   - export default {
38   - name: 'up-box',
39   - data() {
40   - return {
41   - }
42   - },
43   - mixins: [mpMixin, mixin, propsBox],
44   - computed: {
45   - },
46   - emits: [],
47   - methods: {
48   - addStyle,
49   - }
50   - }
51   -</script>
52   -
53   -<style lang="scss" scoped>
54   -
55   - .u-box {
56   - /* #ifndef APP-NVUE */
57   - /* #endif */
58   - @include flex();
59   - flex: 1;
60   -
61   - &__left {
62   - @include flex();
63   - justify-content: center;
64   - align-items: center;
65   - flex: 1;
66   - }
67   - &__gap {
68   - @include flex();
69   - flex-direction: column;
70   - }
71   - &__right {
72   - @include flex();
73   - flex-direction: column;
74   - flex: 1;
75   - }
76   -
77   - &__right-top {
78   - @include flex();
79   - flex: 1;
80   - justify-content: center;
81   - align-items: center;
82   - }
83   -
84   - &__right-bottom {
85   - @include flex();
86   - flex: 1;
87   - justify-content: center;
88   - align-items: center;
89   - }
90   - }
91   -</style>
uni_modules/uview-plus/components/u-button/button.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:51:27
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/button.js
9   - */
10   -export default {
11   - // button组件
12   - button: {
13   - hairline: false,
14   - type: 'info',
15   - size: 'normal',
16   - shape: 'square',
17   - plain: false,
18   - disabled: false,
19   - loading: false,
20   - loadingText: '',
21   - loadingMode: 'spinner',
22   - loadingSize: 15,
23   - openType: '',
24   - formType: '',
25   - appParameter: '',
26   - hoverStopPropagation: true,
27   - lang: 'en',
28   - sessionFrom: '',
29   - sendMessageTitle: '',
30   - sendMessagePath: '',
31   - sendMessageImg: '',
32   - showMessageCard: false,
33   - dataName: '',
34   - throttleTime: 0,
35   - hoverStartTime: 0,
36   - hoverStayTime: 200,
37   - text: '',
38   - icon: '',
39   - iconColor: '',
40   - color: '',
41   - stop: true,
42   - }
43   -}
uni_modules/uview-plus/components/u-button/nvue.scss deleted
1   -$u-button-active-opacity:0.75 !default;
2   -$u-button-loading-text-margin-left:4px !default;
3   -$u-button-text-color: #FFFFFF !default;
4   -$u-button-text-plain-error-color:$u-error !default;
5   -$u-button-text-plain-warning-color:$u-warning !default;
6   -$u-button-text-plain-success-color:$u-success !default;
7   -$u-button-text-plain-info-color:$u-info !default;
8   -$u-button-text-plain-primary-color:$u-primary !default;
9   -.u-button {
10   - &--active {
11   - opacity: $u-button-active-opacity;
12   - }
13   -
14   - &--active--plain {
15   - background-color: rgb(217, 217, 217);
16   - }
17   -
18   - &__loading-text {
19   - margin-left:$u-button-loading-text-margin-left;
20   - }
21   -
22   - &__text,
23   - &__loading-text {
24   - color:$u-button-text-color;
25   - }
26   -
27   - &__text--plain--error {
28   - color:$u-button-text-plain-error-color;
29   - }
30   -
31   - &__text--plain--warning {
32   - color:$u-button-text-plain-warning-color;
33   - }
34   -
35   - &__text--plain--success{
36   - color:$u-button-text-plain-success-color;
37   - }
38   -
39   - &__text--plain--info {
40   - color:$u-button-text-plain-info-color;
41   - }
42   -
43   - &__text--plain--primary {
44   - color:$u-button-text-plain-primary-color;
45   - }
46   -}
47 0 \ No newline at end of file
uni_modules/uview-plus/components/u-button/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 是否细边框
6   - hairline: {
7   - type: Boolean,
8   - default: () => defProps.button.hairline
9   - },
10   - // 按钮的预置样式,info,primary,error,warning,success
11   - type: {
12   - type: String,
13   - default: () => defProps.button.type
14   - },
15   - // 按钮尺寸,large,normal,small,mini
16   - size: {
17   - type: String,
18   - default: () => defProps.button.size
19   - },
20   - // 按钮形状,circle(两边为半圆),square(带圆角)
21   - shape: {
22   - type: String,
23   - default: () => defProps.button.shape
24   - },
25   - // 按钮是否镂空
26   - plain: {
27   - type: Boolean,
28   - default: () => defProps.button.plain
29   - },
30   - // 是否禁止状态
31   - disabled: {
32   - type: Boolean,
33   - default: () => defProps.button.disabled
34   - },
35   - // 是否加载中
36   - loading: {
37   - type: Boolean,
38   - default: () => defProps.button.loading
39   - },
40   - // 加载中提示文字
41   - loadingText: {
42   - type: [String, Number],
43   - default: () => defProps.button.loadingText
44   - },
45   - // 加载状态图标类型
46   - loadingMode: {
47   - type: String,
48   - default: () => defProps.button.loadingMode
49   - },
50   - // 加载图标大小
51   - loadingSize: {
52   - type: [String, Number],
53   - default: () => defProps.button.loadingSize
54   - },
55   - // 开放能力,具体请看uniapp稳定关于button组件部分说明
56   - // https://uniapp.dcloud.io/component/button
57   - openType: {
58   - type: String,
59   - default: () => defProps.button.openType
60   - },
61   - // 用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件
62   - // 取值为submit(提交表单),reset(重置表单)
63   - formType: {
64   - type: String,
65   - default: () => defProps.button.formType
66   - },
67   - // 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效
68   - // 只微信小程序、QQ小程序有效
69   - appParameter: {
70   - type: String,
71   - default: () => defProps.button.appParameter
72   - },
73   - // 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效
74   - hoverStopPropagation: {
75   - type: Boolean,
76   - default: () => defProps.button.hoverStopPropagation
77   - },
78   - // 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。只微信小程序有效
79   - lang: {
80   - type: String,
81   - default: () => defProps.button.lang
82   - },
83   - // 会话来源,open-type="contact"时有效。只微信小程序有效
84   - sessionFrom: {
85   - type: String,
86   - default: () => defProps.button.sessionFrom
87   - },
88   - // 会话内消息卡片标题,open-type="contact"时有效
89   - // 默认当前标题,只微信小程序有效
90   - sendMessageTitle: {
91   - type: String,
92   - default: () => defProps.button.sendMessageTitle
93   - },
94   - // 会话内消息卡片点击跳转小程序路径,open-type="contact"时有效
95   - // 默认当前分享路径,只微信小程序有效
96   - sendMessagePath: {
97   - type: String,
98   - default: () => defProps.button.sendMessagePath
99   - },
100   - // 会话内消息卡片图片,open-type="contact"时有效
101   - // 默认当前页面截图,只微信小程序有效
102   - sendMessageImg: {
103   - type: String,
104   - default: () => defProps.button.sendMessageImg
105   - },
106   - // 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,
107   - // 用户点击后可以快速发送小程序消息,open-type="contact"时有效
108   - showMessageCard: {
109   - type: Boolean,
110   - default: () => defProps.button.showMessageCard
111   - },
112   - // 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取
113   - dataName: {
114   - type: String,
115   - default: () => defProps.button.dataName
116   - },
117   - // 节流,一定时间内只能触发一次
118   - throttleTime: {
119   - type: [String, Number],
120   - default: () => defProps.button.throttleTime
121   - },
122   - // 按住后多久出现点击态,单位毫秒
123   - hoverStartTime: {
124   - type: [String, Number],
125   - default: () => defProps.button.hoverStartTime
126   - },
127   - // 手指松开后点击态保留时间,单位毫秒
128   - hoverStayTime: {
129   - type: [String, Number],
130   - default: () => defProps.button.hoverStayTime
131   - },
132   - // 按钮文字,之所以通过props传入,是因为slot传入的话
133   - // nvue中无法控制文字的样式
134   - text: {
135   - type: [String, Number],
136   - default: () => defProps.button.text
137   - },
138   - // 按钮图标
139   - icon: {
140   - type: String,
141   - default: () => defProps.button.icon
142   - },
143   - // 按钮图标
144   - iconColor: {
145   - type: String,
146   - default: () => defProps.button.icon
147   - },
148   - // 按钮颜色,支持传入linear-gradient渐变色
149   - color: {
150   - type: String,
151   - default: () => defProps.button.color
152   - },
153   - // 停止冒泡
154   - stop: {
155   - type: Boolean,
156   - default: () => defProps.button.stop
157   - },
158   - }
159   -})
uni_modules/uview-plus/components/u-button/u-button.vue deleted
1   -<template>
2   - <!-- #ifndef APP-NVUE -->
3   - <button
4   - :hover-start-time="Number(hoverStartTime)"
5   - :hover-stay-time="Number(hoverStayTime)"
6   - :form-type="formType"
7   - :open-type="openType"
8   - :app-parameter="appParameter"
9   - :hover-stop-propagation="hoverStopPropagation"
10   - :send-message-title="sendMessageTitle"
11   - :send-message-path="sendMessagePath"
12   - :lang="lang"
13   - :data-name="dataName"
14   - :session-from="sessionFrom"
15   - :send-message-img="sendMessageImg"
16   - :show-message-card="showMessageCard"
17   - @getphonenumber="getphonenumber"
18   - @getuserinfo="getuserinfo"
19   - @error="error"
20   - @opensetting="opensetting"
21   - @launchapp="launchapp"
22   - @agreeprivacyauthorization="agreeprivacyauthorization"
23   - :hover-class="!disabled && !loading ? 'u-button--active' : ''"
24   - class="u-button u-reset-button"
25   - :style="[baseColor, addStyle(customStyle)]"
26   - @tap="clickHandler"
27   - :class="bemClass"
28   - >
29   - <template v-if="loading">
30   - <u-loading-icon
31   - :mode="loadingMode"
32   - :size="loadingSize * 1.15"
33   - :color="loadingColor"
34   - ></u-loading-icon>
35   - <text
36   - class="u-button__loading-text"
37   - :style="[{ fontSize: textSize + 'px' }]"
38   - >{{ loadingText || text }}</text
39   - >
40   - </template>
41   - <template v-else>
42   - <up-icon
43   - v-if="icon"
44   - :name="icon"
45   - :color="iconColorCom"
46   - :size="textSize * 1.35"
47   - :customStyle="{ marginRight: '2px' }"
48   - ></up-icon>
49   - <slot>
50   - <text
51   - class="u-button__text"
52   - :style="[{ fontSize: textSize + 'px' }]"
53   - >{{ text }}</text
54   - >
55   - </slot>
56   - </template>
57   - </button>
58   - <!-- #endif -->
59   -
60   - <!-- #ifdef APP-NVUE -->
61   - <view
62   - :hover-start-time="Number(hoverStartTime)"
63   - :hover-stay-time="Number(hoverStayTime)"
64   - class="u-button"
65   - :hover-class="
66   - !disabled && !loading && !color && (plain || type === 'info')
67   - ? 'u-button--active--plain'
68   - : !disabled && !loading && !plain
69   - ? 'u-button--active'
70   - : ''
71   - "
72   - @tap="clickHandler"
73   - :class="bemClass"
74   - :style="[baseColor, addStyle(customStyle)]"
75   - >
76   - <template v-if="loading">
77   - <u-loading-icon
78   - :mode="loadingMode"
79   - :size="loadingSize * 1.15"
80   - :color="loadingColor"
81   - ></u-loading-icon>
82   - <text
83   - class="u-button__loading-text"
84   - :style="[nvueTextStyle]"
85   - :class="[plain && `u-button__text--plain--${type}`]"
86   - >{{ loadingText || text }}</text
87   - >
88   - </template>
89   - <template v-else>
90   - <up-icon
91   - v-if="icon"
92   - :name="icon"
93   - :color="iconColorCom"
94   - :size="textSize * 1.35"
95   - ></up-icon>
96   - <text
97   - class="u-button__text"
98   - :style="[
99   - {
100   - marginLeft: icon ? '2px' : 0,
101   - },
102   - nvueTextStyle,
103   - ]"
104   - :class="[plain && `u-button__text--plain--${type}`]"
105   - >{{ text }}</text
106   - >
107   - </template>
108   - </view>
109   - <!-- #endif -->
110   -</template>
111   -
112   -<script lang="ts">
113   -import { buttonMixin } from "../../libs/mixin/button";
114   -import { openType } from "../../libs/mixin/openType";
115   -import { mpMixin } from '../../libs/mixin/mpMixin';
116   -import { mixin } from '../../libs/mixin/mixin';
117   -import { props } from "./props";
118   -import { addStyle } from '../../libs/function/index';
119   -import { throttle } from '../../libs/function/throttle';
120   -import color from '../../libs/config/color';
121   -/**
122   - * button 按钮
123   - * @description Button 按钮
124   - * @tutorial https://uview-plus.jiangruyi.com/components/button.html
125   - *
126   - * @property {Boolean} hairline 是否显示按钮的细边框 (默认 true )
127   - * @property {String} type 按钮的预置样式,info,primary,error,warning,success (默认 'info' )
128   - * @property {String} size 按钮尺寸,large,normal,mini (默认 normal)
129   - * @property {String} shape 按钮形状,circle(两边为半圆),square(带圆角) (默认 'square' )
130   - * @property {Boolean} plain 按钮是否镂空,背景色透明 (默认 false)
131   - * @property {Boolean} disabled 是否禁用 (默认 false)
132   - * @property {Boolean} loading 按钮名称前是否带 loading 图标(App-nvue 平台,在 ios 上为雪花,Android上为圆圈) (默认 false)
133   - * @property {String | Number} loadingText 加载中提示文字
134   - * @property {String} loadingMode 加载状态图标类型 (默认 'spinner' )
135   - * @property {String | Number} loadingSize 加载图标大小 (默认 15 )
136   - * @property {String} openType 开放能力,具体请看uniapp稳定关于button组件部分说明
137   - * @property {String} formType 用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件
138   - * @property {String} appParameter 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效 (注:只微信小程序、QQ小程序有效)
139   - * @property {Boolean} hoverStopPropagation 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效(默认 true )
140   - * @property {String} lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文(默认 en )
141   - * @property {String} sessionFrom 会话来源,openType="contact"时有效
142   - * @property {String} sendMessageTitle 会话内消息卡片标题,openType="contact"时有效
143   - * @property {String} sendMessagePath 会话内消息卡片点击跳转小程序路径,openType="contact"时有效
144   - * @property {String} sendMessageImg 会话内消息卡片图片,openType="contact"时有效
145   - * @property {Boolean} showMessageCard 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,openType="contact"时有效(默认false)
146   - * @property {String} dataName 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取
147   - * @property {String | Number} throttleTime 节流,一定时间内只能触发一次 (默认 0 )
148   - * @property {String | Number} hoverStartTime 按住后多久出现点击态,单位毫秒 (默认 0 )
149   - * @property {String | Number} hoverStayTime 手指松开后点击态保留时间,单位毫秒 (默认 200 )
150   - * @property {String | Number} text 按钮文字,之所以通过props传入,是因为slot传入的话(注:nvue中无法控制文字的样式)
151   - * @property {String} icon 按钮图标
152   - * @property {String} iconColor 按钮图标颜色
153   - * @property {String} color 按钮颜色,支持传入linear-gradient渐变色
154   - * @property {Object} customStyle 定义需要用到的外部样式
155   - *
156   - * @event {Function} click 非禁止并且非加载中,才能点击
157   - * @event {Function} getphonenumber open-type="getPhoneNumber"时有效
158   - * @event {Function} getuserinfo 用户点击该按钮时,会返回获取到的用户信息,从返回参数的detail中获取到的值同uni.getUserInfo
159   - * @event {Function} error 当使用开放能力时,发生错误的回调
160   - * @event {Function} opensetting 在打开授权设置页并关闭后回调
161   - * @event {Function} launchapp 打开 APP 成功的回调
162   - * @event {Function} agreeprivacyauthorization 用户同意隐私协议事件回调
163   - * @example <u-button>月落</u-button>
164   - */
165   -export default {
166   - name: "u-button",
167   - // #ifdef MP
168   - mixins: [mpMixin, mixin, buttonMixin, openType, props],
169   - // #endif
170   - // #ifndef MP
171   - mixins: [mpMixin, mixin, props],
172   - // #endif
173   - data() {
174   - return {};
175   - },
176   - computed: {
177   - // 生成bem风格的类名
178   - bemClass() {
179   - // this.bem为一个computed变量,在mixin中
180   - if (!this.color) {
181   - return this.bem(
182   - "button",
183   - ["type", "shape", "size"],
184   - ["disabled", "plain", "hairline"]
185   - );
186   - } else {
187   - // 由于nvue的原因,在有color参数时,不需要传入type,否则会生成type相关的类型,影响最终的样式
188   - return this.bem(
189   - "button",
190   - ["shape", "size"],
191   - ["disabled", "plain", "hairline"]
192   - );
193   - }
194   - },
195   - loadingColor() {
196   - if (this.plain) {
197   - // 如果有设置color值,则用color值,否则使用type主题颜色
198   - return this.color
199   - ? this.color
200   - : color[`u-${this.type}`];
201   - }
202   - if (this.type === "info") {
203   - return "#c9c9c9";
204   - }
205   - return "rgb(200, 200, 200)";
206   - },
207   - iconColorCom() {
208   - // 如果是镂空状态,设置了color就用color值,否则使用主题颜色,
209   - // up-icon的color能接受一个主题颜色的值
210   - if (this.iconColor) return this.iconColor;
211   - if (this.plain) {
212   - return this.color ? this.color : this.type;
213   - } else {
214   - return this.type === "info" ? "#000000" : "#ffffff";
215   - }
216   - },
217   - baseColor() {
218   - let style = {};
219   - if (this.color) {
220   - // 针对自定义了color颜色的情况,镂空状态下,就是用自定义的颜色
221   - style.color = this.plain ? this.color : "white";
222   - if (!this.plain) {
223   - // 非镂空,背景色使用自定义的颜色
224   - style["background-color"] = this.color;
225   - }
226   - if (this.color.indexOf("gradient") !== -1) {
227   - // 如果自定义的颜色为渐变色,不显示边框,以及通过backgroundImage设置渐变色
228   - // weex文档说明可以写borderWidth的形式,为什么这里需要分开写?
229   - // 因为weex是阿里巴巴为了部门业绩考核而做的你懂的东西,所以需要这么写才有效
230   - style.borderTopWidth = 0;
231   - style.borderRightWidth = 0;
232   - style.borderBottomWidth = 0;
233   - style.borderLeftWidth = 0;
234   - if (!this.plain) {
235   - style.backgroundImage = this.color;
236   - }
237   - } else {
238   - // 非渐变色,则设置边框相关的属性
239   - style.borderColor = this.color;
240   - style.borderWidth = "1px";
241   - style.borderStyle = "solid";
242   - }
243   - }
244   - return style;
245   - },
246   - // nvue版本按钮的字体不会继承父组件的颜色,需要对每一个text组件进行单独的设置
247   - nvueTextStyle() {
248   - let style = {};
249   - // 针对自定义了color颜色的情况,镂空状态下,就是用自定义的颜色
250   - if (this.type === "info") {
251   - style.color = "#323233";
252   - }
253   - if (this.color) {
254   - style.color = this.plain ? this.color : "white";
255   - }
256   - style.fontSize = this.textSize + "px";
257   - return style;
258   - },
259   - // 字体大小
260   - textSize() {
261   - let fontSize = 14,
262   - { size } = this;
263   - if (size === "large") fontSize = 16;
264   - if (size === "normal") fontSize = 14;
265   - if (size === "small") fontSize = 12;
266   - if (size === "mini") fontSize = 10;
267   - return fontSize;
268   - },
269   - },
270   - emits: ['click', 'getphonenumber', 'getuserinfo',
271   - 'error', 'opensetting', 'launchapp', 'agreeprivacyauthorization'],
272   - methods: {
273   - addStyle,
274   - clickHandler(e: any) {
275   - // 非禁止并且非加载中,才能点击
276   - if (!this.disabled && !this.loading) {
277   - // 进行节流控制,每this.throttle毫秒内,只在开始处执行
278   - throttle(() => {
279   - this.$emit("click", e);
280   - }, this.throttleTime);
281   - }
282   - // 是否阻止事件传播
283   - this.stop && this.preventEvent(e)
284   - },
285   - // 下面为对接uniapp官方按钮开放能力事件回调的对接
286   - getphonenumber(res: any) {
287   - this.$emit("getphonenumber", res);
288   - },
289   - getuserinfo(res: any) {
290   - this.$emit("getuserinfo", res);
291   - },
292   - error(res: any) {
293   - this.$emit("error", res);
294   - },
295   - opensetting(res: any) {
296   - this.$emit("opensetting", res);
297   - },
298   - launchapp(res: any) {
299   - this.$emit("launchapp", res);
300   - },
301   - agreeprivacyauthorization(res) {
302   - this.$emit("agreeprivacyauthorization", res);
303   - },
304   - },
305   -};
306   -</script>
307   -
308   -<style lang="scss" scoped>
309   -/* #ifndef APP-NVUE */
310   -@import "./vue.scss";
311   -/* #endif */
312   -
313   -/* #ifdef APP-NVUE */
314   -@import "./nvue.scss";
315   -/* #endif */
316   -
317   -$u-button-u-button-height: 40px !default;
318   -$u-button-text-font-size: 15px !default;
319   -$u-button-loading-text-font-size: 15px !default;
320   -$u-button-loading-text-margin-left: 4px !default;
321   -$u-button-large-width: 100% !default;
322   -$u-button-large-height: 50px !default;
323   -$u-button-normal-padding: 0 12px !default;
324   -$u-button-large-padding: 0 15px !default;
325   -$u-button-normal-font-size: 14px !default;
326   -$u-button-small-min-width: 60px !default;
327   -$u-button-small-height: 30px !default;
328   -$u-button-small-padding: 0px 8px !default;
329   -$u-button-mini-padding: 0px 8px !default;
330   -$u-button-small-font-size: 12px !default;
331   -$u-button-mini-height: 22px !default;
332   -$u-button-mini-font-size: 10px !default;
333   -$u-button-mini-min-width: 50px !default;
334   -$u-button-disabled-opacity: 0.5 !default;
335   -$u-button-info-color: #323233 !default;
336   -$u-button-info-background-color: #fff !default;
337   -$u-button-info-border-color: #ebedf0 !default;
338   -$u-button-info-border-width: 1px !default;
339   -$u-button-info-border-style: solid !default;
340   -$u-button-success-color: #fff !default;
341   -$u-button-success-background-color: $u-success !default;
342   -$u-button-success-border-color: $u-button-success-background-color !default;
343   -$u-button-success-border-width: 1px !default;
344   -$u-button-success-border-style: solid !default;
345   -$u-button-primary-color: #fff !default;
346   -$u-button-primary-background-color: $u-primary !default;
347   -$u-button-primary-border-color: $u-button-primary-background-color !default;
348   -$u-button-primary-border-width: 1px !default;
349   -$u-button-primary-border-style: solid !default;
350   -$u-button-error-color: #fff !default;
351   -$u-button-error-background-color: $u-error !default;
352   -$u-button-error-border-color: $u-button-error-background-color !default;
353   -$u-button-error-border-width: 1px !default;
354   -$u-button-error-border-style: solid !default;
355   -$u-button-warning-color: #fff !default;
356   -$u-button-warning-background-color: $u-warning !default;
357   -$u-button-warning-border-color: $u-button-warning-background-color !default;
358   -$u-button-warning-border-width: 1px !default;
359   -$u-button-warning-border-style: solid !default;
360   -$u-button-block-width: 100% !default;
361   -$u-button-circle-border-top-right-radius: 100px !default;
362   -$u-button-circle-border-top-left-radius: 100px !default;
363   -$u-button-circle-border-bottom-left-radius: 100px !default;
364   -$u-button-circle-border-bottom-right-radius: 100px !default;
365   -$u-button-square-border-top-right-radius: 3px !default;
366   -$u-button-square-border-top-left-radius: 3px !default;
367   -$u-button-square-border-bottom-left-radius: 3px !default;
368   -$u-button-square-border-bottom-right-radius: 3px !default;
369   -$u-button-icon-min-width: 1em !default;
370   -$u-button-plain-background-color: #fff !default;
371   -$u-button-hairline-border-width: 0.5px !default;
372   -
373   -.u-button {
374   - height: $u-button-u-button-height;
375   - position: relative;
376   - align-items: center;
377   - justify-content: center;
378   - @include flex;
379   - /* #ifndef APP-NVUE */
380   - box-sizing: border-box;
381   - /* #endif */
382   - flex-direction: row;
383   -
384   - &__text {
385   - font-size: $u-button-text-font-size;
386   - }
387   -
388   - &__loading-text {
389   - font-size: $u-button-loading-text-font-size;
390   - margin-left: $u-button-loading-text-margin-left;
391   - }
392   -
393   - &--large {
394   - /* #ifndef APP-NVUE */
395   - width: $u-button-large-width;
396   - /* #endif */
397   - height: $u-button-large-height;
398   - padding: $u-button-large-padding;
399   - }
400   -
401   - &--normal {
402   - padding: $u-button-normal-padding;
403   - font-size: $u-button-normal-font-size;
404   - }
405   -
406   - &--small {
407   - /* #ifndef APP-NVUE */
408   - min-width: $u-button-small-min-width;
409   - /* #endif */
410   - height: $u-button-small-height;
411   - padding: $u-button-small-padding;
412   - font-size: $u-button-small-font-size;
413   - }
414   -
415   - &--mini {
416   - height: $u-button-mini-height;
417   - font-size: $u-button-mini-font-size;
418   - /* #ifndef APP-NVUE */
419   - min-width: $u-button-mini-min-width;
420   - /* #endif */
421   - padding: $u-button-mini-padding;
422   - }
423   -
424   - &--disabled {
425   - opacity: $u-button-disabled-opacity;
426   - }
427   -
428   - &--info {
429   - color: $u-button-info-color;
430   - background-color: $u-button-info-background-color;
431   - border-color: $u-button-info-border-color;
432   - border-width: $u-button-info-border-width;
433   - border-style: $u-button-info-border-style;
434   - }
435   -
436   - &--success {
437   - color: $u-button-success-color;
438   - background-color: $u-button-success-background-color;
439   - border-color: $u-button-success-border-color;
440   - border-width: $u-button-success-border-width;
441   - border-style: $u-button-success-border-style;
442   - }
443   -
444   - &--primary {
445   - color: $u-button-primary-color;
446   - background-color: $u-button-primary-background-color;
447   - border-color: $u-button-primary-border-color;
448   - border-width: $u-button-primary-border-width;
449   - border-style: $u-button-primary-border-style;
450   - }
451   -
452   - &--error {
453   - color: $u-button-error-color;
454   - background-color: $u-button-error-background-color;
455   - border-color: $u-button-error-border-color;
456   - border-width: $u-button-error-border-width;
457   - border-style: $u-button-error-border-style;
458   - }
459   -
460   - &--warning {
461   - color: $u-button-warning-color;
462   - background-color: $u-button-warning-background-color;
463   - border-color: $u-button-warning-border-color;
464   - border-width: $u-button-warning-border-width;
465   - border-style: $u-button-warning-border-style;
466   - }
467   -
468   - &--block {
469   - @include flex;
470   - width: $u-button-block-width;
471   - }
472   -
473   - &--circle {
474   - border-top-right-radius: $u-button-circle-border-top-right-radius;
475   - border-top-left-radius: $u-button-circle-border-top-left-radius;
476   - border-bottom-left-radius: $u-button-circle-border-bottom-left-radius;
477   - border-bottom-right-radius: $u-button-circle-border-bottom-right-radius;
478   - }
479   -
480   - &--square {
481   - border-bottom-left-radius: $u-button-square-border-top-right-radius;
482   - border-bottom-right-radius: $u-button-square-border-top-left-radius;
483   - border-top-left-radius: $u-button-square-border-bottom-left-radius;
484   - border-top-right-radius: $u-button-square-border-bottom-right-radius;
485   - }
486   -
487   - &__icon {
488   - /* #ifndef APP-NVUE */
489   - min-width: $u-button-icon-min-width;
490   - line-height: inherit !important;
491   - vertical-align: top;
492   - /* #endif */
493   - }
494   -
495   - &--plain {
496   - background-color: $u-button-plain-background-color;
497   - }
498   -
499   - &--hairline {
500   - border-width: $u-button-hairline-border-width !important;
501   - }
502   -}
503   -</style>
uni_modules/uview-plus/components/u-button/vue.scss deleted
1   -// nvue下hover-class无效
2   -$u-button-before-top:50% !default;
3   -$u-button-before-left:50% !default;
4   -$u-button-before-width:100% !default;
5   -$u-button-before-height:100% !default;
6   -$u-button-before-transform:translate(-50%, -50%) !default;
7   -$u-button-before-opacity:0 !default;
8   -$u-button-before-background-color:#000 !default;
9   -$u-button-before-border-color:#000 !default;
10   -$u-button-active-before-opacity:.15 !default;
11   -$u-button-icon-margin-left:4px !default;
12   -$u-button-plain-u-button-info-color:$u-info;
13   -$u-button-plain-u-button-success-color:$u-success;
14   -$u-button-plain-u-button-error-color:$u-error;
15   -$u-button-plain-u-button-warning-color:$u-warning;
16   -
17   -.u-button {
18   - width: 100%;
19   - white-space: nowrap;
20   -
21   - &__text {
22   - white-space: nowrap;
23   - line-height: 1;
24   - }
25   -
26   - &:before {
27   - position: absolute;
28   - top:$u-button-before-top;
29   - left:$u-button-before-left;
30   - width:$u-button-before-width;
31   - height:$u-button-before-height;
32   - border: inherit;
33   - border-radius: inherit;
34   - transform:$u-button-before-transform;
35   - opacity:$u-button-before-opacity;
36   - content: " ";
37   - background-color:$u-button-before-background-color;
38   - border-color:$u-button-before-border-color;
39   - }
40   -
41   - &--active {
42   - &:before {
43   - opacity: .15
44   - }
45   - }
46   -
47   - &__icon+&__text:not(:empty),
48   - &__loading-text {
49   - margin-left:$u-button-icon-margin-left;
50   - }
51   -
52   - &--plain {
53   - &.u-button--primary {
54   - color: $u-primary;
55   - }
56   - }
57   -
58   - &--plain {
59   - &.u-button--info {
60   - color:$u-button-plain-u-button-info-color;
61   - }
62   - }
63   -
64   - &--plain {
65   - &.u-button--success {
66   - color:$u-button-plain-u-button-success-color;
67   - }
68   - }
69   -
70   - &--plain {
71   - &.u-button--error {
72   - color:$u-button-plain-u-button-error-color;
73   - }
74   - }
75   -
76   - &--plain {
77   - &.u-button--warning {
78   - color:$u-button-plain-u-button-warning-color;
79   - }
80   - }
81   -}
uni_modules/uview-plus/components/u-calendar/calendar.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:52:43
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/calendar.js
9   - */
10   -import { t } from '../../libs/i18n'
11   -export default {
12   - // calendar 组件
13   - calendar: {
14   - title: t("up.calendar.chooseDates"),
15   - showTitle: true,
16   - showSubtitle: true,
17   - mode: 'single',
18   - startText: t("up.common.start"),
19   - endText: t("up.common.end"),
20   - customList: [],
21   - color: '#3c9cff',
22   - minDate: 0,
23   - maxDate: 0,
24   - defaultDate: null,
25   - maxCount: Number.MAX_SAFE_INTEGER, // Infinity
26   - rowHeight: 56,
27   - formatter: null,
28   - showLunar: false,
29   - showMark: true,
30   - confirmText: t("up.common.confirm"),
31   - confirmDisabledText: t("up.common.confirm"),
32   - show: false,
33   - closeOnClickOverlay: false,
34   - readonly: false,
35   - showConfirm: true,
36   - maxRange: Number.MAX_SAFE_INTEGER, // Infinity
37   - rangePrompt: '',
38   - showRangePrompt: true,
39   - allowSameDay: false,
40   - round: 0,
41   - monthNum: 3,
42   - weekText: [t("up.week.one"), t("up.week.two"), t("up.week.three"), t("up.week.four"), t("up.week.five"), t("up.week.six"), t("up.week.seven")],
43   - forbidDays: [],
44   - forbidDaysToast: t("up.calendar.disabled"),
45   - monthFormat: '',
46   - pageInline: false
47   - }
48   -}
uni_modules/uview-plus/components/u-calendar/header.vue deleted
1   -<template>
2   - <view class="u-calendar-header u-border-bottom">
3   - <text
4   - class="u-calendar-header__title"
5   - v-if="showTitle"
6   - >{{ title }}</text>
7   - <text
8   - class="u-calendar-header__subtitle"
9   - v-if="showSubtitle"
10   - >{{ subtitle }}</text>
11   - <view class="u-calendar-header__weekdays">
12   - <text class="u-calendar-header__weekdays__weekday">{{ weekText[0] }}</text>
13   - <text class="u-calendar-header__weekdays__weekday">{{ weekText[1] }}</text>
14   - <text class="u-calendar-header__weekdays__weekday">{{ weekText[2] }}</text>
15   - <text class="u-calendar-header__weekdays__weekday">{{ weekText[3] }}</text>
16   - <text class="u-calendar-header__weekdays__weekday">{{ weekText[4] }}</text>
17   - <text class="u-calendar-header__weekdays__weekday">{{ weekText[5] }}</text>
18   - <text class="u-calendar-header__weekdays__weekday">{{ weekText[6] }}</text>
19   - </view>
20   - </view>
21   -</template>
22   -
23   -<script>
24   - import { mpMixin } from '../../libs/mixin/mpMixin';
25   - import { mixin } from '../../libs/mixin/mixin';
26   - export default {
27   - name: 'u-calendar-header',
28   - mixins: [mpMixin, mixin],
29   - props: {
30   - // 标题
31   - title: {
32   - type: String,
33   - default: ''
34   - },
35   - // 副标题
36   - subtitle: {
37   - type: String,
38   - default: ''
39   - },
40   - // 是否显示标题
41   - showTitle: {
42   - type: Boolean,
43   - default: true
44   - },
45   - // 是否显示副标题
46   - showSubtitle: {
47   - type: Boolean,
48   - default: true
49   - },
50   - // 星期文本
51   - weekText: {
52   - type: Array,
53   - default: () => {
54   - return []
55   - }
56   - },
57   - },
58   - data() {
59   - return {
60   -
61   - }
62   - },
63   - methods: {
64   - name() {
65   -
66   - }
67   - },
68   - }
69   -</script>
70   -
71   -<style lang="scss" scoped>
72   -
73   - .u-calendar-header {
74   - display: flex;
75   - flex-direction: column;
76   - padding-bottom: 4px;
77   -
78   - &__title {
79   - font-size: 16px;
80   - color: $u-main-color;
81   - text-align: center;
82   - height: 42px;
83   - line-height: 42px;
84   - font-weight: bold;
85   - }
86   -
87   - &__subtitle {
88   - font-size: 14px;
89   - color: $u-main-color;
90   - height: 40px;
91   - text-align: center;
92   - line-height: 40px;
93   - font-weight: bold;
94   - }
95   -
96   - &__weekdays {
97   - @include flex;
98   - justify-content: space-between;
99   -
100   - &__weekday {
101   - font-size: 13px;
102   - color: $u-main-color;
103   - line-height: 30px;
104   - flex: 1;
105   - text-align: center;
106   - }
107   - }
108   - }
109   -</style>
uni_modules/uview-plus/components/u-calendar/month.vue deleted
1   -<template>
2   - <view class="u-calendar-month-wrapper" ref="u-calendar-month-wrapper">
3   - <view v-for="(item, index) in months" :key="index" :class="[`u-calendar-month-${index}`]"
4   - :ref="`u-calendar-month-${index}`" :id="`month-${index}`">
5   - <text v-if="index !== 0" class="u-calendar-month__title">{{ monthTitle(item) }}</text>
6   - <view class="u-calendar-month__days">
7   - <view v-if="showMark" class="u-calendar-month__days__month-mark-wrapper">
8   - <text class="u-calendar-month__days__month-mark-wrapper__text">{{ item.month }}</text>
9   - </view>
10   - <view class="u-calendar-month__days__day" v-for="(item1, index1) in item.date" :key="index1"
11   - :style="[dayStyle(index, index1, item1)]" @tap="clickHandler(index, index1, item1)"
12   - :class="[item1.selected && 'u-calendar-month__days__day__select--selected']">
13   - <view class="u-calendar-month__days__day__select" :style="[daySelectStyle(index, index1, item1)]">
14   - <text class="u-calendar-month__days__day__select__info"
15   - :class="[(item1.disabled || isForbid(item1) ) ? 'u-calendar-month__days__day__select__info--disabled' : '']"
16   - :style="[textStyle(item1)]">{{ item1.day }}</text>
17   - <text v-if="getBottomInfo(index, index1, item1)"
18   - class="u-calendar-month__days__day__select__buttom-info"
19   - :class="[(item1.disabled || isForbid(item1) ) ? 'u-calendar-month__days__day__select__buttom-info--disabled' : '']"
20   - :style="[textStyle(item1)]">{{ getBottomInfo(index, index1, item1) }}</text>
21   - <text v-if="item1.dot" class="u-calendar-month__days__day__select__dot"></text>
22   - </view>
23   - </view>
24   - </view>
25   - </view>
26   - </view>
27   -</template>
28   -
29   -<script>
30   - // #ifdef APP-NVUE
31   - // 由于nvue不支持百分比单位,需要查询宽度来计算每个日期的宽度
32   - const dom = uni.requireNativePlugin('dom')
33   - // #endif
34   - import { mpMixin } from '../../libs/mixin/mpMixin';
35   - import { mixin } from '../../libs/mixin/mixin';
36   - import { addUnit, deepClone, toast, sleep } from '../../libs/function/index';
37   - import { colorGradient } from '../../libs/function/colorGradient';
38   - import test from '../../libs/function/test';
39   - import defProps from '../../libs/config/props';
40   - import dayjs from '../u-datetime-picker/dayjs.esm.min.js';
41   - import { t } from '../../libs/i18n'
42   - export default {
43   - name: 'u-calendar-month',
44   - mixins: [mpMixin, mixin],
45   - props: {
46   - // 是否显示月份背景色
47   - showMark: {
48   - type: Boolean,
49   - default: true
50   - },
51   - // 主题色,对底部按钮和选中日期有效
52   - color: {
53   - type: String,
54   - default: '#3c9cff'
55   - },
56   - // 月份数据
57   - months: {
58   - type: Array,
59   - default: () => []
60   - },
61   - // 日期选择类型
62   - mode: {
63   - type: String,
64   - default: 'single'
65   - },
66   - // 日期行高
67   - rowHeight: {
68   - type: [String, Number],
69   - default: 58
70   - },
71   - // mode=multiple时,最多可选多少个日期
72   - maxCount: {
73   - type: [String, Number],
74   - default: Infinity
75   - },
76   - // mode=range时,第一个日期底部的提示文字
77   - startText: {
78   - type: String,
79   - default: '开始'
80   - },
81   - // mode=range时,最后一个日期底部的提示文字
82   - endText: {
83   - type: String,
84   - default: '结束'
85   - },
86   - // 默认选中的日期,mode为multiple或range是必须为数组格式
87   - defaultDate: {
88   - type: [Array, String, Date],
89   - default: null
90   - },
91   - // 最小的可选日期
92   - minDate: {
93   - type: [String, Number],
94   - default: 0
95   - },
96   - // 最大可选日期
97   - maxDate: {
98   - type: [String, Number],
99   - default: 0
100   - },
101   - // 如果没有设置maxDate,则往后推多少个月
102   - maxMonth: {
103   - type: [String, Number],
104   - default: 2
105   - },
106   - // 是否为只读状态,只读状态下禁止选择日期
107   - readonly: {
108   - type: Boolean,
109   - default: () => defProps.calendar.readonly
110   - },
111   - // 日期区间最多可选天数,默认无限制,mode = range时有效
112   - maxRange: {
113   - type: [Number, String],
114   - default: Infinity
115   - },
116   - // 范围选择超过最多可选天数时的提示文案,mode = range时有效
117   - rangePrompt: {
118   - type: String,
119   - default: ''
120   - },
121   - // 范围选择超过最多可选天数时,是否展示提示文案,mode = range时有效
122   - showRangePrompt: {
123   - type: Boolean,
124   - default: true
125   - },
126   - // 是否允许日期范围的起止时间为同一天,mode = range时有效
127   - allowSameDay: {
128   - type: Boolean,
129   - default: false
130   - },
131   - forbidDays: {
132   - type: Array,
133   - default: () => []
134   - },
135   - forbidDaysToast: {
136   - type: String,
137   - default: ''
138   - }
139   - },
140   - data() {
141   - return {
142   - // 每个日期的宽度
143   - width: 0,
144   - // 当前选中的日期item
145   - item: {},
146   - selected: []
147   - }
148   - },
149   - watch: {
150   - selectedChange: {
151   - immediate: true,
152   - handler(n) {
153   - this.setDefaultDate()
154   - }
155   - }
156   - },
157   - computed: {
158   - // 多个条件的变化,会引起选中日期的变化,这里统一管理监听
159   - selectedChange() {
160   - return [this.minDate, this.maxDate, this.defaultDate]
161   - },
162   - dayStyle(index1, index2, item) {
163   - return (index1, index2, item) => {
164   - const style = {}
165   - let week = item.week
166   - // 不进行四舍五入的形式保留2位小数
167   - const dayWidth = Number(parseFloat(this.width / 7).toFixed(3).slice(0, -1))
168   - // 得出每个日期的宽度
169   - // #ifdef APP-NVUE
170   - style.width = addUnit(dayWidth, 'px')
171   - // #endif
172   - style.height = addUnit(this.rowHeight, 'px')
173   - if (index2 === 0) {
174   - // 获取当前为星期几,如果为0,则为星期天,减一为每月第一天时,需要向左偏移的item个数
175   - week = (week === 0 ? 7 : week) - 1
176   - style.marginLeft = addUnit(week * dayWidth, 'px')
177   - }
178   - if (this.mode === 'range') {
179   - // 之所以需要这么写,是因为DCloud公司的iOS客户端导致的bug
180   - style.paddingLeft = 0
181   - style.paddingRight = 0
182   - style.paddingBottom = 0
183   - style.paddingTop = 0
184   - }
185   - return style
186   - }
187   - },
188   - daySelectStyle() {
189   - return (index1, index2, item) => {
190   - let date = dayjs(item.date).format("YYYY-MM-DD"),
191   - style = {}
192   - // 判断date是否在selected数组中,因为月份可能会需要补0,所以使用dateSame判断,而不用数组的includes判断
193   - if (this.selected.some(item => this.dateSame(item, date))) {
194   - style.backgroundColor = this.color
195   - }
196   - if (this.mode === 'single') {
197   - if (date === this.selected[0]) {
198   - // 因为需要对nvue的兼容,只能这么写,无法缩写,也无法通过类名控制等等
199   - style.borderTopLeftRadius = '3px'
200   - style.borderBottomLeftRadius = '3px'
201   - style.borderTopRightRadius = '3px'
202   - style.borderBottomRightRadius = '3px'
203   - }
204   - } else if (this.mode === 'range') {
205   - if (this.selected.length >= 2) {
206   - const len = this.selected.length - 1
207   - // 第一个日期设置左上角和左下角的圆角
208   - if (this.dateSame(date, this.selected[0])) {
209   - style.borderTopLeftRadius = '3px'
210   - style.borderBottomLeftRadius = '3px'
211   - }
212   - // 最后一个日期设置右上角和右下角的圆角
213   - if (this.dateSame(date, this.selected[len])) {
214   - style.borderTopRightRadius = '3px'
215   - style.borderBottomRightRadius = '3px'
216   - }
217   - // 处于第一和最后一个之间的日期,背景色设置为浅色,通过将对应颜色进行等分,再取其尾部的颜色值
218   - if (dayjs(date).isAfter(dayjs(this.selected[0])) && dayjs(date).isBefore(dayjs(this
219   - .selected[len]))) {
220   - style.backgroundColor = colorGradient(this.color, '#ffffff', 100)[90]
221   - // 增加一个透明度,让范围区间的背景色也能看到底部的mark水印字符
222   - style.opacity = 0.7
223   - }
224   - } else if (this.selected.length === 1) {
225   - // 之所以需要这么写,是因为uni-app的iOS客户端的bug
226   - // 进行还原操作,否则在nvue的iOS,uni-app有bug,会导致诡异的表现
227   - style.borderTopLeftRadius = '3px'
228   - style.borderBottomLeftRadius = '3px'
229   - }
230   - } else {
231   - if (this.selected.some(item => this.dateSame(item, date))) {
232   - style.borderTopLeftRadius = '3px'
233   - style.borderBottomLeftRadius = '3px'
234   - style.borderTopRightRadius = '3px'
235   - style.borderBottomRightRadius = '3px'
236   - }
237   - }
238   - return style
239   - }
240   - },
241   - // 某个日期是否被选中
242   - textStyle() {
243   - return (item) => {
244   - const date = dayjs(item.date).format("YYYY-MM-DD"),
245   - style = {}
246   - // 选中的日期,提示文字设置白色
247   - if (this.selected.some(item => this.dateSame(item, date))) {
248   - style.color = '#ffffff'
249   - }
250   - if (this.mode === 'range') {
251   - const len = this.selected.length - 1
252   - // 如果是范围选择模式,第一个和最后一个之间的日期,文字颜色设置为高亮的主题色
253   - if (dayjs(date).isAfter(dayjs(this.selected[0])) && dayjs(date).isBefore(dayjs(this
254   - .selected[len]))) {
255   - style.color = this.color
256   - }
257   - }
258   - return style
259   - }
260   - },
261   - // 获取底部的提示文字
262   - getBottomInfo() {
263   - return (index1, index2, item) => {
264   - const date = dayjs(item.date).format("YYYY-MM-DD")
265   - const bottomInfo = item.bottomInfo
266   - // 当为日期范围模式时,且选择的日期个数大于0时
267   - if (this.mode === 'range' && this.selected.length > 0) {
268   - if (this.selected.length === 1) {
269   - // 选择了一个日期时,如果当前日期为数组中的第一个日期,则显示底部文字为“开始”
270   - if (this.dateSame(date, this.selected[0])) return this.startText
271   - else return bottomInfo
272   - } else {
273   - const len = this.selected.length - 1
274   - // 如果数组中的日期大于2个时,第一个和最后一个显示为开始和结束日期
275   - if (this.dateSame(date, this.selected[0]) && this.dateSame(date, this.selected[1]) &&
276   - len === 1) {
277   - // 如果长度为2,且第一个等于第二个日期,则提示语放在同一个item中
278   - return `${this.startText}/${this.endText}`
279   - } else if (this.dateSame(date, this.selected[0])) {
280   - return this.startText
281   - } else if (this.dateSame(date, this.selected[len])) {
282   - return this.endText
283   - } else {
284   - return bottomInfo
285   - }
286   - }
287   - } else {
288   - return bottomInfo
289   - }
290   - }
291   - }
292   - },
293   - mounted() {
294   - this.init()
295   - },
296   - emits: ['monthSelected', 'updateMonthTop'],
297   - methods: {
298   - init() {
299   - // 初始化默认选中
300   - this.$emit('monthSelected', this.selected)
301   - this.$nextTick(() => {
302   - // 这里需要另一个延时,因为获取宽度后,会进行月份数据渲染,只有渲染完成之后,才有真正的高度
303   - // 因为nvue下,$nextTick并不是100%可靠的
304   - sleep(10).then(() => {
305   - this.getWrapperWidth()
306   - this.getMonthRect()
307   - })
308   - })
309   - },
310   - monthTitle(item) {
311   - if (uni.getLocale() == 'zh-Hans' || uni.getLocale() == 'zh-Hant') {
312   - return item.year + '年' + (item.month < 10 ? '0' + item.month : item.month) + '月'
313   - } else {
314   - return (item.month < 10 ? '0' + item.month : item.month) + '/' + item.year
315   - }
316   - },
317   - isForbid(item) {
318   - let date = dayjs(item.date).format("YYYY-MM-DD")
319   - if (this.mode !== 'range' && this.forbidDays.includes(date)) {
320   - return true
321   - }
322   - return false
323   - },
324   - // 判断两个日期是否相等
325   - dateSame(date1, date2) {
326   - return dayjs(date1).isSame(dayjs(date2))
327   - },
328   - // 获取月份数据区域的宽度,因为nvue不支持百分比,所以无法通过css设置每个日期item的宽度
329   - getWrapperWidth() {
330   - // #ifdef APP-NVUE
331   - dom.getComponentRect(this.$refs['u-calendar-month-wrapper'], res => {
332   - this.width = res.size.width
333   - })
334   - // #endif
335   - // #ifndef APP-NVUE
336   - this.$uGetRect('.u-calendar-month-wrapper').then(size => {
337   - this.width = size.width
338   - })
339   - // #endif
340   - },
341   - getMonthRect() {
342   - // 获取每个月份数据的尺寸,用于父组件在scroll-view滚动事件中,监听当前滚动到了第几个月份
343   - const promiseAllArr = this.months.map((item, index) => this.getMonthRectByPromise(
344   - `u-calendar-month-${index}`))
345   - // 一次性返回
346   - Promise.all(promiseAllArr).then(
347   - sizes => {
348   - let height = 1
349   - const topArr = []
350   - for (let i = 0; i < this.months.length; i++) {
351   - // 添加到months数组中,供scroll-view滚动事件中,判断当前滚动到哪个月份
352   - topArr[i] = height
353   - height += sizes[i].height
354   - }
355   - // 由于微信下,无法通过this.months[i].top的形式(引用类型)去修改父组件的month的top值,所以使用事件形式对外发出
356   - this.$emit('updateMonthTop', topArr)
357   - })
358   - },
359   - // 获取每个月份区域的尺寸
360   - getMonthRectByPromise(el) {
361   - // #ifndef APP-NVUE
362   - // $uGetRect为uView自带的节点查询简化方法,详见文档介绍:https://uview-plus.jiangruyi.com/js/getRect.html
363   - // 组件内部一般用this.$uGetRect,对外的为uni.$u.getRect,二者功能一致,名称不同
364   - return new Promise(resolve => {
365   - this.$uGetRect(`.${el}`).then(size => {
366   - resolve(size)
367   - })
368   - })
369   - // #endif
370   -
371   - // #ifdef APP-NVUE
372   - // nvue下,使用dom模块查询元素高度
373   - // 返回一个promise,让调用此方法的主体能使用then回调
374   - return new Promise(resolve => {
375   - dom.getComponentRect(this.$refs[el][0], res => {
376   - resolve(res.size)
377   - })
378   - })
379   - // #endif
380   - },
381   - // 点击某一个日期
382   - clickHandler(index1, index2, item) {
383   - if (this.readonly) {
384   - return;
385   - }
386   - this.item = item
387   - const date = dayjs(item.date).format("YYYY-MM-DD")
388   - if (item.disabled) return
389   - if (this.isForbid(item)) {
390   - uni.showToast({
391   - title: this.forbidDaysToast
392   - })
393   - return
394   - }
395   - // 对上一次选择的日期数组进行深度克隆
396   - let selected = deepClone(this.selected)
397   - if (this.mode === 'single') {
398   - // 单选情况下,让数组中的元素为当前点击的日期
399   - selected = [date]
400   - } else if (this.mode === 'multiple') {
401   - if (selected.some(item => this.dateSame(item, date))) {
402   - // 如果点击的日期已在数组中,则进行移除操作,也就是达到反选的效果
403   - const itemIndex = selected.findIndex(item => item === date)
404   - selected.splice(itemIndex, 1)
405   - } else {
406   - // 如果点击的日期不在数组中,且已有的长度小于总可选长度时,则添加到数组中去
407   - if (selected.length < this.maxCount) selected.push(date)
408   - }
409   - } else {
410   - // 选择区间形式
411   - if (selected.length === 0 || selected.length >= 2) {
412   - // 如果原来就为0或者大于2的长度,则当前点击的日期,就是开始日期
413   - selected = [date]
414   - } else if (selected.length === 1) {
415   - // 如果已经选择了开始日期
416   - const existsDate = selected[0]
417   - // 如果当前选择的日期小于上一次选择的日期,则当前的日期定为开始日期
418   - if (dayjs(date).isBefore(existsDate)) {
419   - selected = [date]
420   - } else if (dayjs(date).isAfter(existsDate)) {
421   - // 当前日期减去最大可选的日期天数,如果大于起始时间,则进行提示
422   - if(dayjs(dayjs(date).subtract(this.maxRange, 'day')).isAfter(dayjs(selected[0])) && this.showRangePrompt) {
423   - if(this.rangePrompt) {
424   - toast(this.rangePrompt)
425   - } else {
426   - toast(t("up.calendar.daysExceed", { days: this.maxRange }))
427   - }
428   - return
429   - }
430   - // 如果当前日期大于已有日期,将当前的添加到数组尾部
431   - selected.push(date)
432   - const startDate = selected[0]
433   - const endDate = selected[1]
434   - const arr = []
435   - let i = 0
436   - do {
437   - // 将开始和结束日期之间的日期添加到数组中
438   - arr.push(dayjs(startDate).add(i, 'day').format("YYYY-MM-DD"))
439   - i++
440   - // 累加的日期小于结束日期时,继续下一次的循环
441   - } while (dayjs(startDate).add(i, 'day').isBefore(dayjs(endDate)))
442   - // 为了一次性修改数组,避免computed中多次触发,这里才用arr变量一次性赋值的方式,同时将最后一个日期添加近来
443   - arr.push(endDate)
444   - selected = arr
445   - } else {
446   - // 选择区间时,只有一个日期的情况下,且不允许选择起止为同一天的话,不允许选择自己
447   - if (selected[0] === date && !this.allowSameDay) return
448   - selected.push(date)
449   - }
450   - }
451   - }
452   - this.setSelected(selected)
453   - },
454   - // 设置默认日期
455   - setDefaultDate() {
456   - if (!this.defaultDate) {
457   - // 如果没有设置默认日期,则将当天日期设置为默认选中的日期
458   - const selected = [dayjs().format("YYYY-MM-DD")]
459   - return this.setSelected(selected, false)
460   - }
461   - let defaultDate = []
462   - const minDate = this.minDate || dayjs().format("YYYY-MM-DD")
463   - const maxDate = this.maxDate || dayjs(minDate).add(this.maxMonth - 1, 'month').format("YYYY-MM-DD")
464   - if (this.mode === 'single') {
465   - // 单选模式,可以是字符串或数组,Date对象等
466   - if (!test.array(this.defaultDate)) {
467   - defaultDate = [dayjs(this.defaultDate).format("YYYY-MM-DD")]
468   - } else {
469   - defaultDate = [this.defaultDate[0]]
470   - }
471   - } else {
472   - // 如果为非数组,则不执行
473   - if (!test.array(this.defaultDate)) return
474   - defaultDate = this.defaultDate
475   - }
476   - // 过滤用户传递的默认数组,取出只在可允许最大值与最小值之间的元素
477   - defaultDate = defaultDate.filter(item => {
478   - return dayjs(item).isAfter(dayjs(minDate).subtract(1, 'day')) && dayjs(item).isBefore(dayjs(
479   - maxDate).add(1, 'day'))
480   - })
481   - this.setSelected(defaultDate, false)
482   - },
483   - setSelected(selected, event = true) {
484   - this.selected = selected
485   - event && this.$emit('monthSelected', this.selected,'tap')
486   - }
487   - }
488   - }
489   -</script>
490   -
491   -<style lang="scss" scoped>
492   -
493   - .u-calendar-month-wrapper {
494   - margin-top: 4px;
495   - }
496   -
497   - .u-calendar-month {
498   -
499   - &__title {
500   - display: flex;
501   - flex-direction: column;
502   - font-size: 14px;
503   - line-height: 42px;
504   - height: 42px;
505   - color: $u-main-color;
506   - text-align: center;
507   - font-weight: bold;
508   - }
509   -
510   - &__days {
511   - position: relative;
512   - @include flex;
513   - flex-wrap: wrap;
514   -
515   - &__month-mark-wrapper {
516   - position: absolute;
517   - top: 0;
518   - bottom: 0;
519   - left: 0;
520   - right: 0;
521   - @include flex;
522   - justify-content: center;
523   - align-items: center;
524   -
525   - &__text {
526   - font-size: 155px;
527   - color: rgba(231, 232, 234, 0.83);
528   - }
529   - }
530   -
531   - &__day {
532   - @include flex;
533   - padding: 2px;
534   - /* #ifndef APP-NVUE */
535   - // vue下使用css进行宽度计算,因为某些安卓机会无法进行js获取父元素宽度进行计算得出,会有偏移
536   - width: calc(100% / 7);
537   - box-sizing: border-box;
538   - /* #endif */
539   -
540   - &__select {
541   - flex: 1;
542   - @include flex;
543   - align-items: center;
544   - justify-content: center;
545   - position: relative;
546   -
547   - &__dot {
548   - width: 7px;
549   - height: 7px;
550   - border-radius: 100px;
551   - background-color: $u-error;
552   - position: absolute;
553   - top: 12px;
554   - right: 7px;
555   - }
556   -
557   - &__buttom-info {
558   - color: $u-content-color;
559   - text-align: center;
560   - position: absolute;
561   - bottom: 5px;
562   - font-size: 10px;
563   - text-align: center;
564   - left: 0;
565   - right: 0;
566   -
567   - &--selected {
568   - color: #ffffff;
569   - }
570   -
571   - &--disabled {
572   - color: #cacbcd;
573   - }
574   - }
575   -
576   - &__info {
577   - text-align: center;
578   - font-size: 16px;
579   -
580   - &--selected {
581   - color: #ffffff;
582   - }
583   -
584   - &--disabled {
585   - color: #cacbcd;
586   - }
587   - }
588   -
589   - &--selected {
590   - background-color: $u-primary;
591   - @include flex;
592   - justify-content: center;
593   - align-items: center;
594   - flex: 1;
595   - border-radius: 3px;
596   - }
597   -
598   - &--range-selected {
599   - opacity: 0.3;
600   - border-radius: 0;
601   - }
602   -
603   - &--range-start-selected {
604   - border-top-right-radius: 0;
605   - border-bottom-right-radius: 0;
606   - }
607   -
608   - &--range-end-selected {
609   - border-top-left-radius: 0;
610   - border-bottom-left-radius: 0;
611   - }
612   - }
613   - }
614   - }
615   - }
616   -</style>
uni_modules/uview-plus/components/u-calendar/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -
4   -export const props = defineMixin({
5   - props: {
6   - // 日历顶部标题
7   - title: {
8   - type: String,
9   - default: () => defProps.calendar.title
10   - },
11   - // 是否显示标题
12   - showTitle: {
13   - type: Boolean,
14   - default: () => defProps.calendar.showTitle
15   - },
16   - // 是否显示副标题
17   - showSubtitle: {
18   - type: Boolean,
19   - default: () => defProps.calendar.showSubtitle
20   - },
21   - // 日期类型选择,single-选择单个日期,multiple-可以选择多个日期,range-选择日期范围
22   - mode: {
23   - type: String,
24   - default: () => defProps.calendar.mode
25   - },
26   - // mode=range时,第一个日期底部的提示文字
27   - startText: {
28   - type: String,
29   - default: () => defProps.calendar.startText
30   - },
31   - // mode=range时,最后一个日期底部的提示文字
32   - endText: {
33   - type: String,
34   - default: () => defProps.calendar.endText
35   - },
36   - // 自定义列表
37   - customList: {
38   - type: Array,
39   - default: () => defProps.calendar.customList
40   - },
41   - // 主题色,对底部按钮和选中日期有效
42   - color: {
43   - type: String,
44   - default: () => defProps.calendar.color
45   - },
46   - // 最小的可选日期
47   - minDate: {
48   - type: [String, Number],
49   - default: () => defProps.calendar.minDate
50   - },
51   - // 最大可选日期
52   - maxDate: {
53   - type: [String, Number],
54   - default: () => defProps.calendar.maxDate
55   - },
56   - // 默认选中的日期,mode为multiple或range是必须为数组格式
57   - defaultDate: {
58   - type: [Array, String, Date, null],
59   - default: () => defProps.calendar.defaultDate
60   - },
61   - // mode=multiple时,最多可选多少个日期
62   - maxCount: {
63   - type: [String, Number],
64   - default: () => defProps.calendar.maxCount
65   - },
66   - // 日期行高
67   - rowHeight: {
68   - type: [String, Number],
69   - default: () => defProps.calendar.rowHeight
70   - },
71   - // 日期格式化函数
72   - formatter: {
73   - type: [Function, null],
74   - default: () => defProps.calendar.formatter
75   - },
76   - // 是否显示农历
77   - showLunar: {
78   - type: Boolean,
79   - default: () => defProps.calendar.showLunar
80   - },
81   - // 是否显示月份背景色
82   - showMark: {
83   - type: Boolean,
84   - default: () => defProps.calendar.showMark
85   - },
86   - // 确定按钮的文字
87   - confirmText: {
88   - type: String,
89   - default: () => defProps.calendar.confirmText
90   - },
91   - // 确认按钮处于禁用状态时的文字
92   - confirmDisabledText: {
93   - type: String,
94   - default: () => defProps.calendar.confirmDisabledText
95   - },
96   - // 是否显示日历弹窗
97   - show: {
98   - type: Boolean,
99   - default: () => defProps.calendar.show
100   - },
101   - // 是否允许点击遮罩关闭日历
102   - closeOnClickOverlay: {
103   - type: Boolean,
104   - default: () => defProps.calendar.closeOnClickOverlay
105   - },
106   - // 是否为只读状态,只读状态下禁止选择日期
107   - readonly: {
108   - type: Boolean,
109   - default: () => defProps.calendar.readonly
110   - },
111   - // 是否展示确认按钮
112   - showConfirm: {
113   - type: Boolean,
114   - default: () => defProps.calendar.showConfirm
115   - },
116   - // 日期区间最多可选天数,默认无限制,mode = range时有效
117   - maxRange: {
118   - type: [Number, String],
119   - default: () => defProps.calendar.maxRange
120   - },
121   - // 范围选择超过最多可选天数时的提示文案,mode = range时有效
122   - rangePrompt: {
123   - type: String,
124   - default: () => defProps.calendar.rangePrompt
125   - },
126   - // 范围选择超过最多可选天数时,是否展示提示文案,mode = range时有效
127   - showRangePrompt: {
128   - type: Boolean,
129   - default: () => defProps.calendar.showRangePrompt
130   - },
131   - // 是否允许日期范围的起止时间为同一天,mode = range时有效
132   - allowSameDay: {
133   - type: Boolean,
134   - default: () => defProps.calendar.allowSameDay
135   - },
136   - // 圆角值
137   - round: {
138   - type: [Boolean, String, Number],
139   - default: () => defProps.calendar.round
140   - },
141   - // 最多展示月份数量
142   - monthNum: {
143   - type: [Number, String],
144   - default: 3
145   - },
146   - // 星期文案
147   - weekText: {
148   - type: Array,
149   - default: defProps.calendar.weekText
150   - },
151   - forbidDays: {
152   - type: Array,
153   - default: defProps.calendar.forbidDays
154   - },
155   - forbidDaysToast:{
156   - type: String,
157   - default: defProps.calendar.forbidDaysToast
158   - },
159   - monthFormat:{
160   - type: String,
161   - default: defProps.calendar.monthFormat
162   - },
163   - // 是否页面内展示
164   - pageInline:{
165   - type: Boolean,
166   - default: defProps.calendar.pageInline
167   - }
168   - }
169   -})
uni_modules/uview-plus/components/u-calendar/u-calendar.vue deleted
1   -<template>
2   - <u-popup
3   - :show="show"
4   - mode="bottom"
5   - :closeable="!pageInline"
6   - @close="close"
7   - :round="round"
8   - :pageInline="pageInline"
9   - :closeOnClickOverlay="closeOnClickOverlay"
10   - >
11   - <view class="u-calendar">
12   - <uHeader
13   - :title="title"
14   - :subtitle="subtitle"
15   - :showSubtitle="showSubtitle"
16   - :showTitle="showTitle"
17   - :weekText="weekText"
18   - ></uHeader>
19   - <scroll-view
20   - :style="{
21   - height: addUnit(listHeight, 'px')
22   - }"
23   - scroll-y
24   - @scroll="onScroll"
25   - :scroll-top="scrollTop"
26   - :scrollIntoView="scrollIntoView"
27   - >
28   - <uMonth
29   - :color="color"
30   - :rowHeight="rowHeight"
31   - :showMark="showMark"
32   - :months="months"
33   - :mode="mode"
34   - :maxCount="maxCount"
35   - :startText="startText"
36   - :endText="endText"
37   - :defaultDate="defaultDate"
38   - :minDate="innerMinDate"
39   - :maxDate="innerMaxDate"
40   - :maxMonth="monthNum"
41   - :readonly="readonly"
42   - :maxRange="maxRange"
43   - :rangePrompt="rangePrompt"
44   - :showRangePrompt="showRangePrompt"
45   - :allowSameDay="allowSameDay"
46   - :forbidDays="forbidDays"
47   - :forbidDaysToast="forbidDaysToast"
48   - :monthFormat="monthFormat"
49   - ref="month"
50   - @monthSelected="monthSelected"
51   - @updateMonthTop="updateMonthTop"
52   - ></uMonth>
53   - </scroll-view>
54   - <slot name="footer" v-if="showConfirm">
55   - <view class="u-calendar__confirm">
56   - <u-button
57   - shape="circle"
58   - :text="
59   - buttonDisabled ? confirmDisabledText : confirmText
60   - "
61   - :color="color"
62   - @click="confirm"
63   - :disabled="buttonDisabled"
64   - ></u-button>
65   - </view>
66   - </slot>
67   - </view>
68   - </u-popup>
69   -</template>
70   -
71   -<script>
72   -import uHeader from './header.vue'
73   -import uMonth from './month.vue'
74   -import { props } from './props.js'
75   -import util from './util.js'
76   -import dayjs from '../u-datetime-picker/dayjs.esm.min.js';
77   -import Calendar from '../../libs/util/calendar.js'
78   -import { mpMixin } from '../../libs/mixin/mpMixin.js'
79   -import { mixin } from '../../libs/mixin/mixin.js'
80   -import { addUnit, getPx, range, error, padZero } from '../../libs/function/index';
81   -import test from '../../libs/function/test';
82   -/**
83   - * Calendar 日历
84   - * @description 此组件用于单个选择日期,范围选择日期等,日历被包裹在底部弹起的容器中.
85   - * @tutorial https://uview-plus.jiangruyi.com/components/calendar.html
86   - *
87   - * @property {String} title 标题内容 (默认 日期选择 )
88   - * @property {Boolean} showTitle 是否显示标题 (默认 true )
89   - * @property {Boolean} showSubtitle 是否显示副标题 (默认 true )
90   - * @property {String} mode 日期类型选择 single-选择单个日期,multiple-可以选择多个日期,range-选择日期范围 ( 默认 'single' )
91   - * @property {String} startText mode=range时,第一个日期底部的提示文字 (默认 '开始' )
92   - * @property {String} endText mode=range时,最后一个日期底部的提示文字 (默认 '结束' )
93   - * @property {Array} customList 自定义列表
94   - * @property {String} color 主题色,对底部按钮和选中日期有效 (默认 ‘#3c9cff' )
95   - * @property {String | Number} minDate 最小的可选日期 (默认 0 )
96   - * @property {String | Number} maxDate 最大可选日期 (默认 0 )
97   - * @property {Array | String| Date} defaultDate 默认选中的日期,mode为multiple或range是必须为数组格式
98   - * @property {String | Number} maxCount mode=multiple时,最多可选多少个日期 (默认 Number.MAX_SAFE_INTEGER )
99   - * @property {String | Number} rowHeight 日期行高 (默认 56 )
100   - * @property {Function} formatter 日期格式化函数
101   - * @property {Boolean} showLunar 是否显示农历 (默认 false )
102   - * @property {Boolean} showMark 是否显示月份背景色 (默认 true )
103   - * @property {String} confirmText 确定按钮的文字 (默认 '确定' )
104   - * @property {String} confirmDisabledText 确认按钮处于禁用状态时的文字 (默认 '确定' )
105   - * @property {Boolean} show 是否显示日历弹窗 (默认 false )
106   - * @property {Boolean} closeOnClickOverlay 是否允许点击遮罩关闭日历 (默认 false )
107   - * @property {Boolean} readonly 是否为只读状态,只读状态下禁止选择日期 (默认 false )
108   - * @property {String | Number} maxRange 日期区间最多可选天数,默认无限制,mode = range时有效
109   - * @property {String} rangePrompt 范围选择超过最多可选天数时的提示文案,mode = range时有效
110   - * @property {Boolean} showRangePrompt 范围选择超过最多可选天数时,是否展示提示文案,mode = range时有效 (默认 true )
111   - * @property {Boolean} allowSameDay 是否允许日期范围的起止时间为同一天,mode = range时有效 (默认 false )
112   - * @property {Number|String} round 圆角值,默认无圆角 (默认 0 )
113   - * @property {Number|String} monthNum 最多展示的月份数量 (默认 3 )
114   - * @property {Array} weekText 星期文案 (默认 ['一', '二', '三', '四', '五', '六', '日'] )
115   - *
116   - * @event {Function()} confirm 点击确定按钮时触发 选择日期相关的返回参数
117   - * @event {Function()} close 日历关闭时触发 可定义页面关闭时的回调事件
118   - * @example <u-calendar :defaultDate="defaultDateMultiple" :show="show" mode="multiple" @confirm="confirm">
119   - </u-calendar>
120   - * */
121   -export default {
122   - name: 'u-calendar',
123   - mixins: [mpMixin, mixin, props],
124   - components: {
125   - uHeader,
126   - uMonth
127   - },
128   - data() {
129   - return {
130   - // 需要显示的月份的数组
131   - months: [],
132   - // 在月份滚动区域中,当前视图中月份的index索引
133   - monthIndex: 0,
134   - // 月份滚动区域的高度
135   - listHeight: 0,
136   - // month组件中选择的日期数组
137   - selected: [],
138   - scrollIntoView: '',
139   - scrollIntoViewScroll: '',
140   - scrollTop:0,
141   - // 过滤处理方法
142   - innerFormatter: (value) => value
143   - }
144   - },
145   - watch: {
146   - scrollIntoView: {
147   - immediate: true,
148   - handler(n) {
149   - // console.log('scrollIntoView', n)
150   - }
151   - },
152   - selectedChange: {
153   - immediate: true,
154   - handler(n) {
155   - this.setMonth()
156   - }
157   - },
158   - // 打开弹窗时,设置月份数据
159   - show: {
160   - immediate: true,
161   - handler(n) {
162   - if (n) {
163   - this.setMonth()
164   - } else {
165   - // 关闭时重置scrollIntoView,否则会出现二次打开日历,当前月份数据显示不正确。
166   - // scrollIntoView需要有一个值变动过程,才会产生作用。
167   - this.scrollIntoView = ''
168   - }
169   - }
170   - }
171   - },
172   - computed: {
173   - // 由于maxDate和minDate可以为字符串(2021-10-10),或者数值(时间戳),但是dayjs如果接受字符串形式的时间戳会有问题,这里进行处理
174   - innerMaxDate() {
175   - return test.number(this.maxDate)
176   - ? Number(this.maxDate)
177   - : this.maxDate
178   - },
179   - innerMinDate() {
180   - return test.number(this.minDate)
181   - ? Number(this.minDate)
182   - : this.minDate
183   - },
184   - // 多个条件的变化,会引起选中日期的变化,这里统一管理监听
185   - selectedChange() {
186   - return [this.innerMinDate, this.innerMaxDate, this.defaultDate]
187   - },
188   - subtitle() {
189   - // 初始化时,this.months为空数组,所以需要特别判断处理
190   - if (this.months.length) {
191   - if (uni.getLocale() == 'zh-Hans' || uni.getLocale() == 'zh-Hant') {
192   - return this.months[this.monthIndex].year + '年' + (this.months[this.monthIndex].month < 10 ? '0' + this.months[this.monthIndex].month : this.months[this.monthIndex].month) + '月'
193   - } else {
194   - return (this.months[this.monthIndex].month < 10 ? '0' + this.months[this.monthIndex].month : this.months[this.monthIndex].month) + '/' + this.months[this.monthIndex].year
195   - }
196   - } else {
197   - return ''
198   - }
199   - },
200   - buttonDisabled() {
201   - // 如果为range类型,且选择的日期个数不足1个时,让底部的按钮出于disabled状态
202   - if (this.mode === 'range') {
203   - if (this.selected.length <= 1) {
204   - return true
205   - } else {
206   - return false
207   - }
208   - } else {
209   - return false
210   - }
211   - }
212   - },
213   - mounted() {
214   - this.start = Date.now()
215   - this.init()
216   - },
217   - emits: ["confirm", "close"],
218   - methods: {
219   - addUnit,
220   - // 在微信小程序中,不支持将函数当做props参数,故只能通过ref形式调用
221   - setFormatter(e) {
222   - this.innerFormatter = e
223   - },
224   - // month组件内部选择日期后,通过事件通知给父组件
225   - monthSelected(e,scene ='init') {
226   - this.selected = e
227   - if (!this.showConfirm) {
228   - // 在不需要确认按钮的情况下,如果为单选,或者范围多选且已选长度大于2,则直接进行返还
229   - if (
230   - this.mode === 'multiple' ||
231   - this.mode === 'single' ||
232   - (this.mode === 'range' && this.selected.length >= 2)
233   - ) {
234   - if( scene === 'init'){
235   - return
236   - }
237   - if( scene === 'tap') {
238   - this.$emit('confirm', this.selected)
239   - }
240   - }
241   - }
242   - },
243   - init() {
244   - // 校验maxDate,不能小于minDate。
245   - if (
246   - this.innerMaxDate &&
247   - this.innerMinDate &&
248   - new Date(this.innerMaxDate).getTime() < new Date(this.innerMinDate).getTime()
249   - ) {
250   - return error('maxDate不能小于minDate时间')
251   - }
252   - // 滚动区域的高度
253   - let bottomPadding = 0;
254   - if (this.pageInline) {
255   - bottomPadding = 0
256   - } else {
257   - bottomPadding = 30
258   - }
259   - this.listHeight = this.rowHeight * 5 + bottomPadding
260   - this.setMonth()
261   - },
262   - close() {
263   - this.$emit('close')
264   - },
265   - // 点击确定按钮
266   - confirm() {
267   - if (!this.buttonDisabled) {
268   - this.$emit('confirm', this.selected)
269   - }
270   - },
271   - // 获得两个日期之间的月份数
272   - getMonths(minDate, maxDate) {
273   - const minYear = dayjs(minDate).year()
274   - const minMonth = dayjs(minDate).month() + 1
275   - const maxYear = dayjs(maxDate).year()
276   - const maxMonth = dayjs(maxDate).month() + 1
277   - return (maxYear - minYear) * 12 + (maxMonth - minMonth) + 1
278   - },
279   - // 设置月份数据
280   - setMonth() {
281   - // 最小日期的毫秒数
282   - const minDate = this.innerMinDate || dayjs().valueOf()
283   - // 如果没有指定最大日期,则往后推3个月
284   - const maxDate =
285   - this.innerMaxDate ||
286   - dayjs(minDate)
287   - .add(this.monthNum - 1, 'month')
288   - .valueOf()
289   - // 最大最小月份之间的共有多少个月份,
290   - const months = range(
291   - 1,
292   - this.monthNum,
293   - this.getMonths(minDate, maxDate)
294   - )
295   - // 先清空数组
296   - this.months = []
297   - for (let i = 0; i < months; i++) {
298   - this.months.push({
299   - date: new Array(
300   - dayjs(minDate).add(i, 'month').daysInMonth()
301   - )
302   - .fill(1)
303   - .map((item, index) => {
304   - // 日期,取值1-31
305   - let day = index + 1
306   - // 星期,0-6,0为周日
307   - const week = dayjs(minDate)
308   - .add(i, 'month')
309   - .date(day)
310   - .day()
311   - const date = dayjs(minDate)
312   - .add(i, 'month')
313   - .date(day)
314   - .format('YYYY-MM-DD')
315   - let bottomInfo = ''
316   - if (this.showLunar) {
317   - // 将日期转为农历格式
318   - const lunar = Calendar.solar2lunar(
319   - dayjs(date).year(),
320   - dayjs(date).month() + 1,
321   - dayjs(date).date()
322   - )
323   - bottomInfo = lunar.IDayCn
324   - }
325   - let config = {
326   - day,
327   - week,
328   - // 小于最小允许的日期,或者大于最大的日期,则设置为disabled状态
329   - disabled:
330   - dayjs(date).isBefore(
331   - dayjs(minDate).format('YYYY-MM-DD')
332   - ) ||
333   - dayjs(date).isAfter(
334   - dayjs(maxDate).format('YYYY-MM-DD')
335   - ),
336   - // 返回一个日期对象,供外部的formatter获取当前日期的年月日等信息,进行加工处理
337   - date: new Date(date),
338   - bottomInfo,
339   - dot: false,
340   - month:
341   - dayjs(minDate).add(i, 'month').month() + 1
342   - }
343   - const formatter =
344   - this.formatter || this.innerFormatter
345   - return formatter(config)
346   - }),
347   - // 当前所属的月份
348   - month: dayjs(minDate).add(i, 'month').month() + 1,
349   - // 当前年份
350   - year: dayjs(minDate).add(i, 'month').year()
351   - })
352   - }
353   - },
354   - // 滚动到默认设置的月份
355   - scrollIntoDefaultMonth(selected) {
356   - // 查询默认日期在可选列表的下标
357   - const _index = this.months.findIndex(({
358   - year,
359   - month
360   - }) => {
361   - month = padZero(month)
362   - return `${year}-${month}` === selected
363   - })
364   - if (_index !== -1) {
365   - // #ifndef MP-WEIXIN
366   - this.$nextTick(() => {
367   - this.scrollIntoView = `month-${_index}`
368   - this.scrollIntoViewScroll = this.scrollIntoView
369   - })
370   - // #endif
371   - // #ifdef MP-WEIXIN
372   - this.scrollTop = this.months[_index].top || 0;
373   - // #endif
374   - }
375   - },
376   - // scroll-view滚动监听
377   - onScroll(event) {
378   - // 不允许小于0的滚动值,如果scroll-view到顶了,继续下拉,会出现负数值
379   - const scrollTop = Math.max(0, event.detail.scrollTop)
380   - // 将当前滚动条数值,除以滚动区域的高度,可以得出当前滚动到了哪一个月份的索引
381   - for (let i = 0; i < this.months.length; i++) {
382   - if (scrollTop >= (this.months[i].top || this.listHeight)) {
383   - this.monthIndex = i
384   - this.scrollIntoViewScroll = `month-${i}`
385   - }
386   - }
387   - },
388   - // 更新月份的top值
389   - updateMonthTop(topArr = []) {
390   - // 设置对应月份的top值,用于onScroll方法更新月份
391   - topArr.map((item, index) => {
392   - this.months[index].top = item
393   - })
394   -
395   - // 获取默认日期的下标
396   - if (!this.defaultDate) {
397   - // 如果没有设置默认日期,则将当天日期设置为默认选中的日期
398   - const selected = dayjs().format("YYYY-MM")
399   - this.scrollIntoDefaultMonth(selected)
400   - return
401   - }
402   - let selected = dayjs().format("YYYY-MM");
403   - // 单选模式,可以是字符串或数组,Date对象等
404   - if (!test.array(this.defaultDate)) {
405   - selected = dayjs(this.defaultDate).format("YYYY-MM")
406   - } else {
407   - selected = dayjs(this.defaultDate[0]).format("YYYY-MM");
408   - }
409   - this.scrollIntoDefaultMonth(selected)
410   - }
411   - }
412   -}
413   -</script>
414   -
415   -<style lang="scss" scoped>
416   -.u-calendar {
417   - &__confirm {
418   - padding: 7px 18px;
419   - }
420   -}
421   -</style>
uni_modules/uview-plus/components/u-calendar/util.js deleted
1   -import dayjs from '../u-datetime-picker/dayjs.esm.min.js';
2   -export default {
3   - methods: {
4   - // 设置月份数据
5   - setMonth() {
6   - // 月初是周几
7   - const day = dayjs(this.date).date(1).day()
8   - const start = day == 0 ? 6 : day - 1
9   -
10   - // 本月天数
11   - const days = dayjs(this.date).endOf('month').format('D')
12   -
13   - // 上个月天数
14   - const prevDays = dayjs(this.date).endOf('month').subtract(1, 'month').format('D')
15   -
16   - // 日期数据
17   - const arr = []
18   - // 清空表格
19   - this.month = []
20   -
21   - // 添加上月数据
22   - arr.push(
23   - ...new Array(start).fill(1).map((e, i) => {
24   - const day = prevDays - start + i + 1
25   -
26   - return {
27   - value: day,
28   - disabled: true,
29   - date: dayjs(this.date).subtract(1, 'month').date(day).format('YYYY-MM-DD')
30   - }
31   - })
32   - )
33   -
34   - // 添加本月数据
35   - arr.push(
36   - ...new Array(days - 0).fill(1).map((e, i) => {
37   - const day = i + 1
38   -
39   - return {
40   - value: day,
41   - date: dayjs(this.date).date(day).format('YYYY-MM-DD')
42   - }
43   - })
44   - )
45   -
46   - // 添加下个月
47   - arr.push(
48   - ...new Array(42 - days - start).fill(1).map((e, i) => {
49   - const day = i + 1
50   -
51   - return {
52   - value: day,
53   - disabled: true,
54   - date: dayjs(this.date).add(1, 'month').date(day).format('YYYY-MM-DD')
55   - }
56   - })
57   - )
58   -
59   - // 分割数组
60   - for (let n = 0; n < arr.length; n += 7) {
61   - this.month.push(
62   - arr.slice(n, n + 7).map((e, i) => {
63   - e.index = i + n
64   -
65   - // 自定义信息
66   - const custom = this.customList.find((c) => c.date == e.date)
67   -
68   - // 农历
69   - if (this.lunar) {
70   - const {
71   - IDayCn,
72   - IMonthCn
73   - } = this.getLunar(e.date)
74   - e.lunar = IDayCn == '初一' ? IMonthCn : IDayCn
75   - }
76   -
77   - return {
78   - ...e,
79   - ...custom
80   - }
81   - })
82   - )
83   - }
84   - }
85   - }
86   -}
uni_modules/uview-plus/components/u-car-keyboard/carKeyboard.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:53:20
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/carKeyboard.js
9   - */
10   -export default {
11   - // 车牌号键盘
12   - carKeyboard: {
13   - random: false
14   - }
15   -}
uni_modules/uview-plus/components/u-car-keyboard/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -
4   -export const props = defineMixin({
5   - props: {
6   - // 是否打乱键盘按键的顺序
7   - random: {
8   - type: Boolean,
9   - default: false
10   - },
11   - // 输入一个中文后,是否自动切换到英文
12   - autoChange: {
13   - type: Boolean,
14   - default: false
15   - }
16   - }
17   -})
uni_modules/uview-plus/components/u-car-keyboard/u-car-keyboard.vue deleted
1   -<template>
2   - <view
3   - class="u-keyboard"
4   - @touchmove.stop.prevent="noop"
5   - >
6   - <view
7   - v-for="(group, i) in abc ? engKeyBoardList : areaList"
8   - :key="i"
9   - class="u-keyboard__button"
10   - :index="i"
11   - :class="[i + 1 === 4 && 'u-keyboard__button--center']"
12   - >
13   - <view
14   - v-if="i === 3"
15   - class="u-keyboard__button__inner-wrapper"
16   - >
17   - <view
18   - class="u-keyboard__button__inner-wrapper__left"
19   - hover-class="u-hover-class"
20   - :hover-stay-time="200"
21   - @tap="changeCarInputMode"
22   - >
23   - <text
24   - class="u-keyboard__button__inner-wrapper__left__lang"
25   - :class="[!abc && 'u-keyboard__button__inner-wrapper__left__lang--active']"
26   - >中</text>
27   - <text class="u-keyboard__button__inner-wrapper__left__line">/</text>
28   - <text
29   - class="u-keyboard__button__inner-wrapper__left__lang"
30   - :class="[abc && 'u-keyboard__button__inner-wrapper__left__lang--active']"
31   - >英</text>
32   - </view>
33   - </view>
34   - <view
35   - class="u-keyboard__button__inner-wrapper"
36   - v-for="(item, j) in group"
37   - :key="j"
38   - >
39   - <view
40   - class="u-keyboard__button__inner-wrapper__inner"
41   - :hover-stay-time="200"
42   - @tap="carInputClick(i, j)"
43   - hover-class="u-hover-class"
44   - >
45   - <text class="u-keyboard__button__inner-wrapper__inner__text">{{ item }}</text>
46   - </view>
47   - </view>
48   - <view
49   - v-if="i === 3"
50   - @touchstart="backspaceClick"
51   - @touchend="clearTimer"
52   - class="u-keyboard__button__inner-wrapper"
53   - >
54   - <view
55   - class="u-keyboard__button__inner-wrapper__right"
56   - hover-class="u-hover-class"
57   - :hover-stay-time="200"
58   - >
59   - <up-icon
60   - size="28"
61   - name="backspace"
62   - color="#303133"
63   - ></up-icon>
64   - </view>
65   - </view>
66   - </view>
67   - </view>
68   -</template>
69   -
70   -<script>
71   - import { props } from './props';
72   - import { mpMixin } from '../../libs/mixin/mpMixin';
73   - import { mixin } from '../../libs/mixin/mixin';
74   - import { randomArray, sleep } from '../../libs/function/index';
75   - /**
76   - * keyboard 键盘组件
77   - * @description 此为uview-plus自定义的键盘面板,内含了数字键盘,车牌号键,身份证号键盘3种模式,都有可以打乱按键顺序的选项。
78   - * @tutorial https://uview-plus.jiangruyi.com/components/keyboard.html
79   - * @property {Boolean} random 是否打乱键盘的顺序
80   - * @event {Function} change 点击键盘触发
81   - * @event {Function} backspace 点击退格键触发
82   - * @example <u-keyboard ref="uKeyboard" mode="car" v-model="show"></u-keyboard>
83   - */
84   - export default {
85   - name: "u-car-keyboard",
86   - mixins: [mpMixin, mixin, props],
87   - data() {
88   - return {
89   - // 车牌输入时,abc=true为输入车牌号码,bac=false为输入省份中文简称
90   - abc: false
91   - };
92   - },
93   - computed: {
94   - areaList() {
95   - let data = [
96   - '京',
97   - '沪',
98   - '粤',
99   - '津',
100   - '冀',
101   - '豫',
102   - '云',
103   - '辽',
104   - '黑',
105   - '湘',
106   - '皖',
107   - '鲁',
108   - '苏',
109   - '浙',
110   - '赣',
111   - '鄂',
112   - '桂',
113   - '甘',
114   - '晋',
115   - '陕',
116   - '蒙',
117   - '吉',
118   - '闽',
119   - '贵',
120   - '渝',
121   - '川',
122   - '青',
123   - '琼',
124   - '宁',
125   - '挂',
126   - '藏',
127   - '港',
128   - '澳',
129   - '新',
130   - '使',
131   - '学'
132   - ];
133   - let tmp = [];
134   - // 打乱顺序
135   - if (this.random) data = randomArray(data);
136   - // 切割成二维数组
137   - tmp[0] = data.slice(0, 10);
138   - tmp[1] = data.slice(10, 20);
139   - tmp[2] = data.slice(20, 30);
140   - tmp[3] = data.slice(30, 36);
141   - return tmp;
142   - },
143   - engKeyBoardList() {
144   - let data = [
145   - 1,
146   - 2,
147   - 3,
148   - 4,
149   - 5,
150   - 6,
151   - 7,
152   - 8,
153   - 9,
154   - 0,
155   - 'Q',
156   - 'W',
157   - 'E',
158   - 'R',
159   - 'T',
160   - 'Y',
161   - 'U',
162   - 'I',
163   - 'O',
164   - 'P',
165   - 'A',
166   - 'S',
167   - 'D',
168   - 'F',
169   - 'G',
170   - 'H',
171   - 'J',
172   - 'K',
173   - 'L',
174   - 'Z',
175   - 'X',
176   - 'C',
177   - 'V',
178   - 'B',
179   - 'N',
180   - 'M'
181   - ];
182   - let tmp = [];
183   - if (this.random) data = randomArray(data);
184   - tmp[0] = data.slice(0, 10);
185   - tmp[1] = data.slice(10, 20);
186   - tmp[2] = data.slice(20, 30);
187   - tmp[3] = data.slice(30, 36);
188   - return tmp;
189   - }
190   - },
191   - emits: ["change", "backspace"],
192   - methods: {
193   - // 点击键盘按钮
194   - carInputClick(i, j) {
195   - let value = '';
196   - // 不同模式,获取不同数组的值
197   - if (this.abc) value = this.engKeyBoardList[i][j];
198   - else value = this.areaList[i][j];
199   - // 如果允许自动切换,则将中文状态切换为英文
200   - if (!this.abc && this.autoChange) sleep(200).then(() => this.abc = true)
201   - this.$emit('change', value);
202   - },
203   - // 修改汽车牌键盘的输入模式,中文|英文
204   - changeCarInputMode() {
205   - this.abc = !this.abc;
206   - },
207   - // 点击退格键
208   - backspaceClick() {
209   - this.$emit('backspace');
210   - clearInterval(this.timer); //再次清空定时器,防止重复注册定时器
211   - this.timer = null;
212   - this.timer = setInterval(() => {
213   - this.$emit('backspace');
214   - }, 250);
215   - },
216   - clearTimer() {
217   - clearInterval(this.timer);
218   - this.timer = null;
219   - },
220   - }
221   - };
222   -</script>
223   -
224   -<style lang="scss" scoped>
225   - $u-car-keyboard-background-color: rgb(224, 228, 230) !default;
226   - $u-car-keyboard-padding:6px 0 6px !default;
227   - $u-car-keyboard-button-inner-width:64rpx !default;
228   - $u-car-keyboard-button-inner-background-color:#FFFFFF !default;
229   - $u-car-keyboard-button-height:80rpx !default;
230   - $u-car-keyboard-button-inner-box-shadow:0 1px 0px #999992 !default;
231   - $u-car-keyboard-button-border-radius:4px !default;
232   - $u-car-keyboard-button-inner-margin:8rpx 5rpx !default;
233   - $u-car-keyboard-button-text-font-size:16px !default;
234   - $u-car-keyboard-button-text-color:$u-main-color !default;
235   - $u-car-keyboard-center-inner-margin: 0 4rpx !default;
236   - $u-car-keyboard-special-button-width:134rpx !default;
237   - $u-car-keyboard-lang-font-size:16px !default;
238   - $u-car-keyboard-lang-color:$u-main-color !default;
239   - $u-car-keyboard-active-color:$u-primary !default;
240   - $u-car-keyboard-line-font-size:15px !default;
241   - $u-car-keyboard-line-color:$u-main-color !default;
242   - $u-car-keyboard-line-margin:0 1px !default;
243   - $u-car-keyboard-u-hover-class-background-color:#BBBCC6 !default;
244   -
245   - .u-keyboard {
246   - @include flex(column);
247   - justify-content: space-around;
248   - background-color: $u-car-keyboard-background-color;
249   - align-items: stretch;
250   - padding: $u-car-keyboard-padding;
251   -
252   - &__button {
253   - @include flex;
254   - justify-content: center;
255   - flex: 1;
256   - /* #ifndef APP-NVUE */
257   - /* #endif */
258   -
259   - &__inner-wrapper {
260   - box-shadow: $u-car-keyboard-button-inner-box-shadow;
261   - margin: $u-car-keyboard-button-inner-margin;
262   - border-radius: $u-car-keyboard-button-border-radius;
263   -
264   - &__inner {
265   - @include flex;
266   - justify-content: center;
267   - align-items: center;
268   - width: $u-car-keyboard-button-inner-width;
269   - background-color: $u-car-keyboard-button-inner-background-color;
270   - height: $u-car-keyboard-button-height;
271   - border-radius: $u-car-keyboard-button-border-radius;
272   -
273   - &__text {
274   - font-size: $u-car-keyboard-button-text-font-size;
275   - color: $u-car-keyboard-button-text-color;
276   - }
277   - }
278   -
279   - &__left,
280   - &__right {
281   - border-radius: $u-car-keyboard-button-border-radius;
282   - width: $u-car-keyboard-special-button-width;
283   - height: $u-car-keyboard-button-height;
284   - background-color: $u-car-keyboard-u-hover-class-background-color;
285   - @include flex;
286   - justify-content: center;
287   - align-items: center;
288   - box-shadow: $u-car-keyboard-button-inner-box-shadow;
289   - }
290   -
291   - &__left {
292   - &__line {
293   - font-size: $u-car-keyboard-line-font-size;
294   - color: $u-car-keyboard-line-color;
295   - margin: $u-car-keyboard-line-margin;
296   - }
297   -
298   - &__lang {
299   - font-size: $u-car-keyboard-lang-font-size;
300   - color: $u-car-keyboard-lang-color;
301   -
302   - &--active {
303   - color: $u-car-keyboard-active-color;
304   - }
305   - }
306   - }
307   - }
308   - }
309   - }
310   -
311   - .u-hover-class {
312   - background-color: $u-car-keyboard-u-hover-class-background-color;
313   - }
314   -</style>
uni_modules/uview-plus/components/u-card/card.js deleted
1   -/*
2   - * @Author : jry
3   - * @Description :
4   - * @version : 3.0
5   - * @Date : 2025-04-26 16:37:21
6   - * @LastAuthor : jry
7   - * @lastTime : 2025-04-26 16:37:21
8   - * @FilePath : /uview-plus/libs/config/props/card.js
9   - */
10   -export default {
11   - // card组件的props
12   - card: {
13   - full: false,
14   - title: '',
15   - titleColor: '#303133',
16   - titleSize: '15px',
17   - subTitle: '',
18   - subTitleColor: '#909399',
19   - subTitleSize: '13px',
20   - border: true,
21   - index: '',
22   - margin: '15px',
23   - borderRadius: '8px',
24   - headStyle: {},
25   - bodyStyle: {},
26   - footStyle: {},
27   - headBorderBottom: true,
28   - footBorderTop: true,
29   - thumb: '',
30   - thumbWidth: '30px',
31   - thumbCircle: false,
32   - padding: '15px',
33   - paddingHead: '',
34   - paddingBody: '',
35   - paddingFoot: '',
36   - showHead: true,
37   - showFoot: true,
38   - boxShadow: 'none'
39   - }
40   -}
uni_modules/uview-plus/components/u-card/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -
4   -export const propsCard = defineMixin({
5   - props: {
6   - // 与屏幕两侧是否留空隙
7   - full: {
8   - type: Boolean,
9   - default: () => defProps.card.full
10   - },
11   - // 标题
12   - title: {
13   - type: String,
14   - default: () => defProps.card.title
15   - },
16   - // 标题颜色
17   - titleColor: {
18   - type: String,
19   - default: () => defProps.card.titleColor
20   - },
21   - // 标题字体大小
22   - titleSize: {
23   - type: [Number, String],
24   - default: () => defProps.card.titleSize
25   - },
26   - // 副标题
27   - subTitle: {
28   - type: String,
29   - default: () => defProps.card.subTitle
30   - },
31   - // 副标题颜色
32   - subTitleColor: {
33   - type: String,
34   - default: () => defProps.card.subTitleColor
35   - },
36   - // 副标题字体大小
37   - subTitleSize: {
38   - type: [Number, String],
39   - default: () => defProps.card.subTitleSize
40   - },
41   - // 是否显示外部边框,只对full=false时有效(卡片与边框有空隙时)
42   - border: {
43   - type: Boolean,
44   - default: () => defProps.card.border
45   - },
46   - // 用于标识点击了第几个
47   - index: {
48   - type: [Number, String, Object],
49   - default: () => defProps.card.index
50   - },
51   - // 用于隔开上下左右的边距,带单位的写法,如:"30px 30px","20px 20px 30px 30px"
52   - margin: {
53   - type: String,
54   - default: () => defProps.card.margin
55   - },
56   - // card卡片的圆角
57   - borderRadius: {
58   - type: [Number, String],
59   - default: () => defProps.card.borderRadius
60   - },
61   - // 头部自定义样式,对象形式
62   - headStyle: {
63   - type: Object,
64   - default: () => defProps.card.headStyle
65   - },
66   - // 主体自定义样式,对象形式
67   - bodyStyle: {
68   - type: Object,
69   - default: () => defProps.card.bodyStyle
70   - },
71   - // 底部自定义样式,对象形式
72   - footStyle: {
73   - type: Object,
74   - default: () => defProps.card.footStyle
75   - },
76   - // 头部是否下边框
77   - headBorderBottom: {
78   - type: Boolean,
79   - default: () => defProps.card.headBorderBottom
80   - },
81   - // 底部是否有上边框
82   - footBorderTop: {
83   - type: Boolean,
84   - default: () => defProps.card.footBorderTop
85   - },
86   - // 标题左边的缩略图
87   - thumb: {
88   - type: String,
89   - default: () => defProps.card.thumb
90   - },
91   - // 缩略图宽高
92   - thumbWidth: {
93   - type: [String, Number],
94   - default: () => defProps.card.thumbWidth
95   - },
96   - // 缩略图是否为圆形
97   - thumbCircle: {
98   - type: Boolean,
99   - default: () => defProps.card.thumbCircle
100   - },
101   - // 给head,body,foot的内边距
102   - padding: {
103   - type: [String, Number],
104   - default: () => defProps.card.padding
105   - },
106   - paddingHead: {
107   - type: [String, Number],
108   - default: () => defProps.card.paddingHead
109   - },
110   - paddingBody: {
111   - type: [String, Number],
112   - default: () => defProps.card.paddingBody
113   - },
114   - paddingFoot: {
115   - type: [String, Number],
116   - default: () => defProps.card.paddingFoot
117   - },
118   - // 是否显示头部
119   - showHead: {
120   - type: Boolean,
121   - default: () => defProps.card.showHead
122   - },
123   - // 是否显示尾部
124   - showFoot: {
125   - type: Boolean,
126   - default: () => defProps.card.showFoot
127   - },
128   - // 卡片外围阴影,字符串形式
129   - boxShadow: {
130   - type: String,
131   - default: () => defProps.card.boxShadow
132   - }
133   - }
134   -})
uni_modules/uview-plus/components/u-card/u-card.vue deleted
1   -<template>
2   - <view
3   - class="u-card"
4   - @tap.stop="click"
5   - :class="{ 'u-border': border, 'u-card-full': full, 'u-card--border': getPx(borderRadius) > 0 }"
6   - :style="{
7   - borderRadius: addUnit(borderRadius),
8   - margin: margin,
9   - boxShadow: boxShadow
10   - }"
11   - >
12   - <view
13   - v-if="showHead"
14   - class="u-card__head"
15   - :style="[{padding: addUnit(paddingHead || padding)}, headStyle]"
16   - :class="{
17   - 'u-border-bottom': headBorderBottom
18   - }"
19   - @tap="headClick"
20   - >
21   - <view v-if="!$slots.head" class="u-flex u-flex-between">
22   - <view class="u-card__head--left u-flex u-line-1" v-if="title">
23   - <image
24   - :src="thumb"
25   - class="u-card__head--left__thumb"
26   - mode="aspectFill"
27   - v-if="thumb"
28   - :style="{
29   - height: addUnit(thumbWidth),
30   - width: addUnit(thumbWidth),
31   - borderRadius: thumbCircle ? '50px' : '4px'
32   - }"
33   - ></image>
34   - <text
35   - class="u-card__head--left__title u-line-1"
36   - :style="{
37   - fontSize: addUnit(titleSize),
38   - color: titleColor
39   - }"
40   - >
41   - {{ title }}
42   - </text>
43   - </view>
44   - <view class="u-card__head--right u-line-1" v-if="subTitle">
45   - <text
46   - class="u-card__head__title__text"
47   - :style="{
48   - fontSize: addUnit(subTitleSize),
49   - color: subTitleColor
50   - }"
51   - >
52   - {{ subTitle }}
53   - </text>
54   - </view>
55   - </view>
56   - <slot name="head" v-else />
57   - </view>
58   - <view @tap="bodyClick" class="u-card__body"
59   - :style="[{padding: addUnit(paddingBody || padding)}, bodyStyle]"><slot name="body" /></view>
60   - <view
61   - v-if="showFoot"
62   - class="u-card__foot"
63   - @tap="footClick"
64   - :style="[{padding: $slots.foot ? addUnit(paddingFoot || padding) : 0}, footStyle]"
65   - :class="{
66   - 'u-border-top': footBorderTop
67   - }"
68   - >
69   - <slot name="foot" />
70   - </view>
71   - </view>
72   -</template>
73   -
74   -<script>
75   - import { propsCard } from './props';
76   - import { mpMixin } from '../../libs/mixin/mpMixin';
77   - import { mixin } from '../../libs/mixin/mixin';
78   - import { addStyle, addUnit, getPx } from '../../libs/function/index';
79   - /**
80   - * card 卡片
81   - * @description 卡片组件一般用于多个列表条目,且风格统一的场景
82   - * @tutorial https://uview-plus.jiangruyi.com/components/card.html
83   - * @property {Boolean} full 卡片与屏幕两侧是否留空隙(默认false)
84   - * @property {String} title 头部左边的标题
85   - * @property {String} title-color 标题颜色(默认#303133)
86   - * @property {String | Number} title-size 标题字体大小,单位rpx(默认15px)
87   - * @property {String} sub-title 头部右边的副标题
88   - * @property {String} sub-title-color 副标题颜色(默认#909399)
89   - * @property {String | Number} sub-title-size 副标题字体大小(默认13px
90   - * @property {Boolean} border 是否显示边框(默认true)
91   - * @property {String | Number} index 用于标识点击了第几个卡片
92   - * @property {String} box-shadow 卡片外围阴影,字符串形式(默认none)
93   - * @property {String} margin 卡片与屏幕两边和上下元素的间距,需带单位,如"30px 20px"(默认15px)
94   - * @property {String | Number} border-radius 卡片整体的圆角值,单位rpx(默认8px)
95   - * @property {Object} head-style 头部自定义样式,对象形式
96   - * @property {Object} body-style 中部自定义样式,对象形式
97   - * @property {Object} foot-style 底部自定义样式,对象形式
98   - * @property {Boolean} head-border-bottom 是否显示头部的下边框(默认true)
99   - * @property {Boolean} foot-border-top 是否显示底部的上边框(默认true)
100   - * @property {Boolean} show-head 是否显示头部(默认true)
101   - * @property {Boolean} show-foot 是否显示尾部(默认true)
102   - * @property {String} thumb 缩略图路径,如设置将显示在标题的左边,不建议使用相对路径
103   - * @property {String | Number} thumb-width 缩略图的宽度,高等于宽,单位px(默认30px)
104   - * @property {Boolean} thumb-circle 缩略图是否为圆形(默认false)
105   - * @event {Function} click 整个卡片任意位置被点击时触发
106   - * @event {Function} head-click 卡片头部被点击时触发
107   - * @event {Function} body-click 卡片主体部分被点击时触发
108   - * @event {Function} foot-click 卡片底部部分被点击时触发
109   - * @example <u-card paddingFoot="2px 15px" title="card"></u-card>
110   - */
111   - export default {
112   - name: 'up-card',
113   - data() {
114   - return {};
115   - },
116   - mixins: [mpMixin, mixin, propsCard],
117   - emits: ['click', 'head-click', 'body-click', 'foot-click'],
118   - methods: {
119   - addStyle,
120   - addUnit,
121   - getPx,
122   - click() {
123   - this.$emit('click', this.index);
124   - },
125   - headClick() {
126   - this.$emit('head-click', this.index);
127   - },
128   - bodyClick() {
129   - this.$emit('body-click', this.index);
130   - },
131   - footClick() {
132   - this.$emit('foot-click', this.index);
133   - }
134   - }
135   - };
136   -</script>
137   -
138   -<style lang="scss" scoped>
139   -.u-card {
140   - position: relative;
141   - overflow: hidden;
142   - font-size: 28rpx;
143   - background-color: #ffffff;
144   - box-sizing: border-box;
145   -
146   - &-full {
147   - // 如果是与屏幕之间不留空隙,应该设置左右边距为0
148   - margin-left: 0 !important;
149   - margin-right: 0 !important;
150   - width: 100%;
151   - }
152   -
153   - &--border:after {
154   - border-radius: 16rpx;
155   - }
156   -
157   - &__head {
158   - &--left {
159   - color: $u-main-color;
160   -
161   - &__thumb {
162   - margin-right: 16rpx;
163   - }
164   -
165   - &__title {
166   - max-width: 400rpx;
167   - }
168   - }
169   -
170   - &--right {
171   - color: $u-tips-color;
172   - margin-left: 6rpx;
173   - }
174   - }
175   -
176   - &__body {
177   - color: $u-content-color;
178   - }
179   -
180   - &__foot {
181   - color: $u-tips-color;
182   - }
183   -}
184   -</style>
uni_modules/uview-plus/components/u-cascader/u-cascader.vue deleted
1   -<template>
2   - <up-popup :show="popupShow" mode="bottom" :popup="false"
3   - :mask="true" :closeable="true" :safe-area-inset-bottom="true"
4   - close-icon-color="#ffffff" :z-index="uZIndex"
5   - :maskCloseAble="maskCloseAble" @close="close">
6   - <view class="up-p-t-30 up-p-l-20 up-m-b-10" v-if="headerDirection =='column'">
7   - <up-steps v-if="popupShow" dot direction="column" v-model:current="tabsIndex">
8   - <up-steps-item v-for="(item, index) in genTabsList"
9   - @click="tabsIndex = index" :title="item.name"></up-steps-item>
10   - </up-steps>
11   - </view>
12   - <view class="up-p-t-20 up-m-b-10" v-else>
13   - <up-tabs v-if="popupShow" :list="genTabsList"
14   - :scrollable="true" v-model:current="tabsIndex" @change="tabsChange" ref="tabs"></up-tabs>
15   - </view>
16   - <view class="area-box">
17   - <view class="u-flex" :class="{ 'change':isChange }"
18   - :style="{transform: optionsCols == 2 && isChange ? 'translateX(-33.3333333%)' : ''}">
19   - <template v-for="(levelData, levelIndex) in levelList" :key="levelIndex">
20   - <view v-if="optionsCols == 2 || levelIndex == tabsIndex" class="area-item"
21   - :style="{ width: optionsCols == 2 ? '33.33333%' : '750rpx'}">
22   - <view class="u-padding-10 u-bg-gray" style="height: 100%;">
23   - <scroll-view :scroll-y="true" style="height: 100%">
24   - <up-cell-group v-if="levelIndex === 0 || selectedValueIndexs[levelIndex - 1] !== undefined">
25   - <up-cell v-for="(item,index) in levelData"
26   - :title="item[labelKey]" :arrow="false"
27   - :index="index" :key="index"
28   - @click="levelChange(levelIndex, index)">
29   - <template v-slot:right-icon>
30   - <up-icon v-if="selectedValueIndexs[levelIndex] === index"
31   - size="17" name="checkbox-mark"></up-icon>
32   - </template>
33   - </up-cell>
34   - </up-cell-group>
35   - </scroll-view>
36   - </view>
37   - </view>
38   - </template>
39   - </view>
40   - </view>
41   - <!-- 添加按钮区域 -->
42   - <view class="u-cascader-action up-flex up-flex-between">
43   - <view class="u-padding-20 up-flex-fill">
44   - <up-button @click="handleCancel" type="default">{{ t("up.common.cancel") }}</up-button>
45   - </view>
46   - <view class="u-padding-20 up-flex-fill">
47   - <up-button @click="handleConfirm" type="primary">{{ t("up.common.confirm") }}</up-button>
48   - </view>
49   - </view>
50   - </up-popup>
51   -</template>
52   -
53   -<script>
54   - /**
55   - * u-cascader 通用无限级联选择器
56   - * @property {String Number} z-index 弹出时的z-index值(默认1075)
57   - * @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭Picker(默认true)
58   - * @property {Array} data 级联数据
59   - * @property {Array} default-value 默认选中的值
60   - * @property {String} valueKey 指定选项的值为选项对象中的哪个属性值
61   - * @property {String} labelKey 指定选项标签为选项对象中的哪个属性值
62   - * @property {String} childrenKey 指定选项的子选项为选项对象中的哪个属性值
63   - * @property {Boolean} autoClose 是否在选择最后一级时自动关闭并触发confirm(默认false)
64   - */
65   - import { t } from '../../libs/i18n'
66   - export default {
67   - name: 'up-cascader',
68   - props: {
69   - // 通过双向绑定控制组件的弹出与收起
70   - show: {
71   - type: Boolean,
72   - default: false
73   - },
74   - // 级联数据
75   - data: {
76   - type: Array,
77   - default() {
78   - return [];
79   - }
80   - },
81   - // 默认选中的值
82   - modelValue: {
83   - type: Array,
84   - default() {
85   - return [];
86   - }
87   - },
88   - // 指定选项的值为选项对象中的哪个属性值
89   - valueKey: {
90   - type: String,
91   - default: 'value'
92   - },
93   - // 指定选项标签为选项对象中的哪个属性值
94   - labelKey: {
95   - type: String,
96   - default: 'label'
97   - },
98   - // 指定选项的子选项为选项对象中的哪个属性值
99   - childrenKey: {
100   - type: String,
101   - default: 'children'
102   - },
103   - // 是否允许通过点击遮罩关闭Picker
104   - maskCloseAble: {
105   - type: Boolean,
106   - default: true
107   - },
108   - // 弹出的z-index值
109   - zIndex: {
110   - type: [String, Number],
111   - default: 0
112   - },
113   - // 是否在选择最后一级时自动关闭并触发confirm
114   - autoClose: {
115   - type: Boolean,
116   - default: false
117   - },
118   - // 选中项目的展示方向direction垂直方向适合文字长度过长
119   - headerDirection: {
120   - type: String,
121   - default: 'row'
122   - },
123   - // 选项区域列数,支持1列和2列,默认为2列
124   - optionsCols: {
125   - type: [Number],
126   - default: 2
127   - }
128   - },
129   - data() {
130   - return {
131   - // 存储每一级的数据
132   - levelList: [],
133   - // 存储每一级选中的索引
134   - selectedValueIndexs: [],
135   - tabsIndex: 0,
136   - popupShow: false,
137   - // 新增confirmValues用于存储确认的值
138   - confirmValues: []
139   - }
140   - },
141   - watch: {
142   - data: {
143   - handler() {
144   - this.initLevelList();
145   - },
146   - immediate: true
147   - },
148   - show() {
149   - this.popupShow = this.show;
150   - },
151   - modelValue: {
152   - handler() {
153   - this.init();
154   - },
155   - immediate: true
156   - }
157   - },
158   - computed: {
159   - isChange() {
160   - return this.tabsIndex > 1;
161   - },
162   - genTabsList() {
163   - let tabsList = [{
164   - name: "请选择"
165   - }];
166   -
167   - // 根据选中的值动态生成tabs
168   - for (let i = 0; i < this.selectedValueIndexs.length; i++) {
169   - if (this.selectedValueIndexs[i] !== undefined && this.levelList[i]) {
170   - const selectedItem = this.levelList[i][this.selectedValueIndexs[i]];
171   - if (selectedItem) {
172   - tabsList[i] = {
173   - name: selectedItem[this.labelKey]
174   - };
175   - // 如果还有下一级,则添加"请选择"
176   - if (i === this.selectedValueIndexs.length - 1 &&
177   - selectedItem[this.childrenKey] &&
178   - selectedItem[this.childrenKey].length > 0) {
179   - tabsList.push({
180   - name: "请选择"
181   - });
182   - }
183   - }
184   - }
185   - }
186   -
187   - return tabsList;
188   - },
189   - uZIndex() {
190   - // 如果用户有传递z-index值,优先使用
191   - return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
192   - }
193   - },
194   - // 新增confirm事件
195   - emits: ['update:modelValue', 'change', 'confirm'],
196   - methods: {
197   - t,
198   - init() {
199   - // 初始化选中值
200   - if (this.modelValue && this.modelValue.length > 0) {
201   - this.setDefaultValue();
202   - }
203   - },
204   - initLevelList() {
205   - // 初始化第一级数据
206   - if (this.data && this.data.length > 0) {
207   - this.levelList = [this.data];
208   - this.selectedValueIndexs = [];
209   - }
210   - },
211   - setDefaultValue() {
212   - // 根据默认值设置选中项
213   - // 根据modelValue获取indexs给selectedValueIndexs
214   - this.selectedValueIndexs = [];
215   - let currentLevelData = this.data;
216   -
217   - for (let i = 0; i < this.modelValue.length; i++) {
218   - const value = this.modelValue[i];
219   - const index = currentLevelData.findIndex(item => item[this.valueKey] === value);
220   -
221   - if (index !== -1) {
222   - this.selectedValueIndexs.push(index);
223   - // 更新下一级的数据
224   - if (currentLevelData[index][this.childrenKey]) {
225   - currentLevelData = currentLevelData[index][this.childrenKey];
226   - } else {
227   - // 如果没有子级数据,则停止处理
228   - break;
229   - }
230   - } else {
231   - // 如果找不到匹配项,则停止处理
232   - break;
233   - }
234   - }
235   - },
236   - close() {
237   - this.$emit('update:show', false);
238   - },
239   - tabsChange(item) {
240   - },
241   - levelChange(levelIndex, index) {
242   - // 设置当前级的选中值
243   - this.$set(this.selectedValueIndexs, levelIndex, index);
244   -
245   - // 清除后续级别的选中值
246   - for (let i = levelIndex + 1; i < this.selectedValueIndexs.length; i++) {
247   - this.$set(this.selectedValueIndexs, i, undefined);
248   - }
249   -
250   - // 获取当前选中项
251   - const currentItem = this.levelList[levelIndex][index];
252   -
253   - // 如果有子级数据,则初始化下一级
254   - if (currentItem && currentItem[this.childrenKey] && currentItem[this.childrenKey].length > 0) {
255   - // 确保levelList数组足够长
256   - if (this.levelList.length <= levelIndex + 1) {
257   - this.levelList.push(currentItem[this.childrenKey]);
258   - } else {
259   - this.$set(this.levelList, levelIndex + 1, currentItem[this.childrenKey]);
260   - }
261   - // 切换到下一级tab
262   - this.tabsIndex = levelIndex + 1;
263   - } else {
264   - // 没有子级数据,说明是最后一级
265   - if (this.autoClose) {
266   - // 如果启用自动关闭,则触发change事件并关闭
267   - this.emitChange();
268   - } else {
269   - // 否则只触发change事件,不关闭
270   - this.emitChange(false);
271   - }
272   - }
273   - },
274   - // 修改emitChange方法,增加closePopup参数
275   - emitChange(closePopup = true) {
276   - // 构造选中结果
277   - const result = [];
278   - for (let i = 0; i < this.selectedValueIndexs.length; i++) {
279   - if (this.selectedValueIndexs[i] !== undefined && this.levelList[i]) {
280   - result.push(this.levelList[i][this.selectedValueIndexs[i]][this.valueKey]);
281   - }
282   - }
283   -
284   - // 更新confirmValues
285   - this.confirmValues = [...result];
286   -
287   - // 触发change事件,返回value数组
288   - this.$emit('change', this.confirmValues);
289   -
290   - // 根据参数决定是否关闭弹窗
291   - if (closePopup) {
292   - this.close();
293   - }
294   - },
295   - handleCancel() {
296   - this.close();
297   - },
298   - handleConfirm() {
299   - // 确认时触发confirm事件
300   - this.$emit('update:modelValue', this.confirmValues);
301   - this.$emit('confirm', this.confirmValues);
302   - this.close();
303   - }
304   - }
305   - }
306   -</script>
307   -<style lang="scss">
308   - .area-box {
309   - width: 100%;
310   - overflow: hidden;
311   - height: 800rpx;
312   -
313   - >view {
314   - width: 150%;
315   - transition: transform 0.3s ease-in-out 0s;
316   - transform: translateX(0);
317   -
318   - &.change {
319   - // transform: translateX(-33.3333333%);
320   - }
321   - }
322   -
323   - .area-item {
324   - // width: 750rpx;
325   - height: 800rpx;
326   - }
327   - }
328   -
329   - // 添加按钮区域样式
330   - .u-cascader-action {
331   - border-top: 1px solid #eee;
332   - }
333   -</style>
334 0 \ No newline at end of file
uni_modules/uview-plus/components/u-cate-tab/u-cate-tab.vue deleted
1   -<template>
2   - <view class="u-cate-tab" :style="{ height: addUnit(height) }">
3   - <view class="u-cate-tab__wrap">
4   - <scroll-view class="u-cate-tab__view u-cate-tab__menu-scroll-view"
5   - scroll-y scroll-with-animation :scroll-top="scrollTop"
6   - :scroll-into-view="itemId">
7   - <view v-for="(item, index) in tabList" :key="index" class="u-cate-tab__item"
8   - :class="[innerCurrent == index ? 'u-cate-tab__item-active' : '']"
9   - @tap.stop="swichMenu(index)">
10   - <slot name="tabItem" :item="item">
11   - </slot>
12   - <text v-if="!$slots['tabItem']" class="u-line-1">{{item[tabKeyName]}}</text>
13   - </view>
14   - </scroll-view>
15   - <scroll-view :scroll-top="scrollRightTop" scroll-with-animation :scroll-into-view="scrollIntoView"
16   - scroll-y class="u-cate-tab__right-box" @scroll="rightScroll">
17   - <view class="u-cate-tab__right-top">
18   - <slot name="rightTop" :tabList="tabList">
19   - </slot>
20   - </view>
21   - <view class="u-cate-tab__page-view">
22   - <template :key="index" v-for="(item , index) in tabList">
23   - <view v-if="mode == 'follow' || ( mode == 'tab' && index == innerCurrent)"
24   - class="u-cate-tab__page-item" :id="'item' + index">
25   - <slot name="itemList" :item="item">
26   - </slot>
27   - <template v-if="!$slots['itemList']">
28   - <view class="item-title">
29   - <text>{{item[tabKeyName]}}</text>
30   - </view>
31   - <view class="item-container">
32   - <template v-for="(item1, index1) in item.children" :key="index1">
33   - <slot name="pageItem" :pageItem="item1">
34   - <view class="thumb-box" >
35   - <image class="item-menu-image" :src="item1.icon" mode=""></image>
36   - <view class="item-menu-name">{{item1[itemKeyName]}}</view>
37   - </view>
38   - </slot>
39   - </template>
40   - </view>
41   - </template>
42   - </view>
43   - </template>
44   - </view>
45   - </scroll-view>
46   - </view>
47   - </view>
48   -</template>
49   -<script>
50   - import { addUnit, sleep } from '../../libs/function/index';
51   - export default {
52   - name: 'up-cate-tab',
53   - props: {
54   - mode: {
55   - type: String,
56   - default: 'follow' // follo跟随联动, tab单一显示。
57   - },
58   - height: {
59   - type: String,
60   - default: '100%'
61   - },
62   - tabList: {
63   - type: Array,
64   - default: () => {
65   - return []
66   - }
67   - },
68   - tabKeyName: {
69   - type: String,
70   - default: 'name'
71   - },
72   - itemKeyName: {
73   - type: String,
74   - default: 'name'
75   - },
76   - current: {
77   - type: Number,
78   - default: 0
79   - }
80   - },
81   - watch: {
82   - tabList: {
83   - deep: true,
84   - handler(newVal, oldVal) {
85   - // this.observer();
86   - sleep(30);
87   - this.getMenuItemTop();
88   - this.leftMenuStatus(this.innerCurrent);
89   - }
90   - },
91   - current(nval) {
92   - this.innerCurrent = nval;
93   - this.leftMenuStatus(this.innerCurrent);
94   - },
95   - height() {
96   - // console.log('height change');
97   - this.getMenuItemTop();
98   - this.leftMenuStatus(this.innerCurrent);
99   - }
100   - },
101   - emits: ['update:current'],
102   - data() {
103   - return {
104   - scrollTop: 0, //tab标题的滚动条位置
105   - scrollIntoView: '', // 滚动至哪个元素
106   - oldScrollTop: 0,
107   - innerCurrent: 0, // 预设当前项的值
108   - menuHeight: 0, // 左边菜单的高度
109   - menuItemHeight: 0, // 左边菜单item的高度
110   - itemId: '', // 栏目右边scroll-view用于滚动的id
111   - menuItemPos: [],
112   - rects: [],
113   - arr: [],
114   - scrollRightTop: 0, // 右边栏目scroll-view的滚动条高度
115   - timer: null, // 定时器
116   - }
117   - },
118   - mounted() {
119   - // this.observer();
120   - this.innerCurrent = this.current;
121   - this.leftMenuStatus(this.innerCurrent);
122   - this.getMenuItemTop()
123   - },
124   - methods: {
125   - addUnit,
126   - // 点击左边的栏目切换
127   - async swichMenu(index) {
128   - if (this.mode == 'follow') {
129   - if(this.arr.length == 0) {
130   - await this.getMenuItemTop();
131   - }
132   - this.scrollIntoView = 'item' + index;
133   - }
134   -
135   - if (index == this.innerCurrent) return;
136   - this.$nextTick(function(){
137   - this.innerCurrent = index;
138   - this.$emit('update:current', index);
139   - })
140   - },
141   - // 获取一个目标元素的高度
142   - getElRect(elClass, dataVal) {
143   - return new Promise((resolve, reject) => {
144   - const query = uni.createSelectorQuery().in(this);
145   - query.select('.' + elClass).fields({
146   - size: true
147   - }, res => {
148   - // 如果节点尚未生成,res值为null,循环调用执行
149   - if (!res) {
150   - setTimeout(() => {
151   - this.getElRect(elClass);
152   - }, 10);
153   - return;
154   - }
155   - this[dataVal] = res.height;
156   - resolve();
157   - }).exec();
158   - })
159   - },
160   - // 观测元素相交状态
161   - async observer() {
162   - await this.$nextTick();
163   - // 清除之前的观察器
164   - if (this._observerList) {
165   - this._observerList.forEach(observer => {
166   - observer.disconnect();
167   - });
168   - }
169   - this._observerList = [];
170   -
171   - this.tabList.map((val, index) => {
172   - let observer = uni.createIntersectionObserver(this);
173   - this._observerList.push(observer);
174   - // 检测相交状态
175   - observer.relativeTo('.u-cate-tab__right-box', {
176   - top: 10
177   - }).observe('#item' + index, (res) => {
178   - if (res.intersectionRatio > 0) {
179   - console.log('res', res);
180   - // 修复:确保正确获取索引
181   - let id = res.id ? res.id.substring(4) : index;
182   - this.leftMenuStatus(parseInt(id));
183   - }
184   - })
185   - })
186   - },
187   - // 设置左边菜单的滚动状态
188   - async leftMenuStatus(index) {
189   - this.innerCurrent = index;
190   - this.$emit('update:current', index);
191   - // 如果为0,意味着尚未初始化
192   - if (this.menuHeight == 0 || this.menuItemHeight == 0) {
193   - await this.getElRect('u-cate-tab__menu-scroll-view', 'menuHeight');
194   - await this.getElRect('u-cate-tab__item', 'menuItemHeight');
195   - }
196   - // console.log(this.menuHeight, this.menuItemHeight)
197   - // 将菜单活动item垂直居中
198   - this.scrollTop = index * this.menuItemHeight + this.menuItemHeight / 2 - this.menuHeight / 2;
199   - },
200   - // 获取右边菜单每个item到顶部的距离
201   - async getMenuItemTop() {
202   - // await this.$nextTick();
203   - // console.log('getMenuItemTop')
204   - return new Promise(resolve => {
205   - let selectorQuery = uni.createSelectorQuery().in(this);
206   - selectorQuery.selectAll('.u-cate-tab__page-item').boundingClientRect((rects) => {
207   - // 如果节点尚未生成,rects值为[](因为用selectAll,所以返回的是数组),循环调用执行
208   - if(!rects.length) {
209   - setTimeout(() => {
210   - this.getMenuItemTop();
211   - }, 100);
212   - return ;
213   - }
214   - // console.log(rects)
215   - this.rects = rects;
216   - this.arr = [];
217   - rects.forEach((rect) => {
218   - // 这里减去rects[0].top,是因为第一项顶部可能不是贴到导航栏(比如有个搜索框的情况)
219   - this.arr.push(rect.top - rects[0].top);
220   - })
221   - // console.log(this.arr)
222   - resolve();
223   - }).exec()
224   - })
225   - },
226   - // 右边菜单滚动
227   - async rightScroll(e) {
228   - if (this.mode !== 'follow') return;
229   - this.oldScrollTop = e.detail.scrollTop;
230   - // console.log(e.detail.scrollTop)
231   - // console.log(JSON.stringify(this.arr))
232   - if(this.arr.length == 0) {
233   - await this.getMenuItemTop();
234   - }
235   - if(this.timer) return ;
236   - if(!this.menuHeight) {
237   - await this.getElRect('u-cate-tab__menu-scroll-view', 'menuHeight');
238   - }
239   - setTimeout(() => { // 节流
240   - this.timer = null;
241   - // scrollHeight为右边菜单垂直中点位置
242   - let scrollHeight = e.detail.scrollTop + 1;
243   - // console.log(e.detail.scrollTop)
244   - for (let i = 0; i < this.arr.length; i++) {
245   - let height1 = this.arr[i];
246   - let height2 = this.arr[i + 1];
247   - // console.log('i', i)
248   - // console.log('height1', height1)
249   - // console.log('height2', height2)
250   - // 如果不存在height2,意味着数据循环已经到了最后一个,设置左边菜单为最后一项即可
251   - if (!height2 || scrollHeight >= height1 && scrollHeight <= height2) {
252   - // console.log('scrollHeight', scrollHeight)
253   - // console.log('height1', height1)
254   - // console.log('height2', height2)
255   - this.leftMenuStatus(i);
256   - return ;
257   - }
258   - }
259   - }, 100)
260   - }
261   - }
262   - }
263   -</script>
264   -
265   -<style lang="scss" scoped>
266   - .u-cate-tab {
267   - display: flex;
268   - flex-direction: column;
269   - }
270   -
271   - .u-cate-tab__wrap {
272   - flex: 1;
273   - display: flex;
274   - flex-direction: row;
275   - overflow: hidden;
276   - }
277   -
278   - .u-search-inner {
279   - background-color: rgb(234, 234, 234);
280   - border-radius: 100rpx;
281   - display: flex;
282   - align-items: center;
283   - padding: 10rpx 16rpx;
284   - }
285   -
286   - .u-search-text {
287   - font-size: 26rpx;
288   - color: $u-tips-color;
289   - margin-left: 10rpx;
290   - }
291   -
292   - .u-cate-tab__view {
293   - width: 200rpx;
294   - height: 100%;
295   - }
296   -
297   - .u-cate-tab__item {
298   - height: 110rpx;
299   - background: #f6f6f6;
300   - box-sizing: border-box;
301   - display: flex;
302   - align-items: center;
303   - justify-content: center;
304   - font-size: 26rpx;
305   - color: #444;
306   - font-weight: 400;
307   - line-height: 1;
308   - }
309   -
310   - .u-cate-tab__item-active {
311   - position: relative;
312   - color: #000;
313   - font-size: 30rpx;
314   - font-weight: 600;
315   - background: #fff;
316   - }
317   -
318   - .u-cate-tab__item-active::before {
319   - content: "";
320   - position: absolute;
321   - border-left: 4px solid $u-primary;
322   - height: 32rpx;
323   - left: 0;
324   - top: 39rpx;
325   - }
326   -
327   - .u-cate-tab__view {
328   - height: 100%;
329   - }
330   -
331   - .u-cate-tab__right-box {
332   - flex: 1;
333   - background-color: rgb(250, 250, 250);
334   - }
335   -
336   - .u-cate-tab__page-view {
337   - padding: 16rpx;
338   - }
339   -
340   - .u-cate-tab__page-item {
341   - margin-bottom: 30rpx;
342   - background-color: #fff;
343   - padding: 16rpx;
344   - border-radius: 8rpx;
345   - }
346   -
347   - .u-cate-tab__page-item:last-child {
348   - min-height: 100vh;
349   - }
350   -
351   - .item-title {
352   - font-size: 26rpx;
353   - color: $u-main-color;
354   - font-weight: bold;
355   - }
356   -
357   - .item-menu-name {
358   - font-weight: normal;
359   - font-size: 24rpx;
360   - color: $u-main-color;
361   - }
362   -
363   - .item-container {
364   - display: flex;
365   - flex-wrap: wrap;
366   - }
367   -
368   - .thumb-box {
369   - width: 33.333333%;
370   - display: flex;
371   - align-items: center;
372   - justify-content: center;
373   - flex-direction: column;
374   - margin-top: 20rpx;
375   - }
376   -
377   - .item-menu-image {
378   - width: 120rpx;
379   - height: 120rpx;
380   - }
381   -</style>
uni_modules/uview-plus/components/u-cell-group/cellGroup.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:54:16
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/cellGroup.js
9   - */
10   -export default {
11   - // cell-group组件的props
12   - cellGroup: {
13   - title: '',
14   - border: true,
15   - customStyle: {}
16   - }
17   -}
uni_modules/uview-plus/components/u-cell-group/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 分组标题
6   - title: {
7   - type: String,
8   - default: () => defProps.cellGroup.title
9   - },
10   - // 是否显示外边框
11   - border: {
12   - type: Boolean,
13   - default: () => defProps.cellGroup.border
14   - }
15   - }
16   -})
uni_modules/uview-plus/components/u-cell-group/u-cell-group.vue deleted
1   -<template>
2   - <view :style="[addStyle(customStyle)]" :class="[customClass]" class="u-cell-group">
3   - <view v-if="title" class="u-cell-group__title">
4   - <slot name="title">
5   - <text class="u-cell-group__title__text">{{ title }}</text>
6   - </slot>
7   - </view>
8   - <view class="u-cell-group__wrapper">
9   - <u-line v-if="border"></u-line>
10   - <slot />
11   - </view>
12   - </view>
13   -</template>
14   -
15   -<script>
16   - import { props } from './props';
17   - import { mpMixin } from '../../libs/mixin/mpMixin';
18   - import { mixin } from '../../libs/mixin/mixin';
19   - import { addStyle } from '../../libs/function/index';
20   - /**
21   - * cellGroup 单元格
22   - * @description cell单元格一般用于一组列表的情况,比如个人中心页,设置页等。
23   - * @tutorial https://uview-plus.jiangruyi.com/components/cell.html
24   - *
25   - * @property {String} title 分组标题
26   - * @property {Boolean} border 是否显示外边框 (默认 true )
27   - * @property {Object} customStyle 定义需要用到的外部样式
28   - *
29   - * @event {Function} click 点击cell列表时触发
30   - * @example <u-cell-group title="设置喜好">
31   - */
32   - export default {
33   - name: 'u-cell-group',
34   - mixins: [mpMixin, mixin, props],
35   - methods: {
36   - addStyle
37   - }
38   - }
39   -</script>
40   -
41   -<style lang="scss" scoped>
42   -
43   - $u-cell-group-title-padding: 16px 16px 8px !default;
44   - $u-cell-group-title-font-size: 15px !default;
45   - $u-cell-group-title-line-height: 16px !default;
46   - $u-cell-group-title-color: $u-main-color !default;
47   -
48   - .u-cell-group {
49   - flex: 1;
50   -
51   - &__title {
52   - padding: $u-cell-group-title-padding;
53   -
54   - &__text {
55   - font-size: $u-cell-group-title-font-size;
56   - line-height: $u-cell-group-title-line-height;
57   - color: $u-cell-group-title-color;
58   - }
59   - }
60   -
61   - &__wrapper {
62   - position: relative;
63   - }
64   - }
65   -</style>
66   -
uni_modules/uview-plus/components/u-cell/cell.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-23 20:53:09
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/cell.js
9   - */
10   -export default {
11   - // cell组件的props
12   - cell: {
13   - customClass: '',
14   - title: '',
15   - label: '',
16   - value: '',
17   - icon: '',
18   - disabled: false,
19   - border: true,
20   - center: false,
21   - url: '',
22   - linkType: 'navigateTo',
23   - clickable: false,
24   - isLink: false,
25   - required: false,
26   - arrowDirection: '',
27   - iconStyle: {},
28   - rightIconStyle: {},
29   - rightIcon: 'arrow-right',
30   - titleStyle: {},
31   - size: '',
32   - stop: true,
33   - name: ''
34   - }
35   -}
uni_modules/uview-plus/components/u-cell/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 标题
6   - title: {
7   - type: [String, Number],
8   - default: () => defProps.cell.title
9   - },
10   - // 标题下方的描述信息
11   - label: {
12   - type: [String, Number],
13   - default: () => defProps.cell.label
14   - },
15   - // 右侧的内容
16   - value: {
17   - type: [String, Number],
18   - default: () => defProps.cell.value
19   - },
20   - // 左侧图标名称,或者图片链接(本地文件建议使用绝对地址)
21   - icon: {
22   - type: String,
23   - default: () => defProps.cell.icon
24   - },
25   - // 是否禁用cell
26   - disabled: {
27   - type: Boolean,
28   - default: () => defProps.cell.disabled
29   - },
30   - // 是否显示下边框
31   - border: {
32   - type: Boolean,
33   - default: () => defProps.cell.border
34   - },
35   - // 内容是否垂直居中(主要是针对右侧的value部分)
36   - center: {
37   - type: Boolean,
38   - default: () => defProps.cell.center
39   - },
40   - // 点击后跳转的URL地址
41   - url: {
42   - type: String,
43   - default: () => defProps.cell.url
44   - },
45   - // 链接跳转的方式,内部使用的是uView封装的route方法,可能会进行拦截操作
46   - linkType: {
47   - type: String,
48   - default: () => defProps.cell.linkType
49   - },
50   - // 是否开启点击反馈(表现为点击时加上灰色背景)
51   - clickable: {
52   - type: Boolean,
53   - default: () => defProps.cell.clickable
54   - },
55   - // 是否展示右侧箭头并开启点击反馈
56   - isLink: {
57   - type: Boolean,
58   - default: () => defProps.cell.isLink
59   - },
60   - // 是否显示表单状态下的必填星号(此组件可能会内嵌入input组件)
61   - required: {
62   - type: Boolean,
63   - default: () => defProps.cell.required
64   - },
65   - // 右侧的图标箭头
66   - rightIcon: {
67   - type: String,
68   - default: () => defProps.cell.rightIcon
69   - },
70   - // 右侧箭头的方向,可选值为:left,up,down
71   - arrowDirection: {
72   - type: String,
73   - default: () => defProps.cell.arrowDirection
74   - },
75   - // 左侧图标样式
76   - iconStyle: {
77   - type: [Object, String],
78   - default: () => {
79   - return defProps.cell.iconStyle
80   - }
81   - },
82   - // 右侧箭头图标的样式
83   - rightIconStyle: {
84   - type: [Object, String],
85   - default: () => {
86   - return defProps.cell.rightIconStyle
87   - }
88   - },
89   - // 标题的样式
90   - titleStyle: {
91   - type: [Object, String],
92   - default: () => {
93   - return defProps.cell.titleStyle
94   - }
95   - },
96   - // 单位元的大小,可选值为large
97   - size: {
98   - type: String,
99   - default: () => defProps.cell.size
100   - },
101   - // 点击cell是否阻止事件传播
102   - stop: {
103   - type: Boolean,
104   - default: () => defProps.cell.stop
105   - },
106   - // 标识符,cell被点击时返回
107   - name: {
108   - type: [Number, String],
109   - default: () => defProps.cell.name
110   - }
111   - }
112   -})
uni_modules/uview-plus/components/u-cell/u-cell.vue deleted
1   -<template>
2   - <view class="u-cell" :class="[customClass]" :style="[addStyle(customStyle)]"
3   - :hover-class="(!disabled && (clickable || isLink)) ? 'u-cell--clickable' : ''" :hover-stay-time="250"
4   - @tap="clickHandler">
5   - <view class="u-cell__body" :class="[ center && 'u-cell--center', size === 'large' && 'u-cell__body--large']">
6   - <view class="u-cell__body__content">
7   - <view class="u-cell__left-icon-wrap" v-if="$slots.icon || icon">
8   - <slot name="icon" v-if="$slots.icon">
9   - </slot>
10   - <up-icon v-else :name="icon"
11   - :custom-style="iconStyle"
12   - :size="size === 'large' ? 22 : 18"></up-icon>
13   - </view>
14   - <view class="u-cell__title">
15   - <!-- 将slot与默认内容用if/else分开主要是因为微信小程序不支持slot嵌套传递,这样才能解决collapse组件的slot不失效问题,label暂时未用到。 -->
16   - <slot name="title" v-if="$slots.title || !title">
17   - </slot>
18   - <text v-else class="u-cell__title-text" :style="[titleTextStyle]"
19   - :class="[required && 'u-cell--required', disabled && 'u-cell--disabled', size === 'large' && 'u-cell__title-text--large']">{{ title }}</text>
20   - <slot name="label">
21   - <text class="u-cell__label" v-if="label"
22   - :class="[disabled && 'u-cell--disabled', size === 'large' && 'u-cell__label--large']">{{ label }}</text>
23   - </slot>
24   - </view>
25   - </view>
26   - <slot name="value">
27   - <text class="u-cell__value"
28   - :class="[disabled && 'u-cell--disabled', size === 'large' && 'u-cell__value--large']"
29   - v-if="!testEmpty(value)">{{ value }}</text>
30   - </slot>
31   - <view class="u-cell__right-icon-wrap" v-if="$slots['right-icon'] || isLink"
32   - :class="[`u-cell__right-icon-wrap--${arrowDirection}`]">
33   - <up-icon v-if="rightIcon && !$slots['right-icon']" :name="rightIcon"
34   - :custom-style="rightIconStyle" :color="disabled ? '#c8c9cc' : 'info'"
35   - :size="size === 'large' ? 18 : 16"></up-icon>
36   - <slot v-else name="right-icon">
37   - </slot>
38   - </view>
39   - <view class="u-cell__right-icon-wrap" v-if="$slots['righticon']"
40   - :class="[`u-cell__right-icon-wrap--${arrowDirection}`]">
41   - <slot name="righticon">
42   - </slot>
43   - </view>
44   - </view>
45   - <u-line v-if="border"></u-line>
46   - </view>
47   -</template>
48   -
49   -<script>
50   - import { props } from './props';
51   - import { mpMixin } from '../../libs/mixin/mpMixin';
52   - import { mixin } from '../../libs/mixin/mixin';
53   - import { addStyle } from '../../libs/function/index';
54   - import test from '../../libs/function/test';
55   - /**
56   - * cell 单元格
57   - * @description cell单元格一般用于一组列表的情况,比如个人中心页,设置页等。
58   - * @tutorial https://uview-plus.jiangruyi.com/components/cell.html
59   - * @property {String | Number} title 标题
60   - * @property {String | Number} label 标题下方的描述信息
61   - * @property {String | Number} value 右侧的内容
62   - * @property {String} icon 左侧图标名称,或者图片链接(本地文件建议使用绝对地址)
63   - * @property {Boolean} disabled 是否禁用cell
64   - * @property {Boolean} border 是否显示下边框 (默认 true )
65   - * @property {Boolean} center 内容是否垂直居中(主要是针对右侧的value部分) (默认 false )
66   - * @property {String} url 点击后跳转的URL地址
67   - * @property {String} linkType 链接跳转的方式,内部使用的是uView封装的route方法,可能会进行拦截操作 (默认 'navigateTo' )
68   - * @property {Boolean} clickable 是否开启点击反馈(表现为点击时加上灰色背景) (默认 false )
69   - * @property {Boolean} isLink 是否展示右侧箭头并开启点击反馈 (默认 false )
70   - * @property {Boolean} required 是否显示表单状态下的必填星号(此组件可能会内嵌入input组件) (默认 false )
71   - * @property {String} rightIcon 右侧的图标箭头 (默认 'arrow-right')
72   - * @property {String} arrowDirection 右侧箭头的方向,可选值为:left,up,down
73   - * @property {Object | String} rightIconStyle 右侧箭头图标的样式
74   - * @property {Object | String} titleStyle 标题的样式
75   - * @property {Object | String} iconStyle 左侧图标样式
76   - * @property {String} size 单位元的大小,可选值为 large,normal,mini
77   - * @property {Boolean} stop 点击cell是否阻止事件传播 (默认 true )
78   - * @property {Object} customStyle 定义需要用到的外部样式
79   - *
80   - * @event {Function} click 点击cell列表时触发
81   - * @example 该组件需要搭配cell-group组件使用,见官方文档示例
82   - */
83   - export default {
84   - name: 'u-cell',
85   - data() {
86   - return {
87   -
88   - }
89   - },
90   - mixins: [mpMixin, mixin, props],
91   - computed: {
92   - titleTextStyle() {
93   - return addStyle(this.titleStyle)
94   - }
95   - },
96   - emits: ['click'],
97   - methods: {
98   - addStyle,
99   - testEmpty: test.empty,
100   - // 点击cell
101   - clickHandler(e) {
102   - if (this.disabled) return
103   - this.$emit('click', {
104   - name: this.name
105   - })
106   - // 如果配置了url(此props参数通过mixin引入)参数,跳转页面
107   - this.openPage()
108   - // 是否阻止事件传播
109   - this.stop && this.preventEvent(e)
110   - },
111   - }
112   - }
113   -</script>
114   -
115   -<style lang="scss" scoped>
116   -
117   - $u-cell-padding: 13px 15px !default;
118   - $u-cell-font-size: 15px !default;
119   - $u-cell-line-height: 24px !default;
120   - $u-cell-color: $u-main-color !default;
121   - $u-cell-icon-size: 16px !default;
122   - $u-cell-title-font-size: 15px !default;
123   - $u-cell-title-line-height: 22px !default;
124   - $u-cell-title-color: $u-main-color !default;
125   - $u-cell-label-font-size: 12px !default;
126   - $u-cell-label-color: $u-tips-color !default;
127   - $u-cell-label-line-height: 18px !default;
128   - $u-cell-value-font-size: 14px !default;
129   - $u-cell-value-color: $u-content-color !default;
130   - $u-cell-clickable-color: $u-bg-color !default;
131   - $u-cell-disabled-color: #c8c9cc !default;
132   - $u-cell-padding-top-large: 13px !default;
133   - $u-cell-padding-bottom-large: 13px !default;
134   - $u-cell-value-font-size-large: 15px !default;
135   - $u-cell-label-font-size-large: 14px !default;
136   - $u-cell-title-font-size-large: 16px !default;
137   - $u-cell-left-icon-wrap-margin-right: 4px !default;
138   - $u-cell-right-icon-wrap-margin-left: 4px !default;
139   - $u-cell-title-flex:1 !default;
140   - $u-cell-label-margin-top:5px !default;
141   -
142   -
143   - .u-cell {
144   - &__body {
145   - @include flex();
146   - /* #ifndef APP-NVUE */
147   - box-sizing: border-box;
148   - /* #endif */
149   - padding: $u-cell-padding;
150   - font-size: $u-cell-font-size;
151   - color: $u-cell-color;
152   - // line-height: $u-cell-line-height;
153   - align-items: center;
154   -
155   - &__content {
156   - @include flex(row);
157   - align-items: center;
158   - flex: 1;
159   - }
160   -
161   - &--large {
162   - padding-top: $u-cell-padding-top-large;
163   - padding-bottom: $u-cell-padding-bottom-large;
164   - }
165   - }
166   -
167   - &__left-icon-wrap,
168   - &__right-icon-wrap {
169   - @include flex();
170   - align-items: center;
171   - // height: $u-cell-line-height;
172   - font-size: $u-cell-icon-size;
173   - }
174   -
175   - &__left-icon-wrap {
176   - margin-right: $u-cell-left-icon-wrap-margin-right;
177   - }
178   -
179   - &__right-icon-wrap {
180   - margin-left: $u-cell-right-icon-wrap-margin-left;
181   - transition: transform 0.3s;
182   -
183   - &--up {
184   - transform: rotate(-90deg);
185   - }
186   -
187   - &--down {
188   - transform: rotate(90deg);
189   - }
190   - }
191   -
192   - &__title {
193   - flex: $u-cell-title-flex;
194   - display: flex;
195   - flex-direction: column;
196   -
197   - &-text {
198   - font-size: $u-cell-title-font-size;
199   - line-height: $u-cell-title-line-height;
200   - color: $u-cell-title-color;
201   -
202   - &--large {
203   - font-size: $u-cell-title-font-size-large;
204   - }
205   - }
206   -
207   - }
208   -
209   - &__label {
210   - margin-top: $u-cell-label-margin-top;
211   - font-size: $u-cell-label-font-size;
212   - color: $u-cell-label-color;
213   - line-height: $u-cell-label-line-height;
214   -
215   - &--large {
216   - font-size: $u-cell-label-font-size-large;
217   - }
218   - }
219   -
220   - &__value {
221   - text-align: right;
222   - /* #ifndef APP-NVUE */
223   - margin-left: auto;
224   - /* #endif */
225   - font-size: $u-cell-value-font-size;
226   - line-height: $u-cell-line-height;
227   - color: $u-cell-value-color;
228   - &--large {
229   - font-size: $u-cell-value-font-size-large;
230   - }
231   - }
232   -
233   - &--required {
234   - /* #ifndef APP-NVUE */
235   - overflow: visible;
236   - /* #endif */
237   - @include flex;
238   - align-items: center;
239   - }
240   -
241   - &--required:before {
242   - position: absolute;
243   - /* #ifndef APP-NVUE */
244   - content: '*';
245   - /* #endif */
246   - left: -8px;
247   - margin-top: 4rpx;
248   - font-size: 14px;
249   - color: $u-error;
250   - }
251   -
252   - &--clickable {
253   - background-color: $u-cell-clickable-color;
254   - }
255   -
256   - &--disabled {
257   - color: $u-cell-disabled-color;
258   - /* #ifndef APP-NVUE */
259   - cursor: not-allowed;
260   - /* #endif */
261   - }
262   -
263   - &--center {
264   - align-items: center;
265   - }
266   - }
267   -</style>
uni_modules/uview-plus/components/u-checkbox-group/checkboxGroup.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:54:47
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/checkboxGroup.js
9   - */
10   -export default {
11   - // checkbox-group组件
12   - checkboxGroup: {
13   - name: '',
14   - value: [],
15   - shape: 'square',
16   - disabled: false,
17   - activeColor: '#2979ff',
18   - inactiveColor: '#c8c9cc',
19   - size: 18,
20   - placement: 'row',
21   - labelSize: 14,
22   - labelColor: '#303133',
23   - labelDisabled: false,
24   - iconColor: '#ffffff',
25   - iconSize: 12,
26   - iconPlacement: 'left',
27   - borderBottom: false
28   - }
29   -}
uni_modules/uview-plus/components/u-checkbox-group/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -
4   -export const props = defineMixin({
5   - props: {
6   - // 标识符
7   - name: {
8   - type: String,
9   - default: () => defProps.checkboxGroup.name
10   - },
11   - // #ifdef VUE3
12   - // 绑定的值
13   - modelValue: {
14   - type: Array,
15   - default: () => defProps.checkboxGroup.value
16   - },
17   - // #endif
18   - // #ifdef VUE2
19   - // 绑定的值
20   - value: {
21   - type: Array,
22   - default: () => defProps.checkboxGroup.value
23   - },
24   - // #endif
25   - // 形状,circle-圆形,square-方形
26   - shape: {
27   - type: String,
28   - default: () => defProps.checkboxGroup.shape
29   - },
30   - // 是否禁用全部checkbox
31   - disabled: {
32   - type: Boolean,
33   - default: () => defProps.checkboxGroup.disabled
34   - },
35   -
36   - // 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值
37   - activeColor: {
38   - type: String,
39   - default: () => defProps.checkboxGroup.activeColor
40   - },
41   - // 未选中的颜色
42   - inactiveColor: {
43   - type: String,
44   - default: () => defProps.checkboxGroup.inactiveColor
45   - },
46   -
47   - // 整个组件的尺寸,默认px
48   - size: {
49   - type: [String, Number],
50   - default: () => defProps.checkboxGroup.size
51   - },
52   - // 布局方式,row-横向,column-纵向
53   - placement: {
54   - type: String,
55   - default: () => defProps.checkboxGroup.placement
56   - },
57   - // label的字体大小,px单位
58   - labelSize: {
59   - type: [String, Number],
60   - default: () => defProps.checkboxGroup.labelSize
61   - },
62   - // label的字体颜色
63   - labelColor: {
64   - type: [String],
65   - default: () => defProps.checkboxGroup.labelColor
66   - },
67   - // 是否禁止点击文本操作
68   - labelDisabled: {
69   - type: Boolean,
70   - default: () => defProps.checkboxGroup.labelDisabled
71   - },
72   - // 图标颜色
73   - iconColor: {
74   - type: String,
75   - default: () => defProps.checkboxGroup.iconColor
76   - },
77   - // 图标的大小,单位px
78   - iconSize: {
79   - type: [String, Number],
80   - default: () => defProps.checkboxGroup.iconSize
81   - },
82   - // 勾选图标的对齐方式,left-左边,right-右边
83   - iconPlacement: {
84   - type: String,
85   - default: () => defProps.checkboxGroup.iconPlacement
86   - },
87   - // 竖向配列时,是否显示下划线
88   - borderBottom: {
89   - type: Boolean,
90   - default: () => defProps.checkboxGroup.borderBottom
91   - }
92   - }
93   -})
uni_modules/uview-plus/components/u-checkbox-group/u-checkbox-group.vue deleted
1   -<template>
2   - <view
3   - class="u-checkbox-group"
4   - :class="bemClass"
5   - >
6   - <slot></slot>
7   - </view>
8   -</template>
9   -
10   -<script>
11   - import { props } from './props';
12   - import { mpMixin } from '../../libs/mixin/mpMixin';
13   - import { mixin } from '../../libs/mixin/mixin';
14   - /**
15   - * checkboxGroup 复选框组
16   - * @description 复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便
17   - * @tutorial https://uview-plus.jiangruyi.com/components/checkbox.html
18   - * @property {String} name 标识符
19   - * @property {Array} value 绑定的值
20   - * @property {String} shape 形状,circle-圆形,square-方形 (默认 'square' )
21   - * @property {Boolean} disabled 是否禁用全部checkbox (默认 false )
22   - * @property {String} activeColor 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 (默认 '#2979ff' )
23   - * @property {String} inactiveColor 未选中的颜色 (默认 '#c8c9cc' )
24   - * @property {String | Number} size 整个组件的尺寸 单位px (默认 18 )
25   - * @property {String} placement 布局方式,row-横向,column-纵向 (默认 'row' )
26   - * @property {String | Number} labelSize label的字体大小,px单位 (默认 14 )
27   - * @property {String} labelColor label的字体颜色 (默认 '#303133' )
28   - * @property {Boolean} labelDisabled 是否禁止点击文本操作 (默认 false )
29   - * @property {String} iconColor 图标颜色 (默认 '#ffffff' )
30   - * @property {String | Number} iconSize 图标的大小,单位px (默认 12 )
31   - * @property {String} iconPlacement 勾选图标的对齐方式,left-左边,right-右边 (默认 'left' )
32   - * @property {Boolean} borderBottom placement为row时,是否显示下边框 (默认 false )
33   - * @event {Function} change 任一个checkbox状态发生变化时触发,回调为一个对象
34   - * @event {Function} input 修改通过v-model绑定的值时触发,回调为一个对象
35   - * @example <u-checkbox-group></u-checkbox-group>
36   - */
37   - export default {
38   - name: 'u-checkbox-group',
39   - mixins: [mpMixin, mixin,props],
40   - computed: {
41   - // 这里computed的变量,都是子组件u-checkbox需要用到的,由于头条小程序的兼容性差异,子组件无法实时监听父组件参数的变化
42   - // 所以需要手动通知子组件,这里返回一个parentData变量,供watch监听,在其中去通知每一个子组件重新从父组件(u-checkbox-group)
43   - // 拉取父组件新的变化后的参数
44   - parentData() {
45   - return [
46   - // #ifdef VUE2
47   - this.value,
48   - // #endif
49   - // #ifdef VUE3
50   - this.modelValue,
51   - // #endif
52   - this.disabled,
53   - this.inactiveColor,
54   - this.activeColor,
55   - this.size,
56   - this.labelDisabled,
57   - this.shape,
58   - this.iconSize,
59   - this.borderBottom,
60   - this.placement,
61   - ];
62   - },
63   - bemClass() {
64   - // this.bem为一个computed变量,在mixin中
65   - return this.bem('checkbox-group', ['placement'])
66   - },
67   - },
68   - watch: {
69   - // 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件
70   - parentData: {
71   - handler() {
72   - if (this.children.length) {
73   - this.children.map((child) => {
74   - // 判断子组件(u-checkbox)如果有init方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值)
75   - typeof child.init === "function" && child.init();
76   - });
77   - }
78   - },
79   - deep: true,
80   - },
81   - },
82   - data() {
83   - return {
84   -
85   - }
86   - },
87   - created() {
88   - this.children = []
89   - },
90   - // #ifdef VUE3
91   - emits: ['update:modelValue', 'change'],
92   - // #endif
93   - methods: {
94   - // 将其他的checkbox设置为未选中的状态
95   - unCheckedOther(childInstance) {
96   - const values = []
97   - this.children.map(child => {
98   - // 将被选中的checkbox,放到数组中返回
99   - if (child.isChecked) {
100   - values.push(child.name)
101   - }
102   - })
103   -
104   - // 修改通过v-model绑定的值
105   - // #ifdef VUE3
106   - this.$emit("update:modelValue", values);
107   - // #endif
108   - // #ifdef VUE2
109   - this.$emit("input", values);
110   - // #endif
111   - // 放在最后更新,否则change事件传出去的values不会更新
112   - this.$emit('change', values)
113   - },
114   - }
115   - }
116   -</script>
117   -
118   -<style lang="scss" scoped>
119   -
120   - .u-checkbox-group {
121   -
122   - &--row {
123   - /* #ifndef APP-NVUE */
124   - display: flex;
125   - /* #endif */
126   - flex-flow: row wrap;
127   - }
128   -
129   - &--column {
130   - @include flex(column);
131   - }
132   - }
133   -</style>
uni_modules/uview-plus/components/u-checkbox/checkbox.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-23 21:06:59
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/checkbox.js
9   - */
10   -export default {
11   - // checkbox组件
12   - checkbox: {
13   - name: '',
14   - shape: '',
15   - size: '',
16   - checkbox: false,
17   - disabled: '',
18   - activeColor: '',
19   - inactiveColor: '',
20   - iconSize: '',
21   - iconColor: '',
22   - label: '',
23   - labelSize: '',
24   - labelColor: '',
25   - labelDisabled: ''
26   - }
27   -}
uni_modules/uview-plus/components/u-checkbox/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // checkbox的名称
6   - name: {
7   - type: [String, Number, Boolean],
8   - default: () => defProps.checkbox.name
9   - },
10   - // 形状,square为方形,circle为圆型
11   - shape: {
12   - type: String,
13   - default: () => defProps.checkbox.shape
14   - },
15   - // 整体的大小
16   - size: {
17   - type: [String, Number],
18   - default: () => defProps.checkbox.size
19   - },
20   - // 是否默认选中
21   - checked: {
22   - type: Boolean,
23   - default: () => defProps.checkbox.checked
24   - },
25   - // 是否禁用
26   - disabled: {
27   - type: [String, Boolean],
28   - default: () => defProps.checkbox.disabled
29   - },
30   - // 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值
31   - activeColor: {
32   - type: String,
33   - default: () => defProps.checkbox.activeColor
34   - },
35   - // 未选中的颜色
36   - inactiveColor: {
37   - type: String,
38   - default: () => defProps.checkbox.inactiveColor
39   - },
40   - // 图标的大小,单位px
41   - iconSize: {
42   - type: [String, Number],
43   - default: () => defProps.checkbox.iconSize
44   - },
45   - // 图标颜色
46   - iconColor: {
47   - type: String,
48   - default: () => defProps.checkbox.iconColor
49   - },
50   - // label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式
51   - label: {
52   - type: [String, Number],
53   - default: () => defProps.checkbox.label
54   - },
55   - // label的字体大小,px单位
56   - labelSize: {
57   - type: [String, Number],
58   - default: () => defProps.checkbox.labelSize
59   - },
60   - // label的颜色
61   - labelColor: {
62   - type: String,
63   - default: () => defProps.checkbox.labelColor
64   - },
65   - // 是否禁止点击提示语选中复选框
66   - labelDisabled: {
67   - type: [String, Boolean],
68   - default: () => defProps.checkbox.labelDisabled
69   - },
70   - // 是否独立使用
71   - usedAlone: {
72   - type: [Boolean],
73   - default: () => false
74   - }
75   - }
76   -})
uni_modules/uview-plus/components/u-checkbox/u-checkbox.vue deleted
1   -<template>
2   - <view
3   - class="u-checkbox cursor-pointer"
4   - :style="[checkboxStyle]"
5   - @tap.stop="wrapperClickHandler"
6   - :class="[`u-checkbox-label--${parentData.iconPlacement}`, parentData.borderBottom && parentData.placement === 'column' && 'u-border-bottom']"
7   - >
8   - <view
9   - class="u-checkbox__icon-wrap cursor-pointer"
10   - @tap.stop="iconClickHandler"
11   - :class="iconClasses"
12   - :style="[iconWrapStyle]"
13   - >
14   - <slot name="icon" :elIconSize="elIconSize" :elIconColor="elIconColor">
15   - <up-icon
16   - class="u-checkbox__icon-wrap__icon"
17   - name="checkbox-mark"
18   - :size="elIconSize"
19   - :color="elIconColor"
20   - />
21   - </slot>
22   - </view>
23   - <view class="u-checkbox__label-wrap cursor-pointer" @tap.stop="labelClickHandler">
24   - <slot name="label" :label="label" :elDisabled="elDisabled">
25   - <text
26   - :style="{
27   - color: elDisabled ? elInactiveColor : elLabelColor,
28   - fontSize: elLabelSize,
29   - lineHeight: elLabelSize
30   - }"
31   - >{{label}}</text>
32   - </slot>
33   - </view>
34   - </view>
35   -</template>
36   -
37   -<script>
38   - import { props } from './props';
39   - import { mpMixin } from '../../libs/mixin/mpMixin';
40   - import { mixin } from '../../libs/mixin/mixin';
41   - import { addStyle, addUnit, deepMerge, formValidate, error } from '../../libs/function/index';
42   - import test from '../../libs/function/test';
43   - /**
44   - * checkbox 复选框
45   - * @description 复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便
46   - * @tutorial https://uview-plus.jiangruyi.com/components/checkbox.html
47   - * @property {String | Number | Boolean} name checkbox组件的标示符
48   - * @property {String} shape 形状,square为方形,circle为圆型
49   - * @property {String | Number} size 整体的大小
50   - * @property {Boolean} checked 是否默认选中
51   - * @property {String | Boolean} disabled 是否禁用
52   - * @property {String} activeColor 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值
53   - * @property {String} inactiveColor 未选中的颜色
54   - * @property {String | Number} iconSize 图标的大小,单位px
55   - * @property {String} iconColor 图标颜色
56   - * @property {String | Number} label label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式
57   - * @property {String} labelColor label的颜色
58   - * @property {String | Number} labelSize label的字体大小,px单位
59   - * @property {String | Boolean} labelDisabled 是否禁止点击提示语选中复选框
60   - * @property {Object} customStyle 定义需要用到的外部样式
61   - *
62   - * @event {Function} change 任一个checkbox状态发生变化时触发,回调为一个对象
63   - * @example <u-checkbox v-model="checked" :disabled="false">天涯</u-checkbox>
64   - */
65   - export default {
66   - name: "u-checkbox",
67   - mixins: [mpMixin, mixin, props],
68   - data() {
69   - return {
70   - isChecked: false,
71   - // 父组件的默认值,因为头条小程序不支持在computed中使用this.parent.shape的形式
72   - // 故只能使用如此方法
73   - parentData: {
74   - iconSize: 12,
75   - labelDisabled: null,
76   - disabled: null,
77   - shape: 'square',
78   - activeColor: null,
79   - inactiveColor: null,
80   - size: 18,
81   - // #ifdef VUE2
82   - value: null,
83   - // #endif
84   - // #ifdef VUE3
85   - modelValue: null,
86   - // #endif
87   - iconColor: null,
88   - placement: 'row',
89   - borderBottom: false,
90   - iconPlacement: 'left'
91   - }
92   - }
93   - },
94   - computed: {
95   - // 是否禁用,如果父组件u-radios-group禁用的话,将会忽略子组件的配置
96   - elDisabled() {
97   - return this.disabled !== '' ? this.disabled : this.parentData.disabled !== null ? this.parentData.disabled : false;
98   - },
99   - // 是否禁用label点击
100   - elLabelDisabled() {
101   - return this.labelDisabled !== '' ? this.labelDisabled : this.parentData.labelDisabled !== null ? this.parentData.labelDisabled :
102   - false;
103   - },
104   - // 组件尺寸,对应size的值,默认值为21px
105   - elSize() {
106   - return this.size ? this.size : (this.parentData.size ? this.parentData.size : 21);
107   - },
108   - // 组件的勾选图标的尺寸,默认12px
109   - elIconSize() {
110   - return this.iconSize ? this.iconSize : (this.parentData.iconSize ? this.parentData.iconSize : 12);
111   - },
112   - // 组件选中激活时的颜色
113   - elActiveColor() {
114   - return this.activeColor ? this.activeColor : (this.parentData.activeColor ? this.parentData.activeColor : '#2979ff');
115   - },
116   - // 组件选未中激活时的颜色
117   - elInactiveColor() {
118   - return this.inactiveColor ? this.inactiveColor : (this.parentData.inactiveColor ? this.parentData.inactiveColor :
119   - '#c8c9cc');
120   - },
121   - // label的颜色
122   - elLabelColor() {
123   - return this.labelColor ? this.labelColor : (this.parentData.labelColor ? this.parentData.labelColor : '#606266')
124   - },
125   - // 组件的形状
126   - elShape() {
127   - return this.shape ? this.shape : (this.parentData.shape ? this.parentData.shape : 'circle');
128   - },
129   - // label大小
130   - elLabelSize() {
131   - return addUnit(this.labelSize ? this.labelSize : (this.parentData.labelSize ? this.parentData.labelSize :
132   - '15'))
133   - },
134   - elIconColor() {
135   - const iconColor = this.iconColor ? this.iconColor : (this.parentData.iconColor ? this.parentData.iconColor :
136   - '#ffffff');
137   - // 图标的颜色
138   - if (this.elDisabled) {
139   - // disabled状态下,已勾选的checkbox图标改为elInactiveColor
140   - return this.isChecked ? this.elInactiveColor : 'transparent'
141   - } else {
142   - return this.isChecked ? iconColor : 'transparent'
143   - }
144   - },
145   - iconClasses() {
146   - let classes = []
147   - // 组件的形状
148   - classes.push('u-checkbox__icon-wrap--' + this.elShape)
149   - if (this.elDisabled) {
150   - classes.push('u-checkbox__icon-wrap--disabled')
151   - }
152   - if (this.isChecked && this.elDisabled) {
153   - classes.push('u-checkbox__icon-wrap--disabled--checked')
154   - }
155   - // 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效
156   - // #ifdef MP-ALIPAY || MP-TOUTIAO
157   - classes = classes.join(' ')
158   - // #endif
159   - return classes
160   - },
161   - iconWrapStyle() {
162   - // checkbox的整体样式
163   - const style = {}
164   - style.backgroundColor = this.isChecked && !this.elDisabled ? this.elActiveColor : '#ffffff'
165   - style.borderColor = this.isChecked && !this.elDisabled ? this.elActiveColor : this.elInactiveColor
166   - style.width = addUnit(this.elSize)
167   - style.height = addUnit(this.elSize)
168   - // 如果是图标在右边的话,移除它的右边距
169   - if (!this.usedAlone) {
170   - if (this.parentData.iconPlacement === 'right') {
171   - style.marginRight = 0
172   - }
173   - }
174   - return style
175   - },
176   - checkboxStyle() {
177   - const style = {}
178   - if (!this.usedAlone) {
179   - if (this.parentData.borderBottom && this.parentData.placement === 'row') {
180   - error('检测到您将borderBottom设置为true,需要同时将up-checkbox-group的placement设置为column才有效')
181   - }
182   - // 当父组件设置了显示下边框并且排列形式为纵向时,给内容和边框之间加上一定间隔
183   - if (this.parentData.borderBottom && this.parentData.placement === 'column') {
184   - style.paddingBottom = '8px'
185   - }
186   - }
187   - return deepMerge(style, addStyle(this.customStyle))
188   - }
189   - },
190   - mounted() {
191   - this.init()
192   - },
193   - emits: ["change", "update:checked"],
194   - methods: {
195   - init() {
196   - if (!this.usedAlone) {
197   - // 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环引用
198   - this.updateParentData()
199   - if (!this.parent) {
200   - error('up-checkbox必须搭配up-checkbox-group组件使用')
201   - }
202   - let value = '';
203   - // #ifdef VUE2
204   - value = this.parentData.value
205   - // #endif
206   - // #ifdef VUE3
207   - value = this.parentData.modelValue
208   - // #endif
209   - // 设置初始化时,是否默认选中的状态,父组件u-checkbox-group的value可能是array,所以额外判断
210   - if (this.checked) {
211   - this.isChecked = true
212   - } else if (!this.usedAlone && test.array(value)) {
213   - // 查找数组是是否存在this.name元素值
214   - this.isChecked = value.some(item => {
215   - return item === this.name
216   - })
217   - }
218   - } else {
219   - if (this.checked) {
220   - this.isChecked = true
221   - }
222   - }
223   - },
224   - updateParentData() {
225   - this.getParentData('u-checkbox-group')
226   - },
227   - // 横向两端排列时,点击组件即可触发选中事件
228   - wrapperClickHandler(e) {
229   - if (!this.usedAlone) {
230   - this.parentData.iconPlacement === 'right' && this.iconClickHandler(e)
231   - } else {
232   - this.iconClickHandler(e)
233   - }
234   - },
235   - // 点击图标
236   - iconClickHandler(e) {
237   - this.preventEvent(e)
238   - // 如果整体被禁用,不允许被点击
239   - if (!this.elDisabled) {
240   - this.setRadioCheckedStatus()
241   - }
242   - },
243   - // 点击label
244   - labelClickHandler(e) {
245   - this.preventEvent(e)
246   - // 如果按钮整体被禁用或者label被禁用,则不允许点击文字修改状态
247   - if (!this.elLabelDisabled && !this.elDisabled) {
248   - this.setRadioCheckedStatus()
249   - }
250   - },
251   - emitEvent() {
252   - this.$emit('change', this.isChecked, {
253   - name: this.name
254   - })
255   - // 双向绑定
256   - if (this.usedAlone) {
257   - this.$emit('update:checked', this.isChecked)
258   - }
259   - // 尝试调用u-form的验证方法,进行一定延迟,否则微信小程序更新可能会不及时
260   - this.$nextTick(() => {
261   - formValidate(this, 'change')
262   - })
263   - },
264   - // 改变组件选中状态
265   - // 这里的改变的依据是,更改本组件的checked值为true,同时通过父组件遍历所有u-checkbox实例
266   - // 将本组件外的其他u-checkbox的checked都设置为false(都被取消选中状态),因而只剩下一个为选中状态
267   - setRadioCheckedStatus() {
268   - // 将本组件标记为与原来相反的状态
269   - this.isChecked = !this.isChecked
270   - this.emitEvent()
271   - if (!this.usedAlone) {
272   - typeof this.parent.unCheckedOther === 'function' && this.parent.unCheckedOther(this)
273   - }
274   - }
275   - },
276   - watch:{
277   - checked(newValue, oldValue){
278   - if (newValue !== this.isChecked) {
279   - this.isChecked = newValue
280   - }
281   - }
282   - }
283   - }
284   -</script>
285   -
286   -<style lang="scss" scoped>
287   - $u-checkbox-icon-wrap-margin-right:6px !default;
288   - $u-checkbox-icon-wrap-font-size:6px !default;
289   - $u-checkbox-icon-wrap-border-width:1px !default;
290   - $u-checkbox-icon-wrap-border-color:#c8c9cc !default;
291   - $u-checkbox-icon-wrap-icon-line-height:0 !default;
292   - $u-checkbox-icon-wrap-circle-border-radius:100% !default;
293   - $u-checkbox-icon-wrap-square-border-radius:3px !default;
294   - $u-checkbox-icon-wrap-checked-color:#fff !default;
295   - $u-checkbox-icon-wrap-checked-background-color:red !default;
296   - $u-checkbox-icon-wrap-checked-border-color:#2979ff !default;
297   - $u-checkbox-icon-wrap-disabled-background-color:#ebedf0 !default;
298   - $u-checkbox-icon-wrap-disabled-checked-color:#c8c9cc !default;
299   - $u-checkbox-label-margin-left:5px !default;
300   - $u-checkbox-label-margin-right:12px !default;
301   - $u-checkbox-label-color:$u-content-color !default;
302   - $u-checkbox-label-font-size:15px !default;
303   - $u-checkbox-label-disabled-color:#c8c9cc !default;
304   -
305   - .u-checkbox {
306   - /* #ifndef APP-NVUE */
307   - @include flex(row);
308   - /* #endif */
309   - overflow: hidden;
310   - flex-direction: row;
311   - align-items: center;
312   - margin-bottom: 5px;
313   - margin-top: 5px;
314   -
315   - &-label--left {
316   - flex-direction: row
317   - }
318   -
319   - &-label--right {
320   - flex-direction: row-reverse;
321   - justify-content: space-between
322   - }
323   -
324   - &__icon-wrap {
325   - /* #ifndef APP-NVUE */
326   - box-sizing: border-box;
327   - // nvue下,border-color过渡有问题
328   - transition-property: border-color, background-color, color;
329   - transition-duration: 0.2s;
330   - /* #endif */
331   - color: $u-content-color;
332   - @include flex;
333   - align-items: center;
334   - justify-content: center;
335   - color: transparent;
336   - text-align: center;
337   - margin-right: $u-checkbox-icon-wrap-margin-right;
338   -
339   - font-size: $u-checkbox-icon-wrap-font-size;
340   - border-width: $u-checkbox-icon-wrap-border-width;
341   - border-color: $u-checkbox-icon-wrap-border-color;
342   - border-style: solid;
343   -
344   - /* #ifdef MP-TOUTIAO */
345   - // 头条小程序兼容性问题,需要设置行高为0,否则图标偏下
346   - &__icon {
347   - line-height: $u-checkbox-icon-wrap-icon-line-height;
348   - }
349   -
350   - /* #endif */
351   -
352   - &--circle {
353   - border-radius: $u-checkbox-icon-wrap-circle-border-radius;
354   - }
355   -
356   - &--square {
357   - border-radius: $u-checkbox-icon-wrap-square-border-radius;
358   - }
359   -
360   - &--checked {
361   - color: $u-checkbox-icon-wrap-checked-color;
362   - background-color: $u-checkbox-icon-wrap-checked-background-color;
363   - border-color: $u-checkbox-icon-wrap-checked-border-color;
364   - }
365   -
366   - &--disabled {
367   - background-color: $u-checkbox-icon-wrap-disabled-background-color !important;
368   - }
369   -
370   - &--disabled--checked {
371   - color: $u-checkbox-icon-wrap-disabled-checked-color !important;
372   - }
373   - }
374   -
375   - &__label {
376   - /* #ifndef APP-NVUE */
377   - word-wrap: break-word;
378   - /* #endif */
379   - margin-left: $u-checkbox-label-margin-left;
380   - margin-right: $u-checkbox-label-margin-right;
381   - color: $u-checkbox-label-color;
382   - font-size: $u-checkbox-label-font-size;
383   -
384   - &--disabled {
385   - color: $u-checkbox-label-disabled-color;
386   - }
387   - }
388   - }
389   -</style>
uni_modules/uview-plus/components/u-choose/u-choose.vue deleted
1   -<style scoped lang="scss">
2   - .up-choose {
3   - ::v-deep .up-tag {
4   - font-weight: 600;
5   - }
6   - &:last-child {
7   - margin-right: 0;
8   - }
9   - }
10   -
11   - .up-choose-wrap {
12   - flex-wrap: wrap;
13   - }
14   -
15   - .up-choose-nowrap {
16   - flex-wrap: nowrap;
17   - white-space: nowrap;
18   - }
19   -</style>
20   -
21   -<template>
22   - <scroll-view
23   - :scroll-x="wrap === false"
24   - :class="['up-choose', wrap ? 'up-choose-wrap' : 'up-choose-nowrap']">
25   - <template :key="item.id" v-for="(item,index) in options">
26   - <view :style="{width: itemWidth, display: 'inline-block'}">
27   - <slot :item="item" :index="index">
28   - <up-tag :type="index == currentIndex ? 'primary' : 'info'"
29   - size="large" :plain="index == currentIndex ? false : true"
30   - :class="currentIndex === index ? 'active': ''" :height="itemHeight"
31   - :style="{width: itemWidth, padding: itemPadding}"
32   - @click="change(index)">
33   - {{item[labelName]}}
34   - </up-tag>
35   - </slot>
36   - </view>
37   - </template>
38   - </scroll-view>
39   -</template>
40   -
41   -<script>
42   - export default {
43   - name: 'up-choose',
44   - props: {
45   - options:{
46   - type: Array,
47   - default: ()=>{
48   - return [];
49   - }
50   - },
51   - modelValue: {
52   - type: [Number,String,Array],
53   - default: false
54   - },
55   - type: {
56   - type: [String],
57   - default: 'radio'
58   - },
59   - itemWidth: {
60   - type: [String],
61   - default: 'auto'
62   - },
63   - itemHeight: {
64   - type: [String],
65   - default: '50px'
66   - },
67   - itemPadding: {
68   - type: [String],
69   - default: '8px'
70   - },
71   - labelName: {
72   - type: String,
73   - default: 'title'
74   - },
75   - valueName: {
76   - type: String,
77   - default: 'value'
78   - },
79   - customClick: {
80   - type: Boolean,
81   - default: false
82   - },
83   - // 是否换行
84   - wrap: {
85   - type: Boolean,
86   - default: true
87   - }
88   - },
89   - data() {
90   - return {
91   - currentIndex: ''
92   - }
93   - },
94   - created: function () {
95   - this.currentIndex = this.modelValue;
96   - },
97   - emits: ['update:modelValue', 'custom-click'],
98   - methods: {
99   - change(index){
100   - if (this.customClick) {
101   - this.$emit('custom-click', index);
102   - } else {
103   - this.currentIndex = index;
104   - this.$emit('update:modelValue', index);
105   - }
106   - }
107   - }
108   - }
109   -</script>
110 0 \ No newline at end of file
uni_modules/uview-plus/components/u-circle-progress/circleProgress.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:55:02
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/circleProgress.js
9   - */
10   -export default {
11   - // circleProgress 组件
12   - circleProgress: {
13   - percentage: 30
14   - }
15   -}
uni_modules/uview-plus/components/u-circle-progress/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - percentage: {
6   - type: [String, Number],
7   - default: () => defProps.circleProgress.percentage
8   - }
9   - }
10   -})
uni_modules/uview-plus/components/u-circle-progress/u-circle-progress.vue deleted
1   -<template>
2   - <view class="u-circle-progress">
3   - <view class="u-circle-progress__left">
4   - <view
5   - class="u-circle-progress__left__circle"
6   - :style="[leftSyle]"
7   - ref="left-circle"
8   - >
9   -
10   - </view>
11   - </view>
12   - <view
13   - class="u-circle-progress__right"
14   - >
15   - <view
16   - class="u-circle-progress__right__circle"
17   - ref="right-circle"
18   - :style="[rightSyle]"
19   - >
20   -
21   - </view>
22   - </view>
23   - <view class="u-circle-progress__circle">
24   -
25   - </view>
26   - </view>
27   -</template>
28   -
29   -<script>
30   - import { props } from './props';
31   - import { mpMixin } from '../../libs/mixin/mpMixin';
32   - import { mixin } from '../../libs/mixin/mixin';
33   - import {sleep } from '../../libs/function/index';
34   - // #ifdef APP-NVUE
35   - const animation = uni.requireNativePlugin('animation')
36   - // #endif
37   - /**
38   - * CircleProgress 圆形进度条 TODO: 待完善
39   - * @description 展示操作或任务的当前进度,比如上传文件,是一个圆形的进度环。
40   - * @tutorial https://uview-plus.jiangruyi.com/components/circleProgress.html
41   - * @property {String | Number} percentage 圆环进度百分比值,为数值类型,0-100 (默认 30 )
42   - * @example
43   - */
44   - export default {
45   - name: 'u-circle-progress',
46   - mixins: [mpMixin, mixin, props],
47   - data() {
48   - return {
49   - leftBorderColor: 'rgb(200, 200, 200)',
50   - rightBorderColor: 'rgb(200, 200, 200)',
51   - }
52   - },
53   - computed: {
54   - leftSyle() {
55   - const style = {}
56   - style.borderTopColor = this.leftBorderColor
57   - style.borderRightColor = this.leftBorderColor
58   - return style
59   - },
60   - rightSyle() {
61   - const style = {}
62   - style.borderLeftColor = this.rightBorderColor
63   - style.borderBottomColor = this.rightBorderColor
64   - return style
65   - }
66   - },
67   - mounted() {
68   - sleep().then(() => {
69   - this.rightBorderColor = 'rgb(66, 185, 131)'
70   - // this.init()
71   - })
72   - },
73   - methods: {
74   - init() {
75   - animation.transition(this.$refs['right-circle'].ref, {
76   - styles: {
77   - transform: 'rotate(45deg)',
78   - transformOrigin: 'center center'
79   - },
80   - }, () => {
81   - this.rightBorderColor = 'rgb(66, 185, 131)'
82   - // animation.transition(this.$refs['right-circle'].ref, {
83   - // styles: {
84   - // transform: 'rotate(225deg)',
85   - // transformOrigin: 'center center'
86   - // },
87   - // duration: 3000,
88   - // }, () => {
89   - // animation.transition(this.$refs['left-circle'].ref, {
90   - // styles: {
91   - // transform: 'rotate(45deg)',
92   - // transformOrigin: 'center center'
93   - // },
94   - // }, () => {
95   - // this.leftBorderColor = 'rgb(66, 185, 131)'
96   - // animation.transition(this.$refs['left-circle'].ref, {
97   - // styles: {
98   - // transform: 'rotate(225deg)',
99   - // transformOrigin: 'center center'
100   - // },
101   - // duration: 1500,
102   - // }, () => {
103   -
104   - // })
105   - // })
106   - // })
107   - })
108   -
109   - }
110   - },
111   - }
112   -</script>
113   -
114   -<style lang="scss" scoped>
115   -
116   - .u-circle-progress {
117   - @include flex(row);
118   - position: relative;
119   - border-radius: 100px;
120   - height: 100px;
121   - width: 100px;
122   - // transform: rotate(0deg);
123   - // background-color: rgb(66, 185, 131);
124   - background-color: rgb(200, 200, 200);
125   - overflow: hidden;
126   - justify-content: space-between;
127   -
128   - &__circle {
129   - border-radius: 100px;
130   - height: 90px;
131   - width: 90px;
132   - transform: translate(-50%, -50%);
133   - background-color: rgb(255, 255, 255);
134   - left: 50px;
135   - top: 50px;
136   - position: absolute;
137   - }
138   -
139   - &__left {
140   - position: absolute;
141   - left: 0;
142   - width: 50px;
143   - height: 100px;
144   - overflow: hidden;
145   - box-sizing: border-box;
146   - // background-color: rgb(66, 185, 131);
147   - // background-color: rgb(200, 200, 200);
148   - // transform-origin: left center;
149   -
150   - &__circle {
151   - box-sizing: border-box;
152   - // background-color: red;
153   - border-left-color: transparent;
154   - border-bottom-color: transparent;
155   - border-top-left-radius: 50px;
156   - border-top-right-radius: 50px;
157   - border-bottom-right-radius: 50px;
158   - // border-left-color: rgb(66, 185, 131);
159   - // border-bottom-color: rgb(66, 185, 131);
160   - border-top-color: rgb(66, 185, 131);
161   - border-right-color: rgb(66, 185, 131);
162   - border-width: 5px;
163   - width: 100px;
164   - height: 100px;
165   - transform: rotate(225deg);
166   - // border-radius: 100px;
167   - }
168   - }
169   -
170   - &__right {
171   - position: absolute;
172   - right: 0;
173   - width: 50px;
174   - height: 100px;
175   - overflow: hidden;
176   -
177   - &__circle {
178   - position: absolute;
179   - right: 0;
180   - box-sizing: border-box;
181   - // background-color: red;
182   - border-top-color: transparent;
183   - border-right-color: transparent;
184   - border-top-left-radius: 50px;
185   - border-bottom-left-radius: 50px;
186   - border-bottom-right-radius: 50px;
187   - // border-left-color: rgb(66, 185, 131);
188   - // border-bottom-color: rgb(66, 185, 131);
189   - border-left-color: rgb(200, 200, 200);
190   - border-bottom-color: rgb(200, 200, 200);
191   - border-width: 5px;
192   - width: 100px;
193   - height: 100px;
194   - transform: rotate(45deg);
195   - transform-origin: center center;
196   - // border-radius: 100px;
197   - }
198   - }
199   - }
200   -</style>
uni_modules/uview-plus/components/u-city-locate/u-city-locate.vue deleted
1   -<template>
2   - <view class="u-city-locate">
3   - <up-index-list :indexList="indexList">
4   - <template #header>
5   - <view class="u-current-city-wrap">
6   - <view class="u-current-city-title">{{ t("up.cityLocate.locateCity") }}</view>
7   - <view class="u-current-city-item" @tap="location">
8   - <view class="u-location-city">{{locationCity}}</view>
9   - </view>
10   - </view>
11   - </template>
12   - <template :key="index" v-for="(item, index) in cityList">
13   - <!-- #ifdef APP-NVUE -->
14   - <up-index-anchor :text="indexList[index]"></up-index-anchor>
15   - <!-- #endif -->
16   - <up-index-item>
17   - <!-- #ifndef APP-NVUE -->
18   - <up-index-anchor :text="indexList[index]"></up-index-anchor>
19   - <!-- #endif -->
20   - <view class="hot-city-list" v-if="index == 0">
21   - <view class="" v-for="(item1, index1) in item" @tap="selectedCity(item1)">
22   - <view class="hot-city-item">{{ item1[nameKey] }}</view>
23   - </view>
24   - </view>
25   - <view v-else class="item-list" v-for="(item1, index1) in item" :key="index1">
26   - <view class="list__item" @tap="selectedCity(item1)">
27   - <text class="list__item__city-name">{{item1[nameKey]}}</text>
28   - </view>
29   - <up-line></up-line>
30   - </view>
31   - </up-index-item>
32   - </template>
33   - <template #footer>
34   - <view class="u-safe-area-inset--bottom">
35   - <text class="list__footer"></text>
36   - </view>
37   - </template>
38   - </up-index-list>
39   - </view>
40   -</template>
41   -
42   -<script>
43   - import { t } from '../../libs/i18n'
44   - export default{
45   - name: 'u-city-locate',
46   - props:{
47   - indexList: {
48   - type: Array,
49   - default: ['🔥']
50   - },
51   - cityList:{
52   - type: Array,
53   - default: () => {
54   - return [
55   - [{
56   - name: '北京',
57   - value: 'beijing'
58   - },
59   - {
60   - name: '上海',
61   - value: 'shanghai'
62   - },
63   - {
64   - name: '广州',
65   - value: 'guangzhou'
66   - },
67   - {
68   - name: '深圳',
69   - value: 'shenzhen'
70   - },
71   - {
72   - name: '杭州',
73   - value: 'hangzhou'
74   - }]
75   - ]
76   - }
77   - },
78   - locationType: {
79   - type: String,
80   - default: 'wgs84'
81   - },
82   - currentCity: {
83   - type: String,
84   - default: ''
85   - },
86   - nameKey: {
87   - type: String,
88   - default: 'name'
89   - }
90   - },
91   - computed:{
92   - },
93   - watch:{
94   - currentCity(val) {
95   - this.locationCity = val;
96   - }
97   - },
98   - data(){
99   - return{
100   - locationCity: t("up.cityLocate.locating") + '....'
101   - }
102   - },
103   - emits: ['location-success', 'select-city'],
104   - methods:{
105   - t,
106   - // 获取城市
107   - selectedCity(city){
108   - this.locationCity = city[this.nameKey];
109   - this.$emit('select-city', {
110   - locationCity: this.locationCity
111   - });
112   - },
113   - // 定位操作
114   - location(){
115   - let That = this;
116   - uni.getLocation({
117   - type: this.locationType,
118   - geocode:true,
119   - success(res){
120   - console.log(res);
121   - That.locationCity = res.address && res.address.city;
122   - That.$emit('location-success', {
123   - ...res,
124   - locationCity: That.locationCity
125   - });
126   - },
127   - fail(){
128   - That.locationCity = t("up.cityLocate.fail");
129   - }
130   - });
131   - },
132   - },
133   - // 页面挂载后进行异步操作
134   - created(){
135   - },
136   - mounted(){
137   - this.location();
138   - }
139   - }
140   -</script>
141   -
142   -<style lang="scss">
143   - .list__item {
144   - padding: 8px 1px;
145   - }
146   - .u-current-city-title {
147   - color: grey;
148   - margin-bottom: 5px;
149   - }
150   - .u-current-city-item {
151   - height: 30px;
152   - }
153   - .hot-city-list {
154   - display: flex !important;
155   - flex-direction: row !important;
156   - padding: 12px 0;
157   - .hot-city-item {
158   - padding: 6px 12px;
159   - margin: 5px;
160   - border: 1px solid #ededed;
161   - }
162   - }
163   -</style>
uni_modules/uview-plus/components/u-code-input/codeInput.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:55:58
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/codeInput.js
9   - */
10   -export default {
11   - // codeInput 组件
12   - codeInput: {
13   - adjustPosition: true,
14   - maxlength: 6,
15   - dot: false,
16   - mode: 'box',
17   - hairline: false,
18   - space: 10,
19   - value: '',
20   - focus: false,
21   - bold: false,
22   - color: '#606266',
23   - fontSize: 18,
24   - size: 35,
25   - disabledKeyboard: false,
26   - borderColor: '#c9cacc',
27   - disabledDot: true
28   - }
29   -}
uni_modules/uview-plus/components/u-code-input/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 键盘弹起时,是否自动上推页面
6   - adjustPosition: {
7   - type: Boolean,
8   - default: () => defProps.codeInput.adjustPosition
9   - },
10   - // 最大输入长度
11   - maxlength: {
12   - type: [String, Number],
13   - default: () => defProps.codeInput.maxlength
14   - },
15   - // 是否用圆点填充
16   - dot: {
17   - type: Boolean,
18   - default: () => defProps.codeInput.dot
19   - },
20   - // 显示模式,box-盒子模式,line-底部横线模式
21   - mode: {
22   - type: String,
23   - default: () => defProps.codeInput.mode
24   - },
25   - // 是否细边框
26   - hairline: {
27   - type: Boolean,
28   - default: () => defProps.codeInput.hairline
29   - },
30   - // 字符间的距离
31   - space: {
32   - type: [String, Number],
33   - default: () => defProps.codeInput.space
34   - },
35   - // #ifdef VUE3
36   - // 预置值
37   - modelValue: {
38   - type: [String, Number],
39   - default: () => defProps.codeInput.value
40   - },
41   - // #endif
42   - // #ifdef VUE2
43   - // 预置值
44   - value: {
45   - type: [String, Number],
46   - default: () => defProps.codeInput.value
47   - },
48   - // #endif
49   - // 是否自动获取焦点
50   - focus: {
51   - type: Boolean,
52   - default: () => defProps.codeInput.focus
53   - },
54   - // 字体是否加粗
55   - bold: {
56   - type: Boolean,
57   - default: () => defProps.codeInput.bold
58   - },
59   - // 字体颜色
60   - color: {
61   - type: String,
62   - default: () => defProps.codeInput.color
63   - },
64   - // 字体大小
65   - fontSize: {
66   - type: [String, Number],
67   - default: () => defProps.codeInput.fontSize
68   - },
69   - // 输入框的大小,宽等于高
70   - size: {
71   - type: [String, Number],
72   - default: () => defProps.codeInput.size
73   - },
74   - // 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true
75   - disabledKeyboard: {
76   - type: Boolean,
77   - default: () => defProps.codeInput.disabledKeyboard
78   - },
79   - // 边框和线条颜色
80   - borderColor: {
81   - type: String,
82   - default: () => defProps.codeInput.borderColor
83   - },
84   - // 是否禁止输入"."符号
85   - disabledDot: {
86   - type: Boolean,
87   - default: () => defProps.codeInput.disabledDot
88   - }
89   - }
90   -})
uni_modules/uview-plus/components/u-code-input/u-code-input.vue deleted
1   -<template>
2   - <view class="u-code-input">
3   - <view
4   - class="u-code-input__item"
5   - :style="[itemStyle(index)]"
6   - v-for="(item, index) in codeLength"
7   - :key="index"
8   - >
9   - <view
10   - class="u-code-input__item__dot"
11   - v-if="dot && codeArray.length > index"
12   - ></view>
13   - <text
14   - v-else
15   - :style="{
16   - fontSize: addUnit(fontSize),
17   - fontWeight: bold ? 'bold' : 'normal',
18   - color: color
19   - }"
20   - >{{codeArray[index]}}</text>
21   - <view
22   - class="u-code-input__item__line"
23   - v-if="mode === 'line'"
24   - :style="[lineStyle]"
25   - ></view>
26   - <!-- #ifndef APP-NVUE -->
27   - <view v-if="isFocus && codeArray.length === index"
28   - :style="{backgroundColor: color}" class="u-code-input__item__cursor"></view>
29   - <!-- #endif -->
30   - <!-- #ifdef APP-NVUE -->
31   - <view v-if="isFocus && codeArray.length === index"
32   - :style="{backgroundColor: color, opacity: opacity}" class="u-code-input__item__cursor"></view>
33   - <!-- #endif -->
34   - </view>
35   - <input
36   - :disabled="disabledKeyboard"
37   - type="number"
38   - :focus="focus"
39   - :value="inputValue"
40   - :maxlength="maxlength"
41   - :adjustPosition="adjustPosition"
42   - class="u-code-input__input"
43   - @input="inputHandler"
44   - :style="{
45   - height: addUnit(size)
46   - }"
47   - @focus="isFocus = true"
48   - @blur="isFocus = false"
49   - />
50   - </view>
51   -</template>
52   -
53   -<script>
54   - import { props } from './props';
55   - import { mpMixin } from '../../libs/mixin/mpMixin';
56   - import { mixin } from '../../libs/mixin/mixin';
57   - import { addUnit, getPx } from '../../libs/function/index';
58   - /**
59   - * CodeInput 验证码输入
60   - * @description 该组件一般用于验证用户短信验证码的场景,也可以结合uview-plus的键盘组件使用
61   - * @tutorial https://uview-plus.jiangruyi.com/components/codeInput.html
62   - * @property {String | Number} maxlength 最大输入长度 (默认 6 )
63   - * @property {Boolean} dot 是否用圆点填充 (默认 false )
64   - * @property {String} mode 显示模式,box-盒子模式,line-底部横线模式 (默认 'box' )
65   - * @property {Boolean} hairline 是否细边框 (默认 false )
66   - * @property {String | Number} space 字符间的距离 (默认 10 )
67   - * @property {String | Number} value 预置值
68   - * @property {Boolean} focus 是否自动获取焦点 (默认 false )
69   - * @property {Boolean} bold 字体和输入横线是否加粗 (默认 false )
70   - * @property {String} color 字体颜色 (默认 '#606266' )
71   - * @property {String | Number} fontSize 字体大小,单位px (默认 18 )
72   - * @property {String | Number} size 输入框的大小,宽等于高 (默认 35 )
73   - * @property {Boolean} disabledKeyboard 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true (默认 false )
74   - * @property {String} borderColor 边框和线条颜色 (默认 '#c9cacc' )
75   - * @property {Boolean} disabledDot 是否禁止输入"."符号 (默认 true )
76   - *
77   - * @event {Function} change 输入内容发生改变时触发,具体见上方说明 value:当前输入的值
78   - * @event {Function} finish 输入字符个数达maxlength值时触发,见上方说明 value:当前输入的值
79   - * @example <u-code-input v-model="value4" :focus="true"></u-code-input>
80   - */
81   - export default {
82   - name: 'u-code-input',
83   - mixins: [mpMixin, mixin, props],
84   - data() {
85   - return {
86   - inputValue: '',
87   - isFocus: this.focus,
88   - timer: null,
89   - opacity: 1
90   - }
91   - },
92   - watch: {
93   - // #ifdef VUE2
94   - value: {
95   - immediate: true,
96   - handler(val) {
97   - // 转为字符串,超出部分截掉
98   - this.inputValue = String(val).substring(0, this.maxlength)
99   - }
100   - },
101   - // #endif
102   - // #ifdef VUE3
103   - modelValue: {
104   - immediate: true,
105   - handler(val) {
106   - // 转为字符串,超出部分截掉
107   - this.inputValue = String(val).substring(0, this.maxlength)
108   - }
109   - },
110   - // #endif
111   - isFocus: {
112   - handler(val) {
113   - // #ifdef APP-NVUE
114   - if (val) {
115   - this.timer = setInterval(() => {
116   - this.opacity = Math.abs(this.opacity - 1)
117   - }, 600)
118   - } else {
119   - clearInterval(this.timer)
120   - }
121   - // #endif
122   - }
123   - }
124   - },
125   - created() {
126   -
127   - },
128   - beforeUnmount() {
129   - // #ifdef APP-NVUE
130   - clearInterval(this.timer)
131   - // #endif
132   - },
133   - computed: {
134   - // 根据长度,循环输入框的个数,因为头条小程序数值不能用于v-for
135   - codeLength() {
136   - return new Array(Number(this.maxlength))
137   - },
138   - // 循环item的样式
139   - itemStyle() {
140   - return index => {
141   - const style = {
142   - width: addUnit(this.size),
143   - height: addUnit(this.size)
144   - }
145   - // 盒子模式下,需要额外进行处理
146   - if (this.mode === 'box') {
147   - // 设置盒子的边框,如果是细边框,则设置为0.5px宽度
148   - style.border = `${this.hairline ? 0.5 : 1}px solid ${this.borderColor}`
149   - // 如果盒子间距为0的话
150   - if (getPx(this.space) === 0) {
151   - // 给第一和最后一个盒子设置圆角
152   - if (index === 0) {
153   - style.borderTopLeftRadius = '3px'
154   - style.borderBottomLeftRadius = '3px'
155   - }
156   - if (index === this.codeLength.length - 1) {
157   - style.borderTopRightRadius = '3px'
158   - style.borderBottomRightRadius = '3px'
159   - }
160   - // 最后一个盒子的右边框需要保留
161   - if (index !== this.codeLength.length - 1) {
162   - style.borderRight = 'none'
163   - }
164   - }
165   - }
166   - if (index !== this.codeLength.length - 1) {
167   - // 设置验证码字符之间的距离,通过margin-right设置,最后一个字符,无需右边框
168   - style.marginRight = addUnit(this.space)
169   - } else {
170   - // 最后一个盒子的有边框需要保留
171   - style.marginRight = 0
172   - }
173   -
174   - return style
175   - }
176   - },
177   - // 将输入的值,转为数组,给item历遍时,根据当前的索引显示数组的元素
178   - codeArray() {
179   - return String(this.inputValue).split('')
180   - },
181   - // 下划线模式下,横线的样式
182   - lineStyle() {
183   - const style = {}
184   - style.height = this.hairline ? '2px' : '4px'
185   - style.width = addUnit(this.size)
186   - // 线条模式下,背景色即为边框颜色
187   - style.backgroundColor = this.borderColor
188   - return style
189   - }
190   - },
191   - emits: ["change", 'finish', "update:modelValue"],
192   - methods: {
193   - addUnit,
194   - // 监听输入框的值发生变化
195   - inputHandler(e) {
196   - const value = e.detail.value
197   - this.inputValue = value
198   - // 是否允许输入“.”符号
199   - if(this.disabledDot) {
200   - this.$nextTick(() => {
201   - this.inputValue = value.replace('.', '')
202   - })
203   - }
204   - // 未达到maxlength之前,发送change事件,达到后发送finish事件
205   - this.$emit('change', value)
206   - // 修改通过v-model双向绑定的值
207   - // #ifdef VUE3
208   - this.$emit("update:modelValue", value);
209   - // #endif
210   - // #ifdef VUE2
211   - this.$emit("input", value);
212   - // #endif
213   - // 达到用户指定输入长度时,发出完成事件
214   - if (String(value).length >= Number(this.maxlength)) {
215   - this.$emit('finish', value)
216   - }
217   - }
218   - }
219   - }
220   -</script>
221   -
222   -<style lang="scss" scoped>
223   - $u-code-input-cursor-width: 1px;
224   - $u-code-input-cursor-height: 20px;
225   - $u-code-input-cursor-animation-duration: 1s;
226   - $u-code-input-cursor-animation-name: u-cursor-flicker;
227   -
228   - .u-code-input {
229   - @include flex;
230   - position: relative;
231   - overflow: hidden;
232   -
233   - &__item {
234   - @include flex;
235   - justify-content: center;
236   - align-items: center;
237   - position: relative;
238   -
239   - &__text {
240   - font-size: 15px;
241   - color: $u-content-color;
242   - }
243   -
244   - &__dot {
245   - width: 7px;
246   - height: 7px;
247   - border-radius: 100px;
248   - background-color: $u-content-color;
249   - }
250   -
251   - &__line {
252   - position: absolute;
253   - bottom: 0;
254   - height: 4px;
255   - border-radius: 100px;
256   - width: 40px;
257   - background-color: $u-content-color;
258   - }
259   - &__cursor {
260   - position: absolute;
261   - /* #ifndef APP-NVUE */
262   - top: 50%;
263   - left: 50%;
264   - opacity: 1;
265   - transform: translate(-50%,-50%);
266   - /* #endif */
267   - width: $u-code-input-cursor-width;
268   - height: $u-code-input-cursor-height;
269   - animation: $u-code-input-cursor-animation-duration u-cursor-flicker infinite;
270   - }
271   - }
272   -
273   - &__input {
274   - // 之所以需要input输入框,是因为有它才能唤起键盘
275   - // 这里将它设置为两倍的屏幕宽度,再将左边的一半移出屏幕,为了不让用户看到输入的内容
276   - position: absolute;
277   - left: -750rpx;
278   - width: 1500rpx;
279   - top: 0;
280   - background-color: transparent;
281   - text-align: left;
282   - }
283   - }
284   -
285   - /* #ifndef APP-NVUE */
286   - @keyframes u-cursor-flicker {
287   - 0% {
288   - opacity: 0;
289   - }
290   - 50% {
291   - opacity: 1;
292   - }
293   - 100% {
294   - opacity: 0;
295   - }
296   - }
297   - /* #endif */
298   -
299   -</style>
uni_modules/uview-plus/components/u-code/code.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:55:27
8   - * @FilePath : /uview-plus/libs/config/props/code.js
9   - */
10   -import { t } from '../../libs/i18n'
11   -export default {
12   - // code 组件
13   - code: {
14   - seconds: 60,
15   - startText: t("up.code.send"),
16   - changeText: t("up.code.resendAfter"),
17   - endText: t("up.code.resend"),
18   - keepRunning: false,
19   - uniqueKey: ''
20   - }
21   -}
uni_modules/uview-plus/components/u-code/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 倒计时总秒数
6   - seconds: {
7   - type: [String, Number],
8   - default: () => defProps.code.seconds
9   - },
10   - // 尚未开始时提示
11   - startText: {
12   - type: String,
13   - default: () => defProps.code.startText
14   - },
15   - // 正在倒计时中的提示
16   - changeText: {
17   - type: String,
18   - default: () => defProps.code.changeText
19   - },
20   - // 倒计时结束时的提示
21   - endText: {
22   - type: String,
23   - default: () => defProps.code.endText
24   - },
25   - // 是否在H5刷新或各端返回再进入时继续倒计时
26   - keepRunning: {
27   - type: Boolean,
28   - default: () => defProps.code.keepRunning
29   - },
30   - // 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了
31   - uniqueKey: {
32   - type: String,
33   - default: () => defProps.code.uniqueKey
34   - }
35   - }
36   -})
uni_modules/uview-plus/components/u-code/u-code.vue deleted
1   -<template>
2   - <view class="u-code">
3   - <!-- 此组件功能由js完成,无需写html逻辑 -->
4   - </view>
5   -</template>
6   -
7   -<script>
8   - import { props } from './props';
9   - import { mpMixin } from '../../libs/mixin/mpMixin';
10   - import { mixin } from '../../libs/mixin/mixin';
11   - /**
12   - * Code 验证码输入框
13   - * @description 考虑到用户实际发送验证码的场景,可能是一个按钮,也可能是一段文字,提示语各有不同,所以本组件 不提供界面显示,只提供提示语,由用户将提示语嵌入到具体的场景
14   - * @tutorial https://uview-plus.jiangruyi.com/components/code.html
15   - * @property {String | Number} seconds 倒计时所需的秒数(默认 60 )
16   - * @property {String} startText 开始前的提示语,见官网说明(默认 '获取验证码' )
17   - * @property {String} changeText 倒计时期间的提示语,必须带有字母"x",见官网说明(默认 'X秒重新获取' )
18   - * @property {String} endText 倒计结束的提示语,见官网说明(默认 '重新获取' )
19   - * @property {Boolean} keepRunning 是否在H5刷新或各端返回再进入时继续倒计时( 默认false )
20   - * @property {String} uniqueKey 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了
21   - *
22   - * @event {Function} change 倒计时期间,每秒触发一次
23   - * @event {Function} start 开始倒计时触发
24   - * @event {Function} end 结束倒计时触发
25   - * @example <u-code ref="uCode" @change="codeChange" seconds="20"></u-code>
26   - */
27   - export default {
28   - name: "u-code",
29   - mixins: [mpMixin, mixin,props],
30   - data() {
31   - return {
32   - secNum: this.seconds,
33   - timer: null,
34   - canGetCode: true, // 是否可以执行验证码操作
35   - }
36   - },
37   - mounted() {
38   - this.checkKeepRunning()
39   - },
40   - watch: {
41   - seconds: {
42   - immediate: true,
43   - handler(n) {
44   - this.secNum = n
45   - }
46   - }
47   - },
48   - emits: ["start", "end", "change"],
49   - methods: {
50   - checkKeepRunning() {
51   - // 获取上一次退出页面(H5还包括刷新)时的时间戳,如果没有上次的保存,此值可能为空
52   - let lastTimestamp = Number(uni.getStorageSync(this.uniqueKey + '_$uCountDownTimestamp'))
53   - if(!lastTimestamp) return this.changeEvent(this.startText)
54   - // 当前秒的时间戳
55   - let nowTimestamp = Math.floor((+ new Date()) / 1000)
56   - // 判断当前的时间戳,是否小于上一次的本该按设定结束,却提前结束的时间戳
57   - if(this.keepRunning && lastTimestamp && lastTimestamp > nowTimestamp) {
58   - // 剩余尚未执行完的倒计秒数
59   - this.secNum = lastTimestamp - nowTimestamp
60   - // 清除本地保存的变量
61   - uni.removeStorageSync(this.uniqueKey + '_$uCountDownTimestamp')
62   - // 开始倒计时
63   - this.start()
64   - } else {
65   - // 如果不存在需要继续上一次的倒计时,执行正常的逻辑
66   - this.changeEvent(this.startText)
67   - }
68   - },
69   - // 开始倒计时
70   - start() {
71   - // 防止快速点击获取验证码的按钮而导致内部产生多个定时器导致混乱
72   - if(this.timer) {
73   - clearInterval(this.timer)
74   - this.timer = null
75   - }
76   - this.$emit('start')
77   - this.canGetCode = false
78   - // 这里放这句,是为了一开始时就提示,否则要等setInterval的1秒后才会有提示
79   - this.changeEvent(this.changeText.replace(/x|X/, this.secNum))
80   - this.timer = setInterval(() => {
81   - if (--this.secNum) {
82   - // 用当前倒计时的秒数替换提示字符串中的"x"字母
83   - this.changeEvent(this.changeText.replace(/x|X/, this.secNum))
84   - } else {
85   - clearInterval(this.timer)
86   - this.timer = null
87   - this.changeEvent(this.endText)
88   - this.secNum = this.seconds
89   - this.$emit('end')
90   - this.canGetCode = true
91   - }
92   - }, 1000)
93   - this.setTimeToStorage()
94   - },
95   - // 重置,可以让用户再次获取验证码
96   - reset() {
97   - this.canGetCode = true
98   - clearInterval(this.timer)
99   - this.secNum = this.seconds
100   - this.changeEvent(this.endText)
101   - },
102   - changeEvent(text) {
103   - this.$emit('change', text)
104   - },
105   - // 保存时间戳,为了防止倒计时尚未结束,H5刷新或者各端的右上角返回上一页再进来
106   - setTimeToStorage() {
107   - if(!this.keepRunning || !this.timer) return
108   - // 记录当前的时间戳,为了下次进入页面,如果还在倒计时内的话,继续倒计时
109   - // 倒计时尚未结束,结果大于0;倒计时已经开始,就会小于初始值,如果等于初始值,说明没有开始倒计时,无需处理
110   - if(this.secNum > 0 && this.secNum <= this.seconds) {
111   - // 获取当前时间戳(+ new Date()为特殊写法),除以1000变成秒,再去除小数部分
112   - let nowTimestamp = Math.floor((+ new Date()) / 1000)
113   - // 将本该结束时候的时间戳保存起来 => 当前时间戳 + 剩余的秒数
114   - uni.setStorage({
115   - key: this.uniqueKey + '_$uCountDownTimestamp',
116   - data: nowTimestamp + Number(this.secNum)
117   - })
118   - }
119   - }
120   - },
121   - // 组件销毁的时候,清除定时器,否则定时器会继续存在,系统不会自动清除
122   - beforeUnmount() {
123   - this.setTimeToStorage()
124   - clearTimeout(this.timer)
125   - this.timer = null
126   - }
127   - }
128   -</script>
129   -
130   -<style lang="scss" scoped>
131   -</style>
uni_modules/uview-plus/components/u-col/col.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:56:12
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/col.js
9   - */
10   -export default {
11   - // col 组件
12   - col: {
13   - span: 12,
14   - offset: 0,
15   - justify: 'start',
16   - align: 'stretch',
17   - textAlign: 'left'
18   - }
19   -}
uni_modules/uview-plus/components/u-col/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 占父容器宽度的多少等分,总分为12份
6   - span: {
7   - type: [String, Number],
8   - default: () => defProps.col.span
9   - },
10   - // 指定栅格左侧的间隔数(总12栏)
11   - offset: {
12   - type: [String, Number],
13   - default: () => defProps.col.offset
14   - },
15   - // 水平排列方式,可选值为`start`(或`flex-start`)、`end`(或`flex-end`)、`center`、`around`(或`space-around`)、`between`(或`space-between`)
16   - justify: {
17   - type: String,
18   - default: () => defProps.col.justify
19   - },
20   - // 垂直对齐方式,可选值为top、center、bottom、stretch
21   - align: {
22   - type: String,
23   - default: () => defProps.col.align
24   - },
25   - // 文字对齐方式
26   - textAlign: {
27   - type: String,
28   - default: () => defProps.col.textAlign
29   - }
30   - }
31   -})
uni_modules/uview-plus/components/u-col/u-col.vue deleted
1   -<template>
2   - <view
3   - class="u-col"
4   - ref="u-col"
5   - :class="[
6   - 'u-col-' + span
7   - ]"
8   - :style="[colStyle]"
9   - @tap="clickHandler"
10   - >
11   - <slot></slot>
12   - </view>
13   -</template>
14   -
15   -<script>
16   - import { props } from './props';
17   - import { mpMixin } from '../../libs/mixin/mpMixin';
18   - import { mixin } from '../../libs/mixin/mixin';
19   - import { addStyle, addUnit, deepMerge, getPx } from '../../libs/function/index';
20   - /**
21   - * CodeInput 栅格系统的列
22   - * @description 该组件一般用于Layout 布局 通过基础的 12 分栏,迅速简便地创建布局
23   - * @tutorial https://uview-plus.jiangruyi.com/components/Layout.html
24   - * @property {String | Number} span 栅格占据的列数,总12等份 (默认 12 )
25   - * @property {String | Number} offset 分栏左边偏移,计算方式与span相同 (默认 0 )
26   - * @property {String} justify 水平排列方式,可选值为`start`(或`flex-start`)、`end`(或`flex-end`)、`center`、`around`(或`space-around`)、`between`(或`space-between`) (默认 'start' )
27   - * @property {String} align 垂直对齐方式,可选值为top、center、bottom、stretch (默认 'stretch' )
28   - * @property {String} textAlign 文字水平对齐方式 (默认 'left' )
29   - * @property {Object} customStyle 定义需要用到的外部样式
30   - * @event {Function} click col被点击,会阻止事件冒泡到row
31   - * @example <u-col span="3" offset="3" > <view class="demo-layout bg-purple"></view> </u-col>
32   - */
33   - export default {
34   - name: 'u-col',
35   - mixins: [mpMixin, mixin, props],
36   - data() {
37   - return {
38   - width: 0,
39   - parentData: {
40   - gutter: 0
41   - },
42   - gridNum: 12
43   - }
44   - },
45   - // 微信小程序中 options 选项
46   - options: {
47   - virtualHost: true // 将自定义节点设置成虚拟的,更加接近Vue组件的表现。我们不希望自定义组件的这个节点本身可以设置样式、响应 flex 布局等
48   - },
49   - computed: {
50   - uJustify() {
51   - if (this.justify == 'end' || this.justify == 'start') return 'flex-' + this.justify
52   - else if (this.justify == 'around' || this.justify == 'between') return 'space-' + this.justify
53   - else return this.justify
54   - },
55   - uAlignItem() {
56   - if (this.align == 'top') return 'flex-start'
57   - if (this.align == 'bottom') return 'flex-end'
58   - else return this.align
59   - },
60   - colStyle() {
61   - const style = {
62   - // 这里写成"padding: 0 10px"的形式是因为nvue的需要
63   - paddingLeft: addUnit(getPx(this.parentData.gutter)/2),
64   - paddingRight: addUnit(getPx(this.parentData.gutter)/2),
65   - alignItems: this.uAlignItem,
66   - justifyContent: this.uJustify,
67   - textAlign: this.textAlign,
68   - // #ifndef APP-NVUE
69   - // 在非nvue上,使用百分比形式
70   - flex: `0 0 ${100 / this.gridNum * this.span}%`,
71   - marginLeft: 100 / 12 * this.offset + '%',
72   - // #endif
73   - // #ifdef APP-NVUE
74   - // 在nvue上,由于无法使用百分比单位,这里需要获取父组件的宽度,再计算得出该有对应的百分比尺寸
75   - width: addUnit(Math.floor(this.width / this.gridNum * Number(this.span))),
76   - marginLeft: addUnit(Math.floor(this.width / this.gridNum * Number(this.offset))),
77   - // #endif
78   - }
79   - return deepMerge(style, addStyle(this.customStyle))
80   - }
81   - },
82   - mounted() {
83   - this.init()
84   - },
85   - emits: ["click"],
86   - methods: {
87   - async init() {
88   - // 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环引用
89   - this.updateParentData()
90   - this.width = await this.parent.getComponentWidth()
91   - },
92   - updateParentData() {
93   - this.getParentData('u-row')
94   - },
95   - clickHandler(e) {
96   - this.$emit('click');
97   - }
98   - },
99   - }
100   -</script>
101   -
102   -<style lang="scss" scoped>
103   -
104   - .u-col {
105   - padding: 0;
106   - /* #ifndef APP-NVUE */
107   - box-sizing:border-box;
108   - /* #endif */
109   - /* #ifdef MP */
110   - display: block;
111   - /* #endif */
112   - }
113   -
114   - // nvue下百分比无效
115   - /* #ifndef APP-NVUE */
116   - .u-col-0 {
117   - width: 0;
118   - }
119   -
120   - .u-col-1 {
121   - width: calc(100%/12);
122   - }
123   -
124   - .u-col-2 {
125   - width: calc(100%/12 * 2);
126   - }
127   -
128   - .u-col-3 {
129   - width: calc(100%/12 * 3);
130   - }
131   -
132   - .u-col-4 {
133   - width: calc(100%/12 * 4);
134   - }
135   -
136   - .u-col-5 {
137   - width: calc(100%/12 * 5);
138   - }
139   -
140   - .u-col-6 {
141   - width: calc(100%/12 * 6);
142   - }
143   -
144   - .u-col-7 {
145   - width: calc(100%/12 * 7);
146   - }
147   -
148   - .u-col-8 {
149   - width: calc(100%/12 * 8);
150   - }
151   -
152   - .u-col-9 {
153   - width: calc(100%/12 * 9);
154   - }
155   -
156   - .u-col-10 {
157   - width: calc(100%/12 * 10);
158   - }
159   -
160   - .u-col-11 {
161   - width: calc(100%/12 * 11);
162   - }
163   -
164   - .u-col-12 {
165   - width: calc(100%/12 * 12);
166   - }
167   -
168   - /* #endif */
169   -</style>
uni_modules/uview-plus/components/u-collapse-item/collapseItem.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:56:42
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/collapseItem.js
9   - */
10   -export default {
11   - // collapseItem 组件
12   - collapseItem: {
13   - title: '',
14   - value: '',
15   - label: '',
16   - disabled: false,
17   - isLink: true,
18   - clickable: true,
19   - border: true,
20   - align: 'left',
21   - name: '',
22   - icon: '',
23   - duration: 300,
24   - showRight: true,
25   - titleStyle: {},
26   - iconStyle: {},
27   - rightIconStyle: {},
28   - cellCustomStyle: {},
29   - cellCustomClass: ''
30   - }
31   -}
uni_modules/uview-plus/components/u-collapse-item/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 标题
6   - title: {
7   - type: String,
8   - default: () => defProps.collapseItem.title
9   - },
10   - // 标题的样式
11   - titleStyle: {
12   - type: [Object, String],
13   - default: () => {
14   - return defProps.collapseItem.titleStyle
15   - }
16   - },
17   - // 标题右侧内容
18   - value: {
19   - type: String,
20   - default: () => defProps.collapseItem.value
21   - },
22   - // 标题下方的描述信息
23   - label: {
24   - type: String,
25   - default: () => defProps.collapseItem.label
26   - },
27   - // 是否禁用折叠面板
28   - disabled: {
29   - type: Boolean,
30   - default: () => defProps.collapseItem.disabled
31   - },
32   - // 是否展示右侧箭头并开启点击反馈
33   - isLink: {
34   - type: Boolean,
35   - default: () => defProps.collapseItem.isLink
36   - },
37   - // 是否开启点击反馈
38   - clickable: {
39   - type: Boolean,
40   - default: () => defProps.collapseItem.clickable
41   - },
42   - // 是否显示内边框
43   - border: {
44   - type: Boolean,
45   - default: () => defProps.collapseItem.border
46   - },
47   - // 标题的对齐方式
48   - align: {
49   - type: String,
50   - default: () => defProps.collapseItem.align
51   - },
52   - // 唯一标识符
53   - name: {
54   - type: [String, Number],
55   - default: () => defProps.collapseItem.name
56   - },
57   - // 标题左侧图片,可为绝对路径的图片或内置图标
58   - icon: {
59   - type: String,
60   - default: () => defProps.collapseItem.icon
61   - },
62   - // 面板展开收起的过渡时间,单位ms
63   - duration: {
64   - type: Number,
65   - default: () => defProps.collapseItem.duration
66   - },
67   - // 显示右侧图标
68   - showRight: {
69   - type: Boolean,
70   - default: () => defProps.collapseItem.showRight
71   - },
72   - // 左侧图标样式
73   - iconStyle: {
74   - type: [Object, String],
75   - default: () => {
76   - return defProps.collapseItem.iconStyle
77   - }
78   - },
79   - // 右侧箭头图标的样式
80   - rightIconStyle: {
81   - type: [Object, String],
82   - default: () => {
83   - return defProps.collapseItem.rightIconStyle
84   - }
85   - },
86   - cellCustomStyle: {
87   - type: [Object, String],
88   - default: () => {
89   - return defProps.collapseItem.cellCustomStyle
90   - }
91   - },
92   - cellCustomClass: {
93   - type: String,
94   - default: () => defProps.collapseItem.cellCustomClass
95   - }
96   - }
97   -})
uni_modules/uview-plus/components/u-collapse-item/u-collapse-item.vue deleted
1   -<template>
2   - <view class="u-collapse-item">
3   - <u-cell
4   - :title="$slots.title ? '' : title"
5   - :value="value"
6   - :label="label"
7   - :icon="icon"
8   - :isLink="isLink"
9   - :clickable="clickable"
10   - :border="parentData.border && showBorder"
11   - @click="clickHandler"
12   - :arrowDirection="expanded ? 'up' : 'down'"
13   - :disabled="disabled"
14   - :customClass="cellCustomClass"
15   - :customStyle="cellCustomStyle"
16   - >
17   - <!-- 微信小程序不支持,因为微信中不支持 <slot name="title" #title />的写法 -->
18   - <template #title>
19   - <slot name="title">
20   - <text v-if="!$slots.title && title">
21   - {{title}}
22   - </text>
23   - </slot>
24   - </template>
25   - <template #icon>
26   - <slot name="icon">
27   - <up-icon v-if="!$slots.icon && icon" :size="22" :name="icon"></up-icon>
28   - </slot>
29   - </template>
30   - <template #value>
31   - <slot name="value">
32   - <text v-if="!$slots.value && value">
33   - {{value}}
34   - </text>
35   - </slot>
36   - </template>
37   - <template #right-icon>
38   - <template v-if="showRight">
39   - <up-icon v-if="!$slots['right-icon']" :size="16" name="arrow-right"></up-icon>
40   - <slot name="right-icon">
41   - </slot>
42   - </template>
43   - </template>
44   - </u-cell>
45   - <view
46   - class="u-collapse-item__content"
47   - :animation="animationData"
48   - ref="animation"
49   - >
50   - <view
51   - class="u-collapse-item__content__text content-class"
52   - :id="elId"
53   - :ref="elId"
54   - ><slot /></view>
55   - </view>
56   - <u-line v-if="parentData.border"></u-line>
57   - </view>
58   -</template>
59   -
60   -<script>
61   - import { props } from './props.js';
62   - import { mpMixin } from '../../libs/mixin/mpMixin';
63   - import { mixin } from '../../libs/mixin/mixin';
64   - import { nextTick } from 'vue';
65   - import { guid, sleep, error } from '../../libs/function/index';
66   - import test from '../../libs/function/test';
67   - // #ifdef APP-NVUE
68   - const animation = uni.requireNativePlugin('animation')
69   - const dom = uni.requireNativePlugin('dom')
70   - // #endif
71   - /**
72   - * collapseItem 折叠面板Item
73   - * @description 通过折叠面板收纳内容区域(搭配u-collapse使用)
74   - * @tutorial https://uview-plus.jiangruyi.com/components/collapse.html
75   - * @property {String} title 标题
76   - * @property {String} value 标题右侧内容
77   - * @property {String} label 标题下方的描述信息
78   - * @property {Boolean} disbled 是否禁用折叠面板 ( 默认 false )
79   - * @property {Boolean} isLink 是否展示右侧箭头并开启点击反馈 ( 默认 true )
80   - * @property {Boolean} clickable 是否开启点击反馈 ( 默认 true )
81   - * @property {Boolean} border 是否显示内边框 ( 默认 true )
82   - * @property {String} align 标题的对齐方式 ( 默认 'left' )
83   - * @property {String | Number} name 唯一标识符
84   - * @property {String} icon 标题左侧图片,可为绝对路径的图片或内置图标
85   - * @event {Function} change 某个item被打开或者收起时触发
86   - * @example <u-collapse-item :title="item.head" v-for="(item, index) in itemList" :key="index">{{item.body}}</u-collapse-item>
87   - */
88   - export default {
89   - name: "u-collapse-item",
90   - mixins: [mpMixin, mixin, props],
91   - data() {
92   - return {
93   - elId: guid(),
94   - // uni.createAnimation的导出数据
95   - animationData: {},
96   - // 是否展开状态
97   - expanded: false,
98   - // 根据expanded确定是否显示border,为了控制展开时,cell的下划线更好的显示效果,进行一定时间的延时
99   - showBorder: false,
100   - // 是否动画中,如果是则不允许继续触发点击
101   - animating: false,
102   - // 父组件u-collapse的参数
103   - parentData: {
104   - accordion: false,
105   - border: false
106   - }
107   - };
108   - },
109   - watch: {
110   - expanded(n) {
111   - clearTimeout(this.timer)
112   - this.timer = null
113   - // 这里根据expanded的值来进行一定的延时,是为了cell的下划线更好的显示效果
114   - this.timer = setTimeout(() => {
115   - this.showBorder = n
116   - }, n ? 10 : 290)
117   - }
118   - },
119   - mounted() {
120   - this.init()
121   - // console.log('$slots', this.$slots)
122   - },
123   - methods: {
124   - // 异步获取内容,或者动态修改了内容时,需要重新初始化
125   - async init() {
126   - // 初始化数据
127   - this.updateParentData()
128   - if (!this.parent) {
129   - return error('u-collapse-item必须要搭配u-collapse组件使用')
130   - }
131   - const {
132   - value,
133   - accordion,
134   - children = []
135   - } = this.parent
136   -
137   - if (accordion) {
138   - if (test.array(value)) {
139   - return error('手风琴模式下,u-collapse组件的value参数不能为数组')
140   - }
141   - this.expanded = this.name == value
142   - } else {
143   - if (!test.array(value) && value !== null) {
144   - return error('非手风琴模式下,u-collapse组件的value参数必须为数组')
145   - }
146   - this.expanded = (value || []).some(item => item == this.name)
147   - }
148   - // 设置组件的展开或收起状态
149   - await nextTick()
150   - this.setContentAnimate()
151   - },
152   - updateParentData() {
153   - // 此方法在mixin中
154   - this.getParentData('u-collapse')
155   - },
156   - async setContentAnimate() {
157   - // 每次面板打开或者收起时,都查询元素尺寸
158   - // 好处是,父组件从服务端获取内容后,变更折叠面板后可以获得最新的高度
159   - const rect = await this.queryRect()
160   - const height = this.expanded ? rect.height : 0
161   - this.animating = true
162   - // #ifdef APP-NVUE
163   - const ref = this.$refs['animation'].ref
164   - animation.transition(ref, {
165   - styles: {
166   - height: height + 'px'
167   - },
168   - duration: this.duration,
169   - // 必须设置为true,否则会到面板收起或展开时,页面其他元素不会随之调整它们的布局
170   - needLayout: true,
171   - timingFunction: 'ease-in-out',
172   - }, () => {
173   - this.animating = false
174   - })
175   - // #endif
176   -
177   - // #ifndef APP-NVUE
178   - const animation = uni.createAnimation({
179   - timingFunction: 'ease-in-out',
180   - });
181   - animation
182   - .height(height)
183   - .step({
184   - duration: this.duration,
185   - })
186   - .step()
187   - // 导出动画数据给面板的animationData值
188   - this.animationData = animation.export()
189   - // 标识动画结束
190   - sleep(this.duration).then(() => {
191   - this.animating = false
192   - })
193   - // #endif
194   - },
195   - // 点击collapsehead头部
196   - clickHandler() {
197   - if (this.disabled && this.animating) return
198   - // 设置本组件为相反的状态
199   - this.parent && this.parent.onChange(this)
200   - },
201   - // 查询内容高度
202   - queryRect() {
203   - // #ifndef APP-NVUE
204   - // $uGetRect为uView自带的节点查询简化方法,详见文档介绍:https://uview-plus.jiangruyi.com/js/getRect.html
205   - // 组件内部一般用this.$uGetRect,对外的为uni.$u.getRect,二者功能一致,名称不同
206   - return new Promise(resolve => {
207   - this.$uGetRect(`#${this.elId}`).then(size => {
208   - resolve(size)
209   - })
210   - })
211   - // #endif
212   -
213   - // #ifdef APP-NVUE
214   - // nvue下,使用dom模块查询元素高度
215   - // 返回一个promise,让调用此方法的主体能使用then回调
216   - return new Promise(resolve => {
217   - dom.getComponentRect(this.$refs[this.elId], res => {
218   - resolve(res.size)
219   - })
220   - })
221   - // #endif
222   - }
223   - },
224   - };
225   -</script>
226   -
227   -<style lang="scss" scoped>
228   -
229   - .u-collapse-item {
230   -
231   - &__content {
232   - overflow: hidden;
233   - height: 0;
234   -
235   - &__text {
236   - padding: 12px 15px;
237   - color: $u-content-color;
238   - font-size: 14px;
239   - line-height: 18px;
240   - }
241   - }
242   - }
243   -</style>
uni_modules/uview-plus/components/u-collapse/collapse.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:56:30
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/collapse.js
9   - */
10   -export default {
11   - // collapse 组件
12   - collapse: {
13   - value: null,
14   - accordion: false,
15   - border: true
16   - }
17   -}
uni_modules/uview-plus/components/u-collapse/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 当前展开面板的name,非手风琴模式:[<string | number>],手风琴模式:string | number
6   - value: {
7   - type: [String, Number, Array, null],
8   - default: () => defProps.collapse.value
9   - },
10   - // 是否手风琴模式
11   - accordion: {
12   - type: Boolean,
13   - default: () => defProps.collapse.accordion
14   - },
15   - // 是否显示外边框
16   - border: {
17   - type: Boolean,
18   - default: () => defProps.collapse.border
19   - }
20   - }
21   -})
uni_modules/uview-plus/components/u-collapse/u-collapse.vue deleted
1   -<template>
2   - <view class="u-collapse">
3   - <u-line v-if="border"></u-line>
4   - <slot />
5   - </view>
6   -</template>
7   -
8   -<script>
9   - import { props } from './props';
10   - import { mpMixin } from '../../libs/mixin/mpMixin';
11   - import { mixin } from '../../libs/mixin/mixin';
12   - /**
13   - * collapse 折叠面板
14   - * @description 通过折叠面板收纳内容区域
15   - * @tutorial https://uview-plus.jiangruyi.com/components/collapse.html
16   - * @property {String | Number | Array} value 当前展开面板的name,非手风琴模式:[<string | number>],手风琴模式:string | number
17   - * @property {Boolean} accordion 是否手风琴模式( 默认 false )
18   - * @property {Boolean} border 是否显示外边框 ( 默认 true )
19   - * @event {Function} change 当前激活面板展开时触发(如果是手风琴模式,参数activeNames类型为String,否则为Array)
20   - * @example <u-collapse></u-collapse>
21   - */
22   - export default {
23   - name: "u-collapse",
24   - mixins: [mpMixin, mixin,props],
25   - watch: {
26   - needInit() {
27   - this.init()
28   - },
29   - // 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件
30   - parentData() {
31   - if (this.children.length) {
32   - this.children.map(child => {
33   - // 判断子组件(u-checkbox)如果有updateParentData方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值)
34   - typeof(child.updateParentData) === 'function' && child.updateParentData()
35   - })
36   - }
37   - }
38   - },
39   - created() {
40   - this.children = []
41   - },
42   - computed: {
43   - needInit() {
44   - // 通过computed,同时监听accordion和value值的变化
45   - // 再通过watch去执行init()方法,进行再一次的初始化
46   - return [this.accordion, this.value]
47   - }
48   - },
49   - emits: ["open", "close", "change"],
50   - methods: {
51   - // 重新初始化一次内部的所有子元素
52   - init() {
53   - this.children.map(child => {
54   - child.init()
55   - })
56   - },
57   - /**
58   - * collapse-item被点击时触发,由collapse统一处理各子组件的状态
59   - * @param {Object} target 被操作的面板的实例
60   - */
61   - onChange(target) {
62   - let changeArr = []
63   - this.children.map((child, index) => {
64   - // 如果是手风琴模式,将其他的折叠面板收起来
65   - if (this.accordion) {
66   - child.expanded = child === target ? !target.expanded : false
67   - child.setContentAnimate()
68   - } else {
69   - if(child === target) {
70   - child.expanded = !child.expanded
71   - child.setContentAnimate()
72   - }
73   - }
74   - // 拼接change事件中,数组元素的状态
75   - changeArr.push({
76   - // 如果没有定义name属性,则默认返回组件的index索引
77   - name: child.name || index,
78   - status: child.expanded ? 'open' : 'close'
79   - })
80   - })
81   -
82   - this.$emit('change', changeArr)
83   - this.$emit(target.expanded ? 'open' : 'close', target.name)
84   - }
85   - }
86   - }
87   -</script>
88   -
89   -<style lang="scss" scoped>
90   -</style>
uni_modules/uview-plus/components/u-color-picker/u-color-picker.vue deleted
1   -<template>
2   - <view class="up-color-picker">
3   - <view clas="up-color-picker__trigger" @click="show = true"
4   - :style="{backgroundColor: value}" >
5   - <slot></slot>
6   - </view>
7   - <up-popup :show="show" mode="bottom" round="10" @close="close" :closeOnClickOverlay="true">
8   - <view class="up-color-picker__content">
9   - <view class="up-color-picker__header">
10   - <text class="up-color-picker__title">选择颜色</text>
11   - </view>
12   -
13   - <!-- 纯色/渐变色切换 -->
14   - <view class="up-color-picker__switch">
15   - <up-subsection
16   - :list="[{ name: '纯色' }, { name: '渐变' }]"
17   - :current="colorTypeIndex"
18   - @change="changeColorType"
19   - fontSize="14"
20   - ></up-subsection>
21   - </view>
22   -
23   - <!-- 渐变色选择器 -->
24   - <view v-if="colorTypeIndex == 1" class="up-color-picker__gradient">
25   - <!-- 渐变色控制条 -->
26   - <view
27   - class="up-color-picker__gradient-track"
28   - :style="{ background: gradientStyle }"
29   - >
30   - <view
31   - class="up-color-picker__gradient-pointer"
32   - v-for="(item, index) in gradientColors"
33   - :key="index"
34   - :style="{ left: getGradientPointerPosition(index) + 'px' }"
35   - @click="openColorPickerForGradient(index)"
36   - @touchstart="onPointerTouchStart($event, index)"
37   - @touchmove.stop="onPointerTouchMove"
38   - @touchend.stop="onPointerTouchEnd"
39   - >
40   - <view class="up-color-picker__gradient-pointer-inner" :style="{ backgroundColor: item.color }"></view>
41   - </view>
42   - </view>
43   -
44   - <view class="up-color-picker__gradient-controls">
45   - <up-button
46   - type="primary"
47   - size="mini"
48   - plain
49   - @click="addGradientColor"
50   - class="up-color-picker__add-btn"
51   - >
52   - 添加颜色
53   - </up-button>
54   - </view>
55   -
56   - <!-- 圆形方向选择器 -->
57   - <view class="up-color-picker__gradient-direction">
58   - <text>方向:</text>
59   - <view class="up-color-picker__gradient__direction-circle"
60   - @touchstart="onDirectionTouchStart"
61   - @touchmove="onDirectionTouchMove"
62   - @touchend="onDirectionTouchEnd">
63   - <view
64   - class="up-color-picker__direction-pointer"
65   - :style="{
66   - left: directionPointer.x + 'px',
67   - top: directionPointer.y + 'px'
68   - }"
69   - ></view>
70   - </view>
71   - </view>
72   - </view>
73   -
74   - <!-- 纯色选择器 -->
75   - <view class="up-color-picker__solid">
76   - <!-- 饱和度和明度选择区域 -->
77   - <view
78   - class="up-color-picker__saturation"
79   - :style="{ backgroundColor: `hsl(${hue}, 100%, 50%)` }"
80   - @touchstart="onSaturationTouchStart"
81   - @touchmove="onSaturationTouchMove"
82   - @touchend="onSaturationTouchEnd"
83   - >
84   - <view
85   - class="up-color-picker__saturation-pointer"
86   - :style="{
87   - left: saturationPosition.x + 'px',
88   - top: saturationPosition.y + 'px'
89   - }"
90   - ></view>
91   - </view>
92   -
93   - <!-- 色相选择 -->
94   - <view
95   - class="up-color-picker__hue"
96   - @touchstart="onHueTouchStart"
97   - @touchmove="onHueTouchMove"
98   - @touchend="onHueTouchEnd"
99   - >
100   - <view
101   - class="up-color-picker__hue-pointer"
102   - :style="{ left: huePosition + 'px' }"
103   - ></view>
104   - </view>
105   -
106   - <!-- 透明度选择 -->
107   - <view v-if="colorTypeIndex == 0"
108   - class="up-color-picker__alpha"
109   - @touchstart="onAlphaTouchStart"
110   - @touchmove="onAlphaTouchMove"
111   - @touchend="onAlphaTouchEnd"
112   - >
113   - <view class="up-color-picker__alpha-bg"></view>
114   - <view
115   - class="up-color-picker__alpha-pointer"
116   - :style="{ left: alphaPosition + 'px' }"
117   - ></view>
118   - </view>
119   - </view>
120   -
121   - <!-- 常用颜色 -->
122   - <view v-if="commonColors && commonColors.length" class="up-color-picker__common">
123   - <text class="up-color-picker__common-title">常用颜色</text>
124   - <view class="up-color-picker__common-list">
125   - <view
126   - v-for="(color, index) in commonColors"
127   - :key="index"
128   - class="up-color-picker__common-item"
129   - :style="{ backgroundColor: color }"
130   - @click="selectCommonColor(color)"
131   - ></view>
132   - </view>
133   - </view>
134   -
135   - <!-- 颜色预览和操作按钮 -->
136   - <view class="up-color-picker__footer">
137   - <view class="up-color-picker__preview">
138   - <view
139   - class="up-color-picker__preview-color"
140   - :style="{ backgroundColor: displayColor }"
141   - ></view>
142   - <text class="up-color-picker__preview-text">{{ displayColor }}</text>
143   - </view>
144   - <view class="up-color-picker__actions">
145   - <up-button
146   - type="primary"
147   - size="small"
148   - @click="confirm"
149   - class="up-color-picker__btn"
150   - >
151   - 确定
152   - </up-button>
153   - <up-button
154   - type="info"
155   - size="small"
156   - @click="close"
157   - class="up-color-picker__btn"
158   - >
159   - 取消
160   - </up-button>
161   - </view>
162   - </view>
163   - </view>
164   - </up-popup>
165   - </view>
166   -</template>
167   -
168   -<script>
169   -export default {
170   - name: 'up-color-picker',
171   - props: {
172   - // 初始颜色值
173   - modelValue: {
174   - type: String,
175   - default: '#ff0000'
176   - },
177   - // 常用颜色列表
178   - commonColors: {
179   - type: Array,
180   - default: () => [
181   - ]
182   - }
183   - },
184   - data() {
185   - return {
186   - show: false,
187   - // 颜色类型索引:0-纯色,1-渐变色
188   - colorTypeIndex: 0,
189   - // 纯色相关数据
190   - hue: 0,
191   - saturation: 100,
192   - lightness: 50,
193   - alpha: 1,
194   - saturationPosition: { x: 150, y: 0 },
195   - huePosition: 0,
196   - alphaPosition: 0, // 将在initColor中设置为最右侧
197   - // 渐变色相关数据
198   - gradientColors: [
199   - { color: '#ff0000', percent: 0 },
200   - { color: '#0000ff', percent: 1 }
201   - ],
202   - gradientDirections: [
203   - { label: '从左到右', value: 'to right' },
204   - { label: '从上到下', value: 'to bottom' },
205   - { label: '从左上到右下', value: 'to bottom right' },
206   - { label: '从右上到左下', value: 'to bottom left' }
207   - ],
208   - currentDirection: { label: '从左到右', value: 'to right' },
209   - showDirectionPicker: false,
210   - // 当前选中颜色
211   - currentColor: '#ff0000',
212   - // 渐变色控制相关
213   - draggingPointerIndex: -1,
214   - directionPointer: { x: 20, y: 20 }, // 默认向右(在圆的右侧)
215   - // 渐变节点颜色修改相关
216   - editingGradientIndex: -1,
217   - // 保存纯色和渐变色的各自状态
218   - solidColorState: {
219   - hue: 0,
220   - saturation: 100,
221   - lightness: 50,
222   - alpha: 1,
223   - saturationPosition: { x: 150, y: 0 },
224   - huePosition: 0,
225   - alphaPosition: 0, // 将在initColor中设置为最右侧
226   - currentColor: '#ff0000'
227   - },
228   - gradientColorState: {
229   - gradientColors: [
230   - { color: '#ff0000', percent: 0 },
231   - { color: '#0000ff', percent: 1 }
232   - ],
233   - currentDirection: { label: '从左到右', value: 'to right' },
234   - directionPointer: { x: 100, y: 0 }
235   - },
236   - // 区分预览类型:solid-纯色预览,gradient-整体渐变预览,gradient-point-渐变点预览
237   - previewType: 'solid'
238   - }
239   - },
240   - computed: {
241   - // 渐变色样式
242   - gradientStyle() {
243   - const colors = this.gradientColors.map(item => `${item.color} ${Math.round(item.percent * 100)}%`).join(', ')
244   - return `linear-gradient(${this.currentDirection.value}, ${colors})`
245   - },
246   - // 显示的颜色预览值
247   - displayColor() {
248   - if (this.previewType === 'gradient-point' && this.editingGradientIndex >= 0) {
249   - return this.gradientColors[this.editingGradientIndex].color;
250   - }
251   - console.log(this.editingGradientIndex)
252   - return this.currentColor;
253   - }
254   - },
255   - watch: {
256   - show(newVal) {
257   - if (newVal) {
258   - this.initColor()
259   - }
260   - },
261   - colorTypeIndex(newVal) {
262   - if (newVal == 0) {
263   - this.editingGradientIndex = -1
264   - }
265   - },
266   - },
267   - mounted() {
268   - this.initColor()
269   - },
270   - emits: ['update:modelValue', 'confirm', 'close'],
271   - methods: {
272   - // 初始化颜色
273   - initColor() {
274   - if (this.modelValue) {
275   - this.currentColor = this.modelValue
276   - if (this.modelValue.includes('linear-gradient')) {
277   - // 解析渐变色
278   - this.colorTypeIndex = 1
279   - this.parseGradientColor(this.modelValue)
280   - this.previewType = 'gradient';
281   - } else {
282   - // 解析纯色
283   - this.colorTypeIndex = 0
284   - this.parseSolidColor(this.modelValue)
285   - this.previewType = 'solid';
286   - }
287   - }
288   - // 初始化方向指针位置
289   - this.initDirectionPointer();
290   - // 初始化alphaPosition为最右侧
291   - this.initAlphaPosition();
292   - },
293   -
294   - // 初始化alpha位置为最右侧
295   - async initAlphaPosition() {
296   - const query = uni.createSelectorQuery().in(this);
297   - query.select('.up-color-picker__alpha').boundingClientRect();
298   - await this.$nextTick();
299   - query.exec(res => {
300   - const rect = res[0];
301   - if (rect) {
302   - this.alphaPosition = rect.width || 150; // 默认150像素
303   - } else {
304   - this.alphaPosition = 150; // 默认值
305   - }
306   -
307   - // 同步solidColorState中的alphaPosition
308   - this.solidColorState.alphaPosition = this.alphaPosition;
309   - this.updateSolidColor();
310   - });
311   - },
312   -
313   - // 初始化方向指针位置
314   - initDirectionPointer() {
315   - const angle = this.getDirectionAngle(this.currentDirection.value);
316   - this.setDirectionPointerByAngle(angle);
317   - },
318   -
319   - // 根据方向值获取角度
320   - getDirectionAngle(direction) {
321   - switch(direction) {
322   - case 'to right': return 0;
323   - case 'to bottom': return 90;
324   - case 'to left': return 180;
325   - case 'to top': return 270;
326   - case 'to bottom right': return 45;
327   - case 'to bottom left': return 135;
328   - case 'to top left': return 225;
329   - case 'to top right': return 315;
330   - default: return 0;
331   - }
332   - },
333   -
334   - // 根据角度设置方向指针位置
335   - setDirectionPointerByAngle(angle) {
336   - const radian = angle * Math.PI / 180;
337   - const radius = 20; // 圆半径
338   - this.directionPointer = {
339   - x: radius * Math.cos(radian) + 20, // 20是圆心位置
340   - y: radius * Math.sin(radian) + 20
341   - };
342   - },
343   -
344   - // 打开颜色选择器以修改渐变节点颜色
345   - openColorPickerForGradient(index) {
346   - this.editingGradientIndex = index;
347   - // 设置当前颜色为选中节点的颜色
348   - const color = this.gradientColors[index].color;
349   - this.currentColor = color;
350   - // 设置预览类型为渐变点预览
351   - this.previewType = 'gradient-point';
352   -
353   - // 解析颜色并设置选择器位置
354   - if (!color.includes('linear-gradient')) {
355   - this.colorTypeIndex = 0;
356   - this.parseSolidColor(color);
357   - // 保存当前渐变状态
358   - this.gradientColorState = {
359   - gradientColors: [...this.gradientColors],
360   - currentDirection: {...this.currentDirection},
361   - directionPointer: {...this.directionPointer}
362   - };
363   - }
364   - },
365   -
366   - // 解析纯色
367   - parseSolidColor(color) {
368   - // 简化处理,实际项目中可以使用更复杂的颜色解析
369   - this.currentColor = color
370   - // 如果正在编辑渐变节点,则更新该节点颜色
371   - if (this.editingGradientIndex >= 0) {
372   - this.gradientColors[this.editingGradientIndex].color = color;
373   - // 切换回渐变模式并恢复渐变状态
374   - this.colorTypeIndex = 1;
375   - Object.assign(this, this.solidColorState);
376   - this.previewType = 'gradient-point';
377   - } else {
378   - this.previewType = 'solid';
379   - }
380   - },
381   -
382   - // 解析渐变色
383   - parseGradientColor(gradient) {
384   - // 简化处理,实际项目中可以使用更复杂的渐变解析
385   - this.currentColor = gradient
386   - // this.previewType = 'gradient';
387   - },
388   -
389   - // 切换颜色类型
390   - changeColorType(index) {
391   - // 保存当前状态
392   - if (this.colorTypeIndex === 0) {
393   - // 保存纯色状态
394   - this.solidColorState = {
395   - hue: this.hue,
396   - saturation: this.saturation,
397   - lightness: this.lightness,
398   - alpha: this.alpha,
399   - saturationPosition: {...this.saturationPosition},
400   - huePosition: this.huePosition,
401   - alphaPosition: this.alphaPosition,
402   - currentColor: this.currentColor
403   - };
404   - } else {
405   - // 保存渐变状态
406   - this.gradientColorState = {
407   - gradientColors: [...this.gradientColors],
408   - currentDirection: {...this.currentDirection},
409   - directionPointer: {...this.directionPointer}
410   - };
411   - }
412   -
413   - this.colorTypeIndex = index;
414   -
415   - // 恢复目标状态
416   - if (index === 0) {
417   - Object.assign(this, this.solidColorState);
418   - this.previewType = 'solid';
419   - } else {
420   - Object.assign(this, this.gradientColorState);
421   - // 确保gradientColors是响应式的
422   - this.gradientColors = [...this.gradientColorState.gradientColors];
423   - this.previewType = 'gradient';
424   - }
425   - },
426   -
427   - // 饱和度和明度触摸开始
428   - onSaturationTouchStart(e) {
429   - this.updateSaturationPosition(e)
430   - },
431   -
432   - // 饱和度和明度触摸移动
433   - onSaturationTouchMove(e) {
434   - this.updateSaturationPosition(e)
435   - },
436   -
437   - // 饱和度和明度触摸结束
438   - onSaturationTouchEnd(e) {
439   - this.updateSaturationPosition(e)
440   - },
441   -
442   - // 更新饱和度和明度位置
443   - updateSaturationPosition(e) {
444   - const touch = e.touches[0] || e.changedTouches[0]
445   - const target = e.currentTarget
446   - const query = uni.createSelectorQuery().in(this);
447   - query.select('.up-color-picker__saturation').boundingClientRect()
448   -
449   - query.exec(res => {
450   - const rect = res[0];
451   - if (rect) {
452   - let x = touch.clientX - rect.left
453   - let y = touch.clientY - rect.top
454   -
455   - // 边界处理
456   - x = Math.max(0, Math.min(x, rect.width))
457   - y = Math.max(0, Math.min(y, rect.height))
458   -
459   - this.saturationPosition = { x, y }
460   - this.updateSolidColor()
461   - }
462   - })
463   - },
464   -
465   - // 色相触摸开始
466   - onHueTouchStart(e) {
467   - this.updateHuePosition(e)
468   - },
469   -
470   - // 色相触摸移动
471   - onHueTouchMove(e) {
472   - this.updateHuePosition(e)
473   - },
474   -
475   - // 色相触摸结束
476   - onHueTouchEnd(e) {
477   - this.updateHuePosition(e)
478   - },
479   -
480   - // 更新色相位置
481   - updateHuePosition(e) {
482   - const touch = e.touches[0] || e.changedTouches[0]
483   - const target = e.currentTarget
484   - const query = uni.createSelectorQuery().in(this);
485   - query.select('.up-color-picker__hue').boundingClientRect()
486   -
487   - query.exec(res => {
488   - const rect = res[0];
489   - if (rect) {
490   - let x = touch.clientX - rect.left
491   - x = Math.max(0, Math.min(x, rect.width))
492   - this.huePosition = x
493   - this.hue = Math.round((x / rect.width) * 360)
494   - this.updateSolidColor()
495   - }
496   - })
497   - },
498   -
499   - // 透明度触摸开始
500   - onAlphaTouchStart(e) {
501   - this.updateAlphaPosition(e)
502   - },
503   -
504   - // 透明度触摸移动
505   - onAlphaTouchMove(e) {
506   - this.updateAlphaPosition(e)
507   - },
508   -
509   - // 透明度触摸结束
510   - onAlphaTouchEnd(e) {
511   - this.updateAlphaPosition(e)
512   - },
513   -
514   - // 更新透明度位置
515   - updateAlphaPosition(e) {
516   - const touch = e.touches[0] || e.changedTouches[0]
517   - const target = e.currentTarget
518   - const query = uni.createSelectorQuery().in(this);
519   - query.select('.up-color-picker__alpha').boundingClientRect()
520   -
521   - query.exec(res => {
522   - const rect = res[0];
523   - if (rect) {
524   - let x = touch.clientX - rect.left
525   - x = Math.max(0, Math.min(x, rect.width))
526   - this.alphaPosition = x
527   - this.alpha = x / rect.width
528   - this.updateSolidColor()
529   - }
530   - })
531   - },
532   -
533   - // 更新纯色
534   - updateSolidColor() {
535   - // 使用实际元素尺寸替代硬编码的150
536   - const query = uni.createSelectorQuery().in(this);
537   - query.select('.up-color-picker__saturation').boundingClientRect();
538   -
539   - query.exec(res => {
540   - const rect = res[0];
541   - const size = rect ? Math.min(rect.width, rect.height) : 150; // 默认150作为后备值
542   -
543   - const s = (this.saturationPosition.x / size) * 100
544   - const l = 100 - (this.saturationPosition.y / size) * 100
545   - this.saturation = s
546   - this.lightness = l
547   -
548   - // 使用正确的HSL转RGB算法
549   - if (this.colorTypeIndex == 0) {
550   - this.currentColor = this.hslToRgb(this.hue, this.saturation, this.lightness, this.alpha)
551   - } else if (this.colorTypeIndex == 1) {
552   - this.gradientColors[this.editingGradientIndex].color
553   - = this.hslToRgb(this.hue, this.saturation, this.lightness, this.alpha)
554   - }
555   - });
556   - },
557   -
558   - // 添加渐变色
559   - addGradientColor() {
560   - if (this.gradientColors.length < 5) {
561   - this.gradientColors.push({
562   - color: '#ffffff',
563   - percent: 1
564   - })
565   - }
566   - },
567   -
568   - // 删除渐变色
569   - removeGradientColor(index) {
570   - if (this.gradientColors.length > 2) {
571   - this.gradientColors.splice(index, 1)
572   - }
573   - },
574   -
575   - // 获取渐变控制点位置
576   - getGradientPointerPosition(index) {
577   - const trackWidth = 280; // 需要与样式中的宽度一致
578   - return this.gradientColors[index].percent * trackWidth;
579   - },
580   -
581   - // 更新渐变色
582   - updateGradientColor(e) {
583   - const touch = e.touches[0] || e.changedTouches[0];
584   - const query = uni.createSelectorQuery().in(this);
585   - query.select('.up-color-picker__gradient-track').boundingClientRect();
586   -
587   - query.exec(res => {
588   - const rect = res[0];
589   - if (rect) {
590   - let x = touch.clientX - rect.left;
591   - // 边界处理
592   - x = Math.max(0, Math.min(x, rect.width));
593   - const percent = x / rect.width;
594   -
595   - // 如果正在拖动控制点,则更新该控制点位置
596   - if (this.draggingPointerIndex >= 0) {
597   - this.gradientColors[this.draggingPointerIndex].percent = percent;
598   - // 保持控制点顺序
599   - this.gradientColors.sort((a, b) => a.percent - b.percent);
600   - } else {
601   - // 否则添加新的控制点(此处可选功能)
602   - }
603   - }
604   - });
605   - },
606   -
607   - // 控制点触摸开始
608   - onPointerTouchStart(e, index) {
609   - this.draggingPointerIndex = index;
610   - // 点击控制点时更新预览颜色
611   - this.currentColor = this.gradientColors[index].color;
612   - this.previewType = 'gradient-point';
613   - this.editingGradientIndex = index; // 添加这行以正确设置编辑索引
614   - // 阻止事件冒泡
615   - e.stopPropagation();
616   - },
617   -
618   - // 控制点触摸移动
619   - onPointerTouchMove(e) {
620   - if (this.draggingPointerIndex === -1) return;
621   -
622   - const touch = e.touches[0] || e.changedTouches[0];
623   - const query = uni.createSelectorQuery().in(this);
624   - query.select('.up-color-picker__gradient-track').boundingClientRect();
625   -
626   - query.exec(res => {
627   - const rect = res[0];
628   - if (rect) {
629   - let x = touch.clientX - rect.left;
630   - // 边界处理
631   - x = Math.max(0, Math.min(x, rect.width));
632   - let percent = x / rect.width;
633   -
634   - // 处理边界情况,确保能精确到达两端
635   - if (x === 0) percent = 0;
636   - if (x === rect.width) percent = 1;
637   -
638   - // 更新控制点位置
639   - this.gradientColors[this.draggingPointerIndex].percent = percent;
640   - // 保持控制点顺序
641   - this.gradientColors.sort((a, b) => a.percent - b.percent);
642   - // 更新拖拽索引以匹配排序后的索引
643   - this.draggingPointerIndex = this.gradientColors.findIndex((item, index) => {
644   - // 使用更精确的比较方法,处理浮点数精度问题
645   - return Math.abs(item.percent - percent) < 0.0001;
646   - });
647   - }
648   - });
649   - },
650   -
651   - // 控制点触摸结束
652   - onPointerTouchEnd() {
653   - this.draggingPointerIndex = -1;
654   - },
655   -
656   - // 方向选择器触摸开始
657   - onDirectionTouchStart(e) {
658   - this.updateDirection(e);
659   - },
660   -
661   - // 方向选择器触摸移动
662   - onDirectionTouchMove(e) {
663   - this.updateDirection(e);
664   - },
665   -
666   - // 方向选择器触摸结束
667   - onDirectionTouchEnd(e) {
668   - this.updateDirection(e);
669   - },
670   -
671   - // 更新方向
672   - updateDirection(e) {
673   - const touch = e.touches[0] || e.changedTouches[0];
674   - const query = uni.createSelectorQuery().in(this);
675   - query.select('.up-color-picker__gradient__direction-circle').boundingClientRect();
676   -
677   - query.exec(res => {
678   - const rect = res[0];
679   - if (rect) {
680   - const centerX = rect.left + rect.width / 2;
681   - const centerY = rect.top + rect.height / 2;
682   - const x = touch.clientX - centerX;
683   - const y = touch.clientY - centerY;
684   - const distance = Math.sqrt(x * x + y * y);
685   - const maxDistance = rect.width / 2;
686   -
687   - // 限制在圆内
688   - if (distance <= maxDistance) {
689   - this.directionPointer = {
690   - x: x + rect.width / 2,
691   - y: y + rect.height / 2
692   - };
693   - } else {
694   - // 限制在圆周上
695   - const ratio = maxDistance / distance;
696   - this.directionPointer = {
697   - x: x * ratio + rect.width / 2,
698   - y: y * ratio + rect.height / 2
699   - };
700   - }
701   -
702   - // 计算角度并更新方向
703   - const angle = Math.atan2(y, x) * 180 / Math.PI;
704   - console.log(angle)
705   - this.updateGradientDirection(angle);
706   - }
707   - });
708   - },
709   -
710   - // 根据角度更新渐变方向
711   - updateGradientDirection(angle) {
712   - // 角度转换为标准方向
713   - if (angle < 0) angle += 360;
714   -
715   - if (angle >= 315 || angle < 45) {
716   - this.currentDirection = { label: '从左到右', value: 'to right' };
717   - } else if (angle >= 45 && angle < 135) {
718   - this.currentDirection = { label: '从上到下', value: 'to bottom' };
719   - } else if (angle >= 135 && angle < 225) {
720   - this.currentDirection = { label: '从右到左', value: 'to left' };
721   - } else {
722   - this.currentDirection = { label: '从下到上', value: 'to top' };
723   - }
724   - },
725   -
726   - // 确认方向选择
727   - confirmDirection(e) {
728   - this.currentDirection = this.gradientDirections[e.index]
729   - this.showDirectionPicker = false
730   - },
731   -
732   - // 选择常用颜色
733   - selectCommonColor(color) {
734   - this.currentColor = color
735   - if (this.colorTypeIndex === 0) {
736   - this.parseSolidColor(color)
737   - } else {
738   - // 如果是渐变模式,将常用颜色作为渐变的一个节点
739   - this.gradientColors[this.editingGradientIndex].color = color
740   - }
741   - },
742   -
743   - // 确认选择
744   - confirm() {
745   - let color = this.currentColor
746   - if (this.colorTypeIndex === 1) {
747   - color = this.gradientStyle
748   - }
749   - this.$emit('update:modelValue', color)
750   - this.show = false;
751   - this.$emit('confirm', color)
752   - // 重置编辑状态
753   - this.editingGradientIndex = -1;
754   - this.previewType = this.colorTypeIndex === 0 ? 'solid' : 'gradient';
755   - this.close()
756   - },
757   -
758   - // 关闭选择器
759   - close() {
760   - this.show = false;
761   - this.$emit('close')
762   - },
763   -
764   - // HSL转RGB辅助函数
765   - hslToRgb(h, s, l, a = 1) {
766   - h = h / 360;
767   - s = s / 100;
768   - l = l / 100;
769   -
770   - let r, g, b;
771   -
772   - if (s === 0) {
773   - r = g = b = l; // achromatic
774   - } else {
775   - const hue2rgb = (p, q, t) => {
776   - if (t < 0) t += 1;
777   - if (t > 1) t -= 1;
778   - if (t < 1/6) return p + (q - p) * 6 * t;
779   - if (t < 1/2) return q;
780   - if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
781   - return p;
782   - };
783   -
784   - const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
785   - const p = 2 * l - q;
786   - r = hue2rgb(p, q, h + 1/3);
787   - g = hue2rgb(p, q, h);
788   - b = hue2rgb(p, q, h - 1/3);
789   - }
790   -
791   - const round = (value) => Math.round(value * 255);
792   - return `rgba(${round(r)}, ${round(g)}, ${round(b)}, ${a.toFixed(2)})`;
793   - }
794   - }
795   -}
796   -</script>
797   -
798   -<style lang="scss" scoped>
799   -.up-color-picker {
800   - &__content {
801   - width: 100%;
802   - padding: 20px;
803   - background-color: #fff;
804   - }
805   -
806   - &__header {
807   - text-align: center;
808   - margin-bottom: 20px;
809   - }
810   -
811   - &__title {
812   - font-size: 18px;
813   - font-weight: bold;
814   - color: #333;
815   - }
816   -
817   - &__switch {
818   - margin-bottom: 20px;
819   - }
820   -
821   - &__saturation {
822   - position: relative;
823   - width: 100%;
824   - height: 150px;
825   - border-radius: 4px;
826   - margin-bottom: 15px;
827   - overflow: hidden;
828   -
829   - &:after {
830   - content: '';
831   - position: absolute;
832   - top: 0;
833   - left: 0;
834   - right: 0;
835   - bottom: 0;
836   - background: linear-gradient(to right, #fff, rgba(255,255,255,0));
837   - }
838   -
839   - &:before {
840   - content: '';
841   - position: absolute;
842   - top: 0;
843   - left: 0;
844   - right: 0;
845   - bottom: 0;
846   - background: linear-gradient(to top, #000, rgba(0,0,0,0));
847   - }
848   - }
849   -
850   - &__saturation-pointer {
851   - position: absolute;
852   - width: 12px;
853   - height: 12px;
854   - border: 2px solid #fff;
855   - border-radius: 50%;
856   - transform: translate(-50%, -50%);
857   - box-shadow: 0 0 2px rgba(0,0,0,0.5);
858   - pointer-events: none;
859   - }
860   -
861   - &__hue,
862   - &__alpha {
863   - position: relative;
864   - width: 100%;
865   - height: 12px;
866   - border-radius: 6px;
867   - margin-bottom: 15px;
868   - cursor: pointer;
869   - }
870   -
871   - &__hue {
872   - background: linear-gradient(to right, #f00 0%, #ff0 16.66%, #0f0 33.33%, #0ff 50%, #00f 66.66%, #f0f 83.33%, #f00 100%);
873   - }
874   -
875   - &__alpha {
876   - position: relative;
877   - overflow: hidden;
878   -
879   - &-bg {
880   - position: absolute;
881   - top: 0;
882   - left: 0;
883   - right: 0;
884   - bottom: 0;
885   - background: linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%),
886   - linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%);
887   - background-size: 10px 10px;
888   - background-position: 0 0, 5px 5px;
889   - }
890   -
891   - &:after {
892   - content: '';
893   - position: absolute;
894   - top: 0;
895   - left: 0;
896   - right: 0;
897   - bottom: 0;
898   - background: linear-gradient(to right, rgba(255,255,255,0), rgba(255,255,255,1));
899   - }
900   - }
901   -
902   - &__hue-pointer,
903   - &__alpha-pointer {
904   - position: absolute;
905   - width: 4px;
906   - height: 16px;
907   - background: #fff;
908   - border: 1px solid #ccc;
909   - border-radius: 2px;
910   - transform: translateX(-50%);
911   - top: -2px;
912   - box-shadow: 0 0 2px rgba(0,0,0,0.5);
913   - pointer-events: none;
914   - }
915   -
916   - &__gradient {
917   - &-bar {
918   - width: 100%;
919   - height: 40px;
920   - border-radius: 4px;
921   - }
922   -
923   - &-track {
924   - position: relative;
925   - margin-top: 20px;
926   - width: 100%;
927   - height: 32px;
928   - border-radius: 4px;
929   - margin-bottom: 15px;
930   - cursor: pointer;
931   - }
932   -
933   - &-pointer {
934   - position: absolute;
935   - top: -10px;
936   - transform: translateX(-50%);
937   - width: 0;
938   - height: 0;
939   - border-left: 8px solid transparent;
940   - border-right: 8px solid transparent;
941   - border-top: 10px solid #333;
942   - z-index: 10;
943   - }
944   -
945   - &-pointer-inner {
946   - position: absolute;
947   - top: -25px;
948   - left: -10px;
949   - width: 20px;
950   - height: 20px;
951   - border-radius: 50%;
952   - border: 2px solid #fff;
953   - box-shadow: 0 0 2px rgba(0,0,0,0.5);
954   - }
955   -
956   - &-controls {
957   - display: flex;
958   - flex-direction: row;
959   - flex-wrap: wrap;
960   - align-items: center;
961   - margin-bottom: 15px;
962   - }
963   -
964   - &-item {
965   - display: flex;
966   - flex-direction: row;
967   - align-items: center;
968   - margin-right: 10px;
969   - margin-bottom: 10px;
970   - }
971   -
972   - &-color-preview {
973   - width: 20px;
974   - height: 20px;
975   - border-radius: 50%;
976   - margin-right: 5px;
977   - border: 1px solid #eee;
978   - }
979   -
980   - &-percent {
981   - font-size: 12px;
982   - color: #666;
983   - margin-right: 5px;
984   - }
985   -
986   - &-direction {
987   - display: flex;
988   - flex-direction: row;
989   - align-items: center;
990   - margin: 10px 0;
991   - }
992   -
993   - &__direction-circle {
994   - width: 40px;
995   - height: 40px;
996   - border-radius: 50%;
997   - background: conic-gradient(
998   - #ff0000 0deg,
999   - #ffff00 60deg,
1000   - #00ff00 120deg,
1001   - #00ffff 180deg,
1002   - #0000ff 240deg,
1003   - #ff00ff 300deg,
1004   - #ff0000 360deg
1005   - );
1006   - position: relative;
1007   - margin: 10px auto;
1008   - cursor: pointer;
1009   - border: 2px solid #eee;
1010   - }
1011   -
1012   - &__direction-pointer {
1013   - position: absolute;
1014   - width: 6px;
1015   - height: 6px;
1016   - background: #fff;
1017   - border: 2px solid #333;
1018   - border-radius: 50%;
1019   - transform: translate(-50%, -50%);
1020   - box-shadow: 0 0 2px rgba(0,0,0,0.5);
1021   - z-index: 10;
1022   - pointer-events: none;
1023   - }
1024   - }
1025   -
1026   - &__add-btn {
1027   - margin-top: 10px;
1028   - }
1029   -
1030   - &__common {
1031   - margin-top: 20px;
1032   -
1033   - &-title {
1034   - display: block;
1035   - margin-bottom: 10px;
1036   - font-size: 14px;
1037   - color: #666;
1038   - }
1039   -
1040   - &-list {
1041   - display: flex;
1042   - flex-direction: row;
1043   - flex-wrap: wrap;
1044   - }
1045   -
1046   - &-item {
1047   - width: 24px;
1048   - height: 24px;
1049   - border-radius: 50%;
1050   - margin-right: 10px;
1051   - margin-bottom: 10px;
1052   - border: 1px solid #eee;
1053   - cursor: pointer;
1054   - }
1055   - }
1056   -
1057   - &__footer {
1058   - margin-top: 20px;
1059   - }
1060   -
1061   - &__preview {
1062   - display: flex;
1063   - flex-direction: row;
1064   - align-items: center;
1065   - margin-bottom: 15px;
1066   - }
1067   -
1068   - &__preview-color {
1069   - width: 40px;
1070   - height: 40px;
1071   - border-radius: 4px;
1072   - border: 1px solid #eee;
1073   - margin-right: 10px;
1074   - }
1075   -
1076   - &__preview-text {
1077   - font-size: 14px;
1078   - color: #333;
1079   - flex: 1;
1080   - overflow: hidden;
1081   - text-overflow: ellipsis;
1082   - white-space: nowrap;
1083   - }
1084   -
1085   - &__actions {
1086   - display: flex;
1087   - flex-direction: row;
1088   - justify-content: flex-end;
1089   -
1090   - & .up-color-picker__btn {
1091   - margin-left: 10px;
1092   - }
1093   - }
1094   -}
1095   -</style>
uni_modules/uview-plus/components/u-column-notice/columnNotice.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:57:16
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/columnNotice.js
9   - */
10   -export default {
11   - // columnNotice 组件
12   - columnNotice: {
13   - text: '',
14   - icon: 'volume',
15   - mode: '',
16   - color: '#f9ae3d',
17   - bgColor: '#fdf6ec',
18   - fontSize: 14,
19   - speed: 80,
20   - step: false,
21   - duration: 1500,
22   - disableTouch: true,
23   - justifyContent: 'flex-start'
24   - }
25   -}
uni_modules/uview-plus/components/u-column-notice/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 显示的内容,字符串
6   - text: {
7   - type: [Array],
8   - default: () => defProps.columnNotice.text
9   - },
10   - // 是否显示左侧的音量图标
11   - icon: {
12   - type: String,
13   - default: () => defProps.columnNotice.icon
14   - },
15   - // 通告模式,link-显示右箭头,closable-显示右侧关闭图标
16   - mode: {
17   - type: String,
18   - default: () => defProps.columnNotice.mode
19   - },
20   - // 文字颜色,各图标也会使用文字颜色
21   - color: {
22   - type: String,
23   - default: () => defProps.columnNotice.color
24   - },
25   - // 背景颜色
26   - bgColor: {
27   - type: String,
28   - default: () => defProps.columnNotice.bgColor
29   - },
30   - // 字体大小,单位px
31   - fontSize: {
32   - type: [String, Number],
33   - default: () => defProps.columnNotice.fontSize
34   - },
35   - // 水平滚动时的滚动速度,即每秒滚动多少px(px),这有利于控制文字无论多少时,都能有一个恒定的速度
36   - speed: {
37   - type: [String, Number],
38   - default: () => defProps.columnNotice.speed
39   - },
40   - // direction = row时,是否使用步进形式滚动
41   - step: {
42   - type: Boolean,
43   - default: () => defProps.columnNotice.step
44   - },
45   - // 滚动一个周期的时间长,单位ms
46   - duration: {
47   - type: [String, Number],
48   - default: () => defProps.columnNotice.duration
49   - },
50   - // 是否禁止用手滑动切换
51   - // 目前HX2.6.11,只支持App 2.5.5+、H5 2.5.5+、支付宝小程序、字节跳动小程序
52   - disableTouch: {
53   - type: Boolean,
54   - default: () => defProps.columnNotice.disableTouch
55   - },
56   - justifyContent: {
57   - type: String,
58   - default: () => defProps.columnNotice.justifyContent
59   - }
60   - }
61   -})
uni_modules/uview-plus/components/u-column-notice/u-column-notice.vue deleted
1   -<template>
2   - <view
3   - class="u-notice"
4   - @tap="clickHandler"
5   - >
6   - <slot name="icon">
7   - <view
8   - class="u-notice__left-icon"
9   - v-if="icon"
10   - >
11   - <up-icon
12   - :name="icon"
13   - :color="color"
14   - size="19"
15   - ></up-icon>
16   - </view>
17   - </slot>
18   - <swiper
19   - :disable-touch="disableTouch"
20   - :vertical="step ? false : true"
21   - circular
22   - :interval="duration"
23   - :autoplay="true"
24   - class="u-notice__swiper"
25   - @change="noticeChange"
26   - >
27   - <swiper-item
28   - v-for="(item, index) in text"
29   - :key="index"
30   - class="u-notice__swiper__item"
31   - :style="{'justifyContent': justifyContent}"
32   - >
33   - <text
34   - class="u-notice__swiper__item__text u-line-1"
35   - :style="[textStyle]"
36   - >{{ item }}</text>
37   - </swiper-item>
38   - </swiper>
39   - <view
40   - class="u-notice__right-icon"
41   - v-if="['link', 'closable'].includes(mode)"
42   - >
43   - <up-icon
44   - v-if="mode === 'link'"
45   - name="arrow-right"
46   - :size="17"
47   - :color="color"
48   - ></up-icon>
49   - <up-icon
50   - v-if="mode === 'closable'"
51   - name="close"
52   - :size="16"
53   - :color="color"
54   - @click="close"
55   - ></up-icon>
56   - </view>
57   - </view>
58   -</template>
59   -
60   -<script>
61   - import { props } from './props';
62   - import { mpMixin } from '../../libs/mixin/mpMixin';
63   - import { mixin } from '../../libs/mixin/mixin';
64   - import { addUnit, error } from '../../libs/function/index';
65   - import test from '../../libs/function/test';
66   - /**
67   - * ColumnNotice 滚动通知中的垂直滚动 内部组件
68   - * @description 该组件用于滚动通告场景,是其中的垂直滚动方式
69   - * @tutorial https://uview-plus.jiangruyi.com/components/noticeBar.html
70   - * @property {Array} text 显示的内容,字符串
71   - * @property {String} icon 是否显示左侧的音量图标 ( 默认 'volume' )
72   - * @property {String} mode 通告模式,link-显示右箭头,closable-显示右侧关闭图标
73   - * @property {String} color 文字颜色,各图标也会使用文字颜色 ( 默认 '#f9ae3d' )
74   - * @property {String} bgColor 背景颜色 ( 默认 '#fdf6ec' )
75   - * @property {String | Number} fontSize 字体大小,单位px ( 默认 14 )
76   - * @property {String | Number} speed 水平滚动时的滚动速度,即每秒滚动多少px(rpx),这有利于控制文字无论多少时,都能有一个恒定的速度 ( 默认 80 )
77   - * @property {Boolean} step direction = row时,是否使用步进形式滚动 ( 默认 false )
78   - * @property {String | Number} duration 滚动一个周期的时间长,单位ms ( 默认 1500 )
79   - * @property {Boolean} disableTouch 是否禁止用手滑动切换 目前HX2.6.11,只支持App 2.5.5+、H5 2.5.5+、支付宝小程序、字节跳动小程序 ( 默认 true )
80   - * @example
81   - */
82   - export default {
83   - mixins: [mpMixin, mixin, props],
84   - watch: {
85   - text: {
86   - immediate: true,
87   - handler(newValue, oldValue) {
88   - if(!test.array(newValue)) {
89   - error('noticebar组件direction为column时,要求text参数为数组形式')
90   - }
91   - }
92   - }
93   - },
94   - computed: {
95   - // 文字内容的样式
96   - textStyle() {
97   - let style = {}
98   - style.color = this.color
99   - style.fontSize = addUnit(this.fontSize)
100   - return style
101   - },
102   - // 垂直或者水平滚动
103   - vertical() {
104   - if (this.mode == 'horizontal') return false
105   - else return true
106   - },
107   - },
108   - data() {
109   - return {
110   - index:0
111   - }
112   - },
113   - emits: ["click", "close"],
114   - methods: {
115   - noticeChange(e){
116   - this.index = e.detail.current
117   - },
118   - // 点击通告栏
119   - clickHandler() {
120   - this.$emit('click', this.index)
121   - },
122   - // 点击关闭按钮
123   - close() {
124   - this.$emit('close')
125   - }
126   - }
127   - };
128   -</script>
129   -
130   -<style lang="scss" scoped>
131   -
132   - .u-notice {
133   - @include flex;
134   - align-items: center;
135   - justify-content: space-between;
136   -
137   - &__left-icon {
138   - align-items: center;
139   - margin-right: 5px;
140   - }
141   -
142   - &__right-icon {
143   - margin-left: 5px;
144   - align-items: center;
145   - }
146   -
147   - &__swiper {
148   - height: 16px;
149   - @include flex;
150   - align-items: center;
151   - flex: 1;
152   -
153   - &__item {
154   - @include flex;
155   - align-items: center;
156   - overflow: hidden;
157   -
158   - &__text {
159   - font-size: 14px;
160   - color: $u-warning;
161   - }
162   - }
163   - }
164   - }
165   -</style>
uni_modules/uview-plus/components/u-copy/u-copy.vue deleted
1   -<template>
2   - <view @click="handleClick">
3   - <slot>{{ t("up.common.copy") }}</slot>
4   - </view>
5   -</template>
6   -<script>
7   -import { t } from '../../libs/i18n'
8   -export default {
9   - name: "up-copy",
10   - props: {
11   - content: {
12   - type: String,
13   - default: ''
14   - },
15   - alertStyle: {
16   - type: String,
17   - default: 'toast'
18   - },
19   - notice: {
20   - type: String,
21   - default: t("up.common.copy") + t("up.common.success")
22   - }
23   - },
24   - emits: ['success'],
25   - methods: {
26   - t,
27   - handleClick() {
28   - let content = this.content;
29   - if (!content) {
30   - uni.showToast({
31   - title: t("up.common.none"),
32   - icon: 'none',
33   - duration: 2000,
34   - });
35   - return false;
36   - }
37   - content = typeof content === 'string' ? content : content.toString() // 复制内容,必须字符串,数字需要转换为字符串
38   - /**
39   - * 小程序端 和 app端的复制逻辑
40   - */
41   - let that = this;
42   - uni.setClipboardData({
43   - data: content,
44   - success: function() {
45   - if (that.alertStyle == 'modal') {
46   - uni.showModal({
47   - title: "up.common.tip",
48   - content: that.notice
49   - });
50   - } else {
51   - uni.showToast({
52   - title: that.notice,
53   - icon: 'none'
54   - });
55   - }
56   - that.$emit('success');
57   - },
58   - fail:function(){
59   - uni.showToast({
60   - title: t("up.common.copy") + t("up.common.fail"),
61   - icon: 'none',
62   - duration:3000,
63   - });
64   - }
65   - });
66   - }
67   - }
68   -}
69   -</script>
70   -
71   -<style lang="scss" scoped>
72   -</style>
uni_modules/uview-plus/components/u-count-down/countDown.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 17:11:29
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/countDown.js
9   - */
10   -export default {
11   - // u-count-down 计时器组件
12   - countDown: {
13   - time: 0,
14   - format: 'HH:mm:ss',
15   - autoStart: true,
16   - millisecond: false
17   - }
18   -}
uni_modules/uview-plus/components/u-count-down/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 倒计时时长,单位ms
6   - time: {
7   - type: [String, Number],
8   - default: () => defProps.countDown.time
9   - },
10   - // 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒
11   - format: {
12   - type: String,
13   - default: () => defProps.countDown.format
14   - },
15   - // 是否自动开始倒计时
16   - autoStart: {
17   - type: Boolean,
18   - default: () => defProps.countDown.autoStart
19   - },
20   - // 是否展示毫秒倒计时
21   - millisecond: {
22   - type: Boolean,
23   - default: () => defProps.countDown.millisecond
24   - }
25   - }
26   -})
uni_modules/uview-plus/components/u-count-down/u-count-down.vue deleted
1   -<template>
2   - <view class="u-count-down">
3   - <slot :days="timeData.days" :hours="timeData.hours"
4   - :minutes="timeData.minutes" :seconds="timeData.seconds">
5   - <text class="u-count-down__text">{{ formattedTime }}</text>
6   - </slot>
7   - </view>
8   -</template>
9   -
10   -<script>
11   - import { props } from './props';
12   - import { mpMixin } from '../../libs/mixin/mpMixin';
13   - import { mixin } from '../../libs/mixin/mixin';
14   - import {
15   - isSameSecond,
16   - parseFormat,
17   - parseTimeData
18   - } from './utils';
19   - /**
20   - * u-count-down 倒计时
21   - * @description 该组件一般使用于某个活动的截止时间上,通过数字的变化,给用户明确的时间感受,提示用户进行某一个行为操作。
22   - * @tutorial https://uview-plus.jiangruyi.com/components/countDown.html
23   - * @property {String | Number} time 倒计时时长,单位ms (默认 0 )
24   - * @property {String} format 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒 (默认 'HH:mm:ss' )
25   - * @property {Boolean} autoStart 是否自动开始倒计时 (默认 true )
26   - * @property {Boolean} millisecond 是否展示毫秒倒计时 (默认 false )
27   - * @event {Function} finish 倒计时结束时触发
28   - * @event {Function} change 倒计时变化时触发
29   - * @event {Function} start 开始倒计时
30   - * @event {Function} pause 暂停倒计时
31   - * @event {Function} reset 重设倒计时,若 auto-start 为 true,重设后会自动开始倒计时
32   - * @example <u-count-down :time="time"></u-count-down>
33   - */
34   - export default {
35   - name: 'u-count-down',
36   - mixins: [mpMixin, mixin, props],
37   - data() {
38   - return {
39   - timer: null,
40   - // 各单位(天,时,分等)剩余时间
41   - timeData: parseTimeData(0),
42   - // 格式化后的时间,如"03:23:21"
43   - formattedTime: '0',
44   - // 倒计时是否正在进行中
45   - runing: false,
46   - endTime: 0, // 结束的毫秒时间戳
47   - remainTime: 0, // 剩余的毫秒时间
48   - }
49   - },
50   - watch: {
51   - time(n) {
52   - this.reset()
53   - }
54   - },
55   - mounted() {
56   - this.init()
57   - },
58   - emits: ["change", "finish"],
59   - methods: {
60   - init() {
61   - this.reset()
62   - },
63   - // 开始倒计时
64   - start() {
65   - if (this.runing) return
66   - // 标识为进行中
67   - this.runing = true
68   - // 结束时间戳 = 此刻时间戳 + 剩余的时间
69   - this.endTime = Date.now() + this.remainTime
70   - this.toTick()
71   - },
72   - // 根据是否展示毫秒,执行不同操作函数
73   - toTick() {
74   - if (this.millisecond) {
75   - this.microTick()
76   - } else {
77   - this.macroTick()
78   - }
79   - },
80   - macroTick() {
81   - this.clearTimeout()
82   - // 每隔一定时间,更新一遍定时器的值
83   - // 同时此定时器的作用也能带来毫秒级的更新
84   - this.timer = setTimeout(() => {
85   - // 获取剩余时间
86   - const remain = this.getRemainTime()
87   - // 重设剩余时间
88   - if (!isSameSecond(remain, this.remainTime) || remain === 0) {
89   - this.setRemainTime(remain)
90   - }
91   - // 如果剩余时间不为0,则继续检查更新倒计时
92   - if (this.remainTime !== 0) {
93   - this.macroTick()
94   - }
95   - }, 30)
96   - },
97   - microTick() {
98   - this.clearTimeout()
99   - this.timer = setTimeout(() => {
100   - this.setRemainTime(this.getRemainTime())
101   - if (this.remainTime !== 0) {
102   - this.microTick()
103   - }
104   - }, 50)
105   - },
106   - // 获取剩余的时间
107   - getRemainTime() {
108   - // 取最大值,防止出现小于0的剩余时间值
109   - return Math.max(this.endTime - Date.now(), 0)
110   - },
111   - // 设置剩余的时间
112   - setRemainTime(remain) {
113   - this.remainTime = remain
114   - // 根据剩余的毫秒时间,得出该有天,小时,分钟等的值,返回一个对象
115   - const timeData = parseTimeData(remain)
116   - this.timeData = timeData;
117   - this.$emit('change', timeData)
118   - // 得出格式化后的时间
119   - this.formattedTime = parseFormat(this.format, timeData)
120   - // 如果时间已到,停止倒计时
121   - if (remain <= 0) {
122   - this.pause()
123   - this.$emit('finish')
124   - }
125   - },
126   - // 重置倒计时
127   - reset() {
128   - this.pause()
129   - this.remainTime = this.time
130   - this.setRemainTime(this.remainTime)
131   - if (this.autoStart) {
132   - this.start()
133   - }
134   - },
135   - // 暂停倒计时
136   - pause() {
137   - this.runing = false;
138   - this.clearTimeout()
139   - },
140   - // 清空定时器
141   - clearTimeout() {
142   - clearTimeout(this.timer)
143   - this.timer = null
144   - }
145   - },
146   - beforeUnmount() {
147   - this.clearTimeout()
148   - }
149   - }
150   -</script>
151   -
152   -<style
153   - lang="scss"
154   - scoped
155   ->
156   - $u-count-down-text-color:$u-content-color !default;
157   - $u-count-down-text-font-size:15px !default;
158   - $u-count-down-text-line-height:22px !default;
159   -
160   - .u-count-down {
161   - &__text {
162   - color: $u-count-down-text-color;
163   - font-size: $u-count-down-text-font-size;
164   - line-height: $u-count-down-text-line-height;
165   - }
166   - }
167   -</style>
uni_modules/uview-plus/components/u-count-down/utils.js deleted
1   -// 补0,如1 -> 01
2   -function padZero(num, targetLength = 2) {
3   - let str = `${num}`
4   - while (str.length < targetLength) {
5   - str = `0${str}`
6   - }
7   - return str
8   -}
9   -const SECOND = 1000
10   -const MINUTE = 60 * SECOND
11   -const HOUR = 60 * MINUTE
12   -const DAY = 24 * HOUR
13   -export function parseTimeData(time) {
14   - const days = Math.floor(time / DAY)
15   - const hours = Math.floor((time % DAY) / HOUR)
16   - const minutes = Math.floor((time % HOUR) / MINUTE)
17   - const seconds = Math.floor((time % MINUTE) / SECOND)
18   - const milliseconds = Math.floor(time % SECOND)
19   - return {
20   - days,
21   - hours,
22   - minutes,
23   - seconds,
24   - milliseconds
25   - }
26   -}
27   -export function parseFormat(format, timeData) {
28   - let {
29   - days,
30   - hours,
31   - minutes,
32   - seconds,
33   - milliseconds
34   - } = timeData
35   - // 如果格式化字符串中不存在DD(天),则将天的时间转为小时中去
36   - if (format.indexOf('DD') === -1) {
37   - hours += days * 24
38   - } else {
39   - // 对天补0
40   - format = format.replace('DD', padZero(days))
41   - }
42   - // 其他同理于DD的格式化处理方式
43   - if (format.indexOf('HH') === -1) {
44   - minutes += hours * 60
45   - } else {
46   - format = format.replace('HH', padZero(hours))
47   - }
48   - if (format.indexOf('mm') === -1) {
49   - seconds += minutes * 60
50   - } else {
51   - format = format.replace('mm', padZero(minutes))
52   - }
53   - if (format.indexOf('ss') === -1) {
54   - milliseconds += seconds * 1000
55   - } else {
56   - format = format.replace('ss', padZero(seconds))
57   - }
58   - return format.replace('SSS', padZero(milliseconds, 3))
59   -}
60   -export function isSameSecond(time1, time2) {
61   - return Math.floor(time1 / 1000) === Math.floor(time2 / 1000)
62   -}
uni_modules/uview-plus/components/u-count-to/countTo.js deleted
1   -/*
2   - * @Author : LQ
3   - * @Description :
4   - * @version : 1.0
5   - * @Date : 2021-08-20 16:44:21
6   - * @LastAuthor : LQ
7   - * @lastTime : 2021-08-20 16:57:32
8   - * @FilePath : /u-view2.0/uview-ui/libs/config/props/countTo.js
9   - */
10   -export default {
11   - // countTo 组件
12   - countTo: {
13   - startVal: 0,
14   - endVal: 0,
15   - duration: 2000,
16   - autoplay: true,
17   - decimals: 0,
18   - useEasing: true,
19   - decimal: '.',
20   - color: '#606266',
21   - fontSize: 22,
22   - bold: false,
23   - separator: ''
24   - }
25   -}
uni_modules/uview-plus/components/u-count-to/props.js deleted
1   -import { defineMixin } from '../../libs/vue'
2   -import defProps from '../../libs/config/props.js'
3   -export const props = defineMixin({
4   - props: {
5   - // 开始的数值,默认从0增长到某一个数
6   - startVal: {
7   - type: [String, Number],
8   - default: () => defProps.countTo.startVal
9   - },
10   - // 要滚动的目标数值,必须
11   - endVal: {
12   - type: [String, Number],
13   - default: () => defProps.countTo.endVal
14   - },
15   - // 滚动到目标数值的动画持续时间,单位为毫秒(ms)
16   - duration: {
17   - type: [String, Number],
18   - default: () => defProps.countTo.duration
19   - },
20   - // 设置数值后是否自动开始滚动
21   - autoplay: {
22   - type: Boolean,
23   - default: () => defProps.countTo.autoplay
24   - },
25   - // 要显示的小数位数
26   - decimals: {
27   - type: [String, Number],
28   - default: () => defProps.countTo.decimals
29   - },
30   - // 是否在即将到达目标数值的时候,使用缓慢滚动的效果
31   - useEasing: {
32   - type: Boolean,
33   - default: () => defProps.countTo.useEasing
34   - },
35   - // 十进制分割
36   - decimal: {
37   - type: [String, Number],
38   - default: () => defProps.countTo.decimal
39   - },
40   - // 字体颜色
41   - color: {
42   - type: String,
43   - default: () => defProps.countTo.color
44   - },
45   - // 字体大小
46   - fontSize: {
47   - type: [String, Number],
48   - default: () => defProps.countTo.fontSize
49   - },
50   - // 是否加粗字体
51   - bold: {
52   - type: Boolean,
53   - default: () => defProps.countTo.bold
54   - },
55   - // 千位分隔符,类似金额的分割(¥23,321.05中的",")
56   - separator: {
57   - type: String,
58   - default: () => defProps.countTo.separator
59   - }
60   - }
61   -})
uni_modules/uview-plus/components/u-count-to/u-count-to.vue deleted
1   -<template>
2   - <text
3   - class="u-count-num"
4   - :style="{
5   - fontSize: addUnit(fontSize),
6   - fontWeight: bold ? 'bold' : 'normal',
7   - color: color
8   - }"
9   - >{{ displayValue }}</text>
10   -</template>
11   -
12   -<script>
13   -import { props } from './props';
14   -import { mpMixin } from '../../libs/mixin/mpMixin';
15   -import { mixin } from '../../libs/mixin/mixin';
16   -import { addUnit } from '../../libs/function/index';
17   -/**
18   - * countTo 数字滚动
19   - * @description 该组件一般用于需要滚动数字到某一个值的场景,目标要求是一个递增的值。
20   - * @tutorial https://uview-plus.jiangruyi.com/components/countTo.html
21   - * @property {String | Number} startVal 开始的数值,默认从0增长到某一个数(默认 0 )
22   - * @property {String | Number} endVal 要滚动的目标数值,必须 (默认 0 )
23   - * @property {String | Number} duration 滚动到目标数值的动画持续时间,单位为毫秒(ms) (默认 2000 )
24   - * @property {Boolean} autoplay 设置数值后是否自动开始滚动 (默认 true )
25   - * @property {String | Number} decimals 要显示的小数位数,见官网说明(默认 0 )
26   - * @property {Boolean} useEasing 滚动结束时,是否缓动结尾,见官网说明(默认 true )
27   - * @property {String} decimal 十进制分割 ( 默认 "." )
28   - * @property {String} color 字体颜色( 默认 '#606266' )
29   - * @property {String | Number} fontSize 字体大小,单位px( 默认 22 )
30   - * @property {Boolean} bold 字体是否加粗(默认 false )
31   - * @property {String} separator 千位分隔符,见官网说明
32   - * @event {Function} end 数值滚动到目标值时触发
33   - * @example <u-count-to ref="uCountTo" :end-val="endVal" :autoplay="autoplay"></u-count-to>
34   - */
35   -export default {
36   - name: 'u-count-to',
37   - data() {
38   - return {
39   - localStartVal: this.startVal,
40   - displayValue: this.formatNumber(this.startVal),
41   - printVal: null,
42   - paused: false, // 是否暂停
43   - localDuration: Number(this.duration),
44   - startTime: null, // 开始的时间
45   - timestamp: null, // 时间戳
46   - remaining: null, // 停留的时间
47   - rAF: null,
48   - lastTime: 0 // 上一次的时间
49   - };
50   - },
51   - mixins: [mpMixin, mixin,props],
52   - computed: {
53   - countDown() {
54   - return this.startVal > this.endVal;
55   - }
56   - },
57   - watch: {
58   - startVal() {
59   - this.autoplay && this.start();
60   - },
61   - endVal() {
62   - this.autoplay && this.start();
63   - }
64   - },
65   - mounted() {
66   - this.autoplay && this.start();
67   - },
68   - emits: ["end"],
69   - methods: {
70   - addUnit,
71   - easingFn(t, b, c, d) {
72   - return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b;
73   - },
74   - requestAnimationFrame(callback) {
75   - const currTime = new Date().getTime();
76   - // 为了使setTimteout的尽可能的接近每秒60帧的效果
77   - const timeToCall = Math.max(0, 16 - (currTime - this.lastTime));
78   - const id = setTimeout(() => {
79   - callback(currTime + timeToCall);
80   - }, timeToCall);
81   - this.lastTime = currTime + timeToCall;
82   - return id;
83   - },
84   - cancelAnimationFrame(id) {
85   - clearTimeout(id);
86   - },
87   - // 开始滚动数字
88   - start() {
89   - this.localStartVal = this.startVal;
90   - this.startTime = null;
91   - this.localDuration = this.duration;
92   - this.paused = false;
93   - this.rAF = this.requestAnimationFrame(this.count);
94   - },
95   - // 暂定状态,重新再开始滚动;或者滚动状态下,暂停
96   - reStart() {
97   - if (this.paused) {
98   - this.resume();
99   - this.paused = false;
100   - } else {
101   - this.stop();
102   - this.paused = true;
103   - }
104   - },
105   - // 暂停
106   - stop() {
107   - this.cancelAnimationFrame(this.rAF);
108   - },
109   - // 重新开始(暂停的情况下)
110   - resume() {
111   - if (!this.remaining) return
112   - this.startTime = 0;
113   - this.localDuration = this.remaining;
114   - this.localStartVal = this.printVal;
115   - this.requestAnimationFrame(this.count);
116   - },
117   - // 重置
118   - reset() {
119   - this.startTime = null;
120   - this.cancelAnimationFrame(this.rAF);
121   - this.displayValue = this.formatNumber(this.startVal);
122   - },
123   - count(timestamp) {
124   - if (!this.startTime) this.startTime = timestamp;
125   - this.timestamp = timestamp;
126   - const progress = timestamp - this.startTime;
127   - this.remaining = this.localDuration - progress;
128   - if (this.useEasing) {
129   - if (this.countDown) {
130   - this.printVal = this.localStartVal - this.easingFn(progress, 0, this.localStartVal - this.endVal, this.localDuration);
131   - } else {
132   - this.printVal = this.easingFn(progress, this.localStartVal, this.endVal - this.localStartVal, this.localDuration);
133   - }
134   - } else {
135   - if (this.countDown) {
136   - this.printVal = this.localStartVal - (this.localStartVal - this.endVal) * (progress / this.localDuration);
137   - } else {
138   - this.printVal = this.localStartVal + (this.endVal - this.localStartVal) * (progress / this.localDuration);
139   - }
140   - }
141   - if (this.countDown) {
142   - this.printVal = this.printVal < this.endVal ? this.endVal : this.printVal;
143   - } else {
144   - this.printVal = this.printVal > this.endVal ? this.endVal : this.printVal;
145   - }
146   - this.displayValue = this.formatNumber(this.printVal) || 0;
147   - if (progress < this.localDuration) {
148   - this.rAF = this.requestAnimationFrame(this.count);
149   - } else {
150   - this.$emit('end');
151   - }
152   - },
153   - // 判断是否数字
154   - isNumber(val) {
155   - return !isNaN(parseFloat(val));
156   - },
157   - formatNumber(num) {
158   - // 将num转为Number类型,因为其值可能为字符串数值,调用toFixed会报错
159   - num = Number(num);
160   - num = num.toFixed(Number(this.decimals));
161   - num += '';
162   - const x = num.split('.');
163   - let x1 = x[0];
164   - const x2 = x.length > 1 ? this.decimal + x[1] : '';
165   - const rgx = /(\d+)(\d{3})/;
166   - if (this.separator && !this.isNumber(this.separator)) {
167   - while (rgx.test(x1)) {
168   - x1 = x1.replace(rgx, '$1' + this.separator + '$2');
169   - }
170   - }
171   - return x1 + x2;
172   - },
173   - destroyed() {
174   - this.cancelAnimationFrame(this.rAF);
175   - }
176   - }
177   -};
178   -</script>
179   -
180   -<style lang="scss" scoped>
181   -.u-count-num {
182   - /* #ifndef APP-NVUE */
183   - display: inline-flex;
184   - /* #endif */
185   - text-align: center;
186   -}
187   -</style>
uni_modules/uview-plus/components/u-coupon/u-coupon.vue deleted
1   -<template>
2   - <view class="up-coupon" :class="[`up-coupon--${shape}`, `up-coupon--${type}`, `up-coupon--${size}`, {'up-coupon--disabled': disabled}]"
3   - :style="[couponStyle]" @click="handleClick">
4   - <view class="up-coupon__content">
5   - <!-- 左侧金额区域 -->
6   - <view class="up-coupon__amount">
7   - <slot name="unit" :unit="unit" :unitPosition="unitPosition" v-if="unitPosition === 'left'">
8   - <text class="up-coupon__amount-unit" v-if="unitPosition === 'left'">{{ unit }}</text>
9   - </slot>
10   - <slot name="amount" :amount="amount">
11   - <text class="up-coupon__amount-value">{{ amount }}</text>
12   - </slot>
13   - <slot name="unit" :unit="unit" :unitPosition="unitPosition" v-if="unitPosition === 'right'">
14   - <text class="up-coupon__amount-unit" v-if="unitPosition === 'right'">{{ unit }}</text>
15   - </slot>
16   - <slot name="limit" :limit="limit">
17   - <text class="up-coupon__amount-limit" v-if="limit">{{ limit }}</text>
18   - </slot>
19   - </view>
20   -
21   - <!-- 中间描述区域 -->
22   - <view class="up-coupon__info">
23   - <slot name="title" :title="title">
24   - <text class="up-coupon__info-title">{{ title }}</text>
25   - </slot>
26   - <slot name="desc" :desc="desc">
27   - <text class="up-coupon__info-desc" v-if="desc">{{ desc }}</text>
28   - </slot>
29   - <slot name="time" :time="time">
30   - <text class="up-coupon__info-time" v-if="time">{{ time }}</text>
31   - </slot>
32   - </view>
33   -
34   - <!-- 右侧操作区域 -->
35   - <view class="up-coupon__action u-padding-right-20">
36   - <slot name="action" :actionText="actionText" :circle="circle">
37   - <up-tag type="error" :bgColor="type ? 'transparent' : '#eb433d'"
38   - :borderColor="type ? '#eee' : '#eb433d'" borderRadius="6px"
39   - size="medium" class="up-coupon__action-text"
40   - :shape="circle ? 'circle': 'circle'">{{ actionText }}</up-tag>
41   - </slot>
42   - </view>
43   - </view>
44   -
45   - <!-- 红包绳子效果 -->
46   - <view v-if="shape === 'envelope'" class="up-coupon__rope"></view>
47   -
48   - <!-- 默认插槽,可用于添加额外内容 -->
49   - <slot></slot>
50   - </view>
51   -</template>
52   -
53   -<script>
54   - export default {
55   - name: 'up-coupon',
56   - props: {
57   - // 金额
58   - amount: {
59   - type: [String, Number],
60   - default: ''
61   - },
62   - // 金额单位
63   - unit: {
64   - type: String,
65   - default: '¥'
66   - },
67   - // 单位位置
68   - unitPosition: {
69   - type: String,
70   - default: 'left'
71   - },
72   - // 使用限制
73   - limit: {
74   - type: String,
75   - default: ''
76   - },
77   - // 标题
78   - title: {
79   - type: String,
80   - default: '优惠券'
81   - },
82   - // 描述
83   - desc: {
84   - type: String,
85   - default: ''
86   - },
87   - // 有效期
88   - time: {
89   - type: String,
90   - default: ''
91   - },
92   - // 操作按钮文字
93   - actionText: {
94   - type: String,
95   - default: '使用'
96   - },
97   - // 形状:coupon-优惠券, envelope-红包, card-卡片
98   - shape: {
99   - type: String,
100   - default: 'coupon'
101   - },
102   - // 尺寸:small, medium, large
103   - size: {
104   - type: String,
105   - default: 'medium'
106   - },
107   - // 是否圆形按钮
108   - circle: {
109   - type: Boolean,
110   - default: false
111   - },
112   - // 是否禁用
113   - disabled: {
114   - type: Boolean,
115   - default: false
116   - },
117   - // 背景颜色
118   - bgColor: {
119   - type: String,
120   - default: ''
121   - },
122   - // 文字颜色
123   - color: {
124   - type: String,
125   - default: ''
126   - },
127   - // 内置背景类型
128   - type: {
129   - type: String,
130   - default: ''
131   - },
132   - },
133   - computed: {
134   - couponStyle() {
135   - const style = {};
136   - if (this.bgColor) style.background = this.bgColor;
137   - if (this.color) style.color = this.color;
138   - return style;
139   - },
140   - dotCount() {
141   - // 根据尺寸计算锯齿数量
142   - const map = {
143   - small: 8,
144   - medium: 10,
145   - large: 12
146   - };
147   - return map[this.size] || 10;
148   - }
149   - },
150   - methods: {
151   - handleClick() {
152   - if (this.disabled) return;
153   - this.$emit('click');
154   - }
155   - }
156   - }
157   -</script>
158   -
159   -<style lang="scss" scoped>
160   - .up-coupon {
161   - position: relative;
162   - overflow: hidden;
163   - border-radius: 8rpx;
164   - background: #ffebf0;
165   - color: $u-main-color;
166   -
167   - &--coupon {
168   - border-radius: 16rpx;
169   - overflow: hidden;
170   -
171   - &::before {
172   - content: '';
173   - position: absolute;
174   - left: -24rpx;
175   - top: 50%;
176   - transform: translateY(-50%);
177   - width: 48rpx;
178   - height: 48rpx;
179   - background-color: #fff;
180   - border-radius: 50%;
181   - }
182   -
183   - &::after {
184   - content: '';
185   - position: absolute;
186   - right: -24rpx;
187   - top: 50%;
188   - transform: translateY(-50%);
189   - width: 48rpx;
190   - height: 48rpx;
191   - background-color: #fff;
192   - border-radius: 50%;
193   - }
194   - }
195   -
196   - &--envelope {
197   - border-radius: 16rpx;
198   -
199   - &::before {
200   - content: '';
201   - position: absolute;
202   - left: 0;
203   - top: 0;
204   - right: 0;
205   - height: 20rpx;
206   - background: repeating-linear-gradient(-45deg, #ffd000, #ffd000 10rpx, #ffa000 10rpx, #ffa000 20rpx);
207   - }
208   - }
209   -
210   - &--card {
211   - border-radius: 16rpx;
212   - }
213   -
214   - width: 100%;
215   -
216   - &--small {
217   - // width: 520rpx;
218   - height: 160rpx;
219   - }
220   -
221   - &--medium {
222   - // width: 600rpx;
223   - height: 180rpx;
224   - }
225   -
226   - &--large {
227   - // width: 700rpx;
228   - height: 220rpx;
229   - }
230   -
231   - &--disabled {
232   - opacity: 0.5;
233   - }
234   -
235   - &__content {
236   - display: flex;
237   - flex-direction: row;
238   - align-items: center;
239   - justify-content: space-between;
240   - height: 100%;
241   - padding: 0 30rpx;
242   - position: relative;
243   - z-index: 2;
244   - }
245   -
246   - &__amount {
247   - display: flex;
248   - flex-direction: column;
249   - align-items: flex-start;
250   - padding-left: 10rpx;
251   - padding-right: 30rpx;
252   - border-right: 1px dashed #ccc;
253   -
254   - &-unit {
255   - font-size: 24rpx;
256   - font-weight: normal;
257   - }
258   -
259   - &-value {
260   - font-size: 56rpx;
261   - font-weight: bold;
262   - color: red;
263   - line-height: 1;
264   - margin: 10rpx 0;
265   - }
266   -
267   - &-limit {
268   - font-size: 24rpx;
269   - opacity: 0.9;
270   - }
271   - }
272   -
273   - &__info {
274   - flex: 1;
275   - display: flex;
276   - flex-direction: column;
277   - align-items: flex-start;
278   - padding-left: 30rpx;
279   -
280   - &-title {
281   - font-size: 32rpx;
282   - font-weight: bold;
283   - margin-bottom: 10rpx;
284   - }
285   -
286   - &-desc {
287   - font-size: 24rpx;
288   - opacity: 0.9;
289   - margin-bottom: 10rpx;
290   - }
291   -
292   - &-time {
293   - font-size: 20rpx;
294   - opacity: 0.8;
295   - }
296   - }
297   -
298   - &__action {
299   - display: flex;
300   - flex-direction: row;
301   - align-items: center;
302   - justify-content: center;
303   - }
304   -
305   - &__dots {
306   - position: absolute;
307   - left: 0;
308   - top: 0;
309   - bottom: 0;
310   - width: 100%;
311   - display: flex;
312   - flex-direction: column;
313   - justify-content: space-between;
314   - padding: 30rpx 0;
315   - z-index: 1;
316   - }
317   -
318   - &__dot {
319   - width: 32rpx;
320   - height: 32rpx;
321   - background-color: #fff;
322   - border-radius: 50%;
323   - margin: 0 -16rpx;
324   - z-index: 3;
325   - }
326   -
327   - &__rope {
328   - position: absolute;
329   - top: -40rpx;
330   - left: 50%;
331   - transform: translateX(-50%);
332   - width: 80rpx;
333   - height: 80rpx;
334   - background: linear-gradient(to right, #ffd000, #ffa000);
335   - border-radius: 40rpx 40rpx 0 0;
336   - z-index: 1;
337   -
338   - &::before {
339   - content: '';
340   - position: absolute;
341   - top: 0;
342   - left: -20rpx;
343   - width: 20rpx;
344   - height: 40rpx;
345   - background: linear-gradient(to bottom, #ffd000, #ffa000);
346   - border-radius: 10rpx 0 0 10rpx;
347   - }
348   -
349   - &::after {
350   - content: '';
351   - position: absolute;
352   - top: 0;
353   - right: -20rpx;
354   - width: 20rpx;
355   - height: 40rpx;
356   - background: linear-gradient(to bottom, #ffd000, #ffa000);
357   - border-radius: 0 10rpx 10rpx 0;
358   - }
359   - }
360   -
361   - // 不同主题样式
362   - &--primary {
363   - background: linear-gradient(90deg, #43afff, #3b8cff);
364   - color: #fff;
365   - .up-coupon__amount {
366   - border-right: 1px dashed #eee;
367   - }
368   - .up-coupon__amount-value {
369   - color: #fff;
370   - }
371   - }
372   -
373   - &--success {
374   - background: linear-gradient(90deg, #67dda9, #19be6b);
375   - color: #fff !important;
376   - .up-coupon__amount {
377   - border-right: 1px dashed #eee;
378   - }
379   - .up-coupon__amount-value {
380   - color: #fff;
381   - }
382   - }
383   -
384   - &--warning {
385   - background: linear-gradient(90deg, #ff9739, #ff6a39);
386   - color: #fff;
387   - .up-coupon__amount {
388   - border-right: 1px dashed #eee;
389   - }
390   - .up-coupon__amount-value {
391   - color: #fff;
392   - }
393   - }
394   -
395   - &--error {
396   - background: linear-gradient(90deg, #ff7070, #ff4747);
397   - color: #fff;
398   - .up-coupon__amount {
399   - border-right: 1px dashed #eee;
400   - }
401   - .up-coupon__amount-value {
402   - color: #fff;
403   - }
404   - }
405   - }
406   -</style>
407 0 \ No newline at end of file