8 changed files with 1158 additions and 184 deletions
@ -0,0 +1,594 @@ |
|||
<!-- |
|||
@ 作者: 袁纪菲 |
|||
@ 时间: 2024.4.16 |
|||
@ 备注: 新建应用 |
|||
--> |
|||
<script lang="ts" setup> |
|||
import { ref , onMounted } from 'vue'; |
|||
import { ElMessage, ElMessageBox } from 'element-plus'; |
|||
interface Menu { |
|||
id: number; |
|||
name: string; |
|||
type: string; // 区分分组和表单 |
|||
parentId?: number | undefined; //表示当前分组或表单所属的父分组ID |
|||
children?: Menu[]; //表示当前分组下的子分组和表单 |
|||
expanded?: boolean;// 分组展开状态,默认为 true |
|||
order?: number; // 添加 order 属性用于记录菜单项的顺序 |
|||
} |
|||
// 转换原始menu数据为新的数据结构 |
|||
function transformMenu(menuItems: Menu[], parentId?: number): Menu[] { |
|||
const transformedItems: Menu[] = []; |
|||
let order = 0; // 记录顺序 |
|||
for (const item of menuItems) { |
|||
const newItem: Menu = { ...item, parentId, order: order++ }; // 设置顺序 |
|||
if (item.type === 'group') { |
|||
const childItems = menuItems.filter((m) => m.parentId === item.id); |
|||
newItem.children = transformMenu(childItems, item.id); |
|||
} |
|||
transformedItems.push(newItem); |
|||
} |
|||
return transformedItems; |
|||
} |
|||
// 初始化菜单数据 |
|||
const initialMenu = [ |
|||
{ id: 1, name: '分组A', type: 'group' , expanded: true }, |
|||
{ id: 2, name: '表单1', type: 'form', parentId: 1 }, |
|||
{ id: 3, name: '分组B', type: 'group', parentId: 1 , expanded: true }, |
|||
{ id: 4, name: '表单2', type: 'form', parentId: 3 }, |
|||
]; |
|||
const menu = ref<Menu[]>(transformMenu(initialMenu)); // 将 transformMenu 的结果直接赋值给 menu |
|||
const appName = ref(''); |
|||
const createFormVisible = ref(false); |
|||
const createGroupVisible = ref(false); |
|||
const moveToVisible = ref(false); |
|||
const renameVisible = ref(false); |
|||
const newFormName = ref(''); |
|||
const newGroupName = ref(''); |
|||
const renameValue = ref(''); |
|||
// 用于临时存储待修改的表单或分组及其原始名称 |
|||
let renameItem: Menu | null = null; |
|||
let originalName: string = ''; |
|||
|
|||
const selectedParentId = ref<number | undefined>(undefined); |
|||
//用于存储待移动分组的 ID |
|||
const selectedGroupId = ref<number | null>(null); |
|||
//用于存储新建子表单或子分组时对应的父分组ID |
|||
const currentParentForNewForm = ref<number | undefined>(undefined); |
|||
const currentParentForNewGroup = ref<number | undefined>(undefined); |
|||
// 页面加载完成后初始化应用名称 |
|||
onMounted(() => { |
|||
appName.value = localStorage.getItem('appName') || '未命名应用'; |
|||
}); |
|||
// 保存应用名称 |
|||
const saveAppName = () => { |
|||
localStorage.setItem('appName', appName.value); |
|||
} |
|||
// 打开新建表单对话框 |
|||
const openCreateFormDialog = () =>{ |
|||
createFormVisible.value = true; |
|||
} |
|||
//保存新建表单 |
|||
const saveNewForm = () =>{ |
|||
if (!newFormName.value.trim()) { |
|||
ElMessage.error('表单名称不能为空'); |
|||
return; |
|||
} |
|||
const newForm: Menu = { |
|||
id: menu.value.length + 1, // 假设使用递增的ID |
|||
name: newFormName.value, |
|||
type: 'form', |
|||
parentId: currentParentForNewForm.value, // 根据当前设置的父分组ID |
|||
}; |
|||
// 判断是否为子表单,如果是,则添加到父分组的children数组中 |
|||
if (currentParentForNewForm.value !== undefined) { |
|||
const parent = menu.value.find((item) => item.id === currentParentForNewForm.value); |
|||
if (parent && parent.children) { |
|||
parent.children.push(newForm); |
|||
} |
|||
} else { |
|||
// 不是子表单,按照原有逻辑作为顶级表单添加到menu数组末尾 |
|||
menu.value.push(newForm); |
|||
} |
|||
ElMessage.success('新建成功'); |
|||
createFormVisible.value = false; |
|||
newFormName.value = ''; |
|||
} |
|||
//打开新建分组对话框 |
|||
const openCreateGroupDialog = () =>{ |
|||
createGroupVisible.value = true; |
|||
} |
|||
//保存新建分组 |
|||
const saveNewGroup = () =>{ |
|||
if (!newGroupName.value.trim()) { |
|||
ElMessage.error('分组名称不能为空'); |
|||
return; |
|||
} |
|||
const newGroup: Menu = { |
|||
id: menu.value.length + 1, // 假设使用递增的ID |
|||
name: newGroupName.value, |
|||
type: 'group', |
|||
parentId: currentParentForNewGroup.value, // 根据当前设置的父分组ID |
|||
}; |
|||
// 判断是否为子分组,如果是,则添加到父分组的children数组中 |
|||
if (currentParentForNewGroup.value !== undefined) { |
|||
const parent = menu.value.find((item) => item.id === currentParentForNewGroup.value); |
|||
if (parent && parent.children) { |
|||
parent.children.push(newGroup); |
|||
} |
|||
} else { |
|||
// 不是子分组,按照原有逻辑作为顶级分组添加到menu数组末尾 |
|||
menu.value.push(newGroup); |
|||
} |
|||
createGroupVisible.value = false; |
|||
newGroupName.value = ''; |
|||
} |
|||
//子表单弹窗 |
|||
const openCreateChildFormDialog = (parent: Menu) => { |
|||
// 显示新建表单对话框,并将父分组信息传入,以便保存时使用 |
|||
createFormVisible.value = true; |
|||
// 设置新建表单的初始父分组ID |
|||
currentParentForNewForm.value = parent.id; |
|||
}; |
|||
//子分组弹窗 |
|||
const openCreateChildGroupDialog = (parent: Menu) => { |
|||
// 显示新建分组对话框,并将父分组信息传入,以便保存时使用 |
|||
createGroupVisible.value = true; |
|||
// 设置新建分组的初始父分组ID |
|||
currentParentForNewGroup.value = parent.id; |
|||
}; |
|||
// 删除表单或分组 |
|||
const confirmDelete = (item: Menu) => { |
|||
const isParentGroup = item.children && item.children.length > 0 && item.type === 'group' && item.parentId === selectedParentId.value; // 确保是包含子元素的分组且为当前选中父分组的子分组 |
|||
if (isParentGroup) { |
|||
// 弹出确认删除对话框,包含子元素提示 |
|||
ElMessageBox.confirm( |
|||
`确定要删除分组 "${item.name}" 及其所有子分组和表单吗?`, |
|||
'警告', |
|||
{ |
|||
confirmButtonText: '确定删除', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
} |
|||
).then(() => { |
|||
deleteMenuRecursively(item); // 用户确认后,递归删除该分组及其所有子分组和表单 |
|||
}).catch(() => {}); // 用户取消时不执行任何操作 |
|||
} else { |
|||
// 弹出确认删除对话框,无子元素提示 |
|||
ElMessageBox.confirm( |
|||
`确定要删除 ${item.type === 'group' ? '分组' : '表单'} "${item.name}" 吗?`, |
|||
'警告', |
|||
{ |
|||
confirmButtonText: '确定删除', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
} |
|||
).then(() => { |
|||
removeSingleItem(item); // 用户确认后,删除当前分组或表单 |
|||
}).catch(() => {}); // 用户取消时不执行任何操作 |
|||
} |
|||
}; |
|||
|
|||
// 递归删除指定分组及其所有子分组和表单 |
|||
const deleteMenuRecursively = (parent: Menu) => { |
|||
// 遍历当前分组的子元素 |
|||
for (const child of parent.children ?? []) { |
|||
if (child.children) { |
|||
deleteMenuRecursively(child); // 递归删除子分组及其子元素 |
|||
} |
|||
const childIndex = menu.value.findIndex((i) => i.id === child.id); |
|||
if (childIndex !== -1) { |
|||
menu.value.splice(childIndex, 1); // 从菜单数组中删除子表单 |
|||
} |
|||
} |
|||
const parentIndex = menu.value.findIndex((i) => i.id === parent.id); |
|||
if (parentIndex !== -1) { |
|||
menu.value.splice(parentIndex, 1); // 从菜单数组中删除父分组 |
|||
} |
|||
}; |
|||
|
|||
// 删除单个分组或表单,不影响父分组 |
|||
const removeSingleItem = (item: Menu) => { |
|||
const itemIndex = menu.value.findIndex((i) => i.id === item.id); |
|||
if (itemIndex !== -1) { |
|||
menu.value.splice(itemIndex, 1); // 从菜单数组中删除当前分组或表单 |
|||
} |
|||
|
|||
// 如果被删除的是子分组或子表单,需要从其父分组的children数组中移除 |
|||
if (item.parentId !== undefined) { |
|||
const parent = menu.value.find((i) => i.id === item.parentId); |
|||
if (parent && parent.children) { |
|||
const childIndex = parent.children.findIndex((c) => c.id === item.id); |
|||
if (childIndex !== -1) { |
|||
parent.children.splice(childIndex, 1); |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
//打开修改名称对话框 |
|||
const showRenameDialog = (item: Menu) => { |
|||
renameItem = item; |
|||
originalName = item.name; |
|||
renameVisible.value = true; |
|||
// 更新对应item的name属性,并保存到菜单数组中 |
|||
}; |
|||
// 关闭修改名称对话框 |
|||
const handleRenameClose = () => { |
|||
renameItem = null; |
|||
originalName = ''; |
|||
renameVisible.value = false; |
|||
}; |
|||
// 取消修改名称操作 |
|||
const handleRenameCancel = () => { |
|||
handleRenameClose(); |
|||
renameValue.value = originalName; |
|||
}; |
|||
// 保存修改名称操作 |
|||
const handleRenameSave = () => { |
|||
if (!renameValue.value.trim()) { |
|||
ElMessage.error('名称不能为空'); |
|||
return; |
|||
} |
|||
if (renameItem) { |
|||
renameItem.name = renameValue.value; |
|||
ElMessage.success('重命名成功'); |
|||
} |
|||
handleRenameClose(); |
|||
}; |
|||
//打开移动对话框 |
|||
const showMoveToDialog = (item: Menu) => { |
|||
selectedGroupId.value = item.id; |
|||
moveToVisible.value = true; |
|||
}; |
|||
//关闭移动对话框 |
|||
const handleMoveToClose = () => { |
|||
selectedGroupId.value = null; |
|||
moveToVisible.value = false; |
|||
}; |
|||
//取消移动操作 |
|||
const handleMoveToCancel = () => { |
|||
handleMoveToClose(); |
|||
}; |
|||
//保存移动操作 |
|||
const handleMoveToSave = () => { |
|||
if (!selectedParentId.value) { |
|||
ElMessage.error('请选择目标分组'); |
|||
return; |
|||
} |
|||
const movingItemIndex = menu.value.findIndex((item) => item.id === selectedGroupId.value); |
|||
if (movingItemIndex === -1) { |
|||
ElMessage.error('移动失败,找不到待移动的项'); |
|||
return; |
|||
} |
|||
|
|||
const movingItem = menu.value[movingItemIndex]; |
|||
const targetGroup = menu.value.find((item) => item.id === selectedParentId.value); |
|||
if (!targetGroup || targetGroup.type !== 'group') { |
|||
ElMessage.error('移动失败,找不到目标分组'); |
|||
return; |
|||
} |
|||
// 更新待移动项的parentId并移除原位置 |
|||
const movedItem = menu.value.splice(movingItemIndex, 1)[0]; |
|||
movedItem.parentId = targetGroup.id; |
|||
// 将移动后的项插入到目标分组的children中,并保持正确的排序 |
|||
if (!targetGroup.children) { |
|||
targetGroup.children = []; |
|||
} |
|||
const insertIndex = targetGroup.children.findIndex((child) => child.id > movedItem.id); |
|||
targetGroup.children.splice(insertIndex >= 0 ? insertIndex : targetGroup.children.length, 0, movedItem); |
|||
|
|||
ElMessage.success('移动成功'); |
|||
handleMoveToClose(); |
|||
}; |
|||
//定义一个 toggleExpand 方法,用于切换分组的 expanded 状态。 |
|||
const toggleExpand = (group: Menu) => { |
|||
group.expanded = !group.expanded; |
|||
}; |
|||
</script> |
|||
<template> |
|||
<div class="common-layout"> |
|||
<!-- 顶部导航栏 --> |
|||
<el-header> |
|||
<div> |
|||
<el-input |
|||
v-model="appName" |
|||
class="header-input" |
|||
clearable |
|||
placeholder="未命名应用" |
|||
@clear="saveAppName" |
|||
@blur="saveAppName" |
|||
></el-input> |
|||
</div> |
|||
<div class="header-btn"> |
|||
<el-button type="primary" >编辑表单</el-button> |
|||
</div> |
|||
</el-header> |
|||
<!-- 主体布局容器 --> |
|||
<el-container> |
|||
<!-- 左侧侧边栏 --> |
|||
<el-aside> |
|||
<div class="sidebar-upper"> |
|||
<!-- 搜索框 --> |
|||
<el-input placeholder="搜索" class="search-input" /> |
|||
<!-- 新增按钮 --> |
|||
<el-dropdown trigger="click"> |
|||
<el-button type="primary" plain class="add-btn"> |
|||
<el-icon><Plus /></el-icon> |
|||
</el-button> |
|||
<template #dropdown> |
|||
<el-dropdown-menu> |
|||
<el-dropdown-item @click="() => openCreateFormDialog()"><el-icon><DocumentAdd /></el-icon>新建表单</el-dropdown-item> |
|||
<el-dropdown-item @click="() => openCreateGroupDialog()"><el-icon><FolderAdd /></el-icon>新建分组</el-dropdown-item> |
|||
</el-dropdown-menu> |
|||
</template> |
|||
</el-dropdown> |
|||
</div> |
|||
<!-- 侧边栏下半部区域 --> |
|||
<div class="sidebar-lower"> |
|||
<ul class="sidebar-menu"> |
|||
<template v-for="(item) in menu"> |
|||
<template v-if="item.type === 'group'"> |
|||
<!-- 分组 --> |
|||
<li :key="item.id"> |
|||
<div class="menu-item" :class="{ 'is-collapsed': !item.expanded }" @click="toggleExpand(item)"> |
|||
<span><el-icon><Folder /></el-icon>{{ item.name }}</span> |
|||
<el-dropdown trigger="click" placement="bottom-end"> |
|||
<el-icon><MoreFilled /></el-icon> |
|||
<template #dropdown> |
|||
<el-dropdown-menu> |
|||
<el-dropdown-item @click="openCreateChildFormDialog(item)"><el-icon><DocumentAdd /></el-icon>新建子表单</el-dropdown-item> |
|||
<el-dropdown-item @click="openCreateChildGroupDialog(item)"><el-icon><FolderAdd /></el-icon>新建子分组</el-dropdown-item> |
|||
<el-dropdown-item @click="confirmDelete(item)"><el-icon><Delete /></el-icon>删除</el-dropdown-item> |
|||
<el-dropdown-item @click="showRenameDialog(item)"><el-icon><EditPen /></el-icon>修改名称</el-dropdown-item> |
|||
<el-dropdown-item @click="showMoveToDialog(item)"><el-icon><FolderRemove /></el-icon>移动到</el-dropdown-item> |
|||
</el-dropdown-menu> |
|||
</template> |
|||
</el-dropdown> |
|||
</div> |
|||
<!-- 分组展开后显示子表单/子分组 --> |
|||
<transition name="expand-collapse"> |
|||
<ul v-if="item.children && item.expanded"> |
|||
<li v-for="child in item.children" :key="child.id"> |
|||
<!-- 对子表单和子分组再次进行类型判断,递归渲染 --> |
|||
<template v-if="child.type === 'group'"> |
|||
<!-- 子分组模板 --> |
|||
<div class="menu-item-child"> |
|||
<span @click="toggleExpand(child)"><el-icon><Folder /></el-icon>{{ child.name }}</span> |
|||
<el-dropdown trigger="click" placement="bottom-end"> |
|||
<el-icon><MoreFilled /></el-icon> |
|||
<template #dropdown> |
|||
<el-dropdown-menu> |
|||
<el-dropdown-item @click="openCreateChildFormDialog(item)"><el-icon><DocumentAdd /></el-icon>新建子表单</el-dropdown-item> |
|||
<el-dropdown-item @click="openCreateChildGroupDialog(item)"><el-icon><FolderAdd /></el-icon>新建子分组</el-dropdown-item> |
|||
<el-dropdown-item @click="confirmDelete(item)"><el-icon><Delete /></el-icon>删除</el-dropdown-item> |
|||
<el-dropdown-item @click="showRenameDialog(item)"><el-icon><EditPen /></el-icon>修改名称</el-dropdown-item> |
|||
<el-dropdown-item @click="showMoveToDialog(item)"><el-icon><FolderRemove /></el-icon>移动到</el-dropdown-item> |
|||
</el-dropdown-menu> |
|||
</template> |
|||
</el-dropdown> |
|||
</div> |
|||
</template> |
|||
<template v-else-if="child.type === 'form'"> |
|||
<!-- 子表单模板 --> |
|||
<div class="menu-item-child"> |
|||
<span><el-icon><Document /></el-icon>{{ child.name }}</span> |
|||
<el-dropdown trigger="click" placement="bottom-end"> |
|||
<el-icon><MoreFilled /></el-icon> |
|||
<template #dropdown> |
|||
<el-dropdown-menu> |
|||
<el-dropdown-item @click="confirmDelete(item)"><el-icon><Delete /></el-icon>删除</el-dropdown-item> |
|||
<el-dropdown-item @click="showRenameDialog(item)"><el-icon><EditPen /></el-icon>修改名称</el-dropdown-item> |
|||
<el-dropdown-item @click="showMoveToDialog(item)"><el-icon><FolderRemove /></el-icon>移动到</el-dropdown-item> |
|||
</el-dropdown-menu> |
|||
</template> |
|||
</el-dropdown> |
|||
</div> |
|||
</template> |
|||
</li> |
|||
</ul> |
|||
</transition> |
|||
</li> |
|||
</template> |
|||
<!-- 表单 --> |
|||
<template v-else-if="item.type === 'form'"> |
|||
<!-- 表单模板 --> |
|||
<li :key="item.id" class="menu-item"> |
|||
<span><el-icon><Document /></el-icon>{{ item.name }}</span> |
|||
<el-dropdown trigger="click" placement="bottom-end"> |
|||
<el-icon><MoreFilled /></el-icon> |
|||
<template #dropdown> |
|||
<el-dropdown-menu> |
|||
<el-dropdown-item @click="confirmDelete(item)"><el-icon><Delete /></el-icon>删除</el-dropdown-item> |
|||
<el-dropdown-item @click="showRenameDialog(item)"><el-icon><EditPen /></el-icon>修改名称</el-dropdown-item> |
|||
<el-dropdown-item @click="showMoveToDialog(item)"><el-icon><FolderRemove /></el-icon>移动到</el-dropdown-item> |
|||
</el-dropdown-menu> |
|||
</template> |
|||
</el-dropdown> |
|||
</li> |
|||
</template> |
|||
</template> |
|||
</ul> |
|||
</div> |
|||
</el-aside> |
|||
<!-- 主要内容区域 --> |
|||
<el-main> |
|||
表单预览 |
|||
</el-main> |
|||
</el-container> |
|||
</div> |
|||
<!-- 新建表单对话框 --> |
|||
<el-dialog v-model="createFormVisible" title="新建表单" > |
|||
<el-form label-width="80px"> |
|||
<el-form-item label="表单名称"> |
|||
<el-input v-model="newFormName" /> |
|||
</el-form-item> |
|||
</el-form> |
|||
<div class="dialog-footer"> |
|||
<el-button @click="createFormVisible = false">取消</el-button> |
|||
<el-button type="primary" @click="saveNewForm">保存</el-button> |
|||
</div> |
|||
</el-dialog> |
|||
<!-- 新建分组对话框 --> |
|||
<el-dialog v-model="createGroupVisible" title="新建分组"> |
|||
<el-form label-width="80px"> |
|||
<el-form-item label="分组名称"> |
|||
<el-input v-model="newGroupName" /> |
|||
</el-form-item> |
|||
</el-form> |
|||
<div class="dialog-footer"> |
|||
<el-button @click="createGroupVisible = false">取消</el-button> |
|||
<el-button type="primary" @click="saveNewGroup">保存</el-button> |
|||
</div> |
|||
</el-dialog> |
|||
<!-- 修改名称对话框 --> |
|||
<el-dialog v-model="renameVisible" title="修改名称" @close="handleRenameClose"> |
|||
<el-form label-width="80px"> |
|||
<el-form-item label="名称"> |
|||
<el-input v-model="renameValue" /> |
|||
</el-form-item> |
|||
</el-form> |
|||
<div class="dialog-footer"> |
|||
<el-button @click="handleRenameCancel">取消</el-button> |
|||
<el-button type="primary" @click="handleRenameSave">保存</el-button> |
|||
</div> |
|||
</el-dialog> |
|||
<!-- 移动分组对话框 --> |
|||
<el-dialog |
|||
v-model="moveToVisible" |
|||
title="移动分组" |
|||
@close="handleMoveToClose"> |
|||
<el-select |
|||
v-model="selectedParentId" |
|||
placeholder="选择目标分组" |
|||
> |
|||
<el-option |
|||
v-for="(group, index) in menu.filter((m) => m.type === 'group' && m.id !== selectedGroupId)" |
|||
:key="index" |
|||
:label="group.name" |
|||
:value="group.id" |
|||
/> |
|||
</el-select> |
|||
<div class="dialog-footer"> |
|||
<el-button @click="handleMoveToCancel">取消</el-button> |
|||
<el-button type="primary" @click="handleMoveToSave">保存</el-button> |
|||
</div> |
|||
</el-dialog> |
|||
</template> |
|||
<style scoped> |
|||
.common-layout { |
|||
height: 100vh; |
|||
overflow: hidden; |
|||
} |
|||
.el-header { |
|||
height: 50px; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
} |
|||
/* 应用名称 */ |
|||
.header-input { |
|||
width: 100px; |
|||
margin-top: 10px; |
|||
} |
|||
/* 编辑表单按钮 */ |
|||
.header-btn{ |
|||
margin-top: 10px; |
|||
} |
|||
/* 侧边栏整体 */ |
|||
.el-aside { |
|||
background-color: #f5f7fa; |
|||
width: 250px; |
|||
min-height: 100vh; |
|||
display: flex; |
|||
flex-direction: column; |
|||
position: relative; |
|||
} |
|||
/* 侧边栏上部区域 */ |
|||
.sidebar-upper { |
|||
display: flex; |
|||
padding: 20px; |
|||
border-bottom: 1px solid #ebeef5; |
|||
} |
|||
/* 搜索框 */ |
|||
.search-input{ |
|||
width: 200px; |
|||
margin-right: 10px; |
|||
} |
|||
/* 新建按钮 */ |
|||
.add-btn{ |
|||
cursor: pointer; |
|||
height: 30px; |
|||
width: 30px; |
|||
margin-top: 2px; |
|||
} |
|||
/* 侧边栏下半部分菜单样式 */ |
|||
.sidebar-lower { |
|||
overflow-y: auto; |
|||
padding: 5px 0; |
|||
} |
|||
.sidebar-menu { |
|||
list-style: none; |
|||
margin: 0; |
|||
padding: 0; |
|||
} |
|||
/* 父分组/表单 */ |
|||
.menu-item { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
padding: 8px 16px; |
|||
font-size: 14px; |
|||
line-height: 1.5; |
|||
color: #222222; |
|||
cursor: pointer; |
|||
transition: background-color 0.2s ease; |
|||
} |
|||
.menu-item:hover, |
|||
.menu-item:focus { |
|||
background-color: #cacbcc; |
|||
} |
|||
/* 子分组/表单 */ |
|||
.menu-item-child{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
padding: 8px 16px 8px 35px; |
|||
font-size: 14px; |
|||
line-height: 1.5; |
|||
color: #222222; |
|||
cursor: pointer; |
|||
transition: background-color 0.2s ease; |
|||
} |
|||
.menu-item-child:hover, |
|||
.menu-item-child:focus { |
|||
background-color: #cacbcc; |
|||
} |
|||
/* 定义展开/折叠动画的通用样式 */ |
|||
.expand-collapse-enter-active, |
|||
.expand-collapse-leave-active { |
|||
transition: max-height 0.3s ease, opacity 0.3s ease; |
|||
overflow: hidden; |
|||
} |
|||
/* 定义展开动画 */ |
|||
.expand-collapse-enter-from { |
|||
max-height: 0; |
|||
opacity: 0; |
|||
} |
|||
/* 定义折叠动画 */ |
|||
.expand-collapse-leave-to { |
|||
max-height: 0; |
|||
opacity: 0; |
|||
} |
|||
/* 下拉菜单样式 */ |
|||
.el-dropdown-menu { |
|||
padding: 0; |
|||
min-width: 100px; |
|||
} |
|||
/* 表单预览 */ |
|||
.el-main { |
|||
flex: 1; |
|||
padding: 20px; |
|||
background-color: #ffffff; |
|||
} |
|||
/* 对话框样式 */ |
|||
.dialog-footer { |
|||
text-align:right; |
|||
margin-top: 20px; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,106 @@ |
|||
<!-- |
|||
@ 作者: 袁纪菲 |
|||
@ 时间: 2024.4.16 |
|||
@ 备注: 编辑应用 |
|||
--> |
|||
<script lang="ts" setup> |
|||
import { reactive, ref , computed } from 'vue' |
|||
import { ElMessage} from 'element-plus'; |
|||
|
|||
const props = defineProps({ |
|||
// eslint-disable-next-line vue/prop-name-casing |
|||
Visible:Boolean |
|||
}); |
|||
const emits = defineEmits(["update:Visible", "data"]); |
|||
//标签宽度 |
|||
const formLabelWidth = ref('140px') |
|||
const form = reactive({ |
|||
data: { |
|||
id: '', |
|||
name: '', |
|||
icon: '', |
|||
}, |
|||
visible: computed({ |
|||
get(){ |
|||
return props.Visible |
|||
}, |
|||
set(val) { |
|||
emits('update:Visible', val) |
|||
} |
|||
}) |
|||
}) |
|||
// 图片预览地址 |
|||
const previewImageUrl = ref<string>(''); //初始化为空字符串 |
|||
// 图片上传前的钩子函数 |
|||
const beforeUpload = (file: any) => { |
|||
const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'; |
|||
if (!isJPG) { |
|||
ElMessage.error('只能上传 JPG 或 PNG 格式的图片'); |
|||
return false; |
|||
} |
|||
const isLt2M = file.size / 1024 / 1024 < 2; |
|||
if (!isLt2M) { |
|||
ElMessage.error('图片大小不能超过 2MB'); |
|||
return false; |
|||
} |
|||
// 如果验证通过,则可以将本地图片转为 URL 显示预览 |
|||
const reader = new FileReader(); |
|||
reader.readAsDataURL(file); |
|||
reader.onload = (e: ProgressEvent<FileReader>) => { |
|||
if (e.target?.result) { |
|||
previewImageUrl.value = e.target.result as string; |
|||
form.data.icon = e.target.result as string;// 同样需要确保非null |
|||
} else { |
|||
// 处理读取失败的情况,例如: |
|||
previewImageUrl.value = ''; |
|||
ElMessage.error('无法预览图片,请重新上传'); |
|||
} |
|||
}; |
|||
return isJPG && isLt2M; |
|||
}; |
|||
//保存 |
|||
const submitForm = () => { |
|||
emits('data', form.data); // 发送更新后的卡片数据给父组件 |
|||
emits('update:Visible', false); // 关闭对话框 |
|||
}; |
|||
</script> |
|||
<template> |
|||
<div class="edit-container"> |
|||
<el-dialog |
|||
:model-value="props.Visible" |
|||
title="编辑应用" |
|||
width="500"> |
|||
<el-form :model="form"> |
|||
<el-form-item label="应用名称" :label-width="formLabelWidth"> |
|||
<el-input v-model="form.data.name" placeholder="请输入应用名称" autocomplete="off" /> |
|||
</el-form-item> |
|||
<el-form-item label="应用图标" :label-width=formLabelWidth> |
|||
<el-upload |
|||
class="picture-uploader" |
|||
action="" |
|||
:auto-upload="false" |
|||
:before-upload="beforeUpload" |
|||
list-type="picture-card"> |
|||
<i class="el-icon-plus"></i> |
|||
</el-upload> |
|||
<!-- 预览区域 --> |
|||
<div v-if="form.data.icon" class="preview-image"> |
|||
<img :src="form.data.icon" alt="预览图片" /> |
|||
</div> |
|||
</el-form-item> |
|||
</el-form> |
|||
<template #footer> |
|||
<div class="dialog-footer"> |
|||
<el-button @click="emits('update:Visible', false)">取消</el-button> |
|||
<el-button type="primary" @click="submitForm"> |
|||
保存 |
|||
</el-button> |
|||
</div> |
|||
</template> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<style scoped> |
|||
|
|||
</style> |
|||
@ -1,213 +1,251 @@ |
|||
<!-- |
|||
@ 作者: 袁纪菲 |
|||
@ 时间: 2024.3.18 |
|||
@ 备注: 应用管理父组件 |
|||
@ 时间: 2024.4.16 |
|||
@ 备注: 应用管理 |
|||
--> |
|||
<script lang = "ts" setup> |
|||
import cardedit from './cardedit.vue'; |
|||
import cardadd from './cardadd.vue'; |
|||
import {ref,onMounted,onUnmounted,watch} from 'vue'; |
|||
import {Delete,Edit,View,MoreFilled} from '@element-plus/icons-vue' |
|||
<script lang="ts" setup> |
|||
import editpage from './editpage.vue'; |
|||
import { ref , onMounted } from 'vue'; |
|||
import { useRouter } from 'vue-router'; |
|||
|
|||
// 弹窗状态 |
|||
const props = defineProps({ |
|||
visible:Boolean |
|||
}); |
|||
const drawerRefadd = ref(false); |
|||
const drawerRefedit = ref(false) |
|||
|
|||
// 卡片数据 |
|||
interface cardDatass { |
|||
id: number; |
|||
name: string; |
|||
imageUrl: '', |
|||
} |
|||
const cardData = ref<cardDatass[]>([]); |
|||
const emits = defineEmits(["update:visible", "data"]); |
|||
//添加 |
|||
const opencardadd = () => { |
|||
drawerRefadd.value = true; |
|||
cardadd.value.onSubmit = handleAddCard; |
|||
}; |
|||
// 新增卡片数据的接收与处理 |
|||
const handleAddCard = (newCard: cardDatass) => { |
|||
cardData.value.push(newCard); |
|||
//页面跳转 |
|||
const router = useRouter(); |
|||
const goToCreatePage = () => { |
|||
try { |
|||
router.push({ name: 'create' }); |
|||
} catch (error) { |
|||
console.error("导航到创建页面时发生错误:", error); |
|||
} |
|||
}; |
|||
//编辑 |
|||
const opencardedit = (index: number) => { |
|||
drawerRefedit.value = true; |
|||
// 将当前卡片的数据传给cardedit组件 |
|||
cardedit.value.cardData = cardData.value[index]; |
|||
cardedit.value.onSubmit = handleEditCard; |
|||
const dialogRefedit = ref(false); |
|||
interface cardDatas { |
|||
id: number; |
|||
name: string; |
|||
icon: string; |
|||
} |
|||
//初始化应用卡片数据 |
|||
const cardData = ref<cardDatas[]>([]); |
|||
const emits = defineEmits(["update:Visible", "data"]); |
|||
|
|||
onMounted(() => { |
|||
if (!cardData.value.length) { |
|||
for (let i = 0; i < 9; i++) { |
|||
cardData.value.push({ |
|||
id: i, |
|||
name: '标题' + i, |
|||
icon: 'https://img.zcool.cn/community/01f3fb5a66a75ea80120a123a9f582.jpg@2o.jpg' |
|||
}); |
|||
} |
|||
} |
|||
}); |
|||
//编辑应用 |
|||
const showEditPage = (index: number) => { |
|||
dialogRefedit.value = true; |
|||
editpage.value.cardData = cardData.value[index]; |
|||
editpage.value.onSubmit = handleEdit; |
|||
}; |
|||
// 编辑卡片数据的接收与处理 |
|||
const handleEditCard = (newCard: cardDatass) => { |
|||
cardData.value.splice(0,1,newCard); |
|||
//编辑应用数据的接受与处理 |
|||
const handleEdit = (newCard: cardDatas) => { |
|||
cardData.value.splice(0, 1, newCard); |
|||
}; |
|||
//删除 |
|||
//删除卡片 |
|||
const deleteCard = (index: number) => { |
|||
cardData.value.splice(index, 1); |
|||
emits('data', cardData.value); |
|||
cardData.value.splice(index, 1); |
|||
}; |
|||
//监听子组件发来的 'data' 事件 |
|||
watch(() => props.visible, () => { |
|||
}, |
|||
{ immediate: true } |
|||
); |
|||
// 监听子组件返回的新卡片数据 |
|||
const handleNewCard = (newCard: cardDatass) => { |
|||
cardData.value.push(newCard); |
|||
}; |
|||
|
|||
onMounted(() => { |
|||
for(let i = 0;i<9;i++){ |
|||
cardData.value.push({ |
|||
id: i, |
|||
name: '卡片' + i, |
|||
imageUrl: '' |
|||
}); |
|||
} |
|||
}); |
|||
</script> |
|||
<template> |
|||
<cardadd v-model:visible="drawerRefadd" :keyval="props.visible" @data="handleNewCard"/> |
|||
<cardedit v-model:visible="drawerRefedit" :keyval="props.visible" @data="handleNewCard"/> |
|||
<el-row :gutter="10"> |
|||
<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6"> |
|||
<div class="grid-content ep-bg-purple" > |
|||
<el-card class="cardlarge"> |
|||
<template #header> |
|||
<div class="cardhead-large"> |
|||
<el-row class="block-col-2"> |
|||
<el-col style="text-align: right;"> |
|||
<el-dropdown> |
|||
<span class="el-dropdown-link"> |
|||
<el-icon><MoreFilled /></el-icon> |
|||
</span> |
|||
<template #dropdown> |
|||
<el-dropdown-menu> |
|||
<el-dropdown-item @click="opencardadd" >添加</el-dropdown-item> |
|||
<el-dropdown-item >编辑</el-dropdown-item> |
|||
<el-dropdown-item >删除</el-dropdown-item> |
|||
</el-dropdown-menu> |
|||
</template> |
|||
</el-dropdown> |
|||
</el-col> |
|||
<el-col style="text-align: left;"> |
|||
<span>标题一</span> |
|||
</el-col> |
|||
</el-row> |
|||
</div> |
|||
</template> |
|||
<div class="grid-content ep-bg-purple" > |
|||
<el-row :gutter="10" > |
|||
<el-col v-for="(card, index) in cardData" :key="card.id" :xs="8" :sm="12" :md="8" :lg="8" :xl="8"> |
|||
<el-card class="cardpattern"> |
|||
<img |
|||
v-if="card.imageUrl" |
|||
src="card.imageUrl" |
|||
title="示例图片" |
|||
class="picture" |
|||
/> |
|||
<div class="cardhead"> |
|||
<span>{{ card.name }}</span> |
|||
</div> |
|||
<div class="bottom"> |
|||
<el-button size="small" circle class="button" :icon="View"></el-button> |
|||
<el-button size="small" circle class="button" :icon="Edit" @click="() => opencardedit(index)"></el-button> |
|||
<el-button size="small" circle class="button" :icon="Delete" @click="() => deleteCard(index)"></el-button> |
|||
</div> |
|||
</el-card> |
|||
</el-col> |
|||
</el-row> |
|||
</div> |
|||
</el-card> |
|||
</div> |
|||
</el-col> |
|||
</el-row> |
|||
|
|||
<!-- 分页 --> |
|||
<div class="example-pagination-block"> |
|||
<div class="example-demonstration"></div> |
|||
<el-pagination layout="prev, pager, next" :total="50" /> |
|||
<editpage v-model:Visible="dialogRefedit" @data="handleEdit" /> |
|||
<div class="common-layout"> |
|||
<el-container> |
|||
<el-container> |
|||
<el-main class="layout-content"> |
|||
<el-header class="content-header"> |
|||
<el-button class="create-btn" @click="goToCreatePage"> |
|||
<el-icon><Plus /></el-icon> |
|||
新建应用 |
|||
</el-button> |
|||
</el-header> |
|||
<el-main> |
|||
<el-scrollbar class="scrollbar"> |
|||
<div class="xiangying"> |
|||
<el-col v-for="(card) in cardData" :key="card.id"> |
|||
<el-card class="cardpattern" shadow="hover" > |
|||
<div class="button"> |
|||
<img :src="card.icon" class="picture" /> |
|||
<span>自定义卡片</span> |
|||
<el-icon class="star"> |
|||
<Star /> |
|||
</el-icon> |
|||
<el-dropdown class="xiala" trigger="click"> |
|||
<el-icon> |
|||
<MoreFilled /> |
|||
</el-icon> |
|||
<template #dropdown> |
|||
<el-dropdown-menu> |
|||
<el-dropdown-item @click = "() => showEditPage">编辑应用</el-dropdown-item> |
|||
<el-dropdown-item @click = "() => deleteCard">删除</el-dropdown-item> |
|||
</el-dropdown-menu> |
|||
</template> |
|||
</el-dropdown> |
|||
</div> |
|||
<div class="cardhead"> |
|||
<span>{{ card.name }}</span> |
|||
</div> |
|||
</el-card> |
|||
</el-col> |
|||
</div> |
|||
</el-scrollbar> |
|||
</el-main> |
|||
</el-main> |
|||
</el-container> |
|||
</el-container> |
|||
</div> |
|||
|
|||
</template> |
|||
<style scoped> |
|||
/* 小卡片 */ |
|||
.cardpattern{ |
|||
padding-bottom: 0px; |
|||
margin-bottom: 10px; |
|||
min-width: 100px; |
|||
.common-layout { |
|||
width: 100%; |
|||
height: 100%; |
|||
.el-container { |
|||
height: 100%; |
|||
/* 不折叠的时候宽度是200px,折叠的时候宽度自适应 */ |
|||
} |
|||
} |
|||
svg { |
|||
width: 1.5em; |
|||
margin-right: 5px; |
|||
} |
|||
.el-menu-vertical-demo:not(.el-menu--collapse) { |
|||
width: 200px; |
|||
min-height: 400px; |
|||
} |
|||
/* 小卡片标题 */ |
|||
.cardhead{ |
|||
padding: 10px; |
|||
font-size: 15px; |
|||
.el-aside { |
|||
width: auto; |
|||
} |
|||
/* 大卡片 */ |
|||
.cardlarge{ |
|||
max-width: 480px; |
|||
.el-menu-vertical-demo { |
|||
border-right: none; |
|||
margin-top: 0; |
|||
height: 100%; |
|||
background-color: #586177; |
|||
color: #fff; |
|||
} |
|||
/* 大卡片标题 */ |
|||
.cardhead-large{ |
|||
font-size: 20px; |
|||
.el-menu-item { |
|||
color: #ffffff; |
|||
} |
|||
|
|||
/* 按钮整体 */ |
|||
.bottom { |
|||
margin-top: 20px; |
|||
line-height: 10px; |
|||
/* 侧边栏标题 */ |
|||
.side-header { |
|||
height: 64px; |
|||
padding: 0; |
|||
display: flex; |
|||
justify-content: space-evenly; |
|||
align-items: center; |
|||
|
|||
justify-content: center; |
|||
} |
|||
/* 单个按钮 */ |
|||
.button { |
|||
padding: 0px; |
|||
min-height: auto; |
|||
margin-bottom: 1px; |
|||
/* 右侧上方标题 */ |
|||
.up-header { |
|||
display: flex; |
|||
align-items : center; |
|||
justify-content:left; |
|||
background-color: #fff; |
|||
padding: 0; |
|||
} |
|||
/* 图片 */ |
|||
.picture { |
|||
height: 100%; |
|||
min-height: 50px; |
|||
max-height: 100px; |
|||
display: block; |
|||
width: 100%; |
|||
min-width: 50px; |
|||
/* 缩放侧边栏按钮 */ |
|||
.trigger { |
|||
font-size: 18px; |
|||
line-height: 64px; |
|||
padding: 0 24px; |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.el-col { |
|||
border-radius: 4px; |
|||
.el-main { |
|||
overflow-y: auto; |
|||
padding-right: 0; /* 取消内外边距以免影响滚动区域 */ |
|||
} |
|||
|
|||
.grid-content { |
|||
border-radius: 4px; |
|||
min-height: 36px; |
|||
/* 内容框 */ |
|||
.layout-content{ |
|||
padding: 15px; |
|||
background: #f5f5f5; |
|||
min-height: 280px; |
|||
} |
|||
|
|||
.app_box{ |
|||
margin: 15px 0 0 0px; |
|||
/* 新建按钮框 */ |
|||
.content-header { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
text-align: right; |
|||
font-size: 12px; |
|||
height: 40px; |
|||
} |
|||
|
|||
.block-col-2 .demonstration { |
|||
display: block; |
|||
color: var(--el-text-color-secondary); |
|||
font-size: 14px; |
|||
margin-bottom: 20px; |
|||
/* 新建按钮 */ |
|||
.create-btn { |
|||
margin-right: 10px; |
|||
background-color: #1090ff; |
|||
color: #ffffff; |
|||
} |
|||
/* 卡片整体所在区域 */ |
|||
.scrollbar{ |
|||
height: 700px; |
|||
overflow-y: auto; /* 自动显示垂直滚动条 */ |
|||
margin-right: 10px; |
|||
box-sizing: border-box; /* 保证高度计算包含内边距和边框 */ |
|||
|
|||
/* 当内容不够一屏时,禁用滚动条 */ |
|||
&::-webkit-scrollbar { |
|||
width: 0; |
|||
height: 0; |
|||
} |
|||
} |
|||
/* 内容部分卡片响应式 */ |
|||
.xiangying { |
|||
display: grid; |
|||
grid-auto-rows: minmax(160px, auto); /* 或者指定最大高度 */ |
|||
grid-gap: 1px; |
|||
grid-template-columns: repeat(auto-fit, 230px); |
|||
overflow-y: auto; /* 添加此行以允许卡片区域内部内容滚动 */ |
|||
} |
|||
/* 卡片 */ |
|||
.cardpattern { |
|||
padding: 0px; |
|||
margin-bottom: 10px; |
|||
width: 220px; |
|||
height: 150px; |
|||
transition: all 0.3s ease; |
|||
} |
|||
|
|||
.block-col-2 .el-dropdown-link { |
|||
display: flex; |
|||
align-items: center; |
|||
/* 卡片标题 */ |
|||
.cardhead { |
|||
margin-top: 50px; |
|||
font-size: 18px; |
|||
color: #000000; |
|||
font-weight: 500; |
|||
text-align: left; |
|||
font-family: PingFangSC-Regular; |
|||
line-height: 20px; |
|||
} |
|||
/* 收藏按钮与下拉框区域 */ |
|||
.button { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
margin-top: 3px; |
|||
} |
|||
/* 分页 */ |
|||
.example-pagination-block + .example-pagination-block { |
|||
margin-top: 10px; |
|||
/* 收藏按钮 */ |
|||
.star { |
|||
font-size: 20px; |
|||
margin-right: -5px; |
|||
} |
|||
.example-pagination-block .example-demonstration { |
|||
margin-bottom: 16px; |
|||
|
|||
/* 占位元素 */ |
|||
.placeholder { |
|||
height:14px; |
|||
/* 设置为图标按钮组的高度 */ |
|||
width:100%; |
|||
/* 设置为图标按钮组的宽度 */ |
|||
visibility: hidden; |
|||
/* 或者 opacity: 0; 保证不会影响布局但不可见 */ |
|||
pointer-events: none; |
|||
/* 防止此元素捕获鼠标事件 */ |
|||
} |
|||
/* 图片 */ |
|||
.picture { |
|||
width: 3cap; |
|||
margin: 1px; |
|||
} |
|||
|
|||
</style> |
|||
|
|||
@ -0,0 +1,213 @@ |
|||
<!-- |
|||
@ 作者: 袁纪菲 |
|||
@ 时间: 2024.3.18 |
|||
@ 备注: 应用管理父组件 |
|||
--> |
|||
<script lang = "ts" setup> |
|||
import cardedit from './cardedit.vue'; |
|||
import cardadd from './cardadd.vue'; |
|||
import {ref,onMounted,onUnmounted,watch} from 'vue'; |
|||
import {Delete,Edit,View,MoreFilled} from '@element-plus/icons-vue' |
|||
|
|||
// 弹窗状态 |
|||
const props = defineProps({ |
|||
visible:Boolean |
|||
}); |
|||
const drawerRefadd = ref(false); |
|||
const drawerRefedit = ref(false) |
|||
|
|||
// 卡片数据 |
|||
interface cardDatass { |
|||
id: number; |
|||
name: string; |
|||
imageUrl: '', |
|||
} |
|||
const cardData = ref<cardDatass[]>([]); |
|||
const emits = defineEmits(["update:visible", "data"]); |
|||
//添加 |
|||
const opencardadd = () => { |
|||
drawerRefadd.value = true; |
|||
cardadd.value.onSubmit = handleAddCard; |
|||
}; |
|||
// 新增卡片数据的接收与处理 |
|||
const handleAddCard = (newCard: cardDatass) => { |
|||
cardData.value.push(newCard); |
|||
}; |
|||
//编辑 |
|||
const opencardedit = (index: number) => { |
|||
drawerRefedit.value = true; |
|||
// 将当前卡片的数据传给cardedit组件 |
|||
cardedit.value.cardData = cardData.value[index]; |
|||
cardedit.value.onSubmit = handleEditCard; |
|||
}; |
|||
// 编辑卡片数据的接收与处理 |
|||
const handleEditCard = (newCard: cardDatass) => { |
|||
cardData.value.splice(0,1,newCard); |
|||
}; |
|||
//删除 |
|||
const deleteCard = (index: number) => { |
|||
cardData.value.splice(index, 1); |
|||
emits('data', cardData.value); |
|||
}; |
|||
//监听子组件发来的 'data' 事件 |
|||
watch(() => props.visible, () => { |
|||
}, |
|||
{ immediate: true } |
|||
); |
|||
// 监听子组件返回的新卡片数据 |
|||
const handleNewCard = (newCard: cardDatass) => { |
|||
cardData.value.push(newCard); |
|||
}; |
|||
|
|||
onMounted(() => { |
|||
for(let i = 0;i<9;i++){ |
|||
cardData.value.push({ |
|||
id: i, |
|||
name: '卡片' + i, |
|||
imageUrl: '' |
|||
}); |
|||
} |
|||
}); |
|||
</script> |
|||
<template> |
|||
<cardadd v-model:visible="drawerRefadd" :keyval="props.visible" @data="handleNewCard"/> |
|||
<cardedit v-model:visible="drawerRefedit" :keyval="props.visible" @data="handleNewCard"/> |
|||
<el-row :gutter="10"> |
|||
<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6"> |
|||
<div class="grid-content ep-bg-purple" > |
|||
<el-card class="cardlarge"> |
|||
<template #header> |
|||
<div class="cardhead-large"> |
|||
<el-row class="block-col-2"> |
|||
<el-col style="text-align: right;"> |
|||
<el-dropdown> |
|||
<span class="el-dropdown-link"> |
|||
<el-icon><MoreFilled /></el-icon> |
|||
</span> |
|||
<template #dropdown> |
|||
<el-dropdown-menu> |
|||
<el-dropdown-item @click="opencardadd" >添加</el-dropdown-item> |
|||
<el-dropdown-item >编辑</el-dropdown-item> |
|||
<el-dropdown-item >删除</el-dropdown-item> |
|||
</el-dropdown-menu> |
|||
</template> |
|||
</el-dropdown> |
|||
</el-col> |
|||
<el-col style="text-align: left;"> |
|||
<span>标题一</span> |
|||
</el-col> |
|||
</el-row> |
|||
</div> |
|||
</template> |
|||
<div class="grid-content ep-bg-purple" > |
|||
<el-row :gutter="10" > |
|||
<el-col v-for="(card, index) in cardData" :key="card.id" :xs="8" :sm="12" :md="8" :lg="8" :xl="8"> |
|||
<el-card class="cardpattern"> |
|||
<img |
|||
v-if="card.imageUrl" |
|||
src="card.imageUrl" |
|||
title="示例图片" |
|||
class="picture" |
|||
/> |
|||
<div class="cardhead"> |
|||
<span>{{ card.name }}</span> |
|||
</div> |
|||
<div class="bottom"> |
|||
<el-button size="small" circle class="button" :icon="View"></el-button> |
|||
<el-button size="small" circle class="button" :icon="Edit" @click="() => opencardedit(index)"></el-button> |
|||
<el-button size="small" circle class="button" :icon="Delete" @click="() => deleteCard(index)"></el-button> |
|||
</div> |
|||
</el-card> |
|||
</el-col> |
|||
</el-row> |
|||
</div> |
|||
</el-card> |
|||
</div> |
|||
</el-col> |
|||
</el-row> |
|||
|
|||
<!-- 分页 --> |
|||
<div class="example-pagination-block"> |
|||
<div class="example-demonstration"></div> |
|||
<el-pagination layout="prev, pager, next" :total="50" /> |
|||
</div> |
|||
|
|||
</template> |
|||
<style scoped> |
|||
/* 小卡片 */ |
|||
.cardpattern{ |
|||
padding-bottom: 0px; |
|||
margin-bottom: 10px; |
|||
min-width: 100px; |
|||
} |
|||
/* 小卡片标题 */ |
|||
.cardhead{ |
|||
padding: 10px; |
|||
font-size: 15px; |
|||
} |
|||
/* 大卡片 */ |
|||
.cardlarge{ |
|||
max-width: 480px; |
|||
} |
|||
/* 大卡片标题 */ |
|||
.cardhead-large{ |
|||
font-size: 20px; |
|||
} |
|||
|
|||
/* 按钮整体 */ |
|||
.bottom { |
|||
margin-top: 20px; |
|||
line-height: 10px; |
|||
display: flex; |
|||
justify-content: space-evenly; |
|||
align-items: center; |
|||
|
|||
} |
|||
/* 单个按钮 */ |
|||
.button { |
|||
padding: 0px; |
|||
min-height: auto; |
|||
margin-bottom: 1px; |
|||
} |
|||
/* 图片 */ |
|||
.picture { |
|||
height: 100%; |
|||
min-height: 50px; |
|||
max-height: 100px; |
|||
display: block; |
|||
width: 100%; |
|||
min-width: 50px; |
|||
} |
|||
|
|||
.el-col { |
|||
border-radius: 4px; |
|||
} |
|||
|
|||
.grid-content { |
|||
border-radius: 4px; |
|||
min-height: 36px; |
|||
} |
|||
|
|||
.app_box{ |
|||
margin: 15px 0 0 0px; |
|||
} |
|||
|
|||
.block-col-2 .demonstration { |
|||
display: block; |
|||
color: var(--el-text-color-secondary); |
|||
font-size: 14px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.block-col-2 .el-dropdown-link { |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
/* 分页 */ |
|||
.example-pagination-block + .example-pagination-block { |
|||
margin-top: 10px; |
|||
} |
|||
.example-pagination-block .example-demonstration { |
|||
margin-bottom: 16px; |
|||
} |
|||
</style> |
|||
Loading…
Reference in new issue