diff --git a/package.json b/package.json index 915d68c1..0da54041 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "officeparser": "^4.1.1", "proxy-agent": "^6.5.0", "tar": "^7.4.3", + "tiny-pinyin": "^1.3.2", "turndown": "^7.2.0", "turndown-plugin-gfm": "^1.0.2", "undici": "^7.4.0", diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 73070fcc..96c0366e 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -299,7 +299,12 @@ "topics": "Topics", "warning": "Warning", "you": "You", - "reasoning_content": "Deep reasoning" + "reasoning_content": "Deep reasoning", + "sort": { + "pinyin": "Sort by Pinyin", + "pinyin.asc": "Sort by Pinyin (A-Z)", + "pinyin.desc": "Sort by Pinyin (Z-A)" + } }, "docs": { "title": "Docs" diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index 1b78f598..ef40a614 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -299,7 +299,12 @@ "topics": "トピック", "warning": "警告", "you": "あなた", - "reasoning_content": "深く考察済み" + "reasoning_content": "深く考察済み", + "sort": { + "pinyin": "ピンインでソート", + "pinyin.asc": "ピンインで昇順ソート", + "pinyin.desc": "ピンインで降順ソート" + } }, "docs": { "title": "ドキュメント" diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 4402c736..334bfbf3 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -299,7 +299,12 @@ "topics": "Топики", "warning": "Предупреждение", "you": "Вы", - "reasoning_content": "Глубокий анализ" + "reasoning_content": "Глубокий анализ", + "sort": { + "pinyin": "Сортировать по пиньинь", + "pinyin.asc": "Сортировать по пиньинь (А-Я)", + "pinyin.desc": "Сортировать по пиньинь (Я-А)" + } }, "docs": { "title": "Документация" diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index a0121456..45aa2270 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -299,7 +299,12 @@ "topics": "话题", "warning": "警告", "you": "用户", - "reasoning_content": "已深度思考" + "reasoning_content": "已深度思考", + "sort": { + "pinyin": "按拼音排序", + "pinyin.asc": "按拼音升序", + "pinyin.desc": "按拼音降序" + } }, "docs": { "title": "帮助文档" diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index b4a93998..9301d45b 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -299,7 +299,12 @@ "topics": "話題", "warning": "警告", "you": "您", - "reasoning_content": "已深度思考" + "reasoning_content": "已深度思考", + "sort": { + "pinyin": "按拼音排序", + "pinyin.asc": "按拼音升序", + "pinyin.desc": "按拼音降序" + } }, "docs": { "title": "說明文件" diff --git a/src/renderer/src/pages/home/Tabs/AssistantItem.tsx b/src/renderer/src/pages/home/Tabs/AssistantItem.tsx index 5345bcf2..f88ca3dc 100644 --- a/src/renderer/src/pages/home/Tabs/AssistantItem.tsx +++ b/src/renderer/src/pages/home/Tabs/AssistantItem.tsx @@ -1,7 +1,15 @@ -import { DeleteOutlined, EditOutlined, MinusCircleOutlined, SaveOutlined } from '@ant-design/icons' +import { + DeleteOutlined, + EditOutlined, + MinusCircleOutlined, + SaveOutlined, + SortAscendingOutlined, + SortDescendingOutlined +} from '@ant-design/icons' import ModelAvatar from '@renderer/components/Avatar/ModelAvatar' import CopyIcon from '@renderer/components/Icons/CopyIcon' import { useAssistant } from '@renderer/hooks/useAssistant' +import { useAssistants } from '@renderer/hooks/useAssistant' import { modelGenerating } from '@renderer/hooks/useRuntime' import { useSettings } from '@renderer/hooks/useSettings' import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings' @@ -16,6 +24,7 @@ import { omit } from 'lodash' import { FC, startTransition, useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' +import * as tinyPinyin from 'tiny-pinyin' interface AssistantItemProps { assistant: Assistant @@ -32,6 +41,7 @@ const AssistantItem: FC = ({ assistant, isActive, onSwitch, const { removeAllTopics } = useAssistant(assistant.id) // 使用当前助手的ID const { clickAssistantToShowTopic, topicPosition, showAssistantIcon } = useSettings() const defaultModel = getDefaultModel() + const { assistants, updateAssistants } = useAssistants() const [isPending, setIsPending] = useState(false) useEffect(() => { @@ -44,6 +54,24 @@ const AssistantItem: FC = ({ assistant, isActive, onSwitch, } }, [isActive, assistant.topics]) + const sortByPinyinAsc = useCallback(() => { + const sorted = [...assistants].sort((a, b) => { + const pinyinA = tinyPinyin.convertToPinyin(a.name, '', true) + const pinyinB = tinyPinyin.convertToPinyin(b.name, '', true) + return pinyinA.localeCompare(pinyinB) + }) + updateAssistants(sorted) + }, [assistants, updateAssistants]) + + const sortByPinyinDesc = useCallback(() => { + const sorted = [...assistants].sort((a, b) => { + const pinyinA = tinyPinyin.convertToPinyin(a.name, '', true) + const pinyinB = tinyPinyin.convertToPinyin(b.name, '', true) + return pinyinB.localeCompare(pinyinA) + }) + updateAssistants(sorted) + }, [assistants, updateAssistants]) + const getMenuItems = useCallback( (assistant: Assistant): ItemType[] => [ { @@ -92,6 +120,19 @@ const AssistantItem: FC = ({ assistant, isActive, onSwitch, } }, { type: 'divider' }, + { + label: t('common.sort.pinyin.asc'), + key: 'sort-asc', + icon: , + onClick: () => sortByPinyinAsc() + }, + { + label: t('common.sort.pinyin.desc'), + key: 'sort-desc', + icon: , + onClick: () => sortByPinyinDesc() + }, + { type: 'divider' }, { label: t('common.delete'), key: 'delete', @@ -108,7 +149,7 @@ const AssistantItem: FC = ({ assistant, isActive, onSwitch, } } ], - [addAgent, addAssistant, onSwitch, removeAllTopics, t, onDelete] + [addAgent, addAssistant, onSwitch, removeAllTopics, t, onDelete, sortByPinyinAsc, sortByPinyinDesc] ) const handleSwitch = useCallback(async () => { diff --git a/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx b/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx index f2455a8a..52e84445 100644 --- a/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx @@ -4,7 +4,7 @@ import Scrollbar from '@renderer/components/Scrollbar' import { useAgents } from '@renderer/hooks/useAgents' import { useAssistants } from '@renderer/hooks/useAssistant' import { Assistant } from '@renderer/types' -import { FC, useCallback, useState } from 'react' +import { FC, useCallback, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' @@ -27,6 +27,7 @@ const Assistants: FC = ({ const [dragging, setDragging] = useState(false) const { addAgent } = useAgents() const { t } = useTranslation() + const containerRef = useRef(null) const onDelete = useCallback( (assistant: Assistant) => { @@ -41,7 +42,7 @@ const Assistants: FC = ({ ) return ( - + = ({ ) } -// 样式组件(只定义一次) +// 样式组件 const Container = styled(Scrollbar)` display: flex; flex-direction: column; diff --git a/yarn.lock b/yarn.lock index c06cc929..fdc0d125 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4003,6 +4003,7 @@ __metadata: string-width: "npm:^7.2.0" styled-components: "npm:^6.1.11" tar: "npm:^7.4.3" + tiny-pinyin: "npm:^1.3.2" tinycolor2: "npm:^1.6.0" tokenx: "npm:^0.4.1" turndown: "npm:^7.2.0" @@ -15557,6 +15558,13 @@ __metadata: languageName: node linkType: hard +"tiny-pinyin@npm:^1.3.2": + version: 1.3.2 + resolution: "tiny-pinyin@npm:1.3.2" + checksum: 10c0/26ce82ad7ca4ea112ea0c85b5b509b526ab6f61ee695350ec6ddf14cecbceffe812fd22533549406421dc09db1d9b5187b16e51d45ce4aef9c43b2c4941dd7d2 + languageName: node + linkType: hard + "tiny-typed-emitter@npm:^2.1.0": version: 2.1.0 resolution: "tiny-typed-emitter@npm:2.1.0"