u-table2.vue 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. <template>
  2. <view class="u-table2" :class="{ 'u-table-border': border }">
  3. <scroll-view scroll-x scroll-y class="u-table2-content"
  4. :style="{ height: height ? addUnit(height) : 'auto' }"
  5. @scroll="onScroll">
  6. <!-- 表头 -->
  7. <view v-if="showHeader" class="u-table-header"
  8. :class="{ 'u-table-sticky': fixedHeader }"
  9. :style="{minWidth: scrollWidth}">
  10. <view class="u-table-row">
  11. <view v-for="(col, colIndex) in columns" :key="col.key" class="u-table-cell"
  12. :class="[col.headerAlign ? 'u-text-' + col.headerAlign : (col.align ? 'u-text-' + col.align : '') ,
  13. headerCellClassName ? headerCellClassName(col) : '',
  14. getFixedClass(col)
  15. ]" :style="headerColStyle(col)" @click="handleHeaderClick(col)">
  16. <slot name="header" :column="col" :columnIndex="colIndex" :level="1">
  17. </slot>
  18. <text v-if="!$slots['header']">{{ col.title }}</text>
  19. <template v-if="col.sortable">
  20. <slot name="headerSort" :sortStatus="getSortValue(col.key)" :column="col"
  21. :columnIndex="colIndex" :level="1">
  22. </slot>
  23. <view v-if="!$slots['headerSort']">
  24. {{ getSortIcon(col.key) }}
  25. </view>
  26. </template>
  27. </view>
  28. </view>
  29. </view>
  30. <!-- 表体 -->
  31. <view class="u-table-body" :style="{ minWidth: scrollWidth, maxHeight: maxHeight ? maxHeight + 'px' : 'none' }">
  32. <template v-if="data && data.length > 0">
  33. <table-row
  34. v-for="(row, rowIndex) in sortedData"
  35. :key="row[rowKey] || rowIndex"
  36. :row="row"
  37. :rowIndex="rowIndex"
  38. :parent-row="null"
  39. :columns="columns"
  40. :tree-props="treeProps"
  41. :row-key="rowKey"
  42. :expanded-keys="expandedKeys"
  43. :cell-style-inner="cellStyleInner"
  44. :is-expanded="isExpanded"
  45. :row-class-name="rowClassName"
  46. :stripe="stripe"
  47. :cell-class-name="cellClassName"
  48. :get-fixed-class="getFixedClass"
  49. :highlight-current-row="highlightCurrentRow"
  50. :current-row="currentRow"
  51. :handle-row-click="handleRowClick"
  52. :toggle-expand="toggleExpand"
  53. :level="1"
  54. :rowHeight="rowHeight"
  55. :hasTree="hasTree"
  56. :selectedRows="selectedRows"
  57. :expandWidth="expandWidth"
  58. :computedMainCol="computedMainCol"
  59. :span-method="spanMethod"
  60. @toggle-select="toggleSelect"
  61. @row-click="handleRowClick"
  62. @toggle-expand="toggleExpand"
  63. >
  64. <template v-slot:cellChild="scope">
  65. <slot name="cell" :row="scope.row" :column="scope.column" :prow="scope.prow"
  66. :rowIndex="scope.rowIndex" :columnIndex="scope.columnIndex" :level="scope.level">
  67. </slot>
  68. </template>
  69. </table-row>
  70. </template>
  71. <template v-else>
  72. <slot name="empty">
  73. </slot>
  74. <view v-if="!$slots['empty']" class="u-table-empty">{{ emptyText }}</view>
  75. </template>
  76. </view>
  77. </scroll-view>
  78. <!-- 固定列浮动视图 -->
  79. <view v-if="showFixedColumnShadow" class="u-table-fixed-shadow" :style="{ height: tableHeight }">
  80. <!-- 表头 -->
  81. <view v-if="showHeader" class="u-table-header" :class="{ 'u-table-sticky': fixedHeader }" :style="{minWidth: scrollWidth}">
  82. <view class="u-table-row" :style="{height: headerHeight}">
  83. <view v-for="(col, colIndex) in visibleFixedLeftColumns" :key="col.key" class="u-table-cell"
  84. :style="headerColStyle(col)"
  85. :class="[col.align ? 'u-text-' + col.align : '',
  86. headerCellClassName ? headerCellClassName(col) : '',
  87. getFixedClass(col)
  88. ]" @click="handleHeaderClick(col)">
  89. <slot name="header" :column="col" :columnIndex="colIndex" :level="1">
  90. </slot>
  91. <text v-if="!$slots['header']">{{ col.title }}</text>
  92. <template v-if="col.sortable">
  93. <slot name="headerSort" :sortStatus="getSortValue(col.key)" :column="col"
  94. :columnIndex="colIndex" :level="1">
  95. </slot>
  96. <view v-if="!$slots['headerSort']">
  97. {{ getSortIcon(col.key) }}
  98. </view>
  99. </template>
  100. </view>
  101. </view>
  102. </view>
  103. <!-- 表体 -->
  104. <view class="u-table-body" :style="{ minWidth: scrollWidth, maxHeight: maxHeight ? maxHeight + 'px' : 'none' }">
  105. <template v-if="data && data.length > 0">
  106. <template v-for="(row, rowIndex) in sortedData" :key="row[rowKey] || rowIndex">
  107. <!-- 子级渲染 (递归组件) -->
  108. <table-row
  109. :row="row"
  110. :rowIndex="rowIndex"
  111. :parent-row="null"
  112. :columns="visibleFixedLeftColumns"
  113. :tree-props="treeProps"
  114. :row-key="rowKey"
  115. :expanded-keys="expandedKeys"
  116. :cell-style-inner="cellStyleInner"
  117. :is-expanded="isExpanded"
  118. :row-class-name="rowClassName"
  119. :stripe="stripe"
  120. :cell-class-name="cellClassName"
  121. :get-fixed-class="getFixedClass"
  122. :highlight-current-row="highlightCurrentRow"
  123. :current-row="currentRow"
  124. :handle-row-click="handleRowClick"
  125. :toggle-expand="toggleExpand"
  126. :level="1"
  127. :rowHeight="rowHeight"
  128. :hasTree="hasTree"
  129. :selectedRows="selectedRows"
  130. :expandWidth="expandWidth"
  131. :computedMainCol="computedMainCol"
  132. :span-method="spanMethod"
  133. @toggle-select="toggleSelect"
  134. @row-click="handleRowClick"
  135. @toggle-expand="toggleExpand"
  136. >
  137. <template v-slot:cellChild="scope">
  138. <slot name="cell" :row="scope.row" :column="scope.column" :prow="scope.prow"
  139. :rowIndex="scope.rowIndex" :columnIndex="scope.columnIndex" :level="scope.level">
  140. </slot>
  141. </template>
  142. </table-row>
  143. </template>
  144. </template>
  145. </view>
  146. </view>
  147. </view>
  148. </template>
  149. <script>
  150. import { addUnit, sleep } from '../../libs/function/index';
  151. import tableRow from './tableRow.vue'; // 引入递归组件
  152. export default {
  153. name: 'u-table2',
  154. components: {
  155. tableRow // 注册递归组件
  156. },
  157. props: {
  158. data: {
  159. type: Array,
  160. required: true,
  161. default: () => {
  162. return []
  163. }
  164. },
  165. columns: {
  166. type: Array,
  167. required: true,
  168. default: () => {
  169. return []
  170. },
  171. validator: cols =>
  172. cols.every(col =>
  173. ['default', 'selection', 'expand'].includes(col.type || 'default')
  174. )
  175. },
  176. stripe: {
  177. type: Boolean,
  178. default: false
  179. },
  180. border: {
  181. type: Boolean,
  182. default: false
  183. },
  184. height: {
  185. type: [String, Number],
  186. default: null
  187. },
  188. maxHeight: {
  189. type: [String, Number],
  190. default: null
  191. },
  192. showHeader: {
  193. type: Boolean,
  194. default: true
  195. },
  196. highlightCurrentRow: {
  197. type: Boolean,
  198. default: false
  199. },
  200. rowKey: {
  201. type: String,
  202. default: 'id'
  203. },
  204. currentRowKey: {
  205. type: [String, Number],
  206. default: null
  207. },
  208. rowStyle: {
  209. type: Object,
  210. default: () => ({})
  211. },
  212. cellClassName: {
  213. type: Function,
  214. default: null
  215. },
  216. cellStyle: {
  217. type: Function,
  218. default: null
  219. },
  220. headerCellClassName: {
  221. type: Function,
  222. default: null
  223. },
  224. rowClassName: {
  225. type: Function,
  226. default: null
  227. },
  228. context: {
  229. type: Object,
  230. default: null
  231. },
  232. showOverflowTooltip: {
  233. type: Boolean,
  234. default: false
  235. },
  236. lazy: {
  237. type: Boolean,
  238. default: false
  239. },
  240. load: {
  241. type: Function,
  242. default: null
  243. },
  244. treeProps: {
  245. type: Object,
  246. default: () => ({
  247. children: 'children',
  248. hasChildren: 'hasChildren'
  249. })
  250. },
  251. defaultExpandAll: {
  252. type: Boolean,
  253. default: false
  254. },
  255. expandRowKeys: {
  256. type: Array,
  257. default: () => []
  258. },
  259. sortOrders: {
  260. type: Array,
  261. default: () => ['ascending', 'descending']
  262. },
  263. sortable: {
  264. type: [Boolean, String],
  265. default: false
  266. },
  267. multiSort: {
  268. type: Boolean,
  269. default: false
  270. },
  271. sortBy: {
  272. type: String,
  273. default: null
  274. },
  275. sortMethod: {
  276. type: Function,
  277. default: null
  278. },
  279. filters: {
  280. type: Object,
  281. default: () => ({})
  282. },
  283. fixedHeader: {
  284. type: Boolean,
  285. default: true
  286. },
  287. emptyText: {
  288. type: String,
  289. default: '暂无数据'
  290. },
  291. // 添加mainCol属性,用于指定树形结构展开控制图标所在的列
  292. mainCol: {
  293. type: String,
  294. default: ''
  295. },
  296. expandWidth: {
  297. type: String,
  298. default: '25px'
  299. },
  300. rowHeight: {
  301. type: String,
  302. default: '36px'
  303. },
  304. // 添加spanMethod属性,用于合并单元格
  305. spanMethod: {
  306. type: Function,
  307. default: null
  308. }
  309. },
  310. emits: [
  311. 'select', 'select-all', 'selection-change',
  312. 'cell-click', 'row-click', 'row-dblclick',
  313. 'header-click', 'sort-change', 'filter-change',
  314. 'current-change', 'expand-change'
  315. ],
  316. data() {
  317. return {
  318. scrollWidth: 'auto',
  319. // 将setup中的ref转换为data属性
  320. expandedKeys: [...this.expandRowKeys],
  321. selectedRows: [],
  322. sortConditions: [],
  323. currentRow: null,
  324. scrollLeft: 0, // 新增滚动位置数据
  325. showFixedColumnShadow: false, // 是否显示固定列阴影
  326. fixedLeftColumns: [], // 左侧固定列
  327. tableHeight: 'auto', // 表格高度
  328. headerHeight: 'auto', // 新增表头高度属性
  329. hasTree: false // 新增属性,用于判断是否存在树形结构
  330. }
  331. },
  332. mounted() {
  333. this.getComponentWidth()
  334. // 处理currentRowKey初始化
  335. if (this.currentRowKey !== null) {
  336. const found = this.data.find(item => item[this.rowKey] === this.currentRowKey);
  337. if (found) {
  338. this.currentRow = found;
  339. }
  340. }
  341. // 获取固定列
  342. this.fixedLeftColumns = this.columns.filter(col => col.fixed === 'left');
  343. },
  344. computed: {
  345. // 将setup中的computed转换为computed属性
  346. filteredData() {
  347. return this.data.filter(row => {
  348. return Object.keys(this.filters).every(key => {
  349. const filter = this.filters[key];
  350. if (!filter) return true;
  351. return row[key]?.toString().includes(filter.toString());
  352. });
  353. });
  354. },
  355. sortedData() {
  356. if (!this.sortConditions.length) return this.filteredData;
  357. const data = [...this.filteredData];
  358. return data.sort((a, b) => {
  359. for (const condition of this.sortConditions) {
  360. const { field, order } = condition;
  361. let valA = a[field];
  362. let valB = b[field];
  363. if (this.sortMethod) {
  364. const result = this.sortMethod(a, b, field);
  365. if (result !== 0) return result * (order === 'ascending' ? 1 : -1);
  366. }
  367. if (valA < valB) return order === 'ascending' ? -1 : 1;
  368. if (valA > valB) return order === 'ascending' ? 1 : -1;
  369. }
  370. return 0;
  371. });
  372. },
  373. // 计算当前应该显示的固定左侧列
  374. visibleFixedLeftColumns() {
  375. if (this.scrollLeft <= 0) {
  376. return [];
  377. }
  378. let totalWidth = 0;
  379. let fixedWidth = 0;
  380. const visibleColumns = [];
  381. // 遍历所有列,不仅仅是固定列
  382. for (let i = 0; i < this.columns.length; i++) {
  383. const col = this.columns[i];
  384. const colWidth = col.width ? parseInt(col.width) : 100; // 默认宽度100px
  385. // 如果是固定列且滚动位置足够显示该列
  386. if (col.fixed === 'left' && this.scrollLeft > totalWidth - fixedWidth) {
  387. visibleColumns.push(col);
  388. fixedWidth += colWidth;
  389. }
  390. totalWidth += colWidth;
  391. }
  392. return visibleColumns;
  393. },
  394. // 获取mainCol的值,如果未设置则默认为第一列的key
  395. computedMainCol() {
  396. if (this.mainCol) {
  397. return this.mainCol;
  398. }
  399. // 修改为排除有type值的列
  400. const validColumns = this.columns.filter(col => !col.type);
  401. let mainCol = validColumns && validColumns.length > 0 ? validColumns[0].key : '';
  402. // console.log('mainCol', mainCol)
  403. return mainCol;
  404. }
  405. },
  406. watch: {
  407. // 将setup中的watch转换为watch属性
  408. expandRowKeys: {
  409. handler(newVal) {
  410. this.expandedKeys = [...newVal];
  411. },
  412. immediate: true
  413. },
  414. currentRowKey: {
  415. handler(newVal) {
  416. const found = this.data.find(item => item[this.rowKey] === newVal);
  417. if (found) {
  418. this.currentRow = found;
  419. }
  420. },
  421. immediate: true
  422. },
  423. columns: {
  424. handler() {
  425. // this.fixedLeftColumns = this.columns.filter(col => col.fixed === 'left');
  426. },
  427. deep: true,
  428. immediate: false
  429. }
  430. },
  431. methods: {
  432. addUnit,
  433. onScroll(e) {
  434. this.scrollLeft = e.detail.scrollLeft;
  435. // 获取所有左侧固定列
  436. this.fixedLeftColumns = this.columns.filter(col => col.fixed === 'left');
  437. // 计算是否需要显示固定列阴影
  438. if (this.fixedLeftColumns.length > 0) {
  439. this.showFixedColumnShadow = this.scrollLeft > 0;
  440. }
  441. },
  442. getFixedShadowStyle(col, index) {
  443. let style = {
  444. width: col.width ? addUnit(col.width) : 'auto',
  445. };
  446. if (col?.style) {
  447. style = {...style, ...col?.style};
  448. }
  449. return style;
  450. },
  451. getFixedClass(col) {
  452. return ''; // 不再使用原来的固定列样式类
  453. },
  454. headerColStyle(col) {
  455. let style = {
  456. width: col.width ? addUnit(col.width) : 'auto',
  457. flex: col.width ? 'none' : 1
  458. };
  459. if (col?.style) {
  460. style = {...style, ...col?.style};
  461. }
  462. return style;
  463. },
  464. setCellStyle(e) {
  465. this.cellStyle = e
  466. },
  467. cellStyleInner(scope) {
  468. let style = {
  469. width: scope.column?.width ? addUnit(scope.column.width) : 'auto',
  470. flex: scope.column?.width ? 'none' : 1
  471. };
  472. // 只有展开列设置padding
  473. if (scope.column.key == this.computedMainCol) {
  474. style.paddingLeft = (16 * (scope.level -1 )) + 2 + 'px'
  475. }
  476. if (this.cellStyle != null) {
  477. let styleCalc = this.cellStyle(scope)
  478. if (styleCalc != null) {
  479. style = {...style, ...styleCalc}
  480. }
  481. }
  482. return style;
  483. },
  484. // 获取组件的宽度
  485. async getComponentWidth() {
  486. // 延时一定时间,以获取dom尺寸
  487. await sleep(30)
  488. this.$uGetRect('.u-table-row').then(size => {
  489. this.scrollWidth = size.width + 'px'
  490. })
  491. // 获取表头高度并设置
  492. this.$uGetRect('.u-table-header').then(size => {
  493. if (size.height) {
  494. this.headerHeight = size.height + 'px';
  495. }
  496. })
  497. // 遍历数据列表第一层判断是否存在树形结构
  498. this.hasTree = this.sortedData.some(item => {
  499. return item[this.treeProps.children] && item[this.treeProps.children].length > 0;
  500. });
  501. },
  502. // 将setup中的函数转换为methods
  503. handleRowClick(row) {
  504. if (this.highlightCurrentRow) {
  505. const oldRow = this.currentRow;
  506. this.currentRow = row;
  507. this.$emit('current-change', row, oldRow);
  508. }
  509. this.$emit('row-click', row);
  510. },
  511. handleHeaderClick(column) {
  512. if (!column.sortable) return;
  513. const index = this.sortConditions.findIndex(c => c.field === column.key);
  514. let newOrder = 'ascending';
  515. if (index >= 0) {
  516. if (this.sortConditions[index].order === 'ascending') {
  517. newOrder = 'descending';
  518. } else {
  519. this.sortConditions.splice(index, 1);
  520. this.$emit('sort-change', this.sortConditions);
  521. return;
  522. }
  523. }
  524. if (!this.multiSort) {
  525. this.sortConditions = [{ field: column.key, order: newOrder }];
  526. } else {
  527. if (index >= 0) {
  528. this.sortConditions[index].order = newOrder;
  529. } else {
  530. this.sortConditions.push({ field: column.key, order: newOrder });
  531. }
  532. }
  533. this.$emit('sort-change', this.sortConditions);
  534. },
  535. getSortIcon(field) {
  536. const cond = this.sortConditions.find(c => c.field === field);
  537. if (!cond) return '';
  538. return cond.order === 'ascending' ? '↑' : '↓';
  539. },
  540. getSortValue(field) {
  541. const cond = this.sortConditions.find(c => c.field === field);
  542. if (!cond) return '';
  543. return cond.order === 'ascending';
  544. },
  545. toggleSelect(row) {
  546. const index = this.selectedRows.findIndex(r => r[this.rowKey] === row[this.rowKey]);
  547. if (index >= 0) {
  548. // 取消选中当前行及其所有子节点
  549. this.selectedRows.splice(index, 1);
  550. // 递归取消所有子节点
  551. this.unselectChildren(row);
  552. } else {
  553. // 选中当前行及其所有子节点
  554. this.selectedRows.push(row);
  555. // 递归选中所有子节点
  556. this.selectChildren(row);
  557. }
  558. console.log(this.selectedRows)
  559. this.$emit('selection-change', this.selectedRows);
  560. this.$emit('select', row);
  561. },
  562. toggleExpand(row) {
  563. // console.log(row)
  564. const key = row[this.rowKey];
  565. const index = this.expandedKeys.indexOf(key);
  566. if (index === -1) {
  567. this.expandedKeys.push(key);
  568. } else {
  569. this.expandedKeys.splice(index, 1);
  570. }
  571. this.$emit('expand-change', this.expandedKeys);
  572. },
  573. isExpanded(row) {
  574. if (!row) {
  575. return false;
  576. }
  577. return this.expandedKeys.includes(row[this.rowKey]);
  578. },
  579. // 新增方法:递归选中所有子节点
  580. selectChildren(row) {
  581. const children = row[this.treeProps.children];
  582. if (children && children.length > 0) {
  583. children.forEach(child => {
  584. // 检查是否已选中,避免重复添加
  585. const childIndex = this.selectedRows.findIndex(r => r[this.rowKey] === child[this.rowKey]);
  586. if (childIndex === -1) {
  587. this.selectedRows.push(child);
  588. }
  589. // 递归处理子节点的子节点
  590. this.selectChildren(child);
  591. });
  592. }
  593. },
  594. // 新增方法:递归取消选中所有子节点
  595. unselectChildren(row) {
  596. const children = row[this.treeProps.children];
  597. if (children && children.length > 0) {
  598. children.forEach(child => {
  599. const childIndex = this.selectedRows.findIndex(r => r[this.rowKey] === child[this.rowKey]);
  600. if (childIndex >= 0) {
  601. this.selectedRows.splice(childIndex, 1);
  602. }
  603. // 递归处理子节点的子节点
  604. this.unselectChildren(child);
  605. });
  606. }
  607. },
  608. }
  609. };
  610. </script>
  611. <style lang="scss" scoped>
  612. .u-table2 {
  613. width: auto;
  614. overflow: auto;
  615. white-space: nowrap;
  616. position: relative;
  617. .u-table-header {
  618. min-width: 100% !important;
  619. width: fit-content;
  620. background-color: #f5f7fa;
  621. }
  622. .u-table-body {
  623. min-width: 100% !important;
  624. width: fit-content;
  625. position: relative;
  626. }
  627. .u-table-sticky {
  628. position: sticky;
  629. top: 0;
  630. z-index: 10;
  631. }
  632. .u-table-row {
  633. display: flex;
  634. flex-direction: row;
  635. overflow: hidden;
  636. position: relative;
  637. // min-height: 40px;
  638. }
  639. // 添加border样式支持
  640. &.u-table-border {
  641. border-top: 1px solid #ebeef5;
  642. border-left: 1px solid #ebeef5;
  643. border-right: 1px solid #ebeef5;
  644. .u-table-cell {
  645. border-right: 1px solid #ebeef5;
  646. }
  647. .u-table-cell:last-child {
  648. border-right: none;
  649. }
  650. }
  651. .u-table-cell {
  652. flex: 1;
  653. display: flex;
  654. flex-direction: row;
  655. align-items: center;
  656. padding: 10px 1px;
  657. font-size: 14px;
  658. white-space: nowrap;
  659. overflow: hidden;
  660. text-overflow: ellipsis;
  661. line-height: 1.1;
  662. border-bottom: 1px solid #ebeef5;
  663. &.u-text-left {
  664. justify-content: flex-start;
  665. text-align: left;
  666. }
  667. &.u-text-center {
  668. justify-content: center;
  669. text-align: center;
  670. }
  671. &.u-text-right {
  672. justify-content: flex-end;
  673. text-align: right;
  674. }
  675. }
  676. .u-table-row-zebra {
  677. background-color: #fafafa;
  678. }
  679. .u-table-row-highlight {
  680. background-color: #f5f7fa;
  681. }
  682. .u-table-empty {
  683. text-align: center;
  684. padding: 20px;
  685. color: #999;
  686. }
  687. }
  688. // 固定列浮动视图
  689. .u-table-fixed-shadow {
  690. position: absolute;
  691. top: 0;
  692. left: 0;
  693. width: auto;
  694. z-index: 20;
  695. box-shadow: 2px 0 5px rgba(0, 0, 0, 0.15);
  696. overflow: hidden;
  697. background-color: #ffffff;
  698. }
  699. // .u-table-fixed-row {
  700. // display: flex;
  701. // flex-direction: row;
  702. // align-items: center;
  703. // border-bottom: 1rpx solid #ebeef5;
  704. // position: relative;
  705. // }
  706. // 为固定列也添加border样式支持
  707. .u-table-fixed-shadow .u-table-border {
  708. .u-table-cell {
  709. border-right: 1rpx solid #ebeef5;
  710. }
  711. .u-table-cell:last-child {
  712. border-right: none;
  713. }
  714. }
  715. </style>