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

344 lines
11 KiB
Vue
Raw Permalink 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>
<uni-popup ref="popup" type="bottom" :mask-click="false">
<scroll-view scroll-y="true" class="popup-wrapper" :class="{ 'popup-wrapper--elder': elderMode }">
<view class="">
<view class="drug" :class="{ 'drug--elder': elderMode }">
<view>
<view class="drug-name" :class="{ 'drug-name--elder': elderMode }">
{{ current.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>
<view class="row" :class="{ 'row--elder': elderMode }">
<view class="label" :class="{ 'label--elder': elderMode }">开药数量</view>
<view class="value">
<input-number-box v-model="current.quantity" :elderMode="elderMode" :style="gtMax ? 'color:red' : ''" />
</view>
<view v-if="current.unit" class="unit" :class="{ 'unit--elder': elderMode }">{{ current.unit }}</view>
</view>
<view v-if="gtMax" class="max-tip" :class="{ 'max-tip--elder': elderMode }">已超过建议开药数量</view>
<picker :value="usageIndex" mode="selector" range-key="name" :range="usageList" @change="usageChange">
<view class="row" :class="{ 'row--elder': elderMode }">
<view class="label" :class="{ 'label--elder': elderMode }">用药方式</view>
<view class="value" :class="{ 'value--elder': elderMode }">{{ current.usageName }} </view>
<uni-icons type="right" :size="elderMode ? 32 : 24"></uni-icons>
</view>
</picker>
<view class="row" :class="{ 'row--elder': elderMode }">
<view class="label" :class="{ 'label--elder': elderMode }">单次剂量</view>
<view class="value">
<input-number-box v-model="current.dosage" :elderMode="elderMode" :minStep="0.01" />
</view>
<view v-if="current.dosage_unit" class="unit" :class="{ 'unit--elder': elderMode }">{{ current.dosage_unit }}
</view>
</view>
<picker :value="frequencyIndex" mode="selector" range-key="name" :range="frequencyList"
@change="frequencyChange">
<view class="row" :class="{ 'row--elder': elderMode }">
<view class="label" :class="{ 'label--elder': elderMode }">用药频率</view>
<view class="value" :class="{ 'value--elder': elderMode }">{{ current.frequencyName }} </view>
<uni-icons type="right" :size="elderMode ? 32 : 24"></uni-icons>
</view>
</picker>
<view class="tips" :class="{ 'tips--elder': elderMode }">
<uni-icons color="red" type="info-filled" :size="elderMode ? 24 : 16"></uni-icons>
<text style="margin-left: 12rpx;" :class="{ 'tips-text--elder': elderMode }">已为您填入药品常规用量请确认!</text>
</view>
<view style="height: 80rpx;"></view>
</view>
</scroll-view>
<view class="btn-footer" :class="{ 'btn-footer--elder': elderMode }">
<view class="btn" :class="{ 'btn--elder': elderMode }" @click="close">取消</view>
<view class="btn btn--active" :class="{ 'btn--elder': elderMode }" @click="confirm">确定</view>
</view>
</uni-popup>
</template>
<script setup>
import { computed, ref, watch } from 'vue';
import { storeToRefs } from "pinia";
import useDb from '@/store/db';
import { toast, confirm as uniConfirm } from '@/utils/widget';
import inputNumberBox from './input-number-box.vue';
const emits = defineEmits(['close', 'change'])
const props = defineProps({
consultType: { type: String, default: 'onlineConsult' },
drug: { type: Object, default: () => ({}) },
visible: { type: Boolean, default: false },
elderMode: { type: Boolean, default: false },
type: { type: String, default: 'add', validator: (value) => ['add', 'edit'].includes(value) },
})
const { onlineMedicine, storeMedicine } = storeToRefs(useDb());
const proofTipText = '*购买该药品需上传用药证明';
const popup = ref()
const current = ref({})
const usageIndex = ref(0)
const frequencyIndex = ref(0)
const gtMax = computed(() => {
return current.value.quantity > current.value.recommended_quantity && current.value.recommended_quantity > 0
})
const usageList = computed(() => {
return props.consultType === 'onlineMedicinePurchase' ? onlineMedicine.value.usageList : storeMedicine.value.usageList;
})
const frequencyList = computed(() => {
return props.consultType === 'onlineMedicinePurchase' ? onlineMedicine.value.frequencyList : storeMedicine.value.frequencyList;
})
function usageChange(e) {
const index = e.detail.value;
const usage = usageList.value[index];
current.value.usageName = usage ? usage.name : '';
current.value.usageCode = usage ? usage.code : '';
usageIndex.value = index;
}
function frequencyChange(e) {
const index = e.detail.value;
const frequency = frequencyList.value[index];
current.value.frequencyName = frequency ? frequency.name : '';
current.value.frequencyCode = frequency ? frequency.code : '';
frequencyIndex.value = index;
}
function close() {
emits('close')
}
function confirm() {
if (!Number.isInteger(current.value.quantity) || !(current.value.quantity > 0)) {
return toast('请输入正确的开药数量', { mask: false })
}
if (!(usageIndex.value >= 0)) {
return toast('请选择用药方式', { mask: false })
}
if (!validateNumber(current.value.dosage)) {
return toast('请输入正确的单次剂量', { mask: false })
}
if (!(frequencyIndex.value >= 0)) {
return toast('请选择用药频率', { mask: false })
}
// 延迟执行是因为 单次剂量以及数量 手动输入的时候 值改变有延时 手机端可以可以出现 开发工具不行
setTimeout(() => {
const arr = [current.value.usageName, current.value.frequencyName, current.value.dosage ? `每次${current.value.dosage}${current.value.dosage_unit || ''}` : ''].filter(Boolean);
emits('change', { ...current.value, memo: arr.join('') })
}, 500)
}
watch(() => props.visible, (val) => {
if (val) {
popup.value && popup.value.open();
current.value = { ...props.drug };
current.value.quantity = typeof current.value.quantity === 'number' ? current.value.quantity : (typeof current.value.recommended_quantity === 'number' ? current.value.recommended_quantity : 0);
current.value.dosage = typeof current.value.dosage === 'number' ? current.value.dosage : 1;
usageIndex.value = usageList.value.findIndex(item => item.name === (current.value.usageName || current.value.administration_method));
const usage = usageList.value[usageIndex.value];
current.value.usageName = usage ? usage.name : '';
current.value.usageCode = usage ? usage.code : '';
frequencyIndex.value = frequencyList.value.findIndex(item => item.name === (current.value.frequencyName || current.value.freq));
const frequency = frequencyList.value[frequencyIndex.value];
current.value.frequencyName = frequency ? frequency.name : '';
current.value.frequencyCode = frequency ? frequency.code : '';
} else {
popup.value && popup.value.close()
}
})
function validateNumber(input, type = 'decimal') {
const number = Number(input);
let regex;
// 根据type决定是校验整数还是小数
if (type === 'integer') {
regex = /^[1-9]\d*$/; // 整数且必须大于0
} else {
// 小数,且小数点前必须有至少一个数字,最多支持两位小数
regex = /^(0(\.\d{1,2})?|[1-9]\d*(\.\d{1,2})?)$/; // 小数,且最多两位小数
}
// 校验输入是否符合要求
if (regex.test(number)) {
return true;
} else {
return false;
}
}
watch(() => current.value.quantity, (n, o) => {
const isAdd = !(n - 0 > (o || 0));
if (props.visible && n > 0 && current.value.recommended_quantity && isAdd && n > current.value.recommended_quantity) {
uniConfirm('已超过建议开药数量', { showCancel: false })
}
})
</script>
<style lang="scss" scoped>
@import '../drug.scss';
.row {
display: flex;
align-items: center;
padding: 24rpx 30rpx;
font-size: 28rpx;
color: #333;
width: 690rpx;
border-top: 1rpx solid #e5e5e5;
}
.value {
margin-left: auto;
}
.btn-footer {
display: flex;
align-items: center;
padding: 24rpx 30rpx;
background: white;
}
.btn {
width: 300rpx;
height: 60rpx;
font-size: 28rpx;
color: #333;
border: 1px solid #e5e5e5;
text-align: center;
line-height: 60rpx;
border-radius: 16rpx;
@at-root &--active {
border-color: $theme-brown-primary;
background-color: $theme-brown-primary;
color: white
}
@at-root &+& {
margin-left: 30rpx;
}
}
.popup-wrapper {
max-height: 60vh;
background: white;
}
.tips {
display: flex;
align-items: center;
font-size: 32rpx;
color: red;
padding: 24rpx 30rpx;
}
.max-tip {
padding: 0 30rpx 24rpx;
font-size: 24rpx;
color: red;
}
.drug-proof-tip {
color: #ff4757;
font-size: 24rpx;
line-height: 36rpx;
margin-top: 8rpx;
font-weight: 500;
}
/* 长辈模式样式 */
.popup-wrapper--elder {
max-height: 70vh; // 增加高度
}
.drug--elder {
padding: 36rpx 40rpx; // 增加内边距
}
.drug-name--elder {
font-size: 42rpx !important; // 30 * 1.4
font-weight: bold;
line-height: 58rpx; // 增加行高
margin-bottom: 12rpx; // 增加间距
}
.drug-spec--elder {
font-size: 36rpx !important; // 28 * 1.29
line-height: 50rpx; // 增加行高
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;
}
.row--elder {
padding: 36rpx 40rpx; // 24 * 1.5, 30 * 1.33
font-size: 36rpx; // 28 * 1.29
min-height: 100rpx; // 增加最小高度
border-top: 2rpx solid #e5e5e5; // 加粗边框
}
.label--elder {
font-size: 36rpx; // 28 * 1.29
font-weight: bold;
width: 36*4rpx; // 确保标签宽度
}
.value--elder {
font-size: 36rpx; // 28 * 1.29
font-weight: 600;
}
.unit--elder {
font-size: 36rpx; // 28 * 1.29
font-weight: 500;
margin-left: 16rpx;
}
.btn-footer--elder {
padding: 36rpx 40rpx; // 增加内边距
gap: 40rpx; // 增加按钮间距
}
.btn--elder {
width: 280rpx; // 300 * 0.93
height: 80rpx; // 60 * 1.33
font-size: 36rpx; // 28 * 1.29
line-height: 80rpx;
border-radius: 20rpx; // 16 * 1.25
font-weight: bold;
border: 2rpx solid #e5e5e5; // 加粗边框
&.btn--active {
border: 2rpx solid $theme-brown-primary; // 加粗边框
}
}
.tips--elder {
padding: 36rpx 40rpx; // 增加内边距
font-size: 36rpx; // 32 * 1.125
}
.tips-text--elder {
font-size: 36rpx !important; // 确保文字大小
font-weight: 500;
margin-left: 16rpx !important; // 调整间距
}
.max-tip--elder {
padding: 0 40rpx 36rpx; // 调整内边距
font-size: 32rpx; // 24 * 1.33
font-weight: bold;
}
</style>