优化列表,下一步,优化接口操作!
This commit is contained in:
parent
3d5b72aea1
commit
f4196e3e88
@ -7,6 +7,9 @@ html, body {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
:root{
|
||||||
|
--resizable-content-width: 300px; /* 默认值,会被 JS 覆盖 */
|
||||||
|
}
|
||||||
a {
|
a {
|
||||||
/*去除默认下划线*/
|
/*去除默认下划线*/
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "star-blog"; /* Project id 4905744 */
|
font-family: "star-blogIconFont"; /* Project id 4905744 */
|
||||||
src: url('iconfont.woff2?t=1745569316996') format('woff2'),
|
src: url('iconfont.woff2?t=1745569316996') format('woff2'),
|
||||||
url('iconfont.woff?t=1745569316996') format('woff'),
|
url('iconfont.woff?t=1745569316996') format('woff'),
|
||||||
url('iconfont.ttf?t=1745569316996') format('truetype');
|
url('iconfont.ttf?t=1745569316996') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.star-blogIconFont {
|
.star-blogIconFont {
|
||||||
font-family: "star-blog" !important;
|
font-family: "star-blogIconFont" !important;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
|
272
components/Home/Blog/Menu.vue
Normal file
272
components/Home/Blog/Menu.vue
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps({
|
||||||
|
status:{
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
blogMenuList:{
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 菜单折叠状态
|
||||||
|
const menuCollapseStatus = ref(props.status)
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
menuCollapseStatus.value = props.status
|
||||||
|
})
|
||||||
|
const emit = defineEmits(['createBlogMenu', "update:status", "collapseChildren"])
|
||||||
|
|
||||||
|
// 改变菜单展开状态
|
||||||
|
const handleMenuCollapseStatusChange = () => {
|
||||||
|
emit('update:status', !props.status)
|
||||||
|
}
|
||||||
|
// 展开/关闭子菜单
|
||||||
|
const handleCollapseChildrenEvent = (item, index) => {
|
||||||
|
item.childrenLength && emit('collapseChildren', item, index)
|
||||||
|
}
|
||||||
|
// 创建blog菜单
|
||||||
|
const handleCreateBlogMenuItemEvent = (pid: string) => {
|
||||||
|
emit('createBlogMenu', pid)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="homeBlogMenu">
|
||||||
|
<Transition name="blogmenu">
|
||||||
|
<ResizeContent v-if="menuCollapseStatus">
|
||||||
|
<div class="blogMenuContainer">
|
||||||
|
<header class="contentBox">
|
||||||
|
<div class="title"><div class="oneLineOverMore">博客目录</div></div>
|
||||||
|
<div class="headerBarContainer awaitShow">
|
||||||
|
<div class="bar star-blogIconFont a11 allCenter" @click="handleCreateBlogMenuItemEvent('0')"></div>
|
||||||
|
<div class="bar star-blogIconFont a11 allCenter" @click="handleMenuCollapseStatusChange"></div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div class="line"/>
|
||||||
|
<div class="blogMenuContent">
|
||||||
|
<div class="contentBox blogMenuItem" v-for="(item, index) in blogMenuList" :key="item.id">
|
||||||
|
<div :style="{width: item.rank * 1.4 + 'rem'}"></div>
|
||||||
|
<div class="textIcon"
|
||||||
|
:class="item.childrenLength && 'haveChildren'"
|
||||||
|
@click="handleCollapseChildrenEvent(item, index)"
|
||||||
|
>
|
||||||
|
<div class=" bar a11 allCenter star-blogIconFont"></div>
|
||||||
|
<div class=" bar a11 allCenter sxIconFont" :class="item.open && 'open'"><div></div></div>
|
||||||
|
</div>
|
||||||
|
<div class="text"><div class="oneLineOverMore">{{item.name}}</div></div>
|
||||||
|
<div class="barBox" :class="item.pid === '0' && 'awaistShows'">
|
||||||
|
<div class="star-blogIconFont bar a11 allCenter" @click="handleCreateBlogMenuItemEvent(item.id)"></div>
|
||||||
|
<div class="star-blogIconFont bar a11 allCenter"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer></footer>
|
||||||
|
</div>
|
||||||
|
</ResizeContent>
|
||||||
|
</Transition>
|
||||||
|
<div :class="!menuCollapseStatus && 'menuCollapse'">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
// 动画
|
||||||
|
.blogmenu-enter-active, .blogmenu-leave-active {
|
||||||
|
transition: width .3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blogmenu-enter-from, .blogmenu-leave-to {
|
||||||
|
width: 0px;
|
||||||
|
}
|
||||||
|
.homeBlogMenu{
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes textIconEntry {
|
||||||
|
0%{
|
||||||
|
color: #00000000;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
50%{
|
||||||
|
color: #00000000;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
100%{
|
||||||
|
color: var(--font-color-top3-h2);
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes textIconLeave {
|
||||||
|
0%{
|
||||||
|
color: var(--font-color-top3-h2);
|
||||||
|
}
|
||||||
|
50%{
|
||||||
|
color: #00000000;
|
||||||
|
}
|
||||||
|
100%{
|
||||||
|
color: #00000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.blogMenuContainer{
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
font-family: sans-serif;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: .5rem;
|
||||||
|
|
||||||
|
// 行容器
|
||||||
|
.contentBox{
|
||||||
|
position: relative;
|
||||||
|
height: 2rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: .2rem .5rem;
|
||||||
|
border-radius: .25rem;
|
||||||
|
color: var(--font-color-top3-h2);
|
||||||
|
user-select: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color .3s;
|
||||||
|
&:hover{
|
||||||
|
background: var(--font-color-top3-hover);
|
||||||
|
}
|
||||||
|
&.active{
|
||||||
|
color: var(--font-color-top3-h1);
|
||||||
|
background: var(--font-color-top3-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// 按钮
|
||||||
|
.bar{
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 100%;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--font-color-top3-h2);
|
||||||
|
transition: color .3s, background-color .3s;
|
||||||
|
border-radius: .25rem;
|
||||||
|
&:hover{
|
||||||
|
background-color: #00000015;
|
||||||
|
color: var(--font-color-top3-h1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 进入容器才显示
|
||||||
|
.awaitShow{
|
||||||
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity .3s;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
&:hover{
|
||||||
|
.awaitShow{
|
||||||
|
height: 100%;
|
||||||
|
width: auto;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.blogMenuContainer > header{
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
& > div.title{
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
color: var(--font-color-top3-h1);
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
& > div.headerBarContainer{
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
& > div.bar:last-child{
|
||||||
|
transform: rotate(180deg);
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.blogMenuContainer > div.line{
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
margin: 0.5rem auto;
|
||||||
|
background-color: var(--bg-color-be);
|
||||||
|
}
|
||||||
|
.blogMenuContainer > div.blogMenuContent{
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
& > div.blogMenuItem{
|
||||||
|
position: relative;
|
||||||
|
font-size: 1rem;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
& > div.textIcon{
|
||||||
|
position: relative;
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-right: .5rem;
|
||||||
|
& > div:last-child{
|
||||||
|
position: absolute;
|
||||||
|
top:0;
|
||||||
|
left: 0;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transform: rotate(0);
|
||||||
|
& > div{
|
||||||
|
transition: transform .3s ease-in-out;
|
||||||
|
}
|
||||||
|
&.open{
|
||||||
|
& > div{
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& > div.text{
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;// 关键
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
& > div.barBox{
|
||||||
|
margin-left: .2rem;
|
||||||
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
opacity: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
transition: opacity .3s;
|
||||||
|
& > div.bar{
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover{
|
||||||
|
& > div.barBox{
|
||||||
|
height: 100% !important;
|
||||||
|
width: auto !important;
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
& > div.textIcon.haveChildren> div{
|
||||||
|
&:first-child{
|
||||||
|
animation: textIconLeave .3s linear forwards;
|
||||||
|
}
|
||||||
|
&:last-child{
|
||||||
|
animation: textIconEntry .3s linear forwards;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -6,7 +6,7 @@ import { ref, onMounted, onBeforeUnmount } from 'vue'
|
|||||||
// 响应式数据
|
// 响应式数据
|
||||||
// =====================
|
// =====================
|
||||||
const resizableElement = ref(null) // 元素引用
|
const resizableElement = ref(null) // 元素引用
|
||||||
const width = ref(240) // 显示的宽度值
|
const width = ref(0) // 显示的宽度值
|
||||||
const isDragging = ref(false) // 拖拽状态标识
|
const isDragging = ref(false) // 拖拽状态标识
|
||||||
const startX = ref(0) // 拖拽起始X坐标
|
const startX = ref(0) // 拖拽起始X坐标
|
||||||
const startWidth = ref(0) // 拖拽起始宽度
|
const startWidth = ref(0) // 拖拽起始宽度
|
||||||
@ -45,12 +45,16 @@ const handleDrag = (e) => {
|
|||||||
const clampedWidth = Math.max(100, newWidth)
|
const clampedWidth = Math.max(100, newWidth)
|
||||||
|
|
||||||
// 优化:直接操作 CSS 变量减少响应式更新
|
// 优化:直接操作 CSS 变量减少响应式更新
|
||||||
resizableElement.value.style.setProperty('--width', `${clampedWidth}px`)
|
setRootPropertyValue(clampedWidth)
|
||||||
|
|
||||||
// 低频更新响应式数据(用于显示数值)
|
// 低频更新响应式数据(用于显示数值)
|
||||||
width.value = clampedWidth
|
width.value = clampedWidth
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
function setRootPropertyValue(value){
|
||||||
|
const root = document.documentElement; // 获取根元素
|
||||||
|
root.style.setProperty('--resizable-content-width', `${value}px`)
|
||||||
|
}
|
||||||
|
|
||||||
const stopDrag = () => {
|
const stopDrag = () => {
|
||||||
isDragging.value = false
|
isDragging.value = false
|
||||||
@ -67,7 +71,10 @@ const stopDrag = () => {
|
|||||||
// =====================
|
// =====================
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 初始化 CSS 变量
|
// 初始化 CSS 变量
|
||||||
resizableElement.value.style.setProperty('--width', `${width.value}px`)
|
// 获取CSS变量的值
|
||||||
|
const root = document.documentElement; // 获取根元素
|
||||||
|
const resizableContentWidth = getComputedStyle(root).getPropertyValue('--resizable-content-width').trim();
|
||||||
|
width.value = Number(resizableContentWidth.split('px')[0])
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
@ -77,41 +84,41 @@ onBeforeUnmount(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="resizable-element" :style="{ '--width': width + 'px' }" ref="resizableElement">
|
<div class="resizableContent" ref="resizableElement">
|
||||||
<slot/>
|
<slot/>
|
||||||
<!-- 拖拽手柄(支持触摸事件) -->
|
<!-- 拖拽手柄(支持触摸事件) -->
|
||||||
<div class="dargContainer">
|
<div class="dargContainer" @mousedown="startDrag" @touchstart.passive="startDrag">
|
||||||
<div class="dargBar" @mousedown="startDrag" @touchstart.passive="startDrag"/>
|
<div class="dargBar"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
.resizable-element {
|
.resizableContent {
|
||||||
--width: 300px; /* 默认值,会被 JS 覆盖 */
|
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: #f8f9fa;
|
background: #f8f9fa;
|
||||||
width: var(--width);
|
width: var(--resizable-content-width);
|
||||||
transition: width 0.15s ease; /* 平滑过渡效果 */
|
transition: width 0.15s ease; /* 平滑过渡效果 */
|
||||||
will-change: width; /* 提示浏览器优化重绘 */
|
will-change: width; /* 提示浏览器优化重绘 */
|
||||||
}
|
}
|
||||||
.dargContainer{
|
.dargContainer{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 6px;
|
width: 10px;
|
||||||
height: calc(100% - 10px);
|
height: calc(100% - 10px);
|
||||||
right: 0;
|
right: -5px;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
margin: auto 0;
|
margin: auto 0;
|
||||||
|
z-index: 1;
|
||||||
|
cursor: col-resize;
|
||||||
}
|
}
|
||||||
.dargBar {
|
.dargBar {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 2px;
|
width: 2px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
cursor: col-resize;
|
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
background: #00000000;
|
background: #00000000;
|
||||||
|
@ -13,9 +13,13 @@ definePageMeta({
|
|||||||
})
|
})
|
||||||
// 菜单数据类型
|
// 菜单数据类型
|
||||||
type InsertBlogMenu = typeof blogMenu.$inferInsert;
|
type InsertBlogMenu = typeof blogMenu.$inferInsert;
|
||||||
// 菜单数据
|
// 菜单原始数据
|
||||||
const originalBlogMenuLis = shallowRef([])
|
const originalBlogMenuLis = shallowRef([])
|
||||||
|
// 根据pid存储列表Map
|
||||||
const blogMenuPidMap = ref(new Map)
|
const blogMenuPidMap = ref(new Map)
|
||||||
|
// 根据id存储对象Map
|
||||||
|
const blogMenuIdMap = ref(new Map)
|
||||||
|
// blog渲染列表
|
||||||
const blogMenuList = ref<InsertBlogMenu[]>([]);
|
const blogMenuList = ref<InsertBlogMenu[]>([]);
|
||||||
// blog菜单对象
|
// blog菜单对象
|
||||||
const blogMenuObject = ref<InsertBlogMenu>(null);
|
const blogMenuObject = ref<InsertBlogMenu>(null);
|
||||||
@ -26,6 +30,8 @@ const blogInfoPopupStatus = ref(false)
|
|||||||
|
|
||||||
// 格式化菜单数据
|
// 格式化菜单数据
|
||||||
const formatBlogMenuListToPidMap = (blogMenuList: Array<InsertBlogMenu>) => {
|
const formatBlogMenuListToPidMap = (blogMenuList: Array<InsertBlogMenu>) => {
|
||||||
|
const idMap = new Map()
|
||||||
|
const pidMap = new Map()
|
||||||
const list = clone(blogMenuList)
|
const list = clone(blogMenuList)
|
||||||
const pidObj: Record<string, InsertBlogMenu[]> = {};
|
const pidObj: Record<string, InsertBlogMenu[]> = {};
|
||||||
for(const menuItem of list){
|
for(const menuItem of list){
|
||||||
@ -34,10 +40,22 @@ const formatBlogMenuListToPidMap = (blogMenuList: Array<InsertBlogMenu>) => {
|
|||||||
}else{
|
}else{
|
||||||
pidObj[menuItem.pid] = [menuItem]
|
pidObj[menuItem.pid] = [menuItem]
|
||||||
}
|
}
|
||||||
|
if(menuItem.pid == 0){
|
||||||
|
menuItem.rank = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(const menuItem of list){
|
||||||
|
const id = menuItem.id;
|
||||||
|
if(pidObj[id]){
|
||||||
|
menuItem.childrenLength = pidObj[id].length
|
||||||
|
}
|
||||||
|
idMap.set(id, menuItem)
|
||||||
}
|
}
|
||||||
Object.keys(pidObj).forEach(key => {
|
Object.keys(pidObj).forEach(key => {
|
||||||
blogMenuPidMap.value.set(key, pidObj[key]);
|
pidMap.set(key, pidObj[key]);
|
||||||
})
|
})
|
||||||
|
blogMenuPidMap.value = pidMap
|
||||||
|
blogMenuIdMap.value = idMap
|
||||||
}
|
}
|
||||||
// 获取blog菜单数据
|
// 获取blog菜单数据
|
||||||
const getMenuListFetch = async () => {
|
const getMenuListFetch = async () => {
|
||||||
@ -49,6 +67,20 @@ const getMenuListFetch = async () => {
|
|||||||
formatBlogMenuListToPidMap(data.value);
|
formatBlogMenuListToPidMap(data.value);
|
||||||
blogMenuList.value = blogMenuPidMap.value.get('0')
|
blogMenuList.value = blogMenuPidMap.value.get('0')
|
||||||
}
|
}
|
||||||
|
// 展开/关闭子菜单事件
|
||||||
|
const handleCollapseChildrenEvent = (item, index) => {
|
||||||
|
if(item.open == true){
|
||||||
|
blogMenuIdMap.value.get(item.id).open = false;
|
||||||
|
blogMenuList.value.splice(index + 1, item.childrenLength);
|
||||||
|
}else{
|
||||||
|
blogMenuIdMap.value.get(item.id).open = true;
|
||||||
|
const childrenList = blogMenuPidMap.value.get(item.id)
|
||||||
|
blogMenuList.value.splice(index + 1, 0, ...childrenList.map(i => {
|
||||||
|
i.rank = item.rank + 1;
|
||||||
|
return i
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
// 新增blog事件
|
// 新增blog事件
|
||||||
const handleCreateBlogMenuItemEvent = (pid: string) => {
|
const handleCreateBlogMenuItemEvent = (pid: string) => {
|
||||||
blogMenuObject.value = {
|
blogMenuObject.value = {
|
||||||
@ -77,27 +109,12 @@ onMounted(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="homeBlog">
|
<div class="homeBlog">
|
||||||
<ResizeContent class="left" :class="!menuCollapseStatus && 'menuCollapse'">
|
<HomeBlogMenu
|
||||||
<div class="blogMenuContainer">
|
class="left"
|
||||||
<header class="contentBox">
|
v-model:status="menuCollapseStatus"
|
||||||
<div class="title">博客目录</div>
|
:blogMenuList
|
||||||
<div class="bar add star-blogIconFont awaitShow a11 allCenter" @click="handleCreateBlogMenuItemEvent('0')"></div>
|
@createBlogMenu="handleCreateBlogMenuItemEvent"
|
||||||
<div class="bar star-blogIconFont awaitShow a11 allCenter" @click="menuCollapseStatus = !menuCollapseStatus"></div>
|
@collapseChildren="handleCollapseChildrenEvent"></HomeBlogMenu>
|
||||||
</header>
|
|
||||||
<div class="line"/>
|
|
||||||
<div class="blogMenuContent">
|
|
||||||
<div class="contentBox blogMenuItem" v-for="(item, index) in blogMenuList" :key="item.id">
|
|
||||||
<div class="addIcon star-blogIconFont a11 allCenter"></div>
|
|
||||||
<div class="text"><div class="oneLineOverMore">{{item.name}}</div></div>
|
|
||||||
<div class="barBox" :class="item.pid === '0' && 'awaistShows'">
|
|
||||||
<div class="star-blogIconFont bar a11 allCenter" @click="handleCreateBlogMenuItemEvent(item.pid)"></div>
|
|
||||||
<div class="star-blogIconFont bar a11 allCenter"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer></footer>
|
|
||||||
</div>
|
|
||||||
</ResizeContent>
|
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<header>
|
<header>
|
||||||
<div class="menuCollapse a11 allCenter point" :class="menuCollapseStatus && 'hide'">
|
<div class="menuCollapse a11 allCenter point" :class="menuCollapseStatus && 'hide'">
|
||||||
@ -135,161 +152,23 @@ onMounted(() => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
& > div{
|
& > div.left{
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
background: var(--blog-menu-background-color);
|
||||||
|
border-right: 1px solid var(--bg-color-be);
|
||||||
|
}
|
||||||
|
& > div.right{
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
|
||||||
& > div.left{
|
|
||||||
flex-shrink: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
background: var(--blog-menu-background-color);
|
|
||||||
border-right: 1px solid var(--bg-color-be);
|
|
||||||
transition: width .3s ease-in-out;
|
|
||||||
&.menuCollapse{
|
|
||||||
width: 0;
|
|
||||||
}
|
|
||||||
.bar{
|
|
||||||
position: relative;
|
|
||||||
flex-shrink: 0;
|
|
||||||
height: 100%;
|
|
||||||
font-size: 1rem;
|
|
||||||
opacity: 0;
|
|
||||||
color: var(--font-color-top3-h2);
|
|
||||||
transform: rotate(180deg);
|
|
||||||
transition: color .3s, opacity .3s, background-color .3s;
|
|
||||||
border-radius: .25rem;
|
|
||||||
&:hover{
|
|
||||||
background-color: #00000015;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.awaitShow{
|
|
||||||
height: 0;
|
|
||||||
width: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity .3s;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
&:hover{
|
|
||||||
.awaitShow{
|
|
||||||
height: 100%;
|
|
||||||
width: auto;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.blogMenuContainer{
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
font-family: sans-serif;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: .5rem;
|
|
||||||
& > *{
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
& > header{
|
|
||||||
flex-shrink: 0;
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
& > div.title{
|
|
||||||
position: relative;
|
|
||||||
flex: 1;
|
|
||||||
color: var(--font-color-top3-h1);
|
|
||||||
}
|
|
||||||
|
|
||||||
& > div.bar{
|
|
||||||
&:last-child{
|
|
||||||
font-size: 1.3rem;
|
|
||||||
}
|
|
||||||
&:hover{
|
|
||||||
color: var(--font-color-top3-h1);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
& > footer{
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
& > div.line{
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
height: 1px;
|
|
||||||
margin: 0.5rem auto;
|
|
||||||
background-color: var(--bg-color-be);
|
|
||||||
}
|
|
||||||
& > div.blogMenuContent{
|
|
||||||
position: relative;
|
|
||||||
flex: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
& > div.blogMenuItem{
|
|
||||||
position: relative;
|
|
||||||
font-size: 1rem;
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
& > div.addIcon{
|
|
||||||
position: relative;
|
|
||||||
font-size: 1rem;
|
|
||||||
margin-right: .5rem;
|
|
||||||
}
|
|
||||||
& > div.text{
|
|
||||||
position: relative;
|
|
||||||
flex: 1;
|
|
||||||
min-width: 0;// 关键
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
& > div.barBox{
|
|
||||||
margin-left: .2rem;
|
|
||||||
height: 0;
|
|
||||||
width: 0;
|
|
||||||
opacity: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
transition: opacity .3s;
|
|
||||||
& > div.bar{
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:hover div.barBox{
|
|
||||||
height: 100% !important;
|
|
||||||
width: auto !important;
|
|
||||||
opacity: 1 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.contentBox{
|
|
||||||
position: relative;
|
|
||||||
height: 2rem;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: .2rem .5rem;
|
|
||||||
border-radius: .25rem;
|
|
||||||
color: var(--font-color-top3-h2);
|
|
||||||
user-select: none;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color .3s;
|
|
||||||
&:hover{
|
|
||||||
background: var(--font-color-top3-hover);
|
|
||||||
}
|
|
||||||
&.active{
|
|
||||||
color: var(--font-color-top3-h1);
|
|
||||||
background: var(--font-color-top3-active);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
& > div.right{
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
& > div.main{
|
& > div.main{
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
& > header{
|
& > header{
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -9,9 +9,26 @@ definePageMeta({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>book</div>
|
<div class="book">
|
||||||
|
<div class="left">
|
||||||
|
<ResizeContent>AA</ResizeContent>
|
||||||
|
</div>
|
||||||
|
<div class="right"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
|
.book{
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
&>div.left{
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
|
& > div.right{
|
||||||
|
flex: 1;
|
||||||
|
background-color: #00dc82;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
Loading…
Reference in New Issue
Block a user