You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Syncfusion Scheduler时间线视图中行高度错位问题求助

Syncfusion Scheduler时间线视图中行高度错位问题求助

我最近在做设备预约管理功能,用Syncfusion Scheduler的TimelineWeek视图来组织「分类→子分类→设备」的层级资源。但遇到个挺闹心的问题:每个设备的描述特别长,我用resourceHeaderTemplate渲染这些长文本后,左边的资源单元格能自动撑开高度适配内容,可右边对应的时间线行却没跟着同步增高,导致左右两边行高度完全错位,视觉效果特别差。

先跟大家说下我的实现细节:

资源头部模板代码

我自定义了带背景色的资源头部模板来渲染长文本:

resourceHeaderTemplate: props => {
  const col = props.resourceData.color || '#eee';
  return `
    <div class="my-resource-header" style="background:${col};color:${getContrastColor(col)}">
      ${props.resourceData.text}
    </div>
  `;
}

行高同步的尝试

为了让行高能自适应内容,我不仅开启了rowAutoHeight: true,还手写了一个手动同步行高的辅助函数,在dataBound、contentReady、actionComplete这几个核心事件里都调用了它:

function forceContentRowHeightSync(retries = 10) {
  const resTableRows = document.querySelectorAll('.e-resource-table tbody tr');
  const contentTableRows = document.querySelectorAll('.e-content-table tbody tr.e-content-row');
  const count = Math.min(resTableRows.length, contentTableRows.length);
  
  for (let i = 0; i < count; i++) {
    const resourceCell = resTableRows[i].querySelector('.my-resource-header');
    const height = resourceCell ? resourceCell.offsetHeight : resTableRows[i].offsetHeight;
    resTableRows[i].style.height = `${height}px`;
    resTableRows[i].style.minHeight = `${height}px`;
    contentTableRows[i].style.height = `${height}px`;
    contentTableRows[i].style.minHeight = `${height}px`;
  }
  
  if (retries > 0) {
    requestAnimationFrame(() => forceContentRowHeightSync(retries - 1));
  }
}

除此之外,我还试了一堆办法,都没解决问题:

  • 开启了allowRowHeightAdjustment: true配置
  • 给左右两边的元素统一设置了box-sizing、内边距和字体大小
  • 加了CSS强制长文本自动换行:
.e-resource-text, .my-resource-header {
  white-space: normal !important;
  word-break: break-word;
  overflow-wrap: anywhere;
}

完整的Scheduler初始化代码

window.scheduleObj = new ej.schedule.Schedule({
  height: 'auto',
  width: '100%',
  rowAutoHeight: true,
  allowRowHeightAdjustment: true,
  selectedDate: new Date(2025, 5, 9),
  locale: 'it',
  cssClass: 'custom-scheduler',
  currentView: 'TimelineWeek',
  views: [
    { option: 'TimelineWeek', displayName: 'Settimana' },
    { option: 'TimelineMonth', displayName: 'Mese' },
    { option: 'Agenda', displayName: 'Agenda' }
  ],
  agendaViewSettings: {
    allowVirtualScrolling: false,
    hideEmptyAgendaDays: false
  },
  group: {
    resources: ['Categorie', 'Sottocategorie', 'Mezzi'],
    byGroupID: true,
    allowGroupEdit: false
  },
  timeScale: { enable: false },
  showQuickInfo: true,
  allowResizing: false,
  showHeaderBar: true,
  eventSettings: {
    dataSource: eventi,
    fields: {
      subject: { name: 'Subject', title: 'Titolo' },
      startTime: { name: 'StartTime' },
      endTime: { name: 'EndTime' },
      isAllDay: { name: 'IsAllDay' }
    }
  },
  resources: [
    {
      field: 'CategoriaId',
      title: 'Categoria',
      name: 'Categorie',
      dataSource: risorse.categorie,
      textField: 'text',
      idField: 'id',
      colorField: 'color'
    },
    {
      field: 'SottocategoriaId',
      title: 'Sottocategoria',
      name: 'Sottocategorie',
      dataSource: risorse.sottocategorie,
      textField: 'text',
      idField: 'id',
      groupIDField: 'groupID',
      colorField: 'color'
    },
    {
      field: 'MezzoId',
      title: 'Mezzo',
      name: 'Mezzi',
      dataSource: risorse.mezzi,
      textField: 'text',
      idField: 'id',
      groupIDField: 'groupID',
      colorField: 'color'
    }
  ],
  resourceHeaderTemplate: props => {
    const col = props.resourceData.color || '#eee';
    return `
      <div class="my-resource-header" style="background:${col};color:${getContrastColor(col)}">
        ${props.resourceData.text}
      </div>
    `;
  },
  eventRendered: args => {
    const sc = risorse.sottocategorie.find(x => x.id === args.data.SottocategoriaId);
    const col = sc?.color || '#607d8b';
    args.element.style.backgroundColor = col;
    args.element.style.borderColor = col;
    args.element.style.color = getContrastColor(col);
  },
  dataBound: () => setTimeout(() => forceContentRowHeightSync(), 100),
  contentReady: () => setTimeout(() => forceContentRowHeightSync(), 100),
  actionComplete: args => {
    if (['view','dateNavigate','resourceExpand','resourceCollapse'].includes(args.requestType)) {
      setTimeout(() => forceContentRowHeightSync(), 100);
    }
  }
});
scheduleObj.appendTo('#scheduleContainer');

补充的CSS样式

.e-resource-text, .my-resource-header {
  white-space: normal !important;
  word-break: break-word;
  overflow-wrap: anywhere;
}
.disabled-cell {
  background-color: #ff0000 !important;
  pointer-events: none;
  opacity: 0.6;
}
.e-schedule .e-resource-column {
  width: 130px !important;
  max-width: none !important;
  white-space: normal !important;
  word-wrap: break-word;
}

现在的核心问题就是:左边资源单元格因长内容撑开高度后,右边的时间线行高度完全没跟上,导致左右严重错位。有没有过来人或者官方推荐的解决思路?是不是我在模板渲染或者行高同步的逻辑里漏了什么关键细节?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 08:43:07