|
|
@ -13,7 +13,9 @@ |
|
|
|
separator="cell" |
|
|
|
:rows="table.rows" |
|
|
|
:columns="extractTableColumns" |
|
|
|
:rows-per-page-options="pagination.rowsPerPage && table.refHeightWidth.middleWidth > 600 ? table.pagination.rowsPerPageOptions : []" |
|
|
|
:rows-per-page-options=" |
|
|
|
table.pagination.rowsPerPage && pagination.rowsPerPage && table.refHeightWidth.middleWidth > 600 ? table.pagination.rowsPerPageOptions : [] |
|
|
|
" |
|
|
|
:loading="table.loading" |
|
|
|
:class="tableClassComputed" |
|
|
|
:table-style="tableHeightComputed" |
|
|
@ -73,7 +75,11 @@ |
|
|
|
</template> |
|
|
|
<template v-else> |
|
|
|
<q-tr :props="scope"> |
|
|
|
<q-th v-if="selectionComputed === 'multiple' && props.checkboxSelection && !props.tree" :style="props.tree ? '' : 'padding: 0; width: 50px'"> |
|
|
|
<q-th |
|
|
|
v-if="selectionComputed === 'multiple' && props.checkboxSelection && !props.tree" |
|
|
|
:style="props.tree ? '' : 'padding: 0; width: 50px'" |
|
|
|
auto-width |
|
|
|
> |
|
|
|
<q-checkbox v-model="scope.selected" flat |
|
|
|
/></q-th> |
|
|
|
<q-th v-else></q-th> |
|
|
@ -85,13 +91,7 @@ |
|
|
|
</template> |
|
|
|
<template #body="scope"> |
|
|
|
<template v-if="tree"> |
|
|
|
<TreeGridRow |
|
|
|
:columns-map="tableColumnsMap" |
|
|
|
:row="scope.row" |
|
|
|
:cols="scope.cols" |
|
|
|
:checkbox-selection="props.checkboxSelection" |
|
|
|
:row-key="props.rowKey" |
|
|
|
></TreeGridRow> |
|
|
|
<TreeGridRow :columns-map="tableColumnsMap" :row="scope.row" :cols="scope.cols" :grid-props="props" :row-key="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="props.checkboxSelection" class="text-center" style="padding: 0; width: 50px"> |
|
|
@ -142,7 +142,7 @@ |
|
|
|
</q-inner-loading> |
|
|
|
</template> |
|
|
|
<template #pagination="scope"> |
|
|
|
<template v-if="props.pagination.rowsPerPage || props.pagination.rowsPerPage > 0"> |
|
|
|
<template v-if="table.pagination.rowsPerPage || table.pagination.rowsPerPage > 0"> |
|
|
|
<template v-if="table.refHeightWidth.middleWidth > 600"> |
|
|
|
<q-pagination |
|
|
|
v-model="table.pagination.page" |
|
|
@ -195,7 +195,7 @@ |
|
|
|
|
|
|
|
<script setup lang="ts"> |
|
|
|
import { ref, reactive, computed, onMounted, nextTick, toRaw, useAttrs, getCurrentInstance, provide } from 'vue'; |
|
|
|
import { axios, Environment, NotifyManager, TreeBuilder, VueTools } from '@/platform'; |
|
|
|
import { axios, Environment, NotifyManager, TreeBuilder, VueTools, Tools } from '@/platform'; |
|
|
|
import { useQuasar, getCssVar, exportFile } from 'quasar'; |
|
|
|
import { IconEnum } from '@/platform/enums'; |
|
|
|
import { extractTableColumnsProps, arrayToMap, OperatorTypeEnum, isEmpty, PageStatusEnum } from '@/platform/components/utils'; |
|
|
@ -212,10 +212,8 @@ const props = defineProps({ |
|
|
|
height: { type: Number, default: 0 }, // 表格高度 |
|
|
|
title: { type: String, default: '' }, // 表格标题 |
|
|
|
autoFetchData: { type: Boolean, default: true }, // 自动加载数据 |
|
|
|
rowKey: { type: String, default: 'id' }, // 行唯一键 |
|
|
|
draggable: { type: Boolean, default: false }, // 开启行拖拽 |
|
|
|
fullScreenButton: { type: Boolean, default: true }, // 是否显示全屏按钮 |
|
|
|
templateGridId: { type: String, default: '' }, // 模板ID |
|
|
|
dataUrl: { type: String, default: '' }, // 表格数据操作请求的URL前缀 |
|
|
|
fetchDataUrl: { type: String, default: '' }, // 获取数据URL |
|
|
|
addDataUrl: { type: String, default: '' }, // 新增数据url |
|
|
@ -227,8 +225,18 @@ const props = defineProps({ |
|
|
|
leftColumnStickyNumber: { type: Number, default: 0 }, // 从左侧开始冻结列数,复选框与排序列不计算在内,目前支持1-10列。,暂时不提供了以后放到列属性中,参考el |
|
|
|
checkboxSelection: { type: Boolean, default: true }, // checkbox选择模式,默认启用 |
|
|
|
tree: { type: Boolean, default: false }, // 树形表格模式,按照层级关系构建数据并以树形展现 |
|
|
|
treeRelationship: { type: String, default: 'parent' }, // 树形表格模式的数据关系,包括:parent, children |
|
|
|
treePrimaryField: { type: String, default: 'id' }, // 树形表格模式的数据主键名 |
|
|
|
treeRelationshipField: { type: String, default: 'parent' }, // 树形表格模式的数据关系字段名 |
|
|
|
treeExpand: { type: Boolean, default: false }, // 树形表格数据加载后是否全部展开 |
|
|
|
treeExpandChildren: { type: Boolean, default: false }, // 树形表格父节点被选中时是否展开所有的子节点 |
|
|
|
queryCriteria: { |
|
|
|
// 查询条件,查询、翻页、刷新等操作都会带上的查询条件 |
|
|
|
type: Object, |
|
|
|
default: () => { |
|
|
|
return {}; |
|
|
|
}, |
|
|
|
}, |
|
|
|
columns: { |
|
|
|
type: Array, |
|
|
|
default: () => { |
|
|
@ -363,6 +371,14 @@ const dialogFormRef = ref(); |
|
|
|
const infoRef = ref(); |
|
|
|
const tableColumnsMap = arrayToMap('name', props.columns); |
|
|
|
const queryFormFieldsMap = arrayToMap('name', props.queryFormFields); |
|
|
|
const rowKey_ = 'rowKey_'; |
|
|
|
const url = { |
|
|
|
dataUrl: props.dataUrl, |
|
|
|
fetchDataUrl: props.fetchDataUrl, |
|
|
|
addDataUrl: props.addDataUrl, |
|
|
|
editDataUrl: props.editDataUrl, |
|
|
|
removeDataUrl: props.removeDataUrl, |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* 内置按钮枚举 |
|
|
@ -507,20 +523,8 @@ const buttonObj = { |
|
|
|
}).onOk(() => { |
|
|
|
let requestParams: any = { |
|
|
|
method: 'DELETE', |
|
|
|
url: (props.removeDataUrl ? props.removeDataUrl : props.dataUrl) + '/' + selected[0][props.rowKey], |
|
|
|
}; |
|
|
|
if (props.templateGridId) { |
|
|
|
const data = <any>[]; |
|
|
|
selected.forEach((item) => { |
|
|
|
data.push(item[props.rowKey]); |
|
|
|
}); |
|
|
|
requestParams = { |
|
|
|
method: 'POST', |
|
|
|
url: |
|
|
|
(props.removeDataUrl ? props.removeDataUrl : Environment.apiContextPath('api/jdbc/delete')) + '/' + props.templateGridId + '/' + props.rowKey, |
|
|
|
data: data, |
|
|
|
url: (url.removeDataUrl || url.dataUrl) + '/' + selected[0][rowKey_], |
|
|
|
}; |
|
|
|
} |
|
|
|
axios(requestParams) |
|
|
|
.then((resp) => { |
|
|
|
table.selected = []; |
|
|
@ -908,11 +912,11 @@ const tableFullscreenFun = (value) => { |
|
|
|
|
|
|
|
const rowClick = (evt: any, row: any, index: any) => { |
|
|
|
if (selectionComputed.value === 'multiple') { |
|
|
|
if (table.selected.findIndex((item) => item[props.rowKey] === row[props.rowKey]) < 0) { |
|
|
|
if (table.selected.findIndex((item) => item[rowKey_] === row[rowKey_]) < 0) { |
|
|
|
table.selected.push(row); |
|
|
|
} else { |
|
|
|
table.selected.splice( |
|
|
|
table.selected.findIndex((item) => item[props.rowKey] === row[props.rowKey]), |
|
|
|
table.selected.findIndex((item) => item[rowKey_] === row[rowKey_]), |
|
|
|
1, |
|
|
|
); |
|
|
|
} |
|
|
@ -961,9 +965,15 @@ type CriteriaType = { |
|
|
|
value: any; |
|
|
|
}; |
|
|
|
|
|
|
|
let queryCriteria = { ...props.queryCriteria }; |
|
|
|
|
|
|
|
// 构建 criteria 查询 |
|
|
|
const buildQueryCriterias = (reqParams) => { |
|
|
|
const urlSearchParams = new URLSearchParams(reqParams); |
|
|
|
// 处理默认查询条件 |
|
|
|
if (Object.keys(queryCriteria).length > 0) { |
|
|
|
urlSearchParams.append('criteria', JSON.stringify(queryCriteria)); |
|
|
|
} |
|
|
|
if (queryFormRef.value) { |
|
|
|
const queryFormData = queryFormRef.value.getData(); |
|
|
|
Object.keys(queryFormData).forEach((item) => { |
|
|
@ -997,7 +1007,7 @@ const pageChange = (value) => { |
|
|
|
table.pagination.page = value; |
|
|
|
onRequest(table); |
|
|
|
}; |
|
|
|
const requestHandle = async (ops) => { |
|
|
|
const requestHandler = async (ops) => { |
|
|
|
const reqParams: any = {}; |
|
|
|
if (props.pagination.rowsPerPage) { |
|
|
|
reqParams.page = ops.pagination.page; |
|
|
@ -1005,55 +1015,36 @@ const requestHandle = async (ops) => { |
|
|
|
} |
|
|
|
if (ops.pagination.sortBy && ops.pagination.sortBy !== '') { |
|
|
|
if (ops.pagination.descending) { |
|
|
|
reqParams.sortBy = props.templateGridId ? ops.pagination.sortBy : '-' + ops.pagination.sortBy; |
|
|
|
reqParams.sortBy = '-' + ops.pagination.sortBy; |
|
|
|
reqParams.descending = ops.pagination.descending; |
|
|
|
} else { |
|
|
|
reqParams.sortBy = ops.pagination.sortBy; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (props.templateGridId) { |
|
|
|
// 根据表格模板进行数据库表查询 |
|
|
|
reqParams.templateGridId = props.templateGridId; |
|
|
|
let queryFormDataJson = {}; |
|
|
|
if (queryFormRef.value) { |
|
|
|
const queryFormData = queryFormRef.value.getData(); |
|
|
|
Object.keys(queryFormData).forEach((item) => { |
|
|
|
if (!isEmpty(queryFormData[item])) { |
|
|
|
queryFormDataJson[item] = queryFormData[item]; |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
emit('requestDataBefore', queryFormDataJson, (handlerRequestParams: URLSearchParams | any) => { |
|
|
|
queryFormDataJson = handlerRequestParams; |
|
|
|
}); |
|
|
|
reqParams.params = JSON.stringify(queryFormDataJson); |
|
|
|
const resp = await axios.post(props.fetchDataUrl || props.dataUrl || Environment.apiContextPath('api/jdbc/list'), reqParams).catch((error) => { |
|
|
|
table.loading = false; |
|
|
|
}); |
|
|
|
return resp; |
|
|
|
} else { |
|
|
|
// 后台 RestCrudController 查询 |
|
|
|
// TODO 当前后端 criteria 查询尚未开发完成,只能使用普通实体查询,待后续开发完成替换即可。 |
|
|
|
let urlSearchParams = buildQueryCriterias(reqParams); |
|
|
|
// const urlSearchParams = buildQueryEntity(reqParams); |
|
|
|
emit('requestDataBefore', urlSearchParams, (handlerRequestParams: URLSearchParams | any) => { |
|
|
|
urlSearchParams = handlerRequestParams; |
|
|
|
}); |
|
|
|
const resp = await axios.get(props.fetchDataUrl || props.dataUrl, { params: urlSearchParams }).catch((error) => { |
|
|
|
const resp = await axios.get(url.fetchDataUrl || url.dataUrl, { params: urlSearchParams }).catch((error) => { |
|
|
|
console.info('error-------------', error); |
|
|
|
table.loading = false; |
|
|
|
}); |
|
|
|
return resp; |
|
|
|
} |
|
|
|
}; |
|
|
|
const onRequest = async (ops: any) => { |
|
|
|
table.loading = true; |
|
|
|
const resp: any = await requestHandle(ops); |
|
|
|
const resp: any = await requestHandler(ops); |
|
|
|
table.loading = false; |
|
|
|
// const result = platformRequestResultHandle($q, resp.data); |
|
|
|
if (resp && resp.data && !props.tree) { |
|
|
|
const responseData = resp.data; |
|
|
|
if (Array.isArray(responseData)) { |
|
|
|
table.rows = responseData; |
|
|
|
table.pagination.rowsNumber = responseData.length; |
|
|
|
table.pagination.rowsPerPage = 0; |
|
|
|
} else if (typeof responseData === 'object') { |
|
|
|
if (props.pagination.rowsPerPage) { |
|
|
|
table.pagination.page = table.pagination.reqPageStart === 0 ? responseData.number + 1 : responseData.number; |
|
|
|
table.pagination.rowsPerPage = responseData.size; |
|
|
@ -1062,15 +1053,28 @@ const onRequest = async (ops: any) => { |
|
|
|
table.pagination.sortBy = ops.pagination.sortBy; |
|
|
|
table.pagination.descending = ops.pagination.descending; |
|
|
|
table.rows = responseData.content; |
|
|
|
} |
|
|
|
} else if (resp && resp.data && props.tree) { |
|
|
|
const treeRows = TreeBuilder.build(resp.data); |
|
|
|
table.pagination.rowsNumber = resp.data.length; |
|
|
|
table.pagination.rowsPerPage = 0; |
|
|
|
table.rows = treeRows; |
|
|
|
} |
|
|
|
addRowKey(table.rows); |
|
|
|
stickyHeaderColumn(); |
|
|
|
}; |
|
|
|
|
|
|
|
const addRowKey = (rows: []) => { |
|
|
|
if (rows && rows.length > 0) { |
|
|
|
rows.forEach((item) => { |
|
|
|
item[rowKey_] = Tools.uuid(); |
|
|
|
if (props.tree && item.children && item.children.length > 0) { |
|
|
|
addRowKey(item.children); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
const save = async () => { |
|
|
|
dialog.dialogButtons[0].loading = true; |
|
|
|
const formStatus = dialogFormRef.value.getStatus(); |
|
|
@ -1078,7 +1082,7 @@ const save = async () => { |
|
|
|
if (validate) { |
|
|
|
let dialogFormData = dialogFormRef.value.getData(); |
|
|
|
if (getSelectedRowsComputed.value && getSelectedRowsComputed.value.length > 0) { |
|
|
|
dialogFormData[props.rowKey] = getSelectedRowsComputed.value[0][props.rowKey]; |
|
|
|
dialogFormData[rowKey_] = getSelectedRowsComputed.value[0][rowKey_]; |
|
|
|
} |
|
|
|
let submitFlag = true; |
|
|
|
emit('addEditDataSubmitBefore', dialogFormData, (handlerRequestParams: any | boolean) => { |
|
|
@ -1095,28 +1099,11 @@ const save = async () => { |
|
|
|
data: dialogFormData, |
|
|
|
url: |
|
|
|
formStatus === PageStatusEnum.新增 |
|
|
|
? props.addDataUrl |
|
|
|
? props.addDataUrl |
|
|
|
: props.dataUrl |
|
|
|
: (props.editDataUrl ? props.editDataUrl : props.dataUrl) + '/' + getSelectedRowsComputed.value[0][props.rowKey], |
|
|
|
}; |
|
|
|
if (props.templateGridId) { |
|
|
|
requestParams = { |
|
|
|
method: 'POST', |
|
|
|
headers: { 'content-type': 'application/json;charset=utf-8;' }, |
|
|
|
data: dialogFormData, |
|
|
|
url: |
|
|
|
formStatus === PageStatusEnum.新增 |
|
|
|
? (props.addDataUrl ? props.addDataUrl : Environment.apiContextPath('api/jdbc/add')) + '/' + props.templateGridId |
|
|
|
: (props.editDataUrl ? props.editDataUrl : Environment.apiContextPath('api/jdbc/edit')) + |
|
|
|
'/' + |
|
|
|
props.templateGridId + |
|
|
|
'/' + |
|
|
|
props.rowKey + |
|
|
|
'/' + |
|
|
|
getSelectedRowsComputed.value[0][props.rowKey], |
|
|
|
? url.addDataUrl |
|
|
|
? url.addDataUrl |
|
|
|
: url.dataUrl |
|
|
|
: (url.editDataUrl ? url.editDataUrl : url.dataUrl) + '/' + getSelectedRowsComputed.value[0][rowKey_], |
|
|
|
}; |
|
|
|
} |
|
|
|
dialog.dialogButtons[0].loading = false; |
|
|
|
axios(requestParams) |
|
|
|
.then((resp) => { |
|
|
@ -1187,12 +1174,13 @@ const wrapCsvValue = (val, formatFn, row) => { |
|
|
|
// 替换全部行 |
|
|
|
const replaceRows = (rows: any) => { |
|
|
|
table.rows = rows; |
|
|
|
addRowKey(table.rows); |
|
|
|
stickyHeaderColumn(); |
|
|
|
}; |
|
|
|
// 替换单行数据 |
|
|
|
const replaceRow = (row) => { |
|
|
|
for (let i = 0; i < table.rows.length; i++) { |
|
|
|
if (row[props.rowKey] === table.rows[i][props.rowKey]) { |
|
|
|
if (row[rowKey_] === table.rows[i][rowKey_]) { |
|
|
|
table.rows[i] = { ...table.rows[i], ...row }; |
|
|
|
break; |
|
|
|
} |
|
|
@ -1203,7 +1191,7 @@ const removeRows = (rows) => { |
|
|
|
rows.forEach((item) => { |
|
|
|
table.rows.splice( |
|
|
|
table.rows.findIndex((v) => { |
|
|
|
return v[props.rowKey] === item[props.rowKey]; |
|
|
|
return v[rowKey_] === item[rowKey_]; |
|
|
|
}), |
|
|
|
1, |
|
|
|
); |
|
|
@ -1218,12 +1206,13 @@ const addRow = (row, index) => { |
|
|
|
} else { |
|
|
|
table.rows.splice(index, 0, row); |
|
|
|
} |
|
|
|
addRowKey(table.rows); |
|
|
|
stickyHeaderColumn(); |
|
|
|
}; |
|
|
|
|
|
|
|
const getSelectedRowsHandler = (arr, selectedRows) => { |
|
|
|
arr.forEach((item) => { |
|
|
|
if (table.selected.findIndex((tmp) => tmp[props.rowKey] === item[props.rowKey]) > -1) { |
|
|
|
if (table.selected.findIndex((tmp) => tmp[rowKey_] === item[rowKey_]) > -1) { |
|
|
|
selectedRows.push(item); |
|
|
|
} |
|
|
|
if (props.tree && item.children && item.children.length > 0) { |
|
|
@ -1732,6 +1721,44 @@ const getViewerDrawer = () => { |
|
|
|
const getViewerPanel = () => { |
|
|
|
return infoRef.value; |
|
|
|
}; |
|
|
|
const setQueryCriteria = (criteria) => { |
|
|
|
queryCriteria = criteria; |
|
|
|
}; |
|
|
|
const setQueryCriteriaFieldValueHandler = (criteria, fieldName, fieldValue) => { |
|
|
|
if (criteria.criteria && criteria.criteria.length > 0) { |
|
|
|
criteria.criteria.forEach((item) => { |
|
|
|
if (!item.criteria && item.fieldName && item.fieldName === fieldName) { |
|
|
|
item.value = fieldValue; |
|
|
|
} else { |
|
|
|
setQueryCriteriaFieldValueHandler(item.criteria, fieldName, fieldValue); |
|
|
|
} |
|
|
|
}); |
|
|
|
} else if (criteria.fieldName && criteria.fieldName === fieldName) { |
|
|
|
criteria.value = fieldValue; |
|
|
|
} |
|
|
|
}; |
|
|
|
const setQueryCriteriaFieldValue = (fieldName, fieldValue) => { |
|
|
|
if (Object.keys(queryCriteria).length === 0) { |
|
|
|
console.error('queryCriteria未设置,无法执行setQueryCriteriaFieldValue方法'); |
|
|
|
return; |
|
|
|
} |
|
|
|
setQueryCriteriaFieldValueHandler(queryCriteria, fieldName, fieldValue); |
|
|
|
}; |
|
|
|
const setDataUrl = (url_) => { |
|
|
|
url.dataUrl = url_; |
|
|
|
}; |
|
|
|
const setFetchDataUrl = (url_) => { |
|
|
|
url.fetchDataUrl = url_; |
|
|
|
}; |
|
|
|
const setAddDataUrl = (url_) => { |
|
|
|
url.addDataUrl = url_; |
|
|
|
}; |
|
|
|
const setEditDataUrl = (url_) => { |
|
|
|
url.editDataUrl = url_; |
|
|
|
}; |
|
|
|
const setRemoveDataUrl = (url_) => { |
|
|
|
url.removeDataUrl = url_; |
|
|
|
}; |
|
|
|
|
|
|
|
defineExpose({ |
|
|
|
getSelectedRows, |
|
|
@ -1746,6 +1773,13 @@ defineExpose({ |
|
|
|
getEditorForm, |
|
|
|
getViewerDrawer, |
|
|
|
getViewerPanel, |
|
|
|
setQueryCriteria, |
|
|
|
setQueryCriteriaFieldValue, |
|
|
|
setDataUrl, |
|
|
|
setFetchDataUrl, |
|
|
|
setAddDataUrl, |
|
|
|
setEditDataUrl, |
|
|
|
setRemoveDataUrl, |
|
|
|
}); |
|
|
|
|
|
|
|
const instance = getCurrentInstance(); |
|
|
|