lrj
6 小时以前 bec58fa7fe4fae2deac88200d8d939e12ec8a08f
修复小程序WXS日期显示问题并重新设计【我的】页面

- 修复WXS函数语法错误:移除不支持的try-catch语句
- 重新设计【我的】页面UI:
- 简化用户信息区域,采用圆形头像设计
- 添加【我的项目】卡片式布局
- 使用浅灰色背景和绿色调卡片
- 简化菜单结构,保留核心功能
- 优化整体视觉层次和用户体验
3个文件已修改
4个文件已删除
943 ■■■■ 已修改文件
UI/wx/我的活动(学员版)/code.html 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI/wx/我的活动(学员版)/screen.png 补丁 | 查看 | 原始文档 | blame | 历史
UI/wx/我的评审(评委版)/code.html 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI/wx/我的评审(评委版)/screen.png 补丁 | 查看 | 原始文档 | blame | 历史
wx/pages/message/utils.wxs 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
wx/pages/profile/profile.wxml 206 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
wx/pages/profile/profile.wxss 507 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI/wx/ÎҵĻ£¨Ñ§Ô±°æ£©/code.html
File was deleted
UI/wx/ÎҵĻ£¨Ñ§Ô±°æ£©/screen.png
Binary files differ
UI/wx/Î񵀮ÀÉ󣍯Àί°æ£©/code.html
File was deleted
UI/wx/Î񵀮ÀÉ󣍯Àί°æ£©/screen.png
Binary files differ
wx/pages/message/utils.wxs
@@ -9,30 +9,29 @@
  } 
  // å¤„理字符串格式的日期
  else if (typeof dateStr === 'string') {
    // å°è¯•直接解析
    date = getDate(dateStr);
  } 
  else {
    return '';
  }
  
  // æ£€æŸ¥æ—¥æœŸå¯¹è±¡æ˜¯å¦åˆ›å»ºæˆåŠŸ
  try {
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    var day = date.getDate();
    var hour = date.getHours();
    var minute = date.getMinutes();
    // å¦‚果获取到的值是NaN,说明日期无效
    if (year !== year || month !== month || day !== day) {
      return '';
    }
    return year + '-' + formatNumber(month) + '-' + formatNumber(day) + ' ' + formatNumber(hour) + ':' + formatNumber(minute);
  } catch (e) {
  // æ£€æŸ¥æ—¥æœŸå¯¹è±¡æ˜¯å¦æœ‰æ•ˆ
  if (!date) {
    return '';
  }
  var year = date.getFullYear();
  var month = date.getMonth() + 1;
  var day = date.getDate();
  var hour = date.getHours();
  var minute = date.getMinutes();
  // ç®€å•检查是否为有效数字
  if (!year || !month || !day) {
    return '';
  }
  return year + '-' + formatNumber(month) + '-' + formatNumber(day) + ' ' + formatNumber(hour) + ':' + formatNumber(minute);
}
var formatNumber = function(n) {
wx/pages/profile/profile.wxml
@@ -8,186 +8,66 @@
  <!-- ä¸ªäººä¿¡æ¯åŒºåŸŸ -->
  <view wx:else class="profile-content">
    <!-- ç”¨æˆ·ä¿¡æ¯å¡ç‰‡ -->
    <view class="user-card">
      <view class="user-info">
    <!-- ç”¨æˆ·ä¿¡æ¯åŒºåŸŸ -->
    <view class="user-section">
      <view class="user-avatar-wrapper">
        <image 
          wx:if="{{userInfo.avatar}}"
          class="avatar"
          class="user-avatar"
          src="{{userInfo.avatar}}" 
          mode="aspectFill"
        />
        <view wx:else class="avatar-placeholder">
        <view wx:else class="user-avatar-placeholder">
          <text class="avatar-text">{{avatarText}}</text>
        </view>
        <view class="user-details">
          <text class="username">{{userInfo.name || '未设置姓名'}}</text>
          <text class="user-desc">{{userInfo.school || '未设置学校'}} | {{userInfo.major || '未设置专业'}}</text>
          <view class="user-roles">
            <text wx:for="{{userRoles}}" wx:key="*this" class="role-tag">
              {{item === 'JUDGE' ? '评委' : item === 'ORGANIZER' ? '主办方' : '参赛者'}}
            </text>
          </view>
        </view>
      </view>
      <view class="edit-btn" bindtap="onEditProfile">
        <text class="icon ic-edit"></text>
        <text class="edit-text">编辑</text>
      </view>
      <text class="user-name">{{userInfo.name || 'Ethan'}}</text>
      <text class="user-role">{{userRoles.includes('JUDGE') ? '评委' : userRoles.includes('ORGANIZER') ? '主办方' : '参赛者'}}</text>
    </view>
    <!-- ç»Ÿè®¡æ•°æ® -->
    <view class="stats-section">
      <view class="stats-grid">
        <view class="stat-item">
          <text class="stat-number">{{stats.totalRegistrations}}</text>
          <text class="stat-label">总报名</text>
    <!-- æˆ‘的项目区域 -->
    <view class="projects-section">
      <text class="section-title">我的项目</text>
      <view class="project-list">
        <view class="project-card project-a" bindtap="onMenuItemTap" data-path="/pages/profile/registrations">
          <view class="project-icon">
            <text class="icon-plant">🌱</text>
          </view>
          <view class="project-info">
            <text class="project-name">我的报名</text>
            <text class="project-desc">查看报名记录</text>
          </view>
          <text class="project-arrow">></text>
        </view>
        <view class="stat-item">
          <text class="stat-number">{{stats.ongoingActivities}}</text>
          <text class="stat-label">进行中</text>
        </view>
        <view class="stat-item">
          <text class="stat-number">{{stats.completedActivities}}</text>
          <text class="stat-label">已完成</text>
        </view>
        <view class="stat-item">
          <text class="stat-number">{{stats.awards}}</text>
          <text class="stat-label">获奖数</text>
        <view class="project-card project-b" bindtap="onMenuItemTap" data-path="/pages/profile/achievements">
          <view class="project-icon">
            <text class="icon-trophy">🏆</text>
          </view>
          <view class="project-info">
            <text class="project-name">我的成绩</text>
            <text class="project-desc">查看活动成绩</text>
          </view>
          <text class="project-arrow">></text>
        </view>
      </view>
    </view>
    <!-- è¯„委专区 -->
    <view wx:if="{{isJudge}}" class="role-section">
      <view class="section-header">
        <text class="section-title">评委专区</text>
        <view class="judge-stats">
          <text class="pending-count">待评审: {{judgeStats.pendingReviews}}</text>
        </view>
    <!-- å…¶ä»–功能菜单 -->
    <view class="other-menu-section">
      <view class="menu-item-simple" bindtap="onMenuItemTap" data-path="/pages/profile/favorites">
        <text class="menu-icon">⭐</text>
        <text class="menu-title">我的收藏</text>
        <text class="menu-arrow">></text>
      </view>
      <view class="menu-grid">
        <view
          wx:for="{{judgeMenuItems}}"
          wx:key="path"
          class="menu-item"
          data-path="{{item.path}}"
          bindtap="onMenuItemTap"
        >
          <view class="menu-icon-wrapper">
            <text class="icon {{item.iconName}}"></text>
            <view wx:if="{{item.badge > 0}}" class="badge">{{item.badge}}</view>
          </view>
          <text class="menu-title">{{item.title}}</text>
          <text class="menu-desc">{{item.desc}}</text>
        </view>
      <view class="menu-item-simple" bindtap="onMenuItemTap" data-path="/pages/profile/settings">
        <text class="menu-icon">⚙️</text>
        <text class="menu-title">设置</text>
        <text class="menu-arrow">></text>
      </view>
    </view>
    <!-- ä¸»åŠžæ–¹ä¸“åŒº -->
    <view wx:if="{{isOrganizer}}" class="role-section">
      <view class="section-header">
        <text class="section-title">主办方专区</text>
        <view class="organizer-stats">
          <text class="active-count">活跃活动: {{organizerStats.activeActivities}}</text>
        </view>
      </view>
      <view class="menu-grid">
        <view
          wx:for="{{organizerMenuItems}}"
          wx:key="path"
          class="menu-item"
          data-path="{{item.path}}"
          bindtap="onMenuItemTap"
        >
          <view class="menu-icon-wrapper">
            <text class="icon {{item.iconName}}"></text>
          </view>
          <text class="menu-title">{{item.title}}</text>
          <text class="menu-desc">{{item.desc}}</text>
        </view>
      </view>
    </view>
    <!-- åŠŸèƒ½èœå• -->
    <view class="menu-section">
      <view class="section-title">功能菜单</view>
      <view class="menu-list">
        <view
          wx:for="{{menuItems}}"
          wx:key="path"
          class="menu-item-row"
          data-path="{{item.path}}"
          bindtap="onMenuItemTap"
        >
          <view class="menu-left">
            <text class="icon {{item.iconName}}"></text>
            <view class="menu-text">
              <text class="menu-title">{{item.title}}</text>
              <text class="menu-desc">{{item.desc}}</text>
            </view>
          </view>
          <text class="icon ic-arrow-right"></text>
        </view>
      </view>
    </view>
    <!-- æœ€è¿‘报名 -->
    <view class="recent-section">
      <view class="section-header">
        <text class="section-title">最近报名</text>
        <text class="view-more" bindtap="onViewMoreRegistrations">查看更多</text>
      </view>
      <view wx:if="{{registrationLoading}}" class="loading-wrapper small">
        <view class="loading small"></view>
        <text class="loading-text">加载中...</text>
      </view>
      <view wx:elif="{{registrations.length === 0}}" class="empty-state">
        <text class="empty-icon">📝</text>
        <text class="empty-text">暂无报名记录</text>
      </view>
      <view wx:else class="registration-list">
        <view
          wx:for="{{registrations}}"
          wx:key="id"
          class="registration-item"
          data-id="{{item.id}}"
          bindtap="onRegistrationTap"
        >
          <image
            wx:if="{{item.activity.coverImage && item.activity.coverImage.fullUrl}}"
            class="activity-cover"
            src="{{item.activity.coverImage.fullUrl}}"
            mode="aspectFill"
          />
          <view wx:else class="activity-cover-placeholder">
            <text class="activity-cover-text">{{item.activity.titleText}}</text>
          </view>
          <view class="registration-info">
            <text class="activity-title">{{item.activity.title}}</text>
            <text class="registration-time">报名时间: {{formatDate(item.registrationTime)}}</text>
            <text class="activity-time">活动时间: {{formatDate(item.activity.startTime)}}</text>
            <view class="status-row">
              <text class="registration-status {{getStatusClass(item.status)}}">
                {{getStatusText(item.status)}}
              </text>
              <text class="activity-status">
                {{getActivityStatusText(item.activity.status)}}
              </text>
            </view>
          </view>
          <text class="item-arrow">></text>
        </view>
      </view>
    </view>
    <!-- é€€å‡ºç™»å½• -->
    <view class="logout-section">
      <view class="logout-btn" bindtap="onLogout">
        <text class="logout-text">退出登录</text>
      <view class="menu-item-simple" bindtap="onLogout">
        <text class="menu-icon">🚪</text>
        <text class="menu-title">退出登录</text>
        <text class="menu-arrow">></text>
      </view>
    </view>
  </view>
wx/pages/profile/profile.wxss
@@ -4,7 +4,7 @@
/* å®¹å™¨æ ·å¼ */
.container {
  min-height: 100vh;
  background: #f8f9fa;
  background: #f5f5f5;
  padding-bottom: 40rpx;
}
@@ -31,39 +31,29 @@
  padding: 0 30rpx;
}
/* ç”¨æˆ·ä¿¡æ¯å¡ç‰‡ */
.user-card {
  background: linear-gradient(135deg, #1976d2, #42a5f5);
  border-radius: 20rpx;
  padding: 40rpx;
  margin-bottom: 30rpx;
/* ç”¨æˆ·ä¿¡æ¯åŒºåŸŸ */
.user-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  box-shadow: 0 8rpx 24rpx rgba(25, 118, 210, 0.3);
  padding: 60rpx 0 40rpx 0;
}
.user-info {
  display: flex;
  align-items: center;
  flex: 1;
.user-avatar-wrapper {
  margin-bottom: 20rpx;
}
.avatar {
.user-avatar {
  width: 120rpx;
  height: 120rpx;
  border-radius: 50%;
  margin-right: 30rpx;
  border: 4rpx solid rgba(255, 255, 255, 0.3);
}
.avatar-placeholder {
.user-avatar-placeholder {
  width: 120rpx;
  height: 120rpx;
  border-radius: 50%;
  margin-right: 30rpx;
  border: 4rpx solid rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.2);
  background: #ffa726;
  display: flex;
  align-items: center;
  justify-content: center;
@@ -75,474 +65,139 @@
  font-weight: bold;
}
.user-details {
  flex: 1;
}
.username {
  display: block;
.user-name {
  font-size: 36rpx;
  font-weight: bold;
  color: #ffffff;
  margin-bottom: 12rpx;
}
.user-desc {
  display: block;
  font-size: 24rpx;
  color: rgba(255, 255, 255, 0.8);
  margin-bottom: 16rpx;
}
.user-roles {
  display: flex;
  gap: 12rpx;
}
.role-tag {
  padding: 6rpx 16rpx;
  background: rgba(255, 255, 255, 0.2);
  color: #ffffff;
  border-radius: 20rpx;
  font-size: 20rpx;
  font-weight: 500;
}
.edit-btn {
  width: 60rpx;
  height: 60rpx;
  background: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.edit-icon {
  font-size: 28rpx;
}
/* ç»Ÿè®¡æ•°æ®æ ·å¼ */
.stats-section {
  background: #ffffff;
  border-radius: 16rpx;
  padding: 30rpx;
  margin-bottom: 30rpx;
  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
}
.stats-grid {
  display: flex;
  justify-content: space-between;
}
.stat-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
}
.stat-number {
  font-size: 48rpx;
  font-weight: bold;
  color: #1976d2;
  color: #333333;
  margin-bottom: 8rpx;
}
.stat-label {
  font-size: 24rpx;
  color: #666666;
.user-role {
  font-size: 28rpx;
  color: #999999;
}
/* è§’色专区样式 */
.role-section {
  background: #ffffff;
  border-radius: 16rpx;
  padding: 30rpx;
  margin-bottom: 30rpx;
  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
}
.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 30rpx;
/* é¡¹ç›®åŒºåŸŸ */
.projects-section {
  margin-bottom: 40rpx;
}
.section-title {
  font-size: 32rpx;
  font-weight: bold;
  color: #333333;
  margin-bottom: 30rpx;
  display: block;
}
.judge-stats,
.organizer-stats {
  font-size: 24rpx;
  color: #1976d2;
  font-weight: 500;
}
.pending-count,
.active-count {
  padding: 8rpx 16rpx;
  background: #e3f2fd;
  border-radius: 20rpx;
}
.menu-grid {
.project-list {
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
  gap: 20rpx;
}
.menu-item {
  flex: 0 0 calc(33.333% - 14rpx);
.project-card {
  background: #ffffff;
  border-radius: 16rpx;
  padding: 30rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 30rpx 20rpx;
  background: #f8f9fa;
  border-radius: 12rpx;
  border: 2rpx solid transparent;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
  transition: all 0.3s ease;
}
.menu-item:active {
  background: #e9ecef;
  border-color: #1976d2;
.project-card:active {
  transform: scale(0.98);
}
.menu-icon-wrapper {
  position: relative;
  margin-bottom: 16rpx;
}
.menu-icon {
  font-size: 48rpx;
}
.badge {
  position: absolute;
  top: -8rpx;
  right: -8rpx;
  min-width: 32rpx;
  height: 32rpx;
  background: #ff4757;
  color: #ffffff;
.project-a .project-icon {
  background: #2e7d32;
  width: 80rpx;
  height: 80rpx;
  border-radius: 16rpx;
  font-size: 20rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 8rpx;
  font-weight: bold;
}
.menu-title {
  font-size: 26rpx;
  font-weight: bold;
  color: #333333;
  margin-bottom: 8rpx;
  text-align: center;
}
.menu-desc {
  font-size: 20rpx;
  color: #666666;
  text-align: center;
  line-height: 1.4;
}
/* åŠŸèƒ½èœå•æ ·å¼ */
.menu-section {
  background: #ffffff;
  border-radius: 16rpx;
  padding: 30rpx;
  margin-bottom: 30rpx;
  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
}
.menu-list {
  margin-top: 20rpx;
}
.menu-item-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 30rpx 0;
  border-bottom: 1rpx solid #f0f0f0;
  transition: background 0.3s ease;
}
.menu-item-row:last-child {
  border-bottom: none;
}
.menu-item-row:active {
  background: #f8f9fa;
}
.menu-left {
  display: flex;
  align-items: center;
  flex: 1;
}
.menu-item-row .menu-icon {
  font-size: 40rpx;
  margin-right: 24rpx;
}
.menu-text {
  flex: 1;
}
.menu-item-row .menu-title {
  display: block;
  font-size: 28rpx;
  font-weight: 500;
  color: #333333;
  margin-bottom: 6rpx;
}
.menu-item-row .menu-desc {
  display: block;
  font-size: 22rpx;
  color: #666666;
}
.menu-arrow {
  font-size: 28rpx;
  color: #cccccc;
  font-weight: bold;
}
/* æœ€è¿‘报名样式 */
.recent-section {
  background: #ffffff;
.project-b .project-icon {
  background: #66bb6a;
  width: 80rpx;
  height: 80rpx;
  border-radius: 16rpx;
  padding: 30rpx;
  margin-bottom: 30rpx;
  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
}
.view-more {
  font-size: 24rpx;
  color: #1976d2;
  font-weight: 500;
}
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 80rpx 0;
}
.empty-icon {
  font-size: 80rpx;
  margin-bottom: 20rpx;
  opacity: 0.5;
}
.empty-text {
  font-size: 26rpx;
  color: #999999;
}
.registration-list {
  margin-top: 20rpx;
}
.registration-item {
  display: flex;
  align-items: center;
  padding: 24rpx 0;
  border-bottom: 1rpx solid #f0f0f0;
  transition: background 0.3s ease;
}
.registration-item:last-child {
  border-bottom: none;
}
.registration-item:active {
  background: #f8f9fa;
}
.activity-cover {
  width: 120rpx;
  height: 80rpx;
  border-radius: 8rpx;
  margin-right: 20rpx;
}
.activity-cover-placeholder {
  width: 120rpx;
  height: 80rpx;
  border-radius: 8rpx;
  margin-right: 20rpx;
  background: linear-gradient(135deg, #42a5f5 0%, #1976d2 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 24rpx;
}
.activity-cover-text {
  color: #ffffff;
  font-size: 24rpx;
  font-weight: bold;
.icon-plant,
.icon-trophy {
  font-size: 36rpx;
}
.registration-info {
.project-info {
  flex: 1;
}
.activity-title {
  display: block;
  font-size: 28rpx;
.project-name {
  font-size: 30rpx;
  font-weight: bold;
  color: #333333;
  margin-bottom: 8rpx;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.registration-time,
.activity-time {
  display: block;
  font-size: 22rpx;
  color: #666666;
  margin-bottom: 6rpx;
  margin-bottom: 8rpx;
}
.status-row {
.project-desc {
  font-size: 24rpx;
  color: #999999;
  display: block;
}
.project-arrow {
  font-size: 28rpx;
  color: #cccccc;
}
/* å…¶ä»–菜单区域 */
.other-menu-section {
  background: #ffffff;
  border-radius: 16rpx;
  overflow: hidden;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
.menu-item-simple {
  display: flex;
  align-items: center;
  gap: 16rpx;
  padding: 30rpx;
  border-bottom: 1rpx solid #f0f0f0;
  transition: background-color 0.3s ease;
}
.registration-status,
.activity-status {
  padding: 4rpx 12rpx;
  border-radius: 12rpx;
  font-size: 20rpx;
  font-weight: 500;
.menu-item-simple:last-child {
  border-bottom: none;
}
.registration-status.status-pending {
  background: #fff3cd;
  color: #856404;
.menu-item-simple:active {
  background-color: #f8f8f8;
}
.registration-status.status-approved {
  background: #d4edda;
  color: #155724;
.menu-icon {
  font-size: 32rpx;
  margin-right: 24rpx;
  width: 40rpx;
  text-align: center;
}
.registration-status.status-rejected {
  background: #f8d7da;
  color: #721c24;
.menu-title {
  flex: 1;
  font-size: 28rpx;
  color: #333333;
}
.registration-status.status-cancelled {
  background: #f1f3f4;
  color: #5f6368;
}
.activity-status {
  background: #e3f2fd;
  color: #1976d2;
}
.item-arrow {
.menu-arrow {
  font-size: 24rpx;
  color: #cccccc;
  font-weight: bold;
  margin-left: 16rpx;
}
/* é€€å‡ºç™»å½•样式 */
.logout-section {
  margin-top: 40rpx;
}
.logout-btn {
  background: #ffffff;
  border: 2rpx solid #ff4757;
  border-radius: 12rpx;
  padding: 30rpx 0;
  text-align: center;
  transition: all 0.3s ease;
}
.logout-btn:active {
  background: #ff4757;
}
.logout-text {
  font-size: 28rpx;
  color: #ff4757;
  font-weight: bold;
}
.logout-btn:active .logout-text {
  color: #ffffff;
}
/* å“åº”式适配 */
@media screen and (max-width: 375px) {
  .profile-content {
    padding: 0 20rpx;
  }
  .user-card {
    padding: 30rpx;
  }
  .avatar {
    width: 100rpx;
    height: 100rpx;
    margin-right: 20rpx;
  }
  .username {
    font-size: 32rpx;
  }
  .stats-section,
  .role-section,
  .menu-section,
  .recent-section {
    padding: 24rpx;
  }
  .menu-item {
    flex: 0 0 calc(50% - 10rpx);
    padding: 24rpx 16rpx;
  }
  .stat-number {
    font-size: 40rpx;
  }
}
@media screen and (min-width: 414px) {
  .activity-cover {
    width: 140rpx;
    height: 90rpx;
  }
  .menu-item {
    padding: 36rpx 24rpx;
  }
  .menu-icon {
    font-size: 52rpx;
  }
}