index.tsx 4.7 KB

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