fix:问题修复

This commit is contained in:
huxuejian 2026-08-13 13:50:42 +08:00
parent 68443888bb
commit c7398599bf
4 changed files with 137 additions and 43 deletions

View File

@ -7,7 +7,8 @@
<view v-if="customScroll" class="page-scroll"> <view v-if="customScroll" class="page-scroll">
<slot></slot> <slot></slot>
</view> </view>
<scroll-view v-else :scroll-with-animation="animation" scroll-y="true" :scroll-top="scrollTop" class="page-scroll" <scroll-view v-else :scroll-with-animation="animation" scroll-y="true" :scroll-top="scrollTop"
:scroll-into-view="scrollIntoViewId" class="page-scroll"
@scrolltolower="scrolltolower" @scroll="onScroll"> @scrolltolower="scrolltolower" @scroll="onScroll">
<slot></slot> <slot></slot>
</scroll-view> </scroll-view>
@ -36,6 +37,7 @@ const hasHeader = computed(() => !!slots.header);
const hasFooter = computed(() => !!slots.footer); const hasFooter = computed(() => !!slots.footer);
const scrollTop = ref(0); const scrollTop = ref(0);
const scrollIntoViewId = ref('');
const disableScroll = ref(false); const disableScroll = ref(false);
const scrolltolower = useDebounce(() => { const scrolltolower = useDebounce(() => {
@ -55,8 +57,17 @@ function scrollToBottom() {
}, 500); }, 500);
} }
function scrollToView(id) {
if (!id) return;
scrollIntoViewId.value = '';
setTimeout(() => {
scrollIntoViewId.value = id;
}, 0);
}
defineExpose({ defineExpose({
scrollToBottom scrollToBottom,
scrollToView
}) })
</script> </script>

View File

@ -1,6 +1,6 @@
<template> <template>
<full-page mainStyle="background:#f0f0f0"> <full-page ref="fullPageRef" mainStyle="background:#f0f0f0">
<view class="container" :class="{ 'elder-mode-active': elderMode }"> <view class="container" :class="{ 'elder-mode-active': elderMode }" @click="handlePageClick">
<view class="user-header shadow-lg"> <view class="user-header shadow-lg">
就诊人{{ form.name }} {{ form.sex }} {{ form.age ? `${form.age}` : '' }} 就诊人{{ form.name }} {{ form.sex }} {{ form.age ? `${form.age}` : '' }}
</view> </view>
@ -16,18 +16,27 @@
</radio-group> </radio-group>
</view> </view>
</view> </view>
<view class="description-section relative mt-12 px-15 py-12 bg-white shadow-lg"> <view id="description-section" class="description-section relative mt-12 px-15 py-12 bg-white shadow-lg">
<view class="section-title is-required">请描述您的病情</view> <view class="section-title is-required">请描述您的病情</view>
<textarea v-model="form.description" :show-confirm-bar="false" auto-height="true" class="mt-10 description" <textarea v-model="form.description" :show-confirm-bar="false" auto-height="true" class="mt-10 description"
placeholder-class="placeholderClass" maxlength="300" placeholder="为了更好地获得医生帮助,请尽可能地详细描述病情" placeholder-class="placeholderClass" maxlength="300" placeholder="为了更好地获得医生帮助,请尽可能地详细描述病情"
@focus="showDescriptionGuess" @input="handleDescriptionInput" @blur="hideDescriptionGuess"></textarea> :adjust-position="false"
<view v-if="guessVisible" class="relative"> @click.stop
<view class="guess-popup"> @focus="showDescriptionGuess" @input="handleDescriptionInput" @blur="hideDescriptionGuess"
@keyboardheightchange="handleKeyboardHeightChange"></textarea>
<view v-if="guessVisible" id="description-guess-anchor" class="relative">
<scroll-view class="guess-popup" scroll-y :style="{ height: `${guessPopupHeight}px` }"
@click.stop
@touchstart="handleGuessInteractionStart" @touchend="handleGuessInteractionEnd"
@touchcancel="handleGuessInteractionEnd" @mousedown="handleGuessInteractionStart"
@mouseup="handleGuessInteractionEnd">
<view id="description-guess-content">
<view class="guess-title">猜你想输入</view> <view class="guess-title">猜你想输入</view>
<view v-for="item in guessList" :key="item" class="guess-option" @click="selectDescriptionGuess(item)"> <view v-for="item in guessList" :key="item" class="guess-option" @click="selectDescriptionGuess(item)">
{{ item }} {{ item }}
</view> </view>
</view> </view>
</scroll-view>
</view> </view>
</view> </view>
<view class="relative mt-12 px-15 py-12 bg-white shadow-lg"> <view class="relative mt-12 px-15 py-12 bg-white shadow-lg">
@ -68,7 +77,7 @@
</template> </template>
<script setup> <script setup>
import { ref } from "vue"; import { getCurrentInstance, nextTick, ref } from "vue";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import { onLoad, onUnload } from '@dcloudio/uni-app'; import { onLoad, onUnload } from '@dcloudio/uni-app';
import orderStore from '@/store/order'; import orderStore from '@/store/order';
@ -93,9 +102,16 @@ const guessList = [
const { order: form, histories, medTypeList } = storeToRefs(orderStore()); const { order: form, histories, medTypeList } = storeToRefs(orderStore());
const { init: initOrder, restoreForEdit } = orderStore(); const { init: initOrder, restoreForEdit } = orderStore();
const visible = ref(false); const visible = ref(false);
const fullPageRef = ref(null);
const guessVisible = ref(false); const guessVisible = ref(false);
const guessPopupHeight = ref(320);
const reachBottom = ref(false); const reachBottom = ref(false);
let guessCloseTimer = null; let guessCloseTimer = null;
let guessResizeTimer = null;
let guessInteractionTimer = null;
let keyboardHeight = 0;
let isGuessInteracting = false;
const instance = getCurrentInstance();
// //
const elderMode = ref(false); const elderMode = ref(false);
const titleMap = { const titleMap = {
@ -126,6 +142,36 @@ function showDescriptionGuess() {
if (guessCloseTimer) clearTimeout(guessCloseTimer); if (guessCloseTimer) clearTimeout(guessCloseTimer);
guessCloseTimer = null; guessCloseTimer = null;
guessVisible.value = !form.value.description.trim(); guessVisible.value = !form.value.description.trim();
if (fullPageRef.value) fullPageRef.value.scrollToView('description-section');
if (guessVisible.value) resizeGuessPopup();
}
function resizeGuessPopup(delay = 0) {
if (guessResizeTimer) clearTimeout(guessResizeTimer);
guessResizeTimer = setTimeout(async () => {
await nextTick();
const systemInfo = uni.getSystemInfoSync();
const defaultHeight = Math.round(systemInfo.windowWidth / 750 * 640);
const query = uni.createSelectorQuery();
if (instance && instance.proxy) query.in(instance.proxy);
query.select('#description-guess-anchor').boundingClientRect();
query.select('#description-guess-content').boundingClientRect();
query.exec((rects) => {
if (!guessVisible.value || !rects || !rects[0]) return;
const anchorRect = rects[0];
const contentRect = rects[1];
const keyboardTop = systemInfo.windowHeight - keyboardHeight;
const availableHeight = Math.max(96, keyboardTop - anchorRect.top - 12);
const contentHeight = contentRect && contentRect.height ? contentRect.height : defaultHeight;
guessPopupHeight.value = Math.ceil(Math.min(defaultHeight, contentHeight, availableHeight));
});
guessResizeTimer = null;
}, delay);
}
function handleKeyboardHeightChange(event) {
keyboardHeight = event && event.detail ? Number(event.detail.height) || 0 : 0;
if (guessVisible.value) resizeGuessPopup(50);
} }
function handleDescriptionInput(event) { function handleDescriptionInput(event) {
@ -140,16 +186,51 @@ function handleDescriptionInput(event) {
function hideDescriptionGuess() { function hideDescriptionGuess() {
if (guessCloseTimer) clearTimeout(guessCloseTimer); if (guessCloseTimer) clearTimeout(guessCloseTimer);
guessCloseTimer = setTimeout(() => { guessCloseTimer = setTimeout(() => {
if (isGuessInteracting) {
guessCloseTimer = null;
return;
}
guessVisible.value = false; guessVisible.value = false;
guessCloseTimer = null; guessCloseTimer = null;
}, 200); }, 200);
} }
function selectDescriptionGuess(description) { function closeDescriptionGuess() {
if (guessCloseTimer) clearTimeout(guessCloseTimer);
if (guessInteractionTimer) clearTimeout(guessInteractionTimer);
guessCloseTimer = null;
guessInteractionTimer = null;
isGuessInteracting = false;
guessVisible.value = false;
}
function handlePageClick() {
if (guessVisible.value) closeDescriptionGuess();
}
function handleGuessInteractionStart() {
isGuessInteracting = true;
if (guessInteractionTimer) clearTimeout(guessInteractionTimer);
if (guessCloseTimer) clearTimeout(guessCloseTimer); if (guessCloseTimer) clearTimeout(guessCloseTimer);
guessCloseTimer = null; guessCloseTimer = null;
// scroll-view touchend
guessInteractionTimer = setTimeout(() => {
isGuessInteracting = false;
guessInteractionTimer = null;
}, 500);
}
function handleGuessInteractionEnd() {
if (guessInteractionTimer) clearTimeout(guessInteractionTimer);
guessInteractionTimer = setTimeout(() => {
isGuessInteracting = false;
guessInteractionTimer = null;
}, 300);
}
function selectDescriptionGuess(description) {
form.value.description = description; form.value.description = description;
guessVisible.value = false; closeDescriptionGuess();
} }
function nextStep() { function nextStep() {
@ -248,6 +329,8 @@ onLoad((options) => {
onUnload(() => { onUnload(() => {
uni.$off('on-disease-selected') uni.$off('on-disease-selected')
if (guessCloseTimer) clearTimeout(guessCloseTimer); if (guessCloseTimer) clearTimeout(guessCloseTimer);
if (guessResizeTimer) clearTimeout(guessResizeTimer);
if (guessInteractionTimer) clearTimeout(guessInteractionTimer);
}) })
</script> </script>

View File

@ -2,17 +2,14 @@
<full-page :customScroll="true"> <full-page :customScroll="true">
<view class="qrcode-container"> <view class="qrcode-container">
<view class="qrcode-content"> <view class="qrcode-content">
<canvas <canvas id="auth-qrcode" canvas-id="auth-qrcode" class="qrcode-canvas"
id="auth-qrcode" :style="{ width: `${qrcodeSize}px`, height: `${qrcodeSize}px` }" />
canvas-id="auth-qrcode" <view class="tip">请使用就诊人本人的支付宝</view>
class="qrcode-canvas" <view class="tip">扫描上方二维码授权</view>
:style="{ width: `${qrcodeSize}px`, height: `${qrcodeSize}px` }"
/>
<view class="tip">请使用就诊人本人的支付宝扫描上方二维码授权</view>
</view> </view>
</view> </view>
<template #footer> <template #footer>
<footer-button :text="checking ? '查询中...' : '已授权'" @onClick="hasAuthed" /> <footer-button :text="checking ? '查询中...' : '已授权'" @onClick="hasAuthed" />
</template> </template>
</full-page> </full-page>
</template> </template>
@ -35,7 +32,7 @@ const id = ref("");
const patient = ref(null); const patient = ref(null);
const checking = ref(false); const checking = ref(false);
const qrcodeValue = computed(() => id.value && patient.value ? `${baseQrcode}${id.value}` : ""); const qrcodeValue = computed(() => id.value && patient.value ? `${baseQrcode}${id.value}` : "");
const qrcodeSize = Math.round(uni.upx2px(480)); const qrcodeSize = Math.round(uni.upx2px(640));
function drawQrcode() { function drawQrcode() {
const value = qrcodeValue.value; const value = qrcodeValue.value;
@ -146,6 +143,7 @@ onReady(() => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
transform: translateY(-60rpx);
} }
.qrcode-canvas { .qrcode-canvas {
@ -154,7 +152,11 @@ onReady(() => {
} }
.tip { .tip {
margin-top: 30rpx; font-size: 32rpx;
color: #666; line-height: 52rpx;
color: #333;
font-weight: bold;
} }
</style> </style>

View File

@ -3,13 +3,14 @@
<view v-if="data" class="relative prescription-container"> <view v-if="data" class="relative prescription-container">
<view class="header"> <view class="header">
<view class="row"> <view class="row">
<view class="company">海宁康华医院互联网医院</view> <view class="company"></view>
<view class="prescription-type"> <view class="prescription-type">
<view>普通</view> <view>普通</view>
<view>处方</view> <view>处方</view>
</view> </view>
</view> </view>
<view class="hospital">海宁康华医院互联网医院处方笺</view> <view class="hospital">海宁康华医院互联网医院</view>
<view class="hospital">处方笺</view>
<view class="sub-header"> <view class="sub-header">
<span class="no">NO:{{ data.medOrgOrderNo }}</span> <span class="no">NO:{{ data.medOrgOrderNo }}</span>
</view> </view>
@ -58,7 +59,7 @@
<view class="footer"> <view class="footer">
<view class="stamp-area"> <view class="stamp-area">
<view class="signatures"> <view class="signatures">
<view class="signature-item" style="width: 33%"> <view class="signature-item" style="min-width: 33%">
<view>医生 <view>医生
<image v-if="data.doctorSignImg" class="signImage" :src="data.doctorSignImg"></image> <image v-if="data.doctorSignImg" class="signImage" :src="data.doctorSignImg"></image>
<text v-else>{{ data.doctorName }}</text> <text v-else>{{ data.doctorName }}</text>
@ -67,19 +68,16 @@
<!-- <image class="stamp-img" src="/static/stamp.png"></image> --> <!-- <image class="stamp-img" src="/static/stamp.png"></image> -->
</view> </view>
</view> </view>
<view class="signature-item" style="width: 33%"> <view class="signature-item" style="min-width: 33%">
<view>审方<image v-if="data.pharmacistSignImg" class="signImage" :src="data.pharmacistSignImg"></image> <view>审方药师<image v-if="data.pharmacistSignImg" class="signImage" :src="data.pharmacistSignImg"></image>
<text v-else>{{ data.pharmacist }}</text> <text v-else>{{ data.pharmacist }}</text>
</view> </view>
<view>发药</view>
</view> </view>
<view class="signature-item" style="width: 34%">
<view class="stamp">收费盖章
<!-- <image class="stamp-img" src="/static/stamp.png"></image> -->
</view>
<view>配方</view>
<view>复核</view>
</view> </view>
<view class="signatures">
<view class="signature-item" style="width: 33%">调配</view>
<view class="signature-item" style="width: 33%">复核</view>
<view class="signature-item" style="width: 33%">发药</view>
</view> </view>
</view> </view>
<view class="notice">注意请勿丢失处方当日有效因特殊情况该处方有效为天签名</view> <view class="notice">注意请勿丢失处方当日有效因特殊情况该处方有效为天签名</view>
@ -239,6 +237,10 @@ function viewOrder() {
margin: 16rpx 0; margin: 16rpx 0;
} }
.hospital+.hospital {
margin: 0;
}
.sub-header { .sub-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -358,10 +360,6 @@ function viewOrder() {
margin-top: 30rpx; margin-top: 30rpx;
} }
.no {
margin-top: 10rpx;
}
.expired-icon { .expired-icon {
position: absolute; position: absolute;
right: 80rpx; right: 80rpx;