互联网医院04科室管理

目录

  • [1 创建数据模型](#1 创建数据模型)
  • [2 搭建页面](#2 搭建页面)
  • [3 获取部门信息](#3 获取部门信息)
  • [4 前端读取](#4 前端读取)
  • 总结

上一篇我们已经介绍了医院及院区信息的展示,有了院区之后,我们就需要在院区下建立科室。对于大型医院,通常科室是非常多的,而且科室下边还有子部门。

对于这种有多级结构的,我们通常使用树形结构来管理数据,本篇我们介绍一下科室管理的开发过程。

1 创建数据模型

对于这种父子关系的,我们在建表的时候需要建立自关联的关系。打开MySQL,创建数据模型,创建部门表,增加科室名称字段

增加科室编码字段

增加父部门,类型选择关联关系

增加层级字段

增加排序字段

增加科室简介字段

录入数据的时候就形成了一种层级关系

2 搭建页面

打开我们的后台应用,点击创建页面的图标,添加科室管理页面

在内容插槽里添加布局组件

我们用网格布局来将页面分为左右两部分

第一列添加树组件

第二列,我们用普通容器来搭建布局,形成上下两部分

上半部分,我们搭建一个布局显示当前选中部门的信息,可以添加子部门

下半部分添加数据表格组件,数据模型选择部门表

3 获取部门信息

因为科室是一颗树,但是我们表里的数据是以行进行组织的,所以需要写一个API将行结构改写为树结构。

打开扩展功能,点击+号创建API

选择自定义代码

输入API的名称和标识

修改一下方法名称和标识

输入如下代码

bash 复制代码
/**
 * API 标识: getDepartmentTree
 * 类型: 自定义代码
 */
module.exports = async function (params, context) {
  // 1. 从数据库获取所有部门数据
  // 注意:默认分页限制为 200 条 。
  // 如果部门超过 200,建议使用循环分页获取,此处演示单次获取。
  const result = await context.callModel({
    dataSourceName: 't_department', // 数据模型标识
    methodName: 'wedaGetRecordsV2', // 查询多条方法 [cite: 467]
    params: {
      pageSize: 200, 
      pageNumber: 1,
      select: {
        $master: true, // 获取主表字段 [cite: 859]
        // 确保获取 parent_id,这对于构建树至关重要
        parent_id: true 
      }
    }
  });

  const allDepts = result.records || [];

  // 定义图标常量 (根据你的需求配置)
  const ICONS = {
    fold: "0a94df-1307578329.tcloudbaseapp.com/resources/2023-05/lowcode-1177832",
    expand: "https://lowcode-1gk9y5ik310a94df-1307578329.tcloudbaseapp.com/resources/2023-05/lowcode-1177833",
    leaf: "https://lowcode-1gk9y5ik310a94df-1307578329.tcloudbaseapp.com/resources/2023-05/lowcode-1177834"
  };

  // 2. 定义转换函数:将数据库行转换为 UI 组件节点格式
  const transformNode = (dept) => {
    return {
      label: dept.name || '未命名部门',    // 组件要求的 label
      value: dept._id,                    // 组件要求的 value
      // 这里的 parentId 处理要小心,关联关系通常返回对象 {_id: "..."}
      parentId: dept.parent_id ? dept.parent_id._id : null, 
      foldIcon: ICONS.fold,
      expendIcon: ICONS.expand,
      // 预留 children 数组
      children: []
    };
  };

  // 3. 构建树的核心算法 (Map 映射法)
  const buildTree = (items) => {
    const tree = [];
    const map = {};

    // 第一轮遍历:初始化所有节点并存入 Map
    items.forEach(item => {
      const node = transformNode(item);
      map[node.value] = node; // 以 ID 为 Key 存入 Map
    });

    // 第二轮遍历:利用引用组装树
    items.forEach(item => {
      const node = map[item._id];
      const parentId = node.parentId;

      if (parentId && map[parentId]) {
        // 如果有父节点,且父节点在数据中存在,则加入父节点的 children
        map[parentId].children.push(node);
      } else {
        // 如果没有父节点(或父节点找不到),则视为根节点
        tree.push(node);
      }
    });

    return tree;
  };

  // 4. 执行转换并返回
  const treeData = buildTree(allDepts);
  
  // 可选:后期处理,例如如果是叶子节点(children为空),可以赋予特定的 leafIcon
  // 或处理 disabled 状态
  
  return treeData;
};

上述代码主要是把扁平的数据重新组织成树形目录。这样做有一个问题,我们用个人版去开发API,他默认的是预览库,但是后台写入的是生产库,导致我们的API没办法读取到数据。

为了解决这个问题,我们用API写入一些测试数据,再添加一个API用来生成数据

输入如下代码

bash 复制代码
/**
 * API 标识: initTestData
 * 名称: 初始化测试数据
 * 类型: 自定义代码
 */
module.exports = async function (params, context) {
  const dataSourceName = 't_department'; // 你的表名

  // 🛠️ 定义一个通用的创建函数,简化代码
  const createDept = async (name, parentId = null, level = 1) => {
    // 构造数据对象
    const record = {
      name: name,
      level: level,
      // ⚠️ 关键点:关联关系的写法。
      // 如果有 parentId,必须写成对象形式 {_id: "..."},否则写入失败
      parent_id: parentId ? { _id: parentId } : null 
    };

    // 调用微搭新建单条数据方法
    const result = await context.callModel({
      dataSourceName: dataSourceName,
      methodName: 'wedaCreateV2',
      params: {
        data: record
      }
    });

    // 返回新创建数据的 ID,供子节点使用
    return result.id || result._id; // 兼容不同版本的返回字段
  };

  try {
    console.log("开始生成测试数据...");

    // 1️⃣ 第一层:创建根节点(医院)
    const rootId = await createDept("内蒙古人民医院", null, 0);
    console.log("根节点创建成功 ID:", rootId);

    // 2️⃣ 第二层:创建分类(职能/临床)- 挂载到根节点
    const adminDeptId = await createDept("职能处室", rootId, 1);
    const clinicalDeptId = await createDept("临床科室", rootId, 1);
    const researchDeptId = await createDept("科研中心", rootId, 1);

    // 3️⃣ 第三层:创建具体科室 - 挂载到对应的第二层节点
    
    // --> 挂载到"职能处室"
    await createDept("人事处", adminDeptId, 2);
    await createDept("医务处", adminDeptId, 2);
    await createDept("办公室", adminDeptId, 2);

    // --> 挂载到"临床科室"
    await createDept("心血管内科", clinicalDeptId, 2);
    await createDept("呼吸与危重症医学科", clinicalDeptId, 2);
    await createDept("骨关节科", clinicalDeptId, 2);

    // --> 挂载到"科研中心"
    await createDept("医学科学院", researchDeptId, 2);

    return {
      success: true,
      message: "✅ 测试数据生成完毕!请去验证 getDepartmentTree 接口。",
      rootId: rootId
    };

  } catch (e) {
    console.error("生成失败", e);
    return {
      success: false,
      message: "❌ 生成失败,请查看日志",
      error: e.message
    };
  }
};

4 前端读取

我们有了后端API,主要是解决数据构造的问题,需要在前端创建一个API来读取一下数据

变量设置好之后,就可以绑定到我们的树组件上

继续创建一个变量用来保存部门的名称

当选中叶子节点,将叶子节点的信息赋值给变量

把这个变量绑定给文本,就实现了选中叶子节点,在右边显示部门名称的效果

总结

本篇我们介绍了一个稍微复杂的功能,机构树。难点在设计数据模型你就要让表进行自关联,然后用API去构造机构树,在前端绑定好数据即可。

相关推荐
说私域14 小时前
分享经济应用:以“开源链动2+1模式AI智能名片S2B2C商城小程序”为例
人工智能·小程序·开源
一 乐18 小时前
智慧养老|基于springboot+小程序社区养老保障系统设计与实现(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·后端·小程序
小小王app小程序开发20 小时前
盈利 + 留存双驱动:分销商城小程序的增长法则与落地指南
小程序
不如摸鱼去20 小时前
uni-app 也能远程调试?使用 PageSpy 打开调试的新大门!
前端·小程序·uni-app
峰兄19830521 小时前
8266实现Modbus TCP协议转RTU串口通讯之旅
小程序
UI设计兰亭妙微1 天前
从“功能堆砌“到“体验至上“的蜕变之路:兰亭妙微如何助力“臻选生活馆“实现小程序重生与业绩倍增
小程序·小程序开发
万岳软件开发小城1 天前
开发一套私域直播 APP/Web/小程序需要哪些核心模块?完整技术清单来了
小程序·php·直播带货系统源码·直播带货软件开发·私域直播系统源码·私域直播平台搭建·私域直播软件开发
计算机毕设指导61 天前
基于微信小程序的篮球场馆预订系统【源码文末联系】
java·spring boot·mysql·微信小程序·小程序·tomcat·maven
闹小艾1 天前
制作知识付费线上课程小程序:制作平台实操指南,不用编程3分钟学会搭建
小程序