3f59334fbb57f31f7174e63b09795fb0d440ed2e3d3cbe9319b227a718a02f793dc8a48dc6778089ee698ab4908acc206297ce4041b98d389811d055abc871 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import DescriptionsRow from './descriptions-row';
  2. import { isFunction } from 'element-ui/src/utils/types';
  3. export default {
  4. name: 'ElDescriptions',
  5. components: {
  6. [DescriptionsRow.name]: DescriptionsRow
  7. },
  8. props: {
  9. border: {
  10. type: Boolean,
  11. default: false
  12. },
  13. column: {
  14. type: Number,
  15. default: 3
  16. },
  17. direction: {
  18. type: String,
  19. default: 'horizontal'
  20. },
  21. size: {
  22. type: String
  23. // validator: isValidComponentSize,
  24. },
  25. title: {
  26. type: String,
  27. default: ''
  28. },
  29. extra: {
  30. type: String,
  31. default: ''
  32. },
  33. labelStyle: {
  34. type: Object
  35. },
  36. contentStyle: {
  37. type: Object
  38. },
  39. labelClassName: {
  40. type: String,
  41. default: ''
  42. },
  43. contentClassName: {
  44. type: String,
  45. default: ''
  46. },
  47. colon: {
  48. type: Boolean,
  49. default: true
  50. }
  51. },
  52. computed: {
  53. descriptionsSize() {
  54. return this.size || (this.$ELEMENT || {}).size;
  55. }
  56. },
  57. provide() {
  58. return {
  59. elDescriptions: this
  60. };
  61. },
  62. methods: {
  63. getOptionProps(vnode) {
  64. if (vnode.componentOptions) {
  65. const componentOptions = vnode.componentOptions;
  66. const { propsData = {}, Ctor = {} } = componentOptions;
  67. const props = (Ctor.options || {}).props || {};
  68. const res = {};
  69. for (const k in props) {
  70. const v = props[k];
  71. const defaultValue = v.default;
  72. if (defaultValue !== undefined) {
  73. res[k] = isFunction(defaultValue) ? defaultValue.call(vnode) : defaultValue;
  74. }
  75. }
  76. return { ...res, ...propsData };
  77. }
  78. return {};
  79. },
  80. getSlots(vnode) {
  81. let componentOptions = vnode.componentOptions || {};
  82. const children = vnode.children || componentOptions.children || [];
  83. const slots = {};
  84. children.forEach(child => {
  85. if (!this.isEmptyElement(child)) {
  86. const name = (child.data && child.data.slot) || 'default';
  87. slots[name] = slots[name] || [];
  88. if (child.tag === 'template') {
  89. slots[name].push(child.children);
  90. } else {
  91. slots[name].push(child);
  92. }
  93. }
  94. });
  95. return { ...slots };
  96. },
  97. isEmptyElement(c) {
  98. return !(c.tag || (c.text && c.text.trim() !== ''));
  99. },
  100. filledNode(node, span, count, isLast = false) {
  101. if (!node.props) {
  102. node.props = {};
  103. }
  104. if (span > count) {
  105. node.props.span = count;
  106. }
  107. if (isLast) {
  108. // set the max span, cause of the last td
  109. node.props.span = count;
  110. }
  111. return node;
  112. },
  113. getRows() {
  114. const children = ((this.$slots.default || []).filter(vnode => vnode.tag &&
  115. vnode.componentOptions && vnode.componentOptions.Ctor.options.name === 'ElDescriptionsItem'));
  116. const nodes = children.map(vnode => {
  117. return {
  118. props: this.getOptionProps(vnode),
  119. slots: this.getSlots(vnode),
  120. vnode
  121. };
  122. });
  123. const rows = [];
  124. let temp = [];
  125. let count = this.column;
  126. nodes.forEach((node, index) => {
  127. const span = node.props.span || 1;
  128. if (index === children.length - 1) {
  129. temp.push(this.filledNode(node, span, count, true));
  130. rows.push(temp);
  131. return;
  132. }
  133. if (span < count) {
  134. count -= span;
  135. temp.push(node);
  136. } else {
  137. temp.push(this.filledNode(node, span, count));
  138. rows.push(temp);
  139. count = this.column;
  140. temp = [];
  141. }
  142. });
  143. return rows;
  144. }
  145. },
  146. render() {
  147. const { title, extra, border, descriptionsSize, $slots } = this;
  148. const rows = this.getRows();
  149. return (
  150. <div class="el-descriptions">
  151. {
  152. (title || extra || $slots.title || $slots.extra)
  153. ? <div class="el-descriptions__header">
  154. <div class="el-descriptions__title">
  155. { $slots.title ? $slots.title : title}
  156. </div>
  157. <div class="el-descriptions__extra">
  158. { $slots.extra ? $slots.extra : extra }
  159. </div>
  160. </div>
  161. : null
  162. }
  163. <div class="el-descriptions__body">
  164. <table class={['el-descriptions__table', {'is-bordered': border}, descriptionsSize ? `el-descriptions--${descriptionsSize}` : '']}>
  165. {rows.map(row => (
  166. <DescriptionsRow row={row}></DescriptionsRow>
  167. ))}
  168. </table>
  169. </div>
  170. </div>
  171. );
  172. }
  173. };