修改测试bug 优化页面

This commit is contained in:
guanj
2026-01-04 14:55:31 +08:00
parent cc0f8bc8b6
commit a765cdf9ee
68 changed files with 5396 additions and 3096 deletions

View File

@@ -1,136 +1,195 @@
<template>
<div class="pd10">
<el-card>
<el-form ref="formRef" inline :rules="rules" :model="form" label-width="auto" class="form-four">
<el-form-item label="页面名称" prop="pageName">
<el-input
style="width: 100%"
maxlength="32"
show-word-limit
v-model.trim="form.pageName"
placeholder="请输入页面名称"
></el-input>
</el-form-item>
<el-form-item label="图标">
<IconSelector v-model.trim="form.icon" style="width: 80%" placeholder="请选择图标" />
</el-form-item>
<el-form-item label="页面排序" prop="sort">
<el-input-number style="width: 100%" v-model.trim="form.sort" :min="0" :max="10000" :step="1" />
</el-form-item>
<el-form-item label="是否激活">
<el-switch
v-model="form.state"
inline-prompt
:disabled="form.pagePath == 'dashboard/index'"
:active-value="1"
:inactive-value="0"
active-text=""
inactive-text=""
/>
</el-form-item>
<el-form-item label="备注" class="top">
<el-input
maxlength="300"
show-word-limit
type="textarea"
:rows="1"
placeholder="请输入内容"
v-model.trim="form.remark"
></el-input>
</el-form-item>
<el-form-item>
<div style="width: 100%; display: flex; justify-content: end">
<el-button type="primary" icon="el-icon-Check" @click="onSubmit">保存</el-button>
<back-component />
</div>
</el-form-item>
</el-form>
</el-card>
<el-card class="mt10" :style="height">
<div style="display: flex">
<div style="width: 605px; overflow: auto" :style="indicatorHeight" class="mr10">
<el-collapse v-model="activeNames" :expand-icon-position="position">
<el-collapse-item
v-for="item in treeComponents"
:key="item.id"
:title="item.name"
:name="item.id"
>
<el-collapse v-model="activeNames1" class="ml20">
<el-collapse-item v-for="k in item.children" :key="k.id" :title="k.name" :name="k.id">
<div class="Box">
<div
v-for="(s, index) in k.children"
:key="index"
class="mr10 mb10 imgBox"
draggable="true"
unselectable="on"
@drag="drag(s)"
@dragend="dragEnd(s)"
>
<div class="textName">{{ s.name }}</div>
<img :src="s.image" style="width: 180px" />
<div class="default-main pd10">
<div style="width: 100%; display: flex; justify-content: end">
<el-button type="primary" icon="el-icon-Check" @click="onSubmit">保存</el-button>
<back-component />
</div>
<div style="display: flex" class="mt10">
<!-- <el-tabs type="border-card">
<el-tab-pane label="组件">
<div style="width: 520px; overflow: auto" :style="indicatorHeight" class="mr10">
<el-collapse v-model="activeNames" :expand-icon-position="position">
<el-collapse-item
v-for="item in treeComponents"
:key="item.id"
:title="item.name"
:name="item.id"
>
<el-collapse v-model="activeNames1" class="ml20">
<el-collapse-item
v-for="k in item.children"
:key="k.id"
:title="k.name"
:name="k.id"
>
<div class="Box">
<div
v-for="(s, index) in k.children"
:key="index"
class="mr10 mb10 imgBox"
draggable="true"
unselectable="on"
@drag="drag(s)"
@dragend="dragEnd(s)"
>
<div class="textName">{{ s.name }}</div>
<img :src="s.image" style="width: 150px" />
</div>
</div>
</div>
</el-collapse-item>
</el-collapse>
</el-collapse-item>
</el-collapse>
</div>
<div style="flex: 1" ref="wrapper">
<GridLayout
class="GridLayout"
ref="gridLayout"
v-model:layout="layout"
style="width: 100%"
:style="{ height: GridHeight + 'px' }"
:row-height="rowHeight"
:col-num="12"
prevent-collision
:vertical-compact="false"
>
<template #item="{ item }">
<div class="imgBox">
<div class="textName">{{ item.name }}</div>
<img
:src="getImg(item.path)"
:style="{
height:
item.h * rowHeight -
(item.h == 1
? 30
: item.h == 2
? 20
: item.h == 3
? 10
: item.h == 4
? -0
: item.h == 5
? -10
: -20) +
'px'
}"
/>
<CloseBold class="remove" @click="removeItem(item.i)" />
</el-collapse-item>
</el-collapse>
</el-collapse-item>
</el-collapse>
</div>
</el-tab-pane>
</el-tabs> -->
<el-tabs v-model="tableName" type="border-card" @tab-change="changeTab">
<el-tab-pane v-for="item in treeComponents" :key="item.name" :label="item.name" :name="item.name">
<el-tabs v-model="tableName1" tab-position="top">
<el-tab-pane v-for="k in item?.children" :key="k.name" :label="k.name" :name="k.name">
<div :style="indicatorHeight" style="overflow-y: auto; overflow-x: hidden">
<el-row :gutter="10" class="pl5 pr5 pt5" style="width: 520px">
<el-col :span="8" v-for="component in k.children" :key="component.id" class="mb10">
<el-card
class="box-card"
shadow="hover"
@drag="drag(component)"
@dragend="dragEnd(component)"
>
<div slot="header" class="clearfix">
<span style="display: flex; align-items: center">
{{ component.name }}
</span>
</div>
<img v-if="component.image" :src="component.image" class="image xiaoshou" />
</el-card>
</el-col>
</el-row>
</div>
<!-- <span class="text">{{ `${item?.name}` }}</span>
</el-tab-pane>
</el-tabs>
</el-tab-pane>
</el-tabs>
<div style="flex: 1" ref="wrapper" class="ml10">
<el-tabs type="border-card" class="mb10">
<el-tab-pane label="基础信息">
<el-form ref="formRef" inline :rules="rules" :model="form" label-width="auto" class="form-four">
<el-form-item label="页面名称" prop="pageName">
<el-input
style="width: 100%"
maxlength="32"
show-word-limit
v-model.trim="form.pageName"
placeholder="请输入页面名称"
></el-input>
</el-form-item>
<el-form-item label="图标">
<IconSelector v-model.trim="form.icon" placeholder="请选择图标" />
</el-form-item>
<el-form-item label="页面排序" prop="sort">
<el-input-number
style="width: 100%"
v-model.trim="form.sort"
:min="0"
:max="10000"
:step="1"
/>
</el-form-item>
<el-form-item label="是否激活">
<el-switch
v-model="form.state"
inline-prompt
width="60px"
:disabled="form.pagePath == 'dashboard/index'"
:active-value="1"
:inactive-value="0"
active-text=" "
inactive-text=" "
/>
</el-form-item>
<el-form-item label="是否全局" v-if="hasAdmin">
<el-switch
v-model="form.scope"
inline-prompt
width="60px"
:active-value="1"
:inactive-value="0"
:disabled="form.pagePath == 'dashboard/index'"
active-text=" "
inactive-text=" "
/>
</el-form-item>
<el-form-item label="备注" class="top">
<el-input
maxlength="300"
show-word-limit
style="width: 100%"
type="textarea"
:rows="1"
placeholder="请输入内容"
v-model.trim="form.remark"
></el-input>
</el-form-item>
<el-form-item></el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
<div ref="PaneRef">
<el-tabs type="border-card">
<el-tab-pane label="画布" :style="height">
<GridLayout
class="GridLayout"
ref="gridLayout"
v-model:layout="layout"
style="width: 100%"
:style="{ height: GridHeight + 'px' }"
:row-height="rowHeight"
:col-num="12"
prevent-collision
:is-bounded="true"
:vertical-compact="false"
>
<template #item="{ item }">
<div class="imgBox">
<div class="textName">{{ item.name }}</div>
<img
:src="getImg(item.path)"
:style="{
height:
item.h * rowHeight -
(item.h == 1
? 30
: item.h == 2
? 20
: item.h == 3
? 10
: item.h == 4
? -0
: item.h == 5
? -10
: -20) +
'px'
}"
/>
<CloseBold class="remove" @click="removeItem(item.i)" />
</div>
<!-- <span class="text">{{ `${item?.name}` }}</span>
-->
</template>
</GridLayout>
</template>
</GridLayout>
</el-tab-pane>
</el-tabs>
</div>
</div>
</el-card>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'
import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import BackComponent from '@/components/icon/back/index.vue'
import { mainHeight } from '@/utils/layout'
@@ -145,17 +204,22 @@ import { addDashboard, updateDashboard, queryById } from '@/api/system-boot/csst
import html2canvas from 'html2canvas'
import { useRoute } from 'vue-router'
import { getMenu } from '@/utils/router'
import { useAdminInfo } from '@/stores/adminInfo'
const tableName = ref('')
const tableName1 = ref('')
import { useNavTabs } from '@/stores/navTabs'
// defineOptions({
// name: 'cockpit/popup'
// })
const adminInfo = useAdminInfo()
const hasAdmin = adminInfo.roleCode.some(item => item.includes('operation_manager') || item.includes('root'))
const { go } = useRouter()
const navTabs = useNavTabs()
const { query } = useRoute()
const router = useRouter()
const height = mainHeight(148)
const indicatorHeight = mainHeight(168)
const height = mainHeight(295)
const indicatorHeight = mainHeight(180)
const rowHeight = ref(0)
const pageList: any = ref([])
const GridHeight = ref(0)
@@ -167,6 +231,7 @@ const form: any = reactive({
sort: '100',
id: '',
state: 1,
scope: 0,
icon: '',
pagePath: '',
remark: '',
@@ -205,6 +270,8 @@ const info = () => {
activeNames1.value = []
componentTree().then(res => {
treeComponents.value = res.data
tableName.value = tableName.value == '' ? treeComponents.value[0].name : tableName.value
tableName1.value = tableName1.value == '' ? treeComponents.value[0].children[0].name : tableName1.value
activeNames.value = treeComponents.value.map(item => item.id)
res.data.forEach(item => {
item.children.forEach(k => {
@@ -223,6 +290,7 @@ const info = () => {
form.remark = res.data.remark
form.id = res.data.id
form.state = res.data.state
form.scope = res.data.userId == 0 ? 1 : 0
form.icon = res.data.icon
})
} else {
@@ -251,6 +319,10 @@ const tree2List = (list: any, id: any) => {
// 返回结果数组
return arr
}
const changeTab = (e: any) => {
console.log('🚀 ~ changeTab ~ e:', e)
tableName1.value = treeComponents.filter(item => item.name == e)[0].children[0].name
}
// 删除拖拽
const removeItem = (id: string) => {
const index = layout.value.findIndex(item => item.i === id)
@@ -260,6 +332,7 @@ const removeItem = (id: string) => {
}
}
const wrapper = ref<HTMLElement>()
const PaneRef = ref<HTMLElement>()
const gridLayout = ref<InstanceType<typeof GridLayout>>()
const mouseAt = { x: -1, y: -1 }
@@ -365,6 +438,12 @@ const onSubmit = () => {
if (layout.value.length == 0) {
return ElMessage.warning('页面设计不能为空!')
}
console.log(123, findDuplicateNames(layout.value))
let repeat = findDuplicateNames(layout.value) || []
if (repeat.length > 0) {
return ElMessage.warning(repeat.join('、')+' 组件重复,请删除重复组件!')
}
// const maxValue = Math.max(...layout.value.map(item => item.y + item.h))
// if (maxValue > 6) {
// return ElMessage.warning('组件不能超出当前容器!')
@@ -381,21 +460,27 @@ const onSubmit = () => {
if (valid) {
if (form.id == '') {
await addDashboard({ ...form, containerConfig: JSON.stringify(layout.value), thumbnail: url }).then(
async (res: any) => {
ElMessage.success('新增页面成功!')
// go(-1)
await getMenu()
}
)
await addDashboard({
...form,
containerConfig: JSON.stringify(layout.value),
thumbnail: url,
userId: form.scope == 1 ? '0' : adminInfo.id
}).then(async (res: any) => {
ElMessage.success('新增页面成功!')
// go(-1)
await getMenu()
})
} else {
await updateDashboard({ ...form, containerConfig: JSON.stringify(layout.value), thumbnail: url }).then(
async (res: any) => {
ElMessage.success('修改页面成功!')
// go(-1)
await getMenu()
}
)
await updateDashboard({
...form,
containerConfig: JSON.stringify(layout.value),
thumbnail: url,
userId: form.scope == 1 ? '0' : adminInfo.id
}).then(async (res: any) => {
ElMessage.success('修改页面成功!')
// go(-1)
await getMenu()
})
}
await setTimeout(() => {
router.push({
@@ -406,17 +491,47 @@ const onSubmit = () => {
}
})
}
// 查找重复的name
const findDuplicateNames = (arr: any) => {
// 用于记录每个name出现的次数
const nameCount = {}
// 用于存储重复的name
const duplicates = []
// 遍历数组统计每个name的出现次数
arr.forEach(item => {
const name = item.name
if (nameCount[name]) {
nameCount[name]++
} else {
nameCount[name] = 1
}
})
// 筛选出出现次数大于1的name
for (const name in nameCount) {
if (nameCount[name] > 1) {
duplicates.push(name)
}
}
return duplicates
}
const getImg = throttle((path: string) => {
if (path != undefined) return treeComponentsCopy.value.filter(item => item.path == path)[0]?.image
})
onMounted(() => {
info()
GridHeight.value = wrapper.value?.offsetWidth / 1.77777
rowHeight.value = GridHeight.value / 6 - 11.5
document.documentElement.style.setProperty('--GridLayout-height', rowHeight.value + 10 + 'px')
document.addEventListener('dragover', syncMousePosition)
nextTick(() => {
GridHeight.value = PaneRef.value?.offsetHeight - 60 //wrapper.value?.offsetWidth / 1.77777
setTimeout(() => {
console.log('🚀 ~ wrapper.value?.offsetWidth:', PaneRef.value?.offsetWidth)
}, 500)
rowHeight.value = GridHeight.value / 6 - 11.5
document.documentElement.style.setProperty('--GridLayout-height', rowHeight.value + 10 + 'px')
document.addEventListener('dragover', syncMousePosition)
})
})
onBeforeUnmount(() => {
@@ -436,7 +551,7 @@ onBeforeUnmount(() => {
display: flex;
// flex: 1;
// align-items: center;
width: 24%;
width: 32%;
.el-form-item__content {
width: 100%;
flex: 1;
@@ -516,4 +631,24 @@ onBeforeUnmount(() => {
:deep(.el-form--inline .el-form-item) {
margin-right: 0px;
}
:deep(.el-card__header) {
padding: 13px 20px;
height: 44px;
}
:deep(.el-card__body) {
padding: 10px;
}
.xiaoshou {
cursor: pointer;
}
.image {
display: block;
width: 100%;
height: 100px;
}
.box-card {
width: 100%;
// border: 1px solid #000;
box-shadow: var(--el-box-shadow-light);
}
</style>