feat: 电子药箱小程序 - 4Tab药品管理
- 电子药箱: 药品库存管理 + 手动录入 + 今日用药打卡 - 药品百科: 搜索 + 分类筛选 + 20种药品静态数据 - 惠教中心: 4条药品使用指南课程 - 我的: 家庭成员信息管理 - 自定义TabBar + navigation-bar组件 - SVG药品分类插图
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
import { request } from "./request";
|
||||
|
||||
export const formatTime = (date: Date) => {
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth() + 1
|
||||
const day = date.getDate()
|
||||
const hour = date.getHours()
|
||||
const minute = date.getMinutes()
|
||||
const second = date.getSeconds()
|
||||
|
||||
return (
|
||||
[year, month, day].map(formatNumber).join('/') +
|
||||
' ' +
|
||||
[hour, minute, second].map(formatNumber).join(':')
|
||||
)
|
||||
}
|
||||
|
||||
const formatNumber = (n: number) => {
|
||||
const s = n.toString()
|
||||
return s[1] ? s : '0' + s
|
||||
}
|
||||
|
||||
|
||||
export function useSecondsToHMS(seconds: number) {
|
||||
const hour = Math.floor(seconds / 3600);
|
||||
const minute = Math.floor((seconds - hour * 3600) / 60);
|
||||
const second = Math.floor(seconds - hour * 3600 - minute * 60);
|
||||
let str = '';
|
||||
if (hour > 0) str += `${hour.toString().padStart(2, '0')}:`;
|
||||
str += `${minute.toString().padStart(2, '0')}:`;
|
||||
str += `${second.toString().padStart(2, '0')}`;
|
||||
return str;
|
||||
}
|
||||
|
||||
/**将后端传过来的绝对值px转为相对值rpx,
|
||||
*1rpx为屏幕宽度的750分之1,后台模拟界面写死为375px,
|
||||
*所以1rpx为375/750=0.5px 1px为2rpx
|
||||
*/
|
||||
export function toRpx(px: number): number {
|
||||
return 2 * px
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取红包并拉起微信转账
|
||||
* @param data - 动态请求数据对象
|
||||
* @param url - 请求地址
|
||||
* @param appId - 当前小程序的 appId (也可选择从接口返回或 getAccountInfoSync 获取)
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
export async function receiveRedPacket(data: any, url: string, appId: string): Promise<void> {
|
||||
wx.showLoading({ title: "领取中", mask: true });
|
||||
// 建议移除 3s 延迟。如果为了防抖,建议在外部触发点击事件时处理
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
try {
|
||||
const res = await request<any>({
|
||||
options: {
|
||||
url,
|
||||
method: "POST",
|
||||
data
|
||||
},
|
||||
isLoading: false,
|
||||
});
|
||||
wx.hideLoading();
|
||||
if (res.code !== 200) {
|
||||
const title = res.msg || "领取失败";
|
||||
const duration = res.code === 503 ? 3000 : 1500;
|
||||
wx.showToast({ title, icon: "none", duration });
|
||||
throw new Error(res.msg || "领取失败");
|
||||
}
|
||||
|
||||
const { packageInfo, mchId } = res.data || {};
|
||||
if (!packageInfo || !mchId) {
|
||||
wx.showToast({ title: "领取失败", icon: "none" });
|
||||
throw new Error("领取失败");
|
||||
}
|
||||
|
||||
if (wx.canIUse?.("requestMerchantTransfer")) {
|
||||
// 把回调式 API 包装成 Promise,让调用方能正确捕获成功/失败
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
// @ts-ignore
|
||||
wx.requestMerchantTransfer({
|
||||
mchId,
|
||||
appId,
|
||||
package: packageInfo,
|
||||
success: () => {
|
||||
wx.showToast({ title: "领取成功", icon: "success" });
|
||||
resolve();
|
||||
},
|
||||
fail: (err: any) => {
|
||||
console.error("拉起转账失败:", err);
|
||||
wx.showToast({ title: "领取失败", icon: "none" });
|
||||
reject(new Error(err?.errMsg || "领取失败"));
|
||||
},
|
||||
});
|
||||
});
|
||||
} else {
|
||||
wx.showModal({
|
||||
content: "你的微信版本过低,请更新至最新版本。",
|
||||
showCancel: false,
|
||||
});
|
||||
throw new Error("微信版本过低");
|
||||
}
|
||||
} catch (err: any) {
|
||||
wx.hideLoading();
|
||||
const msg = err?.data?.msg || err?.errMsg || err?.message || "领取失败";
|
||||
wx.showToast({ title: msg, icon: "none" });
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步函数防并发锁
|
||||
* 直接用 lockPromise 包裹原有的点击逻辑
|
||||
handleReceiveClick: lockPromise(async function() {
|
||||
await receiveRedPacket(data, url, appId);
|
||||
})
|
||||
*/
|
||||
/**
|
||||
* 异步函数防并发锁
|
||||
* @param fn - 需要执行的异步函数
|
||||
*/
|
||||
export function lockPromise<T extends any[], R>(
|
||||
fn: (this: any, ...args: T) => Promise<R> | R
|
||||
): (this: any, ...args: T) => Promise<R | void> {
|
||||
let isLocked = false;
|
||||
|
||||
return async function (this: any, ...args: T): Promise<R | void> {
|
||||
// 如果正在执行中,直接返回,返回值为 void
|
||||
if (isLocked) return;
|
||||
|
||||
isLocked = true;
|
||||
try {
|
||||
// 加上 return,确保原函数的返回值能够被向外传递
|
||||
return await fn.apply(this, args);
|
||||
} finally {
|
||||
isLocked = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user