医院绩效考核系统

项目开始时间 2023年10月01日

项目现状 目前(维护中)

一、总结:

1、期间遇到问题,自己网上查资料,最终解决;

去百度搜索的时候,很多情况搜不到的原因是自己没有用专业的语句,口语化的语句很少能搜到答案,有时候问一问别人或许不能直接解决问题,但是却给了我们另一个思路去搜索,这样说不定就能找到答案。

2、前一天晚上想好第二天要做的内容,划分好时间,提高开发效率。

3、拿到需求到代码实现经历了怎样的过程?

站在用户角度使用:

拿到ui设计稿,把所有的页面先点一点,大概了解有哪些功能?在这一步,我们可以参考其他成熟的系统,如果有类似功能的话,就去点一点,了解每个操作。知道新功能的基本流程是哪些。

站在技术角度:

思考自己上一步都做了些什么。每个功能的要点在哪里。实现的难点在哪里。可能会发生什么样的情况,类似于if...else方式的思考。这一步,我们作为技术,考虑的是如何实现。

4、项目描述:

5、项目技术:Vue3 + element-plus + vue-router + Pinia + axios + Echarts

6、项目职责:

使用 Pinia 实现数据统一管理;

使用 Vue3 的 vite 框架 、element-plus 实现快速布局;

使用 watchEffect 方法统一监听数据,从而更高效的解决数据变,页面变;

使用 Axios 网络请求库 ,调用后端接口获取数据 ,并将数据处理后传递给组件进行展示;

进行代码调试和单元测试 ,确保项目的稳定性和可靠性;

利用组件化思想 ,将页面封装成多个组件提高代码的复用性和可维护性;

性能优化,减少不必要的更新、使用异步组件加载、懒加载路由等,以提升页面加载速度和用户体验;

二、系统遇到的问题:

1、适配

什么是自适应布局?

自适应设计是能使网页自适应显示在不同大小终端设备上新网页设计方式及技术。简单的来说自适应就是让同一个页面自动适应不同大小的设备,从而解决为不同设备提供不同版本的页面问题。

解决方式:响应式布局,系统分为header上,menu左,main右,使用flex布局,并且右边main处不能出现滚动条,只可以table出现滚动条。

2、 element-plus的tree组件(一键选择)

需求:页面上展示所有的二/三级指标,要求点击按钮"一键选择二/三级指标",tree组件的复选框勾选上。

问题:使用tree组件自带方法setCheckedKeys,但是时好时坏,有些时候复选框勾不全,控制台会报错。

解决方式:使用tree组件自带方法default-checked-keys。点击按钮时请求拿到所有的二三级指标并循环,根据等级字段判断,把ID push到default-checked-keys变量中。

setCheckedKeys:设置目前选中的节点,使用此方法必须设置 node-key 属性

default-checked-keys:默认勾选的节点的 key 的数组

3.把后端返回的数据,转成tree数据

第一种方式:

后端返回的数据

转换成tree代码

javascript 复制代码
export let transformData2 = (nodes) => {
    const map = {};
    let node;
    let roots = [];
    // 将所有节点转换成一个映射表
    for (let i = 0; i < nodes.length; i++) {
        map[nodes[i].jgbm || nodes[i].id] = nodes[i];
        const hasChidren = nodes.some((item) => {
            return item.fid || item.sjjgbm == nodes[i].jgbm || nodes[i].id;
        });
        if (hasChidren) {
            nodes[i].children = [];
        }
    }
    // 将所有子节点添加到其父节点的 children 属性中
    for (let i = 0; i < nodes.length; i++) {
        node = nodes[i];
        if (
            (node.fid || node.sjjgbm) != 0 &&
            (node.fid || node.sjjgbm) !== null
        ) {
            if (typeof map[node.fid || node.sjjgbm] !== "undefined") {
                map[node.fid || node.sjjgbm].children.push(node);
            } else {
                roots.push(node);
            }
        } else {
            roots.push(node);
        }
    }
    return roots;
};

第二种方式:

后端返回的数据

转换成tree代码

javascript 复制代码
export let transformData = (nodes) => {
    const map1 = [];
    // 第一级树
    nodes.map((item, index) => {
        map1[index] = {};
        map1[index].id = item.flmc_parent_id;
        map1[index].zbmc = item.flmc_parent;
        map1[index].children = [];
    });
    // 去重
    for (let i = 0; i < map1.length; i++) {
        for (let j = i + 1; j < map1.length; j++) {
            if (map1[i].id == map1[j].id) {
                map1.splice(j, 1);
                j--;
            }
        }
    }
    // 第二级树
    map1.map((item, index) => {
        nodes.map((v, i) => {
            if (item.id == v.flmc_parent_id) {
                map1[index].children[i] = {};
                map1[index].children[i].id = v.flmc_id;
                map1[index].children[i].zbmc = v.flmc;
                map1[index].children[i].children = [];
            }
        });
    });
    // 去重
    const newArr = map1.map((item) => {
        return item.children.filter((v, i, arr) => {
            return arr.indexOf(v) === i;
        });
    });
    // 去重
    newArr.map((item) => {
        for (let i = 0; i < item.length; i++) {
            for (let j = i + 1; j < item.length; j++) {
                if (item[i].id == item[j].id) {
                    item.splice(j, 1);
                    j--;
                }
            }
        }
    });
    // 第三级树(自己)
    newArr.map((m, n) =>
        m.map((item, index) => {
            nodes.map((v, i) => {
                if (item.id == v.flmc_id) {
                    item.children[i] = {
                        ...v, // 展开运算符
                    };
                }
            });
        })
    );
    // 去重
    const dudududu = newArr.map((item) => {
        return item.map((m) => {
            return m.children.filter((v, i, arr) => {
                return arr.indexOf(v) === i;
            });
        });
    });
    // 去重
    dudududu.map((item) => {
        item.map((m) => {
            for (let i = 0; i < m.length; i++) {
                for (let j = i + 1; j < m.length; j++) {
                    if (m[i].id == m[j].id) {
                        m.splice(j, 1);
                        j--;
                    }
                }
            }
        });
    });
    // 把第三级树(自己)给到第二级树,第二级树给到第一级树
    for (var i = 0; i < map1.length; i++) {
        for (var m = 0; m < map1[i].children.length; m++) {
            map1[i].children = newArr[i];
            map1[i].children[m].children = dudududu[i][m];
        }
    }
    return map1;
};

4、前端实现分页 (分享)

使用了v3的watchEffect

watchEffect也是监听数据,但是它会立即运行一个函数,而不是懒侦听。

如果需要页面加载完毕立即执行的话,还是用watchEffect

watchEffect 它与 watch 的区别主要有以下几点:

1.不需要手动传入依赖

2.每次初始化时会执行一次回调函数来自动获取依赖

3.无法获取到原值,只能得到变化后的值

4.watch 是惰性的,因此仅当依赖项更改时才会触发。watchEffect 在创建组件后立即运行,然后跟踪依赖关系。

javascript 复制代码
const tableData = ref([]);
const currentTableData = ref([]); // table组件的data值
const current = ref(1);  // 页码
const total = ref(1);  // 总条数

watchEffect(() => {
    current.value = 1;
    total.value = tableData.value.length;
    currentTableData.value = tableData.value.filter(
        (item, index) => index < 30
    );
});

// 第几页
let handleCurrentChange = (val) => {
    current.value = val;
    const index = 30 * (val - 1);
    const nums = 30 * val;
    const tables = [];
    for (let i = index; i < nums; i++) {
        if (tableData.value[i]) tables.push(tableData.value[i]);
    }
    currentTableData.value = tables;
};

// 模板渲染后,立即执行的函数
onMounted(() => {
   // 页面刚进来时,请求的数据给到tableData.value
});

5、页面跳转后,点击返回,改为返回来源页。

javascript 复制代码
// 页面相关参数
const searchParams = reactive({
    ckzYear: "",
    year: "2024",
    SchemeName: "",
    faName: "",
    isJCindex: "",
    options: [],
    newArr: [],
    homeList: [],
});

// 点击按钮跳转
let ckFun = async (item) => {
    let _data = Object.assign(searchParams, {});
    setstorage("nowPageData", JSON.stringify(_data)); //这两行代码用来往sessionStorage存数据
    router.push("/StatisticalAnalysis-detail");
};

// 模板渲染后,立即执行的函数
onMounted(() => {
    if (getstorage("nowPageData")) {
        let _obj = JSON.parse(getstorage("nowPageData"));
        Object.keys(searchParams).forEach((key) => {
            searchParams[key] = _obj[key] || searchParams[key];
        });
        removelist("nowPageData");
    }
});

6、计算指标分(综合计算)

需求:出院患者微创手术占比 = (日间手术台次数 / 同期出院患者择期手术总台次数) * 100%

思路:

1.拿到分子和分母的value

2.用字符串replace方法替换 str.replace(换下的值,换上的值)

3.使用eval。 (eval 是Javascript内置函数,用于计算字符串表达式的值。例如eval(2+3) 返回的是5。)

实现代码:

javascript 复制代码
    // 审核确定按钮
    let util = () =>
    {
      // 计算公式编码
      let jsgsbm = "({SJYLZL_GNDW_5_51 / SJYLZL_GNDW_5_52 * 100%})"
      // 计算公式名称
      let jsgsmc = "(5.1.出院患者微创手术台次数/5.2.同期出院患者手术台次数)*100%"
      // 分子和分母信息
      let fz_fm = [
        {
          bool: false,
          cqz: "0",
          faid: 1,
          fz_or_fm: "fz",
          khdx: "医院",
          khnf: "2024",
          value: "221",
          zbdm: "SJYLZL_GNDW_5_51",
          zbmc: "出院患者微创手术台次数"
        }, {
          bool: false,
          cqz: "0",
          faid: 1,
          fz_or_fm: "fm",
          khdx: "医院",
          khnf: "2024",
          value: "226",
          zbdm: "SJYLZL_GNDW_5_52",
          zbmc: "同期出院患者手术台次数"
        }
      ]
      let str = "";
      for (var i = 0; i < jsgsbm.length; i++) {
        if (
          jsgsbm[i] == "{" ||
          jsgsbm[i] == "}"
        ) {
          continue;
        } else if (jsgsbm[i] == "%") {
          str += "";
        } else {
          str += jsgsbm[i];
        }
      }
      for (var i = 0; i < fz_fm.length; i++) {
        str = str.replace(
          fz_fm[i].zbdm,
          fz_fm[i].value == "/"
            ? "0"
            : fz_fm[i].value
        );
      }
      console.log(str);
      return String((eval(str) / 1).toFixed(2))
    }
    console.log(util());
相关推荐
图表制作解说(目标1000个图表)15 分钟前
ECharts柱状图-带圆角的堆积柱状图,附视频讲解与代码下载
echarts·统计分析·数据可视化·柱状图·大屏可视化
前端拾光者19 分钟前
利用D3.js实现数据可视化的简单示例
开发语言·javascript·信息可视化
风尚云网1 小时前
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计
前端·css·学习·html·html5·风尚云网
木子02041 小时前
前端VUE项目启动方式
前端·javascript·vue.js
endingCode1 小时前
45.坑王驾到第九期:Mac安装typescript后tsc命令无效的问题
javascript·macos·typescript
运维-大白同学2 小时前
将django+vue项目发布部署到服务器
服务器·vue.js·django
Myli_ing2 小时前
HTML的自动定义倒计时,这个配色存一下
前端·javascript·html
I_Am_Me_3 小时前
【JavaEE进阶】 JavaScript
开发语言·javascript·ecmascript
℘团子এ3 小时前
vue3中如何上传文件到腾讯云的桶(cosbrowser)
前端·javascript·腾讯云
学习前端的小z3 小时前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript