114 lines
3.1 KiB
Vue
114 lines
3.1 KiB
Vue
<script lang="ts" setup>
|
|
import TableHeader from "../base-pageable-table/TableHeader.vue";
|
|
import TableMain from "../base-pageable-table/TableMain.vue";
|
|
import type { SearcherProp } from "../search-bar/SearchBarType";
|
|
import type { ToolButtonProp } from "../table-tool-bar/TableToolBarType";
|
|
import type { PropType } from "vue";
|
|
import { get } from "@/common/http/request";
|
|
import BaseTree from "../base-tree/BaseTree.vue";
|
|
|
|
const props = defineProps({
|
|
searchers: Array as PropType<SearcherProp[]>,
|
|
toolButtons: Array as PropType<ToolButtonProp[]>,
|
|
data: Array,
|
|
url: String,
|
|
parse: Function,
|
|
treeSideData: Array,
|
|
treeSideUrl: String,
|
|
treeSideParamName: String,
|
|
treeSideNodeName: String,
|
|
treeSideTitle: String,
|
|
});
|
|
const page = ref(1);
|
|
const pageSize = ref(20);
|
|
const total = ref(0);
|
|
const searcherParams = ref({});
|
|
const tableData = ref<any[]>([]);
|
|
const treeSelect = ref();
|
|
const updatePage = () => loadData();
|
|
const searchClick = () => loadData();
|
|
const resetClick = () => {
|
|
treeSelect.value = undefined;
|
|
loadData();
|
|
};
|
|
|
|
const loadData = async () => {
|
|
if (props.data !== undefined) {
|
|
total.value = props.data.length;
|
|
tableData.value = props.data.slice(
|
|
(page.value - 1) * pageSize.value,
|
|
Math.min(page.value * pageSize.value, props.data.length)
|
|
);
|
|
}
|
|
if (props.url !== undefined) {
|
|
const params = new URLSearchParams();
|
|
for (const [key, value] of Object.entries(searcherParams.value)) {
|
|
params.append(key, String(value));
|
|
}
|
|
params.append("page", page.value.toString());
|
|
params.append("pageSize", pageSize.value.toString());
|
|
if (
|
|
props.treeSideParamName !== undefined &&
|
|
props.treeSideNodeName !== undefined &&
|
|
treeSelect.value !== undefined
|
|
) {
|
|
params.append(props.treeSideParamName, treeSelect.value[props.treeSideNodeName]);
|
|
}
|
|
const urlRawData = await get(props.url, params).then(res => res.data);
|
|
const urlData = props.parse === undefined ? urlRawData : props.parse(urlRawData);
|
|
total.value = urlData.total;
|
|
tableData.value = urlData.records;
|
|
}
|
|
};
|
|
|
|
defineExpose({
|
|
reload: loadData,
|
|
});
|
|
|
|
onMounted(loadData);
|
|
|
|
watch(treeSelect, loadData);
|
|
</script>
|
|
<template>
|
|
<div class="page-container">
|
|
<div class="tree-box">
|
|
<BaseTree :url="treeSideUrl" :data="treeSideData" v-model:current-node="treeSelect" :title="treeSideTitle" />
|
|
</div>
|
|
<div class="table-box">
|
|
<TableHeader
|
|
:searchers="searchers"
|
|
:tool-buttons="toolButtons"
|
|
v-model:searcher-params="searcherParams"
|
|
:search-click="searchClick"
|
|
:reset-click="resetClick"
|
|
>
|
|
<template #tool-button><slot name="tool-button"></slot></template>
|
|
</TableHeader>
|
|
<TableMain
|
|
:data="tableData"
|
|
:total="total"
|
|
:update-page="updatePage"
|
|
v-model:page="page"
|
|
v-model:page-size="pageSize"
|
|
>
|
|
<template #columns><slot name="columns"></slot></template>
|
|
</TableMain>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<style>
|
|
.page-container {
|
|
display: flex;
|
|
flex-direction: row;
|
|
flex-wrap: nowrap;
|
|
}
|
|
.tree-box {
|
|
width: 17.5%;
|
|
height: calc(100vh - 120px);
|
|
overflow: auto;
|
|
}
|
|
.table-box {
|
|
width: 82%;
|
|
}
|
|
</style>
|