OTWB项目代码阅读学习

1.布局
<el-row>
    <el-col :span="21">
        <div class="mb8" style="width: 100%">
          按钮区
        </div>
    </el-col>
</el-row>

2,图标

<el-button icon="图标名"  >

</el-button>

   <el-row>
        <el-col :span="24">
          <div class="mb8">
            <el-button icon="search" type="primary" @click="getDataList" v-auth="'base_unitType_view'">
              {
  { $t('translate.queryBtn') }}
            </el-button>
            <el-button icon="Refresh" @click="resetQuery" v-auth="'base_unitType_view'">{
  {
                $t('translate.resetBtn')
              }}
            </el-button>
            <el-button icon="folder-add" type="primary" class="ml10" @click="formDialogRef.openDialog()"
                       v-auth="'base_unitType_add'"
            >
              {
  { $t('translate.addBtn') }}
            </el-button>
            <el-button icon="edit" type="primary" :disabled="single|| selectDelFlag[0].delFlag==1"
                       v-auth="'base_unitType_edit'" class="ml10"
                       @click="formDialogRef.openDialog(selectObjs[0])"> {
  { $t('translate.editBtn') }}
            </el-button>
            <el-button plain :disabled="multiple" icon="Remove" type="" v-auth="'base_unitType_del'"
                       @click="handleDelete(selectObjs)">
              {
  { $t('translate.delBtn') }}
            </el-button>

            <el-button :disabled="multiple || ExecuteEffectCheck" type="primary" class="ml10" v-auth="'base_unitType_edit'"
                       @click="executeEffect(selectObjs)" icon="CircleCheck">
              {
  { $t('translate.effective') }}
            </el-button>
            <el-button :disabled="multiple || LoseEfficacyCheck" icon="Warning" type="primary" v-auth="'base_unitType_edit'"
                       class="ml10"
                       @click="executeLapse(selectObjs)">
              {
  { $t('translate.inVain') }}
            </el-button>
          </div>
        </el-col>
      </el-row>

 1.控制新建修改按钮是否禁用逻辑

 

2.生效失效按钮控制逻辑

 

3.生效失效按钮执行逻辑

 

4.tabs标签

5.列表展示 

5.1代码阅读

  在创建一个符合该接口结构的响应式状态对象 state。以下是它们之间的具体关系:

1. 接口定义

BasicTableProps 接口定义了表格组件所需的各种属性,包括查询表单、数据列表、分页信息等。它为组件的状态提供了一个结构化的类型约束。

2. 响应式状态对象

const state: BasicTableProps = reactive<BasicTableProps>({
  queryForm: {},
  pageList: fetchList
});
  • 类型约束:在这段代码中,state 被声明为 BasicTableProps 类型,这意味着 state 对象必须符合 BasicTableProps 接口中定义的结构。
  • 响应式对象:使用 reactive 函数将一个普通对象转换为响应式对象,使得对 state 的任何修改都会自动反映到 UI 上。

3. 属性赋值

  • queryForm: {}:这是 BasicTableProps 接口中的一个属性,初始化为一个空对象,通常用于存储查询条件。
  • pageList: fetchList:这是 BasicTableProps 接口中的一个方法属性,指向一个名为 fetchList 的函数,该函数用于获取数据列表。

4. 关系总结

  • 结构一致性state 的定义遵循了 BasicTableProps 接口的结构,确保了类型安全。
  • 状态管理:通过 state,您可以在组件中管理与表格相关的所有状态,这些状态通过接口得到了清晰的定义。

表格样式:

1. 定义表格配置接口

  在一个 .ts 文件中定义表格的相关配置,包括样式和其他属性。可以使用 TypeScript 的接口来确保类型安全。

 2. 在组件中使用表格配置

在需要使用表格的 Vue 组件中,导入这个配置,并进行解构使用。

表格高度:

import { ref, onMounted, onBeforeUnmount, nextTick, getCurrentInstance } from 'vue';

const FIXED_HEIGHT = 230; // 固定高度

export default function () {
  const tableHeight = ref(0);
  const { proxy } = getCurrentInstance();

  const calculateTableHeight = (includeButtonRef = false) => {
    nextTick(() => {
      const queryHeight = proxy.$refs.queryRef ? proxy.$refs.queryRef.$el.offsetHeight : 0;
      const tabsHeight = proxy.$refs.tabsRef ? proxy.$refs.tabsRef.$el.offsetHeight : 0;
      const buttonHeight = includeButtonRef && proxy.$refs.buttonRef ? proxy.$refs.buttonRef.$el.offsetHeight : 0;

      tableHeight.value = window.innerHeight - queryHeight - tabsHeight - buttonHeight - FIXED_HEIGHT;
    });
  };

  const handleResize = () => {
    calculateTableHeight(); // 计算不包含按钮的高度
  };

  onBeforeMount(() => {
    window.addEventListener('resize', handleResize);
  });

  onBeforeUnmount(() => {
    window.removeEventListener('resize', handleResize);
  });

  onMounted(() => {
    calculateTableHeight(); // 初始计算
  });

  return {
    tableHeight,
    calculateTableHeight,
  };
}

代码分析

  1. 引入依赖

    import { ref, onMounted, onBeforeUnmount, nextTick, getCurrentInstance } from 'vue';
    

    这里引入了 Vue 的一些组合式 API 函数,用于管理响应式状态和生命周期钩子。

  2. 定义响应式变量

    const tableHeight = ref(0);
    

    使用 ref 创建一个响应式变量 tableHeight,用于存储计算后的表格高度。

  3. 获取当前实例

    const { proxy } = getCurrentInstance();
    

    通过 getCurrentInstance 获取当前组件实例的 proxy,以便访问组件的引用。

  4. 生命周期钩子

    • onBeforeMount:在组件挂载之前添加窗口的 resize 事件监听器。
    • onBeforeUnmount:在组件卸载之前移除事件监听器。
    • onMounted:组件挂载后,计算表格高度。
  5. 计算表格高度的函数

    const $_calTableHeight = (() => {
      nextTick(() => {
        tableHeight.value = window.innerHeight - (proxy.$refs.queryRef ? proxy.$refs.queryRef.$el.offsetHeight : 0) - (proxy.$refs.tabsRef ? proxy.$refs.tabsRef.$el.offsetHeight : 0) - 230;
      });
    });
    

    这个函数在 DOM 更新后计算表格的高度。它考虑了其他元素的高度(如 queryRef 和 tabsRef),并从窗口高度中减去这些高度和一个固定值(230)。

  6. 使用:

 行点击:

export function clickRow(
  table: any,
  selectDataList: any[],
  row: any,
  e: Event,
  data: any[],
  type?: number,
  open?: boolean
) {
  const { ctrlKey, metaKey } = e as KeyboardEvent; // 进行类型断言
  let selectedRow: any = null;

  // 处理已选中行的逻辑
  if (selectDataList.length > 0 && type) {
    selectedRow = selectDataList[0];
    if (selectedRow === row) {
      table.toggleRowSelection(row, false);
      return;
    }
    // 取消之前选中的行
    table.toggleRowSelection(selectedRow, false);
    // 选中当前点击的行
    table.toggleRowSelection(row, true);
  }

  // 不可选规则
  if (row.roleId === '1' || (row.username === 'admin') || (row.verificationState === '1' && open)) {
    return;
  }

  const rowIndex = findRowIndex(data, row);
  const selected = isRowSelected(selectDataList, row);

  if (ctrlKey || metaKey) {
    handleMultiSelect(table, data, rowIndex, selectDataList);
  } else {
    // 单选逻辑
    table.toggleRowSelection(row, !selected);
  }
}

// 辅助函数:查找行索引
function findRowIndex(data: any[], row: any) {
  return data.findIndex(item => {
    return item.id === row.id || item.userId === row.userId || item.roleId === row.roleId || item.publicId === row.publicId || item.busCode === row.busCode;
  });
}

// 辅助函数:检查行是否已选中
function isRowSelected(selectDataList: any[], row: any) {
  return selectDataList.some(item => {
    return item.id === row.id || item.userId === row.userId || item.roleId === row.roleId || item.publicId === row.publicId || item.busCode === row.busCode;
  });
}

// 辅助函数:处理多选逻辑
function handleMultiSelect(table: any, data: any[], rowIndex: number, selectDataList: any[]) {
  const lastCheckIndex = findRowIndex(data, selectDataList[selectDataList.length - 1]);
  const minIndex = Math.min(rowIndex, lastCheckIndex);
  const maxIndex = Math.max(rowIndex, lastCheckIndex) + 1;

  // 在范围内选中行
  data.slice(minIndex, maxIndex).forEach(item => table.toggleRowSelection(item, true));
}

 clickRow 函数是一个复杂的行点击事件处理器,主要用于管理表格行的选择状态。下面是对该函数的详细分析及一些优化建议。

代码分析

  1. 参数说明

    • table: 表格的引用,通常是一个组件实例。
    • selectDataList: 当前已选中的行数据列表。
    • row: 被点击的行数据。
    • e: 原生事件对象,用于检查按键状态。
    • data: 表格的所有数据列表。
    • type: 可选参数,可能用于指示某种选择模式。
    • open: 可选参数,可能用于控制某些逻辑。
  2. 行选择逻辑

    • 函数首先检查是否有已选中的行,如果有且 type 存在,则根据当前点击的行决定是否取消选中或选中该行。
    • 通过 table.toggleRowSelection 方法来选中或取消选中行。
  3. 不可选规则

    • 角色 ID 为 1 的行和用户名为 admin 的行无法被选中。
    • 如果 verificationState 为 1 并且 open 为 true,则该行也不可选。
  4. 多选逻辑

    • 如果按下 Ctrl 或 Meta 键,支持多选功能。
    • 计算并选择范围内的行。
  5. 状态更新

    • 根据当前行是否已经选中,决定是否将其选中或取消选中。
  6. 使用

排序: 

 展示生效失效;

5.2 知识点了解:
1) 表格组件-hook

2)代码阅读:

useTable 函数-- 通用的表格组件配置和分页逻辑处理的自定义 Hook(在 Vue 3 中称为 Composable)。tables.ts----高度可复用的表格组件,它支持分页、排序、查询等多种功能。useTable 提供了一个集中的地方来管理这些逻辑,使得你的组件代码更加简洁和易于维护。

使用:

useTable 是一个 Vue Composition API 的自定义 Hook(Composable),用于处理表格组件的各种状态管理和数据请求逻辑。下面是对 useTable 函数的详细解释和总结:

1. 默认配置

typescript

深色版本

1const defaultOptions: BasicTableProps = {
2  dataListLoading: false,
3  createdIsNeed: true,
4  isPage: true,
5  queryForm: {},
6  dataList: [],
7  pagination: {
8    current: 1,
9    size: 20,
10    total: 0,
11    pageSizes: [1, 10, 20, 50, 100, 200, 500, 1000],
12    layout: 'total, sizes, prev, pager, next, jumper',
13  },
14  dataListSelections: [],
15  loading: false,
16  selectObjs: [],
17  descs: [],
18  ascs: [],
19  props: {
20    item: 'records',
21    totalCount: 'total',
22  },
23};
  • dataListLoading:表示数据是否正在加载中。

  • createdIsNeed:是否在创建时自动请求数据。

  • isPage:是否显示分页组件。

  • queryForm:查询条件表单对象。

  • dataList:表格展示的数据数组。

  • pagination:分页属性,包括当前页码、每页条数、总条数等。

  • dataListSelections:当前选中的数据项。

  • loading:表示是否正在从服务器加载数据。

  • selectObjs:表格数据项的选择数据。

  • descs 和 ascs:排序字段和方向。

  • props:自定义数据属性,如 item 表示数据记录,totalCount 表示总条数。

2. 合并默认配置和传入配置

typescript

深色版本

1const mergeDefaultOptions = (options2: any, props: any): BasicTableProps => {
2  for (const key in options2) {
3    if (!Object.getOwnPropertyDescriptor(props, key)) {
4      props[key] = options2[key];
5    }
6  }
7  return props;
8};
9
10const state = mergeDefaultOptions(defaultOptions, options);
  • mergeDefaultOptions:将默认配置和传入的配置合并,确保所有必要的属性都被设置。

  • state:最终的状态对象,包含了合并后的配置。

3. 数据请求

typescript

深色版本

1const query = async () => {
2  if (state.pageList) {
3    try {
4      state.loading = true;
5      let res: any;
6      if (state.ids) {
7        res = await state.pageList({
8          ...state.queryForm,
9          current: state.pagination?.current,
10          size: state.pagination?.size,
11          descs: state.descs?.join(','),
12          ascs: state.ascs?.join(','),
13        }, state.ids);
14      } else {
15        res = await state.pageList({
16          ...state.queryForm,
17          current: state.pagination?.current,
18          size: state.pagination?.size,
19          descs: state.descs?.join(','),
20          ascs: state.ascs?.join(','),
21        });
22      }
23      state.dataList = state.isPage ? res.data[state.props.item] : res.data;
24      state.pagination!.total = state.isPage ? res.data[state.props.totalCount] : 0;
25    } catch (err: any) {
26      ElMessage.error(err.msg || err.data.msg);
27    } finally {
28      state.loading = false;
29    }
30  }
31};
  • query:异步函数,用于发起数据请求。

  • state.loading:在请求开始前设置为 true,请求结束后设置为 false

  • state.pageList:调用传入的数据请求函数,传递查询参数。

  • state.dataList 和 state.pagination.total:根据返回的数据更新表格数据和总条数。

4. 生命周期钩子

typescript

深色版本

1onMounted(() => {
2  if (state.createdIsNeed) {
3    query();
4  }
5});
  • onMounted:在组件挂载时,如果 createdIsNeed 为 true,则自动发起数据请求。

5. 事件处理函数

typescript

深色版本

1const sizeChangeHandle = (val: number) => {
2  state.pagination!.size = val;
3  query();
4};
5
6const currentChangeHandle = (val: number) => {
7  state.pagination!.current = val;
8  query();
9};
10
11const sortChangeHandle = (column: any) => {
12  const prop = other.toUnderline(column.prop);
13  if (column.order === 'descending') {
14    state.descs?.push(prop);
15    if (state.ascs!.indexOf(prop) >= 0) {
16      state.ascs?.splice(state.ascs.indexOf(prop), 1);
17    }
18  } else if (column.order === 'ascending') {
19    state.ascs?.push(prop);
20    if (state.descs!.indexOf(prop) >= 0) {
21      state.descs?.splice(state.descs.indexOf(prop), 1);
22    }
23  } else {
24    if (state.ascs!.indexOf(prop) >= 0) {
25      state.ascs?.splice(state.ascs.indexOf(prop), 1);
26    }
27    if (state.descs!.indexOf(prop) >= 0) {
28      state.descs?.splice(state.descs.indexOf(prop), 1);
29    }
30  }
31  query();
32};
  • sizeChangeHandle:处理分页大小改变事件,更新 state.pagination.size 并重新请求数据。

  • currentChangeHandle:处理当前页码改变事件,更新 state.pagination.current 并重新请求数据。

  • sortChangeHandle:处理排序事件,更新排序字段和方向,并重新请求数据。

6. 获取数据列表

typescript

深色版本

1const getDataList = (refresh?: any) => {
2  if (refresh !== false) {
3    state.pagination!.current = 1;
4  }
5  // 处理时间范围
6  // ...
7  query();
8};
  • getDataList:获取数据列表,可选择是否刷新当前页码。处理各种时间范围的查询条件,并重新请求数据。

7. 下载文件

typescript

深色版本

1const downBlobFile = (url: string, requestBody: any, fileName: string, method?: string) => {
2  return other.downBlobFile(url, requestBody, fileName, method);
3};
  • downBlobFile:下载文件的辅助函数,调用 other.downBlobFile 进行实际的文件下载。

8. 表格样式

typescript

深色版本

1const tableStyle: TableStyle = {
2  cellStyle: { height: '40px' },
3  headerCellStyle: {
4    height: '40px',
5    background: 'var(--el-table-row-hover-bg-color)',
6    color: 'var(--el-text-color-primary)',
7  },
8};
  • tableStyle:定义表格的通用样式。

返回值

1return {
2  tableStyle,
3  getDataList,
4  sizeChangeHandle,
5  currentChangeHandle,
6  sortChangeHandle,
7  downBlobFile,
8};
  • tableStyle:表格样式。

  • getDataList:获取数据列表的函数。

  • sizeChangeHandle 和 currentChangeHandle:分页大小和页码改变的处理函数。

  • sortChangeHandle:排序事件的处理函数。

  • downBlobFile:下载文件的辅助函数。

总结

useTable Composable 提供了一个完整的解决方案来管理表格组件的状态和数据请求逻辑。它处理了以下主要功能:

  • 初始化和合并配置:确保所有必要的属性都被正确设置。

  • 数据请求:自动或手动发起数据请求,并处理响应数据。

  • 生命周期管理:在组件挂载时自动请求数据。

  • 事件处理:处理分页、排序等事件,并重新请求数据。

  • 辅助功能:提供下载文件和定义表格样式的辅助函数。

通过这种方式,你可以轻松地在 Vue 组件中使用这个 Composable 来管理复杂的表格逻辑。

 

state 对象集成 BasicTableProps 的所有属性ÿ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值