hn-hlw-app/pages/consult/disease-description.vue

517 lines
11 KiB
Vue
Raw Normal View History

2026-07-27 11:26:39 +08:00
<template>
<full-page :animation="true" ref="pageRef" mainStyle="background:#f0f0f0" @reachBottom="onReachBottom()">
<view class="container" :class="{ 'elder-mode-active': elderMode }">
<view class="user-header shadow-lg">
就诊人{{ form.name }} {{ form.sex }} {{ form.age ? `${form.age}` : '' }}
</view>
<!-- <view class="relative mt-12 px-15 py-12 bg-white shadow-lg" @click="toAddDisease()">
<view class="section-title is-required">已在实体医疗机构确诊的疾病</view>
<view class="disease-tags">
<view v-for="(i, idx) in form.diseases" class="disease-tag" @click.stop="() => { }">
<text>{{ i }}</text>
<text class="disease-remove" @click.stop="removeDisease(idx)"> <uni-icons type="closeempty" color="#b8956a"
size="14"></uni-icons> </text>
</view>
<view class="disease-tag add-tag">+ 添加</view>
</view>
</view> -->
<view class="description-section relative mt-12 px-15 py-12 bg-white shadow-lg">
<view class="section-title is-required">请描述您的病情</view>
<textarea v-model="form.description" :show-confirm-bar="false" auto-height="true" class="mt-10 description"
placeholder-class="placeholderClass" maxlength="300" placeholder="为了更好地获得医生帮助,请尽可能地详细描述病情"
@focus="showDescriptionGuess" @input="handleDescriptionInput" @blur="hideDescriptionGuess"></textarea>
<view v-if="guessVisible" class="guess-popup">
<view class="guess-title">猜你想输入</view>
<view v-for="item in guessList" :key="item" class="guess-option" @click="selectDescriptionGuess(item)">
{{ item }}
</view>
</view>
</view>
<view class="relative mt-12 px-15 py-12 bg-white shadow-lg">
<view class="section-title">上传本院或者外院的病历资料</view>
<view class="mt-10 section-sub-title">
请上传诊断处方出院小结医嘱单浙里办医保结算明细等其中一种
</view>
<view class="image-uploader">
<view v-for="(image, index) in form.images" :key="index" class="image-preview">
<image :src="image" class="image" @click="previewImage(index)" />
<view class="close-icon" @click="removeImage(index)">
<uni-icons color="red" size="24" type="close" />
</view>
</view>
<view v-if="form.images.length < 9" class="upload-button" @click="uploadImage">
<uni-icons type="camera" size="40" />
</view>
</view>
</view>
<view class="relative mt-12 px-15 py-12 bg-white shadow-lg">
<view v-for="history in histories" :key="history.label" class="history-item">
<text class="history-label">{{ history.label }}</text>
<radio-group class="radio-group">
<label v-for="i in history.options" :key="i" class="radio-label">
<radio :value="i" :checked="form[history.prop] === i" @change="changeHistory(history.prop, i)"
class="custom-radio" color="#b8956a" />
<text>{{ i }}</text>
</label>
</radio-group>
</view>
</view>
</view>
<template #footer>
<footer-button text="下一步" theme="brown" @onClick="nextStep" />
</template>
</full-page>
</template>
<script setup>
import { ref } from "vue";
import { storeToRefs } from "pinia";
import { onLoad, onUnload } from '@dcloudio/uni-app';
import orderStore from '@/store/order';
import { uploadUrl, getFullPath } from '@/utils/http';
import { toast, loading, hideLoading } from '@/utils/widget';
import footerButton from '@/components/footer-button.vue';
import fullPage from '@/components/full-page.vue';
const guessList = [
'药已用完,需要再次开药',
'病情稳定,要求开具处方买药',
'没有药了,要求开放续药',
'家里药已用完,需要开具新的处方',
'药用完了,需要再开一些', '病情稳定,要求开方配药',
'上次开的药已经用完,需要续药',
'储备的药品已用完,要求开方配药'
]
const { order: form, histories, ybVisitRecord } = storeToRefs(orderStore());
const { init: initOrder } = orderStore();
const visible = ref(false);
const guessVisible = ref(false);
const reachBottom = ref(false);
const pageRef = ref(null);
let guessCloseTimer = null;
// 长辈模式状态
const elderMode = ref(false);
const titleMap = {
YB: "医保处方",
ZF: "自费处方",
};
function changeHistory(prop, value) {
form.value[prop] = value;
}
function showDescriptionGuess() {
if (guessCloseTimer) clearTimeout(guessCloseTimer);
guessCloseTimer = null;
guessVisible.value = !form.value.description.trim();
}
function handleDescriptionInput(event) {
const description = event && event.detail && typeof event.detail.value === 'string'
? event.detail.value
: form.value.description;
if (description.trim()) {
guessVisible.value = false;
}
}
function hideDescriptionGuess() {
if (guessCloseTimer) clearTimeout(guessCloseTimer);
guessCloseTimer = setTimeout(() => {
guessVisible.value = false;
guessCloseTimer = null;
}, 200);
}
function selectDescriptionGuess(description) {
if (guessCloseTimer) clearTimeout(guessCloseTimer);
guessCloseTimer = null;
form.value.description = description;
guessVisible.value = false;
}
function nextStep() {
if (form.value.description.trim() === '') {
toast('请填写病情描述');
return;
}
if (!reachBottom.value) {
pageRef.value?.scrollToBottom();
reachBottom.value = true;
return
}
for (let item of histories.value) {
if (!item.options.includes(form.value[item.prop])) {
toast(`请选择${item.label}`);
return;
}
}
if (form.value.hasVisitedInLastSixMonths === 'N') {
confirmVisible.value = true;
return;
}
uni.navigateTo({ url: '/pages/consult/info' })
}
function onDiseaseSelected(disease) {
if (form.value.diseases.length < 5) {
form.value.diseases.push(disease);
}
}
function removeImage(index) {
form.value.images.splice(index, 1);
}
function uploadImage() {
uni.chooseImage({
count: 9 - form.value.images.length,
sizeType: ['compressed'],
success: async (res) => {
loading('上传中...');
const arr = await Promise.all(res.tempFilePaths.map(upload));
const urls = arr.filter(Boolean);
form.value.images = [...form.value.images, ...urls];
hideLoading();
toast(`成功上传${urls.length}张图片`);
},
});
}
function previewImage(index) {
uni.previewImage({
urls: form.value.images,
current: index
})
}
function upload(path) {
return new Promise((resolve) => {
uni.uploadFile({
url: uploadUrl, // 替换为你的上传接口地址
filePath: path,
name: 'file',
fileType: 'image',
success: (res) => {
try {
const url = JSON.parse(res.data).filePath;
resolve(url ? getFullPath(url) : '')
} catch (e) {
resolve()
}
},
fail: res => {
resolve()
}
})
})
}
function onReachBottom() {
reachBottom.value = true;
}
onLoad((options) => {
initOrder({ feeType: options.feeType, socialno: options.socialno });
uni.setNavigationBarTitle({
title: titleMap[options.feeType] || ''
})
uni.$on('on-disease-selected', onDiseaseSelected);
})
onUnload(() => {
uni.$off('on-disease-selected')
if (guessCloseTimer) clearTimeout(guessCloseTimer);
})
</script>
<style lang="scss" scoped>
.section-title {
font-weight: bold;
font-size: 32rpx;
&.is-required:before {
display: inline-block;
content: "*";
color: red;
margin-right: 10rpx;
}
}
.title-font {
font-size: 32rpx;
}
.section-sub-title {
font-size: 28rpx;
color: #555;
line-height: 42rpx;
}
.disease-tags {
display: flex;
flex-wrap: wrap;
margin-right: -20rpx;
}
.disease-tag {
padding: 10rpx 20rpx;
background-color: #f5ede0;
border-radius: 16rpx;
margin-right: 20rpx;
margin-top: 20rpx;
font-size: 28rpx;
color: #8b6f47;
border: 1px solid #d4c4a8;
@at-root &.add-tag {
border-color: #b8956a;
background-color: white;
color: #b8956a;
}
}
.disease-remove {
display: inline-block;
padding: 0 16rpx;
}
.image-uploader {
display: flex;
flex-wrap: wrap;
}
.item-guess {
font-size: 28rpx;
font-weight: bold;
}
.image-preview,
.upload-button {
position: relative;
width: 140rpx;
height: 140rpx;
margin: 10rpx 10rpx 0 0;
display: flex;
align-items: center;
justify-content: center;
}
.upload-button {
border: 1px solid #e5e5e5;
}
.close-icon {
position: absolute;
top: -20rpx;
right: -20rpx;
width: 40rpx;
height: 40rpx;
display: flex;
justify-content: flex-end;
}
.image {
width: 140rpx;
height: 140rpx;
}
.next-button {
background-color: $theme-brown-primary;
color: white;
position: fixed;
bottom: 20rpx;
/* width: 100%; */
left: 40rpx;
right: 40rpx;
}
.history-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
border-bottom: 1px solid #eee;
}
.history-item-none {
padding: 0;
}
.history-item:last-child {
border-bottom: none;
}
.history-label {
width: 280rpx;
font-size: 14px;
color: #555;
}
.radio-group {
display: flex;
align-items: center;
justify-content: space-between;
width: 320rpx;
}
.radio-group-auto {
width: auto;
}
.radio-label {
width: 50%;
display: flex;
align-items: center;
margin-left: 15px;
font-size: 28rpx;
white-space: nowrap;
}
.custom-radio {
transform: scale(0.8);
}
.description {
width: 100%;
min-height: 84rpx;
}
.description-section {
z-index: 10;
}
.guess-popup {
position: absolute;
left: 30rpx;
right: 30rpx;
top: 100%;
z-index: 20;
box-sizing: border-box;
background: #fff;
border: 1rpx solid #d9d9d9;
box-shadow: 6rpx 6rpx 12rpx rgba(0, 0, 0, 0.25);
}
.guess-title,
.guess-option {
box-sizing: border-box;
min-height: 64rpx;
padding: 16rpx 20rpx;
border-bottom: 1rpx solid #eee;
font-size: 26rpx;
line-height: 32rpx;
color: #333;
}
.guess-title {
font-weight: bold;
}
.guess-option:last-child {
border-bottom: none;
}
.guess-option:active {
background: #f5f5f5;
}
.placeholderClass {
font-size: 28rpx;
}
.user-header {
padding: 24rpx 30rpx;
background: white;
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.flex-row {
display: flex;
align-items: center;
}
/* 长辈模式特定样式 */
.elder-mode-active {
.user-header {
font-size: 42rpx !important;
padding: 40rpx 30rpx !important;
}
.section-title {
font-size: 42rpx !important;
margin-bottom: 30rpx;
}
.title-font {
font-size: 42rpx !important;
}
.section-sub-title {
font-size: 36rpx !important;
line-height: 1.6 !important;
}
.disease-tag {
font-size: 36rpx !important;
padding: 15rpx 25rpx !important;
margin-right: 25rpx !important;
margin-bottom: 25rpx !important;
}
.description {
font-size: 36rpx !important;
min-height: 200rpx !important;
padding: 20rpx !important;
line-height: 1.6 !important;
box-sizing: border-box !important;
}
.guess-title,
.guess-option {
min-height: 84rpx;
padding: 20rpx 24rpx;
font-size: 34rpx;
line-height: 44rpx;
}
.placeholderClass {
font-size: 36rpx !important;
line-height: 1.6 !important;
}
.history-label {
font-size: 36rpx !important;
width: 320rpx !important;
}
.radio-label {
font-size: 36rpx !important;
margin-left: 20rpx !important;
}
.image-preview,
.upload-button {
width: 200rpx !important;
height: 200rpx !important;
margin: 10rpx !important;
}
.image {
width: 200rpx !important;
height: 200rpx !important;
}
}
</style>