@netang/quasar 0.2.20 → 0.2.21

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 (284) 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/dragger/index.vue +203 -203
  10. package/components/drawer/index.vue +303 -303
  11. package/components/editor-code/index.vue +325 -325
  12. package/components/empty/index.vue +82 -82
  13. package/components/field-date/index.vue +850 -850
  14. package/components/field-date/methods.js +100 -100
  15. package/components/field-table/index.vue +1482 -1482
  16. package/components/field-text/index.vue +165 -165
  17. package/components/field-tree/index.vue +754 -754
  18. package/components/img/index.vue +279 -279
  19. package/components/list-menu/index.vue +149 -149
  20. package/components/list-menu-item/index.vue +79 -79
  21. package/components/mixed-table/index.vue +532 -532
  22. package/components/mixed-table-splitter/index.vue +377 -377
  23. package/components/power-page/index.vue +96 -96
  24. package/components/price/index.vue +188 -188
  25. package/components/private/components/index.js +11 -11
  26. package/components/private/components/move-to-tree/index.vue +154 -154
  27. package/components/private/edit-power-data/index.vue +846 -846
  28. package/components/private/table-visible-columns-button/index.vue +114 -114
  29. package/components/render/index.vue +123 -123
  30. package/components/search/index.vue +231 -231
  31. package/components/search-item/index.vue +210 -210
  32. package/components/select/index.vue +177 -177
  33. package/components/splitter/index.vue +422 -422
  34. package/components/table/index.vue +513 -513
  35. package/components/table-column-fixed/index.vue +110 -110
  36. package/components/table-pagination/index.vue +192 -192
  37. package/components/table-summary/index.vue +107 -107
  38. package/components/thumbnail/index.vue +72 -72
  39. package/components/toolbar/index.vue +146 -146
  40. package/components/tree/index.vue +1728 -1728
  41. package/components/uploader/index.vue +195 -195
  42. package/components/uploader-query/index.vue +945 -945
  43. package/components/value-format/index.vue +274 -274
  44. package/configs/area3.js +1 -1
  45. package/docs/404.html +33 -33
  46. package/docs/assets/404.html-60b35caa.js +1 -1
  47. package/docs/assets/404.html-d1e63d77.js +1 -1
  48. package/docs/assets/alert.html-b2a2a72f.js +5 -5
  49. package/docs/assets/alert.html-ba46d137.js +1 -1
  50. package/docs/assets/app-9f30aa4b.js +6 -6
  51. package/docs/assets/area.html-01b9b58d.js +42 -42
  52. package/docs/assets/area.html-9a4fce6a.js +1 -1
  53. package/docs/assets/arr.html-145d27e7.js +1 -1
  54. package/docs/assets/arr.html-674e65ab.js +11 -11
  55. package/docs/assets/auth.html-579fa830.js +1 -1
  56. package/docs/assets/auth.html-8544ed95.js +8 -8
  57. package/docs/assets/bus.html-c71254aa.js +1 -1
  58. package/docs/assets/bus.html-dc7d3d19.js +6 -6
  59. package/docs/assets/column-title.html-c735cb5a.js +3 -3
  60. package/docs/assets/column-title.html-e9316762.js +1 -1
  61. package/docs/assets/confirm.html-ddfdc27f.js +10 -10
  62. package/docs/assets/confirm.html-ef3e2bef.js +1 -1
  63. package/docs/assets/copy.html-d20345b6.js +1 -1
  64. package/docs/assets/copy.html-ef8c8571.js +13 -13
  65. package/docs/assets/data.html-6432175d.js +30 -30
  66. package/docs/assets/data.html-a3b05d5b.js +1 -1
  67. package/docs/assets/dialog.html-1f698e5a.js +1 -1
  68. package/docs/assets/dialog.html-62902b83.js +68 -68
  69. package/docs/assets/dialog.html-baea77c9.js +1 -1
  70. package/docs/assets/dialog.html-bb082fc4.js +1 -1
  71. package/docs/assets/dict.html-1311da3d.js +23 -23
  72. package/docs/assets/dict.html-b96fbf0c.js +1 -1
  73. package/docs/assets/dictOptions.html-7c4f40a5.js +1 -1
  74. package/docs/assets/dictOptions.html-fb99d175.js +5 -5
  75. package/docs/assets/dragger.html-668d3efa.js +1 -1
  76. package/docs/assets/dragger.html-749d585a.js +1 -1
  77. package/docs/assets/editor-code.html-6ab26ea9.js +1 -1
  78. package/docs/assets/editor-code.html-d196205d.js +1 -1
  79. package/docs/assets/empty.html-1c139131.js +1 -1
  80. package/docs/assets/empty.html-1e9c441d.js +1 -1
  81. package/docs/assets/field-date.html-069fdb13.js +1 -1
  82. package/docs/assets/field-date.html-ad204aa9.js +1 -1
  83. package/docs/assets/field-table.html-ce480f03.js +1 -1
  84. package/docs/assets/field-table.html-d9236160.js +1 -1
  85. package/docs/assets/field-text.html-7277c62f.js +1 -1
  86. package/docs/assets/field-text.html-ccb4cecf.js +1 -1
  87. package/docs/assets/field-tree.html-519bfb45.js +1 -1
  88. package/docs/assets/field-tree.html-fdc748d6.js +1 -1
  89. package/docs/assets/form.html-2b562c37.js +2 -2
  90. package/docs/assets/form.html-75104cd5.js +1 -1
  91. package/docs/assets/framework-204010b2.js +5 -5
  92. package/docs/assets/getData.html-990e3787.js +1 -1
  93. package/docs/assets/getData.html-bb72025f.js +34 -34
  94. package/docs/assets/getFile.html-42368004.js +1 -1
  95. package/docs/assets/getFile.html-99abd054.js +3 -3
  96. package/docs/assets/getImage.html-3429c5a1.js +1 -1
  97. package/docs/assets/getImage.html-4d886d83.js +3 -3
  98. package/docs/assets/getTime.html-7435f922.js +1 -1
  99. package/docs/assets/getTime.html-b37f49eb.js +20 -20
  100. package/docs/assets/img.html-7d1da657.js +1 -1
  101. package/docs/assets/img.html-fbea1105.js +1 -1
  102. package/docs/assets/index.html-1695dd7c.js +1 -1
  103. package/docs/assets/index.html-65a4aa67.js +1 -1
  104. package/docs/assets/index.html-7b98d5bd.js +1 -1
  105. package/docs/assets/index.html-c01f2648.js +1 -1
  106. package/docs/assets/input-number.html-0b250d2a.js +1 -1
  107. package/docs/assets/input-number.html-a8eb0378.js +1 -1
  108. package/docs/assets/list-menu-item.html-7f1b4611.js +1 -1
  109. package/docs/assets/list-menu-item.html-84ed5ab8.js +1 -1
  110. package/docs/assets/list-menu.html-28b4163f.js +1 -1
  111. package/docs/assets/list-menu.html-cb6ba95b.js +1 -1
  112. package/docs/assets/loading.html-dae9e39d.js +6 -6
  113. package/docs/assets/loading.html-dc74c9e6.js +1 -1
  114. package/docs/assets/notify.html-e6c4c514.js +1 -1
  115. package/docs/assets/notify.html-f2c4d914.js +8 -8
  116. package/docs/assets/power-page.html-32e02f82.js +1 -1
  117. package/docs/assets/power-page.html-485e77da.js +1 -1
  118. package/docs/assets/power.html-d258cc19.js +93 -93
  119. package/docs/assets/power.html-e490bd32.js +1 -1
  120. package/docs/assets/previewImage.html-6a6b4245.js +1 -1
  121. package/docs/assets/previewImage.html-c5b7e945.js +2 -2
  122. package/docs/assets/price.html-1882c548.js +19 -19
  123. package/docs/assets/price.html-94d3f5be.js +1 -1
  124. package/docs/assets/price.html-d213df0f.js +1 -1
  125. package/docs/assets/price.html-deaf880f.js +1 -1
  126. package/docs/assets/render.html-8efcbdd4.js +1 -1
  127. package/docs/assets/render.html-df228e38.js +1 -1
  128. package/docs/assets/rule.html-2cd57fc2.js +13 -13
  129. package/docs/assets/rule.html-61662001.js +1 -1
  130. package/docs/assets/ruleValid.html-04fe2552.js +1 -1
  131. package/docs/assets/ruleValid.html-e0a776af.js +14 -14
  132. package/docs/assets/search-0782d0d1.svg +1 -1
  133. package/docs/assets/search-item.html-3f75394c.js +1 -1
  134. package/docs/assets/search-item.html-4e942ecd.js +1 -1
  135. package/docs/assets/search.html-2807043e.js +1 -1
  136. package/docs/assets/search.html-c24f8806.js +1 -1
  137. package/docs/assets/select.html-00d0607c.js +1 -1
  138. package/docs/assets/select.html-de7731f5.js +1 -1
  139. package/docs/assets/splitter.html-56f51a70.js +1 -1
  140. package/docs/assets/splitter.html-f5c836d7.js +1 -1
  141. package/docs/assets/style-161e43ab.css +1 -1
  142. package/docs/assets/symbols.html-a6aea4bf.js +1 -1
  143. package/docs/assets/symbols.html-b1f65bad.js +21 -21
  144. package/docs/assets/table-column-fixed.html-3a69e7b2.js +1 -1
  145. package/docs/assets/table-column-fixed.html-e763c38b.js +1 -1
  146. package/docs/assets/table-pagination.html-236934d3.js +1 -1
  147. package/docs/assets/table-pagination.html-c37ee2ac.js +1 -1
  148. package/docs/assets/table-splitter.html-07eab15c.js +1 -1
  149. package/docs/assets/table-splitter.html-7670ee65.js +1 -1
  150. package/docs/assets/table-summary.html-04db434f.js +1 -1
  151. package/docs/assets/table-summary.html-943c65a0.js +1 -1
  152. package/docs/assets/table.html-36253ad7.js +1 -1
  153. package/docs/assets/table.html-7f9c5d1b.js +38 -38
  154. package/docs/assets/table.html-93d53dc8.js +1 -1
  155. package/docs/assets/table.html-ac99b9cb.js +1 -1
  156. package/docs/assets/thumbnail.html-bab1976b.js +1 -1
  157. package/docs/assets/thumbnail.html-eb64e5e8.js +1 -1
  158. package/docs/assets/timestamp.html-4e54f79b.js +13 -13
  159. package/docs/assets/timestamp.html-d0e1b88a.js +1 -1
  160. package/docs/assets/toast.html-58ecbe21.js +1 -1
  161. package/docs/assets/toast.html-c9b9d36b.js +6 -6
  162. package/docs/assets/toolbar.html-83d9f97c.js +1 -1
  163. package/docs/assets/toolbar.html-ff7b8c92.js +1 -1
  164. package/docs/assets/tree.html-d07cbe79.js +23 -23
  165. package/docs/assets/tree.html-ea04193e.js +1 -1
  166. package/docs/assets/uploader-query.html-05590718.js +1 -1
  167. package/docs/assets/uploader-query.html-3175bac5.js +1 -1
  168. package/docs/assets/uploader.html-36da4394.js +2 -2
  169. package/docs/assets/uploader.html-6b5f3079.js +1 -1
  170. package/docs/assets/uploader.html-b9340b57.js +1 -1
  171. package/docs/assets/uploader.html-bc1c22e3.js +1 -1
  172. package/docs/assets/value-format.html-8ae3d47d.js +1 -1
  173. package/docs/assets/value-format.html-afa99b3d.js +1 -1
  174. package/docs/components/column-title.html +35 -35
  175. package/docs/components/data.html +62 -62
  176. package/docs/components/dialog.html +33 -33
  177. package/docs/components/dragger.html +33 -33
  178. package/docs/components/editor-code.html +33 -33
  179. package/docs/components/empty.html +33 -33
  180. package/docs/components/field-date.html +33 -33
  181. package/docs/components/field-table.html +33 -33
  182. package/docs/components/field-text.html +33 -33
  183. package/docs/components/field-tree.html +33 -33
  184. package/docs/components/img.html +33 -33
  185. package/docs/components/input-number.html +33 -33
  186. package/docs/components/list-menu-item.html +33 -33
  187. package/docs/components/list-menu.html +33 -33
  188. package/docs/components/power-page.html +33 -33
  189. package/docs/components/price.html +33 -33
  190. package/docs/components/render.html +33 -33
  191. package/docs/components/search-item.html +33 -33
  192. package/docs/components/search.html +33 -33
  193. package/docs/components/select.html +33 -33
  194. package/docs/components/splitter.html +33 -33
  195. package/docs/components/table-column-fixed.html +33 -33
  196. package/docs/components/table-pagination.html +33 -33
  197. package/docs/components/table-splitter.html +33 -33
  198. package/docs/components/table-summary.html +33 -33
  199. package/docs/components/table.html +33 -33
  200. package/docs/components/thumbnail.html +33 -33
  201. package/docs/components/toolbar.html +33 -33
  202. package/docs/components/uploader-query.html +33 -33
  203. package/docs/components/uploader.html +33 -33
  204. package/docs/components/value-format.html +33 -33
  205. package/docs/css/index.css +3 -3
  206. package/docs/index.html +33 -33
  207. package/docs/utils/alert.html +37 -37
  208. package/docs/utils/area.html +74 -74
  209. package/docs/utils/arr.html +43 -43
  210. package/docs/utils/auth.html +40 -40
  211. package/docs/utils/bus.html +38 -38
  212. package/docs/utils/confirm.html +42 -42
  213. package/docs/utils/copy.html +45 -45
  214. package/docs/utils/dialog.html +100 -100
  215. package/docs/utils/dict.html +55 -55
  216. package/docs/utils/dictOptions.html +37 -37
  217. package/docs/utils/form.html +34 -34
  218. package/docs/utils/getData.html +66 -66
  219. package/docs/utils/getFile.html +35 -35
  220. package/docs/utils/getImage.html +35 -35
  221. package/docs/utils/getTime.html +52 -52
  222. package/docs/utils/index.html +33 -33
  223. package/docs/utils/loading.html +38 -38
  224. package/docs/utils/notify.html +40 -40
  225. package/docs/utils/power.html +125 -125
  226. package/docs/utils/previewImage.html +34 -34
  227. package/docs/utils/price.html +51 -51
  228. package/docs/utils/rule.html +45 -45
  229. package/docs/utils/ruleValid.html +46 -46
  230. package/docs/utils/symbols.html +53 -53
  231. package/docs/utils/table.html +70 -70
  232. package/docs/utils/timestamp.html +45 -45
  233. package/docs/utils/toast.html +38 -38
  234. package/docs/utils/tree.html +55 -55
  235. package/docs/utils/uploader.html +34 -34
  236. package/package.json +25 -25
  237. package/sass/common.scss +184 -184
  238. package/sass/index.scss +12 -12
  239. package/sass/line.scss +39 -39
  240. package/sass/quasar/btn.scss +46 -46
  241. package/sass/quasar/common.scss +3 -3
  242. package/sass/quasar/drawer.scss +6 -6
  243. package/sass/quasar/field.scss +259 -259
  244. package/sass/quasar/loading.scss +6 -6
  245. package/sass/quasar/table.scss +168 -168
  246. package/sass/quasar/toolbar.scss +22 -22
  247. package/sass/variables.scss +140 -140
  248. package/store/index.js +29 -29
  249. package/utils/$auth.js +127 -127
  250. package/utils/$form.js +72 -72
  251. package/utils/$power.js +1486 -1486
  252. package/utils/$render.js +75 -75
  253. package/utils/$rule.js +13 -13
  254. package/utils/$ruleValid.js +10 -10
  255. package/utils/$search.js +416 -416
  256. package/utils/$table.js +1275 -1275
  257. package/utils/alert.js +12 -12
  258. package/utils/area.js +400 -400
  259. package/utils/arr.js +51 -51
  260. package/utils/bus.js +6 -6
  261. package/utils/config.js +64 -64
  262. package/utils/confirm.js +11 -11
  263. package/utils/copy.js +30 -30
  264. package/utils/dialog.js +36 -36
  265. package/utils/dict.js +21 -21
  266. package/utils/dictOptions.js +28 -28
  267. package/utils/getData.js +88 -88
  268. package/utils/getFile.js +67 -67
  269. package/utils/getImage.js +276 -276
  270. package/utils/getTime.js +113 -113
  271. package/utils/index.js +67 -67
  272. package/utils/loading.js +15 -15
  273. package/utils/notify.js +13 -13
  274. package/utils/play.js +40 -40
  275. package/utils/previewImage.js +14 -14
  276. package/utils/price.js +18 -18
  277. package/utils/symbols.js +18 -18
  278. package/utils/timestamp.js +18 -18
  279. package/utils/toast.js +13 -13
  280. package/utils/uploader.js +2114 -2114
  281. package/utils/useAuth.js +30 -30
  282. package/utils/useFileUrl.js +26 -26
  283. package/utils/useRouter.js +47 -47
  284. package/utils/useSearch.js +499 -499
@@ -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>