feat(AssistantsTab): add sorting functionality by Pinyin and update translations (#4507)
This commit is contained in:
parent
fe7a392116
commit
fa66d048d7
@ -88,6 +88,7 @@
|
|||||||
"officeparser": "^4.1.1",
|
"officeparser": "^4.1.1",
|
||||||
"proxy-agent": "^6.5.0",
|
"proxy-agent": "^6.5.0",
|
||||||
"tar": "^7.4.3",
|
"tar": "^7.4.3",
|
||||||
|
"tiny-pinyin": "^1.3.2",
|
||||||
"turndown": "^7.2.0",
|
"turndown": "^7.2.0",
|
||||||
"turndown-plugin-gfm": "^1.0.2",
|
"turndown-plugin-gfm": "^1.0.2",
|
||||||
"undici": "^7.4.0",
|
"undici": "^7.4.0",
|
||||||
|
|||||||
@ -299,7 +299,12 @@
|
|||||||
"topics": "Topics",
|
"topics": "Topics",
|
||||||
"warning": "Warning",
|
"warning": "Warning",
|
||||||
"you": "You",
|
"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": {
|
"docs": {
|
||||||
"title": "Docs"
|
"title": "Docs"
|
||||||
|
|||||||
@ -299,7 +299,12 @@
|
|||||||
"topics": "トピック",
|
"topics": "トピック",
|
||||||
"warning": "警告",
|
"warning": "警告",
|
||||||
"you": "あなた",
|
"you": "あなた",
|
||||||
"reasoning_content": "深く考察済み"
|
"reasoning_content": "深く考察済み",
|
||||||
|
"sort": {
|
||||||
|
"pinyin": "ピンインでソート",
|
||||||
|
"pinyin.asc": "ピンインで昇順ソート",
|
||||||
|
"pinyin.desc": "ピンインで降順ソート"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"docs": {
|
"docs": {
|
||||||
"title": "ドキュメント"
|
"title": "ドキュメント"
|
||||||
|
|||||||
@ -299,7 +299,12 @@
|
|||||||
"topics": "Топики",
|
"topics": "Топики",
|
||||||
"warning": "Предупреждение",
|
"warning": "Предупреждение",
|
||||||
"you": "Вы",
|
"you": "Вы",
|
||||||
"reasoning_content": "Глубокий анализ"
|
"reasoning_content": "Глубокий анализ",
|
||||||
|
"sort": {
|
||||||
|
"pinyin": "Сортировать по пиньинь",
|
||||||
|
"pinyin.asc": "Сортировать по пиньинь (А-Я)",
|
||||||
|
"pinyin.desc": "Сортировать по пиньинь (Я-А)"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"docs": {
|
"docs": {
|
||||||
"title": "Документация"
|
"title": "Документация"
|
||||||
|
|||||||
@ -299,7 +299,12 @@
|
|||||||
"topics": "话题",
|
"topics": "话题",
|
||||||
"warning": "警告",
|
"warning": "警告",
|
||||||
"you": "用户",
|
"you": "用户",
|
||||||
"reasoning_content": "已深度思考"
|
"reasoning_content": "已深度思考",
|
||||||
|
"sort": {
|
||||||
|
"pinyin": "按拼音排序",
|
||||||
|
"pinyin.asc": "按拼音升序",
|
||||||
|
"pinyin.desc": "按拼音降序"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"docs": {
|
"docs": {
|
||||||
"title": "帮助文档"
|
"title": "帮助文档"
|
||||||
|
|||||||
@ -299,7 +299,12 @@
|
|||||||
"topics": "話題",
|
"topics": "話題",
|
||||||
"warning": "警告",
|
"warning": "警告",
|
||||||
"you": "您",
|
"you": "您",
|
||||||
"reasoning_content": "已深度思考"
|
"reasoning_content": "已深度思考",
|
||||||
|
"sort": {
|
||||||
|
"pinyin": "按拼音排序",
|
||||||
|
"pinyin.asc": "按拼音升序",
|
||||||
|
"pinyin.desc": "按拼音降序"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"docs": {
|
"docs": {
|
||||||
"title": "說明文件"
|
"title": "說明文件"
|
||||||
|
|||||||
@ -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 ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
||||||
import CopyIcon from '@renderer/components/Icons/CopyIcon'
|
import CopyIcon from '@renderer/components/Icons/CopyIcon'
|
||||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||||
|
import { useAssistants } from '@renderer/hooks/useAssistant'
|
||||||
import { modelGenerating } from '@renderer/hooks/useRuntime'
|
import { modelGenerating } from '@renderer/hooks/useRuntime'
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings'
|
import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings'
|
||||||
@ -16,6 +24,7 @@ import { omit } from 'lodash'
|
|||||||
import { FC, startTransition, useCallback, useEffect, useState } from 'react'
|
import { FC, startTransition, useCallback, useEffect, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
import * as tinyPinyin from 'tiny-pinyin'
|
||||||
|
|
||||||
interface AssistantItemProps {
|
interface AssistantItemProps {
|
||||||
assistant: Assistant
|
assistant: Assistant
|
||||||
@ -32,6 +41,7 @@ const AssistantItem: FC<AssistantItemProps> = ({ assistant, isActive, onSwitch,
|
|||||||
const { removeAllTopics } = useAssistant(assistant.id) // 使用当前助手的ID
|
const { removeAllTopics } = useAssistant(assistant.id) // 使用当前助手的ID
|
||||||
const { clickAssistantToShowTopic, topicPosition, showAssistantIcon } = useSettings()
|
const { clickAssistantToShowTopic, topicPosition, showAssistantIcon } = useSettings()
|
||||||
const defaultModel = getDefaultModel()
|
const defaultModel = getDefaultModel()
|
||||||
|
const { assistants, updateAssistants } = useAssistants()
|
||||||
|
|
||||||
const [isPending, setIsPending] = useState(false)
|
const [isPending, setIsPending] = useState(false)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -44,6 +54,24 @@ const AssistantItem: FC<AssistantItemProps> = ({ assistant, isActive, onSwitch,
|
|||||||
}
|
}
|
||||||
}, [isActive, assistant.topics])
|
}, [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(
|
const getMenuItems = useCallback(
|
||||||
(assistant: Assistant): ItemType[] => [
|
(assistant: Assistant): ItemType[] => [
|
||||||
{
|
{
|
||||||
@ -92,6 +120,19 @@ const AssistantItem: FC<AssistantItemProps> = ({ assistant, isActive, onSwitch,
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ type: 'divider' },
|
{ type: 'divider' },
|
||||||
|
{
|
||||||
|
label: t('common.sort.pinyin.asc'),
|
||||||
|
key: 'sort-asc',
|
||||||
|
icon: <SortAscendingOutlined />,
|
||||||
|
onClick: () => sortByPinyinAsc()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('common.sort.pinyin.desc'),
|
||||||
|
key: 'sort-desc',
|
||||||
|
icon: <SortDescendingOutlined />,
|
||||||
|
onClick: () => sortByPinyinDesc()
|
||||||
|
},
|
||||||
|
{ type: 'divider' },
|
||||||
{
|
{
|
||||||
label: t('common.delete'),
|
label: t('common.delete'),
|
||||||
key: 'delete',
|
key: 'delete',
|
||||||
@ -108,7 +149,7 @@ const AssistantItem: FC<AssistantItemProps> = ({ assistant, isActive, onSwitch,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[addAgent, addAssistant, onSwitch, removeAllTopics, t, onDelete]
|
[addAgent, addAssistant, onSwitch, removeAllTopics, t, onDelete, sortByPinyinAsc, sortByPinyinDesc]
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleSwitch = useCallback(async () => {
|
const handleSwitch = useCallback(async () => {
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import Scrollbar from '@renderer/components/Scrollbar'
|
|||||||
import { useAgents } from '@renderer/hooks/useAgents'
|
import { useAgents } from '@renderer/hooks/useAgents'
|
||||||
import { useAssistants } from '@renderer/hooks/useAssistant'
|
import { useAssistants } from '@renderer/hooks/useAssistant'
|
||||||
import { Assistant } from '@renderer/types'
|
import { Assistant } from '@renderer/types'
|
||||||
import { FC, useCallback, useState } from 'react'
|
import { FC, useCallback, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
@ -27,6 +27,7 @@ const Assistants: FC<AssistantsTabProps> = ({
|
|||||||
const [dragging, setDragging] = useState(false)
|
const [dragging, setDragging] = useState(false)
|
||||||
const { addAgent } = useAgents()
|
const { addAgent } = useAgents()
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
const onDelete = useCallback(
|
const onDelete = useCallback(
|
||||||
(assistant: Assistant) => {
|
(assistant: Assistant) => {
|
||||||
@ -41,7 +42,7 @@ const Assistants: FC<AssistantsTabProps> = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container className="assistants-tab">
|
<Container className="assistants-tab" ref={containerRef}>
|
||||||
<DragableList
|
<DragableList
|
||||||
list={assistants}
|
list={assistants}
|
||||||
onUpdate={updateAssistants}
|
onUpdate={updateAssistants}
|
||||||
@ -74,7 +75,7 @@ const Assistants: FC<AssistantsTabProps> = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 样式组件(只定义一次)
|
// 样式组件
|
||||||
const Container = styled(Scrollbar)`
|
const Container = styled(Scrollbar)`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@ -4003,6 +4003,7 @@ __metadata:
|
|||||||
string-width: "npm:^7.2.0"
|
string-width: "npm:^7.2.0"
|
||||||
styled-components: "npm:^6.1.11"
|
styled-components: "npm:^6.1.11"
|
||||||
tar: "npm:^7.4.3"
|
tar: "npm:^7.4.3"
|
||||||
|
tiny-pinyin: "npm:^1.3.2"
|
||||||
tinycolor2: "npm:^1.6.0"
|
tinycolor2: "npm:^1.6.0"
|
||||||
tokenx: "npm:^0.4.1"
|
tokenx: "npm:^0.4.1"
|
||||||
turndown: "npm:^7.2.0"
|
turndown: "npm:^7.2.0"
|
||||||
@ -15557,6 +15558,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
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":
|
"tiny-typed-emitter@npm:^2.1.0":
|
||||||
version: 2.1.0
|
version: 2.1.0
|
||||||
resolution: "tiny-typed-emitter@npm:2.1.0"
|
resolution: "tiny-typed-emitter@npm:2.1.0"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user