|
|
|
import html, { getProp } from "html";
|
|
|
|
import request, { get, post } from "../../request/index.js";
|
|
|
|
import { defineAsyncComponent, ref, reactive, onMounted } 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 VueOfficeExcel from "@vue-office/excel";
|
|
|
|
import { camelCase, capitalize } from "lodash";
|
|
|
|
import { useAppStore } from "../../store/index.js";
|
|
|
|
import { ElMessage, ElMessageBox } from "element-plus";
|
|
|
|
|
|
|
|
export default {
|
|
|
|
name: "AppList",
|
|
|
|
components: {
|
|
|
|
AppForm: defineAsyncComponent(() => import("../form/index.js")),
|
|
|
|
SvgIcon: defineAsyncComponent(() => import("../../components/icon/index.js")),
|
|
|
|
AppFormInput: defineAsyncComponent(() => import("../form/form-input.js")),
|
|
|
|
VueOfficeExcel,
|
|
|
|
},
|
|
|
|
template: html`
|
|
|
|
<div v-loading="tableLoading">
|
|
|
|
<el-row>
|
|
|
|
<el-col>
|
|
|
|
<app-form
|
|
|
|
inline
|
|
|
|
mode="query"
|
|
|
|
label-position="left"
|
|
|
|
:schema="querySchema"
|
|
|
|
v-model="queryModel"
|
|
|
|
@submit="load"
|
|
|
|
:hideButton="true"
|
|
|
|
:isQueryForm="true"
|
|
|
|
v-if="querySchema"
|
|
|
|
/>
|
|
|
|
</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(selectedRows)"
|
|
|
|
>
|
|
|
|
<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)">
|
|
|
|
<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="key==='properties'">
|
|
|
|
<el-table-column :label="subKey" v-for="(subItem,subKey) in item.properties">
|
|
|
|
<template #default="scope">{{ scope.row[key][subKey] }} </template>
|
|
|
|
</el-table-column>
|
|
|
|
</template>
|
|
|
|
<template v-else-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(scope.row[key],item.oneToMany)">
|
|
|
|
<app-form-input mode="details" :schema="item" :prop="key" v-model="scope.row" />
|
|
|
|
</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]">
|
|
|
|
<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>
|
|
|
|
<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-pagination
|
|
|
|
v-if="pageModel.pageSize<pageModel.total"
|
|
|
|
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>
|
|
|
|
</div>
|
|
|
|
<el-drawer v-model="filterDrawer" 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-form inline>
|
|
|
|
<el-form-item>
|
|
|
|
<el-button type="primary" @click="columns.forEach(o=>o.checked=true)"> {{$t('selectAll')}} </el-button>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-button type="primary" @click="columns.forEach(o=>o.checked=!o.checked)">
|
|
|
|
{{$t('selectInverse')}}
|
|
|
|
</el-button>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item v-for="item in columns">
|
|
|
|
<el-checkbox v-model="item.checked" :label="item.title" size="large" />
|
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
|
|
|
</el-col>
|
|
|
|
</el-row>
|
|
|
|
</el-scrollbar>
|
|
|
|
<template #footer>
|
|
|
|
<span class="dialog-footer">
|
|
|
|
<el-button type="primary" @click="filterDrawer=false"> {{$t('confirm')}} </el-button>
|
|
|
|
</span>
|
|
|
|
</template>
|
|
|
|
</el-drawer>
|
|
|
|
<el-drawer v-model="subDrawer" destroy-on-close size="50%">
|
|
|
|
<el-scrollbar>
|
|
|
|
<app-list
|
|
|
|
v-if="subDrawer"
|
|
|
|
:controller="subListQuery.controller"
|
|
|
|
:query="subListQuery.query"
|
|
|
|
:buttons="subListQuery.buttons"
|
|
|
|
/>
|
|
|
|
</el-scrollbar>
|
|
|
|
<template #footer>
|
|
|
|
<span class="dialog-footer">
|
|
|
|
<el-button type="primary" @click="subDrawer=false"> {{$t('confirm')}} </el-button>
|
|
|
|
</span>
|
|
|
|
</template>
|
|
|
|
</el-drawer>
|
|
|
|
<el-dialog
|
|
|
|
v-model="dialogVisible"
|
|
|
|
align-center
|
|
|
|
destroy-on-close
|
|
|
|
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-scrollbar>
|
|
|
|
<template v-if="editFormMode==='create'||editFormMode==='update'||editFormMode==='details'">
|
|
|
|
<app-form
|
|
|
|
:disabled="editFormMode==='details'"
|
|
|
|
:mode="editFormMode"
|
|
|
|
ref="editFormRef"
|
|
|
|
inline
|
|
|
|
label-position="left"
|
|
|
|
:hideButton="true"
|
|
|
|
:schema="config.edit.schema"
|
|
|
|
v-model="editFormModel"
|
|
|
|
style="height:100%;"
|
|
|
|
/>
|
|
|
|
</template>
|
|
|
|
<template v-else-if="editFormMode==='export'">
|
|
|
|
<el-form :model="exportModel">
|
|
|
|
<el-form-item :label="$t('全部')">
|
|
|
|
<el-switch v-model="exportModel.includeAll" />
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item :label="$t('已删除')">
|
|
|
|
<el-switch v-model="exportModel.includeDeleted" />
|
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
|
|
|
</template>
|
|
|
|
<template v-else-if="editFormMode==='import'">
|
|
|
|
<el-form :model="importModel" inline>
|
|
|
|
<el-form-item :label="$t('部分成功')">
|
|
|
|
<el-switch v-model="importModel.partial" />
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item :label="$t('全部替换')">
|
|
|
|
<el-switch v-model="importModel.replace" />
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item :label="$t('导入模板')">
|
|
|
|
<el-link type="primary" @click="getImportTemplate">{{$t('下载')}}</el-link>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item :label="$t('文件')">
|
|
|
|
<el-upload
|
|
|
|
ref="uploadRef"
|
|
|
|
drag
|
|
|
|
accept=".xlsx"
|
|
|
|
:disabled="fileList.length===1"
|
|
|
|
:limit="1"
|
|
|
|
:auto-upload="false"
|
|
|
|
:on-change="handleChange"
|
|
|
|
>
|
|
|
|
<el-icon class="el-icon--upload"><ep-upload-filled /></el-icon>
|
|
|
|
</el-upload>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
|
|
|
</template>
|
|
|
|
<template v-else-if="editFormMode==='filter'">
|
|
|
|
<el-form :model="queryList" inline class="filter">
|
|
|
|
<el-row v-for="(item,index) in queryList">
|
|
|
|
<el-col :span="6">
|
|
|
|
<el-select v-model="item.property" :placeholder="$t('字段')">
|
|
|
|
<el-option v-for="(value, prop) in querySchema.properties" :value="prop" :label="value.title" />
|
|
|
|
</el-select>
|
|
|
|
</el-col>
|
|
|
|
<el-col :span="6">
|
|
|
|
<el-select v-model="item.operator" :placeholder="$t('操作符')">
|
|
|
|
<el-option value="{0}=@0" :label="$t('等于')" />
|
|
|
|
<el-option value="{0}!=@0" :label="$t('不等于')" />
|
|
|
|
<el-option value="{0}>@0" :label="$t('大于')" />
|
|
|
|
<el-option value="{0}>=@0" :label="$t('大于等于')" />
|
|
|
|
<el-option value="{0}<@0" :label="$t('小于')" />
|
|
|
|
<el-option value="{0}<=@0" :label="$t('小于等于')" />
|
|
|
|
<el-option value="{0}.Contains(@0)" :label="$t('包含')" />
|
|
|
|
<el-option value="{0}.StartsWith(@0)" :label="$t('开始于')" />
|
|
|
|
<el-option value="{0}.StartsWith(@0)" :label="$t('结束于')" />
|
|
|
|
</el-select>
|
|
|
|
</el-col>
|
|
|
|
<el-col :span="6">
|
|
|
|
<el-input v-model="item.value" :placeholder="$t('值')" />
|
|
|
|
</el-col>
|
|
|
|
<!-- <el-col :span="4">
|
|
|
|
<el-select v-model="item.logic" :placeholder="$t('关系')">
|
|
|
|
<el-option value="and" :label="$t('且')" />
|
|
|
|
<el-option value="or" :label="$t('或')" />
|
|
|
|
</el-select>
|
|
|
|
</el-col> -->
|
|
|
|
<el-col :span="2">
|
|
|
|
<el-button circle @click="queryList.splice(index, 1)">
|
|
|
|
<template #icon>
|
|
|
|
<ep-close />
|
|
|
|
</template>
|
|
|
|
</el-button>
|
|
|
|
</el-col>
|
|
|
|
</el-row>
|
|
|
|
<el-row>
|
|
|
|
<el-col>
|
|
|
|
<el-button circle @click="pushQueryList">
|
|
|
|
<template #icon>
|
|
|
|
<ep-plus />
|
|
|
|
</template>
|
|
|
|
</el-button>
|
|
|
|
</el-col>
|
|
|
|
</el-row>
|
|
|
|
</el-form>
|
|
|
|
</template>
|
|
|
|
<template v-else>
|
|
|
|
<slot :name="editFormMode"></slot>
|
|
|
|
</template>
|
|
|
|
</el-scrollbar>
|
|
|
|
</el-col>
|
|
|
|
</el-row>
|
|
|
|
<template #footer>
|
|
|
|
<span class="dialog-footer">
|
|
|
|
<el-button type="primary" @click="submit"> {{$t('confirm')}} </el-button>
|
|
|
|
</span>
|
|
|
|
</template>
|
|
|
|
</el-dialog>
|
|
|
|
`,
|
|
|
|
styles: html`<style>
|
|
|
|
.el-form.filter .el-col {
|
|
|
|
padding: 5px;
|
|
|
|
}
|
|
|
|
</style>`,
|
|
|
|
props: ["modelValue", "config", "querySchema", "controller", "query", "buttons"],
|
|
|
|
emits: ["command"],
|
|
|
|
setup(props, context) {
|
|
|
|
/*变量定义*/
|
|
|
|
// 配置
|
|
|
|
const config = reactive(props.config);
|
|
|
|
// 分页
|
|
|
|
const pageModel = reactive({
|
|
|
|
sizeList: [1, 50, 100],
|
|
|
|
pageIndex: 1,
|
|
|
|
pageSize: 10,
|
|
|
|
total: 0,
|
|
|
|
});
|
|
|
|
const treeProps = reactive({
|
|
|
|
children: "children",
|
|
|
|
});
|
|
|
|
const tableKey = ref(false);
|
|
|
|
const tableRef = ref(null);
|
|
|
|
const uploadRef = ref(null);
|
|
|
|
const columns = ref([]);
|
|
|
|
const filterDrawer = ref(false);
|
|
|
|
const subDrawer = ref(false);
|
|
|
|
const subListQuery = ref({});
|
|
|
|
const tableLoading = ref(true);
|
|
|
|
const selectedRows = ref([]);
|
|
|
|
const dialogVisible = ref(false);
|
|
|
|
const route = useRoute();
|
|
|
|
const router = useRouter();
|
|
|
|
const { t } = useI18n();
|
|
|
|
const appStore = useAppStore();
|
|
|
|
// 注释一下代码暂停权限验证
|
|
|
|
// const buttons = ref(props.buttons ?? route.meta.children.filter((o) => o.meta.hasPermission));
|
|
|
|
// 添加下行代码暂停权限验证
|
|
|
|
const buttons = ref(props.buttons ?? route.meta.children);
|
|
|
|
const baseUrl = props.controller ?? `${route.meta.path}`;
|
|
|
|
const queryModel = ref({});
|
|
|
|
const sortColumns = ref(new Map());
|
|
|
|
const querySchema = ref(props.querySchema);
|
|
|
|
const queryList = ref([]);
|
|
|
|
const tableSchema = ref({});
|
|
|
|
const tableData = ref([]);
|
|
|
|
const editFormRef = ref(null);
|
|
|
|
const editFormloading = ref(false);
|
|
|
|
const editFormMode = ref(null);
|
|
|
|
const editFormTitle = ref("");
|
|
|
|
const editFormSchema = ref(null);
|
|
|
|
const editFormModel = ref(null);
|
|
|
|
const exportModel = reactive({
|
|
|
|
includeAll: false,
|
|
|
|
includeDeleted: false,
|
|
|
|
});
|
|
|
|
const importModel = reactive({
|
|
|
|
partial: true,
|
|
|
|
replace: false,
|
|
|
|
});
|
|
|
|
const fileList = ref([]);
|
|
|
|
const getSortModel = (model) => {
|
|
|
|
model.orderBy
|
|
|
|
.split(",")
|
|
|
|
.map((o) => o.trim())
|
|
|
|
.filter((o) => o)
|
|
|
|
.map((o) => ({
|
|
|
|
prop: camelCase(o.split(" ")[0]),
|
|
|
|
order: (o.split(" ").filter((o) => o)[1] ?? "asc") + "ending",
|
|
|
|
}))
|
|
|
|
.forEach((o) => sortColumns.value.set(o.prop, o.order));
|
|
|
|
};
|
|
|
|
const getColumns = (schema) => {
|
|
|
|
Object.keys(schema.properties).forEach((propertyName) => {
|
|
|
|
const property = schema.properties[propertyName];
|
|
|
|
if (property.type !== "object" && property.type !== "array" && !property.hidden && property.showForList) {
|
|
|
|
columns.value.push({ name: propertyName, title: property.title, checked: true });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
const getClass = ({ row, column }) => {
|
|
|
|
if (column.property) {
|
|
|
|
column.order = sortColumns.value.get(column.property);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const sortChange = async ({ column, prop, order }) => {
|
|
|
|
if (order === null) {
|
|
|
|
sortColumns.value.delete(prop);
|
|
|
|
} else {
|
|
|
|
sortColumns.value.set(prop, order);
|
|
|
|
}
|
|
|
|
queryModel.value.orderBy = Array.from(sortColumns.value)
|
|
|
|
.map((o) => capitalize(o[0]) + (o[1] === "ascending" ? "" : ` DESC`))
|
|
|
|
.join(",");
|
|
|
|
await load();
|
|
|
|
};
|
|
|
|
const showColumn = (item, prop) => {
|
|
|
|
return (
|
|
|
|
item.type !== "object" &&
|
|
|
|
item.type !== "array" &&
|
|
|
|
!item.hidden &&
|
|
|
|
columns.value.findIndex((o) => o.name === prop && o.checked) >= 0
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleSelectionChange = (rows) => (selectedRows.value = rows);
|
|
|
|
const load = async () => {
|
|
|
|
tableLoading.value = true;
|
|
|
|
try {
|
|
|
|
const url = config.query.url;
|
|
|
|
const method = config.query.method;
|
|
|
|
//
|
|
|
|
queryModel.value = schemaToModel(config.query.schema);
|
|
|
|
queryModel.value.maxResultCount = pageModel.pageSize;
|
|
|
|
queryModel.value.skipCount = (pageModel.pageIndex - 1) * pageModel.pageSize;
|
|
|
|
//
|
|
|
|
const postData = JSON.parse(JSON.stringify(queryModel.value));
|
|
|
|
postData.filters = queryList.value.filter((o) => o.property && o.value);
|
|
|
|
if (postData.items) {
|
|
|
|
delete postData["items"];
|
|
|
|
}
|
|
|
|
if (postData.query?.id) {
|
|
|
|
delete postData.query["id"];
|
|
|
|
}
|
|
|
|
const listData = (await request(url, postData, { method })).data;
|
|
|
|
const items = listData.items;
|
|
|
|
if (tableSchema.value.isTree) {
|
|
|
|
items = listToTree(listData.items);
|
|
|
|
}
|
|
|
|
tableData.value = items;
|
|
|
|
pageModel.total = listData.totalCount;
|
|
|
|
//data.value = listData;
|
|
|
|
tableKey.value = !tableKey.value;
|
|
|
|
} catch (error) {
|
|
|
|
console.log(error);
|
|
|
|
} finally {
|
|
|
|
tableLoading.value = false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const onPageIndexChange = async () => await load();
|
|
|
|
const onPageSizeChange = async () => await load();
|
|
|
|
const click = async (item, rows) => {
|
|
|
|
editFormloading.value = true;
|
|
|
|
editFormMode.value = item.path ?? item;
|
|
|
|
context.emit("command", item, rows);
|
|
|
|
if (item.path === "index") {
|
|
|
|
//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") {
|
|
|
|
editFormModel.value = schemaToModel(config.edit.schema);
|
|
|
|
} else {
|
|
|
|
const url = format(config.edit.detailsUrl, rows[0].id);
|
|
|
|
editFormModel.value = (await request(url, null, { method: config.edit.detailsMethod })).data;
|
|
|
|
editFormModel.value.id = rows[0].id;
|
|
|
|
}
|
|
|
|
editFormTitle.value = `${t(item.path)}${config.edit.schema.title}`;
|
|
|
|
dialogVisible.value = true;
|
|
|
|
} else if (item.path === "delete") {
|
|
|
|
//delete
|
|
|
|
if (item.meta.isTop) {
|
|
|
|
// 批量删除
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
// 单个删除
|
|
|
|
const url = format(config.edit.deleteUrl, rows[0].id);
|
|
|
|
try {
|
|
|
|
await ElMessageBox.confirm("删除", "提示", {
|
|
|
|
type: "warning",
|
|
|
|
message: format("确认删除当前行数据吗?", rows[0]),
|
|
|
|
});
|
|
|
|
await request(url, null, { method: config.edit.deleteMethod });
|
|
|
|
ElMessage({
|
|
|
|
type: "info",
|
|
|
|
message: "操作完毕",
|
|
|
|
});
|
|
|
|
} catch (error) {
|
|
|
|
if (error === "cancel") {
|
|
|
|
ElMessage({
|
|
|
|
type: "info",
|
|
|
|
message: "删除取消",
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const url = `${baseUrl}/${item.path}`;
|
|
|
|
// await post(
|
|
|
|
// url,
|
|
|
|
// rows.map((o) => o.id)
|
|
|
|
// );
|
|
|
|
await load();
|
|
|
|
} else if (item.path === "export") {
|
|
|
|
//export
|
|
|
|
editFormTitle.value = `${t(item.path)}${querySchema.value?.title}`;
|
|
|
|
dialogVisible.value = true;
|
|
|
|
} else if (item.path === "import") {
|
|
|
|
//import
|
|
|
|
const url = `${baseUrl}/${item.path}`;
|
|
|
|
editFormTitle.value = `${t(item.path)}${querySchema.value?.title}`;
|
|
|
|
fileList.value = [];
|
|
|
|
dialogVisible.value = true;
|
|
|
|
} else if (item === "filter") {
|
|
|
|
editFormTitle.value = t("自定义查询");
|
|
|
|
dialogVisible.value = true;
|
|
|
|
}
|
|
|
|
editFormloading.value = false;
|
|
|
|
};
|
|
|
|
const submit = async () => {
|
|
|
|
if (editFormMode.value === "create" || editFormMode.value === "update") {
|
|
|
|
try {
|
|
|
|
const valid = await editFormRef.value.validate();
|
|
|
|
if (valid) {
|
|
|
|
editFormloading.value = true;
|
|
|
|
let url =
|
|
|
|
(editFormMode.value === "create" ? config.edit.createUrl : config.edit.updateUrl) ?? config.query.url;
|
|
|
|
if (editFormMode.value === "update") {
|
|
|
|
url = format(url, editFormModel.value.id);
|
|
|
|
}
|
|
|
|
const method = editFormMode.value === "create" ? config.edit.createMethod : config.edit.updateMethod;
|
|
|
|
const result = await request(url, editFormModel.value, { method });
|
|
|
|
if (result.errors) {
|
|
|
|
model.errors = result.errors; //??
|
|
|
|
} else {
|
|
|
|
await load();
|
|
|
|
editFormMode.value = null;
|
|
|
|
dialogVisible.value = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.log(error);
|
|
|
|
} finally {
|
|
|
|
editFormloading.value = false;
|
|
|
|
}
|
|
|
|
} else if (editFormMode.value === "details") {
|
|
|
|
dialogVisible.value = false;
|
|
|
|
editFormMode.value = null;
|
|
|
|
} else if (editFormMode.value === "export") {
|
|
|
|
const postData = JSON.parse(JSON.stringify(queryModel.value));
|
|
|
|
postData.filters = queryList.value.filter((o) => o.property && o.value);
|
|
|
|
delete postData.query["items"];
|
|
|
|
delete postData.query["id"];
|
|
|
|
const url = `${baseUrl}/${editFormMode.value}?${qs.stringify(exportModel)}`;
|
|
|
|
const response = await post(url, postData);
|
|
|
|
download(response);
|
|
|
|
dialogVisible.value = false;
|
|
|
|
} else if (editFormMode.value === "import") {
|
|
|
|
editFormloading.value = true;
|
|
|
|
const url = `${baseUrl}/${editFormMode.value}`;
|
|
|
|
const formData = new FormData();
|
|
|
|
formData.append("partial", importModel.partial);
|
|
|
|
formData.append("replace", importModel.replace);
|
|
|
|
formData.append("file", fileList.value[0]?.raw);
|
|
|
|
console.log(uploadRef.value);
|
|
|
|
const response = await post(url, formData);
|
|
|
|
editFormloading.value = false;
|
|
|
|
dialogVisible.value = false;
|
|
|
|
await load();
|
|
|
|
} else if (editFormMode.value === "filter") {
|
|
|
|
await load();
|
|
|
|
dialogVisible.value = false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const showList = (value, nav) => {
|
|
|
|
if (!subDrawer.value) {
|
|
|
|
const controller = nav.substr(0, nav.lastIndexOf(".")).toLowerCase();
|
|
|
|
const findRoute = (tree) => {
|
|
|
|
for (const item of tree) {
|
|
|
|
if (item.meta.controller === controller) {
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
if (item.children) {
|
|
|
|
return findRoute(item.children);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const targetRoute = router.getRoutes().find((o) => o.meta?.controller === controller);
|
|
|
|
subListQuery.value = {
|
|
|
|
controller,
|
|
|
|
query: { [camelCase(nav.substr(nav.lastIndexOf(".") + 1))]: value },
|
|
|
|
buttons: targetRoute.meta.buttons,
|
|
|
|
};
|
|
|
|
subDrawer.value = true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const pushQueryList = () => {
|
|
|
|
queryList.value.push({
|
|
|
|
property: "",
|
|
|
|
operator: "{0}=@0",
|
|
|
|
value: "",
|
|
|
|
logic: "and",
|
|
|
|
});
|
|
|
|
};
|
|
|
|
const download = (response) => {
|
|
|
|
const downloadUrl = window.URL.createObjectURL(response.data);
|
|
|
|
const filename = response.filename;
|
|
|
|
let link = document.createElement("a");
|
|
|
|
link.href = downloadUrl;
|
|
|
|
link.download = filename;
|
|
|
|
link.click();
|
|
|
|
window.URL.revokeObjectURL(downloadUrl);
|
|
|
|
};
|
|
|
|
const getImportTemplate = async () => {
|
|
|
|
const url = `${baseUrl}/${editFormMode.value}`;
|
|
|
|
const response = await get(url);
|
|
|
|
download(response);
|
|
|
|
};
|
|
|
|
const handleChange = (uploadFile, uploadFiles) => {
|
|
|
|
fileList.value = uploadFiles;
|
|
|
|
};
|
|
|
|
const getButtonDisabled = async (src, row) => {
|
|
|
|
if (src) {
|
|
|
|
const method = await importFunction(src);
|
|
|
|
return src.startsWith("async") ? await method(row) : method(row);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
onMounted(async () => {
|
|
|
|
if (route.meta.children?.length) {
|
|
|
|
for (const item of route.meta.children) {
|
|
|
|
if (item.meta.disabled?.constructor === String) {
|
|
|
|
item.meta.disabled = await importFunction(item.meta.disabled);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pushQueryList();
|
|
|
|
// if (!querySchema.value) {
|
|
|
|
// const vm = (await get(indexUrl)).data;
|
|
|
|
// querySchema.value = vm.schema.properties.query;
|
|
|
|
// tableSchema.value = vm.schema.properties.items.items;
|
|
|
|
// data.value = vm.model ?? schemaToModel(vm.schema);
|
|
|
|
// if (props.query) {
|
|
|
|
// Object.assign(data.value.query, props.query);
|
|
|
|
// }
|
|
|
|
// getSortModel(data.value);
|
|
|
|
// getColumns(vm.schema.properties.query);
|
|
|
|
// }
|
|
|
|
if (!config) {
|
|
|
|
//
|
|
|
|
}
|
|
|
|
getColumns(config.table.schema);
|
|
|
|
if (props.query) {
|
|
|
|
Object.assign(queryModel.value.query, props.query);
|
|
|
|
}
|
|
|
|
// getSortModel(data.value);
|
|
|
|
// getColumns(vm.schema.properties.query);
|
|
|
|
await load();
|
|
|
|
});
|
|
|
|
return {
|
|
|
|
config,
|
|
|
|
queryModel,
|
|
|
|
pageModel,
|
|
|
|
treeProps,
|
|
|
|
tableKey,
|
|
|
|
tableRef,
|
|
|
|
uploadRef,
|
|
|
|
tableLoading,
|
|
|
|
columns,
|
|
|
|
showColumn,
|
|
|
|
filterDrawer,
|
|
|
|
subDrawer,
|
|
|
|
dialogVisible,
|
|
|
|
selectedRows,
|
|
|
|
querySchema,
|
|
|
|
queryList,
|
|
|
|
tableSchema,
|
|
|
|
buttons,
|
|
|
|
tableData,
|
|
|
|
getClass,
|
|
|
|
sortChange,
|
|
|
|
getProp,
|
|
|
|
getImportTemplate,
|
|
|
|
editFormRef,
|
|
|
|
editFormloading,
|
|
|
|
editFormMode,
|
|
|
|
editFormTitle,
|
|
|
|
editFormSchema,
|
|
|
|
editFormModel,
|
|
|
|
exportModel,
|
|
|
|
importModel,
|
|
|
|
onPageSizeChange,
|
|
|
|
onPageIndexChange,
|
|
|
|
handleSelectionChange,
|
|
|
|
load,
|
|
|
|
click,
|
|
|
|
submit,
|
|
|
|
showList,
|
|
|
|
subListQuery,
|
|
|
|
pushQueryList,
|
|
|
|
fileList,
|
|
|
|
handleChange,
|
|
|
|
getButtonDisabled,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
};
|