Browse Source

提交树表格支持代码

main
likunming 1 year ago
parent
commit
f6998ca535
  1. 20
      io.sc.platform.core.frontend/src/platform/components/form/WForm.vue
  2. 8
      io.sc.platform.core.frontend/src/platform/components/form/elements/WCheckbox.vue
  3. 12
      io.sc.platform.core.frontend/src/platform/components/form/elements/WDate.vue
  4. 12
      io.sc.platform.core.frontend/src/platform/components/form/elements/WNumber.vue
  5. 12
      io.sc.platform.core.frontend/src/platform/components/form/elements/WPassword.vue
  6. 12
      io.sc.platform.core.frontend/src/platform/components/form/elements/WSelect.vue
  7. 12
      io.sc.platform.core.frontend/src/platform/components/form/elements/WText.vue
  8. 12
      io.sc.platform.core.frontend/src/platform/components/form/elements/WTextBtn.vue
  9. 12
      io.sc.platform.core.frontend/src/platform/components/form/elements/WTextarea.vue
  10. 225
      io.sc.platform.core.frontend/src/platform/components/grid/TreeGridRow.vue
  11. 195
      io.sc.platform.core.frontend/src/platform/components/grid/WGrid.vue
  12. 10
      io.sc.platform.core.frontend/src/platform/components/toolbar/ChildrenBtn.vue
  13. 24
      io.sc.platform.core.frontend/src/platform/components/toolbar/WToolbar.vue
  14. 5
      io.sc.platform.core.frontend/src/views/likm/Dialog.vue
  15. 13
      io.sc.platform.core.frontend/src/views/likm/Form.vue
  16. 38
      io.sc.platform.core.frontend/src/views/likm/Grid.vue
  17. 24
      io.sc.platform.core.frontend/src/views/likm/TreeGrid.vue

20
io.sc.platform.core.frontend/src/platform/components/form/WForm.vue

@ -19,9 +19,10 @@
v-model="formData[field.name]"
v-bind="field"
:form-data="formData"
:form="instance"
@update:model-value="updateModelValue(field.name, formData[field.name])"
></component>
<component :is="fiedType[field.type] || field.type" v-else :form-ref="formRef" v-bind="field" :form-data="formData"></component>
<component :is="fiedType[field.type] || field.type" v-else :form-ref="formRef" v-bind="field" :form-data="formData" :form="instance"></component>
</div>
</template>
</div>
@ -31,8 +32,9 @@
</template>
<script setup lang="ts">
import { ref, reactive, watch, computed, toRaw, defineProps, useAttrs } from 'vue';
import { ref, reactive, watch, computed, toRaw, defineProps, useAttrs, getCurrentInstance } from 'vue';
import { useQuasar } from 'quasar';
import { VueTools } from '@/platform';
import { PageStatusEnum } from '@/platform/components/utils';
const $q = useQuasar();
@ -199,7 +201,7 @@ const getStatus = () => {
/**
* 对外暴露方法-获取当前一行应该显示的元素个数
*/
const getRowColsNum = () => {
const getColsNum = () => {
return screenColsNumComputed.value;
};
@ -238,9 +240,12 @@ const setValidationErrors = (errors: errorType[]) => {
}
};
const getFields = () => {
return formFields;
};
defineExpose({
data: formData,
fields: formFields,
getFields,
getData,
setData,
reset,
@ -249,7 +254,10 @@ defineExpose({
setFieldValue,
setStatus,
getStatus,
getRowColsNum,
getColsNum,
setValidationErrors,
});
const instance = getCurrentInstance();
VueTools.expose2Instance(instance);
</script>

8
io.sc.platform.core.frontend/src/platform/components/form/elements/WCheckbox.vue

@ -23,6 +23,10 @@ const props = defineProps({
return false;
},
},
form: {
type: Object,
default: undefined,
},
});
const rulesComputed = computed(() => {
@ -34,9 +38,9 @@ const rulesComputed = computed(() => {
});
const hideIfComputed = computed(() => {
return props.hideIf();
return props.hideIf(props.form);
});
const disableIfComputed = computed(() => {
return props.disableIf();
return props.disableIf(props.form);
});
</script>

12
io.sc.platform.core.frontend/src/platform/components/form/elements/WDate.vue

@ -64,6 +64,10 @@ const props = defineProps({
return false;
},
},
form: {
type: Object,
default: undefined,
},
});
watch(
@ -87,20 +91,20 @@ const rulesComputed = computed(() => {
});
const hideIfComputed = computed(() => {
return props.hideIf();
return props.hideIf(props.form);
});
const requiredIfComputed = computed(() => {
if (props.requiredIf) {
return props.requiredIf() || false;
return props.requiredIf(props.form) || false;
} else if (props.required) {
return true;
}
return false;
});
const readonlyIfComputed = computed(() => {
return props.readonlyIf();
return props.readonlyIf(props.form);
});
const disableIfComputed = computed(() => {
return props.disableIf();
return props.disableIf(props.form);
});
</script>

12
io.sc.platform.core.frontend/src/platform/components/form/elements/WNumber.vue

@ -54,6 +54,10 @@ const props = defineProps({
return false;
},
},
form: {
type: Object,
default: undefined,
},
});
const rulesComputed = computed(() => {
@ -71,20 +75,20 @@ const rulesComputed = computed(() => {
});
const hideIfComputed = computed(() => {
return props.hideIf();
return props.hideIf(props.form);
});
const requiredIfComputed = computed(() => {
if (props.requiredIf) {
return props.requiredIf() || false;
return props.requiredIf(props.form) || false;
} else if (props.required) {
return true;
}
return false;
});
const readonlyIfComputed = computed(() => {
return props.readonlyIf();
return props.readonlyIf(props.form);
});
const disableIfComputed = computed(() => {
return props.disableIf();
return props.disableIf(props.form);
});
</script>

12
io.sc.platform.core.frontend/src/platform/components/form/elements/WPassword.vue

@ -53,6 +53,10 @@ const props = defineProps({
return false;
},
},
form: {
type: Object,
default: undefined,
},
});
const rulesComputed = computed(() => {
@ -69,20 +73,20 @@ const rulesComputed = computed(() => {
});
const hideIfComputed = computed(() => {
return props.hideIf();
return props.hideIf(props.form);
});
const requiredIfComputed = computed(() => {
if (props.requiredIf) {
return props.requiredIf() || false;
return props.requiredIf(props.form) || false;
} else if (props.required) {
return true;
}
return false;
});
const readonlyIfComputed = computed(() => {
return props.readonlyIf();
return props.readonlyIf(props.form);
});
const disableIfComputed = computed(() => {
return props.disableIf();
return props.disableIf(props.form);
});
</script>

12
io.sc.platform.core.frontend/src/platform/components/form/elements/WSelect.vue

@ -53,6 +53,10 @@ const props = defineProps({
return false;
},
},
form: {
type: Object,
default: undefined,
},
});
const rulesComputed = computed(() => {
@ -69,20 +73,20 @@ const rulesComputed = computed(() => {
});
const hideIfComputed = computed(() => {
return props.hideIf();
return props.hideIf(props.form);
});
const requiredIfComputed = computed(() => {
if (props.requiredIf) {
return props.requiredIf() || false;
return props.requiredIf(props.form) || false;
} else if (props.required) {
return true;
}
return false;
});
const readonlyIfComputed = computed(() => {
return props.readonlyIf();
return props.readonlyIf(props.form);
});
const disableIfComputed = computed(() => {
return props.disableIf();
return props.disableIf(props.form);
});
</script>

12
io.sc.platform.core.frontend/src/platform/components/form/elements/WText.vue

@ -52,6 +52,10 @@ const props = defineProps({
return false;
},
},
form: {
type: Object,
default: undefined,
},
});
const rulesComputed = computed(() => {
@ -68,20 +72,20 @@ const rulesComputed = computed(() => {
});
const hideIfComputed = computed(() => {
return props.hideIf();
return props.hideIf(props.form);
});
const requiredIfComputed = computed(() => {
if (props.requiredIf) {
return props.requiredIf() || false;
return props.requiredIf(props.form) || false;
} else if (props.required) {
return true;
}
return false;
});
const readonlyIfComputed = computed(() => {
return props.readonlyIf();
return props.readonlyIf(props.form);
});
const disableIfComputed = computed(() => {
return props.disableIf();
return props.disableIf(props.form);
});
</script>

12
io.sc.platform.core.frontend/src/platform/components/form/elements/WTextBtn.vue

@ -64,6 +64,10 @@ const props = defineProps({
return false;
},
},
form: {
type: Object,
default: undefined,
},
});
const rulesComputed = computed(() => {
@ -80,20 +84,20 @@ const rulesComputed = computed(() => {
});
const hideIfComputed = computed(() => {
return props.hideIf();
return props.hideIf(props.form);
});
const requiredIfComputed = computed(() => {
if (props.requiredIf) {
return props.requiredIf() || false;
return props.requiredIf(props.form) || false;
} else if (props.required) {
return true;
}
return false;
});
const readonlyIfComputed = computed(() => {
return props.readonlyIf();
return props.readonlyIf(props.form);
});
const disableIfComputed = computed(() => {
return props.disableIf();
return props.disableIf(props.form);
});
</script>

12
io.sc.platform.core.frontend/src/platform/components/form/elements/WTextarea.vue

@ -52,6 +52,10 @@ const props = defineProps({
return false;
},
},
form: {
type: Object,
default: undefined,
},
});
const rulesComputed = computed(() => {
@ -68,20 +72,20 @@ const rulesComputed = computed(() => {
});
const hideIfComputed = computed(() => {
return props.hideIf();
return props.hideIf(props.form);
});
const requiredIfComputed = computed(() => {
if (props.requiredIf) {
return props.requiredIf() || false;
return props.requiredIf(props.form) || false;
} else if (props.required) {
return true;
}
return false;
});
const readonlyIfComputed = computed(() => {
return props.readonlyIf();
return props.readonlyIf(props.form);
});
const disableIfComputed = computed(() => {
return props.disableIf();
return props.disableIf(props.form);
});
</script>

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

@ -1,35 +1,39 @@
<template>
<q-tr :props="scope">
<q-td :style="{ 'padding-left': '2px' }">
<q-tr :class="row.selected ? 'selected' : ''">
<q-td :style="{ 'padding-left': '2px' }" class="nowrap text-nowrap">
<div class="flex flex-nowrap items-center">
<!--层级占位符-->
<span :style="`width:${27 * props.level}px;`"></span>
<!--展开按钮-->
<q-btn
v-if="scope.row.children && scope.row.children.length > 0"
v-if="row.children && row.children.length > 0"
flat
size="16px"
dense
padding="0px 0px"
:icon="scope.row.expand ? 'bi-dash' : 'bi-plus'"
@click="scope.row.expand = !scope.row.expand"
:icon="state.currRow.expand ? 'bi-dash' : 'bi-plus'"
@click="expandFun"
/>
<!--展开按钮占位符-->
<span v-else style="width: 27px"></span>
<!--选择框-->
<q-checkbox v-model="scope.row.selected" flat size="40px" dense />
<q-checkbox
v-if="checkboxSelection"
v-model="state.currRow.selected"
flat
size="40px"
dense
@update:model-value="selectedFun(state.currRow.selected, state.currRow)"
/>
<!--文件夹图标-->
<q-icon v-if="scope.row.children && scope.row.children.length > 0" :name="'folder'" color="amber" size="20px" class="px-1"></q-icon>
<q-icon v-if="row.children && row.children.length > 0" :name="'folder'" color="amber" size="20px" class="px-1"></q-icon>
<!--文件图标-->
<q-icon v-else name="note" size="20px" class="px-1"></q-icon>
</div>
</q-td>
<q-td v-for="(col, index) in scope.cols" :key="col.name" :style="{ 'padding-left': '7px' }">
<q-td v-for="col in cols" :key="col.name" :title="col.classes?.indexOf('truncate') > -1 ? col.value : ''" @click="click($el, row, row.rowIndex)">
<div class="flex flex-nowrap items-center">
<template v-if="col.name === '_sortNo_'">
{{ index + 1 }}
</template>
<template v-else-if="col.value && typeof col.value === 'object' && col.value.componentType">
<template v-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>
@ -38,49 +42,202 @@
</div>
</q-td>
</q-tr>
<template v-for="child in scope.row.children" :key="child.id">
<TreeGridRow v-if="scope.row.expand" :props="propsHandler(child)" :columns-map="columnsMap" :level="props.level + 1"></TreeGridRow>
<template v-for="child in row.children" :key="child[props.rowKey]">
<TreeGridRow
v-if="state.currRow.expand"
:columns-map="props.columnsMap"
:row="child"
:cols="childColsHandler(child)"
:level="props.level + 1"
:checkbox-selection="checkboxSelection"
:row-key="props.rowKey"
></TreeGridRow>
</template>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, inject } from 'vue';
const props = defineProps({
level: { type: Number, default: 0 },
props: {
columnsMap: {
type: Map,
default: () => {
return new Map();
},
},
row: {
type: Object,
default: () => {
return {};
},
},
columnsMap: {
type: Map,
cols: {
type: Array,
default: () => {
return new Map();
return [];
},
},
checkboxSelection: { type: Boolean, default: true },
rowKey: { type: String, default: 'id' },
});
const scope = { ...props.props };
const propsHandler = (child) => {
const table = inject('table');
const state = reactive({
currRow: {},
});
watch(
() => props.row.selected,
(newVal, oldVal) => {
state.currRow.selected = newVal;
},
);
//
const getCurrRow = (arr) => {
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (item[props.rowKey] === props.row[props.rowKey]) {
state.currRow = { expand: false, selected: false, ...item };
break;
} else if (item.children && item.children.length > 0) {
getCurrRow(item.children);
}
}
};
getCurrRow(table.rows);
// key
const getRow = (arr, key) => {
let result = undefined;
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (item[props.rowKey] === key) {
result = item;
break;
} else if (item.children && item.children.length > 0) {
const temp = getRow(item.children, key);
if (temp) {
result = temp;
}
}
}
return result;
};
// /
const expandFun = () => {
if (state.currRow) {
state.currRow.expand = !state.currRow.expand;
}
};
// checkbox
const selectedFun = (value, row) => {
if (value) {
selectedPush(row);
getRow(table.rows, row[props.rowKey]).selected = true;
} else {
selectedRemove(row);
getRow(table.rows, row[props.rowKey]).selected = false;
}
selectedChildren(row, value);
selectedParent(row, value);
};
//
const selectedChildren = (row, selected) => {
if (row.children && row.children.length > 0) {
for (let child of row.children) {
child['selected'] = selected;
if (selected) {
selectedPush(child);
} else {
selectedRemove(child);
}
selectedChildren(child, selected);
}
}
};
//
const selectedParent = (row, selected) => {
if (row.parent) {
const parent = getRow(table.rows, row.parent);
if (parent) {
if (selected && childrenSelectedStatus(parent).allSelected) {
parent.selected = true;
selectedPush(parent);
} else if (selected) {
parent.selected = null;
} else {
selectedRemove(parent);
if (childrenSelectedStatus(parent).partSelected) {
parent.selected = null;
} else {
parent.selected = false;
}
}
}
selectedParent(parent, selected);
}
};
//
const childrenSelectedStatus = (row) => {
let result = {
allSelected: true,
partSelected: false,
};
if (row.children && row.children.length > 0) {
for (let i = 0; i < row.children.length; i++) {
if (!row.children[i].selected) {
result.allSelected = false;
} else {
result.partSelected = true;
}
const temp = childrenSelectedStatus(row.children[i]);
if (!temp.allSelected) {
result.allSelected = false;
}
if (temp.partSelected) {
result.partSelected = true;
}
}
}
return result;
};
//
const selectedPush = (row) => {
// push
if (table.selected.findIndex((item) => item[props.rowKey] === row[props.rowKey]) < 0) {
table.selected.push(row);
}
};
const selectedRemove = (row) => {
// remove
if (table.selected.findIndex((item) => item[props.rowKey] === row[props.rowKey]) > -1) {
table.selected.splice(
table.selected.findIndex((item) => item[props.rowKey] === row[props.rowKey]),
1,
);
}
};
// cols
const childColsHandler = (child) => {
const cols = <any>[];
scope.cols.forEach((col) => {
props.cols.forEach((col) => {
if (props.columnsMap.get(col.name) && props.columnsMap.get(col.name).format) {
cols.push({ ...col, value: props.columnsMap.get(col.name).format(child[col.name]) });
} else {
cols.push({ ...col, value: child[col.name] });
}
});
return {
key: child.id,
row: child,
pageIndex: props.props.pageIndex,
__trClass: props.props.__trClass,
cols: cols,
colsMap: props.props.colsMap,
rowIndex: props.props.rowIndex,
color: props.props.color,
dark: props.props.dark,
dense: props.props.dense,
selected: props.props.selected,
expand: props.props.expand,
return cols;
};
const click = (el, row, rowIndex) => {
selectedFun(!row.selected, row);
};
</script>

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

@ -6,11 +6,11 @@
v-model:selected="table.selected"
flat
binary-state-sort
selection="single"
separator="cell"
:no-data-label="table.noDataLabel"
:loading-label="table.loadingLabel"
v-bind="attrs"
:selection="selectionComputed"
separator="cell"
:rows="table.rows"
:columns="extractTableColumns"
:rows-per-page-options="pagination.rowsPerPage && table.refHeightWidth.middleWidth > 600 ? table.pagination.rowsPerPageOptions : []"
@ -30,15 +30,9 @@
<w-toolbar
v-bind="toolbarConfigure"
:buttons="buttons_"
:grid-prop="{
gridSelected: table.selected,
gridRefs: {
gridRef: tableRef,
queryFormRef: queryFormRef,
addEditDialogRef: dialogRef,
addEditFormRef: dialogFormRef,
viewDrawerRef: drawerRef,
},
:grid-props="{
selected: getSelectedRowsComputed,
grid: instance,
}"
></w-toolbar>
</div>
@ -57,7 +51,7 @@
<template v-if="columnTitleState.columnTitleRowNum > 1">
<q-tr v-for="(r, rIndex) in columnTitleState.columnTitleArr" :key="rIndex">
<q-th
v-if="rIndex === 0 && (!attrs.selection || attrs.selection === 'multiple')"
v-if="rIndex === 0 && selectionComputed === 'multiple' && props.checkboxSelection && !props.tree"
:rowspan="columnTitleState.columnTitleRowNum"
:style="moreColumnTitleTableSelectionStyle"
>
@ -79,8 +73,10 @@
</template>
<template v-else>
<q-tr :props="scope">
<q-th v-if="attrs.selection || attrs.selection === 'multiple'" style="padding: 0; width: 50px"> <q-checkbox v-model="scope.selected" flat /></q-th>
<q-th v-else-if="!attrs.selection || attrs.selection !== 'none'"></q-th>
<q-th v-if="selectionComputed === 'multiple' && props.checkboxSelection && !props.tree" :style="props.tree ? '' : 'padding: 0; width: 50px'">
<q-checkbox v-model="scope.selected" flat
/></q-th>
<q-th v-else></q-th>
<q-th v-for="col in scope.cols" :key="col.name" :props="scope" :style="col.style" :class="col.classes">
{{ col.label }}
</q-th>
@ -89,10 +85,16 @@
</template>
<template #body="scope">
<template v-if="tree">
<TreeGridRow :props="scope" :columns-map="tableColumnsMap" @row-click="rowClick($el, scope.row, scope.rowIndex)"></TreeGridRow>
<TreeGridRow
:columns-map="tableColumnsMap"
:row="scope.row"
:cols="scope.cols"
:checkbox-selection="props.checkboxSelection"
:row-key="props.rowKey"
></TreeGridRow>
</template>
<q-tr v-else :props="scope" @click="rowClick($el, scope.row, scope.rowIndex)" @dblclick="rowDbClick($el, scope.row, scope.rowIndex)">
<q-td v-if="!attrs.selection || attrs.selection !== 'none'" class="text-center" style="padding: 0; width: 50px">
<q-td v-if="props.checkboxSelection" class="text-center" style="padding: 0; width: 50px">
<q-checkbox v-model="scope.selected" flat />
</q-td>
<template v-if="draggable">
@ -115,7 +117,7 @@
<component :is="col.value.componentType" v-bind="col.value.attrs"></component>
</template>
<template v-else>
{{ col.value }}
<span v-dompurify-html="col.value || ''"></span>
</template>
</q-td>
</template>
@ -128,7 +130,7 @@
<component :is="col.value.componentType" v-bind="col.value.attrs"></component>
</template>
<template v-else>
{{ col.value }}
<span v-dompurify-html="col.value || ''"></span>
</template>
</q-td>
</template>
@ -185,15 +187,15 @@
</w-dialog>
<w-drawer ref="drawerRef" title="查看" v-bind="viewer.drawer">
<div class="p-2.5">
<w-info-panel v-bind="viewer.panel" :info="viewInfo.infoArray"></w-info-panel>
<w-info-panel ref="infoRef" v-bind="viewer.panel" :info="viewInfo.infoArray"></w-info-panel>
</div>
</w-drawer>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted, nextTick, toRaw, useAttrs } from 'vue';
import { axios, Environment, NotifyManager, TreeBuilder } from '@/platform';
import { ref, reactive, computed, onMounted, nextTick, toRaw, useAttrs, getCurrentInstance, provide } from 'vue';
import { axios, Environment, NotifyManager, TreeBuilder, VueTools } from '@/platform';
import { useQuasar, getCssVar, exportFile } from 'quasar';
import { IconEnum } from '@/platform/enums';
import { extractTableColumnsProps, arrayToMap, OperatorTypeEnum, isEmpty, PageStatusEnum } from '@/platform/components/utils';
@ -223,8 +225,10 @@ const props = defineProps({
denseBody: { type: Boolean, default: false }, //
sortNo: { type: Boolean, default: false }, //
leftColumnStickyNumber: { type: Number, default: 0 }, // 1-10el
clickSelectedRow: { type: Boolean, default: true }, // selection'none'
checkboxSelection: { type: Boolean, default: true }, // checkbox
tree: { type: Boolean, default: false }, //
treeExpand: { type: Boolean, default: false }, //
treeExpandChildren: { type: Boolean, default: false }, //
columns: {
type: Array,
default: () => {
@ -356,6 +360,7 @@ const tableRef = ref();
const dialogRef = ref();
const drawerRef = ref();
const dialogFormRef = ref();
const infoRef = ref();
const tableColumnsMap = arrayToMap('name', props.columns);
const queryFormFieldsMap = arrayToMap('name', props.queryFormFields);
@ -444,15 +449,15 @@ const buttonObj = {
return false;
},
click: (selected, context) => {
if (!table.selected || table.selected.length <= 0) {
if (!selected || selected.length <= 0) {
NotifyManager.warn('请选择要编辑的记录');
} else {
dialogRef.value.show();
dialog.dialogTitle = '编辑';
nextTick(() => {
dialogFormRef.value.setStatus(PageStatusEnum.编辑);
dialogFormRef.value.setData(table.selected[0]);
emit('editDialogOpenAfter', table.selected[0]);
dialogFormRef.value.setData(selected[0]);
emit('editDialogOpenAfter', selected[0]);
});
}
},
@ -468,14 +473,14 @@ const buttonObj = {
return false;
},
click: (selected, context) => {
if (!table.selected || table.selected.length <= 0) {
if (!selected || selected.length <= 0) {
NotifyManager.warn('请选择要复制的记录');
} else {
dialogRef.value.show();
dialog.dialogTitle = '复制';
nextTick(() => {
dialogFormRef.value.setStatus(PageStatusEnum.新增);
dialogFormRef.value.setData(table.selected[0]);
dialogFormRef.value.setData(selected[0]);
});
}
},
@ -491,7 +496,7 @@ const buttonObj = {
return false;
},
click: (selected, context) => {
if (!table.selected || table.selected.length <= 0) {
if (!selected || selected.length <= 0) {
NotifyManager.warn('请选择要删除的记录');
} else {
$q.dialog({
@ -502,11 +507,11 @@ const buttonObj = {
}).onOk(() => {
let requestParams: any = {
method: 'DELETE',
url: (props.removeDataUrl ? props.removeDataUrl : props.dataUrl) + '/' + table.selected[0][props.rowKey],
url: (props.removeDataUrl ? props.removeDataUrl : props.dataUrl) + '/' + selected[0][props.rowKey],
};
if (props.templateGridId) {
const data = <any>[];
table.selected.forEach((item) => {
selected.forEach((item) => {
data.push(item[props.rowKey]);
});
requestParams = {
@ -658,6 +663,7 @@ const table = reactive({
},
inFullscreen: false, //
});
provide('table', table);
const dialog = reactive({
dialogTitle: '新增',
@ -822,6 +828,14 @@ const handlerMoreRowColumnTitle = () => {
});
};
const selectionComputed = computed(() => {
if (attrs.selection && attrs.selection === 'multiple') {
return 'multiple';
} else {
return 'single';
}
});
const tableHeightComputed = computed(() => {
//
const screenHeight = $q.screen.height;
@ -893,25 +907,24 @@ const tableFullscreenFun = (value) => {
};
const rowClick = (evt: any, row: any, index: any) => {
if (props.onRowClick) {
if (props.clickSelectedRow && (!attrs.selection || attrs.selection !== 'none')) {
rowClickFun(row);
}
emit('rowClick', evt, row, index);
if (selectionComputed.value === 'multiple') {
if (table.selected.findIndex((item) => item[props.rowKey] === row[props.rowKey]) < 0) {
table.selected.push(row);
} else {
rowClickFun(row);
table.selected.splice(
table.selected.findIndex((item) => item[props.rowKey] === row[props.rowKey]),
1,
);
}
};
const rowClickFun = (row: any) => {
//
if (!attrs.selection || attrs.selection === 'single') {
table.selected = [];
table.selected.push(row);
} else if (attrs.selection && attrs.selection === 'multiple') {
} else {
table.selected = [];
table.selected.push(row);
}
if (props.onRowClick) {
emit('rowClick', evt, row, index);
}
};
const rowDbClick = (evt, row, index) => {
if (props.onRowDbClick) {
emit('rowDbClick', evt, row, index);
@ -957,7 +970,7 @@ const buildQueryCriterias = (reqParams) => {
if (!isEmpty(queryFormData[item])) {
const criteria = <CriteriaType>{
fieldName: item,
operator: queryFormFieldsMap.get(item)?.hasOwnProperty.call('queryOperator') ? queryFormFieldsMap.get(item).queryOperator : OperatorTypeEnum.contains,
operator: queryFormFieldsMap.get(item).queryOperator || OperatorTypeEnum.contains,
value: queryFormData[item],
};
urlSearchParams.append('criteria', JSON.stringify(criteria));
@ -1050,10 +1063,10 @@ const onRequest = async (ops: any) => {
table.pagination.descending = ops.pagination.descending;
table.rows = responseData.content;
} else if (resp && resp.data && props.tree) {
const treeData = TreeBuilder.build(resp.data);
const treeRows = TreeBuilder.build(resp.data);
table.pagination.rowsNumber = resp.data.length;
console.info('treeData============', treeData);
table.rows = treeData;
table.pagination.rowsPerPage = 0;
table.rows = treeRows;
}
stickyHeaderColumn();
};
@ -1064,8 +1077,8 @@ const save = async () => {
const validate = await dialogFormRef.value.validate();
if (validate) {
let dialogFormData = dialogFormRef.value.getData();
if (table.selected && table.selected.length > 0) {
dialogFormData[props.rowKey] = table.selected[0][props.rowKey];
if (getSelectedRowsComputed.value && getSelectedRowsComputed.value.length > 0) {
dialogFormData[props.rowKey] = getSelectedRowsComputed.value[0][props.rowKey];
}
let submitFlag = true;
emit('addEditDataSubmitBefore', dialogFormData, (handlerRequestParams: any | boolean) => {
@ -1085,7 +1098,7 @@ const save = async () => {
? props.addDataUrl
? props.addDataUrl
: props.dataUrl
: (props.editDataUrl ? props.editDataUrl : props.dataUrl) + '/' + table.selected[0][props.rowKey],
: (props.editDataUrl ? props.editDataUrl : props.dataUrl) + '/' + getSelectedRowsComputed.value[0][props.rowKey],
};
if (props.templateGridId) {
requestParams = {
@ -1101,7 +1114,7 @@ const save = async () => {
'/' +
props.rowKey +
'/' +
table.selected[0][props.rowKey],
getSelectedRowsComputed.value[0][props.rowKey],
};
}
dialog.dialogButtons[0].loading = false;
@ -1127,20 +1140,20 @@ const save = async () => {
}
};
const onView = () => {
if (!table.selected || table.selected.length <= 0) {
if (!getSelectedRowsComputed.value || getSelectedRowsComputed.value.length <= 0) {
NotifyManager.warn('请选择要查看的记录');
} else {
viewInfo.infoArray = <any>[];
if (props.viewer.panel.fields && props.viewer.panel.fields.length > 0) {
for (let item of props.viewer.panel.fields) {
if (item.format) {
viewInfo.infoArray.push({ label: item.label, value: item.format(table.selected[0][item.name]) });
viewInfo.infoArray.push({ label: item.label, value: item.format(getSelectedRowsComputed.value[0][item.name]) });
} else {
let value = null;
if (tableColumnsMap.get(item.name) && tableColumnsMap.get(item.name).format) {
value = tableColumnsMap.get(item.name).format(table.selected[0][item.name]);
value = tableColumnsMap.get(item.name).format(getSelectedRowsComputed.value[0][item.name]);
} else {
value = table.selected[0][item.name];
value = getSelectedRowsComputed.value[0][item.name];
}
viewInfo.infoArray.push({ label: item.label, value: value });
}
@ -1148,9 +1161,9 @@ const onView = () => {
} else {
for (let item of tableColumnsMap) {
if (item[1].format) {
viewInfo.infoArray.push({ label: item[1].label, value: item[1].format(table.selected[0][item[0]]) });
viewInfo.infoArray.push({ label: item[1].label, value: item[1].format(getSelectedRowsComputed.value[0][item[0]]) });
} else {
viewInfo.infoArray.push({ label: item[1].label, value: table.selected[0][item[0]] });
viewInfo.infoArray.push({ label: item[1].label, value: getSelectedRowsComputed.value[0][item[0]] });
}
}
}
@ -1186,7 +1199,7 @@ const replaceRow = (row) => {
}
};
//
const deleteRows = (rows) => {
const removeRows = (rows) => {
rows.forEach((item) => {
table.rows.splice(
table.rows.findIndex((v) => {
@ -1208,15 +1221,26 @@ const addRow = (row, index) => {
stickyHeaderColumn();
};
const getSelectedRows = () => {
return table.selected;
const getSelectedRowsHandler = (arr, selectedRows) => {
arr.forEach((item) => {
if (table.selected.findIndex((tmp) => tmp[props.rowKey] === item[props.rowKey]) > -1) {
selectedRows.push(item);
}
if (props.tree && item.children && item.children.length > 0) {
getSelectedRowsHandler(item.children, selectedRows);
}
});
};
const getQueryFormRef = () => {
return queryFormRef;
};
const getAddEditFormRef = () => {
return dialogFormRef;
const getSelectedRowsComputed = computed(() => {
const selectedRows = <any>[];
getSelectedRowsHandler(table.rows, selectedRows);
return selectedRows;
});
//
const getSelectedRows = () => {
return getSelectedRowsComputed.value;
};
const getRows = () => {
@ -1326,10 +1350,7 @@ const stickyHeaderColumn = () => {
};
const excludeColumnNum = computed(() => {
let num = 0;
if (!attrs.selection || attrs.selection !== 'none') {
num += 1;
}
let num = 1;
if (props.sortNo) {
num += 1;
}
@ -1379,8 +1400,12 @@ const getStickyColumn = () => {
const stickyColumnArr = getStickyColumn();
const moreColumnTitleTableSelectionStyle = computed(() => {
if ((!attrs.selection || attrs.selection !== 'none') && props.leftColumnStickyNumber > 0) {
if (props.leftColumnStickyNumber > 0) {
if (props.tree) {
return 'z-index: 3;position: sticky;left: 0px;';
} else {
return 'z-index: 3;position: sticky;left: 0px;padding: 0; width: 50px;';
}
}
return '';
});
@ -1663,7 +1688,7 @@ const handlerQueryFormShowField = () => {
table.queryFormFields.push(item);
});
} else {
const rowColsNum = queryFormRef.value.getRowColsNum() * (props.queryFormRowNum || 1);
const rowColsNum = queryFormRef.value.getColsNum() * (props.queryFormRowNum || 1);
let currRowColsNum = 0;
props.queryFormFields.forEach((item) => {
if (item.hasOwnProperty('colspan')) {
@ -1692,17 +1717,39 @@ onMounted(() => {
}
});
const getQueryForm = () => {
return queryFormRef.value;
};
const getEditorDialog = () => {
return dialogRef.value;
};
const getEditorForm = () => {
return dialogFormRef.value;
};
const getViewerDrawer = () => {
return drawerRef.value;
};
const getViewerPanel = () => {
return infoRef.value;
};
defineExpose({
getSelectedRows,
getRows,
refresh,
replaceRows,
replaceRow,
deleteRows,
removeRows,
addRow,
getQueryFormRef,
getAddEditFormRef,
getQueryForm,
getEditorDialog,
getEditorForm,
getViewerDrawer,
getViewerPanel,
});
const instance = getCurrentInstance();
VueTools.expose2Instance(instance);
</script>
<style scoped lang="css">

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

@ -1,5 +1,5 @@
<template>
<q-item clickable :disable="button[0].enableIf ? !button[0].enableIf(gridProp.gridSelected) : false">
<q-item clickable :disable="button[0].enableIf ? !button[0].enableIf(gridProps.selected, gridProps.grid) : false">
<q-item-section>
<q-item-label><q-icon v-if="button[0].icon" :name="button[0].icon" left size="20px"></q-icon> {{ button[0].label }}</q-item-label>
</q-item-section>
@ -17,7 +17,7 @@
<q-item
v-close-popup
clickable
:disable="childrenBtn.enableIf ? !childrenBtn.enableIf(gridProp.gridSelected) : false"
:disable="childrenBtn.enableIf ? !childrenBtn.enableIf(gridProps.selected, gridProps.grid) : false"
@click="buttonClick(childrenBtn)"
>
<q-item-section>
@ -38,12 +38,12 @@ const props = defineProps({
return [];
},
},
gridProp: {
gridProps: {
type: Object,
default: () => {
return {
gridSelected: [],
gridRefs: {},
selected: [],
grid: undefined,
};
},
},

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

@ -13,7 +13,7 @@
outline
v-bind="btn.data[0]"
:split="btn.data[0].click ? true : false"
:disable="btn.data[0].enableIf ? !btn.data[0].enableIf(gridProp.gridSelected) : false"
:disable="btn.data[0].enableIf ? !btn.data[0].enableIf(gridProps.selected, gridProps.grid) : false"
class="class-action-item"
@click="buttonClick(btn.data[0])"
>
@ -25,14 +25,14 @@
<ChildrenBtn
v-else-if="Array.isArray(childrenBtn) && childrenBtn.length > 0"
:button="childrenBtn"
:grid-prop="gridProp"
:grid-props="gridProps"
:button-click="buttonClick"
></ChildrenBtn>
<q-item
v-else
v-close-popup
clickable
:disable="childrenBtn.enableIf ? !childrenBtn.enableIf(gridProp.gridSelected) : false"
:disable="childrenBtn.enableIf ? !childrenBtn.enableIf(gridProps.selected) : false"
@click="buttonClick(childrenBtn)"
>
<q-item-section>
@ -45,7 +45,7 @@
</q-btn-dropdown>
<q-btn
v-else
:disable="btn.data.enableIf ? !btn.data.enableIf(gridProp.gridSelected) : false"
:disable="btn.data.enableIf ? !btn.data.enableIf(gridProps.selected, gridProps.grid) : false"
no-wrap
outline
v-bind="btn.data"
@ -62,14 +62,14 @@
<ChildrenBtn
v-else-if="Array.isArray(childrenBtn.data) && childrenBtn.data.length > 0"
:button="childrenBtn.data"
:grid-prop="gridProp"
:grid-props="gridProps"
:button-click="buttonClick"
></ChildrenBtn>
<q-item
v-else
v-close-popup
clickable
:disable="childrenBtn.data.enableIf ? !childrenBtn.data.enableIf(gridProp.gridSelected) : false"
:disable="childrenBtn.data.enableIf ? !childrenBtn.data.enableIf(gridProps.selected, gridProps.grid) : false"
@click="buttonClick(childrenBtn.data)"
>
<q-item-section>
@ -100,12 +100,12 @@ const props = defineProps({
return [];
},
},
gridProp: {
gridProps: {
type: Object,
default: () => {
return {
gridSelected: [],
gridRefs: {},
selected: [],
grid: undefined,
};
},
},
@ -259,13 +259,13 @@ const buttonClick = async (button) => {
let beforeResult = true;
const context = {};
if (button.beforeClick) {
beforeResult = await button.beforeClick(props.gridProp.gridSelected, context, props.gridProp.gridRefs);
beforeResult = await button.beforeClick(props.gridProps.selected, context, props.gridProps.grid);
}
if (beforeResult && button.click) {
await button.click(props.gridProp.gridSelected, context, button._click, props.gridProp.gridRefs);
await button.click(props.gridProps.selected, context, button._click, props.gridProps.grid);
if (button.afterClick) {
nextTick(() => {
button.afterClick(props.gridProp.gridSelected, context, props.gridProp.gridRefs);
button.afterClick(props.gridProps.selected, context, props.gridProps.grid);
});
}
}

5
io.sc.platform.core.frontend/src/views/likm/Dialog.vue

@ -11,7 +11,10 @@
@hide="aaaaa"
>
<q-splitter v-model="aa" style="height: 100%">
<template #before> 11111 </template>
<template #before>
<q-input></q-input><q-input></q-input><q-input></q-input><q-input></q-input><q-input></q-input><q-input></q-input><q-input></q-input
><q-input></q-input><q-input></q-input><q-input></q-input><q-input></q-input>
</template>
<template #after> 22222 </template>
</q-splitter>
<template #buttons> <q-btn label="xxx"></q-btn> </template

13
io.sc.platform.core.frontend/src/views/likm/Form.vue

@ -18,10 +18,15 @@ const aaaa = {
name: 'name',
type: 'password',
// maxlength: 10,
required: true,
// requiredIf: () => {
// return false;
// },
requiredIf: (form) => {
console.info('form====', form.getData().age);
return false;
},
rules: [
() => {
return true;
},
],
colspan: 2,
// requiredIf: () => false,
// 'onUpdate:modelValue': (value) => {

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

@ -1,12 +1,13 @@
<template>
<div>
<component :is="aaa"></component>
<w-grid
:title="testGrid.title"
draggable
:row-key="testGrid.rowKey"
:data-url="testGrid.tableDataUrl"
sort-no
selection="multiple"
:checkbox-selection="false"
:columns="testGrid.tableColumns"
:toolbar-actions="testGrid.toolbar"
:query-form-fields="testGrid.queryForm"
@ -20,17 +21,16 @@
</template>
<script setup lang="ts">
import { ref, onMounted, nextTick, h } from 'vue';
import { QBtn } from 'quasar';
import { ref, onMounted, nextTick } from 'vue';
import { axios, Environment } from '@/platform';
import EnableIcon from '@/platform/components/grid/EnableIcon.vue';
import { IconEnum } from '@/platform/enums';
const selection = (details) => {
console.info('details====', details);
// console.info('details====', details);
};
const rowClick = (evt, row, index) => {
console.info('row====', row);
// console.info('row====', row);
};
const rowDbClick = (evt, row, index) => {
console.info('row1====', row);
@ -63,7 +63,7 @@ const testGrid = {
// context.aaa = '111';
// },
click: (selected, context, _click, gridRefs) => {
_click();
// _click();
},
afterClick: (selected, context, gridRefs) => {
gridRefs.addEditFormRef.setFieldValue('userName', '李四');
@ -103,14 +103,7 @@ const testGrid = {
label: '用户信息',
childrenColumns: [
{ name: 'loginName', label: '登录名', align: 'right' },
{
name: 'userName',
label: '用户名',
format: () => {
const a = h(QBtn, { label: 'ok' }, 'OK');
console.log(a);
},
},
{ name: 'userName', label: '用户名' },
],
},
{
@ -135,6 +128,7 @@ const testGrid = {
label: '是否可用',
align: 'center',
format: (val, row) => {
return '1<br/>2';
// return {
// _vuecomp_: true,
// type: EnableIcon,
@ -152,14 +146,14 @@ const testGrid = {
// color: val ? 'green' : 'red',
// },
// };
return {
componentsType: 'q-icon',
attrs: {
name: val ? IconEnum.是状态 : IconEnum.否状态,
color: val ? 'green' : 'red',
size: 'sm',
},
};
// return {
// componentsType: 'q-icon',
// attrs: {
// name: val ? IconEnum. : IconEnum.,
// color: val ? 'green' : 'red',
// size: 'sm',
// },
// };
// return {
// _vuecomp_: true,
// type: 'w-text',

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

@ -1,17 +1,20 @@
<template>
<div>
<w-grid
ref="gridRef"
:title="testGrid.title"
draggable
sort-no
tree
selection="multiple"
:row-key="testGrid.rowKey"
:data-url="testGrid.dataUrl"
:columns="testGrid.tableColumns"
:toolbar-actions="testGrid.toolbar"
:query-form-fields="testGrid.queryFormFields"
:query-form-cols-num="3"
:table-pagination="testGrid.pagination"
:pagination="testGrid.pagination"
@selection="selection"
></w-grid>
</div>
</template>
@ -25,6 +28,10 @@ import { IconEnum } from '@/platform/enums';
const { t } = useI18n();
const gridRef = ref();
const selection = (details) => {
console.info('details====', details);
};
const testGrid = {
title: '菜单列表',
rowKey: 'id',
@ -45,21 +52,22 @@ const testGrid = {
extend: 'add',
icon: undefined,
label: '自定义按钮',
enableIf: (selected) => {
enableIf: (selected, grid) => {
if (selected && selected.length > 0) {
return true;
}
return false;
},
// beforeClick: (selected, context, gridRefs) => {
// beforeClick: (selected, context, grid) => {
// console.info('before');
// context.aaa = '111';
// },
click: (selected, context, _click, gridRefs) => {
_click();
click: (selected, context, _click, grid) => {
_click(selected);
},
afterClick: (selected, context, gridRefs) => {
gridRefs.addEditFormRef.setFieldValue('userName', '李四');
afterClick: (selected, context, grid) => {
console.info('=grid==', grid.getEditorForm());
// gridRefs.addEditFormRef.setFieldValue('userName', '');
},
},
[
@ -79,7 +87,7 @@ const testGrid = {
'separator',
],
queryFormFields: [
{ label: '菜单名称', name: 'name', type: 'password' },
{ label: '菜单名称', name: 'name', type: 'w-password' },
{ label: '菜单类型', name: 'userName', type: 'select' },
{ label: '是否可用', name: 'enable', type: 'select' },
],

Loading…
Cancel
Save