互联网医院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去构造机构树,在前端绑定好数据即可。

相关推荐
前端 贾公子10 小时前
小程序蓝牙打印探索与实践(上)
小程序
UXbot10 小时前
AI网页开发工具能替代工具吗?5大平台对比
前端·人工智能·低代码·ui·原型模式·web app
拙慕JULY11 小时前
小程序返回 base64 文件报错
开发语言·javascript·小程序
dh1312225052512 小时前
按月季度销售业绩核算小程序
小程序·销售小程序·绩效小程序·业绩统计小程序·业绩核算小程序
拙慕JULY12 小时前
微信小程序自定义标题背景色
微信小程序·小程序
yinmaisoft13 小时前
JNPF 三大主流行业解决方案,按需定制
大数据·低代码·开发工具
前端 贾公子14 小时前
小程序蓝牙打印探索与实践(下)
小程序·apache
00后程序员张14 小时前
Jenkins 自动上传 IPA 到 App Store 把发布步骤融入 CI/CD
android·ios·小程序·https·uni-app·iphone·webview
SL-staff17 小时前
Vue3私有化AI白板落地实战|解决政企项目智能绘图合规难题(可直接复用源码)
人工智能·低代码·开源·vue3·白板·jvs规则引擎·jvs-draw
万岳科技系统开发17 小时前
骑手配送系统如何支持外卖与跑腿一体化运营
大数据·前端·小程序