|
|
@ -1,10 +1,9 @@ |
|
|
|
import html, { getProp } from "html"; |
|
|
|
import request, { get, getUrl, post } from "../../request/index.js"; |
|
|
|
import { defineAsyncComponent, ref, reactive, onMounted, watch } from "vue"; |
|
|
|
import request, { getUrl } from "../../request/index.js"; |
|
|
|
import { defineAsyncComponent, ref, reactive, onMounted, watch, nextTick } from "vue"; |
|
|
|
import { useRoute, useRouter } from "vue-router"; |
|
|
|
import { useI18n } from "vue-i18n"; |
|
|
|
import { listToTree, schemaToModel, importFunction, format } from "../../utils/index.js"; |
|
|
|
import qs from "../../lib/qs/shim.js"; |
|
|
|
import { camelCase, capitalize } from "lodash"; |
|
|
|
import { ElMessage, ElMessageBox } from "element-plus"; |
|
|
|
|
|
|
@ -17,153 +16,146 @@ export default { |
|
|
|
AppFormInput: defineAsyncComponent(() => import("../form/form-input.js")), |
|
|
|
}, |
|
|
|
template: html` |
|
|
|
<div v-loading="tableLoading"> |
|
|
|
<el-row> |
|
|
|
<el-col> |
|
|
|
<app-form inline mode="query" label-position="left" :schema="config.query.schema" v-model="queryModel" @submit="load" :hideButton="true" :isQueryForm="true"> |
|
|
|
<template v-for="item in filterList.filter(o=>!o.hidden&&o.readOnly)"> |
|
|
|
<el-form-item :label="config.edit.schema.properties[item.column].title"> |
|
|
|
<app-form-input v-model="item" :schema="config.edit.schema.properties[item.column]" prop="value" /> |
|
|
|
</el-form-item> |
|
|
|
</template> |
|
|
|
</app-form> |
|
|
|
</el-col> |
|
|
|
</el-row> |
|
|
|
<el-row style="padding-bottom:20px;"> |
|
|
|
<el-col> |
|
|
|
<template v-for="item in buttons"> |
|
|
|
<el-button |
|
|
|
:class="item.meta.htmlClass??'el-button--primary'" |
|
|
|
v-if="item.meta.isTop" |
|
|
|
@click="click(item,selectedRows)" |
|
|
|
:disabled="item.meta.disabled && item.meta.disabled.constructor === Function && item.meta.disabled(selectedRows,queryModel)" |
|
|
|
> |
|
|
|
<el-icon v-if="item.meta.icon"><svg-icon :name="item.meta.icon" /></el-icon> |
|
|
|
<span>{{item.meta.title}}</span> |
|
|
|
</el-button> |
|
|
|
</template> |
|
|
|
<el-button @click="click('filter',selectedRows)" v-if="config.query.hasFilter"> |
|
|
|
<el-icon><ep-filter /></el-icon> |
|
|
|
<span>{{$t('筛选')}}</span> |
|
|
|
</el-button> |
|
|
|
<slot name="tableButtons" :rows="selectedRows"></slot> |
|
|
|
</el-col> |
|
|
|
</el-row> |
|
|
|
<el-row> |
|
|
|
<el-col> |
|
|
|
<el-scrollbar> |
|
|
|
<el-table |
|
|
|
:key="tableKey" |
|
|
|
ref="tableRef" |
|
|
|
:tree-props="treeProps" |
|
|
|
:data="tableData" |
|
|
|
@selection-change="handleSelectionChange" |
|
|
|
@sort-change="sortChange" |
|
|
|
:header-cell-class-name="getClass" |
|
|
|
row-key="id" |
|
|
|
table-layout="auto" |
|
|
|
border |
|
|
|
fit |
|
|
|
> |
|
|
|
<el-table-column fixed="left" type="selection" :selectable="config.table.selectable" /> |
|
|
|
<el-table-column type="index" :label="$t('rowIndex')"> |
|
|
|
<template #default="scope"> {{ (pageModel.pageIndex - 1) * pageModel.pageSize + scope.$index + 1 }} </template> |
|
|
|
</el-table-column> |
|
|
|
<template v-for="(item,key) in config.table.schema.properties"> |
|
|
|
<template v-if="item.navigation"> |
|
|
|
<el-table-column :prop="key" :label="item.title"> |
|
|
|
<template #default="scope">{{getProp(scope.row,item.navigation)}}</template> |
|
|
|
</el-table-column> |
|
|
|
<div class="c-list" v-loading="tableLoading" style="height:100%;"> |
|
|
|
<div style="height:calc(100% - 52px);"> |
|
|
|
<el-scrollbar ref="listScrollbarRef" :always="true" style="height:100%;"> |
|
|
|
<el-row style="padding-bottom:20px;"> |
|
|
|
<el-col> |
|
|
|
<app-form inline mode="query" label-position="left" :schema="config.query.schema" v-model="queryModel" @submit="load" :hideButton="true" :isQueryForm="true"> |
|
|
|
<template v-for="item in filterList.filter(o=>!o.hidden&&o.readOnly)"> |
|
|
|
<el-form-item :label="config.edit.schema.properties[item.column].title"> |
|
|
|
<app-form-input v-model="item" :schema="config.edit.schema.properties[item.column]" prop="value" /> |
|
|
|
</el-form-item> |
|
|
|
</template> |
|
|
|
<template v-else-if="item.oneToMany"> |
|
|
|
<el-table-column :prop="key" :label="item.title"> |
|
|
|
</app-form> |
|
|
|
<template v-for="item in buttons"> |
|
|
|
<el-button |
|
|
|
:class="item.meta.htmlClass??'el-button--primary'" |
|
|
|
v-if="item.meta.isTop" |
|
|
|
@click="click(item,selectedRows)" |
|
|
|
:disabled="item.meta.disabled && item.meta.disabled.constructor === Function && item.meta.disabled(selectedRows,queryModel)" |
|
|
|
> |
|
|
|
<el-icon v-if="item.meta.icon"><svg-icon :name="item.meta.icon" /></el-icon> |
|
|
|
<span>{{item.meta.title}}</span> |
|
|
|
</el-button> |
|
|
|
</template> |
|
|
|
<el-button @click="click('filter',selectedRows)" v-if="config.query.hasFilter"> |
|
|
|
<el-icon><ep-filter /></el-icon> |
|
|
|
<span>{{$t('筛选')}}</span> |
|
|
|
</el-button> |
|
|
|
<slot name="tableButtons" :rows="selectedRows"></slot> |
|
|
|
</el-col> |
|
|
|
</el-row> |
|
|
|
<el-table |
|
|
|
:key="tableKey" |
|
|
|
ref="tableRef" |
|
|
|
:tree-props="treeProps" |
|
|
|
:data="tableData" |
|
|
|
@selection-change="handleSelectionChange" |
|
|
|
@sort-change="sortChange" |
|
|
|
:header-cell-class-name="getClass" |
|
|
|
row-key="id" |
|
|
|
table-layout="auto" |
|
|
|
border |
|
|
|
fit |
|
|
|
style="width:calc(100% - 26px);" |
|
|
|
> |
|
|
|
<el-table-column fixed="left" type="selection" :selectable="config.table.selectable" /> |
|
|
|
<el-table-column type="index" :label="$t('rowIndex')"> |
|
|
|
<template #default="scope"> {{ (pageModel.pageIndex - 1) * pageModel.pageSize + scope.$index + 1 }} </template> |
|
|
|
</el-table-column> |
|
|
|
<template v-for="(item,key) in config.table.schema.properties"> |
|
|
|
<template v-if="item.navigation"> |
|
|
|
<el-table-column :prop="key" :label="item.title"> |
|
|
|
<template #default="scope">{{getProp(scope.row,item.navigation)}}</template> |
|
|
|
</el-table-column> |
|
|
|
</template> |
|
|
|
<template v-else-if="item.oneToMany"> |
|
|
|
<el-table-column :prop="key" :label="item.title"> |
|
|
|
<template #default="scope"> |
|
|
|
<el-link type="primary" @click="showList({[key]:scope.row[key]},item.oneToMany,item.config)"> |
|
|
|
<app-form-input mode="details" :schema="item" :prop="key" v-model="scope.row" /> |
|
|
|
</el-link> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
</template> |
|
|
|
<template v-else-if="item.link"> |
|
|
|
<el-table-column :prop="key" :label="item.title"> |
|
|
|
<template #default="scope"> |
|
|
|
<el-link type="primary" @click="click({path:key},[scope.row])"> {{scope.row[key]}} </el-link> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
</template> |
|
|
|
<template v-else> |
|
|
|
<template v-if="showColumn(item,key)"> |
|
|
|
<el-table-column :prop="key" sortable="custom" :sort-orders="['descending', 'ascending', null]" :filters="getFilters(item,key)"> |
|
|
|
<template #header="scope">{{item.title}}</template> |
|
|
|
<template #default="scope"> |
|
|
|
<el-link type="primary" @click="showList({[key]:scope.row[key]},item.oneToMany,item.config)"> |
|
|
|
<app-form-input mode="details" :schema="item" :prop="key" v-model="scope.row" /> |
|
|
|
</el-link> |
|
|
|
<app-form-input mode="details" :schema="item" :prop="key" v-model="scope.row" /> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
</template> |
|
|
|
<template v-else-if="item.link"> |
|
|
|
<el-table-column :prop="key" :label="item.title"> |
|
|
|
</template> |
|
|
|
<template v-if="item.type==='object'"> |
|
|
|
<template v-for="(item2,key2) in item['properties']"> |
|
|
|
<el-table-column :prop="key+'.'+key2"> |
|
|
|
<template #header="scope">{{item2.title}}</template> |
|
|
|
<template #default="scope"> |
|
|
|
<el-link type="primary" @click="click({path:key},[scope.row])"> {{scope.row[key]}} </el-link> |
|
|
|
<app-form-input mode="details" :schema="item2" :prop="key+'.'+key2" v-model="scope.row[key]" /> |
|
|
|
{{scope.row[key][key2]}} |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
</template> |
|
|
|
<template v-else> |
|
|
|
<template v-if="showColumn(item,key)"> |
|
|
|
<el-table-column :prop="key" sortable="custom" :sort-orders="['descending', 'ascending', null]" :filters="getFilters(item,key)"> |
|
|
|
<template #header="scope">{{item.title}}</template> |
|
|
|
<template #default="scope"> |
|
|
|
<app-form-input mode="details" :schema="item" :prop="key" v-model="scope.row" /> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
<template v-if="item.type==='object'"> |
|
|
|
<template v-for="(item2,key2) in item['properties']"> |
|
|
|
<el-table-column :prop="key+'.'+key2"> |
|
|
|
<template #header="scope">{{item2.title}}</template> |
|
|
|
<template #default="scope"> |
|
|
|
<app-form-input mode="details" :schema="item2" :prop="key+'.'+key2" v-model="scope.row[key]" /> |
|
|
|
{{scope.row[key][key2]}} |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
<slot name="columns"></slot> |
|
|
|
<el-table-column fixed="right"> |
|
|
|
<template #header> |
|
|
|
<el-button @click="filterDrawer = true"> |
|
|
|
{{$t('operations')}} |
|
|
|
<el-icon class="el-icon--right"><ep-filter /></el-icon> |
|
|
|
</el-button> |
|
|
|
</template> |
|
|
|
<template #default="scope"> |
|
|
|
<div class="flex"> |
|
|
|
<template v-for="item in buttons"> |
|
|
|
<el-button |
|
|
|
:class="item.meta.htmlClass??'el-button--primary'" |
|
|
|
v-if="!item.meta.isTop" |
|
|
|
@click="click(item,[scope.row])" |
|
|
|
:disabled="item.meta.disabled && item.meta.disabled(scope.row)" |
|
|
|
> |
|
|
|
<el-icon v-if="item.meta.icon"><svg-icon :name="item.meta.icon" /></el-icon> |
|
|
|
<span>{{item.meta.title}}</span> |
|
|
|
</el-button> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
<slot name="rowButtons" :rows="[scope.row]"></slot> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
<slot name="columns"></slot> |
|
|
|
<el-table-column fixed="right"> |
|
|
|
<template #header> |
|
|
|
<el-button @click="filterDrawer = true"> |
|
|
|
{{$t('operations')}} |
|
|
|
<el-icon class="el-icon--right"><ep-filter /></el-icon> |
|
|
|
</el-button> |
|
|
|
</template> |
|
|
|
<template #default="scope"> |
|
|
|
<div class="flex"> |
|
|
|
<template v-for="item in buttons"> |
|
|
|
<el-button |
|
|
|
:class="item.meta.htmlClass??'el-button--primary'" |
|
|
|
v-if="!item.meta.isTop" |
|
|
|
@click="click(item,[scope.row])" |
|
|
|
:disabled="item.meta.disabled && item.meta.disabled(scope.row)" |
|
|
|
> |
|
|
|
<el-icon v-if="item.meta.icon"><svg-icon :name="item.meta.icon" /></el-icon> |
|
|
|
<span>{{item.meta.title}}</span> |
|
|
|
</el-button> |
|
|
|
</template> |
|
|
|
<slot name="rowButtons" :rows="[scope.row]"></slot> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
</el-table> |
|
|
|
</el-scrollbar> |
|
|
|
</el-col> |
|
|
|
</el-row> |
|
|
|
<el-row> |
|
|
|
<el-col> |
|
|
|
</el-table-column> |
|
|
|
</el-table> |
|
|
|
</el-scrollbar> |
|
|
|
</div> |
|
|
|
<div style="height:52px;padding-top:20px;"> |
|
|
|
<el-scrollbar> |
|
|
|
<el-pagination |
|
|
|
v-model:currentPage="pageModel.pageIndex" |
|
|
|
v-model:page-size="pageModel.pageSize" |
|
|
|
:total="pageModel.total" |
|
|
|
:page-sizes="pageModel.sizeList" |
|
|
|
class="justify-end" |
|
|
|
:background="true" |
|
|
|
layout="total, sizes, prev, pager, next, jumper" |
|
|
|
@size-change="onPageSizeChange" |
|
|
|
@current-change="onPageIndexChange" |
|
|
|
style="margin-top:20px" |
|
|
|
/> |
|
|
|
</el-col> |
|
|
|
</el-row> |
|
|
|
</el-scrollbar> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<el-drawer v-model="filterDrawer" :close-on-click-modal="false" destroy-on-close @close="tableRef.doLayout()"> |
|
|
|
<template #header> <span class="el-dialog__title"> {{$t('filter')}} </span> </template> |
|
|
|
<el-scrollbar> |
|
|
|
<el-row> |
|
|
|
<el-col style="max-height:calc(100vh - 180px);"> |
|
|
|
<el-col style="max-height:calc(100% - 180px);"> |
|
|
|
<el-form inline> |
|
|
|
<el-form-item> |
|
|
|
<el-button type="primary" @click="columns.forEach(o=>o.checked=true)"> {{$t('selectAll')}} </el-button> |
|
|
@ -197,7 +189,7 @@ export default { |
|
|
|
<el-dialog v-model="dialogVisible" align-center destroy-on-close :close-on-click-modal="false" style="width:auto;min-width:500px;max-width:1000px;"> |
|
|
|
<template #header> <span class="el-dialog__title"> {{editFormTitle}} </span> </template> |
|
|
|
<el-row v-loading="editFormloading"> |
|
|
|
<el-col style="max-height:calc(100vh - 180px );min-height:100%;"> |
|
|
|
<el-col style="max-height:calc(100% - 180px );min-height:100%;"> |
|
|
|
<el-scrollbar> |
|
|
|
<template v-if="editFormMode==='create'||editFormMode==='update'||editFormMode==='details'"> |
|
|
|
<app-form |
|
|
@ -326,6 +318,7 @@ export default { |
|
|
|
props: ["modelValue", "config", "querySchema", "query", "buttons"], |
|
|
|
emits: ["command"], |
|
|
|
setup(props, context) { |
|
|
|
const listScrollbarRef = ref(null); |
|
|
|
/*变量定义*/ |
|
|
|
// 配置
|
|
|
|
const config = reactive(props.config); |
|
|
@ -466,6 +459,10 @@ export default { |
|
|
|
pageModel.total = listData.totalCount; |
|
|
|
//data.value = listData;
|
|
|
|
tableKey.value = !tableKey.value; |
|
|
|
nextTick(() => { |
|
|
|
tableRef.value.doLayout(); |
|
|
|
nextTick(() => listScrollbarRef.value.update()); |
|
|
|
}); |
|
|
|
} catch (error) { |
|
|
|
console.log(error); |
|
|
|
} finally { |
|
|
@ -483,13 +480,6 @@ export default { |
|
|
|
if (item.path === "query") { |
|
|
|
//list
|
|
|
|
await load(); |
|
|
|
} else if (item.path === "details") { |
|
|
|
//details
|
|
|
|
const url = `${baseUrl}/${item.path}?${qs.stringify({ id: rows[0].id })}`; |
|
|
|
editFormSchema.value = (await get(url)).data; |
|
|
|
editFormModel.value = (await post(url)).data; |
|
|
|
editFormTitle.value = `${config.edit.schema.title}${t("details")}`; |
|
|
|
dialogVisible.value = true; |
|
|
|
} else if (item.path === "create" || item.path === "update") { |
|
|
|
//create
|
|
|
|
if (item.path === "create") { |
|
|
@ -519,17 +509,11 @@ export default { |
|
|
|
rows.map((o) => o.id), |
|
|
|
{ method: config.edit.deleteMethod } |
|
|
|
); |
|
|
|
if (!response.errors) { |
|
|
|
ElMessage({ |
|
|
|
type: "info", |
|
|
|
message: "操作完毕", |
|
|
|
}); |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
if (error === "cancel") { |
|
|
|
ElMessage({ |
|
|
|
type: "info", |
|
|
|
message: "删除取消", |
|
|
|
message: "操作取消", |
|
|
|
}); |
|
|
|
} |
|
|
|
} finally { |
|
|
@ -542,15 +526,11 @@ export default { |
|
|
|
type: "warning", |
|
|
|
}); |
|
|
|
await request(url, null, { method: config.edit.deleteMethod }); |
|
|
|
ElMessage({ |
|
|
|
type: "info", |
|
|
|
message: "操作完毕", |
|
|
|
}); |
|
|
|
} catch (error) { |
|
|
|
if (error === "cancel") { |
|
|
|
ElMessage({ |
|
|
|
type: "info", |
|
|
|
message: "删除取消", |
|
|
|
message: "操作取消", |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
@ -699,11 +679,6 @@ export default { |
|
|
|
link.click(); |
|
|
|
window.URL.revokeObjectURL(downloadUrl); |
|
|
|
}; |
|
|
|
const getImportTemplate = async () => { |
|
|
|
const url = `${baseUrl}/${editFormMode.value}`; |
|
|
|
const response = await get(url); |
|
|
|
download(url, response.filename); |
|
|
|
}; |
|
|
|
const getButtonDisabled = async (src, row) => { |
|
|
|
if (src) { |
|
|
|
const method = await importFunction(src); |
|
|
@ -719,10 +694,6 @@ export default { |
|
|
|
value: null, |
|
|
|
}); |
|
|
|
}; |
|
|
|
const logic = [ |
|
|
|
{ value: "and", label: "且" }, |
|
|
|
{ value: "or", label: "或" }, |
|
|
|
]; |
|
|
|
const operators = [ |
|
|
|
{ |
|
|
|
value: "equal", |
|
|
@ -825,13 +796,11 @@ export default { |
|
|
|
result = method(); |
|
|
|
} |
|
|
|
if (!result.errors) { |
|
|
|
await ElMessage({ |
|
|
|
type: "info", |
|
|
|
message: successMessage, |
|
|
|
}); |
|
|
|
if (reload) { |
|
|
|
pageModel.pageIndex = 1; |
|
|
|
await load(); |
|
|
|
if (!result.data?.code || result.data.code === 200) { |
|
|
|
if (reload) { |
|
|
|
pageModel.pageIndex = 1; |
|
|
|
await load(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
@ -865,6 +834,7 @@ export default { |
|
|
|
} |
|
|
|
}); |
|
|
|
return { |
|
|
|
listScrollbarRef, |
|
|
|
load, |
|
|
|
action, |
|
|
|
config, |
|
|
@ -890,7 +860,6 @@ export default { |
|
|
|
getClass, |
|
|
|
sortChange, |
|
|
|
getProp, |
|
|
|
getImportTemplate, |
|
|
|
importFormRef, |
|
|
|
editFormRef, |
|
|
|
editFormloading, |
|
|
|