feat: chat integration, tenant admin spec, backend chat service, miniprogram updates, DEMO moved to tmp, XCX-TEST removed, migrations & docs

This commit is contained in:
Neo
2026-03-20 09:02:10 +08:00
parent 3d2e5f8165
commit beb88d5bea
388 changed files with 6436 additions and 25458 deletions

View File

@@ -1,5 +1,5 @@
import { mockTaskDetails } from '../../utils/mock-data'
import type { TaskDetail, Note } from '../../utils/mock-data'
import { fetchTaskDetail } from '../../services/api'
import { sortByTimestamp } from '../../utils/sort'
import { formatRelativeTime } from '../../utils/time'
import { formatMoney } from '../../utils/money'
@@ -130,55 +130,45 @@ Page({
this.loadData(id)
},
loadData(id: string) {
async loadData(id: string) {
this.setData({ pageState: 'loading' })
setTimeout(() => {
try {
const detail = mockTaskDetails.find((t) => t.id === id) || mockTaskDetails[0]
if (!detail) {
this.setData({ pageState: 'empty' })
return
}
// 根据任务类型设置 Banner 背景
let bannerBgSvg = '/assets/images/banner-bg-red-aurora.svg'
if (detail.taskType === 'high_priority') {
bannerBgSvg = '/assets/images/banner-bg-red-aurora.svg'
} else if (detail.taskType === 'priority_recall') {
bannerBgSvg = '/assets/images/banner-bg-orange-aurora.svg'
} else if (detail.taskType === 'relationship') {
bannerBgSvg = '/assets/images/banner-bg-pink-aurora.svg'
} else if (detail.taskType === 'callback') {
bannerBgSvg = '/assets/images/banner-bg-teal-aurora.svg'
}
// 添加更多 mock 备注
const mockNotes: Note[] = [
{ id: 'note-1', content: '已通过微信联系王先生,表示对新到的斯诺克球桌感兴趣,周末可能来体验。', tagType: 'customer', tagLabel: '客户:王先生', createdAt: '2026-03-10T16:30', score: 10 },
{ id: 'note-2', content: '王先生最近出差较多,到店频率降低。建议等他回来后再约。', tagType: 'customer', tagLabel: '客户:王先生', createdAt: '2026-03-05T14:20', score: 7.5 },
{ id: 'note-3', content: '上次到店时推荐了会员续费活动,客户说考虑一下。', tagType: 'customer', tagLabel: '客户:王先生', createdAt: '2026-02-28T18:45', score: 6 },
{ id: 'note-4', content: '客户对今天的服务非常满意,特别提到小燕的教学很专业。', tagType: 'customer', tagLabel: '客户:王先生', createdAt: '2026-02-20T21:15', score: 9.5 },
{ id: 'note-5', content: '完成高优先召回任务。客户反馈最近工作太忙,这周末会来店里。', tagType: 'customer', tagLabel: '客户:王先生', createdAt: '2026-02-15T10:30', score: 8 },
]
// 附加 timeLabel 字段
const notesWithLabel = mockNotes.map((n) => ({
...n,
timeLabel: formatRelativeTime(n.createdAt),
}))
const sorted = sortByTimestamp(notesWithLabel) as (Note & { timeLabel: string })[]
this.updateRelationshipDisplay(detail.heartScore)
this.setData({
pageState: 'normal',
detail,
sortedNotes: sorted,
debugHeartScore: detail.heartScore,
bannerBgSvg,
})
} catch (_e) {
this.setData({ pageState: 'error' })
try {
const detail = await fetchTaskDetail(id)
if (!detail) {
this.setData({ pageState: 'empty' })
return
}
}, 500)
// 根据任务类型设置 Banner 背景
let bannerBgSvg = '/assets/images/banner-bg-red-aurora.svg'
if (detail.taskType === 'high_priority') {
bannerBgSvg = '/assets/images/banner-bg-red-aurora.svg'
} else if (detail.taskType === 'priority_recall') {
bannerBgSvg = '/assets/images/banner-bg-orange-aurora.svg'
} else if (detail.taskType === 'relationship') {
bannerBgSvg = '/assets/images/banner-bg-pink-aurora.svg'
} else if (detail.taskType === 'callback') {
bannerBgSvg = '/assets/images/banner-bg-teal-aurora.svg'
}
// 附加 timeLabel 字段
const notes = detail.notes || []
const notesWithLabel = notes.map((n: Note) => ({
...n,
timeLabel: formatRelativeTime(n.createdAt),
}))
const sorted = sortByTimestamp(notesWithLabel) as (Note & { timeLabel: string })[]
this.updateRelationshipDisplay(detail.heartScore)
this.setData({
pageState: 'normal',
detail,
sortedNotes: sorted,
debugHeartScore: detail.heartScore,
bannerBgSvg,
})
} catch (_e) {
this.setData({ pageState: 'error' })
}
},
/** 更新关系等级显示 */
@@ -340,16 +330,19 @@ Page({
/** 问问助手 */
onAskAssistant() {
const customerId = this.data.detail?.id || ''
// CHANGE 2026-03-20 | T12.2: 从 task-detail 进入 chat 应传 taskId非 customerId
// 使 chat 页面使用 contextType=task 入口,同一 taskId 始终复用同一对话
const taskId = this.data.detail?.id || ''
wx.navigateTo({
url: `/pages/chat/chat?customerId=${customerId}`,
url: `/pages/chat/chat?taskId=${taskId}`,
fail: () => wx.showToast({ title: '页面跳转失败', icon: 'none' }),
})
},
/** 查看全部服务记录 */
onViewAllRecords() {
const customerId = this.data.detail?.id || ''
// CHANGE 2026-03-20 | T12.2: 使用后端返回的 customerId 而非 task id
const customerId = (this.data.detail as any)?.customerId || this.data.detail?.id || ''
wx.navigateTo({
url: `/pages/customer-service-records/customer-service-records?customerId=${customerId}`,
fail: () => wx.showToast({ title: '页面跳转失败', icon: 'none' }),