Browse Source

普通表格与树表格拖拽排序代码提交

main
likunming 7 months ago
parent
commit
3d8ec8321f
  1. 118
      io.sc.platform.core.frontend/src/platform/components/grid/TreeGridRow.vue
  2. 126
      io.sc.platform.core.frontend/src/platform/components/grid/WGrid.vue
  3. 254
      io.sc.platform.core.frontend/src/views/likm/Grid.vue
  4. 12
      io.sc.platform.core.frontend/src/views/likm/TreeGrid.vue
  5. 25
      io.sc.platform.mvc/src/main/java/io/sc/platform/mvc/controller/support/RestCrudController.java

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

@ -2,18 +2,20 @@
<q-tr <q-tr
ref="trRef" ref="trRef"
:class="row[table.selectedField] ? 'selected ' : ''" :class="row[table.selectedField] ? 'selected ' : ''"
:draggable="
(typeof gridProps.draggable === 'boolean' && gridProps.draggable) || (typeof gridProps.draggable === 'string' && gridProps.draggable === 'local')
? true
: false
"
@click.stop.prevent="click($event, row, row.rowIndex)" @click.stop.prevent="click($event, row, row.rowIndex)"
@dblclick.stop.prevent="dbClick($event, row, row.rowIndex)" @dblclick.stop.prevent="dbClick($event, row, row.rowIndex)"
@dragenter="onDragEnter($event, row)"
@dragleave="onDragLeave($event, row)"
@dragover="onDragOver($event, row)"
@drop="onDrop($event, row)"
@dragstart="onDragStart($event, row)"
> >
<q-td <q-td class="nowrap text-nowrap">
class="nowrap text-nowrap"
:draggable="gridProps.draggable"
@dragenter="onDragEnter($event, row)"
@dragleave="onDragLeave($event, row)"
@dragover="onDragOver($event, row)"
@drop="onDrop($event, row)"
@dragstart="onDragStart($event, row)"
>
<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>
@ -58,12 +60,6 @@
:class="col.__thClass + ' ' + col.classes" :class="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"
:draggable="gridProps.draggable"
@dragenter="onDragEnter($event, row)"
@dragleave="onDragLeave($event, row)"
@dragover="onDragOver($event, row)"
@drop="onDrop($event, row)"
@dragstart="onDragStart($event, row)"
> >
<template v-if="col.value && typeof col.value === 'object' && col.value.componentType && col.value.bindModelValue"> <template v-if="col.value && typeof col.value === 'object' && col.value.componentType && col.value.bindModelValue">
<component :is="col.value.componentType" v-bind="col.value.attrs" v-model="getRow(table.rows, row[props.rowKey], false)[col.name]"></component> <component :is="col.value.componentType" v-bind="col.value.attrs" v-model="getRow(table.rows, row[props.rowKey], false)[col.name]"></component>
@ -90,11 +86,12 @@
:grid="props.grid" :grid="props.grid"
:grid-row-click="props.gridRowClick" :grid-row-click="props.gridRowClick"
:grid-row-db-click="gridRowDbClick" :grid-row-db-click="gridRowDbClick"
:after-row-draggable="props.afterRowDraggable"
></TreeGridRow> ></TreeGridRow>
</template> </template>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, watch, inject, toRwa } from 'vue'; import { ref, reactive, computed, watch, inject, toRaw, nextTick } from 'vue';
import { Tools } from '@/platform'; import { Tools } from '@/platform';
const trRef = ref(); const trRef = ref();
@ -140,6 +137,10 @@ const props = defineProps({
type: Function, type: Function,
default: () => {}, default: () => {},
}, },
afterRowDraggable: {
type: Function,
default: () => {},
},
}); });
const table = inject('table'); const table = inject('table');
@ -433,11 +434,26 @@ const dragRecordsContains = (dataRow) => {
); );
}; };
//
const isLastNode = (dataRow) => {
if (Tools.isEmpty(dataRow[props.gridProps.foreignKey])) {
if (table.rows[table.rows.length - 1][props.gridProps.primaryKey] === dataRow[props.gridProps.primaryKey]) {
return true;
}
} else {
const parent = getRow(table.rows, dataRow[props.gridProps.foreignKey], true);
if (parent.children[parent.children.length - 1][props.gridProps.primaryKey] === dataRow[props.gridProps.primaryKey]) {
return true;
}
}
return false;
};
// //
const onDragEnter = (e, dataRow) => { const onDragEnter = (e, dataRow) => {
if (e.target.nodeName === 'TD' && e.offsetY <= gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { if (e.target.nodeName === 'TD' && e.offsetY <= gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) {
addDragTopStyle(e); addDragTopStyle(e);
} else if (e.target.nodeName === 'TD' && e.offsetY > gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { } else if (isLastNode(dataRow) && e.target.nodeName === 'TD' && e.offsetY > gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) {
addDragBottomStyle(e); addDragBottomStyle(e);
} }
}; };
@ -467,7 +483,7 @@ const onDragOver = (e, dataRow) => {
if (e.target.nodeName === 'TD' && e.offsetY <= gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { if (e.target.nodeName === 'TD' && e.offsetY <= gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) {
removeDragBottomStyle(e); removeDragBottomStyle(e);
addDragTopStyle(e); addDragTopStyle(e);
} else if (e.target.nodeName === 'TD' && e.offsetY > gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { } else if (isLastNode(dataRow) && e.target.nodeName === 'TD' && e.offsetY > gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) {
removeDragTopStyle(e); removeDragTopStyle(e);
addDragBottomStyle(e); addDragBottomStyle(e);
} }
@ -482,58 +498,86 @@ const onDragOver = (e, dataRow) => {
// //
const removeRecord = (arr, removeData) => { const removeRecord = (arr, removeData) => {
let index = 0;
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {
if (arr[i][props.rowKey] === removeData[props.rowKey]) { if (arr[i][props.rowKey] === removeData[props.rowKey]) {
arr.splice(i, 1); arr.splice(i, 1);
index = i;
break; break;
} else if (arr[i].children && arr[i].children.length > 0) { } else if (arr[i].children && arr[i].children.length > 0) {
removeRecord(arr[i].children, removeData); const a = removeRecord(arr[i].children, removeData);
if (a > 0) {
index = a;
}
} }
} }
return index;
}; };
//
const updateOrderData = <any>[];
// //
const setOrder = (arr) => { const setOrder = (arr) => {
arr.forEach((item, index) => { arr.forEach((item, index) => {
item[props.gridProps.orderBy] = index + 1; item[props.gridProps.orderBy] = index + 1;
//
updateOrderData.push(toRaw(item));
}); });
}; };
// //
const addRecord = (arr, addData, targetData, targetIndex) => { const addRecord = (e, arr, addData, targetData, dragIndex, targetIndex) => {
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {
if (arr[i][props.gridProps.primaryKey] === targetData[props.gridProps.foreignKey]) { if (arr[i][props.gridProps.primaryKey] === targetData[props.gridProps.foreignKey]) {
if (
e.offsetY <= gridTrMiddleHeightComputed.value &&
isTrue(dragIndex, targetIndex) &&
addData[props.gridProps.foreignKey] === targetData[props.gridProps.foreignKey]
) {
arr[i].children.splice(targetIndex - 1, 0, addData);
} else if (e.offsetY > gridTrMiddleHeightComputed.value && addData[props.gridProps.foreignKey] !== targetData[props.gridProps.foreignKey]) {
arr[i].children.splice(arr[i].children.length, 0, addData);
} else {
arr[i].children.splice(targetIndex, 0, addData);
}
// //
addData[props.gridProps.foreignKey] = arr[i][props.gridProps.primaryKey]; addData[props.gridProps.foreignKey] = arr[i][props.gridProps.primaryKey];
arr[i].children.splice(targetIndex + 1, 0, addData);
// //
setOrder(arr[i].children); setOrder(arr[i].children);
break; break;
} else if (arr[i].children && arr[i].children.length > 0) { } else if (arr[i].children && arr[i].children.length > 0) {
addRecord(arr[i].children, addData, targetData, targetIndex); addRecord(e, arr[i].children, addData, targetData, dragIndex, targetIndex);
} }
} }
}; };
const isTrue = (dragIndex, targetIndex) => {
if (dragIndex < targetIndex) {
return true;
}
return false;
};
// //
const resetOrderDataHandler = (e, dragRecords, targetData, targetIndex) => { const resetOrderDataHandler = (e, dragRecords, targetData, targetIndex) => {
// 1 // 1
dragRecords.forEach((item) => { dragRecords.forEach((item) => {
removeRecord(table.rows, item); const itemIndex = removeRecord(table.rows, item);
// 2 // 2
if (Tools.isEmpty(targetData[props.gridProps.foreignKey])) { if (Tools.isEmpty(targetData[props.gridProps.foreignKey])) {
if (e.offsetY <= gridTrMiddleHeightComputed.value) { // 3使splice-11
item[props.gridProps.foreignKey] = null; if (e.offsetY <= gridTrMiddleHeightComputed.value && Tools.isEmpty(item[props.gridProps.foreignKey]) && isTrue(itemIndex, targetIndex)) {
table.rows.splice(targetIndex, 0, item); table.rows.splice(targetIndex - 1, 0, item);
setOrder(table.rows);
} else { } else {
item[props.gridProps.foreignKey] = null; table.rows.splice(targetIndex, 0, item);
table.rows.splice(targetIndex + 1, 0, item);
setOrder(table.rows);
} }
item[props.gridProps.foreignKey] = null;
setOrder(table.rows);
//
updateOrderData.push(...toRaw(table.rows));
} else { } else {
addRecord(table.rows, item, targetData, targetIndex); addRecord(e, table.rows, item, targetData, itemIndex, targetIndex);
} }
}); });
}; };
@ -563,9 +607,17 @@ const onDrop = (e, dataRow) => {
) { ) {
return; return;
} }
//
updateOrderData.splice(0, updateOrderData.length);
// //
resetOrder(e, table.dragRecords, table.rows, dataRow); resetOrder(e, table.dragRecords, table.rows, dataRow);
// emit('afterRowDraggable');
//
if (typeof props.gridProps.draggable === 'boolean' && props.gridProps.draggable && updateOrderData?.length > 0) {
props.grid.updates(updateOrderData);
}
props.afterRowDraggable(updateOrderData);
}; };
const click = (evt, row, rowIndex) => { const click = (evt, row, rowIndex) => {

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

@ -120,66 +120,44 @@
:grid="instance" :grid="instance"
:grid-row-click="rowClick" :grid-row-click="rowClick"
:grid-row-db-click="rowDbClick" :grid-row-db-click="rowDbClick"
:after-row-draggable="afterRowDraggable"
></TreeGridRow> ></TreeGridRow>
</template> </template>
<q-tr <q-tr
v-else v-else
:class="scope.row[table.selectedField] ? 'selected' : ''" :class="scope.row[table.selectedField] ? 'selected' : ''"
:props="scope" :props="scope"
:draggable="(typeof draggable === 'boolean' && draggable) || (typeof draggable === 'string' && draggable === 'local') ? true : false"
@click.stop="rowClick($event, scope.row, scope.rowIndex)" @click.stop="rowClick($event, scope.row, scope.rowIndex)"
@dblclick.stop="rowDbClick($event, scope.row, scope.rowIndex)" @dblclick.stop="rowDbClick($event, scope.row, scope.rowIndex)"
@dragenter="onDragEnter($event, scope)"
@dragleave="onDragLeave"
@dragover="onDragOver($event, scope)"
@drop="onDrop($event, scope)"
@dragstart="onDragStart($event, scope)"
> >
<q-td v-if="table.checkboxSelection" class="text-center" style="padding: 0; width: 50px"> <q-td v-if="table.checkboxSelection" class="text-center" style="padding: 0; width: 50px">
<q-checkbox v-model="scope.row[table.tickedField]" flat :dense="denseBodyComputed" @update:model-value="updateTicked($event, scope.row)" /> <q-checkbox v-model="scope.row[table.tickedField]" flat :dense="denseBodyComputed" @update:model-value="updateTicked($event, scope.row)" />
</q-td> </q-td>
<template v-if="draggable"> <q-td
<q-td v-for="col in scope.cols"
v-for="col in scope.cols" :key="col.name"
:key="col.name" :props="scope"
draggable="true" :title="col.classes?.indexOf('truncate') > -1 && col.value && typeof col.value !== 'object' ? col.value : ''"
:props="scope" >
:title="col.classes?.indexOf('truncate') > -1 ? col.value : ''" <template v-if="col.name === '_sortNo_'">
@dragenter="onDragEnter($event, scope)" {{ scope.rowIndex + 1 }}
@dragleave="onDragLeave" </template>
@dragover="onDragOver($event, scope)" <template v-else-if="col.value && typeof col.value === 'object' && col.value.componentType && col.value.bindModelValue">
@drop="onDrop($event, scope)" <component :is="col.value.componentType" v-bind="col.value.attrs" v-model="scope.row[col.name]"></component>
@dragstart="onDragStart($event, scope)" </template>
> <template v-else-if="col.value && typeof col.value === 'object' && col.value.componentType">
<template v-if="col.name === '_sortNo_'"> <component :is="col.value.componentType" v-bind="col.value.attrs"></component>
{{ scope.rowIndex + 1 }} </template>
</template> <template v-else>
<template v-else-if="col.value && typeof col.value === 'object' && col.value.componentType && col.value.bindModelValue"> <span v-dompurify-html="Tools.isUndefinedOrNull(col.value) ? '' : col.value"></span>
<component :is="col.value.componentType" v-bind="col.value.attrs" v-model="scope.row[col.name]"></component> </template>
</template> </q-td>
<template v-else-if="col.value && typeof col.value === 'object' && col.value.componentType">
<component :is="col.value.componentType" v-bind="col.value.attrs"></component>
</template>
<template v-else>
<span v-dompurify-html="Tools.isUndefinedOrNull(col.value) ? '' : col.value"></span>
</template>
</q-td>
</template>
<template v-else>
<q-td
v-for="col in scope.cols"
:key="col.name"
:props="scope"
:title="col.classes?.indexOf('truncate') > -1 && col.value && typeof col.value !== 'object' ? col.value : ''"
>
<template v-if="col.name === '_sortNo_'">
{{ scope.rowIndex + 1 }}
</template>
<template v-else-if="col.value && typeof col.value === 'object' && col.value.componentType && col.value.bindModelValue">
<component :is="col.value.componentType" v-bind="col.value.attrs" v-model="scope.row[col.name]"></component>
</template>
<template v-else-if="col.value && typeof col.value === 'object' && col.value.componentType">
<component :is="col.value.componentType" v-bind="col.value.attrs"></component>
</template>
<template v-else>
<span v-dompurify-html="Tools.isUndefinedOrNull(col.value) ? '' : col.value"></span>
</template>
</q-td>
</template>
</q-tr> </q-tr>
</template> </template>
<!-- <template v-if="table.rows.length === 0" #top-row> <!-- <template v-if="table.rows.length === 0" #top-row>
@ -269,7 +247,7 @@ const props = defineProps({
height: { type: Number, default: 0 }, // height: { type: Number, default: 0 }, //
title: { type: String, default: '' }, // title: { type: String, default: '' }, //
autoFetchData: { type: Boolean, default: true }, // autoFetchData: { type: Boolean, default: true }, //
draggable: { type: Boolean, default: false }, // draggable: { type: [Boolean, String], default: false }, // true访local
pageable: { type: Boolean, default: true }, // pageable: { type: Boolean, default: true }, //
configButton: { type: Boolean, default: true }, // configButton: { type: Boolean, default: true }, //
dataUrl: { type: String, default: '' }, // URL dataUrl: { type: String, default: '' }, // URL
@ -294,7 +272,7 @@ const props = defineProps({
treeRelationship: { type: String, default: 'parent' }, // parent, childrenparentchildren treeRelationship: { type: String, default: 'parent' }, // parent, childrenparentchildren
primaryKey: { type: String, default: 'id' }, // APIRestCrudControllerupdate primaryKey: { type: String, default: 'id' }, // APIRestCrudControllerupdate
foreignKey: { type: String, default: 'parent' }, // foreignKey: { type: String, default: 'parent' }, //
orderBy: { type: String, default: 'order' }, // orderBy: { type: String, default: 'order' }, //
refreshData: { type: Boolean, default: false }, // primaryKey refreshData: { type: Boolean, default: false }, // primaryKey
dbClickOperation: { type: String, default: 'view' }, // vieweditcloneexpand dbClickOperation: { type: String, default: 'view' }, // vieweditcloneexpand
sortBy: { sortBy: {
@ -399,6 +377,10 @@ const props = defineProps({
type: Function, type: Function,
default: undefined, default: undefined,
}, },
onAfterRowDraggable: {
type: Function,
default: undefined,
},
}); });
const emit = defineEmits<{ const emit = defineEmits<{
// //
@ -440,6 +422,8 @@ const emit = defineEmits<{
): void; ): void;
( (
e: 'afterRowDraggable', // e: 'afterRowDraggable', //
grid: any,
data: any,
): void; ): void;
}>(); }>();
@ -594,8 +578,8 @@ const table = reactive({
denseBody: props.denseBody !== undefined ? props.denseBody : false, denseBody: props.denseBody !== undefined ? props.denseBody : false,
denseBottom: props.denseBottom !== undefined ? props.denseBottom : false, denseBottom: props.denseBottom !== undefined ? props.denseBottom : false,
queryFormFields: <any>[], queryFormFields: <any>[],
moreQueryStatus: false, //
rows: <any>[], rows: <any>[],
moreQueryStatus: false, //
inFullscreen: false, // inFullscreen: false, //
}); });
provide('table', table); provide('table', table);
@ -2456,18 +2440,49 @@ const onDrop = (e, scope) => {
return; return;
} }
const dragRow = table.rows[dragRowIndex]; const dragRow = table.rows[dragRowIndex];
if (e.offsetY < state.bodyCellHeight / 2 && dragRowIndex !== scope.rowIndex && e.target.parentNode.parentNode.children.length === scope.rowIndex + 1) { table.rows.splice(dragRowIndex, 1);
table.rows.splice(dragRowIndex, 1); if (e.offsetY < state.bodyCellHeight / 2 && dragRowIndex < scope.rowIndex) {
table.rows.splice(scope.rowIndex - 1, 0, dragRow); table.rows.splice(scope.rowIndex - 1, 0, dragRow);
} else { } else {
table.rows.splice(dragRowIndex, 1);
table.rows.splice(scope.rowIndex, 0, dragRow); table.rows.splice(scope.rowIndex, 0, dragRow);
} }
removeDragTopStyle(e); removeDragTopStyle(e);
removeDragBottomStyle(e); removeDragBottomStyle(e);
emit('afterRowDraggable'); const updateData = <any>[];
table.rows.forEach((item, index) => {
item[props.orderBy] = index + 1;
updateData.push(toRaw(item));
});
if (typeof props.draggable === 'boolean' && props.draggable) {
// 访
updates(updateData);
}
afterRowDraggable(updateData);
};
const afterRowDraggable = (updateData) => {
if (!Tools.isUndefined(props.onAfterRowDraggable)) {
emit('afterRowDraggable', instance, updateData);
}
}; };
//
const updates = (data) => {
const requestParams = {
method: 'PUT',
headers: { 'content-type': 'application/json;charset=utf-8;' },
data: data,
url: url.dataUrl + '/updates',
};
axios(requestParams).catch((error) => {
console.info('=======error======', error);
});
};
// form // form
const handlerQueryFormShowField = () => { const handlerQueryFormShowField = () => {
table.queryFormFields = []; table.queryFormFields = [];
@ -2694,6 +2709,7 @@ defineExpose({
refresh, refresh,
getLocalData, getLocalData,
setLocalData, setLocalData,
updates,
replaceRow, replaceRow,
removeRows, removeRows,
addRow, addRow,

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

@ -57,14 +57,14 @@
</q-tab-panels> </q-tab-panels>
</template> </template>
</q-splitter> --> </q-splitter> -->
<w-grid <!-- <w-grid
ref="gridRef" ref="gridRef"
:title="testGrid.title" :title="testGrid.title"
draggable draggable
:dense="state.dense" :dense="state.dense"
:hide-bottom="false" :hide-bottom="false"
:data-url="testGrid.tableDataUrl" :data-url="testGrid.tableDataUrl"
:auto-fetch-data="false" :auto-fetch-data="true"
:checkbox-selection="true" :checkbox-selection="true"
selection="multiple" selection="multiple"
:query-form-cols-num="6" :query-form-cols-num="6"
@ -95,16 +95,86 @@
@row-db-click="rowDbClick" @row-db-click="rowDbClick"
@after-request-data=" @after-request-data="
() => { () => {
// console.info('1111111111111111111111111111');
} }
" "
></w-grid> ></w-grid> -->
<w-grid
ref="applicationGridRef"
:title="$t('system.application.grid.title')"
:config-button="true"
selection="multiple"
:checkbox-selection="true"
:sort-no="true"
:draggable="true"
:data-url="Environment.apiContextPath('/api/system/application')"
:sort-by="['order']"
:query-form-cols-num="3"
:query-form-fields="[
{ name: 'code', label: $t('code'), type: 'text' },
{ name: 'name', label: $t('name'), type: 'text' },
{ name: 'enable', label: $t('isEnable'), type: 'select', options: Options.yesNo() },
]"
:toolbar-configure="{ noIcon: false }"
:toolbar-actions="['query', 'refresh', 'separator', 'add', 'clone', 'edit', 'remove', 'separator', 'view', 'separator', 'export']"
:columns="[
{ width: 60, name: 'order', label: $t('order') },
{ width: 100, name: 'code', label: $t('code') },
{ width: '100%', name: 'name', label: $t('name') },
{ width: 80, name: 'enable', label: $t('status'), format: Formater.enableTag() },
{ width: 120, name: 'lastModifier', label: $t('lastModifier') },
{ width: 120, name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.dateOnly() },
]"
:editor="{
dialog: {
width: '600px',
height: '300px',
},
form: {
colsNum: 1,
fields: [
{ name: 'code', label: $t('code'), type: 'text', required: true },
{ name: 'name', label: $t('name'), type: 'text', required: true },
{ name: 'description', label: $t('description'), type: 'textarea', rows: 1 },
{ name: 'order', label: $t('order'), type: 'number' },
{ name: 'enable', label: $t('enable'), type: 'checkbox', defaultValue: true },
],
},
}"
:viewer="{
panel: {
columnNum: 1,
fields: [
{ name: 'id', label: $t('id') },
{ name: 'code', label: $t('code') },
{ name: 'name', label: $t('name') },
{ name: 'description', label: $t('description') },
{ name: 'enable', label: $t('enable'), format: Formater.none() },
{ name: 'order', label: $t('order') },
{ name: 'dataComeFrom', label: $t('dataComeFrom') },
{ name: 'creator', label: $t('creator') },
{ name: 'createDate', label: $t('createDate') },
{ name: 'lastModifier', label: $t('lastModifier') },
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
{ name: 'corporationCode', label: $t('corporationCode') },
],
},
}"
@row-click="(evt, row, index) => {}"
@before-request-data="() => {}"
@after-row-draggable="
(grid, updateDatas) => {
console.info('grid=====', grid);
console.info('updateDatas======', updateDatas);
}
"
>
</w-grid>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, nextTick, reactive, computed } from 'vue'; import { ref, onMounted, nextTick, reactive, computed } from 'vue';
import { axios, Environment, EnumTools, Options } from '@/platform'; import { axios, Environment, EnumTools, Options, Formater } from '@/platform';
import EnableIcon from '@/platform/components/grid/EnableIcon.vue'; import EnableIcon from '@/platform/components/grid/EnableIcon.vue';
import { IconEnum } from '@/platform/enums'; import { IconEnum } from '@/platform/enums';
@ -300,52 +370,52 @@ const testGrid = {
// { label: '', name: 'lastModifyDate', type: 'w-date' }, // { label: '', name: 'lastModifyDate', type: 'w-date' },
], ],
tableColumns: [ tableColumns: [
{ // {
name: 'info', // name: 'info',
label: '用户信息', // label: '',
columns: [ // columns: [
{ name: 'loginName', label: '登录名', align: 'right' }, // { name: 'loginName', label: '', align: 'right' },
{ name: 'userName', label: '用户名' }, // { name: 'userName', label: '' },
], // ],
}, // },
// { name: 'loginName', label: '', align: 'right' }, { name: 'loginName', label: '登录名', align: 'right' },
// { name: 'userName', label: '' }, { name: 'userName', label: '用户名' },
{ // {
name: 'lxxx', // name: 'lxxx',
label: '联系方式', // label: '',
columns: [ // columns: [
{ // {
name: 'email', // name: 'email',
label: '邮箱地址', // label: '',
columns: [ // columns: [
{ width: 100, name: 'auc', label: 'auc' }, // { width: 100, name: 'auc', label: 'auc' },
{ width: 100, name: 'ar', label: 'ar' }, // { width: 100, name: 'ar', label: 'ar' },
{ width: 100, name: 'ks', label: 'ks' }, // { width: 100, name: 'ks', label: 'ks' },
], // ],
}, // },
{ // {
name: 'tx', // name: 'tx',
label: '通讯', // label: '',
columns: [ // columns: [
{ name: 'phone', label: '电话' }, // { name: 'phone', label: '' },
{ name: 'mobile', label: '手机号' }, // { name: 'mobile', label: '' },
], // ],
}, // },
{ // {
name: 'qq', // name: 'qq',
label: 'QQ', // label: 'QQ',
// columns: [ // // columns: [
// { width: 100, name: 'aucQualitative', label: 'aucQualitative' }, // // { width: 100, name: 'aucQualitative', label: 'aucQualitative' },
// { width: 100, name: 'arQualitative', label: 'arQualitative' }, // // { width: 100, name: 'arQualitative', label: 'arQualitative' },
// { width: 100, name: 'ksQualitative', label: 'ksQualitative' }, // // { width: 100, name: 'ksQualitative', label: 'ksQualitative' },
// ], // // ],
}, // },
], // ],
}, // },
// { name: 'email', label: '' }, { name: 'email', label: '邮箱地址' },
// { name: 'phone', label: '' }, { name: 'phone', label: '电话' },
// { name: 'mobile', label: '' }, { name: 'mobile', label: '手机号' },
// { name: 'qq', label: 'QQ' }, { name: 'qq', label: 'QQ' },
{ name: 'description', label: '描述', width: 400 }, { name: 'description', label: '描述', width: 400 },
{ {
name: 'enable', name: 'enable',
@ -417,46 +487,46 @@ const testGrid = {
}; };
onMounted(() => { onMounted(() => {
gridRef.value.setLocalData([ // gridRef.value.setLocalData([
{ // {
loginName: 'admin1', // loginName: 'admin1',
}, // },
{ // {
loginName: 'admin2', // loginName: 'admin2',
}, // },
{ // {
loginName: 'admin3', // loginName: 'admin3',
}, // },
{ // {
loginName: 'admin4', // loginName: 'admin4',
}, // },
{ // {
loginName: 'admin5', // loginName: 'admin5',
}, // },
{ // {
loginName: 'admin6', // loginName: 'admin6',
}, // },
{ // {
loginName: 'admin7', // loginName: 'admin7',
}, // },
{ // {
loginName: 'admin8', // loginName: 'admin8',
}, // },
{ // {
loginName: 'admin9', // loginName: 'admin9',
}, // },
{ // {
loginName: 'admin10', // loginName: 'admin10',
}, // },
{ // {
loginName: 'admin11', // loginName: 'admin11',
}, // },
{ // {
loginName: 'admin12', // loginName: 'admin12',
}, // },
{ // {
loginName: 'admin13', // loginName: 'admin13',
}, // },
]); // ]);
}); });
</script> </script>

12
io.sc.platform.core.frontend/src/views/likm/TreeGrid.vue

@ -1,5 +1,5 @@
<template> <template>
<div> <div class="h-full">
<w-grid <w-grid
ref="gridRef" ref="gridRef"
:title="testGrid.title" :title="testGrid.title"
@ -15,6 +15,12 @@
:query-form-fields="testGrid.queryFormFields" :query-form-fields="testGrid.queryFormFields"
:query-form-cols-num="3" :query-form-cols-num="3"
@update-ticked="updateTicked" @update-ticked="updateTicked"
@after-row-draggable="
(grid, updateDatas) => {
console.info('grid=====', grid);
console.info('updateDatas======', updateDatas);
}
"
></w-grid> ></w-grid>
</div> </div>
</template> </template>
@ -29,8 +35,8 @@ import { IconEnum } from '@/platform/enums';
const { t } = useI18n(); const { t } = useI18n();
const updateTicked = (event, row) => { const updateTicked = (event, row) => {
console.info('treeGrid.updateTicked.event====', event); // console.info('treeGrid.updateTicked.event====', event);
console.info('treeGrid.updateTicked.row====', row); // console.info('treeGrid.updateTicked.row====', row);
}; };
const startY = ref(0); const startY = ref(0);

25
io.sc.platform.mvc/src/main/java/io/sc/platform/mvc/controller/support/RestCrudController.java

@ -14,6 +14,7 @@ import io.sc.platform.orm.service.support.QueryResult;
import io.sc.platform.orm.service.support.criteria.Criteria; import io.sc.platform.orm.service.support.criteria.Criteria;
import io.sc.platform.orm.service.support.criteria.impl.Equals; import io.sc.platform.orm.service.support.criteria.impl.Equals;
import io.sc.platform.orm.service.support.criteria.impl.IContains; import io.sc.platform.orm.service.support.criteria.impl.IContains;
import io.sc.platform.orm.util.EntityVoUtil;
import io.sc.platform.security.util.SecurityUtil; import io.sc.platform.security.util.SecurityUtil;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
@ -124,6 +125,30 @@ public abstract class RestCrudController<V extends BaseVo, E extends BaseEntity<
return update(request,response,id,entity); return update(request,response,id,entity);
} }
/**
* 更新多个实体
* @param request Http 请求对象
* @param response Http 响应对象
* @param entitys 实体对象集合
* @return 更新后的实体 VO 对象
* @throws Exception 违例
*/
@AuditLog(action=AuditLogAction.UPDATE)
@PutMapping("updates")
@ResponseBody
public List<V> updates(HttpServletRequest request,HttpServletResponse response,@RequestBody List<E> entitys) throws Exception{
Map<ID, E> map = new HashMap<>();
List<E> list = new ArrayList<>();
if (entitys!=null && entitys.size() > 0) {
for(E entity: entitys) {
ID id = service.getRepository().getId(entity);
map.put(id, entity);
}
list = service.update(map);
}
return EntityVoUtil.toVo(list);
}
protected V update(HttpServletRequest request,HttpServletResponse response,@PathVariable(name="id")ID id,@RequestBody @Valid E entity) throws Exception{ protected V update(HttpServletRequest request,HttpServletResponse response,@PathVariable(name="id")ID id,@RequestBody @Valid E entity) throws Exception{
E updatedEntity =service.update(id,entity); E updatedEntity =service.update(id,entity);
if(updatedEntity instanceof BaseEntity){ if(updatedEntity instanceof BaseEntity){

Loading…
Cancel
Save