feat: 为 slug 生成过程添加加载状态与交互反馈
continuous-integration/drone/push Build is passing

This commit is contained in:
seahi committed 2026-08-08 08:21:50 +08:00
1 parent fba532d7f5
commit 61e2f6ad9e
5 files changed
+31 -14

No files matched your search

+6 -1
View File
@@ -31,6 +31,7 @@ export function createSlugAutoHandler(opts: {
setSlug: (val: string) => void; setSlug: (val: string) => void;
getIsUserModified: () => boolean; getIsUserModified: () => boolean;
setIsUserModified: (val: boolean) => void; setIsUserModified: (val: boolean) => void;
setIsGenerating?: (val: boolean) => void;
delayMs?: number; delayMs?: number;
}) { }) {
const delay = opts.delayMs ?? 400; const delay = opts.delayMs ?? 400;
@@ -52,7 +53,9 @@ export function createSlugAutoHandler(opts: {
} }
timer = setTimeout(async () => { timer = setTimeout(async () => {
if (opts.setIsGenerating) opts.setIsGenerating(true);
const generated = await fetchSlug(nameValue); const generated = await fetchSlug(nameValue);
if (opts.setIsGenerating) opts.setIsGenerating(false);
// 在异步返回后,再次确认用户期间没有手动修改 slug // 在异步返回后,再次确认用户期间没有手动修改 slug
if (!opts.getIsUserModified() && generated) { if (!opts.getIsUserModified() && generated) {
opts.setSlug(generated); opts.setSlug(generated);
@@ -73,11 +76,13 @@ export function createSlugAutoHandler(opts: {
}, },
/** /**
* 用户点击 🔄 重新生成按钮时强制生成 * 用户点击 重新生成按钮时强制生成
*/ */
async forceGenerate(nameValue: string) { async forceGenerate(nameValue: string) {
if (!nameValue.trim()) return; if (!nameValue.trim()) return;
if (opts.setIsGenerating) opts.setIsGenerating(true);
const generated = await fetchSlug(nameValue); const generated = await fetchSlug(nameValue);
if (opts.setIsGenerating) opts.setIsGenerating(false);
if (generated) { if (generated) {
opts.setSlug(generated); opts.setSlug(generated);
// 标记为重置/由系统填充 // 标记为重置/由系统填充
+6 -3
View File
@@ -8,12 +8,14 @@
let name = $state(''); let name = $state('');
let slug = $state(''); let slug = $state('');
let isSlugUserModified = $state(false); let isSlugUserModified = $state(false);
let isGenerating = $state(false);
const slugHandler = createSlugAutoHandler({ const slugHandler = createSlugAutoHandler({
getSlug: () => slug, getSlug: () => slug,
setSlug: (val) => (slug = val), setSlug: (val) => (slug = val),
getIsUserModified: () => isSlugUserModified, getIsUserModified: () => isSlugUserModified,
setIsUserModified: (val) => (isSlugUserModified = val) setIsUserModified: (val) => (isSlugUserModified = val),
setIsGenerating: (val) => (isGenerating = val)
}); });
function handleNameInput() { function handleNameInput() {
@@ -60,10 +62,11 @@
<button <button
type="button" type="button"
class="btn btn-secondary" class="btn btn-secondary"
style="padding: 0.2rem 0.6rem; font-size: 0.8rem; cursor: pointer;" style="padding: 0.2rem 0.6rem; font-size: 0.8rem; cursor: pointer; flex-shrink: 0; min-width: max-content;"
onclick={() => slugHandler.forceGenerate(name)} onclick={() => slugHandler.forceGenerate(name)}
disabled={isGenerating}
> >
重新生成 {isGenerating ? '正在生成...' : '重新生成'}
</button> </button>
</div> </div>
<input <input
+6 -3
View File
@@ -13,12 +13,14 @@
let content = $state(''); let content = $state('');
let mode = $state<'edit' | 'preview'>('edit'); let mode = $state<'edit' | 'preview'>('edit');
let isSlugUserModified = $state(false); let isSlugUserModified = $state(false);
let isGenerating = $state(false);
const slugHandler = createSlugAutoHandler({ const slugHandler = createSlugAutoHandler({
getSlug: () => slug, getSlug: () => slug,
setSlug: (val) => (slug = val), setSlug: (val) => (slug = val),
getIsUserModified: () => isSlugUserModified, getIsUserModified: () => isSlugUserModified,
setIsUserModified: (val) => (isSlugUserModified = val) setIsUserModified: (val) => (isSlugUserModified = val),
setIsGenerating: (val) => (isGenerating = val)
}); });
function handleTitleInput() { function handleTitleInput() {
@@ -107,10 +109,11 @@
<button <button
type="button" type="button"
class="btn btn-secondary" class="btn btn-secondary"
style="padding: 0.2rem 0.6rem; font-size: 0.8rem; cursor: pointer;" style="padding: 0.2rem 0.6rem; font-size: 0.8rem; cursor: pointer; flex-shrink: 0; min-width: max-content;"
onclick={() => slugHandler.forceGenerate(title)} onclick={() => slugHandler.forceGenerate(title)}
disabled={isGenerating}
> >
重新生成 {isGenerating ? '正在生成...' : '重新生成'}
</button> </button>
</div> </div>
<input <input
+7 -4
View File
@@ -30,14 +30,16 @@
let tagsList = $state(initialData.tags || []); let tagsList = $state(initialData.tags || []);
let seriesList = $state(initialData.series || []); let seriesList = $state(initialData.series || []);
let isPublished = $state(true);
let isSlugUserModified = $state(false); let isSlugUserModified = $state(false);
let isGenerating = $state(false);
const slugHandler = createSlugAutoHandler({ const slugHandler = createSlugAutoHandler({
getSlug: () => slug, getSlug: () => slug,
setSlug: (val) => (slug = val), setSlug: (val) => (slug = val),
getIsUserModified: () => isSlugUserModified, getIsUserModified: () => isSlugUserModified,
setIsUserModified: (val) => (isSlugUserModified = val) setIsUserModified: (val) => (isSlugUserModified = val),
setIsGenerating: (val) => (isGenerating = val)
}); });
function handleTitleInput() { function handleTitleInput() {
@@ -517,11 +519,12 @@
<button <button
type="button" type="button"
class="btn btn-secondary" class="btn btn-secondary"
style="padding: 0.2rem 0.6rem; font-size: 0.8rem; cursor: pointer;" style="padding: 0.2rem 0.6rem; font-size: 0.8rem; cursor: pointer; flex-shrink: 0; min-width: max-content;"
title="生成英文 Slug" title="生成英文 Slug"
onclick={() => slugHandler.forceGenerate(title)} onclick={() => slugHandler.forceGenerate(title)}
disabled={isGenerating}
> >
重新生成 {isGenerating ? '正在生成...' : '重新生成'}
</button> </button>
</div> </div>
<input <input
+6 -3
View File
@@ -8,12 +8,14 @@
let name = $state(''); let name = $state('');
let slug = $state(''); let slug = $state('');
let isSlugUserModified = $state(false); let isSlugUserModified = $state(false);
let isGenerating = $state(false);
const slugHandler = createSlugAutoHandler({ const slugHandler = createSlugAutoHandler({
getSlug: () => slug, getSlug: () => slug,
setSlug: (val) => (slug = val), setSlug: (val) => (slug = val),
getIsUserModified: () => isSlugUserModified, getIsUserModified: () => isSlugUserModified,
setIsUserModified: (val) => (isSlugUserModified = val) setIsUserModified: (val) => (isSlugUserModified = val),
setIsGenerating: (val) => (isGenerating = val)
}); });
function handleNameInput() { function handleNameInput() {
@@ -54,10 +56,11 @@
<button <button
type="button" type="button"
class="btn btn-secondary" class="btn btn-secondary"
style="padding: 0.2rem 0.6rem; font-size: 0.8rem; cursor: pointer;" style="padding: 0.2rem 0.6rem; font-size: 0.8rem; cursor: pointer; flex-shrink: 0; min-width: max-content;"
onclick={() => slugHandler.forceGenerate(name)} onclick={() => slugHandler.forceGenerate(name)}
disabled={isGenerating}
> >
重新生成 {isGenerating ? '正在生成...' : '重新生成'}
</button> </button>
</div> </div>
<input <input