diff --git a/src/pages/QrCode/__tests__/index.test.tsx b/src/pages/QrCode/__tests__/index.test.tsx
index 1f52b3c..75eac20 100644
--- a/src/pages/QrCode/__tests__/index.test.tsx
+++ b/src/pages/QrCode/__tests__/index.test.tsx
@@ -27,12 +27,7 @@ vi.mock('@/config/features', async (importOriginal) => {
});
vi.mock('@/components/QrCodePreview', () => ({
- default: ({ placeholderText }: { placeholderText?: string }) => (
-
- QrCodePreview
- {placeholderText && {placeholderText}}
-
- ),
+ default: () => QrCodePreview
,
}));
vi.mock('@/components/ImageUploader', () => ({
@@ -60,7 +55,8 @@ describe('QrCodePage', () => {
render();
expect(screen.getByText('输入 URL 或文本')).toBeInTheDocument();
expect(screen.getByText('生成二维码')).toBeInTheDocument();
- expect(screen.getByTestId('qr-code-preview')).toBeInTheDocument();
+ // 输入态应该隐藏二维码预览
+ expect(screen.queryByTestId('qr-code-preview')).not.toBeInTheDocument();
});
it('应该渲染模式切换按钮', () => {
@@ -73,17 +69,16 @@ describe('QrCodePage', () => {
render();
fireEvent.click(screen.getByText('二维码转文本'));
expect(screen.getByTestId('image-uploader')).toBeInTheDocument();
- expect(screen.queryByTestId('qr-code-preview')).not.toBeInTheDocument();
});
- it('切换回生成模式应该渲染 QrCodePreview', () => {
+ it('切换回生成模式应该渲染输入态', () => {
render();
// 先切换到解析模式
fireEvent.click(screen.getByText('二维码转文本'));
- expect(screen.getByTestId('image-uploader')).toBeInTheDocument();
// 再切换回生成模式
fireEvent.click(screen.getByText('文本转二维码'));
- expect(screen.getByTestId('qr-code-preview')).toBeInTheDocument();
+ expect(screen.getByText('输入 URL 或文本')).toBeInTheDocument();
+ expect(screen.getByText('生成二维码')).toBeInTheDocument();
});
it('应该渲染输入区域的系统标签', () => {
@@ -91,12 +86,6 @@ describe('QrCodePage', () => {
expect(screen.getByText('输入 URL 或文本')).toBeInTheDocument();
});
- it('应该渲染双翼响应式卡片网格布局', () => {
- const { container } = render();
- const gridContainer = container.querySelector('.grid');
- expect(gridContainer).toBeInTheDocument();
- });
-
it('输入态应该显示生成按钮', () => {
render();
const generateButton = screen.getByText('生成二维码');
@@ -128,20 +117,40 @@ describe('QrCodePage', () => {
expect(screen.getByText('原始文本')).toBeInTheDocument();
expect(screen.getByText('编辑')).toBeInTheDocument();
expect(screen.queryByText('生成二维码')).not.toBeInTheDocument();
+ // 预览态应该显示二维码
+ expect(screen.getByTestId('qr-code-preview')).toBeInTheDocument();
});
- it('预览态应该显示保存的文本', () => {
+ it('预览态应该显示截断的文本', () => {
render();
- // 输入文本
+ // 输入长文本
+ const longText =
+ 'https://example.com/very/long/path/that/should/be/truncated/in/the/preview/because/it/exceeds/the/maximum/length';
const textarea = screen.getByPlaceholderText('请输入 URL 或文本内容,将自动生成二维码');
- fireEvent.change(textarea, { target: { value: 'https://example.com' } });
+ fireEvent.change(textarea, { target: { value: longText } });
// 点击生成按钮
fireEvent.click(screen.getByText('生成二维码'));
- // 验证显示保存的文本
- expect(screen.getByText('https://example.com')).toBeInTheDocument();
+ // 验证显示截断的文本(100字符 + "...")
+ const truncatedText = longText.slice(0, 100) + '...';
+ expect(screen.getByText(truncatedText)).toBeInTheDocument();
+ });
+
+ it('预览态应该显示完整的短文本', () => {
+ render();
+
+ // 输入短文本
+ const shortText = 'https://example.com';
+ const textarea = screen.getByPlaceholderText('请输入 URL 或文本内容,将自动生成二维码');
+ fireEvent.change(textarea, { target: { value: shortText } });
+
+ // 点击生成按钮
+ fireEvent.click(screen.getByText('生成二维码'));
+
+ // 验证显示完整文本
+ expect(screen.getByText(shortText)).toBeInTheDocument();
});
it('点击编辑按钮应该返回输入态', () => {
@@ -159,6 +168,8 @@ describe('QrCodePage', () => {
expect(screen.getByText('输入 URL 或文本')).toBeInTheDocument();
expect(screen.getByText('生成二维码')).toBeInTheDocument();
expect(screen.queryByText('编辑')).not.toBeInTheDocument();
+ // 输入态应该隐藏二维码预览
+ expect(screen.queryByTestId('qr-code-preview')).not.toBeInTheDocument();
});
it('返回编辑态应该保留上次输入的内容', () => {
diff --git a/src/pages/QrCode/components/GeneratePanel.tsx b/src/pages/QrCode/components/GeneratePanel.tsx
index 76bfdca..a21b692 100644
--- a/src/pages/QrCode/components/GeneratePanel.tsx
+++ b/src/pages/QrCode/components/GeneratePanel.tsx
@@ -7,6 +7,9 @@ import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { cn } from '@/lib/utils';
+/** 文本预览的最大显示字符数 */
+const TEXT_PREVIEW_MAX_LENGTH = 100;
+
export default function GeneratePanel() {
const { t } = useI18n('qrCode');
const {
@@ -21,60 +24,40 @@ export default function GeneratePanel() {
const isInputStep = generatorState.step === 'input';
const hasText = generatorState.textToEncode.trim().length > 0;
- return (
-
- {/* 左侧:输入态显示输入框,预览态显示文本预览 */}
-
-
-
+ /** 截断文本用于预览显示 */
+ const getTruncatedText = (text: string) => {
+ if (text.length <= TEXT_PREVIEW_MAX_LENGTH) return text;
+ return text.slice(0, TEXT_PREVIEW_MAX_LENGTH) + '...';
+ };
+
+ // 输入态:只显示输入框和生成按钮
+ if (isInputStep) {
+ return (
+
+
+
- {/* 预览态显示编辑按钮 */}
- {!isInputStep && (
-
- )}
-
+
setTextToEncode('')}
+ />
-
- {isInputStep ? (
- /* 输入态:可编辑的输入框 */
-
setTextToEncode('')}
- />
- ) : (
- /* 预览态:只读文本预览 */
-
-
- {generatorState.savedText}
-
-
- )}
-
-
- {/* 输入态显示生成按钮 */}
- {isInputStep && (
)}
- )}
+
+
+
+ );
+ }
+
+ // 预览态:显示文本预览 + 二维码
+ return (
+
+ {/* 文本预览区域 */}
+
+
+
+
+
+
+ {getTruncatedText(generatorState.savedText)}
- {/* 右侧:二维码预览区域 */}
-
-
-
+ {/* 二维码预览区域 */}
+
);
}