grid-control.tsx 6.7 KB
Newer Older
1 2
import { GridModel } from '@ibiz-template/model';
import { useGridController, useNamespace } from '@ibiz-template/vue-util';
3
import {
4
  computed,
5 6 7
  defineComponent,
  getCurrentInstance,
  h,
8
  onUnmounted,
9 10 11
  PropType,
  Ref,
  ref,
12
  watch,
13
} from 'vue';
14
import { IModal } from '@ibiz-template/runtime';
15 16 17 18 19 20 21 22 23 24 25
import { AppGridPagination } from '@/components/common';
import {
  useAppGridPagination,
  useITableColumns,
  useITableEvent,
} from './grid-control.util';
import '@ibiz-template/theme/style/components/widgets/grid/grid.scss';

export const GridControl = defineComponent({
  props: {
    modelData: GridModel,
26
    context: { type: Object as PropType<IContext>, required: true },
27 28 29 30 31 32 33 34 35 36
    params: { type: Object as PropType<IParams>, default: () => ({}) },
    /**
     * 表格行数据默认激活模式
     * - 0 不激活
     * - 1 单击激活
     * - 2 双击激活(默认值)
     *
     * @type {(number | 0 | 1 | 2)}
     */
    gridRowActiveMode: { type: Number, default: 2 },
37
    modal: { type: Object as PropType<IModal> },
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
  },
  setup(props) {
    const { proxy } = getCurrentInstance()!;

    const ns = useNamespace('grid');
    const c = useGridController(
      proxy,
      props.modelData!,
      props.context!,
      props.params,
    );

    const [columns] = useITableColumns(c);
    const { onRowClick, onDbRowClick, onSelectionChange, onSortChange } =
      useITableEvent(c);
    const { onPageChange, onPageReset, onPageSizeChange } =
      useAppGridPagination(c);

    // iView表格单击行选中没有,必须手动调用选中方法
    const onUIRowClick = (data: IData, index: number) => {
      const gridInstance: IData | undefined = proxy.$refs.grid;
      if (gridInstance) {
        if (gridInstance.toggleSelect) {
          gridInstance.toggleSelect(index);
        }
        if (gridInstance.highlightCurrentRow) {
          gridInstance.highlightCurrentRow(index);
        }
      }
      onRowClick(data);
    };

70
    // 给到iView table组件的高度
71 72
    const tableHeight = ref(0);

73
    // 表格外层div的引用
74
    const gridRef: Ref<HTMLElement | null> = ref(null);
75 76

    // 表格分页组件的引用
77 78 79 80
    const girdPaginationRef: Ref<InstanceType<
      typeof AppGridPagination
    > | null> = ref(null);

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    // 浏览器ResizeObserver对象
    let resizeObserver: ResizeObserver | null = null;

    // 上次监听到的表格外层div高度,一旦发生变化就重新计算
    let lastGridHeight = 0;

    // 计算表格高度(用于固定头部)
    const calcGridHeight = () => {
      // 不是嵌入视图里的表格才去算高度
      if (gridRef.value && props.modal?.mode !== 'EMBED') {
        if (c.model.source.enablePagingBar && girdPaginationRef.value) {
          const gridPage = girdPaginationRef.value.$el as HTMLElement;
          const gridPageHeight =
            gridPage.offsetHeight +
            parseFloat(window.getComputedStyle(gridPage).paddingTop);
          tableHeight.value = gridRef.value.offsetHeight - gridPageHeight;
        } else {
          tableHeight.value = gridRef.value.offsetHeight;
99
        }
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
      }
      // 如果模型配置了高度走配置的
      if (c.model.source.height > 0) {
        tableHeight.value = c.model.source.height;
      }
    };

    watch(gridRef, (newVal, oldVal) => {
      if (newVal && newVal !== oldVal) {
        calcGridHeight();
        if (window.ResizeObserver && gridRef.value) {
          resizeObserver = new ResizeObserver(entries => {
            // 处理组件高度变化
            const height = entries[0].contentRect.height;
            if (height !== lastGridHeight) {
              calcGridHeight();
              lastGridHeight = height;
            }
          });
          resizeObserver.observe(gridRef.value);
120
        }
121 122 123 124 125 126 127 128
      }
    });

    onUnmounted(() => {
      // 在组件销毁前取消 ResizeObserver 的观察
      if (resizeObserver) {
        resizeObserver.disconnect();
      }
129
    });
130

131 132 133 134
    const tableData = computed(() => {
      return [{ hiddenRow: true }, ...c.items];
    });

135 136 137 138
    return {
      c,
      ns,
      columns,
139
      tableData,
140 141 142 143 144 145 146
      onDbRowClick,
      onUIRowClick,
      onSelectionChange,
      onSortChange,
      onPageChange,
      onPageSizeChange,
      onPageReset,
147 148 149
      tableHeight,
      gridRef,
      girdPaginationRef,
150 151 152 153 154 155 156 157 158 159 160
    };
  },
  render() {
    if (!this.c.complete) {
      return;
    }

    // 绘制作用域插槽
    const columnSlots: IData = {};
    // 表格列自定义
    this.c.model.columns.forEach(column => {
161 162 163
      if (column.source.columnType === 'GROUPGRIDCOLUMN') {
        return;
      }
164 165
      const columnName = column.codeName;
      columnSlots[columnName] = ({ row, index }: IData) => {
166
        const rowController = this.c.rows[index - 1];
167 168 169 170 171 172 173
        if (row.hiddenRow) {
          return (
            <span style='word-break: break-word;white-space: pre-wrap;'>
              隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列隐藏行的列
            </span>
          );
        }
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
        if (rowController) {
          return h(this.c.providers[columnName].component, {
            props: {
              controller: this.c.columns[columnName],
              row: rowController,
            },
            key: row.srfkey + columnName,
          });
        }
      };
    });

    return (
      <control-layout modelData={this.c.model}>
        <div
189
          ref='gridRef'
190 191 192 193 194 195 196 197
          class={[
            this.ns.b(),
            this.ns.is('show-header', !this.c.model.source.hideHeader),
            this.ns.is('enable-page', this.c.model.source.enablePagingBar),
          ]}
        >
          <i-table
            ref={'grid'}
198
            height={this.tableHeight}
199 200 201
            class={this.ns.b('content')}
            show-header={!this.c.model.source.hideHeader}
            highlight-row
202
            data={this.tableData}
203 204 205 206 207
            columns={this.columns}
            on-on-row-click={this.onUIRowClick}
            on-on-row-dblclick={this.onDbRowClick}
            on-on-selection-change={this.onSelectionChange}
            on-on-sort-change={this.onSortChange}
208
            row-class-name={(row: IData) => (row.hiddenRow ? 'hidden-row' : '')}
209 210 211 212
            scopedSlots={columnSlots}
          ></i-table>
          {this.c.model.source.enablePagingBar && (
            <AppGridPagination
213
              ref='girdPaginationRef'
214 215 216 217 218 219 220 221 222 223 224 225 226
              total={this.c.total}
              curPage={this.c.curPage}
              size={this.c.size}
              on-change={this.onPageChange}
              on-page-size-change={this.onPageSizeChange}
              on-page-reset={this.onPageReset}
            ></AppGridPagination>
          )}
        </div>
      </control-layout>
    );
  },
});