Browse Source

feat(tab-bar): 移除医生角色的后台选项,优化角色标签配置
feat(doctor-index): 添加药品管理和危急值管理功能项,更新健康资讯管理描述
refactor(public-index): 清理首页模板,移除不必要的代码
refactor(login): 修改患者家属按钮文本为“家属”

mcbaiyun 2 weeks ago
parent
commit
175339705b

+ 1 - 1
src/components/tab-bar.vue

@@ -31,7 +31,7 @@ const roleTabs: RoleTabs = {
   // 医生
   // 医生
   2: [
   2: [
     { icon: '/static/icons/remixicon/home-3-line.svg', text: '首页', url: '/pages/doctor/index/index' },
     { icon: '/static/icons/remixicon/home-3-line.svg', text: '首页', url: '/pages/doctor/index/index' },
-    { icon: '/static/icons/remixicon/settings-line.svg', text: '后台', url: '/pages/doctor/manage/index' },
+    // { icon: '/static/icons/remixicon/settings-line.svg', text: '后台', url: '/pages/doctor/manage/index' },
     { icon: '/static/icons/remixicon/account-circle-line.svg', text: '我的', url: '/pages/doctor/profile/index' }
     { icon: '/static/icons/remixicon/account-circle-line.svg', text: '我的', url: '/pages/doctor/profile/index' }
   ],
   ],
   // 患者
   // 患者

+ 87 - 47
src/pages/doctor/index/index.vue

@@ -15,7 +15,8 @@
           </view>
           </view>
           <view class="message-button" @click="onMessageClick">
           <view class="message-button" @click="onMessageClick">
             <image src="/static/icons/remixicon/message-3-line.svg" class="message-icon" />
             <image src="/static/icons/remixicon/message-3-line.svg" class="message-icon" />
-            <view class="badge" v-if="unreadMessageCount > 0">{{ unreadMessageCount > 99 ? '99+' : unreadMessageCount }}</view>
+            <view class="badge" v-if="unreadMessageCount > 0">{{ unreadMessageCount > 99 ? '99+' : unreadMessageCount }}
+            </view>
           </view>
           </view>
           <view class="qr-button" @click="onQrClick">
           <view class="qr-button" @click="onQrClick">
             <image src="/static/icons/remixicon/qr-code-line.svg" class="qr-icon" />
             <image src="/static/icons/remixicon/qr-code-line.svg" class="qr-icon" />
@@ -34,13 +35,33 @@
               <text class="item-desc">管理慢性病患者</text>
               <text class="item-desc">管理慢性病患者</text>
             </view>
             </view>
           </view>
           </view>
-          <view class="function-item orange" @click="onItemClick('复诊管理')">
+          <view class="function-item orange" @click="onItemClick('药品信息管理')">
+            <view class="item-content">
+              <view class="title-row">
+                <view class="item-line"></view>
+                <text class="item-title">药品管理</text>
+              </view>
+              <text class="item-desc">管理药品信息</text>
+            </view>
+          </view>
+        </view>
+        <view class="function-row">
+          <view class="function-item purple" @click="onItemClick('危急值管理')">
+            <view class="item-content">
+              <view class="title-row">
+                <view class="item-line"></view>
+                <text class="item-title">危急值管理</text>
+              </view>
+              <text class="item-desc">设置与管理危急值阈值</text>
+            </view>
+          </view>
+          <view class="function-item green" @click="onItemClick('健康资讯管理')">
             <view class="item-content">
             <view class="item-content">
               <view class="title-row">
               <view class="title-row">
                 <view class="item-line"></view>
                 <view class="item-line"></view>
-                <text class="item-title">复诊管理</text>
+                <text class="item-title">健康资讯管理</text>
               </view>
               </view>
-              <text class="item-desc">安排复诊随访</text>
+              <text class="item-desc">管理健康资讯与文章</text>
             </view>
             </view>
           </view>
           </view>
         </view>
         </view>
@@ -182,30 +203,30 @@ const fetchUserInfo = async () => {
         const userIdRaw = resp.data.id || resp.data.userId
         const userIdRaw = resp.data.id || resp.data.userId
         const userId = userIdRaw ? String(userIdRaw) : ''
         const userId = userIdRaw ? String(userIdRaw) : ''
         if (userId) {
         if (userId) {
-            try {
-              // 使用 avatarCache.getOrFetch 做并发去重,loader 只在真正需要下载时被调用一次
-              const path = await avatarCache.getOrFetch(userId, async (id) => {
-                try {
-                  const downloadRes = await uni.downloadFile({
-                    url: `https://wx.baiyun.work/user/avatar/${id}`,
-                    header: {
-                      Authorization: `Bearer ${token}`
-                    }
-                  })
-                  if (downloadRes.statusCode === 200 && downloadRes.tempFilePath) {
-                    return downloadRes.tempFilePath
+          try {
+            // 使用 avatarCache.getOrFetch 做并发去重,loader 只在真正需要下载时被调用一次
+            const path = await avatarCache.getOrFetch(userId, async (id) => {
+              try {
+                const downloadRes = await uni.downloadFile({
+                  url: `https://wx.baiyun.work/user/avatar/${id}`,
+                  header: {
+                    Authorization: `Bearer ${token}`
                   }
                   }
-                } catch (e) {
-                  console.error('Download avatar error:', e)
+                })
+                if (downloadRes.statusCode === 200 && downloadRes.tempFilePath) {
+                  return downloadRes.tempFilePath
                 }
                 }
-                return undefined
-              })
-
-              if (path) resp.data.avatar = path
-            } catch (e) {
-              console.error('avatar fetch error:', e)
-            }
+              } catch (e) {
+                console.error('Download avatar error:', e)
+              }
+              return undefined
+            })
+
+            if (path) resp.data.avatar = path
+          } catch (e) {
+            console.error('avatar fetch error:', e)
           }
           }
+        }
       }
       }
       user.value = resp.data
       user.value = resp.data
       uni.setStorageSync('user_info', resp.data)
       uni.setStorageSync('user_info', resp.data)
@@ -243,21 +264,21 @@ const fetchPatientActivities = async () => {
       console.log('No token found, skipping fetchPatientActivities')
       console.log('No token found, skipping fetchPatientActivities')
       return
       return
     }
     }
-    
+
     console.log('Fetching patient activities...')
     console.log('Fetching patient activities...')
-    
+
     // 调用真实接口获取患者动态
     // 调用真实接口获取患者动态
     const response = await queryBoundPatientsActivities({
     const response = await queryBoundPatientsActivities({
       pageNum: 1,
       pageNum: 1,
       pageSize: 10
       pageSize: 10
     })
     })
-    
+
     console.log('Patient activities response:', response)
     console.log('Patient activities response:', response)
-    
+
     const resp = response.data as any
     const resp = response.data as any
     if (resp && resp.code === 200 && resp.data) {
     if (resp && resp.code === 200 && resp.data) {
       console.log('Patient activities data:', resp.data)
       console.log('Patient activities data:', resp.data)
-      
+
       // 转换数据格式,异步获取头像
       // 转换数据格式,异步获取头像
       const activitiesPromises = resp.data.records.map(async (activity: any) => ({
       const activitiesPromises = resp.data.records.map(async (activity: any) => ({
         desc: formatActivityDescription(activity),
         desc: formatActivityDescription(activity),
@@ -265,7 +286,7 @@ const fetchPatientActivities = async () => {
         // 强制把 userId 转为字符串,避免数值精度或类型不匹配引起的问题
         // 强制把 userId 转为字符串,避免数值精度或类型不匹配引起的问题
         patientAvatar: await getPatientAvatar(String(activity.userId))
         patientAvatar: await getPatientAvatar(String(activity.userId))
       }))
       }))
-      
+
       // 等待所有头像获取完成
       // 等待所有头像获取完成
       const activities = await Promise.all(activitiesPromises)
       const activities = await Promise.all(activitiesPromises)
       console.log('Converted activities:', activities)
       console.log('Converted activities:', activities)
@@ -374,16 +395,16 @@ const formatTime = (createTime: string) => {
     const now = new Date()
     const now = new Date()
     const create = new Date(createTime)
     const create = new Date(createTime)
     const diff = now.getTime() - create.getTime()
     const diff = now.getTime() - create.getTime()
-    
+
     const minutes = Math.floor(diff / (1000 * 60))
     const minutes = Math.floor(diff / (1000 * 60))
     const hours = Math.floor(diff / (1000 * 60 * 60))
     const hours = Math.floor(diff / (1000 * 60 * 60))
     const days = Math.floor(diff / (1000 * 60 * 60 * 24))
     const days = Math.floor(diff / (1000 * 60 * 60 * 24))
-    
+
     if (minutes < 1) return '刚刚'
     if (minutes < 1) return '刚刚'
     if (minutes < 60) return `${minutes}分钟前`
     if (minutes < 60) return `${minutes}分钟前`
     if (hours < 24) return `${hours}小时前`
     if (hours < 24) return `${hours}小时前`
     if (days < 7) return `${days}天前`
     if (days < 7) return `${days}天前`
-    
+
     return create.toLocaleDateString('zh-CN')
     return create.toLocaleDateString('zh-CN')
   } catch (e) {
   } catch (e) {
     return createTime
     return createTime
@@ -391,7 +412,7 @@ const formatTime = (createTime: string) => {
 }
 }
 
 
 function onMessageClick() {
 function onMessageClick() {
-  uni.navigateTo({ 
+  uni.navigateTo({
     url: '/pages/public/message-detail',
     url: '/pages/public/message-detail',
     events: {
     events: {
       // 监听消息详情页的消息已读事件
       // 监听消息详情页的消息已读事件
@@ -407,7 +428,7 @@ const getPatientAvatar = async (userId: string | number): Promise<string> => {
   try {
   try {
     const token = uni.getStorageSync('token')
     const token = uni.getStorageSync('token')
     if (!token) return defaultAvatarUrl
     if (!token) return defaultAvatarUrl
-    
+
     // 使用 getOrFetch 去重并缓存下载结果
     // 使用 getOrFetch 去重并缓存下载结果
     const idStr = String(userId)
     const idStr = String(userId)
     try {
     try {
@@ -435,7 +456,7 @@ const getPatientAvatar = async (userId: string | number): Promise<string> => {
   } catch (e) {
   } catch (e) {
     console.error('Download patient avatar error:', e)
     console.error('Download patient avatar error:', e)
   }
   }
-  
+
   // 如果获取失败,使用默认头像
   // 如果获取失败,使用默认头像
   return defaultAvatarUrl
   return defaultAvatarUrl
 }
 }
@@ -466,10 +487,21 @@ function handleScan(res: any) {
 }
 }
 
 
 function onItemClick(type: string) {
 function onItemClick(type: string) {
-  if (type === '我的病人') {
-    uni.navigateTo({ url: '/pages/doctor/index/my-patients' })
-  } else {
-    uni.showToast({ title: '功能正在开发中', icon: 'none' })
+  switch (type) {
+    case '我的病人':
+      uni.navigateTo({ url: '/pages/doctor/index/my-patients' })
+      break
+    case '药品管理':
+      uni.navigateTo({ url: '/pages/doctor/manage/medicine' })
+      break
+    case '健康资讯管理':
+      uni.navigateTo({ url: '/pages/doctor/manage/news' })
+      break
+    case '危急值管理':
+      uni.navigateTo({ url: '/pages/doctor/manage/critical-values' })
+      break
+    default:
+      uni.showToast({ title: '功能正在开发中', icon: 'none' })
   }
   }
 }
 }
 
 
@@ -483,11 +515,11 @@ const formatActivityDescription = (activity: any) => {
   if (activity.friendlyDescription) {
   if (activity.friendlyDescription) {
     return activity.friendlyDescription
     return activity.friendlyDescription
   }
   }
-  
+
   // 根据 activityDescription 内容进一步细化描述
   // 根据 activityDescription 内容进一步细化描述
   const description = activity.activityDescription || ''
   const description = activity.activityDescription || ''
   let baseDescription = ''
   let baseDescription = ''
-  
+
   // 根据活动类型生成基础描述
   // 根据活动类型生成基础描述
   switch (activity.activityType) {
   switch (activity.activityType) {
     case 'BLOOD_GLUCOSE_UPLOAD':
     case 'BLOOD_GLUCOSE_UPLOAD':
@@ -530,11 +562,11 @@ const formatActivityDescription = (activity: any) => {
       break
       break
     default:
     default:
       // 如果没有匹配的类型,尝试使用 activityDescription 或返回默认值
       // 如果没有匹配的类型,尝试使用 activityDescription 或返回默认值
-      baseDescription = description && !description.includes('Controller') 
-        ? description 
+      baseDescription = description && !description.includes('Controller')
+        ? description
         : '执行了操作'
         : '执行了操作'
   }
   }
-  
+
   return baseDescription
   return baseDescription
 }
 }
 
 
@@ -717,6 +749,14 @@ const formatActivityDescription = (activity: any) => {
   background-color: #ffa502;
   background-color: #ffa502;
 }
 }
 
 
+.green .item-line {
+  background-color: #2ecc71;
+}
+
+.purple .item-line {
+  background-color: #9b59b6;
+}
+
 .item-title {
 .item-title {
   font-size: 36rpx;
   font-size: 36rpx;
   font-weight: bold;
   font-weight: bold;
@@ -760,7 +800,7 @@ const formatActivityDescription = (activity: any) => {
   padding: 24rpx 28rpx;
   padding: 24rpx 28rpx;
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
-  background: linear-gradient(90deg, rgba(255,255,255,0.9), rgba(255,255,255,0.75));
+  background: linear-gradient(90deg, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.75));
   border-bottom: 1rpx solid #f3f4f6;
   border-bottom: 1rpx solid #f3f4f6;
 }
 }
 
 

+ 2 - 2
src/pages/doctor/manage/index.vue

@@ -3,11 +3,11 @@
   <view class="content">
   <view class="content">
     <view class="menu-card">
     <view class="menu-card">
       <view class="menu-list">
       <view class="menu-list">
-        <view class="menu-item" @click="onItemClick('药品信息管理')">
+        <!-- <view class="menu-item" @click="onItemClick('药品信息管理')">
           <image src="/static/icons/remixicon/capsule-fill.svg" class="menu-icon" mode="widthFix" />
           <image src="/static/icons/remixicon/capsule-fill.svg" class="menu-icon" mode="widthFix" />
           <text class="menu-text">药品信息管理</text>
           <text class="menu-text">药品信息管理</text>
           <uni-icons class="menu-arrow" type="arrowright" size="20" color="#c0c0c0" />
           <uni-icons class="menu-arrow" type="arrowright" size="20" color="#c0c0c0" />
-        </view>
+        </view> -->
         <view class="menu-item" @click="onItemClick('健康资讯管理')">
         <view class="menu-item" @click="onItemClick('健康资讯管理')">
           <image src="/static/icons/remixicon/article-line.svg" class="menu-icon" mode="widthFix" />
           <image src="/static/icons/remixicon/article-line.svg" class="menu-icon" mode="widthFix" />
           <text class="menu-text">健康资讯管理</text>
           <text class="menu-text">健康资讯管理</text>

+ 2 - 86
src/pages/public/index/index.vue

@@ -1,43 +1,17 @@
 <template>
 <template>
   <CustomNav title="首页" leftType="none" />
   <CustomNav title="首页" leftType="none" />
   <view class="content">
   <view class="content">
-    <!-- 原始页面已移至此文件,保留以备参考 -->
-    <swiper class="banner-swiper" :indicator-dots="true" :autoplay="true" :interval="3000" :circular="true">
-      <swiper-item v-for="(img, idx) in bannerImages" :key="idx">
-        <image :src="img" class="banner-img" mode="aspectFill" />
-      </swiper-item>
-    </swiper>
-    <view class="card-list">
-      <view class="card" v-for="(card, idx) in cards" :key="idx">
-        <view class="card-title">{{ card.title }}</view>
-        <view class="card-desc">{{ card.desc }}</view>
-      </view>
-    </view>
+    
   </view>
   </view>
   <TabBar />
   <TabBar />
 </template>
 </template>
 
 
 <script setup lang="ts">
 <script setup lang="ts">
-import { ref } from 'vue'
 import { onShow } from '@dcloudio/uni-app'
 import { onShow } from '@dcloudio/uni-app'
 import CustomNav from '@/components/custom-nav.vue'
 import CustomNav from '@/components/custom-nav.vue'
 import TabBar from '@/components/tab-bar.vue'
 import TabBar from '@/components/tab-bar.vue'
 import { isLoggedIn as checkLogin, getRole } from '@/composables/useAuth'
 import { isLoggedIn as checkLogin, getRole } from '@/composables/useAuth'
 
 
-const title = ref('Hello')
-
-const bannerImages = [
-  '/static/carousel/BHFIIABBCDJII-5kCEkD6zh9.jpg',
-  '/static/carousel/BHFIIABBDGHEA-wtWLrLS75o.jpg',
-  '/static/carousel/BHFIIABBHJBAH-yDeckRiiQP.jpg'
-]
-
-const cards = [
-  { title: '健康档案', desc: '管理您的健康信息' },
-  { title: '慢病管理', desc: '查看慢病相关数据' },
-  { title: '医生预约', desc: '在线预约医生' },
-  { title: '用药提醒', desc: '设置用药提醒' }
-]
 
 
 onShow(() => {
 onShow(() => {
   try {
   try {
@@ -82,62 +56,4 @@ onShow(() => {
   height: calc(100vh - var(--status-bar-height) - 44px);
   height: calc(100vh - var(--status-bar-height) - 44px);
   background: #f7f8fa;
   background: #f7f8fa;
 }
 }
-
-.banner-swiper {
-  width: 670rpx;
-  max-width: 100vw;
-  height: 400rpx;
-  margin: 20rpx auto 30rpx auto;
-  border-radius: 16rpx;
-  overflow: hidden;
-  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.08);
-  background: #fff;
-}
-
-.banner-img {
-  width: 100%;
-  height: 100%;
-  display: block;
-}
-
-.card-list {
-  width: 90%;
-  display: flex;
-  flex-direction: column;
-  gap: 32rpx;
-  padding: 0 40rpx;
-  margin: 0 auto;
-}
-
-.card {
-  background: #fff;
-  border-radius: 16rpx;
-  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.06);
-  padding: 40rpx 32rpx;
-  box-sizing: border-box;
-  display: flex;
-  flex-direction: column;
-}
-
-.card-title {
-  font-size: 36rpx;
-  font-weight: bold;
-  color: #333;
-  margin-bottom: 16rpx;
-}
-
-.card-desc {
-  font-size: 28rpx;
-  color: #888;
-}
-
-.text-area {
-  display: flex;
-  justify-content: center;
-}
-
-.title {
-  font-size: 36rpx;
-  color: #8f8f94;
-}
-</style>
+</style>

+ 1 - 1
src/pages/public/login/index.vue

@@ -11,7 +11,7 @@
 
 
       <view class="role-section">
       <view class="role-section">
         <button class="role-btn" @click="onSelectRole(3)" :disabled="isLogging">患者</button>
         <button class="role-btn" @click="onSelectRole(3)" :disabled="isLogging">患者</button>
-        <button class="role-btn" @click="onSelectRole(4)" :disabled="isLogging">患者家属</button>
+        <button class="role-btn" @click="onSelectRole(4)" :disabled="isLogging">家属</button>
         <button class="role-btn" @click="onSelectRole(2)" :disabled="isLogging">医生</button>
         <button class="role-btn" @click="onSelectRole(2)" :disabled="isLogging">医生</button>
       </view>
       </view>