type GuideMenuItem = { key: string; label: string; icon: string; }; interface GuidePopupProperties { show: boolean; title: string; subtitle: string; images: string[]; amount: string; } interface GuidePopupData { mounted: boolean; visible: boolean; displayName: string; displaySubtitle: string; avatarUrl: string; avatarLetter: string; balanceLabel: string; withdrawText: string; incomeText: string; menuItems: GuideMenuItem[]; } interface GuidePopupInstance extends WechatMiniprogram.Component.TrivialInstance { data: GuidePopupData; properties: GuidePopupProperties; _hideTimer?: number | null; } const DEFAULT_NAME = "当前用户"; const DEFAULT_ENTRY = "个人中心"; const DEFAULT_BALANCE_LABEL = "可提现金额"; const DEFAULT_WITHDRAW_TEXT = "立即提现"; const DEFAULT_INCOME_TEXT = "收益明细"; const HIDE_DELAY = 280; const DEFAULT_MENU_ITEMS: GuideMenuItem[] = [ { key: "orders", label: "我的订单", icon: "./icons/orders.svg", }, { key: "prize-records", label: "中奖记录", icon: "./icons/gift.svg", }, { key: "coupons", label: "我的优惠券", icon: "./icons/coupon.svg", }, { key: "comment-board", label: "评论记录板", icon: "./icons/comment.svg", }, { key: "nickname", label: "修改昵称", icon: "./icons/edit.svg", }, { key: "complaint", label: "投诉", icon: "./icons/warning.svg", }, ]; function normalizeImages(value: unknown): string[] { if (!Array.isArray(value)) return []; return value.filter( (item): item is string => typeof item === "string" && item.length > 0, ); } function syncViewModel( instance: GuidePopupInstance, titleText: string, subtitleText: string, imageList: string[], ) { const name = titleText || wx.getStorageSync("userName") || DEFAULT_NAME; const subtitle = subtitleText || DEFAULT_ENTRY; const avatarUrl = imageList.length ? imageList[0] : ""; const avatarLetter = String(name).trim().slice(0, 1).toUpperCase() || "U"; instance.setData({ displayName: name, displaySubtitle: subtitle, avatarUrl, avatarLetter, }); } function clearHideTimer(instance: GuidePopupInstance) { if (!instance._hideTimer) return; clearTimeout(instance._hideTimer); instance._hideTimer = null; } function togglePopup(instance: GuidePopupInstance, show: boolean) { clearHideTimer(instance); if (show) { if (instance.data.mounted) { wx.nextTick(() => { instance.setData({ visible: true }); }); return; } instance.setData( { mounted: true, visible: false, }, () => { wx.nextTick(() => { instance.setData({ visible: true }); }); }, ); return; } if (!instance.data.mounted) return; instance.setData({ visible: false }); instance._hideTimer = setTimeout(() => { instance.setData({ mounted: false }); instance._hideTimer = null; }, HIDE_DELAY); } Component({ properties: { show: { type: Boolean, value: false, observer(this: GuidePopupInstance, nextValue: boolean) { togglePopup(this, !!nextValue); }, }, title: { type: String, value: "", observer(this: GuidePopupInstance, nextValue: string) { syncViewModel( this, nextValue || "", this.properties.subtitle || "", normalizeImages(this.properties.images), ); }, }, subtitle: { type: String, value: "", observer(this: GuidePopupInstance, nextValue: string) { syncViewModel( this, this.properties.title || "", nextValue || "", normalizeImages(this.properties.images), ); }, }, images: { type: Array, value: [], observer(this: GuidePopupInstance, nextValue: unknown) { syncViewModel( this, this.properties.title || "", this.properties.subtitle || "", normalizeImages(nextValue), ); }, }, amount: { type: String, value: "0.00", }, }, data: { mounted: false, visible: false, displayName: DEFAULT_NAME, displaySubtitle: DEFAULT_ENTRY, avatarUrl: "", avatarLetter: "U", balanceLabel: DEFAULT_BALANCE_LABEL, withdrawText: DEFAULT_WITHDRAW_TEXT, incomeText: DEFAULT_INCOME_TEXT, menuItems: DEFAULT_MENU_ITEMS, } as GuidePopupData, lifetimes: { attached(this: GuidePopupInstance) { syncViewModel( this, this.properties.title || "", this.properties.subtitle || "", normalizeImages(this.properties.images), ); togglePopup(this, !!this.properties.show); }, detached(this: GuidePopupInstance) { clearHideTimer(this); }, }, methods: { noop() {}, handleClose(this: GuidePopupInstance) { this.triggerEvent("close"); }, handlePreviewAvatar(this: GuidePopupInstance) { const images = normalizeImages(this.properties.images); if (!images.length) return; wx.previewImage({ current: images[0], urls: images, }); }, handleQuickAction( this: GuidePopupInstance, e: WechatMiniprogram.CustomEvent, ) { const key = (e.currentTarget.dataset as { key?: string }).key || ""; if (!key) return; this.triggerEvent("action", { key }); }, handleMenuTap(this: GuidePopupInstance, e: WechatMiniprogram.CustomEvent) { const key = (e.currentTarget.dataset as { key?: string }).key || ""; if (!key) return; this.triggerEvent("action", { key }); }, }, });