|
@@ -1,33 +1,50 @@
|
|
|
<template>
|
|
|
<div class="BI-board-content">
|
|
|
<div class="BI-board-list" :style="{height:renderHeight}">
|
|
|
- <table-no-data v-if="value.length===0" style="flex:1"/>
|
|
|
- <div
|
|
|
- class="BI-board-item-box"
|
|
|
- v-for="(item, index) in value"
|
|
|
- :key="item.BiDashboardDetailId"
|
|
|
- @dragover.prevent
|
|
|
- @drop="drop(index)"
|
|
|
- >
|
|
|
- <component :is="getCompType(item.Type)" :compData="item">
|
|
|
- <template v-slot:drag>
|
|
|
- <!-- Draggable icon -->
|
|
|
- <img
|
|
|
- v-if="canDrag"
|
|
|
- class="icon"
|
|
|
- src="~@/assets/img/data_m/move_ico.png"
|
|
|
- alt=""
|
|
|
- @mousedown="setDraggable(true, index)"
|
|
|
- @dragstart="dragStart(index)"
|
|
|
- @dragend="setDraggable(false, index)"
|
|
|
- style="cursor: move"
|
|
|
- />
|
|
|
- </template>
|
|
|
- <template v-slot:delete>
|
|
|
- <img class="icon" v-if="canDelete" src="~@/assets/img/icons/delete-red.png" alt="" @click="handleDel(index)"/>
|
|
|
- </template>
|
|
|
- </component>
|
|
|
- </div>
|
|
|
+ <table-no-data v-if="dataList.length===0" style="flex:1"/>
|
|
|
+ <grid-layout :layout.sync="dataList"
|
|
|
+ :col-num="layout.colNum"
|
|
|
+ :rowHeight="layout.rowHeight"
|
|
|
+ :is-draggable="canDrag"
|
|
|
+ :is-resizable="canDrag"
|
|
|
+ :vertical-compact="true"
|
|
|
+ :use-css-transforms="true"
|
|
|
+ :margin="layout.margin"
|
|
|
+ >
|
|
|
+ <grid-item v-for="(item) in dataList"
|
|
|
+ :key="item.i"
|
|
|
+ :x="item.x"
|
|
|
+ :y="item.y"
|
|
|
+ :w="item.w"
|
|
|
+ :h="item.h"
|
|
|
+ :i="item.i"
|
|
|
+ drag-allow-from=".vue-draggable-handle"
|
|
|
+ @resized="resizedEvent"
|
|
|
+ @moved="movedEvent"
|
|
|
+ >
|
|
|
+ <component
|
|
|
+ :is="getCompType(item.Type)"
|
|
|
+ :compData="item"
|
|
|
+ :knowList="knowList"
|
|
|
+ :ref="'item' + item.i"
|
|
|
+ :canDelete="canDelete"
|
|
|
+ @deleteKnowledge="deleteKnowledge($event,item)"
|
|
|
+ @deleteKnowledgeType="deleteKnowledgeType($event,item)">
|
|
|
+ <template v-slot:drag>
|
|
|
+ <img
|
|
|
+ v-if="canDrag"
|
|
|
+ class="icon vue-draggable-handle"
|
|
|
+ src="~@/assets/img/data_m/move_ico.png"
|
|
|
+ alt=""
|
|
|
+ style="cursor: move"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ <template v-slot:delete>
|
|
|
+ <img class="icon" v-if="canDelete" src="~@/assets/img/icons/delete-red.png" alt="" @click="handleDel(item)"/>
|
|
|
+ </template>
|
|
|
+ </component>
|
|
|
+ </grid-item>
|
|
|
+ </grid-layout>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
@@ -37,9 +54,12 @@ import apiBiBoard from '@/api/modules/BIBoard.js'
|
|
|
import TableNoData from '../../../components/tableNoData.vue';
|
|
|
import ChartBox from './ChartBox.vue';
|
|
|
import TableBox from './TableBox.vue';
|
|
|
+import KnowBox from './KnowBox.vue';
|
|
|
+import { GridLayout, GridItem } from "vue-grid-layout";
|
|
|
+import {createRandomCode} from '@/views/ppt_manage/newVersion/utils/untils';
|
|
|
|
|
|
export default {
|
|
|
- components: { ChartBox, TableBox, TableNoData },
|
|
|
+ components: { ChartBox, TableBox, TableNoData, GridLayout, GridItem, KnowBox },
|
|
|
props: {
|
|
|
value: {
|
|
|
type: Array,
|
|
@@ -57,37 +77,178 @@ export default {
|
|
|
renderHeight:{
|
|
|
type:String,
|
|
|
default:"calc(100vh - 300px)"
|
|
|
- }
|
|
|
+ },
|
|
|
+ knowList:{//知识资源列表
|
|
|
+ type:Array,
|
|
|
+ default: () => []
|
|
|
+ },
|
|
|
+ },
|
|
|
+ watch:{
|
|
|
+ value(newval){
|
|
|
+ const { wItem , hItem , colNum } = this.layout;
|
|
|
+ let itemList = _.cloneDeep(newval) || [];
|
|
|
+ itemList.map((item,index) => {
|
|
|
+ if(!item.Conf){ //旧数据
|
|
|
+ item.w = wItem;
|
|
|
+ item.h = hItem;
|
|
|
+ item.x = wItem * (index % (colNum / wItem));
|
|
|
+ item.y = hItem * Math.floor(index / (colNum / wItem));
|
|
|
+ item.i = `${item.UniqueCode}_${createRandomCode()}_${index}`;
|
|
|
+ } else {
|
|
|
+ let conf = JSON.parse(item.Conf)
|
|
|
+ item.w = conf.w;
|
|
|
+ item.h = conf.h;
|
|
|
+ item.x = conf.x;
|
|
|
+ item.y = conf.y;
|
|
|
+ item.i = `${item.UniqueCode}_${createRandomCode()}_${index}`
|
|
|
+ }
|
|
|
+ });
|
|
|
+ this.dataList = itemList;
|
|
|
+ },
|
|
|
+ dataList(newval){
|
|
|
+ let list = this.knowList || [];
|
|
|
+ this.$emit('update:knowList',list);//处理插件拖拽重新渲染知识资源列表不展示
|
|
|
+ this.setFirstKnow()
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$emit('checkDataList',newval);//grid-layout对x.y进行处理之后数据发生变化 同步给编辑页面
|
|
|
+ })
|
|
|
+ },
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
draggedIndex: null,
|
|
|
+ dataList:[], //看板列表
|
|
|
+ layout:{
|
|
|
+ colNum:12,
|
|
|
+ rowHeight:96,
|
|
|
+ margin:[20,20],
|
|
|
+ wItem:3,
|
|
|
+ hItem:4,
|
|
|
+ },
|
|
|
+ typeWidth:{ //不同种类的占位宽度
|
|
|
+ 1:3,
|
|
|
+ 2:3,
|
|
|
+ 3:6,
|
|
|
+ },
|
|
|
};
|
|
|
},
|
|
|
methods: {
|
|
|
+ getAddMessage(arr){ //获取添加内容的位置信息
|
|
|
+ if(!arr || !arr.length) return;
|
|
|
+ let d = _.cloneDeep(this.dataList) || [];
|
|
|
+ let result = [];
|
|
|
+ arr.map((item) => { //位置只与最后一个元素的位置有关
|
|
|
+ let yMax = d.length ? Math.max.apply(null,d.map(_=>_.y)) : 0;
|
|
|
+ let yMaxItems = d.length ? d.filter(_=>_.y == yMax) : [];
|
|
|
+
|
|
|
+ let xMax = d.length ? Math.max.apply(null,yMaxItems.map(_=>_.x)) : 0;
|
|
|
+ let hMax = d.length ? Math.max.apply(null,yMaxItems.map(_=>_.h)) : 0;
|
|
|
+ let lastTag = d.length ? d.find(_=>_.y == yMax &&_.x == xMax) : null;
|
|
|
+ let y =d.length ? (this.layout.colNum - xMax - lastTag.w >= this.typeWidth[item.Type] ? yMax : yMax + hMax) : 0;
|
|
|
+ let x =d.length ? (this.layout.colNum - xMax - lastTag.w >= this.typeWidth[item.Type] ? xMax + lastTag.w : 0) : 0;
|
|
|
+
|
|
|
+ let configs = {
|
|
|
+ x,
|
|
|
+ y,
|
|
|
+ w:this.typeWidth[item.Type],
|
|
|
+ h:this.layout.hItem,
|
|
|
+ i:`${item.UniqueCode}_${createRandomCode()}_${d.length}`
|
|
|
+ };
|
|
|
+ let i = {...item,...configs,Conf:JSON.stringify(configs)};
|
|
|
+ d.push(i);
|
|
|
+ result.push(i);
|
|
|
+ })
|
|
|
+ return result;
|
|
|
+ },
|
|
|
+ resizedEvent(i){
|
|
|
+ // this.$refs[`item${i}`] && this.$refs[`item${i}`][0] && this.$refs[`item${i}`][0].handleResize && this.$refs[`item${i}`][0].handleResize();
|
|
|
+ this.handleChangeDataList();
|
|
|
+ },
|
|
|
+ movedEvent(){
|
|
|
+ this.handleChangeDataList();
|
|
|
+ },
|
|
|
getCompType(type) {
|
|
|
- return type === 1 ? ChartBox : TableBox;
|
|
|
+ return type === 1 ? ChartBox : type === 2 ? TableBox : KnowBox;
|
|
|
+ },
|
|
|
+ handleDel(item){
|
|
|
+ if(item.Type == 3) {
|
|
|
+ this.deleteKnowBox(item)
|
|
|
+ };
|
|
|
+ let index = this.dataList.findIndex(_=>_.BiDashboardDetailId == item.BiDashboardDetailId);
|
|
|
+ this.dataList.splice(index,1);
|
|
|
+ this.handleChangeDataList();
|
|
|
+ this.$emit('delete',this.dataList)
|
|
|
},
|
|
|
- handleDel(index){
|
|
|
- this.value.splice(index,1)
|
|
|
- this.$emit('delete',this.value)
|
|
|
+ handleChangeDataList(){
|
|
|
+ this.dataList.map(item=>{
|
|
|
+ let configs = {
|
|
|
+ w : item.w,
|
|
|
+ h : item.h,
|
|
|
+ x : item.x,
|
|
|
+ y : item.y,
|
|
|
+ i : item.i,
|
|
|
+ }
|
|
|
+ item.Conf = JSON.stringify(configs);
|
|
|
+ });
|
|
|
+ this.$emit('input',this.dataList)
|
|
|
},
|
|
|
- setDraggable(draggable, index) {
|
|
|
- const box = this.$el.querySelectorAll('.BI-board-item-box')[index];
|
|
|
- box.draggable = draggable;
|
|
|
+ deleteKnowBox(v){
|
|
|
+ this.$emit('update:knowList',[]);
|
|
|
+ apiBiBoard.saveKnowledge({
|
|
|
+ BiDashboardDetailId:v ? (/^selfId_\d+$/.test(v.BiDashboardDetailId) ? 0 : v.BiDashboardDetailId) : 0,
|
|
|
+ KnowledgeResourceList:[]
|
|
|
+ });
|
|
|
},
|
|
|
- dragStart(index) {
|
|
|
- this.draggedIndex = index;
|
|
|
+ async deleteKnowledgeType(item,v){
|
|
|
+ let { type } = item;
|
|
|
+ let knowList = this.knowList.filter(_=>_.ResourceType != type);
|
|
|
+ let res = await apiBiBoard.saveKnowledge({
|
|
|
+ BiDashboardDetailId:v ? (/^selfId_\d+$/.test(v.BiDashboardDetailId) ? 0 : v.BiDashboardDetailId) : 0,
|
|
|
+ KnowledgeResourceList:knowList.map(_=>({
|
|
|
+ ResourceType:_.ResourceType,
|
|
|
+ KnowledgeResourceId:_.KnowledgeResourceId
|
|
|
+ }))
|
|
|
+ });
|
|
|
+ if(res.Ret != 200) return this.$message.warning('删除失败,请重试');
|
|
|
+ this.knowList = knowList;
|
|
|
+ if(!this.knowList.length){ //清空掉知识资源
|
|
|
+ this.dataList = this.dataList.filter(_=>_.Type != 3);
|
|
|
+ this.$emit('input',this.dataList)
|
|
|
+ }
|
|
|
+ this.setFirstKnow();
|
|
|
},
|
|
|
- async drop(index) {
|
|
|
- if (this.draggedIndex === null) return
|
|
|
- // Swap the two items
|
|
|
- const temp=this.value[this.draggedIndex]
|
|
|
- this.$set(this.value, this.draggedIndex, this.value[index]);
|
|
|
- this.$set(this.value, index, temp);
|
|
|
- this.draggedIndex = null;
|
|
|
- this.$emit('input',this.value)
|
|
|
- this.$emit('change',this.value)
|
|
|
+ async deleteKnowledge(item,v){
|
|
|
+ let index = this.knowList.findIndex(_=>_.KnowledgeResourceId == item.KnowledgeResourceId && _.ResourceType == item.ResourceType)
|
|
|
+ if(index >= 0){
|
|
|
+ let knowList = _.cloneDeep(this.knowList);
|
|
|
+ knowList.splice(index,1)
|
|
|
+ let r = await apiBiBoard.saveKnowledge({
|
|
|
+ BiDashboardDetailId:v ? (/^selfId_\d+$/.test(v.BiDashboardDetailId) ? 0 : v.BiDashboardDetailId) : 0,
|
|
|
+ KnowledgeResourceList:knowList.map(_=>({
|
|
|
+ ResourceType:_.ResourceType,
|
|
|
+ KnowledgeResourceId:_.KnowledgeResourceId
|
|
|
+ }))
|
|
|
+ });
|
|
|
+ if(r.Ret != 200) return this.$message.warning('删除失败,请重试')
|
|
|
+
|
|
|
+ this.knowList.splice(index,1);
|
|
|
+ this.$emit('update:knowList',this.knowList)
|
|
|
+
|
|
|
+ //当前删除后为当前种类为空时
|
|
|
+ let nowTypeKnows = this.knowList.filter(_=>_.ResourceType == item.ResourceType);
|
|
|
+ if(!nowTypeKnows.length) this.setFirstKnow();
|
|
|
+ }
|
|
|
+ if(!this.knowList.length){ //清空掉知识资源
|
|
|
+ this.dataList = this.dataList.filter(_=>_.Type != 3);
|
|
|
+ this.$emit('input',this.dataList)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ setFirstKnow(){
|
|
|
+ this.$nextTick(() => {
|
|
|
+ let v = this.dataList.find(_=>_.Type == 3); //寻找唯一的知识资源库类型
|
|
|
+ if(!v) return;
|
|
|
+ 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();
|
|
|
+ });
|
|
|
},
|
|
|
}
|
|
|
};
|
|
@@ -95,19 +256,21 @@ export default {
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
.BI-board-content {
|
|
|
- padding: 20px;
|
|
|
+ // padding: 20px;
|
|
|
.BI-board-list {
|
|
|
height: calc(100vh - 300px);
|
|
|
overflow-y: auto;
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
|
gap: 20px;
|
|
|
- .BI-board-item-box {
|
|
|
- width: calc(50% - 14px);
|
|
|
- height: 560px;
|
|
|
- border: 1px solid #dcdfe6;
|
|
|
- box-shadow: 0px 2px 8px 0px #00000014;
|
|
|
+ .vue-grid-layout {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ .vue-grid-item {
|
|
|
+ overflow: hidden;
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ box-shadow: 0px 2px 8px 0px #00000014;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-</style>
|
|
|
+</style>
|