2026-07-27 11:26:39 +08:00

509 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page-container" :class="{ 'elder-mode': elderMode }">
<view class="search-container" :class="{ 'search-container--elder': elderMode }">
<view class="search" :class="{ 'search--elder': elderMode }">
<uni-icons class="search-icon" type="search" :size="elderMode ? 36 : 28"></uni-icons>
<input v-model="keyword" type="text" placeholder="搜索药品" class="search-input"
:class="{ 'search-input--elder': elderMode }" />
<view class="search-btn" :class="{ 'search-btn--elder': elderMode }" :style="keyword ? '' : 'opacity:0'"
@click="clear()">取消</view>
</view>
<view class="scan-code flex flex-col items-center" :class="{ 'scan-code--elder': elderMode }" @click="scanCode">
<uni-icons class="" color="#999" type="scan" :size="elderMode ? 36 : 30"></uni-icons>
<view v-if="order.consultType === 'onlineMedicinePurchase'" class="text-dark">条形码</view>
</view>
</view>
<view class="drug-wrapper">
<scroll-view scroll-y="true" class="drug-list" @scrolltolower="loadMore">
<view v-for="drug in list" :key="drug._id" class="drug" :class="{ 'drug--elder': elderMode }"
@click="select(drug)">
<view class="drug-info" :class="{ 'drug-info--elder': elderMode }">
<view class="drug-name" :class="{ 'drug-name--elder': elderMode }">{{ drug.name }}</view>
<view v-if="drug.medication_proof_desc" class="drug-proof-tip"
:class="{ 'drug-proof-tip--elder': elderMode }">{{ proofTipText }}</view>
<view v-if="drug.specification" class="drug-spec" :class="{ 'drug-spec--elder': elderMode }">药品规格:{{
drug.specification }}</view>
<view v-if="drug.manufacturer" class="drug-spec" :class="{ 'drug-spec--elder': elderMode }">{{
drug.manufacturer }}</view>
</view>
<view v-if="selectMap[drug._id]" class="drug-btn drug-btn--unactive"
:class="{ 'drug-btn--elder': elderMode }">已选择</view>
<view v-else class="drug-btn" :class="{ 'drug-btn--elder': elderMode }">选择该药</view>
</view>
<uni-load-more v-if="loading && page > 1" status="loading"></uni-load-more>
<view v-if="list.length === 0 && order.consultType === 'onlineMedicinePurchase'"
class="lack-tip-container flex flex-col items-center justify-center" :style="elderVarStyle">
<image class="lack-img" :class="elderClass" src="/static/empty.svg" />
<view class="text-lg text-dark">搜索不到该药品</view>
<view class="pt-5" @click="showRegPopup()">
<text class="mr-5 text-lg text-dark">您可进行</text>
<text class="text-lg text-primary">缺货登记</text>
</view>
</view>
</scroll-view>
</view>
<view class="my-drugs-container">
<view v-if="showDrugs" class="shopcart-list">
<my-drugs :drugs="drugs" :elderMode="elderMode" @edit="edit" @remove="cancel" />
</view>
</view>
<view class="shopcart-footer" :class="{ 'shopcart-footer--elder': elderMode }" @click="showDrugs = !showDrugs">
<image class="shopcart-icon" :class="{ 'shopcart-icon--elder': elderMode }" src="/static/shopcart.svg" />
<view class="shopcart-text" :class="{ 'shopcart-text--elder': elderMode }">
<text>已选</text>
<text class="shopcart-num" :class="{ 'shopcart-num--elder': elderMode }">{{ drugs.length }}</text>
<text>种药品</text>
</view>
<view class="confirm-btn"
:class="[drugs.length ? '' : 'confirm-btn--unactive', { 'confirm-btn--elder': elderMode }]"
@click.stop="confirm">确认</view>
</view>
<view class="safearea-bottom" style="background: white;"></view>
</view>
<edit-popup :consultType="order.consultType" :drug="editDrug" :visible="showEditPopup" :elderMode="elderMode"
@close="showEditPopup = false" @change="changeDrug" />
<view v-if="showDrugs" class="mask" @click="showDrugs = false"></view>
<lack-reg-popup :order="order" :visible="visible" @close="visible = false" />
<!-- 自定义确认弹窗仅用于本页面 -->
<confirm-popup :visible="customConfirmVisible" :title="customConfirmData.title" :content="customConfirmData.content"
:showCancel="customConfirmData.showCancel" :cancelText="customConfirmData.cancelText"
:confirmText="customConfirmData.confirmText" @confirm="handleCustomConfirm" @cancel="handleCustomCancel"
@close="customConfirmVisible = false" />
</template>
<script setup>
import { computed, ref, onMounted, onUnmounted } from 'vue';
import { storeToRefs } from "pinia";
import { onLoad } from '@dcloudio/uni-app';
import useDebounce from '@/hooks/useDebounce';
import useRefChange from '@/hooks/useRefChange';
import useElder from '@/hooks/useElder';
import orderStore from '@/store/order';
import { getDrugs, getOnlineDrugList } from '@/utils/api'
import { toast } from '@/utils/widget';
import editPopup from './edit-popup.vue'
import myDrugs from './my-drugs.vue'
import lackRegPopup from './lack-reg-popup.vue'
import confirmPopup from '@/components/confirm-popup.vue'
// 长辈模式状态
const { elderMode, elderClass, elderVarStyle } = useElder();
const proofTipText = '*购买该药品需上传用药证明';
const { order } = storeToRefs(orderStore());
const keyword = ref('');
const drugs = ref([]);
const editDrug = ref({})
const editType = ref('add')
const showEditPopup = ref(false)
const showDrugs = ref(false)
const page = ref(1);
const list = ref([]);
const loading = ref(false)
const more = ref(false)
const visible = ref(false)
// 自定义确认弹窗状态(仅用于本页面)
const customConfirmVisible = ref(false);
const customConfirmData = ref({
title: '提示',
content: '',
showCancel: true,
cancelText: '取消',
confirmText: '确定',
onConfirm: null,
onCancel: null
});
const selectMap = computed(() => drugs.value.reduce((acc, cur) => {
acc[cur._id] = true;
return acc
}, {}))
useRefChange(keyword, search);
onLoad(() => {
drugs.value = order.value && Array.isArray(order.value.drugs) ? order.value.drugs.map(i => ({ ...i })) : [];
search()
})
// 监听全局确认弹窗事件(仅用于本页面)
onMounted(() => {
uni.$on('showConfirmPopup_selectDrug', showCustomConfirm);
});
onUnmounted(() => {
uni.$off('showConfirmPopup_selectDrug', showCustomConfirm);
});
function showCustomConfirm(data) {
customConfirmData.value = { ...customConfirmData.value, ...data };
customConfirmVisible.value = true;
}
function handleCustomConfirm() {
if (customConfirmData.value.onConfirm) {
customConfirmData.value.onConfirm();
}
customConfirmVisible.value = false;
customConfirmData.value.onConfirm = null;
customConfirmData.value.onCancel = null;
}
function handleCustomCancel() {
if (customConfirmData.value.onCancel) {
customConfirmData.value.onCancel();
}
customConfirmVisible.value = false;
customConfirmData.value.onConfirm = null;
customConfirmData.value.onCancel = null;
}
function edit(drug) {
showDrugs.value = false;
setTimeout(() => {
select(drug, 'edit')
}, 600);
}
function loadMore() {
if (!loading.value && more.value) {
page.value++;
getList()
}
}
function select(drug = {}, type = 'add') {
if (type === 'add' && drugs.value.length >= 5) {
toast('最多只能选择5种药品')
return
}
editDrug.value = { ...drug };
editType.value = type;
showEditPopup.value = true
}
function showRegPopup() {
visible.value = true
}
function cancel({ _id }) {
drugs.value = drugs.value.filter(item => item._id !== _id)
if (drugs.value.length === 0 && showDrugs.value) {
showDrugs.value = false
}
}
function changeDrug(drug) {
if (editType.value === 'add') {
if (!drugs.value.some(i => i._id === drug._id)) {
drugs.value.push(drug)
}
} else {
const index = drugs.value.findIndex(item => item._id === drug._id)
drugs.value.splice(index, 1, drug)
}
showEditPopup.value = false;
}
function clear() {
keyword.value = ''
}
const confirm = useDebounce(_confirm, 1000);
function _confirm() {
if (drugs.value.length) {
order.value.drugs = drugs.value.map(i => ({ ...i }))
uni.navigateBack()
} else {
toast('请添加药品')
}
}
function search() {
page.value = 1;
loading.value = false;
getList()
}
async function getList() {
if (loading.value) return;
loading.value = true;
const apiName = order.value.consultType === 'onlineMedicinePurchase' ? getOnlineDrugList : getDrugs;
const res = await apiName({ page: page.value, pageSize: 15, keyword: keyword.value });
const listData = res && Array.isArray(res.data) ? res.data : [];
list.value = page.value === 1 ? res.data : [...list.value, ...listData];
const message = res && typeof res.message === 'string' ? res.message : '获取药品失败';
if (!res || !res.success) {
toast(message)
}
loading.value = false;
more.value = res && res.pages > page.value;
}
function scanCode() {
uni.scanCode({
success: (res) => {
keyword.value = res.result
}
})
}
</script>
<style lang="scss" scoped>
@import '../drug.scss';
.page-container {
display: flex;
flex-direction: column;
height: 100%;
background: white;
}
.search-container {
padding: 24rpx;
display: flex;
align-items: center;
flex-shrink: 0;
}
.scan-code {
margin-left: 30rpx;
flex-shrink: 0;
}
.search {
width: 0;
flex-grow: 1;
flex-shrink: 0;
display: flex;
align-items: center;
background: #f5f6f7;
height: 100rpx;
border-radius: 50rpx;
padding: 0 40rpx 0 30rpx;
&-input {
flex-grow: 1;
margin: 0 20rpx 0 10rpx;
background-color: transparent;
}
&-btn {
flex-shrink: 0;
}
}
.drug-wrapper {
border-top: 1rpx solid #e5e5e5;
flex-grow: 1;
position: relative;
}
.drug-list {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.shopcart-footer {
display: flex;
align-items: center;
height: 120rpx;
background: #fff;
border-top: 1rpx solid #e5e5e5;
padding: 24rpx 30rpx;
flex-shrink: 0;
position: relative;
z-index: 2;
}
.shopcart-list {
position: absolute;
left: 0;
right: 0;
bottom: 0;
}
.my-drugs-container {
position: relative;
}
.shopcart-icon {
width: 80rpx;
height: 80rpx;
flex-shrink: 0;
}
.shopcart-num {
color: $theme-brown-primary;
font-size: 36rpx;
font-weight: bold;
margin: 0 10rpx;
}
.shopcart-text {
flex-grow: 1;
font-size: 28rpx;
color: #333;
margin: 0 16rpx;
}
.confirm-btn {
flex-shrink: 0;
width: 240rpx;
height: 80rpx;
background: $theme-brown-primary;
color: #fff;
font-size: 28rpx;
text-align: center;
line-height: 80rpx;
border-radius: 16rpx;
@at-root &--disabled {
background: #ccc;
}
}
.mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .1);
z-index: 1;
}
.drug-proof-tip {
color: #ff4757;
font-size: 24rpx;
line-height: 36rpx;
margin-top: 8rpx;
font-weight: 500;
}
/* 长辈模式样式 */
.elder-mode {
// 搜索容器样式
.search-container--elder {
padding: 36rpx 30rpx; // 24 * 1.5
}
.search--elder {
height: 120rpx; // 100 * 1.2
padding: 0 50rpx 0 40rpx; // 增加内边距
border-radius: 60rpx; // 50 * 1.2
}
.search-input--elder {
font-size: 36rpx; // 增大字体
margin: 0 25rpx 0 15rpx; // 调整间距
}
.search-btn--elder {
font-size: 36rpx; // 增大字体
font-weight: 600;
}
.scan-code--elder {
margin-left: 40rpx; // 30 * 1.33
}
// 药品列表样式
.drug--elder {
padding: 36rpx 30rpx; // 增加内边距
border-bottom: 2rpx solid #e5e5e5; // 加粗边框
}
.drug-info--elder {
flex: 1;
}
.drug-name--elder {
font-size: 42rpx; // 30 * 1.4
font-weight: bold;
line-height: 58rpx; // 42 * 1.38
margin-bottom: 12rpx; // 增加间距
}
.drug-spec--elder {
font-size: 36rpx; // 26 * 1.38
line-height: 50rpx; // 36 * 1.4
color: #666;
margin-bottom: 8rpx; // 增加间距
font-weight: 500;
}
.drug-proof-tip--elder {
color: #ff4757;
font-size: 32rpx; // 24 * 1.33
line-height: 48rpx; // 36 * 1.33
margin-top: 12rpx; // 8 * 1.5
font-weight: 600;
}
.drug-btn--elder {
font-size: 36rpx; // 28 * 1.29
padding: 16rpx 32rpx; // 12 * 1.33, 24 * 1.33
border-radius: 32rpx; // 24 * 1.33
min-width: 140rpx; // 增加最小宽度
text-align: center;
font-weight: bold;
border: 2rpx solid $theme-brown-primary; // 加粗边框
}
// 购物车底部样式
.shopcart-footer--elder {
height: 140rpx; // 120 * 1.17
padding: 30rpx 40rpx; // 增加内边距
border-top: 2rpx solid #e5e5e5; // 加粗边框
}
.shopcart-icon--elder {
width: 100rpx; // 80 * 1.25
height: 100rpx;
}
.shopcart-text--elder {
font-size: 36rpx; // 28 * 1.29
font-weight: 600;
margin: 0 20rpx; // 16 * 1.25
}
.shopcart-num--elder {
font-size: 44rpx; // 36 * 1.22
font-weight: bold;
margin: 0 12rpx; // 10 * 1.2
}
.confirm-btn--elder {
width: 280rpx; // 240 * 1.17
height: 96rpx; // 80 * 1.2
font-size: 36rpx; // 28 * 1.29
line-height: 96rpx;
border-radius: 20rpx; // 16 * 1.25
font-weight: bold;
}
}
.lack-tip-container {
height: 60vh;
}
.lack-img {
width: 240rpx;
height: 240rpx;
}
.lack-img.caring-mode-active {
width: 360rpx;
height: 360rpx;
}
</style>