1. 医生端开方2.0测试
This commit is contained in:
@@ -115,10 +115,41 @@
|
||||
<view class="info-row"><text class="label">订单号</text><text class="value order-font">{{ parsedContent.order_no }}</text></view>
|
||||
<view class="info-row"><text class="label">就诊人</text><text class="value">{{ (parsedContent.user_patient && parsedContent.user_patient.name) || '未知' }}</text></view>
|
||||
<view class="info-row highlight"><text class="label">费用</text><text class="value price">¥{{ parsedContent.price }}</text></view>
|
||||
<view class="text-block" v-if="parsedContent.chief_complaint">
|
||||
<text class="block-label">主诉</text>
|
||||
<text class="block-content">{{ parsedContent.chief_complaint }}</text>
|
||||
</view>
|
||||
<view class="info-row" v-if="registerCardDrugNamesLine">
|
||||
<text class="label">所选药品</text>
|
||||
<text class="value">{{ registerCardDrugNamesLine }}</text>
|
||||
</view>
|
||||
<view class="info-row" v-if="parsedContent.number != null && parsedContent.number !== ''">
|
||||
<text class="label">数量</text>
|
||||
<text class="value">各 {{ parsedContent.number }} 盒</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="card-footer"><button class="action-btn" @click="$emit('viewRegister', parsedContent.id)">查看详情</button></view>
|
||||
</block>
|
||||
|
||||
<block v-else-if="msg.message_type === 11 && parsedContent && parsedContent.flow === 'follow_up_drug'">
|
||||
<view class="card-header bg-gray">
|
||||
<view class="title-group"><u-icon name="question-circle-fill" size="16" color="#64748B"></u-icon><text class="card-title">医生助理</text></view>
|
||||
</view>
|
||||
<view class="card-body">
|
||||
<view class="text-block" v-if="parsedContent.question">
|
||||
<text class="block-content">{{ parsedContent.question }}</text>
|
||||
</view>
|
||||
<view class="info-row" v-for="(row, idx) in (parsedContent.drugs || [])" :key="'dfd-' + idx">
|
||||
<text class="label">{{ row.name || '药品' }}</text>
|
||||
<text class="value">×{{ row.quantity != null ? row.quantity : 1 }}</text>
|
||||
</view>
|
||||
<view v-if="followUpAnsweredLabel" class="info-row">
|
||||
<text class="label">患者选择</text>
|
||||
<text class="value">{{ followUpAnsweredLabel }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!-- 类型11: 患者就诊经历 -->
|
||||
<block v-else-if="msg.message_type === 11">
|
||||
<view class="card-header bg-gray">
|
||||
@@ -228,6 +259,25 @@ export default {
|
||||
}
|
||||
}
|
||||
return message_content;
|
||||
},
|
||||
registerCardDrugNamesLine() {
|
||||
if (this.msg.message_type !== 10) return '';
|
||||
const pc = this.parsedContent;
|
||||
if (!pc || typeof pc !== 'object') return '';
|
||||
const arr = pc.selected_western_drugs;
|
||||
if (Array.isArray(arr) && arr.length) {
|
||||
return arr.map((d) => d && d.name).filter(Boolean).join('、');
|
||||
}
|
||||
if (pc.drug && pc.drug.name) return pc.drug.name;
|
||||
return '';
|
||||
},
|
||||
followUpAnsweredLabel() {
|
||||
const pc = this.parsedContent;
|
||||
if (!pc || pc.flow !== 'follow_up_drug') return '';
|
||||
const st = pc.answer_status;
|
||||
if (st === 'yes' || st === '1') return '是,曾使用过';
|
||||
if (st === 'no' || st === '0') return '否,未使用过';
|
||||
return '';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -97,6 +97,44 @@
|
||||
<text class="card-text">点击查看处方详情</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 挂号卡片 type10 -->
|
||||
<view v-else-if="msg.message_type === 10" class="register-msg-card">
|
||||
<view class="rmc-head">
|
||||
<text class="rmc-title">预约挂号</text>
|
||||
</view>
|
||||
<view class="rmc-body">
|
||||
<view class="rmc-row" v-if="getParsedContent(msg).order_no"><text class="k">订单号</text><text class="v">{{ getParsedContent(msg).order_no }}</text></view>
|
||||
<view class="rmc-row" v-if="getParsedContent(msg).chief_complaint"><text class="k">主诉</text><text class="v">{{ getParsedContent(msg).chief_complaint }}</text></view>
|
||||
<view class="rmc-row" v-if="registerCardDrugLine(msg)"><text class="k">所选药品</text><text class="v">{{ registerCardDrugLine(msg) }}</text></view>
|
||||
<view class="rmc-row" v-if="getParsedContent(msg).number != null && getParsedContent(msg).number !== ''"><text class="k">数量</text><text class="v">各 {{ getParsedContent(msg).number }} 盒</text></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- type11:复诊助理 / 患者就诊经历 -->
|
||||
<view v-else-if="msg.message_type === 11" class="register-msg-card">
|
||||
<template v-if="getParsedContent(msg).flow === 'follow_up_drug'">
|
||||
<view class="rmc-head"><text class="rmc-title">医生助理</text></view>
|
||||
<view class="rmc-body">
|
||||
<text class="rmc-q">{{ getParsedContent(msg).question }}</text>
|
||||
<view class="rmc-row" v-for="(row, iix) in (getParsedContent(msg).drugs || [])" :key="'rxd-' + iix">
|
||||
<text class="k">{{ row.name || '药品' }}</text>
|
||||
<text class="v">×{{ row.quantity != null ? row.quantity : 1 }}</text>
|
||||
</view>
|
||||
<view class="rmc-row" v-if="followUpAnswerLine(msg)"><text class="k">患者选择</text><text class="v">{{ followUpAnswerLine(msg) }}</text></view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="rmc-head"><text class="rmc-title">患者就诊经历</text></view>
|
||||
<view class="rmc-body">
|
||||
<view class="rmc-row" v-if="getParsedContent(msg).drug_name"><text class="k">药品</text><text class="v">{{ getParsedContent(msg).drug_name }}</text></view>
|
||||
<view class="rmc-row"><text class="k">是否就诊过</text><text class="v">{{ getParsedContent(msg).has_visited === '1' ? '是' : '否' }}</text></view>
|
||||
<view class="rmc-row"><text class="k">是否用过药</text><text class="v">{{ getParsedContent(msg).has_used_drug === '1' ? '是' : '否' }}</text></view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<text v-else class="text-content">{{ formatUnknownMessage(msg) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -186,7 +224,7 @@ const uploadBaseUrl = isDev ? 'http://127.0.0.1:18001/api/mobile' : 'https://api
|
||||
|
||||
// 辅助函数
|
||||
function getParsedContent(messageType, messageContent) {
|
||||
if ([4, 9, 10, 11, 12, 13].includes(messageType)) {
|
||||
if ([4, 9, 10, 11, 12, 13, 14].includes(messageType)) {
|
||||
try {
|
||||
return typeof messageContent === 'object' ? messageContent : JSON.parse(messageContent);
|
||||
} catch (e) {
|
||||
@@ -385,6 +423,10 @@ export default {
|
||||
|
||||
// 获取消息头像
|
||||
getMsgAvatar(msg) {
|
||||
const sid = msg.sender_user_id || '';
|
||||
if (sid === 'doctor_assistant') {
|
||||
return 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk_upload_20250108/29bdb9560340373bb3096394a845afa5.jpg';
|
||||
}
|
||||
if (this.isMsgMine(msg)) {
|
||||
// 医生头像
|
||||
return uni.getStorageSync('doctor_avatar') || 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk_upload_20250108/29bdb9560340373bb3096394a845afa5.jpg';
|
||||
@@ -393,6 +435,33 @@ export default {
|
||||
return this.patientInfo?.user_patient?.avatar || 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk_upload_20250108/29bdb9560340373bb3096394a845afa5.jpg';
|
||||
}
|
||||
},
|
||||
|
||||
registerCardDrugLine(msg) {
|
||||
const pc = getParsedContent(msg.message_type, msg.message_content);
|
||||
if (!pc || typeof pc !== 'object') return '';
|
||||
const arr = pc.selected_western_drugs;
|
||||
if (Array.isArray(arr) && arr.length) {
|
||||
return arr.map((d) => d && d.name).filter(Boolean).join('、');
|
||||
}
|
||||
if (pc.drug && pc.drug.name) return pc.drug.name;
|
||||
return '';
|
||||
},
|
||||
|
||||
followUpAnswerLine(msg) {
|
||||
const pc = getParsedContent(msg.message_type, msg.message_content);
|
||||
if (!pc || pc.flow !== 'follow_up_drug') return '';
|
||||
const st = pc.answer_status;
|
||||
if (st === 'yes' || st === '1') return '是,曾使用过';
|
||||
if (st === 'no' || st === '0') return '否,未使用过';
|
||||
return '';
|
||||
},
|
||||
|
||||
formatUnknownMessage(msg) {
|
||||
if (msg.message_content == null) return '[消息]';
|
||||
if (typeof msg.message_content === 'object') return '[卡片消息]';
|
||||
const s = String(msg.message_content);
|
||||
return s.length > 120 ? s.slice(0, 120) + '…' : s;
|
||||
},
|
||||
|
||||
// 解析消息内容
|
||||
getParsedContent(msg) {
|
||||
@@ -1090,6 +1159,32 @@ $bg-white: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.register-msg-card {
|
||||
background: #fff;
|
||||
border: 1rpx solid #e8e8e8;
|
||||
border-radius: 12rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
max-width: 520rpx;
|
||||
.rmc-head {
|
||||
margin-bottom: 12rpx;
|
||||
.rmc-title { font-size: 28rpx; font-weight: 600; color: #333; }
|
||||
}
|
||||
.rmc-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10rpx;
|
||||
.rmc-q { font-size: 26rpx; color: #333; line-height: 1.4; }
|
||||
.rmc-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 24rpx;
|
||||
gap: 12rpx;
|
||||
.k { color: #888; flex-shrink: 0; }
|
||||
.v { color: #333; text-align: right; word-break: break-all; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.recording-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
class="drug-item white b-r-8 p-32 m-t-2"
|
||||
v-for="(item, index) in drugList"
|
||||
:key="item.id || index"
|
||||
:class="{ selected: isSelected(item) }"
|
||||
:class="{ selected: isInSelected(item) }"
|
||||
>
|
||||
<view class="drug-header flex-row flex-jus-sp flex-ali-center">
|
||||
<d-text :text="getDrugName(item)" className="fs-3 color0 bold"></d-text>
|
||||
@@ -47,7 +47,7 @@
|
||||
<view class="drug-info m-t-16">
|
||||
<view class="specification-row flex-row flex-jus-sp flex-ali-center m-b-16">
|
||||
<d-text :text="`规格:${getSpecification(item)}`" className="fs-24 color9"></d-text>
|
||||
<view class="selected-tag" v-if="isSelected(item)">已选</view>
|
||||
<view class="selected-tag" v-if="isInSelected(item)">已选</view>
|
||||
</view>
|
||||
<view class="common-quantity-tags m-b-16" v-if="commonQuantities.length > 0">
|
||||
<view
|
||||
@@ -61,29 +61,47 @@
|
||||
{{ qty }}g
|
||||
</view>
|
||||
</view>
|
||||
<view class="quantity-input-row flex-row flex-ali-center">
|
||||
<view class="quantity-label">用量:</view>
|
||||
<view class="quantity-input-wrapper flex-row flex-ali-center">
|
||||
<view
|
||||
class="quantity-btn"
|
||||
@click.stop="handleDecreaseQuantity"
|
||||
:data-index="index"
|
||||
>-</view>
|
||||
<input
|
||||
class="quantity-input"
|
||||
type="number"
|
||||
:value="getQuantity(item)"
|
||||
@input="handleQuantityInput"
|
||||
:data-index="index"
|
||||
placeholder="请输入"
|
||||
/>
|
||||
<view
|
||||
class="quantity-btn"
|
||||
@click.stop="handleIncreaseQuantity"
|
||||
:data-index="index"
|
||||
>+</view>
|
||||
<view class="quantity-input-row flex-row flex-ali-center flex-jus-sp">
|
||||
<view class="quantity-input-left flex-row flex-ali-center">
|
||||
<view class="quantity-label">用量:</view>
|
||||
<view class="quantity-input-wrapper flex-row flex-ali-center">
|
||||
<view
|
||||
class="quantity-btn"
|
||||
@click.stop="handleDecreaseQuantity"
|
||||
:data-index="index"
|
||||
>-</view>
|
||||
<input
|
||||
class="quantity-input"
|
||||
type="number"
|
||||
:value="getQuantity(item)"
|
||||
@input="handleQuantityInput"
|
||||
:data-index="index"
|
||||
placeholder="请输入"
|
||||
/>
|
||||
<view
|
||||
class="quantity-btn"
|
||||
@click.stop="handleIncreaseQuantity"
|
||||
:data-index="index"
|
||||
>+</view>
|
||||
</view>
|
||||
<text class="unit-text">{{ getUnitName(item) }}</text>
|
||||
</view>
|
||||
<view
|
||||
v-if="isInSelected(item)"
|
||||
class="action-icon delete-icon"
|
||||
@click.stop="handleRemoveDrug"
|
||||
:data-index="index"
|
||||
>
|
||||
<u-icon name="trash" size="44" color="#FC3636"></u-icon>
|
||||
</view>
|
||||
<view
|
||||
v-else
|
||||
class="action-icon add-icon"
|
||||
@click.stop="handleAddDrug"
|
||||
:data-index="index"
|
||||
>
|
||||
<u-icon name="plus-circle" size="44" color="#6ACDBB"></u-icon>
|
||||
</view>
|
||||
<text class="unit-text">{{ getUnitName(item) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -105,15 +123,18 @@
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="modal-footer">
|
||||
<view class="modal-footer flex-jus-center flex-ali-center">
|
||||
<u-button
|
||||
:throttle-time="0"
|
||||
@click="handleClose"
|
||||
:custom-style="{ backgroundColor: '#f5f5f5', color: '#333' }"
|
||||
>取消</u-button>
|
||||
<u-button
|
||||
@click="handleConfirm"
|
||||
:custom-style="{ backgroundColor: '#6ACDBB', color: '#fff' }"
|
||||
>确定</u-button>
|
||||
shape="circle"
|
||||
:custom-style="{
|
||||
backgroundColor: '#6ACDBB',
|
||||
color: '#fff',
|
||||
height: '86rpx',
|
||||
width: '670rpx'
|
||||
}"
|
||||
>关闭</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
@@ -207,8 +228,15 @@ export default {
|
||||
const list = res.data || res.result || [];
|
||||
this.hasMore = list.length >= this.pageSize;
|
||||
// 合并已选中的药品数量,使用 $set 确保响应式
|
||||
// 匹配优先级:selectedDrugs.index_id === drug.id,再 fallback 到 entity id
|
||||
const merged = list.map(drug => {
|
||||
const selected = this.selectedDrugs.find(item => (item.id || item.drug_id) === drug.id);
|
||||
const entityId = (drug.drug && drug.drug.id) || drug.id;
|
||||
const selected = this.selectedDrugs.find(item => {
|
||||
const matchByIndexId = (item.index_id !== undefined && item.index_id !== null) && item.index_id === drug.id;
|
||||
const matchByEntityId = (item.id !== undefined && item.id !== null) && item.id === entityId;
|
||||
const matchByDrugId = (item.drug_id !== undefined && item.drug_id !== null) && item.drug_id === entityId;
|
||||
return matchByIndexId || matchByEntityId || matchByDrugId;
|
||||
});
|
||||
// 直接使用原对象,使用 $set 添加响应式属性
|
||||
this.$set(drug, '_quantity', selected ? selected.number : 0);
|
||||
return drug;
|
||||
@@ -320,7 +348,7 @@ export default {
|
||||
},
|
||||
|
||||
/**
|
||||
* 判断是否已选中该中药
|
||||
* 判断是否已选中该中药(基于父组件传入的 currentDrugs,初始展示用)
|
||||
* @param {Object} drug
|
||||
* @returns {boolean}
|
||||
*/
|
||||
@@ -329,6 +357,141 @@ export default {
|
||||
const id = drug.id || drug.drug_id;
|
||||
return this.currentDrugs.some(item => (item.id || item.drug_id) === id);
|
||||
},
|
||||
|
||||
/**
|
||||
* 判断是否已加入本次会话的处方(基于实时 selectedDrugs)
|
||||
* @param {Object} drug
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isInSelected(drug) {
|
||||
return this.findSelectedIndex(drug) !== -1;
|
||||
},
|
||||
|
||||
/**
|
||||
* 在 selectedDrugs 中查找当前 drug 对应的索引
|
||||
* 匹配优先级:index_id === drug.id;否则 id === drug.drug?.id || drug.id
|
||||
* @param {Object} drug
|
||||
* @returns {number} 找到返回索引,未找到返回 -1
|
||||
*/
|
||||
findSelectedIndex(drug) {
|
||||
if (!drug || !Array.isArray(this.selectedDrugs)) return -1;
|
||||
const listId = drug.id;
|
||||
const entityId = (drug.drug && drug.drug.id) || drug.id;
|
||||
return this.selectedDrugs.findIndex(item => {
|
||||
const matchByIndexId = (item.index_id !== undefined && item.index_id !== null) && item.index_id === listId;
|
||||
const matchByEntityId = (item.id !== undefined && item.id !== null) && item.id === entityId;
|
||||
const matchByDrugId = (item.drug_id !== undefined && item.drug_id !== null) && item.drug_id === entityId;
|
||||
return matchByIndexId || matchByEntityId || matchByDrugId;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 把 drugList 中某个药品转成 selectedDrugs 的标准条目
|
||||
* 字段与原 handleConfirm 中保持一致
|
||||
* @param {Object} drug
|
||||
* @returns {Object}
|
||||
*/
|
||||
buildSelectedItem(drug) {
|
||||
let drugName = '';
|
||||
if (drug.drug && drug.drug.drug_name) {
|
||||
drugName = drug.drug.drug_name;
|
||||
} else if (drug.drug_name) {
|
||||
drugName = drug.drug_name;
|
||||
} else if (drug.name) {
|
||||
drugName = drug.name;
|
||||
}
|
||||
return {
|
||||
index_id: drug.id,
|
||||
id: (drug.drug && drug.drug.id) || drug.id,
|
||||
drug_name: drugName,
|
||||
number: drug._quantity,
|
||||
price: drug.price || 0,
|
||||
way_id: (drug.drug && drug.drug.way_id) || drug.way_id || 0,
|
||||
select_number: 1
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* emit select 事件,传出当前完整的 selectedDrugs(深拷贝)
|
||||
*/
|
||||
emitSelect() {
|
||||
const payload = JSON.parse(JSON.stringify(this.selectedDrugs));
|
||||
this.$emit('select', payload);
|
||||
},
|
||||
|
||||
/**
|
||||
* 添加药品到处方
|
||||
* @param {Event} event - 点击事件对象
|
||||
*/
|
||||
handleAddDrug(event) {
|
||||
const index = event.currentTarget.dataset.index;
|
||||
if (index === undefined || index === null) {
|
||||
console.error('handleAddDrug: index is undefined');
|
||||
return;
|
||||
}
|
||||
const drug = this.drugList[index];
|
||||
if (!drug) {
|
||||
console.error('handleAddDrug: drug not found at index', index);
|
||||
return;
|
||||
}
|
||||
|
||||
// 用量为空或 0 时,默认设为 1
|
||||
if (!drug._quantity || drug._quantity <= 0) {
|
||||
this.$set(drug, '_quantity', 1);
|
||||
}
|
||||
|
||||
// 已经在 selectedDrugs 中则只更新数量
|
||||
const existIndex = this.findSelectedIndex(drug);
|
||||
if (existIndex !== -1) {
|
||||
this.$set(this.selectedDrugs[existIndex], 'number', drug._quantity);
|
||||
} else {
|
||||
this.selectedDrugs.push(this.buildSelectedItem(drug));
|
||||
}
|
||||
this.emitSelect();
|
||||
this.$toast(`已将${this.getDrugName(drug)}添加到处方`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 从处方中移除药品
|
||||
* @param {Event} event - 点击事件对象
|
||||
*/
|
||||
handleRemoveDrug(event) {
|
||||
const index = event.currentTarget.dataset.index;
|
||||
if (index === undefined || index === null) {
|
||||
console.error('handleRemoveDrug: index is undefined');
|
||||
return;
|
||||
}
|
||||
const drug = this.drugList[index];
|
||||
if (!drug) {
|
||||
console.error('handleRemoveDrug: drug not found at index', index);
|
||||
return;
|
||||
}
|
||||
|
||||
const existIndex = this.findSelectedIndex(drug);
|
||||
if (existIndex !== -1) {
|
||||
this.selectedDrugs.splice(existIndex, 1);
|
||||
}
|
||||
this.$set(drug, '_quantity', 0);
|
||||
this.emitSelect();
|
||||
},
|
||||
|
||||
/**
|
||||
* 把 drug 的最新 _quantity 同步到 selectedDrugs 中(如果已加入处方)
|
||||
* 用于 +/-、输入、点击常用克数后实时同步
|
||||
* @param {Object} drug
|
||||
*/
|
||||
syncQuantityToSelected(drug) {
|
||||
const existIndex = this.findSelectedIndex(drug);
|
||||
if (existIndex === -1) return;
|
||||
const newNumber = drug._quantity || 0;
|
||||
if (newNumber <= 0) {
|
||||
// 数量被改为 0,从处方中移除
|
||||
this.selectedDrugs.splice(existIndex, 1);
|
||||
} else {
|
||||
this.$set(this.selectedDrugs[existIndex], 'number', newNumber);
|
||||
}
|
||||
this.emitSelect();
|
||||
},
|
||||
|
||||
/**
|
||||
* 增加数量
|
||||
@@ -357,6 +520,7 @@ export default {
|
||||
this.$set(drug, '_quantity', 0);
|
||||
}
|
||||
this.$set(drug, '_quantity', (drug._quantity || 0) + 1);
|
||||
this.syncQuantityToSelected(drug);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -388,6 +552,7 @@ export default {
|
||||
}
|
||||
if (drug._quantity > 0) {
|
||||
this.$set(drug, '_quantity', drug._quantity - 1);
|
||||
this.syncQuantityToSelected(drug);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -428,8 +593,10 @@ export default {
|
||||
|
||||
if (!isNaN(numValue) && numValue >= 0) {
|
||||
this.$set(drug, '_quantity', numValue);
|
||||
this.syncQuantityToSelected(drug);
|
||||
} else if (value === '') {
|
||||
this.$set(drug, '_quantity', 0);
|
||||
this.syncQuantityToSelected(drug);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -467,6 +634,7 @@ export default {
|
||||
}
|
||||
// 设置数量
|
||||
this.$set(drug, '_quantity', quantity);
|
||||
this.syncQuantityToSelected(drug);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -481,45 +649,10 @@ export default {
|
||||
this.loadDrugList(this.searchKey);
|
||||
},
|
||||
|
||||
/**
|
||||
* 确认选择
|
||||
* 职责:将选中的药品传递给父组件
|
||||
*/
|
||||
handleConfirm() {
|
||||
// 过滤出数量大于0的药品
|
||||
// 参考PC端:index_id 使用 drug.id(列表项ID),id 使用 drug.drug.id(药品本身的ID)
|
||||
const selected = this.drugList
|
||||
.filter(drug => drug._quantity > 0)
|
||||
.map(drug => {
|
||||
// 获取药品名称
|
||||
let drugName = '';
|
||||
if (drug.drug && drug.drug.drug_name) {
|
||||
drugName = drug.drug.drug_name;
|
||||
} else if (drug.drug_name) {
|
||||
drugName = drug.drug_name;
|
||||
} else if (drug.name) {
|
||||
drugName = drug.name;
|
||||
}
|
||||
|
||||
// 参考PC端数据结构:index_id, id, drug_name, number, price, way_id, select_number
|
||||
return {
|
||||
index_id: drug.id, // 列表项ID(对应PC端的 data.id)
|
||||
id: drug.drug?.id || drug.id, // 药品本身的ID(对应PC端的 data.drug.id)
|
||||
drug_name: drugName,
|
||||
number: drug._quantity,
|
||||
price: drug.price || 0,
|
||||
way_id: drug.drug?.way_id || drug.way_id || 0, // 用法ID(对应PC端的 data.drug?.way_id)
|
||||
select_number: 1 // 默认为1(与PC端一致)
|
||||
};
|
||||
});
|
||||
|
||||
this.$emit('select', selected);
|
||||
this.handleClose();
|
||||
},
|
||||
|
||||
/**
|
||||
* 关闭弹窗
|
||||
* 职责:关闭弹窗,触发input事件
|
||||
* 注:由于 add/remove/调用量都是实时 emit,关闭无需额外提交
|
||||
*/
|
||||
handleClose() {
|
||||
this.show = false;
|
||||
@@ -626,6 +759,28 @@ export default {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.quantity-input-left {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.action-icon {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.action-icon:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.quantity-label {
|
||||
font-size: 28rpx;
|
||||
color: #6C7380;
|
||||
@@ -673,13 +828,15 @@ export default {
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
gap: 24rpx;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 32rpx;
|
||||
border-top: 1rpx solid #eee;
|
||||
|
||||
.u-button {
|
||||
flex: 1;
|
||||
}
|
||||
background-color: #fff;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.white {
|
||||
@@ -711,6 +868,10 @@ export default {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.flex-jus-center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.flex-ali-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@@ -32,23 +32,32 @@
|
||||
class="product-item white b-r-8 p-32 m-t-2"
|
||||
v-for="item in productList"
|
||||
:key="item.id"
|
||||
@click="handleSelectProduct(item)"
|
||||
>
|
||||
<view class="product-header flex-row flex-jus-sp flex-ali-center">
|
||||
<d-text :text="item.drug.drug_name || item.drug.name" className="fs-3 color0 bold"></d-text>
|
||||
<d-text :text="`¥${parseFloat(item.price || 0).toFixed(2)}`" className="fs-3 error-c"></d-text>
|
||||
</view>
|
||||
<view class="product-info m-t-16">
|
||||
<d-text :text="`规格:${item.drug.specification || '--'}`" className="fs-24 color9"></d-text>
|
||||
</view>
|
||||
<view class="product-action m-t-16">
|
||||
<u-button
|
||||
size="mini"
|
||||
:custom-style="{ backgroundColor: '#6ACDBB', color: '#fff' }"
|
||||
@click.stop="handleSelectProduct(item)"
|
||||
>
|
||||
选择
|
||||
</u-button>
|
||||
<view class="product-content flex-row">
|
||||
<image
|
||||
v-if="(item.drug && item.drug.image) || item.image"
|
||||
:src="(item.drug && item.drug.image) || item.image"
|
||||
class="product-image"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view class="product-info-wrapper flex-1">
|
||||
<view class="product-header flex-row flex-jus-sp flex-ali-center">
|
||||
<d-text :text="item.drug.drug_name || item.drug.name" className="fs-3 color0 bold"></d-text>
|
||||
<d-text :text="`¥${parseFloat(item.price || 0).toFixed(2)}`" className="fs-3 error-c"></d-text>
|
||||
</view>
|
||||
<view class="product-info m-t-16">
|
||||
<d-text :text="`规格:${item.drug.specification || '--'}`" className="fs-24 color9"></d-text>
|
||||
</view>
|
||||
<view class="product-action m-t-16">
|
||||
<u-button
|
||||
size="mini"
|
||||
:custom-style="{ backgroundColor: '#6ACDBB', color: '#fff' }"
|
||||
@click.stop="handleSelectProduct(item)"
|
||||
>
|
||||
选择
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -58,6 +67,32 @@
|
||||
<d-empty text="暂无产品"></d-empty>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="modal-footer flex-jus-sp flex-ali-center">
|
||||
<u-button
|
||||
:throttle-time="0"
|
||||
@click="handleClose"
|
||||
shape="circle"
|
||||
:custom-style="{
|
||||
backgroundColor: '#f5f5f5',
|
||||
color: '#333',
|
||||
height: '86rpx',
|
||||
width: '320rpx'
|
||||
}"
|
||||
>取消</u-button>
|
||||
<u-button
|
||||
:throttle-time="0"
|
||||
@click="handleClose"
|
||||
shape="circle"
|
||||
:custom-style="{
|
||||
backgroundColor: '#6ACDBB',
|
||||
color: '#fff',
|
||||
height: '86rpx',
|
||||
width: '320rpx'
|
||||
}"
|
||||
>确定</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
@@ -221,6 +256,23 @@ export default {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.product-content {
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 8rpx;
|
||||
flex-shrink: 0;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.product-info-wrapper {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.product-header {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
@@ -235,7 +287,7 @@ export default {
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
padding: 100rpx 0;
|
||||
//padding: 100rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -283,4 +335,17 @@ export default {
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 32rpx;
|
||||
border-top: 1rpx solid #eee;
|
||||
background-color: #fff;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -79,6 +79,32 @@
|
||||
<d-empty text="暂无药品"></d-empty>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="modal-footer flex-jus-sp flex-ali-center">
|
||||
<u-button
|
||||
:throttle-time="0"
|
||||
@click="handleClose"
|
||||
shape="circle"
|
||||
:custom-style="{
|
||||
backgroundColor: '#f5f5f5',
|
||||
color: '#333',
|
||||
height: '86rpx',
|
||||
width: '320rpx'
|
||||
}"
|
||||
>取消</u-button>
|
||||
<u-button
|
||||
:throttle-time="0"
|
||||
@click="handleClose"
|
||||
shape="circle"
|
||||
:custom-style="{
|
||||
backgroundColor: '#6ACDBB',
|
||||
color: '#fff',
|
||||
height: '86rpx',
|
||||
width: '320rpx'
|
||||
}"
|
||||
>确定</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
@@ -291,6 +317,7 @@ export default {
|
||||
|
||||
.empty-state {
|
||||
padding: 100rpx 0;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -342,4 +369,17 @@ export default {
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 32rpx;
|
||||
border-top: 1rpx solid #eee;
|
||||
background-color: #fff;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -197,17 +197,43 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="bottom-border p-col-32" v-for="(item, index) in currentDrugs" :key="index">
|
||||
<view class="flex-row flex-jus-sp flex-ali-center">
|
||||
<d-text :text="`${index+1}、${item.drug_name}`" className="fs-3 content-c"></d-text>
|
||||
<d-text :text="`¥${parseFloat(item.price || 0).toFixed(2)}`" className="error-c fs-3"></d-text>
|
||||
</view>
|
||||
<view class="flex-row flex-ali-center flex-jus-sp m-t-16">
|
||||
<view class="flex-row flex-ali-center m-t-16">
|
||||
<d-text text="规格:" color="#6C7380"></d-text>
|
||||
<d-text :text="item.specification || '--'" color="#6C7380"></d-text>
|
||||
</view>
|
||||
<view class="flex-row flex-ali-center m-t-16">
|
||||
<d-text :text="`${item.select_number || item.number}${getProductUnit(activeCategory)}`" color="#6C7380"></d-text>
|
||||
<view class="drug-item-content flex-row">
|
||||
<image
|
||||
v-if="item.image"
|
||||
:src="item.image"
|
||||
class="drug-image"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view class="drug-info-wrapper flex-1">
|
||||
<view class="flex-row flex-jus-sp flex-ali-center">
|
||||
<d-text :text="`${index+1}、${item.drug_name}`" className="fs-3 content-c"></d-text>
|
||||
<d-text :text="`¥${parseFloat(item.price || 0).toFixed(2)}`" className="error-c fs-3"></d-text>
|
||||
</view>
|
||||
<view class="flex-row flex-ali-center flex-jus-sp m-t-16">
|
||||
<view class="flex-row flex-ali-center m-t-16">
|
||||
<d-text text="规格:" color="#6C7380"></d-text>
|
||||
<d-text :text="item.specification || '--'" color="#6C7380"></d-text>
|
||||
</view>
|
||||
<view class="flex-row flex-ali-center m-t-16">
|
||||
<view class="quantity-control flex-row flex-ali-center">
|
||||
<u-button
|
||||
size="mini"
|
||||
:custom-style="{ backgroundColor: '#6ACDBB', color: '#fff', width: '48rpx', height: '48rpx', padding: 0 }"
|
||||
@click.stop="handleDecrementSimpleProduct(index)"
|
||||
>
|
||||
-
|
||||
</u-button>
|
||||
<d-text :text="`${item.select_number || item.number}${getProductUnit(activeCategory)}`" color="#6C7380" className="m-l-16 m-r-16"></d-text>
|
||||
<u-button
|
||||
size="mini"
|
||||
:custom-style="{ backgroundColor: '#6ACDBB', color: '#fff', width: '48rpx', height: '48rpx', padding: 0 }"
|
||||
@click.stop="handleIncrementSimpleProduct(index)"
|
||||
>
|
||||
+
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="m-t-24 flex-row flex-jus-sa btnBox">
|
||||
@@ -1155,17 +1181,17 @@ export default {
|
||||
}
|
||||
|
||||
// 添加到列表
|
||||
// 参考PC端:index_id, id, drug_name, number, price, image, instruction, type, select_number
|
||||
const newProduct = {
|
||||
index_id: product.id,
|
||||
id: product.drug_id || product.drug?.id || product.id,
|
||||
drug_id: product.drug_id || product.drug?.id || product.id,
|
||||
drug_name: product.drug_name || product.drug?.drug_name || product.name,
|
||||
number: 1,
|
||||
select_number: 1,
|
||||
price: product.price || 0,
|
||||
specification: product.specification || product.drug?.specification || '',
|
||||
image: product.image || product.drug?.image || '',
|
||||
instruction: product.instruction || product.drug?.instruction || ''
|
||||
instruction: product.instruction || product.drug?.instruction || '',
|
||||
type: product.drug?.type || product.type || this.activeCategory,
|
||||
select_number: 1
|
||||
};
|
||||
|
||||
this.currentDrugs.push(newProduct);
|
||||
@@ -1236,6 +1262,52 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 增加简单产品数量
|
||||
* @param {number} index - 产品索引
|
||||
* 职责:增加简单产品的数量
|
||||
*/
|
||||
handleIncrementSimpleProduct(index) {
|
||||
if (index >= 0 && index < this.currentDrugs.length) {
|
||||
const product = this.currentDrugs[index];
|
||||
const currentNumber = product.select_number || product.number || 1;
|
||||
this.$set(product, 'select_number', currentNumber + 1);
|
||||
// 保存到本地存储
|
||||
this.saveToLocalStorage();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 减少简单产品数量
|
||||
* @param {number} index - 产品索引
|
||||
* 职责:减少简单产品的数量,如果为1则提示删除
|
||||
*/
|
||||
handleDecrementSimpleProduct(index) {
|
||||
if (index >= 0 && index < this.currentDrugs.length) {
|
||||
const product = this.currentDrugs[index];
|
||||
const currentNumber = product.select_number || product.number || 1;
|
||||
if (currentNumber > 1) {
|
||||
this.$set(product, 'select_number', currentNumber - 1);
|
||||
// 保存到本地存储
|
||||
this.saveToLocalStorage();
|
||||
} else {
|
||||
// 数量为1时,提示是否删除
|
||||
uni.showModal({
|
||||
title: '删除产品',
|
||||
content: '数量为1时,是否要删除该产品?',
|
||||
showCancel: true,
|
||||
success: ({ confirm }) => {
|
||||
if (confirm) {
|
||||
this.currentDrugs.splice(index, 1);
|
||||
// 保存到本地存储
|
||||
this.saveToLocalStorage();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除所有药品(中药)
|
||||
* 职责:清空中药列表,保存到本地存储
|
||||
@@ -1630,6 +1702,30 @@ export default {
|
||||
select_number: drug.select_number || 1 // 选择数量
|
||||
};
|
||||
|
||||
return cleanDrug;
|
||||
});
|
||||
} else if ([3, 5, 6, 7].includes(this.activeCategory)) {
|
||||
// 简单产品(保健食品、产品服务包、非药品、医疗器械):参考PC端,不需要用法用量
|
||||
// PC端字段:index_id, id, drug_name, number, price, image, instruction, type, select_number
|
||||
drugsData = this.currentDrugs.map((drug) => {
|
||||
const cleanDrug = {
|
||||
index_id: drug.index_id,
|
||||
id: drug.id,
|
||||
drug_name: drug.drug_name || drug.name,
|
||||
number: drug.number || 1,
|
||||
price: drug.price || '0.0000',
|
||||
select_number: drug.select_number || 1
|
||||
};
|
||||
// 可选字段:image, instruction, type(如果存在则保留)
|
||||
if (drug.image) {
|
||||
cleanDrug.image = drug.image;
|
||||
}
|
||||
if (drug.instruction) {
|
||||
cleanDrug.instruction = drug.instruction;
|
||||
}
|
||||
if (drug.type) {
|
||||
cleanDrug.type = drug.type;
|
||||
}
|
||||
return cleanDrug;
|
||||
});
|
||||
} else {
|
||||
@@ -1903,6 +1999,20 @@ export default {
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.m-l-16 {
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.m-r-16 {
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.quantity-control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
@@ -1986,12 +2096,17 @@ export default {
|
||||
background: #fff;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
color: #6ACDBB;
|
||||
font-size: 28rpx;
|
||||
padding: 0 32rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
|
||||
Reference in New Issue
Block a user