Column.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. <script>
  2. import {
  3. getAssetUrl,
  4. getThumbnailUrl
  5. } from '@/api/asset'
  6. import { AssetType } from '@/constant'
  7. export default {
  8. name: 'SchemaTableColumn',
  9. inject: ['table'],
  10. props: {
  11. schema: {
  12. type: Object,
  13. required: true
  14. }
  15. },
  16. methods: {
  17. renderRefreshColumn (h, props) {
  18. const { render } = this.schema
  19. return h('el-table-column', {
  20. props: {
  21. width: 48,
  22. align: 'center',
  23. ...props
  24. },
  25. scopedSlots: {
  26. header: this.renderRefreshColumnHeader,
  27. default: render && function ({ store, row }) {
  28. return render(row, store.$createElement)
  29. }
  30. }
  31. })
  32. },
  33. renderRefreshColumnHeader () {
  34. return this.$createElement('i', {
  35. staticClass: 'el-icon-refresh u-color--black light u-font-size--xl u-vertical--middle has-active',
  36. on: { click: $event => {
  37. $event.stopPropagation()
  38. this.table.pageTo()
  39. } }
  40. })
  41. },
  42. renderExpandColumn (h, props) {
  43. const { refresh, render } = this.schema
  44. return h('el-table-column', {
  45. props: {
  46. type: 'expand',
  47. ...props
  48. },
  49. scopedSlots: {
  50. header: refresh ? this.renderRefreshColumnHeader : null,
  51. default ({ store, row }) {
  52. return render(row, store.$createElement)
  53. }
  54. }
  55. })
  56. },
  57. renderAssetColumn (h, { refresh, ...props }) {
  58. return h('el-table-column', {
  59. props: {
  60. 'class-name': 'c-thumbnail-column',
  61. label: '资源',
  62. align: 'center',
  63. width: 100,
  64. ...props
  65. },
  66. scopedSlots: {
  67. header: refresh ? this.renderRefreshColumnHeader : null,
  68. default: this.renderAsset
  69. }
  70. })
  71. },
  72. renderAsset ({ row: data }) {
  73. const value = this.getRenderValue(data)
  74. if (!value) {
  75. return this.$createElement('div', {
  76. staticClass: 'o-thumbnail u-font-size--sm'
  77. }, data.draft || '-')
  78. }
  79. const { on } = this.schema
  80. const thumb = value.thumb || (value.type === AssetType.IMAGE ? value.url : null)
  81. if (thumb) {
  82. return this.$createElement('auto-image', {
  83. staticClass: `o-thumbnail u-font-size--lg u-color--blue ${on ? 'u-pointer' : ''}`,
  84. props: {
  85. src: value.net
  86. ? thumb
  87. : value.origin
  88. ? getAssetUrl(thumb)
  89. : getThumbnailUrl(thumb, '80,fit'),
  90. broken: 'image-broken'
  91. },
  92. nativeOn: on && { click: $event => {
  93. $event.stopPropagation()
  94. on(data, value)
  95. } }
  96. })
  97. }
  98. let svgIcon = null
  99. switch (value.type) {
  100. case AssetType.AUDIO:
  101. svgIcon = 'audio-thumb'
  102. break
  103. default:
  104. svgIcon = 'video-thumb'
  105. break
  106. }
  107. return this.$createElement('SvgIcon', {
  108. staticClass: `o-thumbnail ${on ? 'u-pointer' : ''}`,
  109. props: { 'icon-class': svgIcon },
  110. on: on && { click: $event => {
  111. $event.stopPropagation()
  112. on(data, value)
  113. } }
  114. })
  115. },
  116. renderChildren (data) {
  117. const { type, render } = this.schema
  118. let children = null
  119. switch (type) {
  120. case 'tag':
  121. children = this.renderTags(data.row)
  122. break
  123. case 'invoke':
  124. children = this.renderInvokes(data)
  125. break
  126. default:
  127. children = render && render(data.row, this.$createElement)
  128. break
  129. }
  130. if (children && !Array.isArray(children)) {
  131. children = [children]
  132. }
  133. return children && children.length ? children : null
  134. },
  135. getRenderValue (data) {
  136. const { prop, render } = this.schema
  137. return render ? render(data) : data[prop]
  138. },
  139. renderTags (data) {
  140. const tags = this.getRenderValue(data)
  141. if (tags) {
  142. if (Array.isArray(tags)) {
  143. if (tags.length > 1) {
  144. return this.$createElement('div', {
  145. staticClass: 'c-tags'
  146. }, tags.map(tag => this.renderTag(tag, data)))
  147. }
  148. return tags.map(tag => this.renderTag(tag, data))
  149. }
  150. return this.renderTag(tags, data)
  151. }
  152. return '-'
  153. },
  154. renderTag (tag, data) {
  155. if (!tag) {
  156. return this.$createElement('span', {
  157. staticClass: 'o-tag u-readonly',
  158. staticStyle: { display: 'inline-block' }
  159. }, '-')
  160. }
  161. if (!tag.type) {
  162. return this.$createElement('span', {
  163. staticClass: 'o-tag u-readonly',
  164. staticStyle: { display: 'inline-block' }
  165. }, tag.label)
  166. }
  167. const { msg } = tag
  168. if (msg) {
  169. return this.$createElement('el-tooltip', {
  170. props: {
  171. content: msg,
  172. placement: 'left',
  173. enterable: false
  174. }
  175. }, [
  176. this.createTag(tag, data)
  177. ])
  178. }
  179. return this.createTag(tag, data)
  180. },
  181. createTag (tag, data) {
  182. const { label, ignore, size = '', ...tagProps } = tag
  183. const { on } = this.schema
  184. return this.$createElement('el-tag', {
  185. staticClass: on && !ignore ? `o-tag ${size} u-pointer` : `o-tag ${size} u-readonly`,
  186. props: {
  187. size: 'medium',
  188. 'disable-transitions': true,
  189. ...tagProps
  190. },
  191. on: on && !ignore && { click: $event => {
  192. $event.stopPropagation()
  193. on(data, tag)
  194. } }
  195. }, label)
  196. },
  197. renderInvokes (data) {
  198. const { render, use } = this.schema
  199. const h = this.$createElement
  200. if (!use || use(data.row)) {
  201. return (Array.isArray(render) ? render : render(data.row))
  202. .filter(({ render }) => !render || render(data.row))
  203. .map(({ label, allow, on }) => {
  204. const allowed = allow ? allow(data.row) : true
  205. return h('div', {
  206. staticClass: allowed ? 'c-table__btn' : 'c-table__btn disabled',
  207. on: allowed && on && {
  208. click ($event) {
  209. $event.stopPropagation()
  210. on(data.row, data.$index)
  211. }
  212. }
  213. }, label
  214. ? typeof label === 'string'
  215. ? label
  216. : label(data.row)
  217. : '操作')
  218. })
  219. }
  220. return null
  221. }
  222. },
  223. render (h) {
  224. const { type, render, ...columnProps } = this.schema
  225. let defaultProps = null
  226. switch (type) {
  227. case 'refresh':
  228. return this.renderRefreshColumn(h, columnProps)
  229. case 'expand':
  230. return this.renderExpandColumn(h, columnProps)
  231. case 'asset':
  232. return this.renderAssetColumn(h, columnProps)
  233. case 'selection':
  234. return h('el-table-column', {
  235. props: {
  236. type,
  237. width: 42,
  238. ...columnProps
  239. }
  240. })
  241. case 'tag':
  242. defaultProps = {
  243. label: '状态',
  244. width: 100,
  245. align: 'center'
  246. }
  247. break
  248. case 'invoke':
  249. defaultProps = {
  250. label: '操作',
  251. width: render?.length > 1 ? 120 : 80,
  252. align: render?.length > 1 ? 'right' : 'center'
  253. }
  254. break
  255. default:
  256. defaultProps = { 'show-overflow-tooltip': true }
  257. break
  258. }
  259. return h('el-table-column', {
  260. props: {
  261. ...defaultProps,
  262. ...columnProps
  263. },
  264. scopedSlots: {
  265. default: type || render ? this.renderChildren : null
  266. }
  267. })
  268. }
  269. }
  270. </script>