Skip to content

Commit a1b34e7

Browse files
committed
fix: 修复了右侧边栏操作卡顿问题
- 修改为只创建选中消息的 dom,不再遍历后用 v-show 隐藏 - 为 resize 操作做了 debounce ,每帧最多更新 1 次避免卡顿
1 parent 9bbf827 commit a1b34e7

2 files changed

Lines changed: 165 additions & 169 deletions

File tree

src/components/layout/SidebarRight.vue

Lines changed: 147 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -23,190 +23,171 @@
2323
</div>
2424
</div>
2525

26-
<div v-for="chunk in allChunks" :key="chunk.chunkId">
27-
<div
28-
v-for="message in chunk.messages"
29-
:key="message.messageId"
30-
v-show="
31-
activeContext.selectedMessageIds.value.has(
32-
message.messageId,
33-
)
34-
"
35-
class="message-detail-card"
36-
>
37-
<div class="card-header">
38-
<span class="id-badge">
39-
ID: {{ message.messageId }}
40-
</span>
26+
<div
27+
v-for="{ message, chunkId } in selectedItems"
28+
:key="message.messageId"
29+
class="message-detail-card"
30+
>
31+
<div class="card-header">
32+
<span class="id-badge">
33+
ID: {{ message.messageId }}
34+
</span>
35+
</div>
36+
37+
<div class="property-grid">
38+
<div class="prop-item-time">
39+
<label>时间:</label>
40+
<div>{{ formatDate(message.time) }}</div>
4141
</div>
4242

43-
<div class="property-grid">
44-
<div class="prop-item-time">
45-
<label>时间:</label>
46-
<div>{{ formatDate(message.time) }}</div>
47-
</div>
48-
49-
<div class="prop-item">
50-
<label>玩家名</label>
51-
<input
52-
type="text"
53-
:value="
54-
getDraftValue(message, 'playerName')
55-
"
56-
@input="
57-
updateDraft(
58-
message,
59-
'playerName',
60-
$event,
61-
)
62-
"
63-
v-click-outside="
64-
() =>
65-
commitDraft(
66-
chunk.chunkId,
67-
message.messageId,
68-
'playerName',
69-
)
70-
"
71-
@keydown.enter.exact.prevent="
43+
<div class="prop-item">
44+
<label>玩家名</label>
45+
<input
46+
type="text"
47+
:value="getDraftValue(message, 'playerName')"
48+
@input="
49+
updateDraft(message, 'playerName', $event)
50+
"
51+
v-click-outside="
52+
() =>
7253
commitDraft(
73-
chunk.chunkId,
54+
chunkId,
7455
message.messageId,
7556
'playerName',
7657
)
77-
"
78-
/>
79-
</div>
80-
81-
<div class="prop-item">
82-
<label>账号</label>
83-
<input
84-
type="text"
85-
:value="getDraftValue(message, 'account')"
86-
@input="
87-
updateDraft(message, 'account', $event)
88-
"
89-
v-click-outside="
90-
() =>
91-
commitDraft(
92-
chunk.chunkId,
93-
message.messageId,
94-
'account',
95-
)
96-
"
97-
@keydown.enter.exact.prevent="
58+
"
59+
@keydown.enter.exact.prevent="
60+
commitDraft(
61+
chunkId,
62+
message.messageId,
63+
'playerName',
64+
)
65+
"
66+
/>
67+
</div>
68+
69+
<div class="prop-item">
70+
<label>账号</label>
71+
<input
72+
type="text"
73+
:value="getDraftValue(message, 'account')"
74+
@input="updateDraft(message, 'account', $event)"
75+
v-click-outside="
76+
() =>
9877
commitDraft(
99-
chunk.chunkId,
78+
chunkId,
10079
message.messageId,
10180
'account',
10281
)
103-
"
104-
/>
105-
</div>
106-
107-
<div class="prop-item">
108-
<label>身份</label>
109-
<select
110-
:value="message.role"
111-
@change="
112-
updateField(
113-
chunk.chunkId,
114-
message.messageId,
115-
'role',
116-
$event,
117-
)
118-
"
119-
>
120-
<option value="pl">玩家</option>
121-
<option value="gm">主持人</option>
122-
<option value="npc">NPC</option>
123-
<option value="ob">观众</option>
124-
<option value="bot">骰子</option>
125-
</select>
126-
</div>
127-
<div class="prop-row">
128-
<ToggleButton
129-
:model-value="message.isOoc"
130-
class="inspector-toggle"
131-
@update:model-value="
132-
updateBooleanField(
133-
chunk.chunkId,
134-
message.messageId,
135-
'isOoc',
136-
Boolean($event),
137-
)
138-
"
139-
>
140-
场外消息
141-
</ToggleButton>
142-
<ToggleButton
143-
:model-value="message.isCommand"
144-
class="inspector-toggle"
145-
@update:model-value="
146-
updateBooleanField(
147-
chunk.chunkId,
148-
message.messageId,
149-
'isCommand',
150-
Boolean($event),
151-
)
152-
"
153-
>
154-
指令消息
155-
</ToggleButton>
156-
</div>
157-
158-
<div class="prop-item full-width">
159-
<label>消息内容</label>
160-
<textarea
161-
:value="getDraftValue(message, 'content')"
162-
@input="
163-
updateDraft(message, 'content', $event)
164-
"
165-
v-click-outside="
166-
() =>
167-
commitDraft(
168-
chunk.chunkId,
169-
message.messageId,
170-
'content',
171-
)
172-
"
173-
@keydown.enter.exact.prevent="
82+
"
83+
@keydown.enter.exact.prevent="
84+
commitDraft(
85+
chunkId,
86+
message.messageId,
87+
'account',
88+
)
89+
"
90+
/>
91+
</div>
92+
93+
<div class="prop-item">
94+
<label>身份</label>
95+
<select
96+
:value="message.role"
97+
@change="
98+
updateField(
99+
chunkId,
100+
message.messageId,
101+
'role',
102+
$event,
103+
)
104+
"
105+
>
106+
<option value="pl">玩家</option>
107+
<option value="gm">主持人</option>
108+
<option value="npc">NPC</option>
109+
<option value="ob">观众</option>
110+
<option value="bot">骰子</option>
111+
</select>
112+
</div>
113+
<div class="prop-row">
114+
<ToggleButton
115+
:model-value="message.isOoc"
116+
class="inspector-toggle"
117+
@update:model-value="
118+
updateBooleanField(
119+
chunkId,
120+
message.messageId,
121+
'isOoc',
122+
Boolean($event),
123+
)
124+
"
125+
>
126+
场外消息
127+
</ToggleButton>
128+
<ToggleButton
129+
:model-value="message.isCommand"
130+
class="inspector-toggle"
131+
@update:model-value="
132+
updateBooleanField(
133+
chunkId,
134+
message.messageId,
135+
'isCommand',
136+
Boolean($event),
137+
)
138+
"
139+
>
140+
指令消息
141+
</ToggleButton>
142+
</div>
143+
144+
<div class="prop-item full-width">
145+
<label>消息内容</label>
146+
<textarea
147+
:value="getDraftValue(message, 'content')"
148+
@input="updateDraft(message, 'content', $event)"
149+
v-click-outside="
150+
() =>
174151
commitDraft(
175-
chunk.chunkId,
152+
chunkId,
176153
message.messageId,
177154
'content',
178155
)
179-
"
180-
rows="5"
181-
></textarea>
182-
</div>
183-
184-
<div class="prop-item full-width">
185-
<label>备注</label>
186-
<input
187-
type="text"
188-
:value="getDraftValue(message, 'note')"
189-
@input="
190-
updateDraft(message, 'note', $event)
191-
"
192-
v-click-outside="
193-
() =>
194-
commitDraft(
195-
chunk.chunkId,
196-
message.messageId,
197-
'note',
198-
)
199-
"
200-
@keydown.enter.exact.prevent="
156+
"
157+
@keydown.enter.exact.prevent="
158+
commitDraft(
159+
chunkId,
160+
message.messageId,
161+
'content',
162+
)
163+
"
164+
rows="5"
165+
></textarea>
166+
</div>
167+
168+
<div class="prop-item full-width">
169+
<label>备注</label>
170+
<input
171+
type="text"
172+
:value="getDraftValue(message, 'note')"
173+
@input="updateDraft(message, 'note', $event)"
174+
v-click-outside="
175+
() =>
201176
commitDraft(
202-
chunk.chunkId,
177+
chunkId,
203178
message.messageId,
204179
'note',
205180
)
206-
"
207-
placeholder="备注信息..."
208-
/>
209-
</div>
181+
"
182+
@keydown.enter.exact.prevent="
183+
commitDraft(
184+
chunkId,
185+
message.messageId,
186+
'note',
187+
)
188+
"
189+
placeholder="备注信息..."
190+
/>
210191
</div>
211192
</div>
212193
</div>
@@ -232,7 +213,6 @@ const activeContext = useActiveContext();
232213
const logStore = useLogStore();
233214
const logEditorStore = useLogEditorStore();
234215
const uiStore = useUiStore();
235-
const allChunks = computed(() => logStore.allChunks);
236216
const { startResize } = usePanelResize({
237217
edge: 'left',
238218
getWidth: () => uiStore.rightPanelWidth,

src/composables/usePanelResize.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,31 @@ export function usePanelResize(options: UsePanelResizeOptions) {
2222
const direction = options.edge === 'right' ? 1 : -1;
2323
const minWidth = options.minWidth ?? PANEL_MIN_WIDTH;
2424
const maxWidth = options.maxWidth ?? PANEL_MAX_WIDTH;
25+
let frameId: number | null = null;
26+
let pendingWidth = startWidth;
27+
28+
function applyPendingWidth() {
29+
frameId = null;
30+
options.setWidth(pendingWidth);
31+
}
2532

2633
function onMouseMove(ev: MouseEvent) {
2734
const delta = ev.clientX - startX;
28-
options.setWidth(
29-
clampWidth(startWidth + delta * direction, minWidth, maxWidth),
35+
pendingWidth = clampWidth(
36+
startWidth + delta * direction,
37+
minWidth,
38+
maxWidth,
3039
);
40+
if (frameId === null) {
41+
frameId = requestAnimationFrame(applyPendingWidth);
42+
}
3143
}
3244

3345
function onMouseUp() {
46+
if (frameId !== null) {
47+
cancelAnimationFrame(frameId);
48+
applyPendingWidth();
49+
}
3450
document.removeEventListener('mousemove', onMouseMove);
3551
document.removeEventListener('mouseup', onMouseUp);
3652
document.body.style.cursor = '';

0 commit comments

Comments
 (0)