fix: 优化文章编辑页标签自动完成下拉菜单的定位和滚动关闭行为
continuous-integration/drone/push Build is passing

This commit is contained in:
seahi committed 2026-09-28 20:42:36 +08:00
1 parent a3322f9750
commit 6dac534f4e
2 files changed
+84 -18

No files matched your search

+42 -9
View File
@@ -53,6 +53,30 @@
let isAddingTag = $state(false);
let showTagDropdown = $state(false);
let tagInputContainer = $state<HTMLDivElement>();
let tagDropdownTop = $state(0);
let tagDropdownBottom = $state(0);
let tagDropdownLeft = $state(0);
let tagDropdownWidth = $state(0);
let tagDropdownUpwards = $state(false);
function updateTagDropdownPosition() {
if (tagInputContainer) {
const rect = tagInputContainer.getBoundingClientRect();
const spaceBelow = window.innerHeight - rect.bottom;
const spaceAbove = rect.top;
if (spaceBelow < 200 && spaceAbove > spaceBelow) {
tagDropdownUpwards = true;
tagDropdownBottom = window.innerHeight - rect.top;
} else {
tagDropdownUpwards = false;
tagDropdownTop = rect.bottom;
}
tagDropdownLeft = rect.left;
tagDropdownWidth = rect.width;
}
}
let filteredTags = $derived(
(() => {
const input = newTagInput.trim().toLowerCase();
@@ -121,6 +145,7 @@
<Alert message={form.error} />
{/if}
<svelte:window onresize={() => (showTagDropdown = false)} />
<form method="POST" action="?/update" id="post-form" class="post-form">
<!-- 正文由页面统一持有并始终提交,避免切到「预览」时编辑器卸载导致正文丢失 -->
<input type="hidden" name="content" value={content} />
@@ -172,7 +197,7 @@
</div>
</div>
<div class="form-sidebar">
<div class="form-sidebar" onscroll={() => (showTagDropdown = false)}>
<EditorSidebarTabs {outline} bind:activeTab={sidebarTab} />
<!-- 设置面板始终挂载(仅切换显隐),确保别名/分类/系列/标签等字段在提交时始终存在 -->
@@ -244,14 +269,17 @@
{/each}
</div>
<div class="tag-input-container">
<div class="tag-input-container" bind:this={tagInputContainer}>
<TextInput
type="text"
class="tag-input-new"
placeholder="+ 添加{$page.data.aliases?.tag || '标签'}..."
bind:value={newTagInput}
onkeydown={handleAddTag}
onfocus={() => (showTagDropdown = true)}
onfocus={() => {
updateTagDropdownPosition();
showTagDropdown = true;
}}
onblur={() => setTimeout(() => (showTagDropdown = false), 200)}
disabled={isAddingTag}
autocomplete="off"
@@ -259,7 +287,16 @@
/>
{#if showTagDropdown && filteredTags.length > 0}
<div class="tag-autocomplete-dropdown">
<div
class="tag-autocomplete-dropdown"
style="top: {tagDropdownUpwards
? 'auto'
: `${tagDropdownTop}px`}; bottom: {tagDropdownUpwards
? `${tagDropdownBottom}px`
: 'auto'}; left: {tagDropdownLeft}px; width: {tagDropdownWidth}px; margin-top: {tagDropdownUpwards
? '0'
: '4px'}; margin-bottom: {tagDropdownUpwards ? '4px' : '0'};"
>
{#each filteredTags as tag (tag.id || tag)}
<button
type="button"
@@ -474,10 +511,7 @@
}
.tag-autocomplete-dropdown {
position: absolute;
top: 100%;
left: 0;
right: 0;
position: fixed;
background: var(--bg-color);
border: 1px solid var(--text-color);
box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.15);
@@ -486,7 +520,6 @@
overflow-y: auto;
display: flex;
flex-direction: column;
margin-top: 4px;
}
.tag-dropdown-item {
+42 -9
View File
@@ -71,6 +71,30 @@
let isAddingTag = $state(false);
let showTagDropdown = $state(false);
let tagInputContainer = $state<HTMLDivElement>();
let tagDropdownTop = $state(0);
let tagDropdownBottom = $state(0);
let tagDropdownLeft = $state(0);
let tagDropdownWidth = $state(0);
let tagDropdownUpwards = $state(false);
function updateTagDropdownPosition() {
if (tagInputContainer) {
const rect = tagInputContainer.getBoundingClientRect();
const spaceBelow = window.innerHeight - rect.bottom;
const spaceAbove = rect.top;
if (spaceBelow < 200 && spaceAbove > spaceBelow) {
tagDropdownUpwards = true;
tagDropdownBottom = window.innerHeight - rect.top;
} else {
tagDropdownUpwards = false;
tagDropdownTop = rect.bottom;
}
tagDropdownLeft = rect.left;
tagDropdownWidth = rect.width;
}
}
let filteredTags = $derived(
(() => {
const input = newTagInput.trim().toLowerCase();
@@ -139,6 +163,7 @@
<Alert message={form.error} />
{/if}
<svelte:window onresize={() => (showTagDropdown = false)} />
<form method="POST" id="post-form" class="post-form">
<!-- 正文由页面统一持有并始终提交,避免切到「预览」时编辑器卸载导致正文丢失 -->
<input type="hidden" name="content" value={content} />
@@ -190,7 +215,7 @@
</div>
</div>
<div class="form-sidebar">
<div class="form-sidebar" onscroll={() => (showTagDropdown = false)}>
<EditorSidebarTabs {outline} bind:activeTab={sidebarTab} />
<!-- 设置面板始终挂载(仅切换显隐),确保别名/分类/系列/标签等字段在提交时始终存在 -->
@@ -274,14 +299,17 @@
{/each}
</div>
<div class="tag-input-container">
<div class="tag-input-container" bind:this={tagInputContainer}>
<TextInput
type="text"
class="tag-input-new"
placeholder="+ 添加{$page.data.aliases?.tag || '标签'}..."
bind:value={newTagInput}
onkeydown={handleAddTag}
onfocus={() => (showTagDropdown = true)}
onfocus={() => {
updateTagDropdownPosition();
showTagDropdown = true;
}}
onblur={() => setTimeout(() => (showTagDropdown = false), 200)}
disabled={isAddingTag}
autocomplete="off"
@@ -289,7 +317,16 @@
/>
{#if showTagDropdown && filteredTags.length > 0}
<div class="tag-autocomplete-dropdown">
<div
class="tag-autocomplete-dropdown"
style="top: {tagDropdownUpwards
? 'auto'
: `${tagDropdownTop}px`}; bottom: {tagDropdownUpwards
? `${tagDropdownBottom}px`
: 'auto'}; left: {tagDropdownLeft}px; width: {tagDropdownWidth}px; margin-top: {tagDropdownUpwards
? '0'
: '4px'}; margin-bottom: {tagDropdownUpwards ? '4px' : '0'};"
>
{#each filteredTags as tag (tag.id || tag)}
<button
type="button"
@@ -504,10 +541,7 @@
}
.tag-autocomplete-dropdown {
position: absolute;
top: 100%;
left: 0;
right: 0;
position: fixed;
background: var(--bg-color);
border: 1px solid var(--text-color);
box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.15);
@@ -516,7 +550,6 @@
overflow-y: auto;
display: flex;
flex-direction: column;
margin-top: 4px;
}
.tag-dropdown-item {