普通视图

发现新文章,点击刷新页面。
今天 — 2025年11月30日首页

我国航空遥感领域多项数据成果发布

2025年11月30日 14:12
记者从中国科学院空天信息创新研究院获悉,在昨天(29日)举行的第二十三届中国遥感大会上,高分辨率机载多维度合成孔径雷达(SAR)地物分类数据集、多波段全极化机载SAR农作物精细分类数据集、机载多角度光学图像与激光点云数据集、典型场景高分光学与SAR全极化多模态特性数据集等典型数据集发布。这些数据集兼具多模态、高分辨率、高精度等属性,将在地物分类、三维重建、图像生成及修复等领域发挥重要作用。 (每经网)

全国首个儿童身心健康脑机临床研究中心在津建立

2025年11月30日 13:35
据天津日报,记者日前从市儿童医院(天津大学儿童医院)获悉,该院和天津大学脑机交互与人机共融海河实验室联合共建全国首个“儿童身心健康脑机临床研究中心”。这一创新平台的建立,标志着我国儿科医疗领域在脑机技术临床转化与儿童身心健康保障方面迈出关键一步。 据介绍,作为面向儿童群体的创新科研平台,该中心聚焦五大重点研究方向:罕见疾病诊疗研究、神经系统疾病精准干预、儿童精神及心理行为干预技术研发、视听等功能评估与康复方案优化以及儿童健康管理与早期干预体系构建。通过整合临床病例资源与前沿技术研发能力,该中心将助力推动儿科医疗模式从传统“对症治疗”向“精准干预+早期预防”转型,打造医工交叉协同创新的标杆项目,为儿童受试者提供标准化试验环境、友好诊疗空间及专业管理团队,为临床药物研发、创新疗法转化及儿科精准诊疗指南制定提供有力支撑。 (天津日报)

长期限大额存单“缺货”,储户转战转让市场寻宝

2025年11月30日 12:51
据第一财经报道,目前多家大型银行APP中,五年期大额存单已难觅踪影,三年期及以上产品也“缺货”,利率水平较前几年大幅下调,甚至出现与普通定存最高利率“倒挂”的罕见现象。多家银行已在APP中开辟“大额存单转让专区”,并大力推广相关交易。(第一财经)

全国海水淡化产业联盟在津成立

2025年11月30日 12:35
据天津日报,全国海水淡化产业联盟成立大会近日在天津港保税区举行。该联盟的成立,标志着我国海水淡化产业迈入协同发展、合作共赢的新阶段,有望进一步增强我国在该领域的整体竞争力。

业内人士:我国近9成老年人倾向于居家养老,潜在护理人才需求或超1000万

2025年11月30日 12:17
据央视财经,国家卫生健康委、民政部等五部门近日印发通知,决定开展为期三年的医养结合促进行动。未来三年,我国将大力发展居家和社区医养结合服务,推动医疗资源较丰富地区的部分二级及以下医疗卫生机构转型为康复医院、护理院,并扩大养老专业人才培养规模。北京协和医学院教授刘远立表示:“根据我们全国调查,87%的老年人选择在家里得到照护服务,这也意味着我们需要大量规范培训的护理员。”调查显示,我国失能老年群体超过4000万人,而持证的养老护理员只有50万人。按照国家标准养老护理员与老人的比例1:4计算,潜在的护理人才需求将达1000万以上。(格隆汇)

海南自贸港首个船东互保组织成立

2025年11月30日 12:04
据海南日报,11月29日,记者从海南国际船舶登记管理局获悉,海南船东互保协会已于日前获得省民政厅批准注册,标志着海南自贸港首个船东互保组织正式成立。该协会是由船东自愿组成的非营利性组织,以互助共济的模式为会员船东提供保赔险等多险种、一站式保险服务。(e公司)

## React Native 中的 dp、dpi 和分辨率,到底是什么关系?

2025年11月30日 11:47

一、三个概念:px、dpi、dp

  1. px:物理像素 / 分辨率里的那个像素 当我们说“720p、1080p”时,其实说的是分辨率:

    • 720p ≈ 1280 × 720 像素
    • 1080p ≈ 1920 × 1080 像素 这里的“1280、1920、720、1080”,都是 px(物理像素点的个数)。
  2. dpi:像素密度(每英寸多少个像素) dpi(dots per inch)表示:一英寸(2.54cm)长度上有多少个像素点。

    • 160dpi:每英寸约 160 个像素
    • 320dpi:每英寸约 320 个像素(比 160dpi 更细腻) dpi 是硬件属性,跟屏幕多大、分辨率多少一起决定“看起来多清晰”。
  3. dp:密度无关像素(React Native 用的逻辑单位) dp(density-independent pixel)是系统定义的一种“逻辑长度单位”,让同样的数值在不同 dpi 的设备上,看起来差不多大。 在 React Native 里,你写 width: 100,这个 100 本质上就是 100dp,而不是 100px。

二、dp 和 dpi 的数学关系

Android / React Native 的约定:

  • 160dpi 的屏幕当成基准屏幕。
  • 在 160dpi 屏幕上:1dp ≈ 1px
  • 在其它密度屏幕上,系统用这个公式换算:px = dp × (dpi / 160)

举几个数字例子:

  • 160dpi(基准) 1dp = 1 × (160 / 160) = 1px 100dp = 100px
  • 320dpi 1dp = 1 × (320 / 160) = 2px 100dp = 200px
  • 480dpi 1dp = 1 × (480 / 160) = 3px 100dp = 300px(四舍五入后近似)

也就是说:

当你在代码里写 width: 100 时,这个 100 实际上是 100dp。系统会根据当前设备的 dpi,把它换算成应该使用多少个物理像素:

  • 在 160dpi 的屏幕上,大约使用 100px(1dp ≈ 1px);
  • 在 320dpi 的屏幕上,大约使用 200px(1dp ≈ 2px);
  • 在 480dpi 的屏幕上,大约使用 300px(1dp ≈ 3px)。

随着屏幕像素密度提高,单个像素本身变得更小,所以虽然不同设备实际使用的物理像素数量不一样,但这个“100dp 宽”的控件在现实世界里的物理尺寸(比如看起来有多宽、占多大一块屏幕)会尽量保持接近。

现在,160/320/480dpi 和 dp→px 的关系就理清楚了,也解释了“为什么同样的 dp 在不同手机上看起来差不多大”。

三、示意图:同样 100dp 的按钮,在不同 dpi / 分辨率上长什么样?

Gemini_Generated_Image_hl6v29hl6v29hl6v.png1)左边:720p,160dpi

  • 分辨率:1280 × 720 px
  • dpi:160
  • 换算:1dp = 1px100dp = 100px
  • 按钮在屏幕上大约占据“某个具体宽度 A 厘米”。

2)中间:1080p,320dpi

  • 分辨率:1920 × 1080 px
  • dpi:320(像素更密)
  • 换算:1dp = 2px100dp = 200px
  • 按钮用更多像素画出来,但因为像素更小,实际占据的物理宽度依然接近 A 厘米。

3)右边:更高分辨率,2K,480dpi

  • 分辨率:例如 2560 × 1440 px(举例)
  • dpi:480
  • 换算:1dp = 3px100dp = 300px
  • 按钮在屏幕上依然大约是 A 厘米宽,只是边缘、文字更细腻。

图中三个按钮,看起来差不多宽,但右边那台的像素数量最多——这就是“dp + dpi 换算”的效果:同样的 dp 值,在高密度屏上用更多 px 去画,从而保持视觉尺寸接近。

四、那 720p、 1080p 在这个故事里扮演什么角色?

  • 720p、1080p 说明的是总像素数(分辨率),即屏幕一共多少个 px。
  • dpi 说明的是这些像素在物理尺寸上的“密度”,和“屏幕有多大”一起决定屏幕看起来多清晰。
  • dp 是在 React Native / Android / iOS 布局里用的“逻辑尺寸单位”,用来写 UI 尺寸。系统会根据当前设备的 dpi 和分辨率,用公式把 dp 换成 px。

你可以大致这样理解:

  • px:砖头总数(分辨率)
  • dpi:每 1cm 摆多少块砖(密度)
  • dp:设计图上画的“这堵墙要 2 米宽”,具体到现场要用多少砖,由工人(系统)根据砖尺寸(dpi)来算。

五、在 React Native 里怎么用 dp 写尺寸?

在 RN 代码里,你不用写 dp、px 这样的单位,直接写数字即可,这个数字默认就是 dp:

// 宽高都是 dp 单位
<View style={{ width: 100, height: 40, borderRadius: 8 }} />

React Native 会做几件事:

  1. 获取当前设备的:
    • 分辨率(总px数)
    • 屏幕尺寸(英寸)
    • 像素密度dpi(ppi)
  2. 用公式 px = dp × (dpi / 160),把你的dp换算成真实px
  3. 把这个px告诉底层原生视图去渲染

你也可以用 DimensionsPixelRatio 看一下当前设备的逻辑尺寸和像素比:

import { Dimensions, PixelRatio } from 'react-native';

const { width, height } = Dimensions.get('window'); // 宽高,单位是 dp
const pixelRatio = PixelRatio.get();                // 设备像素比,约等于 dpi / 160

比如某台设备:

  • width = 375,height = 812(单位是逻辑尺寸dp)
  • pixelRatio = 3
  • 分辨率大约是:宽 375 × 3 = 1125px,高 812 × 3 ≈ 2436px(类似iPhoneX)

六、和设计稿的连接:从px到dp

最后再把“设计稿”这块挂上来,形成闭环:

  1. 设计稿给的一般是px,比如 750 × 1334。
  2. 我们约定它对应某个“逻辑宽度”(比如375dp,即2倍图)。
  3. 换算关系:RN中 dp = 设计稿px / 2(以750px为例)。

西藏人工智能从场景应用走向藏语大模型研发

2025年11月30日 11:44
据中国新闻网,就日前千亿级参数藏语基座大模型“阳光清言”V1.0成果发布,中国工程院院士、西藏大学教授尼玛扎西30日接受采访时表示,“西藏在藏语大模型研发领域取得了重要进展,标志着西藏AI发展将从场景应用走向系统性研发阶段。”作为西藏人工智能自主研发的成果,“阳光清言”V1.0模型训练依托约288亿Token的高质量藏语数据,涵盖新闻、法律、医学、教育、科技等多个领域,包括藏语单语数据、多语种平行语料、双语辞典条目等丰富内容。(中国新闻网)

uni-app开发app之前提须知(IOS/安卓)

作者 鱼樱前端
2025年11月30日 11:44

大家好,我是鱼樱!!!

关注公众号【鱼樱AI实验室】持续分享更多前端和AI辅助前端编码新知识~~

不定时写点笔记写点生活~写点前端经验。

在当前环境下,纯前端开发者可以通过技术深化、横向扩展、切入新兴领域(MCP TOOLS AI应用产品方向 等)以及产品化思维找到突破口。(不管写多久的代码,技术深度广度如何一定要具备独立赚钱的能力呀!!老铁们,因为总有一天你不在职场总有一天会面对选择和职场的无情)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

前端最卷的开发语言一点不为过,三天一小更,五天一大更。。。一年一个框架升级~=嗯,要的就是这样感觉!与时俱进~ 接下来会逐步分享uni-app的一些开发经验。从文档到基础到实战以及遇到的问题~时间节点不限。

最近依旧比较忙,技术文章还是会不定时更新一些核心的技术分享,和大家一起学习前端路程。

前言须知

uni-app App 端内置了一个基于 weex 改进的原生渲染引擎,提供了原生渲染能力,在 App 端,如果使用 vue 页面,则使用 webview 渲染;如果使用 nvue 页面(native vue 的缩写),则使用原生渲染。一个 App 中可以同时使用两种页面,比如首页使用 nvue,二级页使用 vue 页面

虽然 nvue 也可以多端编译,输出 H5 和小程序,但 nvue 的 css 写法受限,所以如果你不开发 App,那么不需要使用 nvue

nvue 的组件和 API 写法与 vue 页面一致

如果你熟悉 weex 或 react native 开发,那么 nvue 是你的更优选择,能切实提升你的开发效率,降低成本

如果你是 web 前端,不熟悉原生排版,那么建议你仍然以使用 vue 页面为主,在 App 端某些 vue 页面表现不佳的场景下使用 nvue 作为强化补充。

uni-app 在 App 端,支持 vue 页面和 nvue 页面混搭、互相跳转。也支持纯 nvue 原生渲染。

启用纯原生渲染模式,可以减少 App 端的包体积、减少使用时的内存占用。因为 webview 渲染模式的相关模块将被移除。

在 manifest.json 源码视图的"app-plus"下配置"renderer":"native",即代表 App 端启用纯原生渲染模式。此时 pages.json 注册的 vue 页面将被忽略,vue 组件也将被原生渲染引擎来渲染。

如果不指定该值,默认是不启动纯原生渲染的。

// manifest.json
{
   // ...
// App平台特有配置
   "app-plus": {
      "renderer": "native", //App端纯原生渲染模式
   }
}

编译模式

weex 编译模式和 uni-app 编译模式(推荐)

weex 的组件和 JS API,与 uni-app 不同。uni-app 与微信小程序相同 主要介绍 uni-app 方式 weex自行了解

image.png

在 manifest.json 中修改 2 种编译模式,manifest.json -> app-plus -> nvueCompiler 切换编译模式。 nvueCompiler 有两个值:

  • weex
  • uni-app
// manifest.json
{
// ...
// App平台特有配置
"app-plus": {
"nvueCompiler":"uni-app" //是否启用 uni-app 模式
}
}

原生开发没有页面滚动的概念,页面内容高过屏幕高度时,内容并不会自动滚动;只有将页面内容放在listwaterfallscroll-view/scroller这几个组件下内容才可滚动。这不符合前端开发的习惯,所以在 nvue 编译为 uni-app模式时,uni-app框架会给 nvue 页面外层自动嵌套一个 scroller,从而实现页面内容的自动滚动。

注意

  • uni-app框架仅对 nvue 页面嵌套scroller容器,不会给组件自动套scroller容器;
  • 若 nvue 页面有recycle-list组件时,uni-app框架也不会自动给页面嵌套scroller容器
  • 若你不希望自动嵌套scroller容器,可在pages.json中通过如下配置进行关闭:
{
    "path": "",
    "style": {
        "disableScroll": true // 不嵌套 scroller
    }
}

HBuilderX 3.1.0+ 开始支持新的样式编译模式

  • weex 编译模式:老模式,样式支持与普通 weex 相同
  • uni-app 编译模式:新模式,在 weex 原有样式基础上支持组合选择器(相邻兄弟选择器、普通兄弟选择器、子选择器、后代选择器)详见
  // manifest.json
  {
      // ...
      // App平台特有配置
      "app-plus":  {
          "nvueStyleCompiler": "uni-app"
      }
  }

快速上手

在 HBuilderX 的 uni-app 项目中,新建页面,弹出界面右上角可以选择是建立vue页面还是nvue页面,或者 2 个同时建

不管是 vue 页面还是 nvue 页面,都需要在pages.json中注册。如果在 HBuilderX 中新建页面是会自动注册的,如果使用其他编辑器,则需要自行在 pages.json 里注册。

如果一个页面路由下同时有 vue 页面和 nvue 页面,即出现同名的 vue 和 nvue 文件。那么在 App 端,会仅使用 nvue 页面,同名的 vue 文件将不会被编译到 App 端。而在非 App 端,会优先使用 vue 页面。

如果不同名,只有 nvue 页面,则在非 app 端,只有 uni-app 编译模式的 nvue 文件才会编译。

image.png

开发 nvue 页面需注意

nvue 页面结构同 vue, 由 templatestylescript 构成。

  • template: 模板写法、数据绑定同 vue。组件支持 2 种模式,

  • style:由于采用原生渲染,并非所有浏览器的 css 均支持,布局模型只支持 flex 布局,虽然不会造成某些界面布局无法实现,但写法要注意。详见:样式

  • script:写法同 vue,并支持 3 种 API:

调试 nvue 页面

HBuilderX 内置了 weex 调试工具的强化版,包括审查界面元素、看 log、debug 打断点,详见

注意事项

  • vue 和 nvue 页面均支持断点调试
  • 目前仅支持 nvue 页面审查元素,vue 页面暂不支持,以及 Android 平台的 nvue 审查元素暂不支持查看 style
  • App 端提供真机运行的console.log日志输出,运行到真机或模拟器时,不用点debug按钮,运行手机 App,会在HBuilderX的控制台直接输出日志。
  • 如果是调试App的界面和常规 API,推荐编译到 H5 端,点HBuilderX右上角的预览,在内置浏览器里调Dom,保存后立即看到结果,调试更方便。并且 H5 端也支持titleNView的各种复杂设置。唯一要注意的就是css兼容性,使用太新的csspc上预览可能正常,但低端Android上异常,具体可查询caniuse等网站。
  • 常用的开发模式就是pc上使用内置浏览器预览调 dom,运行到真机上看console.log。如果是很复杂的问题才使用debug
  • uni-app 的 App 端的 webkit remote debug,只能调试视图层,不能调试逻辑层。因为 uni-app 的 js 不是运行在 webview 里,而是独立的 jscore 里。
  • 部分 manifest 配置,如三方 sdk 配置,需要打包后生效的,可以打包一个自定义运行基座。打包自定义基座后运行这个自定义基座,同样可以真机运行和 debug。打包正式包将无法真机运行和 debug。
  • 调试依赖 chrome 安装位置,找不到可能会导致调试报错。社区反馈中有用户主动修改了 chrome 的安装位置,导致内置的 puppeteer 查找 chrome失败,如果你修改了 chrome 的安装位置,请参考 《HBuilderX APP端 uni/nvue 调试报错问题

nvue开发与vue开发的常见区别

  1. nvue 页面控制显隐只可以使用v-if不可以使用v-show
  2. nvue 页面只能使用flex布局,不支持其他布局方式。页面开发前,首先想清楚这个页面的纵向内容有什么,哪些是要滚动的,然后每个纵向内容的横轴排布有什么,按 flex 布局设计好界面。
  3. nvue 页面的布局排列方向默认为竖排(column),如需改变布局方向,可以在 manifest.json -> app-plus -> nvue -> flex-direction 节点下修改,仅在 uni-app 模式下生效。详情
  4. nvue页面编译为H5、小程序时,会做一件css默认值对齐的工作。因为weex渲染引擎只支持flex,并且默认flex方向是垂直。而H5和小程序端,使用web渲染,默认不是flex,并且设置display:flex后,它的flex方向默认是水平而不是垂直的。所以nvue编译为H5、小程序时,会自动把页面默认布局设为flex、方向为垂直。当然开发者手动设置后会覆盖默认设置。
  5. 文字内容,必须、只能在<text>组件下。不能在<div><view>text区域里直接写文字。否则即使渲染了,也无法绑定js里的变量。
  6. 只有text标签可以设置字体大小,字体颜色。
  7. 布局不能使用百分比、没有媒体查询。
  8. nvue 切换横竖屏时可能导致样式出现问题,建议有 nvue 的页面锁定手机方向。
  9. 支持的css有限,不过并不影响布局出你需要的界面,flex还是非常强大的。详见
  10. 不支持背景图。但可以使用image组件和层级来实现类似web中的背景效果。因为原生开发本身也没有web这种背景图概念
  11. css选择器支持的比较少,只能使用 class 选择器。详见
  12. nvue 的各组件在安卓端默认是透明的,如果不设置background-color,可能会导致出现重影的问题。
  13. class 进行绑定时只支持数组语法。
  14. Android端在一个页面内使用大量圆角边框会造成性能问题,尤其是多个角的样式还不一样的话更耗费性能。应避免这类使用。
  15. nvue页面没有bounce回弹效果,只有几个列表组件有bounce效果,包括 listrecycle-listwaterfall
  16. 原生开发没有页面滚动的概念,页面内容高过屏幕高度并不会自动滚动,只有部分组件可滚动(listwaterfallscroll-view/scroller),要滚的内容需要套在可滚动组件下。这不符合前端开发的习惯,所以在 nvue 编译为 uni-app模式时,给页面外层自动套了一个 scroller,页面内容过高会自动滚动。(组件不会套,页面有recycle-list时也不会套)。后续会提供配置,可以设置不自动套。
  17. 在 App.vue 中定义的全局js变量不会在 nvue 页面生效。globalDatavuex是生效的。
  18. App.vue 中定义的全局css,对nvue和vue页面同时生效。如果全局css中有些css在nvue下不支持,编译时控制台会报警,建议把这些不支持的css包裹在条件编译里,APP-PLUS-NVUE
  19. 不能在 style 中引入字体文件,nvue 中字体图标的使用参考:加载自定义字体。如果是本地字体,可以用plus.io的API转换路径。
  20. 目前不支持在 nvue 页面使用 typescript/ts21. nvue 页面关闭原生导航栏时,想要模拟状态栏,可以参考文章。但是,仍然强烈建议在nvue页面使用原生导航栏。nvue的渲染速度再快,也没有原生导航栏快。原生排版引擎解析json绘制原生导航栏耗时很少,而解析nvue的js绘制整个页面的耗时要大的多,尤其在新页面进入动画期间,对于复杂页面,没有原生导航栏会在动画期间产生整个屏幕的白屏或闪屏。

iOS 平台下拉组件 refresh 组件注意问题

iOS 平台默认情况下滚动容器组件(如listwaterfall组件)内容不足时,由于没有撑满容器的可视区域会导致无法上下滚动,此时无法操作下拉刷新功能,无法触发refresh组件的@refresh@pullingdown事件。 此时可在容器组件中配置alwaysScrollableVertical属性值为true来设置支持上下滚动,支持下拉刷新操作。

Android 平台不存在此问题

用法

<list class="scroll-v list" enableBackToTop="true" scroll-y alwaysScrollableVertical="true">
<refresh class="refresh" @refresh="onrefresh()" @pullingdown="onpullingdown">
<!-- refresh content -->
</refresh>
<cell v-for="(newsitem,index) in list" :key="newsitem.id">
<!-- cell content -->
</cell>
</list>

image.png

HTML5+ 能力

uni-app App 端内置 HTML5+ 引擎,让 js 可以直接调用丰富的原生能力

image.png

条件编译调用 HTML5+

小程序及 H5 等平台是没有 HTML5+ 扩展规范的,因此在 uni-app 调用 HTML5+ 的扩展规范时,需要注意使用条件编译。否则运行到h5、小程序等平台会出现 plus is not defined错误。

// #ifdef APP-PLUS
var appid = plus.runtime.appid;
console.log('应用的 appid 为:' + appid);
// #endif

uni-app不需要 plus ready

在html中使用plus的api,需要等待plus ready。 而uni-app不需要等,可以直接使用。而且如果你调用plus ready,反而不会触发。

uni-app 中的事件监听

在普通的 H5+ 项目中,需要使用 document.addEventListener 监听原生扩展的事件。

uni-app 中,没有 document。可以使用 plus.globalEvent.addEventListener 来实现。

// #ifdef APP-PLUS
// 监听新意图事件
plus.globalEvent.addEventListener('newintent', function(){});
// #endif

复制代码

同理,在 uni-app 中使用 Native.js 时,一些 Native.js 中对于原生事件的监听同样需要按照上面的方法去实现。

Native.js 能力

Native.js技术,简称NJS,是一种将手机操作系统的原生对象转义,映射为JS对象,在JS里编写原生代码的技术。 如果说Node.js把js扩展到服务器世界,那么Native.js则把js扩展到手机App的原生世界。 HTML/JS/Css全部语法只有7万多,而原生语法有几十万,Native.js大幅提升了HTML5的能力。 NJS突破了浏览器的功能限制,也不再需要像Hybrid那样由原生语言开发插件才能补足浏览器欠缺的功能。 NJS编写的代码,最终需要在HBuilder里打包发行为App安装包,或者在支持Native.js技术的浏览器里运行。目前Native.js技术不能在普通手机浏览器里直接运行。

  • NJS大幅扩展了HTML5的能力范围,原本只有原生或Hybrid App的原生插件才能实现的功能如今可以使用JS实现。
  • NJS大幅提升了App开发效率,将iOS、Android、Web的3个工程师组队才能完成的App,变为1个web工程师就搞定。
  • NJS不再需要配置原生开发和编译环境,调试、打包均在HBuilder里进行。没有mac和xcode一样可以开发iOS应用。
  • 如果不熟悉原生API也没关系,我们汇总了很多NJS的代码示例,复制粘贴就可以用。ask.dcloud.net.cn/article/114

再次强调,Native.js不是一个js库,不需要下载引入到页面的script中,也不像nodejs那样有单独的运行环境,Native.js的运行环境是集成在5+runtime里的,使用HBuilder打包的app或流应用都可以直接使用Native.js。

注意事项:

  • Uni-app不支持Native.js执行UI相关操作的API调用及webview相关API调用。将失效无法正常使用。Uni-app不推荐使用Native.js

  • Native API具有平台依赖性,所以需要通过以下方式判断当前的运行平台

function judgePlatform(){
switch ( plus.os.name ) {
case "Android":
// Android平台: plus.android.*
break;
case "iOS":
// iOS平台: plus.ios.*
break;
default:
// 其它平台
break;
}
}
  • 在NJS中调用Native API或从Native API返回数据到NJS时会自动转换数据类型

image.png

技术要求

由于NJS是直接调用Native API,需要对Native API有一定了解,知道所需要的功能调用了哪些原生API,能看懂原生代码并参考原生代码修改为JS代码。 否则只能直接copy别人写好的NJS代码。

renderjs能力

renderjs是一个运行在视图层的js。它比WXS更加强大。它只支持app-vue和web。

renderjs的主要作用有2个:

  1. 大幅降低逻辑层和视图层的通讯损耗,提供高性能视图交互能力
  2. 在视图层操作dom,运行 for web 的 js库

image.png

  • nvue的视图层是原生的,无法运行js。但提供了bindingx技术来解决通信阻塞。详见
  • 微信小程序下替代方案是wxs,这是微信提供的一个裁剪版renderjs。详见
  • web下不存在逻辑层和视图层的通信阻塞,也可以直接操作dom,所以在web端使用renderjs主要是为了跨端复用代码。如果只开发web端,没有必要使用renderjs
<script module="test" lang="renderjs">
export default {
mounted() {
// ...
},
methods: {
// ...
}
}
</script>

过去的问题

  • H5端流行的echart报表因为涉及大量dom操作,无法跨端使用
  • wx-chart在跨端和更新方面都不足
  • 插件市场提供了比wx-chart更好的、全端可用的uChart。但受限于小程序架构逻辑层和视图层分离,导致的通信折损,图表的动画性能不佳。并且uchart只实现了echart的常用功能,还有一些功能没有实现。

新的解决方案

从uni-app 2.5.5+起,新提供了renderjs技术。它是wxs的升级版,一种可以运行在视图层的js。

通过renderjs编写的代码,直接运行在视图层(也就是webview中),可以完整的运行echart等库,并且没有了逻辑层和视图层频繁通行的折损,让动画不再卡顿。

renderjs支持app-vue和h5,不支持其他平台。如果你只考虑这2个平台,可以直接使用本示例,使用完整版的echart。如果还要兼容多端小程序,建议仍然使用uchart。

renderjs,不止能运行echart,其他如F2、threejs等web库都可以运行。

renderjs使用注意事项

  • 目前仅支持内联使用。
  • 不要直接引用大型类库,推荐通过动态创建 script 方式引用。
  • 可以使用 vue 组件的生命周期(不支持 beforeDestroy、destroyed、beforeUnmount、unmounted),不可以使用 App、Page 的生命周期
  • 视图层和逻辑层通讯方式与 WXS 一致,另外可以通过 this.$ownerInstance 获取当前组件的 ComponentDescriptor 实例。
  • this.$ownerInstance.callMethod() 仅支持调用逻辑层vue选项式中的 methods 中定义的方法。
  • 注意逻辑层给数据时最好一次性给到渲染层,而不是不停从逻辑层向渲染层发消息,那样还是会产生逻辑层和视图层的多次通信,还是会卡
  • 观测更新的数据在视图层可以直接访问到。
  • APP 端视图层的页面引用资源的路径相对于根目录计算,例如:./static/test.js。
  • APP 端可以使用 dom、bom API,不可直接访问逻辑层数据,不可以使用 uni 相关接口(如:uni.request)
  • H5 端逻辑层和视图层实际运行在同一个环境中,相当于使用 mixin 方式,可以直接访问逻辑层数据。
  • vue3 项目不支持 setup script 用法。

APP 离线 SDK

App离线开发工具包,即App离线SDK,是把App运行环境(runtime)封装为原生开发调用接口,开发者可以在自己的 Android 及 iOS 原生开发环境配置工程使用,包括 Android离线开发SDK 及 iOS离线开发SDK。

注意:本SDK仅限于uni-app项目使用

使用 Node.js 批量导入多语言标签到 Strapi

2025年11月30日 11:40

在多语言网站开发中,我们常常需要在 Strapi 中维护大量的标签(Tags),比如文章标签、产品分类标签等。如果手动在后台创建上百条标签,会非常耗时且容易出错。本文将介绍如何使用 Node.js 脚本批量导入标签,并支持多语言(英文 / 德语 / 法语)与自动生成 slug。


一、项目背景

假设我们有一个 Next.js + Strapi 项目,Strapi 作为内容管理系统(CMS),我们希望:

  • 批量导入 1000+ 标签
  • 支持多语言(en / de / fr)
  • 自动生成 URL slug
  • 避免重复创建

为了实现这些目标,我们可以写一个 Node.js 脚本,调用 Strapi 的 REST API 来批量创建标签。


二、准备工作

  1. 获取 Strapi API Token 在 Strapi 后台创建一个 API Token,选择 Full Access 或者至少有 Tags CRUD 权限。 在项目根目录创建 .env 文件:

    STRAPI_API_URL=https://your-strapi-domain.com
    STRAPI_API_TOKEN=YOUR_API_TOKEN
    
  2. 安装依赖

    npm install node-fetch@2 dotenv
    
  3. 准备标签数据 我们将标签写成 tags.json 文件,示例:

    {
      "tags": [
        {
          "title_en": "Economy",
          "title_de": "Wirtschaft",
          "title_fr": "Économie",
          "slug_en": "economy",
          "slug_de": "wirtschaft",
          "slug_fr": "economie"
        },
        {
          "title_en": "Technology",
          "title_de": "Technologie",
          "title_fr": "Technologie",
          "slug_en": "technology",
          "slug_de": "technologie",
          "slug_fr": "technologie"
        }
      ]
    }
    

三、核心脚本解析

以下是 import_tags_to_strapi.js 的核心实现:

const fs = require('fs');
const fetch = require('node-fetch'); // npm install node-fetch@2
require('dotenv').config();

const STRAPI_URL = process.env.STRAPI_API_URL || 'http://localhost:1337';
const TOKEN = process.env.STRAPI_API_TOKEN;

const raw = fs.readFileSync('tags.json', 'utf8');
const { tags } = JSON.parse(raw);

// helper: sleep
const sleep = (ms) => new Promise((res) => setTimeout(res, ms));

1. 创建英文标签

const enBody = {
  data: {
    title: tagObj.title_en,
    slug: tagObj.slug_en
  }
};
await fetch(`${STRAPI_URL}/api/tags?populate=none`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${TOKEN}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(enBody)
});

2. 创建德语和法语本地化

const deBody = {
  data: { title: tagObj.title_de, slug: tagObj.slug_de },
  locale: 'de'
};
await fetch(`${STRAPI_URL}/api/tags/${createdId}/localizations`, { ... });

const frBody = {
  data: { title: tagObj.title_fr, slug: tagObj.slug_fr },
  locale: 'fr'
};
await fetch(`${STRAPI_URL}/api/tags/${createdId}/localizations`, { ... });

这里使用了 Strapi Localizations API,保证不同语言之间的标签关联。

3. 批量处理与防刷限流

for (let i = 0; i < tags.length; i++) {
  await createTag(tags[i], i + 1);
  await sleep(200); // 避免 API 请求过快
}

四、运行脚本

node import_tags_to_strapi.js

执行后,你会看到:

1 created EN id= 15
1 created DE localization
1 created FR localization
2 created EN id= 16
...
done import

五、注意事项

  1. API Token 权限:确保 Token 有 Tag 的读写权限。
  2. slug 唯一性:Strapi 对 slug 有唯一性要求,建议提前生成或使用 slugify
  3. 请求频率:一次导入大量标签时,增加 sleep 时间可避免 Strapi 报 429。
  4. 多语言管理:Localizations API 保证标签在多语言之间关联,便于前端展示。

六、总结

通过 Node.js 脚本批量导入 Strapi 标签可以大幅提高效率,并且可以:

  • 支持上千条标签
  • 自动生成 slug
  • 支持多语言
  • 可在 CI/CD 或部署脚本中重复执行

这种方式特别适合新闻网站、博客、产品目录、跨语言项目等。

【URP】Unity[内置Shader]非光照Unlit

作者 SmalBox
2025年11月30日 11:38

【从UnityURP开始探索游戏渲染】专栏-直达

URP内置Unlit Shader的作用与原理

Unlit Shader是Unity通用渲染管线(URP)中的基础着色器,主要用于渲染不受光照影响的物体。其核心原理是通过直接采样纹理或颜色值输出到屏幕,跳过了复杂的光照计算流程。这种着色器特别适合UI元素、粒子特效、全息投影等需要保持恒定亮度的场景,因为它的渲染结果不会随光照环境变化而改变。

在URP架构中,Unlit Shader通过ShaderLab语法定义,内部使用HLSL编写核心逻辑。与Built-in管线相比,URP版本优化了渲染流程,包含三个关键Pass:主绘制Pass、深度Only Pass和元数据Pass(用于光照烘焙)。其核心特点是:

  • 无光照计算:直接输出Albedo颜色或纹理采样结果
  • 支持Alpha混合:可实现透明效果
  • 移动端优化:减少了GPU指令数量

发展历史演变

Unlit Shader随着Unity渲染管线的演进经历了三个阶段:

  • Built-in管线时期‌(2012-2018):最初作为简单着色器出现在标准资源包中,使用CG语言编写,功能较为基础
  • LWRP过渡期‌(2018-2020):轻量级渲染管线中首次针对移动平台优化,引入HLSL替代CG
  • URP成熟期‌(2020至今):成为Universal RP的核心组件,支持Shader Graph可视化编程,并优化了多Pass协作机制

具体使用示例

创建Unlit材质的基本步骤:

  • 在Project窗口右键创建Material
  • 材质Inspector中选择Shader路径:"Universal Render Pipeline/Unlit"
  • 配置基础属性:
    • Base Map‌:主纹理贴图
    • Base Color‌:色调叠加
    • Alpha‌:透明度控制

代码说明:

  • 定义包含纹理和颜色属性的基础Unlit Shader

  • 使用URP核心库中的TransformObjectToHClip方法进行坐标转换

  • 片元着色器直接返回纹理采样结果与颜色的乘积

  • UnlitExample.shader

    Shader "Custom/UnlitTexture"
    {
        Properties {
            _MainTex ("Texture", 2D) = "white" {}
            _Color ("Color", Color) = (1,1,1,1)
        }
        SubShader {
            Tags { "RenderType"="Opaque" }
            Pass {
                HLSLPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    
                struct Attributes {
                    float4 positionOS : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct Varyings {
                    float4 positionCS : SV_POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                sampler2D _MainTex;
                float4 _Color;
    
                Varyings vert(Attributes IN) {
                    Varyings OUT;
                    OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
                    OUT.uv = IN.uv;
                    return OUT;
                }
    
                half4 frag(Varyings IN) : SV_Target {
                    return tex2D(_MainTex, IN.uv) * _Color;
                }
                ENDHLSL
            }
        }
    }
    
  • UnlitGraph.shadergraph

    {
        "m_Nodes": [
            {
                "m_Id": "d4f5e3c7-1a2d-4b8f-a3e1-6c9b8d2e1f0a",
                "m_Type": "UnityEditor.ShaderGraph.Texture2DNode",
                "m_Position": { "x": -208, "y": -16 },
                "m_Outputs": [ { "m_Id": "out" } ],
                "m_Texture": { "m_DefaultValue": {} }
            },
            {
                "m_Id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
                "m_Type": "UnityEditor.ShaderGraph.ColorNode",
                "m_Position": { "x": -200, "y": 100 },
                "m_Outputs": [ { "m_Id": "out" } ],
                "m_Color": { "r": 1, "g": 1, "b": 1, "a": 1 }
            },
            {
                "m_Id": "b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7",
                "m_Type": "UnityEditor.ShaderGraph.MultiplyNode",
                "m_Position": { "x": 0, "y": 0 },
                "m_Inputs": [
                    { "m_Id": "a", "m_SlotId": 0 },
                    { "m_Id": "b", "m_SlotId": 1 }
                ],
                "m_Outputs": [ { "m_Id": "out" } ]
            }
        ],
        "m_Edges": [
            { "m_OutputSlot": "d4f5e3c7-1a2d-4b8f-a3e1-6c9b8d2e1f0a.out", "m_InputSlot": "b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7.a" },
            { "m_OutputSlot": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6.out", "m_InputSlot": "b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7.b" }
        ]
    }
    

Shader Graph应用示例

在Shader Graph中创建Unlit效果的步骤:

  • 创建新的Shader Graph文件(右键 > Create > Shader > Universal Render Pipeline > Unlit Shader Graph)
  • 核心节点配置:
    • 添加‌Sample Texture 2D‌节点作为基础纹理输入
    • 连接‌Color‌参数节点实现色调控制
    • 使用‌Multiply‌节点混合纹理和颜色
  • 高级功能扩展:
    • 添加‌Time‌节点驱动UV动画
    • 通过‌Vertex Position‌节点实现顶点变形

代码说明:

  • 构建包含纹理采样和颜色混合的基础Unlit着色器

  • 通过节点连接实现材质属性的可视化编辑

  • 可扩展添加UV滚动、顶点动画等高级效果

  • UnlitExample.shader

    Shader "Custom/UnlitTexture"
    {
        Properties {
            _MainTex ("Texture", 2D) = "white" {}
            _Color ("Color", Color) = (1,1,1,1)
        }
        SubShader {
            Tags { "RenderType"="Opaque" }
            Pass {
                HLSLPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    
                struct Attributes {
                    float4 positionOS : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct Varyings {
                    float4 positionCS : SV_POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                sampler2D _MainTex;
                float4 _Color;
    
                Varyings vert(Attributes IN) {
                    Varyings OUT;
                    OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
                    OUT.uv = IN.uv;
                    return OUT;
                }
    
                half4 frag(Varyings IN) : SV_Target {
                    return tex2D(_MainTex, IN.uv) * _Color;
                }
                ENDHLSL
            }
        }
    }
    
  • UnlitGraph.shadergraph

    {
        "m_Nodes": [
            {
                "m_Id": "d4f5e3c7-1a2d-4b8f-a3e1-6c9b8d2e1f0a",
                "m_Type": "UnityEditor.ShaderGraph.Texture2DNode",
                "m_Position": { "x": -208, "y": -16 },
                "m_Outputs": [ { "m_Id": "out" } ],
                "m_Texture": { "m_DefaultValue": {} }
            },
            {
                "m_Id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
                "m_Type": "UnityEditor.ShaderGraph.ColorNode",
                "m_Position": { "x": -200, "y": 100 },
                "m_Outputs": [ { "m_Id": "out" } ],
                "m_Color": { "r": 1, "g": 1, "b": 1, "a": 1 }
            },
            {
                "m_Id": "b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7",
                "m_Type": "UnityEditor.ShaderGraph.MultiplyNode",
                "m_Position": { "x": 0, "y": 0 },
                "m_Inputs": [
                    { "m_Id": "a", "m_SlotId": 0 },
                    { "m_Id": "b", "m_SlotId": 1 }
                ],
                "m_Outputs": [ { "m_Id": "out" } ]
            }
        ],
        "m_Edges": [
            { "m_OutputSlot": "d4f5e3c7-1a2d-4b8f-a3e1-6c9b8d2e1f0a.out", "m_InputSlot": "b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7.a" },
            { "m_OutputSlot": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6.out", "m_InputSlot": "b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7.b" }
        ]
    }
    

实际应用时可结合粒子系统创建发光轨迹,或为UI元素添加动态高亮效果。URP Unlit Shader的轻量级特性使其在移动设备上能保持60fps以上的渲染性能

典型应用场景及实现

光晕效果(Halo)

  • 应用实例‌:角色技能特效、UI高亮提示。通过透明纹理实现边缘发光,如1中描述的透明光晕材质。
  • 实现步骤‌:
    • 导入纹理并设置:Texture TypeDefault (sRGB),勾选Alpha Is TransparencyWrap Mode设为Clamp
    • 创建材质:选择Universal Render Pipeline/Unlit Shader,设置Surface TypeTransparent,拖拽纹理到Base Map插槽。
    • 调整Tint颜色控制光晕色彩。

全息投影效果

  • 应用实例‌:科幻场景中的虚拟角色或界面。结合透明度与扫描线纹理。
  • 实现步骤‌:
    • 使用Unlit Shader并启用透明混合(Blend SrcAlpha OneMinusSrcAlpha)。
    • 添加顶点偏移代码模拟全息抖动,通过_Time变量控制动态效果。
    • 叠加扫描线纹理(如_HologramLine1)和菲涅尔反射增强立体感。

透明遮罩(如塑料薄膜)

  • 应用实例‌:UI遮罩或半透明装饰物。通过Alpha通道控制透明度,如中的塑料薄膜材质。
  • 实现步骤‌:
    • 在图片编辑器中创建带Alpha通道的纹理,白色区域不透明,灰色区域半透明。
    • 材质Shader选择Unlit,设置Transparent模式,纹理绑定到Base Map

发光广告牌(Billboard)

  • 应用实例‌:游戏内固定亮度标识或霓虹灯。直接显示纹理颜色不受光照影响。
  • 实现步骤‌:
    • 使用Unlit Shader,Surface Type设为Opaque
    • 通过Base Map设置发光纹理,调整Tint颜色增强亮度。

景深遮挡标记

  • 应用实例‌:半透明物体深度写入(如玻璃瓶),解决景深效果失效问题。
  • 实现步骤‌:
    • 创建两个材质:一个透明材质(Queue=Transparent),一个深度写入材质(Queue=2000)。
    • 深度写入材质使用Unlit Shader并启用ZWrite On

关键注意事项

  • 渲染顺序‌:透明物体需关闭深度写入(ZWrite Off),并合理设置Queue标签避免混合错误。
  • 性能优化‌:复杂效果(如全息投影)建议结合顶点着色器计算,减少片元着色器负担

【从UnityURP开始探索游戏渲染】专栏-直达 (欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

2025年11月中国汽车经销商库存预警指数为55.6%

2025年11月30日 11:27
11月30日,中国汽车流通协会发布的最新一期“中国汽车经销商库存预警指数调查”VIA(Vehicle Inventory Alert Index)显示,2025年11月中国汽车经销商库存预警指数为55.6%,同比上升3.8个百分点,环比上升3.0个百分点。库存预警指数位于荣枯线之上,汽车流通行业景气度有所下降。(每经网)

中国移动仍为上证180、沪深300等主要指数成份股 调出上证50指数并不代表其基本面发生变化

2025年11月30日 11:16
近日,上交所和中证指数公司公告了2025年下半年的调样安排。根据指数编制方案,上证50指数对样本空间内的证券按照过去一年的A股日均总市值、日均成交金额进行综合排名。如中国移动今年以来股价小幅下跌约5%,A股总市值约为1000亿元,最新排名位于沪市第100名左右,结合成交金额后的综合排名不满足上证50指数的纳入条件,因此在本次调样中被调出。 值得指出的是,本次调样实施后,中国移动仍为上证180、沪深300、中证A500等主要指数的成份股,调出上证50指数并不代表其基本面发生了变化。同时,因权重有限,亦不会对其股价产生显著影响,投资者无需多虑。(上海证券报)

我国单机容量最大燃气电厂首台机组今日投产

2025年11月30日 11:01
我国单机容量最大的燃气电厂——国家能源集团浙江安吉电厂1号机组预计今天(30日)20点完成168小时满负荷试运行,即将正式投产。该项目采用国内单机容量最大、效率最高的燃机,机组效率高达64.15%,与常规百万千瓦燃煤机组相比,效率提升约17个百分点。此次投产的1号机组具备低碳、高效、启停快及变负荷能力强等特点,能精准响应用电峰谷变化,有效保障电网稳定运行,实现与可再生能源的高效互补,为华东电网迎峰度冬贡献力量。(央视新闻)

中信建投:北京、上海等地发文支持医疗器械创新,看好医疗器械行业投资机会

2025年11月30日 10:47
中信建投研报称,近期,北京、上海等地密集发布医疗器械产业高质量发展具体实施措施,从创新器械临床研发、注册上市、落地生产、推广应用、集群发展、数字赋能及出海远航等多维度出发,加大力度支持医疗器械行业发展。中信建投预计国家及各地政府对创新器械的支持政策将持续加强、医疗器械创新有望加速。中信建投继续看好2026年医疗器械板块结构性投资机会,建议把握2026年业绩改善个股的业绩和估值修复机会,多家医疗器械行业细分赛道龙头公司将于2026年迎来加速增长。长期来看,医疗器械行业投资机会来自创新、出海和并购整合,板块的创新和国际化能力得到认可,估值正在重构。(界面新闻)

近期中国电建连签海外多个项目

2025年11月30日 10:32
近期,中国电建相继在多个国家实现“连连签”,涵盖新能源、基础设施等多个领域。项目包括:阿联酋阿布扎比哈兹纳1500兆瓦光伏项目、肯尼亚柯本大坝供水项目、马来西亚槟城轻轨(LRT)项目桩基工程、柬埔寨菩萨省100兆瓦生物质光伏联合电站项目、肯尼亚奈瓦沙供水项目、毛里求斯混合光储项目群、乌兹别克斯坦污水处理厂项目。(证券时报)
❌
❌