flameresttable 1.0.38 → 1.0.40
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/package.json +4 -4
- package/src/App.vue +1 -0
- package/src/Table/FlameTable.ts +80 -18
- package/src/Table/Table.vue +15 -36
- package/src/Table/TableFilters.vue +6 -5
- package/src/Table/TableLoadParams.ts +9 -3
- package/src/Table/TableRowParams.ts +1 -0
- package/src/Table/TableTasksPanel.vue +192 -0
- package/src/Table/TableFiltersSelector.vue +0 -47
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flameresttable",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.40",
|
|
4
4
|
"main": "./src/plugin.ts",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"android": "npm run build && npx cap add android && npx cap sync && npx cap open android"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@vuepic/vue-datepicker": "^7.2.
|
|
19
|
-
"flamerest": "^1.0.
|
|
18
|
+
"@vuepic/vue-datepicker": "^7.2.1",
|
|
19
|
+
"flamerest": "^1.0.94",
|
|
20
20
|
"lodash-es": "^4.17.21",
|
|
21
21
|
"pinia": "^2.1.7",
|
|
22
22
|
"pug": "github:FlameArt/pug-tailwind-only",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@volar/vue-language-plugin-pug": "^1.6.5",
|
|
39
39
|
"@vue/compiler-sfc": "^3.3.7",
|
|
40
40
|
"autoprefixer": "^10.4.16",
|
|
41
|
-
"eslint": "^8.
|
|
41
|
+
"eslint": "^8.53.0",
|
|
42
42
|
"eslint-plugin-vue": "^8.7.1",
|
|
43
43
|
"postcss": "^8.4.31",
|
|
44
44
|
"postcss-import": "^14.1.0",
|
package/src/App.vue
CHANGED
|
@@ -54,6 +54,7 @@ opts.LoadParams.sort = ['-dt1'];
|
|
|
54
54
|
Table(:model="Model", :opts="opts")
|
|
55
55
|
template(v-slot:RowSubSlot="params")
|
|
56
56
|
| {{ params.row.name + ' LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG LOOOONG line' }}
|
|
57
|
+
template(#otherButtons)
|
|
57
58
|
</template>
|
|
58
59
|
|
|
59
60
|
<style>
|
package/src/Table/FlameTable.ts
CHANGED
|
@@ -125,12 +125,17 @@ export default class FlameTable<T> {
|
|
|
125
125
|
|
|
126
126
|
// удаляем чтобы при перезагрузке не сохранялось состояние пред. строк
|
|
127
127
|
// производительность: если не стирать параметры строк, то при долгом пользовании таблицей и больших её объёмах в памяти накопится куча позиций, это утечка
|
|
128
|
-
|
|
128
|
+
|
|
129
|
+
// upd: Не удаляем, чтобы хранить данные по выделениям между фильтрацией и паджинацией. Сбрасывается вручную
|
|
130
|
+
for (const key in this.RowsParams)
|
|
131
|
+
if (!this.RowsParams[key].selected)
|
|
132
|
+
delete this.RowsParams[key];
|
|
129
133
|
|
|
130
134
|
// Заполняем параметры каждой строки
|
|
131
135
|
this.Rows.rows.forEach(row => {
|
|
132
|
-
|
|
133
|
-
|
|
136
|
+
const newParam = new TableRowParams;
|
|
137
|
+
newParam.item = row;
|
|
138
|
+
this.RowsParams[(row as any)[(this.model as any).constructor.primaryKeys[0]]] = newParam;
|
|
134
139
|
})
|
|
135
140
|
}
|
|
136
141
|
|
|
@@ -194,14 +199,12 @@ export default class FlameTable<T> {
|
|
|
194
199
|
|
|
195
200
|
/**
|
|
196
201
|
* Обновить результаты от RESTа
|
|
197
|
-
* @param
|
|
202
|
+
* @param CustomLoadParams Применить кастомные параметры загрузки
|
|
198
203
|
*/
|
|
199
|
-
public async update(
|
|
200
|
-
|
|
201
|
-
if (SaveLoadParams !== null) this.opts.LoadParams = SaveLoadParams;
|
|
204
|
+
public async update(CustomLoadParams: ITableLoadParams = {}) {
|
|
202
205
|
|
|
203
206
|
// Дополняем загрузочные параметры фильтрами
|
|
204
|
-
const filters = this.applyFiltersParams();
|
|
207
|
+
const filters = merge(this.applyFiltersParams(), CustomLoadParams);
|
|
205
208
|
|
|
206
209
|
const rows: Rows<T> = await (this.model as any).constructor.all(merge({}, this.opts.LoadParams, filters, { page: this.Pager.page, perPage: this.Pager.perPage }));
|
|
207
210
|
|
|
@@ -209,6 +212,10 @@ export default class FlameTable<T> {
|
|
|
209
212
|
|
|
210
213
|
}
|
|
211
214
|
|
|
215
|
+
/**
|
|
216
|
+
* Применить параметры, указанные в фильтрах
|
|
217
|
+
* @returns
|
|
218
|
+
*/
|
|
212
219
|
public applyFiltersParams() {
|
|
213
220
|
const customFilters: ITableLoadParams = {
|
|
214
221
|
where: {},
|
|
@@ -227,9 +234,11 @@ export default class FlameTable<T> {
|
|
|
227
234
|
customFilters.params[key] = el.valueString;
|
|
228
235
|
continue;
|
|
229
236
|
case 'daterange':
|
|
230
|
-
case 'number':
|
|
231
237
|
customFilters.params[key] = el.valueRange;
|
|
232
238
|
continue;
|
|
239
|
+
case 'number':
|
|
240
|
+
customFilters.params[key] = el.valueRangeNumbers;
|
|
241
|
+
continue;
|
|
233
242
|
case 'selector':
|
|
234
243
|
if (this.columns[key].Filter.selector.multiselect) {
|
|
235
244
|
customFilters.params[key] = el.valueRange;
|
|
@@ -381,22 +390,20 @@ export default class FlameTable<T> {
|
|
|
381
390
|
return res;
|
|
382
391
|
}
|
|
383
392
|
|
|
393
|
+
/**
|
|
394
|
+
* Получить все выбранные колонки массивом объектов строк
|
|
395
|
+
* @returns
|
|
396
|
+
*/
|
|
384
397
|
public getSelectedRows() {
|
|
385
|
-
|
|
386
|
-
this.Rows.rows.forEach((r: any) => {
|
|
387
|
-
const param = this.RowsParams[r[(this.model as any).constructor.primaryKeys[0]]]
|
|
388
|
-
if (param.selected)
|
|
389
|
-
result.push(r)
|
|
390
|
-
})
|
|
391
|
-
return result;
|
|
398
|
+
return this.Rows.rows.filter((r: any) => r.selected).map((r: any) => r.item);
|
|
392
399
|
}
|
|
393
400
|
|
|
394
401
|
/**
|
|
395
|
-
* Выгрузить существующие колонки в CSV
|
|
402
|
+
* Выгрузить существующие колонки в CSV средствами браузера
|
|
396
403
|
* @param filename
|
|
397
404
|
* @param arr
|
|
398
405
|
*/
|
|
399
|
-
public
|
|
406
|
+
public exportToCSV(filename: string = "table.csv", arr: any = null) {
|
|
400
407
|
|
|
401
408
|
arr = arr ?? this.getSelectedRows();
|
|
402
409
|
|
|
@@ -412,4 +419,59 @@ export default class FlameTable<T> {
|
|
|
412
419
|
|
|
413
420
|
}
|
|
414
421
|
|
|
422
|
+
/**
|
|
423
|
+
* Выгрузить в Excel средствами бекенда
|
|
424
|
+
* @param filename
|
|
425
|
+
* @param arr
|
|
426
|
+
*/
|
|
427
|
+
public exportToXLS(onlySelected: boolean = false, filename: string | null = null, arr: any = null, columnList: Array<string> | null = null) {
|
|
428
|
+
|
|
429
|
+
const tClass = Object.getPrototypeOf(this.model).constructor;
|
|
430
|
+
const indexKey = tClass.primaryKeys[0];
|
|
431
|
+
|
|
432
|
+
const customFilter: ITableLoadParams = {
|
|
433
|
+
where: {}
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
// Только выбранные элементы
|
|
437
|
+
if (onlySelected) {
|
|
438
|
+
// Получаем айдишки и затем вносим их в условие IN
|
|
439
|
+
arr = arr ?? this.getSelectedRows();
|
|
440
|
+
const INArray: Array<any> = [];
|
|
441
|
+
for (const row of arr) {
|
|
442
|
+
if (typeof row[indexKey] !== 'undefined') {
|
|
443
|
+
INArray.push(row[indexKey]);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
if (INArray.length > 0) {
|
|
447
|
+
customFilter.where = {
|
|
448
|
+
indexKey: ['IN', indexKey, INArray]
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
customFilter.export = {
|
|
454
|
+
format: "xlsx",
|
|
455
|
+
titles: [],
|
|
456
|
+
filename: filename ?? 'export_' + Date.now() + ".xlsx"
|
|
457
|
+
};
|
|
458
|
+
customFilter.fields = [];
|
|
459
|
+
|
|
460
|
+
for (const colKey in this.columns) {
|
|
461
|
+
|
|
462
|
+
const col = this.columns[colKey];
|
|
463
|
+
if (columnList !== null && (!columnList.includes(col.name))) continue;
|
|
464
|
+
if (columnList === null && (col.isVirtual || !col.Table.isShow)) continue;
|
|
465
|
+
|
|
466
|
+
// проверки пройдены, все оставшиеся колонки добавляем в вывод
|
|
467
|
+
(customFilter as any).export.titles.push(col.title !== '' ? col.title : col.name);
|
|
468
|
+
customFilter.fields.push(col.name);
|
|
469
|
+
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Делаем запрос на отдачу
|
|
473
|
+
this.update(customFilter);
|
|
474
|
+
|
|
475
|
+
}
|
|
476
|
+
|
|
415
477
|
}
|
package/src/Table/Table.vue
CHANGED
|
@@ -4,40 +4,18 @@
|
|
|
4
4
|
<!-- ФИЛЬТРЫ -->
|
|
5
5
|
<TableFilters :columns="Table.columns" :table="Table"></TableFilters>
|
|
6
6
|
|
|
7
|
-
<!--
|
|
8
|
-
<
|
|
9
|
-
<
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
</div>
|
|
20
|
-
<div v-show="$props.opts?.Export.CSV.can"
|
|
21
|
-
class="flex mr-3 cursor-pointer justify-center items-center text-white bg-blue-600 font-medium rounded text-sm px-4 text-center hover:bg-blue-700 .focus:ring-4.focus:ring-blue-200.dark:focus:ring-blue-900"
|
|
22
|
-
@click="Table.exportSelectedToCSV()">
|
|
23
|
-
<div class="text-xl">
|
|
24
|
-
+
|
|
25
|
-
</div>
|
|
26
|
-
<div class="ml-2">
|
|
27
|
-
{{ $props.opts?.Export.CSV.buttonTitle }}
|
|
28
|
-
</div>
|
|
29
|
-
</div>
|
|
30
|
-
</slot>
|
|
31
|
-
<slot name="otherButtons" />
|
|
32
|
-
|
|
33
|
-
<!-- ЧИСЛО ЗАПИСЕЙ -->
|
|
34
|
-
<div class="text-xs text-gray-400">
|
|
35
|
-
{{ opts.lang === 'ru' ? 'Показано:' : 'Showing' }} {{ Table.Pager.total > Table.Pager.perPage * Table.Pager.page ?
|
|
36
|
-
Table.Pager.perPage * Table.Pager.page : Table.Pager.total }} / {{ Table.Pager.total }} {{ opts.lang === 'ru' ?
|
|
37
|
-
'записей' : ' records' }}
|
|
38
|
-
</div>
|
|
39
|
-
|
|
40
|
-
</div>
|
|
7
|
+
<!-- ПАНЕЛЬ ОПЕРАЦИЙ НАД ТАБЛИЦЕЙ -->
|
|
8
|
+
<TableTasksPanel :table="Table" @add="add">
|
|
9
|
+
<template #defaultButtons>
|
|
10
|
+
<slot name="defaultButtons">
|
|
11
|
+
</slot>
|
|
12
|
+
</template>
|
|
13
|
+
<template #otherButtons>
|
|
14
|
+
<slot name="otherButtons">
|
|
15
|
+
</slot>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
</TableTasksPanel>
|
|
41
19
|
|
|
42
20
|
<!-- ТАБЛИЦА-->
|
|
43
21
|
<div class="mt-2 table table-fixed w-full ">
|
|
@@ -72,7 +50,7 @@
|
|
|
72
50
|
</div>
|
|
73
51
|
|
|
74
52
|
<!-- СТРОКИ-->
|
|
75
|
-
<div class="table-row-group">
|
|
53
|
+
<div class="table-row-group text-left">
|
|
76
54
|
|
|
77
55
|
<template v-for="(row) in (Table.Rows.rows)">
|
|
78
56
|
<div :key="'row_' + (row as any).id" class="defaultRow table-row cursor-pointer hover:bg-slate-100" v-if="true">
|
|
@@ -248,10 +226,11 @@ import Datepicker from '@vuepic/vue-datepicker';
|
|
|
248
226
|
import '@vuepic/vue-datepicker/dist/main.css';
|
|
249
227
|
import { isNumber } from 'lodash';
|
|
250
228
|
import 'vue-select/dist/vue-select.css';
|
|
229
|
+
import TableTasksPanel from './TableTasksPanel.vue';
|
|
251
230
|
|
|
252
231
|
|
|
253
232
|
export default defineComponent({
|
|
254
|
-
components: { ModalVue, Paginator, Datepicker, TableFilters },
|
|
233
|
+
components: { ModalVue, Paginator, Datepicker, TableFilters, TableTasksPanel },
|
|
255
234
|
props: {
|
|
256
235
|
rows: {
|
|
257
236
|
default: [] as Array<any>,
|
|
@@ -44,11 +44,12 @@
|
|
|
44
44
|
</div>
|
|
45
45
|
|
|
46
46
|
<!-- ДАТА -->
|
|
47
|
-
<div v-if="col.Filter.type === 'date' || col.Filter.type === 'daterange'">
|
|
48
|
-
<Datepicker v-if="col.Filter.type === 'date'" v-model="col.Filter.valueString"
|
|
49
|
-
:enable-time-picker="false" @update:model-value="update()" :teleport="true"></Datepicker>
|
|
50
|
-
<Datepicker v-if="col.Filter.type === 'daterange'" v-model="col.Filter.valueRange"
|
|
51
|
-
:enable-time-picker="false" :auto-apply="true" @update:model-value="update()" :teleport="true"
|
|
47
|
+
<div class="mobile:w-full" v-if="col.Filter.type === 'date' || col.Filter.type === 'daterange'">
|
|
48
|
+
<Datepicker class="mobile:w-full" v-if="col.Filter.type === 'date'" v-model="col.Filter.valueString"
|
|
49
|
+
:auto-apply="true" :enable-time-picker="false" @update:model-value="update()" :teleport="true"></Datepicker>
|
|
50
|
+
<Datepicker class="mobile:w-full" v-if="col.Filter.type === 'daterange'" v-model="col.Filter.valueRange"
|
|
51
|
+
:range="true" :enable-time-picker="false" :auto-apply="true" @update:model-value="update()" :teleport="true">
|
|
52
|
+
</Datepicker>
|
|
52
53
|
</div>
|
|
53
54
|
</div>
|
|
54
55
|
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
export default interface ITableLoadParams {
|
|
2
2
|
|
|
3
3
|
where?: any
|
|
4
|
-
fields?:
|
|
5
|
-
expand?: any
|
|
4
|
+
fields?: Array<string>,
|
|
5
|
+
expand?: Array<any>,
|
|
6
6
|
sort?: Array<string>,
|
|
7
7
|
page?: number,
|
|
8
8
|
perPage?: number,
|
|
9
|
-
params?: any
|
|
9
|
+
params?: any,
|
|
10
|
+
|
|
11
|
+
export?: {
|
|
12
|
+
format: 'xlsx' | 'csv',
|
|
13
|
+
titles?: Array<string>,
|
|
14
|
+
filename?: string,
|
|
15
|
+
}
|
|
10
16
|
|
|
11
17
|
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- "ДОБАВИТЬ" И ЧИСЛО ЗАПИСЕЙ-->
|
|
3
|
+
<div class="flex flex-wrap items-center justify-between">
|
|
4
|
+
|
|
5
|
+
<!-- ЛЕВАЯ ЧАСТЬ -->
|
|
6
|
+
<div>
|
|
7
|
+
<!-- Стандартные кнопки -->
|
|
8
|
+
<slot name="defaultButtons">
|
|
9
|
+
<div v-show="state.opts?.Add.can"
|
|
10
|
+
class="flex mr-3 cursor-pointer justify-center items-center text-white bg-blue-600 font-medium rounded text-sm px-4 text-center hover:bg-blue-700 .focus:ring-4.focus:ring-blue-200.dark:focus:ring-blue-900"
|
|
11
|
+
@click="emit('add')">
|
|
12
|
+
<div class="text-xl">
|
|
13
|
+
+
|
|
14
|
+
</div>
|
|
15
|
+
<div class="ml-2">
|
|
16
|
+
{{ state.opts?.Add.buttonTitle }}
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
<div v-show="state.opts?.Export.CSV.can"
|
|
20
|
+
class="flex mr-3 cursor-pointer justify-center items-center text-white bg-blue-600 font-medium rounded text-sm px-4 text-center hover:bg-blue-700 .focus:ring-4.focus:ring-blue-200.dark:focus:ring-blue-900"
|
|
21
|
+
@click="state.Table.exportToCSV()">
|
|
22
|
+
<div class="text-xl">
|
|
23
|
+
+
|
|
24
|
+
</div>
|
|
25
|
+
<div class="ml-2">
|
|
26
|
+
{{ state.opts?.Export.CSV.buttonTitle }}
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</slot>
|
|
30
|
+
|
|
31
|
+
<!-- Доп кнопки -->
|
|
32
|
+
<slot name="otherButtons" />
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
<!-- ЧИСЛО ЗАПИСЕЙ -->
|
|
36
|
+
<div class="text-xs text-gray-400">
|
|
37
|
+
{{ state.opts.lang === 'ru' ? 'Показано:' : 'Showing' }} {{ state.Table.Pager.total > state.Table.Pager.perPage *
|
|
38
|
+
state.Table.Pager.page ?
|
|
39
|
+
state.Table.Pager.perPage * state.Table.Pager.page : state.Table.Pager.total }} / {{ state.Table.Pager.total }} {{
|
|
40
|
+
state.opts.lang === 'ru' ?
|
|
41
|
+
'записей' : ' records' }}
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<!-- ПРАВАЯ ЧАСТЬ -->
|
|
47
|
+
<div>
|
|
48
|
+
|
|
49
|
+
<!-- ДЕЙСТВИЯ С ОТМЕЧЕННЫМИ -->
|
|
50
|
+
<div class="fc">
|
|
51
|
+
<div>
|
|
52
|
+
<label>
|
|
53
|
+
<select class="minimal text-xs text-center text-slate-500" v-model="state.selectModel" @change="selectAction">
|
|
54
|
+
<option :value="0">{{ state.opts.lang === 'ru' ? 'ДЕЙСТВИЯ' : 'ACTIONS' }}</option>
|
|
55
|
+
<option :value="1">{{ state.opts.lang === 'ru' ? 'Выгрузить выбранные' : 'Export selected' }} [{{ 5 }}]
|
|
56
|
+
</option>
|
|
57
|
+
<option :value="2">{{ state.opts.lang === 'ru' ? 'Выгрузить всё' : 'Export all' }} [{{
|
|
58
|
+
state.Table.Pager.total }}]</option>
|
|
59
|
+
</select>
|
|
60
|
+
</label>
|
|
61
|
+
</div>
|
|
62
|
+
<!--
|
|
63
|
+
<div
|
|
64
|
+
class="flex mr-3 cursor-pointer justify-center items-center text-white bg-blue-600 font-medium rounded text-sm px-4 text-center hover:bg-blue-700 .focus:ring-4.focus:ring-blue-200.dark:focus:ring-blue-900">
|
|
65
|
+
<div class="text-xl">
|
|
66
|
+
+
|
|
67
|
+
</div>
|
|
68
|
+
<div class="ml-2">
|
|
69
|
+
Экспорт отмеченных {{ 5 }}
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
<div
|
|
73
|
+
class="flex mr-3 cursor-pointer justify-center items-center text-white bg-blue-600 font-medium rounded text-sm px-4 text-center hover:bg-blue-700 .focus:ring-4.focus:ring-blue-200.dark:focus:ring-blue-900">
|
|
74
|
+
<div class="text-xl">
|
|
75
|
+
+
|
|
76
|
+
</div>
|
|
77
|
+
<div class="ml-2">
|
|
78
|
+
Экспорт всех {{ state.Table.Pager.total }}
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
-->
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
</div>
|
|
86
|
+
</template>
|
|
87
|
+
|
|
88
|
+
<script setup lang="ts">
|
|
89
|
+
import { onMounted, reactive, ref, defineProps, defineEmits, nextTick } from '@vue/runtime-core'; import type { Ref } from 'vue'; import { storeFile } from "@/store"; import { useRoute, useRouter } from 'vue-router'; import REST from "flamerest"
|
|
90
|
+
|
|
91
|
+
// Иконки
|
|
92
|
+
import { } from '@icons/24/solid'
|
|
93
|
+
import FlameTable from './FlameTable';
|
|
94
|
+
|
|
95
|
+
// Глобальное хранилище и роуты
|
|
96
|
+
const store = storeFile(), router = useRouter(), route = useRoute();
|
|
97
|
+
|
|
98
|
+
// Входящие данные компонента
|
|
99
|
+
const props = defineProps<{
|
|
100
|
+
table: FlameTable<any>,
|
|
101
|
+
}>()
|
|
102
|
+
const emit = defineEmits(['add'])
|
|
103
|
+
|
|
104
|
+
// Локальное состояние компонента
|
|
105
|
+
const state = reactive({
|
|
106
|
+
opts: props.table.opts,
|
|
107
|
+
Table: props.table,
|
|
108
|
+
selectModel: 0
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
const selectAction = () => {
|
|
112
|
+
|
|
113
|
+
switch (state.selectModel) {
|
|
114
|
+
case 0:
|
|
115
|
+
return;
|
|
116
|
+
case 1:
|
|
117
|
+
|
|
118
|
+
return;
|
|
119
|
+
case 2:
|
|
120
|
+
state.Table.exportToXLS();
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
</script>
|
|
127
|
+
|
|
128
|
+
<style scoped lang="scss">
|
|
129
|
+
$height: 36;
|
|
130
|
+
|
|
131
|
+
label {
|
|
132
|
+
position: relative;
|
|
133
|
+
display: inline-block;
|
|
134
|
+
|
|
135
|
+
&:before {
|
|
136
|
+
content: '';
|
|
137
|
+
height: ($height - 5) + px;
|
|
138
|
+
position: absolute;
|
|
139
|
+
right: 7px;
|
|
140
|
+
top: 3px;
|
|
141
|
+
width: 22px;
|
|
142
|
+
|
|
143
|
+
//background: -webkit-linear-gradient(#fff, #f0f0f0);
|
|
144
|
+
//background: -moz-linear-gradient(#fff, #f0f0f0);
|
|
145
|
+
//background: linear-gradient(#f5f5f5, #e0e0e0);
|
|
146
|
+
background: #fff; //for Firefox in Android
|
|
147
|
+
|
|
148
|
+
border-top-right-radius: 3px;
|
|
149
|
+
border-bottom-right-radius: 3px;
|
|
150
|
+
pointer-events: none;
|
|
151
|
+
display: block;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
&:after {
|
|
155
|
+
content: " ";
|
|
156
|
+
position: absolute;
|
|
157
|
+
right: 15px;
|
|
158
|
+
top: 46%;
|
|
159
|
+
margin-top: -3px;
|
|
160
|
+
z-index: 2;
|
|
161
|
+
pointer-events: none;
|
|
162
|
+
width: 0;
|
|
163
|
+
height: 0;
|
|
164
|
+
border-style: solid;
|
|
165
|
+
border-width: 6.9px 4px 0 4px;
|
|
166
|
+
border-color: #aaa transparent transparent transparent;
|
|
167
|
+
pointer-events: none;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
select {
|
|
171
|
+
-webkit-appearance: none;
|
|
172
|
+
-moz-appearance: none;
|
|
173
|
+
appearance: none;
|
|
174
|
+
padding: 0 30px 0 10px;
|
|
175
|
+
|
|
176
|
+
border: 1px solid #e0e0e0;
|
|
177
|
+
border-radius: 3px;
|
|
178
|
+
line-height: $height + px;
|
|
179
|
+
height: $height + px;
|
|
180
|
+
//box-shadow: inset 1px 1px 1px 0px rgba(0, 0, 0, 0.2);
|
|
181
|
+
background: #fff;
|
|
182
|
+
|
|
183
|
+
//min-width: 200px;
|
|
184
|
+
margin: 0 5px 5px 0;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
//fix for ie 10 later
|
|
189
|
+
select::-ms-expand {
|
|
190
|
+
display: none;
|
|
191
|
+
}
|
|
192
|
+
</style>
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<!-- Это селектор c мультивыбором -->
|
|
3
|
-
<div>
|
|
4
|
-
|
|
5
|
-
</div>
|
|
6
|
-
</template>
|
|
7
|
-
|
|
8
|
-
<script setup lang="ts" generic="T">
|
|
9
|
-
import { onMounted, reactive, ref, defineProps } from '@vue/runtime-core'; import type { Ref } from 'vue'; import { storeFile } from "@/store"; import { useRoute, useRouter } from 'vue-router'; import REST from "flamerest"
|
|
10
|
-
|
|
11
|
-
// Иконки
|
|
12
|
-
import { XCircleIcon } from '@icons/24/solid'
|
|
13
|
-
import TableOpts from './TableOpts';
|
|
14
|
-
import { Column } from './Columns';
|
|
15
|
-
//import { TableFilter } from './TableOpts.js';
|
|
16
|
-
import FlameTable from './FlameTable';
|
|
17
|
-
import Datepicker from '@vuepic/vue-datepicker';
|
|
18
|
-
|
|
19
|
-
// Глобальное хранилище и роуты
|
|
20
|
-
const store = storeFile(), router = useRouter(), route = useRoute();
|
|
21
|
-
|
|
22
|
-
// Локальное состояние компонента
|
|
23
|
-
const state = reactive({
|
|
24
|
-
data: {}
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
// Входящие данные компонента
|
|
28
|
-
const props = defineProps<{
|
|
29
|
-
columns: { [key: string]: Column; },
|
|
30
|
-
table: FlameTable<any>,
|
|
31
|
-
}>()
|
|
32
|
-
|
|
33
|
-
// Примонтировано
|
|
34
|
-
onMounted(async () => {
|
|
35
|
-
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const update = () => {
|
|
40
|
-
|
|
41
|
-
props.table.update();
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
</script>
|
|
46
|
-
|
|
47
|
-
<style scoped lang="scss"></style>
|