feat: 累积功能变更 — 聊天集成、租户管理、小程序更新、ETL 增强、迁移脚本
包含多个会话的累积代码变更: - backend: AI 聊天服务、触发器调度、认证增强、WebSocket、调度器最小间隔 - admin-web: ETL 状态页、任务管理、调度配置、登录优化 - miniprogram: 看板页面、聊天集成、UI 组件、导航更新 - etl: DWS 新任务(finance_area_daily/board_cache)、连接器增强 - tenant-admin: 项目初始化 - db: 19 个迁移脚本(etl_feiqiu 11 + zqyy_app 8) - packages/shared: 枚举和工具函数更新 - tools: 数据库工具、报表生成、健康检查 - docs: PRD/架构/部署/合约文档更新 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
/* AI_CHANGELOG
|
||||
| 日期 | Prompt | 变更 |
|
||||
|------|--------|------|
|
||||
| 2026-03-23 | 角色路由+页面权限守卫 | onShow 添加 checkPageAccess 权限守卫 |
|
||||
*/
|
||||
import { checkPageAccess } from '../../utils/auth-guard'
|
||||
// pages/chat/chat.ts — AI 对话页
|
||||
// CHANGE 2026-03-20 | RNS1.4 T8.1: 多入口参数路由,替换 mock 为真实 API
|
||||
// CHANGE 2026-03-20 | RNS1.4 T8.2: 替换 simulateStreamOutput 为真实 SSE 连接
|
||||
@@ -177,6 +183,10 @@ Page({
|
||||
customerId: '',
|
||||
/** 输入栏距底部距离(软键盘弹出时动态调整)*/
|
||||
inputBarBottom: 0,
|
||||
/** 来源页面标识(看板入口) */
|
||||
sourcePage: '',
|
||||
/** 看板筛选参数 */
|
||||
pageFilters: {} as Record<string, string>,
|
||||
},
|
||||
|
||||
/** 消息计数器,用于生成唯一 ID */
|
||||
@@ -188,6 +198,11 @@ Page({
|
||||
/** 最后一次发送的用户消息内容(用于重试) */
|
||||
_lastUserContent: '',
|
||||
|
||||
onShow() {
|
||||
// 权限守卫:检查登录状态、账号禁用、角色权限
|
||||
checkPageAccess('pages/chat/chat')
|
||||
},
|
||||
|
||||
// CHANGE 2026-03-20 | RNS1.4 T8.1: 多入口参数路由
|
||||
// 优先级:historyId → taskId → customerId → coachId → general
|
||||
onLoad(options) {
|
||||
@@ -210,6 +225,15 @@ Page({
|
||||
} else if (options?.coachId) {
|
||||
// 从 coach-detail 跳转:≤ 3 天复用、> 3 天新建
|
||||
this.loadMessagesByContext('coach', options.coachId)
|
||||
} else if (options?.sourcePage) {
|
||||
// 看板类入口:保存来源页面和筛选参数
|
||||
const filterKeys = ['timeDimension', 'areaFilter', 'dimension', 'typeFilter', 'projectFilter']
|
||||
const pageFilters: Record<string, string> = {}
|
||||
for (const key of filterKeys) {
|
||||
if (options[key]) pageFilters[key] = options[key]
|
||||
}
|
||||
this.setData({ sourcePage: options.sourcePage, pageFilters })
|
||||
this.loadMessagesByContext(options.sourcePage, '')
|
||||
} else {
|
||||
// 无参数入口:始终新建通用对话
|
||||
this.loadMessagesByContext('general', '')
|
||||
@@ -219,6 +243,7 @@ Page({
|
||||
/** 通过 chatId 加载历史消息(historyId 入口) */
|
||||
async loadMessages(chatId: string) {
|
||||
this.setData({ pageState: 'loading' })
|
||||
wx.showLoading({ title: '加载中...', mask: true })
|
||||
try {
|
||||
const res = await fetchChatMessages(chatId)
|
||||
this.setData({ chatId: String(res.chatId) })
|
||||
@@ -231,12 +256,15 @@ Page({
|
||||
this.scrollToBottom()
|
||||
} catch {
|
||||
this.setData({ pageState: 'error' })
|
||||
} finally {
|
||||
wx.hideLoading()
|
||||
}
|
||||
},
|
||||
|
||||
/** 通过上下文类型加载消息(task/customer/coach/general 入口) */
|
||||
async loadMessagesByContext(contextType: string, contextId: string) {
|
||||
this.setData({ pageState: 'loading' })
|
||||
wx.showLoading({ title: '加载中...', mask: true })
|
||||
try {
|
||||
const res = await fetchChatMessagesByContext(contextType, contextId)
|
||||
// 缓存后端返回的 chatId,后续发送消息使用
|
||||
@@ -258,6 +286,8 @@ Page({
|
||||
this.scrollToBottom()
|
||||
} catch {
|
||||
this.setData({ pageState: 'error' })
|
||||
} finally {
|
||||
wx.hideLoading()
|
||||
}
|
||||
},
|
||||
|
||||
@@ -427,7 +457,14 @@ Page({
|
||||
const requestTask = wx.request({
|
||||
url: `${API_BASE}/api/xcx/chat/stream`,
|
||||
method: 'POST',
|
||||
data: { chatId: Number(chatId), content },
|
||||
data: {
|
||||
chatId: Number(chatId),
|
||||
content,
|
||||
...(this.data.sourcePage ? {
|
||||
sourcePage: this.data.sourcePage,
|
||||
pageContext: this.data.pageFilters,
|
||||
} : {}),
|
||||
},
|
||||
header: headers,
|
||||
enableChunked: true,
|
||||
responseType: 'arraybuffer',
|
||||
|
||||
Reference in New Issue
Block a user