import dayjs from "dayjs"; import PageContainerBehavior from "../../../../core/behavior/page-container.behavior"; import I18nBehavior from "../../../../i18n/behavior"; // module/chats/pages/index/index.ts interface ScrollIntoViewEvent { detail: string; } interface HandleEvent { detail: { component: "guide" | "questionnaire"; scroll?: boolean }; } interface NextTypeEvent { detail: { messageType: number }; } interface Message extends Omit { id: string; } function getScrollcontext(this: any) { return this as { scroll: WechatMiniprogram.ScrollViewContext; timer: number; }; } Component({ behaviors: [I18nBehavior, PageContainerBehavior], lifetimes: { attached() { this.setData({ date: dayjs().format("MM-DD HH:mm:ss"), }); const component = this.data.component as "guide" | "questionnaire"; // 若路由指定进入 guide,确保展示 guide if (component === "guide") { this.setData({ isShowGuide: true }); } this.handle({ detail: { component, scroll: true } }); // 计算底部bottom const systemInfo = wx.getSystemInfoSync(); const windowHeight = systemInfo.windowHeight; const safeAreaBottom = systemInfo.safeArea?.bottom ?? windowHeight; // 没有safeArea时,bottom等于windowHeight const safeBottom = windowHeight - safeAreaBottom; // 安全区底部距离(px) const safeBottomRpx = (750 / systemInfo.windowWidth) * safeBottom; // rpx this.setData({ paddingBottom: this.data.paddingBottom + safeBottomRpx, }); }, ready() { wx.createSelectorQuery() .select("#scrollview") .node() .exec((res) => { getScrollcontext.call(this).scroll = res[0].node; }); }, }, properties: { component: { type: String, value: "guide" }, messageType: { type: Number, value: 0 }, isShowGuide: { type: Boolean, value: false }, id: { type: Number, value: 0 }, }, data: { i18n: { chats: { title: '聊天', analysis: '测评' }, }, date: "", messages: {} as Record, lastId: "", inputBoxBottom: 0, tabbarValue: "/module/chats/pages/index/index", analysisCount: 0, paddingBottom: 100, // 底部tabbar高度是100 }, observers: { "messages.**"(messages) { const message = Object.values(messages).pop() as Message; this.setData({ lastId: message?.id }); }, }, methods: { boxBottom(event: boxBottom) { // 直接使用子组件传递的 inputBoxBottom 值 this.setData({ inputBoxBottom: event.detail.inputBoxBottom, }); // 更新 scroll-view 的 padding-bottom,确保内容不被输入框遮挡 this.setData({ paddingBottom: event.detail.inputBoxBottom, }); }, nextType(event: NextTypeEvent) { this.setData({ messageType: event.detail.MessageType }); }, getCount(event: GetCountEvent) { this.setData({ analysisCount: event.detail.analysisCount }); }, handle(event: HandleEvent) { const index = Object.keys(this.data.messages).length; this.setData({ [`messages.${index}`]: { id: `${this.is.replace(/\//g, "_")}-${index}`, component: event.detail?.component, }, }); // 当切换到 guide 时,强制显示 guide if (event.detail?.component === "guide") { this.setData({ isShowGuide: true }); } if (event.detail?.scroll) this.scrollIntoView(); }, scrollIntoView(event?: ScrollIntoViewEvent) { clearTimeout(getScrollcontext.call(this).timer); const id = event?.detail ?? this.data.lastId; const doScroll = ( scroll: WechatMiniprogram.ScrollViewContext | undefined ) => { if (!scroll) return; if (id === "bottom") { // 使用 scrollIntoView 滚动到 #bottom 元素,实现平滑滚动 scroll.scrollIntoView(`#bottom`, { alignment: "end" }); } else if (id) { scroll.scrollIntoView(`#${id}`, { alignment: "end" }); } // 再补一次,处理内容异步渲染晚于滚动触发的情况 // setTimeout(() => { // if (id === "bottom") { // // 使用 scrollIntoView 滚动到 #bottom 元素,实现平滑滚动 // scroll.scrollIntoView(`#bottom`, { alignment: "end" }); // } else if (id) { // scroll.scrollIntoView(`#${id}`, { alignment: "end" }); // } // }, 200); }; getScrollcontext.call(this).timer = setTimeout(() => { let scroll = getScrollcontext.call(this).scroll; if (!scroll) { // 若还未拿到scroll上下文,立即尝试获取后再滚动 wx.createSelectorQuery() .select("#scrollview") .node() .exec((res) => { getScrollcontext.call(this).scroll = res?.[0]?.node; doScroll(getScrollcontext.call(this).scroll); }); } else { doScroll(scroll); } }, 300); }, }, });