<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 emit = defineEmits(["update:current-node"]);
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();
};

watch(treeSelect, newVal => {
  emit("update:current-node", newVal);
});

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 scoped>
.page-container {
  display: flex;
  flex-flow: row nowrap;
  gap: 12px;
  height: calc(100vh - 120px);
  padding: 12px;
  background-color: var(--el-bg-color-page);
}

.tree-box {
  width: 200px;
  min-width: 160px;
  max-width: 260px;
  height: 100%;
  padding: 12px;
  overflow: auto;
  background-color: var(--el-bg-color);
  border-radius: 8px;
  box-shadow: 0 1px 4px rgb(0 0 0 / 5%);
}

.table-box {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-width: 0;
  height: 100%;
  padding: 12px;
  overflow: hidden;
  background-color: var(--el-bg-color);
  border-radius: 8px;
  box-shadow: 0 1px 4px rgb(0 0 0 / 5%);
}

:deep(.table-box > .table-header) {
  flex: none;
  margin-bottom: 8px;
}

:deep(.table-box > .table-main) {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

:deep(.el-pagination) {
  padding-top: 8px;
  margin-top: 0;
}
</style>
