feat(miniapp): improve session navigation and auth guard
This commit is contained in:
@@ -2,9 +2,14 @@ const {
|
||||
checkAuth,
|
||||
createAgentRun,
|
||||
getAgentRun,
|
||||
loadSession
|
||||
loadSession,
|
||||
logout
|
||||
} = require('../../utils/api');
|
||||
const { AGENT_RUN_MAX_POLLS, AGENT_RUN_POLL_MS } = require('../../utils/config');
|
||||
const {
|
||||
AGENT_RUN_MAX_POLLS,
|
||||
AGENT_RUN_POLL_MS,
|
||||
SELECTED_SESSION_KEY
|
||||
} = require('../../utils/config');
|
||||
const { createUserMessage, normalizeMessages } = require('../../utils/messages');
|
||||
|
||||
function delay(ms) {
|
||||
@@ -17,6 +22,7 @@ Page({
|
||||
messages: [],
|
||||
draft: '',
|
||||
loading: false,
|
||||
error: '',
|
||||
scrollIntoView: ''
|
||||
},
|
||||
|
||||
@@ -25,6 +31,14 @@ Page({
|
||||
const status = await checkAuth();
|
||||
if (!status?.authenticated) {
|
||||
wx.redirectTo({ url: '/pages/login/index' });
|
||||
return;
|
||||
}
|
||||
const selectedSessionId = wx.getStorageSync(SELECTED_SESSION_KEY);
|
||||
if (selectedSessionId) {
|
||||
wx.removeStorageSync(SELECTED_SESSION_KEY);
|
||||
if (selectedSessionId !== this.data.sessionId) {
|
||||
await this.openSession(selectedSessionId);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
wx.redirectTo({ url: '/pages/login/index' });
|
||||
@@ -49,7 +63,7 @@ Page({
|
||||
...this.data.messages,
|
||||
{ id: userMessage.id, role: 'user', text }
|
||||
];
|
||||
this.setData({ messages: nextMessages, draft: '', loading: true });
|
||||
this.setData({ messages: nextMessages, draft: '', loading: true, error: '' });
|
||||
this.scrollToBottom();
|
||||
|
||||
try {
|
||||
@@ -61,6 +75,7 @@ Page({
|
||||
const run = await createAgentRun(payload);
|
||||
await this.waitForRun(run?.id || run?.runId);
|
||||
} catch (error) {
|
||||
this.setData({ error: error?.message || '发送失败' });
|
||||
wx.showToast({ title: error?.message || '发送失败', icon: 'none' });
|
||||
} finally {
|
||||
this.setData({ loading: false });
|
||||
@@ -92,6 +107,35 @@ Page({
|
||||
async refreshSession(sessionId) {
|
||||
const detail = await loadSession(sessionId);
|
||||
const messages = normalizeMessages(detail?.messages || detail?.data?.messages || []);
|
||||
this.setData({ messages });
|
||||
this.setData({ sessionId, messages, error: '' });
|
||||
},
|
||||
|
||||
async openSession(sessionId) {
|
||||
this.setData({ loading: true, error: '' });
|
||||
try {
|
||||
await this.refreshSession(sessionId);
|
||||
} catch (error) {
|
||||
this.setData({ error: error?.message || '会话加载失败' });
|
||||
} finally {
|
||||
this.setData({ loading: false });
|
||||
this.scrollToBottom();
|
||||
}
|
||||
},
|
||||
|
||||
startNewChat() {
|
||||
wx.removeStorageSync(SELECTED_SESSION_KEY);
|
||||
this.setData({ sessionId: '', messages: [], draft: '', error: '' });
|
||||
},
|
||||
|
||||
async handleLogout() {
|
||||
this.setData({ loading: true, error: '' });
|
||||
try {
|
||||
await logout();
|
||||
wx.redirectTo({ url: '/pages/login/index' });
|
||||
} catch (error) {
|
||||
this.setData({ error: error?.message || '退出失败' });
|
||||
} finally {
|
||||
this.setData({ loading: false });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
<view class="page chat-page">
|
||||
<view class="chat-header">
|
||||
<view class="chat-title">
|
||||
<text>{{sessionId ? '继续会话' : '新会话'}}</text>
|
||||
<text wx:if="{{error}}" class="header-error">{{error}}</text>
|
||||
</view>
|
||||
<view class="header-actions">
|
||||
<button class="header-button" bindtap="startNewChat">新聊天</button>
|
||||
<button class="header-button" bindtap="handleLogout">退出</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view class="messages" scroll-y scroll-into-view="{{scrollIntoView}}">
|
||||
<view wx:if="{{messages.length === 0 && !loading}}" class="empty-state">
|
||||
<text>发一条消息开始使用 TKMind。</text>
|
||||
</view>
|
||||
<view wx:for="{{messages}}" wx:key="id" id="msg-{{index}}" class="message {{item.role}}">
|
||||
<text>{{item.text}}</text>
|
||||
</view>
|
||||
|
||||
@@ -5,12 +5,63 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.chat-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16rpx;
|
||||
padding: 20rpx 24rpx;
|
||||
background: #ffffff;
|
||||
border-bottom: 1rpx solid #dbe3eb;
|
||||
}
|
||||
|
||||
.chat-title {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4rpx;
|
||||
min-width: 0;
|
||||
font-size: 30rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.header-error {
|
||||
max-width: 420rpx;
|
||||
color: #b42318;
|
||||
font-size: 22rpx;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.header-button {
|
||||
width: 112rpx;
|
||||
height: 58rpx;
|
||||
line-height: 58rpx;
|
||||
border-radius: 10rpx;
|
||||
background: #eef6f5;
|
||||
color: #0f766e;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.messages {
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
padding: 28rpx;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
margin: 160rpx auto 0;
|
||||
color: #64748b;
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.message {
|
||||
max-width: 84%;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const {
|
||||
checkAuth,
|
||||
loginWithPassword,
|
||||
loginWithWechatCode
|
||||
} = require('../../utils/api');
|
||||
@@ -13,6 +14,17 @@ Page({
|
||||
passwordLoading: false
|
||||
},
|
||||
|
||||
async onLoad() {
|
||||
try {
|
||||
const status = await checkAuth();
|
||||
if (status?.authenticated) {
|
||||
wx.switchTab({ url: '/pages/chat/index' });
|
||||
}
|
||||
} catch {
|
||||
// Stay on the login page when the existing session cannot be verified.
|
||||
}
|
||||
},
|
||||
|
||||
handleUsername(event) {
|
||||
this.setData({ username: event.detail.value, error: '' });
|
||||
},
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const { listSessions } = require('../../utils/api');
|
||||
const { checkAuth, listSessions } = require('../../utils/api');
|
||||
const { SELECTED_SESSION_KEY } = require('../../utils/config');
|
||||
|
||||
function formatTime(value) {
|
||||
const timestamp = Number(value || 0);
|
||||
@@ -15,7 +16,20 @@ Page({
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.loadSessions();
|
||||
this.ensureAndLoad();
|
||||
},
|
||||
|
||||
async ensureAndLoad() {
|
||||
try {
|
||||
const status = await checkAuth();
|
||||
if (!status?.authenticated) {
|
||||
wx.redirectTo({ url: '/pages/login/index' });
|
||||
return;
|
||||
}
|
||||
await this.loadSessions();
|
||||
} catch {
|
||||
wx.redirectTo({ url: '/pages/login/index' });
|
||||
}
|
||||
},
|
||||
|
||||
async loadSessions() {
|
||||
@@ -40,6 +54,7 @@ Page({
|
||||
openSession(event) {
|
||||
const id = event.currentTarget.dataset.id;
|
||||
if (!id) return;
|
||||
wx.setStorageSync(SELECTED_SESSION_KEY, id);
|
||||
wx.switchTab({ url: '/pages/chat/index' });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { listMindSpacePages } = require('../../utils/api');
|
||||
const { checkAuth, listMindSpacePages } = require('../../utils/api');
|
||||
|
||||
Page({
|
||||
data: {
|
||||
@@ -8,7 +8,20 @@ Page({
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.loadPages();
|
||||
this.ensureAndLoad();
|
||||
},
|
||||
|
||||
async ensureAndLoad() {
|
||||
try {
|
||||
const status = await checkAuth();
|
||||
if (!status?.authenticated) {
|
||||
wx.redirectTo({ url: '/pages/login/index' });
|
||||
return;
|
||||
}
|
||||
await this.loadPages();
|
||||
} catch {
|
||||
wx.redirectTo({ url: '/pages/login/index' });
|
||||
}
|
||||
},
|
||||
|
||||
async loadPages() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
module.exports = {
|
||||
API_BASE_URL: 'https://h5.tkmind.cn',
|
||||
MINIAPP_LOGIN_PATH: '/auth/wechat-miniapp/login',
|
||||
SELECTED_SESSION_KEY: 'tkmind_selected_session_id',
|
||||
AGENT_RUN_POLL_MS: 1200,
|
||||
AGENT_RUN_MAX_POLLS: 120
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user