yxh
2026-09-15 9b47bfa2cc65963b487035772db15eccebab9b54
优化了科室选择页面布局
已修改3个文件
261 ■■■■■ 文件已修改
.env.prod 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/RoomBedSelect/src/RoomBedSelect.vue 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ecg/room/RoomLoginSelect.vue 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.prod
@@ -5,11 +5,13 @@
# 请求路径
VITE_BASE_URL='http://10.0.2.193'
# VITE_BASE_URL='http://localhost'
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
VITE_UPLOAD_TYPE=server
# 上传路径
VITE_UPLOAD_URL='http://10.0.2.193/admin-api/infra/file/upload'
# VITE_UPLOAD_URL='http://localhost/admin-api/infra/file/upload'
# 接口地址
VITE_API_URL=/admin-api
src/components/RoomBedSelect/src/RoomBedSelect.vue
@@ -1,9 +1,11 @@
<script lang="ts" setup>
import { RoomVO } from '@/api/ecg/room'
import { PropType } from "vue";
import { useCheckTypeStore } from "@/store/modules/checkType";
import { UserVO } from "@/store/modules/user";
import { getCheckTypeName } from "../../../utils/checkTypeFormatter";
// 动态 :src 不会被 Vite 自动处理,需要显式 import
import openImg from '@/assets/room/open.jpg'
import doctorImg from '@/assets/room/desk-doctor.jpg'
const emit = defineEmits(['event-haveseat', 'event-leaveseat', 'event-setcurseat'])
@@ -12,13 +14,9 @@
})
const props = defineProps({
  // defineProps({
  title: {
    type: Number,
    required: true
  },
  bedList: {
    type: Array as PropType<RoomVO[]>,
  // 一个床位一张卡片
  bed: {
    type: Object as PropType<RoomVO>,
    required: true
  },
  curBed: {
@@ -31,86 +29,129 @@
  }
})
const checkTypeStore = useCheckTypeStore();
// 该床位是否已由当前医生入座
const isMine = computed(() => props.bed.docId != null && props.bed.docId === props.curUser.id)
// 该床位是否就是当前会话使用中的工位
const isCurSeat = computed(
  () => props.bed.roomId === props.curBed.roomId && props.bed.bedNo === props.curBed.bedNo
)
const onHaveSeatclick = (newItem: RoomVO) => {
  emit('event-haveseat', newItem)
const onHaveSeatclick = (bed: RoomVO) => {
  emit('event-haveseat', bed)
}
const onLeaveSeatclick = (curItem: RoomVO) => {
  emit('event-leaveseat', curItem)
const onLeaveSeatclick = (bed: RoomVO) => {
  emit('event-leaveseat', bed)
}
const onSetCurSeatclick = (curItem: RoomVO) => {
  emit('event-setcurseat', curItem)
const onSetCurSeatclick = (bed: RoomVO) => {
  emit('event-setcurseat', bed)
}
/** 初始化 **/
onMounted(() => {
  console.info(props.bedList)
})
</script>
<template>
  <el-card style="width: 200px" shadow="hover">
    <template #header>{{ bedList[0].roomName }}</template>
    <div v-for="(bedItem, index) in bedList" :key="index">
      <div class="deskwarp">
  <el-card class="bed-card" shadow="hover" :body-style="{ padding: '10px' }">
    <template #header>
      <div class="bed-card__title">{{ bed.roomName }}</div>
    </template>
        <div v-for="(checkType, subIndex) in bedItem.checkTypes" :key="subIndex">
          {{ getCheckTypeName(checkType) }}
        </div>
        <div>
          {{ bedItem.opType === 1 ? "领用" : "" }}
          {{ bedItem.opType === 2 ? "安装" : "" }}
        </div>
    <img
      class="bed-card__img"
      :src="bed.docId === null ? openImg : doctorImg"
      :alt="bed.docId === null ? '无医生' : '有医生'"
    />
        <img v-if="bedItem.docId === null" src="@/assets/room/open.jpg" style="width: 100%" alt="无医生" />
        <img v-else src="@/assets/room/desk-doctor.jpg" style="width: 100%" alt="有医生" />
        <div>{{ bedItem.bedNo }} {{ bedItem.docName }} {{ bedItem.status === 30 ? "-暂停" : "" }}</div>
        <el-button v-if="bedItem.docId == null || bedItem.docId != curUser.id" @click="onHaveSeatclick(bedItem)">
          入座
        </el-button>
        <div v-if="bedItem.docId === curUser.id">
          <el-button @click=onLeaveSeatclick(bedItem)>
            离座
          </el-button>
          <span v-if="bedItem.roomId === curBed.roomId && bedItem.bedNo === curBed.bedNo">
            当前
          </span>
          <el-button v-else @click=onSetCurSeatclick(bedItem)>
            设为当前
          </el-button>
        </div>
        <el-divider />
      </div>
    <div class="bed-card__label">
      {{ bed.bedNo }} {{ bed.docName }} {{ bed.status === 30 ? "-暂停" : "" }}
    </div>
    <div class="bed-card__meta">
      <span v-for="(checkType, subIndex) in bed.checkTypes" :key="subIndex">
        {{ getCheckTypeName(checkType) }}
      </span>
      <span v-if="bed.opType === 1">领用</span>
      <span v-if="bed.opType === 2">安装</span>
    </div>
    <div class="bed-card__actions">
      <el-button v-if="!isMine" @click="onHaveSeatclick(bed)"> 入座 </el-button>
      <template v-else>
        <el-button @click="onLeaveSeatclick(bed)"> 离座 </el-button>
        <span v-if="isCurSeat" class="bed-card__current">当前</span>
        <el-button v-else @click="onSetCurSeatclick(bed)"> 设为当前 </el-button>
      </template>
    </div>
  </el-card>
</template>
<style scoped lang="scss">
.card-title {
  font-size: 14px;
  font-weight: 600;
  &::before {
    position: relative;
    top: 8px;
    left: -5px;
    display: inline-block;
    width: 3px;
    height: 14px;
    //background-color: #105cfb;
    background: var(--el-color-primary);
    border-radius: 5px;
    content: '';
    transform: translateY(-50%);
  }
}
.deskwarp {
.bed-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  /*height: 260px;*/
  height: 100%;
  overflow: hidden;
  // 卡片头(诊室名)紧凑化
  :deep(.el-card__header) {
    flex: none;
    padding: 6px 10px;
    text-align: center;
  }
  // 卡片体:纵向排列、水平居中
  :deep(.el-card__body) {
    display: flex;
    flex: 1;
    flex-direction: column;
    align-items: center;
    gap: 4px;
  }
  &__title {
    font-size: 16px;
    font-weight: 600;
    line-height: 1.2;
  }
  // 图片固定小尺寸,不再随卡片宽度放大
  &__img {
    flex: none;
    width: 80px;
    height: 64px;
    object-fit: contain;
  }
  &__label {
    font-size: 15px;
    font-weight: 600;
    line-height: 1.3;
    // 列宽固定,允许换行避免溢出卡片
    text-align: center;
  }
  &__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0 5px;
    justify-content: center;
    font-size: 14px;
    line-height: 1.3;
    color: var(--el-text-color-secondary);
    text-align: center;
  }
  &__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    align-items: center;
    justify-content: center;
    margin-top: 3px;
  }
  &__current {
    font-size: 15px;
    font-weight: 600;
    color: var(--el-color-primary);
  }
}
</style>
src/views/ecg/room/RoomLoginSelect.vue
@@ -1,14 +1,16 @@
<template>
  <div style="display: flex; flex-direction: column; align-items: center; height: 100vh; overflow-y: auto;">
    <div style="display: flex; flex-wrap: wrap; justify-content: center; margin-bottom: 20px">
      <div class=roomwrap v-for="(value, key) in bedMap" :key="key">
        <RoomBedSelect :title="key" :bedList="value" :curBed="curSel" :curUser='curUser' @event-haveseat="haveSeat" @event-leaveseat="leaveSeat" @event-setcurseat="setCurSeat"/>
  <div class="room-select">
    <div class="room-select__scroll">
      <div class="room-select__list">
        <div class="room-select__item" v-for="(bed, index) in bedList" :key="`${bed.roomId}-${bed.bedNo}-${index}`">
          <RoomBedSelect :bed="bed" :curBed="curSel" :curUser='curUser' @event-haveseat="haveSeat" @event-leaveseat="leaveSeat" @event-setcurseat="setCurSeat"/>
        </div>
        <el-empty v-if="isEmptyOpeningBed" class="room-select__empty" description="工位没有开放"/>
      </div>
      <el-empty v-if="isEmptyOpeningBed" description="工位没有开放"/>
    </div>
    <div>
      <el-button @click="confirmCurSel">确认</el-button>
      <el-button @click="resetPage">重置</el-button>
    <div class="room-select__actions">
      <el-button type="primary" size="large" @click="confirmCurSel">确认</el-button>
      <el-button size="large" @click="resetPage">重置</el-button>
    </div>
  </div>
</template>
@@ -44,6 +46,22 @@
  ip: "",
  checkTypes: [],
  opType: 0
})
// 一个床位一个卡片:把 {诊室名: 床位[]} 拍平成床位列表
const bedList = computed<RoomVO[]>(() => {
  const list: RoomVO[] = []
  const map = bedMap.value
  if (!map) {
    return list
  }
  for (const key in map) {
    const beds = map[key] as RoomVO[]
    if (beds && beds.length > 0) {
      list.push(...beds)
    }
  }
  return list
})
/** 初始化 **/
@@ -289,7 +307,43 @@
</script>
<style scoped lang="scss">
.roomwrap {
  margin-right: 20px;
// 床位多时全部压缩在一屏内显示,不出现页面滚动条
.room-select {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  height: 100vh;
  padding: 15px;
  overflow: hidden;
  // 高度随卡片数量自适应;卡片多到装不下时才内部滚动(页面本身始终不滚动)
  &__scroll {
    flex: 0 1 auto;
    min-height: 0;
    overflow-y: auto;
  }
  &__list {
    display: grid;
    // 固定列宽:卡片不会被拉伸变形,从左到右、从上往下排列
    grid-template-columns: repeat(auto-fit, 188px);
    justify-content: center;
    gap: 12px;
  }
  &__item {
    min-width: 0;
  }
  // 空状态跨满整行,避免被挤到单独一列里
  &__empty {
    grid-column: 1 / -1;
  }
  &__actions {
    flex: none;
    padding-top: 12px;
    text-align: center;
  }
}
</style>