2025-09-08 17:44:31 +08:00

366 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="content">
<!-- 顶部导航栏 -->
<uni-nav-bar
left-icon="left"
title="添加随访计划"
@clickLeft="goBack"
fixed
color="#8B2316"
height="140rpx"
:border="false"
backgroundColor="#eee"
>
<template #right>
<view class="nav-right" @click="submitPlan">
<text class="submit-text">提交</text>
</view>
</template>
</uni-nav-bar>
<!-- 患者选择 -->
<view class="form-section" @click="selectPatient">
<view class="section-label"><text class="label-text">患者</text></view>
<view class="section-content">
<text class="content-text">{{patientName}}</text>
<uni-icons type="right" size="20" color="#999" v-if="from"></uni-icons>
</view>
</view>
<!-- 随访内容列表 -->
<view class="title-bar">随访内容</view>
<view class="visitbox">
<view class="divider"></view>
<scroll-view class="visit-list" scroll-y scroll-with-animation :scroll-into-view="scrollIntoViewId">
<view class="visit-item" v-for="(item, idx) in visits" :key="item.id" :id="`visit-${item.id}`">
<view class="left">
<uni-icons type="close" size="20" :color="idx===0 ? '#cfcfcf' : '#c0392b'" @click="removeVisit(idx)"></uni-icons>
</view>
<view class="mid" @click="goVisitNote(idx,item.note)">
<text class="visit-text">{{ idx+1 }}.{{ item.note}}</text>
</view>
<view class="right" @click="pickDate(idx)">
<text class="date-text">{{ item.date }}</text>
<uni-icons type="right" size="20" color="#999"></uni-icons>
</view>
</view>
</scroll-view>
</view>
<!-- 添加随访日程按钮 -->
<view class="add-row" @click="addVisit">
<text class="plus"></text>
<text class="add-text">添加随访日程</text>
</view>
<!-- 提醒开关 -->
<view class="reminder-section">
<view class="reminder-item" @click="toggleRemindMe">
<text class="reminder-text">提醒我</text>
<view class="checkbox" :class="{ active: remindMe }">
<uni-icons v-if="remindMe" type="checkmarkempty" size="16" color="#ffffff"></uni-icons>
</view>
</view>
<view class="reminder-item" @click="toggleRemindPatient">
<text class="reminder-text">提醒患者</text>
<view class="checkbox" :class="{ active: remindPatient }">
<uni-icons v-if="remindPatient" type="checkmarkempty" size="16" color="#ffffff"></uni-icons>
</view>
</view>
</view>
</view>
<up-overlay :show="show">
<view class="warp">
<view class="calendarbox">
<view class="calendartop">
<!-- <view class="title">时间日期</view> -->
<view class="datebox">
<view class="year">{{ headerYear }}</view>
<view class="day">{{ headerDay }}</view>
</view>
</view>
<uni-calendar class="uni-calendar--hook" :date="calendarDate" @change="change" @monthSwitch="monthSwitch" />
<view class="calendarbottom">
<view class="cancel" @click="show=false">取消</view>
<view class="ok" @click="confirmDate">确定</view>
</view>
</view>
</view>
</up-overlay>
</template>
<script setup>
import { ref,nextTick } from 'vue';
import { onShow,onLoad } from "@dcloudio/uni-app";
import navTo from '@/utils/navTo.js';
const patientUuid = ref('');
const patientName = ref('');
const show = ref(false);
const dealIndex=ref(0);
import api from '@/api/api.js'
const from = ref('');
onLoad((options) => {
patientUuid.value = options.uuid;
patientName.value = options.patient_name;
from.value = options.from;
});
const selectedPatient = ref('');
const defaultContent = '请近日来医院复诊、复查';
const visits = ref([
{ id: 1, date: formatDate(addDays(new Date(), 1)),note:defaultContent},
{ id: 2, date: formatDate(addMonths(new Date(), 6)),note:defaultContent },
{ id: 3, date: formatDate(addMonths(new Date(), 9)),note:defaultContent },
{ id: 4, date: formatDate(addMonths(new Date(), 12)),note:defaultContent }
]);
const remindMe = ref(false);
const remindPatient = ref(true);
const scrollIntoViewId = ref('');
const tempDate=ref('');
const headerYear=ref('');
const headerDay=ref('');
const calendarDate=ref('');
const setHeaderByDate=(d)=>{
const y=d.getFullYear();
const m=d.getMonth()+1;
const dd=d.getDate();
const w=['日','一','二','三','四','五','六'][d.getDay()];
headerYear.value=`${y}`;
headerDay.value=`${m}${dd}日周${w}`;
}
const change=(e)=>{
tempDate.value = formatDate(new Date(e.fulldate));
setHeaderByDate(new Date(e.fulldate));
calendarDate.value = e.fulldate;
}
const confirmDate=()=>{
visits.value[dealIndex.value].date = tempDate.value;
show.value=false;
}
const goVisitNote=(idx,note)=>{
navTo({
url: '/pages_app/visitNote/visitNote?idx='+idx+'&note='+encodeURIComponent(note)+'&patient_name='+encodeURIComponent(patientName.value),
events: {
onVisitNoteSubmit: ({ note, idx }) => {
console.log('onVisitNoteSubmit', note, idx)
visits.value[Number(idx)].note = note
}
}
})
}
function formatDate(d){
const y=d.getFullYear();
const m=`${d.getMonth()+1}`.padStart(2,'0');
const day=`${d.getDate()}`.padStart(2,'0');
const w=['日','一','二','三','四','五','六'][d.getDay()];
return `${y}.${m}.${day}(星期${w})`;
}
function addMonths(d, m){
const nd=new Date(d);
nd.setMonth(nd.getMonth()+m);
return nd;
}
function addDays(d, days){
const nd = new Date(d);
nd.setDate(nd.getDate() + days);
return nd;
}
const addFollowUps=()=>{
api.addFollowUps({
patient_uuid: patientUuid.value,
note: visits.value.map(item=>item.note).join('☆'),
datetime: visits.value.map(item=>String(item.date).split('(')[0]).join('☆').replace(/\./g,'-'),
isremindpatient: remindPatient.value?1:0,
isremindme:remindMe.value?1:0,
type:2
}).then(res=>{
console.log(res)
if(res.code==200){
uni.showToast({ title: '已提交', icon: 'success' });
setTimeout(()=>uni.navigateBack(),700);
}
})
}
const goBack=()=>uni.navigateBack();
const submitPlan=()=>{
addFollowUps();
uni.showToast({ title: '已提交', icon: 'success' });
setTimeout(()=>uni.navigateBack(),1000);
};
const selectPatient=()=>{
if(from.value=='patientMsg'){
navTo({
url:'/pages_app/selectPatient/selectPatient',
events: {
onPatientsSelected: ({ ids, list }) => {
//console.log(ids, list)
patientUuid.value = list.map(item=>item.uuid).join(',');
patientName.value = list.map(item=>item.realName).join(',');
}
}
})
}
};
const addVisit=()=>{
const id= Date.now();
// 以最后一条的日期为基准加3个月
let baseDate = new Date();
const last = visits.value[visits.value.length - 1];
if (last && last.date) {
// last.date 形如 2025.09.02(星期二),取括号前并替换为日期
const pure = String(last.date).split('(')[0].replace(/\./g, '-');
const parsed = new Date(pure);
if (!isNaN(parsed.getTime())) baseDate = parsed;
}
const nextDate = addMonths(baseDate, 3);
visits.value.push({ id, date: formatDate(nextDate) });
// 下一帧滚动到新项
nextTick(()=>{ scrollIntoViewId.value = `visit-${id}`; });
};
const removeVisit=(idx)=>{
if(idx===0) return; // 第一条不可删
visits.value.splice(idx,1);
};
const pickDate=(idx)=>{
show.value=true;
dealIndex.value=idx;
// 打开时始终显示今天
const base=new Date();
tempDate.value=formatDate(base);
setHeaderByDate(base);
const y=base.getFullYear();
const m=`${base.getMonth()+1}`.padStart(2,'0');
const d=`${base.getDate()}`.padStart(2,'0');
calendarDate.value=`${y}-${m}-${d}`;
};
const toggleRemindMe=()=>{ remindMe.value=!remindMe.value; };
const toggleRemindPatient=()=>{ remindPatient.value=!remindPatient.value; };
onShow(()=>{});
</script>
<style lang="scss" scoped>
.warp {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
.calendarbox{
margin-top: 140rpx;
display: flex;
background-color: #ffffff;
flex-direction: column;
align-items: center;
justify-content: center;
:deep(.uni-calendar-item--checked){
background:#ff3346!important;
border-radius: 50%;
color:#fff;
}
:deep(.uni-calendar-item--isDay){
border-radius: 50%;
background:#ff3346!important;
}
.calendartop {
width:100%;
.title{
font-size:34rpx;
padding:20rpx 30rpx 8rpx;
}
.datebox{
background:#ff3346;
display: flex;
width:100%;
color:#fff;
font-size: 46rpx;
padding:20rpx 30rpx;
box-sizing:border-box;
align-items: center;
justify-content: center;
}
}
.calendarbottom{
color:#ff3346;
display: flex;
box-sizing:border-box;
padding:30rpx 40rpx 40rpx;
width:100%;
justify-content: flex-end;
.ok{
font-size: 28rpx;
margin-left: 40rpx;
}
.cancel{
font-size: 28rpx;
}
}
}
}
.content {
background-color: #f5f5f5;
min-height: 100vh;
}
.content {
background-color: #f5f5f5;
min-height: 100vh;
}
.nav-right { display: flex; align-items: center; }
.submit-text { font-size: 32rpx; color: #8B2316; font-weight: 500; }
.form-section {
margin-top: 20rpx;
display: flex; align-items: center; justify-content: space-between;
padding: 30rpx; background: #ffffff; border-bottom: 1rpx solid #f0f0f0;
.section-label { width: 160rpx; flex-shrink: 0; }
.label-text { font-size: 32rpx; color: #8B2316; font-weight: 500; }
.section-content { display: flex; align-items: center; }
.content-text { font-size: 32rpx; color:#333; }
}
.title-bar { padding: 20rpx 30rpx; color:#8B2316; font-size: 32rpx; background:#ffffff; margin-top: 20rpx; border-top: 1rpx solid #f0f0f0; border-bottom: 1rpx solid #f0f0f0; }
.visitbox{
position: relative;
.divider{
position: absolute;
left: 50%;
transform: translateX(-50%);
height: 100%;
width: 2rpx;
background: #f0f0f0;
z-index:2;
}
}
.visit-list {
position: relative;
/* 让列表在可视区域内滚动 */
height: 400rpx;
background-color: #ffffff;
}
.visit-item { box-sizing:border-box;display:flex; align-items:center; padding: 26rpx 30rpx; border-bottom:1rpx solid #f0f0f0; }
.visit-item .left { width: 60rpx; display:flex; justify-content:center; }
.visit-item .mid { flex:1;width:354rpx; }
.visit-text { font-size: 30rpx; color:#333; display: inline-block;white-space: nowrap;width:80%;overflow: hidden;}
.visit-item .right { flex:1;display:flex; align-items:center; }
.date-text { display: inline-block;white-space: nowrap; font-size: 30rpx; color:#333; margin-right: 10rpx; }
.add-row { display:flex; align-items:center; padding: 26rpx 30rpx; background:#ffffff; margin-top: 20rpx; }
.plus { color:#8B2316; font-size: 36rpx; margin-right: 14rpx; }
.add-text { color:#8B2316; font-size: 32rpx; }
.reminder-section { background:#ffffff; margin-top: 20rpx; }
.reminder-item { display:flex; align-items:center; justify-content:space-between; padding: 30rpx; border-bottom:1rpx solid #f0f0f0; }
.reminder-item:last-child { border-bottom:none; }
.reminder-text { font-size: 32rpx; color:#8B2316; font-weight: 500; }
.checkbox { width: 40rpx; height: 40rpx; border-radius: 50%; border: 2rpx solid #cccccc; display:flex; align-items:center; justify-content:center; background:#ffffff; }
.checkbox.active { background:#8B2316; border-color:#8B2316; }
</style>