// 我的界面逻辑
(function() {
let currentUsername = null;
let currentUserInfo = null;
// 超时配置(与后端保持一致)
const TASK_TIMEOUT = 5 * 60 * 1000; // 5分钟超时
// 下载弹窗相关
let downloadConfirmOverlay = null;
let downloadConfirmClose = null;
let downloadOptions = null;
let pendingDownloadUrl = null;
let pendingDownloadFilename = null;
let exportViewFrame = null;
function init() {
// 初始化下载弹窗元素
downloadConfirmOverlay = document.getElementById('downloadConfirmOverlay');
downloadConfirmClose = document.getElementById('downloadConfirmClose');
downloadOptions = document.querySelectorAll('.download-option');
exportViewFrame = document.getElementById('exportViewFrame');
// 加载VIP抠图价格
loadVIPMattingPrice();
// 初始化下载确认弹窗事件
initDownloadConfirmEvents();
bindEvents();
// 延迟加载,确保DOM完全渲染
setTimeout(() => {
loadUserInfo();
loadPoints();
loadAIHistory();
loadPurchaseHistory();
}, 200);
}
/**
* 加载VIP抠图价格
*/
async function loadVIPMattingPrice() {
try {
const response = await fetch('/api/product-pricing');
if (response.ok) {
const result = await response.json();
if (result.success && result.products) {
const vipMattingProduct = result.products.find(p => p.id === 'vip-matting');
const priceEl = document.getElementById('vipMattingPrice');
if (vipMattingProduct && priceEl) {
const price = vipMattingProduct.price || 0;
if (price > 0) {
priceEl.textContent = `${price} Ani币`;
} else {
priceEl.textContent = '免费';
}
}
}
}
} catch (error) {
console.error('[ExportView] 加载VIP抠图价格失败:', error);
const priceEl = document.getElementById('vipMattingPrice');
if (priceEl) {
priceEl.textContent = '-';
}
}
}
function bindEvents() {
// 返回按钮
const backBtn = document.getElementById('backBtn');
if (backBtn) {
backBtn.addEventListener('click', () => {
// 如果在 iframe 中,通过 postMessage 通知父窗口切换页面
if (window.parent && window.parent !== window) {
window.parent.postMessage({
type: 'navigation',
page: 'store'
}, '*');
} else {
// 独立页面,直接跳转到主页面
window.location.href = '../../index.html';
}
});
}
// 头像上传功能已移除
// 充值按钮
const rechargeBtn = document.getElementById('rechargeBtn');
if (rechargeBtn) {
rechargeBtn.addEventListener('click', () => {
// 打开充值界面(通过postMessage通知父窗口,如果是独立页面则直接打开)
if (window.parent && window.parent !== window) {
window.parent.postMessage({
type: 'open-recharge-view'
}, '*');
} else {
// 独立页面,需要创建充值iframe
openRechargeView();
}
});
}
// 退出登录按钮
const logoutBtn = document.getElementById('logoutBtn');
if (logoutBtn) {
logoutBtn.addEventListener('click', handleLogout);
}
// 监听消息
window.addEventListener('message', (event) => {
if (event.data && event.data.type === 'recharge-success') {
loadPoints(); // 刷新点数
closeRechargeView(); // 关闭充值界面
} else if (event.data && event.data.type === 'close-recharge-view') {
closeRechargeView();
} else if (event.data && event.data.type === 'open-recharge-view') {
// 如果充值iframe发送消息,也打开充值界面
openRechargeView();
} else if (event.data && event.data.type === 'refresh-points') {
// 刷新点数(购买成功后触发)
loadPoints();
loadPurchaseHistory(); // 同时刷新购买记录
} else if (event.data && event.data.type === 'refresh-ai-history') {
// 刷新AI历史(生图请求成功后触发)
loadAIHistory();
} else if (event.data && (event.data.type === 'close-export-view' || event.data.type === 'export-confirmed')) {
hideExportViewFrame();
} else if (event.data && event.data.type === 'export-view-ready') {
// 内容准备好后显示 iframe
showExportViewFrame();
}
});
}
// 打开充值界面
function openRechargeView() {
const rechargeFrame = document.getElementById('rechargeViewFrame');
if (rechargeFrame) {
rechargeFrame.style.display = 'block';
rechargeFrame.style.pointerEvents = 'auto';
rechargeFrame.style.visibility = 'visible';
// 发送消息给充值iframe
const sendRechargeData = () => {
if (rechargeFrame.contentWindow) {
rechargeFrame.contentWindow.postMessage({
type: 'open-recharge-view'
}, '*');
} else {
setTimeout(sendRechargeData, 100);
}
};
sendRechargeData();
const handleLoad = () => {
setTimeout(() => {
sendRechargeData();
}, 50);
};
if (rechargeFrame.contentDocument && rechargeFrame.contentDocument.readyState === 'complete') {
handleLoad();
} else {
rechargeFrame.addEventListener('load', handleLoad, { once: true });
}
}
}
// 关闭充值界面
function closeRechargeView() {
const rechargeFrame = document.getElementById('rechargeViewFrame');
if (rechargeFrame) {
rechargeFrame.style.display = 'none';
rechargeFrame.style.pointerEvents = 'none';
rechargeFrame.style.visibility = 'hidden';
}
}
// 显示导出视图 iframe
function showExportViewFrame() {
if (!exportViewFrame) return;
exportViewFrame.style.display = 'block';
exportViewFrame.style.pointerEvents = 'auto';
exportViewFrame.style.visibility = 'visible';
}
// 隐藏导出视图 iframe
function hideExportViewFrame() {
if (!exportViewFrame) return;
exportViewFrame.style.display = 'none';
exportViewFrame.style.pointerEvents = 'none';
exportViewFrame.style.visibility = 'hidden';
}
// 显示下载确认弹窗
function showDownloadConfirm(imageUrl, fileName) {
pendingDownloadUrl = imageUrl;
pendingDownloadFilename = fileName || 'ai-image';
if (downloadConfirmOverlay) {
downloadConfirmOverlay.style.display = 'flex';
}
}
// 隐藏下载确认弹窗
function hideDownloadConfirm() {
if (downloadConfirmOverlay) {
downloadConfirmOverlay.style.display = 'none';
}
pendingDownloadUrl = null;
pendingDownloadFilename = null;
}
// 初始化下载弹窗事件
function initDownloadConfirmEvents() {
// 关闭按钮
if (downloadConfirmClose) {
downloadConfirmClose.addEventListener('click', hideDownloadConfirm);
}
// 点击遮罩关闭
if (downloadConfirmOverlay) {
downloadConfirmOverlay.addEventListener('click', (e) => {
if (e.target === downloadConfirmOverlay) {
hideDownloadConfirm();
}
});
}
// 下载选项点击
if (downloadOptions) {
downloadOptions.forEach(option => {
option.addEventListener('click', () => {
const downloadType = option.getAttribute('data-option');
handleDownloadOption(downloadType);
});
});
}
}
// 处理下载选项
async function handleDownloadOption(downloadType) {
if (!pendingDownloadUrl) {
console.error('[Profile] 没有待下载的图片');
return;
}
hideDownloadConfirm();
// 根据下载类型处理
if (downloadType === 'original') {
// 直接下载原始图片
downloadImage(pendingDownloadUrl, pendingDownloadFilename);
} else {
// 普通抠图或VIP抠图,使用 iframe 处理
// iframe 会在准备好后发送 'export-view-ready' 消息,此时再显示
if (exportViewFrame) {
const sendData = () => {
try {
exportViewFrame.contentWindow.postMessage({
type: 'show-export-preview',
imageUrl: pendingDownloadUrl,
fileName: pendingDownloadFilename,
skipPreviewUI: true,
directDownloadType: downloadType // 传递下载类型
}, '*');
// iframe 会在准备好后发送 'export-view-ready' 消息
} catch (error) {
console.error('[Profile] 发送导出数据失败:', error);
hideExportViewFrame();
downloadImage(pendingDownloadUrl, pendingDownloadFilename);
}
};
if (exportViewFrame.contentDocument && exportViewFrame.contentDocument.readyState === 'complete') {
setTimeout(sendData, 50);
} else {
exportViewFrame.addEventListener('load', () => setTimeout(sendData, 50), { once: true });
let baseSrc = exportViewFrame.getAttribute('data-base-src');
if (!baseSrc) {
baseSrc = exportViewFrame.src.split('?')[0];
exportViewFrame.setAttribute('data-base-src', baseSrc);
}
exportViewFrame.src = `${baseSrc}?t=${Date.now()}`;
}
} else {
downloadImage(pendingDownloadUrl, pendingDownloadFilename);
}
}
}
// 打开导出视图并传递图片数据
function openExportView(imageUrl, fileName, options = {}) {
if (!imageUrl) {
return;
}
// 如果是跳过预览UI(直接下载),显示下载选择弹窗
if (options.skipPreviewUI) {
showDownloadConfirm(imageUrl, fileName);
return;
}
if (!exportViewFrame) {
downloadImage(imageUrl, fileName || 'ai-image');
return;
}
showExportViewFrame();
const sendPreviewData = () => {
try {
exportViewFrame.contentWindow.postMessage({
type: 'show-export-preview',
imageUrl: imageUrl,
fileName: fileName || 'ai-image',
skipPreviewUI: false
}, '*');
} catch (error) {
console.error('[Profile] 发送导出预览数据失败:', error);
hideExportViewFrame();
downloadImage(imageUrl, fileName || 'ai-image');
}
};
const handleLoad = () => {
setTimeout(sendPreviewData, 50);
};
if (exportViewFrame.contentDocument && exportViewFrame.contentDocument.readyState === 'complete') {
handleLoad();
} else {
exportViewFrame.addEventListener('load', handleLoad, { once: true });
let baseSrc = exportViewFrame.getAttribute('data-base-src');
if (!baseSrc) {
baseSrc = exportViewFrame.src.split('?')[0];
exportViewFrame.setAttribute('data-base-src', baseSrc);
}
exportViewFrame.src = `${baseSrc}?t=${Date.now()}`;
}
}
// 加载用户信息
async function loadUserInfo() {
const username = getCurrentUsername();
if (!username) {
// 未登录,跳转到登录页
window.location.href = '../../index.html';
return;
}
currentUsername = username;
// 先从localStorage读取用户信息作为备用
try {
const loginDataStr = localStorage.getItem('loginData');
if (loginDataStr) {
const loginData = JSON.parse(loginDataStr);
if (loginData.user) {
// 先显示localStorage中的用户信息
displayUserInfo(loginData.user);
}
}
} catch (error) {
console.error('[Profile] 从localStorage读取用户信息失败:', error);
}
// 然后从API获取最新信息
try {
const response = await fetch(`/api/user/info?username=${encodeURIComponent(username)}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
if (result.success && result.user) {
currentUserInfo = result.user;
displayUserInfo(result.user);
} else {
console.error('[Profile] API返回数据格式错误:', result);
}
} catch (error) {
console.error('[Profile] 加载用户信息失败:', error);
// 如果API调用失败,至少显示localStorage中的信息
if (window.parent && window.parent.HintView) {
window.parent.HintView.error('加载用户信息失败,显示缓存信息', 2000);
}
}
}
// 手机号脱敏处理
function maskPhone(phone) {
if (!phone || phone.length < 7) {
return phone;
}
// 保留前3位和后4位,中间用*代替
const start = phone.substring(0, 3);
const end = phone.substring(phone.length - 4);
const middle = '*'.repeat(phone.length - 7);
return start + middle + end;
}
// 显示用户信息
function displayUserInfo(user) {
if (!user) {
console.error('[Profile] 用户信息为空');
return;
}
// 使用函数来确保元素存在
const setUserInfo = () => {
const avatarImage = document.getElementById('avatarImage');
const usernameInput = document.getElementById('usernameInput');
const phoneInput = document.getElementById('phoneInput');
if (avatarImage) {
let avatarUrl = user.avatar;
if (avatarUrl && !avatarUrl.startsWith('http') && !avatarUrl.startsWith('data:')) {
avatarUrl = 'http://localhost:3000' + (avatarUrl.startsWith('/') ? avatarUrl : '/' + avatarUrl);
}
avatarImage.src = avatarUrl || '../../static/default-avatar.png';
avatarImage.onerror = function() {
this.src = '../../static/default-avatar.png';
};
}
if (usernameInput) {
usernameInput.value = user.username || '';
}
if (phoneInput) {
const phone = user.phone || '';
phoneInput.value = maskPhone(phone);
}
};
// 如果元素还没准备好,等待一下再试
if (!document.getElementById('usernameInput') || !document.getElementById('phoneInput')) {
setTimeout(setUserInfo, 100);
} else {
setUserInfo();
}
}
// 加载点数
async function loadPoints() {
const username = getCurrentUsername();
if (!username) return;
try {
const response = await fetch(`/api/user/points?username=${encodeURIComponent(username)}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
if (result.success) {
const pointsValue = document.getElementById('pointsValue');
if (pointsValue) {
const points = parseFloat(result.points || 0);
pointsValue.textContent = points.toFixed(2);
}
}
} catch (error) {
console.error('[Profile] 加载点数失败:', error);
}
}
// 处理退出登录
function handleLogout() {
if (confirm('确定要退出登录吗?')) {
// 清除localStorage
localStorage.removeItem('loginData');
// 通知父窗口(如果是在iframe中)
if (window.parent && window.parent !== window) {
window.parent.postMessage({
type: 'logout'
}, '*');
}
// 跳转到登录页
window.location.href = '../../index.html';
}
}
// 加载AI生图历史
async function loadAIHistory() {
const username = getCurrentUsername();
if (!username) return;
const historyLoading = document.getElementById('historyLoading');
const historyEmpty = document.getElementById('historyEmpty');
const historyGrid = document.getElementById('historyGrid');
if (historyLoading) {
historyLoading.style.display = 'block';
}
if (historyEmpty) {
historyEmpty.style.display = 'none';
}
if (historyGrid) {
historyGrid.innerHTML = '';
}
try {
const response = await fetch(`/api/ai/history?username=${encodeURIComponent(username)}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
if (historyLoading) {
historyLoading.style.display = 'none';
}
if (result.success && result.history && result.history.length > 0) {
if (historyGrid) {
result.history.forEach(item => {
const historyItem = createHistoryItem(item);
historyGrid.appendChild(historyItem);
});
}
} else {
if (historyEmpty) {
historyEmpty.style.display = 'block';
}
}
// 如果有正在处理的任务,定期刷新
if (result.success && result.history) {
const hasProcessing = result.history.some(item => item.status === 'rendering' || item.status === 'queued');
if (hasProcessing) {
setTimeout(loadAIHistory, 3000); // 3秒后刷新
}
}
} catch (error) {
console.error('[Profile] 加载AI历史失败:', error);
if (historyLoading) {
historyLoading.style.display = 'none';
}
if (historyEmpty) {
historyEmpty.style.display = 'block';
}
}
}
// 创建历史记录项
function createHistoryItem(item) {
const div = document.createElement('div');
div.className = 'history-item';
div.dataset.taskId = item.id;
// 格式化时间 - 显示具体年月日时分秒
const formatTime = (dateString) => {
if (!dateString) return '';
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};
const timeText = formatTime(item.createdAt);
// 预览图URL(模糊显示)
const previewUrl = item.previewUrl || '';
// 计算已等待时间
const calculateElapsedTime = () => {
const startTime = item.renderStartTime || new Date(item.createdAt).getTime();
const elapsed = Date.now() - startTime;
const mins = Math.floor(elapsed / 60000);
const secs = Math.floor((elapsed % 60000) / 1000);
return `已等待 ${mins}:${String(secs).padStart(2, '0')}`;
};
if (item.status === 'rendering' || item.status === 'queued') {
div.classList.add(item.status);
const statusText = item.status === 'rendering' ? '正在生成' : '等待中';
const elapsedText = (item.status === 'rendering' || item.status === 'queued') ? calculateElapsedTime() : '';
div.innerHTML = `
${previewUrl ? `` : ''}