shared-ritm 1.2.70 → 1.2.72
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.
- package/dist/index.css +1 -1
- package/dist/shared-ritm.es.js +9431 -8815
- package/dist/shared-ritm.umd.js +233 -233
- package/dist/types/api/services/RepairsService.d.ts +6 -1
- package/dist/types/api/types/Api_Repairs.d.ts +20 -4
- package/dist/types/index.d.ts +2 -1
- package/package.json +1 -1
- package/src/api/services/RepairsService.ts +18 -0
- package/src/api/types/Api_Repairs.ts +22 -4
- package/src/common/app-datepicker/AppDatepicker.vue +165 -0
- package/src/common/app-input-new/AppInputNew.vue +35 -10
- package/src/common/app-table/AppTable.vue +67 -20
- package/src/common/app-table/components/ModalSelect.vue +4 -1
- package/src/common/app-toggle/AppToggle.vue +3 -2
- package/src/index.ts +2 -0
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import ApiService from '@/api/settings/ApiService';
|
|
2
2
|
import { ResponseApi } from '@/api/types/Api_Service';
|
|
3
|
-
import { Api_Create_Repair_With_Equipments, Api_Equipment_Full_Dto, Api_Repair_Dto, Api_Update_Repair, OptionFilters } from '@/api/types/Api_Repairs';
|
|
3
|
+
import { Api_Create_Repair_With_Equipments, Api_Create_Repair_With_Template, Api_Equipment_Full_Dto, Api_Repair_Dto, Api_Repair_Template, Api_Update_Repair, OptionFilters } from '@/api/types/Api_Repairs';
|
|
4
4
|
declare class RepairsService extends ApiService {
|
|
5
5
|
fetchFilters(fullParams: string): Promise<OptionFilters>;
|
|
6
6
|
fetchRepairs(isQuery: boolean, queries?: string, hasTeams?: boolean | string, teamsFilter?: string, typeFilter?: string): Promise<ResponseApi<Api_Repair_Dto[]>>;
|
|
7
|
+
fetchRepairTemplates({ equipmentId, categoryCode, }: {
|
|
8
|
+
equipmentId?: string;
|
|
9
|
+
categoryCode?: string;
|
|
10
|
+
}): Promise<ResponseApi<Api_Repair_Template[]>>;
|
|
7
11
|
fetchEquipment(): Promise<ResponseApi<Api_Equipment_Full_Dto[]>>;
|
|
8
12
|
createRepair(payload: Api_Create_Repair_With_Equipments): Promise<any>;
|
|
13
|
+
createRepairFromTemplate(payload: Api_Create_Repair_With_Template): Promise<any>;
|
|
9
14
|
startRepair(id: string): Promise<void>;
|
|
10
15
|
finishRepair(id: string): Promise<any>;
|
|
11
16
|
finishPreparationProject(id: string): Promise<any>;
|
|
@@ -62,21 +62,26 @@ export type Api_Task_Video_Source_Stream = {
|
|
|
62
62
|
export type Api_Create_Repair_With_Equipments = {
|
|
63
63
|
name: string;
|
|
64
64
|
display_name: string;
|
|
65
|
-
description
|
|
65
|
+
description?: string;
|
|
66
66
|
equipment_id: string;
|
|
67
67
|
power_output_MWh?: number;
|
|
68
68
|
cost_per_MWh?: number;
|
|
69
|
-
category
|
|
69
|
+
category: number;
|
|
70
70
|
user_id_list?: string[];
|
|
71
71
|
team_id_list?: string[];
|
|
72
72
|
};
|
|
73
|
+
export type Api_Create_Repair_With_Template = Omit<Api_Create_Repair_With_Equipments, 'category' | 'equipment_id'> & {
|
|
74
|
+
repair_template_id: string;
|
|
75
|
+
plan_start_date: string;
|
|
76
|
+
task_id_list: string[];
|
|
77
|
+
};
|
|
73
78
|
export type Api_Update_Repair = {
|
|
74
79
|
name?: string;
|
|
75
80
|
display_name?: string;
|
|
76
|
-
description
|
|
81
|
+
description?: string;
|
|
77
82
|
power_output_MWh?: number;
|
|
78
83
|
cost_per_MWh?: number;
|
|
79
|
-
category?:
|
|
84
|
+
category?: number;
|
|
80
85
|
user_id_list?: string[];
|
|
81
86
|
team_id_list?: string[];
|
|
82
87
|
};
|
|
@@ -90,3 +95,14 @@ export type Api_Repair_Dto = {
|
|
|
90
95
|
projects: Api_Projects[];
|
|
91
96
|
equipments: Api_Equipment_Full_Dto[];
|
|
92
97
|
};
|
|
98
|
+
export type Api_Repair_Template = {
|
|
99
|
+
id: string;
|
|
100
|
+
repair_seconds: number;
|
|
101
|
+
equipment: Pick<Api_Equipment_Full_Dto, 'id' | 'name' | 'registration_number'>;
|
|
102
|
+
category: {
|
|
103
|
+
display_name: string;
|
|
104
|
+
name: string;
|
|
105
|
+
code: number;
|
|
106
|
+
};
|
|
107
|
+
task_list: string;
|
|
108
|
+
};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import '@/shared/styles/general.css';
|
|
|
2
2
|
import AppButton from '@/common/app-button/AppButton.vue';
|
|
3
3
|
import AppCheckbox from '@/common/app-checkbox/AppCheckbox.vue';
|
|
4
4
|
import AppDatePicker from '@/common/app-date-picker/AppDatePicker.vue';
|
|
5
|
+
import AppDatepicker from '@/common/app-datepicker/AppDatepicker.vue';
|
|
5
6
|
import AppInput from '@/common/app-input/AppInput.vue';
|
|
6
7
|
import AppInputNew from '@/common/app-input-new/AppInputNew.vue';
|
|
7
8
|
import AppInputSearch from '@/common/app-input-search/AppInputSearch.vue';
|
|
@@ -36,7 +37,7 @@ import usePhotoService from '@/api/services/PhotoService';
|
|
|
36
37
|
import useInstrumentsService from '@/api/services/InstrumentsService';
|
|
37
38
|
import useControlsService from '@/api/services/ControlsService';
|
|
38
39
|
import useSearchService from '@/api/services/SearchService';
|
|
39
|
-
export { AppButton, AppCheckbox, AppDatePicker, AppInput, AppInputNew, AppInputSearch, AppLayout, AppLayoutHeader, AppLayoutPage, AppLoader, AppSelect, AppSheet, AppSidebar, AppToggle, AppWrapper, AppConfirmDialog, AppDropdown, AppTablePagination, AppTableSearch, AppTableModal, AppTable, AppTableLayout, AppModalSelect, };
|
|
40
|
+
export { AppButton, AppCheckbox, AppDatepicker, AppDatePicker, AppInput, AppInputNew, AppInputSearch, AppLayout, AppLayoutHeader, AppLayoutPage, AppLoader, AppSelect, AppSheet, AppSidebar, AppToggle, AppWrapper, AppConfirmDialog, AppDropdown, AppTablePagination, AppTableSearch, AppTableModal, AppTable, AppTableLayout, AppModalSelect, };
|
|
40
41
|
export { ApiService, useAuthService, useGanttService, useMetricsService, useProjectsService, useRepairsService, useTasksService, useFileService, useControlsService, useVideoService, useUserService, usePhotoService, useInstrumentsService, useSearchService, };
|
|
41
42
|
export { useBaseTable } from './common/app-table/controllers/useBaseTable';
|
|
42
43
|
export { useTableModel } from './common/app-table/controllers/useTableModel';
|
package/package.json
CHANGED
|
@@ -2,8 +2,10 @@ import ApiService from '@/api/settings/ApiService'
|
|
|
2
2
|
import { ResponseApi } from '@/api/types/Api_Service'
|
|
3
3
|
import {
|
|
4
4
|
Api_Create_Repair_With_Equipments,
|
|
5
|
+
Api_Create_Repair_With_Template,
|
|
5
6
|
Api_Equipment_Full_Dto,
|
|
6
7
|
Api_Repair_Dto,
|
|
8
|
+
Api_Repair_Template,
|
|
7
9
|
Api_Update_Repair,
|
|
8
10
|
OptionFilters,
|
|
9
11
|
} from '@/api/types/Api_Repairs'
|
|
@@ -28,6 +30,18 @@ class RepairsService extends ApiService {
|
|
|
28
30
|
)
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
public fetchRepairTemplates({
|
|
34
|
+
equipmentId,
|
|
35
|
+
categoryCode,
|
|
36
|
+
}: {
|
|
37
|
+
equipmentId?: string
|
|
38
|
+
categoryCode?: string
|
|
39
|
+
}): Promise<ResponseApi<Api_Repair_Template[]>> {
|
|
40
|
+
return this.get(
|
|
41
|
+
`repairs/get_repair_template_list?per_page=100000&categoryCodeList[0]=${categoryCode}&equipmentIdList[0]=${equipmentId}`,
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
31
45
|
public fetchEquipment(): Promise<ResponseApi<Api_Equipment_Full_Dto[]>> {
|
|
32
46
|
return this.get('repairs/equipment/list?per_page=100000')
|
|
33
47
|
}
|
|
@@ -36,6 +50,10 @@ class RepairsService extends ApiService {
|
|
|
36
50
|
return this.post<Api_Create_Repair_With_Equipments, any>('/repairs/equipments', payload)
|
|
37
51
|
}
|
|
38
52
|
|
|
53
|
+
public createRepairFromTemplate(payload: Api_Create_Repair_With_Template) {
|
|
54
|
+
return this.post<Api_Create_Repair_With_Template, any>('/repairs/create_repair_from_repair_template', payload)
|
|
55
|
+
}
|
|
56
|
+
|
|
39
57
|
public startRepair(id: string): Promise<void> {
|
|
40
58
|
return this.post<null, void>(`/repairs/${id}/start`, null)
|
|
41
59
|
}
|
|
@@ -65,22 +65,28 @@ export type Api_Task_Video_Source_Stream = {
|
|
|
65
65
|
export type Api_Create_Repair_With_Equipments = {
|
|
66
66
|
name: string
|
|
67
67
|
display_name: string
|
|
68
|
-
description
|
|
68
|
+
description?: string
|
|
69
69
|
equipment_id: string
|
|
70
70
|
power_output_MWh?: number
|
|
71
71
|
cost_per_MWh?: number
|
|
72
|
-
category
|
|
72
|
+
category: number
|
|
73
73
|
user_id_list?: string[]
|
|
74
74
|
team_id_list?: string[]
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
export type Api_Create_Repair_With_Template = Omit<Api_Create_Repair_With_Equipments, 'category' | 'equipment_id'> & {
|
|
78
|
+
repair_template_id: string
|
|
79
|
+
plan_start_date: string
|
|
80
|
+
task_id_list: string[]
|
|
81
|
+
}
|
|
82
|
+
|
|
77
83
|
export type Api_Update_Repair = {
|
|
78
84
|
name?: string
|
|
79
85
|
display_name?: string
|
|
80
|
-
description
|
|
86
|
+
description?: string
|
|
81
87
|
power_output_MWh?: number
|
|
82
88
|
cost_per_MWh?: number
|
|
83
|
-
category?:
|
|
89
|
+
category?: number
|
|
84
90
|
user_id_list?: string[]
|
|
85
91
|
team_id_list?: string[]
|
|
86
92
|
}
|
|
@@ -95,3 +101,15 @@ export type Api_Repair_Dto = {
|
|
|
95
101
|
projects: Api_Projects[]
|
|
96
102
|
equipments: Api_Equipment_Full_Dto[]
|
|
97
103
|
}
|
|
104
|
+
|
|
105
|
+
export type Api_Repair_Template = {
|
|
106
|
+
id: string
|
|
107
|
+
repair_seconds: number
|
|
108
|
+
equipment: Pick<Api_Equipment_Full_Dto, 'id' | 'name' | 'registration_number'>
|
|
109
|
+
category: {
|
|
110
|
+
display_name: string
|
|
111
|
+
name: string
|
|
112
|
+
code: number
|
|
113
|
+
}
|
|
114
|
+
task_list: string
|
|
115
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="datepicker">
|
|
3
|
+
<app-input-new
|
|
4
|
+
v-model="model"
|
|
5
|
+
readonly
|
|
6
|
+
input-class="cursor-pointer"
|
|
7
|
+
:label="label"
|
|
8
|
+
:required="required"
|
|
9
|
+
:rules="rules"
|
|
10
|
+
:error="error"
|
|
11
|
+
:disable="disabled"
|
|
12
|
+
placeholder="Выберите дату"
|
|
13
|
+
>
|
|
14
|
+
<q-popup-proxy v-if="!disabled" class="datepicker__wrapper" @update:model-value="updateError">
|
|
15
|
+
<q-date
|
|
16
|
+
v-model="model"
|
|
17
|
+
:mask="`DD.MM.YYYY ${timeFormat}`"
|
|
18
|
+
:options="disablePastDates"
|
|
19
|
+
@update:model-value="error = false"
|
|
20
|
+
/>
|
|
21
|
+
<q-time
|
|
22
|
+
v-if="time"
|
|
23
|
+
v-model="model"
|
|
24
|
+
:mask="`DD.MM.YYYY ${timeFormat}`"
|
|
25
|
+
format24h
|
|
26
|
+
:hour-options="hourOptions()"
|
|
27
|
+
:minute-options="minuteOptions()"
|
|
28
|
+
/>
|
|
29
|
+
</q-popup-proxy>
|
|
30
|
+
<template #append>
|
|
31
|
+
<q-icon name="event" class="cursor-pointer"></q-icon>
|
|
32
|
+
</template>
|
|
33
|
+
</app-input-new>
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script setup lang="ts">
|
|
38
|
+
import AppInputNew from '@/common/app-input-new/AppInputNew.vue'
|
|
39
|
+
import { ref, withDefaults, defineEmits, defineProps, defineModel } from 'vue'
|
|
40
|
+
|
|
41
|
+
interface Props {
|
|
42
|
+
label: string
|
|
43
|
+
modelValue?: string
|
|
44
|
+
rules?: ((val?: string | number | null) => boolean | string)[]
|
|
45
|
+
disableRuleDates?: string
|
|
46
|
+
time?: boolean
|
|
47
|
+
noPastDates?: boolean
|
|
48
|
+
disabled?: boolean
|
|
49
|
+
required?: boolean
|
|
50
|
+
timeFormat?: string
|
|
51
|
+
}
|
|
52
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
53
|
+
timeFormat: 'HH:mm',
|
|
54
|
+
rules: () => [],
|
|
55
|
+
disableRuleDates: undefined,
|
|
56
|
+
modelValue: undefined,
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
defineEmits(['update:modelValue'])
|
|
60
|
+
|
|
61
|
+
const model = defineModel<string | null | undefined>()
|
|
62
|
+
|
|
63
|
+
const error = ref(false)
|
|
64
|
+
|
|
65
|
+
const updateError = (state: boolean) => {
|
|
66
|
+
if (!error.value && !model.value && !state) {
|
|
67
|
+
error.value = true
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const disablePastDates = (date: string) => {
|
|
72
|
+
if (!props.noPastDates && !props.disableRuleDates) return true
|
|
73
|
+
|
|
74
|
+
const [year, month, day] = date.split('/')
|
|
75
|
+
const currentDate = new Date(Number(year), Number(month) - 1, Number(day))
|
|
76
|
+
|
|
77
|
+
if (props.disableRuleDates) {
|
|
78
|
+
const firstDate = new Date(props.disableRuleDates)
|
|
79
|
+
return currentDate >= firstDate
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const today = new Date()
|
|
83
|
+
const todayDate = new Date(today.getFullYear(), today.getMonth(), today.getDate())
|
|
84
|
+
|
|
85
|
+
return currentDate >= todayDate
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function getSelectedDate() {
|
|
89
|
+
if (!model.value) return null
|
|
90
|
+
|
|
91
|
+
return model.value.toString().substring(0, 10)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function getSelectedHour() {
|
|
95
|
+
if (!model.value) return null
|
|
96
|
+
|
|
97
|
+
const timePart = model.value.toString().split(' ')[1]
|
|
98
|
+
return timePart ? Number(timePart.split(':')[0]) : null
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function hourOptions(): number[] {
|
|
102
|
+
const today = new Date()
|
|
103
|
+
const selectedDate = getSelectedDate()
|
|
104
|
+
const todayStr = today.toISOString().slice(0, 10)
|
|
105
|
+
|
|
106
|
+
if (selectedDate !== todayStr) {
|
|
107
|
+
return Array.from({ length: 24 }, (_, i) => i)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const currentHour = today.getHours()
|
|
111
|
+
return Array.from({ length: 24 - currentHour }, (_, i) => currentHour + i)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function minuteOptions(): number[] {
|
|
115
|
+
const today = new Date()
|
|
116
|
+
const selectedDate = getSelectedDate()
|
|
117
|
+
const todayStr = today.toISOString().slice(0, 10)
|
|
118
|
+
const selectedHour = getSelectedHour()
|
|
119
|
+
|
|
120
|
+
if (selectedDate !== todayStr) {
|
|
121
|
+
return Array.from({ length: 60 }, (_, i) => i)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (selectedHour === today.getHours()) {
|
|
125
|
+
const currentMinutes = today.getMinutes()
|
|
126
|
+
return Array.from({ length: 60 - currentMinutes }, (_, i) => currentMinutes + i)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return Array.from({ length: 60 }, (_, i) => i)
|
|
130
|
+
}
|
|
131
|
+
</script>
|
|
132
|
+
|
|
133
|
+
<style scoped lang="scss">
|
|
134
|
+
.datepicker {
|
|
135
|
+
:deep(input),
|
|
136
|
+
:deep(.q-field--readonly.q-field--float .q-field__native) {
|
|
137
|
+
cursor: pointer;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
&__label {
|
|
141
|
+
font-size: 14px;
|
|
142
|
+
font-weight: 700;
|
|
143
|
+
color: #7d8592;
|
|
144
|
+
|
|
145
|
+
.required {
|
|
146
|
+
color: #f65160;
|
|
147
|
+
font-weight: bold;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
</style>
|
|
152
|
+
|
|
153
|
+
<style lang="scss">
|
|
154
|
+
.datepicker {
|
|
155
|
+
&__wrapper {
|
|
156
|
+
display: flex;
|
|
157
|
+
|
|
158
|
+
.q-time,
|
|
159
|
+
.q-date {
|
|
160
|
+
box-shadow: none;
|
|
161
|
+
border-radius: 0;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
</style>
|
|
@@ -5,10 +5,22 @@
|
|
|
5
5
|
<span v-if="required" class="required">*</span>
|
|
6
6
|
</label>
|
|
7
7
|
|
|
8
|
-
<q-input
|
|
8
|
+
<q-input
|
|
9
|
+
v-model="model"
|
|
10
|
+
filled
|
|
11
|
+
:type="type"
|
|
12
|
+
:rules="rules"
|
|
13
|
+
:placeholder="placeholder"
|
|
14
|
+
:disable="disable"
|
|
15
|
+
:readonly="readonly"
|
|
16
|
+
:class="inputClass"
|
|
17
|
+
:error="error"
|
|
18
|
+
>
|
|
19
|
+
<slot />
|
|
9
20
|
<template #append>
|
|
21
|
+
<slot name="append" />
|
|
10
22
|
<q-icon
|
|
11
|
-
v-if="clearable && model?.length"
|
|
23
|
+
v-if="clearable && String(model)?.length"
|
|
12
24
|
name="close"
|
|
13
25
|
class="cursor-pointer clear-input"
|
|
14
26
|
@click="model = null"
|
|
@@ -28,37 +40,49 @@
|
|
|
28
40
|
</template>
|
|
29
41
|
|
|
30
42
|
<script setup lang="ts">
|
|
31
|
-
import { defineEmits, defineProps,
|
|
43
|
+
import { defineEmits, defineProps, computed } from 'vue'
|
|
32
44
|
import { uuidv4 } from '@/utils/helpers'
|
|
33
45
|
import { notificationSettings } from '@/utils/notification'
|
|
34
46
|
import { QInputProps, useQuasar } from 'quasar'
|
|
35
47
|
|
|
36
|
-
defineProps<
|
|
48
|
+
const props = defineProps<
|
|
37
49
|
QInputProps & {
|
|
38
50
|
modelValue?: string | number | null
|
|
39
51
|
label?: string
|
|
40
52
|
placeholder?: string
|
|
41
53
|
rules?: ((val: string | number | null | undefined) => boolean | string)[]
|
|
54
|
+
inputClass?: string
|
|
42
55
|
required?: boolean
|
|
56
|
+
readonly?: boolean
|
|
43
57
|
disable?: boolean
|
|
44
58
|
uuid?: boolean
|
|
45
59
|
clearable?: boolean
|
|
46
60
|
copyable?: boolean
|
|
61
|
+
error?: boolean
|
|
47
62
|
}
|
|
48
63
|
>()
|
|
49
64
|
|
|
50
|
-
defineEmits<{
|
|
51
|
-
(e: 'update:modelValue', val
|
|
65
|
+
const emit = defineEmits<{
|
|
66
|
+
(e: 'update:modelValue', val?: string | number | null): void
|
|
52
67
|
}>()
|
|
53
68
|
|
|
54
|
-
const model = defineModel<string | null>()
|
|
55
|
-
|
|
56
69
|
const $q = useQuasar()
|
|
57
70
|
|
|
71
|
+
const model = computed({
|
|
72
|
+
get: () => getValue(props.modelValue),
|
|
73
|
+
set: (newValue?: string | number | null) => emit('update:modelValue', getValue(newValue)),
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
const getValue = (value?: string | number | null) => {
|
|
77
|
+
if (props.type === 'number') return value ? +value : value
|
|
78
|
+
|
|
79
|
+
return value
|
|
80
|
+
}
|
|
81
|
+
|
|
58
82
|
const copyToClipboard = () => {
|
|
59
|
-
if (!model.value) return
|
|
83
|
+
if (!model.value && model.value !== 0) return
|
|
60
84
|
|
|
61
|
-
navigator.clipboard.writeText(model.value).then(() => {
|
|
85
|
+
navigator.clipboard.writeText(model.value.toString()).then(() => {
|
|
62
86
|
$q.notify(notificationSettings('success', 'Данные скопированы'))
|
|
63
87
|
})
|
|
64
88
|
}
|
|
@@ -105,6 +129,7 @@ const copyToClipboard = () => {
|
|
|
105
129
|
}
|
|
106
130
|
|
|
107
131
|
:deep(.q-field__control) {
|
|
132
|
+
min-height: 58px;
|
|
108
133
|
border-radius: 8px;
|
|
109
134
|
border: 1px solid #d8e0f0;
|
|
110
135
|
background: #fff;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<q-table
|
|
4
4
|
v-model:selected="selected"
|
|
5
5
|
:rows="rows.value"
|
|
6
|
-
:columns="
|
|
6
|
+
:columns="resCols"
|
|
7
7
|
row-key="id"
|
|
8
8
|
flat
|
|
9
9
|
bordered
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
:rows-per-page-options="[0]"
|
|
13
13
|
:selection="props.enableMultiSelect ? 'multiple' : 'none'"
|
|
14
14
|
style="height: 100%"
|
|
15
|
-
@row-click="
|
|
15
|
+
@row-click="rowClick"
|
|
16
16
|
>
|
|
17
17
|
<template #header-selection="scope">
|
|
18
18
|
<q-toggle v-model="scope.selected" />
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
<q-toggle v-model="scope.selected" />
|
|
23
23
|
</template>
|
|
24
24
|
|
|
25
|
-
<template #body-cell-index="
|
|
26
|
-
<q-td :props="
|
|
27
|
-
{{
|
|
25
|
+
<template #body-cell-index="cellProps">
|
|
26
|
+
<q-td :props="cellProps" class="text-center" :class="{ 'q-td--no-hover': noHover }">
|
|
27
|
+
{{ cellProps.rowIndex + 1 + (meta.value.currentPage - 1) * meta.value.perPage }}
|
|
28
28
|
</q-td>
|
|
29
29
|
</template>
|
|
30
30
|
|
|
31
|
-
<template v-for="col in
|
|
32
|
-
<q-th :props="propsSlot" :class="{ 'cursor-pointer': col.filterType }">
|
|
31
|
+
<template v-for="col in resCols" :key="col.name" #[`header-cell-${col.name}`]="propsSlot">
|
|
32
|
+
<q-th :props="propsSlot" :class="{ 'cursor-pointer': col.filterType, actions: col.name === 'actions' }">
|
|
33
33
|
<div
|
|
34
34
|
v-if="col.filterType"
|
|
35
35
|
class="row items-center no-wrap"
|
|
@@ -90,26 +90,35 @@
|
|
|
90
90
|
</q-th>
|
|
91
91
|
</template>
|
|
92
92
|
|
|
93
|
-
<template #body-cell="
|
|
94
|
-
<q-td
|
|
93
|
+
<template #body-cell="cellProps">
|
|
94
|
+
<q-td
|
|
95
|
+
:props="cellProps"
|
|
96
|
+
:class="{
|
|
97
|
+
'q-td--no-hover': noHover || cellProps.col.name === 'actions',
|
|
98
|
+
actions: cellProps.col.name === 'actions',
|
|
99
|
+
}"
|
|
100
|
+
>
|
|
101
|
+
<div v-if="cellProps.col.name === 'actions'" class="actions__btns">
|
|
102
|
+
<q-btn square icon="edit" size="sm" unelevated title="Редактировать" @click="emit('edit', cellProps.row)" />
|
|
103
|
+
</div>
|
|
95
104
|
<q-badge
|
|
96
|
-
v-if="
|
|
105
|
+
v-else-if="cellProps.col.badge && typeof cellProps.value === 'boolean'"
|
|
97
106
|
:color="
|
|
98
|
-
|
|
99
|
-
?
|
|
100
|
-
:
|
|
101
|
-
?
|
|
102
|
-
:
|
|
107
|
+
cellProps.col.badge.colorTrue && cellProps.value
|
|
108
|
+
? cellProps.col.badge.colorTrue
|
|
109
|
+
: cellProps.col.badge.colorFalse && !cellProps.value
|
|
110
|
+
? cellProps.col.badge.colorFalse
|
|
111
|
+
: cellProps.value
|
|
103
112
|
? 'green'
|
|
104
113
|
: 'red'
|
|
105
114
|
"
|
|
106
115
|
outline
|
|
107
116
|
class="text-bold"
|
|
108
117
|
>
|
|
109
|
-
{{
|
|
118
|
+
{{ cellProps.value ? cellProps.col.badge.true ?? 'Да' : cellProps.col.badge.false ?? 'Нет' }}
|
|
110
119
|
</q-badge>
|
|
111
|
-
<span v-else-if="
|
|
112
|
-
<span v-else>{{
|
|
120
|
+
<span v-else-if="cellProps.col.html" v-html="cellProps.value"></span>
|
|
121
|
+
<span v-else>{{ cellProps.value }}</span>
|
|
113
122
|
</q-td>
|
|
114
123
|
</template>
|
|
115
124
|
</q-table>
|
|
@@ -131,6 +140,7 @@ interface TableEmits {
|
|
|
131
140
|
'open-filter-menu': [colName: string, isOpen: boolean]
|
|
132
141
|
'row-click': [row: Record<string, any>]
|
|
133
142
|
'update:selectedRows': [rows: any[]] // синтаксис defineEmits для эмита с именованными параметрами
|
|
143
|
+
edit: [row: Record<string, any>]
|
|
134
144
|
}
|
|
135
145
|
|
|
136
146
|
const props = defineProps<{
|
|
@@ -143,12 +153,19 @@ const props = defineProps<{
|
|
|
143
153
|
enableMultiSelect?: boolean
|
|
144
154
|
noHover?: boolean
|
|
145
155
|
selectedRows: any[]
|
|
156
|
+
actions?: string[]
|
|
146
157
|
}>()
|
|
147
158
|
const emit = defineEmits<TableEmits>()
|
|
148
159
|
|
|
149
160
|
const localSearches = ref<Record<string, string>>({})
|
|
150
161
|
const selected = ref<any[]>([])
|
|
151
162
|
|
|
163
|
+
const resCols = computed(() => {
|
|
164
|
+
if (!props.actions?.length) return props.columns
|
|
165
|
+
|
|
166
|
+
return [...props.columns, { name: 'actions', label: 'Действия', align: 'center' }]
|
|
167
|
+
})
|
|
168
|
+
|
|
152
169
|
const filteredOptions = computed(() => {
|
|
153
170
|
const result: Record<string, FilterOption[]> = {}
|
|
154
171
|
for (const col of props.columns) {
|
|
@@ -159,6 +176,14 @@ const filteredOptions = computed(() => {
|
|
|
159
176
|
return result
|
|
160
177
|
})
|
|
161
178
|
|
|
179
|
+
const rowClick = (e: Event, row: Record<string, any>) => {
|
|
180
|
+
const target = e?.target
|
|
181
|
+
|
|
182
|
+
if (!(target instanceof HTMLElement) || target.closest('.actions') || document.getSelection()?.toString()) return
|
|
183
|
+
|
|
184
|
+
emit('row-click', row)
|
|
185
|
+
}
|
|
186
|
+
|
|
162
187
|
watch(
|
|
163
188
|
() => props.selectedRows,
|
|
164
189
|
val => {
|
|
@@ -176,6 +201,28 @@ watch(
|
|
|
176
201
|
)
|
|
177
202
|
</script>
|
|
178
203
|
<style scoped lang="scss">
|
|
204
|
+
.actions {
|
|
205
|
+
width: 100px;
|
|
206
|
+
background-color: #f2f7fb;
|
|
207
|
+
position: sticky;
|
|
208
|
+
right: 0;
|
|
209
|
+
z-index: 1;
|
|
210
|
+
border-left: 1px solid #d7e0ef;
|
|
211
|
+
|
|
212
|
+
&__btns {
|
|
213
|
+
display: flex;
|
|
214
|
+
justify-content: center;
|
|
215
|
+
gap: 0.5rem;
|
|
216
|
+
|
|
217
|
+
button {
|
|
218
|
+
background-color: #a4b4cf50;
|
|
219
|
+
width: 32px;
|
|
220
|
+
height: 32px;
|
|
221
|
+
border-radius: 8px;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
179
226
|
.cursor-pointer {
|
|
180
227
|
cursor: pointer;
|
|
181
228
|
}
|
|
@@ -196,7 +243,7 @@ watch(
|
|
|
196
243
|
}
|
|
197
244
|
.q-item__section {
|
|
198
245
|
min-width: 30px;
|
|
199
|
-
padding:
|
|
246
|
+
padding: 0;
|
|
200
247
|
}
|
|
201
248
|
::v-deep(.q-radio__inner),
|
|
202
249
|
::v-deep(.q-checkbox__inner) {
|
|
@@ -214,7 +261,7 @@ watch(
|
|
|
214
261
|
position: sticky;
|
|
215
262
|
top: 0;
|
|
216
263
|
background: #f2f7fb;
|
|
217
|
-
z-index:
|
|
264
|
+
z-index: 2;
|
|
218
265
|
}
|
|
219
266
|
|
|
220
267
|
::v-deep(.q-table th) {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
filled
|
|
21
21
|
map-options
|
|
22
22
|
stack-label
|
|
23
|
-
:use-input="!selected
|
|
23
|
+
:use-input="!selected?.length && typeof selected !== 'number'"
|
|
24
24
|
:use-chips="!simple"
|
|
25
25
|
:hide-bottom-space="hideBottomSpace"
|
|
26
26
|
input-debounce="100"
|
|
@@ -237,6 +237,9 @@ function debounce<T>(fn: T, ms) {
|
|
|
237
237
|
background: #fff;
|
|
238
238
|
box-shadow: 0 1px 2px 0 rgba(184, 200, 224, 0.22);
|
|
239
239
|
}
|
|
240
|
+
:deep(.q-field__control:before) {
|
|
241
|
+
display: none;
|
|
242
|
+
}
|
|
240
243
|
:global(.q-field--filled.q-field--highlighted .q-field__control:before) {
|
|
241
244
|
background: #fff !important;
|
|
242
245
|
border: none;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<q-toggle v-model="value" />
|
|
3
|
+
<q-toggle v-model="value" :disable="disable" />
|
|
4
4
|
</div>
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script setup lang="ts">
|
|
8
|
-
import { computed } from 'vue'
|
|
8
|
+
import { computed, defineProps, defineEmits } from 'vue'
|
|
9
9
|
|
|
10
10
|
interface Props {
|
|
11
11
|
modelValue: any
|
|
12
|
+
disable?: boolean
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
const props = defineProps<Props>()
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ import '@/shared/styles/general.css'
|
|
|
2
2
|
import AppButton from '@/common/app-button/AppButton.vue'
|
|
3
3
|
import AppCheckbox from '@/common/app-checkbox/AppCheckbox.vue'
|
|
4
4
|
import AppDatePicker from '@/common/app-date-picker/AppDatePicker.vue'
|
|
5
|
+
import AppDatepicker from '@/common/app-datepicker/AppDatepicker.vue'
|
|
5
6
|
import AppInput from '@/common/app-input/AppInput.vue'
|
|
6
7
|
import AppInputNew from '@/common/app-input-new/AppInputNew.vue'
|
|
7
8
|
import AppInputSearch from '@/common/app-input-search/AppInputSearch.vue'
|
|
@@ -41,6 +42,7 @@ import useSearchService from '@/api/services/SearchService'
|
|
|
41
42
|
export {
|
|
42
43
|
AppButton,
|
|
43
44
|
AppCheckbox,
|
|
45
|
+
AppDatepicker,
|
|
44
46
|
AppDatePicker,
|
|
45
47
|
AppInput,
|
|
46
48
|
AppInputNew,
|