feat(快捷短语): 添加快捷短语核心功能模块
工具函数模块: - 实现 localStorage 存储和加载功能 - 提供默认快捷短语模板(写作助手、代码解释、优化建议等) - 添加数据验证和排序函数 Hook 模块: - 实现增删改查功能 - 支持拖拽排序 - 自动同步到 localStorage - 提供重置为默认值功能
This commit is contained in:
parent
92deb89e2a
commit
4499f7befd
141
src/hooks/useQuickPhrases.ts
Normal file
141
src/hooks/useQuickPhrases.ts
Normal 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
118
src/lib/quick-phrases.ts
Normal 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);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user