935 lines
32 KiB
Vue
935 lines
32 KiB
Vue
<template>
|
||
<view v-if="mode === 'clinic_post_register'">
|
||
<AssistantConsultationShell
|
||
header-title="复诊用药确认"
|
||
:show-notice="showPostRegisterNotice"
|
||
:parsed-notice-parts="parsedPostRegisterNoticeParts"
|
||
:show-agreement.sync="showPostRegisterAgreement"
|
||
:agreement-content="postRegisterAgreementContent"
|
||
:current-agreement-name="postRegisterCurrentAgreementName"
|
||
:displayed-messages="postRegisterDisplayedMessages"
|
||
:assistant-avatar="postRegAssistantAvatar"
|
||
:assistant-name="postRegAssistantName"
|
||
user-avatar="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/images/user-avatar.png"
|
||
:prescription-info="postRegisterPrescriptionInfo"
|
||
:is-typing="postRegisterIsTyping"
|
||
:scroll-into-view="postRegisterScrollIntoView"
|
||
:show-question-buttons="postRegisterStep === 'await_answer'"
|
||
:current-question="postRegisterCurrentQuestion"
|
||
:current-question-answers="postRegisterQuestionAnswers"
|
||
:is-submitting="postRegisterSubmitting"
|
||
:show-waiting="postRegisterWaiting"
|
||
@back="handlePostRegisterBack"
|
||
@answer="onPostRegisterShellAnswer"
|
||
@view-agreement="viewPostRegisterAgreement"
|
||
/>
|
||
<u-toast ref="uToast" />
|
||
</view>
|
||
|
||
<view v-else class="page">
|
||
<view class="page-inner safe-area-bottom">
|
||
<view class="page-title">{{ pageTitle }}</view>
|
||
|
||
<!-- 药店:商品摘要 -->
|
||
<block v-if="mode === 'pharmacy'">
|
||
<view class="product-info-row">
|
||
<image class="p-img" :src="productDetail.image" mode="aspectFill"></image>
|
||
<view class="p-info">
|
||
<view class="p-name">{{ productDetail.drug_name }}</view>
|
||
<view class="p-spec">{{ productDetail.specification || '暂无规格' }}</view>
|
||
<view class="p-price">¥{{ productPrice }}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="quantity-row">
|
||
<text class="label">购买数量</text>
|
||
<u-number-box v-model="prescriptionQuantity" :min="1" :max="999" integer :step="1"></u-number-box>
|
||
</view>
|
||
|
||
<u-form :model="prescriptionFormData" ref="prescriptionForm">
|
||
<u-form-item label="是否就诊过" prop="hasVisited" label-width="200">
|
||
<u-radio-group v-model="prescriptionFormData.hasVisited">
|
||
<u-radio name="1" active-color="#2B85E4" style="margin-right: 40rpx;">是</u-radio>
|
||
<u-radio name="0" active-color="#2B85E4">否</u-radio>
|
||
</u-radio-group>
|
||
</u-form-item>
|
||
<u-form-item label="是否用过此药" prop="hasUsedDrug" label-width="200">
|
||
<u-radio-group v-model="prescriptionFormData.hasUsedDrug">
|
||
<u-radio name="1" active-color="#2B85E4" style="margin-right: 40rpx;">是</u-radio>
|
||
<u-radio name="0" active-color="#2B85E4">否</u-radio>
|
||
</u-radio-group>
|
||
</u-form-item>
|
||
<view class="illness-section">
|
||
<view class="illness-label">症状</view>
|
||
<view class="illness-tags">
|
||
<u-tag
|
||
v-for="(item, index) in illnessOptions"
|
||
:key="index"
|
||
:text="item.label"
|
||
mode="dark"
|
||
:bg-color="selectedIllnessIndexes.includes(index) ? '#2B85E4' : 'rgba(43,133,228,0.08)'"
|
||
:color="selectedIllnessIndexes.includes(index) ? '#FFFFFF' : '#475569'"
|
||
@tap="toggleIllnessTag(index)"
|
||
/>
|
||
</view>
|
||
<u-input
|
||
v-if="showIllnessOtherInput"
|
||
v-model="illnessOtherText"
|
||
placeholder="请填写具体症状"
|
||
:border="true"
|
||
@input="syncIllnessInfo"
|
||
/>
|
||
</view>
|
||
</u-form>
|
||
</block>
|
||
|
||
<!-- 诊所复诊:用药确认(仅聊天内入口) -->
|
||
<block v-else-if="mode === 'clinic_followup'">
|
||
<view v-if="clinicQuestion" class="clinic-question">{{ clinicQuestion }}</view>
|
||
<view v-if="clinicDrugs.length" class="clinic-drugs">
|
||
<view class="sub-title">涉及药品</view>
|
||
<view v-for="(row, idx) in clinicDrugs" :key="'d-' + idx" class="drug-line">
|
||
<text class="n">{{ row.name || '药品' }}</text>
|
||
<text class="q">×{{ row.quantity != null ? row.quantity : 1 }}</text>
|
||
</view>
|
||
</view>
|
||
<u-form :model="clinicForm" ref="clinicFormRef">
|
||
<u-form-item label="是否用过此类药" prop="hasUsedDrug" label-width="220">
|
||
<u-radio-group v-model="clinicForm.hasUsedDrug">
|
||
<u-radio name="1" active-color="#2B85E4" style="margin-right: 40rpx;">是</u-radio>
|
||
<u-radio name="0" active-color="#2B85E4">否</u-radio>
|
||
</u-radio-group>
|
||
</u-form-item>
|
||
</u-form>
|
||
</block>
|
||
|
||
<view class="popup-actions">
|
||
<button class="btn-cancel" @click="goBack">取消</button>
|
||
<button class="btn-confirm" @click="onSubmit">{{ submitButtonText }}</button>
|
||
</view>
|
||
</view>
|
||
|
||
<u-toast ref="uToast" />
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { getStoreDrugDetailApi, checkOnlineConsultationConfigApi } from '@/request/api/product';
|
||
import request from '@/request/api/request';
|
||
import { confirmFollowUpDrugUseApi } from '@/request/api/order';
|
||
import {
|
||
CLINIC_POST_REGISTER_STORAGE_KEY,
|
||
markFollowUpAssistSent,
|
||
sendFollowUpDrugAssistantMessage,
|
||
wasFollowUpAssistSent,
|
||
} from '@/utils/clinicFollowUpAssistantIm';
|
||
import AssistantConsultationShell from '@/components/AssistantConsultationShell.vue';
|
||
import {
|
||
getTransferAssistantConfigApi,
|
||
getTransferConsultationAgreementInfoApi,
|
||
getAgreementDetailApi,
|
||
} from '@/request/api/transferPrescription.js';
|
||
|
||
const FOLLOWUP_PAYLOAD_KEY = '__medication_followup_payload';
|
||
|
||
export default {
|
||
components: { AssistantConsultationShell },
|
||
data() {
|
||
return {
|
||
mode: 'pharmacy',
|
||
productDetail: {
|
||
id: '',
|
||
type: 2,
|
||
drug_name: '',
|
||
image: '',
|
||
price: 0,
|
||
specification: '',
|
||
indications_array: [],
|
||
},
|
||
prescriptionQuantity: 1,
|
||
prescriptionFormData: {
|
||
hasVisited: '1',
|
||
hasUsedDrug: '1',
|
||
illnessInfo: '',
|
||
},
|
||
illnessOptions: [],
|
||
selectedIllnessIndexes: [],
|
||
illnessOtherText: '',
|
||
delegateStoreId: '',
|
||
doctorIdFromQuery: '',
|
||
submitted: false,
|
||
// clinic
|
||
registerInfoId: '',
|
||
messageId: '',
|
||
clinicQuestion: '',
|
||
clinicDrugs: [],
|
||
clinicForm: {
|
||
hasUsedDrug: '1',
|
||
},
|
||
postRegisterRoomId: '',
|
||
postRegisterDoctorId: '',
|
||
postRegisterPatientId: '',
|
||
postRegisterDoctorPrefixed: '',
|
||
postRegisterRegisterId: '',
|
||
// clinic_post_register(与转诊咨询壳共用 UI)
|
||
postRegisterQuestionList: [],
|
||
postRegisterQuestionIndex: -1,
|
||
postRegisterUserAnswers: [],
|
||
postRegisterReplyDelay: 0.65,
|
||
postRegisterIsTyping: false,
|
||
postRegisterShowWelcome: true,
|
||
/** idle | await_answer | typing_after | submitting */
|
||
postRegisterStep: 'idle',
|
||
postRegisterScrollIntoView: '',
|
||
postRegisterSubmitting: false,
|
||
postRegisterWaiting: false,
|
||
postRegAssistantAvatar: 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/images/assistant-avatar.png',
|
||
postRegAssistantName: '医生助理',
|
||
showPostRegisterNotice: true,
|
||
parsedPostRegisterNoticeParts: [],
|
||
postRegisterAgreements: [],
|
||
postRegisterNoticeText: '',
|
||
showPostRegisterAgreement: false,
|
||
postRegisterAgreementContent: '',
|
||
postRegisterCurrentAgreementName: '',
|
||
};
|
||
},
|
||
computed: {
|
||
pageTitle() {
|
||
if (this.mode === 'clinic_followup') return '请填写用药信息';
|
||
return '请填写用药信息';
|
||
},
|
||
submitButtonText() {
|
||
return '提交';
|
||
},
|
||
postRegisterPrescriptionInfo() {
|
||
if (!this.clinicDrugs || !this.clinicDrugs.length) return '相关药品';
|
||
return this.clinicDrugs
|
||
.map((row) => `${row.name || '药品'}×${row.quantity != null ? row.quantity : 1}`)
|
||
.join('、');
|
||
},
|
||
postRegisterDisplayedMessages() {
|
||
const messages = [];
|
||
if (this.postRegisterShowWelcome) {
|
||
messages.push({ type: 'welcome', id: 'welcome-msg', timestamp: 0 });
|
||
}
|
||
const qs = this.postRegisterQuestionList;
|
||
const idx = this.postRegisterQuestionIndex;
|
||
for (let i = 0; i <= idx && i < qs.length; i++) {
|
||
const q = qs[i];
|
||
messages.push({
|
||
type: 'question',
|
||
id: `question-${q.id}`,
|
||
questionId: q.id,
|
||
content: q.question,
|
||
timestamp: i * 2 + 1,
|
||
});
|
||
if (i < this.postRegisterUserAnswers.length) {
|
||
messages.push({
|
||
type: 'answer',
|
||
id: `answer-${i}`,
|
||
content: this.postRegisterUserAnswers[i],
|
||
timestamp: i * 2 + 2,
|
||
});
|
||
}
|
||
}
|
||
if (this.postRegisterWaiting) {
|
||
messages.push({
|
||
type: 'waiting',
|
||
id: 'waiting-msg',
|
||
timestamp: messages.length,
|
||
});
|
||
}
|
||
return messages;
|
||
},
|
||
postRegisterCurrentQuestion() {
|
||
if (this.postRegisterStep !== 'await_answer') return null;
|
||
if (!this.postRegisterQuestionList.length) return null;
|
||
return this.postRegisterQuestionList[0];
|
||
},
|
||
postRegisterQuestionAnswers() {
|
||
return ['是', '否'];
|
||
},
|
||
productPrice() {
|
||
const rel = this.productDetail.drug_store_relations;
|
||
if (rel && rel.price) {
|
||
return parseFloat(rel.price);
|
||
}
|
||
if (this.productDetail.drug_store_drug && this.productDetail.drug_store_drug.price) {
|
||
return parseFloat(this.productDetail.drug_store_drug.price);
|
||
}
|
||
return parseFloat(this.productDetail.price || 0);
|
||
},
|
||
showIllnessOtherInput() {
|
||
return this.selectedIllnessIndexes.some(
|
||
(idx) => this.illnessOptions[idx] && this.illnessOptions[idx].value === '__other__',
|
||
);
|
||
},
|
||
},
|
||
onLoad(options) {
|
||
if (options.mode === 'clinic_post_register') {
|
||
this.mode = 'clinic_post_register';
|
||
try {
|
||
const raw = uni.getStorageSync(CLINIC_POST_REGISTER_STORAGE_KEY);
|
||
if (raw) {
|
||
const o = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
||
this.registerInfoId = String(o.register_info_id || '');
|
||
this.clinicQuestion = o.question || '您是否曾使用过此类药品?';
|
||
this.clinicDrugs = Array.isArray(o.drugs) ? o.drugs : [];
|
||
this.postRegisterRoomId = o.room_id || '';
|
||
this.postRegisterDoctorId = o.doctor_id != null ? String(o.doctor_id) : '';
|
||
this.postRegisterPatientId = String(o.patient_id || '');
|
||
this.postRegisterDoctorPrefixed = o.doctor_prefixed || '';
|
||
this.postRegisterRegisterId = String(o.register_id || '');
|
||
}
|
||
} catch (e) {
|
||
console.error('medication-info clinic_post_register', e);
|
||
}
|
||
uni.removeStorageSync(CLINIC_POST_REGISTER_STORAGE_KEY);
|
||
if (!this.registerInfoId || !this.postRegisterRoomId || !this.postRegisterDoctorId || !this.postRegisterRegisterId) {
|
||
uni.showToast({ title: '参数无效', icon: 'none' });
|
||
} else {
|
||
this.postRegisterQuestionList = [
|
||
{
|
||
id: 'clinic-post-reg-1',
|
||
question: this.clinicQuestion || '您是否曾使用过此类药品?',
|
||
answers: ['是', '否'],
|
||
},
|
||
];
|
||
this.loadPostRegisterAssistantConfig();
|
||
this.loadPostRegisterAgreementInfo();
|
||
this.$nextTick(() => this.beginPostRegisterAssistantFlow());
|
||
}
|
||
return;
|
||
}
|
||
this.mode = options.mode === 'clinic_followup' ? 'clinic_followup' : 'pharmacy';
|
||
if (this.mode === 'clinic_followup') {
|
||
this.messageId = options.message_id || '';
|
||
try {
|
||
const raw = uni.getStorageSync(FOLLOWUP_PAYLOAD_KEY);
|
||
if (raw) {
|
||
const o = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
||
this.registerInfoId = String(o.register_info_id || '');
|
||
this.clinicQuestion = o.question || '';
|
||
this.clinicDrugs = Array.isArray(o.drugs) ? o.drugs : [];
|
||
}
|
||
} catch (e) {
|
||
console.error('medication-info clinic payload', e);
|
||
}
|
||
uni.removeStorageSync(FOLLOWUP_PAYLOAD_KEY);
|
||
if (!this.registerInfoId) {
|
||
uni.showToast({ title: '参数无效', icon: 'none' });
|
||
}
|
||
return;
|
||
}
|
||
this.productDetail.id = options.id || '';
|
||
this.doctorIdFromQuery = options.doctor_id || '';
|
||
this.delegateStoreId = options.delegate_store_id || '';
|
||
if (options.drug_name) {
|
||
try {
|
||
this.productDetail.drug_name = decodeURIComponent(options.drug_name);
|
||
} catch {
|
||
this.productDetail.drug_name = options.drug_name;
|
||
}
|
||
}
|
||
if (options.image) {
|
||
try {
|
||
this.productDetail.image = decodeURIComponent(options.image);
|
||
} catch {
|
||
this.productDetail.image = options.image;
|
||
}
|
||
}
|
||
if (options.price) this.productDetail.price = parseFloat(options.price);
|
||
if (options.type) this.productDetail.type = parseInt(options.type, 10) || 2;
|
||
if (this.productDetail.id) {
|
||
this.getDetail();
|
||
} else {
|
||
uni.showToast({ title: '缺少商品信息', icon: 'none' });
|
||
}
|
||
},
|
||
onBackPress() {
|
||
if (this.mode === 'clinic_post_register' && this.showPostRegisterAgreement) {
|
||
this.showPostRegisterAgreement = false;
|
||
return true;
|
||
}
|
||
return false;
|
||
},
|
||
methods: {
|
||
postRegisterScrollToBottom() {
|
||
this.postRegisterScrollIntoView = 'bottom-anchor';
|
||
setTimeout(() => {
|
||
this.postRegisterScrollIntoView = '';
|
||
}, 120);
|
||
},
|
||
beginPostRegisterAssistantFlow() {
|
||
this.postRegisterStep = 'idle';
|
||
this.postRegisterShowWelcome = true;
|
||
this.postRegisterUserAnswers = [];
|
||
this.postRegisterWaiting = false;
|
||
this.postRegisterQuestionIndex = -1;
|
||
this.postRegisterIsTyping = true;
|
||
const delayMs = Math.max(200, (this.postRegisterReplyDelay || 0.65) * 1000);
|
||
setTimeout(() => {
|
||
this.postRegisterIsTyping = false;
|
||
this.postRegisterQuestionIndex = 0;
|
||
this.postRegisterStep = 'await_answer';
|
||
this.$nextTick(() => this.postRegisterScrollToBottom());
|
||
}, delayMs);
|
||
},
|
||
onPostRegisterShellAnswer(answer) {
|
||
if (this.postRegisterStep !== 'await_answer' || this.submitted) return;
|
||
this.postRegisterUserAnswers = [answer];
|
||
this.clinicForm.hasUsedDrug = answer === '是' ? '1' : '0';
|
||
this.postRegisterStep = 'typing_after';
|
||
this.postRegisterIsTyping = true;
|
||
this.$nextTick(() => this.postRegisterScrollToBottom());
|
||
const typingMs = Math.max(200, (this.postRegisterReplyDelay || 0.65) * 1000);
|
||
setTimeout(() => {
|
||
this.postRegisterIsTyping = false;
|
||
this.$nextTick(() => this.postRegisterScrollToBottom());
|
||
// 与转诊一致:最后一题答完后短延迟再自动提交
|
||
setTimeout(() => {
|
||
this.submitClinicPostRegister();
|
||
}, 500);
|
||
}, typingMs);
|
||
},
|
||
resetPostRegisterAfterSubmitFailure() {
|
||
this.submitted = false;
|
||
this.postRegisterWaiting = false;
|
||
this.postRegisterStep = 'await_answer';
|
||
if (this.clinicForm.hasUsedDrug === '0' || this.clinicForm.hasUsedDrug === '1') {
|
||
this.postRegisterUserAnswers = [this.clinicForm.hasUsedDrug === '1' ? '是' : '否'];
|
||
} else {
|
||
this.postRegisterUserAnswers = [];
|
||
}
|
||
this.$nextTick(() => this.postRegisterScrollToBottom());
|
||
},
|
||
async loadPostRegisterAssistantConfig() {
|
||
try {
|
||
const res = await getTransferAssistantConfigApi();
|
||
if (res.data && res.data.code === 0) {
|
||
const config = res.data.result || {};
|
||
this.postRegAssistantName = config.name || '医生助理';
|
||
this.postRegAssistantAvatar = config.avatar || 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/images/assistant-avatar.png';
|
||
const d = parseFloat(config.reply_delay);
|
||
if (!Number.isNaN(d) && d > 0) {
|
||
this.postRegisterReplyDelay = d;
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.warn('loadPostRegisterAssistantConfig', e);
|
||
}
|
||
},
|
||
async loadPostRegisterAgreementInfo() {
|
||
try {
|
||
const res = await getTransferConsultationAgreementInfoApi();
|
||
if (res.data && res.data.code === 0) {
|
||
const result = res.data.result || {};
|
||
this.postRegisterNoticeText = result.notice_text || '';
|
||
this.postRegisterAgreements = result.agreements || [];
|
||
this.parsePostRegisterNoticeText();
|
||
this.showPostRegisterNotice =
|
||
this.parsedPostRegisterNoticeParts.length > 0 || !!this.postRegisterNoticeText;
|
||
}
|
||
} catch (e) {
|
||
console.warn('loadPostRegisterAgreementInfo', e);
|
||
this.postRegisterNoticeText =
|
||
'根据国家互联网医院管理办法要求,平台仅为复诊患者提供服务。为了保障您的用药安全,请根据真实情况回答,并请仔细阅读《互联网医疗风险告知及知情同意书》,继续咨询即表示您已知悉相关规则与风险并同意相关条款。';
|
||
this.parsePostRegisterNoticeText();
|
||
this.showPostRegisterNotice =
|
||
this.parsedPostRegisterNoticeParts.length > 0 || !!this.postRegisterNoticeText;
|
||
}
|
||
},
|
||
parsePostRegisterNoticeText() {
|
||
if (!this.postRegisterNoticeText) {
|
||
this.parsedPostRegisterNoticeParts = [];
|
||
return;
|
||
}
|
||
const parts = [];
|
||
const regex = /《([^》]+)》/g;
|
||
let lastIndex = 0;
|
||
let match;
|
||
while ((match = regex.exec(this.postRegisterNoticeText)) !== null) {
|
||
if (match.index > lastIndex) {
|
||
parts.push({
|
||
type: 'text',
|
||
text: this.postRegisterNoticeText.substring(lastIndex, match.index),
|
||
});
|
||
}
|
||
const agreementName = match[1];
|
||
const agreement = this.postRegisterAgreements.find(
|
||
(ag) => ag.name === agreementName || (ag.name && ag.name.includes(agreementName)),
|
||
);
|
||
if (agreement) {
|
||
parts.push({
|
||
type: 'agreement',
|
||
text: agreementName,
|
||
agreementId: agreement.id,
|
||
});
|
||
} else {
|
||
parts.push({ type: 'text', text: match[0] });
|
||
}
|
||
lastIndex = regex.lastIndex;
|
||
}
|
||
if (lastIndex < this.postRegisterNoticeText.length) {
|
||
parts.push({
|
||
type: 'text',
|
||
text: this.postRegisterNoticeText.substring(lastIndex),
|
||
});
|
||
}
|
||
this.parsedPostRegisterNoticeParts = parts;
|
||
},
|
||
async viewPostRegisterAgreement(agreementId) {
|
||
if (!agreementId) {
|
||
uni.showToast({ title: '协议ID不能为空', icon: 'none' });
|
||
return;
|
||
}
|
||
const agreement = this.postRegisterAgreements.find((ag) => ag.id === agreementId);
|
||
this.postRegisterCurrentAgreementName = agreement ? agreement.name : '协议详情';
|
||
this.showPostRegisterAgreement = true;
|
||
try {
|
||
const res = await getAgreementDetailApi(agreementId);
|
||
if (res.data && res.data.code === 0) {
|
||
const result = res.data.result || {};
|
||
this.postRegisterAgreementContent = result.content || '';
|
||
if (result.name) {
|
||
this.postRegisterCurrentAgreementName = result.name;
|
||
}
|
||
} else {
|
||
throw new Error((res.data && res.data.message) || '获取协议详情失败');
|
||
}
|
||
} catch (error) {
|
||
console.error('viewPostRegisterAgreement', error);
|
||
uni.showToast({
|
||
title: (error && error.message) || '获取协议详情失败',
|
||
icon: 'none',
|
||
});
|
||
this.showPostRegisterAgreement = false;
|
||
}
|
||
},
|
||
handlePostRegisterBack() {
|
||
if (this.showPostRegisterAgreement) {
|
||
this.showPostRegisterAgreement = false;
|
||
return;
|
||
}
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定返回首页吗?未完成确认将无法同步给医生。',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
uni.switchTab({ url: '/pages/home/home' });
|
||
}
|
||
},
|
||
});
|
||
},
|
||
goBack() {
|
||
if (this.mode === 'clinic_post_register') {
|
||
uni.switchTab({ url: '/pages/home/home' });
|
||
return;
|
||
}
|
||
uni.navigateBack({ delta: 1 });
|
||
},
|
||
getDetail() {
|
||
getStoreDrugDetailApi({ id: this.productDetail.id }).then((res) => {
|
||
if (res.data.code === 0) {
|
||
const data = res.data.result;
|
||
Object.assign(this.productDetail, data);
|
||
const options = (data.indications_array || []).map((item) => ({
|
||
value: item.label || item.value,
|
||
label: item.label || item.value,
|
||
}));
|
||
options.push({ value: '__other__', label: '其他' });
|
||
this.illnessOptions = options;
|
||
}
|
||
});
|
||
},
|
||
toggleIllnessTag(index) {
|
||
const pos = this.selectedIllnessIndexes.indexOf(index);
|
||
if (pos === -1) {
|
||
this.selectedIllnessIndexes.push(index);
|
||
} else {
|
||
this.selectedIllnessIndexes.splice(pos, 1);
|
||
if (this.illnessOptions[index] && this.illnessOptions[index].value === '__other__') {
|
||
this.illnessOtherText = '';
|
||
}
|
||
}
|
||
this.syncIllnessInfo();
|
||
},
|
||
syncIllnessInfo() {
|
||
const parts = this.selectedIllnessIndexes
|
||
.map((idx) => {
|
||
const opt = this.illnessOptions[idx];
|
||
if (!opt) return '';
|
||
if (opt.value === '__other__') {
|
||
return (this.illnessOtherText || '').trim();
|
||
}
|
||
return opt.label || opt.value;
|
||
})
|
||
.filter(Boolean);
|
||
this.prescriptionFormData.illnessInfo = parts.join('、');
|
||
},
|
||
async getDefaultDoctorId() {
|
||
try {
|
||
const storeId = uni.getStorageSync('store_id');
|
||
if (!storeId) {
|
||
return { data: { result: { doctor_id: null } } };
|
||
}
|
||
const res = await request('/xkApi/online-consultation/get-default-doctor-id', {
|
||
method: 'GET',
|
||
data: { store_id: storeId },
|
||
}, 0);
|
||
return res;
|
||
} catch (error) {
|
||
console.error('获取默认医生ID失败:', error);
|
||
return { data: { result: { doctor_id: null } } };
|
||
}
|
||
},
|
||
onSubmit() {
|
||
if (this.mode === 'clinic_followup') {
|
||
this.submitClinic();
|
||
} else {
|
||
this.submitPharmacy();
|
||
}
|
||
},
|
||
submitClinicPostRegister() {
|
||
if (!this.registerInfoId || !this.postRegisterRoomId || !this.postRegisterDoctorId || !this.postRegisterRegisterId) {
|
||
uni.showToast({ title: '参数缺失', icon: 'none' });
|
||
return;
|
||
}
|
||
if (this.clinicForm.hasUsedDrug !== '0' && this.clinicForm.hasUsedDrug !== '1') {
|
||
uni.showToast({ title: '请先选择是否用过药', icon: 'none' });
|
||
return;
|
||
}
|
||
if (this.submitted) return;
|
||
this.submitted = true;
|
||
this.postRegisterSubmitting = true;
|
||
this.postRegisterWaiting = true;
|
||
this.postRegisterStep = 'submitting';
|
||
this.$nextTick(() => this.postRegisterScrollToBottom());
|
||
const val = this.clinicForm.hasUsedDrug;
|
||
const answerStatus = val === '1' ? 'yes' : 'no';
|
||
confirmFollowUpDrugUseApi({
|
||
register_info_id: this.registerInfoId,
|
||
has_used_drug: val,
|
||
})
|
||
.then(async (res) => {
|
||
const d = res.data || {};
|
||
const ok = d.errcode === 0 || d.code === 0 || d.status === true;
|
||
if (!ok) {
|
||
this.resetPostRegisterAfterSubmitFailure();
|
||
uni.showToast({ title: d.msg || d.message || '提交失败', icon: 'none' });
|
||
return;
|
||
}
|
||
try {
|
||
if (!wasFollowUpAssistSent(this.postRegisterRegisterId)) {
|
||
await sendFollowUpDrugAssistantMessage({
|
||
roomId: this.postRegisterRoomId,
|
||
doctorId: this.postRegisterDoctorId,
|
||
registerId: this.postRegisterRegisterId,
|
||
registerInfoId: this.registerInfoId,
|
||
drugsPayload: this.clinicDrugs,
|
||
question: this.clinicQuestion,
|
||
answerStatus,
|
||
});
|
||
markFollowUpAssistSent(this.postRegisterRegisterId);
|
||
}
|
||
} catch (e) {
|
||
console.error('sendFollowUpDrugAssistantMessage', e);
|
||
this.resetPostRegisterAfterSubmitFailure();
|
||
uni.showToast({ title: '发送消息失败,请重试', icon: 'none' });
|
||
return;
|
||
}
|
||
const encUser = encodeURIComponent(
|
||
this.postRegisterDoctorPrefixed || `doctor-${this.postRegisterDoctorId}`,
|
||
);
|
||
const chatUrl = `/subPackages/chat/chat?user_id=${encUser}&room_id=${this.postRegisterRoomId}®ister_id=${this.postRegisterRegisterId}`;
|
||
uni.redirectTo({ url: chatUrl });
|
||
})
|
||
.catch(() => {
|
||
this.resetPostRegisterAfterSubmitFailure();
|
||
uni.showToast({ title: '提交失败', icon: 'none' });
|
||
})
|
||
.finally(() => {
|
||
this.postRegisterSubmitting = false;
|
||
this.postRegisterWaiting = false;
|
||
});
|
||
},
|
||
submitClinic() {
|
||
if (!this.registerInfoId) {
|
||
uni.showToast({ title: '缺少登记信息', icon: 'none' });
|
||
return;
|
||
}
|
||
if (this.clinicForm.hasUsedDrug !== '0' && this.clinicForm.hasUsedDrug !== '1') {
|
||
uni.showToast({ title: '请选择是否用过药', icon: 'none' });
|
||
return;
|
||
}
|
||
uni.showLoading({ title: '提交中', mask: true });
|
||
confirmFollowUpDrugUseApi({
|
||
register_info_id: this.registerInfoId,
|
||
has_used_drug: this.clinicForm.hasUsedDrug,
|
||
})
|
||
.then((res) => {
|
||
const d = res.data || {};
|
||
const ok = d.errcode === 0 || d.code === 0 || d.status === true;
|
||
if (ok) {
|
||
const val = this.clinicForm.hasUsedDrug;
|
||
const answerStatus = val === '1' ? 'yes' : 'no';
|
||
try {
|
||
const ec = this.getOpenerEventChannel && this.getOpenerEventChannel();
|
||
if (ec && ec.emit) {
|
||
ec.emit('followUpDrugCompleted', {
|
||
messageId: this.messageId,
|
||
answerStatus,
|
||
raw: val,
|
||
});
|
||
}
|
||
} catch (e) {
|
||
console.warn('eventChannel', e);
|
||
}
|
||
uni.showToast({ title: '已记录', icon: 'success' });
|
||
setTimeout(() => uni.navigateBack({ delta: 1 }), 400);
|
||
} else {
|
||
uni.showToast({ title: d.msg || d.message || '提交失败', icon: 'none' });
|
||
}
|
||
})
|
||
.catch(() => {
|
||
uni.showToast({ title: '提交失败', icon: 'none' });
|
||
})
|
||
.finally(() => {
|
||
uni.hideLoading();
|
||
});
|
||
},
|
||
async submitPharmacy() {
|
||
if (!this.prescriptionFormData.hasVisited || !this.prescriptionFormData.hasUsedDrug) {
|
||
uni.showToast({ title: '请填写完整信息', icon: 'none' });
|
||
return;
|
||
}
|
||
if (!this.selectedIllnessIndexes.length) {
|
||
uni.showToast({ title: '请选择症状', icon: 'none' });
|
||
return;
|
||
}
|
||
if (this.showIllnessOtherInput && !(this.illnessOtherText || '').trim()) {
|
||
uni.showToast({ title: '请填写具体症状', icon: 'none' });
|
||
return;
|
||
}
|
||
this.syncIllnessInfo();
|
||
if (!this.prescriptionFormData.illnessInfo) {
|
||
uni.showToast({ title: '请选择症状', icon: 'none' });
|
||
return;
|
||
}
|
||
if (this.submitted) return;
|
||
const formData = { ...this.prescriptionFormData };
|
||
const quantity = this.prescriptionQuantity;
|
||
this.submitted = true;
|
||
try {
|
||
const storeId = uni.getStorageSync('store_id');
|
||
let delegateStoreId = this.delegateStoreId;
|
||
let doctorId = this.doctorIdFromQuery || null;
|
||
if (!delegateStoreId) {
|
||
const configRes = await checkOnlineConsultationConfigApi({ store_id: storeId });
|
||
if (!configRes.data?.result?.can_use) {
|
||
uni.showToast({
|
||
title: configRes.data?.result?.message || '该门店暂不支持在线复诊功能',
|
||
icon: 'none',
|
||
duration: 2000,
|
||
});
|
||
this.submitted = false;
|
||
return;
|
||
}
|
||
delegateStoreId = configRes.data.result.delegate_store_id || storeId;
|
||
doctorId = configRes.data.result.doctor_id;
|
||
} else if (!doctorId) {
|
||
const doctorRes = await this.getDefaultDoctorId();
|
||
doctorId = doctorRes.data.result?.doctor_id;
|
||
}
|
||
if (!doctorId) {
|
||
uni.showToast({ title: '该门店暂不支持在线复诊', icon: 'none', duration: 2000 });
|
||
this.submitted = false;
|
||
return;
|
||
}
|
||
const createRes = await request('/xkApi/order/create-register-info', {
|
||
method: 'POST',
|
||
data: {
|
||
doctor_id: doctorId,
|
||
drug_id: this.productDetail.id,
|
||
has_visited: formData.hasVisited,
|
||
has_used_drug: formData.hasUsedDrug,
|
||
illnessInfo: formData.illnessInfo,
|
||
type: this.productDetail.type || 2,
|
||
number: quantity,
|
||
},
|
||
}, 1);
|
||
const infoId = createRes.data?.result?.info_id || createRes.data?.info_id;
|
||
if (!infoId) {
|
||
throw new Error('创建就诊信息失败');
|
||
}
|
||
const rInfo = {
|
||
info_id: infoId,
|
||
doctor_id: doctorId,
|
||
has_visited: formData.hasVisited,
|
||
has_used_drug: formData.hasUsedDrug,
|
||
illness_info: formData.illnessInfo,
|
||
drug_name: this.productDetail.drug_name,
|
||
drug_id: this.productDetail.id,
|
||
number: quantity,
|
||
type: this.productDetail.type || 2,
|
||
created_at: new Date().toLocaleString('zh-CN'),
|
||
};
|
||
uni.navigateTo({
|
||
url: `/subPackages/doctor/doctor-userinfo?id=${doctorId}&r_type=3&r_info=${encodeURIComponent(JSON.stringify(rInfo))}&delegate_store_id=${delegateStoreId}`,
|
||
});
|
||
} catch (error) {
|
||
console.error('提交处方药信息失败:', error);
|
||
uni.showToast({ title: '提交失败,请重试', icon: 'none' });
|
||
this.submitted = false;
|
||
}
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.page {
|
||
min-height: 100vh;
|
||
background: #f5f7fa;
|
||
}
|
||
.page-inner {
|
||
padding: 30rpx;
|
||
background: #fff;
|
||
min-height: 100vh;
|
||
}
|
||
.page-title {
|
||
text-align: center;
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
.product-info-row {
|
||
display: flex;
|
||
margin-bottom: 30rpx;
|
||
.p-img {
|
||
width: 160rpx;
|
||
height: 160rpx;
|
||
border-radius: 12rpx;
|
||
background: #f8f8f8;
|
||
margin-right: 20rpx;
|
||
}
|
||
.p-info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
.p-name {
|
||
font-size: 30rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
}
|
||
.p-spec {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
.p-price {
|
||
font-size: 36rpx;
|
||
color: #ff4d4f;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
}
|
||
.quantity-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 20rpx 0;
|
||
border-top: 1rpx solid #f5f5f5;
|
||
border-bottom: 1rpx solid #f5f5f5;
|
||
margin-bottom: 40rpx;
|
||
.label {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
}
|
||
.illness-section {
|
||
padding: 20rpx 0;
|
||
.illness-label {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
.illness-tags {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
::v-deep .u-tag {
|
||
margin: 0 20rpx 16rpx 0;
|
||
}
|
||
}
|
||
}
|
||
.popup-actions {
|
||
display: flex;
|
||
gap: 30rpx;
|
||
margin-top: 40rpx;
|
||
&.post-register-actions {
|
||
flex-direction: column;
|
||
}
|
||
button {
|
||
flex: 1;
|
||
height: 80rpx;
|
||
border-radius: 40rpx;
|
||
font-size: 30rpx;
|
||
border: none;
|
||
&.btn-cancel {
|
||
background: #f5f7fa;
|
||
color: #606266;
|
||
}
|
||
&.btn-confirm {
|
||
background: #2b85e4;
|
||
color: #fff;
|
||
}
|
||
&.btn-confirm-block {
|
||
flex: none;
|
||
width: 100%;
|
||
}
|
||
}
|
||
}
|
||
.post-register-exit {
|
||
text-align: center;
|
||
margin-top: 28rpx;
|
||
font-size: 26rpx;
|
||
color: #909399;
|
||
padding: 16rpx 0;
|
||
}
|
||
.clinic-question {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
line-height: 1.6;
|
||
margin-bottom: 24rpx;
|
||
padding: 20rpx;
|
||
background: #f7f8fa;
|
||
border-radius: 12rpx;
|
||
}
|
||
.clinic-drugs {
|
||
margin-bottom: 24rpx;
|
||
.sub-title {
|
||
font-size: 26rpx;
|
||
color: #909399;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
.drug-line {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
font-size: 28rpx;
|
||
padding: 12rpx 0;
|
||
border-bottom: 1rpx solid #eee;
|
||
.n {
|
||
color: #333;
|
||
}
|
||
.q {
|
||
color: #666;
|
||
}
|
||
}
|
||
}
|
||
.safe-area-bottom {
|
||
padding-bottom: calc(30rpx + env(safe-area-inset-bottom));
|
||
}
|
||
|
||
</style>
|