Files
game_server/API_COMPLETION_TIMESTAMP.md

7.0 KiB
Raw Permalink Blame History

Game Interface API - 完成时间戳快速参考

📡 接口

GET /api/link/{codeNo}/game-interface

📊 响应字段(新增)

completedAt - 完成时间戳

字段 类型 说明 示例
completedAt Long 秒级Unix时间戳 1730644245
status String 任务状态 "COMPLETED"

💡 特点

  • 秒级时间戳10位数字1730644245
  • 仅完成时有值:只有 status === "COMPLETED" 时才有值
  • 其他状态为null:未完成的任务返回 null

🎯 响应示例

任务完成时

{
  "codeNo": "MYNM5JHA",
  "status": "COMPLETED",
  "completedAt": 1730644245,
  "completedPoints": 1000,
  "totalPoints": 1000,
  "homepageUrl": "https://uzi1.cn/api/link/completion/MYNM5JHA/homepage.png",
  "firstRewardUrl": "https://uzi1.cn/api/link/completion/MYNM5JHA/first-reward.png",
  "midRewardUrl": "https://uzi1.cn/api/link/completion/MYNM5JHA/mid-reward.png",
  "endRewardUrl": "https://uzi1.cn/api/link/completion/MYNM5JHA/end-reward.png",
  ...
}

任务进行中

{
  "codeNo": "MYNM5JHA",
  "status": "LOGGED_IN",
  "completedAt": null,
  "completedPoints": null,
  "homepageUrl": "https://uzi1.cn/api/link/image/MYNM5JHA/homepage.png",
  ...
}

🔧 前端使用JavaScript

基础用法

fetch(`/api/link/${codeNo}/game-interface`)
  .then(res => res.json())
  .then(data => {
    if (data.status === 'COMPLETED' && data.completedAt) {
      // 秒级时间戳需要 * 1000 转换为毫秒
      const completedTime = new Date(data.completedAt * 1000);
      console.log('完成时间:', completedTime.toLocaleString('zh-CN'));
    }
  });

格式化时间

// 方法1: 原生 JavaScript
const formatTimestamp = (timestamp) => {
  const date = new Date(timestamp * 1000);  // 秒转毫秒
  return date.toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit'
  });
};

console.log(formatTimestamp(1730644245));
// 输出: 2025/11/03 20:30:45

// 方法2: 使用 dayjs
import dayjs from 'dayjs';
console.log(dayjs.unix(1730644245).format('YYYY-MM-DD HH:mm:ss'));
// 输出: 2025-11-03 20:30:45

// 方法3: 使用 moment
import moment from 'moment';
console.log(moment.unix(1730644245).format('YYYY-MM-DD HH:mm:ss'));
// 输出: 2025-11-03 20:30:45

计算完成多久

const getTimeAgo = (timestamp) => {
  const completedTime = new Date(timestamp * 1000);
  const now = new Date();
  const diffSeconds = Math.floor((now - completedTime) / 1000);
  
  if (diffSeconds < 60) return `${diffSeconds} 秒前`;
  
  const diffMins = Math.floor(diffSeconds / 60);
  if (diffMins < 60) return `${diffMins} 分钟前`;
  
  const diffHours = Math.floor(diffMins / 60);
  if (diffHours < 24) return `${diffHours} 小时前`;
  
  const diffDays = Math.floor(diffHours / 24);
  return `${diffDays} 天前`;
};

console.log(getTimeAgo(1730644245));
// 输出: 5 分钟前

🎨 Vue 组件示例

<template>
  <div v-if="gameData">
    <!-- 状态徽章 -->
    <div class="status-badge" :class="statusClass">
      {{ statusText }}
    </div>
    
    <!-- 完成信息仅完成时显示 -->
    <div v-if="gameData.status === 'COMPLETED'" class="completion-info">
      <div class="completion-time">
        <span class="label">完成时间:</span>
        <span class="value">{{ formattedCompletedTime }}</span>
      </div>
      <div class="time-ago">{{ completedAgo }}</div>
      <div class="points">
        完成点数: {{ gameData.completedPoints }} / {{ gameData.totalPoints }}
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';

const gameData = ref(null);

// 状态类名
const statusClass = computed(() => {
  const classMap = {
    'NEW': 'status-new',
    'USING': 'status-using',
    'LOGGED_IN': 'status-logged-in',
    'COMPLETED': 'status-completed',
    'REFUNDED': 'status-refunded',
    'EXPIRED': 'status-expired'
  };
  return classMap[gameData.value?.status] || 'status-default';
});

// 状态文本
const statusText = computed(() => {
  const textMap = {
    'NEW': '等待开始',
    'USING': '使用中',
    'LOGGED_IN': '游戏中',
    'COMPLETED': '已完成',
    'REFUNDED': '已退款',
    'EXPIRED': '已过期'
  };
  return textMap[gameData.value?.status] || '未知';
});

// 格式化完成时间
const formattedCompletedTime = computed(() => {
  if (gameData.value?.completedAt) {
    const date = new Date(gameData.value.completedAt * 1000);
    return date.toLocaleString('zh-CN');
  }
  return '';
});

// 完成多久前
const completedAgo = computed(() => {
  if (!gameData.value?.completedAt) return '';
  
  const completedTime = new Date(gameData.value.completedAt * 1000);
  const now = new Date();
  const diffSeconds = Math.floor((now - completedTime) / 1000);
  
  if (diffSeconds < 60) return `${diffSeconds} 秒前`;
  const diffMins = Math.floor(diffSeconds / 60);
  if (diffMins < 60) return `${diffMins} 分钟前`;
  const diffHours = Math.floor(diffMins / 60);
  if (diffHours < 24) return `${diffHours} 小时前`;
  const diffDays = Math.floor(diffHours / 24);
  return `${diffDays} 天前`;
});

// 加载数据
const loadGameData = async (codeNo) => {
  const res = await fetch(`/api/link/${codeNo}/game-interface`);
  gameData.value = await res.json();
};
</script>

<style scoped>
.status-badge {
  display: inline-block;
  padding: 6px 16px;
  border-radius: 20px;
  font-weight: 600;
  font-size: 14px;
}

.status-completed {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
}

.completion-info {
  margin-top: 16px;
  padding: 16px;
  background: #f8f9fa;
  border-radius: 8px;
}

.completion-time {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.time-ago {
  color: #6c757d;
  font-size: 13px;
}
</style>

🔍 时间戳对照表

时间戳 日期时间(北京时间)
1730644245 2025-11-03 20:30:45
1730640000 2025-11-03 19:20:00
1730635200 2025-11-03 18:00:00

🧪 快速测试

# 测试接口
curl "http://localhost:18080/api/link/MYNM5JHA/game-interface" | jq '.completedAt'

# 转换时间戳Linux/Mac
date -r 1730644245
# 或
date -d @1730644245

常见时间处理库

JavaScript

# dayjs (推荐 - 轻量)
npm install dayjs

# moment.js (功能强大)
npm install moment

# date-fns (函数式)
npm install date-fns

使用 dayjs

import dayjs from 'dayjs';

// 格式化
dayjs.unix(1730644245).format('YYYY-MM-DD HH:mm:ss');

// 相对时间
import relativeTime from 'dayjs/plugin/relativeTime';
import 'dayjs/locale/zh-cn';
dayjs.extend(relativeTime);
dayjs.locale('zh-cn');
dayjs.unix(1730644245).fromNow();  // "5分钟前"

更新时间: 2025-11-03
格式: Unix时间戳秒级
状态: 已完成