Files
admin-sjzx/src/views/pqs/cockpit/setUp/components/popup1.vue

375 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-dialog
draggable
:title="title"
v-model.trim="dialogVisible"
width="900px"
:before-close="handleClose"
:close-on-click-modal="false"
>
<div style="display: flex">
<el-form ref="formRef" style="flex: 1" :rules="rules" :model="form" label-width="auto" class="form mr10">
<el-form-item label="页面名称:" prop="pageName">
<el-input
maxlength="32"
show-word-limit
v-model.trim="form.pageName"
placeholder="请输入页面名称"
></el-input>
</el-form-item>
<el-form-item label="页面排序:" prop="sort">
<el-input
maxlength="32"
show-word-limit-number
v-model.trim.number="form.sort"
:min="0"
:step="1"
step-strictly
style="width: 100%"
/>
</el-form-item>
<el-form-item label="备注:" class="top">
<el-input
maxlength="300"
show-word-limit
type="textarea"
:rows="2"
placeholder="请输入内容"
v-model.trim="form.remark"
></el-input>
</el-form-item>
</el-form>
<!-- 拖拽组件 -->
<div>
<div class="image">
<img
v-for="(item, index) in imgList"
:key="index"
:src="item"
class="mr10"
@click="imgData(index)"
/>
<el-button type="primary" icon="el-icon-Plus" size="small" @click="addItem">添加容器</el-button>
</div>
<GridLayout
class="GridLayout"
v-model:layout="layout"
style="width: 511px; height: 310px"
:row-height="40"
:col-num="12"
>
<template #item="{ item }">
<span class="text">{{ `${item.name}` }}</span>
<!-- <span class="remove" @click="removeItem(item.i)">x</span> -->
<CloseBold class="remove" @click="removeItem(item.i)" />
<el-popover placement="top" :width="230" trigger="click">
<template #reference>
<!-- <span class="bind">绑定页面</span> -->
<Tools class="bind" />
</template>
<el-select
v-model="item.path"
filterable
placeholder="选择绑定页面"
class="mb10"
@change="change($event, item)"
>
<el-option
v-for="item in treeList"
:key="item.id"
:label="item.name"
:value="item.path"
/>
</el-select>
</el-popover>
</template>
</GridLayout>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose"> </el-button>
<el-button type="primary" @click="addFn">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { componentTree } from '@/api/user-boot/user'
import { ref, reactive, onMounted, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { GridLayout, GridItem } from 'grid-layout-plus'
import { Tools, CloseBold } from '@element-plus/icons-vue'
import { addDashboard, updateDashboard } from '@/api/system-boot/csstatisticalset'
import html2canvas from 'html2canvas'
const title = ref('')
const formRef = ref()
const treeList: any = ref([])
const dialogVisible = ref(false)
let index = 9
const emit = defineEmits(['submit'])
const layout: any = ref([
{ x: 0, y: 0, w: 4, h: 2, i: '0', name: '', path: '' },
{ x: 4, y: 0, w: 4, h: 2, i: '1', name: '', path: '' },
{ x: 8, y: 0, w: 4, h: 2, i: '2', name: '', path: '' },
{ x: 0, y: 0, w: 4, h: 2, i: '3', name: '', path: '' },
{ x: 4, y: 0, w: 4, h: 2, i: '4', name: '', path: '' },
{ x: 8, y: 0, w: 4, h: 2, i: '5', name: '', path: '' },
{ x: 0, y: 0, w: 4, h: 2, i: '6', name: '', path: '' },
{ x: 4, y: 0, w: 4, h: 2, i: '7', name: '', path: '' },
{ x: 8, y: 0, w: 4, h: 2, i: '8', name: '', path: '' }
])
const imgList = [
new URL(`@/assets/imgs/1x1.png`, import.meta.url),
new URL(`@/assets/imgs/2x2.png`, import.meta.url),
new URL(`@/assets/imgs/2x3.png`, import.meta.url),
new URL(`@/assets/imgs/3x3.png`, import.meta.url)
]
const form: any = reactive({
pageName: '',
thumbnail: '',
containerConfig: [],
sort: '100',
id: '',
remark: ''
})
const rules = {
pageName: [{ required: true, message: '请输入页面名称', trigger: 'blur' }],
projectIds: [{ required: true, message: '请选择工程页面', trigger: 'change' }],
sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
}
// 删除拖拽
const removeItem = (id: string) => {
const index = layout.value.findIndex(item => item.i === id)
if (index > -1) {
layout.value.splice(index, 1)
}
}
// 添加拖拽容器
function addItem() {
layout.value.push({
x: (layout.value.length * 2) % 6,
y: layout.value.length + 6, // puts it at the bottom
w: 4,
h: 2,
i: `${index++}`,
name: '',
path: ''
})
}
const addFn = () => {
if (layout.value.length == 0) {
return ElMessage.warning('页面设计不能为空!')
}
const maxValue = Math.max(...layout.value.map(item => item.y + item.h))
if (maxValue > 6) {
return ElMessage.warning('组件不能超出当前容器!')
}
formRef.value.validate(async (valid: boolean) => {
let url = ''
await html2canvas(document.querySelector('.GridLayout'), {
useCORS: true
}).then(canvas => {
url = canvas.toDataURL('image/png')
})
if (valid) {
if (title.value == '新增页面') {
addDashboard({ ...form, containerConfig: JSON.stringify(layout.value), thumbnail: url }).then(
(res: any) => {
ElMessage.success('新增页面成功!')
handleClose()
}
)
} else {
updateDashboard({ ...form, containerConfig: JSON.stringify(layout.value), thumbnail: url }).then(
(res: any) => {
ElMessage.success('修改页面成功!')
handleClose()
}
)
}
}
})
}
const change = (e: any, item: any) => {
item.name = treeList.value.filter((item: any) => item.path == e)[0].name
}
// 设置布局
const imgData = i => {
switch (i) {
case 0:
// 1x1
layout.value = [{ x: 0, y: 0, w: 12, h: 6, i: '0', name: '', path: '' }]
return
case 1:
// 2x2
layout.value = [
{ x: 0, y: 0, w: 6, h: 3, i: '0', name: '', path: '' },
{ x: 6, y: 0, w: 6, h: 3, i: '1', name: '', path: '' },
{ x: 0, y: 3, w: 6, h: 3, i: '3', name: '', path: '' },
{ x: 6, y: 3, w: 6, h: 3, i: '4', name: '', path: '' }
]
return
case 2:
// 2x3
layout.value = [
{ x: 0, y: 0, w: 8, h: 4, i: '0', name: '', path: '' },
{ x: 8, y: 0, w: 4, h: 2, i: '2', name: '', path: '' },
{ x: 8, y: 2, w: 4, h: 2, i: '5', name: '', path: '' },
{ x: 0, y: 4, w: 4, h: 2, i: '6', name: '', path: '' },
{ x: 4, y: 4, w: 4, h: 2, i: '7', name: '', path: '' },
{ x: 8, y: 4, w: 4, h: 2, i: '8', name: '', path: '' }
]
return
case 3:
// 3x3
layout.value = [
{ x: 0, y: 0, w: 4, h: 2, i: '0', name: '', path: '' },
{ x: 4, y: 0, w: 4, h: 2, i: '1', name: '', path: '' },
{ x: 8, y: 0, w: 4, h: 2, i: '2', name: '', path: '' },
{ x: 0, y: 0, w: 4, h: 2, i: '3', name: '', path: '' },
{ x: 4, y: 0, w: 4, h: 2, i: '4', name: '', path: '' },
{ x: 8, y: 0, w: 4, h: 2, i: '5', name: '', path: '' },
{ x: 0, y: 0, w: 4, h: 2, i: '6', name: '', path: '' },
{ x: 4, y: 0, w: 4, h: 2, i: '7', name: '', path: '' },
{ x: 8, y: 0, w: 4, h: 2, i: '8', name: '', path: '' }
]
return
default:
}
}
const open = ref((row: any) => {
if (row.data) {
layout.value = JSON.parse(row.data.containerConfig)
form.pageName = row.data.pageName
form.sort = row.data.sort
form.remark = row.data.remark
form.id = row.data.id
}
title.value = row.title
dialogVisible.value = true
// if (row.title == '新增页面') {
// form.name = ''
// form.projectIds = []
// form.sort = '100'
// form.remark = ''
// } else {
// for (let key in form) {
// form[key] = row.row[key] || ''
// }
// form.id = row.row.id
// }
})
onMounted(() => {
componentTree().then((res: any) => {
const uniqueArray = tree2List(res.data, Math.random() * 1000).filter(
(item: any) => item.path != '' && item.path != null
)
treeList.value = Array.from(new Map(uniqueArray.map(item => [item.path, item])).values())
})
})
const tree2List = (list: any, id: any) => {
//存储结果的数组
let arr: any = []
// 遍历 tree 数组
list.forEach((item: any) => {
item.uPid = id
item.uId = Math.random() * 1000
// 判断item是否存在children
if (!item.children) return arr.push(item)
// 函数递归对children数组进行tree2List的转换
const children = tree2List(item.children, item.uId)
// 删除item的children属性
delete item.children
// 把item和children数组添加至结果数组
//..children: 意思是把children数组展开
arr.push(item, ...children)
})
// 返回结果数组
return arr
}
const handleClose = () => {
dialogVisible.value = false
emit('submit')
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.vgl-layout {
background-color: #eee;
}
:deep(.vgl-item:not(.vgl-item--placeholder)) {
background-color: #ccc;
border: 1px solid black;
}
:deep(.vgl-item--resizing) {
opacity: 90%;
}
:deep(.vgl-item--static) {
background-color: #cce;
}
.text {
position: absolute;
display: flex;
align-items: center;
inset: 0;
width: 80%;
height: 100%;
padding: 5px;
color: #000;
font-size: 14px;
}
.layout-json {
padding: 10px;
margin-top: 10px;
background-color: #ddd;
border: 1px solid black;
}
.columns {
columns: 120px;
}
.remove {
position: absolute;
top: 5px;
right: 2px;
width: 16px;
cursor: pointer;
}
.bind {
position: absolute;
top: 50%;
right: -5px;
transform: translate(-50%, -50%);
color: var(--el-color-primary);
cursor: pointer;
width: 16px;
}
.image {
display: flex;
align-items: center;
margin-bottom: 5px;
img {
height: 20px;
cursor: pointer;
}
.el-button {
margin-left: auto;
}
}
</style>