From cd24c776d772c7ad797891afd779b3b072293ec2 Mon Sep 17 00:00:00 2001
From: zrlibs <jesting_rr@163.com>
Date: 星期五, 21 三月 2025 17:35:07 +0800
Subject: [PATCH] fixed

---
 src/components/examples/data-table.vue |  414 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 392 insertions(+), 22 deletions(-)

diff --git a/src/components/examples/data-table.vue b/src/components/examples/data-table.vue
index d2db141..e9e2ca6 100644
--- a/src/components/examples/data-table.vue
+++ b/src/components/examples/data-table.vue
@@ -1,19 +1,196 @@
 <template>
-  <div class="data-table">
+  <div class="data-table" ref="refDataTable">
+    <div v-if="showForm" class="forms" :class="{ collapse: !formExpand }">
+      <Form :model="form" v-bind="formObject.options" ref="refForm">
+        <Row>
+          <Col
+            v-for="(col, index) in formList"
+            :key="`${index}`"
+            :span="col.span"
+          >
+            <FormItem :label="`${col.label}`">
+              <Input
+                v-if="col.type == 'input'"
+                v-model="form[col.field]"
+                size="small"
+              >
+                <template v-if="col.suffix" #suffix>
+                  <Icon :type="col.suffix" @click="col.onSuffixClick" />
+                </template>
+              </Input>
+              <DatePicker
+                v-else-if="col.type == 'daterange'"
+                type="daterange"
+                v-model="form[col.field]"
+                separator=" 鑷�"
+                size="small"
+                style="width: 100%"
+                @on-change="col.onChange"
+              ></DatePicker>
+              <DatePicker
+                v-else-if="col.type == 'date'"
+                type="date"
+                v-model="form[field]"
+                size="small"
+                @on-change="col.onChange"
+              />
+              <Select
+                v-else-if="col.type == 'select'"
+                v-model="form[col.field]"
+                size="small"
+              >
+                <Option
+                  v-for="(opt, i) in col.options"
+                  :key="i"
+                  :value="col.value"
+                  >{{ col.label }}</Option
+                >
+              </Select>
+              <Checkbox
+                v-else-if="col.type == 'checkbox'"
+                v-model="form[col.field]"
+                size="small"
+                >{{ form.label }}</Checkbox
+              >
+            </FormItem>
+          </Col>
+        </Row>
+      </Form>
+      <div class="btns">
+        <Button type="primary" size="small"
+          ><Icon type="md-settings" @click="onShowFormDialog"
+        /></Button>
+        <Button
+          v-if="formExpand"
+          v-show="showFormExpand"
+          type="primary"
+          size="small"
+          @click="formExpand = !formExpand"
+          ><Icon type="ios-arrow-up"
+        /></Button>
+        <Button
+          v-else
+          v-show="showFormExpand"
+          type="primary"
+          size="small"
+          @click="formExpand = !formExpand"
+          ><Icon type="ios-arrow-down"
+        /></Button>
+      </div>
+    </div>
+    <div class="buttons" v-if="showTopButtons">
+      <Space>
+        <Button
+          v-for="(btn, i) in buttons"
+          :key="i"
+          type="primary"
+          size="small"
+          @click="btn.onClick"
+          >{{ btn.showName }}</Button
+        >
+      </Space>
+      <Space class="ivu-fr">
+        <Poptip title="鍒嗛〉鍣ㄤ綅缃� placement="left-start">
+          <Tooltip content="璁剧疆鍒嗛〉鍣ㄤ綅缃� transfer>
+            <Button size="small"><Icon type="md-apps" /></Button>
+          </Tooltip>
+          <template #content>
+            <RadioGroup
+              v-model="paganationPlacement"
+              @on-change="onPaganationPlacementChange"
+            >
+              <Radio label="top">
+                <Icon type="md-at"></Icon>
+                <span>涓�/span>
+              </Radio>
+              <Radio label="bottom">
+                <Icon type="md-basketball"></Icon>
+                <span>涓�/span>
+              </Radio>
+            </RadioGroup>
+          </template>
+        </Poptip>
+        <Poptip popper-class="col-list" placement="left-start">
+          <Tooltip content="璋冩暣鍒� transfer>
+            <Button size="small"><Icon type="md-settings" /></Button>
+          </Tooltip>
+          <template #title>
+            <Checkbox
+              :indeterminate="columnListIndeterminate"
+              :model-value="columnCheckAll"
+              @click.prevent="onColumnCheckAll"
+              >鍏ㄩ�</Checkbox
+            >
+          </template>
+          <template #content>
+            <CheckboxGroup
+              v-model="columnShowList"
+              @on-change="onShowColumnChange"
+            >
+              <Checkbox v-for="(col, i) in columns" :key="i" :label="col.key">{{
+                toColumnLabel(col)
+              }}</Checkbox>
+            </CheckboxGroup>
+          </template>
+        </Poptip>
+        <Poptip title="璁剧疆瀛椾綋澶у皬" placement="left-start">
+          <Tooltip content="璋冩暣瀛椾綋" transfer>
+            <Button size="small"><Icon type="md-apps" /></Button>
+          </Tooltip>
+          <template #content>
+            <RadioGroup v-model="fontSize">
+              <Radio label="small">
+                <Icon type="md-at"></Icon>
+                <span>灏�/span>
+              </Radio>
+              <Radio label="default">
+                <Icon type="md-basketball"></Icon>
+                <span>涓�/span>
+              </Radio>
+              <Radio label="large">
+                <Icon type="ios-briefcase"></Icon>
+                <span>澶�/span>
+              </Radio>
+            </RadioGroup>
+          </template>
+        </Poptip>
+        <Tooltip content="鎵撳嵃" transfer>
+          <Button size="small"><Icon type="ios-print" /></Button>
+        </Tooltip>
+      </Space>
+      <Page
+        v-if="paged && paganationPlacement == 'top'"
+        class="absolute"
+        :model-value="page"
+        :total="total"
+        :page-size="limit"
+        :page-size-opts="limits"
+        show-sizer
+        show-total
+        show-elevator
+        transfer
+        simple
+        @on-change="onPageChange"
+        @on-page-size-change="onPageSizeChange"
+        @on-prev="onPrev"
+        @on-next="onNext"
+      />
+    </div>
     <Table
-      class="ivu-table-mini"
-      :row-class-name="() => ['no-wrap', 'col-gap-none']"
-      :columns="columns"
+      class="col-gap-none"
+      :row-class-name="() => ['no-wrap']"
+      :columns="tableColumns"
       :data="data"
-      :height="paged ? tableHeight - 70 : tableHeight"
-      border
+      :height="tableHeight"
       :highlight-row="highlightRow"
+      :size="fontSize"
+      @on-row-click="onRowClick"
       @on-current-change="onCurrentChange"
       @on-selection-change="onSelectionChange"
       ref="refTable"
     ></Table>
     <Page
-      v-if="paged"
+      v-if="paged && paganationPlacement == 'bottom'"
       class="text-center"
       :model-value="page"
       :total="total"
@@ -30,50 +207,173 @@
       ref="refPage"
     />
     <Spin fix :show="loading" />
+    <FormDialog
+      v-model="formDialogVisible"
+      :list="formObject.items"
+      @ok="onFormDialogOK"
+    ></FormDialog>
   </div>
 </template>
 
 <script>
 import { ref } from "vue";
+import FormDialog from "./form-dialog.vue";
 export default {
   name: "DataTable",
+  components: {
+    FormDialog,
+  },
   props: {
-    tableHeight: Number | String,
+    // 瀹瑰櫒楂樺害
+    height: Number | String,
+    // 甯歌椤堕儴鎸夐挳
+    buttons: {
+      type: Array,
+      default: () => [],
+    },
+    // 鏄惁鍒嗛〉
     paged: {
       type: Boolean,
       default: () => true,
     },
+    // 鍒楀畾涔�     columns: {
       type: Array,
       default: () => [],
     },
+    // 鏁版嵁婧�     data: {
       type: Array,
       default: () => [],
     },
+    // 鏁版嵁鎬绘暟
     total: {
       type: Number,
       default: () => 0,
     },
+    // 褰撳墠椤�     page: {
       type: Number,
       default: () => 1,
     },
+    // 姣忛〉鍑犳潯鏁版嵁
     limit: {
       type: Number,
       default: () => 10,
     },
+    // limit鍒楄〃
     limits: {
       type: Array,
       default: () => [10, 20, 30, 40],
     },
+    // 璁板綍鍔犺浇鐘舵�
     loading: Boolean,
+    // 鍗曢�妯″紡
     highlightRow: Boolean,
+    showForm: {
+      type: Boolean,
+      default: () => true,
+    },
+    showTopButtons: {
+      type: Boolean,
+      default: () => true,
+    },
+    size: {
+      type: String,
+      default: () => "default",
+    },
+    pagePlacement: {
+      type: String,
+      default: () => "bottom", // top/bottom
+    },
+    formObject: {
+      type: Object,
+      default: () => ({}),
+    },
   },
   data() {
-    return {};
+    return {
+      // 閰嶇疆鍝簺鍒楁樉绀�+      columnListIndeterminate: false,
+      columnCheckAll: true,
+      columnShowList: [],
+      // 閰嶇疆瀛椾綋
+      fontSize: this.size,
+      // 鏌ヨ琛ㄥ崟
+      // 鏌ヨ琛ㄥ崟鐨勫畾涔�+      form: {},
+      formExpand: false,
+      showFormExpand: true,
+      formDialogVisible: false,
+      formShowList: [],
+      paganationPlacement: this.pagePlacement,
+    };
+  },
+  computed: {
+    // 鏁版嵁鍒楄〃楂樺害
+    tableHeight() {
+      let formHeight = this.showForm
+        ? this.refDataTable?.querySelector(".forms")?.clientHeight + 9
+        : 0;
+      let buttonHeight = this.showTopButtons
+        ? this.refDataTable?.querySelector(".buttons")?.clientHeight
+        : 0;
+      let pageHeight =
+        this.paged && this.paganationPlacement == "bottom" ? 70 - 18 : 0;
+      return this.height - formHeight - buttonHeight - pageHeight;
+    },
+    // 瀹為檯瑕佹樉绀虹殑鍒�+    tableColumns() {
+      return this.columns.filter((col) =>
+        this.columnShowList.includes(col.key)
+      );
+    },
+    // 瀹為檯瑕佹樉绀虹殑琛ㄥ崟椤�+    formList() {
+      return (
+        this.formObject.items?.filter((l) =>
+          this.formShowList.includes(l.field)
+        ) || []
+      );
+    },
   },
   methods: {
+    toColumnLabel(col) {
+      if (col.key == "index") return "搴忓彿";
+      else if (col.key == "row_button") return "鎿嶄綔鎸夐挳";
+      else return col.title;
+    },
+    onPaganationPlacementChange() {
+      this.$nextTick(() => this.resize());
+    },
+    // 閰嶇疆鍒�鍏ㄩ�
+    onColumnCheckAll() {
+      if (this.columnListIndeterminate) {
+        this.columnCheckAll = false;
+      } else {
+        this.columnCheckAll = !this.columnCheckAll;
+      }
+      this.columnListIndeterminate = false;
+
+      if (this.columnCheckAll) {
+        this.columnShowList = this.columns.map((c) => c.key);
+      } else {
+        this.columnShowList = [];
+      }
+    },
+    // 閰嶇疆鍒�鍗曢�
+    onShowColumnChange(data) {
+      if (data.length == this.columns.length) {
+        this.columnListIndeterminate = false;
+        this.columnCheckAll = true;
+      } else if (data.length > 0) {
+        this.columnListIndeterminate = true;
+        this.columnCheckAll = false;
+      } else {
+        this.columnListIndeterminate = false;
+        this.columnCheckAll = false;
+      }
+    },
     onPageChange(page) {
       this.$emit("on-change", page);
     },
@@ -100,17 +400,8 @@
     onCurrentChange(currentRow) {
       this.$emit("on-current-change", currentRow);
     },
-    onRowClick(row, index, emit = true) {
-      this.clickedRowIndex = index;
-      this.onCurrentChange(row);
-      if (emit) this.$emit("on-row-click", row, index);
-    },
-    onCellClick(row, column, data, event) {
-      event.stopPropagation();
-      let index = row._index;
-      if (index === undefined) index = this.rows.find((r) => r.id == row.id);
-      if (column.key == "row_button") this.onRowClick(row, index, false);
-      else this.onRowClick(row, index, true);
+    onRowClick(row, index) {
+      this.$emit("on-row-click", row, index);
     },
     onSelect(selection, row) {
       this.$emit("on-select", selection, row);
@@ -127,21 +418,100 @@
     onColumnWidthResize(newWidth, oldWidth, column, event) {
       this.$emit("on-column-width-resize", newWidth, oldWidth, column, event);
     },
+    onShowFormDialog() {
+      this.formDialogVisible = true;
+    },
+    resize() {
+      this.$nextTick(() => {
+        let height = this.refForm?.$el?.clientHeight;
+        if (height < 50) {
+          this.formExpand = false;
+          this.showFormExpand = false;
+        } else {
+          this.formExpand = true;
+          this.showFormExpand = true;
+        }
+      });
+    },
+    onFormDialogOK(showList) {
+      this.formShowList = showList;
+    },
   },
   setup() {
+    const refDataTable = ref(null);
+    const refForm = ref(null);
     const refTable = ref(null);
     const refPage = ref(null);
-    return { refTable, refPage };
+    return { refDataTable, refForm, refTable, refPage };
+  },
+  watch: {
+    columns(columns) {
+      this.columnShowList = columns.map((c) => c.key);
+    },
+    ["formObject.items"](list) {
+      this.formShowList = list.map((l) => l.field);
+    },
+    formShowList() {
+      this.resize();
+    },
   },
 };
 </script>
 
-<style lang="less" scoped>
+<style lang="less">
 .data-table {
   height: 100%;
   position: relative;
+  .forms {
+    margin-bottom: 9px;
+    padding: 0 10px;
+    position: relative;
+    &.collapse {
+      height: 30px;
+      padding-right: 100px;
+      overflow: hidden;
+    }
+    .btns {
+      position: absolute;
+      right: 10px;
+      bottom: 0;
+      display: flex;
+      flex-direction: row;
+      gap: 10px;
+      z-index: 1;
+    }
+    .ivu-form .ivu-form-item-label,
+    .ivu-checkbox-wrapper {
+      font-size: 12px;
+    }
+    .ivu-input-wrapper {
+      .ivu-icon {
+        cursor: pointer;
+      }
+    }
+  }
+  .buttons {
+    padding: 0 9px;
+    line-height: 33px;
+    position: relative;
+  }
   .text-center {
     text-align: center;
   }
 }
+.col-list {
+  .ivu-checkbox-group {
+    display: flex;
+    flex-direction: column;
+  }
+}
+.ivu-page {
+  padding: 9px;
+}
+.absolute {
+  position: absolute;
+  top: 0;
+  right: 180px;
+  padding: 0px;
+}
 </style>
\ No newline at end of file

--
Gitblit v1.9.1