@netang/quasar 0.1.35 → 0.1.37

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