gugu 18 órája
szülő
commit
3a51f582de

+ 166 - 0
src/main/java/org/example/controller/PatientController.java

@@ -0,0 +1,166 @@
+package org.example.controller;
+
+import org.example.entity.Patient;
+import org.example.service.PatientService;
+import org.example.util.PatientDataConverter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/patients")
+public class PatientController {
+    
+    @Autowired
+    private PatientService patientService;
+    
+    /**
+     * 获取所有患者列表
+     * @return 患者列表
+     */
+    @GetMapping
+    public List<Patient> getAllPatients(
+        @RequestParam(required = false) String name,
+        @RequestParam(required = false) String department,
+        @RequestParam(required = false) String ward,
+        @RequestParam(required = false) String roomNo,
+        @RequestParam(required = false) String bedNo,
+        @RequestParam(required = false) String inpatientNo,
+        @RequestParam(required = false) String nurseLevel,
+        @RequestParam(required = false) String status,
+        @RequestParam(required = false) String admissionDateTime
+    ) {
+        List<Patient> patients;
+        if (name != null || department != null || ward != null || roomNo != null || 
+            bedNo != null || inpatientNo != null || nurseLevel != null || 
+            status != null || admissionDateTime != null) {
+            // 如果有任何查询参数,则执行带条件的查询
+            patients = patientService.findWithConditions(name, department, ward, roomNo, bedNo, 
+                                                     inpatientNo, nurseLevel, status, admissionDateTime);
+        } else {
+            // 否则返回所有患者
+            patients = patientService.findAll();
+        }
+        // 转换患者数据中的代码为中文描述
+        return PatientDataConverter.convertPatientListData(patients);
+    }
+    
+    /**
+     * 获取所有不同的护理级别
+     * @return 护理级别列表
+     */
+    @GetMapping("/nurse-levels")
+    public List<String> getDistinctNurseLevels() {
+        List<String> nurseLevels = patientService.findDistinctNurseLevels();
+        // 将护理级别代码转换为中文描述
+        return nurseLevels.stream()
+                .map(PatientDataConverter::convertNurseLevel)
+                .distinct()
+                .collect(Collectors.toList());
+    }
+    
+    /**
+     * 获取所有不同的在院状态
+     * @return 在院状态列表
+     */
+    @GetMapping("/inpatient-statuses")
+    public List<String> getDistinctInpatientStatuses() {
+        List<String> inpatientStatuses = patientService.findDistinctInpatientStatuses();
+        // 将在院状态代码转换为中文描述
+        return inpatientStatuses.stream()
+                .map(PatientDataConverter::convertInpatientStatus)
+                .distinct()
+                .collect(Collectors.toList());
+    }
+    
+    /**
+     * 根据住院号获取患者信息
+     * @param inpatientNo 住院号
+     * @return 患者信息
+     */
+    @GetMapping("/{inpatientNo}")
+    public Map<String, Object> getPatientByInpatientNo(@PathVariable String inpatientNo) {
+        Map<String, Object> result = new HashMap<>();
+        try {
+            Patient patient = patientService.findByInpatientNo(inpatientNo);
+            if (patient != null) {
+                // 转换患者数据中的代码为中文描述
+                PatientDataConverter.convertPatientData(patient);
+                result.put("success", true);
+                result.put("data", patient);
+            } else {
+                result.put("success", false);
+                result.put("message", "患者不存在");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            result.put("success", false);
+            result.put("message", "获取患者信息失败: " + e.getMessage());
+        }
+        return result;
+    }
+    
+    /**
+     * 添加新患者
+     * @param patient 患者信息
+     * @return 操作结果
+     */
+    @PostMapping
+    public Map<String, Object> addPatient(@RequestBody Patient patient) {
+        Map<String, Object> result = new HashMap<>();
+        try {
+            patientService.addPatient(patient);
+            result.put("success", true);
+            result.put("message", "患者添加成功");
+        } catch (Exception e) {
+            e.printStackTrace();
+            result.put("success", false);
+            result.put("message", "患者添加失败: " + e.getMessage());
+        }
+        return result;
+    }
+    
+    /**
+     * 更新患者信息
+     * @param patient 患者信息
+     * @return 操作结果
+     */
+    @PutMapping
+    public Map<String, Object> updatePatient(@RequestBody Patient patient) {
+        Map<String, Object> result = new HashMap<>();
+        try {
+            patientService.updatePatient(patient);
+            result.put("success", true);
+            result.put("message", "患者信息更新成功");
+        } catch (Exception e) {
+            e.printStackTrace();
+            result.put("success", false);
+            result.put("message", "患者信息更新失败: " + e.getMessage());
+        }
+        return result;
+    }
+    
+    /**
+     * 删除患者
+     * @param inpatientNo 住院号
+     * @return 操作结果
+     */
+    @DeleteMapping("/{inpatientNo}")
+    public Map<String, Object> deletePatient(@PathVariable String inpatientNo) {
+        Map<String, Object> result = new HashMap<>();
+        try {
+            patientService.deletePatient(inpatientNo);
+            result.put("success", true);
+            result.put("message", "患者删除成功");
+        } catch (Exception e) {
+            e.printStackTrace();
+            result.put("success", false);
+            result.put("message", "患者删除失败: " + e.getMessage());
+        }
+        return result;
+    }
+}

+ 140 - 0
src/main/java/org/example/entity/Patient.java

@@ -0,0 +1,140 @@
+package org.example.entity;
+
+public class Patient {
+    private String admissionDateTime;  // 入院时间
+    private String inpatientNo;        // 住院号
+    private String name;               // 患者姓名
+    private String sex;                // 性别
+    private Integer age;               // 年龄
+    private String deptCode;           // 所属科室
+    private String wardCode;           // 所属病区
+    private String roomNo;             // 房间号
+    private String bedNo;              // 床位号
+    private String nurseLevel;         // 护理级别
+    private String inpatientStatus;    // 在院状态
+
+    // Constructors
+    public Patient() {}
+
+    public Patient(String admissionDateTime, String inpatientNo, String name, String sex, Integer age,
+                   String deptCode, String wardCode, String roomNo, String bedNo, String nurseLevel,
+                   String inpatientStatus) {
+        this.admissionDateTime = admissionDateTime;
+        this.inpatientNo = inpatientNo;
+        this.name = name;
+        this.sex = sex;
+        this.age = age;
+        this.deptCode = deptCode;
+        this.wardCode = wardCode;
+        this.roomNo = roomNo;
+        this.bedNo = bedNo;
+        this.nurseLevel = nurseLevel;
+        this.inpatientStatus = inpatientStatus;
+    }
+
+    // Getters and Setters
+    public String getAdmissionDateTime() {
+        return admissionDateTime;
+    }
+
+    public void setAdmissionDateTime(String admissionDateTime) {
+        this.admissionDateTime = admissionDateTime;
+    }
+
+    public String getInpatientNo() {
+        return inpatientNo;
+    }
+
+    public void setInpatientNo(String inpatientNo) {
+        this.inpatientNo = inpatientNo;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getSex() {
+        return sex;
+    }
+
+    public void setSex(String sex) {
+        this.sex = sex;
+    }
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
+
+    public String getDeptCode() {
+        return deptCode;
+    }
+
+    public void setDeptCode(String deptCode) {
+        this.deptCode = deptCode;
+    }
+
+    public String getWardCode() {
+        return wardCode;
+    }
+
+    public void setWardCode(String wardCode) {
+        this.wardCode = wardCode;
+    }
+
+    public String getRoomNo() {
+        return roomNo;
+    }
+
+    public void setRoomNo(String roomNo) {
+        this.roomNo = roomNo;
+    }
+
+    public String getBedNo() {
+        return bedNo;
+    }
+
+    public void setBedNo(String bedNo) {
+        this.bedNo = bedNo;
+    }
+
+    public String getNurseLevel() {
+        return nurseLevel;
+    }
+
+    public void setNurseLevel(String nurseLevel) {
+        this.nurseLevel = nurseLevel;
+    }
+
+    public String getInpatientStatus() {
+        return inpatientStatus;
+    }
+
+    public void setInpatientStatus(String inpatientStatus) {
+        this.inpatientStatus = inpatientStatus;
+    }
+
+    @Override
+    public String toString() {
+        return "Patient{" +
+                "admissionDateTime='" + admissionDateTime + '\'' +
+                ", inpatientNo='" + inpatientNo + '\'' +
+                ", name='" + name + '\'' +
+                ", sex='" + sex + '\'' +
+                ", age=" + age +
+                ", deptCode='" + deptCode + '\'' +
+                ", wardCode='" + wardCode + '\'' +
+                ", roomNo='" + roomNo + '\'' +
+                ", bedNo='" + bedNo + '\'' +
+                ", nurseLevel='" + nurseLevel + '\'' +
+                ", inpatientStatus='" + inpatientStatus + '\'' +
+                '}';
+    }
+}

+ 96 - 0
src/main/java/org/example/mapper/PatientMapper.java

@@ -0,0 +1,96 @@
+package org.example.mapper;
+
+import org.apache.ibatis.annotations.*;
+import org.example.entity.Patient;
+
+import java.util.List;
+
+@Mapper
+public interface PatientMapper {
+    
+    /**
+     * 查询所有患者
+     * @return 患者列表
+     */
+    @Select("SELECT admission_date_time AS admissionDateTime, inpatient_no AS inpatientNo, name, sex, age, " +
+            "dept_code AS deptCode, ward_code AS wardCode, room_no AS roomNo, bed_no AS bedNo, " +
+            "nurse_level AS nurseLevel, inpatient_status AS inpatientStatus FROM tb_hospital_patient")
+    List<Patient> findAll();
+    
+    /**
+     * 根据条件查询患者
+     * @return 患者列表
+     */
+    @Select({
+        "<script>",
+        "SELECT admission_date_time AS admissionDateTime, inpatient_no AS inpatientNo, name, sex, age, " +
+        "dept_code AS deptCode, ward_code AS wardCode, room_no AS roomNo, bed_no AS bedNo, " +
+        "nurse_level AS nurseLevel, inpatient_status AS inpatientStatus FROM tb_hospital_patient",
+        "WHERE 1=1",
+        "<if test='name != null and name != \"\"'> AND name LIKE CONCAT('%', #{name}, '%')</if>",
+        "<if test='department != null and department != \"\"'> AND dept_code = #{department}</if>",
+        "<if test='ward != null and ward != \"\"'> AND ward_code = #{ward}</if>",
+        "<if test='roomNo != null and roomNo != \"\"'> AND room_no = #{roomNo}</if>",
+        "<if test='bedNo != null and bedNo != \"\"'> AND bed_no = #{bedNo}</if>",
+        "<if test='inpatientNo != null and inpatientNo != \"\"'> AND inpatient_no = #{inpatientNo}</if>",
+        "<if test='nurseLevel != null and nurseLevel != \"\"'> AND nurse_level = #{nurseLevel}</if>",
+        "<if test='status != null and status != \"\"'> AND inpatient_status = #{status}</if>",
+        "<if test='admissionDateTime != null and admissionDateTime != \"\"'> AND admission_date_time LIKE CONCAT('%', #{admissionDateTime}, '%')</if>",
+        "</script>"
+    })
+    List<Patient> findWithConditions(@Param("name") String name, @Param("department") String department, 
+                                  @Param("ward") String ward, @Param("roomNo") String roomNo, 
+                                  @Param("bedNo") String bedNo, @Param("inpatientNo") String inpatientNo,
+                                  @Param("nurseLevel") String nurseLevel, @Param("status") String status,
+                                  @Param("admissionDateTime") String admissionDateTime);
+    
+    /**
+     * 查询所有不同的护理级别
+     * @return 护理级别列表
+     */
+    @Select("SELECT DISTINCT nurse_level FROM tb_hospital_patient WHERE nurse_level IS NOT NULL AND nurse_level != ''")
+    List<String> findDistinctNurseLevels();
+    
+    /**
+     * 查询所有不同的在院状态
+     * @return 在院状态列表
+     */
+    @Select("SELECT DISTINCT inpatient_status FROM tb_hospital_patient WHERE inpatient_status IS NOT NULL AND inpatient_status != ''")
+    List<String> findDistinctInpatientStatuses();
+    
+    /**
+     * 根据住院号查询患者
+     * @param inpatientNo 住院号
+     * @return 患者信息
+     */
+    @Select("SELECT admission_date_time AS admissionDateTime, inpatient_no AS inpatientNo, name, sex, age, " +
+            "dept_code AS deptCode, ward_code AS wardCode, room_no AS roomNo, bed_no AS bedNo, " +
+            "nurse_level AS nurseLevel, inpatient_status AS inpatientStatus FROM tb_hospital_patient WHERE inpatient_no = #{inpatientNo}")
+    Patient findByInpatientNo(String inpatientNo);
+    
+    /**
+     * 插入新患者
+     * @param patient 患者信息
+     */
+    @Insert("INSERT INTO tb_hospital_patient(admission_date_time, inpatient_no, name, sex, age, " +
+            "dept_code, ward_code, room_no, bed_no, nurse_level, inpatient_status) " +
+            "VALUES(#{admissionDateTime}, #{inpatientNo}, #{name}, #{sex}, #{age}, " +
+            "#{deptCode}, #{wardCode}, #{roomNo}, #{bedNo}, #{nurseLevel}, #{inpatientStatus})")
+    void insert(Patient patient);
+    
+    /**
+     * 更新患者信息
+     * @param patient 患者信息
+     */
+    @Update("UPDATE tb_hospital_patient SET admission_date_time=#{admissionDateTime}, name=#{name}, sex=#{sex}, age=#{age}, " +
+            "dept_code=#{deptCode}, ward_code=#{wardCode}, room_no=#{roomNo}, bed_no=#{bedNo}, " +
+            "nurse_level=#{nurseLevel}, inpatient_status=#{inpatientStatus} WHERE inpatient_no=#{inpatientNo}")
+    void update(Patient patient);
+    
+    /**
+     * 根据住院号删除患者
+     * @param inpatientNo 住院号
+     */
+    @Delete("DELETE FROM tb_hospital_patient WHERE inpatient_no = #{inpatientNo}")
+    void deleteByInpatientNo(String inpatientNo);
+}

+ 96 - 0
src/main/java/org/example/service/PatientService.java

@@ -0,0 +1,96 @@
+package org.example.service;
+
+import org.example.entity.Patient;
+import org.example.mapper.PatientMapper;
+import org.example.util.PatientDataConverter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class PatientService {
+    
+    @Autowired
+    private PatientMapper patientMapper;
+    
+    /**
+     * 获取所有患者列表
+     * @return 患者列表
+     */
+    public List<Patient> findAll() {
+        return patientMapper.findAll();
+    }
+    
+    /**
+     * 获取所有不同的护理级别
+     * @return 护理级别列表
+     */
+    public List<String> findDistinctNurseLevels() {
+        return patientMapper.findDistinctNurseLevels();
+    }
+    
+    /**
+     * 获取所有不同的在院状态
+     * @return 在院状态列表
+     */
+    public List<String> findDistinctInpatientStatuses() {
+        return patientMapper.findDistinctInpatientStatuses();
+    }
+    
+    /**
+     * 根据条件查询患者
+     * @return 患者列表
+     */
+    public List<Patient> findWithConditions(String name, String department, String ward, 
+                                          String roomNo, String bedNo, String inpatientNo,
+                                          String nurseLevel, String status, String admissionDateTime) {
+        // 如果护理级别是中文描述,则转换为代码再查询
+        String nurseLevelCode = null;
+        if (nurseLevel != null && !nurseLevel.isEmpty()) {
+            nurseLevelCode = PatientDataConverter.convertNurseLevelToCode(nurseLevel);
+        }
+        
+        // 如果在院状态是中文描述,则转换为代码再查询
+        String statusCode = null;
+        if (status != null && !status.isEmpty()) {
+            statusCode = PatientDataConverter.convertInpatientStatusToCode(status);
+        }
+        
+        return patientMapper.findWithConditions(name, department, ward, roomNo, bedNo, 
+                                              inpatientNo, nurseLevelCode, statusCode, admissionDateTime);
+    }
+    
+    /**
+     * 根据住院号查询患者
+     * @param inpatientNo 住院号
+     * @return 患者信息
+     */
+    public Patient findByInpatientNo(String inpatientNo) {
+        return patientMapper.findByInpatientNo(inpatientNo);
+    }
+    
+    /**
+     * 添加新患者
+     * @param patient 患者信息
+     */
+    public void addPatient(Patient patient) {
+        patientMapper.insert(patient);
+    }
+    
+    /**
+     * 更新患者信息
+     * @param patient 患者信息
+     */
+    public void updatePatient(Patient patient) {
+        patientMapper.update(patient);
+    }
+    
+    /**
+     * 删除患者
+     * @param inpatientNo 住院号
+     */
+    public void deletePatient(String inpatientNo) {
+        patientMapper.deleteByInpatientNo(inpatientNo);
+    }
+}

+ 166 - 0
src/main/java/org/example/util/PatientDataConverter.java

@@ -0,0 +1,166 @@
+package org.example.util;
+
+import org.example.entity.Patient;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.stream.Collectors;
+
+/**
+ * 患者数据转换工具类
+ * 用于将患者数据中的代码转换为可读的中文描述
+ */
+public class PatientDataConverter {
+    
+    // 护理级别代码到中文的映射
+    private static final Map<String, String> NURSE_LEVEL_MAP = new HashMap<>();
+    // 中文到护理级别代码的映射
+    private static final Map<String, String> NURSE_LEVEL_CODE_MAP = new HashMap<>();
+    
+    // 在院状态代码到中文的映射
+    private static final Map<String, String> INPATIENT_STATUS_MAP = new HashMap<>();
+    // 中文到在院状态代码的映射
+    private static final Map<String, String> INPATIENT_STATUS_CODE_MAP = new HashMap<>();
+    
+    static {
+        NURSE_LEVEL_MAP.put("0", "特级护理");
+        NURSE_LEVEL_MAP.put("1", "一级护理");
+        NURSE_LEVEL_MAP.put("2", "二级护理");
+        NURSE_LEVEL_MAP.put("3", "三级护理");
+        NURSE_LEVEL_MAP.put("-1", "未设置");
+        
+        // 建立反向映射
+        NURSE_LEVEL_CODE_MAP.put("特级护理", "0");
+        NURSE_LEVEL_CODE_MAP.put("一级护理", "1");
+        NURSE_LEVEL_CODE_MAP.put("二级护理", "2");
+        NURSE_LEVEL_CODE_MAP.put("三级护理", "3");
+        NURSE_LEVEL_CODE_MAP.put("未设置", "-1");
+        
+        INPATIENT_STATUS_MAP.put("1", "入院");
+        INPATIENT_STATUS_MAP.put("2", "已入科");
+        INPATIENT_STATUS_MAP.put("3", "待入科");
+        INPATIENT_STATUS_MAP.put("4", "已出院");
+        INPATIENT_STATUS_MAP.put("-1", "未设置");
+        
+        // 建立反向映射
+        INPATIENT_STATUS_CODE_MAP.put("入院", "1");
+        INPATIENT_STATUS_CODE_MAP.put("已入科", "2");
+        INPATIENT_STATUS_CODE_MAP.put("待入科", "3");
+        INPATIENT_STATUS_CODE_MAP.put("已出院", "4");
+        INPATIENT_STATUS_CODE_MAP.put("未设置", "-1");
+    }
+    
+    /**
+     * 转换单个患者数据
+     * @param patient 患者对象
+     * @return 转换后的患者对象
+     */
+    public static Patient convertPatientData(Patient patient) {
+        if (patient == null) {
+            return null;
+        }
+        
+        // 转换护理级别
+        patient.setNurseLevel(convertNurseLevel(patient.getNurseLevel()));
+        
+        // 转换在院状态
+        patient.setInpatientStatus(convertInpatientStatus(patient.getInpatientStatus()));
+        
+        return patient;
+    }
+    
+    /**
+     * 转换患者列表数据
+     * @param patients 患者列表
+     * @return 转换后的患者列表
+     */
+    public static List<Patient> convertPatientListData(List<Patient> patients) {
+        if (patients == null) {
+            return null;
+        }
+        
+        return patients.stream()
+                .map(PatientDataConverter::convertPatientData)
+                .collect(Collectors.toList());
+    }
+    
+    /**
+     * 转换护理级别代码为中文描述
+     * @param nurseLevelCode 护理级别代码
+     * @return 中文描述
+     */
+    public static String convertNurseLevel(String nurseLevelCode) {
+        if (nurseLevelCode == null || nurseLevelCode.isEmpty()) {
+            return nurseLevelCode;
+        }
+        
+        // 根据实际数据字典进行映射
+        String converted = NURSE_LEVEL_MAP.get(nurseLevelCode);
+        if (converted != null) {
+            return converted;
+        }
+        
+        // 如果已经是中文描述,则直接返回
+        return nurseLevelCode;
+    }
+    
+    /**
+     * 将中文描述转换回护理级别代码
+     * @param nurseLevelDesc 中文描述
+     * @return 护理级别代码
+     */
+    public static String convertNurseLevelToCode(String nurseLevelDesc) {
+        if (nurseLevelDesc == null || nurseLevelDesc.isEmpty()) {
+            return nurseLevelDesc;
+        }
+        
+        // 根据实际数据字典进行映射
+        String converted = NURSE_LEVEL_CODE_MAP.get(nurseLevelDesc);
+        if (converted != null) {
+            return converted;
+        }
+        
+        // 如果已经是代码,则直接返回
+        return nurseLevelDesc;
+    }
+    
+    /**
+     * 转换在院状态代码为中文描述
+     * @param statusCode 在院状态代码
+     * @return 中文描述
+     */
+    public static String convertInpatientStatus(String statusCode) {
+        if (statusCode == null || statusCode.isEmpty()) {
+            return statusCode;
+        }
+        
+        // 根据实际数据字典进行映射
+        String converted = INPATIENT_STATUS_MAP.get(statusCode);
+        if (converted != null) {
+            return converted;
+        }
+        
+        // 如果已经是中文描述,则直接返回
+        return statusCode;
+    }
+    
+    /**
+     * 将中文描述转换回在院状态代码
+     * @param statusDesc 中文描述
+     * @return 在院状态代码
+     */
+    public static String convertInpatientStatusToCode(String statusDesc) {
+        if (statusDesc == null || statusDesc.isEmpty()) {
+            return statusDesc;
+        }
+        
+        // 根据实际数据字典进行映射
+        String converted = INPATIENT_STATUS_CODE_MAP.get(statusDesc);
+        if (converted != null) {
+            return converted;
+        }
+        
+        // 如果已经是代码,则直接返回
+        return statusDesc;
+    }
+}

+ 747 - 113
src/main/resources/static/home.html

@@ -276,11 +276,6 @@
                         <li><a href="#" onclick="loadContent('wardManagement')">病区管理</a></li>
                         <li><a href="#" onclick="loadContent('roomManagement')">病房管理</a></li>
                         <li><a href="#" onclick="loadContent('bedManagement')">床位管理</a></li>
-                    </ul>
-                </li>
-                <li class="menu-item">
-                    <a href="#" onclick="toggleSubmenu('medicalSubmenu')">👨‍⚕️ 医护管理</a>
-                    <ul class="submenu" id="medicalSubmenu">
                         <li><a href="#" onclick="loadContent('patientManagement')">患者管理</a></li>
                     </ul>
                 </li>
@@ -322,12 +317,6 @@
                             <p>查看和管理院区相关信息</p>
                         </div>
                         
-                        <div class="card" onclick="loadContent('medicalStaff')">
-                            <div class="card-icon">👨‍⚕️</div>
-                            <h3>医护人员</h3>
-                            <p>管理医生和护士信息</p>
-                        </div>
-                        
                         <div class="card" onclick="loadContent('patientManagement')">
                             <div class="card-icon">👤</div>
                             <h3>患者信息</h3>
@@ -786,6 +775,170 @@
                     }, 0);
                     break;
                     
+                case 'patientManagement':
+                    pageTitle.textContent = '患者管理';
+                    breadcrumb.textContent = '首页 > 院区信息管理 > 患者管理';
+                    mainContent.innerHTML = `
+                        <div style="background: white; padding: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
+                            <div style="margin-bottom: 15px;">
+                                <!-- 第一行查询条件 -->
+                                <div style="display: flex; flex-wrap: wrap; gap: 20px; margin-bottom: 15px; align-items: center;">
+                                    <div style="display: flex; align-items: center;">
+                                        <label style="white-space: nowrap; margin-right: 10px;">患者姓名:</label>
+                                        <input type="text" id="patientName" placeholder="请输入患者姓名(模糊查询)" style="padding: 6px; border: 1px solid #ddd; border-radius: 4px; width: 100px;">
+                                    </div>
+                                    <div style="display: flex; align-items: center;">
+                                        <label style="white-space: nowrap; margin-right: 10px;">所属科室:</label>
+                                        <select id="patientDepartment" style="padding: 6px; border: 1px solid #ddd; border-radius: 4px; width: 100px;">
+                                            <option value="">全部科室</option>
+                                        </select>
+                                    </div>
+                                    <div style="display: flex; align-items: center;">
+                                        <label style="white-space: nowrap; margin-right: 10px;">所属病区:</label>
+                                        <select id="patientWard" style="padding: 6px; border: 1px solid #ddd; border-radius: 4px; width: 100px;">
+                                            <option value="">全部病区</option>
+                                        </select>
+                                    </div>
+                                    <div style="display: flex; align-items: center;">
+                                        <label style="white-space: nowrap; margin-right: 10px;">住院号:</label>
+                                        <select id="patientInpatientNo" style="padding: 6px; border: 1px solid #ddd; border-radius: 4px; width: 100px;">
+                                            <option value="">全部</option>
+                                        </select>
+                                    </div>
+                                    <div style="display: flex; align-items: center;">
+                                        <label style="white-space: nowrap; margin-right: 10px;">房间号:</label>
+                                        <select id="patientRoomNo" style="padding: 6px; border: 1px solid #ddd; border-radius: 4px; width: 80px;">
+                                            <option value="">全部</option>
+                                        </select>
+                                    </div>
+                                </div>
+
+                                <!-- 第二行查询条件 -->
+                                <div style="display: flex; flex-wrap: wrap; gap: 20px; margin-bottom: 15px; align-items: center;">
+                                    <div style="display: flex; align-items: center;">
+                                        <label style="white-space: nowrap; margin-right: 10px;">床位号:</label>
+                                        <select id="patientBedNo" style="padding: 6px; border: 1px solid #ddd; border-radius: 4px; width: 80px;">
+                                            <option value="">全部</option>
+                                        </select>
+                                    </div>
+                                    <div style="display: flex; align-items: center;">
+                                        <label style="white-space: nowrap; margin-right: 10px;">护理级别:</label>
+                                        <select id="patientNurseLevel" style="padding: 6px; border: 1px solid #ddd; border-radius: 4px; width: 100px;">
+                                            <option value="">全部级别</option>
+                                        </select>
+                                    </div>
+                                    <div style="display: flex; align-items: center;">
+                                        <label style="white-space: nowrap; margin-right: 10px;">在院状态:</label>
+                                        <select id="patientStatus" style="padding: 6px; border: 1px solid #ddd; border-radius: 4px; width: 100px;">
+                                            <option value="">全部状态</option>
+                                        </select>
+                                    </div>
+                                    <div style="display: flex; align-items: center;">
+                                        <label style="white-space: nowrap; margin-right: 10px;">入院时间:</label>
+                                        <input type="date" id="patientAdmissionDate" style="padding: 6px; border: 1px solid #ddd; border-radius: 4px; width: 140px;">
+                                    </div>
+                                    <div style="display: flex;">
+                                        <button class="btn btn-primary" onclick="searchPatients()" style="padding: 6px 12px; margin-right: 5px;">查询</button>
+                                        <button class="btn btn-secondary" onclick="clearPatientSearch()" style="padding: 6px 12px;">重置</button>
+                                    </div>
+                                </div>
+                            </div>
+                            <table class="data-table" id="patientTable">
+                                <thead>
+                                    <tr>
+                                        <th>入院时间</th>
+                                        <th>住院号</th>
+                                        <th>患者姓名</th>
+                                        <th>性别</th>
+                                        <th>年龄</th>
+                                        <th>所属科室</th>
+                                        <th>所属病区</th>
+                                        <th>房间号</th>
+                                        <th>床位号</th>
+                                        <th>护理级别</th>
+                                        <th>在院状态</th>
+                                        <th>操作</th>
+                                    </tr>
+                                </thead>
+                                <tbody id="patientTableBody">
+                                    <!-- 数据将通过JS动态加载 -->
+                                </tbody>
+                            </table>
+                        </div>
+                        
+                        <!-- 患者详情模态框 -->
+                        <div id="patientModal" style="display:none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.4); overflow: auto; padding: 50px 0;">
+                            <div style="background-color: #fff; margin: 0 auto; padding: 0; border: 1px solid #888; width: 80%; max-width: 600px; border-radius: 5px; max-height: 80%; display: flex; flex-direction: column;">
+                                <div style="padding: 20px; border-bottom: 1px solid #eee;">
+                                    <h2 style="margin-top: 0;">患者详情</h2>
+                                </div>
+                                <div style="overflow-y: auto; flex: 1; padding: 15px;">
+                                    <div class="form-group">
+                                        <label>入院时间:</label>
+                                        <input type="text" id="modalAdmissionTime" readonly style="width: 100%; padding: 6px;">
+                                    </div>
+                                    <div class="form-group">
+                                        <label>住院号:</label>
+                                        <input type="text" id="modalInpatientNo" readonly style="width: 100%; padding: 6px;">
+                                    </div>
+                                    <div class="form-group">
+                                        <label>患者姓名:</label>
+                                        <input type="text" id="modalName" readonly style="width: 100%; padding: 6px;">
+                                    </div>
+                                    <div class="form-group">
+                                        <label>性别:</label>
+                                        <input type="text" id="modalSex" readonly style="width: 100%; padding: 6px;">
+                                    </div>
+                                    <div class="form-group">
+                                        <label>年龄:</label>
+                                        <input type="text" id="modalAge" readonly style="width: 100%; padding: 6px;">
+                                    </div>
+                                    <div class="form-group">
+                                        <label>所属科室:</label>
+                                        <input type="text" id="modalDept" readonly style="width: 100%; padding: 6px;">
+                                    </div>
+                                    <div class="form-group">
+                                        <label>所属病区:</label>
+                                        <input type="text" id="modalWard" readonly style="width: 100%; padding: 6px;">
+                                    </div>
+                                    <div class="form-group">
+                                        <label>房间号:</label>
+                                        <input type="text" id="modalRoomNo" readonly style="width: 100%; padding: 6px;">
+                                    </div>
+                                    <div class="form-group">
+                                        <label>床位号:</label>
+                                        <input type="text" id="modalBedNo" readonly style="width: 100%; padding: 6px;">
+                                    </div>
+                                    <div class="form-group">
+                                        <label>护理级别:</label>
+                                        <input type="text" id="modalNurseLevel" readonly style="width: 100%; padding: 6px;">
+                                    </div>
+                                    <div class="form-group">
+                                        <label>在院状态:</label>
+                                        <input type="text" id="modalInpatientStatus" readonly style="width: 100%; padding: 6px;">
+                                    </div>
+                                </div>
+                                <div style="padding: 20px; border-top: 1px solid #eee; text-align: right;">
+                                    <button class="btn btn-secondary" onclick="closePatientModal()">关闭</button>
+                                </div>
+                            </div>
+                        </div>
+                    `;
+                    // 使用setTimeout确保DOM元素完全加载后再加载数据
+                    setTimeout(function() {
+                        // 加载科室下拉框数据
+                        loadPatientDepartmentOptions();
+                        // 加载病区下拉框数据
+                        loadPatientWardOptions();
+                        // 加载患者数据
+                        loadPatientData();
+                        // 确保页面首次加载时也能显示所有患者数据
+                        if (document.getElementById('patientTableBody').children.length === 0) {
+                            searchPatients();
+                        }
+                    }, 100);
+                    break;
+                    
                 case 'bedManagement':
                     pageTitle.textContent = '床位管理';
                     breadcrumb.textContent = '首页 > 院区信息管理 > 床位管理';
@@ -950,76 +1103,6 @@
                     break;
                     
                 case 'applicationManagement':
-                    pageTitle.textContent = '应用管理';
-                    breadcrumb.textContent = '首页 > 院区信息管理 > 应用管理';
-                    mainContent.innerHTML = `
-                        <div style="background: white; padding: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
-                            <table class="data-table">
-                                <thead>
-                                    <tr>
-                                        <th>应用代码</th>
-                                        <th>应用名称</th>
-                                        <th>应用类型</th>
-                                        <th>应用版本</th>
-                                        <th>应用描述</th>
-                                        <th>是否启用</th>
-                                        <th>备注</th>
-                                        <th>详情</th>
-                                    </tr>
-                                </thead>
-                                <tbody id="appTableBody">
-                                    <!-- 数据将通过JS动态加载 -->
-                                </tbody>
-                            </table>
-                        </div>
-                        
-                        <!-- 应用详情模态框 -->
-                        <div id="appModal" style="display:none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.4); overflow: auto; padding: 50px 0;">
-                            <div style="background-color: #fff; margin: 0 auto; padding: 0; border: 1px solid #888; width: 80%; max-width: 600px; border-radius: 5px; max-height: 80%; display: flex; flex-direction: column;">
-                                <div style="padding: 20px; border-bottom: 1px solid #eee;">
-                                    <h2 style="margin-top: 0;">应用详情</h2>
-                                </div>
-                                <div style="overflow-y: auto; flex: 1; padding: 10px;">
-                                    <div class="form-group" style="margin-bottom: 8px;">
-                                        <label style="margin-bottom: 2px;">应用代码:</label>
-                                        <input type="text" id="modalCode" readonly style="width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 4px;">
-                                    </div>
-                                    <div class="form-group" style="margin-bottom: 8px;">
-                                        <label style="margin-bottom: 2px;">应用名称:</label>
-                                        <input type="text" id="modalName" readonly style="width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 4px;">
-                                    </div>
-                                    <div class="form-group" style="margin-bottom: 8px;">
-                                        <label style="margin-bottom: 2px;">应用类型:</label>
-                                        <input type="text" id="modalType" readonly style="width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 4px;">
-                                    </div>
-                                    <div class="form-group" style="margin-bottom: 8px;">
-                                        <label style="margin-bottom: 2px;">应用版本:</label>
-                                        <input type="text" id="modalVersion" readonly style="width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 4px;">
-                                    </div>
-                                    <div class="form-group" style="margin-bottom: 8px;">
-                                        <label style="margin-bottom: 2px;">应用描述:</label>
-                                        <textarea id="modalDescription" readonly style="width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 4px; height: 40px;"></textarea>
-                                    </div>
-                                    <div class="form-group" style="margin-bottom: 8px;">
-                                        <label style="margin-bottom: 2px;">是否启用:</label>
-                                        <input type="text" id="modalEnabled" readonly style="width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 4px;">
-                                    </div>
-                                    <div class="form-group" style="margin-bottom: 8px;">
-                                        <label style="margin-bottom: 2px;">备注:</label>
-                                        <textarea id="modalRemark" readonly style="width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 4px; height: 40px;"></textarea>
-                                    </div>
-                                </div>
-                                <div style="padding: 20px; border-top: 1px solid #eee; text-align: right;">
-                                    <button class="btn btn-secondary" onclick="closeAppModal()">关闭</button>
-                                </div>
-                            </div>
-                        </div>
-                    `;
-                    loadAppData();
-                    break;
-                    
-                case 'userManagement':
-                    pageTitle.textContent = '用户管理';
                     breadcrumb.textContent = '首页 > 院区信息管理 > 用户管理';
                     mainContent.innerHTML = `
                         <div style="background: white; padding: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
@@ -1251,42 +1334,33 @@
                     
                 case 'patientManagement':
                     pageTitle.textContent = '患者管理';
-                    breadcrumb.textContent = '首页 > 医护管理 > 患者管理';
+                    breadcrumb.textContent = '首页 > 院区信息管理 > 患者管理';
                     mainContent.innerHTML = `
                         <div style="background: white; padding: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
-                            <div style="margin-bottom: 20px;">
-                                <button class="btn btn-success" onclick="showAddPatientForm()">新增患者</button>
-                            </div>
                             <table class="data-table">
                                 <thead>
                                     <tr>
-                                        <th>患者编号</th>
-                                        <th>姓名</th>
+                                        <th>入院时间</th>
+                                        <th>住院号</th>
+                                        <th>患者姓名</th>
                                         <th>性别</th>
                                         <th>年龄</th>
-                                        <th>主治医生</th>
-                                        <th>所在病房</th>
+                                        <th>所属科室</th>
+                                        <th>所属病区</th>
+                                        <th>房间号</th>
+                                        <th>床位号</th>
+                                        <th>护理级别</th>
+                                        <th>在院状态</th>
                                         <th>操作</th>
                                     </tr>
                                 </thead>
                                 <tbody>
-                                    <tr>
-                                        <td>P001</td>
-                                        <td>张三</td>
-                                        <td>男</td>
-                                        <td>45</td>
-                                        <td>李医生</td>
-                                        <td>101病房</td>
-                                        <td>
-                                            <button class="btn btn-primary">详情</button>
-                                            <button class="btn btn-warning">编辑</button>
-                                            <button class="btn btn-danger"> discharge</button>
-                                        </td>
-                                    </tr>
+                                    <!-- 数据将通过JS动态加载 -->
                                 </tbody>
                             </table>
                         </div>
                     `;
+                    setTimeout(loadPatientData, 0);
                     break;
                     
                 case 'equipmentInfo':
@@ -1512,12 +1586,6 @@
                                 <p>查看和管理院区相关信息</p>
                             </div>
                             
-                            <div class="card" onclick="loadContent('medicalStaff')">
-                                <div class="card-icon">👨‍⚕️</div>
-                                <h3>医护人员</h3>
-                                <p>管理医生和护士信息</p>
-                            </div>
-                            
                             <div class="card" onclick="loadContent('patientManagement')">
                                 <div class="card-icon">👤</div>
                                 <h3>患者信息</h3>
@@ -1553,10 +1621,6 @@
                     // 展开院区信息管理子菜单
                     document.getElementById('hospitalSubmenu').classList.add('open');
                     break;
-                case 'patientManagement':
-                    menuItem = document.querySelector('#medicalSubmenu a[href="#"][onclick*="' + contentType + '"]');
-                    // 展开医护管理子菜单
-                    document.getElementById('medicalSubmenu').classList.add('open');
                     break;
                 case 'equipmentInfo':
                 case 'equipmentQuery':
@@ -1635,6 +1699,11 @@
                 loadBedData();
             }
             
+            // 页面加载完成后初始化患者管理数据
+            if (document.getElementById('patientTableBody')) {
+                loadPatientData();
+            }
+            
             // 退出登录
             document.getElementById('logoutBtn').addEventListener('click', function() {
                 fetch('/shixian/api/logout', {
@@ -2228,6 +2297,7 @@
                 const roomModal = document.getElementById('roomModal');
                 const roomCodeSettingModal = document.getElementById('roomCodeSettingModal');
                 const bedModal = document.getElementById('bedModal');
+                const patientModal = document.getElementById('patientModal');
                 
                 if (wardModal && wardModal.style.display === 'block') {
                     wardModal.style.display = 'none';
@@ -2241,10 +2311,33 @@
                     roomCodeSettingModal.style.display = 'none';
                 } else if (bedModal && bedModal.style.display === 'block') {
                     bedModal.style.display = 'none';
+                } else if (patientModal && patientModal.style.display === 'block') {
+                    patientModal.style.display = 'none';
                 }
             }
         });
         
+        // 点击弹窗外部关闭弹窗
+        window.onclick = function(event) {
+            const departmentModal = document.getElementById('departmentModal');
+            const wardModal = document.getElementById('wardModal');
+            const roomModal = document.getElementById('roomModal');
+            const bedModal = document.getElementById('bedModal');
+            const patientModal = document.getElementById('patientModal');
+            
+            if (event.target === departmentModal) {
+                departmentModal.style.display = 'none';
+            } else if (event.target === wardModal) {
+                wardModal.style.display = 'none';
+            } else if (event.target === roomModal) {
+                roomModal.style.display = 'none';
+            } else if (event.target === bedModal) {
+                bedModal.style.display = 'none';
+            } else if (event.target === patientModal) {
+                patientModal.style.display = 'none';
+            }
+        };
+        
         // 编辑床位
         function editBed(code) {
             alert('编辑床位: ' + code);
@@ -2308,6 +2401,363 @@
             });
         }
         
+        // 加载患者数据
+        function loadPatientData() {
+            // 并行加载患者数据、护理级别选项和在院状态选项
+            Promise.all([
+                fetch('/shixian/api/patients').then(response => response.json()),
+                fetch('/shixian/api/patients/nurse-levels').then(response => response.json()),
+                fetch('/shixian/api/patients/inpatient-statuses').then(response => response.json()),
+                fetch('/shixian/api/beds').then(response => response.json())
+            ])
+            .then(([patientData, nurseLevels, inpatientStatuses, bedData]) => {
+                // 填充患者表格
+                const tbody = document.getElementById('patientTableBody');
+                // 确保tbody元素存在再操作
+                if (!tbody) {
+                    console.error('找不到患者表格tbody元素');
+                    return;
+                }
+                
+                tbody.innerHTML = '';
+                
+                // 安全地更新下拉框
+                try {
+                    // 获取唯一的科室列表并更新下拉框
+                    const departments = [...new Set(patientData.map(patient => patient.deptCode).filter(dept => dept))];
+                    const departmentSelect = document.getElementById('patientDepartment');
+                    if (departmentSelect) {
+                        const currentDepartmentValue = departmentSelect.value;
+                        
+                        // 保留当前选项,只更新选项列表
+                        const defaultOption = departmentSelect.options[0];
+                        departmentSelect.innerHTML = '';
+                        departmentSelect.appendChild(defaultOption);
+                        
+                        departments.forEach(dept => {
+                            const option = document.createElement('option');
+                            option.value = dept;
+                            option.textContent = dept;
+                            departmentSelect.appendChild(option);
+                        });
+                        departmentSelect.value = currentDepartmentValue;
+                    }
+                    
+                    // 获取唯一的病区列表并更新下拉框
+                    const wards = [...new Set(patientData.map(patient => patient.wardCode).filter(ward => ward))];
+                    const wardSelect = document.getElementById('patientWard');
+                    if (wardSelect) {
+                        const currentWardValue = wardSelect.value;
+                        
+                        // 保留当前选项,只更新选项列表
+                        const defaultWardOption = wardSelect.options[0];
+                        wardSelect.innerHTML = '';
+                        wardSelect.appendChild(defaultWardOption);
+                        
+                        wards.forEach(ward => {
+                            const option = document.createElement('option');
+                            option.value = ward;
+                            option.textContent = ward;
+                            wardSelect.appendChild(option);
+                        });
+                        wardSelect.value = currentWardValue;
+                    }
+                    
+                    // 获取唯一的房间号列表并更新下拉框
+                    const roomNos = [...new Set(patientData.map(patient => patient.roomNo).filter(roomNo => roomNo))];
+                    const roomNoSelect = document.getElementById('patientRoomNo');
+                    if (roomNoSelect) {
+                        const currentRoomNoValue = roomNoSelect.value;
+                        
+                        // 保留当前选项,只更新选项列表
+                        const defaultRoomNoOption = roomNoSelect.options[0];
+                        roomNoSelect.innerHTML = '';
+                        roomNoSelect.appendChild(defaultRoomNoOption);
+                        
+                        roomNos.forEach(roomNo => {
+                            const option = document.createElement('option');
+                            option.value = roomNo;
+                            option.textContent = roomNo;
+                            roomNoSelect.appendChild(option);
+                        });
+                        roomNoSelect.value = currentRoomNoValue;
+                    }
+                    
+                    // 获取唯一的床位号列表并更新下拉框
+                    const bedNos = [...new Set(bedData.map(bed => bed.name).filter(bedNo => bedNo))];
+                    const bedNoSelect = document.getElementById('patientBedNo');
+                    if (bedNoSelect) {
+                        const currentBedNoValue = bedNoSelect.value;
+                        
+                        // 保留当前选项,只更新选项列表
+                        const defaultBedNoOption = bedNoSelect.options[0];
+                        bedNoSelect.innerHTML = '';
+                        bedNoSelect.appendChild(defaultBedNoOption);
+                        
+                        bedNos.forEach(bedNo => {
+                            const option = document.createElement('option');
+                            option.value = bedNo;
+                            option.textContent = bedNo;
+                            bedNoSelect.appendChild(option);
+                        });
+                        bedNoSelect.value = currentBedNoValue;
+                    }
+                    
+                    // 获取唯一的住院号列表并更新下拉框
+                    const inpatientNos = [...new Set(patientData.map(patient => patient.inpatientNo).filter(inpatientNo => inpatientNo))];
+                    const inpatientNoSelect = document.getElementById('patientInpatientNo');
+                    if (inpatientNoSelect) {
+                        const currentInpatientNoValue = inpatientNoSelect.value;
+                        
+                        // 保留当前选项,只更新选项列表
+                        const defaultInpatientNoOption = inpatientNoSelect.options[0];
+                        inpatientNoSelect.innerHTML = '';
+                        inpatientNoSelect.appendChild(defaultInpatientNoOption);
+                        
+                        inpatientNos.forEach(inpatientNo => {
+                            const option = document.createElement('option');
+                            option.value = inpatientNo;
+                            option.textContent = inpatientNo;
+                            inpatientNoSelect.appendChild(option);
+                        });
+                        inpatientNoSelect.value = currentInpatientNoValue;
+                    }
+                    
+                    // 更新护理级别下拉框
+                    const nurseLevelSelect = document.getElementById('patientNurseLevel');
+                    if (nurseLevelSelect) {
+                        const currentNurseLevelValue = nurseLevelSelect.value;
+                        
+                        // 保留默认选项
+                        const defaultNurseLevelOption = nurseLevelSelect.options[0];
+                        nurseLevelSelect.innerHTML = '';
+                        nurseLevelSelect.appendChild(defaultNurseLevelOption);
+                        
+                        // 添加从数据库获取的真实护理级别选项
+                        nurseLevels.forEach(level => {
+                            const option = document.createElement('option');
+                            option.value = level;
+                            option.textContent = level;
+                            nurseLevelSelect.appendChild(option);
+                        });
+                        nurseLevelSelect.value = currentNurseLevelValue;
+                    }
+                    
+                    // 更新在院状态下拉框
+                    const inpatientStatusSelect = document.getElementById('patientStatus');
+                    if (inpatientStatusSelect) {
+                        const currentInpatientStatusValue = inpatientStatusSelect.value;
+                        
+                        // 保留默认选项
+                        const defaultInpatientStatusOption = inpatientStatusSelect.options[0];
+                        inpatientStatusSelect.innerHTML = '';
+                        inpatientStatusSelect.appendChild(defaultInpatientStatusOption);
+                        
+                        // 添加从数据库获取的真实在院状态选项
+                        inpatientStatuses.forEach(status => {
+                            const option = document.createElement('option');
+                            option.value = status;
+                            option.textContent = status;
+                            inpatientStatusSelect.appendChild(option);
+                        });
+                        inpatientStatusSelect.value = currentInpatientStatusValue;
+                    }
+                } catch (error) {
+                    console.error('更新下拉框时出错:', error);
+                }
+                
+                // 填充患者数据到表格
+                patientData.forEach(patient => {
+                    const row = document.createElement('tr');
+                    row.innerHTML = `
+                        <td>${patient.admissionDateTime || ''}</td>
+                        <td>${patient.inpatientNo || ''}</td>
+                        <td>${patient.name || ''}</td>
+                        <td>${patient.sex || ''}</td>
+                        <td>${patient.age || ''}</td>
+                        <td>${patient.deptCode || ''}</td>
+                        <td>${patient.wardCode || ''}</td>
+                        <td>${patient.roomNo || ''}</td>
+                        <td>${patient.bedNo || ''}</td>
+                        <td>${patient.nurseLevel || ''}</td>
+                        <td>${patient.inpatientStatus || ''}</td>
+                        <td>
+                            <button class="btn btn-primary" onclick="viewPatient('${patient.inpatientNo}')">详情</button>
+                        </td>
+                    `;
+                    tbody.appendChild(row);
+                });
+            })
+            .catch(error => {
+                console.error('加载患者数据失败:', error);
+                // 即使出错也要尝试加载基本数据
+                fetch('/shixian/api/patients')
+                .then(response => response.json())
+                .then(data => {
+                    const tbody = document.getElementById('patientTableBody');
+                    if (tbody) {
+                        tbody.innerHTML = '';
+                        data.forEach(patient => {
+                            const row = document.createElement('tr');
+                            row.innerHTML = `
+                                <td>${patient.admissionDateTime || ''}</td>
+                                <td>${patient.inpatientNo || ''}</td>
+                                <td>${patient.name || ''}</td>
+                                <td>${patient.sex || ''}</td>
+                                <td>${patient.age || ''}</td>
+                                <td>${patient.deptCode || ''}</td>
+                                <td>${patient.wardCode || ''}</td>
+                                <td>${patient.roomNo || ''}</td>
+                                <td>${patient.bedNo || ''}</td>
+                                <td>${patient.nurseLevel || ''}</td>
+                                <td>${patient.inpatientStatus || ''}</td>
+                                <td>
+                                    <button class="btn btn-primary" onclick="viewPatient('${patient.inpatientNo}')">详情</button>
+                                </td>
+                            `;
+                            tbody.appendChild(row);
+                        });
+                    }
+                })
+                .catch(err => {
+                    console.error('加载基础患者数据也失败了:', err);
+                });
+            });
+        }
+
+        // 查询患者
+        function searchPatients() {
+            const name = document.getElementById('patientName').value;
+            const department = document.getElementById('patientDepartment').value;
+            const ward = document.getElementById('patientWard').value;
+            const roomNo = document.getElementById('patientRoomNo').value;
+            const bedNo = document.getElementById('patientBedNo').value;
+            const inpatientNo = document.getElementById('patientInpatientNo').value;
+            const nurseLevel = document.getElementById('patientNurseLevel').value;
+            const status = document.getElementById('patientStatus').value;
+            const admissionDate = document.getElementById('patientAdmissionDate').value;
+            
+            let url = '/shixian/api/patients?';
+            const params = [];
+            
+            if (name) params.push(`name=${encodeURIComponent(name)}`);
+            if (department) params.push(`department=${encodeURIComponent(department)}`);
+            if (ward) params.push(`ward=${encodeURIComponent(ward)}`);
+            if (roomNo) params.push(`roomNo=${encodeURIComponent(roomNo)}`);
+            if (bedNo) params.push(`bedNo=${encodeURIComponent(bedNo)}`);
+            if (inpatientNo) params.push(`inpatientNo=${encodeURIComponent(inpatientNo)}`);
+            if (nurseLevel) params.push(`nurseLevel=${encodeURIComponent(nurseLevel)}`);
+            if (status) params.push(`status=${encodeURIComponent(status)}`);
+            if (admissionDate) params.push(`admissionDateTime=${encodeURIComponent(admissionDate)}`);
+            
+            url += params.join('&');
+            
+            // 并行获取患者数据和护理级别选项
+            Promise.all([
+                fetch(url).then(response => response.json()),
+                fetch('/shixian/api/patients/nurse-levels').then(response => response.json()),
+                fetch('/shixian/api/beds').then(response => response.json())
+            ])
+            .then(([data, nurseLevels, bedData]) => {
+                const tbody = document.getElementById('patientTableBody');
+                tbody.innerHTML = '';
+                
+                // 更新护理级别下拉框
+                const nurseLevelSelect = document.getElementById('patientNurseLevel');
+                const currentNurseLevelValue = nurseLevelSelect.value;
+                
+                // 保留默认选项
+                const defaultNurseLevelOption = nurseLevelSelect.options[0];
+                nurseLevelSelect.innerHTML = '';
+                nurseLevelSelect.appendChild(defaultNurseLevelOption);
+                
+                // 添加从数据库获取的真实护理级别选项
+                nurseLevels.forEach(level => {
+                    const option = document.createElement('option');
+                    option.value = level;
+                    option.textContent = level;
+                    nurseLevelSelect.appendChild(option);
+                });
+                nurseLevelSelect.value = currentNurseLevelValue;
+                
+                // 获取唯一的床位号列表并更新下拉框
+                const bedNos = [...new Set(bedData.map(bed => bed.name).filter(bedNo => bedNo))];
+                const bedNoSelect = document.getElementById('patientBedNo');
+                const currentBedNoValue = bedNoSelect.value;
+                
+                // 保留当前选项,只更新选项列表
+                const defaultBedNoOption = bedNoSelect.options[0];
+                bedNoSelect.innerHTML = '';
+                bedNoSelect.appendChild(defaultBedNoOption);
+                
+                bedNos.forEach(bedNo => {
+                    const option = document.createElement('option');
+                    option.value = bedNo;
+                    option.textContent = bedNo;
+                    bedNoSelect.appendChild(option);
+                });
+                bedNoSelect.value = currentBedNoValue;
+                
+                // 获取唯一的住院号列表并更新下拉框
+                const inpatientNos = [...new Set(data.map(patient => patient.inpatientNo).filter(inpatientNo => inpatientNo))];
+                const inpatientNoSelect = document.getElementById('patientInpatientNo');
+                const currentInpatientNoValue = inpatientNoSelect.value;
+                
+                // 保留当前选项,只更新选项列表
+                const defaultInpatientNoOption = inpatientNoSelect.options[0];
+                inpatientNoSelect.innerHTML = '';
+                inpatientNoSelect.appendChild(defaultInpatientNoOption);
+                
+                inpatientNos.forEach(inpatientNo => {
+                    const option = document.createElement('option');
+                    option.value = inpatientNo;
+                    option.textContent = inpatientNo;
+                    inpatientNoSelect.appendChild(option);
+                });
+                inpatientNoSelect.value = currentInpatientNoValue;
+                
+                // 处理患者数据
+                data.forEach(patient => {
+                    const row = document.createElement('tr');
+                    row.innerHTML = `
+                        <td>${patient.admissionDateTime || ''}</td>
+                        <td>${patient.inpatientNo || ''}</td>
+                        <td>${patient.name || ''}</td>
+                        <td>${patient.sex || ''}</td>
+                        <td>${patient.age || ''}</td>
+                        <td>${patient.deptCode || ''}</td>
+                        <td>${patient.wardCode || ''}</td>
+                        <td>${patient.roomNo || ''}</td>
+                        <td>${patient.bedNo || ''}</td>
+                        <td>${patient.nurseLevel || ''}</td>
+                        <td>${patient.inpatientStatus || ''}</td>
+                        <td>
+                            <button class="btn btn-primary" onclick="viewPatient('${patient.inpatientNo}')">详情</button>
+                        </td>
+                    `;
+                    tbody.appendChild(row);
+                });
+            })
+            .catch(error => {
+                console.error('查询患者数据失败:', error);
+                alert('查询失败,请稍后重试');
+            });
+        }
+        
+        // 清空患者查询条件
+        function clearPatientSearch() {
+            document.getElementById('patientName').value = '';
+            document.getElementById('patientDepartment').value = '';
+            document.getElementById('patientWard').value = '';
+            document.getElementById('patientRoomNo').value = '';
+            document.getElementById('patientBedNo').value = '';
+            document.getElementById('patientInpatientNo').value = '';
+            document.getElementById('patientNurseLevel').value = '';
+            document.getElementById('patientStatus').value = '';
+            document.getElementById('patientAdmissionDate').value = '';
+            loadPatientData();
+        }
+        
         // 查询病房
         function searchRooms() {
             const code = document.getElementById('roomCode').value;
@@ -2576,6 +3026,189 @@
             document.getElementById('roomCodeSettingModal').style.display = 'none';
         }
         
+        // 查询患者
+        function searchPatients() {
+            const name = document.getElementById('patientName').value;
+            const department = document.getElementById('patientDepartment').value;
+            const ward = document.getElementById('patientWard').value;
+            const roomNo = document.getElementById('patientRoomNo').value;
+            const bedNo = document.getElementById('patientBedNo').value;
+            const inpatientNo = document.getElementById('patientInpatientNo').value;
+            const nurseLevel = document.getElementById('patientNurseLevel').value;
+            const status = document.getElementById('patientStatus').value;
+            const admissionDate = document.getElementById('patientAdmissionDate').value;
+            
+            let url = '/shixian/api/patients?';
+            const params = [];
+            
+            if (name) params.push(`name=${encodeURIComponent(name)}`);
+            if (department) params.push(`department=${encodeURIComponent(department)}`);
+            if (ward) params.push(`ward=${encodeURIComponent(ward)}`);
+            if (roomNo) params.push(`roomNo=${encodeURIComponent(roomNo)}`);
+            if (bedNo) params.push(`bedNo=${encodeURIComponent(bedNo)}`);
+            if (inpatientNo) params.push(`inpatientNo=${encodeURIComponent(inpatientNo)}`);
+            if (nurseLevel) params.push(`nurseLevel=${encodeURIComponent(nurseLevel)}`);
+            if (status) params.push(`status=${encodeURIComponent(status)}`);
+            if (admissionDate) params.push(`admissionDateTime=${encodeURIComponent(admissionDate)}`);
+            
+            url += params.join('&');
+            
+            // 并行获取患者数据和护理级别选项
+            Promise.all([
+                fetch(url).then(response => response.json()),
+                fetch('/shixian/api/patients/nurse-levels').then(response => response.json())
+            ])
+            .then(([data, nurseLevels]) => {
+                const tbody = document.getElementById('patientTableBody');
+                tbody.innerHTML = '';
+                
+                // 更新护理级别下拉框
+                const nurseLevelSelect = document.getElementById('patientNurseLevel');
+                const currentNurseLevelValue = nurseLevelSelect.value;
+                
+                // 保留默认选项
+                const defaultNurseLevelOption = nurseLevelSelect.options[0];
+                nurseLevelSelect.innerHTML = '';
+                nurseLevelSelect.appendChild(defaultNurseLevelOption);
+                
+                // 添加从数据库获取的真实护理级别选项
+                nurseLevels.forEach(level => {
+                    const option = document.createElement('option');
+                    option.value = level;
+                    option.textContent = level;
+                    nurseLevelSelect.appendChild(option);
+                });
+                nurseLevelSelect.value = currentNurseLevelValue;
+                
+                // 处理患者数据
+                data.forEach(patient => {
+                    const row = document.createElement('tr');
+                    row.innerHTML = `
+                        <td>${patient.admissionDateTime || ''}</td>
+                        <td>${patient.inpatientNo || ''}</td>
+                        <td>${patient.name || ''}</td>
+                        <td>${patient.sex || ''}</td>
+                        <td>${patient.age || ''}</td>
+                        <td>${patient.deptCode || ''}</td>
+                        <td>${patient.wardCode || ''}</td>
+                        <td>${patient.roomNo || ''}</td>
+                        <td>${patient.bedNo || ''}</td>
+                        <td>${patient.nurseLevel || ''}</td>
+                        <td>${patient.inpatientStatus || ''}</td>
+                        <td>
+                            <button class="btn btn-primary" onclick="viewPatient('${patient.inpatientNo}')">详情</button>
+                        </td>
+                    `;
+                    tbody.appendChild(row);
+                });
+            })
+            .catch(error => {
+                console.error('查询患者数据失败:', error);
+                alert('查询失败,请稍后重试');
+            });
+        }
+        
+        // 清空患者查询条件
+        function clearPatientSearch() {
+            document.getElementById('patientName').value = '';
+            document.getElementById('patientDepartment').value = '';
+            document.getElementById('patientWard').value = '';
+            document.getElementById('patientRoomNo').value = '';
+            document.getElementById('patientBedNo').value = '';
+            document.getElementById('patientInpatientNo').value = '';
+            document.getElementById('patientNurseLevel').value = '';
+            document.getElementById('patientStatus').value = '';
+            document.getElementById('patientAdmissionDate').value = '';
+            loadPatientData();
+        }
+        
+        // 查看患者详情
+        function viewPatient(inpatientNo) {
+            fetch(`/shixian/api/patients/${inpatientNo}`)
+            .then(response => response.json())
+            .then(data => {
+                if (data.success) {
+                    const patient = data.data;
+                    
+                    // 填充弹窗内容
+                    document.getElementById('modalAdmissionTime').value = patient.admissionDateTime || '';
+                    document.getElementById('modalInpatientNo').value = patient.inpatientNo || '';
+                    document.getElementById('modalName').value = patient.name || '';
+                    document.getElementById('modalSex').value = patient.sex || '';
+                    document.getElementById('modalAge').value = patient.age || '';
+                    document.getElementById('modalDept').value = patient.deptCode || '';
+                    document.getElementById('modalWard').value = patient.wardCode || '';
+                    document.getElementById('modalRoomNo').value = patient.roomNo || '';
+                    document.getElementById('modalBedNo').value = patient.bedNo || '';
+                    document.getElementById('modalNurseLevel').value = patient.nurseLevel || '';
+                    document.getElementById('modalInpatientStatus').value = patient.inpatientStatus || '';
+                    
+                    // 显示弹窗
+                    document.getElementById('patientModal').style.display = 'block';
+                } else {
+                    alert('获取患者信息失败: ' + data.message);
+                }
+            })
+            .catch(error => {
+                console.error('获取患者信息失败:', error);
+                alert('获取患者信息失败,请稍后重试');
+            });
+        }
+        
+        // 关闭患者详情弹窗
+        function closePatientModal() {
+            document.getElementById('patientModal').style.display = 'none';
+        }
+        
+        // 加载患者管理科室下拉框数据
+        function loadPatientDepartmentOptions() {
+            fetch('/shixian/api/departments')
+            .then(response => response.json())
+            .then(data => {
+                const departmentSelect = document.getElementById('patientDepartment');
+                
+                // 清空现有选项
+                departmentSelect.innerHTML = '<option value="">全部科室</option>';
+                
+                // 添加新的选项
+                data.forEach(dept => {
+                    const option = document.createElement('option');
+                    option.value = dept.name;
+                    option.textContent = dept.name;
+                    departmentSelect.appendChild(option);
+                });
+            })
+            .catch(error => {
+                console.error('加载科室下拉框数据失败:', error);
+            });
+        }
+        
+        // 加载患者管理病区下拉框数据
+        function loadPatientWardOptions() {
+            fetch('/shixian/api/patients')
+            .then(response => response.json())
+            .then(data => {
+                const wardSelect = document.getElementById('patientWard');
+                
+                // 清空现有选项
+                wardSelect.innerHTML = '<option value="">全部病区</option>';
+                
+                // 获取唯一的病区列表
+                const wards = [...new Set(data.map(patient => patient.wardCode).filter(ward => ward))];
+                
+                // 添加新的选项
+                wards.forEach(ward => {
+                    const option = document.createElement('option');
+                    option.value = ward;
+                    option.textContent = ward;
+                    wardSelect.appendChild(option);
+                });
+            })
+            .catch(error => {
+                console.error('加载病区下拉框数据失败:', error);
+            });
+        }
+        
         // 关闭床位代码设置
         function closeBedCodeSetting() {
             document.getElementById('bedCodeSettingModal').style.display = 'none';
@@ -2996,4 +3629,5 @@
         }
         
     </script>
-</body>
+</body>
+</html>

+ 60 - 0
src/test/java/org/example/util/PatientDataConverterTest.java

@@ -0,0 +1,60 @@
+package org.example.util;
+
+import org.example.entity.Patient;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class PatientDataConverterTest {
+    
+    @Test
+    public void testConvertNurseLevel() {
+        // 测试数字代码转换
+        assertEquals("特级护理", PatientDataConverter.convertNurseLevel("0"));
+        assertEquals("一级护理", PatientDataConverter.convertNurseLevel("1"));
+        assertEquals("二级护理", PatientDataConverter.convertNurseLevel("2"));
+        assertEquals("三级护理", PatientDataConverter.convertNurseLevel("3"));
+        assertEquals("未设置", PatientDataConverter.convertNurseLevel("-1"));
+        
+        // 测试已有的中文描述
+        assertEquals("特级护理", PatientDataConverter.convertNurseLevel("特级护理"));
+        assertEquals("一级护理", PatientDataConverter.convertNurseLevel("一级护理"));
+        
+        // 测试空值
+        assertNull(PatientDataConverter.convertNurseLevel(null));
+        assertEquals("", PatientDataConverter.convertNurseLevel(""));
+    }
+    
+    @Test
+    public void testConvertInpatientStatus() {
+        // 测试数字代码转换
+        assertEquals("入院", PatientDataConverter.convertInpatientStatus("1"));
+        assertEquals("已入科", PatientDataConverter.convertInpatientStatus("2"));
+        assertEquals("待入科", PatientDataConverter.convertInpatientStatus("3"));
+        assertEquals("已出院", PatientDataConverter.convertInpatientStatus("4"));
+        assertEquals("未设置", PatientDataConverter.convertInpatientStatus("-1"));
+        
+        // 测试已有的中文描述
+        assertEquals("入院", PatientDataConverter.convertInpatientStatus("入院"));
+        assertEquals("已入科", PatientDataConverter.convertInpatientStatus("已入科"));
+        
+        // 测试空值
+        assertNull(PatientDataConverter.convertInpatientStatus(null));
+        assertEquals("", PatientDataConverter.convertInpatientStatus(""));
+    }
+    
+    @Test
+    public void testConvertPatientData() {
+        // 测试患者对象转换
+        Patient patient = new Patient();
+        patient.setNurseLevel("0");
+        patient.setInpatientStatus("1");
+        
+        Patient convertedPatient = PatientDataConverter.convertPatientData(patient);
+        
+        assertEquals("特级护理", convertedPatient.getNurseLevel());
+        assertEquals("入院", convertedPatient.getInpatientStatus());
+        
+        // 测试null对象
+        assertNull(PatientDataConverter.convertPatientData(null));
+    }
+}