BoardContent.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <template>
  2. <div class="BI-board-content">
  3. <div class="BI-board-list" :style="{height:renderHeight}">
  4. <table-no-data v-if="dataList.length===0" style="flex:1"/>
  5. <grid-layout :layout.sync="dataList"
  6. :col-num="layout.colNum"
  7. :rowHeight="layout.rowHeight"
  8. :is-draggable="canDrag"
  9. :is-resizable="canDrag"
  10. :vertical-compact="true"
  11. :use-css-transforms="true"
  12. :margin="layout.margin"
  13. >
  14. <grid-item v-for="(item) in dataList"
  15. :key="item.i"
  16. :x="item.x"
  17. :y="item.y"
  18. :w="item.w"
  19. :h="item.h"
  20. :i="item.i"
  21. drag-allow-from=".vue-draggable-handle"
  22. @resized="resizedEvent"
  23. @moved="movedEvent"
  24. >
  25. <component
  26. :is="getCompType(item.Type)"
  27. :compData="item"
  28. :knowList="knowList"
  29. :ref="'item' + item.i"
  30. :canDelete="canDelete"
  31. @deleteKnowledge="deleteKnowledge($event,item)">
  32. <template v-slot:drag>
  33. <img
  34. v-if="canDrag"
  35. class="icon vue-draggable-handle"
  36. src="~@/assets/img/data_m/move_ico.png"
  37. alt=""
  38. style="cursor: move"
  39. />
  40. </template>
  41. <template v-slot:delete>
  42. <img class="icon" v-if="canDelete" src="~@/assets/img/icons/delete-red.png" alt="" @click="handleDel(item)"/>
  43. </template>
  44. </component>
  45. </grid-item>
  46. </grid-layout>
  47. </div>
  48. </div>
  49. </template>
  50. <script>
  51. import apiBiBoard from '@/api/modules/BIBoard.js'
  52. import TableNoData from '../../../components/tableNoData.vue';
  53. import ChartBox from './ChartBox.vue';
  54. import TableBox from './TableBox.vue';
  55. import KnowBox from './KnowBox.vue';
  56. import { GridLayout, GridItem } from "vue-grid-layout";
  57. import {createRandomCode} from '@/views/ppt_manage/newVersion/utils/untils';
  58. export default {
  59. components: { ChartBox, TableBox, TableNoData, GridLayout, GridItem, KnowBox },
  60. props: {
  61. value: {
  62. type: Array,
  63. default: () => []
  64. },
  65. boardInfo:{},//看板详情数据
  66. canDrag: {//能否拖动
  67. type: Boolean,
  68. default: false
  69. },
  70. canDelete:{//能否删除
  71. type: Boolean,
  72. default: false
  73. },
  74. renderHeight:{
  75. type:String,
  76. default:"calc(100vh - 300px)"
  77. },
  78. knowList:{//知识资源列表
  79. type:Array,
  80. default: () => []
  81. },
  82. },
  83. watch:{
  84. value(newval){
  85. const { wItem , hItem , colNum } = this.layout;
  86. let itemList = _.cloneDeep(newval) || [];
  87. itemList.map((item,index) => {
  88. if(!item.Conf){ //旧数据
  89. item.w = wItem;
  90. item.h = hItem;
  91. item.x = wItem * (index % (colNum / wItem));
  92. item.y = hItem * Math.floor(index / (colNum / wItem));
  93. item.i = `${item.UniqueCode}_${createRandomCode()}_${index}`;
  94. } else {
  95. let conf = JSON.parse(item.Conf)
  96. item.w = conf.w;
  97. item.h = conf.h;
  98. item.x = conf.x;
  99. item.y = conf.y;
  100. item.i = `${item.UniqueCode}_${createRandomCode()}_${index}`
  101. }
  102. });
  103. this.dataList = itemList;
  104. },
  105. dataList(newval){
  106. let list = this.knowList || [];
  107. this.$emit('update:knowList',list);//处理插件拖拽重新渲染知识资源列表不展示
  108. this.setFirstKnow()
  109. this.$nextTick(() => {
  110. this.$emit('checkDataList',newval);//grid-layout对x.y进行处理之后数据发生变化 同步给编辑页面
  111. })
  112. },
  113. },
  114. data() {
  115. return {
  116. draggedIndex: null,
  117. dataList:[], //看板列表
  118. layout:{
  119. colNum:12,
  120. rowHeight:96,
  121. margin:[20,20],
  122. wItem:3,
  123. hItem:4,
  124. },
  125. typeWidth:{ //不同种类的占位宽度
  126. 1:3,
  127. 2:3,
  128. 3:6,
  129. },
  130. };
  131. },
  132. methods: {
  133. getAddMessage(arr){ //获取添加内容的位置信息
  134. if(!arr || !arr.length) return;
  135. let d = _.cloneDeep(this.dataList) || [];
  136. let result = [];
  137. arr.map((item) => { //位置只与最后一个元素的位置有关
  138. let yMax = d.length ? Math.max.apply(null,d.map(_=>_.y)) : 0;
  139. let yMaxItems = d.length ? d.filter(_=>_.y == yMax) : [];
  140. let xMax = d.length ? Math.max.apply(null,yMaxItems.map(_=>_.x)) : 0;
  141. let hMax = d.length ? Math.max.apply(null,yMaxItems.map(_=>_.h)) : 0;
  142. let lastTag = d.length ? d.find(_=>_.y == yMax &&_.x == xMax) : null;
  143. let y =d.length ? (this.layout.colNum - xMax - lastTag.w >= this.typeWidth[item.Type] ? yMax : yMax + hMax) : 0;
  144. let x =d.length ? (this.layout.colNum - xMax - lastTag.w >= this.typeWidth[item.Type] ? xMax + lastTag.w : 0) : 0;
  145. let configs = {
  146. x,
  147. y,
  148. w:this.typeWidth[item.Type],
  149. h:this.layout.hItem,
  150. i:`${item.UniqueCode}_${createRandomCode()}_${d.length}`
  151. };
  152. let i = {...item,...configs,Conf:JSON.stringify(configs)};
  153. d.push(i);
  154. result.push(i);
  155. })
  156. return result;
  157. },
  158. resizedEvent(i){
  159. // this.$refs[`item${i}`] && this.$refs[`item${i}`][0] && this.$refs[`item${i}`][0].handleResize && this.$refs[`item${i}`][0].handleResize();
  160. this.handleChangeDataList();
  161. },
  162. movedEvent(){
  163. this.handleChangeDataList();
  164. },
  165. getCompType(type) {
  166. return type === 1 ? ChartBox : type === 2 ? TableBox : KnowBox;
  167. },
  168. handleDel(item){
  169. let index = this.dataList.findIndex(_=>_.BiDashboardDetailId == item.BiDashboardDetailId);
  170. this.dataList.splice(index,1);
  171. this.handleChangeDataList();
  172. this.$emit('delete',this.dataList)
  173. },
  174. handleChangeDataList(){
  175. this.dataList.map(item=>{
  176. let configs = {
  177. w : item.w,
  178. h : item.h,
  179. x : item.x,
  180. y : item.y,
  181. i : item.i,
  182. }
  183. item.Conf = JSON.stringify(configs);
  184. });
  185. this.$emit('input',this.dataList)
  186. },
  187. async deleteKnowledge(item,v){
  188. let index = this.knowList.findIndex(_=>_.KnowledgeResourceId == item.KnowledgeResourceId && _.ResourceType == item.ResourceType)
  189. if(index >= 0){
  190. let knowList = _.cloneDeep(this.knowList);
  191. knowList.splice(index,1)
  192. let r = await apiBiBoard.saveKnowledge({
  193. BiDashboardDetailId:v ? (/^selfId_\d+$/.test(v.BiDashboardDetailId) ? 0 : v.BiDashboardDetailId) : 0,
  194. KnowledgeResourceList:knowList.map(_=>({
  195. ResourceType:_.ResourceType,
  196. KnowledgeResourceId:_.KnowledgeResourceId
  197. }))
  198. });
  199. if(r.Ret != 200) return this.$message.warning('删除失败,请重试')
  200. this.knowList.splice(index,1);
  201. this.$emit('update:knowList',this.knowList)
  202. //当前删除后为当前种类为空时
  203. let nowTypeKnows = this.knowList.filter(_=>_.ResourceType == item.ResourceType);
  204. if(!nowTypeKnows.length) this.setFirstKnow();
  205. }
  206. if(!this.knowList.length){ //清空掉知识资源
  207. this.dataList = this.dataList.filter(_=>_.Type != 3);
  208. this.$emit('input',this.dataList)
  209. }
  210. },
  211. setFirstKnow(){
  212. this.$nextTick(() => {
  213. let v = this.dataList.find(_=>_.Type == 3); //寻找唯一的知识资源库类型
  214. if(!v) return;
  215. this.$refs[`item${v.i}`] && this.$refs[`item${v.i}`][0] && this.$refs[`item${v.i}`][0].setFirstKnow && this.$refs[`item${v.i}`][0].setFirstKnow();
  216. });
  217. },
  218. }
  219. };
  220. </script>
  221. <style lang="scss" scoped>
  222. .BI-board-content {
  223. // padding: 20px;
  224. .BI-board-list {
  225. height: calc(100vh - 300px);
  226. overflow-y: auto;
  227. display: flex;
  228. flex-wrap: wrap;
  229. gap: 20px;
  230. .vue-grid-layout {
  231. width: 100%;
  232. }
  233. .vue-grid-item {
  234. overflow: hidden;
  235. border: 1px solid #dcdfe6;
  236. box-shadow: 0px 2px 8px 0px #00000014;
  237. }
  238. }
  239. }
  240. </style>