301 lines
6.1 KiB
Vue
301 lines
6.1 KiB
Vue
<template>
|
||
<view class="follow-up-drug-drawer">
|
||
<view class="trigger" @click="openPopup">
|
||
<view class="trigger-main">
|
||
<text v-if="!displaySummary" class="placeholder">请选择药品</text>
|
||
<text v-else class="summary">{{ displaySummary }}</text>
|
||
</view>
|
||
<u-icon name="arrow-right" color="#94A3B8" size="28"></u-icon>
|
||
</view>
|
||
|
||
<u-popup
|
||
v-model="popupVisible"
|
||
mode="bottom"
|
||
border-radius="24"
|
||
height="66%"
|
||
:safe-area-inset-bottom="true"
|
||
:closeable="true"
|
||
@close="onPopupClose"
|
||
>
|
||
<view class="drawer-inner">
|
||
<view class="drawer-title">选择相关西药</view>
|
||
<view v-if="!drugList.length" class="drawer-empty">暂无可选西药</view>
|
||
<scroll-view v-else scroll-y class="drawer-scroll">
|
||
<view
|
||
v-for="d in drugList"
|
||
:key="d.id"
|
||
class="drawer-row"
|
||
>
|
||
<view class="drug-check" :class="{ on: getQty(d.id) > 0 }" @click="toggleRow(d)">
|
||
<text v-if="getQty(d.id) > 0" class="check-mark">✓</text>
|
||
</view>
|
||
<image class="drug-thumb" :src="drugImage(d)" mode="aspectFill" @click="toggleRow(d)" />
|
||
<view class="drug-meta" @click="toggleRow(d)">
|
||
<text class="dn">{{ d.drug_name }}</text>
|
||
<text class="ds" v-if="d.specification">{{ d.specification }}</text>
|
||
</view>
|
||
<view class="drawer-row-actions">
|
||
<u-number-box
|
||
:value="getQty(d.id)"
|
||
:min="0"
|
||
:max="99"
|
||
:size="22"
|
||
:index="d.id"
|
||
@input="onQtyInput(d, $event)"
|
||
/>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
<view class="drawer-footer safe-area-inset-bottom">
|
||
<view class="btn-text" @click="clearDraft">清空</view>
|
||
<view class="btn-primary" @click="confirm">确定</view>
|
||
</view>
|
||
</view>
|
||
</u-popup>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'FollowUpDrugDrawer',
|
||
props: {
|
||
drugList: {
|
||
type: Array,
|
||
default: () => [],
|
||
},
|
||
value: {
|
||
type: Array,
|
||
default: () => [],
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
popupVisible: false,
|
||
draftQty: {},
|
||
};
|
||
},
|
||
computed: {
|
||
displaySummary() {
|
||
const v = this.value || [];
|
||
if (!v.length) return '';
|
||
return v.map((i) => `${i.drug_name} * ${i.quantity}`).join(',');
|
||
},
|
||
},
|
||
methods: {
|
||
drugImage(d) {
|
||
const u = d && d.image;
|
||
return u && String(u).trim() ? u : '/static/mine/avatar_1.png';
|
||
},
|
||
getQty(id) {
|
||
const q = this.draftQty[id];
|
||
return q != null && q > 0 ? Number(q) : 0;
|
||
},
|
||
initDraftFromValue() {
|
||
const next = {};
|
||
for (const it of this.value || []) {
|
||
const id = it.id;
|
||
const q = Number(it.quantity);
|
||
if (id != null && q > 0) {
|
||
next[id] = q;
|
||
}
|
||
}
|
||
this.draftQty = next;
|
||
},
|
||
openPopup() {
|
||
this.initDraftFromValue();
|
||
this.popupVisible = true;
|
||
},
|
||
onPopupClose() {
|
||
this.popupVisible = false;
|
||
},
|
||
toggleRow(d) {
|
||
const id = d.id;
|
||
if (this.getQty(id) > 0) {
|
||
this.$delete(this.draftQty, id);
|
||
} else {
|
||
this.$set(this.draftQty, id, 1);
|
||
}
|
||
},
|
||
onQtyInput(d, val) {
|
||
const n = Number(val);
|
||
if (!n || n < 1) {
|
||
this.$delete(this.draftQty, d.id);
|
||
} else {
|
||
this.$set(this.draftQty, d.id, Math.min(99, n));
|
||
}
|
||
},
|
||
clearDraft() {
|
||
this.draftQty = {};
|
||
},
|
||
confirm() {
|
||
const out = [];
|
||
for (const d of this.drugList) {
|
||
const q = this.getQty(d.id);
|
||
if (q > 0) {
|
||
out.push({
|
||
id: d.id,
|
||
drug_name: d.drug_name || '',
|
||
quantity: q,
|
||
});
|
||
}
|
||
}
|
||
this.$emit('input', out);
|
||
this.$emit('confirm', out);
|
||
this.popupVisible = false;
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.follow-up-drug-drawer {
|
||
width: 100%;
|
||
}
|
||
|
||
.trigger {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 24rpx 20rpx;
|
||
margin-top: 12rpx;
|
||
background: #f8fafc;
|
||
border-radius: 12rpx;
|
||
border: 1rpx solid #e2e8f0;
|
||
}
|
||
|
||
.trigger-main {
|
||
flex: 1;
|
||
min-width: 0;
|
||
margin-right: 16rpx;
|
||
}
|
||
|
||
.placeholder {
|
||
font-size: 28rpx;
|
||
color: #94a3b8;
|
||
}
|
||
|
||
.summary {
|
||
font-size: 28rpx;
|
||
color: #0f172a;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.drawer-inner {
|
||
display: flex;
|
||
flex-direction: column;
|
||
height: 100%;
|
||
box-sizing: border-box;
|
||
padding: 24rpx 24rpx 0;
|
||
}
|
||
|
||
.drawer-title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #0f172a;
|
||
text-align: center;
|
||
padding-bottom: 20rpx;
|
||
}
|
||
|
||
.drawer-empty {
|
||
flex: 1;
|
||
padding: 48rpx 0;
|
||
text-align: center;
|
||
color: #94a3b8;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.drawer-scroll {
|
||
flex: 1;
|
||
max-height: 55vh;
|
||
min-height: 200rpx;
|
||
}
|
||
|
||
.drawer-row {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 20rpx 0;
|
||
border-bottom: 1rpx solid #f1f5f9;
|
||
}
|
||
|
||
.drug-check {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
border: 2rpx solid #cbd5e1;
|
||
border-radius: 8rpx;
|
||
margin-right: 16rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
|
||
&.on {
|
||
background: #4175ee;
|
||
border-color: #4175ee;
|
||
}
|
||
|
||
.check-mark {
|
||
color: #fff;
|
||
font-size: 24rpx;
|
||
line-height: 1;
|
||
}
|
||
}
|
||
|
||
.drug-thumb {
|
||
width: 96rpx;
|
||
height: 96rpx;
|
||
border-radius: 12rpx;
|
||
margin-right: 16rpx;
|
||
flex-shrink: 0;
|
||
background: #f1f5f9;
|
||
}
|
||
|
||
.drug-meta {
|
||
flex: 1;
|
||
min-width: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
|
||
.dn {
|
||
font-size: 28rpx;
|
||
color: #0f172a;
|
||
}
|
||
|
||
.ds {
|
||
font-size: 24rpx;
|
||
color: #64748b;
|
||
margin-top: 6rpx;
|
||
}
|
||
}
|
||
|
||
.drawer-row-actions {
|
||
flex-shrink: 0;
|
||
margin-left: 12rpx;
|
||
}
|
||
|
||
.drawer-footer {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 24rpx 0 32rpx;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.btn-text {
|
||
flex: 1;
|
||
text-align: center;
|
||
font-size: 30rpx;
|
||
color: #64748b;
|
||
padding: 22rpx 0;
|
||
}
|
||
|
||
.btn-primary {
|
||
flex: 2;
|
||
text-align: center;
|
||
font-size: 30rpx;
|
||
color: #fff;
|
||
background: #4175ee;
|
||
border-radius: 12rpx;
|
||
padding: 22rpx 0;
|
||
}
|
||
</style>
|