fix: 修复博客文章弹窗打开顺序

This commit is contained in:
sunlei 2026-07-01 18:30:56 +08:00
parent f67e1a6a5f
commit b9d3fb6b86
2 changed files with 54 additions and 4 deletions

View File

@ -7,6 +7,22 @@ import { describe, expect, it } from 'vitest';
const source = readFileSync(new URL('list.tsx', import.meta.url), 'utf8'); const source = readFileSync(new URL('list.tsx', import.meta.url), 'utf8');
describe('blog article list preview entry', () => { describe('blog article list preview entry', () => {
/**
* Reads a source slice between two stable markers for modal ordering guards.
* @param start Marker before the function body under assertion.
* @param end Marker after the function body under assertion.
* @returns Source slice used by regression assertions.
*/
function getSourceSlice(start: string, end: string) {
const startIndex = source.indexOf(start);
const endIndex = source.indexOf(end, startIndex + start.length);
expect(startIndex).toBeGreaterThanOrEqual(0);
expect(endIndex).toBeGreaterThan(startIndex);
return source.slice(startIndex, endIndex);
}
it('keeps the preview row action wired to the hidden iframe route', () => { it('keeps the preview row action wired to the hidden iframe route', () => {
expect(source).toContain("key: 'preview'"); expect(source).toContain("key: 'preview'");
expect(source).toContain("permissionCodes: ['Blog:Article:Preview']"); expect(source).toContain("permissionCodes: ['Blog:Article:Preview']");
@ -14,6 +30,31 @@ describe('blog article list preview entry', () => {
expect(source).toContain('articleId: row.id'); expect(source).toContain('articleId: row.id');
}); });
it('opens the article modal before waiting for modal-contained form schema updates', () => {
const openCreateBody = getSourceSlice(
'async function openCreate',
'function openEdit',
);
const openEditBody = getSourceSlice(
'function openEdit',
'function openPreview',
);
expect(source).toContain('void resetArticleModalForm(');
expect(openCreateBody).toContain(
'articleModalApi.setData({ values }).open();',
);
expect(openEditBody).toContain(
'articleModalApi.setData({ values }).open();',
);
expect(openCreateBody).not.toMatch(
/await setArticleEditorMode[\s\S]*articleModalApi\.setData\(\{ values \}\)\.open\(\)/,
);
expect(openEditBody).not.toMatch(
/await setArticleEditorMode[\s\S]*articleModalApi\.setData\(\{ values \}\)\.open\(\)/,
);
});
it('wires Tiptap editor mode switching without dropping current content', () => { it('wires Tiptap editor mode switching without dropping current content', () => {
expect(source).toContain( expect(source).toContain(
"import { KtTiptapHtmlEditor } from '#/components/richText';", "import { KtTiptapHtmlEditor } from '#/components/richText';",

View File

@ -174,7 +174,9 @@ export default defineComponent({
const { values } = articleModalApi.getData<{ const { values } = articleModalApi.getData<{
values?: BlogArticleFormValues; values?: BlogArticleFormValues;
}>(); }>();
void resetArticleForm(values || getBlogArticleCreateFormDefaults()); void resetArticleModalForm(
values || getBlogArticleCreateFormDefaults(),
);
}, },
}); });
const columns: Array<TableColumnType<WordpressBlogApi.Article>> = [ const columns: Array<TableColumnType<WordpressBlogApi.Article>> = [
@ -391,6 +393,15 @@ export default defineComponent({
}); });
} }
/**
* Applies editor schema and form values after the modal has opened so the modal-contained form can mount first.
* @param values Article values selected for the current modal session.
*/
async function resetArticleModalForm(values: BlogArticleFormValues) {
await setArticleEditorMode(values.editorMode || 'markdown');
await resetArticleForm(values);
}
/** /**
* Resets modal form state before applying create or edit values. * Resets modal form state before applying create or edit values.
* @param values Article values selected for the current modal session. * @param values Article values selected for the current modal session.
@ -460,7 +471,6 @@ export default defineComponent({
editingId.value = undefined; editingId.value = undefined;
const values = getBlogArticleCreateFormDefaults(searchValues); const values = getBlogArticleCreateFormDefaults(searchValues);
await setArticleEditorMode(values.editorMode || 'markdown');
articleModalApi.setData({ values }).open(); articleModalApi.setData({ values }).open();
} }
@ -468,10 +478,9 @@ export default defineComponent({
* Opens the article modal using raw HTML mode for imported WordPress/Argon content. * Opens the article modal using raw HTML mode for imported WordPress/Argon content.
* @param row Article row selected from the table. * @param row Article row selected from the table.
*/ */
async function openEdit(row: WordpressBlogApi.Article) { function openEdit(row: WordpressBlogApi.Article) {
editingId.value = `${row.id}`; editingId.value = `${row.id}`;
const values = getBlogArticleEditFormValues(row); const values = getBlogArticleEditFormValues(row);
await setArticleEditorMode(values.editorMode || 'markdown');
articleModalApi.setData({ values }).open(); articleModalApi.setData({ values }).open();
} }