Skip to content

Commit 0d1c95b

Browse files
committed
chore: 优化样式
1 parent 99dbbdc commit 0d1c95b

3 files changed

Lines changed: 91 additions & 37 deletions

File tree

src/renderer/components/VirtualList.vue

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const props = defineProps({
1616
type: Number,
1717
default: 0
1818
},
19-
gridItems: {
19+
gridSize: {
2020
type: Number,
2121
default: 1
2222
},
@@ -50,7 +50,7 @@ const visibleRange = computed(() => {
5050
// 计算起始索引
5151
const startRowIndex = Math.floor(currentScrollTop / props.itemHeight)
5252
const startBufferedRowIndex = Math.max(0, startRowIndex - bufferRows)
53-
const start = Math.max(0, startBufferedRowIndex * props.gridItems)
53+
const start = Math.max(0, startBufferedRowIndex * props.gridSize)
5454
5555
// 计算可见行数
5656
const visibleRowCount = Math.ceil(currentWrapperHeight / props.itemHeight)
@@ -62,7 +62,7 @@ const visibleRange = computed(() => {
6262
// 确保 end 不会是负数
6363
const end = Math.max(
6464
0,
65-
Math.min(props.items.length - 1, endBufferedRowIndex * props.gridItems - 1)
65+
Math.min(props.items.length - 1, endBufferedRowIndex * props.gridSize - 1)
6666
)
6767
6868
return { start, end }
@@ -90,31 +90,34 @@ const visibleItems = computed(() => {
9090
// 包装器样式
9191
const wrapperStyle = computed(() => {
9292
return {
93-
height: `${Math.ceil(props.items.length / props.gridItems) * props.itemHeight}px`,
94-
position: 'relative'
93+
height: `${Math.ceil(props.items.length / props.gridSize) * props.itemHeight}px`
9594
}
9695
})
9796
9897
// 获取项目样式
9998
const getItemStyle = (item) => {
100-
const row = Math.floor(item.index / props.gridItems)
101-
const col = item.index % props.gridItems
99+
const row = Math.floor(item.index / props.gridSize)
100+
const col = item.index % props.gridSize
102101
103102
const gridGap = props.gridGap
104103
105-
// 计算每项的宽度百分比,考虑间距
106-
const totalGapWidth = (props.gridItems - 1) * gridGap
107-
const itemWidthPercent = (100 - totalGapWidth) / props.gridItems
104+
// 计算总可用宽度和单个项目宽度百分比
105+
const totalGap = (props.gridSize - 1) * gridGap
106+
const itemWidthPercent = 100 / props.gridSize
107+
108+
// 计算左侧偏移和宽度,使用更精确的计算方式
109+
const left = props.itemWidth
110+
? `${col * (props.itemWidth + gridGap)}px`
111+
: `calc(${itemWidthPercent * col}% + ${col * gridGap}px)`
112+
113+
const width = props.itemWidth
114+
? `${props.itemWidth}px`
115+
: `calc(${itemWidthPercent}% - ${(totalGap / props.gridSize).toFixed(4)}px)` // 使用toFixed提高精度
108116
109117
return {
110-
position: 'absolute',
111118
top: `${row * (props.itemHeight + gridGap)}px`,
112-
left: props.itemWidth
113-
? `${col * (props.itemWidth + gridGap)}px`
114-
: `calc(${col * (100 / props.gridItems)}% + ${col * gridGap}px)`,
115-
width: props.itemWidth
116-
? `${props.itemWidth}px`
117-
: `calc(${100 / props.gridItems}% - ${props.gridItems > 1 ? totalGapWidth / props.gridItems : 0}px)`,
119+
left,
120+
width,
118121
height: `${props.itemHeight}px`
119122
}
120123
}
@@ -185,9 +188,9 @@ const scrollToIndex = (index) => {
185188
// 确保索引有效
186189
const validIndex = Math.max(0, Math.min(index, props.items.length - 1))
187190
// 计算行号
188-
const row = Math.floor(validIndex / props.gridItems)
191+
const row = Math.floor(validIndex / props.gridSize)
189192
// 计算滚动位置
190-
const top = row * props.itemHeight
193+
const top = row * (props.itemHeight + props.gridGap)
191194
// 调用 scrollToTop 方法
192195
scrollToTop(top)
193196
}
@@ -220,14 +223,20 @@ defineExpose({
220223
221224
:deep(.el-scrollbar__wrap) {
222225
overflow-x: hidden;
226+
scroll-behavior: smooth;
223227
}
224228
}
225229
226230
.virtual-list-wrapper {
231+
position: relative;
232+
box-sizing: border-box;
227233
width: 100%;
228234
}
229235
230236
.virtual-list-item {
237+
position: absolute;
231238
box-sizing: border-box;
239+
transform: translateZ(0);
240+
will-change: transform;
232241
}
233242
</style>

src/renderer/windows/MainWindow/components/ExploreCommon.vue

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { h } from 'vue'
33
import clipboard from 'clipboardy'
44
import UseCommonStore from '@renderer/stores/commonStore.js'
5+
import UseMenuStore from '@renderer/stores/menuStore.js'
56
import UseSettingStore from '@renderer/stores/settingStore.js'
67
import UseWordsStore from '@renderer/stores/wordsStore.js'
78
import { useTranslation } from 'i18next-vue'
@@ -18,9 +19,11 @@ import { debounce } from '@renderer/utils/index.js'
1819
1920
const { t } = useTranslation()
2021
const commonStore = UseCommonStore()
22+
const menuStore = UseMenuStore()
2123
const settingStore = UseSettingStore()
2224
const wordsStore = UseWordsStore()
2325
const { settingData } = storeToRefs(settingStore)
26+
const { selectedMenu, menuList } = storeToRefs(menuStore)
2427
const { wordTypeList, wordDrawerVisible } = storeToRefs(wordsStore)
2528
2629
const cardBlockRef = ref(null)
@@ -49,6 +52,31 @@ const props = defineProps({
4952
menuParams: Object
5053
})
5154
55+
// 启用的菜单列表
56+
const enabledMenus = computed(() => {
57+
const list = menuList.value.filter((item) => item.placement.includes('sideMenu'))
58+
if (
59+
!settingData.value ||
60+
!Array.isArray(settingData.value?.enabledMenus) ||
61+
!settingData.value?.enabledMenus?.length
62+
) {
63+
return list
64+
}
65+
return list.filter((item) => {
66+
if (item.canBeEnabled) {
67+
return settingData.value.enabledMenus.includes(item.name)
68+
}
69+
return true
70+
})
71+
})
72+
73+
// 是否启用WordDraw
74+
const enabledWordDraw = computed(() => {
75+
// 词云菜单
76+
const WordsMenu = enabledMenus.value.find((item) => item.name === 'Words')
77+
return WordsMenu && selectedMenu.value && selectedMenu.value.name === 'Search'
78+
})
79+
5280
const isExploreMenu = computed(() => {
5381
return props.menu === 'Explore'
5482
})
@@ -216,8 +244,8 @@ const gridForm = reactive({
216244
const cardForm = reactive({
217245
cardWidth: 225,
218246
cardHeight: Math.floor(225 * 0.618),
219-
gridItems: gridForm.gridSize === 'auto' ? 4 : gridForm.gridSize,
220-
gridGap: 10,
247+
gridSize: gridForm.gridSize === 'auto' ? 4 : gridForm.gridSize,
248+
gridGap: 4,
221249
buffer: 100
222250
})
223251
@@ -490,7 +518,7 @@ const onTabChange = () => {
490518
wordFilter.value = ''
491519
}
492520
const getWords = () => {
493-
if (isSearchMenu.value) {
521+
if (enabledWordDraw.value) {
494522
window.FBW.getWords({
495523
types: [1, 2],
496524
size: 1000
@@ -708,24 +736,34 @@ const onSwitchGridSize = async (childVal) => {
708736
const handleGridSize = (blockWidth = 900, blockHeight = 600) => {
709737
if (!blockWidth || !blockHeight) return
710738
const { gridSize, gridHWRatio } = gridForm
739+
740+
// 减去VirtualList组件的左右margin (10px * 2)
741+
const availableWidth = blockWidth - 20
742+
711743
// 批量计算所有需要更新的值
712744
const updates = {}
713745
if (gridSize === 'auto') {
714746
for (let i = 0; i < 10; i++) {
715747
const size = gridSizeRange.size * Math.pow(1.5, i)
716748
const minWidth = gridSizeRange.wrapperWidth * Math.pow(1.5, i)
717749
const maxWidth = gridSizeRange.wrapperWidth * Math.pow(1.5, i + 1)
718-
if (blockWidth >= minWidth && blockWidth < maxWidth) {
719-
updates.gridItems = size
720-
updates.cardWidth = Math.floor(blockWidth / updates.gridItems)
721-
updates.cardHeight = Math.floor(updates.cardWidth * gridHWRatio)
750+
if (availableWidth >= minWidth && availableWidth < maxWidth) {
751+
updates.gridSize = size
752+
// 计算总间距并从总宽度中减去
753+
const totalGap = (updates.gridSize - 1) * cardForm.gridGap
754+
// 使用更精确的计算方法,保留一位小数
755+
updates.cardWidth = Math.round(((availableWidth - totalGap) / updates.gridSize) * 10) / 10
756+
updates.cardHeight = Math.round(updates.cardWidth * gridHWRatio * 10) / 10
722757
break
723758
}
724759
}
725760
} else {
726-
updates.gridItems = gridSize
727-
updates.cardWidth = Math.floor(blockWidth / updates.gridItems)
728-
updates.cardHeight = Math.floor(updates.cardWidth * gridHWRatio)
761+
updates.gridSize = gridSize
762+
// 计算总间距并从总宽度中减去
763+
const totalGap = (updates.gridSize - 1) * cardForm.gridGap
764+
// 使用更精确的计算方法,保留一位小数
765+
updates.cardWidth = Math.round(((availableWidth - totalGap) / updates.gridSize) * 10) / 10
766+
updates.cardHeight = Math.round(updates.cardWidth * gridHWRatio * 10) / 10
729767
}
730768
// 计算最优缓冲区大小
731769
updates.buffer = calculateOptimalBuffer(blockHeight, updates.cardHeight)
@@ -735,9 +773,9 @@ const handleGridSize = (blockWidth = 900, blockHeight = 600) => {
735773
(blockWidth * blockHeight) / (updates.cardWidth * updates.cardHeight)
736774
)
737775
// 计算当前卡片大小下,block容器可以包含行
738-
const rows = Math.floor(allCardSize / updates.gridItems)
776+
const rows = Math.floor(allCardSize / updates.gridSize)
739777
// 在当前block容器可以包含的行数基础上再加1行,乘以每行grid数量得出新的分页量
740-
updates.pageSize = Math.floor((rows + 2) * updates.gridItems)
778+
updates.pageSize = Math.floor((rows + 2) * updates.gridSize)
741779
742780
// 一次性应用所有更新,减少重排次数
743781
Object.assign(cardForm, updates)
@@ -1044,7 +1082,8 @@ const onSyncToWallpaperSetting = async () => {
10441082
10451083
// 设置为壁纸
10461084
const setAsWallpaperWithDownload = async (item, index) => {
1047-
const res = await window.FBW.setAsWallpaperWithDownload(toRaw(item))
1085+
const res = await window.FBW.setAsWallpaperWithDownload(JSON.parse(JSON.stringify(item)))
1086+
10481087
let options = {}
10491088
if (res && res.success) {
10501089
options.type = 'success'
@@ -1237,7 +1276,7 @@ const onCopyFilePath = (filePath) => {
12371276
12381277
const onDeleteFile = (item, index) => {
12391278
const onConfirmDeleteFile = async () => {
1240-
const res = await window.FBW.deleteFile(toRaw(item))
1279+
const res = await window.FBW.deleteFile(JSON.parse(JSON.stringify(item)))
12411280
let callback
12421281
if (res.success) {
12431282
callback = async () => {
@@ -1503,7 +1542,7 @@ onBeforeUnmount(() => {
15031542
</div>
15041543
<div class="body-block">
15051544
<div
1506-
v-if="isSearchMenu"
1545+
v-if="enabledWordDraw"
15071546
:class="{ 'word-drawer': true, 'word-drawer-visible': wordDrawerVisible }"
15081547
>
15091548
<el-tabs v-model="activeWordTab" class="words-tabs" @tab-change="onTabChange">
@@ -1583,7 +1622,7 @@ onBeforeUnmount(() => {
15831622
:items="cardList"
15841623
:item-height="cardForm.cardHeight"
15851624
:item-width="cardForm.cardWidth"
1586-
:grid-items="cardForm.gridItems"
1625+
:grid-size="cardForm.gridSize"
15871626
:grid-gap="cardForm.gridGap"
15881627
:buffer="cardForm.buffer"
15891628
key-field="uniqueKey"
@@ -1853,6 +1892,8 @@ onBeforeUnmount(() => {
18531892
justify-content: center;
18541893
align-items: center;
18551894
overflow: hidden;
1895+
transform: translateZ(0);
1896+
will-change: transform, opacity;
18561897
18571898
&:hover {
18581899
background-color: rgba(50, 57, 65, 0.9);
@@ -2092,6 +2133,10 @@ onBeforeUnmount(() => {
20922133
+ .card-item-btn {
20932134
margin: 0;
20942135
}
2136+
2137+
&:hover {
2138+
background-color: rgba(0, 0, 0, 0.3);
2139+
}
20952140
}
20962141
}
20972142

src/renderer/windows/MainWindow/components/SideMenu.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<script setup>
2-
import UseSettingStore from '@renderer/stores/settingStore.js'
2+
import UseCommonStore from '@renderer/stores/commonStore.js'
33
import UseMenuStore from '@renderer/stores/menuStore.js'
4+
import UseSettingStore from '@renderer/stores/settingStore.js'
45
import UseWordsStore from '@renderer/stores/wordsStore.js'
5-
import UseCommonStore from '@renderer/stores/commonStore.js'
66
import iconLogo from '@resources/icons/icon_64x64.png'
77
import QRCode from 'qrcode'
88

0 commit comments

Comments
 (0)