shared-ritm 1.2.53 → 1.2.54

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 (73) hide show
  1. package/dist/index.css +1 -1
  2. package/dist/shared-ritm.es.js +4771 -4778
  3. package/dist/shared-ritm.umd.js +7 -7
  4. package/package.json +1 -1
  5. package/src/App.vue +2461 -2461
  6. package/src/api/services/AuthService.ts +58 -58
  7. package/src/api/services/ControlsService.ts +64 -64
  8. package/src/api/services/FileService.ts +15 -15
  9. package/src/api/services/TasksService.ts +137 -137
  10. package/src/api/settings/ApiService.ts +128 -128
  11. package/src/api/types/Api_Controls.ts +72 -72
  12. package/src/common/app-button/AppButton.vue +173 -173
  13. package/src/common/app-date-picker/AppDatePicker.vue +81 -81
  14. package/src/common/app-icon/AppIcon.vue +108 -108
  15. package/src/common/app-input/AppInput.vue +147 -147
  16. package/src/common/app-input-search/AppInputSearch.vue +174 -174
  17. package/src/common/app-layout/AppLayout.vue +84 -84
  18. package/src/common/app-layout/components/AppLayoutHeader.vue +246 -246
  19. package/src/common/app-layout/components/AppLayoutPage.vue +16 -16
  20. package/src/common/app-loader/index.vue +43 -43
  21. package/src/common/app-page-layout/AppPageLayout.vue +122 -122
  22. package/src/common/app-sidebar/AppSidebar.vue +168 -168
  23. package/src/common/app-sidebar/components/SidebarMenu.vue +37 -37
  24. package/src/common/app-table/AppTable.vue +2 -2
  25. package/src/common/app-table/AppTableLayout.vue +24 -24
  26. package/src/common/app-table/components/ModalSelect.vue +264 -264
  27. package/src/common/app-table/components/TableModal.vue +357 -357
  28. package/src/common/app-table/controllers/useBaseTable.ts +42 -42
  29. package/src/global.d.ts +1 -1
  30. package/src/icons/components/arrow-down-icon.vue +25 -25
  31. package/src/icons/components/arrow-frame-icon.vue +19 -19
  32. package/src/icons/components/arrow-square.vue +22 -22
  33. package/src/icons/header/NotificationIcon.vue +18 -18
  34. package/src/icons/header/PersonIcon.vue +11 -11
  35. package/src/icons/header/SettingIcon.vue +14 -14
  36. package/src/icons/header/flashIcon.vue +24 -24
  37. package/src/icons/header/searchStatusIcon.vue +24 -24
  38. package/src/icons/header/smallCapsIcon.vue +34 -34
  39. package/src/icons/sidebar/assign-module-icon.vue +36 -36
  40. package/src/icons/sidebar/instrument-history-icon.vue +32 -32
  41. package/src/icons/sidebar/instrument-order-icon.vue +38 -38
  42. package/src/icons/sidebar/instrument-work-zone-icon.vue +18 -18
  43. package/src/icons/sidebar/instruments-icon.vue +45 -45
  44. package/src/icons/sidebar/logo-icon.vue +15 -15
  45. package/src/icons/sidebar/logout-icon.vue +13 -13
  46. package/src/icons/sidebar/modules-icon.vue +16 -16
  47. package/src/icons/sidebar/notifications-icon.vue +24 -24
  48. package/src/icons/sidebar/order-icon.vue +44 -44
  49. package/src/icons/sidebar/pass-icon.vue +38 -38
  50. package/src/icons/sidebar/positions-icon.vue +42 -42
  51. package/src/icons/sidebar/preorder-icon.vue +19 -19
  52. package/src/icons/sidebar/projects-icon.vue +31 -31
  53. package/src/icons/sidebar/repair-object-icon.vue +18 -18
  54. package/src/icons/sidebar/repairs-icon.vue +20 -20
  55. package/src/icons/sidebar/roles-icon.vue +26 -26
  56. package/src/icons/sidebar/status-history-icon.vue +24 -24
  57. package/src/icons/sidebar/tasks-icon.vue +28 -28
  58. package/src/icons/sidebar/tasks_tasks-icon.vue +39 -39
  59. package/src/icons/sidebar/tasks_today-icon.vue +27 -27
  60. package/src/icons/sidebar/teams-icon.vue +32 -32
  61. package/src/icons/sidebar/user-icon.vue +18 -18
  62. package/src/icons/sidebar/users-icon.vue +46 -46
  63. package/src/icons/sidebar/videosources-icon.vue +19 -19
  64. package/src/icons/sidebar/videowall-icon.vue +13 -13
  65. package/src/icons/sidebar/videozones-icon.vue +21 -21
  66. package/src/icons/sidebar/warehouses-icon.vue +43 -43
  67. package/src/icons/sidebar/workshop-icon.vue +100 -100
  68. package/src/icons/sidebar/workzones-icon.vue +22 -22
  69. package/src/index.ts +84 -84
  70. package/src/main.ts +28 -28
  71. package/src/quasar-user-options.ts +17 -17
  72. package/src/router/index.ts +10 -10
  73. package/src/shims-vue.d.ts +5 -5
@@ -1,357 +1,357 @@
1
- <script setup lang="ts">
2
- import { ref, watch, defineProps, defineEmits, nextTick, computed } from 'vue'
3
- import AppModalSelect from '../components/ModalSelect.vue'
4
- import { useQuasar } from 'quasar'
5
- import { notificationSettings } from '@/utils/notification'
6
-
7
- const $q = useQuasar()
8
-
9
- type ModalMode = 'view' | 'edit' | 'create'
10
- type FieldType = 'text' | 'select'
11
-
12
- interface FieldOption {
13
- label: string
14
- value: string
15
- }
16
-
17
- interface FieldSchema {
18
- key: string
19
- label: string
20
- type: FieldType
21
- rules?: ((val: any) => boolean | string)[]
22
- options?: FieldOption[]
23
- placeholder?: string
24
- onSearch?: (val: string) => void
25
- onScroll?: () => void
26
- loading?: boolean
27
- }
28
-
29
- const props = defineProps<{
30
- modelValue: boolean
31
- title: string
32
- mode: ModalMode
33
- fields: FieldSchema[]
34
- initialData?: Record<string, any>
35
- }>()
36
-
37
- const emit = defineEmits<{
38
- (e: 'update:modelValue', val: boolean): void
39
- (e: 'submit', data: Record<string, any>): void
40
- (e: 'edit'): void
41
- (e: 'delete'): void
42
- }>()
43
-
44
- const formData = ref<Record<string, any>>({})
45
- const formRef = ref()
46
-
47
- watch(
48
- () => props.modelValue,
49
- val => {
50
- if (val) {
51
- formData.value = { ...(props.initialData ?? {}) }
52
- }
53
- },
54
- { immediate: true },
55
- )
56
- function isEqual(a: any, b: any): boolean {
57
- if (Array.isArray(a) && Array.isArray(b)) {
58
- if (a.length !== b.length) return false
59
- return a.every((item, i) => isEqual(item, b[i]))
60
- }
61
- if (typeof a === 'object' && typeof b === 'object') {
62
- return JSON.stringify(a) === JSON.stringify(b)
63
- }
64
- return a === b
65
- }
66
-
67
- function normalizeValue(val: any): any {
68
- if (Array.isArray(val)) {
69
- return val.map(v => (typeof v === 'object' && v !== null ? v.value ?? v : v))
70
- }
71
- return typeof val === 'object' && val !== null ? val.value ?? val : val
72
- }
73
-
74
- function submit() {
75
- formRef.value?.validate().then(ok => {
76
- if (!ok) return
77
-
78
- const changed: Record<string, any> = {}
79
-
80
- for (const field of props.fields) {
81
- const key = field.key
82
- const current = formData.value[key]
83
- const initial = props.initialData?.[key]
84
-
85
- const normalizedCurrent = field.type === 'select' ? normalizeValue(current) : current
86
- const normalizedInitial = field.type === 'select' ? normalizeValue(initial) : initial
87
-
88
- if (!isEqual(normalizedCurrent, normalizedInitial)) {
89
- changed[key] = normalizedCurrent
90
- }
91
- }
92
-
93
- emit('submit', changed)
94
- })
95
- }
96
-
97
- function handleClear(key: string) {
98
- const field = props.fields.find(f => f.key === key)
99
- formData.value[key] = field?.type === 'select' ? [] : ''
100
-
101
- nextTick(() => {
102
- formRef.value?.validate()
103
- })
104
- }
105
- const isSubmitDisabled = computed(() => {
106
- if (props.mode === 'view') return false
107
-
108
- const hasEmptyRequired = props.fields.some(field => {
109
- const isRequired = field.rules?.some(rule => rule('') !== true)
110
- const val = formData.value[field.key]
111
- const normalized = normalizeValue(val)
112
-
113
- const empty =
114
- normalized === null ||
115
- normalized === undefined ||
116
- (typeof normalized === 'string' && normalized.trim() === '') ||
117
- (Array.isArray(normalized) && normalized.length === 0)
118
-
119
- return isRequired && empty
120
- })
121
-
122
- if (hasEmptyRequired) return true
123
-
124
- const hasChanges = props.fields.some(field => {
125
- const key = field.key
126
- const current = normalizeValue(formData.value[key])
127
- const initial = normalizeValue(props.initialData?.[key])
128
- return !isEqual(current, initial)
129
- })
130
-
131
- return !hasChanges
132
- })
133
- function uuidv4() {
134
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
135
- const r = (Math.random() * 16) | 0
136
- const v = c === 'x' ? r : (r & 0x3) | 0x8
137
- return v.toString(16)
138
- })
139
- }
140
-
141
- function generateUuid() {
142
- formData.value.uuid = uuidv4()
143
- }
144
- function copyToClipboard(text: string) {
145
- navigator.clipboard.writeText(text).then(() => {
146
- $q.notify(notificationSettings('success', 'UUID скопирован'))
147
- })
148
- }
149
- const filteredOptions = ref<Record<string, FieldOption[]>>({})
150
- </script>
151
-
152
- <template>
153
- <q-dialog :model-value="modelValue" @update:model-value="val => emit('update:modelValue', val)">
154
- <q-card style="min-width: 700px">
155
- <q-card-section>
156
- <div class="modal-title">{{ title }}</div>
157
- </q-card-section>
158
-
159
- <q-card-section>
160
- <q-form ref="formRef" @submit.prevent="submit">
161
- <div v-for="field in fields" :key="field.key" class="field-wrapper">
162
- <label v-if="field.type === 'text'" class="field-label">
163
- {{ field.label }}
164
- <span v-if="field.rules?.length && mode !== 'view'" class="required">*</span>
165
- </label>
166
-
167
- <q-input
168
- v-if="field.type === 'text'"
169
- v-model="formData[field.key]"
170
- :rules="field.rules"
171
- :readonly="mode === 'view' || (field.key === 'uuid' && mode === 'edit')"
172
- filled
173
- :placeholder="field.placeholder"
174
- >
175
- <template #append>
176
- <q-icon
177
- v-if="mode !== 'view' && formData[field.key] && !(field.key === 'uuid' && mode === 'edit')"
178
- name="close"
179
- class="cursor-pointer clear-input"
180
- @click="() => handleClear(field.key)"
181
- />
182
- <q-btn
183
- v-if="field.key === 'uuid' && mode === 'create'"
184
- flat
185
- no-caps
186
- label="UUID"
187
- size="sm"
188
- class="q-ml-sm uuid-btn"
189
- @click="generateUuid"
190
- />
191
- <q-icon
192
- v-else-if="field.key === 'uuid' && mode !== 'create'"
193
- name="content_copy"
194
- class="cursor-pointer q-ml-sm copy-icon"
195
- color="primary"
196
- @click="copyToClipboard(formData[field.key])"
197
- />
198
- </template>
199
- </q-input>
200
-
201
- <app-modal-select
202
- v-else-if="field.type === 'select'"
203
- v-model="formData[field.key]"
204
- :options="filteredOptions[field.key] || field.options"
205
- :rules="field.rules"
206
- :placeholder="mode === 'view' ? '' : field.placeholder"
207
- :multiple="true"
208
- :show-chip="true"
209
- :is-disabled="mode === 'view'"
210
- :loading="field.loading"
211
- :label="field.label"
212
- :is-show-required="mode !== 'view'"
213
- empty-text="Ничего не найдено"
214
- option-label="label"
215
- option-value="value"
216
- chip-color="#e9eff9"
217
- @update:search="val => field.onSearch?.(val)"
218
- @update:scroll="() => field.onScroll?.()"
219
- @clear="
220
- () => {
221
- handleClear(field.key)
222
- nextTick(() => formRef.value?.validate())
223
- }
224
- "
225
- />
226
- </div>
227
- </q-form>
228
- </q-card-section>
229
-
230
- <q-card-actions align="center">
231
- <q-btn v-if="mode === 'view'" class="remove" flat label="Удалить" @click="emit('delete')" />
232
- <q-btn
233
- v-if="mode !== 'view'"
234
- class="confirm"
235
- flat
236
- :label="mode === 'edit' ? 'Сохранить' : 'Создать'"
237
- :disable="isSubmitDisabled"
238
- @click="submit"
239
- />
240
- <q-btn v-else class="confirm" flat label="Редактировать" @click="$emit('edit')" />
241
- <q-btn v-close-popup class="cancel" flat label="Закрыть" />
242
- </q-card-actions>
243
- </q-card>
244
- </q-dialog>
245
- </template>
246
- <style lang="scss">
247
- .custom-select-menu {
248
- max-height: 250px !important;
249
- overflow-y: auto !important;
250
- }
251
- </style>
252
- <style scoped lang="scss">
253
- .uuid-btn {
254
- height: 32px;
255
- padding: 0 10px;
256
- border: 1px solid #3f8cff;
257
- color: #3f8cff;
258
- font-weight: 700;
259
- font-size: 14px;
260
- background: white;
261
- border-radius: 6px;
262
- }
263
-
264
- .q-card {
265
- border-radius: 12px;
266
- background: #fff;
267
- box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.25);
268
- font-family: NunitoSansFont, sans-serif;
269
-
270
- .modal-title {
271
- color: #1d425d;
272
- text-align: center;
273
- font-size: 32px;
274
- font-weight: 700;
275
- padding: 18px 29px;
276
- }
277
-
278
- .q-card__section {
279
- padding: 0;
280
- }
281
-
282
- .q-form {
283
- padding: 0 29px;
284
- }
285
-
286
- .field-wrapper {
287
- display: flex;
288
- flex-direction: column;
289
- margin-bottom: 15px;
290
- }
291
-
292
- .field-label {
293
- font-size: 14px;
294
- font-weight: 700;
295
- color: #7d8592;
296
- }
297
- ::v-deep(.q-placeholder) {
298
- color: #7d8592;
299
- }
300
- ::v-deep(.q-field__control) {
301
- border-radius: 8px;
302
- border: 1px solid #d8e0f0;
303
- background: #fff;
304
- box-shadow: 0px 1px 2px 0px rgba(184, 200, 224, 0.22);
305
- }
306
-
307
- ::v-deep(.q-field--filled .q-field__control:before) {
308
- background: #fff !important;
309
- border: none;
310
- }
311
-
312
- ::v-deep(.q-field--with-bottom) {
313
- padding-bottom: 0;
314
- }
315
-
316
- ::v-deep(.q-field__bottom) {
317
- padding: 0;
318
- }
319
-
320
- .clear-input {
321
- color: #d8e0f0;
322
- }
323
-
324
- .required {
325
- color: #f65160;
326
- font-weight: bold;
327
- }
328
-
329
- &__actions {
330
- padding: 18px 0;
331
- border-radius: 0px 0px 16px 16px;
332
- background: #f4f9fd;
333
-
334
- button {
335
- padding: 13px 37px;
336
- border-radius: 4px;
337
- font-size: 16px;
338
- font-weight: 700;
339
- text-transform: none;
340
-
341
- &.remove {
342
- border: 1px solid #f65160;
343
- color: #f65160;
344
- }
345
- &.confirm {
346
- background: #3f8cff;
347
- color: #fff;
348
- }
349
-
350
- &.cancel {
351
- color: #3f8cff;
352
- border: 1px solid #3f8cff;
353
- }
354
- }
355
- }
356
- }
357
- </style>
1
+ <script setup lang="ts">
2
+ import { ref, watch, defineProps, defineEmits, nextTick, computed } from 'vue'
3
+ import AppModalSelect from '../components/ModalSelect.vue'
4
+ import { useQuasar } from 'quasar'
5
+ import { notificationSettings } from '@/utils/notification'
6
+
7
+ const $q = useQuasar()
8
+
9
+ type ModalMode = 'view' | 'edit' | 'create'
10
+ type FieldType = 'text' | 'select'
11
+
12
+ interface FieldOption {
13
+ label: string
14
+ value: string
15
+ }
16
+
17
+ interface FieldSchema {
18
+ key: string
19
+ label: string
20
+ type: FieldType
21
+ rules?: ((val: any) => boolean | string)[]
22
+ options?: FieldOption[]
23
+ placeholder?: string
24
+ onSearch?: (val: string) => void
25
+ onScroll?: () => void
26
+ loading?: boolean
27
+ }
28
+
29
+ const props = defineProps<{
30
+ modelValue: boolean
31
+ title: string
32
+ mode: ModalMode
33
+ fields: FieldSchema[]
34
+ initialData?: Record<string, any>
35
+ }>()
36
+
37
+ const emit = defineEmits<{
38
+ (e: 'update:modelValue', val: boolean): void
39
+ (e: 'submit', data: Record<string, any>): void
40
+ (e: 'edit'): void
41
+ (e: 'delete'): void
42
+ }>()
43
+
44
+ const formData = ref<Record<string, any>>({})
45
+ const formRef = ref()
46
+
47
+ watch(
48
+ () => props.modelValue,
49
+ val => {
50
+ if (val) {
51
+ formData.value = { ...(props.initialData ?? {}) }
52
+ }
53
+ },
54
+ { immediate: true },
55
+ )
56
+ function isEqual(a: any, b: any): boolean {
57
+ if (Array.isArray(a) && Array.isArray(b)) {
58
+ if (a.length !== b.length) return false
59
+ return a.every((item, i) => isEqual(item, b[i]))
60
+ }
61
+ if (typeof a === 'object' && typeof b === 'object') {
62
+ return JSON.stringify(a) === JSON.stringify(b)
63
+ }
64
+ return a === b
65
+ }
66
+
67
+ function normalizeValue(val: any): any {
68
+ if (Array.isArray(val)) {
69
+ return val.map(v => (typeof v === 'object' && v !== null ? v.value ?? v : v))
70
+ }
71
+ return typeof val === 'object' && val !== null ? val.value ?? val : val
72
+ }
73
+
74
+ function submit() {
75
+ formRef.value?.validate().then(ok => {
76
+ if (!ok) return
77
+
78
+ const changed: Record<string, any> = {}
79
+
80
+ for (const field of props.fields) {
81
+ const key = field.key
82
+ const current = formData.value[key]
83
+ const initial = props.initialData?.[key]
84
+
85
+ const normalizedCurrent = field.type === 'select' ? normalizeValue(current) : current
86
+ const normalizedInitial = field.type === 'select' ? normalizeValue(initial) : initial
87
+
88
+ if (!isEqual(normalizedCurrent, normalizedInitial)) {
89
+ changed[key] = normalizedCurrent
90
+ }
91
+ }
92
+
93
+ emit('submit', changed)
94
+ })
95
+ }
96
+
97
+ function handleClear(key: string) {
98
+ const field = props.fields.find(f => f.key === key)
99
+ formData.value[key] = field?.type === 'select' ? [] : ''
100
+
101
+ nextTick(() => {
102
+ formRef.value?.validate()
103
+ })
104
+ }
105
+ const isSubmitDisabled = computed(() => {
106
+ if (props.mode === 'view') return false
107
+
108
+ const hasEmptyRequired = props.fields.some(field => {
109
+ const isRequired = field.rules?.some(rule => rule('') !== true)
110
+ const val = formData.value[field.key]
111
+ const normalized = normalizeValue(val)
112
+
113
+ const empty =
114
+ normalized === null ||
115
+ normalized === undefined ||
116
+ (typeof normalized === 'string' && normalized.trim() === '') ||
117
+ (Array.isArray(normalized) && normalized.length === 0)
118
+
119
+ return isRequired && empty
120
+ })
121
+
122
+ if (hasEmptyRequired) return true
123
+
124
+ const hasChanges = props.fields.some(field => {
125
+ const key = field.key
126
+ const current = normalizeValue(formData.value[key])
127
+ const initial = normalizeValue(props.initialData?.[key])
128
+ return !isEqual(current, initial)
129
+ })
130
+
131
+ return !hasChanges
132
+ })
133
+ function uuidv4() {
134
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
135
+ const r = (Math.random() * 16) | 0
136
+ const v = c === 'x' ? r : (r & 0x3) | 0x8
137
+ return v.toString(16)
138
+ })
139
+ }
140
+
141
+ function generateUuid() {
142
+ formData.value.uuid = uuidv4()
143
+ }
144
+ function copyToClipboard(text: string) {
145
+ navigator.clipboard.writeText(text).then(() => {
146
+ $q.notify(notificationSettings('success', 'UUID скопирован'))
147
+ })
148
+ }
149
+ const filteredOptions = ref<Record<string, FieldOption[]>>({})
150
+ </script>
151
+
152
+ <template>
153
+ <q-dialog :model-value="modelValue" @update:model-value="val => emit('update:modelValue', val)">
154
+ <q-card style="min-width: 700px">
155
+ <q-card-section>
156
+ <div class="modal-title">{{ title }}</div>
157
+ </q-card-section>
158
+
159
+ <q-card-section>
160
+ <q-form ref="formRef" @submit.prevent="submit">
161
+ <div v-for="field in fields" :key="field.key" class="field-wrapper">
162
+ <label v-if="field.type === 'text'" class="field-label">
163
+ {{ field.label }}
164
+ <span v-if="field.rules?.length && mode !== 'view'" class="required">*</span>
165
+ </label>
166
+
167
+ <q-input
168
+ v-if="field.type === 'text'"
169
+ v-model="formData[field.key]"
170
+ :rules="field.rules"
171
+ :readonly="mode === 'view' || (field.key === 'uuid' && mode === 'edit')"
172
+ filled
173
+ :placeholder="field.placeholder"
174
+ >
175
+ <template #append>
176
+ <q-icon
177
+ v-if="mode !== 'view' && formData[field.key] && !(field.key === 'uuid' && mode === 'edit')"
178
+ name="close"
179
+ class="cursor-pointer clear-input"
180
+ @click="() => handleClear(field.key)"
181
+ />
182
+ <q-btn
183
+ v-if="field.key === 'uuid' && mode === 'create'"
184
+ flat
185
+ no-caps
186
+ label="UUID"
187
+ size="sm"
188
+ class="q-ml-sm uuid-btn"
189
+ @click="generateUuid"
190
+ />
191
+ <q-icon
192
+ v-else-if="field.key === 'uuid' && mode !== 'create'"
193
+ name="content_copy"
194
+ class="cursor-pointer q-ml-sm copy-icon"
195
+ color="primary"
196
+ @click="copyToClipboard(formData[field.key])"
197
+ />
198
+ </template>
199
+ </q-input>
200
+
201
+ <app-modal-select
202
+ v-else-if="field.type === 'select'"
203
+ v-model="formData[field.key]"
204
+ :options="filteredOptions[field.key] || field.options"
205
+ :rules="field.rules"
206
+ :placeholder="mode === 'view' ? '' : field.placeholder"
207
+ :multiple="true"
208
+ :show-chip="true"
209
+ :is-disabled="mode === 'view'"
210
+ :loading="field.loading"
211
+ :label="field.label"
212
+ :is-show-required="mode !== 'view'"
213
+ empty-text="Ничего не найдено"
214
+ option-label="label"
215
+ option-value="value"
216
+ chip-color="#e9eff9"
217
+ @update:search="val => field.onSearch?.(val)"
218
+ @update:scroll="() => field.onScroll?.()"
219
+ @clear="
220
+ () => {
221
+ handleClear(field.key)
222
+ nextTick(() => formRef.value?.validate())
223
+ }
224
+ "
225
+ />
226
+ </div>
227
+ </q-form>
228
+ </q-card-section>
229
+
230
+ <q-card-actions align="center">
231
+ <q-btn v-if="mode === 'view'" class="remove" flat label="Удалить" @click="emit('delete')" />
232
+ <q-btn
233
+ v-if="mode !== 'view'"
234
+ class="confirm"
235
+ flat
236
+ :label="mode === 'edit' ? 'Сохранить' : 'Создать'"
237
+ :disable="isSubmitDisabled"
238
+ @click="submit"
239
+ />
240
+ <q-btn v-else class="confirm" flat label="Редактировать" @click="$emit('edit')" />
241
+ <q-btn v-close-popup class="cancel" flat label="Закрыть" />
242
+ </q-card-actions>
243
+ </q-card>
244
+ </q-dialog>
245
+ </template>
246
+ <style lang="scss">
247
+ .custom-select-menu {
248
+ max-height: 250px !important;
249
+ overflow-y: auto !important;
250
+ }
251
+ </style>
252
+ <style scoped lang="scss">
253
+ .uuid-btn {
254
+ height: 32px;
255
+ padding: 0 10px;
256
+ border: 1px solid #3f8cff;
257
+ color: #3f8cff;
258
+ font-weight: 700;
259
+ font-size: 14px;
260
+ background: white;
261
+ border-radius: 6px;
262
+ }
263
+
264
+ .q-card {
265
+ border-radius: 12px;
266
+ background: #fff;
267
+ box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.25);
268
+ font-family: NunitoSansFont, sans-serif;
269
+
270
+ .modal-title {
271
+ color: #1d425d;
272
+ text-align: center;
273
+ font-size: 32px;
274
+ font-weight: 700;
275
+ padding: 18px 29px;
276
+ }
277
+
278
+ .q-card__section {
279
+ padding: 0;
280
+ }
281
+
282
+ .q-form {
283
+ padding: 0 29px;
284
+ }
285
+
286
+ .field-wrapper {
287
+ display: flex;
288
+ flex-direction: column;
289
+ margin-bottom: 15px;
290
+ }
291
+
292
+ .field-label {
293
+ font-size: 14px;
294
+ font-weight: 700;
295
+ color: #7d8592;
296
+ }
297
+ ::v-deep(.q-placeholder) {
298
+ color: #7d8592;
299
+ }
300
+ ::v-deep(.q-field__control) {
301
+ border-radius: 8px;
302
+ border: 1px solid #d8e0f0;
303
+ background: #fff;
304
+ box-shadow: 0px 1px 2px 0px rgba(184, 200, 224, 0.22);
305
+ }
306
+
307
+ ::v-deep(.q-field--filled .q-field__control:before) {
308
+ background: #fff !important;
309
+ border: none;
310
+ }
311
+
312
+ ::v-deep(.q-field--with-bottom) {
313
+ padding-bottom: 0;
314
+ }
315
+
316
+ ::v-deep(.q-field__bottom) {
317
+ padding: 0;
318
+ }
319
+
320
+ .clear-input {
321
+ color: #d8e0f0;
322
+ }
323
+
324
+ .required {
325
+ color: #f65160;
326
+ font-weight: bold;
327
+ }
328
+
329
+ &__actions {
330
+ padding: 18px 0;
331
+ border-radius: 0px 0px 16px 16px;
332
+ background: #f4f9fd;
333
+
334
+ button {
335
+ padding: 13px 37px;
336
+ border-radius: 4px;
337
+ font-size: 16px;
338
+ font-weight: 700;
339
+ text-transform: none;
340
+
341
+ &.remove {
342
+ border: 1px solid #f65160;
343
+ color: #f65160;
344
+ }
345
+ &.confirm {
346
+ background: #3f8cff;
347
+ color: #fff;
348
+ }
349
+
350
+ &.cancel {
351
+ color: #3f8cff;
352
+ border: 1px solid #3f8cff;
353
+ }
354
+ }
355
+ }
356
+ }
357
+ </style>