diff --git a/electron-builder.yml b/electron-builder.yml
index bf96b6e9..2b422256 100644
--- a/electron-builder.yml
+++ b/electron-builder.yml
@@ -56,4 +56,4 @@ electronDownload:
afterSign: scripts/notarize.js
releaseInfo:
releaseNotes: |
- 添加 MiniMax 服务商
+ 新增AI小程序模块
diff --git a/resources/graphrag.html b/resources/graphrag.html
index 0328ab4a..6661aa9f 100644
--- a/resources/graphrag.html
+++ b/resources/graphrag.html
@@ -58,7 +58,9 @@
window.api.minApp({
url,
windowOptions: {
- title: node.properties.title
+ title: node.properties.title,
+ width: 500,
+ height: 800
}
})
})
diff --git a/src/main/window.ts b/src/main/window.ts
index 7f6a229f..eeadee29 100644
--- a/src/main/window.ts
+++ b/src/main/window.ts
@@ -62,10 +62,33 @@ export function createMainWindow() {
})
mainWindow.webContents.setWindowOpenHandler((details) => {
- shell.openExternal(details.url)
+ const websiteReg = /accounts.google.com/i
+
+ if (websiteReg.test(details.url)) {
+ createMinappWindow({ url: details.url, windowOptions: { width: 1000, height: 680 } })
+ } else {
+ shell.openExternal(details.url)
+ }
+
return { action: 'deny' }
})
+ mainWindow.webContents.session.webRequest.onHeadersReceived({ urls: ['*://*/*'] }, (details, callback) => {
+ if (details.responseHeaders?.['X-Frame-Options']) {
+ delete details.responseHeaders['X-Frame-Options']
+ }
+ if (details.responseHeaders?.['x-frame-options']) {
+ delete details.responseHeaders['x-frame-options']
+ }
+ if (details.responseHeaders?.['Content-Security-Policy']) {
+ delete details.responseHeaders['Content-Security-Policy']
+ }
+ if (details.responseHeaders?.['content-security-policy']) {
+ delete details.responseHeaders['content-security-policy']
+ }
+ callback({ cancel: false, responseHeaders: details.responseHeaders })
+ })
+
// HMR for renderer base on electron-vite cli.
// Load the remote URL for development or the local html file for production.
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
@@ -84,8 +107,8 @@ export function createMinappWindow({
url: string
windowOptions?: Electron.BrowserWindowConstructorOptions
}) {
- const width = 500
- const height = 800
+ const width = 1000
+ const height = 680
const headerHeight = 40
const minappWindow = new BrowserWindow({
diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx
index 81a582f0..ec07c95a 100644
--- a/src/renderer/src/App.tsx
+++ b/src/renderer/src/App.tsx
@@ -6,6 +6,7 @@ import { PersistGate } from 'redux-persist/integration/react'
import Sidebar from './components/app/Sidebar'
import TopViewContainer from './components/TopView'
import AgentsPage from './pages/agents/AgentsPage'
+import AppsPage from './pages/apps/AppsPage'
import HomePage from './pages/home/HomePage'
import SettingsPage from './pages/settings/SettingsPage'
import TranslatePage from './pages/translate/TranslatePage'
@@ -23,8 +24,9 @@ function App(): JSX.Element {
} />
- } />
+ } />
} />
+ } />
} />
diff --git a/src/renderer/src/assets/fonts/icon-fonts/iconfont.css b/src/renderer/src/assets/fonts/icon-fonts/iconfont.css
index a80dfc13..f9b26b32 100644
--- a/src/renderer/src/assets/fonts/icon-fonts/iconfont.css
+++ b/src/renderer/src/assets/fonts/icon-fonts/iconfont.css
@@ -1,63 +1,64 @@
@font-face {
- font-family: "iconfont"; /* Project id 4563475 */
- src: url('iconfont.woff2?t=1723186111414') format('woff2'),
- url('iconfont.woff?t=1723186111414') format('woff'),
- url('iconfont.ttf?t=1723186111414') format('truetype');
+ font-family: 'iconfont'; /* Project id 4563475 */
+ src: url('iconfont.woff2?t=1724204739157') format('woff2');
}
.iconfont {
- font-family: "iconfont" !important;
+ font-family: 'iconfont' !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
+.icon-business-smart-assistant:before {
+ content: '\e601';
+}
+
.icon-copy:before {
- content: "\e6ae";
+ content: '\e6ae';
}
.icon-ic_send:before {
- content: "\e795";
+ content: '\e795';
}
.icon-dark1:before {
- content: "\e72f";
+ content: '\e72f';
}
.icon-theme-light:before {
- content: "\e6b7";
+ content: '\e6b7';
}
.icon-translate_line:before {
- content: "\e7de";
+ content: '\e7de';
}
.icon-history:before {
- content: "\e758";
+ content: '\e758';
}
.icon-hidesidebarhoriz:before {
- content: "\e8eb";
+ content: '\e8eb';
}
.icon-showsidebarhoriz:before {
- content: "\e944";
+ content: '\e944';
}
.icon-a-addchat:before {
- content: "\e658";
+ content: '\e658';
}
.icon-appstore:before {
- content: "\e792";
+ content: '\e792';
}
.icon-chat:before {
- content: "\e615";
+ content: '\e615';
}
.icon-setting:before {
- content: "\e78e";
+ content: '\e78e';
}
-
diff --git a/src/renderer/src/assets/fonts/icon-fonts/iconfont.ttf b/src/renderer/src/assets/fonts/icon-fonts/iconfont.ttf
deleted file mode 100644
index 4341a838..00000000
Binary files a/src/renderer/src/assets/fonts/icon-fonts/iconfont.ttf and /dev/null differ
diff --git a/src/renderer/src/assets/fonts/icon-fonts/iconfont.woff b/src/renderer/src/assets/fonts/icon-fonts/iconfont.woff
deleted file mode 100644
index 74e47150..00000000
Binary files a/src/renderer/src/assets/fonts/icon-fonts/iconfont.woff and /dev/null differ
diff --git a/src/renderer/src/assets/fonts/icon-fonts/iconfont.woff2 b/src/renderer/src/assets/fonts/icon-fonts/iconfont.woff2
index 60ae9bc6..8f1731e6 100644
Binary files a/src/renderer/src/assets/fonts/icon-fonts/iconfont.woff2 and b/src/renderer/src/assets/fonts/icon-fonts/iconfont.woff2 differ
diff --git a/src/renderer/src/assets/images/apps/360-ai.png b/src/renderer/src/assets/images/apps/360-ai.png
new file mode 100644
index 00000000..34f1e939
Binary files /dev/null and b/src/renderer/src/assets/images/apps/360-ai.png differ
diff --git a/src/renderer/src/assets/images/apps/baidu-ai.png b/src/renderer/src/assets/images/apps/baidu-ai.png
new file mode 100644
index 00000000..019ffea3
Binary files /dev/null and b/src/renderer/src/assets/images/apps/baidu-ai.png differ
diff --git a/src/renderer/src/assets/images/apps/baixiaoying.webp b/src/renderer/src/assets/images/apps/baixiaoying.webp
new file mode 100644
index 00000000..abb91015
Binary files /dev/null and b/src/renderer/src/assets/images/apps/baixiaoying.webp differ
diff --git a/src/renderer/src/assets/images/apps/kimi.jpg b/src/renderer/src/assets/images/apps/kimi.jpg
new file mode 100644
index 00000000..a7b3b0c7
Binary files /dev/null and b/src/renderer/src/assets/images/apps/kimi.jpg differ
diff --git a/src/renderer/src/assets/images/apps/yuewen.png b/src/renderer/src/assets/images/apps/yuewen.png
new file mode 100644
index 00000000..de9d81e5
Binary files /dev/null and b/src/renderer/src/assets/images/apps/yuewen.png differ
diff --git a/src/renderer/src/assets/images/models/yi.png b/src/renderer/src/assets/images/models/yi.png
new file mode 100644
index 00000000..3700850b
Binary files /dev/null and b/src/renderer/src/assets/images/models/yi.png differ
diff --git a/src/renderer/src/assets/images/models/yi.svg b/src/renderer/src/assets/images/models/yi.svg
deleted file mode 100644
index 83ebd22d..00000000
--- a/src/renderer/src/assets/images/models/yi.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/src/renderer/src/assets/images/providers/moonshot.jpeg b/src/renderer/src/assets/images/providers/moonshot.jpeg
deleted file mode 100644
index c0d8127a..00000000
Binary files a/src/renderer/src/assets/images/providers/moonshot.jpeg and /dev/null differ
diff --git a/src/renderer/src/assets/images/providers/moonshot.jpg b/src/renderer/src/assets/images/providers/moonshot.jpg
new file mode 100644
index 00000000..30b27b88
Binary files /dev/null and b/src/renderer/src/assets/images/providers/moonshot.jpg differ
diff --git a/src/renderer/src/assets/images/providers/yi.png b/src/renderer/src/assets/images/providers/yi.png
new file mode 100644
index 00000000..3700850b
Binary files /dev/null and b/src/renderer/src/assets/images/providers/yi.png differ
diff --git a/src/renderer/src/assets/images/providers/yi.svg b/src/renderer/src/assets/images/providers/yi.svg
deleted file mode 100644
index 19806791..00000000
--- a/src/renderer/src/assets/images/providers/yi.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/src/renderer/src/assets/styles/index.scss b/src/renderer/src/assets/styles/index.scss
index 93492afe..8c21944a 100644
--- a/src/renderer/src/assets/styles/index.scss
+++ b/src/renderer/src/assets/styles/index.scss
@@ -1,7 +1,7 @@
@import './markdown.scss';
@import './scrollbar.scss';
@import '../fonts/icon-fonts/iconfont.css';
-@import '../fonts/Ubuntu/Ubuntu.css';
+@import '../fonts/ubuntu/ubuntu.css';
:root {
--color-white: #ffffff;
@@ -102,6 +102,14 @@ body[theme-mode='light'] {
font-weight: normal;
}
+*:focus {
+ outline: none;
+}
+
+* {
+ -webkit-tap-highlight-color: transparent;
+}
+
ul {
list-style: none;
}
@@ -175,6 +183,9 @@ body,
}
.minapp-drawer {
+ .ant-drawer-content-wrapper {
+ box-shadow: none;
+ }
.ant-drawer-header {
position: absolute;
-webkit-app-region: drag;
diff --git a/src/renderer/src/components/Icons/CopyIcon.tsx b/src/renderer/src/components/Icons/CopyIcon.tsx
new file mode 100644
index 00000000..79f2b56a
--- /dev/null
+++ b/src/renderer/src/components/Icons/CopyIcon.tsx
@@ -0,0 +1,7 @@
+import { FC } from 'react'
+
+const CopyIcon: FC = () => {
+ return
+}
+
+export default CopyIcon
diff --git a/src/renderer/src/components/MinApp/index.tsx b/src/renderer/src/components/MinApp/index.tsx
index 0741acab..e7b74c82 100644
--- a/src/renderer/src/components/MinApp/index.tsx
+++ b/src/renderer/src/components/MinApp/index.tsx
@@ -3,28 +3,25 @@ import { isMac, isWindows } from '@renderer/config/constant'
import { useBridge } from '@renderer/hooks/useBridge'
import store from '@renderer/store'
import { setMinappShow } from '@renderer/store/runtime'
+import { MinAppType } from '@renderer/types'
import { Drawer } from 'antd'
import { useRef, useState } from 'react'
import styled from 'styled-components'
import { TopView } from '../TopView'
-interface ShowParams {
- title?: string
- url: string
-}
-
-interface Props extends ShowParams {
+interface Props {
+ app: MinAppType
resolve: (data: any) => void
}
-const PopupContainer: React.FC = ({ title, url, resolve }) => {
+const PopupContainer: React.FC = ({ app, resolve }) => {
const [open, setOpen] = useState(true)
const iframeRef = useRef(null)
useBridge()
- const canOpenExternalLink = url.startsWith('http://') || url.startsWith('https://')
+ const canOpenExternalLink = app.url.startsWith('http://') || app.url.startsWith('https://')
const onClose = () => {
setOpen(false)
@@ -33,19 +30,19 @@ const PopupContainer: React.FC = ({ title, url, resolve }) => {
const onReload = () => {
if (iframeRef.current) {
- iframeRef.current.src = url
+ iframeRef.current.src = app.url
}
}
const onOpenLink = () => {
- window.api.openWebsite(url)
+ window.api.openWebsite(app.url)
}
const Title = () => {
return (
-
- {title}
-
+
+ {app.name}
+
@@ -75,7 +72,7 @@ const PopupContainer: React.FC = ({ title, url, resolve }) => {
maskClosable={false}
closeIcon={null}
style={{ marginLeft: 'var(--sidebar-width)' }}>
-
+
)
}
@@ -84,6 +81,7 @@ const Frame = styled.iframe`
width: calc(100vw - var(--sidebar-width));
height: calc(100vh - var(--navbar-height));
border: none;
+ background-color: white;
`
const TitleContainer = styled.div`
@@ -113,6 +111,13 @@ const ButtonsGroup = styled.div`
align-items: center;
gap: 5px;
-webkit-app-region: no-drag;
+ &.windows {
+ margin-right: ${isWindows ? '130px' : 0};
+ background-color: var(--color-background-mute);
+ border-radius: 50px;
+ padding: 0 3px;
+ overflow: hidden;
+ }
`
const Button = styled.div`
@@ -139,12 +144,12 @@ export default class MinApp {
TopView.hide('MinApp')
store.dispatch(setMinappShow(false))
}
- static start(props: ShowParams) {
+ static start(app: MinAppType) {
store.dispatch(setMinappShow(true))
return new Promise((resolve) => {
TopView.show(
{
resolve(v)
this.close()
diff --git a/src/renderer/src/components/app/Sidebar.tsx b/src/renderer/src/components/app/Sidebar.tsx
index c73d871e..414b7149 100644
--- a/src/renderer/src/components/app/Sidebar.tsx
+++ b/src/renderer/src/components/app/Sidebar.tsx
@@ -33,9 +33,9 @@ const Sidebar: FC = () => {
-
-
-
+
+
+
@@ -43,6 +43,11 @@ const Sidebar: FC = () => {
+
+
+
+
+
@@ -62,6 +67,7 @@ const Container = styled.div`
align-items: center;
padding: 8px 0;
width: var(--sidebar-width);
+ min-width: var(--sidebar-width);
height: ${isMac ? 'calc(100vh - var(--navbar-height))' : '100vh'};
-webkit-app-region: drag !important;
border-right: 0.5px solid var(--color-border);
diff --git a/src/renderer/src/config/provider.ts b/src/renderer/src/config/provider.ts
index 43ce17da..2c3da572 100644
--- a/src/renderer/src/config/provider.ts
+++ b/src/renderer/src/config/provider.ts
@@ -1,3 +1,6 @@
+import BaicuanAppLogo from '@renderer/assets/images/apps/baixiaoying.webp'
+import KimiAppLogo from '@renderer/assets/images/apps/kimi.jpg'
+import YuewenAppLogo from '@renderer/assets/images/apps/yuewen.png'
import BaichuanModelLogo from '@renderer/assets/images/models/baichuan.png'
import ChatGLMModelLogo from '@renderer/assets/images/models/chatglm.jpeg'
import ChatGPTModelLogo from '@renderer/assets/images/models/chatgpt.jpeg'
@@ -14,7 +17,7 @@ import MixtralModelLogo from '@renderer/assets/images/models/mixtral.jpeg'
import PalmModelLogo from '@renderer/assets/images/models/palm.svg'
import QwenModelLogo from '@renderer/assets/images/models/qwen.png'
import StepModelLogo from '@renderer/assets/images/models/step.jpg'
-import YiModelLogo from '@renderer/assets/images/models/yi.svg'
+import YiModelLogo from '@renderer/assets/images/models/yi.png'
import AiHubMixProviderLogo from '@renderer/assets/images/providers/aihubmix.jpg'
import AnthropicProviderLogo from '@renderer/assets/images/providers/anthropic.jpeg'
import BaichuanProviderLogo from '@renderer/assets/images/providers/baichuan.png'
@@ -25,14 +28,14 @@ import GeminiProviderLogo from '@renderer/assets/images/providers/gemini.png'
import GraphRagProviderLogo from '@renderer/assets/images/providers/graph-rag.png'
import GroqProviderLogo from '@renderer/assets/images/providers/groq.png'
import MinimaxProviderLogo from '@renderer/assets/images/providers/minimax.png'
-import MoonshotProviderLogo from '@renderer/assets/images/providers/moonshot.jpeg'
-import MoonshotModelLogo from '@renderer/assets/images/providers/moonshot.jpeg'
+import MoonshotProviderLogo from '@renderer/assets/images/providers/moonshot.jpg'
+import MoonshotModelLogo from '@renderer/assets/images/providers/moonshot.jpg'
import OllamaProviderLogo from '@renderer/assets/images/providers/ollama.png'
import OpenAiProviderLogo from '@renderer/assets/images/providers/openai.png'
import OpenRouterProviderLogo from '@renderer/assets/images/providers/openrouter.png'
import SiliconFlowProviderLogo from '@renderer/assets/images/providers/silicon.png'
import StepFunProviderLogo from '@renderer/assets/images/providers/stepfun.png'
-import YiProviderLogo from '@renderer/assets/images/providers/yi.svg'
+import YiProviderLogo from '@renderer/assets/images/providers/yi.png'
import ZhipuProviderLogo from '@renderer/assets/images/providers/zhipu.png'
export function getProviderLogo(providerId: string) {
@@ -126,6 +129,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://platform.openai.com/api-keys',
docs: 'https://platform.openai.com/docs',
models: 'https://platform.openai.com/docs/models'
+ },
+ app: {
+ name: 'ChatGPT',
+ url: 'https://chatgpt.com/',
+ logo: OpenAiProviderLogo
}
},
gemini: {
@@ -138,6 +146,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://aistudio.google.com/app/apikey',
docs: 'https://ai.google.dev/gemini-api/docs',
models: 'https://ai.google.dev/gemini-api/docs/models/gemini'
+ },
+ app: {
+ name: 'Gemini',
+ url: 'https://gemini.google.com/',
+ logo: GeminiProviderLogo
}
},
silicon: {
@@ -150,6 +163,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://cloud.siliconflow.cn/account/ak?referrer=clxty1xuy0014lvqwh5z50i88',
docs: 'https://docs.siliconflow.cn/',
models: 'https://docs.siliconflow.cn/docs/model-names'
+ },
+ app: {
+ name: 'SiliconFlow',
+ url: 'https://cloud.siliconflow.cn/playground/chat',
+ logo: SiliconFlowProviderLogo
}
},
deepseek: {
@@ -162,6 +180,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://platform.deepseek.com/api_keys',
docs: 'https://platform.deepseek.com/api-docs/',
models: 'https://platform.deepseek.com/api-docs/'
+ },
+ app: {
+ name: 'DeepSeek',
+ url: 'https://chat.deepseek.com/',
+ logo: DeepSeekProviderLogo
}
},
yi: {
@@ -174,6 +197,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://platform.lingyiwanwu.com/apikeys',
docs: 'https://platform.lingyiwanwu.com/docs',
models: 'https://platform.lingyiwanwu.com/docs#%E6%A8%A1%E5%9E%8B'
+ },
+ app: {
+ name: 'Yi',
+ url: 'https://www.wanzhi.com/',
+ logo: YiProviderLogo
}
},
zhipu: {
@@ -186,6 +214,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://open.bigmodel.cn/usercenter/apikeys',
docs: 'https://open.bigmodel.cn/dev/howuse/introduction',
models: 'https://open.bigmodel.cn/modelcenter/square'
+ },
+ app: {
+ name: '智谱',
+ url: 'https://chatglm.cn/main/alltoolsdetail',
+ logo: ZhipuProviderLogo
}
},
moonshot: {
@@ -198,6 +231,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://platform.moonshot.cn/console/api-keys',
docs: 'https://platform.moonshot.cn/docs/',
models: 'https://platform.moonshot.cn/docs/intro#%E6%A8%A1%E5%9E%8B%E5%88%97%E8%A1%A8'
+ },
+ app: {
+ name: 'Kimi',
+ url: 'https://kimi.moonshot.cn/',
+ logo: KimiAppLogo
}
},
baichuan: {
@@ -210,6 +248,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://platform.baichuan-ai.com/console/apikey',
docs: 'https://platform.baichuan-ai.com/docs',
models: 'https://platform.baichuan-ai.com/price'
+ },
+ app: {
+ name: '百小应',
+ url: 'https://ying.baichuan-ai.com/chat',
+ logo: BaicuanAppLogo
}
},
dashscope: {
@@ -222,6 +265,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://help.aliyun.com/zh/dashscope/developer-reference/acquisition-and-configuration-of-api-key',
docs: 'https://help.aliyun.com/zh/dashscope/',
models: 'https://dashscope.console.aliyun.com/model'
+ },
+ app: {
+ name: '通义千问',
+ url: 'https://tongyi.aliyun.com/qianwen/',
+ logo: QwenModelLogo
}
},
stepfun: {
@@ -234,6 +282,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://platform.stepfun.com/interface-key',
docs: 'https://platform.stepfun.com/docs/overview/concept',
models: 'https://platform.stepfun.com/docs/llm/text'
+ },
+ app: {
+ name: '跃问',
+ url: 'https://yuewen.cn/chats/new',
+ logo: YuewenAppLogo
}
},
doubao: {
@@ -246,6 +299,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey',
docs: 'https://www.volcengine.com/docs/82379/1182403',
models: 'https://console.volcengine.com/ark/region:ark+cn-beijing/endpoint'
+ },
+ app: {
+ name: '豆包',
+ url: 'https://www.doubao.com/chat/',
+ logo: DoubaoProviderLogo
}
},
minimax: {
@@ -258,6 +316,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://platform.minimaxi.com/user-center/basic-information/interface-key',
docs: 'https://platform.minimaxi.com/document/Announcement',
models: 'https://platform.minimaxi.com/document/Models'
+ },
+ app: {
+ name: '海螺',
+ url: 'https://hailuoai.com/',
+ logo: HailuoModelLogo
}
},
'graphrag-kylin-mountain': {
@@ -288,6 +351,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://console.groq.com/keys',
docs: 'https://console.groq.com/docs/quickstart',
models: 'https://console.groq.com/docs/models'
+ },
+ app: {
+ name: 'Groq',
+ url: 'https://groq.com/',
+ logo: GroqProviderLogo
}
},
ollama: {
@@ -311,6 +379,11 @@ export const PROVIDER_CONFIG = {
apiKey: 'https://console.anthropic.com/settings/keys',
docs: 'https://docs.anthropic.com/en/docs',
models: 'https://docs.anthropic.com/en/docs/about-claude/models'
+ },
+ app: {
+ name: 'Claude',
+ url: 'https://claude.ai/',
+ logo: AnthropicProviderLogo
}
},
aihubmix: {
diff --git a/src/renderer/src/pages/apps/App.tsx b/src/renderer/src/pages/apps/App.tsx
new file mode 100644
index 00000000..989a78d7
--- /dev/null
+++ b/src/renderer/src/pages/apps/App.tsx
@@ -0,0 +1,49 @@
+import MinApp from '@renderer/components/MinApp'
+import { useTheme } from '@renderer/providers/ThemeProvider'
+import { MinAppType } from '@renderer/types'
+import { FC } from 'react'
+import styled from 'styled-components'
+
+interface Props {
+ app: MinAppType
+}
+
+const App: FC = ({ app }) => {
+ const { theme } = useTheme()
+
+ const onClick = () => {
+ MinApp.start(app)
+ }
+
+ return (
+
+
+ {app.name}
+
+ )
+}
+
+const Container = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+`
+
+const AppIcon = styled.img`
+ width: 60px;
+ height: 60px;
+ border-radius: 16px;
+ user-select: none;
+ -webkit-user-drag: none;
+`
+
+const AppTitle = styled.div`
+ font-size: 12px;
+ margin-top: 5px;
+ color: var(--color-text-soft);
+ text-align: center;
+`
+
+export default App
diff --git a/src/renderer/src/pages/apps/AppsPage.tsx b/src/renderer/src/pages/apps/AppsPage.tsx
new file mode 100644
index 00000000..3aadd70f
--- /dev/null
+++ b/src/renderer/src/pages/apps/AppsPage.tsx
@@ -0,0 +1,77 @@
+import AiAssistantAppLogo from '@renderer/assets/images/apps/360-ai.png'
+import BaiduAiAppLogo from '@renderer/assets/images/apps/baidu-ai.png'
+import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
+import { PROVIDER_CONFIG } from '@renderer/config/provider'
+import { MinAppType } from '@renderer/types'
+import { FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import styled from 'styled-components'
+
+import App from './App'
+
+const _apps: MinAppType[] = [
+ {
+ name: 'AI 助手',
+ logo: AiAssistantAppLogo,
+ url: 'https://bot.360.com/'
+ },
+ {
+ name: '文心一言',
+ logo: BaiduAiAppLogo,
+ url: 'https://yiyan.baidu.com/'
+ }
+]
+
+const AppsPage: FC = () => {
+ const { t } = useTranslation()
+
+ const apps: MinAppType[] = (Object.entries(PROVIDER_CONFIG) as any[])
+ .filter(([, config]) => config.app)
+ .map(([key, config]) => ({ id: key, ...config.app }))
+ .concat(_apps)
+
+ return (
+
+
+ {t('agents.title')}
+
+
+
+ {apps.map((app) => (
+
+ ))}
+
+
+
+ )
+}
+
+const Container = styled.div`
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ height: 100%;
+`
+
+const ContentContainer = styled.div`
+ display: flex;
+ flex: 1;
+ flex-direction: row;
+ justify-content: center;
+ height: 100%;
+ overflow-y: scroll;
+ background-color: var(--color-background);
+ padding: 50px;
+`
+
+const AppsContainer = styled.div`
+ display: flex;
+ min-width: 900px;
+ max-width: 900px;
+ flex-direction: row;
+ flex-wrap: wrap;
+ align-content: flex-start;
+ gap: 50px;
+`
+
+export default AppsPage
diff --git a/src/renderer/src/pages/settings/ProviderSettings/GraphRAGSettings.tsx b/src/renderer/src/pages/settings/ProviderSettings/GraphRAGSettings.tsx
index 2cc8ab51..ff7b65c7 100644
--- a/src/renderer/src/pages/settings/ProviderSettings/GraphRAGSettings.tsx
+++ b/src/renderer/src/pages/settings/ProviderSettings/GraphRAGSettings.tsx
@@ -1,5 +1,5 @@
import MinApp from '@renderer/components/MinApp'
-import { Provider } from '@renderer/types'
+import { MinAppType, Provider } from '@renderer/types'
import { Button } from 'antd'
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
@@ -19,7 +19,14 @@ const GraphRAGSettings: FC = ({ provider }) => {
const onShowGraphRAG = async () => {
const { appPath } = await window.api.getAppInfo()
const url = `file://${appPath}/resources/graphrag.html?apiUrl=${apiUrl}&modelId=${modalId}`
- MinApp.start({ url, title: t('words.knowledgeGraph') })
+
+ const app: MinAppType = {
+ name: t('words.knowledgeGraph'),
+ logo: '',
+ url
+ }
+
+ MinApp.start(app)
}
if (!modalId) {
diff --git a/src/renderer/src/pages/translate/TranslatePage.tsx b/src/renderer/src/pages/translate/TranslatePage.tsx
index 5b60152e..3b115734 100644
--- a/src/renderer/src/pages/translate/TranslatePage.tsx
+++ b/src/renderer/src/pages/translate/TranslatePage.tsx
@@ -1,12 +1,6 @@
-import {
- CheckOutlined,
- CopyOutlined,
- SendOutlined,
- SettingOutlined,
- SwapOutlined,
- WarningOutlined
-} from '@ant-design/icons'
+import { CheckOutlined, SendOutlined, SettingOutlined, SwapOutlined, WarningOutlined } from '@ant-design/icons'
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
+import CopyIcon from '@renderer/components/Icons/CopyIcon'
import { useDefaultModel } from '@renderer/hooks/useAssistant'
import { fetchTranslate } from '@renderer/services/api'
import { getDefaultAssistant } from '@renderer/services/assistant'
@@ -211,7 +205,7 @@ const TranslatePage: FC = () => {
: }
+ icon={copied ? : }
/>
diff --git a/src/renderer/src/types/index.ts b/src/renderer/src/types/index.ts
index 122617d9..71da5e98 100644
--- a/src/renderer/src/types/index.ts
+++ b/src/renderer/src/types/index.ts
@@ -75,3 +75,9 @@ export type Agent = {
export type Suggestion = {
content: string
}
+
+export type MinAppType = {
+ name: string
+ logo: string
+ url: string
+}