Browse Source

增加w-query-builder组件

main
likunming 5 months ago
parent
commit
2f80425ae1
  1. 16
      io.sc.platform.core.frontend/src/platform/components/grid/GridBody.vue
  2. 34
      io.sc.platform.core.frontend/src/platform/components/grid/GridTd.vue
  3. 75
      io.sc.platform.core.frontend/src/platform/components/grid/TreeGridRow.vue
  4. 15
      io.sc.platform.core.frontend/src/platform/components/grid/WGrid.vue
  5. 6
      io.sc.platform.core.frontend/src/platform/components/grid/css/grid.css
  6. 8
      io.sc.platform.core.frontend/src/platform/components/grid/ts/grid.ts
  7. 3
      io.sc.platform.core.frontend/src/platform/components/toolbar/ChildrenBtn.vue
  8. 9
      io.sc.platform.core.frontend/src/platform/components/toolbar/WToolbar.vue
  9. 4
      io.sc.platform.core.frontend/src/views/likm/Grid.vue

16
io.sc.platform.core.frontend/src/platform/components/grid/GridBody.vue

@ -22,7 +22,8 @@
<template v-else> <template v-else>
<q-tr <q-tr
ref="trRef" ref="trRef"
:class="props.scope.row[table.selectedField] ? 'selected' : ''" :no-hover="!props.grid.props.cellSelected ? false : true"
:class="props.scope.row[table.selectedField] && !props.grid.props.cellSelected ? 'selected' : ''"
:props="props.scope" :props="props.scope"
:draggable="draggableComputed" :draggable="draggableComputed"
@click.stop="props.rowClick($event, scope.row, scope.rowIndex)" @click.stop="props.rowClick($event, scope.row, scope.rowIndex)"
@ -68,7 +69,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, inject, ref, toRaw } from 'vue'; import { computed, inject, ref, toRaw } from 'vue';
import { Tools, noErrorAxios, NotifyManager, t } from '@/platform'; import { Tools, noErrorAxios, NotifyManager, t } from '@/platform';
import { draggableImage } from './ts/grid'; import { draggableImage, draggableMode } from './ts/grid';
import TreeGridRow from './TreeGridRow.vue'; import TreeGridRow from './TreeGridRow.vue';
import GridTd from './GridTd.vue'; import GridTd from './GridTd.vue';
import GridEditToolbar from './GridEditToolbar.vue'; import GridEditToolbar from './GridEditToolbar.vue';
@ -178,9 +179,12 @@ const setTreeRowComponentRef = (el, row) => {
}; };
const draggableComputed = computed(() => { const draggableComputed = computed(() => {
if (typeof props.grid.props.draggable === 'boolean' && props.grid.props.draggable && table.bodyEditStatus === 'none') { if (
return true; props.grid.props.draggable &&
} else if (typeof props.grid.props.draggable === 'string' && props.grid.props.draggable === 'local' && table.bodyEditStatus === 'none') { typeof props.grid.props.draggable === 'string' &&
!Tools.isEmpty(draggableMode[props.grid.props.draggable]) &&
table.bodyEditStatus === 'none'
) {
return true; return true;
} }
return false; return false;
@ -329,7 +333,7 @@ const onDrop = (e, scope) => {
updateData.push(toRaw(item)); updateData.push(toRaw(item));
} }
}); });
if (typeof props.grid.props.draggable === 'boolean' && props.grid.props.draggable) { if (props.grid.props.draggable === draggableMode.remote && updateData.length > 0) {
// 访 // 访
updates(updateData, () => {}); updates(updateData, () => {});
} }

34
io.sc.platform.core.frontend/src/platform/components/grid/GridTd.vue

@ -1,5 +1,23 @@
<template> <template>
<q-td :key="col.name" :props="scope" :title="col.classes?.indexOf('truncate') > -1 && !Tools.isEmpty(value) && typeof value !== 'object' ? value : ''"> <q-td
:key="col.name"
:props="scope"
:title="col.classes?.indexOf('truncate') > -1 && !Tools.isEmpty(value) && typeof value !== 'object' ? value : ''"
:class="props.grid.props.cellSelected ? tdClassComputed : ''"
@click="
() => {
if (table && props.grid.props.cellSelected) {
table['cellSelected'] = {
row: toRaw(scope.row),
rowKey: scope.row[props.rowKeyName],
primaryKey: scope.row[props.grid.props.primaryKey],
colName: col['name'],
value: value,
};
}
}
"
>
<template v-if="col.name === '_sortNo_'"> <template v-if="col.name === '_sortNo_'">
{{ scope.rowIndex + 1 }} {{ scope.rowIndex + 1 }}
</template> </template>
@ -26,7 +44,7 @@
</q-td> </q-td>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { inject, computed, ref } from 'vue'; import { inject, computed, ref, toRaw } from 'vue';
import { Tools } from '@/platform'; import { Tools } from '@/platform';
const componentRef = ref(); const componentRef = ref();
@ -70,6 +88,18 @@ const getComponentRef = () => {
return componentRef.value; return componentRef.value;
}; };
const tdClassComputed = computed(() => {
const tdClass = <any>[];
if (props.grid.props.cellSelected) {
tdClass.push('cellSelected_hover');
}
if (table && table['cellSelected'] && Tools.hasOwnProperty(table['cellSelected'], 'colName')) {
if (table['cellSelected']['colName'] === props.col['name'] && table['cellSelected']['rowKey'] === props.scope.row[props.rowKeyName])
tdClass.push('cellSelected');
}
return tdClass;
});
defineExpose({ defineExpose({
getComponentRef, getComponentRef,
}); });

75
io.sc.platform.core.frontend/src/platform/components/grid/TreeGridRow.vue

@ -1,7 +1,8 @@
<template> <template>
<q-tr <q-tr
ref="trRef" ref="trRef"
:class="row[table.selectedField] ? 'selected ' : ''" :no-hover="!props.grid.props.cellSelected ? false : true"
:class="row[table.selectedField] && !props.grid.props.cellSelected ? 'selected' : ''"
:draggable="draggableComputed" :draggable="draggableComputed"
@click.stop.prevent="click($event, row, props.rowIndex)" @click.stop.prevent="click($event, row, props.rowIndex)"
@dblclick.stop.prevent="dbClick($event, row, props.rowIndex)" @dblclick.stop.prevent="dbClick($event, row, props.rowIndex)"
@ -10,7 +11,22 @@
@drop="draggableComputed ? onDrop($event, row) : () => {}" @drop="draggableComputed ? onDrop($event, row) : () => {}"
@dragstart="draggableComputed ? onDragStart($event, row) : () => {}" @dragstart="draggableComputed ? onDragStart($event, row) : () => {}"
> >
<q-td class="nowrap text-nowrap"> <q-td
:class="props.grid.props.cellSelected ? firstTdClassComputed : 'nowrap text-nowrap'"
@click="
() => {
if (table && props.grid.props.cellSelected) {
table['cellSelected'] = {
row: toRaw(props.row),
rowKey: props.row[props.rowKey],
primaryKey: props.row[props.grid.props.primaryKey],
colName: cols[0]['name'],
value: cols[0]['value'],
};
}
}
"
>
<div ref="tdDivRef" class="flex flex-nowrap items-center h-full w-full" style="flex-wrap: nowrap"> <div ref="tdDivRef" class="flex flex-nowrap items-center h-full w-full" style="flex-wrap: nowrap">
<!--层级占位符--> <!--层级占位符-->
<span :style="`width:${24 * props.level}px;`"></span> <span :style="`width:${24 * props.level}px;`"></span>
@ -65,9 +81,22 @@
<template v-for="(col, index) in cols" :key="col.name"> <template v-for="(col, index) in cols" :key="col.name">
<q-td <q-td
v-if="index > 0" v-if="index > 0"
:class="col.__thClass + ' ' + col.classes" :class="props.grid.props.cellSelected ? tdClassComputed(col) : col.__thClass + ' ' + col.classes"
:title="col.classes?.indexOf('truncate') > -1 && col.value && typeof col.value !== 'object' ? col.value : ''" :title="col.classes?.indexOf('truncate') > -1 && col.value && typeof col.value !== 'object' ? col.value : ''"
:style="col.style" :style="col.style"
@click="
() => {
if (table && props.grid.props.cellSelected) {
table['cellSelected'] = {
row: toRaw(props.row),
rowKey: props.row[props.rowKey],
primaryKey: props.row[props.grid.props.primaryKey],
colName: col['name'],
value: col['value'],
};
}
}
"
> >
<template v-if="!Tools.isEmpty(col['type']) && ((isSelectedRowComputed && table.bodyEditStatus === 'rowEdit') || table.bodyEditStatus === 'rowsEdit')"> <template v-if="!Tools.isEmpty(col['type']) && ((isSelectedRowComputed && table.bodyEditStatus === 'rowEdit') || table.bodyEditStatus === 'rowsEdit')">
<component <component
@ -132,7 +161,7 @@
import { ref, computed, inject, toRaw } from 'vue'; import { ref, computed, inject, toRaw } from 'vue';
import { Tools, NotifyManager } from '@/platform'; import { Tools, NotifyManager } from '@/platform';
import GridEditToolbar from './GridEditToolbar.vue'; import GridEditToolbar from './GridEditToolbar.vue';
import { draggableImage } from './ts/grid'; import { draggableImage, draggableMode } from './ts/grid';
const trRef = ref(); const trRef = ref();
const tdDivRef = ref(); const tdDivRef = ref();
@ -236,10 +265,40 @@ const style = {
}, },
}; };
const firstTdClassComputed = computed(() => {
const tdClass = <any>['nowrap', 'text-nowrap'];
if (props.grid.props.cellSelected) {
tdClass.push('cellSelected_hover');
}
if (table && table['cellSelected'] && Tools.hasOwnProperty(table['cellSelected'], 'colName')) {
if (table['cellSelected']['colName'] === props.cols[0]['name'] && table['cellSelected']['rowKey'] === props.row[props.rowKey]) {
tdClass.push('cellSelected');
}
}
return tdClass;
});
const tdClassComputed = computed(() => {
return (col) => {
let tdClass = col.__thClass + ' ' + col.classes;
if (props.grid.props.cellSelected) {
tdClass += ' cellSelected_hover';
}
if (table && table['cellSelected'] && Tools.hasOwnProperty(table['cellSelected'], 'colName')) {
if (table['cellSelected']['colName'] === col['name'] && table['cellSelected']['rowKey'] === props.row[props.rowKey]) {
tdClass += ' cellSelected';
}
}
return tdClass;
};
});
const draggableComputed = computed(() => { const draggableComputed = computed(() => {
if (typeof props.grid.props.draggable === 'boolean' && props.grid.props.draggable && table.bodyEditStatus === 'none') { if (
return true; props.grid.props.draggable &&
} else if (typeof props.grid.props.draggable === 'string' && props.grid.props.draggable === 'local' && table.bodyEditStatus === 'none') { typeof props.grid.props.draggable === 'string' &&
!Tools.isEmpty(draggableMode[props.grid.props.draggable]) &&
table.bodyEditStatus === 'none'
) {
return true; return true;
} }
return false; return false;
@ -672,7 +731,7 @@ const onDrop = (e, dataRow) => {
resetOrder(e, table.dragRecords, table.rows, dataRow); resetOrder(e, table.dragRecords, table.rows, dataRow);
// //
if (typeof props.grid.props.draggable === 'boolean' && props.grid.props.draggable && updateOrderData?.length > 0) { if (props.grid.props.draggable === draggableMode.remote && updateOrderData?.length > 0) {
props.updates(updateOrderData); props.updates(updateOrderData);
} }

15
io.sc.platform.core.frontend/src/platform/components/grid/WGrid.vue

@ -147,7 +147,8 @@ const props = defineProps({
title: { type: String, default: '' }, // title: { type: String, default: '' }, //
autoFetchData: { type: Boolean, default: true }, // autoFetchData: { type: Boolean, default: true }, //
// localMode: { type: Boolean, default: false },// autoFetchData // localMode: { type: Boolean, default: false },// autoFetchData
draggable: { type: [Boolean, String], default: false }, // true访local cellSelected: { type: Boolean, default: false }, //
draggable: { type: String, default: undefined }, // `local``remote`
draggableOrderBy: { type: String, default: 'order' }, // draggableOrderBy: { type: String, default: 'order' }, //
pageable: { type: Boolean, default: true }, // pageable: { type: Boolean, default: true }, //
configButton: { type: Boolean, default: true }, // configButton: { type: Boolean, default: true }, //
@ -379,6 +380,7 @@ const table = reactive({
rows: <any>[], rows: <any>[],
inFullscreen: false, // inFullscreen: false, //
bodyEditStatus: 'none', // none()rowEdit()rowsEdit() bodyEditStatus: 'none', // none()rowEdit()rowsEdit()
cellSelected: {}, //
}); });
provide('table', table); provide('table', table);
@ -1129,6 +1131,16 @@ const getCascadeChildrenData = (rows: [], propertyName) => {
} }
return data; return data;
}; };
/**
* 获得选中的单元格
*/
const getSelectedCell = () => {
return {
row: table.cellSelected['row'],
colName: table.cellSelected['colName'],
value: table.cellSelected['value'],
};
};
/** /**
* 获取选择的行记录及所有子记录 * 获取选择的行记录及所有子记录
* @param propertyName 属性名称 * @param propertyName 属性名称
@ -1683,6 +1695,7 @@ defineExpose({
getTickedRows, getTickedRows,
getCascadeChildren, getCascadeChildren,
getCascadeParents, getCascadeParents,
getSelectedCell,
// =========refAPI========= // =========refAPI=========
getQueryForm, getQueryForm,
getEditorDialog, getEditorDialog,

6
io.sc.platform.core.frontend/src/platform/components/grid/css/grid.css

@ -1,3 +1,9 @@
.w-grid .cellSelected {
background-color: #0000001f;
}
.w-grid .cellSelected_hover:hover {
background-color: #0000001f;
}
.w-grid .q-table__top { .w-grid .q-table__top {
padding: var(--tableTopPadding) var(--tableTopPadding); padding: var(--tableTopPadding) var(--tableTopPadding);
} }

8
io.sc.platform.core.frontend/src/platform/components/grid/ts/grid.ts

@ -1,5 +1,11 @@
import { Tools, t } from '@/platform'; import { Tools, t } from '@/platform';
export const draggableMode = {
local: 'local',
remote: 'remote',
};
export const draggableImage = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' %3E%3Cpath /%3E%3C/svg%3E`;
// 列样式处理 // 列样式处理
const columnStyle = (item: any) => { const columnStyle = (item: any) => {
let style = ''; let style = '';
@ -53,5 +59,3 @@ export const columnDefaultProps = (columns: any, sortNo: boolean = true) => {
} }
return []; return [];
}; };
export const draggableImage = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' %3E%3Cpath /%3E%3C/svg%3E`;

3
io.sc.platform.core.frontend/src/platform/components/toolbar/ChildrenBtn.vue

@ -9,6 +9,7 @@
ticked: firstTickedComputed, ticked: firstTickedComputed,
tickeds: tickedComputed, tickeds: tickedComputed,
grid: grid, grid: grid,
selectedColName: props.grid.getSelectedCell()['colName'],
}) })
: false : false
" "
@ -46,6 +47,7 @@
ticked: firstTickedComputed, ticked: firstTickedComputed,
tickeds: tickedComputed, tickeds: tickedComputed,
grid: grid, grid: grid,
selectedColName: props.grid.getSelectedCell()['colName'],
}) })
: button[0].enableIf : button[0].enableIf
? !button[0].enableIf({ ? !button[0].enableIf({
@ -54,6 +56,7 @@
ticked: firstTickedComputed, ticked: firstTickedComputed,
tickeds: tickedComputed, tickeds: tickedComputed,
grid: grid, grid: grid,
selectedColName: props.grid.getSelectedCell()['colName'],
}) })
: false : false
" "

9
io.sc.platform.core.frontend/src/platform/components/toolbar/WToolbar.vue

@ -26,6 +26,7 @@
selecteds: selectedComputed, selecteds: selectedComputed,
ticked: firstTickedComputed, ticked: firstTickedComputed,
tickeds: tickedComputed, tickeds: tickedComputed,
selectedColName: props.grid.getSelectedCell()['colName'],
grid: grid, grid: grid,
}) })
: false : false
@ -66,6 +67,7 @@
ticked: firstTickedComputed, ticked: firstTickedComputed,
tickeds: tickedComputed, tickeds: tickedComputed,
grid: grid, grid: grid,
selectedColName: props.grid.getSelectedCell()['colName'],
}) })
: false : false
" "
@ -93,6 +95,7 @@
ticked: firstTickedComputed, ticked: firstTickedComputed,
tickeds: tickedComputed, tickeds: tickedComputed,
grid: grid, grid: grid,
selectedColName: props.grid.getSelectedCell()['colName'],
}) })
: false : false
" "
@ -155,6 +158,7 @@
ticked: firstTickedComputed, ticked: firstTickedComputed,
tickeds: tickedComputed, tickeds: tickedComputed,
grid: grid, grid: grid,
selectedColName: props.grid.getSelectedCell()['colName'],
}) })
: false : false
" "
@ -406,6 +410,7 @@ const getIcon = (icon) => {
ticked: firstTickedComputed.value, ticked: firstTickedComputed.value,
tickeds: tickedComputed.value, tickeds: tickedComputed.value,
grid: props.grid, grid: props.grid,
selectedColName: props.grid.getSelectedCell()['colName'],
}); });
} else { } else {
return icon; return icon;
@ -421,6 +426,7 @@ const getLabel = (label) => {
ticked: firstTickedComputed.value, ticked: firstTickedComputed.value,
tickeds: tickedComputed.value, tickeds: tickedComputed.value,
grid: props.grid, grid: props.grid,
selectedColName: props.grid.getSelectedCell()['colName'],
}); });
} else { } else {
return label; return label;
@ -455,6 +461,7 @@ const buttonClick = async (button) => {
tickeds: tickedComputed.value, tickeds: tickedComputed.value,
grid: props.grid, grid: props.grid,
context: context, context: context,
selectedColName: props.grid.getSelectedCell()['colName'],
}); });
} }
if (beforeResult && button.click) { if (beforeResult && button.click) {
@ -466,6 +473,7 @@ const buttonClick = async (button) => {
grid: props.grid, grid: props.grid,
_click: button._click, _click: button._click,
context: context, context: context,
selectedColName: props.grid.getSelectedCell()['colName'],
}); });
if (button.afterClick) { if (button.afterClick) {
nextTick(() => { nextTick(() => {
@ -476,6 +484,7 @@ const buttonClick = async (button) => {
tickeds: tickedComputed.value, tickeds: tickedComputed.value,
grid: props.grid, grid: props.grid,
context: context, context: context,
selectedColName: props.grid.getSelectedCell()['colName'],
}); });
}); });
} }

4
io.sc.platform.core.frontend/src/views/likm/Grid.vue

@ -5,13 +5,15 @@
title="示例列表" title="示例列表"
:data-url="Environment.apiContextPath('/api/system/application')" :data-url="Environment.apiContextPath('/api/system/application')"
db-click-operation="testAdd" db-click-operation="testAdd"
:cell-selected="true"
:toolbar-actions="[ :toolbar-actions="[
'add', 'add',
{ {
extend: 'add', extend: 'add',
name: 'testAdd', name: 'testAdd',
click: (args) => { click: (args) => {
console.info('testAdd======', args); const cell = args.grid.getSelectedCell();
console.info('cell=========', args);
}, },
}, },
[ [

Loading…
Cancel
Save