app-card.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import { ChatContext } from '@/app/chat-context';
  2. import { apiInterceptors, collectApp, delApp, newDialogue, publishApp, unCollectApp, unPublishApp } from '@/client/api';
  3. import { IApp } from '@/types/app';
  4. import { DeleteFilled, MessageFilled, StarFilled, WarningOutlined } from '@ant-design/icons';
  5. import { Modal, Popconfirm, Tooltip, message } from 'antd';
  6. import { useRouter } from 'next/router';
  7. import React, { useContext, useMemo } from 'react';
  8. import { useTranslation } from 'react-i18next';
  9. import IconFont from '@/new-components/common/Icon';
  10. import { useRequest } from 'ahooks';
  11. import GPTCard from '../common/gpt-card';
  12. interface IProps {
  13. updateApps: (params?: Record<string, any>) => void;
  14. app: IApp;
  15. handleEdit: (app: any) => void;
  16. activeKey: string;
  17. }
  18. const { confirm } = Modal;
  19. export default function AppCard(props: IProps) {
  20. const { updateApps, app, handleEdit, activeKey } = props;
  21. const { model } = useContext(ChatContext);
  22. const router = useRouter();
  23. const { setAgent: setAgentToChat } = useContext(ChatContext);
  24. const { t } = useTranslation();
  25. const languageMap = {
  26. en: t('English'),
  27. zh: t('Chinese'),
  28. };
  29. const showDeleteConfirm = () => {
  30. confirm({
  31. title: t('Tips'),
  32. icon: <WarningOutlined />,
  33. content: `do you want delete the application?`,
  34. okText: 'Yes',
  35. okType: 'danger',
  36. cancelText: 'No',
  37. async onOk() {
  38. await apiInterceptors(delApp({ app_code: app.app_code }));
  39. if (activeKey === 'collected') {
  40. updateApps({ is_collected: 'true', ignore_user: 'true' });
  41. } else {
  42. updateApps();
  43. }
  44. },
  45. });
  46. };
  47. const collect = async () => {
  48. const [error] = await apiInterceptors(
  49. app.is_collected === 'true' ? unCollectApp({ app_code: app.app_code }) : collectApp({ app_code: app.app_code }),
  50. );
  51. if (error) return;
  52. if (activeKey === 'collected') {
  53. updateApps({ is_collected: 'true', ignore_user: 'true' });
  54. } else if (activeKey === 'common') {
  55. updateApps({ ignore_user: 'true', published: 'true' });
  56. } else {
  57. updateApps();
  58. }
  59. };
  60. const handleChat = async () => {
  61. const [, res] = await apiInterceptors(newDialogue({ chat_mode: 'chat_agent' }));
  62. if (res) {
  63. // 原生应用跳转
  64. if (app.team_mode === 'native_app') {
  65. const { chat_scene = '' } = app.team_context;
  66. router.push(`/chat?scene=${chat_scene}&id=${res.conv_uid}${model ? `&model=${model}` : ''}`);
  67. } else {
  68. setAgentToChat?.(app.app_code);
  69. router.push(`/chat/?scene=chat_agent&id=${res.conv_uid}${model ? `&model=${model}` : ''}`);
  70. }
  71. }
  72. };
  73. // 发布或取消发布应用
  74. const { run: operate } = useRequest(
  75. async () => {
  76. if (app.published === 'true') {
  77. return await apiInterceptors(unPublishApp(app.app_code));
  78. } else {
  79. return await apiInterceptors(publishApp(app.app_code));
  80. }
  81. },
  82. {
  83. manual: true,
  84. onSuccess: data => {
  85. if (data[2]?.success) {
  86. if (app.published === 'true') {
  87. message.success(t('cancel_success'));
  88. } else {
  89. message.success(t('published_success'));
  90. }
  91. }
  92. updateApps?.();
  93. },
  94. },
  95. );
  96. const publicContent = () => {
  97. const { published = '' } = app;
  98. const stopPropagationFn = (e: React.MouseEvent<HTMLDivElement>) => {
  99. e.stopPropagation();
  100. };
  101. return (
  102. <Popconfirm
  103. title={t('Tips')}
  104. description={t(published == 'true' ? 'unPublish_desc' : 'publish_desc')}
  105. onCancel={(e: any) => {
  106. stopPropagationFn(e);
  107. }}
  108. onConfirm={async (e: any) => {
  109. stopPropagationFn(e);
  110. operate();
  111. }}
  112. >
  113. <Tooltip title={t(published == 'true' ? 'unpublish' : 'publish')}>
  114. {published == 'true' ? (
  115. <IconFont
  116. type='icon-unPublish-cloud'
  117. style={{
  118. fontSize: 20,
  119. }}
  120. onClick={stopPropagationFn}
  121. />
  122. ) : (
  123. <IconFont
  124. type='icon-publish-cloud'
  125. style={{
  126. fontSize: 20,
  127. }}
  128. onClick={stopPropagationFn}
  129. />
  130. )}
  131. </Tooltip>
  132. </Popconfirm>
  133. );
  134. };
  135. const canDelete = useMemo(() => {
  136. return activeKey === 'app';
  137. }, [activeKey]);
  138. const operations = useMemo(() => {
  139. const defaultArr = [
  140. {
  141. label: t('Chat'),
  142. children: <MessageFilled />,
  143. onClick: handleChat,
  144. },
  145. {
  146. label: t('collect'),
  147. children: <StarFilled className={app.is_collected === 'false' ? 'text-gray-400' : 'text-yellow-400'} />,
  148. onClick: collect,
  149. },
  150. ];
  151. if (canDelete) {
  152. defaultArr.push({
  153. label: t('Delete'),
  154. children: <DeleteFilled />,
  155. onClick: () => showDeleteConfirm() as any,
  156. });
  157. }
  158. return defaultArr;
  159. // eslint-disable-next-line react-hooks/exhaustive-deps
  160. }, [app, canDelete]);
  161. return (
  162. <GPTCard
  163. title={app.app_name}
  164. icon={'/icons/node/vis.png'}
  165. iconBorder={false}
  166. desc={app.app_describe}
  167. tags={[
  168. { text: languageMap[app.language], color: 'default' },
  169. { text: app.team_mode, color: 'default' },
  170. ]}
  171. onClick={() => {
  172. if (!canDelete) {
  173. return;
  174. }
  175. handleEdit(app);
  176. }}
  177. operations={operations}
  178. extraContent={canDelete && publicContent()}
  179. />
  180. );
  181. }