@neatui/nuxt 0.1.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BUILD.md +128 -0
- package/IMPORT_GUIDE.md +142 -0
- package/README.md +98 -1
- package/SSR_COMPATIBILITY.md +201 -0
- package/USAGE.md +291 -0
- package/nuxt.config.example.ts +37 -0
- package/package.json +34 -11
- package/src/components/basic/IDraggable.vue +87 -65
- package/src/components/basic/IFollowView.vue +32 -23
- package/src/components/basic/IRouterView.vue +38 -23
- package/src/components/basic/IScrollView.vue +11 -7
- package/src/components/basic/Icon.vue +17 -17
- package/src/components/basic/LayerView/Layer.vue +33 -106
- package/src/components/basic/follow.ts +133 -0
- package/src/components/display/Calendar.vue +14 -14
- package/src/components/display/CalendarReg.vue +14 -14
- package/src/components/display/Image.vue +8 -8
- package/src/components/display/PhotoEditor.vue +36 -36
- package/src/components/display/PhotoViewer.vue +8 -8
- package/src/components/display/Tree.vue +6 -6
- package/src/components/display/TreeView.vue +4 -4
- package/src/components/display/index.ts +2 -2
- package/src/components/form/Cascader.vue +19 -19
- package/src/components/form/Checkbox.vue +64 -0
- package/src/components/form/DatePicker.vue +6 -7
- package/src/components/form/DateRangePicker@v3.vue +4 -4
- package/src/components/form/DateRangeView@v3.vue +18 -19
- package/src/components/form/DateView.vue +14 -14
- package/src/components/form/DateView@v2.vue +14 -14
- package/src/components/form/DateView@v3.vue +331 -318
- package/src/components/form/ImgUpload.vue +7 -7
- package/src/components/form/Input@v3.vue +11 -11
- package/src/components/form/MoreSelect@v3.vue +87 -17
- package/src/components/form/MoreSelectList.vue +8 -8
- package/src/components/form/MoreSelectPanel@v3.vue +3 -3
- package/src/components/form/MoreSelectPicker.vue +7 -7
- package/src/components/form/MoreSelectTags.vue +8 -8
- package/src/components/form/PageMoreSelect.vue +14 -14
- package/src/components/form/PageSelect.vue +16 -16
- package/src/components/form/SearchMoreSelect.vue +12 -12
- package/src/components/form/SearchSelect@v3.vue +3 -3
- package/src/components/form/Select@v3.vue +229 -23
- package/src/components/form/SelectList.vue +8 -8
- package/src/components/form/SelectPicker.vue +6 -6
- package/src/components/form/SelectTags.vue +7 -7
- package/src/components/form/SelectTree/SelectTree@v1.vue +5 -5
- package/src/components/form/Switch.vue +38 -103
- package/src/components/form/TextArea.vue +18 -18
- package/src/components/form/Textarea@v2.vue +275 -0
- package/src/components/form/TimeView.vue +14 -14
- package/src/components/form/Upload.vue +806 -297
- package/src/components/form/date.ts +321 -0
- package/src/components/form/index.ts +7 -5
- package/src/components/form/number.ts +3 -0
- package/src/components/form/type.ts +224 -0
- package/src/components/icon/OrderIcon.vue +113 -0
- package/src/components/loader/FormLoader/FormLoader@v2.vue +193 -195
- package/src/components/loader/FormLoader/FormLoader@v3.vue.backup +372 -291
- package/src/components/loader/FormLoader/FormRender@v3.vue.backup +4 -0
- package/src/components/loader/FormLoader/NodeLoader.vue +85 -0
- package/src/components/loader/FormLoader@v1/FormLoader.vue +1 -1
- package/src/components/loader/FormLoader@v1/FormRender.vue +49 -24
- package/src/components/loader/LayerLoader/LayerLoader.vue +318 -0
- package/src/components/loader/LayerLoader/index.ts +2 -0
- package/src/components/loader/LayerLoader/style.scss +77 -0
- package/src/components/loader/LimitLoader/LimitLoader@v3.vue +39 -28
- package/src/components/loader/MoveLoader/MoveLoader.vue +628 -0
- package/src/components/loader/MoveLoader/index.ts +2 -0
- package/src/components/loader/MoveLoader/style.scss +77 -0
- package/src/components/loader/TableLoader/TableLoader.vue +227 -195
- package/src/components/loader/TableLoader/TableRender.vue +141 -0
- package/src/components/loader/TableLoader/index.ts +47 -0
- package/src/components/loader/index.ts +3 -2
- package/src/components/tools/Pagination@a.vue +17 -18
- package/src/components/tools/Pagination@b.vue +16 -16
- package/src/index.ts +2 -1
- package/src/module.ts +169 -0
- package/src/runtime/types.d.ts +36 -0
- package/src/store/{myui.ts → frame.ts} +4 -4
- package/src/utils/theme.ts +14 -0
- package/tsconfig.json +1 -1
- package/src/components/loader/FormLoader/index.ts +0 -2
- package/src/components/loader/LimitLoader/LimitLoader.vue.backup +0 -131
- package/src/components/loader/LimitLoader/LimitLoader@v2.vue.backup +0 -174
- package/src/components/loader/TableLoader/TableColView.vue +0 -115
@@ -1,345 +1,854 @@
|
|
1
1
|
<template>
|
2
|
-
<
|
3
|
-
<
|
4
|
-
<
|
5
|
-
|
6
|
-
|
7
|
-
<
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
<path d="M255 707m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1917"></path>
|
15
|
-
<path d="M255 639m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1918"></path>
|
16
|
-
<path d="M255 774m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1919"></path>
|
17
|
-
<path d="M255 842m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1920"></path>
|
18
|
-
<path d="M67 193m16 0l287 0q16 0 16 16l0 287q0 16-16 16l-287 0q-16 0-16-16l0-287q0-16 16-16Z" fill="#FF4867" p-id="1921"></path>
|
19
|
-
<path
|
20
|
-
d="M314.229 459.289c-21.407 0-40.606-36.765-50.708-60.673-16.991-7.098-35.722-13.728-53.918-18.014-15.92 10.514-43.014 26.251-63.818 26.251-12.911 0-22.21-6.496-25.622-17.813-2.609-9.309-0.4-15.738 2.409-19.22 5.485-7.5 16.79-11.317 33.715-11.317 13.714 0 31.107 2.41 50.507 7.098 12.51-8.907 25.22-19.22 36.525-30.135-5.017-23.84-10.503-62.48 3.412-80.294 6.89-8.505 17.393-11.318 30.103-7.5 13.914 4.017 19.199 12.522 20.804 19.22 5.887 23.237-20.804 54.578-38.8 72.994 4.015 15.938 9.3 32.747 15.721 48.15 25.822 11.518 56.527 28.728 60.006 47.48 1.405 6.495-0.602 12.522-5.887 17.813-4.549 3.75-9.365 5.96-14.45 5.96z m-31.647-52.419c12.785 26.402 24.975 38.862 31.4 38.862 0.995 0 2.386-0.404 4.373-2.02 2.385-2.425 2.385-4.041 1.988-5.523-1.325-6.937-12.124-18.32-37.761-31.319z m-126.377-35.247c-16.73 0-21.33 4.093-22.73 6.003-0.399 0.614-1.599 2.455-0.399 7.23 1 4.092 3.8 8.458 12.464 8.458 10.865 0 26.595-6.207 44.857-17.325-13.063-2.933-24.594-4.366-34.192-4.366z m67.632-1.765c10.845 2.983 22.09 6.827 32.535 10.803-3.792-9.809-6.853-20.015-9.448-29.824-7.651 6.561-15.436 12.99-23.087 19.021zM265.9 259.556c-3.827 0-6.513 1.409-8.93 4.024-7.118 8.917-7.924 31.38-2.418 60.144 20.884-22.26 32.232-42.711 29.411-53.64-0.402-1.61-1.611-6.504-11.348-9.32-2.686-0.805-4.7-1.208-6.715-1.208z"
|
21
|
-
fill="#FFFFFF"
|
22
|
-
p-id="1922"
|
23
|
-
></path>
|
24
|
-
</svg>
|
25
|
-
</template>
|
26
|
-
<template v-else-if="file.type === 'xlsx'">
|
27
|
-
<svg t="1705645380770" class="w-ss h-ss" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2060">
|
28
|
-
<path
|
29
|
-
d="M205.799024 64.936585H664.850732l231.773658 231.773659v638.376585c0 13.79353-11.18208 24.97561-24.97561 24.97561H205.799024c-13.79353 0-24.97561-11.18208-24.975609-24.97561V89.912195c0-13.79353 11.18208-24.97561 24.975609-24.97561z m448.70681 24.97561H205.799024v845.174634H871.64878V307.055141L654.505834 89.912195z"
|
30
|
-
fill="#B7B7BD"
|
31
|
-
p-id="2061"
|
32
|
-
></path>
|
33
|
-
<path
|
34
|
-
d="M664.850732 64.936585l-10.989269 23.477074v196.807804c0 13.79353 11.18208 24.97561 24.97561 24.97561h194.310244L896.62439 296.710244 664.850732 64.936585z m13.986341 49.306849L849.815102 285.221463H678.837073V114.243434z"
|
35
|
-
fill="#B7B7BD"
|
36
|
-
p-id="2062"
|
37
|
-
></path>
|
38
|
-
<path
|
39
|
-
d="M255.250732 571.441951m9.990244 0l555.457561 0q9.990244 0 9.990243 9.990244l0 0q0 9.990244-9.990243 9.990244l-555.457561 0q-9.990244 0-9.990244-9.990244l0 0q0-9.990244 9.990244-9.990244Z"
|
40
|
-
fill="#B7B7BD"
|
41
|
-
p-id="2063"
|
42
|
-
></path>
|
43
|
-
<path
|
44
|
-
d="M255.250732 707.309268m9.990244 0l555.457561 0q9.990244 0 9.990243 9.990244l0 0q0 9.990244-9.990243 9.990244l-555.457561 0q-9.990244 0-9.990244-9.990244l0 0q0-9.990244 9.990244-9.990244Z"
|
45
|
-
fill="#B7B7BD"
|
46
|
-
p-id="2064"
|
47
|
-
></path>
|
48
|
-
<path
|
49
|
-
d="M255.250732 639.37561m9.990244 0l555.457561 0q9.990244 0 9.990243 9.990244l0 0q0 9.990244-9.990243 9.990244l-555.457561 0q-9.990244 0-9.990244-9.990244l0 0q0-9.990244 9.990244-9.990244Z"
|
50
|
-
fill="#B7B7BD"
|
51
|
-
p-id="2065"
|
52
|
-
></path>
|
53
|
-
<path
|
54
|
-
d="M255.250732 774.243902m9.990244 0l555.457561 0q9.990244 0 9.990243 9.990244l0 0q0 9.990244-9.990243 9.990244l-555.457561 0q-9.990244 0-9.990244-9.990244l0 0q0-9.990244 9.990244-9.990244Z"
|
55
|
-
fill="#B7B7BD"
|
56
|
-
p-id="2066"
|
57
|
-
></path>
|
58
|
-
<path
|
59
|
-
d="M255.250732 842.177561m9.990244 0l555.457561 0q9.990244 0 9.990243 9.990244l0 0q0 9.990244-9.990243 9.990244l-555.457561 0q-9.990244 0-9.990244-9.990244l0 0q0-9.990244 9.990244-9.990244Z"
|
60
|
-
fill="#B7B7BD"
|
61
|
-
p-id="2067"
|
62
|
-
></path>
|
63
|
-
<path
|
64
|
-
d="M67.434146 193.810732m15.984391 0l286.72 0q15.98439 0 15.98439 15.98439l0 286.72q0 15.98439-15.98439 15.98439l-286.72 0q-15.98439 0-15.984391-15.98439l0-286.72q0-15.98439 15.984391-15.98439Z"
|
65
|
-
fill="#00C090"
|
66
|
-
p-id="2068"
|
67
|
-
></path>
|
68
|
-
<path
|
69
|
-
d="M242.569116 353.23904l89.224866 84.502478c4.337764 4.107988 4.523582 10.954302 0.415595 15.291067-4.107988 4.337764-10.954302 4.523582-15.291068 0.415595l-89.224866-84.502479-84.502478 89.224867c-4.107988 4.337764-10.954302 4.523582-15.291067 0.415594-4.337764-4.107988-4.523582-10.954302-0.415595-15.291067l84.502478-89.224867-89.224866-84.502478c-4.337764-4.107988-4.523582-10.954302-0.415594-15.291067 4.107988-4.337764 10.954302-4.523582 15.291067-0.415594l89.224867 84.502478 84.502478-89.224867c4.107988-4.337764 10.954302-4.523582 15.291067-0.415594 4.337764 4.107988 4.523582 10.954302 0.415594 15.291068l-84.502478 89.224866z"
|
70
|
-
fill="#FFFFFF"
|
71
|
-
p-id="2069"
|
72
|
-
></path>
|
73
|
-
</svg>
|
74
|
-
</template>
|
75
|
-
<template v-else-if="file.type === 'docx'">
|
76
|
-
<svg t="1705645401993" class="w-ss h-ss" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2207">
|
77
|
-
<path
|
78
|
-
d="M205.5 64H665l232 232v639c0 13.807-11.193 25-25 25H205.5c-13.807 0-25-11.193-25-25V89c0-13.807 11.193-25 25-25z m449.145 25H205.5v846H872V306.355L654.645 89z"
|
79
|
-
fill="#B7B7BD"
|
80
|
-
p-id="2208"
|
81
|
-
></path>
|
82
|
-
<path d="M665 64l-11 23.5v197c0 13.807 11.193 25 25 25h194.5L897 296 665 64z m14 49.355L850.145 284.5H679V113.355z" fill="#B7B7BD" p-id="2209"></path>
|
83
|
-
<path d="M67 193m16 0l287 0q16 0 16 16l0 287q0 16-16 16l-287 0q-16 0-16-16l0-287q0-16 16-16Z" fill="#4297FC" p-id="2210"></path>
|
84
|
-
<path d="M255 571m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2211"></path>
|
85
|
-
<path d="M255 707m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2212"></path>
|
86
|
-
<path d="M255 639m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2213"></path>
|
87
|
-
<path d="M255 774m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2214"></path>
|
88
|
-
<path d="M255 842m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2215"></path>
|
89
|
-
<path
|
90
|
-
d="M315.269 451.314c7.015 7.61 19.731 2.651 19.731-7.693V271h-22.737v143.524l-76.9-83.418c-4.503-4.885-12.223-4.885-16.726 0l-76.9 83.418V271H119v172.62c0 10.345 12.716 15.303 19.731 7.694L227 355.564l88.269 95.75z"
|
91
|
-
fill="#FFFFFF"
|
92
|
-
p-id="2216"
|
93
|
-
></path>
|
94
|
-
</svg>
|
95
|
-
</template>
|
96
|
-
<template v-else-if="file.type === 'pptx'">
|
97
|
-
<svg t="1705645414803" class="w-ss h-ss" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2354">
|
98
|
-
<path
|
99
|
-
d="M205.5 64H665l232 232v639c0 13.807-11.193 25-25 25H205.5c-13.807 0-25-11.193-25-25V89c0-13.807 11.193-25 25-25z m449.145 25H205.5v846H872V306.355L654.645 89z"
|
100
|
-
fill="#B7B7BD"
|
101
|
-
p-id="2355"
|
102
|
-
></path>
|
103
|
-
<path d="M665 64l-11 23.5v197c0 13.807 11.193 25 25 25h194.5L897 296 665 64z m14 49.355L850.145 284.5H679V113.355z" fill="#B7B7BD" p-id="2356"></path>
|
104
|
-
<path d="M255 571m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2357"></path>
|
105
|
-
<path d="M255 707m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2358"></path>
|
106
|
-
<path d="M255 639m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2359"></path>
|
107
|
-
<path d="M255 774m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2360"></path>
|
108
|
-
<path d="M255 842m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2361"></path>
|
109
|
-
<path d="M67 193m16 0l287 0q16 0 16 16l0 287q0 16-16 16l-287 0q-16 0-16-16l0-287q0-16 16-16Z" fill="#FF7A64" p-id="2362"></path>
|
110
|
-
<path
|
111
|
-
d="M314 312.055c0 16.701-8.014 25.218-26.96 27.787H129c-5.523 0-10 4.477-10 10V451.5c0 5.523 4.477 10 10 10s10-4.477 10-10v-91.658h148.694a10 10 0 0 0 1.264-0.08C317.98 356.065 334 339.393 334 312.055c0-26.83-15.298-44.972-43.677-52.703a10 10 0 0 0-2.629-0.352H129c-5.523 0-10 4.477-10 10s4.477 10 10 10h157.317C305.466 284.553 314 295.032 314 312.055z"
|
112
|
-
fill="#FFFFFF"
|
113
|
-
p-id="2363"
|
114
|
-
></path>
|
115
|
-
</svg>
|
116
|
-
</template>
|
117
|
-
<template v-else>
|
118
|
-
<svg t="1705645436666" class="w-ss h-ss" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2501">
|
119
|
-
<path
|
120
|
-
d="M205.5 64H665l232 232v639c0 13.807-11.193 25-25 25H205.5c-13.807 0-25-11.193-25-25V89c0-13.807 11.193-25 25-25z m449.145 25H205.5v846H872V306.355L654.645 89z"
|
121
|
-
fill="#B7B7BD"
|
122
|
-
p-id="2502"
|
123
|
-
></path>
|
124
|
-
<path d="M665 64l-11 23.5v197c0 13.807 11.193 25 25 25h194.5L897 296 665 64z m14 49.355L850.145 284.5H679V113.355z" fill="#B7B7BD" p-id="2503"></path>
|
125
|
-
<path d="M255 571m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2504"></path>
|
126
|
-
<path d="M255 707m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2505"></path>
|
127
|
-
<path d="M255 639m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2506"></path>
|
128
|
-
<path d="M255 774m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2507"></path>
|
129
|
-
<path d="M255 842m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2508"></path>
|
130
|
-
<path d="M67 193m16 0l287 0q16 0 16 16l0 287q0 16-16 16l-287 0q-16 0-16-16l0-287q0-16 16-16Z" fill="#CCCCCC" p-id="2509"></path>
|
131
|
-
<path
|
132
|
-
d="M226.274 240c14.845 0 29.79 4.862 41.18 13.738C280.444 263.86 288 278.458 288 295.57c0 22.53-15.93 43.423-46.252 63.48l-0.31 0.203V387c0 6.525-5.208 11.834-11.695 11.996l-0.305 0.004c-6.627 0-12-5.373-12-12v-34.314a12 12 0 0 1 5.673-10.196C250.988 325.189 264 309.227 264 295.57c0-9.498-3.99-17.207-11.298-22.902-7.059-5.5-16.796-8.668-26.428-8.668-9.598 0-19.202 3.147-26.147 8.625-7.064 5.571-10.985 13.116-11.123 22.435l-0.004 0.51c0 6.628-5.373 12-12 12s-12-5.372-12-12c0-33.201 28.361-55.57 61.274-55.57zM230 453c9.389 0 17-7.611 17-17s-7.611-17-17-17-17 7.611-17 17 7.611 17 17 17z"
|
133
|
-
fill="#FFFFFF"
|
134
|
-
p-id="2510"
|
135
|
-
></path>
|
136
|
-
</svg>
|
137
|
-
</template>
|
138
|
-
<p ui-omit="1" class="fs-ss ac">{{ file.name }}</p>
|
139
|
-
</li>
|
140
|
-
<li v-if="(!multiple && state.files && state.files.length === 0) || (multiple && (!limit || (limit && state.files && state.files.length < limit)))">
|
141
|
-
<slot>
|
142
|
-
<label ui-flex="row cm" ui-form="@a type:upload tips:hover" :class="`upload w-ms h-ms n-sl bg-fore b-solid bk-line b-xs ${uploadClass}`" :style="uploadStyle">
|
143
|
-
<div v-if="tips" ui-form-tips>
|
144
|
-
{{ tips }}
|
2
|
+
<div ui-flex="row lm :wrap" class="neatui-upload mb-sm-sub mr-sm-sub" v-bind="{ ...attrs }">
|
3
|
+
<div v-for="(file, idx) in state.files" :key="idx" ui-flex="col cm" class="flex-fixed pr" :style="`width: ${isNumber(width) ? width + 'em' : width}`" v-bind="itemAttrs">
|
4
|
+
<div class="w-full pr" :style="`box-sizing: content-box; padding-top: ${ratio}%`">
|
5
|
+
<div class="pa full ot-no ol-no bg-fore n-sm b-solid bk-case b-xs r-sm" ui-flex="col cm">
|
6
|
+
<!-- 删除按钮 -->
|
7
|
+
<div class="pa w-xs h-xs ot-ss or-ss bg-fore co-risk lh-xs r-xl parent-hover:show z-ls" ui-flex="row cm" @click="remove(idx)">
|
8
|
+
<svg class="block" style="width: 1.2em; height: 1.2em" viewBox="0 0 1024 1024">
|
9
|
+
<path
|
10
|
+
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66 0.3L512 563.4l-99.3 118.4-66.1-0.3c-4.4 0-8-3.5-8-8 0-1.9 0.7-3.7 1.9-5.2l130.1-155L340.5 359c-1.2-1.5-1.9-3.3-1.9-5.2 0-4.4 3.6-8 8-8l66.1 0.3L512 464.6l99.3-118.4 66-0.3c4.4 0 8 3.5 8 8 0 1.9-0.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"
|
11
|
+
fill="currentColor"
|
12
|
+
/>
|
13
|
+
</svg>
|
145
14
|
</div>
|
146
|
-
|
147
|
-
|
148
|
-
|
15
|
+
|
16
|
+
<!-- 文件预览 -->
|
17
|
+
<img v-if="file.type === 'image'" class="r-ss" :src="getImageUrl(file)" alt="" />
|
18
|
+
<video v-else-if="file.type === 'video'" class="full r-ss" :src="getImageUrl(file)" controls muted></video>
|
19
|
+
<template v-else-if="file.type === 'pdf'">
|
20
|
+
<svg t="1705645350800" class="w-ss h-ss" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1913">
|
21
|
+
<path
|
22
|
+
d="M205.5 64H665l232 232v639c0 13.807-11.193 25-25 25H205.5c-13.807 0-25-11.193-25-25V89c0-13.807 11.193-25 25-25z m449.145 25H205.5v846H872V306.355L654.645 89z"
|
23
|
+
fill="#B7B7BD"
|
24
|
+
p-id="1914"
|
25
|
+
></path>
|
26
|
+
<path d="M665 64l-11 23.5v197c0 13.807 11.193 25 25 25h194.5L897 296 665 64z m14 49.355L850.145 284.5H679V113.355z" fill="#B7B7BD" p-id="1915"></path>
|
27
|
+
<path d="M255 571m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1916"></path>
|
28
|
+
<path d="M255 707m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1917"></path>
|
29
|
+
<path d="M255 639m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1918"></path>
|
30
|
+
<path d="M255 774m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1919"></path>
|
31
|
+
<path d="M255 842m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1920"></path>
|
32
|
+
<path d="M67 193m16 0l287 0q16 0 16 16l0 287q0 16-16 16l-287 0q-16 0-16-16l0-287q0-16 16-16Z" fill="#FF4867" p-id="1921"></path>
|
33
|
+
<path
|
34
|
+
d="M314.229 459.289c-21.407 0-40.606-36.765-50.708-60.673-16.991-7.098-35.722-13.728-53.918-18.014-15.92 10.514-43.014 26.251-63.818 26.251-12.911 0-22.21-6.496-25.622-17.813-2.609-9.309-0.4-15.738 2.409-19.22 5.485-7.5 16.79-11.317 33.715-11.317 13.714 0 31.107 2.41 50.507 7.098 12.51-8.907 25.22-19.22 36.525-30.135-5.017-23.84-10.503-62.48 3.412-80.294 6.89-8.505 17.393-11.318 30.103-7.5 13.914 4.017 19.199 12.522 20.804 19.22 5.887 23.237-20.804 54.578-38.8 72.994 4.015 15.938 9.3 32.747 15.721 48.15 25.822 11.518 56.527 28.728 60.006 47.48 1.405 6.495-0.602 12.522-5.887 17.813-4.549 3.75-9.365 5.96-14.45 5.96z m-31.647-52.419c12.785 26.402 24.975 38.862 31.4 38.862 0.995 0 2.386-0.404 4.373-2.02 2.385-2.425 2.385-4.041 1.988-5.523-1.325-6.937-12.124-18.32-37.761-31.319z m-126.377-35.247c-16.73 0-21.33 4.093-22.73 6.003-0.399 0.614-1.599 2.455-0.399 7.23 1 4.092 3.8 8.458 12.464 8.458 10.865 0 26.595-6.207 44.857-17.325-13.063-2.933-24.594-4.366-34.192-4.366z m67.632-1.765c10.845 2.983 22.09 6.827 32.535 10.803-3.792-9.809-6.853-20.015-9.448-29.824-7.651 6.561-15.436 12.99-23.087 19.021zM265.9 259.556c-3.827 0-6.513 1.409-8.93 4.024-7.118 8.917-7.924 31.38-2.418 60.144 20.884-22.26 32.232-42.711 29.411-53.64-0.402-1.61-1.611-6.504-11.348-9.32-2.686-0.805-4.7-1.208-6.715-1.208z"
|
35
|
+
fill="#FFFFFF"
|
36
|
+
p-id="1922"
|
37
|
+
></path>
|
38
|
+
</svg>
|
39
|
+
</template>
|
40
|
+
<template v-else-if="file.type === 'xlsx'">
|
41
|
+
<svg t="1705645380770" class="w-ss h-ss" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2060">
|
42
|
+
<path
|
43
|
+
d="M205.799024 64.936585H664.850732l231.773658 231.773659v638.376585c0 13.79353-11.18208 24.97561-24.97561 24.97561H205.799024c-13.79353 0-24.97561-11.18208-24.975609-24.97561V89.912195c0-13.79353 11.18208-24.97561 24.975609-24.97561z m448.70681 24.97561H205.799024v845.174634H871.64878V307.055141L654.505834 89.912195z"
|
44
|
+
fill="#B7B7BD"
|
45
|
+
p-id="2061"
|
46
|
+
></path>
|
47
|
+
<path
|
48
|
+
d="M664.850732 64.936585l-10.989269 23.477074v196.807804c0 13.79353 11.18208 24.97561 24.97561 24.97561h194.310244L896.62439 296.710244 664.850732 64.936585z m13.986341 49.306849L849.815102 285.221463H678.837073V114.243434z"
|
49
|
+
fill="#B7B7BD"
|
50
|
+
p-id="2062"
|
51
|
+
></path>
|
52
|
+
<path
|
53
|
+
d="M255.250732 571.441951m9.990244 0l555.457561 0q9.990244 0 9.990243 9.990244l0 0q0 9.990244-9.990243 9.990244l-555.457561 0q-9.990244 0-9.990244-9.990244l0 0q0-9.990244 9.990244-9.990244Z"
|
54
|
+
fill="#B7B7BD"
|
55
|
+
p-id="2063"
|
56
|
+
></path>
|
57
|
+
<path
|
58
|
+
d="M255.250732 707.309268m9.990244 0l555.457561 0q9.990244 0 9.990243 9.990244l0 0q0 9.990244-9.990243 9.990244l-555.457561 0q-9.990244 0-9.990244-9.990244l0 0q0-9.990244 9.990244-9.990244Z"
|
59
|
+
fill="#B7B7BD"
|
60
|
+
p-id="2064"
|
61
|
+
></path>
|
62
|
+
<path
|
63
|
+
d="M255.250732 639.37561m9.990244 0l555.457561 0q9.990244 0 9.990243 9.990244l0 0q0 9.990244-9.990243 9.990244l-555.457561 0q-9.990244 0-9.990244-9.990244l0 0q0-9.990244 9.990244-9.990244Z"
|
64
|
+
fill="#B7B7BD"
|
65
|
+
p-id="2065"
|
66
|
+
></path>
|
67
|
+
<path
|
68
|
+
d="M255.250732 774.243902m9.990244 0l555.457561 0q9.990244 0 9.990243 9.990244l0 0q0 9.990244-9.990243 9.990244l-555.457561 0q-9.990244 0-9.990244-9.990244l0 0q0-9.990244 9.990244-9.990244Z"
|
69
|
+
fill="#B7B7BD"
|
70
|
+
p-id="2066"
|
71
|
+
></path>
|
72
|
+
<path
|
73
|
+
d="M255.250732 842.177561m9.990244 0l555.457561 0q9.990244 0 9.990243 9.990244l0 0q0 9.990244-9.990243 9.990244l-555.457561 0q-9.990244 0-9.990244-9.990244l0 0q0-9.990244 9.990244-9.990244Z"
|
74
|
+
fill="#B7B7BD"
|
75
|
+
p-id="2067"
|
76
|
+
></path>
|
77
|
+
<path
|
78
|
+
d="M67.434146 193.810732m15.984391 0l286.72 0q15.98439 0 15.98439 15.98439l0 286.72q0 15.98439-15.98439 15.98439l-286.72 0q-15.98439 0-15.984391-15.98439l0-286.72q0-15.98439 15.984391-15.98439Z"
|
79
|
+
fill="#00C090"
|
80
|
+
p-id="2068"
|
81
|
+
></path>
|
149
82
|
<path
|
150
|
-
d="
|
151
|
-
|
83
|
+
d="M242.569116 353.23904l89.224866 84.502478c4.337764 4.107988 4.523582 10.954302 0.415595 15.291067-4.107988 4.337764-10.954302 4.523582-15.291067 0.415595l-89.224866-84.502479-84.502478 89.224867c-4.107988 4.337764-10.954302 4.523582-15.291067 0.415594-4.337764-4.107988-4.523582-10.954302-0.415595-15.291067l84.502478-89.224867-89.224866-84.502478c-4.337764-4.107988-4.523582-10.954302-0.415594-15.291067 4.107988-4.337764 10.954302-4.523582 15.291067-0.415594l89.224867 84.502478 84.502478-89.224867c4.107988-4.337764 10.954302-4.523582 15.291067-0.415594 4.337764 4.107988 4.523582 10.954302 0.415594 15.291068l-84.502478 89.224866z"
|
84
|
+
fill="#FFFFFF"
|
85
|
+
p-id="2069"
|
152
86
|
></path>
|
153
87
|
</svg>
|
88
|
+
</template>
|
89
|
+
<template v-else-if="file.type === 'docx'">
|
90
|
+
<svg t="1705645401993" class="w-ss h-ss" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2207">
|
91
|
+
<path
|
92
|
+
d="M205.5 64H665l232 232v639c0 13.807-11.193 25-25 25H205.5c-13.807 0-25-11.193-25-25V89c0-13.807 11.193-25 25-25z m449.145 25H205.5v846H872V306.355L654.645 89z"
|
93
|
+
fill="#B7B7BD"
|
94
|
+
p-id="2208"
|
95
|
+
></path>
|
96
|
+
<path d="M665 64l-11 23.5v197c0 13.807 11.193 25 25 25h194.5L897 296 665 64z m14 49.355L850.145 284.5H679V113.355z" fill="#B7B7BD" p-id="2209"></path>
|
97
|
+
<path d="M67 193m16 0l287 0q16 0 16 16l0 287q0 16-16 16l-287 0q-16 0-16-16l0-287q0-16 16-16Z" fill="#4297FC" p-id="2210"></path>
|
98
|
+
<path d="M255 571m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2211"></path>
|
99
|
+
<path d="M255 707m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2212"></path>
|
100
|
+
<path d="M255 639m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2213"></path>
|
101
|
+
<path d="M255 774m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2214"></path>
|
102
|
+
<path d="M255 842m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2215"></path>
|
103
|
+
<path
|
104
|
+
d="M315.269 451.314c7.015 7.61 19.731 2.651 19.731-7.693V271h-22.737v143.524l-76.9-83.418c-4.503-4.885-12.223-4.885-16.726 0l-76.9 83.418V271H119v172.62c0 10.345 12.716 15.303 19.731 7.694L227 355.564l88.269 95.75z"
|
105
|
+
fill="#FFFFFF"
|
106
|
+
p-id="2216"
|
107
|
+
></path>
|
108
|
+
</svg>
|
109
|
+
</template>
|
110
|
+
<template v-else-if="file.type === 'pptx'">
|
111
|
+
<svg t="1705645414803" class="w-ss h-ss" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2354">
|
112
|
+
<path
|
113
|
+
d="M205.5 64H665l232 232v639c0 13.807-11.193 25-25 25H205.5c-13.807 0-25-11.193-25-25V89c0-13.807 11.193-25 25-25z m449.145 25H205.5v846H872V306.355L654.645 89z"
|
114
|
+
fill="#B7B7BD"
|
115
|
+
p-id="2355"
|
116
|
+
></path>
|
117
|
+
<path d="M665 64l-11 23.5v197c0 13.807 11.193 25 25 25h194.5L897 296 665 64z m14 49.355L850.145 284.5H679V113.355z" fill="#B7B7BD" p-id="2356"></path>
|
118
|
+
<path d="M255 571m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2357"></path>
|
119
|
+
<path d="M255 707m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2358"></path>
|
120
|
+
<path d="M255 639m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2359"></path>
|
121
|
+
<path d="M255 774m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2360"></path>
|
122
|
+
<path d="M255 842m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2361"></path>
|
123
|
+
<path d="M67 193m16 0l287 0q16 0 16 16l0 287q0 16-16 16l-287 0q-16 0-16-16l0-287q0-16 16-16Z" fill="#FF7A64" p-id="2362"></path>
|
124
|
+
<path
|
125
|
+
d="M314 312.055c0 16.701-8.014 25.218-26.96 27.787H129c-5.523 0-10 4.477-10 10V451.5c0 5.523 4.477 10 10 10s10-4.477 10-10v-91.658h148.694a10 10 0 0 0 1.264-0.08C317.98 356.065 334 339.393 334 312.055c0-26.83-15.298-44.972-43.677-52.703a10 10 0 0 0-2.629-0.352H129c-5.523 0-10 4.477-10 10s4.477 10 10 10h157.317C305.466 284.553 314 295.032 314 312.055z"
|
126
|
+
fill="#FFFFFF"
|
127
|
+
p-id="2363"
|
128
|
+
></path>
|
129
|
+
</svg>
|
130
|
+
</template>
|
131
|
+
<template v-else>
|
132
|
+
<svg t="1705645436666" class="w-ss h-ss" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2501">
|
133
|
+
<path
|
134
|
+
d="M205.5 64H665l232 232v639c0 13.807-11.193 25-25 25H205.5c-13.807 0-25-11.193-25-25V89c0-13.807 11.193-25 25-25z m449.145 25H205.5v846H872V306.355L654.645 89z"
|
135
|
+
fill="#B7B7BD"
|
136
|
+
p-id="2502"
|
137
|
+
></path>
|
138
|
+
<path d="M665 64l-11 23.5v197c0 13.807 11.193 25 25 25h194.5L897 296 665 64z m14 49.355L850.145 284.5H679V113.355z" fill="#B7B7BD" p-id="2503"></path>
|
139
|
+
<path d="M255 571m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2504"></path>
|
140
|
+
<path d="M255 707m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2505"></path>
|
141
|
+
<path d="M255 639m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2506"></path>
|
142
|
+
<path d="M255 774m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2507"></path>
|
143
|
+
<path d="M255 842m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="2508"></path>
|
144
|
+
<path d="M67 193m16 0l287 0q16 0 16 16l0 287q0 16-16 16l-287 0q-16 0-16-16l0-287q0-16 16-16Z" fill="#CCCCCC" p-id="2509"></path>
|
145
|
+
<path
|
146
|
+
d="M226.274 240c14.845 0 29.79 4.862 41.18 13.738C280.444 263.86 288 278.458 288 295.57c0 22.53-15.93 43.423-46.252 63.48l-0.31 0.203V387c0 6.525-5.208 11.834-11.695 11.996l-0.305 0.004c-6.627 0-12-5.373-12-12v-34.314a12 12 0 0 1 5.673-10.196C250.988 325.189 264 309.227 264 295.57c0-9.498-3.99-17.207-11.298-22.902-7.059-5.5-16.796-8.668-26.428-8.668-9.598 0-19.202 3.147-26.147 8.625-7.064 5.571-10.985 13.116-11.123 22.435l-0.004 0.51c0 6.628-5.373 12-12 12s-12-5.372-12-12c0-33.201 28.361-55.57 61.274-55.57zM230 453c9.389 0 17-7.611 17-17s-7.611-17-17-17-17 7.611-17 17 7.611 17 17 17z"
|
147
|
+
fill="#FFFFFF"
|
148
|
+
p-id="2510"
|
149
|
+
></path>
|
150
|
+
</svg>
|
151
|
+
</template>
|
152
|
+
|
153
|
+
<!-- 上传状态 -->
|
154
|
+
<div class="upload-status" :data-status="file.status">
|
155
|
+
<div class="neatui-upload-icon"><i></i></div>
|
156
|
+
</div>
|
157
|
+
</div>
|
158
|
+
</div>
|
159
|
+
</div>
|
160
|
+
|
161
|
+
<!-- 上传按钮 -->
|
162
|
+
<template v-if="showUploadButton">
|
163
|
+
<slot name="btn">
|
164
|
+
<label class="pr flex-block" ui-form="@a type:upload tips:hover" :style="`width: ${isNumber(width) ? width + 'em' : width}`" v-bind="itemAttrs">
|
165
|
+
<div class="w-full pr" :style="`box-sizing: content-box; padding-top: ${ratio}%`">
|
166
|
+
<div ui-flex="row cm" :class="`pa ot-no ol-no full upload n-sl bg-fore b-solid bk-case b-xs r-sm ${uploadClass}`" :style="uploadStyle">
|
167
|
+
<div v-if="tips" ui-form-tips>
|
168
|
+
{{ tips }}
|
169
|
+
</div>
|
170
|
+
<input style="display: none" type="file" class="pa input" :multiple="!max || max > 1" :accept="accept" @change="change" />
|
171
|
+
<div class="co-note ac input-icon">
|
172
|
+
<svg t="1705642180833" style="width: 1em; height: 1em" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4215">
|
173
|
+
<path
|
174
|
+
d="M906.212134 565.732986 565.732986 565.732986 565.732986 906.212134C565.732986 926.013685 541.666486 959.972 511.97312 959.972 482.297674 959.972 458.213254 926.013685 458.213254 906.212134L458.213254 565.732986 117.734106 565.732986C97.950475 565.732986 63.97424 541.666486 63.97424 511.97312 63.97424 482.279754 97.950475 458.213254 117.734106 458.213254L458.213254 458.213254 458.213254 117.734106C458.213254 97.950475 482.297674 63.97424 511.97312 63.97424 541.666486 63.97424 565.732986 97.950475 565.732986 117.734106L565.732986 458.213254 906.212134 458.213254C925.995765 458.213254 959.972 482.279754 959.972 511.97312 959.972 541.666486 925.995765 565.732986 906.212134 565.732986Z"
|
175
|
+
p-id="4216"
|
176
|
+
></path>
|
177
|
+
</svg>
|
178
|
+
</div>
|
179
|
+
</div>
|
154
180
|
</div>
|
155
181
|
</label>
|
156
182
|
</slot>
|
157
|
-
</
|
158
|
-
</
|
159
|
-
<Layer :id="layerId" am="as"></Layer>
|
183
|
+
</template>
|
184
|
+
</div>
|
160
185
|
</template>
|
161
186
|
<script setup lang="ts">
|
162
|
-
import { reactive,
|
163
|
-
import { Image } from '../display';
|
164
|
-
import draggable from 'vuedraggable';
|
187
|
+
import { reactive, watch, onUnmounted, computed } from 'vue';
|
165
188
|
import Compressor from 'compressorjs';
|
166
|
-
import {
|
167
|
-
import { isArray, isFunction } from '@fekit/utils';
|
168
|
-
|
169
|
-
const layerId = Math.random().toString(36).slice(-6);
|
189
|
+
import { isNumber } from '@fekit/utils';
|
170
190
|
|
171
191
|
interface Props {
|
172
192
|
modelValue?: string | any[];
|
173
|
-
|
174
|
-
limit?: number;
|
193
|
+
max?: number;
|
175
194
|
attrs?: object;
|
195
|
+
itemAttrs?: object;
|
176
196
|
uploadClass?: string;
|
177
197
|
uploadStyle?: string;
|
178
|
-
|
179
|
-
|
180
|
-
// 文件类型
|
181
|
-
accept?: string;
|
182
|
-
// 是否可以上传多个文件
|
183
|
-
multiple?: boolean;
|
184
|
-
// 是否需要抠图处理
|
185
|
-
crop?: boolean;
|
186
|
-
// 上传路径
|
187
|
-
action?: string;
|
188
|
-
// 请求上传接口
|
198
|
+
tips?: string;
|
199
|
+
accept?: string | 'image/*' | 'video/*' | 'audio/*';
|
189
200
|
upload?: (formData: FormData) => Promise<any>;
|
201
|
+
maxSize?: number;
|
202
|
+
compress?: boolean;
|
203
|
+
disabled?: boolean;
|
204
|
+
width?: number | string;
|
205
|
+
ratio?: number;
|
190
206
|
}
|
191
207
|
|
192
208
|
const props = withDefaults(defineProps<Props>(), {
|
209
|
+
modelValue: '',
|
193
210
|
uploadClass: '',
|
194
211
|
uploadStyle: '',
|
195
|
-
id: '',
|
196
212
|
attrs: () => ({}),
|
213
|
+
itemAttrs: () => ({}),
|
197
214
|
tips: '',
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
215
|
+
accept: '*',
|
216
|
+
upload: async () => null,
|
217
|
+
maxSize: 10,
|
218
|
+
compress: true,
|
219
|
+
max: 0,
|
220
|
+
disabled: false,
|
221
|
+
width: 10,
|
222
|
+
ratio: 100,
|
204
223
|
});
|
205
224
|
|
206
|
-
|
207
|
-
|
225
|
+
interface UploadFile {
|
226
|
+
name: string;
|
227
|
+
type: string;
|
228
|
+
path: string;
|
229
|
+
status: 'ing' | 'yes' | 'err' | 'end';
|
230
|
+
size?: number;
|
231
|
+
progress?: number;
|
232
|
+
result?: any; // 直接保存上传函数的返回值
|
233
|
+
timer?: number; // 用于存储定时器ID
|
234
|
+
}
|
235
|
+
|
236
|
+
const state = reactive<{
|
237
|
+
files: UploadFile[];
|
238
|
+
isInternalUpdate: boolean; // 标记是否为内部更新
|
239
|
+
}>({
|
240
|
+
files: [],
|
241
|
+
isInternalUpdate: false,
|
208
242
|
});
|
209
243
|
|
210
|
-
const emit = defineEmits(['update:modelValue', 'change']);
|
211
|
-
|
212
|
-
//
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
//
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
244
|
+
const emit = defineEmits(['update:modelValue', 'change', 'error']);
|
245
|
+
|
246
|
+
// 获取图片URL
|
247
|
+
const getImageUrl = (file: UploadFile): string => {
|
248
|
+
if ((file.status === 'yes' || file.status === 'end') && file.result) {
|
249
|
+
// 如果上传成功,优先使用上传返回的URL
|
250
|
+
if (typeof file.result === 'string') {
|
251
|
+
return file.result;
|
252
|
+
}
|
253
|
+
// 如果是对象,尝试获取url或path
|
254
|
+
return file.result.url || file.result.path || file.path;
|
255
|
+
}
|
256
|
+
// 否则使用预览URL
|
257
|
+
return file.path;
|
258
|
+
};
|
259
|
+
|
260
|
+
// 计算属性
|
261
|
+
const showUploadButton = computed(() => {
|
262
|
+
const currentCount = state.files.length;
|
263
|
+
|
264
|
+
if (!props.max) {
|
265
|
+
return true; // 无限制
|
266
|
+
}
|
267
|
+
|
268
|
+
return currentCount < props.max;
|
269
|
+
});
|
270
|
+
|
271
|
+
// 获取文件类型
|
272
|
+
const getFileType = (file: File): string => {
|
273
|
+
if (file.type === 'application/msword' || file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
|
274
|
+
return 'docx';
|
275
|
+
} else if (file.type === 'application/vnd.ms-excel' || file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
|
276
|
+
return 'xlsx';
|
277
|
+
} else if (file.type === 'application/vnd.openxmlformats-officedocument.presentationml.presentation') {
|
278
|
+
return 'pptx';
|
279
|
+
} else if (file.type === 'application/pdf') {
|
280
|
+
return 'pdf';
|
281
|
+
} else if (file.type === 'text/html') {
|
282
|
+
return 'html';
|
283
|
+
} else if (file.type.startsWith('image/') && file.type !== 'image/vnd.adobe.photoshop') {
|
284
|
+
return 'image';
|
285
|
+
} else if (file.type.startsWith('video/')) {
|
286
|
+
return 'video';
|
287
|
+
}
|
288
|
+
return 'file';
|
289
|
+
};
|
290
|
+
|
291
|
+
// 从URL判断文件类型
|
292
|
+
const getFileTypeFromUrl = (url: string): string => {
|
293
|
+
const extension = url.split('.').pop()?.toLowerCase() || '';
|
294
|
+
|
295
|
+
// 图片格式
|
296
|
+
if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp', 'ico'].includes(extension)) {
|
297
|
+
return 'image';
|
298
|
+
}
|
299
|
+
|
300
|
+
// 视频格式
|
301
|
+
if (['mp4', 'avi', 'mov', 'wmv', 'flv', 'webm', 'mkv', 'm4v', '3gp'].includes(extension)) {
|
302
|
+
return 'video';
|
303
|
+
}
|
304
|
+
|
305
|
+
// 文档格式
|
306
|
+
if (['pdf'].includes(extension)) {
|
307
|
+
return 'pdf';
|
308
|
+
}
|
309
|
+
if (['doc', 'docx'].includes(extension)) {
|
310
|
+
return 'docx';
|
311
|
+
}
|
312
|
+
if (['xls', 'xlsx'].includes(extension)) {
|
313
|
+
return 'xlsx';
|
314
|
+
}
|
315
|
+
if (['ppt', 'pptx'].includes(extension)) {
|
316
|
+
return 'pptx';
|
317
|
+
}
|
318
|
+
|
319
|
+
return 'file';
|
320
|
+
};
|
321
|
+
|
322
|
+
// 验证文件
|
323
|
+
const validateFile = (file: File): string | null => {
|
324
|
+
// 检查文件大小
|
325
|
+
if (props.maxSize && file.size > props.maxSize * 1024 * 1024) {
|
326
|
+
return `文件大小不能超过 ${props.maxSize}MB`;
|
327
|
+
}
|
328
|
+
|
329
|
+
// 检查文件类型
|
330
|
+
if (props.accept && props.accept !== '*') {
|
331
|
+
const acceptTypes = props.accept.split(',').map((type) => type.trim());
|
332
|
+
const isValidType = acceptTypes.some((type) => {
|
333
|
+
if (type.endsWith('/*')) {
|
334
|
+
return file.type.startsWith(type.replace('/*', ''));
|
335
|
+
}
|
336
|
+
return file.type === type;
|
337
|
+
});
|
338
|
+
|
339
|
+
if (!isValidType) {
|
340
|
+
return `不支持的文件类型: ${file.type}`;
|
341
|
+
}
|
342
|
+
}
|
343
|
+
|
344
|
+
return null;
|
345
|
+
};
|
346
|
+
|
347
|
+
// 压缩图片
|
348
|
+
const compressImage = async (file: File): Promise<File> => {
|
349
|
+
if (!props.compress || !file.type.startsWith('image/')) {
|
350
|
+
return file;
|
351
|
+
}
|
352
|
+
|
353
|
+
return new Promise((resolve, reject) => {
|
354
|
+
new Compressor(file, {
|
355
|
+
quality: 0.8,
|
356
|
+
maxWidth: 1920,
|
357
|
+
maxHeight: 1080,
|
358
|
+
checkOrientation: true,
|
359
|
+
success: (result) => {
|
360
|
+
resolve(new File([result], file.name, { type: result.type }));
|
361
|
+
},
|
362
|
+
error: reject,
|
363
|
+
});
|
364
|
+
});
|
365
|
+
};
|
366
|
+
|
367
|
+
// 清除文件定时器
|
368
|
+
const clearFileTimer = (file: UploadFile) => {
|
369
|
+
if (file.timer) {
|
370
|
+
clearTimeout(file.timer);
|
371
|
+
file.timer = undefined;
|
372
|
+
}
|
373
|
+
};
|
374
|
+
|
375
|
+
// 设置状态转换定时器
|
376
|
+
const setStatusTransitionTimer = (file: UploadFile, delay: number = 2000) => {
|
377
|
+
clearFileTimer(file);
|
378
|
+
file.timer = window.setTimeout(() => {
|
379
|
+
const fileIndex = state.files.findIndex((f) => f.path === file.path);
|
380
|
+
if (fileIndex !== -1) {
|
381
|
+
if (file.status === 'yes') {
|
382
|
+
// yes 状态 3 秒后变为 end
|
383
|
+
state.files[fileIndex].status = 'end';
|
384
|
+
clearFileTimer(state.files[fileIndex]);
|
385
|
+
} else if (file.status === 'err') {
|
386
|
+
// err 状态 3 秒后清除占位(删除文件)
|
387
|
+
removeFile(fileIndex, true);
|
388
|
+
}
|
389
|
+
}
|
390
|
+
}, delay);
|
391
|
+
};
|
392
|
+
|
393
|
+
// 删除文件函数
|
394
|
+
const remove = (index: number) => {
|
395
|
+
removeFile(index, false);
|
396
|
+
};
|
397
|
+
|
398
|
+
// 内部删除文件函数
|
399
|
+
const removeFile = (index: number, isAutoRemove: boolean = false) => {
|
400
|
+
const file = state.files[index];
|
401
|
+
if (!file) return;
|
402
|
+
|
403
|
+
// 清除定时器
|
404
|
+
clearFileTimer(file);
|
405
|
+
|
406
|
+
// 释放对象URL,防止内存泄漏
|
407
|
+
if (file.path && file.path.startsWith('blob:')) {
|
408
|
+
URL.revokeObjectURL(file.path);
|
409
|
+
}
|
410
|
+
|
411
|
+
// 从数组中移除文件
|
412
|
+
state.files.splice(index, 1);
|
413
|
+
|
414
|
+
// 如果不是自动移除,发射更新事件
|
415
|
+
if (!isAutoRemove) {
|
416
|
+
emitUpdateEvents();
|
417
|
+
} else {
|
418
|
+
// 自动移除时也需要更新外部数据源
|
419
|
+
emitUpdateEvents();
|
420
|
+
}
|
421
|
+
};
|
422
|
+
|
423
|
+
// 发射更新事件
|
424
|
+
const emitUpdateEvents = () => {
|
425
|
+
// 设置内部更新标志
|
426
|
+
state.isInternalUpdate = true;
|
427
|
+
|
428
|
+
const successFiles = state.files.filter((file) => file.status === 'yes' || file.status === 'end');
|
429
|
+
|
430
|
+
// 如果没有成功文件,返回空值
|
431
|
+
if (successFiles.length === 0) {
|
432
|
+
const emptyValue = props.max === 1 ? '' : [];
|
433
|
+
emit('update:modelValue', emptyValue);
|
434
|
+
emit('change', emptyValue);
|
435
|
+
} else {
|
436
|
+
// 直接使用上传函数的返回值
|
437
|
+
const filesForModel = successFiles.map((file) => file.result);
|
438
|
+
const modelValue = props.max === 1 ? filesForModel[0] || '' : filesForModel;
|
439
|
+
|
440
|
+
emit('update:modelValue', modelValue);
|
441
|
+
emit('change', modelValue);
|
442
|
+
}
|
443
|
+
|
444
|
+
// 重置标志
|
445
|
+
setTimeout(() => {
|
446
|
+
state.isInternalUpdate = false;
|
447
|
+
}, 0);
|
448
|
+
};
|
449
|
+
|
450
|
+
// 文件上传处理
|
451
|
+
const change = (e: Event) => {
|
452
|
+
const target = e.target as HTMLInputElement;
|
453
|
+
const selectedFiles = target.files || [];
|
454
|
+
|
455
|
+
// 检查文件数量限制
|
456
|
+
if (props.max && state.files.length + selectedFiles.length > props.max) {
|
457
|
+
const errorMsg = `文件数量超过限制: ${props.max}`;
|
458
|
+
console.warn(errorMsg);
|
459
|
+
emit('error', errorMsg);
|
460
|
+
return;
|
461
|
+
}
|
462
|
+
|
463
|
+
// 步骤1:立即添加所有文件到UI,显示占位图
|
464
|
+
const validFiles: { file: File; uploadFile: UploadFile }[] = [];
|
465
|
+
|
466
|
+
for (let i = 0; i < selectedFiles.length; i++) {
|
467
|
+
const file = selectedFiles[i];
|
468
|
+
|
469
|
+
// 验证文件
|
470
|
+
const validationError = validateFile(file);
|
471
|
+
if (validationError) {
|
472
|
+
emit('error', validationError);
|
473
|
+
continue;
|
474
|
+
}
|
475
|
+
|
476
|
+
// 创建预览URL
|
477
|
+
const previewUrl = URL.createObjectURL(file);
|
478
|
+
|
479
|
+
// 添加到文件列表
|
480
|
+
const uploadFile: UploadFile = {
|
481
|
+
name: file.name,
|
482
|
+
type: getFileType(file),
|
483
|
+
path: previewUrl,
|
484
|
+
status: 'ing',
|
485
|
+
size: file.size,
|
486
|
+
};
|
487
|
+
state.files.push(uploadFile);
|
488
|
+
validFiles.push({ file, uploadFile });
|
259
489
|
}
|
260
490
|
|
261
|
-
//
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
//
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
491
|
+
// 步骤2:异步上传所有文件
|
492
|
+
validFiles.forEach(({ file, uploadFile }) => {
|
493
|
+
uploadSingleFile(file, uploadFile);
|
494
|
+
});
|
495
|
+
|
496
|
+
// 清空input值,允许重复选择同一文件
|
497
|
+
target.value = '';
|
498
|
+
};
|
499
|
+
|
500
|
+
// 单个文件上传函数
|
501
|
+
const uploadSingleFile = async (file: File, uploadFile: UploadFile) => {
|
502
|
+
try {
|
503
|
+
// 压缩图片(如果需要)
|
504
|
+
let processedFile = file;
|
505
|
+
if (props.compress && file.type.startsWith('image/')) {
|
506
|
+
try {
|
507
|
+
processedFile = await compressImage(file);
|
508
|
+
} catch (error) {
|
509
|
+
console.warn('图片压缩失败,使用原文件:', error);
|
510
|
+
}
|
511
|
+
}
|
512
|
+
|
513
|
+
// 上传到服务器
|
514
|
+
if (typeof props.upload !== 'function') {
|
515
|
+
throw new Error('upload 函数未定义');
|
516
|
+
}
|
517
|
+
|
518
|
+
const formData = new FormData();
|
519
|
+
formData.append('file', processedFile);
|
520
|
+
|
521
|
+
// 获取文件扩展名
|
522
|
+
const fileExtension = file.name.split('.').pop()?.toLowerCase() || '';
|
523
|
+
|
524
|
+
// 通过修改upload函数调用来传递扩展名
|
525
|
+
const result = await props.upload(formData, fileExtension);
|
526
|
+
|
527
|
+
// 更新文件状态
|
528
|
+
const fileIndex = state.files.findIndex((f) => f.path === uploadFile.path);
|
529
|
+
if (fileIndex !== -1) {
|
530
|
+
if (result) {
|
531
|
+
// 直接保存上传函数的返回值
|
532
|
+
state.files[fileIndex].result = result;
|
533
|
+
state.files[fileIndex].status = 'yes';
|
534
|
+
// 设置3秒后转换为end状态的定时器
|
535
|
+
setStatusTransitionTimer(state.files[fileIndex]);
|
536
|
+
// 每个文件完成后更新外部数据源
|
537
|
+
emitUpdateEvents();
|
538
|
+
} else {
|
539
|
+
// 上传失败时先显示错误状态,3秒后移除文件
|
540
|
+
state.files[fileIndex].status = 'err';
|
541
|
+
// 设置3秒后删除文件的定时器
|
542
|
+
setStatusTransitionTimer(state.files[fileIndex]);
|
543
|
+
// 发射错误事件
|
544
|
+
emit('error', `文件 ${file.name} 上传失败: 上传函数返回空值`);
|
545
|
+
}
|
546
|
+
}
|
547
|
+
} catch (error) {
|
548
|
+
console.error('文件处理失败:', error);
|
549
|
+
|
550
|
+
// 上传失败时先显示错误状态,3秒后移除文件
|
551
|
+
const fileIndex = state.files.findIndex((f) => f.path === uploadFile.path);
|
552
|
+
if (fileIndex !== -1) {
|
553
|
+
state.files[fileIndex].status = 'err';
|
554
|
+
// 设置3秒后删除文件的定时器
|
555
|
+
setStatusTransitionTimer(state.files[fileIndex]);
|
556
|
+
}
|
557
|
+
|
558
|
+
emit('error', `文件 ${file.name} 上传失败: ${error}`);
|
559
|
+
}
|
295
560
|
};
|
296
561
|
|
297
|
-
//
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
562
|
+
// 监听外部传入的modelValue变化,同步到内部状态
|
563
|
+
watch(
|
564
|
+
() => props.modelValue,
|
565
|
+
(newValue) => {
|
566
|
+
// 如果是内部更新,跳过处理
|
567
|
+
if (state.isInternalUpdate) {
|
568
|
+
return;
|
569
|
+
}
|
570
|
+
if (newValue && Array.isArray(newValue)) {
|
571
|
+
state.files = newValue.map((item) => {
|
572
|
+
if (typeof item === 'string') {
|
573
|
+
// 如果是字符串URL,尝试从URL判断类型
|
574
|
+
const urlType = getFileTypeFromUrl(item);
|
575
|
+
return {
|
576
|
+
name: 'file',
|
577
|
+
type: urlType,
|
578
|
+
path: item,
|
579
|
+
status: 'end' as const,
|
580
|
+
result: item,
|
581
|
+
};
|
582
|
+
} else {
|
583
|
+
// 如果是对象
|
584
|
+
return {
|
585
|
+
name: item.name || 'file',
|
586
|
+
type: item.type || 'file',
|
587
|
+
path: item.url || item.path || '',
|
588
|
+
status: 'end' as const,
|
589
|
+
result: item,
|
590
|
+
};
|
591
|
+
}
|
592
|
+
});
|
593
|
+
} else if (newValue && typeof newValue === 'string') {
|
594
|
+
const urlType = getFileTypeFromUrl(newValue);
|
595
|
+
state.files = [
|
596
|
+
{
|
597
|
+
name: 'file',
|
598
|
+
type: urlType,
|
599
|
+
path: newValue,
|
600
|
+
status: 'end',
|
601
|
+
result: newValue,
|
602
|
+
},
|
603
|
+
];
|
604
|
+
} else if (newValue && typeof newValue === 'object') {
|
605
|
+
const objValue = newValue as any;
|
606
|
+
const objPath = objValue.url || objValue.path || '';
|
607
|
+
const objType = objValue.type || (objPath ? getFileTypeFromUrl(objPath) : 'file');
|
608
|
+
state.files = [
|
609
|
+
{
|
610
|
+
name: objValue.name || 'file',
|
611
|
+
type: objType,
|
612
|
+
path: objPath,
|
613
|
+
status: 'end',
|
614
|
+
result: newValue,
|
615
|
+
},
|
616
|
+
];
|
617
|
+
} else {
|
618
|
+
state.files = [];
|
619
|
+
}
|
620
|
+
},
|
621
|
+
{ immediate: true, deep: true },
|
622
|
+
);
|
623
|
+
|
624
|
+
// 组件销毁时清理资源
|
625
|
+
onUnmounted(() => {
|
626
|
+
state.files.forEach((file) => {
|
627
|
+
// 清除定时器
|
628
|
+
clearFileTimer(file);
|
629
|
+
// 释放对象URL
|
630
|
+
if (file.path && file.path.startsWith('blob:')) {
|
631
|
+
URL.revokeObjectURL(file.path);
|
632
|
+
}
|
633
|
+
});
|
634
|
+
});
|
311
635
|
</script>
|
312
636
|
<style lang="scss">
|
313
|
-
.
|
637
|
+
.neatui-upload {
|
314
638
|
flex-wrap: wrap;
|
315
|
-
|
316
|
-
.upload {
|
317
|
-
|
318
|
-
|
639
|
+
// 上传状态样式
|
640
|
+
.upload-status {
|
641
|
+
position: absolute;
|
642
|
+
top: 0;
|
643
|
+
left: 0;
|
644
|
+
right: 0;
|
645
|
+
bottom: 0;
|
646
|
+
background: rgba(255, 255, 255, 0.8);
|
647
|
+
backdrop-filter: blur(0.5em);
|
648
|
+
-webkit-backdrop-filter: blur(0.5em);
|
649
|
+
display: flex;
|
650
|
+
flex-direction: column;
|
651
|
+
align-items: center;
|
652
|
+
justify-content: center;
|
653
|
+
color: #666;
|
654
|
+
font-size: 0.75em;
|
319
655
|
border-radius: 0.25em;
|
320
|
-
transition:
|
321
|
-
all 0.35s,
|
322
|
-
background-color 0s;
|
323
|
-
// background-color: #ffffff;
|
324
|
-
position: relative;
|
656
|
+
transition: opacity 0.3s ease;
|
325
657
|
|
326
|
-
|
658
|
+
// 完成
|
659
|
+
&[data-status='end'] {
|
327
660
|
opacity: 0;
|
328
|
-
|
661
|
+
pointer-events: none;
|
662
|
+
}
|
663
|
+
|
664
|
+
.status-text {
|
665
|
+
margin-top: 0.5em;
|
666
|
+
}
|
667
|
+
}
|
668
|
+
|
669
|
+
// 加载动画
|
670
|
+
.loading-spinner {
|
671
|
+
width: 1.5em;
|
672
|
+
height: 1.5em;
|
673
|
+
border: 2px solid rgba(255, 255, 255, 0.3);
|
674
|
+
border-top: 2px solid white;
|
675
|
+
border-radius: 50%;
|
676
|
+
animation: spin 1s linear infinite;
|
677
|
+
}
|
678
|
+
|
679
|
+
@keyframes spin {
|
680
|
+
0% {
|
681
|
+
transform: rotate(0deg);
|
682
|
+
}
|
683
|
+
100% {
|
684
|
+
transform: rotate(360deg);
|
685
|
+
}
|
686
|
+
}
|
687
|
+
|
688
|
+
// 上传动画
|
689
|
+
@keyframes am-ing {
|
690
|
+
0% {
|
691
|
+
transform: translateY(120%);
|
692
|
+
}
|
693
|
+
50% {
|
694
|
+
transform: translateY(0%);
|
695
|
+
}
|
696
|
+
60% {
|
697
|
+
transform: translateY(2%);
|
698
|
+
}
|
699
|
+
99% {
|
700
|
+
transform: translateY(-80%);
|
701
|
+
}
|
702
|
+
100% {
|
703
|
+
transform: translateY(0%);
|
704
|
+
}
|
705
|
+
}
|
706
|
+
// 动画定义
|
707
|
+
@keyframes am-yes-a {
|
708
|
+
0% {
|
709
|
+
transform: rotate(43deg) scale3d(0, 1, 1);
|
710
|
+
}
|
711
|
+
40%,
|
712
|
+
100% {
|
713
|
+
transform: rotate(43deg) scale3d(1, 1, 1);
|
714
|
+
}
|
715
|
+
}
|
716
|
+
|
717
|
+
@keyframes am-yes-b {
|
718
|
+
0%,
|
719
|
+
40% {
|
720
|
+
transform: rotate(-53deg) scale3d(0, 1, 1);
|
721
|
+
}
|
722
|
+
100% {
|
723
|
+
transform: rotate(-53deg) scale3d(1, 1, 1);
|
724
|
+
}
|
725
|
+
}
|
726
|
+
|
727
|
+
@keyframes am-err-a {
|
728
|
+
0%,
|
729
|
+
50% {
|
730
|
+
transform: rotate(45deg) scale3d(0, 1, 1);
|
731
|
+
}
|
732
|
+
100% {
|
733
|
+
transform: rotate(45deg) scale3d(1, 1, 1);
|
734
|
+
}
|
735
|
+
}
|
736
|
+
@keyframes am-err-b {
|
737
|
+
0% {
|
738
|
+
transform: rotate(-45deg) scale3d(0, 1, 1);
|
739
|
+
}
|
740
|
+
50%,
|
741
|
+
100% {
|
742
|
+
transform: rotate(-45deg) scale3d(1, 1, 1);
|
743
|
+
}
|
744
|
+
}
|
745
|
+
|
746
|
+
.neatui-upload-icon {
|
747
|
+
position: relative;
|
748
|
+
width: 2em;
|
749
|
+
height: 2em;
|
750
|
+
border-radius: 50%;
|
751
|
+
border: 1px solid currentColor;
|
752
|
+
overflow: hidden;
|
753
|
+
}
|
754
|
+
|
755
|
+
// 上传
|
756
|
+
[data-status='ing'] .neatui-upload-icon {
|
757
|
+
color: var(--co-warn);
|
758
|
+
|
759
|
+
& > * {
|
760
|
+
position: absolute;
|
761
|
+
display: block;
|
329
762
|
width: 100%;
|
763
|
+
height: 100%;
|
764
|
+
animation: am-ing 0.8s infinite both;
|
765
|
+
|
766
|
+
&::before,
|
767
|
+
&::after {
|
768
|
+
content: '';
|
769
|
+
position: absolute;
|
770
|
+
top: 24%;
|
771
|
+
}
|
772
|
+
|
773
|
+
&::before {
|
774
|
+
border-left: 2px solid currentColor;
|
775
|
+
border-top: 2px solid currentColor;
|
776
|
+
width: 0.7em;
|
777
|
+
height: 0.7em;
|
778
|
+
left: 30.5%;
|
779
|
+
transform: rotate(45deg);
|
780
|
+
}
|
781
|
+
&::after {
|
782
|
+
width: 2px;
|
783
|
+
height: 1em;
|
784
|
+
left: 44%;
|
785
|
+
background-color: currentColor;
|
786
|
+
}
|
330
787
|
}
|
331
|
-
|
332
|
-
|
788
|
+
}
|
789
|
+
|
790
|
+
// 成功
|
791
|
+
[data-status='yes'] .neatui-upload-icon {
|
792
|
+
color: var(--co-well);
|
793
|
+
|
794
|
+
&:before,
|
795
|
+
&:after {
|
796
|
+
position: absolute;
|
797
|
+
content: '';
|
798
|
+
display: block;
|
799
|
+
background-color: currentColor;
|
800
|
+
border-radius: 10rem;
|
801
|
+
}
|
802
|
+
|
803
|
+
&::before {
|
804
|
+
width: 35%;
|
805
|
+
height: 10%;
|
806
|
+
left: 18%;
|
807
|
+
top: 41%;
|
808
|
+
transform: rotate(43deg);
|
809
|
+
transform-origin: 0% 100%;
|
810
|
+
animation: am-yes-a ease-out 0.5s both;
|
811
|
+
}
|
812
|
+
|
813
|
+
&::after {
|
814
|
+
width: 61%;
|
815
|
+
height: 10%;
|
816
|
+
left: 46.5%;
|
817
|
+
bottom: 24.5%;
|
818
|
+
transform-origin: 0% 100%;
|
819
|
+
transform: rotate(-53deg);
|
820
|
+
animation: am-yes-b ease-out 0.5s both;
|
333
821
|
}
|
334
822
|
}
|
335
823
|
|
336
|
-
|
337
|
-
|
338
|
-
|
824
|
+
// 失败
|
825
|
+
[data-status='err'] .neatui-upload-icon {
|
826
|
+
color: var(--co-risk);
|
827
|
+
|
828
|
+
&:before,
|
829
|
+
&:after {
|
830
|
+
position: absolute;
|
831
|
+
content: '';
|
832
|
+
display: block;
|
833
|
+
background-color: currentColor;
|
834
|
+
border-radius: 10rem;
|
835
|
+
width: 70%;
|
836
|
+
height: 10%;
|
837
|
+
top: 17.25%;
|
838
|
+
}
|
839
|
+
|
840
|
+
&::before {
|
841
|
+
left: 23%;
|
842
|
+
transform: rotate(45deg);
|
843
|
+
transform-origin: 0% 100%;
|
844
|
+
animation: am-err-a ease 0.5s both;
|
845
|
+
}
|
339
846
|
|
340
|
-
|
341
|
-
|
342
|
-
|
847
|
+
&::after {
|
848
|
+
right: 23%;
|
849
|
+
transform-origin: 100% 100%;
|
850
|
+
transform: rotate(45deg);
|
851
|
+
animation: am-err-b ease 0.5s both;
|
343
852
|
}
|
344
853
|
}
|
345
854
|
}
|