Merge branch 'master' of https://gitea.igandanyiyuan.com/gdxz/uniapp-app
# Conflicts: # pages/my/my.vue
This commit is contained in:
commit
71136a03a6
15
api/api.js
15
api/api.js
@ -556,6 +556,21 @@ const api = {
|
||||
toAddNickname(data){
|
||||
return request('/expertAPI/toAddNickname', data, 'post', false);
|
||||
},
|
||||
caseDetail(data){
|
||||
return request('/expertAPI/caseDetail', data, 'post', false);
|
||||
},
|
||||
conditionRecordList(data){
|
||||
return request('/expertAPI/conditionRecordList', data, 'post', false);
|
||||
},
|
||||
addConditionRecord(data){
|
||||
return request('/expertAPI/addConditionRecord', data, 'post', false);
|
||||
},
|
||||
updateConditionRecord(data){
|
||||
return request('/expertAPI/upConditionRecord', data, 'post', false);
|
||||
},
|
||||
deleteConditionRecord(data){
|
||||
return request('/expertAPI/delConditionRecord', data, 'post', false);
|
||||
},
|
||||
}
|
||||
|
||||
export default api
|
||||
@ -8,14 +8,15 @@
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"@xkit-yx/im-store-v2": "^0.8.3",
|
||||
"@xkit-yx/utils": "^0.7.2",
|
||||
"crypto-js": "^4.2.0",
|
||||
"@xkit-yx/im-store-v2": "^0.8.3",
|
||||
"@xkit-yx/utils": "^0.7.2",
|
||||
"mobx": "^6.6.1",
|
||||
"nim-web-sdk-ng": "^10.9.30",
|
||||
"dayjs": "^1.11.18",
|
||||
"image-tools": "^1.4.0",
|
||||
"js-base64": "^3.7.8",
|
||||
"js-md5": "^0.8.3",
|
||||
"mobx": "^6.6.1",
|
||||
"nim-web-sdk-ng": "^10.9.30",
|
||||
"pinyin": "^4.0.0",
|
||||
"uview-plus": "^3.4.73"
|
||||
}
|
||||
|
||||
53
pages.json
53
pages.json
@ -606,6 +606,58 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "caseRecord/caseRecord",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarTitleText": "uni-app分页",
|
||||
"app": {
|
||||
"bounce": "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "searchPatient/searchPatient",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarTitleText": "uni-app分页",
|
||||
"app": {
|
||||
"bounce": "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "visitPlan/visitPlan",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarTitleText": "uni-app分页",
|
||||
"app": {
|
||||
"bounce": "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "caseList/caseList",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarTitleText": "uni-app分页",
|
||||
"app": {
|
||||
"bounce": "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "checkRecord/checkRecord",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarTitleText": "uni-app分页",
|
||||
"app": {
|
||||
"bounce": "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "qikan/qikan",
|
||||
"style": {
|
||||
@ -1011,6 +1063,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "productDetail/productDetail",
|
||||
"style": {
|
||||
|
||||
@ -472,6 +472,11 @@
|
||||
url='/pages_course/course/course'
|
||||
}else if(name=='积分商城'){
|
||||
url='/pages_goods/pointMall/pointMall'
|
||||
}else if(name=='我的福利'){
|
||||
url='/pages_app/myWelfare/myWelfare'
|
||||
}else if(name=='专题e站'){
|
||||
const encoded = encodeURIComponent('https://wx.igandan.com/Esite/index.htm#/home?fromtype=doctor')
|
||||
url=`/pages_app/webview/webview?url=${encoded}`
|
||||
}else{
|
||||
url='/pages_app/myApplication/myApplication'
|
||||
}
|
||||
|
||||
119
pages/my/my.vue
119
pages/my/my.vue
@ -215,12 +215,35 @@
|
||||
<!-- 底部导航栏 -->
|
||||
<CustomTabbar></CustomTabbar>
|
||||
</view>
|
||||
<unidialog :visible="hasSign" content="今日已签到,每天只能签到一次。<br>请明日继续哦~" @close="hasSign=false" :showCancel="true" cancelText="关闭"></unidialog>
|
||||
<up-overlay :show="showSign" >
|
||||
<view class="signwrap">
|
||||
<view class="signbox">
|
||||
<view class="close" @click="showSign=false"></view>
|
||||
<view class="signbg">
|
||||
<up-image :src="signImg" width="604rpx" height="964rpx" ></up-image>
|
||||
</view>
|
||||
<view class="signcontent">
|
||||
<view class="day">今天是我们相识的第{{signInfo.gdxzday}}天</view>
|
||||
<view class="signtotal">本周共签到{{signInfo.totalDay}}次</view>
|
||||
<view class="signcontinue">已经连续签到{{signInfo.continuous_day}}天</view>
|
||||
<view class="tip">连续签到获取更多积分</view>
|
||||
<view class="news" @click.stop="goNews">
|
||||
{{signInfo.news.summary}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</up-overlay>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import unidialog from '@/components/dialog/dialog.vue'
|
||||
import signImg from "@/static/sign_in_bng_big.png"
|
||||
import CustomTabbar from '@/components/tabBar/tabBar.vue';
|
||||
import {
|
||||
ref
|
||||
ref,reactive
|
||||
} from 'vue';
|
||||
import {
|
||||
onShow
|
||||
@ -246,7 +269,7 @@
|
||||
import ghsjhImg from "@/static/ghsjh.png"
|
||||
import tzykImg from "@/static/xxtx.png"
|
||||
import versionImg from "@/static/fxxbb.png"
|
||||
|
||||
import jifenImg from "@/static/point_buy.png"
|
||||
|
||||
import fulicard from "@/static/fulicard.png"
|
||||
import fpgl from "@/static/fpgl.png"
|
||||
@ -258,7 +281,13 @@
|
||||
import linkUrl from "@/utils/docUrl"
|
||||
// 响应式数据
|
||||
const isLargeFont = ref(false);
|
||||
|
||||
const hasSign = ref(false)
|
||||
const showSign = ref(false)
|
||||
const signInfo=reactive({
|
||||
news:{
|
||||
summary:''
|
||||
}
|
||||
})
|
||||
// 新增:我的信息数据
|
||||
const avatar = ref('')
|
||||
const username = ref('')
|
||||
@ -269,7 +298,26 @@
|
||||
const totalPoints = ref(0)
|
||||
const sign_in = ref(0)
|
||||
const honor_list = ref([])
|
||||
|
||||
const notice_on = ref(false)
|
||||
const goNews=()=>{
|
||||
let url=docUrl+signInfo.news.path;
|
||||
// #ifdef H5
|
||||
window.open(url, '_blank');
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
plus.runtime.openURL(url);
|
||||
// #endif
|
||||
|
||||
// #ifdef MP
|
||||
const encoded = encodeURIComponent(url);
|
||||
navTo({
|
||||
url: `/pages_app/webview/webview?url=${encoded}`
|
||||
});
|
||||
// #endif
|
||||
}
|
||||
|
||||
// 从storage获取用户信息
|
||||
const getUserInfoFromStorage = () => {
|
||||
try {
|
||||
@ -300,6 +348,7 @@
|
||||
title: '签到成功,获得'+res.bonuspoints+'积分',
|
||||
icon: 'none'
|
||||
});
|
||||
Object.assign(signInfo,res);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res?.msg || '签到失败',
|
||||
@ -647,7 +696,66 @@ const switchPushPermissions = () => {
|
||||
padding-bottom: 100rpx;
|
||||
}
|
||||
|
||||
.signwrap{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height:100%;
|
||||
.signbox{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
z-index:0;
|
||||
.close{
|
||||
position:absolute;
|
||||
right:0;
|
||||
height:60rpx;
|
||||
width:60rpx;
|
||||
opacity: 0;
|
||||
background:#fff;
|
||||
z-index:2;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.signwrap .signcontent{
|
||||
width:100%;
|
||||
top:0;
|
||||
position: absolute;
|
||||
z-index:1;
|
||||
}
|
||||
.signwrap .signcontent .day{
|
||||
margin-top: 384rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.signwrap .signtotal{
|
||||
margin-top: 30rpx;
|
||||
text-align: center;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.signwrap .signcontinue{
|
||||
font-size: 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.signwrap .signcontent .tip{
|
||||
margin-top: 40rpx;
|
||||
color:red;
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.signwrap .signcontent .news{
|
||||
margin: 196rpx 60rpx 0;
|
||||
height: 116rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.signwrap .signbg{
|
||||
width:604rpx;
|
||||
height:964rpx;
|
||||
}
|
||||
// 用户信息卡片
|
||||
.user-card {
|
||||
|
||||
@ -747,7 +855,7 @@ const switchPushPermissions = () => {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 54rpx;
|
||||
width: 160rpx;
|
||||
width: 150rpx;
|
||||
height: 56rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -769,10 +877,11 @@ const switchPushPermissions = () => {
|
||||
right: 0;
|
||||
top: 54rpx;
|
||||
width: 160rpx;
|
||||
height: 56rpx;
|
||||
height: 54rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1rpx solid #fc564a;
|
||||
border-right: none;
|
||||
border-radius: 30rpx 0 0 30rpx;
|
||||
background: #fff url("@/static/qd_bg.9.png")no-repeat 0 0;
|
||||
background-size: 57rpx 56rpx;
|
||||
|
||||
450
pages_app/caseList/caseList.vue
Normal file
450
pages_app/caseList/caseList.vue
Normal file
@ -0,0 +1,450 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 头部导航 -->
|
||||
<uni-nav-bar
|
||||
left-icon="left"
|
||||
title="病情记录"
|
||||
@clickLeft="goBack"
|
||||
fixed
|
||||
color="#8B2316"
|
||||
height="140rpx"
|
||||
:border="false"
|
||||
backgroundColor="#eee"
|
||||
>
|
||||
<template #right>
|
||||
<view class="nav-right">
|
||||
<uni-icons type="plus" size="24" color="#8B2316" @click="goAddRecord" style="margin-left: 30rpx;"></uni-icons>
|
||||
</view>
|
||||
</template>
|
||||
</uni-nav-bar>
|
||||
|
||||
|
||||
<!-- 主要内容区域 -->
|
||||
<scroll-view
|
||||
class="main-content"
|
||||
scroll-y
|
||||
refresher-enabled
|
||||
:refresher-triggered="refreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
@scrolltolower="onLoadMore"
|
||||
:lower-threshold="100"
|
||||
>
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-state" v-if="recordList.length === 0 && !loading">
|
||||
<text class="empty-text">暂无病情记录</text>
|
||||
<button class="add-first-btn" @click="addRecord">添加第一条记录</button>
|
||||
</view>
|
||||
|
||||
<!-- 时间线容器 -->
|
||||
<view class="timeline-container" v-else>
|
||||
<!-- 时间线 -->
|
||||
<view class="timeline-line"></view>
|
||||
|
||||
<!-- 记录条目 -->
|
||||
<view
|
||||
class="record-item"
|
||||
v-for="(record, index) in recordList"
|
||||
:key="record.uuid"
|
||||
@click="goToDetail(record)"
|
||||
>
|
||||
<!-- 时间线节点 -->
|
||||
<view class="timeline-node">
|
||||
<view class="node-circle"></view>
|
||||
</view>
|
||||
|
||||
<!-- 记录内容 -->
|
||||
<view class="record-content">
|
||||
<!-- 日期气泡 -->
|
||||
<view class="date-bubble">
|
||||
<text class="date-text">{{ record.create_date }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 记录描述 -->
|
||||
<view class="record-description" v-if="record.des">
|
||||
<text class="description-text">{{ record.des }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 记录图片 -->
|
||||
<view class="record-images" v-if="record.photo && record.photo.length > 0">
|
||||
<view class="image-grid">
|
||||
<view
|
||||
class="image-item"
|
||||
v-for="(imagePath, imgIndex) in record.photo"
|
||||
:key="imgIndex"
|
||||
@click.stop="previewImages(record.photo, imgIndex)"
|
||||
>
|
||||
<image
|
||||
:src="docUrl + imagePath"
|
||||
class="content-image"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多状态 -->
|
||||
<view class="load-more" v-if="recordList.length > 0">
|
||||
<view class="loading-text" v-if="loadingMore">
|
||||
<uni-load-more status="loading" content-text="{ contentText: { contentdown: '上拉显示更多', contentrefresh: '正在加载...', contentnomore: '没有更多数据了' } }"></uni-load-more>
|
||||
</view>
|
||||
<!-- <view class="no-more-text" v-else-if="currentPage >= totalPage">
|
||||
<text>没有更多数据了</text>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// Vue3 Composition API
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import { onShow, onLoad } from '@dcloudio/uni-app'
|
||||
import navBar from '@/components/navBar/navBar.vue'
|
||||
import api from '@/api/api.js'
|
||||
import docUrl from '@/utils/docUrl.js'
|
||||
|
||||
const patientUuid = ref('')
|
||||
const getRecordList = (isRefresh = false) => {
|
||||
let usrInfo = uni.getStorageSync('userInfo')
|
||||
|
||||
// 如果是刷新,重置页码
|
||||
if (isRefresh) {
|
||||
currentPage.value = 1
|
||||
}
|
||||
|
||||
// 设置加载状态
|
||||
if (isRefresh) {
|
||||
refreshing.value = true
|
||||
} else if (currentPage.value === 1) {
|
||||
loading.value = true
|
||||
} else {
|
||||
loadingMore.value = true
|
||||
}
|
||||
|
||||
api.conditionRecordList({
|
||||
patient_uuid: patientUuid.value,
|
||||
expert_uuid: usrInfo.uuid,
|
||||
page: currentPage.value
|
||||
}).then(res => {
|
||||
console.log(res)
|
||||
if(res.code == 200){
|
||||
const newList = res.data.list || []
|
||||
|
||||
if (isRefresh || currentPage.value === 1) {
|
||||
// 刷新或首次加载,替换数据
|
||||
recordList.value = newList
|
||||
} else {
|
||||
// 加载更多,追加数据
|
||||
recordList.value = [...recordList.value, ...newList]
|
||||
}
|
||||
|
||||
totalPage.value = res.data.totalPage || 1
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error('获取病情记录失败:', err)
|
||||
uni.showToast({
|
||||
title: '获取数据失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}).finally(() => {
|
||||
// 重置加载状态
|
||||
loading.value = false
|
||||
refreshing.value = false
|
||||
loadingMore.value = false
|
||||
})
|
||||
}
|
||||
const goToDetail = (record) => {
|
||||
uni.setStorageSync('caseRecord', record)
|
||||
uni.navigateTo({
|
||||
url: '/pages_app/caseRecord/caseRecord?uuid=' + record.uuid + '&patientUuid=' + patientUuid.value
|
||||
})
|
||||
}
|
||||
const goAddRecord = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages_app/caseRecord/caseRecord?patientUuid=' + patientUuid.value
|
||||
})
|
||||
}
|
||||
onLoad((options) => {
|
||||
patientUuid.value = options.uuid
|
||||
})
|
||||
onShow(() => {
|
||||
getRecordList()
|
||||
})
|
||||
|
||||
// 响应式数据
|
||||
const recordList = ref([])
|
||||
const totalPage = ref(1)
|
||||
const currentPage = ref(1)
|
||||
const loading = ref(false)
|
||||
const refreshing = ref(false)
|
||||
const loadingMore = ref(false)
|
||||
|
||||
// 方法
|
||||
const goBack = () => {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
fail() {
|
||||
uni.redirectTo({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const addRecord = () => {
|
||||
// 跳转到添加记录页面
|
||||
uni.navigateTo({
|
||||
url: '/pages_app/addRecord/addRecord?patientUuid=' + patientUuid.value
|
||||
})
|
||||
}
|
||||
|
||||
const managePatients = () => {
|
||||
// 管理患者功能
|
||||
addRecord()
|
||||
}
|
||||
|
||||
const previewImages = (imageList, currentIndex) => {
|
||||
const urls = imageList.map(img => docUrl + img)
|
||||
uni.previewImage({
|
||||
current: currentIndex,
|
||||
urls: urls
|
||||
})
|
||||
}
|
||||
|
||||
// 下拉刷新
|
||||
const onRefresh = () => {
|
||||
console.log('下拉刷新')
|
||||
getRecordList(true)
|
||||
}
|
||||
|
||||
// 上拉加载更多
|
||||
const onLoadMore = () => {
|
||||
console.log('上拉加载更多')
|
||||
|
||||
// 如果正在加载或没有更多数据,则不执行
|
||||
if (loadingMore.value || loading.value || refreshing.value) {
|
||||
return
|
||||
}
|
||||
|
||||
// 如果已经是最后一页,不执行
|
||||
if (currentPage.value >= totalPage.value) {
|
||||
return
|
||||
}
|
||||
|
||||
// 页码加1
|
||||
currentPage.value++
|
||||
|
||||
// 加载更多数据
|
||||
getRecordList(false)
|
||||
}
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
console.log('病情记录页面已加载')
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
background-color: #ffffff;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 头部导航样式 */
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 30rpx;
|
||||
background-color: #ffffff;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #8B2316;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 36rpx;
|
||||
color: #8B2316;
|
||||
font-weight: bold;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.add-icon {
|
||||
font-size: 40rpx;
|
||||
color: #8B2316;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 主要内容区域 */
|
||||
.main-content {
|
||||
height: calc(100vh - 140rpx);
|
||||
padding: 40rpx 30rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.timeline-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.timeline-line {
|
||||
position: absolute;
|
||||
left: 30rpx;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 4rpx;
|
||||
background-color: #8B2316;
|
||||
}
|
||||
|
||||
.record-item {
|
||||
position: relative;
|
||||
margin-bottom: 60rpx;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.timeline-node {
|
||||
position: relative;
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.node-circle {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background-color: #8B2316;
|
||||
border-radius: 50%;
|
||||
border: 4rpx solid #ffffff;
|
||||
box-shadow: 0 0 0 2rpx #8B2316;
|
||||
}
|
||||
|
||||
.record-content {
|
||||
flex: 1;
|
||||
margin-left: 30rpx;
|
||||
}
|
||||
|
||||
.date-bubble {
|
||||
background-color: #ffffff;
|
||||
border: 2rpx solid #8B2316;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.date-text {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.record-description {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.description-text {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.record-images {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.image-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 15rpx;
|
||||
}
|
||||
|
||||
.image-item {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.content-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* 空状态样式 */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 40rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 32rpx;
|
||||
color: #999999;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.add-first-btn {
|
||||
background-color: #8B2316;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 25rpx;
|
||||
padding: 20rpx 40rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
/* 加载更多样式 */
|
||||
.load-more {
|
||||
padding: 40rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.no-more-text {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 750rpx) {
|
||||
.content-image {
|
||||
width: 100%;
|
||||
max-width: 400rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
460
pages_app/caseRecord/caseRecord.vue
Normal file
460
pages_app/caseRecord/caseRecord.vue
Normal file
@ -0,0 +1,460 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 头部导航 -->
|
||||
<uni-nav-bar
|
||||
left-icon="left"
|
||||
title="病情记录"
|
||||
@clickLeft="goBack"
|
||||
fixed
|
||||
color="#8B2316"
|
||||
height="140rpx"
|
||||
:border="false"
|
||||
backgroundColor="#eee"
|
||||
>
|
||||
<template #right>
|
||||
<view class="nav-right">
|
||||
<text class="modify-btn" @click="saveRecord" v-if="recordUuid"
|
||||
>修改</text
|
||||
>
|
||||
<text class="save-btn" @click="saveRecord" v-else>保存</text>
|
||||
</view>
|
||||
</template>
|
||||
</uni-nav-bar>
|
||||
|
||||
<!-- 主要内容区域 -->
|
||||
<view class="main-content">
|
||||
<!-- 日期选择区域 -->
|
||||
<view class="form-item row">
|
||||
<view class="form-label">日期</view>
|
||||
<view class="form-value" @click="openDateTime">
|
||||
<text class="date-text">{{ dateTime }}</text>
|
||||
<uni-icons type="right" size="16" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">描述</view>
|
||||
<view class="form-value">
|
||||
<textarea
|
||||
class="description-input"
|
||||
v-model="des"
|
||||
placeholder="请输入患者病情"
|
||||
></textarea>
|
||||
</view>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
<!-- 图片上传区域 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">图片</view>
|
||||
<view class="image-upload-area">
|
||||
<!-- 已上传的图片 -->
|
||||
<view
|
||||
class="image-item"
|
||||
v-for="(image, index) in tempImageList"
|
||||
:key="index"
|
||||
>
|
||||
<image
|
||||
:src="image"
|
||||
class="uploaded-image"
|
||||
mode="aspectFill"
|
||||
@click="previewImage(index)"
|
||||
/>
|
||||
<view class="delete-btn" @click="deleteImage(index)">
|
||||
<uni-icons type="closeempty" size="15" color="#fff"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 添加图片按钮 -->
|
||||
<view
|
||||
class="add-image-btn"
|
||||
v-if="imageList.length < 9"
|
||||
@click="chooseImage"
|
||||
>
|
||||
<uni-icons type="plus" size="24" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部删除按钮 -->
|
||||
<view class="bottom-actions" v-if="recordUuid">
|
||||
<button class="delete-btn" @click="deleteRecord">删除该条记录</button>
|
||||
</view>
|
||||
|
||||
<up-datetime-picker
|
||||
:show="showDate"
|
||||
v-model="selectedDate"
|
||||
@cancel="showDate = false"
|
||||
@confirm="confirmDate"
|
||||
mode="date"
|
||||
></up-datetime-picker>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// Vue3 Composition API
|
||||
import { ref, reactive, onMounted, computed } from "vue";
|
||||
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||
import api from "@/api/api.js";
|
||||
import docUrl from "@/utils/docUrl.js";
|
||||
import dayjs from "dayjs";
|
||||
import { pathToBase64, base64ToPath } from "image-tools";
|
||||
|
||||
// 响应式数据
|
||||
const des = ref("");
|
||||
const showDate = ref(false);
|
||||
const recordUuid = ref("");
|
||||
const patientUuid = ref("");
|
||||
const dateTime = ref(dayjs().format("YYYY年MM月DD日"));
|
||||
const selectedDate = ref(dayjs());
|
||||
const description = ref("");
|
||||
const imageList = ref([]);
|
||||
const tempImageList = ref([]);
|
||||
const originalData = ref({});
|
||||
|
||||
// 方法
|
||||
const goBack = () => {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
fail() {
|
||||
uni.redirectTo({
|
||||
url: "/pages/index/index",
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const confirmDate = ({ value, mode }) => {
|
||||
console.log(value);
|
||||
dateTime.value = dayjs(value).format("YYYY年MM月DD日");
|
||||
selectedDate.value = dayjs(value).format("YYYY-MM-DD");
|
||||
showDate.value = false;
|
||||
};
|
||||
const openDateTime = () => {
|
||||
console.log("openDateTime");
|
||||
showDate.value = true;
|
||||
};
|
||||
|
||||
const chooseImage = () => {
|
||||
uni.chooseImage({
|
||||
count: 8 - imageList.value.length,
|
||||
sizeType: ["original", "compressed"],
|
||||
sourceType: ["album", "camera"],
|
||||
success: (res) => {
|
||||
// 这里应该上传图片到服务器
|
||||
// imageList.value = [...imageList.value, ...res.tempFilePaths]
|
||||
tempImageList.value = [...tempImageList.value, ...res.tempFilePaths];
|
||||
const fileManager = uni.getFileSystemManager();
|
||||
for (let i = 0; i < res.tempFilePaths.length; i++) {
|
||||
fileManager.readFile({
|
||||
filePath: res.tempFilePaths[i],
|
||||
encoding: "base64",
|
||||
success: (res) => {
|
||||
imageList.value.push(res.data);
|
||||
},
|
||||
fail: (error) => {
|
||||
console.log("chooseImage", error);
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const deleteImage = (index) => {
|
||||
// 显示模态框
|
||||
uni.showModal({
|
||||
title: "确认删除",
|
||||
content: "确定要删除这张图片吗?",
|
||||
// 设置模态框点击确定按钮后的回调函数
|
||||
success: (res) => {
|
||||
// 如果用户点击了确认按钮
|
||||
if (res.confirm) {
|
||||
// 从imageList数组中删除指定索引的图片
|
||||
imageList.value.splice(index, 1);
|
||||
tempImageList.value.splice(index, 1);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const previewImage = (index) => {
|
||||
uni.previewImage({
|
||||
current: index,
|
||||
urls: imageList.value,
|
||||
});
|
||||
};
|
||||
const addRecord = async () => {
|
||||
if (!des.value) {
|
||||
uni.showToast({
|
||||
title: "请输入患者病情",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
let usrInfo = uni.getStorageSync("userInfo");
|
||||
const res = await api.addConditionRecord({
|
||||
patient_uuid: patientUuid.value,
|
||||
expert_uuid: usrInfo.uuid,
|
||||
des: des.value,
|
||||
create_date: dayjs(selectedDate.value).format("YYYY-MM-DD"),
|
||||
img1: imageList.value[0] || "",
|
||||
img2: imageList.value[1] || "",
|
||||
img3: imageList.value[2] || "",
|
||||
img4: imageList.value[3] || "",
|
||||
img5: imageList.value[4] || "",
|
||||
img6: imageList.value[5] || "",
|
||||
img7: imageList.value[6] || "",
|
||||
img8: imageList.value[7] || "",
|
||||
});
|
||||
if (res.code == 200) {
|
||||
uni.showToast({
|
||||
title: "添加成功",
|
||||
icon: "none",
|
||||
});
|
||||
goBack();
|
||||
}
|
||||
};
|
||||
const updateRecord = async () => {
|
||||
if (!des.value) {
|
||||
uni.showToast({
|
||||
title: "请输入患者病情",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
let usrInfo = uni.getStorageSync("userInfo");
|
||||
const res = await api.updateConditionRecord({
|
||||
uuid: recordUuid.value,
|
||||
patient_uuid: patientUuid.value,
|
||||
expert_uuid: usrInfo.uuid,
|
||||
des: des.value,
|
||||
create_date: dayjs(selectedDate.value).format("YYYY-MM-DD"),
|
||||
img1: imageList.value[0] || "",
|
||||
img2: imageList.value[1] || "",
|
||||
img3: imageList.value[2] || "",
|
||||
img4: imageList.value[3] || "",
|
||||
img5: imageList.value[4] || "",
|
||||
img6: imageList.value[5] || "",
|
||||
img7: imageList.value[6] || "",
|
||||
img8: imageList.value[7] || "",
|
||||
});
|
||||
if (res.code == 200) {
|
||||
uni.showToast({
|
||||
title: "修改成功",
|
||||
icon: "none",
|
||||
});
|
||||
uni.setStorageSync("caseRecord",null);
|
||||
goBack();
|
||||
}
|
||||
};
|
||||
const deleteConditionRecord = async () => {
|
||||
const res = await api.deleteConditionRecord({
|
||||
uuid: recordUuid.value,
|
||||
});
|
||||
if (res.code == 200) {
|
||||
uni.showToast({
|
||||
title: "删除成功",
|
||||
icon: "none",
|
||||
});
|
||||
goBack();
|
||||
}
|
||||
};
|
||||
|
||||
const deleteRecord = () => {
|
||||
uni.showModal({
|
||||
title: "确认删除",
|
||||
content: "确定要删除这条记录吗?",
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
deleteConditionRecord();
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 生命周期
|
||||
onLoad((options) => {
|
||||
console.log(options);
|
||||
recordUuid.value = options.uuid || "";
|
||||
patientUuid.value = options.patientUuid || "";
|
||||
if (recordUuid.value) {
|
||||
imageList.value = [];
|
||||
let record = uni.getStorageSync("caseRecord");
|
||||
des.value = record.des;
|
||||
tempImageList.value = record.photo.map((item) => docUrl + item);
|
||||
// imageList.value = record.photo.map(item=>docUrl+item);
|
||||
dateTime.value = dayjs(record.create_date).format("YYYY年MM月DD日");
|
||||
selectedDate.value = dayjs(record.create_date);
|
||||
for (let i = 0; i < record.photo.length; i++) {
|
||||
console.log("url", docUrl + record.photo[i]);
|
||||
uni.request({
|
||||
url: docUrl + record.photo[i],
|
||||
method: 'GET',
|
||||
responseType: 'arraybuffer',
|
||||
success: (res) => {
|
||||
const base64 = `${uni.arrayBufferToBase64(res.data)}`
|
||||
console.log(base64);
|
||||
imageList.value.push(base64);
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err);
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const saveRecord = () => {
|
||||
if (recordUuid.value) {
|
||||
updateRecord();
|
||||
} else {
|
||||
addRecord();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
}
|
||||
.container {
|
||||
background-color: #ffffff;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 头部导航样式 */
|
||||
.nav-right {
|
||||
padding-right: 30rpx;
|
||||
}
|
||||
|
||||
.modify-btn,
|
||||
.save-btn {
|
||||
font-size: 32rpx;
|
||||
color: #8b2316;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 主要内容区域 */
|
||||
.main-content {
|
||||
padding: 0rpx 30rpx;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
margin-bottom: 20rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.form-value {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.date-text {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.description-input {
|
||||
width: 100%;
|
||||
min-height: 200rpx;
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
line-height: 1.6;
|
||||
background-color: 2rpx solid #f5f5f5;
|
||||
border: none;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.description-input:disabled {
|
||||
color: #999999;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 图片上传区域 */
|
||||
.image-upload-area {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.image-item {
|
||||
position: relative;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uploaded-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.image-item .delete-btn {
|
||||
position: absolute;
|
||||
top: 10rpx;
|
||||
right: 10rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.add-image-btn {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border: 2rpx dashed #cccccc;
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.divider {
|
||||
height: 1rpx;
|
||||
background-color: #f0f0f0;
|
||||
margin: 0 -30rpx;
|
||||
}
|
||||
|
||||
/* 底部操作区域 */
|
||||
.bottom-actions {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 30rpx;
|
||||
background-color: #ffffff;
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.bottom-actions .delete-btn {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
background-color: #8b2316;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 12rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
341
pages_app/checkRecord/checkRecord.vue
Normal file
341
pages_app/checkRecord/checkRecord.vue
Normal file
@ -0,0 +1,341 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 头部导航 -->
|
||||
<navBar :title="headerTitle" />
|
||||
|
||||
<!-- 主要内容区域 -->
|
||||
<view class="main-content">
|
||||
<!-- 疾病诊断部分 -->
|
||||
<view class="section">
|
||||
<view class="section-header">
|
||||
<view class="red-bar"></view>
|
||||
<text class="section-title">疾病诊断</text>
|
||||
</view>
|
||||
<view class="section-content">
|
||||
<text class="diagnosis-text">疾病诊断: {{ pageData.diseaseName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 化验报告部分 -->
|
||||
<view class="section">
|
||||
<view class="section-header">
|
||||
<text class="section-title">化验报告</text>
|
||||
</view>
|
||||
<view class="section-content">
|
||||
<text class="no-report-text" v-if="!pageData.hasLabReport">无检查化验报告</text>
|
||||
<view v-else class="lab-report-container">
|
||||
<view class="image-grid">
|
||||
<view
|
||||
class="image-item"
|
||||
v-for="(image, index) in caseImages"
|
||||
:key="image.uuid"
|
||||
@click="previewImage(index)"
|
||||
>
|
||||
<image
|
||||
:src="docUrl+image.path"
|
||||
class="report-image"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<!-- <view class="image-date">{{ formatDate(image.createDate) }}</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 疾病描述部分 -->
|
||||
<view class="section">
|
||||
<view class="section-header">
|
||||
<text class="section-title">疾病描述</text>
|
||||
</view>
|
||||
<view class="section-content">
|
||||
<text class="description-text">{{ pageData.des || '暂无描述' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部线条 -->
|
||||
<view class="bottom-line"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// Vue3 Composition API
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import { onShow,onLoad } from '@dcloudio/uni-app'
|
||||
import navBar from '@/components/navBar/navBar.vue'
|
||||
import api from '@/api/api.js'
|
||||
import docUrl from '@/utils/docUrl.js'
|
||||
const uuid = ref('')
|
||||
onLoad((options) => {
|
||||
uuid.value = options.uuid
|
||||
})
|
||||
onShow(() => {
|
||||
getDetail()
|
||||
})
|
||||
// 响应式数据
|
||||
const pageData = ref({
|
||||
date: '',
|
||||
diseaseName: '',
|
||||
diagnosis: '',
|
||||
hasLabReport: false,
|
||||
labReport: '',
|
||||
description: '',
|
||||
photo: '',
|
||||
age: 0,
|
||||
title: '',
|
||||
patientUuid: '',
|
||||
diseaseUuid: '',
|
||||
state: 0,
|
||||
createDate: '',
|
||||
modifyDate: null
|
||||
})
|
||||
|
||||
// 案例图片数据
|
||||
const caseImages = ref([])
|
||||
|
||||
const getDetail = () => {
|
||||
api.caseDetail({
|
||||
caseUuid: uuid.value
|
||||
}).then(res => {
|
||||
console.log(res)
|
||||
if(res.code == 200){
|
||||
// 更新案例数据
|
||||
pageData.value = res.data.case
|
||||
// 更新案例图片
|
||||
caseImages.value = res.data.caseImg || []
|
||||
// 设置是否有化验报告(根据图片数量判断)
|
||||
pageData.value.hasLabReport = caseImages.value.length > 0
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error('获取案例详情失败:', err)
|
||||
uni.showToast({
|
||||
title: '获取数据失败',
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 计算属性
|
||||
const headerTitle = computed(() => {
|
||||
return pageData.value.title || `${pageData.value.createDate}${pageData.value.diseaseName}`
|
||||
})
|
||||
|
||||
// 格式化日期
|
||||
const formatDate = (dateStr) => {
|
||||
if (!dateStr) return ''
|
||||
const date = new Date(dateStr)
|
||||
return date.toLocaleDateString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit'
|
||||
}).replace(/\//g, '-')
|
||||
}
|
||||
|
||||
// 方法
|
||||
const goBack = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
|
||||
// 预览图片
|
||||
const previewImage = (index) => {
|
||||
const urls = caseImages.value.map(img => docUrl+img.path)
|
||||
uni.previewImage({
|
||||
current: index,
|
||||
urls: urls
|
||||
})
|
||||
}
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
// 页面加载时的逻辑
|
||||
console.log('检查记录页面已加载')
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
background-color: #ffffff;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 状态栏样式 */
|
||||
.status-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10rpx 30rpx;
|
||||
background-color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.status-left {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.status-center {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.network-icons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.bluetooth-icon, .wifi-icon {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.speed {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.signal {
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.status-right {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 头部导航样式 */
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 30rpx;
|
||||
background-color: #ffffff;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #ff4444;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 36rpx;
|
||||
color: #ff4444;
|
||||
font-weight: bold;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* 主要内容区域 */
|
||||
.main-content {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
margin-top: 20rpx;
|
||||
position: relative;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.red-bar {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 8rpx;
|
||||
height: 40rpx;
|
||||
background-color: #ff4444;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
font-weight: bold;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.section-content {
|
||||
padding-left: 28rpx;
|
||||
}
|
||||
|
||||
.diagnosis-text {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.no-report-text {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.lab-report-text {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.lab-report-container {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.image-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.image-item {
|
||||
position: relative;
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.report-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.image-date {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
|
||||
color: white;
|
||||
font-size: 20rpx;
|
||||
padding: 20rpx 10rpx 10rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.description-text {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 底部线条 */
|
||||
.bottom-line {
|
||||
height: 2rpx;
|
||||
background-color: #f0f0f0;
|
||||
margin: 40rpx 30rpx 0;
|
||||
}
|
||||
</style>
|
||||
@ -47,7 +47,7 @@
|
||||
<uni-icons type="right" color="#999" size="18"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="cell" @click="editDesc">
|
||||
<view class="cell" @click="openGroup">
|
||||
<text class="cell-label">描述</text>
|
||||
<view class="cell-right">
|
||||
<text class="hint">补充患者关键信息,方便随访患者</text>
|
||||
@ -62,10 +62,22 @@
|
||||
</view>
|
||||
|
||||
<!-- 患者病史 -->
|
||||
<view class="section-title">患者病史</view>
|
||||
<view class="card history-card">
|
||||
<text class="history-text" :class="{ fold: !showAllHistory }">{{ patientDetail.medicalHistoryContent }}</text>
|
||||
<text class="toggle" @click="toggleHistory" v-if="patientDetail.patientHistoryText">{{ showAllHistory ? '收起' : '展开全部' }}</text>
|
||||
<view class="history-section" v-if="patientDetail.medicalHistoryContent">
|
||||
<view class="section-title">患者病史</view>
|
||||
<view class="card history-card">
|
||||
<text class="history-text" :class="{ fold: !showAllHistory }">{{ patientDetail.medicalHistoryContent }}</text>
|
||||
<text class="toggle" @click="toggleHistory" v-if="patientDetail.medicalHistoryContent">{{ showAllHistory ? '收起' : '展开全部' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 检查报告 -->
|
||||
<view class="history-section" v-if="patientDetail.patientCase && patientDetail.patientCase.length>0">
|
||||
<view class="section-title">检查报告</view>
|
||||
<view class="card report-card">
|
||||
<view class="report-item" v-for="item in patientDetail.patientCase" :key="item.diseaseUuid" @click="openCase(item.uuid)">
|
||||
<view class="report-item-title">{{ $u.timeFormat(item.createDate, 'yyyy-mm-dd') }}</view>
|
||||
<view class="report-item-content">{{ item.diseaseName }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部操作 -->
|
||||
@ -116,8 +128,8 @@
|
||||
|
||||
// 计算属性:完整地址
|
||||
const fullAddress = computed(() => {
|
||||
const { provName, cityName, countyName, detailed_address } = patientInfo.value;
|
||||
const addressParts = [provName, cityName, countyName, detailed_address].filter(Boolean);
|
||||
const { provName, cityName, countyName } = patientInfo.value;
|
||||
const addressParts = [provName, cityName, countyName].filter(Boolean);
|
||||
return addressParts.length > 0 ? addressParts.join('') : '未设置';
|
||||
});
|
||||
|
||||
@ -127,13 +139,29 @@
|
||||
patient_uuid.value = options.uuid;
|
||||
});
|
||||
const goBack = ()=> uni.navigateBack()
|
||||
const editPatient = ()=> uni.showToast({ title:'编辑资料', icon:'none' })
|
||||
const openGroup = ()=> uni.showToast({ title:'分组', icon:'none' })
|
||||
const editDesc = ()=> uni.showToast({ title:'编辑描述', icon:'none' })
|
||||
const sendMessage = ()=>{
|
||||
const openCase = (uuid)=>{
|
||||
navTo({
|
||||
url: '/pages_app/chat/chat?patient_uuid='+patient_uuid,
|
||||
url:'/pages_app/checkRecord/checkRecord?uuid='+uuid
|
||||
})
|
||||
}
|
||||
const editPatient = ()=> {
|
||||
navTo({
|
||||
url:'/pages_app/patientSetting/patientSetting?uuid=' + patient_uuid.value
|
||||
})
|
||||
}
|
||||
const openGroup = ()=>{
|
||||
navTo({
|
||||
url:'/pages_app/patientRemark/patientRemark?uuid=' + patientInfo.value.uuid
|
||||
})
|
||||
}
|
||||
const editDesc = ()=> uni.showToast({ title:'编辑描述', icon:'none' })
|
||||
const sendMessage = async()=>{
|
||||
let userId=uni.getStorageSync('userInfo').uuid.toLowerCase();
|
||||
let conversationId=userId+'|1|'+patientInfo.value.uuid.toLowerCase();
|
||||
await uni.$UIKitStore.uiStore.selectConversation(conversationId)
|
||||
navTo({
|
||||
url:'/pages_chat/chat/index'
|
||||
})
|
||||
};
|
||||
const nickname = ref('');
|
||||
const group = ref({});
|
||||
@ -186,17 +214,48 @@
|
||||
getToAddNickname();
|
||||
getPatientCard();
|
||||
});
|
||||
const goMakePlan = ()=> uni.navigateTo({ url:'/pages_app/visit/visit' })
|
||||
const recordIllness = ()=> uni.showToast({ title:'记录病情', icon:'none' })
|
||||
const goMakePlan = ()=> {
|
||||
navTo({
|
||||
url:'/pages_app/visitPlan/visitPlan'
|
||||
})
|
||||
}
|
||||
const recordIllness = ()=> {
|
||||
navTo({
|
||||
url:'/pages_app/caseList/caseList?uuid='+patient_uuid.value
|
||||
})
|
||||
}
|
||||
const toggleHistory = ()=> showAllHistory.value = !showAllHistory.value
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.report-card{
|
||||
display: flex;
|
||||
gap: 55rpx;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.report-item{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10rpx;
|
||||
|
||||
background: #f5f5f5;
|
||||
padding: 20rpx;
|
||||
align-items: center;
|
||||
border-radius: 12rpx;
|
||||
.report-item-title{
|
||||
font-size: 28rpx;
|
||||
color:#666;
|
||||
}
|
||||
.report-item-content{
|
||||
font-size: 28rpx;
|
||||
color:#333;
|
||||
}
|
||||
}
|
||||
.content { background:#f5f5f5; min-height:100vh; }
|
||||
.nav-right { padding-right: 20rpx; }
|
||||
|
||||
.card { background:#ffffff; padding: 20rpx; }
|
||||
.header-card { display:flex; }
|
||||
.card { background:#ffffff; padding: 20rpx; padding-top: 0;}
|
||||
.header-card { display:flex; padding-top: 20rpx;}
|
||||
.avatar { width: 140rpx; height: 140rpx; border-radius: 12rpx; margin-right: 20rpx; }
|
||||
.base-info { flex:1; }
|
||||
.name-row { display:flex; align-items:center; margin-bottom: 10rpx; }
|
||||
@ -215,11 +274,11 @@
|
||||
.hint { font-size: 28rpx; color:#999; margin-right: 12rpx; }
|
||||
.phone { font-size: 32rpx; color:#b10000; }
|
||||
|
||||
.section-title { padding: 16rpx 30rpx; color:#8B2316; font-size: 30rpx; margin-top: 20rpx; }
|
||||
.section-title { padding: 16rpx 30rpx; color:#8B2316; font-size: 30rpx; margin-top: 20rpx; background: #fff;}
|
||||
.history-card { position: relative; }
|
||||
.history-text { font-size: 28rpx; color:#666; line-height: 1.7; display:block; }
|
||||
.history-text.fold { display:-webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
||||
.toggle { position:absolute; right: 20rpx; bottom: 16rpx; color:#b10000; font-size: 28rpx; }
|
||||
.toggle { position:absolute; right: 20rpx; bottom: 25rpx; color:#b10000; font-size: 28rpx;background: #fff; z-index: 10;}
|
||||
|
||||
.actions { background:#ffffff; margin-top: 20rpx;}
|
||||
.action { display:flex; align-items:center;justify-content: center; padding: 28rpx 30rpx; border-top:1rpx solid #f0f0f0; }
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<!-- 顶部导航栏 -->
|
||||
<uni-nav-bar
|
||||
left-icon="left"
|
||||
title="患者消息"
|
||||
:title="title"
|
||||
@clickLeft="goBack"
|
||||
fixed
|
||||
color="#8B2316"
|
||||
@ -12,10 +12,18 @@
|
||||
backgroundColor="#eee"
|
||||
>
|
||||
<template #right>
|
||||
<view class="nav-right">
|
||||
<view class="nav-right" v-if="activeTab === 'message'">
|
||||
<uni-icons type="search" size="24" color="#8B2316" @click="searchPatients"></uni-icons>
|
||||
<uni-icons type="staff" size="24" color="#8B2316" @click="managePatients" style="margin-left: 30rpx;"></uni-icons>
|
||||
</view>
|
||||
<view class="nav-right" v-else-if="activeTab === 'list'">
|
||||
<uni-icons type="search" size="24" color="#8B2316" @click="searchPatients"></uni-icons>
|
||||
<uni-icons type="plusempty" size="24" color="#8B2316" @click="goCode" style="margin-left: 30rpx;" ></uni-icons>
|
||||
</view>
|
||||
<view class="nav-right" v-else-if="activeTab === 'plan'" @click="showAddMenu">
|
||||
<view class="save-btn">保存</view>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
</uni-nav-bar>
|
||||
|
||||
@ -167,10 +175,10 @@
|
||||
</scroll-view>
|
||||
|
||||
<!-- 悬浮添加按钮 -->
|
||||
<view class="floating-add-btn" @click="showAddMenu">
|
||||
<!-- <view class="floating-add-btn" @click="showAddMenu">
|
||||
<uni-icons type="plus" size="24" color="#ffffff"></uni-icons>
|
||||
<text class="btn-text">添加</text>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 添加菜单弹窗 -->
|
||||
<view class="add-menu-popup" v-if="showAddMenuFlag" @click="hideAddMenu">
|
||||
@ -191,13 +199,11 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view
|
||||
<!-- 底部标签栏 -->
|
||||
<view class="tab-bar">
|
||||
<view class="tab-item" :class="{active: activeTab === 'message'}" @click="switchTab('message')">
|
||||
<text class="tab-text">患者消息</text>
|
||||
|
||||
</view>
|
||||
<view class="tab-item" :class="{active: activeTab === 'list'}" @click="switchTab('list')">
|
||||
<text class="tab-text">患者列表</text>
|
||||
@ -223,7 +229,7 @@
|
||||
import dayjs from 'dayjs'
|
||||
import lineImg from "@/static/item_visitplan_fg.png"
|
||||
import ConversationList from './conversation-list/index.vue'
|
||||
|
||||
const title = ref('患者消息');
|
||||
const goPatientDetail = (uuid) => {
|
||||
navTo({
|
||||
url: `/pages_app/patientDetail/patientDetail?uuid=${uuid}`
|
||||
@ -235,6 +241,11 @@
|
||||
url: `/pages_app/patientSetting/patientSetting?uuid=${uuid}`
|
||||
})
|
||||
}
|
||||
const goCode = () => {
|
||||
navTo({
|
||||
url: `/pages_app/myCode/myCode`
|
||||
})
|
||||
}
|
||||
// 仅保留年月日
|
||||
const formatYMD = (input) => {
|
||||
if (!input) return '';
|
||||
@ -489,10 +500,9 @@
|
||||
|
||||
// 搜索患者
|
||||
const searchPatients = () => {
|
||||
uni.showToast({
|
||||
title: '搜索患者',
|
||||
icon: 'none'
|
||||
});
|
||||
navTo({
|
||||
url: `/pages_app/searchPatient/searchPatient`
|
||||
})
|
||||
};
|
||||
|
||||
// 管理患者
|
||||
@ -519,15 +529,19 @@
|
||||
const switchTab = (tab) => {
|
||||
activeTab.value = tab;
|
||||
|
||||
|
||||
switch(tab) {
|
||||
case 'message':
|
||||
// 患者消息页面逻辑 - 刷新申请列表
|
||||
getApplyList();
|
||||
title.value = '患者消息';
|
||||
break;
|
||||
case 'list':
|
||||
title.value = '患者列表';
|
||||
// 显示患者列表
|
||||
break;
|
||||
case 'plan':
|
||||
title.value = '随访计划';
|
||||
// 随访计划页面 - 加载随访计划数据
|
||||
if (followUpList.value.length === 0) {
|
||||
getFollowUpList(true);
|
||||
@ -618,6 +632,11 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.save-btn {
|
||||
font-size: 32rpx;
|
||||
color: #8b2316;
|
||||
font-weight: 500;
|
||||
}
|
||||
.content {
|
||||
background-color: #f5f5f5;
|
||||
height: 100vh;
|
||||
@ -893,7 +912,7 @@
|
||||
.group-section {
|
||||
.group-header {
|
||||
padding: 20rpx 30rpx;
|
||||
background-color: #f8f8f8;
|
||||
background-color: #e4e4e4;
|
||||
font-size: 36rpx;
|
||||
color: #666666;
|
||||
font-weight: bold;
|
||||
@ -1044,7 +1063,6 @@
|
||||
}
|
||||
|
||||
.plan-list{
|
||||
margin-top: 20rpx;
|
||||
padding-bottom: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
98
pages_app/searchPatient/searchPatient.vue
Normal file
98
pages_app/searchPatient/searchPatient.vue
Normal file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<view class="select-page">
|
||||
|
||||
<navBar title="搜索患者" />
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<view class="search-bar">
|
||||
<view class="input-wrap">
|
||||
<input class="search-input" v-model.trim="keyword" placeholder="搜索患者的备注名、昵称或手机号" placeholder-class="ph" @input="$u.debounce(onSearch, 500)" />
|
||||
</view>
|
||||
<view class="search-btn" @click="onSearch">
|
||||
<uni-icons type="search" size="50rpx" color="#999" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 列表 -->
|
||||
<scroll-view class="list" scroll-y>
|
||||
<view class="item" @click="goDetail(p.uuid)" v-for="p in availablePatientList" :key="p.uuid">
|
||||
<image class="avatar" :src="docUrl + (p.photo || '')" mode="aspectFill" />
|
||||
<view class="name">{{ p.nickname || p.realName }}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import docUrl from '@/utils/docUrl.js'
|
||||
import { onShow,onLoad} from "@dcloudio/uni-app";
|
||||
import api from '@/api/api.js'
|
||||
import navTo from '@/utils/navTo.js'
|
||||
import navBar from '@/components/navBar/navBar.vue'
|
||||
const from = ref('');
|
||||
const keyword = ref('')
|
||||
const patientList = ref([])
|
||||
// 计算属性:显示所有患者,但标记已选中的状态
|
||||
const availablePatientList = computed(() => {
|
||||
return patientList.value
|
||||
})
|
||||
const patientListByGBK = async () => {
|
||||
|
||||
const res = await api.patientListByGBK();
|
||||
if(res.code == 1){
|
||||
patientList.value = res.data;
|
||||
}
|
||||
};
|
||||
onLoad((options) => {
|
||||
if(options.from == 'chatMsg'){
|
||||
from.value = 'chatMsg';
|
||||
}
|
||||
|
||||
})
|
||||
onShow(() => {
|
||||
patientListByGBK();
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
const goDetail = (uuid) => {
|
||||
navTo({ url: `/pages_app/patientDetail/patientDetail?uuid=${uuid}` })
|
||||
}
|
||||
|
||||
const onSearch = () => {
|
||||
patientList.value = patientList.value.filter(p => p.realName.indexOf(keyword.value) !== -1 || (p.nickname && p.nickname.indexOf(keyword.value) !== -1) || p.mobile.indexOf(keyword.value) !== -1)
|
||||
}
|
||||
const goBack = () => uni.navigateBack()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.select-page{
|
||||
min-height: 100vh; background:#fefefe;
|
||||
}
|
||||
.confirm-text{ color:#fff; font-size: 28rpx;white-space: nowrap; }
|
||||
.confirm-btn{ background:#7f7f7f; padding: 10rpx 18rpx; border-radius: 26rpx; }
|
||||
.confirm-btn.active{ background:#8B2316; }
|
||||
.search-bar{
|
||||
border: 2rpx solid #eee;
|
||||
margin: 20rpx 30rpx; display:flex; align-items:center; gap: 16rpx;
|
||||
.input-wrap{ flex:1; background:#fff; border-radius: 12rpx; padding: 16rpx 20rpx; }
|
||||
.search-input{ font-size: 28rpx; color:#333; }
|
||||
.ph{ color:#bfbfbf; }
|
||||
.search-btn{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 88rpx; height: 72rpx; background:#fff;
|
||||
}
|
||||
}
|
||||
.list{ border-radius: 12rpx; }
|
||||
.item{background:#fff; display:flex; align-items:center;padding: 24rpx 30rpx; border-bottom: 2rpx solid #eee; }
|
||||
.avatar{ width: 96rpx; height:96rpx; border-radius: 16rpx; background:#ffe; }
|
||||
.name{ flex:1; margin-left: 20rpx; font-size: 32rpx; color:#333; }
|
||||
.check{ padding-left: 12rpx; }
|
||||
.circle{ width: 40rpx; height: 40rpx; border-radius: 50%; border: 2rpx solid #cfcfcf; }
|
||||
.circle.active{ background:#8B2316; border-color:#8B2316; position: relative; }
|
||||
.circle.active::after{ content:''; position:absolute; left: 14rpx; top: 6rpx; width: 10rpx; height: 18rpx; border: 4rpx solid #fff; border-top: 0; border-left: 0; transform: rotate(45deg); }
|
||||
</style>
|
||||
@ -20,7 +20,7 @@
|
||||
<!-- 搜索框 -->
|
||||
<view class="search-bar">
|
||||
<view class="input-wrap">
|
||||
<input class="search-input" v-model.trim="keyword" placeholder="搜索患者的备注名、昵称或手机号" placeholder-class="ph" @confirm="onSearch" />
|
||||
<input class="search-input" v-model.trim="keyword" placeholder="搜索患者的备注名、昵称或手机号" placeholder-class="ph" @input="$u.debounce(onSearch, 500)" />
|
||||
</view>
|
||||
<view class="search-btn" @click="onSearch">
|
||||
<uni-icons type="search" size="50rpx" color="#999" />
|
||||
@ -31,7 +31,7 @@
|
||||
<scroll-view class="list" scroll-y>
|
||||
<view class="item" @click="toggle(p.uuid)" v-for="p in availablePatientList" :key="p.uuid">
|
||||
<image class="avatar" :src="docUrl + (p.photo || '')" mode="aspectFill" />
|
||||
<view class="name">{{ p.realName || '-' }}</view>
|
||||
<view class="name">{{ p.nickname || p.realName }}</view>
|
||||
<view class="check" >
|
||||
<view class="circle" :class="{ active: selectedIds.includes(p.uuid) }"></view>
|
||||
</view>
|
||||
@ -111,7 +111,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
const onSearch = () => {}
|
||||
const onSearch = () => {
|
||||
patientList.value = patientList.value.filter(p => p.realName.indexOf(keyword.value) !== -1 || (p.nickname && p.nickname.indexOf(keyword.value) !== -1) || p.mobile.indexOf(keyword.value) !== -1)
|
||||
}
|
||||
const goBack = () => uni.navigateBack()
|
||||
const confirmSelect = () => {
|
||||
const payload = { ids: selectedIds.value, list: selectedDetail.value }
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
<!-- 搜索框 -->
|
||||
<view class="search-bar">
|
||||
<view class="input-wrap">
|
||||
<input class="search-input" v-model.trim="keyword" placeholder="搜索患者的备注名、昵称或手机号" placeholder-class="ph" @confirm="onSearch" />
|
||||
<input class="search-input" v-model.trim="keyword" placeholder="搜索患者的备注名、昵称或手机号" placeholder-class="ph" @input="$u.debounce(onSearch, 500)" />
|
||||
</view>
|
||||
<view class="search-btn" @click="onSearch">
|
||||
<uni-icons type="search" size="50rpx" color="#999" />
|
||||
@ -31,7 +31,7 @@
|
||||
<scroll-view class="list" scroll-y>
|
||||
<view class="item" @click="toggle(p.uuid)" v-for="p in availablePatientList" :key="p.uuid">
|
||||
<image class="avatar" :src="docUrl + (p.photo || '')" mode="aspectFill" />
|
||||
<view class="name">{{ p.realName || '-' }}</view>
|
||||
<view class="name">{{ p.nickname || p.realName }}</view>
|
||||
<view class="check" >
|
||||
<view class="circle" :class="{ active: selectedIds.includes(p.uuid) }"></view>
|
||||
</view>
|
||||
@ -114,7 +114,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
const onSearch = () => {}
|
||||
const onSearch = () => {
|
||||
patientList.value = patientList.value.filter(p => p.realName.indexOf(keyword.value) !== -1 || (p.nickname && p.nickname.indexOf(keyword.value) !== -1) || p.mobile.indexOf(keyword.value) !== -1)
|
||||
}
|
||||
const goBack = () => uni.navigateBack()
|
||||
const confirmSelect = (id) => {
|
||||
const payload =patientList.value.find(x => x.uuid === id)
|
||||
|
||||
209
pages_app/visitPlan/visitPlan.vue
Normal file
209
pages_app/visitPlan/visitPlan.vue
Normal file
@ -0,0 +1,209 @@
|
||||
<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">
|
||||
|
||||
<text class="save-btn" @click="showAddMenu" >添加</text>
|
||||
</view>
|
||||
</template>
|
||||
</uni-nav-bar>
|
||||
<view class="plan">
|
||||
<scroll-view
|
||||
class="plan-scroll"
|
||||
scroll-y="true"
|
||||
refresher-enabled="true"
|
||||
:refresher-triggered="followUpRefreshing"
|
||||
@refresherrefresh="onFollowUpRefresh"
|
||||
@scrolltolower="onFollowUpLoadMore"
|
||||
:lower-threshold="100"
|
||||
>
|
||||
<view class="plan-list" v-if="groupedFollowUpList.length > 0">
|
||||
<view class="plan-group" v-for="group in groupedFollowUpList" :key="group.yearMonth">
|
||||
<view class="group-header">{{ group.yearMonth }}</view>
|
||||
<view class="plan-card" v-for="item in group.items" :key="item.uuid" @click="goFollowDetail(item)">
|
||||
<view class="left-rail">
|
||||
<text class="day">{{ formatDay(item.datetime) }}</text>
|
||||
</view>
|
||||
<view class="linebox">
|
||||
<up-image :src="lineImg" width="14rpx" height="140rpx" ></up-image>
|
||||
</view>
|
||||
<view class="right-content">
|
||||
<view class="leftcontent">
|
||||
<view class="note">{{ item.note }}</view>
|
||||
<view class="name">{{ item.patientname }}</view>
|
||||
</view>
|
||||
<uni-icons type="forward" size="20" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="load-more" v-if="followUpLoading">
|
||||
<uni-icons type="spinner-cycle" size="20" color="#999"></uni-icons>
|
||||
<text class="load-text">加载中...</text>
|
||||
</view>
|
||||
<view class="no-more" v-if="!followUpHasMore && followUpList.length > 0">
|
||||
<text class="no-more-text">没有更多数据了</text>
|
||||
</view>
|
||||
</view>
|
||||
<empty v-else></empty>
|
||||
</scroll-view>
|
||||
|
||||
<!-- <view class="floating-add-btn" @click="showAddMenu">
|
||||
<uni-icons type="plus" size="24" color="#ffffff"></uni-icons>
|
||||
<text class="btn-text">添加</text>
|
||||
</view> -->
|
||||
|
||||
<view class="add-menu-popup" v-if="showAddMenuFlag" @click="hideAddMenu">
|
||||
<view class="menu-content" @click.stop>
|
||||
<view class="menu-item" @click="addSchedule">
|
||||
<up-image :src="dayImg" width="34rpx" height="34rpx" ></up-image>
|
||||
<text class="menu-text">添加日程</text>
|
||||
</view>
|
||||
<view class="menu-divider"></view>
|
||||
<view class="menu-item" @click="addFollowUpPlan">
|
||||
<up-image :src="planImg" width="34rpx" height="34rpx" ></up-image>
|
||||
<text class="menu-text">添加随访计划</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import dayjs from 'dayjs'
|
||||
import api from '@/api/api.js'
|
||||
import navTo from '@/utils/navTo.js'
|
||||
import dayImg from '@/static/visit_data11.png'
|
||||
import planImg from '@/static/visitplan.png'
|
||||
import lineImg from '@/static/item_visitplan_fg.png'
|
||||
|
||||
const formatYearMonth = (input) => {
|
||||
if (!input) return ''
|
||||
const d = dayjs(input)
|
||||
return d.isValid() ? d.format('YYYY年MM月') : ''
|
||||
}
|
||||
const formatDay = (input) => {
|
||||
if (!input) return ''
|
||||
const d = dayjs(input)
|
||||
return d.isValid() ? d.format('DD日') : ''
|
||||
}
|
||||
|
||||
const followUpList = ref([])
|
||||
const followUpLoading = ref(false)
|
||||
const followUpRefreshing = ref(false)
|
||||
const followUpHasMore = ref(true)
|
||||
const followUpPageSize = ref(10)
|
||||
const page = ref(1)
|
||||
|
||||
const groupedFollowUpList = computed(() => {
|
||||
if (!followUpList.value || followUpList.value.length === 0) return []
|
||||
const groups = new Map()
|
||||
followUpList.value.forEach(item => {
|
||||
const yearMonth = formatYearMonth(item.datetime)
|
||||
if (!groups.has(yearMonth)) groups.set(yearMonth, [])
|
||||
groups.get(yearMonth).push(item)
|
||||
})
|
||||
return Array.from(groups.entries()).map(([yearMonth, items]) => ({
|
||||
yearMonth,
|
||||
items: items.sort((a, b) => new Date(a.datetime) - new Date(b.datetime))
|
||||
})).sort((a, b) => new Date(a.items[0].datetime) - new Date(b.items[0].datetime))
|
||||
})
|
||||
|
||||
const getFollowUpList = async (isRefresh = false) => {
|
||||
if (followUpLoading.value) return
|
||||
followUpLoading.value = true
|
||||
try {
|
||||
const currentPage = isRefresh ? 1 : page.value
|
||||
const res = await api.followUpList({ page: currentPage, pageSize: followUpPageSize.value })
|
||||
if (res.code === 200) {
|
||||
const newData = res.data.list || []
|
||||
if (isRefresh) {
|
||||
followUpList.value = newData
|
||||
page.value = 1
|
||||
} else {
|
||||
followUpList.value = [...followUpList.value, ...newData]
|
||||
}
|
||||
followUpHasMore.value = newData.length >= followUpPageSize.value
|
||||
if (!isRefresh) page.value++
|
||||
}
|
||||
} catch (e) {
|
||||
uni.showToast({ title: '获取数据失败', icon: 'error' })
|
||||
} finally {
|
||||
followUpLoading.value = false
|
||||
followUpRefreshing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const onFollowUpRefresh = async () => {
|
||||
followUpRefreshing.value = true
|
||||
await getFollowUpList(true)
|
||||
uni.showToast({ title: '刷新成功', icon: 'none' })
|
||||
}
|
||||
const onFollowUpLoadMore = async () => {
|
||||
if (!followUpHasMore.value || followUpLoading.value) return
|
||||
await getFollowUpList(false)
|
||||
}
|
||||
const goBack = () => uni.navigateBack()
|
||||
const showAddMenuFlag = ref(false)
|
||||
const showAddMenu = () => { showAddMenuFlag.value = true }
|
||||
const hideAddMenu = () => { showAddMenuFlag.value = false }
|
||||
const addFollowUpPlan = () => { showAddMenuFlag.value = false; uni.navigateTo({ url: '/pages_app/visit/visit?from=visitPlan' }) }
|
||||
const addSchedule = () => { showAddMenuFlag.value = false; uni.navigateTo({ url: '/pages_app/schedule/schedule' }) }
|
||||
const goFollowDetail = (raw) => { if (!raw) return; navTo({ url: `/pages_app/followDetail/followDetail?followUpUuid=${encodeURIComponent(raw.uuid || '')}&patient_name=${raw.patientname}` }) }
|
||||
|
||||
onShow(() => {
|
||||
followUpList.value = []
|
||||
page.value = 1
|
||||
followUpHasMore.value = true
|
||||
followUpLoading.value = false
|
||||
followUpRefreshing.value = false
|
||||
getFollowUpList(true)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.save-btn {
|
||||
font-size: 32rpx;
|
||||
color: #8b2316;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.content { background-color: #f5f5f5; height: 100vh; overflow-y: hidden; }
|
||||
.linebox{ margin:0 20rpx; }
|
||||
.plan{ position: fixed; top: 140rpx; left: 0; right: 0; bottom:0rpx; }
|
||||
.plan-scroll { height: 100%; }
|
||||
.plan-list{ padding-bottom: 20rpx; }
|
||||
.plan-group{ background:#f5f5f5; }
|
||||
.group-header{ text-align: center; background:#e4e4e4; color:#333; font-size: 30rpx; padding: 20rpx 30rpx; }
|
||||
.plan-card{ display:flex; align-items:center; background:#fff; padding: 26rpx 30rpx; border-bottom:1rpx solid #f0f0f0; }
|
||||
.left-rail{ display:flex; align-items:center; color:#8B2316; }
|
||||
.left-rail .day{ font-size: 36rpx; margin-right: 12rpx; }
|
||||
.right-content{ flex:1; display:flex; align-items:center; justify-content:space-between; }
|
||||
.right-content .note{ font-size: 30rpx; color:#333; }
|
||||
.right-content .name{ margin-top: 30rpx; font-size: 28rpx; color:#8B2316; }
|
||||
.load-more { display:flex; align-items:center; justify-content:center; padding:30rpx; color:#999; }
|
||||
.load-more .load-text { margin-left:10rpx; font-size:28rpx; }
|
||||
.no-more { display:flex; align-items:center; justify-content:center; padding:30rpx; }
|
||||
.no-more .no-more-text{ font-size:28rpx; color:#999; }
|
||||
.floating-add-btn { position: fixed; bottom: 140rpx; right: 30rpx; background-color: #8B2316; border-radius: 50%; width: 100rpx; height: 100rpx; display:flex; flex-direction:column; align-items:center; justify-content:center; z-index:999; box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1); }
|
||||
.floating-add-btn .btn-text{ font-size:20rpx; color:#fff; margin-top:4rpx; }
|
||||
.add-menu-popup { position: fixed; top:0; left:0; right:0; bottom:0; background-color: rgba(0,0,0,0); display:flex; align-items:center; justify-content:center; z-index:1000; }
|
||||
.menu-content { background:#fff; border-radius:20rpx; box-shadow:0 8rpx 24rpx rgba(0,0,0,0.2); width:80%; max-width:400rpx; overflow:hidden; }
|
||||
.menu-item { display:flex; align-items:center; padding:30rpx 40rpx; border-bottom:1rpx solid #f0f0f0; }
|
||||
.menu-item:last-child{ border-bottom:none; }
|
||||
.menu-text{ font-size:32rpx; color:#333; margin-left:20rpx; }
|
||||
.menu-divider{ height:1rpx; background:#f0f0f0; margin:0 40rpx; }
|
||||
</style>
|
||||
|
||||
BIN
static/point_buy.png
Normal file
BIN
static/point_buy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
Loading…
x
Reference in New Issue
Block a user