@netang/quasar 0.2.30 → 0.2.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/.editorconfig +12 -12
  2. package/_docs/docs/components/field-table.md +58 -58
  3. package/_docs/docs/components/field-tree.md +21 -21
  4. package/_docs/docs/components/table.md +24 -24
  5. package/_docs/docs/utils/table.md +196 -196
  6. package/components/column-title/index.vue +38 -38
  7. package/components/data/index.vue +20 -20
  8. package/components/dialog/img-viewer/index.vue +697 -697
  9. package/components/dialog/index.vue +387 -387
  10. package/components/dragger/index.vue +203 -203
  11. package/components/drawer/index.vue +303 -303
  12. package/components/editor-code/index.vue +328 -328
  13. package/components/empty/index.vue +82 -82
  14. package/components/field-date/index.vue +860 -860
  15. package/components/field-date/methods.js +100 -100
  16. package/components/field-table/index.vue +1483 -1483
  17. package/components/field-text/index.vue +166 -166
  18. package/components/field-tree/index.vue +755 -755
  19. package/components/img/index.vue +279 -279
  20. package/components/input-number/index.vue +560 -560
  21. package/components/list-menu/index.vue +149 -149
  22. package/components/list-menu-item/index.vue +79 -79
  23. package/components/mixed-table/index.vue +532 -532
  24. package/components/mixed-table-splitter/index.vue +377 -377
  25. package/components/power-page/index.vue +96 -96
  26. package/components/price/index.vue +188 -188
  27. package/components/private/components/index.js +11 -11
  28. package/components/private/components/move-to-tree/index.vue +154 -154
  29. package/components/private/edit-power-data/index.vue +846 -846
  30. package/components/private/table-visible-columns-button/index.vue +114 -114
  31. package/components/render/index.vue +123 -123
  32. package/components/search/index.vue +231 -231
  33. package/components/search-item/index.vue +210 -210
  34. package/components/select/index.vue +177 -177
  35. package/components/splitter/index.vue +422 -422
  36. package/components/table/index.vue +513 -513
  37. package/components/table-column-fixed/index.vue +110 -110
  38. package/components/table-pagination/index.vue +192 -192
  39. package/components/table-summary/index.vue +107 -107
  40. package/components/thumbnail/index.vue +72 -72
  41. package/components/toolbar/index.vue +150 -150
  42. package/components/tree/index.vue +1728 -1728
  43. package/components/tree/virtual-scroll.vue +41 -41
  44. package/components/uploader/index.vue +196 -196
  45. package/components/uploader-query/index.vue +945 -945
  46. package/components/value-format/index.vue +274 -274
  47. package/components/virtual-scroll/index.vue +136 -136
  48. package/configs/area3.js +1 -1
  49. package/docs/404.html +33 -33
  50. package/docs/assets/404.html-60b35caa.js +1 -1
  51. package/docs/assets/404.html-d1e63d77.js +1 -1
  52. package/docs/assets/alert.html-b2a2a72f.js +5 -5
  53. package/docs/assets/alert.html-ba46d137.js +1 -1
  54. package/docs/assets/app-9f30aa4b.js +6 -6
  55. package/docs/assets/area.html-01b9b58d.js +42 -42
  56. package/docs/assets/area.html-9a4fce6a.js +1 -1
  57. package/docs/assets/arr.html-145d27e7.js +1 -1
  58. package/docs/assets/arr.html-674e65ab.js +11 -11
  59. package/docs/assets/auth.html-579fa830.js +1 -1
  60. package/docs/assets/auth.html-8544ed95.js +8 -8
  61. package/docs/assets/bus.html-c71254aa.js +1 -1
  62. package/docs/assets/bus.html-dc7d3d19.js +6 -6
  63. package/docs/assets/column-title.html-c735cb5a.js +3 -3
  64. package/docs/assets/column-title.html-e9316762.js +1 -1
  65. package/docs/assets/confirm.html-ddfdc27f.js +10 -10
  66. package/docs/assets/confirm.html-ef3e2bef.js +1 -1
  67. package/docs/assets/copy.html-d20345b6.js +1 -1
  68. package/docs/assets/copy.html-ef8c8571.js +13 -13
  69. package/docs/assets/data.html-6432175d.js +30 -30
  70. package/docs/assets/data.html-a3b05d5b.js +1 -1
  71. package/docs/assets/dialog.html-1f698e5a.js +1 -1
  72. package/docs/assets/dialog.html-62902b83.js +68 -68
  73. package/docs/assets/dialog.html-baea77c9.js +1 -1
  74. package/docs/assets/dialog.html-bb082fc4.js +1 -1
  75. package/docs/assets/dict.html-1311da3d.js +23 -23
  76. package/docs/assets/dict.html-b96fbf0c.js +1 -1
  77. package/docs/assets/dictOptions.html-7c4f40a5.js +1 -1
  78. package/docs/assets/dictOptions.html-fb99d175.js +5 -5
  79. package/docs/assets/dragger.html-668d3efa.js +1 -1
  80. package/docs/assets/dragger.html-749d585a.js +1 -1
  81. package/docs/assets/editor-code.html-6ab26ea9.js +1 -1
  82. package/docs/assets/editor-code.html-d196205d.js +1 -1
  83. package/docs/assets/empty.html-1c139131.js +1 -1
  84. package/docs/assets/empty.html-1e9c441d.js +1 -1
  85. package/docs/assets/field-date.html-069fdb13.js +1 -1
  86. package/docs/assets/field-date.html-ad204aa9.js +1 -1
  87. package/docs/assets/field-table.html-ce480f03.js +1 -1
  88. package/docs/assets/field-table.html-d9236160.js +1 -1
  89. package/docs/assets/field-text.html-7277c62f.js +1 -1
  90. package/docs/assets/field-text.html-ccb4cecf.js +1 -1
  91. package/docs/assets/field-tree.html-519bfb45.js +1 -1
  92. package/docs/assets/field-tree.html-fdc748d6.js +1 -1
  93. package/docs/assets/form.html-2b562c37.js +2 -2
  94. package/docs/assets/form.html-75104cd5.js +1 -1
  95. package/docs/assets/framework-204010b2.js +5 -5
  96. package/docs/assets/getData.html-990e3787.js +1 -1
  97. package/docs/assets/getData.html-bb72025f.js +34 -34
  98. package/docs/assets/getFile.html-42368004.js +1 -1
  99. package/docs/assets/getFile.html-99abd054.js +3 -3
  100. package/docs/assets/getImage.html-3429c5a1.js +1 -1
  101. package/docs/assets/getImage.html-4d886d83.js +3 -3
  102. package/docs/assets/getTime.html-7435f922.js +1 -1
  103. package/docs/assets/getTime.html-b37f49eb.js +20 -20
  104. package/docs/assets/img.html-7d1da657.js +1 -1
  105. package/docs/assets/img.html-fbea1105.js +1 -1
  106. package/docs/assets/index.html-1695dd7c.js +1 -1
  107. package/docs/assets/index.html-65a4aa67.js +1 -1
  108. package/docs/assets/index.html-7b98d5bd.js +1 -1
  109. package/docs/assets/index.html-c01f2648.js +1 -1
  110. package/docs/assets/input-number.html-0b250d2a.js +1 -1
  111. package/docs/assets/input-number.html-a8eb0378.js +1 -1
  112. package/docs/assets/list-menu-item.html-7f1b4611.js +1 -1
  113. package/docs/assets/list-menu-item.html-84ed5ab8.js +1 -1
  114. package/docs/assets/list-menu.html-28b4163f.js +1 -1
  115. package/docs/assets/list-menu.html-cb6ba95b.js +1 -1
  116. package/docs/assets/loading.html-dae9e39d.js +6 -6
  117. package/docs/assets/loading.html-dc74c9e6.js +1 -1
  118. package/docs/assets/notify.html-e6c4c514.js +1 -1
  119. package/docs/assets/notify.html-f2c4d914.js +8 -8
  120. package/docs/assets/power-page.html-32e02f82.js +1 -1
  121. package/docs/assets/power-page.html-485e77da.js +1 -1
  122. package/docs/assets/power.html-d258cc19.js +93 -93
  123. package/docs/assets/power.html-e490bd32.js +1 -1
  124. package/docs/assets/previewImage.html-6a6b4245.js +1 -1
  125. package/docs/assets/previewImage.html-c5b7e945.js +2 -2
  126. package/docs/assets/price.html-1882c548.js +19 -19
  127. package/docs/assets/price.html-94d3f5be.js +1 -1
  128. package/docs/assets/price.html-d213df0f.js +1 -1
  129. package/docs/assets/price.html-deaf880f.js +1 -1
  130. package/docs/assets/render.html-8efcbdd4.js +1 -1
  131. package/docs/assets/render.html-df228e38.js +1 -1
  132. package/docs/assets/rule.html-2cd57fc2.js +13 -13
  133. package/docs/assets/rule.html-61662001.js +1 -1
  134. package/docs/assets/ruleValid.html-04fe2552.js +1 -1
  135. package/docs/assets/ruleValid.html-e0a776af.js +14 -14
  136. package/docs/assets/search-0782d0d1.svg +1 -1
  137. package/docs/assets/search-item.html-3f75394c.js +1 -1
  138. package/docs/assets/search-item.html-4e942ecd.js +1 -1
  139. package/docs/assets/search.html-2807043e.js +1 -1
  140. package/docs/assets/search.html-c24f8806.js +1 -1
  141. package/docs/assets/select.html-00d0607c.js +1 -1
  142. package/docs/assets/select.html-de7731f5.js +1 -1
  143. package/docs/assets/splitter.html-56f51a70.js +1 -1
  144. package/docs/assets/splitter.html-f5c836d7.js +1 -1
  145. package/docs/assets/style-161e43ab.css +1 -1
  146. package/docs/assets/symbols.html-a6aea4bf.js +1 -1
  147. package/docs/assets/symbols.html-b1f65bad.js +21 -21
  148. package/docs/assets/table-column-fixed.html-3a69e7b2.js +1 -1
  149. package/docs/assets/table-column-fixed.html-e763c38b.js +1 -1
  150. package/docs/assets/table-pagination.html-236934d3.js +1 -1
  151. package/docs/assets/table-pagination.html-c37ee2ac.js +1 -1
  152. package/docs/assets/table-splitter.html-07eab15c.js +1 -1
  153. package/docs/assets/table-splitter.html-7670ee65.js +1 -1
  154. package/docs/assets/table-summary.html-04db434f.js +1 -1
  155. package/docs/assets/table-summary.html-943c65a0.js +1 -1
  156. package/docs/assets/table.html-36253ad7.js +1 -1
  157. package/docs/assets/table.html-7f9c5d1b.js +38 -38
  158. package/docs/assets/table.html-93d53dc8.js +1 -1
  159. package/docs/assets/table.html-ac99b9cb.js +1 -1
  160. package/docs/assets/thumbnail.html-bab1976b.js +1 -1
  161. package/docs/assets/thumbnail.html-eb64e5e8.js +1 -1
  162. package/docs/assets/timestamp.html-4e54f79b.js +13 -13
  163. package/docs/assets/timestamp.html-d0e1b88a.js +1 -1
  164. package/docs/assets/toast.html-58ecbe21.js +1 -1
  165. package/docs/assets/toast.html-c9b9d36b.js +6 -6
  166. package/docs/assets/toolbar.html-83d9f97c.js +1 -1
  167. package/docs/assets/toolbar.html-ff7b8c92.js +1 -1
  168. package/docs/assets/tree.html-d07cbe79.js +23 -23
  169. package/docs/assets/tree.html-ea04193e.js +1 -1
  170. package/docs/assets/uploader-query.html-05590718.js +1 -1
  171. package/docs/assets/uploader-query.html-3175bac5.js +1 -1
  172. package/docs/assets/uploader.html-36da4394.js +2 -2
  173. package/docs/assets/uploader.html-6b5f3079.js +1 -1
  174. package/docs/assets/uploader.html-b9340b57.js +1 -1
  175. package/docs/assets/uploader.html-bc1c22e3.js +1 -1
  176. package/docs/assets/value-format.html-8ae3d47d.js +1 -1
  177. package/docs/assets/value-format.html-afa99b3d.js +1 -1
  178. package/docs/components/column-title.html +35 -35
  179. package/docs/components/data.html +62 -62
  180. package/docs/components/dialog.html +33 -33
  181. package/docs/components/dragger.html +33 -33
  182. package/docs/components/editor-code.html +33 -33
  183. package/docs/components/empty.html +33 -33
  184. package/docs/components/field-date.html +33 -33
  185. package/docs/components/field-table.html +33 -33
  186. package/docs/components/field-text.html +33 -33
  187. package/docs/components/field-tree.html +33 -33
  188. package/docs/components/img.html +33 -33
  189. package/docs/components/input-number.html +33 -33
  190. package/docs/components/list-menu-item.html +33 -33
  191. package/docs/components/list-menu.html +33 -33
  192. package/docs/components/power-page.html +33 -33
  193. package/docs/components/price.html +33 -33
  194. package/docs/components/render.html +33 -33
  195. package/docs/components/search-item.html +33 -33
  196. package/docs/components/search.html +33 -33
  197. package/docs/components/select.html +33 -33
  198. package/docs/components/splitter.html +33 -33
  199. package/docs/components/table-column-fixed.html +33 -33
  200. package/docs/components/table-pagination.html +33 -33
  201. package/docs/components/table-splitter.html +33 -33
  202. package/docs/components/table-summary.html +33 -33
  203. package/docs/components/table.html +33 -33
  204. package/docs/components/thumbnail.html +33 -33
  205. package/docs/components/toolbar.html +33 -33
  206. package/docs/components/uploader-query.html +33 -33
  207. package/docs/components/uploader.html +33 -33
  208. package/docs/components/value-format.html +33 -33
  209. package/docs/css/index.css +3 -3
  210. package/docs/index.html +33 -33
  211. package/docs/utils/alert.html +37 -37
  212. package/docs/utils/area.html +74 -74
  213. package/docs/utils/arr.html +43 -43
  214. package/docs/utils/auth.html +40 -40
  215. package/docs/utils/bus.html +38 -38
  216. package/docs/utils/confirm.html +42 -42
  217. package/docs/utils/copy.html +45 -45
  218. package/docs/utils/dialog.html +100 -100
  219. package/docs/utils/dict.html +55 -55
  220. package/docs/utils/dictOptions.html +37 -37
  221. package/docs/utils/form.html +34 -34
  222. package/docs/utils/getData.html +66 -66
  223. package/docs/utils/getFile.html +35 -35
  224. package/docs/utils/getImage.html +35 -35
  225. package/docs/utils/getTime.html +52 -52
  226. package/docs/utils/index.html +33 -33
  227. package/docs/utils/loading.html +38 -38
  228. package/docs/utils/notify.html +40 -40
  229. package/docs/utils/power.html +125 -125
  230. package/docs/utils/previewImage.html +34 -34
  231. package/docs/utils/price.html +51 -51
  232. package/docs/utils/rule.html +45 -45
  233. package/docs/utils/ruleValid.html +46 -46
  234. package/docs/utils/symbols.html +53 -53
  235. package/docs/utils/table.html +70 -70
  236. package/docs/utils/timestamp.html +45 -45
  237. package/docs/utils/toast.html +38 -38
  238. package/docs/utils/tree.html +55 -55
  239. package/docs/utils/uploader.html +34 -34
  240. package/package.json +25 -25
  241. package/sass/common.scss +184 -184
  242. package/sass/index.scss +12 -12
  243. package/sass/line.scss +39 -39
  244. package/sass/quasar/btn.scss +46 -46
  245. package/sass/quasar/common.scss +3 -3
  246. package/sass/quasar/drawer.scss +6 -6
  247. package/sass/quasar/field.scss +259 -259
  248. package/sass/quasar/loading.scss +6 -6
  249. package/sass/quasar/table.scss +168 -168
  250. package/sass/quasar/toolbar.scss +22 -22
  251. package/sass/variables.scss +140 -140
  252. package/store/index.js +29 -29
  253. package/utils/$auth.js +128 -128
  254. package/utils/$form.js +72 -72
  255. package/utils/$power.js +1494 -1492
  256. package/utils/$render.js +75 -75
  257. package/utils/$rule.js +13 -13
  258. package/utils/$ruleValid.js +10 -10
  259. package/utils/$search.js +416 -416
  260. package/utils/$table.js +1348 -1276
  261. package/utils/$tree.js +682 -682
  262. package/utils/alert.js +12 -12
  263. package/utils/area.js +400 -400
  264. package/utils/arr.js +51 -51
  265. package/utils/bus.js +6 -6
  266. package/utils/config.js +66 -66
  267. package/utils/confirm.js +11 -11
  268. package/utils/copy.js +30 -30
  269. package/utils/dialog.js +36 -36
  270. package/utils/dict.js +21 -21
  271. package/utils/dictOptions.js +28 -28
  272. package/utils/getData.js +88 -88
  273. package/utils/getFile.js +67 -67
  274. package/utils/getImage.js +276 -276
  275. package/utils/getTime.js +113 -113
  276. package/utils/index.js +67 -67
  277. package/utils/loading.js +15 -15
  278. package/utils/notify.js +13 -13
  279. package/utils/play.js +40 -40
  280. package/utils/previewImage.js +14 -14
  281. package/utils/price.js +18 -18
  282. package/utils/symbols.js +18 -18
  283. package/utils/timestamp.js +18 -18
  284. package/utils/toast.js +13 -13
  285. package/utils/uploader.js +2114 -2114
  286. package/utils/useAuth.js +30 -30
  287. package/utils/useFileUrl.js +26 -26
  288. package/utils/useRouter.js +47 -47
  289. package/utils/useSearch.js +562 -562
@@ -1,697 +1,697 @@
1
- <template>
2
- <q-dialog
3
- class="n-img-viewer"
4
- ref="dialogRef"
5
- v-model="currentModelValue"
6
- :no-backdrop-dismiss="noBackdropDismiss"
7
- transition-show="fade"
8
- transition-hide="fade"
9
- maximized
10
- v-bind="$attrs"
11
- @hide="onDialogHide"
12
- >
13
- <div class="absolute-full" @click.self="onMask">
14
-
15
- <!-- 关闭 -->
16
- <q-btn
17
- class="n-img-viewer__btn n-img-viewer__btn--close cursor-pointer"
18
- :icon="closeIcon"
19
- round
20
- @click="onDialogCancel"
21
- unelevated
22
- :ripple="false"
23
- />
24
-
25
- <!-- 翻页按钮 -->
26
- <template v-if="! isSingle">
27
-
28
- <!-- 上一张按钮 -->
29
- <q-btn
30
- class="n-img-viewer__btn n-img-viewer__btn--prev cursor-pointer"
31
- :icon="prevIcon"
32
- round
33
- @click="prev"
34
- unelevated
35
- :ripple="false"
36
- />
37
-
38
- <!-- 下一张按钮 -->
39
- <q-btn
40
- class="n-img-viewer__btn n-img-viewer__btn--next cursor-pointer"
41
- :icon="nextIcon"
42
- round
43
- @click="next"
44
- unelevated
45
- :ripple="false"
46
- />
47
- </template>
48
-
49
- <!-- 操作面板 -->
50
- <div class="n-img-viewer__btn n-img-viewer__settings">
51
- <div class="n-img-viewer__settings__inner">
52
-
53
- <!-- 缩小 -->
54
- <q-icon
55
- class="cursor-pointer"
56
- :name="zoomOutIcon"
57
- @click="handleActions('zoomOut')"
58
- />
59
-
60
- <!-- 放大 -->
61
- <q-icon
62
- class="cursor-pointer"
63
- :name="zoomInIcon"
64
- @click="handleActions('zoomIn')"
65
- />
66
-
67
- <!-- 切换比例 -->
68
- <q-icon
69
- class="cursor-pointer"
70
- :name="isContain ? fullscreenIcon : exitFullscreenIcon"
71
- @click="toggleMode"
72
- />
73
-
74
- <!-- 水平反转 -->
75
- <q-icon
76
- class="cursor-pointer"
77
- :name="flipHorizontalIcon"
78
- @click="handleActions('flipX')"
79
- />
80
-
81
- <!-- 垂直反转 -->
82
- <q-icon
83
- class="cursor-pointer"
84
- :name="flipVerticalIcon"
85
- @click="handleActions('flipY')"
86
- />
87
-
88
- <!-- 左旋转 -->
89
- <q-icon
90
- class="cursor-pointer"
91
- :name="rotateLeftIcon"
92
- @click="handleActions('anticlockwise')"
93
- />
94
-
95
- <!-- 右旋转 -->
96
- <q-icon
97
- class="cursor-pointer"
98
- :name="rotateRightIcon"
99
- @click="handleActions('clockwise')"
100
- />
101
-
102
- </div>
103
- </div>
104
-
105
-
106
- <!-- 图片列表(有点击事件) -->
107
- <template v-if="isClickImg">
108
- <div
109
- v-for="(src, i) in currentImages"
110
- :key="`${src}-${i}`"
111
- class="non-selectable no-outline"
112
- @click="onClickImg({ src })"
113
- >
114
- <img
115
- :ref="(el) => (imgRefs[i] = el)"
116
- :src="src"
117
- :style="imgStyle"
118
- @load="handleImgLoad"
119
- @error="handleImgError"
120
- v-show="i === activeIndex"
121
- />
122
- </div>
123
- </template>
124
- <!-- 图片列表(点击跳转原图) -->
125
- <template v-else>
126
- <a
127
- v-for="(src, i) in currentImages"
128
- :key="`${src}-${i}`"
129
- :href="src"
130
- target="_blank"
131
- class="non-selectable no-outline"
132
- >
133
- <img
134
- :ref="(el) => (imgRefs[i] = el)"
135
- :src="src"
136
- :style="imgStyle"
137
- @load="handleImgLoad"
138
- @error="handleImgError"
139
- v-show="i === activeIndex"
140
- />
141
- </a>
142
- </template>
143
-
144
- </div>
145
- </q-dialog>
146
- </template>
147
-
148
- <script>
149
- import { computed, nextTick, onMounted, ref, watch } from 'vue'
150
- import { useDialogPluginComponent } from 'quasar'
151
-
152
- import $n_get from 'lodash/get'
153
-
154
- import $n_forEach from '@netang/utils/forEach'
155
- import $n_run from '@netang/utils/run'
156
-
157
- import $n_getImage from '../../../utils/getImage'
158
-
159
- import { configs } from '../../../utils/config'
160
-
161
- export default {
162
-
163
- /**
164
- * 标识
165
- */
166
- name: 'NDialog',
167
-
168
- /**
169
- * 声明属性
170
- */
171
- props: {
172
- // 值
173
- modelValue: {
174
- type: Boolean,
175
- default: true,
176
- },
177
- noBackdropDismiss: Boolean,
178
-
179
- // 需要预览的图片 URL 数组
180
- images: {
181
- type: Array,
182
- default: () => [],
183
- },
184
- // 图片预览起始位置索引
185
- startPosition: {
186
- type: Number,
187
- default: 0,
188
- },
189
- infinite: {
190
- type: Boolean,
191
- default: true,
192
- },
193
- zoomRate: {
194
- type: Number,
195
- default: 1.2,
196
- },
197
- // 关闭图标
198
- closeIcon: {
199
- type: String,
200
- default: 'close',
201
- },
202
- // 上一张图标
203
- prevIcon: {
204
- type: String,
205
- default: 'arrow_back_ios_new',
206
- },
207
- // 下一张图标
208
- nextIcon: {
209
- type: String,
210
- default: 'arrow_forward_ios',
211
- },
212
- // 缩小图标
213
- zoomOutIcon: {
214
- type: String,
215
- default: 'zoom_out',
216
- },
217
- // 放大图标
218
- zoomInIcon: {
219
- type: String,
220
- default: 'zoom_in',
221
- },
222
- // 全屏图标
223
- fullscreenIcon: {
224
- type: String,
225
- default: 'fullscreen',
226
- },
227
- // 退出全屏图标
228
- exitFullscreenIcon: {
229
- type: String,
230
- default: 'fullscreen_exit',
231
- },
232
- // 水平反转图标
233
- flipHorizontalIcon: {
234
- type: String,
235
- default: 'swap_horiz',
236
- },
237
- // 垂直反转图标
238
- flipVerticalIcon: {
239
- type: String,
240
- default: 'swap_vert',
241
- },
242
- // 左旋转图标
243
- rotateLeftIcon: {
244
- type: String,
245
- default: 'rotate_left',
246
- },
247
- // 右旋转图标
248
- rotateRightIcon: {
249
- type: String,
250
- default: 'rotate_right',
251
- },
252
- },
253
-
254
- /**
255
- * 声明事件
256
- */
257
- emits: [
258
- 'update:modelValue',
259
- 'change',
260
- ...useDialogPluginComponent.emits
261
- ],
262
-
263
- /**
264
- * 组合式
265
- */
266
- setup(props, { emit }) {
267
-
268
- // ==========【数据】============================================================================================
269
-
270
- // 当前值
271
- const currentModelValue = ref(props.modelValue)
272
-
273
- // 目标节点
274
- const targetRef = ref()
275
-
276
- // 图片节点数组
277
- const imgRefs = ref([])
278
-
279
- // 加载中
280
- const loading = ref(true)
281
-
282
- // 当前激活索引
283
- const activeIndex = ref(props.startPosition)
284
-
285
- // 模式
286
- const isContain = ref(true)
287
-
288
- // 图片是否可点击
289
- const isClickImg = ref($n_get(configs, 'components.imgViewer.isClickImg') === true)
290
-
291
- // 转换效果
292
- const transform = ref({
293
- scale: 1,
294
- deg: 0,
295
- rotateX: 1,
296
- rotateY: 1,
297
- offsetX: 0,
298
- offsetY: 0,
299
- enableTransition: false,
300
- })
301
-
302
- // ==========【计算属性】==========================================================================================
303
-
304
- /**
305
- * 当前图片数组
306
- */
307
- const currentImages = computed(function () {
308
-
309
- const lists = []
310
-
311
- $n_forEach(props.images, function (url) {
312
- const origin = $n_getImage(url, { compress: false })
313
- if (origin) {
314
- lists.push($n_getImage(url, { w: 1000 }))
315
- // lists.push({
316
- // src: $n_getImage(url, { w: 1000 }),
317
- // origin,
318
- // })
319
- }
320
- })
321
-
322
- return lists
323
- })
324
-
325
- /**
326
- * 是否单图
327
- */
328
- const isSingle = computed(function () {
329
- return currentImages.value.length <= 1
330
- })
331
-
332
- /**
333
- * 是否第一张
334
- */
335
- const isFirst = computed(function () {
336
- return activeIndex.value === 0
337
- })
338
-
339
- /**
340
- * 是否最后一张
341
- */
342
- const isLast = computed(function () {
343
- return activeIndex.value === currentImages.value.length - 1
344
- })
345
-
346
- /**
347
- * 当前图片
348
- */
349
- const currentImg = computed(function () {
350
- return currentImages.value[activeIndex.value]
351
- })
352
-
353
- /**
354
- * 图片样式
355
- */
356
- const imgStyle = computed(function () {
357
- const { scale, deg, rotateX, rotateY, offsetX, offsetY, enableTransition } = transform.value
358
- let translateX = offsetX / scale
359
- let translateY = offsetY / scale
360
-
361
- switch (deg % 360) {
362
- case 90:
363
- case -270:
364
- ;[translateX, translateY] = [translateY, -translateX]
365
- break
366
- case 180:
367
- case -180:
368
- ;[translateX, translateY] = [-translateX, -translateY]
369
- break
370
- case 270:
371
- case -90:
372
- ;[translateX, translateY] = [-translateY, translateX]
373
- break
374
- }
375
-
376
- const style = {
377
- transform: `scale(${scale}) scale3d(${rotateX}, ${rotateY}, 1) rotate(${deg}deg) translate(${translateX}px, ${translateY}px)`,
378
- transition: enableTransition ? 'transform .3s' : '',
379
- }
380
-
381
- if (isContain.value) {
382
- style.maxWidth = style.maxHeight = '100%'
383
- }
384
-
385
- return style
386
- })
387
-
388
- // ==========【监听数据】=========================================================================================
389
-
390
- /**
391
- * 监听当前图片
392
- */
393
- watch(currentImg, function () {
394
- nextTick(function () {
395
- const $img = imgRefs.value[0]
396
- if (!$img?.complete) {
397
- loading.value = true
398
- }
399
- })
400
- })
401
-
402
- /**
403
- * 监听当前索引
404
- */
405
- watch(activeIndex, function (val) {
406
- reset()
407
- emit('change', val)
408
- })
409
-
410
- /**
411
- * 监听值
412
- */
413
- watch(()=>props.modelValue, function (val) {
414
- currentModelValue.value = val
415
- })
416
-
417
- /**
418
- * 监听当前值
419
- */
420
- watch(currentModelValue, function (val) {
421
- emit('update:modelValue', val)
422
- })
423
-
424
- const {
425
- // 对话框节点
426
- dialogRef,
427
- // 对话框取消
428
- onDialogCancel,
429
- // 对话框隐藏
430
- onDialogHide,
431
- } = useDialogPluginComponent()
432
-
433
- // ==========【方法】=============================================================================================
434
-
435
- /**
436
- * 图片加载完成
437
- */
438
- function handleImgLoad() {
439
- loading.value = false
440
- }
441
-
442
- /**
443
- * 图片加载错误
444
- */
445
- function handleImgError() {
446
- loading.value = false
447
- }
448
-
449
- /**
450
- * 重置
451
- */
452
- function reset() {
453
- transform.value = {
454
- scale: 1,
455
- deg: 0,
456
- rotateX: 1,
457
- rotateY: 1,
458
- offsetX: 0,
459
- offsetY: 0,
460
- enableTransition: false,
461
- }
462
- }
463
-
464
- /**
465
- * 切换模式
466
- */
467
- function toggleMode() {
468
- if (loading.value) return
469
-
470
- // 切换是否包含
471
- isContain.value = ! isContain.value
472
-
473
- reset()
474
- }
475
-
476
- /**
477
- * 设置激活
478
- */
479
- function setActiveItem(index) {
480
- const len = currentImages.value.length
481
- activeIndex.value = (index + len) % len
482
- }
483
-
484
- /**
485
- * 前一张
486
- */
487
- function prev() {
488
- if (isFirst.value && !props.infinite) return
489
- setActiveItem(activeIndex.value - 1)
490
- }
491
-
492
- /**
493
- * 后一张
494
- */
495
- function next() {
496
- if (isLast.value && !props.infinite) return
497
- setActiveItem(activeIndex.value + 1)
498
- }
499
-
500
- /**
501
- * 操作
502
- */
503
- function handleActions(action, options = {}) {
504
- if (loading.value) return
505
- const { zoomRate, rotateDeg, enableTransition } = {
506
- zoomRate: props.zoomRate,
507
- rotateDeg: 90,
508
- enableTransition: true,
509
- ...options,
510
- }
511
- switch (action) {
512
- case 'zoomOut':
513
- if (transform.value.scale > 0.2) {
514
- transform.value.scale = Number.parseFloat(
515
- (transform.value.scale / zoomRate).toFixed(3)
516
- )
517
- }
518
- break
519
- case 'zoomIn':
520
- if (transform.value.scale < 7) {
521
- transform.value.scale = Number.parseFloat(
522
- (transform.value.scale * zoomRate).toFixed(3)
523
- )
524
- }
525
- break
526
- case 'clockwise':
527
- transform.value.deg += rotateDeg
528
- break
529
- case 'anticlockwise':
530
- transform.value.deg -= rotateDeg
531
- break
532
- case 'flipX':
533
- transform.value.rotateX = -transform.value.rotateX
534
- break
535
- case 'flipY':
536
- transform.value.rotateY = -transform.value.rotateY
537
- break
538
- }
539
- transform.value.enableTransition = enableTransition
540
- }
541
-
542
- /**
543
- * 点击遮蔽
544
- */
545
- function onMask() {
546
- if (! props.noBackdropDismiss) {
547
- onDialogCancel()
548
- }
549
- }
550
-
551
- /**
552
- * 点击图片
553
- */
554
- function onClickImg(e) {
555
- $n_run($n_get(configs, 'components.imgViewer.onClickImg'))(e)
556
- }
557
-
558
- // ==========【声明周期】=========================================================================================
559
-
560
- /**
561
- * 实例被挂载后调用
562
- */
563
- onMounted(function() {
564
- targetRef.value?.focus?.()
565
- })
566
-
567
- // ==========【返回】=============================================================================================
568
-
569
- return {
570
- currentModelValue,
571
- // 对话框节点
572
- dialogRef,
573
- // 对话框取消
574
- onDialogCancel,
575
- // 对话框隐藏
576
- onDialogHide,
577
-
578
- // 目标节点
579
- targetRef,
580
- // 图片节点数组
581
- imgRefs,
582
- // 加载中
583
- loading,
584
- // 当前激活索引
585
- activeIndex,
586
- // 是否包含
587
- isContain,
588
- // 转换效果
589
- transform,
590
- // 图片是否可点击
591
- isClickImg,
592
-
593
- // 当前图片数组
594
- currentImages,
595
- // 是否单图
596
- isSingle,
597
- // 是否第一张
598
- isFirst,
599
- // 是否最后一张
600
- isLast,
601
- // 当前图片
602
- currentImg,
603
- // 图片样式
604
- imgStyle,
605
-
606
- // 图片加载完成
607
- handleImgLoad,
608
- // 图片加载错误
609
- handleImgError,
610
- // 重置
611
- reset,
612
- // 切换模式
613
- toggleMode,
614
- // 设置激活
615
- setActiveItem,
616
- // 前一张
617
- prev,
618
- // 后一张
619
- next,
620
- // 操作
621
- handleActions,
622
- // 点击遮蔽
623
- onMask,
624
- // 点击图片
625
- onClickImg,
626
- }
627
- }
628
- }
629
- </script>
630
-
631
- <style lang="scss">
632
- .n-img-viewer {
633
-
634
- .q-dialog__inner > div {
635
- display: flex;
636
- justify-content: center;
637
- align-items: center;
638
- }
639
-
640
- // 按钮
641
- &__btn {
642
- position: fixed !important;
643
- opacity: 0.8;
644
- color: #ffffff !important;
645
- background: #606266 !important;
646
- user-select: none;
647
- z-index: 1;
648
-
649
- // 关闭按钮
650
- &--close {
651
- top: 40px;
652
- right: 40px;
653
- width: 40px;
654
- height: 40px;
655
- }
656
-
657
- // 上一张按钮
658
- &--prev {
659
- top: 50%;
660
- left: 40px;
661
- width: 40px;
662
- height: 40px;
663
- }
664
-
665
- // 下一张按钮
666
- &--next {
667
- top: 50%;
668
- right: 40px;
669
- width: 40px;
670
- height: 40px;
671
- }
672
- }
673
-
674
- // 操作面板
675
- &__settings {
676
- left: 50%;
677
- bottom: 30px;
678
- transform: translateX(-50%);
679
- width: 282px;
680
- height: 44px;
681
- padding: 0 23px;
682
- border-radius: 22px;
683
-
684
- &__inner {
685
- width: 100%;
686
- height: 100%;
687
- text-align: justify;
688
- cursor: default;
689
- font-size: 23px;
690
- color: #ffffff;
691
- display: flex;
692
- align-items: center;
693
- justify-content: space-around;
694
- }
695
- }
696
- }
697
- </style>
1
+ <template>
2
+ <q-dialog
3
+ class="n-img-viewer"
4
+ ref="dialogRef"
5
+ v-model="currentModelValue"
6
+ :no-backdrop-dismiss="noBackdropDismiss"
7
+ transition-show="fade"
8
+ transition-hide="fade"
9
+ maximized
10
+ v-bind="$attrs"
11
+ @hide="onDialogHide"
12
+ >
13
+ <div class="absolute-full" @click.self="onMask">
14
+
15
+ <!-- 关闭 -->
16
+ <q-btn
17
+ class="n-img-viewer__btn n-img-viewer__btn--close cursor-pointer"
18
+ :icon="closeIcon"
19
+ round
20
+ @click="onDialogCancel"
21
+ unelevated
22
+ :ripple="false"
23
+ />
24
+
25
+ <!-- 翻页按钮 -->
26
+ <template v-if="! isSingle">
27
+
28
+ <!-- 上一张按钮 -->
29
+ <q-btn
30
+ class="n-img-viewer__btn n-img-viewer__btn--prev cursor-pointer"
31
+ :icon="prevIcon"
32
+ round
33
+ @click="prev"
34
+ unelevated
35
+ :ripple="false"
36
+ />
37
+
38
+ <!-- 下一张按钮 -->
39
+ <q-btn
40
+ class="n-img-viewer__btn n-img-viewer__btn--next cursor-pointer"
41
+ :icon="nextIcon"
42
+ round
43
+ @click="next"
44
+ unelevated
45
+ :ripple="false"
46
+ />
47
+ </template>
48
+
49
+ <!-- 操作面板 -->
50
+ <div class="n-img-viewer__btn n-img-viewer__settings">
51
+ <div class="n-img-viewer__settings__inner">
52
+
53
+ <!-- 缩小 -->
54
+ <q-icon
55
+ class="cursor-pointer"
56
+ :name="zoomOutIcon"
57
+ @click="handleActions('zoomOut')"
58
+ />
59
+
60
+ <!-- 放大 -->
61
+ <q-icon
62
+ class="cursor-pointer"
63
+ :name="zoomInIcon"
64
+ @click="handleActions('zoomIn')"
65
+ />
66
+
67
+ <!-- 切换比例 -->
68
+ <q-icon
69
+ class="cursor-pointer"
70
+ :name="isContain ? fullscreenIcon : exitFullscreenIcon"
71
+ @click="toggleMode"
72
+ />
73
+
74
+ <!-- 水平反转 -->
75
+ <q-icon
76
+ class="cursor-pointer"
77
+ :name="flipHorizontalIcon"
78
+ @click="handleActions('flipX')"
79
+ />
80
+
81
+ <!-- 垂直反转 -->
82
+ <q-icon
83
+ class="cursor-pointer"
84
+ :name="flipVerticalIcon"
85
+ @click="handleActions('flipY')"
86
+ />
87
+
88
+ <!-- 左旋转 -->
89
+ <q-icon
90
+ class="cursor-pointer"
91
+ :name="rotateLeftIcon"
92
+ @click="handleActions('anticlockwise')"
93
+ />
94
+
95
+ <!-- 右旋转 -->
96
+ <q-icon
97
+ class="cursor-pointer"
98
+ :name="rotateRightIcon"
99
+ @click="handleActions('clockwise')"
100
+ />
101
+
102
+ </div>
103
+ </div>
104
+
105
+
106
+ <!-- 图片列表(有点击事件) -->
107
+ <template v-if="isClickImg">
108
+ <div
109
+ v-for="(src, i) in currentImages"
110
+ :key="`${src}-${i}`"
111
+ class="non-selectable no-outline"
112
+ @click="onClickImg({ src })"
113
+ >
114
+ <img
115
+ :ref="(el) => (imgRefs[i] = el)"
116
+ :src="src"
117
+ :style="imgStyle"
118
+ @load="handleImgLoad"
119
+ @error="handleImgError"
120
+ v-show="i === activeIndex"
121
+ />
122
+ </div>
123
+ </template>
124
+ <!-- 图片列表(点击跳转原图) -->
125
+ <template v-else>
126
+ <a
127
+ v-for="(src, i) in currentImages"
128
+ :key="`${src}-${i}`"
129
+ :href="src"
130
+ target="_blank"
131
+ class="non-selectable no-outline"
132
+ >
133
+ <img
134
+ :ref="(el) => (imgRefs[i] = el)"
135
+ :src="src"
136
+ :style="imgStyle"
137
+ @load="handleImgLoad"
138
+ @error="handleImgError"
139
+ v-show="i === activeIndex"
140
+ />
141
+ </a>
142
+ </template>
143
+
144
+ </div>
145
+ </q-dialog>
146
+ </template>
147
+
148
+ <script>
149
+ import { computed, nextTick, onMounted, ref, watch } from 'vue'
150
+ import { useDialogPluginComponent } from 'quasar'
151
+
152
+ import $n_get from 'lodash/get'
153
+
154
+ import $n_forEach from '@netang/utils/forEach'
155
+ import $n_run from '@netang/utils/run'
156
+
157
+ import $n_getImage from '../../../utils/getImage'
158
+
159
+ import { configs } from '../../../utils/config'
160
+
161
+ export default {
162
+
163
+ /**
164
+ * 标识
165
+ */
166
+ name: 'NDialog',
167
+
168
+ /**
169
+ * 声明属性
170
+ */
171
+ props: {
172
+ // 值
173
+ modelValue: {
174
+ type: Boolean,
175
+ default: true,
176
+ },
177
+ noBackdropDismiss: Boolean,
178
+
179
+ // 需要预览的图片 URL 数组
180
+ images: {
181
+ type: Array,
182
+ default: () => [],
183
+ },
184
+ // 图片预览起始位置索引
185
+ startPosition: {
186
+ type: Number,
187
+ default: 0,
188
+ },
189
+ infinite: {
190
+ type: Boolean,
191
+ default: true,
192
+ },
193
+ zoomRate: {
194
+ type: Number,
195
+ default: 1.2,
196
+ },
197
+ // 关闭图标
198
+ closeIcon: {
199
+ type: String,
200
+ default: 'close',
201
+ },
202
+ // 上一张图标
203
+ prevIcon: {
204
+ type: String,
205
+ default: 'arrow_back_ios_new',
206
+ },
207
+ // 下一张图标
208
+ nextIcon: {
209
+ type: String,
210
+ default: 'arrow_forward_ios',
211
+ },
212
+ // 缩小图标
213
+ zoomOutIcon: {
214
+ type: String,
215
+ default: 'zoom_out',
216
+ },
217
+ // 放大图标
218
+ zoomInIcon: {
219
+ type: String,
220
+ default: 'zoom_in',
221
+ },
222
+ // 全屏图标
223
+ fullscreenIcon: {
224
+ type: String,
225
+ default: 'fullscreen',
226
+ },
227
+ // 退出全屏图标
228
+ exitFullscreenIcon: {
229
+ type: String,
230
+ default: 'fullscreen_exit',
231
+ },
232
+ // 水平反转图标
233
+ flipHorizontalIcon: {
234
+ type: String,
235
+ default: 'swap_horiz',
236
+ },
237
+ // 垂直反转图标
238
+ flipVerticalIcon: {
239
+ type: String,
240
+ default: 'swap_vert',
241
+ },
242
+ // 左旋转图标
243
+ rotateLeftIcon: {
244
+ type: String,
245
+ default: 'rotate_left',
246
+ },
247
+ // 右旋转图标
248
+ rotateRightIcon: {
249
+ type: String,
250
+ default: 'rotate_right',
251
+ },
252
+ },
253
+
254
+ /**
255
+ * 声明事件
256
+ */
257
+ emits: [
258
+ 'update:modelValue',
259
+ 'change',
260
+ ...useDialogPluginComponent.emits
261
+ ],
262
+
263
+ /**
264
+ * 组合式
265
+ */
266
+ setup(props, { emit }) {
267
+
268
+ // ==========【数据】============================================================================================
269
+
270
+ // 当前值
271
+ const currentModelValue = ref(props.modelValue)
272
+
273
+ // 目标节点
274
+ const targetRef = ref()
275
+
276
+ // 图片节点数组
277
+ const imgRefs = ref([])
278
+
279
+ // 加载中
280
+ const loading = ref(true)
281
+
282
+ // 当前激活索引
283
+ const activeIndex = ref(props.startPosition)
284
+
285
+ // 模式
286
+ const isContain = ref(true)
287
+
288
+ // 图片是否可点击
289
+ const isClickImg = ref($n_get(configs, 'components.imgViewer.isClickImg') === true)
290
+
291
+ // 转换效果
292
+ const transform = ref({
293
+ scale: 1,
294
+ deg: 0,
295
+ rotateX: 1,
296
+ rotateY: 1,
297
+ offsetX: 0,
298
+ offsetY: 0,
299
+ enableTransition: false,
300
+ })
301
+
302
+ // ==========【计算属性】==========================================================================================
303
+
304
+ /**
305
+ * 当前图片数组
306
+ */
307
+ const currentImages = computed(function () {
308
+
309
+ const lists = []
310
+
311
+ $n_forEach(props.images, function (url) {
312
+ const origin = $n_getImage(url, { compress: false })
313
+ if (origin) {
314
+ lists.push($n_getImage(url, { w: 1000 }))
315
+ // lists.push({
316
+ // src: $n_getImage(url, { w: 1000 }),
317
+ // origin,
318
+ // })
319
+ }
320
+ })
321
+
322
+ return lists
323
+ })
324
+
325
+ /**
326
+ * 是否单图
327
+ */
328
+ const isSingle = computed(function () {
329
+ return currentImages.value.length <= 1
330
+ })
331
+
332
+ /**
333
+ * 是否第一张
334
+ */
335
+ const isFirst = computed(function () {
336
+ return activeIndex.value === 0
337
+ })
338
+
339
+ /**
340
+ * 是否最后一张
341
+ */
342
+ const isLast = computed(function () {
343
+ return activeIndex.value === currentImages.value.length - 1
344
+ })
345
+
346
+ /**
347
+ * 当前图片
348
+ */
349
+ const currentImg = computed(function () {
350
+ return currentImages.value[activeIndex.value]
351
+ })
352
+
353
+ /**
354
+ * 图片样式
355
+ */
356
+ const imgStyle = computed(function () {
357
+ const { scale, deg, rotateX, rotateY, offsetX, offsetY, enableTransition } = transform.value
358
+ let translateX = offsetX / scale
359
+ let translateY = offsetY / scale
360
+
361
+ switch (deg % 360) {
362
+ case 90:
363
+ case -270:
364
+ ;[translateX, translateY] = [translateY, -translateX]
365
+ break
366
+ case 180:
367
+ case -180:
368
+ ;[translateX, translateY] = [-translateX, -translateY]
369
+ break
370
+ case 270:
371
+ case -90:
372
+ ;[translateX, translateY] = [-translateY, translateX]
373
+ break
374
+ }
375
+
376
+ const style = {
377
+ transform: `scale(${scale}) scale3d(${rotateX}, ${rotateY}, 1) rotate(${deg}deg) translate(${translateX}px, ${translateY}px)`,
378
+ transition: enableTransition ? 'transform .3s' : '',
379
+ }
380
+
381
+ if (isContain.value) {
382
+ style.maxWidth = style.maxHeight = '100%'
383
+ }
384
+
385
+ return style
386
+ })
387
+
388
+ // ==========【监听数据】=========================================================================================
389
+
390
+ /**
391
+ * 监听当前图片
392
+ */
393
+ watch(currentImg, function () {
394
+ nextTick(function () {
395
+ const $img = imgRefs.value[0]
396
+ if (!$img?.complete) {
397
+ loading.value = true
398
+ }
399
+ })
400
+ })
401
+
402
+ /**
403
+ * 监听当前索引
404
+ */
405
+ watch(activeIndex, function (val) {
406
+ reset()
407
+ emit('change', val)
408
+ })
409
+
410
+ /**
411
+ * 监听值
412
+ */
413
+ watch(()=>props.modelValue, function (val) {
414
+ currentModelValue.value = val
415
+ })
416
+
417
+ /**
418
+ * 监听当前值
419
+ */
420
+ watch(currentModelValue, function (val) {
421
+ emit('update:modelValue', val)
422
+ })
423
+
424
+ const {
425
+ // 对话框节点
426
+ dialogRef,
427
+ // 对话框取消
428
+ onDialogCancel,
429
+ // 对话框隐藏
430
+ onDialogHide,
431
+ } = useDialogPluginComponent()
432
+
433
+ // ==========【方法】=============================================================================================
434
+
435
+ /**
436
+ * 图片加载完成
437
+ */
438
+ function handleImgLoad() {
439
+ loading.value = false
440
+ }
441
+
442
+ /**
443
+ * 图片加载错误
444
+ */
445
+ function handleImgError() {
446
+ loading.value = false
447
+ }
448
+
449
+ /**
450
+ * 重置
451
+ */
452
+ function reset() {
453
+ transform.value = {
454
+ scale: 1,
455
+ deg: 0,
456
+ rotateX: 1,
457
+ rotateY: 1,
458
+ offsetX: 0,
459
+ offsetY: 0,
460
+ enableTransition: false,
461
+ }
462
+ }
463
+
464
+ /**
465
+ * 切换模式
466
+ */
467
+ function toggleMode() {
468
+ if (loading.value) return
469
+
470
+ // 切换是否包含
471
+ isContain.value = ! isContain.value
472
+
473
+ reset()
474
+ }
475
+
476
+ /**
477
+ * 设置激活
478
+ */
479
+ function setActiveItem(index) {
480
+ const len = currentImages.value.length
481
+ activeIndex.value = (index + len) % len
482
+ }
483
+
484
+ /**
485
+ * 前一张
486
+ */
487
+ function prev() {
488
+ if (isFirst.value && !props.infinite) return
489
+ setActiveItem(activeIndex.value - 1)
490
+ }
491
+
492
+ /**
493
+ * 后一张
494
+ */
495
+ function next() {
496
+ if (isLast.value && !props.infinite) return
497
+ setActiveItem(activeIndex.value + 1)
498
+ }
499
+
500
+ /**
501
+ * 操作
502
+ */
503
+ function handleActions(action, options = {}) {
504
+ if (loading.value) return
505
+ const { zoomRate, rotateDeg, enableTransition } = {
506
+ zoomRate: props.zoomRate,
507
+ rotateDeg: 90,
508
+ enableTransition: true,
509
+ ...options,
510
+ }
511
+ switch (action) {
512
+ case 'zoomOut':
513
+ if (transform.value.scale > 0.2) {
514
+ transform.value.scale = Number.parseFloat(
515
+ (transform.value.scale / zoomRate).toFixed(3)
516
+ )
517
+ }
518
+ break
519
+ case 'zoomIn':
520
+ if (transform.value.scale < 7) {
521
+ transform.value.scale = Number.parseFloat(
522
+ (transform.value.scale * zoomRate).toFixed(3)
523
+ )
524
+ }
525
+ break
526
+ case 'clockwise':
527
+ transform.value.deg += rotateDeg
528
+ break
529
+ case 'anticlockwise':
530
+ transform.value.deg -= rotateDeg
531
+ break
532
+ case 'flipX':
533
+ transform.value.rotateX = -transform.value.rotateX
534
+ break
535
+ case 'flipY':
536
+ transform.value.rotateY = -transform.value.rotateY
537
+ break
538
+ }
539
+ transform.value.enableTransition = enableTransition
540
+ }
541
+
542
+ /**
543
+ * 点击遮蔽
544
+ */
545
+ function onMask() {
546
+ if (! props.noBackdropDismiss) {
547
+ onDialogCancel()
548
+ }
549
+ }
550
+
551
+ /**
552
+ * 点击图片
553
+ */
554
+ function onClickImg(e) {
555
+ $n_run($n_get(configs, 'components.imgViewer.onClickImg'))(e)
556
+ }
557
+
558
+ // ==========【声明周期】=========================================================================================
559
+
560
+ /**
561
+ * 实例被挂载后调用
562
+ */
563
+ onMounted(function() {
564
+ targetRef.value?.focus?.()
565
+ })
566
+
567
+ // ==========【返回】=============================================================================================
568
+
569
+ return {
570
+ currentModelValue,
571
+ // 对话框节点
572
+ dialogRef,
573
+ // 对话框取消
574
+ onDialogCancel,
575
+ // 对话框隐藏
576
+ onDialogHide,
577
+
578
+ // 目标节点
579
+ targetRef,
580
+ // 图片节点数组
581
+ imgRefs,
582
+ // 加载中
583
+ loading,
584
+ // 当前激活索引
585
+ activeIndex,
586
+ // 是否包含
587
+ isContain,
588
+ // 转换效果
589
+ transform,
590
+ // 图片是否可点击
591
+ isClickImg,
592
+
593
+ // 当前图片数组
594
+ currentImages,
595
+ // 是否单图
596
+ isSingle,
597
+ // 是否第一张
598
+ isFirst,
599
+ // 是否最后一张
600
+ isLast,
601
+ // 当前图片
602
+ currentImg,
603
+ // 图片样式
604
+ imgStyle,
605
+
606
+ // 图片加载完成
607
+ handleImgLoad,
608
+ // 图片加载错误
609
+ handleImgError,
610
+ // 重置
611
+ reset,
612
+ // 切换模式
613
+ toggleMode,
614
+ // 设置激活
615
+ setActiveItem,
616
+ // 前一张
617
+ prev,
618
+ // 后一张
619
+ next,
620
+ // 操作
621
+ handleActions,
622
+ // 点击遮蔽
623
+ onMask,
624
+ // 点击图片
625
+ onClickImg,
626
+ }
627
+ }
628
+ }
629
+ </script>
630
+
631
+ <style lang="scss">
632
+ .n-img-viewer {
633
+
634
+ .q-dialog__inner > div {
635
+ display: flex;
636
+ justify-content: center;
637
+ align-items: center;
638
+ }
639
+
640
+ // 按钮
641
+ &__btn {
642
+ position: fixed !important;
643
+ opacity: 0.8;
644
+ color: #ffffff !important;
645
+ background: #606266 !important;
646
+ user-select: none;
647
+ z-index: 1;
648
+
649
+ // 关闭按钮
650
+ &--close {
651
+ top: 40px;
652
+ right: 40px;
653
+ width: 40px;
654
+ height: 40px;
655
+ }
656
+
657
+ // 上一张按钮
658
+ &--prev {
659
+ top: 50%;
660
+ left: 40px;
661
+ width: 40px;
662
+ height: 40px;
663
+ }
664
+
665
+ // 下一张按钮
666
+ &--next {
667
+ top: 50%;
668
+ right: 40px;
669
+ width: 40px;
670
+ height: 40px;
671
+ }
672
+ }
673
+
674
+ // 操作面板
675
+ &__settings {
676
+ left: 50%;
677
+ bottom: 30px;
678
+ transform: translateX(-50%);
679
+ width: 282px;
680
+ height: 44px;
681
+ padding: 0 23px;
682
+ border-radius: 22px;
683
+
684
+ &__inner {
685
+ width: 100%;
686
+ height: 100%;
687
+ text-align: justify;
688
+ cursor: default;
689
+ font-size: 23px;
690
+ color: #ffffff;
691
+ display: flex;
692
+ align-items: center;
693
+ justify-content: space-around;
694
+ }
695
+ }
696
+ }
697
+ </style>