- 电子药箱: 药品库存管理 + 手动录入 + 今日用药打卡 - 药品百科: 搜索 + 分类筛选 + 20种药品静态数据 - 惠教中心: 4条药品使用指南课程 - 我的: 家庭成员信息管理 - 自定义TabBar + navigation-bar组件 - SVG药品分类插图
258 lines
5.6 KiB
TypeScript
258 lines
5.6 KiB
TypeScript
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 });
|
|
},
|
|
},
|
|
});
|