index.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import { EllipsisOutlined } from '@ant-design/icons';
  2. import { Divider, DropDownProps, Dropdown, Tooltip, Typography } from 'antd';
  3. import cls from 'classnames';
  4. import { t } from 'i18next';
  5. import Image from 'next/image';
  6. import React from 'react';
  7. import AppDefaultIcon from '../AppDefaultIcon';
  8. import './style.css';
  9. const BlurredCard: React.FC<{
  10. RightTop?: React.ReactNode;
  11. Tags?: React.ReactNode;
  12. LeftBottom?: React.ReactNode;
  13. RightBottom?: React.ReactNode;
  14. rightTopHover?: boolean;
  15. name: string;
  16. description: string | React.ReactNode;
  17. logo?: string;
  18. onClick?: () => void;
  19. className?: string;
  20. scene?: string;
  21. code?: string;
  22. }> = ({
  23. RightTop,
  24. Tags,
  25. LeftBottom,
  26. RightBottom,
  27. onClick,
  28. rightTopHover = true,
  29. logo,
  30. name,
  31. description,
  32. className,
  33. scene,
  34. code,
  35. }) => {
  36. if (typeof description === 'string') {
  37. description = (
  38. <p className='line-clamp-2 relative bottom-4 text-ellipsis min-h-[42px] text-sm text-[#525964] dark:text-[rgba(255,255,255,0.65)]'>
  39. {description}
  40. </p>
  41. );
  42. }
  43. return (
  44. <div className={cls('flex justify-center mt-6 relative group w-1/3 px-2 mb-6', className)}
  45. style={{ backgroundColor: '#f0f!important' }}
  46. >
  47. <div
  48. onClick={onClick}
  49. className='backdrop-filter backdrop-blur-lg cursor-pointer hover:bg-slate-200 bg-white bg-opacity-70 border-2 border-white rounded-lg shadow p-4 relative w-full h-full dark:border-[#6f7f95] dark:bg-[#6f7f95] dark:bg-opacity-60'
  50. >
  51. <div className='flex items-end relative bottom-8 justify-between w-full'
  52. style={{ backgroundColor: '#f0f!important' }}
  53. >
  54. <div className='flex items-end gap-4 w-11/12 flex-1'>
  55. <div className='bg-white rounded-lg shadow-sm w-14 h-14 flex items-center p-3'>
  56. {scene ? (
  57. <AppDefaultIcon scene={scene} width={14} height={14} />
  58. ) : (
  59. logo && (
  60. <Image src={logo} width={44} height={44} alt={name} className='w-8 min-w-8 rounded-full max-w-none' />
  61. )
  62. )}
  63. </div>
  64. <div className='flex-1'>
  65. {/** 先简单判断下 */}
  66. {name.length > 6 ? (
  67. <Tooltip title={name}>
  68. <span
  69. className='line-clamp-1 text-ellipsis font-semibold text-base'
  70. style={{
  71. maxWidth: '60%',
  72. }}
  73. >
  74. {name}
  75. </span>
  76. </Tooltip>
  77. ) : (
  78. <span
  79. className='line-clamp-1 text-ellipsis font-semibold text-base'
  80. style={{
  81. maxWidth: '60%',
  82. }}
  83. >
  84. {name}
  85. </span>
  86. )}
  87. </div>
  88. </div>
  89. <span
  90. className={cls('shrink-0', {
  91. hidden: rightTopHover,
  92. 'group-hover:block': rightTopHover,
  93. })}
  94. onClick={e => {
  95. e.stopPropagation();
  96. }}
  97. >
  98. {RightTop}
  99. </span>
  100. </div>
  101. {description}
  102. <div className='relative bottom-2'>{Tags}</div>
  103. <div className='flex justify-between items-center'>
  104. <div>{LeftBottom}</div>
  105. <div>{RightBottom}</div>
  106. </div>
  107. {code && (
  108. <>
  109. <Divider className='my-3' />
  110. <Typography.Text copyable={true} className='absolute bottom-1 right-4 text-xs text-gray-500'>
  111. {code}
  112. </Typography.Text>
  113. </>
  114. )}
  115. </div>
  116. </div>
  117. );
  118. };
  119. const ChatButton: React.FC<{
  120. onClick?: () => void;
  121. Icon?: React.ReactNode | string;
  122. text?: string;
  123. }> = ({ onClick, Icon = '/pictures/card_chat.png', text = t('start_chat') }) => {
  124. if (typeof Icon === 'string') {
  125. Icon = <Image src={Icon as string} alt={Icon as string} width={17} height={15} />;
  126. }
  127. return (
  128. <div
  129. className='flex items-center gap-1 text-default'
  130. onClick={e => {
  131. e.stopPropagation();
  132. onClick && onClick();
  133. }}
  134. >
  135. {Icon}
  136. <span>{text}</span>
  137. </div>
  138. );
  139. };
  140. const InnerDropdown: React.FC<{ menu: DropDownProps['menu'] }> = ({ menu }) => {
  141. return (
  142. <Dropdown
  143. menu={menu}
  144. getPopupContainer={node => node.parentNode as HTMLElement}
  145. placement='bottomRight'
  146. autoAdjustOverflow={false}
  147. >
  148. <EllipsisOutlined className='p-2 hover:bg-white hover:dark:bg-black rounded-md' />
  149. </Dropdown>
  150. );
  151. };
  152. export { ChatButton, InnerDropdown };
  153. export default BlurredCard;