@netang/quasar 0.2.4 → 0.2.6

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 (248) 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/dialog/img-viewer/index.vue +657 -657
  8. package/components/dialog/index.vue +373 -373
  9. package/components/drawer/index.vue +303 -303
  10. package/components/editor-code/index.vue +325 -325
  11. package/components/empty/index.vue +80 -80
  12. package/components/field-date/index.vue +850 -850
  13. package/components/field-table/index.vue +33 -11
  14. package/components/field-tree/index.vue +754 -754
  15. package/components/img/index.vue +239 -239
  16. package/components/input-number/index.vue +547 -547
  17. package/components/mixed-table/index.vue +532 -532
  18. package/components/mixed-table-splitter/index.vue +377 -377
  19. package/components/power-page/index.vue +94 -94
  20. package/components/private/components/move-to-tree/index.vue +154 -154
  21. package/components/private/edit-power-data/index.vue +846 -846
  22. package/components/private/table-visible-columns-button/index.vue +114 -114
  23. package/components/render/index.vue +123 -123
  24. package/components/search/index.vue +231 -231
  25. package/components/search-item/index.vue +210 -210
  26. package/components/select/index.vue +177 -177
  27. package/components/splitter/index.vue +422 -422
  28. package/components/table/index.vue +513 -513
  29. package/components/table-column-fixed/index.vue +110 -110
  30. package/components/table-summary/index.vue +107 -107
  31. package/components/toolbar/index.vue +146 -146
  32. package/components/tree/index.vue +1728 -1728
  33. package/components/uploader/index.vue +190 -190
  34. package/components/uploader-query/index.vue +928 -928
  35. package/docs/404.html +33 -33
  36. package/docs/assets/404.html-60b35caa.js +1 -1
  37. package/docs/assets/404.html-d1e63d77.js +1 -1
  38. package/docs/assets/alert.html-b2a2a72f.js +5 -5
  39. package/docs/assets/alert.html-ba46d137.js +1 -1
  40. package/docs/assets/app-9f30aa4b.js +6 -6
  41. package/docs/assets/area.html-01b9b58d.js +42 -42
  42. package/docs/assets/area.html-9a4fce6a.js +1 -1
  43. package/docs/assets/arr.html-145d27e7.js +1 -1
  44. package/docs/assets/arr.html-674e65ab.js +11 -11
  45. package/docs/assets/auth.html-579fa830.js +1 -1
  46. package/docs/assets/auth.html-8544ed95.js +8 -8
  47. package/docs/assets/bus.html-c71254aa.js +1 -1
  48. package/docs/assets/bus.html-dc7d3d19.js +6 -6
  49. package/docs/assets/column-title.html-c735cb5a.js +3 -3
  50. package/docs/assets/column-title.html-e9316762.js +1 -1
  51. package/docs/assets/confirm.html-ddfdc27f.js +10 -10
  52. package/docs/assets/confirm.html-ef3e2bef.js +1 -1
  53. package/docs/assets/copy.html-d20345b6.js +1 -1
  54. package/docs/assets/copy.html-ef8c8571.js +13 -13
  55. package/docs/assets/data.html-6432175d.js +30 -30
  56. package/docs/assets/data.html-a3b05d5b.js +1 -1
  57. package/docs/assets/dialog.html-1f698e5a.js +1 -1
  58. package/docs/assets/dialog.html-62902b83.js +68 -68
  59. package/docs/assets/dialog.html-baea77c9.js +1 -1
  60. package/docs/assets/dialog.html-bb082fc4.js +1 -1
  61. package/docs/assets/dict.html-1311da3d.js +23 -23
  62. package/docs/assets/dict.html-b96fbf0c.js +1 -1
  63. package/docs/assets/dictOptions.html-7c4f40a5.js +1 -1
  64. package/docs/assets/dictOptions.html-fb99d175.js +5 -5
  65. package/docs/assets/dragger.html-668d3efa.js +1 -1
  66. package/docs/assets/dragger.html-749d585a.js +1 -1
  67. package/docs/assets/editor-code.html-6ab26ea9.js +1 -1
  68. package/docs/assets/editor-code.html-d196205d.js +1 -1
  69. package/docs/assets/empty.html-1c139131.js +1 -1
  70. package/docs/assets/empty.html-1e9c441d.js +1 -1
  71. package/docs/assets/field-date.html-069fdb13.js +1 -1
  72. package/docs/assets/field-date.html-ad204aa9.js +1 -1
  73. package/docs/assets/field-table.html-ce480f03.js +1 -1
  74. package/docs/assets/field-table.html-d9236160.js +1 -1
  75. package/docs/assets/field-text.html-7277c62f.js +1 -1
  76. package/docs/assets/field-text.html-ccb4cecf.js +1 -1
  77. package/docs/assets/field-tree.html-519bfb45.js +1 -1
  78. package/docs/assets/field-tree.html-fdc748d6.js +1 -1
  79. package/docs/assets/form.html-2b562c37.js +2 -2
  80. package/docs/assets/form.html-75104cd5.js +1 -1
  81. package/docs/assets/framework-204010b2.js +5 -5
  82. package/docs/assets/getData.html-990e3787.js +1 -1
  83. package/docs/assets/getData.html-bb72025f.js +34 -34
  84. package/docs/assets/getFile.html-42368004.js +1 -1
  85. package/docs/assets/getFile.html-99abd054.js +3 -3
  86. package/docs/assets/getImage.html-3429c5a1.js +1 -1
  87. package/docs/assets/getImage.html-4d886d83.js +3 -3
  88. package/docs/assets/getTime.html-7435f922.js +1 -1
  89. package/docs/assets/getTime.html-b37f49eb.js +20 -20
  90. package/docs/assets/img.html-7d1da657.js +1 -1
  91. package/docs/assets/img.html-fbea1105.js +1 -1
  92. package/docs/assets/index.html-1695dd7c.js +1 -1
  93. package/docs/assets/index.html-65a4aa67.js +1 -1
  94. package/docs/assets/index.html-7b98d5bd.js +1 -1
  95. package/docs/assets/index.html-c01f2648.js +1 -1
  96. package/docs/assets/input-number.html-0b250d2a.js +1 -1
  97. package/docs/assets/input-number.html-a8eb0378.js +1 -1
  98. package/docs/assets/list-menu-item.html-7f1b4611.js +1 -1
  99. package/docs/assets/list-menu-item.html-84ed5ab8.js +1 -1
  100. package/docs/assets/list-menu.html-28b4163f.js +1 -1
  101. package/docs/assets/list-menu.html-cb6ba95b.js +1 -1
  102. package/docs/assets/loading.html-dae9e39d.js +6 -6
  103. package/docs/assets/loading.html-dc74c9e6.js +1 -1
  104. package/docs/assets/notify.html-e6c4c514.js +1 -1
  105. package/docs/assets/notify.html-f2c4d914.js +8 -8
  106. package/docs/assets/power-page.html-32e02f82.js +1 -1
  107. package/docs/assets/power-page.html-485e77da.js +1 -1
  108. package/docs/assets/power.html-d258cc19.js +93 -93
  109. package/docs/assets/power.html-e490bd32.js +1 -1
  110. package/docs/assets/previewImage.html-6a6b4245.js +1 -1
  111. package/docs/assets/previewImage.html-c5b7e945.js +2 -2
  112. package/docs/assets/price.html-1882c548.js +19 -19
  113. package/docs/assets/price.html-94d3f5be.js +1 -1
  114. package/docs/assets/price.html-d213df0f.js +1 -1
  115. package/docs/assets/price.html-deaf880f.js +1 -1
  116. package/docs/assets/render.html-8efcbdd4.js +1 -1
  117. package/docs/assets/render.html-df228e38.js +1 -1
  118. package/docs/assets/rule.html-2cd57fc2.js +13 -13
  119. package/docs/assets/rule.html-61662001.js +1 -1
  120. package/docs/assets/ruleValid.html-04fe2552.js +1 -1
  121. package/docs/assets/ruleValid.html-e0a776af.js +14 -14
  122. package/docs/assets/search-0782d0d1.svg +1 -1
  123. package/docs/assets/search-item.html-3f75394c.js +1 -1
  124. package/docs/assets/search-item.html-4e942ecd.js +1 -1
  125. package/docs/assets/search.html-2807043e.js +1 -1
  126. package/docs/assets/search.html-c24f8806.js +1 -1
  127. package/docs/assets/select.html-00d0607c.js +1 -1
  128. package/docs/assets/select.html-de7731f5.js +1 -1
  129. package/docs/assets/splitter.html-56f51a70.js +1 -1
  130. package/docs/assets/splitter.html-f5c836d7.js +1 -1
  131. package/docs/assets/style-161e43ab.css +1 -1
  132. package/docs/assets/symbols.html-a6aea4bf.js +1 -1
  133. package/docs/assets/symbols.html-b1f65bad.js +21 -21
  134. package/docs/assets/table-column-fixed.html-3a69e7b2.js +1 -1
  135. package/docs/assets/table-column-fixed.html-e763c38b.js +1 -1
  136. package/docs/assets/table-pagination.html-236934d3.js +1 -1
  137. package/docs/assets/table-pagination.html-c37ee2ac.js +1 -1
  138. package/docs/assets/table-splitter.html-07eab15c.js +1 -1
  139. package/docs/assets/table-splitter.html-7670ee65.js +1 -1
  140. package/docs/assets/table-summary.html-04db434f.js +1 -1
  141. package/docs/assets/table-summary.html-943c65a0.js +1 -1
  142. package/docs/assets/table.html-36253ad7.js +1 -1
  143. package/docs/assets/table.html-7f9c5d1b.js +38 -38
  144. package/docs/assets/table.html-93d53dc8.js +1 -1
  145. package/docs/assets/table.html-ac99b9cb.js +1 -1
  146. package/docs/assets/thumbnail.html-bab1976b.js +1 -1
  147. package/docs/assets/thumbnail.html-eb64e5e8.js +1 -1
  148. package/docs/assets/timestamp.html-4e54f79b.js +13 -13
  149. package/docs/assets/timestamp.html-d0e1b88a.js +1 -1
  150. package/docs/assets/toast.html-58ecbe21.js +1 -1
  151. package/docs/assets/toast.html-c9b9d36b.js +6 -6
  152. package/docs/assets/toolbar.html-83d9f97c.js +1 -1
  153. package/docs/assets/toolbar.html-ff7b8c92.js +1 -1
  154. package/docs/assets/tree.html-d07cbe79.js +23 -23
  155. package/docs/assets/tree.html-ea04193e.js +1 -1
  156. package/docs/assets/uploader-query.html-05590718.js +1 -1
  157. package/docs/assets/uploader-query.html-3175bac5.js +1 -1
  158. package/docs/assets/uploader.html-36da4394.js +2 -2
  159. package/docs/assets/uploader.html-6b5f3079.js +1 -1
  160. package/docs/assets/uploader.html-b9340b57.js +1 -1
  161. package/docs/assets/uploader.html-bc1c22e3.js +1 -1
  162. package/docs/assets/value-format.html-8ae3d47d.js +1 -1
  163. package/docs/assets/value-format.html-afa99b3d.js +1 -1
  164. package/docs/components/column-title.html +35 -35
  165. package/docs/components/data.html +62 -62
  166. package/docs/components/dialog.html +33 -33
  167. package/docs/components/dragger.html +33 -33
  168. package/docs/components/editor-code.html +33 -33
  169. package/docs/components/empty.html +33 -33
  170. package/docs/components/field-date.html +33 -33
  171. package/docs/components/field-table.html +33 -33
  172. package/docs/components/field-text.html +33 -33
  173. package/docs/components/field-tree.html +33 -33
  174. package/docs/components/img.html +33 -33
  175. package/docs/components/input-number.html +33 -33
  176. package/docs/components/list-menu-item.html +33 -33
  177. package/docs/components/list-menu.html +33 -33
  178. package/docs/components/power-page.html +33 -33
  179. package/docs/components/price.html +33 -33
  180. package/docs/components/render.html +33 -33
  181. package/docs/components/search-item.html +33 -33
  182. package/docs/components/search.html +33 -33
  183. package/docs/components/select.html +33 -33
  184. package/docs/components/splitter.html +33 -33
  185. package/docs/components/table-column-fixed.html +33 -33
  186. package/docs/components/table-pagination.html +33 -33
  187. package/docs/components/table-splitter.html +33 -33
  188. package/docs/components/table-summary.html +33 -33
  189. package/docs/components/table.html +33 -33
  190. package/docs/components/thumbnail.html +33 -33
  191. package/docs/components/toolbar.html +33 -33
  192. package/docs/components/uploader-query.html +33 -33
  193. package/docs/components/uploader.html +33 -33
  194. package/docs/components/value-format.html +33 -33
  195. package/docs/index.html +33 -33
  196. package/docs/utils/alert.html +37 -37
  197. package/docs/utils/area.html +74 -74
  198. package/docs/utils/arr.html +43 -43
  199. package/docs/utils/auth.html +40 -40
  200. package/docs/utils/bus.html +38 -38
  201. package/docs/utils/confirm.html +42 -42
  202. package/docs/utils/copy.html +45 -45
  203. package/docs/utils/dialog.html +100 -100
  204. package/docs/utils/dict.html +55 -55
  205. package/docs/utils/dictOptions.html +37 -37
  206. package/docs/utils/form.html +34 -34
  207. package/docs/utils/getData.html +66 -66
  208. package/docs/utils/getFile.html +35 -35
  209. package/docs/utils/getImage.html +35 -35
  210. package/docs/utils/getTime.html +52 -52
  211. package/docs/utils/index.html +33 -33
  212. package/docs/utils/loading.html +38 -38
  213. package/docs/utils/notify.html +40 -40
  214. package/docs/utils/power.html +125 -125
  215. package/docs/utils/previewImage.html +34 -34
  216. package/docs/utils/price.html +51 -51
  217. package/docs/utils/rule.html +45 -45
  218. package/docs/utils/ruleValid.html +46 -46
  219. package/docs/utils/symbols.html +53 -53
  220. package/docs/utils/table.html +70 -70
  221. package/docs/utils/timestamp.html +45 -45
  222. package/docs/utils/toast.html +38 -38
  223. package/docs/utils/tree.html +55 -55
  224. package/docs/utils/uploader.html +34 -34
  225. package/package.json +2 -1
  226. package/sass/common.scss +184 -184
  227. package/sass/index.scss +12 -12
  228. package/sass/quasar/field.scss +250 -250
  229. package/sass/quasar/table.scss +168 -168
  230. package/sass/variables.scss +140 -140
  231. package/utils/$form.js +72 -72
  232. package/utils/$power.js +1464 -1460
  233. package/utils/$render.js +75 -75
  234. package/utils/$search.js +416 -416
  235. package/utils/$table.js +1275 -1275
  236. package/utils/config.js +52 -52
  237. package/utils/dialog.js +36 -36
  238. package/utils/dict.js +21 -21
  239. package/utils/getData.js +88 -88
  240. package/utils/getFile.js +62 -62
  241. package/utils/getImage.js +227 -227
  242. package/utils/getTime.js +113 -113
  243. package/utils/index.js +65 -65
  244. package/utils/previewImage.js +14 -14
  245. package/utils/timestamp.js +18 -18
  246. package/utils/useFileUrl.js +26 -26
  247. package/utils/useSearch.js +499 -499
  248. package/utils/useUploader.js +303 -303
@@ -1,657 +1,657 @@
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
- <a
107
- v-for="(src, i) in currentImages"
108
- :key="`${src}-${i}`"
109
- :href="src"
110
- target="_blank"
111
- class="non-selectable no-outline"
112
- >
113
- <img
114
- :ref="(el) => (imgRefs[i] = el)"
115
- :src="src"
116
- :style="imgStyle"
117
- @load="handleImgLoad"
118
- @error="handleImgError"
119
- v-show="i === activeIndex"
120
- />
121
- </a>
122
-
123
- </div>
124
- </q-dialog>
125
- </template>
126
-
127
- <script>
128
- import { computed, nextTick, onMounted, ref, watch } from 'vue'
129
- import { useDialogPluginComponent } from 'quasar'
130
-
131
- import $n_forEach from '@netang/utils/forEach'
132
-
133
- import $n_getImage from '../../../utils/getImage'
134
-
135
- export default {
136
-
137
- /**
138
- * 标识
139
- */
140
- name: 'NDialog',
141
-
142
- /**
143
- * 声明属性
144
- */
145
- props: {
146
- // 值
147
- modelValue: {
148
- type: Boolean,
149
- default: true,
150
- },
151
- noBackdropDismiss: Boolean,
152
-
153
- // 需要预览的图片 URL 数组
154
- images: {
155
- type: Array,
156
- default: () => [],
157
- },
158
- // 图片预览起始位置索引
159
- startPosition: {
160
- type: Number,
161
- default: 0,
162
- },
163
- infinite: {
164
- type: Boolean,
165
- default: true,
166
- },
167
- zoomRate: {
168
- type: Number,
169
- default: 1.2,
170
- },
171
- // 关闭图标
172
- closeIcon: {
173
- type: String,
174
- default: 'close',
175
- },
176
- // 上一张图标
177
- prevIcon: {
178
- type: String,
179
- default: 'arrow_back_ios_new',
180
- },
181
- // 下一张图标
182
- nextIcon: {
183
- type: String,
184
- default: 'arrow_forward_ios',
185
- },
186
- // 缩小图标
187
- zoomOutIcon: {
188
- type: String,
189
- default: 'zoom_out',
190
- },
191
- // 放大图标
192
- zoomInIcon: {
193
- type: String,
194
- default: 'zoom_in',
195
- },
196
- // 全屏图标
197
- fullscreenIcon: {
198
- type: String,
199
- default: 'fullscreen',
200
- },
201
- // 退出全屏图标
202
- exitFullscreenIcon: {
203
- type: String,
204
- default: 'fullscreen_exit',
205
- },
206
- // 水平反转图标
207
- flipHorizontalIcon: {
208
- type: String,
209
- default: 'swap_horiz',
210
- },
211
- // 垂直反转图标
212
- flipVerticalIcon: {
213
- type: String,
214
- default: 'swap_vert',
215
- },
216
- // 左旋转图标
217
- rotateLeftIcon: {
218
- type: String,
219
- default: 'rotate_left',
220
- },
221
- // 右旋转图标
222
- rotateRightIcon: {
223
- type: String,
224
- default: 'rotate_right',
225
- },
226
- },
227
-
228
- /**
229
- * 声明事件
230
- */
231
- emits: [
232
- 'update:modelValue',
233
- 'change',
234
- ...useDialogPluginComponent.emits
235
- ],
236
-
237
- /**
238
- * 组合式
239
- */
240
- setup(props, { emit }) {
241
-
242
- // ==========【数据】============================================================================================
243
-
244
- // 当前值
245
- const currentModelValue = ref(props.modelValue)
246
-
247
- // 目标节点
248
- const targetRef = ref()
249
-
250
- // 图片节点数组
251
- const imgRefs = ref([])
252
-
253
- // 加载中
254
- const loading = ref(true)
255
-
256
- // 当前激活索引
257
- const activeIndex = ref(props.startPosition)
258
-
259
- // 模式
260
- const isContain = ref(true)
261
-
262
- // 转换效果
263
- const transform = ref({
264
- scale: 1,
265
- deg: 0,
266
- rotateX: 1,
267
- rotateY: 1,
268
- offsetX: 0,
269
- offsetY: 0,
270
- enableTransition: false,
271
- })
272
-
273
- // ==========【计算属性】==========================================================================================
274
-
275
- /**
276
- * 当前图片数组
277
- */
278
- const currentImages = computed(function () {
279
-
280
- const lists = []
281
-
282
- $n_forEach(props.images, function (url) {
283
- const origin = $n_getImage(url, { compress: false })
284
- if (origin) {
285
- lists.push($n_getImage(url, { w: 1000 }))
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
- function onMask() {
517
- if (! props.noBackdropDismiss) {
518
- onDialogCancel()
519
- }
520
- }
521
-
522
- // ==========【声明周期】=========================================================================================
523
-
524
- /**
525
- * 实例被挂载后调用
526
- */
527
- onMounted(function() {
528
- targetRef.value?.focus?.()
529
- })
530
-
531
- // ==========【返回】=============================================================================================
532
-
533
- return {
534
- currentModelValue,
535
- // 对话框节点
536
- dialogRef,
537
- // 对话框取消
538
- onDialogCancel,
539
- // 对话框隐藏
540
- onDialogHide,
541
-
542
- // 目标节点
543
- targetRef,
544
- // 图片节点数组
545
- imgRefs,
546
- // 加载中
547
- loading,
548
- // 当前激活索引
549
- activeIndex,
550
- // 是否包含
551
- isContain,
552
- // 转换效果
553
- transform,
554
-
555
- // 当前图片数组
556
- currentImages,
557
- // 是否单图
558
- isSingle,
559
- // 是否第一张
560
- isFirst,
561
- // 是否最后一张
562
- isLast,
563
- // 当前图片
564
- currentImg,
565
- // 图片样式
566
- imgStyle,
567
-
568
- // 图片加载完成
569
- handleImgLoad,
570
- // 图片加载错误
571
- handleImgError,
572
- // 重置
573
- reset,
574
- // 切换模式
575
- toggleMode,
576
- // 设置激活
577
- setActiveItem,
578
- // 前一张
579
- prev,
580
- // 后一张
581
- next,
582
- // 操作
583
- handleActions,
584
- // 点击遮蔽
585
- onMask,
586
- }
587
- }
588
- }
589
- </script>
590
-
591
- <style lang="scss">
592
- .n-img-viewer {
593
-
594
- .q-dialog__inner > div {
595
- display: flex;
596
- justify-content: center;
597
- align-items: center;
598
- }
599
-
600
- // 按钮
601
- &__btn {
602
- position: fixed !important;
603
- opacity: 0.8;
604
- color: #ffffff !important;
605
- background: #606266 !important;
606
- user-select: none;
607
- z-index: 1;
608
-
609
- // 关闭按钮
610
- &--close {
611
- top: 40px;
612
- right: 40px;
613
- width: 40px;
614
- height: 40px;
615
- }
616
-
617
- // 上一张按钮
618
- &--prev {
619
- top: 50%;
620
- left: 40px;
621
- width: 40px;
622
- height: 40px;
623
- }
624
-
625
- // 下一张按钮
626
- &--next {
627
- top: 50%;
628
- right: 40px;
629
- width: 40px;
630
- height: 40px;
631
- }
632
- }
633
-
634
- // 操作面板
635
- &__settings {
636
- left: 50%;
637
- bottom: 30px;
638
- transform: translateX(-50%);
639
- width: 282px;
640
- height: 44px;
641
- padding: 0 23px;
642
- border-radius: 22px;
643
-
644
- &__inner {
645
- width: 100%;
646
- height: 100%;
647
- text-align: justify;
648
- cursor: default;
649
- font-size: 23px;
650
- color: #ffffff;
651
- display: flex;
652
- align-items: center;
653
- justify-content: space-around;
654
- }
655
- }
656
- }
657
- </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
+ <a
107
+ v-for="(src, i) in currentImages"
108
+ :key="`${src}-${i}`"
109
+ :href="src"
110
+ target="_blank"
111
+ class="non-selectable no-outline"
112
+ >
113
+ <img
114
+ :ref="(el) => (imgRefs[i] = el)"
115
+ :src="src"
116
+ :style="imgStyle"
117
+ @load="handleImgLoad"
118
+ @error="handleImgError"
119
+ v-show="i === activeIndex"
120
+ />
121
+ </a>
122
+
123
+ </div>
124
+ </q-dialog>
125
+ </template>
126
+
127
+ <script>
128
+ import { computed, nextTick, onMounted, ref, watch } from 'vue'
129
+ import { useDialogPluginComponent } from 'quasar'
130
+
131
+ import $n_forEach from '@netang/utils/forEach'
132
+
133
+ import $n_getImage from '../../../utils/getImage'
134
+
135
+ export default {
136
+
137
+ /**
138
+ * 标识
139
+ */
140
+ name: 'NDialog',
141
+
142
+ /**
143
+ * 声明属性
144
+ */
145
+ props: {
146
+ // 值
147
+ modelValue: {
148
+ type: Boolean,
149
+ default: true,
150
+ },
151
+ noBackdropDismiss: Boolean,
152
+
153
+ // 需要预览的图片 URL 数组
154
+ images: {
155
+ type: Array,
156
+ default: () => [],
157
+ },
158
+ // 图片预览起始位置索引
159
+ startPosition: {
160
+ type: Number,
161
+ default: 0,
162
+ },
163
+ infinite: {
164
+ type: Boolean,
165
+ default: true,
166
+ },
167
+ zoomRate: {
168
+ type: Number,
169
+ default: 1.2,
170
+ },
171
+ // 关闭图标
172
+ closeIcon: {
173
+ type: String,
174
+ default: 'close',
175
+ },
176
+ // 上一张图标
177
+ prevIcon: {
178
+ type: String,
179
+ default: 'arrow_back_ios_new',
180
+ },
181
+ // 下一张图标
182
+ nextIcon: {
183
+ type: String,
184
+ default: 'arrow_forward_ios',
185
+ },
186
+ // 缩小图标
187
+ zoomOutIcon: {
188
+ type: String,
189
+ default: 'zoom_out',
190
+ },
191
+ // 放大图标
192
+ zoomInIcon: {
193
+ type: String,
194
+ default: 'zoom_in',
195
+ },
196
+ // 全屏图标
197
+ fullscreenIcon: {
198
+ type: String,
199
+ default: 'fullscreen',
200
+ },
201
+ // 退出全屏图标
202
+ exitFullscreenIcon: {
203
+ type: String,
204
+ default: 'fullscreen_exit',
205
+ },
206
+ // 水平反转图标
207
+ flipHorizontalIcon: {
208
+ type: String,
209
+ default: 'swap_horiz',
210
+ },
211
+ // 垂直反转图标
212
+ flipVerticalIcon: {
213
+ type: String,
214
+ default: 'swap_vert',
215
+ },
216
+ // 左旋转图标
217
+ rotateLeftIcon: {
218
+ type: String,
219
+ default: 'rotate_left',
220
+ },
221
+ // 右旋转图标
222
+ rotateRightIcon: {
223
+ type: String,
224
+ default: 'rotate_right',
225
+ },
226
+ },
227
+
228
+ /**
229
+ * 声明事件
230
+ */
231
+ emits: [
232
+ 'update:modelValue',
233
+ 'change',
234
+ ...useDialogPluginComponent.emits
235
+ ],
236
+
237
+ /**
238
+ * 组合式
239
+ */
240
+ setup(props, { emit }) {
241
+
242
+ // ==========【数据】============================================================================================
243
+
244
+ // 当前值
245
+ const currentModelValue = ref(props.modelValue)
246
+
247
+ // 目标节点
248
+ const targetRef = ref()
249
+
250
+ // 图片节点数组
251
+ const imgRefs = ref([])
252
+
253
+ // 加载中
254
+ const loading = ref(true)
255
+
256
+ // 当前激活索引
257
+ const activeIndex = ref(props.startPosition)
258
+
259
+ // 模式
260
+ const isContain = ref(true)
261
+
262
+ // 转换效果
263
+ const transform = ref({
264
+ scale: 1,
265
+ deg: 0,
266
+ rotateX: 1,
267
+ rotateY: 1,
268
+ offsetX: 0,
269
+ offsetY: 0,
270
+ enableTransition: false,
271
+ })
272
+
273
+ // ==========【计算属性】==========================================================================================
274
+
275
+ /**
276
+ * 当前图片数组
277
+ */
278
+ const currentImages = computed(function () {
279
+
280
+ const lists = []
281
+
282
+ $n_forEach(props.images, function (url) {
283
+ const origin = $n_getImage(url, { compress: false })
284
+ if (origin) {
285
+ lists.push($n_getImage(url, { w: 1000 }))
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
+ function onMask() {
517
+ if (! props.noBackdropDismiss) {
518
+ onDialogCancel()
519
+ }
520
+ }
521
+
522
+ // ==========【声明周期】=========================================================================================
523
+
524
+ /**
525
+ * 实例被挂载后调用
526
+ */
527
+ onMounted(function() {
528
+ targetRef.value?.focus?.()
529
+ })
530
+
531
+ // ==========【返回】=============================================================================================
532
+
533
+ return {
534
+ currentModelValue,
535
+ // 对话框节点
536
+ dialogRef,
537
+ // 对话框取消
538
+ onDialogCancel,
539
+ // 对话框隐藏
540
+ onDialogHide,
541
+
542
+ // 目标节点
543
+ targetRef,
544
+ // 图片节点数组
545
+ imgRefs,
546
+ // 加载中
547
+ loading,
548
+ // 当前激活索引
549
+ activeIndex,
550
+ // 是否包含
551
+ isContain,
552
+ // 转换效果
553
+ transform,
554
+
555
+ // 当前图片数组
556
+ currentImages,
557
+ // 是否单图
558
+ isSingle,
559
+ // 是否第一张
560
+ isFirst,
561
+ // 是否最后一张
562
+ isLast,
563
+ // 当前图片
564
+ currentImg,
565
+ // 图片样式
566
+ imgStyle,
567
+
568
+ // 图片加载完成
569
+ handleImgLoad,
570
+ // 图片加载错误
571
+ handleImgError,
572
+ // 重置
573
+ reset,
574
+ // 切换模式
575
+ toggleMode,
576
+ // 设置激活
577
+ setActiveItem,
578
+ // 前一张
579
+ prev,
580
+ // 后一张
581
+ next,
582
+ // 操作
583
+ handleActions,
584
+ // 点击遮蔽
585
+ onMask,
586
+ }
587
+ }
588
+ }
589
+ </script>
590
+
591
+ <style lang="scss">
592
+ .n-img-viewer {
593
+
594
+ .q-dialog__inner > div {
595
+ display: flex;
596
+ justify-content: center;
597
+ align-items: center;
598
+ }
599
+
600
+ // 按钮
601
+ &__btn {
602
+ position: fixed !important;
603
+ opacity: 0.8;
604
+ color: #ffffff !important;
605
+ background: #606266 !important;
606
+ user-select: none;
607
+ z-index: 1;
608
+
609
+ // 关闭按钮
610
+ &--close {
611
+ top: 40px;
612
+ right: 40px;
613
+ width: 40px;
614
+ height: 40px;
615
+ }
616
+
617
+ // 上一张按钮
618
+ &--prev {
619
+ top: 50%;
620
+ left: 40px;
621
+ width: 40px;
622
+ height: 40px;
623
+ }
624
+
625
+ // 下一张按钮
626
+ &--next {
627
+ top: 50%;
628
+ right: 40px;
629
+ width: 40px;
630
+ height: 40px;
631
+ }
632
+ }
633
+
634
+ // 操作面板
635
+ &__settings {
636
+ left: 50%;
637
+ bottom: 30px;
638
+ transform: translateX(-50%);
639
+ width: 282px;
640
+ height: 44px;
641
+ padding: 0 23px;
642
+ border-radius: 22px;
643
+
644
+ &__inner {
645
+ width: 100%;
646
+ height: 100%;
647
+ text-align: justify;
648
+ cursor: default;
649
+ font-size: 23px;
650
+ color: #ffffff;
651
+ display: flex;
652
+ align-items: center;
653
+ justify-content: space-around;
654
+ }
655
+ }
656
+ }
657
+ </style>