diff --git a/client/web/plugins/com.msgbyte.integration/manifest.json b/client/web/plugins/com.msgbyte.integration/manifest.json new file mode 100644 index 00000000..ca79646f --- /dev/null +++ b/client/web/plugins/com.msgbyte.integration/manifest.json @@ -0,0 +1,9 @@ +{ + "label": "第三方集成", + "name": "com.msgbyte.integration", + "url": "/plugins/com.msgbyte.integration/index.js", + "version": "0.0.0", + "author": "moonrailgun", + "description": "用于在群组中集成第三方应用", + "requireRestart": true +} diff --git a/client/web/plugins/com.msgbyte.integration/package.json b/client/web/plugins/com.msgbyte.integration/package.json new file mode 100644 index 00000000..e16e35d9 --- /dev/null +++ b/client/web/plugins/com.msgbyte.integration/package.json @@ -0,0 +1,16 @@ +{ + "name": "@plugins/com.msgbyte.integration", + "main": "src/index.tsx", + "version": "0.0.0", + "description": "用于在群组中集成第三方应用", + "private": true, + "scripts": { + "sync:declaration": "tailchat declaration github" + }, + "dependencies": {}, + "devDependencies": { + "@types/styled-components": "^5.1.26", + "react": "18.2.0", + "styled-components": "^5.3.6" + } +} diff --git a/client/web/plugins/com.msgbyte.integration/src/IntegrationPanel.tsx b/client/web/plugins/com.msgbyte.integration/src/IntegrationPanel.tsx new file mode 100644 index 00000000..80899a77 --- /dev/null +++ b/client/web/plugins/com.msgbyte.integration/src/IntegrationPanel.tsx @@ -0,0 +1,108 @@ +import React, { useCallback, useState } from 'react'; +import { Avatar, Button, Input, UserName } from '@capital/component'; +import styled from 'styled-components'; +import type { OpenAppInfo } from 'types'; +import { useAsyncRequest, postRequest } from '@capital/common'; + +const Tip = styled.div` + color: #999; + margin-bottom: 10px; +`; + +const Row = styled.div` + display: flex; +`; + +const AppInfoCard = styled.div({ + backgroundColor: 'rgba(0, 0, 0, 0.1)', + borderRadius: 3, + padding: 10, + marginTop: 10, + + '.app-info': { + flex: 1, + marginLeft: 10, + + '.title': { + fontSize: 18, + fontWeight: 'bold', + }, + + '.action': { + marginTop: 10, + }, + }, +}); + +const IntegrationPanel: React.FC = React.memo(() => { + const [appId, setAppId] = useState(''); + const [openAppInfo, setOpenAppInfo] = useState(null); + + const [{ loading }, handleQueryApp] = useAsyncRequest(async () => { + const { data } = await postRequest('/openapi/app/get', { + appId, + }); + + setOpenAppInfo(data); + }, [appId]); + + const handleAddBotIntoGroup = useCallback(() => { + console.log('TODO', appId); + }, [appId]); + + return ( +
+ 目前仅支持通过应用ID手动添加 + + + setAppId(e.target.value)} + /> + + + + {openAppInfo && ( +
+ + + + +
+
{openAppInfo.appName}
+
{openAppInfo.appDesc}
+ +
开发者:
+ +
+ +
+ {openAppInfo.capability.includes('bot') && ( + + )} +
+
+
+
+
+ )} +
+ ); +}); +IntegrationPanel.displayName = 'IntegrationPanel'; + +export default IntegrationPanel; diff --git a/client/web/plugins/com.msgbyte.integration/src/index.tsx b/client/web/plugins/com.msgbyte.integration/src/index.tsx new file mode 100644 index 00000000..d9a3416c --- /dev/null +++ b/client/web/plugins/com.msgbyte.integration/src/index.tsx @@ -0,0 +1,14 @@ +import { Loadable, regCustomPanel } from '@capital/common'; +import { Translate } from './translate'; + +const PLUGIN_NAME = '第三方集成'; + +console.log(`Plugin ${PLUGIN_NAME} is loaded`); + +regCustomPanel({ + position: 'groupdetail', + name: 'com.msgbyte.integration/groupdetail', + icon: '', + label: Translate.groupdetail, + render: Loadable(() => import('./IntegrationPanel')), +}); diff --git a/client/web/plugins/com.msgbyte.integration/src/translate.ts b/client/web/plugins/com.msgbyte.integration/src/translate.ts new file mode 100644 index 00000000..eb605880 --- /dev/null +++ b/client/web/plugins/com.msgbyte.integration/src/translate.ts @@ -0,0 +1,8 @@ +import { localTrans } from '@capital/common'; + +export const Translate = { + groupdetail: localTrans({ + 'zh-CN': '集成', + 'en-US': 'Integration', + }), +}; diff --git a/client/web/plugins/com.msgbyte.integration/src/types.ts b/client/web/plugins/com.msgbyte.integration/src/types.ts new file mode 100644 index 00000000..dd512c70 --- /dev/null +++ b/client/web/plugins/com.msgbyte.integration/src/types.ts @@ -0,0 +1,11 @@ +export type OpenAppCapability = 'bot' | 'webpage' | 'oauth'; + +export interface OpenAppInfo { + _id: string; + owner: string; + appId: string; + appName: string; + appDesc: string; + appIcon: string; + capability: OpenAppCapability[]; +} diff --git a/client/web/plugins/com.msgbyte.integration/tsconfig.json b/client/web/plugins/com.msgbyte.integration/tsconfig.json new file mode 100644 index 00000000..bf45bec1 --- /dev/null +++ b/client/web/plugins/com.msgbyte.integration/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "baseUrl": "./src", + "esModuleInterop": true, + "jsx": "react", + "importsNotUsedAsValues": "error", + "paths": { + "@capital/*": ["../../../src/plugin/*"], + } + } +} diff --git a/server/services/openapi/app.service.ts b/server/services/openapi/app.service.ts index d437f65d..44631129 100644 --- a/server/services/openapi/app.service.ts +++ b/server/services/openapi/app.service.ts @@ -131,7 +131,7 @@ class OpenAppService extends TcService { async get(ctx: TcContext<{ appId: string }>) { const appId = ctx.params.appId; - const apps = await this.adapter.model.findOne( + const app = await this.adapter.model.findOne( { appId, }, @@ -140,7 +140,7 @@ class OpenAppService extends TcService { } ); - return await this.transformDocuments(ctx, {}, apps); + return await this.transformDocuments(ctx, {}, app); } /**