feat: 电子药箱小程序 - 4Tab药品管理
- 电子药箱: 药品库存管理 + 手动录入 + 今日用药打卡 - 药品百科: 搜索 + 分类筛选 + 20种药品静态数据 - 惠教中心: 4条药品使用指南课程 - 我的: 家庭成员信息管理 - 自定义TabBar + navigation-bar组件 - SVG药品分类插图
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"popup": "/components/popup/popup",
|
||||
"van-stepper": "@vant/weapp/stepper/index",
|
||||
"sku-item":"/components/static/sku-item/sku-item",
|
||||
"coupon-popup":"../coupon-popup/coupon-popup"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/* components/static/good-detail-popup/good-detail-popup.wxss */
|
||||
@import "variables";
|
||||
|
||||
.popup-header {
|
||||
.location {
|
||||
min-height: 60rpx;
|
||||
width: 100%;
|
||||
color: $primary-color;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
// align-items:end;
|
||||
border-bottom: 1rpx solid rgba(0, 0, 0, 0.1);
|
||||
.icon {
|
||||
min-width: 40rpx;
|
||||
line-height: 60rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
.address{
|
||||
padding-bottom: $primary-gap;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
margin-top: $primary-gap;
|
||||
|
||||
.left {
|
||||
border-radius: $primary-border-radius;
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
overflow: hidden;
|
||||
margin-right: $primary-gap;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
;
|
||||
|
||||
.price {
|
||||
color: $primary-color;
|
||||
font-size: $x-large-font-size;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.count {
|
||||
width: 400rpx;
|
||||
}
|
||||
|
||||
.stock {
|
||||
font-size: $large-font-size;
|
||||
color: $gray-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sku-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// max-height: 500rpx;
|
||||
// margin-bottom: 54rpx;
|
||||
.skuTitle {
|
||||
font-size: $large-font-size;
|
||||
font-weight: 600;
|
||||
margin: $primary-gap 0rpx;
|
||||
}
|
||||
.scroll {
|
||||
max-height: 500rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
// gap: $primary-gap;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 702rpx;
|
||||
|
||||
.submit {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
background: $primary-color;
|
||||
color: white;
|
||||
font-size: $large-font-size;
|
||||
font-weight: 600;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
border-radius: 0rpx $primary-border-radius $primary-border-radius 0rpx;
|
||||
}
|
||||
.submit1 {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
background: $primary-color;
|
||||
color: white;
|
||||
font-size: $large-font-size;
|
||||
font-weight: 600;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.add-cart {
|
||||
background-color: #FEB30C;
|
||||
border-radius: $primary-border-radius 0rpx 0rpx $primary-border-radius ;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
// components/static/good-detail-popup/good-detail-popup.ts
|
||||
import { request } from "../../../utils/request";
|
||||
import { getAddress } from "../../../utils/get-address";
|
||||
import { appId, shopId } from "../../../env";
|
||||
import { wxRequestSubscribe } from "../../../utils/wx-api";
|
||||
// @ts-ignore
|
||||
const systemInfo = wx.getWindowInfo();
|
||||
const app = getApp<IAppOption>();
|
||||
Component({
|
||||
properties: {
|
||||
mode: {
|
||||
// one: 单规格, list: 多规格
|
||||
type: String,
|
||||
value: "one",
|
||||
},
|
||||
skuId: Number,
|
||||
spuId: Number,
|
||||
hasTabBar: Boolean,
|
||||
showShopCart: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
joinedGroupI9d: {
|
||||
type: String,
|
||||
value: null,
|
||||
},
|
||||
},
|
||||
|
||||
data: {
|
||||
goodList: {},
|
||||
showPopup: false,
|
||||
swiperList: [],
|
||||
count: 1,
|
||||
checkItem: null,
|
||||
skus: [],
|
||||
addressId: null,
|
||||
defualtAddress: "未知地址",
|
||||
safeBottom: getApp().globalData.safeBottom,
|
||||
showStock: app.globalData.showStock,
|
||||
selectedCoupon: null //选择的优惠券
|
||||
},
|
||||
|
||||
methods: {
|
||||
async openPopup(this: WechatMiniprogram.Component.TrivialInstance) {
|
||||
await this.handleGetInfo();
|
||||
this.setData({ showPopup: true });
|
||||
},
|
||||
|
||||
closePopup(this: WechatMiniprogram.Component.TrivialInstance) {
|
||||
this.setData({ showPopup: false });
|
||||
},
|
||||
|
||||
async handleGetInfo(this: WechatMiniprogram.Component.TrivialInstance) {
|
||||
await getAddress(this);
|
||||
|
||||
let api = "";
|
||||
let params = {};
|
||||
|
||||
if (this.data.mode === "one") {
|
||||
api = "/app/shop-store/sku-one";
|
||||
params = { id: Number(this.data.skuId) };
|
||||
} else {
|
||||
api = "/app/shop-store/sku-list";
|
||||
params = { id: Number(this.data.spuId) };
|
||||
}
|
||||
|
||||
try {
|
||||
const res: any = await request({
|
||||
options: { url: api, data: params },
|
||||
loadingTitle: "获取商品信息中",
|
||||
needLogin: false,
|
||||
});
|
||||
|
||||
let swiperList: string[] = [];
|
||||
let checkItem = null;
|
||||
|
||||
if (this.data.mode === "one") {
|
||||
// 单规格
|
||||
swiperList = res.sliderPicUrls?.filter(Boolean) || [res.picUrl];
|
||||
checkItem = res;
|
||||
} else {
|
||||
// 多规格
|
||||
swiperList = res.sliderPicUrls?.filter(Boolean);
|
||||
|
||||
if ((!swiperList || !swiperList.length) && res.skus) {
|
||||
swiperList = res.skus.map((s: any) => s.picUrl ?? s.picUrl);
|
||||
}
|
||||
|
||||
// 找到默认可售SKU
|
||||
checkItem = res.skus.find((s: any) => s.stock > 0) || res.skus[0];
|
||||
|
||||
// 给goodList添加最低价
|
||||
const min = res.skus.reduce((p: any, c: any) =>
|
||||
c.price < p.price ? c : p
|
||||
);
|
||||
res.price = min.price;
|
||||
}
|
||||
|
||||
this.setData({
|
||||
goodList: res,
|
||||
skus: this.data.mode === "one" ? [res] : res.skus,
|
||||
swiperList,
|
||||
checkItem,
|
||||
skuId: checkItem.skuId,
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
wx.showToast({ icon: "none", title: "商品信息获取失败" });
|
||||
} finally {
|
||||
wx.hideLoading();
|
||||
}
|
||||
},
|
||||
|
||||
/** SKU 切换 */
|
||||
onSetSkuId(e: any) {
|
||||
const that = this as any;
|
||||
const checkItem = e.detail.checkItem;
|
||||
if (that.data.checkItem?.skuId === checkItem.skuId) {
|
||||
that.setData({ checkItem: null, skuId: null });
|
||||
return;
|
||||
}
|
||||
if (checkItem.stock < 1) {
|
||||
return wx.showToast({ icon: "none", title: "库存不足" });
|
||||
}
|
||||
that.setData({ checkItem, skuId: checkItem.skuId });
|
||||
},
|
||||
|
||||
onCountChange(e: any) {
|
||||
const that = this as any;
|
||||
that.setData({ count: e.detail });
|
||||
},
|
||||
|
||||
/** 下单 */
|
||||
async handleSubmit() {
|
||||
const that = this as any;
|
||||
if (!app.redirectLogin()) return;
|
||||
if (!that.data.checkItem) {
|
||||
return wx.showToast({ title: "未选择商品!", icon: "none", duration: 2000 });
|
||||
}
|
||||
if (that.data.checkItem.price == 0) return wx.showToast({ title: "暂无报价", icon: "none", duration: 3000 });
|
||||
if (that.data.count > that.data.checkItem.stock) {
|
||||
if (!that.data.showStock) {
|
||||
return wx.showToast({ title: "暂无报价", icon: "none", duration: 2000 });
|
||||
}
|
||||
return wx.showToast({ title: "库存不足!", icon: "none", duration: 2000 });
|
||||
}
|
||||
if (!that.data.addressId || !that.data.defualtAddress) {
|
||||
wx.showToast({ title: "请先填写地址!", icon: "none", duration: 2000 });
|
||||
wx.navigateTo({ url: "/pages/common/location/location" })
|
||||
return
|
||||
}
|
||||
const value = {
|
||||
addressId: that.data.addressId,
|
||||
userId: wx.getStorageSync("userId"),
|
||||
mbuId: wx.getStorageSync("mbuId"),
|
||||
appId,
|
||||
goods: [{ id: that.data.skuId, count: that.data.count }],
|
||||
shopId,
|
||||
type: 1
|
||||
} as any;
|
||||
if (that.data.joinedGroupId) value.roomId = that.data.joinedGroupId;
|
||||
if (that.data.selectedCoupon) {
|
||||
value.couponIds = that.data.selectedCoupon.couponIds;
|
||||
}
|
||||
let subscribeTmplIds = [] as any[];
|
||||
try {
|
||||
const subscribe = await wxRequestSubscribe(['3gO2ryTGiXvUWhMgjMH8il3CyBrYmPaO0AR_gwsx69M', 'ts3RBa4gtlEEAtPomEyr4l1Bt1C8PAjbD7-jvtpddkg']) as any;
|
||||
subscribeTmplIds = Object.entries(subscribe)
|
||||
.filter(([id, status]) => status === 'accept')
|
||||
.map(([id]) => id);
|
||||
if (subscribeTmplIds.length > 0) {
|
||||
value.subscribeTmplIds = subscribeTmplIds;
|
||||
}
|
||||
} catch (e: any) {
|
||||
console.log(e, '下单失败')
|
||||
}
|
||||
try {
|
||||
wx.showLoading({ title: "下单中" });
|
||||
const res: any = await request({
|
||||
options: { url: "/app/app-pay/js-api", data: value },
|
||||
});
|
||||
|
||||
wx.requestPayment({
|
||||
...res.data,
|
||||
package: res.data.packageVal,
|
||||
success: () => {
|
||||
wx.switchTab({ url: "/pages/tab-bar/user/user" });
|
||||
wx.showToast({ title: "支付成功" });
|
||||
},
|
||||
fail() {
|
||||
wx.showToast({ title: "支付取消", icon: "none" });
|
||||
},
|
||||
complete: () => wx.hideLoading(),
|
||||
});
|
||||
} catch (err) {
|
||||
wx.hideLoading();
|
||||
console.log(err, '下单失败')
|
||||
wx.showToast({ title: "下单失败", icon: "none" });
|
||||
}
|
||||
},
|
||||
|
||||
// 选优惠券下单
|
||||
async handleBeforeSubmit() {
|
||||
const that = this as any;
|
||||
if (!app.redirectLogin()) return;
|
||||
if (!that.data.checkItem) {
|
||||
return wx.showToast({ title: "未选择商品!", icon: "none", duration: 2000 });
|
||||
}
|
||||
if (that.data.checkItem.price == 0) return wx.showToast({ title: "暂无报价", icon: "none", duration: 3000 });
|
||||
if (that.data.count > that.data.checkItem.stock) {
|
||||
if (!that.data.showStock) {
|
||||
return wx.showToast({ title: "暂无报价", icon: "none", duration: 2000 });
|
||||
}
|
||||
return wx.showToast({ title: "库存不足!", icon: "none", duration: 2000 });
|
||||
}
|
||||
if (!that.data.addressId || !that.data.defualtAddress) {
|
||||
wx.showToast({ title: "请先填写地址!", icon: "none", duration: 2000 });
|
||||
wx.navigateTo({ url: "/pages/common/location/location" })
|
||||
return
|
||||
}
|
||||
|
||||
const amount = that.data.checkItem.price * that.data.count;
|
||||
|
||||
// 打开优惠券弹窗
|
||||
that.selectComponent("#couponPopup").handleSwitch(amount);
|
||||
},
|
||||
|
||||
//选择优惠券后
|
||||
onCouponSelect(e: any) {
|
||||
const that = this as any;
|
||||
const { coupon } = e.detail;
|
||||
if (coupon) {
|
||||
that.setData({ selectedCoupon: coupon });
|
||||
} else {
|
||||
that.setData({ selectedCoupon: null });
|
||||
}
|
||||
if (that.data.selectedCoupon !== null) {
|
||||
wx.showToast({
|
||||
title: "已使用优惠券",
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
// 继续下单
|
||||
this.handleSubmit();
|
||||
},
|
||||
|
||||
/** 加购物车 */
|
||||
handleAddCart() {
|
||||
const that = this as any;
|
||||
if (!app.redirectLogin()) return;
|
||||
|
||||
const item = that.data.checkItem;
|
||||
if (!item) return wx.showToast({ title: "未选择商品", icon: "none", duration: 3000 });
|
||||
if (item.price == 0) return wx.showToast({ title: "暂无报价", icon: "none", duration: 3000 });
|
||||
if (that.data.count > item.stock) {
|
||||
if (!that.data.showStock) {
|
||||
return wx.showToast({ title: "暂无报价", icon: "none", duration: 2000 });
|
||||
}
|
||||
return wx.showToast({ title: "库存不足", icon: "none", duration: 3000 });
|
||||
}
|
||||
|
||||
let all = wx.getStorageSync("shoppingCart") || [];
|
||||
const mbuId = wx.getStorageSync("mbuId");
|
||||
|
||||
let cart = all.find((i: any) => i.mbuId == mbuId);
|
||||
if (!cart) {
|
||||
cart = { mbuId, data: [] };
|
||||
all.push(cart);
|
||||
}
|
||||
|
||||
const exist = cart.data.find((i: any) => i.skuId == item.skuId);
|
||||
if (exist) {
|
||||
exist.count += that.data.count;
|
||||
if (exist.count > item.stock) {
|
||||
return wx.showToast({ title: "超过库存限制", icon: "none" });
|
||||
}
|
||||
} else {
|
||||
cart.data.push({ ...item, count: that.data.count });
|
||||
}
|
||||
|
||||
wx.setStorageSync("shoppingCart", all);
|
||||
wx.showToast({ title: "加入购物车成功" });
|
||||
},
|
||||
handleSelcetLocation() {
|
||||
if (!app.redirectLogin()) return;
|
||||
wx.navigateTo({
|
||||
url: "/pages/common/location/location",
|
||||
});
|
||||
},
|
||||
},
|
||||
pageLifetimes: {
|
||||
show() {
|
||||
const that = this as any;
|
||||
if (that.data.showPopup === true) getAddress(this);
|
||||
},
|
||||
},
|
||||
lifetimes: {
|
||||
attached: function () {
|
||||
getAddress(this);
|
||||
},
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
<!--components/static/good-detail-popup/good-detail-popup.wxml-->
|
||||
<popup visible="{{showPopup}}" bind:close="closePopup">
|
||||
<view slot="header" class="popup-header">
|
||||
<view class="location">
|
||||
<image src="/assets/img/location.svg" class="icon"></image>
|
||||
<view class="address" bind:tap="handleSelcetLocation">{{defualtAddress}}</view>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="left">
|
||||
<image src="{{checkItem ? checkItem.picUrl : skus[0].picUrl}}" mode="aspectFill" />
|
||||
</view>
|
||||
<view class="right">
|
||||
<view wx:if="skuId" class="price">
|
||||
{{ checkItem ? checkItem.price?'¥'+checkItem.price/100:'暂无报价' : skus[0].price?'¥'+skus[0].price/100:'暂无报价' }}
|
||||
</view>
|
||||
<!-- 如果不显示库存的话最多可以加到99999去,显示的话就最多可以加到库存量去 -->
|
||||
<van-stepper integer max="{{showStock?checkItem ? checkItem.stock : skus[0].stock :99999}}" value="{{ count }}"
|
||||
bind:change="onCountChange" />
|
||||
<view class="stock" wx:if="{{showStock}}">库存 {{ checkItem ? checkItem.stock : skus[0].stock }}
|
||||
{{checkItem?checkItem.unit:goodList[0].stock}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="sku-container" style="padding-bottom: {{hasTabBar?safeBottom+ 80 + 120 + 24 :safeBottom + 80+24}}rpx;">
|
||||
<view class="skuTitle">商品分类 ({{skus.length}})</view>
|
||||
<scroll-view scroll-y class="scroll">
|
||||
<view wx:for="{{skus}}" wx:key="skuId">
|
||||
<sku-item active="{{(skuId && skuId==item.skuId)?true:false}}" disable="{{item.stock===0?true:false}}"
|
||||
bind:selectsku="onSetSkuId" item="{{item}}" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="footer">
|
||||
<view bind:tap="handleAddCart" class="submit add-cart" wx:if="{{show}}">
|
||||
加入购物车
|
||||
</view>
|
||||
<view class="footer">
|
||||
<view bind:tap="handleAddCart" wx:if="{{showShopCart}}" class="submit add-cart">
|
||||
加入购物车
|
||||
</view>
|
||||
<!-- bind:tap="handleSubmit" -->
|
||||
<view bind:tap="handleBeforeSubmit" class="submit"
|
||||
style="margin-bottom:{{hasTabBar? safeBottom/2 + 140 : safeBottom}}rpx;border-top-left-radius: {{showShopCart?0:24}}rpx;border-Bottom-left-radius: {{showShopCart?0:24}}rpx;">
|
||||
{{ skuId ? ('立即支付 ¥' + (checkItem.price * count / 100)) : '选择商品' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</popup>
|
||||
|
||||
<coupon-popup
|
||||
id="couponPopup"
|
||||
bind:select="onCouponSelect"
|
||||
/>
|
||||
Reference in New Issue
Block a user