feat(快捷短语): 添加快捷短语核心功能模块

工具函数模块:
- 实现 localStorage 存储和加载功能
- 提供默认快捷短语模板(写作助手、代码解释、优化建议等)
- 添加数据验证和排序函数

Hook 模块:
- 实现增删改查功能
- 支持拖拽排序
- 自动同步到 localStorage
- 提供重置为默认值功能
This commit is contained in:
gaoziman 2025-12-24 00:07:30 +08:00
parent 92deb89e2a
commit 4499f7befd
2 changed files with 259 additions and 0 deletions

View File

@ -0,0 +1,141 @@
import { useState, useEffect, useCallback, useMemo } from 'react';
import type { QuickPhrase } from '@/types';
import {
loadPhrasesFromStorage,
savePhrasesToStorage,
generatePhraseId,
sortPhrases,
validatePhrase,
} from '@/lib/quick-phrases';
interface UseQuickPhrasesReturn {
phrases: QuickPhrase[];
addPhrase: (phrase: Omit<QuickPhrase, 'id' | 'createdAt' | 'updatedAt' | 'sortOrder'>) => void;
updatePhrase: (id: string, updates: Partial<Omit<QuickPhrase, 'id' | 'createdAt'>>) => void;
deletePhrase: (id: string) => void;
reorderPhrases: (reorderedPhrases: QuickPhrase[]) => void;
resetToDefaults: () => void;
}
/**
* Hook
* localStorage
*/
export function useQuickPhrases(): UseQuickPhrasesReturn {
const [phrases, setPhrases] = useState<QuickPhrase[]>([]);
// 初始化:从 localStorage 加载数据
useEffect(() => {
const loadedPhrases = loadPhrasesFromStorage();
setPhrases(loadedPhrases);
}, []);
// 保存到 localStorage 的辅助函数
const saveAndUpdate = useCallback((newPhrases: QuickPhrase[]) => {
savePhrasesToStorage(newPhrases);
setPhrases(newPhrases);
}, []);
/**
*
*/
const addPhrase = useCallback(
(phrase: Omit<QuickPhrase, 'id' | 'createdAt' | 'updatedAt' | 'sortOrder'>) => {
const now = Date.now();
const newPhrase: QuickPhrase = {
...phrase,
id: generatePhraseId(),
sortOrder: phrases.length + 1, // 添加到末尾
createdAt: now,
updatedAt: now,
};
// 验证短语数据
if (!validatePhrase(newPhrase)) {
console.error('Invalid phrase data:', newPhrase);
return;
}
const newPhrases = [...phrases, newPhrase];
saveAndUpdate(newPhrases);
},
[phrases, saveAndUpdate]
);
/**
*
*/
const updatePhrase = useCallback(
(id: string, updates: Partial<Omit<QuickPhrase, 'id' | 'createdAt'>>) => {
const newPhrases = phrases.map((phrase) => {
if (phrase.id === id) {
const updatedPhrase = {
...phrase,
...updates,
updatedAt: Date.now(),
};
return updatedPhrase;
}
return phrase;
});
saveAndUpdate(newPhrases);
},
[phrases, saveAndUpdate]
);
/**
*
*/
const deletePhrase = useCallback(
(id: string) => {
const newPhrases = phrases.filter((phrase) => phrase.id !== id);
// 重新调整 sortOrder
const reorderedPhrases = newPhrases.map((phrase, index) => ({
...phrase,
sortOrder: index + 1,
}));
saveAndUpdate(reorderedPhrases);
},
[phrases, saveAndUpdate]
);
/**
*
*/
const reorderPhrases = useCallback(
(reorderedPhrases: QuickPhrase[]) => {
// 更新 sortOrder
const phrasesWithNewOrder = reorderedPhrases.map((phrase, index) => ({
...phrase,
sortOrder: index + 1,
updatedAt: Date.now(),
}));
saveAndUpdate(phrasesWithNewOrder);
},
[saveAndUpdate]
);
/**
*
*/
const resetToDefaults = useCallback(() => {
const defaultPhrases = loadPhrasesFromStorage();
// 清除 localStorage 并重新加载默认值
localStorage.removeItem('cch_quick_phrases');
const freshDefaults = loadPhrasesFromStorage();
saveAndUpdate(freshDefaults);
}, [saveAndUpdate]);
// 返回排序后的短语列表
const sortedPhrases = useMemo(() => sortPhrases(phrases), [phrases]);
return {
phrases: sortedPhrases,
addPhrase,
updatePhrase,
deletePhrase,
reorderPhrases,
resetToDefaults,
};
}

118
src/lib/quick-phrases.ts Normal file
View File

@ -0,0 +1,118 @@
import type { QuickPhrase } from '@/types';
/**
* ID
*/
export function generatePhraseId(): string {
return `phrase-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
}
/**
*
*/
export const DEFAULT_PHRASES: QuickPhrase[] = [
{
id: 'default-1',
title: '写作助手',
content: '请帮我写一篇关于',
icon: 'PenTool',
sortOrder: 1,
createdAt: Date.now(),
updatedAt: Date.now(),
},
{
id: 'default-2',
title: '代码解释',
content: '请解释这段代码的功能和工作原理:\n\n',
icon: 'Code',
sortOrder: 2,
createdAt: Date.now(),
updatedAt: Date.now(),
},
{
id: 'default-3',
title: '优化建议',
content: '请帮我优化以下内容,使其更加专业和准确:\n\n',
icon: 'Sparkles',
sortOrder: 3,
createdAt: Date.now(),
updatedAt: Date.now(),
},
{
id: 'default-4',
title: '翻译助手',
content: '请帮我翻译以下内容:\n\n',
icon: 'Languages',
sortOrder: 4,
createdAt: Date.now(),
updatedAt: Date.now(),
},
{
id: 'default-5',
title: '头脑风暴',
content: '请帮我进行头脑风暴,给我一些关于以下主题的创意想法:\n\n',
icon: 'Lightbulb',
sortOrder: 5,
createdAt: Date.now(),
updatedAt: Date.now(),
},
];
/**
* localStorage key
*/
export const STORAGE_KEY = 'cch_quick_phrases';
/**
* localStorage
*/
export function loadPhrasesFromStorage(): QuickPhrase[] {
try {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored) {
const phrases = JSON.parse(stored) as QuickPhrase[];
// 验证数据格式
if (Array.isArray(phrases) && phrases.length > 0) {
return phrases;
}
}
} catch (error) {
console.error('Failed to load quick phrases from storage:', error);
}
// 如果没有存储的数据或加载失败,返回默认短语
return DEFAULT_PHRASES;
}
/**
* localStorage
*/
export function savePhrasesToStorage(phrases: QuickPhrase[]): void {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(phrases));
} catch (error) {
console.error('Failed to save quick phrases to storage:', error);
}
}
/**
*
*/
export function validatePhrase(phrase: Partial<QuickPhrase>): phrase is QuickPhrase {
return (
typeof phrase.id === 'string' &&
typeof phrase.title === 'string' &&
phrase.title.trim().length > 0 &&
typeof phrase.content === 'string' &&
phrase.content.trim().length > 0 &&
typeof phrase.sortOrder === 'number' &&
typeof phrase.createdAt === 'number' &&
typeof phrase.updatedAt === 'number'
);
}
/**
*
*/
export function sortPhrases(phrases: QuickPhrase[]): QuickPhrase[] {
return [...phrases].sort((a, b) => a.sortOrder - b.sortOrder);
}