index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. <template>
  2. <div class="header-actions" v-if="getActionList.length != 0">
  3. <div class="overflow-box">
  4. <el-button
  5. v-for="(item, index) in getActionList"
  6. :key="index"
  7. :type="item.type || 'primary'"
  8. :plain="item.plain ? item.plain : index != 0"
  9. v-bind="getHeaderActions(item)"
  10. @click="item.action"
  11. :disabled="item.disabled || false"
  12. >
  13. {{ item.text }}
  14. </el-button>
  15. </div>
  16. </div>
  17. <!-- statWarpHeight > 200 && -->
  18. <div
  19. class="stat-warp"
  20. v-if="statConfig.length != 0"
  21. :class="isMore ? 'show-more' : ''"
  22. >
  23. <div class="title">
  24. <select
  25. v-model="statSelectVal"
  26. v-if="statConfig.length > 1"
  27. @change="changeStatData"
  28. >
  29. <option :value="index" v-for="(i, index) in statConfig" :key="index">
  30. {{ i.label }}
  31. </option>
  32. </select>
  33. <div v-if="statConfig.length === 1">{{ statConfig[0].label }}</div>
  34. </div>
  35. <!-- v-if="statWarpHeight > 200" -->
  36. <div class="more-btn" @click="isMore = !isMore" >
  37. <span>
  38. <i v-if="!isMore" class="iconfont icon-btn_xiala22"></i>
  39. <i v-else class="iconfont icon-btn_shouqi22"></i>
  40. </span>
  41. </div>
  42. <ul id="statWarp">
  43. <li
  44. v-show="!i.data"
  45. :class="'theme' + i.type"
  46. v-for="(i, index) in statConfig[statSelectVal].data"
  47. :key="index"
  48. @click="i.click ? i.click(i, index) : ''"
  49. :style="i.click ? 'cursor: pointer' : ''"
  50. >
  51. <div class="label">{{ i.label }}</div>
  52. <div class="num">{{ i.num }}</div>
  53. </li>
  54. <li
  55. v-show="i.data"
  56. v-for="(i, index) in statConfig[statSelectVal].data"
  57. :key="index"
  58. class="multi-data"
  59. :class="'theme' + i.type"
  60. @click="i.click ? i.click(i, index) : ''"
  61. :style="i.click ? 'cursor: pointer' : ''"
  62. >
  63. <div class="label">{{ i.label }}</div>
  64. <div class="num-warp">
  65. <div class="num-box" v-for="(j, jindex) in i.data" :key="jindex">
  66. <div class="num-small" :style="'color:' + j.color">
  67. {{ j.num }}
  68. </div>
  69. <div class="label-small">{{ j.label }}</div>
  70. </div>
  71. </div>
  72. </li>
  73. </ul>
  74. </div>
  75. <div class="table-list-container by-table" v-loading="loading">
  76. <!-- v-if="!hideHeader" -->
  77. <header v-if="false" class="header">
  78. <h2>{{ title }}</h2>
  79. </header>
  80. <div class="by-search" v-if="!hideSearch">
  81. <div style="display: flex">
  82. <div
  83. class="by-dropdown"
  84. v-for="(i, index) in selectConfigCopy"
  85. :key="i.prop"
  86. style="margin-right: 10px"
  87. >
  88. <div class="by-dropdown-title">
  89. {{
  90. pagination[i.prop]
  91. ? i.data.find((j) => j.value === pagination[i.prop])
  92. ? i.data.find((j) => j.value === pagination[i.prop]).label
  93. : i.label
  94. : i.labelCopy
  95. }}
  96. <!-- {{ i.label || i.labelCopy }} -->
  97. <i style="margin-left: 5px" class="iconfont icon-iconm_xialan1"></i>
  98. </div>
  99. <ul class="by-dropdown-lists">
  100. <li
  101. @click="searchItemSelct('all', i, index)"
  102. v-if="i.isShowAll === false ? i.isShowAll : true"
  103. style=""
  104. >
  105. {{ $t("common.all") }}
  106. </li>
  107. <li
  108. v-for="j in i.data"
  109. :key="j.value"
  110. @click="searchItemSelct(j, i)"
  111. style=""
  112. >
  113. {{ j.label }}
  114. </li>
  115. </ul>
  116. </div>
  117. </div>
  118. <div style="display: flex">
  119. <el-input
  120. :placeholder="$t('common.pleaseEnterKeywords')"
  121. suffix-icon="search"
  122. size="mini"
  123. v-model="pagination.keyword"
  124. @keyup.enter="searchFn"
  125. >
  126. </el-input>
  127. <el-button
  128. type="primary"
  129. style="margin-left: 10px"
  130. size="default"
  131. v-no-double-click="searchFn"
  132. >{{ $t("common.search") }}</el-button
  133. >
  134. <div
  135. class="more-icon"
  136. @click="retrievalModalFn"
  137. v-if="$attrs.onMoreSearch"
  138. >
  139. <i class="iconfont icon-iconx_saixuan"></i>
  140. </div>
  141. </div>
  142. </div>
  143. <component :is="containerTag">
  144. <div class="filter-form-container">
  145. <slot />
  146. </div>
  147. <el-table
  148. ref="hocElTable"
  149. id="example"
  150. :data="source"
  151. v-if="!hideTable"
  152. style="width: 100%"
  153. v-bind="$attrs"
  154. v-on="tableEvents"
  155. row-key="id"
  156. lazy
  157. :load="load"
  158. :tree-props="{
  159. children: 'children',
  160. hasChildren: 'hasChildren',
  161. }"
  162. :height="tableHeight"
  163. >
  164. <el-table-column
  165. v-for="(item, index) in config"
  166. :key="index"
  167. v-bind="getAttrsValue(item)"
  168. :type="item.type || ''"
  169. :selectable="
  170. (rowData, rowIndex) => isSelectable(rowData, rowIndex, item)
  171. "
  172. >
  173. <template #default="scope" v-if="!item.type">
  174. <slot
  175. :name="item.attrs.slot"
  176. :item="scope.row"
  177. v-if="item.attrs.slot"
  178. >
  179. 插槽占位符
  180. </slot>
  181. <div v-else-if="isFunction(getValue(scope, item))">
  182. <component
  183. :is="renderTypeList[getMatchRenderFunction(item)].target"
  184. :cell-list="getValue(scope, item)()"
  185. :row="scope.row"
  186. :parent="getParent"
  187. @click="
  188. ($event) => {
  189. handleNativeClick(getAttrsValue(item), $event, item);
  190. }
  191. "
  192. />
  193. </div>
  194. <div v-else>
  195. {{ getValue(scope, item) }}
  196. </div>
  197. </template>
  198. </el-table-column>
  199. </el-table>
  200. <el-row
  201. v-if="!hidePagination"
  202. class="table-pagination"
  203. justify="end"
  204. type="flex"
  205. >
  206. <el-pagination
  207. background
  208. layout="total, sizes, prev, pager, next, jumper"
  209. :current-page="getPagination.pageNum"
  210. :page-size="getPagination.pageSize"
  211. :total="getPagination.total"
  212. @size-change="handleSizeChange"
  213. @current-change="handlePageChange"
  214. />
  215. </el-row>
  216. </component>
  217. </div>
  218. </template>
  219. <script>
  220. import { isFunction as isFn, isBoolean } from "./type";
  221. import ElementsMapping from "./ElementsMapping";
  222. import ComponentsMapping from "./ComponentsMapping";
  223. import { computed, defineComponent, getCurrentInstance, ref, watch } from "vue";
  224. import expand from "./expand";
  225. import Sortable from "sortablejs";
  226. export default defineComponent({
  227. name: "Table",
  228. components: {
  229. ElementsMapping,
  230. ComponentsMapping,
  231. },
  232. props: {
  233. hideSearch: {
  234. type: Boolean,
  235. default: false,
  236. },
  237. hideTable: {
  238. type: Boolean,
  239. default: false,
  240. },
  241. //顶部搜索下拉配置
  242. selectConfig: {
  243. type: Array,
  244. default() {
  245. return [];
  246. },
  247. },
  248. // 获取表格元数据时携带的参数
  249. filterParams: {
  250. type: Object,
  251. default() {
  252. return {};
  253. },
  254. },
  255. // 表格加载 loading
  256. loading: {
  257. type: Boolean,
  258. default: false,
  259. },
  260. // 表格名称
  261. title: {
  262. type: String,
  263. default: "",
  264. },
  265. // 表格元数据
  266. source: {
  267. type: Array,
  268. required: true,
  269. default() {
  270. return [];
  271. },
  272. },
  273. tableHeight: {
  274. type: Number,
  275. required: false,
  276. },
  277. searchConfig: {
  278. type: Object,
  279. default() {
  280. return {
  281. keyword: "",
  282. };
  283. },
  284. },
  285. statConfig: {
  286. type: Array,
  287. default() {
  288. return [];
  289. },
  290. },
  291. // 指定外层容器的渲染组件
  292. containerTag: {
  293. type: String,
  294. default: "div",
  295. },
  296. // 是否隐藏表头
  297. hideHeader: {
  298. type: Boolean,
  299. default: false,
  300. },
  301. // 是否隐藏分页
  302. hidePagination: {
  303. type: Boolean,
  304. default: false,
  305. },
  306. // 分页配置
  307. pagination: {
  308. type: Object,
  309. default() {
  310. return {};
  311. },
  312. },
  313. // 表格配置文件
  314. config: {
  315. type: Array,
  316. default() {
  317. return [];
  318. },
  319. },
  320. // 表头右上方的按钮组
  321. actionList: {
  322. type: Array,
  323. default() {
  324. return [{ text: "", action: () => {} }];
  325. },
  326. },
  327. // element table 原生事件
  328. tableEvents: {
  329. type: Object,
  330. default() {
  331. return {};
  332. },
  333. },
  334. searchKey: {
  335. type: String,
  336. default: "keyword",
  337. },
  338. // 是否显示过滤的全部选项
  339. // isShowAll: {
  340. // type: Boolean,
  341. // default: true,
  342. // },
  343. },
  344. setup(props) {
  345. const { proxy } = getCurrentInstance();
  346. const selectConfigCopy = computed(() => {
  347. return props.selectConfig.map((item) => {
  348. if (!item.labelCopy) item.labelCopy = { ...item }.label;
  349. return item;
  350. });
  351. });
  352. let isMore = ref(false);
  353. const changeStatData = () => {
  354. statWarpHeight.value = document.getElementById("statWarp").offsetHeight;
  355. };
  356. let statWarpHeight = ref(0);
  357. watch(
  358. proxy.statConfig,
  359. (newValue, oldValue) => {
  360. setTimeout(() => {
  361. //获取statWarp的height
  362. statWarpHeight.value =
  363. document.getElementById("statWarp").offsetHeight;
  364. }, 500);
  365. },
  366. { immediate: true }
  367. );
  368. let statSelectVal = ref(0);
  369. const retrievalModal = ref(false);
  370. const getAttrsValue = (item) => {
  371. const { attrs } = item;
  372. const result = {
  373. ...attrs,
  374. };
  375. delete result.prop;
  376. return result;
  377. };
  378. const renderTypeList = ref({
  379. render: {},
  380. renderHTML: {
  381. target: "elements-mapping",
  382. },
  383. renderComponent: {
  384. target: "components-mapping",
  385. },
  386. renderMoreBtn: {
  387. target: "more-btn",
  388. },
  389. });
  390. const getParent = computed(() => {
  391. return proxy.$parent;
  392. });
  393. const getPagination = computed(() => {
  394. const params = {
  395. pageNum: 1,
  396. pageSize: 10,
  397. total: 0,
  398. };
  399. return Object.assign({}, params, props.pagination);
  400. });
  401. const getActionList = computed(() => {
  402. return props.actionList
  403. .slice()
  404. .reverse()
  405. .filter((it) => it.text);
  406. });
  407. const getValue = (scope, configItem) => {
  408. const prop = configItem.attrs.prop;
  409. const renderName = getMatchRenderFunction(configItem);
  410. const renderObj = renderTypeList.value[renderName];
  411. if (renderObj && isFunction(configItem[renderName])) {
  412. return renderObj.target
  413. ? getRenderValue(scope, configItem, {
  414. name: renderName,
  415. type: "bind",
  416. })
  417. : getRenderValue(scope, configItem);
  418. }
  419. return scope.row[prop];
  420. };
  421. const getRenderValue = (
  422. scope,
  423. item,
  424. fn = { name: "render", type: "call" }
  425. ) => {
  426. const prop = item.attrs.prop;
  427. const propValue = prop && scope.row[prop];
  428. scope.row.$index = scope.$index;
  429. const args = propValue !== undefined ? propValue : scope.row;
  430. return item[fn.name][fn.type](getParent.value, args);
  431. };
  432. // 匹配 render 开头的函数
  433. const getMatchRenderFunction = (obj) => {
  434. return Object.keys(obj).find((key) => {
  435. const matchRender = key.match(/^render.*/);
  436. return matchRender && matchRender[0];
  437. });
  438. };
  439. const isFunction = (fn) => {
  440. return isFn(fn);
  441. };
  442. const searchFn = (val) => {
  443. if(props.loading) return;
  444. proxy.$emit(
  445. "getList",
  446. Object.assign(props.filterParams, {
  447. [props.searchKey]: props.pagination.keyword,
  448. })
  449. );
  450. };
  451. const retrievalModalFn = () => {
  452. proxy.$emit("moreSearch", "");
  453. //获取父组件定义的moreSearch方法
  454. };
  455. const handlePageChange = (val) => {
  456. proxy.$emit(
  457. "getList",
  458. Object.assign(props.filterParams, { pageNum: val })
  459. );
  460. };
  461. const handleSizeChange = (val) => {
  462. proxy.$emit(
  463. "getList",
  464. Object.assign(props.filterParams, { pageSize: val })
  465. );
  466. };
  467. const getHeaderActions = (item) => {
  468. return {
  469. ...item.attrs,
  470. };
  471. };
  472. const stopBubbles = (e) => {
  473. const event = e || window.event;
  474. if (event && event.stopPropagation) {
  475. event.stopPropagation();
  476. } else {
  477. event.cancelBubble = true;
  478. }
  479. };
  480. const handleNativeClick = ({ isBubble }, e, item) => {
  481. // 考虑到单元格内渲染了组件,并且组件自身可能含有点击事件,故添加了阻止冒泡机制
  482. // 若指定 isBubble 为 false,则当前单元格恢复冒泡机制
  483. if (isBoolean(isBubble) && !isBubble) return;
  484. stopBubbles(e);
  485. };
  486. //下拉搜索相关
  487. const searchItemSelct = (item, i, index) => {
  488. if (item == "all") {
  489. i.label = { ...props.selectConfig[index] }.labelCopy;
  490. proxy.$emit(
  491. "getList",
  492. Object.assign(props.filterParams, { [i.prop]: "" })
  493. );
  494. return;
  495. }
  496. i.label = item.label;
  497. proxy.$emit(
  498. "getList",
  499. Object.assign(props.filterParams, { [i.prop]: item.value })
  500. );
  501. };
  502. const isSelectable = (row, index, item) => {
  503. if (item.type === "selection") {
  504. if (item.attrs && item.attrs.checkAtt) {
  505. if (row[item.attrs.checkAtt]) {
  506. return row[item.attrs.checkAtt];
  507. }
  508. } else {
  509. return true;
  510. }
  511. }
  512. };
  513. const hocElTable = ref();
  514. return {
  515. getParent,
  516. getPagination,
  517. renderTypeList,
  518. getActionList,
  519. getAttrsValue,
  520. getValue,
  521. getRenderValue,
  522. getMatchRenderFunction,
  523. isFunction,
  524. handlePageChange,
  525. handleSizeChange,
  526. getHeaderActions,
  527. stopBubbles,
  528. handleNativeClick,
  529. searchFn,
  530. searchItemSelct,
  531. selectConfigCopy,
  532. isSelectable,
  533. retrievalModal,
  534. retrievalModalFn,
  535. statSelectVal,
  536. statWarpHeight,
  537. isMore,
  538. changeStatData,
  539. hocElTable,
  540. };
  541. },
  542. });
  543. </script>
  544. <style>
  545. .table-list-container th {
  546. color: #333 !important;
  547. }
  548. .by-table td .el-button + .el-button {
  549. margin-left: 0 !important;
  550. }
  551. .by-table td .el-button {
  552. background: none !important;
  553. margin: 0 !important;
  554. padding: 8px 6px !important;
  555. }
  556. .el-checkbox__input.is-disabled .el-checkbox__inner {
  557. background-color: #dee1e6;
  558. border-color: #b2b4b9;
  559. }
  560. .el-table .cell {
  561. line-height: 34px;
  562. }
  563. </style>
  564. <style lang="scss" scoped>
  565. .sortableActive {
  566. background: #f5f7fa !important;
  567. }
  568. .show-more {
  569. height: auto !important;
  570. }
  571. .stat-warp {
  572. margin-bottom: 20px;
  573. background: #fff;
  574. padding: 0 20px;
  575. height: 200px;
  576. overflow: hidden;
  577. position: relative;
  578. .more-btn {
  579. position: absolute;
  580. right: 0;
  581. bottom: 0;
  582. left: 0;
  583. height: 40px;
  584. cursor: pointer;
  585. font-size: 12px;
  586. line-height: 30px;
  587. text-align: center;
  588. background: linear-gradient(180deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.8) 100%);
  589. i{
  590. color:#999;
  591. }
  592. }
  593. .title {
  594. height: 60px;
  595. select {
  596. height: 60px;
  597. border: none;
  598. outline: none;
  599. -webkit-appearance: none;
  600. appearance: none;
  601. font-size: 14px;
  602. font-weight: bold;
  603. background: url("@/assets/images/sanjiao.png") no-repeat right center;
  604. padding-right: 20px;
  605. }
  606. div {
  607. height: 60px;
  608. font-size: 14px;
  609. font-weight: bold;
  610. line-height: 60px;
  611. }
  612. }
  613. ul {
  614. padding: 0;
  615. overflow: hidden;
  616. margin: 0;
  617. li {
  618. list-style: none;
  619. min-width: 285px;
  620. box-sizing: border-box;
  621. margin: 0 20px 20px 0;
  622. background: #eff6ff;
  623. float: left;
  624. overflow: hidden;
  625. padding: 20px;
  626. color: #333333;
  627. border-radius: 10px;
  628. .label {
  629. font-size: 14px;
  630. }
  631. .label::before {
  632. width: 10px;
  633. height: 10px;
  634. content: "";
  635. border-radius: 50%;
  636. background: #0084ff;
  637. display: inline-block;
  638. margin-right: 10px;
  639. }
  640. .num {
  641. margin-top: 10px;
  642. font-size: 24px;
  643. font-weight: bold;
  644. }
  645. }
  646. //#F5F3FF #9E64ED
  647. .theme2 {
  648. background: #f5f3ff;
  649. .label::before {
  650. background: #9e64ed;
  651. }
  652. }
  653. //#FFF1E1 #FF9315
  654. .theme3 {
  655. background: #fff1e1;
  656. .label::before {
  657. background: #ff9315;
  658. }
  659. }
  660. //#E2FBE8 #39C55A
  661. .theme4 {
  662. background: #e2fbe8;
  663. .label::before {
  664. background: #39c55a;
  665. }
  666. }
  667. .theme5 {
  668. background: #ffebe9;
  669. .label::before {
  670. background: #f94539;
  671. }
  672. }
  673. .theme6 {
  674. background: #e4f9f9;
  675. .label::before {
  676. background: #53cbcb;
  677. }
  678. }
  679. .multi-data {
  680. .label::before {
  681. display: none;
  682. }
  683. .label {
  684. font-size: 14px;
  685. font-weight: bold;
  686. color: #333;
  687. margin-bottom: 8px;
  688. }
  689. .num-warp {
  690. overflow: hidden;
  691. .num-box {
  692. float: left;
  693. min-width: 80px;
  694. margin-right: 20px;
  695. .num-small {
  696. font-size: 16px;
  697. font-weight: bold;
  698. margin-bottom: 8px;
  699. }
  700. .label-small {
  701. color: #666;
  702. font-size: 14px;
  703. }
  704. }
  705. }
  706. }
  707. }
  708. }
  709. .by-search {
  710. display: flex;
  711. justify-content: space-between;
  712. margin-bottom: 10px;
  713. .more-icon {
  714. float: right;
  715. cursor: pointer;
  716. line-height: 32px;
  717. text-align: center;
  718. margin-left: 5px;
  719. }
  720. }
  721. .by-dropdown {
  722. position: relative;
  723. text-align: left;
  724. height: 32px;
  725. z-index: 1010;
  726. padding: 0 10px;
  727. transition: all 0.5s ease;
  728. cursor: pointer;
  729. line-height: 32px;
  730. .by-dropdown-title {
  731. font-size: 14px;
  732. background-color: #fff;
  733. }
  734. ul {
  735. position: absolute;
  736. left: 0;
  737. top: 32px;
  738. padding: 0;
  739. margin: 0;
  740. z-index: 100;
  741. display: none;
  742. white-space: nowrap;
  743. min-width: 100%;
  744. li {
  745. list-style: none;
  746. font-size: 12px;
  747. height: 30px;
  748. padding: 0 10px;
  749. text-align: left;
  750. line-height: 30px;
  751. }
  752. li:hover {
  753. background-color: #eff6ff;
  754. color: #0084ff;
  755. }
  756. }
  757. }
  758. .by-dropdown::before {
  759. display: block;
  760. width: 1px;
  761. content: " ";
  762. position: absolute;
  763. height: 14px;
  764. top: 8px;
  765. background-color: #ddd;
  766. right: 0;
  767. z-index: 1011;
  768. }
  769. .by-dropdown:hover {
  770. background: #ffffff;
  771. border-radius: 2px 2px 2px 2px;
  772. opacity: 1;
  773. ul {
  774. background: #ffffff;
  775. box-shadow: 0px 2px 16px 1px rgba(0, 0, 0, 0.06);
  776. border-radius: 2px 2px 2px 2px;
  777. opacity: 1;
  778. display: block;
  779. text-align: left;
  780. }
  781. }
  782. .header-actions {
  783. flex: 1;
  784. overflow-x: auto;
  785. padding: 20px;
  786. background: #fff;
  787. margin-bottom: 20px;
  788. .overflow-box {
  789. :deep() .el-button:nth-child(1) {
  790. margin-left: 10px;
  791. }
  792. }
  793. }
  794. .table-list-container {
  795. background: #fff;
  796. padding: 13px 20px 20px;
  797. .table-pagination {
  798. padding-top: 20px;
  799. }
  800. .header {
  801. display: flex;
  802. padding-bottom: 20px;
  803. }
  804. .el-table {
  805. :deep() th {
  806. font-size: 14px;
  807. }
  808. :deep() td {
  809. font-size: 14px;
  810. }
  811. }
  812. }
  813. .by-dropdown-lists {
  814. max-height: 50vh;
  815. overflow-y: auto;
  816. line-height: 1;
  817. }
  818. </style>