elective-generation-table.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <template>
  2. <mx-table ref="table" :prop-defines="resolvedTable.columns" :rows="resolvedTable.rows" border>
  3. <template #elective-cell="{value, label}">
  4. <el-popover trigger="hover" :disabled="value&&value.disabled"
  5. popper-class="zero-padding-popover">
  6. <div class="fx-column">
  7. <el-button plain type="text" @click="goDetails(value, label)">查看名单</el-button>
  8. </div>
  9. <div slot="reference" :style="getCellStyles(value)">
  10. <span v-if="value.star">*</span>
  11. <span>{{ value && value.value }}</span>
  12. </div>
  13. </el-popover>
  14. </template>
  15. </mx-table>
  16. </template>
  17. <script>
  18. import config from '@/common/mx-config'
  19. import MxTransferMixin from '@/components/mx-transfer-mixin'
  20. export default {
  21. mixins: [MxTransferMixin],
  22. name: 'elective-generation-table',
  23. props: ['chartBinding'],
  24. computed: {
  25. resolvedTable() {
  26. // setting data
  27. const columns = { groupName: { label: '组合', fixed: true }, expectedCount: { label: '设置人数', fixed: true } }
  28. const rows = this.deepClone(this.chartBinding.generation.roundGroups) // TODO: need clone?
  29. // generation data
  30. const mergedColumns = []
  31. this.chartBinding.tableData.forEach(item => {
  32. if (this.chartBinding.generation.hiddenGenerations.includes(item.generation)) return
  33. const isPreference = item.categories.every(item => Array.isArray(item))
  34. const generationQueryableCategories = []
  35. const generationQueryableIgnoreGroupCategories = []
  36. const ext = {
  37. roundId: item.roundId,
  38. generation: item.generation,
  39. queryableCategories: generationQueryableCategories, // 本代支持查询的列
  40. ignoreGroupCategories: generationQueryableIgnoreGroupCategories // 本代支持查询,且与组合无关的列
  41. }
  42. const subColumns = {}
  43. const mergedHeaderKey = 'generation_' + item.generation
  44. const options = Object.values(this.chartBinding.generation.options)
  45. const mergedHeaderOpt = options.find(opt => opt.value == item.generation)
  46. const mergedHeaderDefine = { label: mergedHeaderOpt.title, children: subColumns }
  47. if (isPreference) {
  48. const cnIndexer = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
  49. item.categories.forEach((subItem, idx) => {
  50. const cnIndex = idx < cnIndexer.length ? cnIndexer[idx] : (idx + 1)
  51. const innerHeaderKey = mergedHeaderKey + '_' + idx
  52. const innerHeaderDefine = item.categories.length > 1
  53. ? { label: `${cnIndex}志愿`, children: {} }
  54. : mergedHeaderDefine
  55. const overrideQueryName = item.categories.length > 1 ? innerHeaderDefine.label : ''
  56. subItem.forEach(data => this.resolveTableGeneration(ext, data, innerHeaderDefine.children, rows, mergedColumns, innerHeaderKey, false, overrideQueryName))
  57. columns[innerHeaderKey] = innerHeaderDefine
  58. })
  59. } else {
  60. item.categories.forEach(data => this.resolveTableGeneration(ext, data, subColumns, rows, mergedColumns))
  61. columns[mergedHeaderKey] = mergedHeaderDefine
  62. }
  63. })
  64. // accumulate data
  65. if (this.chartBinding.generation.active > this.chartBinding.generation.options.primaryDM.value
  66. && this.chartBinding.chartData?.accumulates?.length) {
  67. const prefix = 'accumulate_'
  68. const ext = {
  69. roundId: this.chartBinding.generation.status.roundId,
  70. generation: -1, // for detail page special display,
  71. queryableCategories: [], // 本代支持查询的列
  72. ignoreGroupCategories: [] // 本代支持查询,且与组合无关的列
  73. }
  74. this.chartBinding.chartData.accumulates.forEach(acc => this.resolveTableGeneration(ext, acc, columns, rows, mergedColumns, prefix, true))
  75. }
  76. // completed
  77. this.$refs.table?.scrollToRight()
  78. return {
  79. mergedColumns,
  80. columns,
  81. rows
  82. }
  83. }
  84. },
  85. mounted() {
  86. window.tableVue = this
  87. },
  88. provide() {
  89. return {
  90. mergeTable: this.mergeTable
  91. }
  92. },
  93. methods: {
  94. resolveTableGeneration(ext, data, columnsRef, rowsRef, mergedColumnsRef, prefix = '', fixed = false, overrideQueryName = '') {
  95. // resolve core
  96. const prop = prefix + ext.generation + '_' + data.category
  97. const name = data.displayName
  98. const shouldMerge = data.values.length != rowsRef.length || data.values.some(v => v.groupId == 0)
  99. if (data.queryCode) {
  100. let nextName = data.displayName
  101. if (overrideQueryName) nextName = overrideQueryName + '/' + nextName
  102. ext.queryableCategories.push({ id: data.queryCode, name: nextName, detailName: data.detailName })
  103. if (shouldMerge) ext.ignoreGroupCategories.push(data.queryCode)
  104. }
  105. columnsRef[prop] = { label: name, slot: 'elective-cell', fixed: fixed }
  106. if (!shouldMerge) {
  107. data.values.forEach(val => {
  108. const row = rowsRef.find(row => row.groupId == val.groupId)
  109. if (row) {
  110. row[prop] = { ...ext, ...val, queryCode: data.queryCode }
  111. }
  112. })
  113. } else {
  114. // mark for table rows merge
  115. mergedColumnsRef.push(prop)
  116. // keep value in display row
  117. const val = data.values.first()
  118. const row = rowsRef.first()
  119. row[prop] = { ...ext, ...val, queryCode: data.queryCode }
  120. }
  121. },
  122. mergeTable({ row, column, rowIndex }) {
  123. if (this.resolvedTable.mergedColumns.includes(column.property)) {
  124. return rowIndex === 0 ? [this.resolvedTable.rows.length, 1] : [0, 0]
  125. }
  126. },
  127. getCellStyles(option) {
  128. const styles = {}
  129. if (option.color) {
  130. const map = {
  131. R: config.color.error,
  132. r: config.color.error,
  133. G: config.color.yellow_up,
  134. g: config.color.yellow_up,
  135. B: config.color.blue_up,
  136. b: config.color.blue_up
  137. }
  138. styles.color = map[option.color] || option.color
  139. }
  140. return styles
  141. },
  142. goDetails(option) {
  143. const path = '/elective/generation/detail'
  144. const nextData = {
  145. year: this.chartBinding.generation.status.year,
  146. roundId: this.chartBinding.generation.status.roundId,
  147. roundName: this.chartBinding.generation.status.roundName,
  148. queryGeneration: option.generation,
  149. queryGroupId: option.groupId,
  150. queryCode: option.queryCode,
  151. queryableCategories: option.queryableCategories,
  152. ignoreGroupCategories: option.ignoreGroupCategories,
  153. groups: this.chartBinding.generation.roundGroups.map(rg => ({ groupId: rg.groupId, groupName: rg.groupName }))
  154. }
  155. this.transferTo(path, nextData)
  156. }
  157. }
  158. }
  159. </script>
  160. <style scoped>
  161. </style>