作者: 孟繁永

  • 慢阻肺如何选择医用制氧机来进行长期氧疗

    本文仅以个人非医学专业了解到的产品和医疗信息分享,不能替代医学治疗方案。

    据医嘱,吸氧需要达到4L/min的流量才有效,但这个指标的前提是制氧机或者气瓶出氧的浓度要在90%以上,虽然国标要求医用制氧机必须达到90%,而目前市场上的制氧机普遍宣称符合这个标准,但从评论以及个人非严格检测来看,这个标准似乎没有那么容易实现。

    这里列出制氧机的几个关键指标,请逐一核实:

    1. 可连续工作时间,这个涉及制氧机的可用性和耐用性,有的声称达到72小时或96小时,关键要看说明书上是否有明文说明,不能只看商品标题或视频,有的宣称7*24小时,目前来看,多半是虚假宣传,因为目前几千元的制氧机显然达不到7天连续工作。
    2. 出氧浓度,国家标准要求90%以上,有的机器标>=90%,有的标93%(+-3%),但有的机器会有附加说明,比如开机15分钟才能达到这个浓度(因内部有储气罐,可能需要排空一段时间),我买了一台欧姆龙(安徽迈睿思代工),前几次开机数分钟后出氧浓度基本上只在85%左右,最高89,但机器自身的氧气浓度一直显示为95%,我在12315上做了投诉,不知道接下来多久会有回复。还有的机器并不是在任何流量下都是90%以上,比如有的机器在详细描述中会补充说只在某个低流量区间能达到这个浓度,再大了相当于就是多吹点空气了,也难怪有的制氧机宣称不做空气的搬运机。我前些年买的那个鱼跃的流量控制显示是1L~5L,现在仔细查才知道其实是3L的机器,调到5L也没有多大意义,而现在实测出氧只有50%,所以买个新的。欧姆龙这个因为是周末提交的投诉,12315无反馈,退货申请暂时没有通过,但后来开机测试能达到93%(机身还是显示95%),就先用着了。
    3. 机器工作噪音,这个也挺关键的,在欧姆龙那台出氧浓度不达标的情况下,我又下单了一台鱼跃的6L机器,但下单后仔细再看评论,很多视频评论反馈机器噪音大,看了下他的说明书,是小于60分贝,这个确实高了,从视频里看,也确实比手上这台欧姆龙大得多。看网上的商品资料,有的说在29分贝,有的说在36分贝,能接受哪一种,还是要慎重考虑。
    4. 能否退货,从欧姆龙和鱼跃的评论区看,普遍退货困难,有的是因为噪音大,有的因为出氧浓度不达标,但都是因为开机过,不能退货,但这东西不开机怎么知道怎么样呢?所以有的评论总结不如在线下买,可以当场试机,不知道厂家是否针对线上有特殊政策。这类产品质量不稳定的现实应该是可以确认的,这种特殊商品如何退货还需要更清晰的政策和规则,有的商品明确说明只要一次性使用的附件没有拆封就可以退货,比如吸氧管之类的,这算比较合理的。
    5. 分子筛是否进口,尽管这玩意近些年国产化做的很到位,但从产品定价来看,一两千的产品都用国产的,四五干就出现用进口的了,显然,国产的还是达不到进口产品的水平。

    测试成本很高,自己搞不定,网购的氧气检测仪也不一定精度就很高,但如果氧气浓度检测仪和制氧机自身的氧气浓度值都不可靠,那还有什么可靠的产品呢?

  • Vue3+VueUse 极简实现可拖拽侧边栏

    <script setup lang="ts">
    import { computed, onMounted, ref } from 'vue'
    import { useMousePressed, useMouseInElement } from '@vueuse/core'
    
    const containerRef = shallowRef()
    const dividerRef = shallowRef()
    
    const { pressed } = useMousePressed({ target: dividerRef, touch: false })
    const { elementX } = useMouseInElement(containerRef)
    
    const asideWidth = ref('300px')
    
    watch(elementX, (newVal) => {
      console.log(newVal, pressed.value)
      if (!pressed.value) return
      if (newVal < 300) {
        asideWidth.value = '300px'
        return
      }
      asideWidth.value = `${Math.floor(newVal)}px`
    })
    
    </script>
    
    <template>
    <ElContainer v-show="panel === 'tree'" ref="containerRef" class="container">
          <ElAside class="aside"
            ></ElAside>
          <div ref="dividerRef" class="divider"></div>
          <ElMain class="main">
          </ElMain>
     </ElContainer>
    <ElContainer v-show="panel === 'card'"> <BookCard :book="currentBook" /></ElContainer>
    </template>
    <style scoped lang="less">
    .aside {
      width: v-bind('asideWidth');
    }
    .divider {
      flex: 0 0 4px;
      &:hover {
        background-color: var(--el-border-color);
        cursor: col-resize;
      }
      &:active {
        background-color: var(--el-border-color);
        cursor: col-resize;
      }
    }
    </style>

    在flex容器(container)中横向排布侧边栏(aside)、分隔线(divider)和主要区域(main)通过useMousePressed获取分隔线上的鼠标按压状态,通过useMouseInElement获取容器内的鼠标移动状态,这些状态是响应式的侦听鼠标横向移动距离,仅当鼠标在分隔线按下(即拖拽)时,同步修改侧边栏宽度。

    参考:流烨(链接:https://juejin.cn/post/7384242126429405225),相比调整了一下动态设置宽度的方式,改为width: v-bind(‘asideWidth’),同时,优化.divider的样式,增加hover,让它平时隐藏,鼠标滑过时显示更容易寻找。

  • l5-swagger如何设置服务端路径

    正如tests/storage/annotations/OpenApi/L5SwaggerAnnotationsExampleServer.php所示:

    <?php
    
    namespace Tests\storage\annotations\OpenApi;
    
    /**
     *  @OA\Server(
     *      url=L5_SWAGGER_CONST_HOST,
     *      description="L5 Swagger OpenApi dynamic host server"
     *  )
     *
     *  @OA\Server(
     *      url="https://projects.dev/api/v1",
     *      description="L5 Swagger OpenApi Server"
     * )
     */
    class L5SwaggerAnnotationsExampleServer
    {
    }

    L5_SWAGGER_CONST_HOST是作为一个变量直接引用的,这个变量在.env中设置,在实际项目中,尤其是多实例部署的产品,优先考虑用这种方法,而其中第二个是直接写死的地址,这种更适合相对固定的内部测试或者官方接口站点作为对照。实际上,api/doc还会依据L5_SWAGGER_BASE_PATH自动加载一个相对的接口地址,这个更适合用在调试环境,启动端口有可能会变,而且多个开发者的配置也不一定一致。L5_SWAGGER_CONST_HOST和L5_SWAGGER_BASE_PATH之间是相对独立的,可以搜索一下l5-swagger源代码看看逻辑,可惜这一点在l5-swagger的文档中说的并不清楚。

  • 出版行业如何选择大模型

    过年期间deepseek吵得很热闹,不过就我看到的信息,更像是一次冲喜,毕竟要过除夕了。我不太相信惊喜,二十年前在武汉的某博士沙龙上我突发灵感得到的结论,一切惊喜都可视作异常。回京后,做了下简单的测试,拿一个简单地问题去问这几个模型,这个问题还不算很苛刻,只是想看看训练时的语料审查有多么严重。

    按结果的省略程度排序依次是:

    1. deepseek
    2. qwen
    3. mistral

    拿出版行业来说,尽管审查也是一个很重的任务,但这个任务是由编辑来承担的,大模型没有权力直接来操刀,否则很容易造成失真,编辑就没法干活了。即使有deepseek无审查版也不行,因为那个无审查只是推理时无审查,并不能解决训练阶段的语料审查。

    所以,这个可以当作出版行业大模型的一个选择条件,如果是2C我没有什么意见,安全第一,但是从编辑专业角度而言,必须选择一个中立的大模型来作为基础模型。这几个里面,没有哪个合适的,勉强选择的话只有mistral可以考虑,但这家伙中立的过分了,其实作为专业模型,我们不需要大模型给出态度和立场。

    所以,行业模型还要从更基础的模型来做。

  • 用Caddy部署wordpress

    年前把公司网站的服务器换到了caddy上,今天想写一篇博客,发现证书过期了,之前用了certbot但是配置自动任务还是比较麻烦的,尤其是用了docker。索性一起换掉。

    docker-compose.yml中的配置如下:

      caddy:
        image: registry.cn-beijing.aliyuncs.com/futuremeng/caddy:1.1
        container_name: caddy
        restart: unless-stopped
        environment:
          - TZ=Asia/Shanghai
        volumes:
          - ./services/caddy/config:/config
          - ${DATA_DIR}/caddy:/data
          - ${SOURCE_DIR}:/www/:rw
          - ${LOGS_DIR}/caddy:/var/log/caddy
        ports:
          - "80:80"
          - "443:443"
        networks:
          - default

    其中的env变量请自行脑补。

    caddyfile:

    https://WordPress.com {
            root * /www/WordPress
            php_fastcgi php80:9000 {
                    trusted_proxies private_ranges
            }
            file_server
            encode gzip
            @disallowed {
                    path /xmlrpc.php
                    path *.sql
                    path /wp-content/uploads/*.php
            }
            rewrite @disallowed '/index.php'
    }

    详情可见:

    https://github.com/futuremeng/dnmp

  • 把mac相册中的图片批量导入到immich

    在mac上打开终端:

    cd /Users/mengfanyong/Pictures/照片图库.photoslibrary

    接下来参照https://immich.app/docs/features/command-line-interface/

    首先需要安装immich客户端,如果没有node或者版本太低,请跳转到:https://nodejs.org/en/download

    npm i -g @immich/cli

    首先向 Immich 服务器进行身份验证。

    immich login-key [instanceUrl] [apiKey]

    开始批量上传

    immich upload --recursive directory/

  • 用Caddy部署vue3和laravel

    二级目录部署vue3的Caddyfile

    https://domain.com {
        redir /portal /portal/ 308
        handle /portal/* {
            uri strip_prefix /portal
            root * /www/domain.com/portal   #打包后的静态文件
            try_files {path} /index.html
            file_server
            encode    zstd   gzip  #开启zip
        }
    }

    在根目录部署laravel的Caddyfile

    https://api.domain.com {
        root /www/api.domain.com/my-laravel/public
        encode gzip
        # PHP-FPM Configuration for Caddy use docker php80
        php_fastcgi php80:9000 
        file_server
    }
    

    如果laravel的接口需要开启跨域访问,则可以参考以下的Caddyfile,此外laravel也要根据版本,选择相应的开启cors的方法,此处不展开。

    (cors) {
            @cors_preflight{args.0} method OPTIONS
            @cors{args.0} header Origin {args.0}
    
            handle @cors_preflight{args.0} {
                    header {
                            Access-Control-Allow-Origin "{args.0}"
                            Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS"
                            Access-Control-Allow-Headers *
                            Vary Origin
                            Access-Control-Max-Age "3600"
                            defer
                    }
                    respond "" 204
            }
    
            handle @cors{args.0} {
                    header {
                            Access-Control-Allow-Origin "{args.0}"
                            Access-Control-Expose-Headers *
                            defer
                    }
            }
    }
    
    https://api.domain.com {
        import cors {header.origin}  # 允许任意来源的跨域访问
        root /www/api.domain.com/my-laravel/public
        encode gzip
        # PHP-FPM Configuration for Caddy use docker php80
        php_fastcgi php80:9000 
        file_server
    }
  • 最彻底的关闭Windows10 的更新!

    写在最前面,前阵子收了一台笔记本电脑,sony的,固态盘还是触摸屏,小惊喜了一把,结果这个电脑的系统是win,每天自动更新,但是更新失败回退。搜了一些方法,但都不解决问题,终于找到下面这篇最全的。

    文章附图

    前言:

    Windows10的自动更新给工作带来很多不便,想关闭更新很难,我们经过多次尝试,基本找全了与更新有关的条目。

          1、与更新有关的Windows服务,大致就这三个服务。

          Windows update

          Update Orchestrator UsoSvc(更新Orchestrator 服务)

          Windows update medic service(更新医生服务)

          2、组策略

           计算机配置 – 管理模板 -Windows组件 -Windows更新

          3、计划任务

           Microsoft -Windows -WindowsUpdate

    以下内容(一、二、三)

    一、禁用三大服务(三种方法)

      1、手工操作停止禁用服务。

          进入服务的方式很多,从此电脑右键属性-管理-可以找到。也可以从控制面板进入。

          可以运行services.msc直接进入。

          (1)、先停止Windows Update,后禁用。如图

    Windows update.png

    找到【恢复】页,改为无操作

    Windows update1.png

    (2)、关闭 禁止 Update Orchestrator UsoSvc服务   更新适配Orchestrator服务

    ORCHESTRATOR.png
    ORCHESTRATOR1.png

    (3)、停止 禁用 Windows update medic service 更新医生服务

    medic.png
    medic1.png

    这个服务有时会拒绝访问或改不了。你就要参考下面注册表修改了。

    2、注册表修改。(如果上面的修改的很顺利,就不必要再做这项的内容,手工修改和注册表修改是异曲同工,互相验证的关系)

       打开注册表,开始 运行   regedit

        (1)、禁用 Windows update(第一个图是禁用更新,第二个图修改恢复里面的“无操作”)

           HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\wuauserv

    Windows update2.png
    Windows update3.png

    (2)、关闭 禁止 Update Orchestrator UsoSvc服务   更新适配Orchestrator服务

                HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\UsoSvc

                这项的改的地方同(1)。只是注册表位置不一样。【UsoSvc】

    (3)、停止 禁用 Windows update medic service 更新医生服务

                HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WaaSMedicSvc

                这项的改的地方同(1)。只是注册表位置不一样。【WaaSMedicSvc】

        3、运行命令修改。(这个要求稍微专业点的知识,高手可采用。但要先检查三个FailureActions的值你有没有特殊设置再用。)

    net stop wuauserv

    net stop UsoSvc

    net stop WaaSMedicSvc

    reg add “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\wuauserv” /v “Start” /t REG_DWORD /d 4 /f

    rem ********   停止 禁用 Windows update

    reg add “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\wuauserv” /v “FailureActions” /t REG_BINARY /d 80510100000000000000000003000000140000000000000060ea000000000000000000000000000000000000 /f

    rem ********“改服务里面恢复,00-无操作,01-重新启动服务   03-运行一个程序   02 -重新启动计算机   14后面00 00 00 XX”

    reg add “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\UsoSvc” /v “Start” /t REG_DWORD /d 4 /f

    rem *******停止 禁用 Update Orchestrator UsoSvc服务   更新适配Orchestrator服务

    reg add “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\UsoSvc” /v “FailureActions” /t REG_BINARY /d 805101000000000000000000030000001400000000000000c0d4010000000000e09304000000000000000000 /f

    rem *******“改服务里面恢复,00-无操作,01-重新启动服务   03-运行一个程序   02 -重新启动计算机   14后面00 00 00 XX”

    reg add “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WaaSMedicSvc” /v “Start” /t REG_DWORD /d 4 /f

    rem *******停止 禁用 Windows update medic service 更新医生服务

    reg add “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WaaSMedicSvc” /v “FailureActions” /t REG_BINARY /d

    840300000000000000000000030000001400000000000000c0d4010000000000e09304000000000000000000 /f

    rem ******“改服务里面恢复,00-无操作,01-重新启动服务   03-运行一个程序   02 -重新启动计算机   14后面00 00 00 XX”

    复制做成BAT文件,以管理员身份运行。

    二、配置组策略:gpedit.msc

    Windows10家庭版没有gpedit.msc,需要配置一下。首先要新建一个txt文件,打开,在里面输入以下内容并保存:

    @echo off

    pushd “%~dp0”

    dir /b C:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientExtensions-Package~3*.mum >List.txt

    dir /b C:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientTools-Package~3*.mum >>List.txt

    for /f %%i in (‘findstr /i . List.txt 2^>nul’) do dism /online /norestart /add-package:”C:\Windows\servicing\Packages\%%i”

    pause

    将文件后缀改bat,随后右键点击以管理员身份运行,等待加载完成,就可以启用组策略了。

    gpedit0.png

    成功打开组策略编辑器后,在组策略编辑器中,按顺序点开:计算机配置 – 管理模板 -Windows组件 -Windows更新 ,在右侧配置自动更新设置中,将其设置为已禁用并点击下方的确定保存即可

    gpedit1.png
    gpedit2.png
    gpedit3.png
    gpedit4.png
    gpedit5.png
    gpedit6.png

    三、计划任务关闭windows更新:taskschd.msc

    tasks0.png

    在打开的计划任务的界面中,按顺序点击 任务计划程序库 – Microsoft -Windows -WindowsUpdate,把里面的项目都设置为禁用,能删除也可以删除。

    tasks.png

    注【高手可操作】:计划任务删除命令是:schtasks /delete /tn “任务名称”   

    终于写完了,测试通过。作者:众嘉软件

  • 老毛桃PE工具可以用,别用它装系统

    很久没有重装系统了,手上有一个Dell的笔记本,系统恢复分区占了好几个,还不挨着,win11装docker还跑不起来,索性重装,用老毛桃PE进去格了盘,然后加载win11重装,结果装完发现系统被注入很多程序和广告,试着装了一下wsl也有问题。还得用原装win11镜像安装。切记。

  • Monorepo+federation+defineAsyncComponent构建一栈式主分前端架构

    构建一栈式主分前端架构,结合 Monorepo、Federation 和 defineAsyncComponent 是一种现代且高效的开发模式,特别适用于大型项目或微前端架构。

    以下是如何将这些技术结合起来实现这一架构的详细步骤:

    1. Monorepo(单仓库多包管理)

    定义: Monorepo 是一种将多个相关的代码库存储在一个单一的版本控制系统中的方法。它允许你更方便地管理和协调多个项目的依赖关系和版本更新。

    工具选择:
    •Lerna:用于管理多个 npm 包。
    •Yarn Workspaces 或 npm workspaces:用于处理多个包之间的依赖关系。(我选的是pnpm,虽然我觉得pnpm这个词打起来最费劲,但我在.zshrc里面给它设置成了p)
    •Nx:不仅支持包管理,还提供了丰富的工具链来优化构建和测试流程。
    优点:
    •统一的代码风格和配置。
    •更容易进行跨项目依赖管理。
    •提高了团队协作效率,减少了重复工作。

    用Monorepo关键的地方有两个:

    1)配置package.json里面的”scripts”,根据调试和打包的组合配置参数。

    2)配置dependencies,将共用的部分放到项目根,不过这一点没有上面那条那么重要,属于优化。

    1. Federation(模块联邦)

    定义: 模块联邦允许多个独立的应用程序或微前端共享模块,而不需要通过传统的打包方式。实现步骤:
    •设置主机应用(Host App):
    •使用 Webpack 5 的 ModuleFederationPlugin 配置远程模块。
    •示例配置: new ModuleFederationPlugin({
    name: ‘hostApp’,
    filename: ‘remoteEntry.js’,
    remotes: {
    remoteApp: ‘remoteApp@http://localhost:3001/remoteEntry.js’,
    },
    shared: [‘react’, ‘react-dom’],
    });

    •设置远程应用(Remote App):
    •同样使用 ModuleFederationPlugin 暴露模块。
    •示例配置: new ModuleFederationPlugin({
    name: ‘remoteApp’,
    filename: ‘remoteEntry.js’,
    exposes: {
    ‘./Button’: ‘./src/Button’,
    },
    shared: [‘react’, ‘react-dom’],
    });

    优点:
    •独立部署和开发。
    •模块级别的共享,减少冗余代码。
    •动态加载远程模块,提升性能。

    当然,我用的是vue,上面是钉钉ai助理给的代码,没有仔细看。后面我会整理代码发布到github上供参考。

    1. defineAsyncComponent(异步组件)

    定义:defineAsyncComponent 是 Vue 3 提供的一个 API,用于定义异步组件。它可以按需加载组件,从而优化初始加载时间和性能。实现步骤:
    •在 Vue 项目中使用 defineAsyncComponent 加载远程组件。 import { defineAsyncComponent } from ‘vue’;

    const RemoteButton = defineAsyncComponent(() =>
    import(‘remoteApp/Button’)
    );

    export default {
    components: {
    RemoteButton,
    },
    };

    优点:
    •按需加载,减少初始加载时间。
    •提升用户体验,特别是在网络条件不佳的情况下。
    综合应用项目结构示例:monorepo/
    ├── packages/
    │ ├── host-app/
    │ │ ├── src/
    │ │ └── webpack.config.js
    │ ├── remote-app/
    │ │ ├── src/
    │ │ └── webpack.config.js
    │ └── shared-components/
    │ ├── src/
    │ └── webpack.config.js
    └── package.json
    构建与部署
    •构建:使用 Lerna 或 Nx 进行统一构建。
    •部署:可以分别部署主机应用和远程应用,确保每个应用可以独立更新和维护。
    总结通过结合 Monorepo、Federation 和 defineAsyncComponent,你可以创建一个高效、可扩展的一栈式主分前端架构。这种方式不仅提高了开发效率,还能有效管理和优化大型项目的复杂度。如果你有更多具体的技术问题或需要进一步的帮助,请随时告诉我!(部分内容由AI生成)

    实际上,我没有采用ssr的架构,而是采用普通的vite。

    实际的目录结构如下:

    /apps/one-main
      package.json
    /packages/one-basic
      package.json
    package.json
    pnpm-workspace.yaml

    one-main作为我的主应用,one-basic作为的分应用之一,后续还会有one-beau之类的,主应用是作为门户提供最终用户访问的门面的,分应用有两个作用,提供remote-component组件以及对remote-component的单独演示,同时也方便调试。

    总体上one-main和one-basic也是同构的,都是采用了https://starchart.cc/xiangshu233/vue3-vant4-mobile这个脚手架,我计划将其中的UI替换为naive-ui,我更喜欢这个简洁的风格。

    简单来说,Monorepo是为了这一组代码库方便联调,Federation提供应用间(远程)组件共享,defineAsyncComponent实现动态加载(远程)组件,将远程组件参数化。最终实现的是一个有限灵活度的模板可配置电子书系统。

    本方案的代码库:https://github.com/futuremeng/one-momorepo