index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. <template>
  2. <Water></Water>
  3. <view class="detail-page">
  4. <view class="tabs">
  5. <view
  6. class="tab"
  7. v-for="(t, i) in tabs"
  8. :key="t.label"
  9. :class="{ active: category == t.value }"
  10. :style="{ opacity: isLoading ? 0.5 : 1 }"
  11. @click="selectTab(t)"
  12. >
  13. {{ t.label }}
  14. </view>
  15. </view>
  16. <view class="card" :style="{ height: tableBodyHeight + 'rpx' }">
  17. <scroll-view
  18. class="grid-scroll"
  19. scroll-y="true"
  20. scroll-x="true"
  21. :show-scrollbar="false"
  22. :style="{
  23. maxHeight: tableBodyHeight + 'rpx',
  24. opacity: category == 1 ? 1 : 0,
  25. }"
  26. enhanced
  27. @scrolltolower="onTableScrollToLower"
  28. >
  29. <view
  30. :style="{
  31. width: '3000rpx',
  32. }"
  33. >
  34. <view class="grid-header">
  35. <text class="hcell hcell-sticky-left">查询企业名称</text>
  36. <text class="hcell">出库方企业名称</text>
  37. <text class="hcell">产品名称</text>
  38. <text class="hcell">规格</text>
  39. <text class="hcell">批号</text>
  40. <text class="hcell">货源地区</text>
  41. <text class="hcell">货源数量</text>
  42. <text class="hcell">终端到达数量</text>
  43. <text class="hcell">出库时间</text>
  44. <text class="hcell">追溯码抽样</text>
  45. <text class="hcell">链路</text>
  46. </view>
  47. <view v-if="!loading && rows.length > 0" class="grid-body">
  48. <view
  49. v-for="(row, idx) in rows"
  50. :key="idx + '-' + (row.produceBatchNo || '')"
  51. class="grow"
  52. >
  53. <view
  54. v-if="row.flags.enterpriseName"
  55. class="gcell gcol-1 gspan"
  56. :class="['sticky-left']"
  57. :style="{ gridRowEnd: 'span ' + row.spans.enterpriseName }"
  58. >{{ row.enterpriseName }}</view
  59. >
  60. <view
  61. v-if="row.flags.fromEntName"
  62. class="gcell gcol-2 gspan"
  63. :style="{ gridRowEnd: 'span ' + row.spans.fromEntName }"
  64. >{{ row.fromEntName }}</view
  65. >
  66. <view
  67. v-if="row.flags.physicName"
  68. class="gcell gcol-3 gspan"
  69. :style="{ gridRowEnd: 'span ' + row.spans.physicName }"
  70. >{{ row.physicName }}</view
  71. >
  72. <view
  73. v-if="row.flags.spec"
  74. class="gcell gcol-4 gspan"
  75. :style="{ gridRowEnd: 'span ' + row.spans.spec }"
  76. >
  77. {{ row.spec }}</view
  78. >
  79. <view class="gcell gcol-5">{{ row.produceBatchNo }}</view>
  80. <view class="gcell gcol-6">{{ row.fromRegionName }}</view>
  81. <view class="gcell gcol-7">{{ row.fromQuantity }}</view>
  82. <view class="gcell gcol-8">{{ row.toQuantity }}</view>
  83. <view class="gcell gcol-9">{{ row.billTime }}</view>
  84. <view class="gcell gcol-10">{{ row.tracCode }}</view>
  85. <view class="gcell gcol-11">{{ row.batchTraceLink }}</view>
  86. </view>
  87. <view class="gcell gcell-full loading-row" v-if="hasMore">
  88. <view class="loading-wrapper">
  89. <image
  90. class="loading-icon"
  91. src="../../../../static/images/loading.png"
  92. />
  93. </view>
  94. </view>
  95. </view>
  96. </view>
  97. </scroll-view>
  98. <scroll-view
  99. class="grid-scroll"
  100. scroll-y="true"
  101. scroll-x="true"
  102. :show-scrollbar="false"
  103. :style="{
  104. maxHeight: tableBodyHeight + 'rpx',
  105. opacity: category == 2 ? 1 : 0,
  106. position: 'absolute',
  107. top: '0',
  108. left: '0',
  109. zIndex: category == 2 ? '92' : '-1',
  110. }"
  111. enhanced
  112. @scrolltolower="onTableScrollToLower"
  113. >
  114. <view
  115. :style="{
  116. width: '3000rpx',
  117. }"
  118. >
  119. <view class="grid-header">
  120. <text class="hcell hcell-sticky-left">查询企业名称</text>
  121. <text class="hcell">入库方企业名称</text>
  122. <text class="hcell">产品名称</text>
  123. <text class="hcell">规格</text>
  124. <text class="hcell">批号</text>
  125. <text class="hcell">货源地区</text>
  126. <text class="hcell">货源数量</text>
  127. <text class="hcell">终端到达数量</text>
  128. <text class="hcell">入库时间</text>
  129. <text class="hcell">追溯码抽样</text>
  130. <text class="hcell">链路</text>
  131. </view>
  132. <view v-if="!_loading && _rows.length > 0" class="grid-body">
  133. <view
  134. v-for="(row, idx) in _rows"
  135. :key="idx + '-' + (row.produceBatchNo || '')"
  136. class="grow"
  137. >
  138. <view
  139. v-if="row.flags.enterpriseName"
  140. class="gcell gcol-1 gspan"
  141. :class="['sticky-left']"
  142. :style="{ gridRowEnd: 'span ' + row.spans.enterpriseName }"
  143. >{{ row.enterpriseName }}</view
  144. >
  145. <view
  146. v-if="row.flags.fromEntName"
  147. class="gcell gcol-2 gspan"
  148. :style="{ gridRowEnd: 'span ' + row.spans.fromEntName }"
  149. >{{ row.fromEntName }}</view
  150. >
  151. <view
  152. v-if="row.flags.physicName"
  153. class="gcell gcol-3 gspan"
  154. :style="{ gridRowEnd: 'span ' + row.spans.physicName }"
  155. >{{ row.physicName }}</view
  156. >
  157. <view
  158. v-if="row.flags.spec"
  159. class="gcell gcol-4 gspan"
  160. :style="{ gridRowEnd: 'span ' + row.spans.spec }"
  161. >
  162. {{ row.spec }}</view
  163. >
  164. <view class="gcell gcol-5">{{ row.produceBatchNo }}</view>
  165. <view class="gcell gcol-6">{{ row.fromRegionName }}</view>
  166. <view class="gcell gcol-7">{{ row.fromQuantity }}</view>
  167. <view class="gcell gcol-8">{{ row.toQuantity }}</view>
  168. <view class="gcell gcol-9">{{ row.billTime }}</view>
  169. <view class="gcell gcol-10">{{ row.tracCode }}</view>
  170. <view class="gcell gcol-11">{{ row.batchTraceLink }}</view>
  171. </view>
  172. <view class="gcell gcell-full loading-row" v-if="_hasMore">
  173. <view class="loading-wrapper">
  174. <image
  175. class="loading-icon"
  176. src="../../../../static/images/loading.png"
  177. />
  178. </view>
  179. </view>
  180. </view>
  181. </view>
  182. </scroll-view>
  183. <view v-if="isLoading" class="loading-wrap">
  184. <view class="loading-row">
  185. <view class="loading-wrapper">
  186. <image
  187. class="loading-icon"
  188. src="../../../../static/images/loading.png"
  189. />
  190. </view>
  191. </view>
  192. </view>
  193. <view v-if="showEmptyData" class="empty-data">
  194. <EmptyView text="无相关数据" />
  195. </view>
  196. </view>
  197. </view>
  198. </template>
  199. <script>
  200. import EmptyView from "../../../../wigets/empty.vue";
  201. import Water from "@/components/water/water.vue";
  202. import request from "../../../../request/index.js";
  203. import { formatDate } from "../../../../utils/utils.js";
  204. export default {
  205. components: {
  206. EmptyView,
  207. Water,
  208. },
  209. data() {
  210. return {
  211. taskId: "",
  212. tableBodyHeight: 0,
  213. baseRowHeight: 76,
  214. tabs: [
  215. {
  216. label: "药品购进",
  217. value: "1",
  218. },
  219. {
  220. label: "药品销售",
  221. value: "2",
  222. },
  223. ],
  224. category: "1",
  225. loading: true,
  226. rows: [],
  227. totalCount: 0,
  228. fetchLoading: false,
  229. hasMore: true,
  230. pageNum: 1,
  231. pageSize: 10,
  232. _loading: true,
  233. _rows: [],
  234. _totalCount: 0,
  235. _fetchLoading: false,
  236. _hasMore: true,
  237. _pageNum: 1,
  238. _pageSize: 10,
  239. };
  240. },
  241. onLoad(options) {
  242. const title =
  243. options && options.title ? decodeURIComponent(options.title) : "报表详情";
  244. this.taskId = options && options.id ? options.id : "";
  245. uni.setNavigationBarTitle({ title });
  246. this.tableBodyHeight = 14 * 80;
  247. // this.rows = this.buildRows(this.genHierData());
  248. //this._rows = this.buildRows(this.genHierData());
  249. this.fetchList();
  250. },
  251. computed: {
  252. // isFixedHeight() {
  253. // const arr = Array.isArray(this.rows) ? this.rows : [];
  254. // const countLeaves = (node) => {
  255. // if (!node || !node.enterpriseList || node.enterpriseList.length === 0) return 1;
  256. // let sum = 0;
  257. // for (let i = 0; i < node.enterpriseList.length; i++) {
  258. // sum += countLeaves(node.enterpriseList[i]);
  259. // }
  260. // return sum;
  261. // };
  262. // let total = 0;
  263. // for (let i = 0; i < arr.length; i++) {
  264. // total += countLeaves(arr[i]);
  265. // }
  266. // return total >= 12;
  267. // },
  268. isLoading() {
  269. return (
  270. (this.loading && this.category == 1) ||
  271. (this._loading && this.category == 2)
  272. );
  273. },
  274. showEmptyData() {
  275. if (this.isLoading) return false;
  276. if (
  277. (this.category == 1 && this.rows.length === 0) ||
  278. (this.category == 2 && this._rows.length === 0)
  279. )
  280. return true;
  281. return false;
  282. },
  283. },
  284. methods: {
  285. selectTab(t) {
  286. if (this.isLoading) return;
  287. this.category = t.value;
  288. this.fetchList();
  289. },
  290. genHierData() {
  291. return [
  292. {
  293. enterpriseName: "上海海王星辰药房有限公司",
  294. enterpriseList: [
  295. {
  296. fromEntName: "福建广药洁达医药有限公司",
  297. enterpriseList: [
  298. {
  299. physicName: "感冲",
  300. produceBatchNo: "2502104H",
  301. fromRegionName: "广东",
  302. fromQuantity: 1000,
  303. toQuantity: 30,
  304. billTime: "区间内第一次出库时间——区间内最后一次出库时间",
  305. tracCode: "A",
  306. },
  307. {
  308. physicName: "皮炎平",
  309. produceBatchNo: "2502105H",
  310. fromRegionName: "广西",
  311. fromQuantity: 200,
  312. toQuantity: 20,
  313. billTime: "区间内第一次出库时间——区间内最后一次出库时间",
  314. tracCode: "B",
  315. },
  316. {
  317. physicName: "感冲",
  318. produceBatchNo: "2502105H",
  319. fromRegionName: "广西",
  320. fromQuantity: 200,
  321. toQuantity: 20,
  322. billTime: "区间内第一次出库时间——区间内最后一次出库时间",
  323. tracCode: "B",
  324. },
  325. {
  326. physicName: "感冲",
  327. produceBatchNo: "2502105H",
  328. fromRegionName: "广西",
  329. fromQuantity: 200,
  330. toQuantity: 20,
  331. billTime: "区间内第一次出库时间——区间内最后一次出库时间",
  332. tracCode: "B",
  333. },
  334. ],
  335. },
  336. {
  337. fromEntName: "B有限公司",
  338. enterpriseList: [
  339. {
  340. physicName: "感冲",
  341. produceBatchNo: "2502104H",
  342. fromRegionName: "广东",
  343. fromQuantity: 1000,
  344. toQuantity: 30,
  345. billTime: "区间内第一次出库时间——区间内最后一次出库时间",
  346. tracCode: "A",
  347. },
  348. ],
  349. },
  350. ],
  351. },
  352. {
  353. enterpriseName: "大参林连锁药店",
  354. enterpriseList: [
  355. {
  356. fromEntName: "C有限公司",
  357. enterpriseList: [
  358. {
  359. physicName: "感冲",
  360. produceBatchNo: "2502105H",
  361. fromRegionName: "广东",
  362. fromQuantity: 1000,
  363. toQuantity: 30,
  364. billTime: "区间内第一次出库时间——区间内最后一次出库时间",
  365. tracCode: "A",
  366. },
  367. {
  368. physicName: "皮炎平",
  369. produceBatchNo: "2502105H",
  370. fromRegionName: "广西",
  371. fromQuantity: 200,
  372. toQuantity: 20,
  373. billTime: "区间内第一次出库时间——区间内最后一次出库时间",
  374. tracCode: "B",
  375. },
  376. ],
  377. },
  378. {
  379. fromEntName: "D有限公司",
  380. enterpriseList: [
  381. {
  382. physicName: "皮炎平",
  383. produceBatchNo: "2502105H",
  384. fromRegionName: "广西",
  385. fromQuantity: 200,
  386. toQuantity: 20,
  387. billTime: "区间内第一次出库时间——区间内最后一次出库时间",
  388. tracCode: "B",
  389. },
  390. ],
  391. },
  392. ],
  393. },
  394. ];
  395. },
  396. computeLeafCount(node) {
  397. if (!node || !node.enterpriseList || !node.enterpriseList.length)
  398. return 1;
  399. let sum = 0;
  400. node.enterpriseList.forEach((c) => {
  401. sum += this.computeLeafCount(c);
  402. });
  403. node.leafCount = sum;
  404. return sum;
  405. },
  406. buildRows(data) {
  407. const res = [];
  408. (data || []).forEach((companyNode) => {
  409. const cLeaves = this.computeLeafCount(companyNode);
  410. let companyStarted = false;
  411. (companyNode.enterpriseList || []).forEach((expNode) => {
  412. const eLeaves = this.computeLeafCount(expNode);
  413. let exporterStarted = false;
  414. const groups = {};
  415. const specGroups = {};
  416. (expNode.enterpriseList || []).forEach((item) => {
  417. const key = item.physicName || "";
  418. if (!groups[key]) groups[key] = [];
  419. groups[key].push(item);
  420. if (!specGroups[key]) specGroups[key] = [];
  421. specGroups[key].push(item.pkgSpec || "");
  422. });
  423. Object.keys(groups).forEach((prodName) => {
  424. const group = groups[prodName];
  425. let productStarted = false;
  426. group.forEach((batch) => {
  427. const { minBillTime, maxBillTime } = batch;
  428. const billTime = `${formatDate(minBillTime, "YYYY-MM-DD")}——${formatDate(maxBillTime, "YYYY-MM-DD")}`;
  429. res.push({
  430. enterpriseName: companyNode.enterpriseName,
  431. fromEntName: expNode.fromEntName,
  432. physicName: prodName,
  433. spec: batch.pkgSpec || "",
  434. produceBatchNo: batch.produceBatchNo,
  435. fromRegionName: batch.regionName,
  436. fromQuantity: batch.fromQty,
  437. toQuantity: batch.toQty,
  438. billTime,
  439. tracCode: batch.tracCode,
  440. batchTraceLink: batch.batchTraceLink,
  441. spans: {
  442. enterpriseName: companyStarted ? 0 : cLeaves,
  443. fromEntName: exporterStarted ? 0 : eLeaves,
  444. physicName: productStarted ? 0 : group.length,
  445. spec: productStarted ? 0 : group.length,
  446. },
  447. flags: {
  448. enterpriseName: !companyStarted,
  449. fromEntName: !exporterStarted,
  450. physicName: !productStarted,
  451. spec: !productStarted,
  452. },
  453. });
  454. companyStarted = true;
  455. exporterStarted = true;
  456. productStarted = true;
  457. });
  458. });
  459. });
  460. });
  461. return res;
  462. },
  463. onTableScrollToLower(e) {
  464. if (e?.detail?.direction === "right") return;
  465. // if (this.isLoading) return;
  466. // if (this.rows.length >= this.totalCount) return;
  467. // this.isLoading = true;
  468. // const remain = this.totalCount - this.rows.length;
  469. // const toAdd = Math.min(15, remain);
  470. // setTimeout(() => {
  471. // const more = this.rows.slice(0, toAdd);
  472. // this.rows = this.rows.concat(more);
  473. // this.isLoading = false;
  474. // }, 800);
  475. this.fetchList();
  476. },
  477. fetchList() {
  478. let obj = {
  479. pageNum: "pageNum",
  480. pageSize: "pageSize",
  481. totalCount: "totalCount",
  482. hasMore: "hasMore",
  483. fetchLoading: "fetchLoading",
  484. rows: "rows",
  485. loading: "loading",
  486. };
  487. if (this.category == 2) {
  488. obj.pageNum = "_pageNum";
  489. obj.pageSize = "_pageSize";
  490. obj.totalCount = "_totalCount";
  491. obj.hasMore = "_hasMore";
  492. obj.fetchLoading = "_fetchLoading";
  493. obj.rows = "_rows";
  494. obj.loading = "_loading";
  495. }
  496. if (this[obj.fetchLoading] || !this[obj.hasMore]) return;
  497. this[obj.fetchLoading] = true;
  498. let url = `/report/getTaskTableData`;
  499. try {
  500. request(url, {
  501. id: this.taskId,
  502. category: this.category,
  503. pageNum: this[obj.pageNum],
  504. pageSize: this[obj.pageSize],
  505. path: "/reportExport/detail/index.vue",
  506. }).then((res) => {
  507. if (res.code == 200) {
  508. const { total, list } = res.data || {};
  509. this[obj.totalCount] = total || 0;
  510. let _list = [];
  511. if (Array.isArray(list)) {
  512. _list = this.buildRows(list);
  513. }
  514. this[obj.rows] = [...this[obj.rows], ..._list];
  515. if (this[obj.rows].length < this[obj.totalCount]) {
  516. this[obj.hasMore] = true;
  517. this[obj.pageNum]++;
  518. } else {
  519. this[obj.hasMore] = false;
  520. }
  521. }
  522. this[obj.fetchLoading] = false;
  523. this[obj.loading] = false;
  524. });
  525. } catch (res) {
  526. console.log(res);
  527. this[obj.fetchLoading] = false;
  528. this[obj.loading] = false;
  529. }
  530. // this.rows = [];
  531. // setTimeout(() => {
  532. // const n = Math.min(15, this.totalCount);
  533. // this.rows = this.buildRows(this.genHierData()).slice(0, n);
  534. // this.fetchLoading = false;
  535. // }, 1000);
  536. },
  537. },
  538. };
  539. </script>
  540. <style scoped>
  541. .detail-page {
  542. box-sizing: border-box;
  543. padding: 24rpx;
  544. position: relative;
  545. min-height: 100vh;
  546. background: #f3f6f9;
  547. padding-bottom: calc(50rpx + env(safe-area-inset-bottom));
  548. }
  549. .tabs {
  550. display: flex;
  551. align-items: center;
  552. background: #fff;
  553. border-radius: 90rpx;
  554. padding: 10rpx;
  555. margin-bottom: 30rpx;
  556. }
  557. .tab {
  558. flex: 1;
  559. height: 70rpx;
  560. display: flex;
  561. align-items: center;
  562. justify-content: center;
  563. padding: 0 24rpx;
  564. border-radius: 70rpx;
  565. font-size: 28rpx;
  566. color: #333;
  567. }
  568. .tab + .tab {
  569. margin-left: 12rpx;
  570. }
  571. .tab.active {
  572. background: #2c69ff;
  573. color: #fff;
  574. }
  575. .card {
  576. position: relative;
  577. margin-top: 12rpx;
  578. font-size: 30rpx;
  579. overflow: hidden;
  580. }
  581. .grid-header {
  582. position: sticky;
  583. top: 0;
  584. z-index: 10;
  585. display: grid;
  586. grid-template-columns: 340rpx 300rpx 220rpx 220rpx 220rpx 220rpx 220rpx 220rpx 340rpx 200rpx 500rpx;
  587. }
  588. .grid-header .hcell {
  589. background: #eaf2ff;
  590. font-weight: bold;
  591. color: #2c69ff;
  592. }
  593. .hcell {
  594. height: 76rpx;
  595. display: flex;
  596. align-items: center;
  597. justify-content: center;
  598. }
  599. .hcell:last-child {
  600. border-right: none;
  601. }
  602. .hcell-sticky-left {
  603. position: sticky;
  604. left: 0;
  605. z-index: 11;
  606. }
  607. .grid-scroll {
  608. border-radius: 16rpx;
  609. margin-top: 8rpx;
  610. overflow: hidden;
  611. }
  612. .grid-body {
  613. background: #fff;
  614. display: grid;
  615. grid-template-columns: 340rpx 300rpx 220rpx 220rpx 220rpx 220rpx 220rpx 220rpx 340rpx 200rpx 500rpx;
  616. grid-auto-rows: auto;
  617. }
  618. .grow {
  619. display: contents;
  620. }
  621. .gcell {
  622. display: flex;
  623. align-items: center;
  624. justify-content: center;
  625. border-bottom: 1rpx solid #eef0f4;
  626. border-right: 1rpx solid #eef0f4;
  627. background: #fff;
  628. color: #333;
  629. padding: 0 20rpx;
  630. text-align: center;
  631. line-height: 50rpx;
  632. word-break: break-all;
  633. }
  634. .gcell:last-child {
  635. border-right: none;
  636. }
  637. .gcell.gcell-full {
  638. grid-column: 1 / -1;
  639. background: transparent;
  640. border: none;
  641. }
  642. .gspan {
  643. background: #fff;
  644. }
  645. .gcol-1 {
  646. grid-column: 1;
  647. }
  648. .gcol-2 {
  649. grid-column: 2;
  650. }
  651. .gcol-3 {
  652. grid-column: 3;
  653. }
  654. .gcol-4 {
  655. grid-column: 4;
  656. }
  657. .gcol-5 {
  658. grid-column: 5;
  659. }
  660. .gcol-6 {
  661. grid-column: 6;
  662. }
  663. .gcol-7 {
  664. grid-column: 7;
  665. }
  666. .gcol-8 {
  667. grid-column: 8;
  668. }
  669. .gcol-9 {
  670. grid-column: 9;
  671. }
  672. .gcol-10 {
  673. grid-column: 10;
  674. }
  675. .gcol-11 {
  676. grid-column: 11;
  677. }
  678. .sticky-left {
  679. position: sticky;
  680. left: 0;
  681. z-index: 9;
  682. background: #fff;
  683. }
  684. .loading-row {
  685. justify-content: flex-start;
  686. }
  687. .loading-wrapper {
  688. position: sticky;
  689. top: 50%;
  690. left: 0;
  691. width: calc(100vw - 48rpx);
  692. height: 76rpx;
  693. display: flex;
  694. align-items: center;
  695. justify-content: center;
  696. }
  697. .loading-icon {
  698. width: 40rpx;
  699. height: 40rpx;
  700. animation: spin 1s linear infinite;
  701. }
  702. @keyframes spin {
  703. from {
  704. transform: rotate(0deg);
  705. }
  706. to {
  707. transform: rotate(360deg);
  708. }
  709. }
  710. .empty-data,
  711. .loading-wrap {
  712. position: absolute;
  713. left: 0;
  714. top: 85rpx;
  715. z-index: 91;
  716. width: 100%;
  717. background-color: #fff;
  718. border-bottom-left-radius: 16rpx;
  719. border-bottom-right-radius: 16rpx;
  720. }
  721. </style>