zb-table.vue 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342
  1. <template>
  2. <!-- #ifdef H5 || APP-PLUS -->
  3. <view :class="['zb-table','zb-table-fixed-header',!border&&(bodyTableLeft>50||headerTableLeft>50)&&'scroll-left-fixed']">
  4. <view class="zb-table-content" style="flex: 1">
  5. <view class="zb-table-scroll" style="height: 100%;">
  6. <template v-if="showHeader">
  7. <view class="zb-table-header top-header-uni"
  8. >
  9. <scroll-view class="zb-table-headers"
  10. @scroll="handleTableScrollLeft"
  11. scroll-x="true"
  12. scroll-y="false"
  13. id="tableHeaders"
  14. scroll-anchoring="true"
  15. :scroll-left="headerTableLeft"
  16. style="
  17. height: 100%">
  18. <view class="zb-table-fixed" >
  19. <view class="zb-table-thead" style="position: relative;" >
  20. <view class="item-tr">
  21. <view
  22. @click.stop="sortAction(item,index)"
  23. class="item-th"
  24. :style="[{
  25. width:`${item.width?item.width:'100'}px`,
  26. flex:index===transColumns.length-1?1:'none',
  27. minWidth:`${item.width?item.width:'100'}px`,
  28. borderRight:`${border?'1px solid #e8e8e8':''}`,
  29. borderTop:`${border?'1px solid #e8e8e8':''}`,
  30. textAlign:item.align||'left'
  31. },getHeaderCellStyle(item,index)]"
  32. v-for="(item,index) in transColumns" :key="index">
  33. <template v-if="item.type==='selection'">
  34. <view class="checkbox-item">
  35. <tableCheckbox
  36. :indeterminate="indeterminate" :checked="checkedAll" @checkboxSelected="checkboxSelectedAll"></tableCheckbox>
  37. </view>
  38. </template>
  39. <template v-else>
  40. {{ item.label }}
  41. <view class="sorter-table" v-if="item.sorter">
  42. <view :class="['sorter-table-icon',item.sorterMode==='_asc'&&`sorting${item.sorterMode||''}`]"></view>
  43. <view :class="['sorter-table-icon',item.sorterMode==='_desc'&&`sorting${item.sorterMode||''}`]"></view>
  44. </view>
  45. </template>
  46. </view>
  47. <view
  48. v-if="scrollbarSize"
  49. class="item-th "
  50. :style="{
  51. borderTop:`${border?'1px solid #e8e8e8':''}`,
  52. padding:0,
  53. width:`${scrollbarSize}px`,
  54. }">
  55. </view>
  56. </view>
  57. </view>
  58. </view>
  59. </scroll-view>
  60. </view>
  61. </template>
  62. <template v-if="!data.length">
  63. <view class="no-data">暂无数据~~</view>
  64. </template>
  65. <scroll-view
  66. class="zb-table-body" ref="tableBody" scroll-x="true" scroll-y="true" id="tableBody"
  67. :lower-threshold="40"
  68. :upper-threshold="10"
  69. @scrolltolower="scrolltolower"
  70. @scrolltoupper="(e)=>debounce(scrollToLeft)(e)"
  71. @scroll="handleBodyScroll" :scroll-left="bodyTableLeft" :scroll-top="bodyScrollTop"
  72. :style=" `height: calc(100% - ${showSummary?80:40}px)`" >
  73. <view class="zb-table-fixed">
  74. <view class="zb-table-tbody">
  75. <view :class="['item-tr',highlight&&isHighlight(item,index)?'current-row':'']"
  76. @click.stop="rowClick(item,index)"
  77. v-for="(item,index) in transData" :key="item.key" >
  78. <view
  79. :style="[{
  80. width:`${ite.width?ite.width:'100'}px`,
  81. flex:i===transColumns.length-1?1:'none',
  82. minWidth:`${ite.width?ite.width:'100'}px`,
  83. borderRight:`${border?'1px solid #e8e8e8':''}`,
  84. textAlign:ite.align||'left',
  85. },cellStyle&&getCellStyle(item,ite,index,i)]"
  86. @click="cellClick(item,index,ite)"
  87. :class="['item-td',stripe?(index % 2) != 0?'odd':'even':'']"
  88. v-for="(ite,i) in transColumns" :key="i">
  89. <template v-if="ite.type==='operation'">
  90. <view style="display: flex;align-items: center;height: 100%">
  91. <view
  92. v-for="ren,ind in permission(item,ite.renders,index)"
  93. :key="ind"
  94. @click.stop="$emit(ren.func,item,index)"
  95. :style="{
  96. display:'flex',
  97. alignItems: 'center',
  98. marginRight:ite.renders.length>1?'8px':'0'
  99. }">
  100. <template v-if="ren.type==='custom'">
  101. <view :class="ren.class||''" style="cursor: pointer">
  102. {{ren.name}}
  103. </view>
  104. </template>
  105. <template v-else>
  106. <button
  107. :class="ren.class||''"
  108. :type="ren.type||'primary'" :size="ren.size||'mini'">{{ren.name}}</button>
  109. </template>
  110. </view>
  111. </view>
  112. </template>
  113. <template v-else-if="ite.type==='selection'">
  114. <view class="checkbox-item">
  115. <tableCheckbox @checkboxSelected="(e)=>checkboxSelected(e,item)" :cellData="item" :checked="item.checked"/>
  116. </view>
  117. </template>
  118. <template v-else-if="ite.type==='index'">
  119. {{index+1}}
  120. </template>
  121. <template v-else-if="ite.type==='img'">
  122. <view class="checkbox-item">
  123. <template v-if="item[ite.name]">
  124. <image
  125. @click.stop="previewImage(item,item[ite.name],iImage)"
  126. v-for="iImageTem,iImage in imgs(item[ite.name])"
  127. :show-menu-by-longpress="false"
  128. :key="iImage"
  129. :src="iImageTem" style="width: 40px;height:30px; " mode="aspectFit"></image>
  130. </template>
  131. <text v-else>{{ite.emptyString}}</text>
  132. </view>
  133. </template>
  134. <template v-else>
  135. <!-- {{ ite.filters?itemFilter(item,ite):(item[ite.name]==null||item[ite.name]==='')?ite.emptyString:item[ite.name] }}-->
  136. {{ ite.filters?itemFilter(item,ite):formatterAction(item,ite,index,i) }}
  137. </template>
  138. </view>
  139. </view>
  140. </view>
  141. </view>
  142. </scroll-view>
  143. <table-h5-summary
  144. :scrollbarSize="scrollbarSize"
  145. :data="data"
  146. :handleFooterTableScrollLeft="handleFooterTableScrollLeft"
  147. :headerFooterTableLeft="headerFooterTableLeft"
  148. v-if="showSummary"
  149. :showSummary="showSummary"
  150. :transColumns="transColumns"
  151. :border="border"
  152. :summary-method="summaryMethod"
  153. :sumText="sumText"
  154. :fixedLeftColumns="fixedLeftColumns"/>
  155. </view>
  156. <view class="zb-table-fixed-left"
  157. v-if="isFixedLeft"
  158. :style=" {height: `calc(100% - ${scrollbarSize}px)`}"
  159. >
  160. <template v-if="showHeader">
  161. <view class="zb-table-header" style="display: flex">
  162. <view class="item-tr"
  163. style=""
  164. @click.stop="rowClick(item,index)"
  165. v-for="(item,index) in fixedLeftColumns" :key="index">
  166. <view
  167. :style="{
  168. width:`${item.width?item.width:'100'}px`,
  169. borderRight:`${border?'1px solid #e8e8e8':''}`,
  170. borderTop:`${border?'1px solid #e8e8e8':''}`,
  171. textAlign:item.align||'left'
  172. }"
  173. @click.stop="sortAction(item,index)"
  174. class="item-th"
  175. >
  176. <template v-if="item.type==='selection'">
  177. <view class="checkbox-item">
  178. <tableCheckbox
  179. :indeterminate="indeterminate" :checked="checkedAll" @checkboxSelected="checkboxSelectedAll"></tableCheckbox>
  180. </view>
  181. </template>
  182. <template v-else>
  183. {{ item.label }}
  184. <view class="sorter-table" v-if="item.sorter">
  185. <view :class="['sorter-table-icon',item.sorterMode==='_asc'&&`sorting${item.sorterMode||''}`]"></view>
  186. <view :class="['sorter-table-icon',item.sorterMode==='_desc'&&`sorting${item.sorterMode||''}`]"></view>
  187. </view>
  188. </template>
  189. </view>
  190. </view>
  191. </view>
  192. </template>
  193. <scroll-view
  194. scroll-y="true"
  195. id="leftTableFixed"
  196. :upper-threshold="15"
  197. @scrolltoupper="(e)=>scrollToFixedLeft(e)"
  198. @scroll="leftFixedScrollAction"
  199. :scroll-top="leftFiexScrollTop"
  200. class="zb-table-body-inner"
  201. :style=" `height: calc(100% - ${showSummary?80:40}px)`">
  202. <view class="zb-table-fixed">
  203. <view class="zb-table-tbody">
  204. <view
  205. :class="['item-tr',stripe?(i % 2) != 0?'odd':'even':'',highlight&&isHighlight(ite,i)?'current-row':'']"
  206. v-for="(ite,i) in transData"
  207. @click.stop="rowClick(ite,i)"
  208. :key="ite.key"
  209. style="">
  210. <view class='item-td'
  211. @click="cellClick(ite,index,item)"
  212. :style="[{
  213. width:`${item.width?item.width:'100'}px`,
  214. borderRight:`${border?'1px solid #e8e8e8':''}`,
  215. textAlign:item.align||'left'
  216. },cellStyle&&getCellStyle(ite,item,i,index)]"
  217. :key="index"
  218. v-for="(item,index) in fixedLeftColumns">
  219. <template v-if="item.type==='selection'">
  220. <view class="checkbox-item">
  221. <tableCheckbox @checkboxSelected="(e)=>checkboxSelected(e,ite)" :cellData="ite" :checked="ite.checked"/>
  222. </view>
  223. </template>
  224. <template v-else-if="item.type==='index'">
  225. {{i+1}}
  226. </template>
  227. <template v-else>
  228. {{ite[item.name]||item.emptyString}}
  229. </template>
  230. </view>
  231. </view>
  232. </view>
  233. </view>
  234. </scroll-view>
  235. <table-side-summary
  236. :scrollbarSize="scrollbarSize"
  237. v-if="showSummary&&!(scrollbarSize>0)"
  238. :data="data"
  239. :showSummary="showSummary"
  240. :transColumns="transColumns"
  241. :border="border"
  242. :summary-method="summaryMethod"
  243. :sumText="sumText"
  244. :fixedLeftColumns="fixedLeftColumns"/>
  245. </view>
  246. </view>
  247. <zb-load-more v-if="isLoadMore&&!completeLoading"/>
  248. </view>
  249. <!-- #endif -->
  250. <!-- #ifndef H5 || APP-PLUS -->
  251. <view class="zb-table-applet">
  252. <view class="zb-table-content" style="white-space: nowrap">
  253. <scroll-view
  254. <!-- #ifdef MP-ALIPAY -->
  255. @scroll="scrollAlipay"
  256. <!-- #endif -->
  257. @scrolltolower="scrolltolower"
  258. <!-- #ifdef MP-ALIPAY -->
  259. style=" height: 100%;overflow-x:scroll"
  260. <!-- #endif -->
  261. <!-- #ifndef MP-ALIPAY -->
  262. style=" height: 100%"
  263. <!-- #endif -->
  264. scroll-y="true"
  265. scroll-x="true">
  266. <view class="zb-table-scroll" >
  267. <template v-if="showHeader">
  268. <view class="zb-table-header top-header-uni" style="">
  269. <view class="zb-table-fixed" >
  270. <view class="zb-table-thead" style="position: relative;" >
  271. <view class="item-tr">
  272. <view
  273. @click.stop="sortAction(item,index)"
  274. :class="['item-th',index <fixedLeftColumns.length&&'zb-stick-side']"
  275. :style="{
  276. left:`${item.left}px`,
  277. width:`${item.width?item.width:'100'}px`,
  278. flex:index===transColumns.length-1?1:'none',
  279. minWidth:`${item.width?item.width:'100'}px`,
  280. borderRight:`${border?'1px solid #e8e8e8':''}`,
  281. borderTop:`${border?'1px solid #e8e8e8':''}`,
  282. textAlign:item.align||'left'
  283. }"
  284. v-for="(item,index) in transColumns" :key="index">
  285. <template v-if="item.type==='selection'">
  286. <view class="checkbox-item">
  287. <tableCheckbox
  288. :indeterminate="indeterminate" :checked="checkedAll" @checkboxSelected="checkboxSelectedAll"></tableCheckbox>
  289. </view>
  290. </template>
  291. <template v-else>
  292. {{ item.label||'' }}
  293. <view class="sorter-table" v-if="item.sorter">
  294. <view :class="['sorter-table-icon',item.sorterMode==='_asc'&&`sorting${item.sorterMode||''}`]"></view>
  295. <view :class="['sorter-table-icon',item.sorterMode==='_desc'&&`sorting${item.sorterMode||''}`]"></view>
  296. </view>
  297. </template>
  298. </view>
  299. </view>
  300. </view>
  301. </view>
  302. </view>
  303. </template>
  304. <template v-if="!data.length">
  305. <view class="no-data">暂无数据~~</view>
  306. </template>
  307. <view class="zb-table-fixed">
  308. <view class="zb-table-tbody">
  309. <view :class="['item-tr',highlight&&isHighlight(item,index)?'current-row':'']"
  310. @click.stop="rowClick(item,index)"
  311. v-for="(item,index) in transData" :key="item.key" >
  312. <view
  313. :style="[{
  314. left:`${ite.left}px`,
  315. width:`${ite.width?ite.width:'100'}px`,
  316. flex:i===transColumns.length-1?1:'none',
  317. minWidth:`${ite.width?ite.width:'100'}px`,
  318. borderRight:`${border?'1px solid #e8e8e8':''}`,
  319. textAlign:ite.align||'left',
  320. },getCellStyle(item,ite,index,i)]"
  321. @click="cellClick(item,index,ite)"
  322. :class="['item-td', i <fixedLeftColumns.length&&'zb-stick-side',stripe?(index % 2) != 0?'odd':'even':'']"
  323. v-for="(ite,i) in transColumns" :key="i">
  324. <template v-if="ite.type==='operation'">
  325. <view style="display: flex;align-items: center;height: 100%">
  326. <view
  327. v-for="ren,ind in permission(item,ite.renders,index)"
  328. :key="ind"
  329. @click.stop="$emit(ren.func,item,index)"
  330. :style="{
  331. display:'flex',
  332. alignItems: 'center',
  333. marginRight:ite.renders.length>1?'8px':'0'
  334. }">
  335. <template v-if="ren.type==='custom'">
  336. <view :class="ren.class||''" style="cursor: pointer">
  337. {{ren.name}}
  338. </view>
  339. </template>
  340. <template v-else>
  341. <button
  342. :class="ren.class||''"
  343. :type="ren.type||'primary'" :size="ren.size||'mini'">{{ren.name}}</button>
  344. </template>
  345. </view>
  346. </view>
  347. </template>
  348. <template v-else-if="ite.type==='selection'">
  349. <view class="checkbox-item">
  350. <tableCheckbox @checkboxSelected="(e)=>checkboxSelected(e,item)" :cellData="item" :checked="item.checked"/>
  351. </view>
  352. </template>
  353. <template v-else-if="ite.type==='img'">
  354. <template v-if="item[ite.name]">
  355. <view class="checkbox-item" @click.stop>
  356. <image
  357. @click.stop="previewImage(iImageTem,item[ite.name],iImage)"
  358. v-for="iImageTem,iImage in imgs(item[ite.name])"
  359. :show-menu-by-longpress="false"
  360. :key="iImage"
  361. :src="iImageTem" style="width: 40px;height:30px; " mode="aspectFit"></image>
  362. </view>
  363. </template>
  364. <text v-else>{{ite.emptyString}}</text>
  365. </template>
  366. <template v-else-if="ite.type==='index'">
  367. {{index+1}}
  368. </template>
  369. <template v-else>
  370. <!-- {{ ite.filters?itemFilter(item,ite):(item[ite.name]==null||item[ite.name]==='')?ite.emptyString:item[ite.name] }}-->
  371. {{ ite.filters?itemFilter(item,ite):formatterAction(item,ite,index,i) }}
  372. </template>
  373. </view>
  374. </view>
  375. </view>
  376. </view>
  377. <table-summary
  378. v-if="showSummary"
  379. :data="data"
  380. :showSummary="showSummary"
  381. :fixedLeftColumns="fixedLeftColumns"
  382. :transColumns="transColumns"
  383. :border="border"
  384. :summary-method="summaryMethod"
  385. :sumText="sumText"
  386. />
  387. </view>
  388. </scroll-view>
  389. </view>
  390. <zb-load-more v-if="isLoadMore&&!completeLoading"/>
  391. </view>
  392. <!-- #endif -->
  393. </template>
  394. <script>
  395. import TableCheckbox from './components/table-checkbox.vue'
  396. import TableSummary from "./components/table-summary.vue";
  397. import TableSideSummary from "./components/table-side-summary.vue";
  398. import TableH5Summary from './components/table-h5-summary'
  399. import ZbLoadMore from './components/zb-load-more'
  400. // #ifdef H5
  401. import {getScrollbarSize} from "./js/util";
  402. // #endif
  403. export default {
  404. components:{
  405. TableCheckbox,
  406. TableSummary,
  407. TableSideSummary,
  408. TableH5Summary,
  409. ZbLoadMore
  410. },
  411. props:{
  412. highlight:{
  413. type:Boolean,
  414. default:false
  415. },
  416. itemDate:{
  417. type:Object,
  418. default:()=>{}
  419. },
  420. columns:{
  421. type:Array,
  422. default:()=>[]
  423. },
  424. showSummary:{
  425. type:Boolean,
  426. default:false
  427. },
  428. isShowLoadMore:{
  429. type:Boolean,
  430. default:false
  431. },
  432. data:{
  433. type:Array,
  434. default:()=>[]
  435. },
  436. sumText:{
  437. type:String,
  438. default:'合计'
  439. },
  440. showHeader:{
  441. type:Boolean,
  442. default:true
  443. },
  444. border:{
  445. type:Boolean,
  446. default:false
  447. },
  448. stripe:{
  449. type:Boolean,
  450. default:true
  451. },
  452. fit:{
  453. type:Boolean,
  454. default:false
  455. },
  456. rowKey:[String, Function],
  457. summaryMethod:Function,
  458. pullUpLoading:Function,
  459. formatter:Function,
  460. cellStyle:Function,
  461. cellHeaderStyle:Function,
  462. permissionBtn:Function,
  463. },
  464. computed:{
  465. loadMoreHeight(){
  466. return this.isLoadMore?40:0
  467. },
  468. fixedLeftColumns(){
  469. let arr = []
  470. for(let i=0;i<this.columns.length;i++){
  471. let item = this.columns[i]
  472. if(item.fixed){
  473. arr.push(item)
  474. }else {
  475. break
  476. }
  477. }
  478. return arr
  479. },
  480. imgs(){
  481. return (item)=>{
  482. return typeof item==='string'?[item]:item
  483. }
  484. },
  485. itemfilters(){
  486. return(item,ite)=>{
  487. if(item[ite.name]==null){
  488. return ite.emptyString
  489. }
  490. return item[ite.name]
  491. }
  492. },
  493. scrollbarSize(){
  494. // #ifdef H5
  495. return getScrollbarSize()
  496. // #endif
  497. // #ifndef H5
  498. return 0
  499. // #endif
  500. },
  501. isFixedLeft(){
  502. if(!this.columns.length){
  503. return false
  504. }
  505. if(!this.data.length){
  506. return false
  507. }
  508. let [firstArr] = this.columns
  509. return !!firstArr.fixed;
  510. },
  511. transColumns(){
  512. if(this.fit){
  513. this.columns.forEach(column=>{
  514. if(column.type==="operation"&&column.renders){
  515. let str = ''
  516. column.renders.map((item)=>{
  517. str+=item.name
  518. })
  519. column.width = this.getTextWidth(str)+column.renders.length*40
  520. }else if(column.type==="img"){
  521. }else if(column.type==="selection"){
  522. }else{
  523. let arr = [this.getTextWidth(column.label)]
  524. this.data.forEach(data=>{
  525. let str = (data[column.name]+'')
  526. if(str==='undefined'){
  527. arr.push(30)
  528. }else{
  529. let width = this.getTextWidth(str)
  530. arr.push(width)
  531. }
  532. })
  533. column.width = Math.max(...arr)+20
  534. }
  535. })
  536. }
  537. let number = 0
  538. this.columns.forEach((item,index)=>{
  539. if(item.type==="operation"&&item.renders&&!item.width){
  540. let str = ''
  541. item.renders.map((item)=>{
  542. str+=item.name
  543. })
  544. item.width = this.getTextWidth(str)+item.renders.length*40
  545. }
  546. if(item.type==="img"){
  547. if(!item.width){
  548. let arr = []
  549. let widImg = this.getTextWidth(item.label)
  550. this.data.forEach(data=>{
  551. if(data[item.name]){
  552. let urls = typeof data[item.name]==='string'?[data[item.name]]:data[item.name]
  553. arr.push(urls.length)
  554. }
  555. item.width = Math.max(...arr)*40+widImg
  556. })
  557. }
  558. }
  559. if(item.fixed){
  560. if(index===0){
  561. item.left = 0
  562. number+=item.width
  563. }else {
  564. item.left = number
  565. number+=item.width
  566. }
  567. }
  568. item.emptyString = item.emptyString||'--'
  569. })
  570. return this.columns
  571. },
  572. transData(){
  573. let flag = this.columns.some(item=>item.type==='selection')
  574. this.data.forEach((item,index)=>{
  575. if(flag){
  576. if(item.checked){
  577. if(!this.selectArr.length){
  578. this.selectArr.push(item)
  579. }
  580. }
  581. }
  582. if(this.rowKey){
  583. if(typeof this.rowKey==='function'){
  584. item.key = Object.freeze(this.rowKey(item))||Date.now()
  585. }else {
  586. item.key = Object.freeze(item[this.rowKey])||Date.now()
  587. }
  588. }else {
  589. item.key = index
  590. }
  591. })
  592. if(flag){
  593. if(this.data.length){
  594. let le = this.data.filter(item=>item.checked).length
  595. if(le){
  596. if(le===this.data.length){
  597. this.checkedAll = true
  598. }else {
  599. this.indeterminate = true
  600. }
  601. }else {
  602. this.checkedAll = false
  603. this.indeterminate = false
  604. this.selectArr = []
  605. }
  606. }else {
  607. this.checkedAll = false
  608. this.indeterminate = false
  609. this.selectArr = []
  610. }
  611. }
  612. return this.data
  613. },
  614. isHighlight(){
  615. return (item,index)=>{
  616. if(this.rowKey){
  617. return item.key === this.currentRow['key']
  618. }else{
  619. return index === this.currentRowIndex
  620. }
  621. }
  622. },
  623. getHeaderCellStyle() {
  624. return (column, columnIndex,childIndex)=>{
  625. const cellStyle = this.cellHeaderStyle;
  626. if(typeof cellStyle==='function'){
  627. return cellStyle({ column, columnIndex})
  628. }
  629. return {}
  630. }
  631. },
  632. getCellStyle() {
  633. return (row, column, rowIndex, columnIndex)=>{
  634. const cellStyle = this.cellStyle;
  635. if(typeof cellStyle==='function'){
  636. return cellStyle({row, column, rowIndex, columnIndex})
  637. }
  638. return {}
  639. }
  640. },
  641. },
  642. data() {
  643. return {
  644. button:[],
  645. alipayScrollTop:0,
  646. alipayScrollOldTop:0,
  647. alipayFlag:false,
  648. bodyTableLeft:0,
  649. headerTableLeft:0,
  650. lastScrollLeft:0,
  651. isLoadMore:false,
  652. headerFooterTableLeft:0,
  653. leftFiexScrollTop:0,
  654. bodyScrollTop:0,
  655. currentDriver:null,
  656. currentDriver1:null,
  657. bodyTime:null,
  658. currentRowIndex:null,
  659. currentRow: {},
  660. bodyTime1:null,
  661. headerTime:null,
  662. debounceTime:null,
  663. operation:{},
  664. completedFlag:false,
  665. selectArr:[],
  666. indeterminate:false,
  667. checkedAll:false,
  668. completeLoading:false,
  669. aliTime:null,
  670. }
  671. },
  672. created(){
  673. },
  674. mounted(){
  675. // setTimeout(()=>{
  676. // uni.createSelectorQuery().in(this).select(".top-header-uni").boundingClientRect( data => {
  677. // console.log('data=======',data)
  678. // //data 可以打印data输出看详细数据,有很多数据信息
  679. // var left = data.width;//表示元素宽度
  680. // }).exec();
  681. // },1000)
  682. },
  683. beforeDestroy(){
  684. this.aliTime&&clearTimeout(this.aliTime)
  685. this.debounceTime&&clearTimeout(this.debounceTime)
  686. this.bodyTime1&&clearTimeout(this.bodyTime1)
  687. this.bodyTime&&clearTimeout(this.bodyTime)
  688. this.selectArr = []
  689. this.indeterminate = false
  690. this.checkedAll = false
  691. },
  692. methods: {
  693. clearSelection(){
  694. this.transData.forEach(item=>{
  695. item.checked = false
  696. })
  697. this.selectArr = []
  698. this.indeterminate = false
  699. this.checkedAll = false
  700. },
  701. formatterAction(row,column,rowIndex,columnIndex){
  702. if(column.formatter&&typeof this.formatter==='function'){
  703. return this.formatter(row,column,rowIndex,columnIndex)
  704. }
  705. return (row[column.name]==null||row[column.name]==='')?column.emptyString:row[column.name]
  706. },
  707. permission(item,renders,index){
  708. if(this.permissionBtn&&typeof this.permissionBtn==='function'){
  709. return this.permissionBtn(item,renders,index)
  710. }
  711. return renders
  712. },
  713. pullUpCompleteLoading(type){
  714. this.isLoadMore = false
  715. if(type==='ok'){
  716. this.completeLoading = true
  717. }
  718. },
  719. scrollAlipay(e){
  720. if(!this.alipayScrollOldTop){
  721. this.alipayScrollOldTop = e.detail.scrollTop
  722. }
  723. this.aliTime&&clearTimeout(this.aliTime)
  724. this.aliTime = setTimeout(()=>{
  725. if(this.alipayFlag&&e.detail.scrollTop>this.alipayScrollOldTop){
  726. this.pullLoad()
  727. }
  728. this.alipayFlag = false
  729. this.alipayScrollOldTop = null
  730. },500)
  731. },
  732. pullLoad(){
  733. if(this.isShowLoadMore){
  734. this.isLoadMore = true
  735. this.$emit('pullUpLoading')
  736. let that = this
  737. this.pullUpLoading&&this.pullUpLoading.call(this.$parent.$parent, (type)=>{
  738. that.isLoadMore = false
  739. if(type==='ok'){
  740. that.completeLoading=true
  741. }
  742. })
  743. }
  744. },
  745. scrolltolower(e){
  746. this.alipayFlag = true
  747. if(e.detail.direction==='bottom'){
  748. this.pullLoad()
  749. }
  750. // this.pullUpLoading.call(this.$parent)
  751. },
  752. previewImage(item,url,current){
  753. let urls = typeof url==='string'?[url]:url
  754. uni.previewImage({
  755. current,
  756. urls:urls
  757. })
  758. },
  759. resetHighlight(){
  760. this.currentRowIndex = null
  761. this.currentRow = {}
  762. },
  763. cellClick(row,index,column){
  764. this.$emit('cellClick',row,index,column)
  765. },
  766. rowClick(row,index){
  767. if(this.highlight){
  768. this.currentRowIndex = index
  769. this.currentRow = row
  770. this.$emit('currentChange',row,index)
  771. }
  772. this.$emit('rowClick',row,index)
  773. },
  774. checkboxSelectedAll(e){
  775. this.indeterminate = false
  776. if(e.checked){
  777. this.selectArr = []
  778. this.checkedAll = true
  779. this.data.forEach(item=>{
  780. // this.$set(item,'checked',true)
  781. item.checked = true
  782. this.selectArr.push(item)
  783. })
  784. }else{
  785. this.checkedAll = false
  786. this.data.forEach(item=>{
  787. this.$set(item,'checked',false)
  788. })
  789. this.selectArr = []
  790. }
  791. // #ifndef H5 || APP-PLUS
  792. this.$forceUpdate()
  793. // #endif
  794. this.$emit('toggleAllSelection',e.checked,this.selectArr)
  795. },
  796. checkboxSelected(e,item){
  797. // #ifdef H5 || APP-PLUS
  798. this.$set(item,'checked',e.checked)
  799. // #endif
  800. // #ifndef H5 || APP-PLUS
  801. this.data.forEach(item=>{
  802. if(item.key===e.data.key){
  803. item.checked = e.checked
  804. }
  805. })
  806. // #endif
  807. item.checked = e.checked
  808. e.data.checked = e.checked
  809. if(e.checked){
  810. this.selectArr.push(e.data)
  811. }else{
  812. this.selectArr = this.selectArr.filter(item=>item.key!==e.data.key)
  813. }
  814. if(this.selectArr.length===this.transData.length){
  815. this.indeterminate = false
  816. this.checkedAll = true
  817. }else{
  818. this.indeterminate = true
  819. this.checkedAll = false
  820. }
  821. if(!this.selectArr.length){
  822. this.checkedAll = false
  823. this.indeterminate = false
  824. }
  825. // #ifndef H5 || APP-PLUS
  826. this.$forceUpdate()
  827. // #endif
  828. this.$emit('toggleRowSelection',e.checked,this.selectArr)
  829. },
  830. itemFilter(item,ite){
  831. if(ite.filters&&ite.name){
  832. let key = item[ite.name]
  833. return ite.filters[key]||''
  834. }
  835. return item[ite.name]||ite.emptyString
  836. },
  837. // 默认字体为微软雅黑 Microsoft YaHei,字体大小为 14px
  838. getTextWidth(str) {
  839. if(str.length<3){
  840. return 40
  841. }
  842. let regx = /^[0-9]+.?[0-9]*$/
  843. let flexWidth = 0
  844. for (const char of str) {
  845. if ((char >= 'A' && char <= 'Z') || (char >= 'a' && char <= 'z')) {
  846. // 如果是英文字符,为字符分配8个单位宽度
  847. flexWidth += 10
  848. } else if (char >= '\u4e00' && char <= '\u9fa5') {
  849. // 如果是中文字符,为字符分配15个单位宽度
  850. flexWidth += 15
  851. } else if(regx.test(char)){
  852. flexWidth += 9
  853. }else {
  854. // 其他种类字符,为字符分配8个单位宽度
  855. flexWidth += 7
  856. }
  857. }
  858. return flexWidth
  859. },
  860. width(item){
  861. return `${item.width?item.width:'100'}px`
  862. },
  863. showStripe(index){
  864. if(this.currentDriver)return
  865. if(this.stripe){
  866. return (index % 2) != 0?'odd':'even'
  867. }else{
  868. return ''
  869. }
  870. },
  871. //验证字符串是否是数字
  872. checkNumber(theObj) {
  873. var reg = /^[0-9]+.?[0-9]*$/;
  874. if (reg.test(theObj)) {
  875. return true;
  876. }
  877. return false;
  878. },
  879. isDate(data){
  880. if(isNaN(data)&&!isNaN(Date.parse(data))){
  881. return true
  882. }
  883. return false
  884. },
  885. sortAction(item,index){
  886. if(!item.sorter){return false}
  887. this.$set(item,'sorterMode',item.sorterMode==='_asc'?'_desc':'_asc')
  888. if(item.sorter==='custom'){
  889. this.$emit('sort-change',item,item.sorterMode.replace('_',''),index)
  890. }else {
  891. this.sortData(item)
  892. }
  893. // #ifndef H5 || APP-PLUS
  894. this.$forceUpdate()
  895. // #endif
  896. },
  897. sortData(item){
  898. let key = item.name
  899. if(item.sorterMode==='_asc'){
  900. this.data.sort((a,b)=>{
  901. if(this.checkNumber(a[key])){
  902. return a[key]-b[key]
  903. }
  904. if(this.isDate(a[key])){
  905. let a1 = new Date(a[key]).getTime()
  906. let b1 = new Date(b[key]).getTime()
  907. return a1-b1
  908. }
  909. })
  910. }else {
  911. this.data.sort((a,b)=>{
  912. if(this.checkNumber(a[key])){
  913. return b[key]-a[key]
  914. }
  915. if(this.isDate(a[key])){
  916. let a1 = new Date(a[key]).getTime()
  917. let b1 = new Date(b[key]).getTime()
  918. return b1-a1
  919. }
  920. })
  921. }
  922. },
  923. throttle(method,delay=60){
  924. let time = null
  925. return (...args)=>{
  926. if(!time){
  927. time = setTimeout(()=>{
  928. method(...args)
  929. time = null;
  930. },delay)
  931. }
  932. }
  933. },
  934. debounce(method,delay=1000){
  935. return (...args)=>{
  936. this.debounceTime&&clearTimeout(this.debounceTime)
  937. this.debounceTime = setTimeout(()=>{
  938. method(...args)
  939. },delay)
  940. }
  941. },
  942. handleBodyScroll(e){
  943. if(this.currentDriver&&this.currentDriver!==e.currentTarget.id)return
  944. this.currentDriver = e.currentTarget.id
  945. this.headerTableLeft = e.detail.scrollLeft
  946. this.headerFooterTableLeft = e.detail.scrollLeft
  947. this.leftFiexScrollTop = e.detail.scrollTop
  948. this.bodyTime&&clearTimeout(this.bodyTime)
  949. this.bodyTime = setTimeout(()=>{
  950. this.currentDriver=null
  951. },200)
  952. },
  953. leftFixedScrollAction(e){
  954. if(this.currentDriver&&this.currentDriver!==e.currentTarget.id)return
  955. this.currentDriver = e.currentTarget.id
  956. this.bodyScrollTop = e.detail.scrollTop
  957. this.bodyTime&&clearTimeout(this.bodyTime)
  958. this.bodyTime = setTimeout(()=>{
  959. this.currentDriver=null
  960. },200)
  961. },
  962. scrollToLeft(e){
  963. if(this.currentDriver1&&this.currentDriver1!==e.currentTarget.id)return
  964. this.currentDriver1 = e.currentTarget.id
  965. if(e.detail.direction==='left'&&this.headerTableLeft<10){
  966. this.headerTableLeft = 0
  967. }else if(e.detail.direction==='top'&&this.leftFiexScrollTop<10){
  968. this.leftFiexScrollTop = 0
  969. }
  970. this.bodyTime&&clearTimeout(this.bodyTime)
  971. this.bodyTime = setTimeout(()=>{
  972. this.currentDriver1=null
  973. },200)
  974. },
  975. scrollToFixedLeft(e){
  976. if(this.currentDriver1&&this.currentDriver1!==e.currentTarget.id)return
  977. this.currentDriver1 = e.currentTarget.id
  978. if(e.detail.direction==='top'&&this.bodyScrollTop<10){
  979. this.bodyScrollTop = 0
  980. }
  981. this.bodyTime&&clearTimeout(this.bodyTime)
  982. this.bodyTime = setTimeout(()=>{
  983. this.currentDriver1=null
  984. },200)
  985. },
  986. handleTableScrollLeft(e,type){
  987. if(this.currentDriver&&this.currentDriver!==e.currentTarget.id)return
  988. this.currentDriver = e.currentTarget.id
  989. this.bodyTableLeft = e.detail.scrollLeft
  990. this.headerFooterTableLeft = e.detail.scrollLeft
  991. this.bodyTime&&clearTimeout(this.bodyTime)
  992. this.bodyTime = setTimeout(()=>{
  993. this.currentDriver=null
  994. },200)
  995. },
  996. handleFooterTableScrollLeft(e){
  997. if(this.currentDriver&&this.currentDriver!==e.currentTarget.id)return
  998. this.currentDriver = e.currentTarget.id
  999. this.bodyTableLeft = e.detail.scrollLeft
  1000. this.headerTableLeft = e.detail.scrollLeft
  1001. this.bodyTime&&clearTimeout(this.bodyTime)
  1002. this.bodyTime = setTimeout(()=>{
  1003. this.currentDriver=null
  1004. },200)
  1005. }
  1006. }
  1007. }
  1008. </script>
  1009. <style lang="scss">
  1010. .zb-table-fixed-left{
  1011. /*去除左边滚动条 */
  1012. scroll-view ::-webkit-scrollbar {
  1013. display: none !important;
  1014. width: 0 !important;
  1015. height: 0 !important;
  1016. -webkit-appearance: none;
  1017. background: transparent;
  1018. }
  1019. }
  1020. .zb-table-header{
  1021. ///*去除头部滚动条 */
  1022. scroll-view ::-webkit-scrollbar {
  1023. display: none !important;
  1024. width: 0 !important;
  1025. height: 0 !important;
  1026. -webkit-appearance: none;
  1027. background: transparent;
  1028. }
  1029. }
  1030. </style>
  1031. <style lang="scss" scoped>
  1032. .sorter-table{
  1033. position: absolute;
  1034. right: 6px;
  1035. top:50%;
  1036. transform:translateY(-50%);
  1037. .sorter-table-icon{
  1038. width: 0;
  1039. height: 0;
  1040. color: #dcdcdc;
  1041. border-right: 4px solid transparent;
  1042. border-left: 4px solid transparent;
  1043. }
  1044. .sorter-table-icon:first-child{
  1045. border-bottom: 5px solid currentColor;
  1046. }
  1047. .sorter-table-icon:last-child{
  1048. margin-top: 1.5px;
  1049. border-top: 5px solid currentColor;
  1050. }
  1051. .sorting_desc{
  1052. color: #2979ff;
  1053. }
  1054. .sorting_asc{
  1055. color: #2979ff;
  1056. }
  1057. }
  1058. .checkbox-item{
  1059. display: flex;align-items: center;justify-content: center;width: 100%;height: 100%
  1060. }
  1061. .no-data{
  1062. width: 100%;
  1063. height: 80rpx;
  1064. display: flex;
  1065. justify-content: center;
  1066. align-items: center;
  1067. border-bottom: 1px solid #e8e8e8;
  1068. }
  1069. .item-th{
  1070. position: relative;
  1071. flex-shrink: 0;
  1072. width: 100px;
  1073. overflow-wrap: break-word;
  1074. border-bottom: 1px solid #e8e8e8;
  1075. transition: background 0.3s;
  1076. padding-right: 20px;
  1077. word-break:keep-all; /* 不换行 */
  1078. white-space:nowrap; /* 不换行 */
  1079. overflow:hidden; /* 内容超出宽度时隐藏超出部分的内容 */
  1080. text-overflow:ellipsis; /* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
  1081. overflow-wrap: break-word;
  1082. }
  1083. .zb-table{
  1084. height: 100%;
  1085. overflow: hidden;
  1086. width: 100%;
  1087. display: flex;
  1088. flex-direction: column;
  1089. font-size: 12px;
  1090. position: relative;
  1091. .zb-table-content{
  1092. //height: 100%;
  1093. //flex: 1;
  1094. position: relative;
  1095. overflow: hidden;
  1096. }
  1097. .zb-table-fixed{
  1098. min-width: 100%;
  1099. }
  1100. .zb-table-body{
  1101. position: relative;
  1102. background: #fff;
  1103. transition: opacity 0.3s;
  1104. }
  1105. .item-tr{
  1106. display: flex;
  1107. //height: 41px;
  1108. }
  1109. .item-td{
  1110. flex-shrink: 0;
  1111. width: 100px;
  1112. padding-left: 8px;
  1113. height: 40px;
  1114. line-height: 40px;
  1115. padding-right: 20px;
  1116. box-sizing: border-box;
  1117. word-break:keep-all; /* 不换行 */
  1118. white-space:nowrap; /* 不换行 */
  1119. overflow:hidden; /* 内容超出宽度时隐藏超出部分的内容 */
  1120. text-overflow:ellipsis; /* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
  1121. overflow-wrap: break-word;
  1122. border-bottom: 1px solid #e8e8e8;
  1123. //transition: background 0.3s;
  1124. }
  1125. .zb-table-fixed-left .zb-table-header{
  1126. overflow-y: hidden;
  1127. }
  1128. .zb-table-header {
  1129. overflow: hidden;
  1130. background: #fafafa;
  1131. .item-th{
  1132. padding-left: 8px;
  1133. line-height: 39px;
  1134. height: 40px;
  1135. //display: flex;
  1136. //align-items: center;
  1137. box-sizing: border-box;
  1138. }
  1139. }
  1140. .zb-table-fixed-left .zb-table-fixed{
  1141. background: #fff;
  1142. }
  1143. .zb-table-fixed-right .zb-table-fixed{
  1144. background: #fff;
  1145. }
  1146. .zb-table-body-inner{
  1147. height: 100%;
  1148. // overflow: scroll;
  1149. }
  1150. .zb-table-fixed-left{
  1151. position: absolute;
  1152. top: 0;
  1153. z-index: 1;
  1154. overflow: hidden;
  1155. border-radius: 0;
  1156. height: 100%;
  1157. //transition: box-shadow 0.3s ease;
  1158. }
  1159. .odd{
  1160. background-color:rgba(249,249,249,0.6);
  1161. //height: 100%;
  1162. width: 100%;
  1163. }
  1164. .even{
  1165. background-color:white ;
  1166. //height: 100%;
  1167. width: 100%;
  1168. }
  1169. }
  1170. .scroll-left-fixed{
  1171. .zb-table-fixed-left {
  1172. left: 0;
  1173. box-shadow: 6px 0 6px -4px #ccc;
  1174. }
  1175. }
  1176. .zb-table-applet{
  1177. height: 100%;
  1178. //overflow: hidden;
  1179. width: 100%;
  1180. position: relative;
  1181. display: flex;
  1182. flex-direction: column;
  1183. font-size: 12px;
  1184. .zb-table-content{
  1185. //height: 100%;
  1186. flex: 1;
  1187. overflow: hidden;
  1188. position: relative;
  1189. }
  1190. .zb-table-fixed{
  1191. min-width: 100%;
  1192. width: fit-content;
  1193. }
  1194. .zb-table-body{
  1195. position: relative;
  1196. background: #fff;
  1197. transition: opacity 0.3s;
  1198. }
  1199. .item-tr{
  1200. display: flex;
  1201. //height: 41px;
  1202. }
  1203. .item-td{
  1204. flex-shrink: 0;
  1205. width: 100px;
  1206. padding-left: 8px;
  1207. height: 40px;
  1208. line-height: 40px;
  1209. padding-right:20px;
  1210. box-sizing: border-box;
  1211. word-break:keep-all; /* 不换行 */
  1212. white-space:nowrap; /* 不换行 */
  1213. overflow:hidden; /* 内容超出宽度时隐藏超出部分的内容 */
  1214. text-overflow:ellipsis; /* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
  1215. overflow-wrap: break-word;
  1216. border-bottom: 1px solid #e8e8e8;
  1217. //transition: background 0.3s;
  1218. }
  1219. .zb-table-header {
  1220. //overflow: hidden;
  1221. position: sticky;
  1222. top: 0;
  1223. z-index: 2;
  1224. //width: fit-content;
  1225. .item-th{
  1226. padding-left: 8px;
  1227. line-height: 39px;
  1228. height: 40px;
  1229. box-sizing: border-box;
  1230. background: #fafafa;
  1231. }
  1232. .zb-stick-side{
  1233. position: sticky;
  1234. top: 0;
  1235. left: 0;
  1236. z-index: 2;
  1237. //border-right: solid 1rpx #dbdbdb;
  1238. box-sizing: border-box;
  1239. background: #fafafa;
  1240. //box-shadow: 6px 0 6px -4px #ccc;
  1241. }
  1242. }
  1243. .zb-table-fixed-left .zb-table-fixed{
  1244. background: #fff;
  1245. }
  1246. .zb-table-fixed-right .zb-table-fixed{
  1247. background: #fff;
  1248. }
  1249. .zb-table-fixed-header .zb-table-body-inner{
  1250. height: 100%;
  1251. // overflow: scroll;
  1252. }
  1253. .zb-table-fixed-left{
  1254. position: absolute;
  1255. top: 0;
  1256. z-index: 1;
  1257. overflow: hidden;
  1258. border-radius: 0;
  1259. height: 100%;
  1260. //transition: box-shadow 0.3s ease;
  1261. }
  1262. .scroll-left-fixed{
  1263. .zb-table-fixed-left {
  1264. left: 0;
  1265. box-shadow: 6px 0 6px -4px #ccc;
  1266. }
  1267. }
  1268. .odd{
  1269. background-color:rgba(249,249,249,0.6);
  1270. //height: 100%;
  1271. width: 100%;
  1272. }
  1273. .even{
  1274. background-color:white ;
  1275. //height: 100%;
  1276. width: 100%;
  1277. }
  1278. .zb-table-tbody {
  1279. .zb-stick-side{
  1280. position: sticky;
  1281. left: 0;
  1282. z-index: 1;
  1283. box-sizing: border-box;
  1284. background:white;
  1285. //box-shadow: 6px 0 6px -2px #ccc;
  1286. }
  1287. .odd{
  1288. background:#f9f9f9;
  1289. //height: 100%;
  1290. width: 100%;
  1291. }
  1292. .even{
  1293. background:white ;
  1294. //height: 100%;
  1295. width: 100%;
  1296. }
  1297. }
  1298. .current-row{
  1299. .item-td{
  1300. background-color: #ecf5ff;
  1301. }
  1302. }
  1303. }
  1304. .current-row{
  1305. .item-td{
  1306. background-color: #ecf5ff;
  1307. }
  1308. }
  1309. .zb-table-header{
  1310. height: 40px;
  1311. }
  1312. .scrollPosition{
  1313. position: absolute;right: 0;top: 0;height: 100%;background: red;
  1314. z-index: 999;
  1315. }
  1316. </style>