@dongkboy 1 rok temu
rodzic
commit
5b0c72f824
2 zmienionych plików z 288 dodań i 3 usunięć
  1. 3 3
      .env.development
  2. 285 0
      src/components/complexTable/index.vue

+ 3 - 3
.env.development

@@ -4,10 +4,10 @@ VITE_APP_SETTING = true
 VITE_APP_TITLE = 租户平台
 # 接口请求地址,会设置到 axios 的 baseURL 参数上
 # VITE_APP_API_BASEURL = https://test.baoxianzhanggui.com/web-api #默认地址
-VITE_APP_API_BASEURL = http://192.168.0.253:8001  #田智
-# VITE_APP_API_BASEURL = http://192.168.0.55:8001  #董鑫
+# VITE_APP_API_BASEURL = http://192.168.0.253:8001  #田智
+VITE_APP_API_BASEURL = http://192.168.0.55:8001  #董鑫
 # VITE_APP_API_BASEURL = http://192.168.0.106:8001  #屈晨
-#VITE_APP_API_BASEURL = http://192.168.0.59:8001  #徐强
+# VITE_APP_API_BASEURL = http://192.168.0.59:8001  #徐强
 
 # 调试工具,可设置 eruda 或 vconsole,如果不需要开启则留空
 VITE_APP_DEBUG_TOOL =

+ 285 - 0
src/components/complexTable/index.vue

@@ -0,0 +1,285 @@
+<template>
+  <div class="containerTable">
+    <div class="table_box">
+      <div class="table-title-btn">
+        <slot name="table-title-btn"></slot>
+      </div>
+      <el-table ref="multipleTableRef"
+        :header-cell-style="{ 'background-color': '#F7F7F9', 'border-bottom': '1px solid #EEF1F6', 'font-size': '15px', 'color': '#333', 'padding': '10px 0' }"
+        :data="props.tableData" :height="tableHeight" :max-height="maxHeight" table-layout="fixed" style="width: 100%;"
+        @selection-change="selectionChange" @select-all="selectAllChange">
+        <!-- 空内容自定义 -->
+        <template #empty>
+          <div class="flex f-c a-c ">
+            <img src="../../assets/images/empty.png" alt="">
+            <span style="font-size: 14px;color: #909399;">暂无数据</span>
+          </div>
+        </template>
+        <el-table-column type="selection" v-if="showSelect" :selectable="selectable" width="55" fixed="left" />
+        <el-table-column type="expand" v-if="secondaryTable">
+          <template #default="props">
+            <div>
+              <el-table :data="props.row.children">
+                <el-table-column v-for="column in secondaryColumns" :key="column.prop" :prop="column.prop"
+                  :label="column.label" :sortable="column.sortable ? 'custom' : false" :width="column.width">
+                  <template #header>
+                    <slot name="search" :slotData="column"></slot>
+                  </template>
+                  <template #default="scope">
+                    <RouterLink v-if="column.component === 'RouterLink'" :to="getRouterLinkTo(scope.row, column)"
+                      class="custom-link">
+                      {{ scope.row[column.prop] }}
+                    </RouterLink>
+                    <el-tag v-else-if="column.component === 'Tag'" :type="getTagTypeAndText(scope.row, column).type">
+                      {{ getTagTypeAndText(scope.row, column).text }}
+                    </el-tag>
+                    <ImagePreview v-else-if="column.component === 'Image'" :src="getImgTo(scope.row, column)"
+                      width="50px" height="50px"></ImagePreview>
+                    <span v-else>
+                      {{ getDisplayText(scope.row, column) }}
+                    </span>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" fixed="right" :width="props.columnwidth">
+                  <template #default="scope">
+                    <slot name="secondary" :secondaryData="scope.row"></slot>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+
+          </template>
+        </el-table-column>
+        <el-table-column v-if="showIndex" type="index" label="序号" width="55" />
+        <el-table-column v-for="column in columns" :key="column.prop" :prop="column.prop" :label="column.label"
+          :sortable="column.sortable ? 'custom' : false" :width="column.width"
+          :align="column.align ? column.align : 'center'">
+          <template #header>
+            <slot name="search" :slotData="column"></slot>
+          </template>
+          <template #default="scope">
+            <RouterLink v-if="column.component === 'RouterLink'" :to="getRouterLinkTo(scope.row, column)"
+              class="custom-link">
+              {{ scope.row[column.prop] }}
+            </RouterLink>
+            <el-tag v-else-if="column.component === 'Tag'" :type="getTagTypeAndText(scope.row, column).type">
+              {{ getTagTypeAndText(scope.row, column).text }}
+            </el-tag>
+            <ImagePreview v-else-if="column.component === 'Image'" :src="getImgTo(scope.row, column)" width="50px"
+              height="50px"></ImagePreview>
+            <div v-else>
+              <div
+                v-if="typeof getDisplayText(scope.row, column) === 'string' && getDisplayText(scope.row, column).includes('\n')"
+                class="flex f-c ">
+                <span v-for="(line, index) in getDisplayText(scope.row, column).split('\n')" :key="index">{{ line
+                  }}</span>
+              </div>
+              <span v-else>
+                {{ getDisplayText(scope.row, column) }}
+              </span>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" fixed="right" :width="props.columnwidth" align="center">
+          <template #default="scope">
+            <div class="flex a-c j-c">
+              <slot name="operation" :operationData="scope.row"></slot>
+            </div>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <div class="page_box" v-if="props.pageInfo">
+      <el-pagination v-model:current-page="props.pageInfo.pageNum" v-model:page-size="props.pageInfo.pageSize"
+        :page-sizes="props.pageInfo.sizes" layout="total, sizes, prev, pager, next, jumper"
+        :total="props.pageInfo.total" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { defineProps, ref, onMounted, defineEmits } from "vue";
+import type { TableInstance } from "element-plus";
+
+interface TableRow {
+  [key: string]: any;
+}
+const emit = defineEmits(['getList', 'selectAllChange', 'selectionChange']);
+const props = defineProps<{
+  tableData: Array<TableRow>;
+  columnwidth: number,//操作栏宽度
+  secondaryTable?: boolean,//是否展示二级表格
+  columns: {
+    prop: string;
+    label: string;
+    sortable?: boolean;
+    width?: string;
+    style?: string;
+    align?: string,
+    component?: string,
+    formatter?: (row: any, column: any, cellValue: any, index: number) => any;
+
+  }[];
+  secondaryColumns?: {
+    prop: string;
+    label: string;
+    sortable?: boolean;
+    width?: string;
+    style?: string;
+    component?: string,
+    formatter?: (row: any, column: any, cellValue: any, index: number) => any;
+  }[];
+  pageInfo?: {
+    pageNum: number;
+    pageSize: number;
+    sizes: number[];
+    total: number;
+  };
+  showSelect: boolean;
+  showIndex: boolean;
+  tableheight?: (number | string),
+  maxHeight?: (number | string),
+  uniqueIdName?: string,
+}>();
+interface Row {
+  [key: string]: any; // 假设Row是一个具有任意属性的对象
+}
+interface RouterLink {
+  name: string;
+}
+const tableHeight = ref(props.tableheight); // 初始化表格高度
+const newSelectionList = ref<string[]>([]);
+const multipleTableRef = ref<TableInstance>();
+const TableData = ref<TableRow[]>();
+onMounted(() => {
+  let counter = 1;
+  TableData.value = props.tableData.map((row) => ({
+    ...row,
+    _edit: false, // 设置默认非编辑状态
+    counter: counter++
+
+  }));
+  setTimeout(() => {
+    const tableElement = multipleTableRef.value?.$el as HTMLElement;
+    if (tableElement && !props.maxHeight) {
+      const offsetTop = tableElement.offsetTop; // 获取 offsetTop
+      let height = window.innerHeight;
+      tableHeight.value = height - offsetTop - 270 + "px";
+    }
+  }, 10);
+
+
+});
+const selectable = () => true;
+const handleSizeChange = (val: number) => {
+  if (props.pageInfo) {
+    props.pageInfo.pageSize = val
+    emit('getList', props.pageInfo);
+  }
+}
+//多选
+
+const selectAllChange = (value: any[]) => {
+
+  newSelectionList.value = [];
+  if (value.length > 0) {
+    value.map(val => {
+      newSelectionList.value.push(val.id)
+    })
+  } else {
+    newSelectionList.value = [];
+  }
+  emit('selectAllChange', newSelectionList.value)
+
+}
+const selectionChange = (value: any[]) => {
+  newSelectionList.value = [];
+  if (value.length > 0) {
+    value.map(val => {
+      if (props.uniqueIdName) {
+        newSelectionList.value.push(val[props.uniqueIdName])
+      } else {
+        newSelectionList.value.push(val.id)
+      }
+    })
+  } else {
+    newSelectionList.value = [];
+  }
+  emit('selectionChange', newSelectionList.value)
+}
+const handleCurrentChange = (val: number) => {
+  if (props.pageInfo) {
+    props.pageInfo.pageNum = val
+    emit('getList', props.pageInfo);
+  }
+
+}
+//空值处理
+const displayValue = (value: any) => {
+  return value === null || value === undefined || value === '' ? '-' : value;
+}
+// 格式化内容配置
+function getRouterLinkTo(row: Row, column: any): RouterLink {
+  return column.formatter ? column.formatter(row, column, row[column.prop]) : { name: 'OrganizationAdd' };
+}
+function getImgTo(row: Row, column: any) {
+  return row[column.prop];
+}
+function getTagTypeAndText(row: Row, column: any) {
+  // 使用 formatter 返回一个对象,包含 type 和 text
+  return column.formatter ? column.formatter(row, column, row[column.prop]) : { type: 'primary', text: row[column.prop] };
+}
+function getDisplayText(row: Row, column: any): string {
+  return column.formatter ? column.formatter(row, column, row[column.prop]) : displayValue(row[column.prop]);
+}
+</script>
+<style lang="scss" scoped>
+.el-table .el-table__cell .routerlick > a {
+  color: red;
+}
+
+.containerTable {
+  display: flex;
+  flex-direction: column;
+  width: 100%;
+  height: auto;
+}
+
+.custom-link {
+  color: #0083ff;
+
+  /* 设置文字颜色 */
+  text-decoration: none;
+
+  /* 去掉下划线 */
+}
+
+.table_box {
+  flex: 1;
+  margin-bottom: 10px;
+  overflow-y: auto;
+
+  .table_item_container {
+    padding: 0;
+    margin-left: 20px;
+
+    .table_item {
+      margin: 5px 0;
+    }
+  }
+
+  .table-title-btn {
+    margin-bottom: 20px;
+
+    :deep(.el-button) {
+      margin-right: 20px;
+    }
+  }
+}
+
+.page_box {
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+}
+</style>