Procházet zdrojové kódy

✨ feat(mobile): 优化银发人才卡片展示信息与样式

- 扩展talent数据模型,新增realName、nickname、organization等15+字段
- 重构人才卡片UI,采用新布局展示头像、认证状态、基本信息和个人简介
- 添加技能标签展示功能,支持最多显示3个技能标签及数量提示
- 增加知识分享统计数据展示,包括阅读量、点赞数、评分和积分
- 显示求职状态标签,区分"求职中"和"开放机会"状态
- 优化排版和间距,提升整体视觉层次感和信息可读性

🐛 fix(server): 修复人才查询SQL格式问题

- 移除查询语句中的无效空白字符,确保SQL语法正确性
yourname před 9 měsíci
rodič
revize
69a472c0ad

+ 145 - 41
src/client/mobile/pages/NewHomePage.tsx

@@ -137,11 +137,22 @@ const transformTimeBank = (activities: any[]) =>
 const transformSilverTalents = (talents: any[]) =>
   talents.map(talent => ({
     id: talent.id,
-    name: talent.user?.username || talent.realName || '匿名用户',
-    specialty: talent.personalSkills || talent.profession || '暂无特长',
+    realName: talent.realName,
+    nickname: talent.nickname || '',
+    organization: talent.organization || '',
+    age: talent.age,
+    gender: talent.gender === 1 ? 'MALE' : talent.gender === 2 ? 'FEMALE' : 'OTHER',
+    avatarUrl: talent.avatarUrl,
+    personalIntro: talent.personalIntro || '',
+    personalSkills: talent.personalSkills || '',
+    certificationStatus: talent.certificationStatus === 2 ? 'CERTIFIED' : 'PENDING',
+    jobSeekingStatus: talent.jobSeekingStatus === 1 ? 'ACTIVELY_SEEKING' : talent.jobSeekingStatus === 2 ? 'OPEN_TO_OPPORTUNITIES' : 'NOT_SEEKING',
+    knowledgeShareCount: talent.knowledgeShareCount || 0,
+    knowledgeReadCount: talent.knowledgeReadCount || 0,
+    knowledgeRankingScore: parseFloat(talent.knowledgeRankingScore || 0),
+    totalPoints: talent.totalPoints || 0,
     city: talent.city || '未知地区',
-    createdAt: talent.createdAt,
-    avatar: unsplash.getElderlyAvatar(talent.userId || talent.id)
+    createdAt: talent.createdAt
   }));
 
 const transformSilverPositions = (positions: any[]) =>
@@ -545,54 +556,147 @@ const NewHomePage: React.FC = () => {
               </button>
             </div>
             
-            <div className="space-y-3">
+            <div className="space-y-4">
               {silverTalents.map((talent) => (
                 <div
                   key={talent.id}
-                  className="flex items-center p-4 rounded-xl shadow-sm hover:shadow-lg transition-all duration-300 cursor-pointer backdrop-blur-sm"
+                  className="p-4 rounded-xl shadow-sm hover:shadow-lg transition-all duration-300 cursor-pointer backdrop-blur-sm"
                   style={{
                     backgroundColor: 'rgba(255,255,255,0.8)',
                     border: `1px solid ${COLORS.ink.medium}`
                   }}
                   onClick={() => navigate(`/silver-talents/${talent.id}`)}
                 >
-                  <img
-                    src={talent.avatar || '/images/avatar-placeholder.jpg'}
-                    alt={talent.name}
-                    className="w-16 h-16 rounded-full object-cover mr-4 border-2 shadow-sm"
-                    style={{ borderColor: COLORS.ink.medium }}
-                  />
-                  <div className="flex-1">
-                    <h4
-                      className={`font-medium ${FONT_STYLES.body}`}
-                      style={{ color: COLORS.text.primary }}
-                    >
-                      {talent.name}
-                    </h4>
-                    <p
-                      className={`${FONT_STYLES.caption}`}
-                      style={{ color: COLORS.text.secondary }}
-                    >
-                      {talent.specialty || '暂无特长信息'}
-                    </p>
-                    <div className="flex items-center mt-2 space-x-2">
-                      <span
-                        className={`${FONT_STYLES.small} px-3 py-1 rounded-full flex items-center`}
-                        style={{
-                          backgroundColor: COLORS.accent.blue,
-                          color: 'white'
+                  <div className="flex items-start space-x-4">
+                    {/* 头像区域 */}
+                    <div className="relative flex-shrink-0">
+                      <img
+                        src={talent.avatarUrl || '/images/placeholder.jpg'}
+                        alt={talent.realName}
+                        className="w-20 h-20 rounded-full object-cover border-2"
+                        style={{ borderColor: COLORS.ink.medium }}
+                        onError={(e) => {
+                          (e.target as HTMLImageElement).src = '/images/placeholder.jpg';
                         }}
+                      />
+                      {talent.certificationStatus === 'CERTIFIED' && (
+                        <div
+                          className="absolute -top-1 -right-1 w-6 h-6 rounded-full flex items-center justify-center text-white text-xs shadow-lg"
+                          style={{ backgroundColor: COLORS.accent.green }}
+                        >
+                          ✓
+                        </div>
+                      )}
+                    </div>
+
+                    {/* 内容区域 */}
+                    <div className="flex-1 min-w-0">
+                      <div className="flex items-center justify-between mb-2">
+                        <h3
+                          className="font-serif text-lg font-bold"
+                          style={{ color: COLORS.text.primary }}
+                        >
+                          {talent.realName}
+                        </h3>
+                        <span
+                          className="font-sans text-sm"
+                          style={{ color: COLORS.text.light }}
+                        >
+                          {talent.nickname}
+                        </span>
+                      </div>
+
+                      <p className="font-sans text-sm mb-2" style={{ color: COLORS.text.secondary }}>
+                        <span className="font-semibold">{talent.age}岁</span>
+                        {talent.organization && (
+                          <span className="ml-2" style={{ color: COLORS.text.light }}>
+                            · {talent.organization}
+                          </span>
+                        )}
+                      </p>
+
+                      {/* 个人简介 */}
+                      <p
+                        className="font-sans text-sm mb-3 line-clamp-2"
+                        style={{ color: COLORS.text.secondary }}
                       >
-                        <MapPinIcon className="w-3 h-3 mr-1" />
-                        {talent.city || '未知地区'}
-                      </span>
-                      <span
-                        className={`${FONT_STYLES.small} flex items-center`}
-                        style={{ color: COLORS.text.light }}
-                      >
-                        <CalendarDaysIcon className="w-3 h-3 mr-1" />
-                        {new Date(talent.createdAt).toLocaleDateString()}
-                      </span>
+                        {talent.personalIntro}
+                      </p>
+
+                      {/* 技能标签 */}
+                      {talent.personalSkills && (
+                        <div className="flex flex-wrap gap-1 mb-3">
+                          {talent.personalSkills.split(',').slice(0, 3).map((skill: string, i: number) => (
+                            <span
+                              key={i}
+                              className="px-2 py-1 text-xs rounded-full border"
+                              style={{
+                                backgroundColor: 'rgba(92, 124, 92, 0.1)',
+                                color: COLORS.accent.green,
+                                borderColor: COLORS.accent.green
+                              }}
+                            >
+                              {skill.trim()}
+                            </span>
+                          ))}
+                          {talent.personalSkills.split(',').length > 3 && (
+                            <span
+                              className="px-2 py-1 text-xs rounded-full border"
+                              style={{
+                                backgroundColor: COLORS.ink.light,
+                                color: COLORS.text.secondary,
+                                borderColor: COLORS.ink.medium
+                              }}
+                            >
+                              +{talent.personalSkills.split(',').length - 3}
+                            </span>
+                          )}
+                        </div>
+                      )}
+
+                      {/* 统计信息 */}
+                      <div className="flex items-center justify-between text-xs">
+                        <div className="flex items-center space-x-4">
+                          <span style={{ color: COLORS.text.light }}>
+                            📖 {talent.knowledgeReadCount}
+                          </span>
+                          <span style={{ color: COLORS.text.light }}>
+                            👍 {talent.knowledgeLikeCount || 0}
+                          </span>
+                          <span style={{ color: COLORS.text.light }}>
+                            ⭐ {talent.knowledgeRankingScore}
+                          </span>
+                          <span style={{ color: COLORS.text.light }}>
+                            💰 {talent.totalPoints}
+                          </span>
+                        </div>
+                        <div className="flex items-center space-x-2">
+                          {talent.jobSeekingStatus === 'ACTIVELY_SEEKING' && (
+                            <span
+                              className="px-2 py-1 rounded-full text-xs font-sans"
+                              style={{
+                                backgroundColor: 'rgba(92, 124, 92, 0.1)',
+                                color: COLORS.accent.green,
+                                border: `1px solid ${COLORS.accent.green}`
+                              }}
+                            >
+                              求职中
+                            </span>
+                          )}
+                          {talent.jobSeekingStatus === 'OPEN_TO_OPPORTUNITIES' && (
+                            <span
+                              className="px-2 py-1 rounded-full text-xs font-sans"
+                              style={{
+                                backgroundColor: 'rgba(74, 107, 124, 0.1)',
+                                color: COLORS.accent.blue,
+                                border: `1px solid ${COLORS.accent.blue}`
+                              }}
+                            >
+                              开放机会
+                            </span>
+                          )}
+                        </div>
+                      </div>
                     </div>
                   </div>
                 </div>

+ 1 - 0
src/server/modules/home/home.service.ts

@@ -241,6 +241,7 @@ export class HomeService {
     return await this.userProfileRepo
       .createQueryBuilder('profile')
       .leftJoinAndSelect('profile.user', 'user')
+     
       .where('profile.certificationStatus = :certificationStatus', { certificationStatus: 2 })
       .andWhere('profile.personalSkills IS NOT NULL')
       .andWhere('profile.personalSkills != :empty', { empty: '' })