feat: 用户对话数据同步到backend + 用户资料修改同步
This commit is contained in:
212
www/app.js
212
www/app.js
@@ -1620,14 +1620,43 @@ function showEditProfilePage() {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取完整用户信息
|
||||
const users = JSON.parse(localStorage.getItem('registeredUsers') || '[]');
|
||||
const fullUser = users.find(u => u.username === currentUser.username);
|
||||
|
||||
// 如果用户已登录且有ID,从 backend 获取完整用户信息
|
||||
if (currentUser.id) {
|
||||
fetch(`/api/admin/users/${currentUser.id}`)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data && data.id) {
|
||||
// 更新 currentUser 的完整信息
|
||||
currentUser.avatar = data.avatar || '👤';
|
||||
currentUser.signature = data.signature || '';
|
||||
currentUser.email = data.email || '';
|
||||
currentUser.gender = data.gender || '';
|
||||
currentUser.age = data.age || '';
|
||||
currentUser.region = data.region || '';
|
||||
currentUser.phone = data.phone || '';
|
||||
|
||||
// 渲染编辑页面
|
||||
renderEditProfilePage();
|
||||
} else {
|
||||
// 使用本地数据
|
||||
renderEditProfilePage();
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
// 使用本地数据
|
||||
renderEditProfilePage();
|
||||
});
|
||||
} else {
|
||||
// 游客用户,使用本地数据
|
||||
renderEditProfilePage();
|
||||
}
|
||||
}
|
||||
|
||||
function renderEditProfilePage() {
|
||||
const avatar = currentUser.avatar || '👤';
|
||||
const signature = currentUser.signature || '';
|
||||
const phone = fullUser?.phone || '';
|
||||
const email = fullUser?.email || '';
|
||||
const phone = currentUser.phone || '';
|
||||
const email = currentUser.email || '';
|
||||
const gender = currentUser.gender || '';
|
||||
const age = currentUser.age || '';
|
||||
const region = currentUser.region || '';
|
||||
@@ -1773,26 +1802,6 @@ function handleSaveProfile() {
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查用户名是否被其他人占用
|
||||
const users = JSON.parse(localStorage.getItem('registeredUsers') || '[]');
|
||||
if (newUsername !== currentUser.username) {
|
||||
if (users.find(u => u.username === newUsername)) {
|
||||
showToast('用户名已被占用');
|
||||
return;
|
||||
}
|
||||
// 更新用户名
|
||||
const userIndex = users.findIndex(u => u.username === currentUser.username);
|
||||
if (userIndex >= 0) {
|
||||
users[userIndex].username = newUsername;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新邮箱
|
||||
const userIndex = users.findIndex(u => u.username === currentUser.username);
|
||||
if (userIndex >= 0) {
|
||||
users[userIndex].email = newEmail;
|
||||
}
|
||||
|
||||
// 更新 currentUser
|
||||
currentUser.avatar = newAvatar;
|
||||
currentUser.username = newUsername;
|
||||
@@ -1800,12 +1809,42 @@ function handleSaveProfile() {
|
||||
currentUser.gender = newGender;
|
||||
currentUser.age = newAge ? parseInt(newAge) : '';
|
||||
currentUser.region = newRegion;
|
||||
currentUser.email = newEmail;
|
||||
|
||||
saveCurrentUser();
|
||||
localStorage.setItem('registeredUsers', JSON.stringify(users));
|
||||
|
||||
showToast('保存成功');
|
||||
switchPage('profile');
|
||||
// 如果用户已登录,调用 backend API 更新
|
||||
if (currentUser.id) {
|
||||
fetch(`/api/user/${currentUser.id}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
username: newUsername,
|
||||
email: newEmail,
|
||||
avatar: newAvatar,
|
||||
signature: newSignature,
|
||||
gender: newGender,
|
||||
age: newAge ? parseInt(newAge) : null,
|
||||
region: newRegion
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
saveCurrentUser();
|
||||
showToast('保存成功');
|
||||
switchPage('profile');
|
||||
} else {
|
||||
showToast(data.error || '保存失败');
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
showToast('网络错误,请重试');
|
||||
});
|
||||
} else {
|
||||
// 未登录用户,保存到本地
|
||||
saveCurrentUser();
|
||||
showToast('保存成功');
|
||||
switchPage('profile');
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 消息通知页面 ====================
|
||||
@@ -2466,8 +2505,12 @@ function handleLogin() {
|
||||
registeredAt: Date.now()
|
||||
};
|
||||
saveCurrentUser();
|
||||
showToast('登录成功');
|
||||
showMainPage();
|
||||
|
||||
// 从 backend 加载用户对话数据
|
||||
loadUserConversations().then(() => {
|
||||
showToast('登录成功');
|
||||
showMainPage();
|
||||
});
|
||||
} else {
|
||||
showToast(data.error || '用户名或密码错误');
|
||||
}
|
||||
@@ -2633,8 +2676,12 @@ function handleRegister() {
|
||||
registeredAt: Date.now()
|
||||
};
|
||||
saveCurrentUser();
|
||||
showToast('注册成功');
|
||||
showMainPage();
|
||||
|
||||
// 加载对话数据(新用户为空)
|
||||
loadUserConversations().then(() => {
|
||||
showToast('注册成功');
|
||||
showMainPage();
|
||||
});
|
||||
} else {
|
||||
showToast(data.error || '注册失败');
|
||||
}
|
||||
@@ -3496,6 +3543,17 @@ function deleteConversation(id) {
|
||||
|
||||
conversations = conversations.filter(c => c.id !== id);
|
||||
saveConversations();
|
||||
|
||||
// 如果用户已登录,从 backend 删除
|
||||
if (currentUser && currentUser.id) {
|
||||
const convId = parseInt(id);
|
||||
if (convId > 0) {
|
||||
fetch(`/api/user/${currentUser.id}/conversations/${convId}`, {
|
||||
method: 'DELETE'
|
||||
}).catch(e => console.error('删除对话失败:', e));
|
||||
}
|
||||
}
|
||||
|
||||
showConversationList();
|
||||
}
|
||||
|
||||
@@ -4166,7 +4224,91 @@ function setupScrollListener() {
|
||||
|
||||
// 保存对话列表
|
||||
function saveConversations() {
|
||||
// 保存到本地存储(离线可用)
|
||||
localStorage.setItem('conversations', JSON.stringify(conversations));
|
||||
|
||||
// 如果用户已登录,同步到 backend
|
||||
if (currentUser && currentUser.id) {
|
||||
syncConversationsToBackend();
|
||||
}
|
||||
}
|
||||
|
||||
// 同步对话数据到 backend
|
||||
async function syncConversationsToBackend() {
|
||||
if (!currentUser || !currentUser.id) return;
|
||||
|
||||
try {
|
||||
// 批量同步所有对话
|
||||
for (const conv of conversations) {
|
||||
const convId = parseInt(conv.id);
|
||||
if (convId > 0) {
|
||||
// 更新现有对话
|
||||
await fetch(`/api/user/${currentUser.id}/conversations/${convId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
title: conv.title,
|
||||
messages: conv.messages,
|
||||
agentId: conv.agentId
|
||||
})
|
||||
});
|
||||
} else {
|
||||
// 新对话,需要创建
|
||||
const res = await fetch(`/api/user/${currentUser.id}/conversations`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
title: conv.title,
|
||||
messages: conv.messages,
|
||||
agentId: conv.agentId
|
||||
})
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.success && data.id) {
|
||||
// 更新本地ID为backend ID
|
||||
conv.id = data.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// 同步失败,静默处理(下次登录时会重新加载)
|
||||
console.error('同步对话失败:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// 从 backend 加载用户对话数据
|
||||
async function loadUserConversations() {
|
||||
if (!currentUser || !currentUser.id) return;
|
||||
|
||||
try {
|
||||
const res = await fetch(`/api/user/${currentUser.id}/conversations`);
|
||||
const data = await res.json();
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
// 合并本地和云端数据(云端优先)
|
||||
const localConvIds = conversations.map(c => c.id);
|
||||
|
||||
for (const cloudConv of data) {
|
||||
const localIdx = localConvIds.indexOf(cloudConv.id);
|
||||
if (localIdx >= 0) {
|
||||
// 更新本地对话(云端数据优先)
|
||||
conversations[localIdx] = cloudConv;
|
||||
} else {
|
||||
// 添加云端对话
|
||||
conversations.push(cloudConv);
|
||||
}
|
||||
}
|
||||
|
||||
// 按更新时间排序
|
||||
conversations.sort((a, b) => b.updatedAt - a.updatedAt);
|
||||
|
||||
// 保存到本地
|
||||
localStorage.setItem('conversations', JSON.stringify(conversations));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载对话失败:', e);
|
||||
// 使用本地数据
|
||||
}
|
||||
}
|
||||
|
||||
// 显示提示
|
||||
|
||||
Reference in New Issue
Block a user