experimental-data.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <template>
  2. <div class="info-container">
  3. <div class="experimental-data info-item">
  4. <div class="title">
  5. <i class="ibps-icon-star" />
  6. <span>实验数据</span>
  7. </div>
  8. <div class="operate">
  9. <template v-for="btn in toolbars">
  10. <el-button
  11. v-if="!btn.hidden"
  12. :key="btn.key"
  13. :type="btn.type"
  14. :icon="btn.icon"
  15. :size="btn.size || 'mini'"
  16. plain
  17. @click="handleActionEvent(btn.key)"
  18. >
  19. {{ btn.label }}
  20. </el-button>
  21. </template>
  22. </div>
  23. <div class="content">
  24. <template v-if="expData && $utils.isNotEmpty(expData.dataDTO)">
  25. <el-table
  26. :data="expData.dataDTO.list"
  27. border
  28. stripe
  29. highlight-current-row
  30. style="width: 100%"
  31. max-height="250px"
  32. >
  33. <el-table-column
  34. v-for="(h, hIndex) in expData.dataDTO.header"
  35. :key="h.children && h.children.length ? hIndex : h.prop"
  36. :prop="h.prop"
  37. :label="h.label"
  38. width="80"
  39. header-align="center"
  40. align="center"
  41. >
  42. <template slot="header" slot-scope="scope">
  43. <span v-html="scope.column.label" />
  44. </template>
  45. <el-table-column
  46. v-for="c in h.children"
  47. :key="c.prop"
  48. :prop="c.prop"
  49. :label="c.label"
  50. header-align="center"
  51. align="center"
  52. >
  53. <template slot="header" slot-scope="scope">
  54. <span v-html="scope.column.label" />
  55. </template>
  56. </el-table-column>
  57. </el-table-column>
  58. </el-table>
  59. <div class="note" v-html="expData.dataDTO.note" />
  60. </template>
  61. <el-empty v-else description="暂无数据,请导出模板填写后导入" />
  62. </div>
  63. </div>
  64. <!-- <import-table
  65. :visible="showImportTable"
  66. title="导入"
  67. @close="visible => (showImportTable = visible)"
  68. @action-event="handleImport"
  69. /> -->
  70. </div>
  71. </template>
  72. <script>
  73. // import IbpsImport from '@/plugins/import'
  74. import ActionUtils from '@/utils/action'
  75. import { exportTemplate, importTemplate } from '@/api/business/pv'
  76. export default {
  77. components: {
  78. ImportTable: () => import('@/business/platform/form/formrender/dynamic-form/components/import-table')
  79. },
  80. props: {
  81. expData: {
  82. type: Object,
  83. default: () => {}
  84. },
  85. formId: {
  86. type: String,
  87. default: ''
  88. },
  89. readonly: {
  90. type: Boolean,
  91. default: false
  92. }
  93. },
  94. data () {
  95. return {
  96. showImportTable: false,
  97. toolbars: [
  98. { key: 'export', icon: 'ibps-icon-cloud-download', label: '导出模板', type: 'info', hidden: this.readonly },
  99. { key: 'import', icon: 'ibps-icon-cloud-upload', label: '导入数据', type: 'warning', hidden: this.readonly },
  100. { key: 'generate', icon: 'ibps-icon-file-text-o', label: '查看实验报告', type: 'success', hidden: true }
  101. ]
  102. }
  103. },
  104. methods: {
  105. handleActionEvent (key) {
  106. switch (key) {
  107. case 'generate':
  108. this.handleGenerate()
  109. break
  110. case 'export':
  111. // this.handleExport()
  112. this.$emit('export')
  113. break
  114. case 'import':
  115. // this.showImportTable = true
  116. // this.handleImport()
  117. this.$emit('import')
  118. break
  119. }
  120. },
  121. handleGenerate () {
  122. this.$message.info('waiting...')
  123. },
  124. handleExport () {
  125. if (!this.formId) {
  126. return this.$message.error('请先保存数据!')
  127. }
  128. exportTemplate({ id: this.formId }).then(res => {
  129. ActionUtils.download(res.data, '实验数据模板.xlsx')
  130. })
  131. },
  132. objectSpanMethod ({ row, column, rowIndex, columnIndex }) {
  133. // 判断当前列是否需要进行同值合并
  134. if (column.merge) {
  135. const firstSameRowIndex = this.getFirstSameRowIndex(this.tableData, rowIndex, column.property)
  136. const firstSameColIndex = this.getFirstSameColIndex(this.tableData, columnIndex, rowIndex)
  137. return {
  138. rowspan: firstSameRowIndex === -1 ? 1 : rowIndex - firstSameRowIndex + 1,
  139. colspan: firstSameColIndex === -1 ? 1 : columnIndex - firstSameColIndex + 1
  140. }
  141. }
  142. },
  143. // 获取行同值合并的起始下标
  144. getFirstSameRowIndex (data, rowIndex, prop) {
  145. for (let i = rowIndex; i >= 0; i--) {
  146. if (data[i][prop] === data[rowIndex][prop]) {
  147. return i
  148. }
  149. }
  150. return -1
  151. },
  152. // 获取列同值合并的起始下标
  153. getFirstSameColIndex (data, colIndex, rowIndex) {
  154. for (let i = colIndex; i >= 0; i--) {
  155. if (data[rowIndex][i] === data[rowIndex][colIndex]) {
  156. return i
  157. }
  158. }
  159. return -1
  160. },
  161. // handleImport (file, options) {
  162. // this.loading = false
  163. // IbpsImport.xlsx(file, options).then(res => {
  164. // console.log(res)
  165. // })
  166. // },
  167. handleImport () {
  168. if (!this.formId) {
  169. return this.$message.error('请先保存数据!')
  170. }
  171. const input = document.createElement('input')
  172. input.type = 'file'
  173. input.accept = '.xlsx'
  174. input.onchange = event => {
  175. const file = event.target.files[0]
  176. const reader = new FileReader()
  177. reader.onload = event => {
  178. const data = new FormData()
  179. data.append('id', this.formId)
  180. data.append('applyFiles', file)
  181. importTemplate(data).then(res => {
  182. this.$message.success('实验数据导入成功')
  183. this.expData = res.data
  184. }).catch(({ state, cause }) => {
  185. const errMsg = JSON.parse(cause)
  186. let msgContent = ''
  187. Object.keys(errMsg).forEach(key => {
  188. let msgItem = '<div >'
  189. errMsg[key].forEach(item => {
  190. msgItem += `<div>${item}</div>`
  191. })
  192. msgContent += `<div><div style="font-weight: bold;">${key}:</div>${msgItem}<div>`
  193. })
  194. this.$confirm(`<div style="font-size: 14px;">${msgContent}</div>`, '数据校验失败,请根据以下提示完善您的数据!', {
  195. confirmButtonText: '确认',
  196. showClose: false,
  197. showCancelButton: false,
  198. closeOnClickModal: false,
  199. dangerouslyUseHTMLString: true,
  200. customClass: 'errorTips',
  201. type: 'error'
  202. }).then(() => {}).catch(() => {})
  203. })
  204. }
  205. reader.readAsBinaryString(file)
  206. }
  207. input.click()
  208. }
  209. }
  210. }
  211. </script>
  212. <style lang="scss" scoped>
  213. .info-container {
  214. .experimental-data {
  215. position: relative;
  216. .operate {
  217. position: absolute;
  218. right: 0;
  219. top: -2px;
  220. }
  221. .content {
  222. padding: 10px;
  223. position: relative;
  224. .note {
  225. margin-top: 10px;
  226. }
  227. }
  228. }
  229. }
  230. </style>