普通视图

发现新文章,点击刷新页面。
今天 — 2026年1月16日首页

前端网络实战手册:15个高频工作场景全解析

2026年1月15日 23:57

在前端开发中,网络问题是绕不开的坎——真机调试连不上、端口被占、跨域报错、线上打不开... 这些问题看似棘手,实则有固定排查逻辑。本文整理15个高频工作场景,从问题本质到解决方案逐一拆解,附关键命令与架构解析,帮你快速搞定80%的网络难题。

实战应用:工作场景全解析

场景一:React Native 真机调试红屏问题

img_v3_02tv_dee58d9d-0365-4056-a992-95570b48ea6g.png

问题描述

Metro Bundler 已正常启动,但手机端显示红屏报错:Unable to connect to development server

排查与解决方案

核心原因:手机与电脑属于不同设备,默认监听 localhost:8081 的 Metro 服务仅本机可访问,手机无法穿透到电脑的 127.0.0.1。

示意图说明:电脑(192.168.252.118)运行Metro服务,手机需通过内网IP而非localhost连接,二者需处于同一局域网

  1. 第一步:获取电脑内网IP 执行命令(Mac系统): ipconfig getifaddr en0 示例输出:192.168.252.118(Windows用 ipconfig 查找以太网/无线局域网IPv4)。
  2. 第二步:确认同网环境 手机连接与电脑相同的WiFi,进入手机WiFi设置查看IP,需与电脑IP前三段一致(如 192.168.252.xxx),确保处于同一局域网。
  3. 第三步:配置手机连接地址 在手机RN应用中摇一摇唤起调试菜单 → 进入 Dev Settings → 找到 Debug server host & port → 填入电脑内网IP+端口:192.168.252.118:8081

延伸问题:IP为何每天变化?

因路由器开启 DHCP动态分配,每次联网会重新分配IP。解决方案按优先级排序:

  • 简单方案:每次开发前重新执行命令获取IP。
  • 一劳永逸:在路由器后台绑定电脑MAC地址与固定IP。
  • 谨慎方案:手动设置电脑静态IP(可能与局域网内其他设备冲突)。

场景二:端口被占用报错

问题描述

执行 npm start 启动服务时,终端报错:Error: Port 3000 is already in use

两种解决方案

  1. 方案一:查杀占用进程(推荐) 1. 查找占用端口的进程: lsof -i :3000 终端输出示例: COMMAND PID USER FD TYPE NODE NAME ``node 12345 you 23u IPv4 TCP *:3000 (LISTEN) 2. 强制终止进程(PID为上述输出中的数字): kill -9 12345
  2. 方案二:更换端口启动 临时指定端口启动: PORT=3001 npm start 若为Vite项目: vite --port 3001

场景三:跨域问题(CORS)

img_v3_02tv_815b78f4-159f-4fdd-8499-d50d2e41ef3g.png

问题描述

前端(localhost:3000)请求后端接口(localhost:8080),浏览器控制台报错: Access to fetch has been blocked by CORS policy

问题本质:同源策略

浏览器同源策略要求:协议、域名、端口三者必须完全一致,否则拦截跨域请求。本例中端口不同(3000 vs 8080),属于跨域场景。

示意图说明:前端localhost:3000与后端localhost:8080虽域名相同,但端口不一致,属于跨域请求,需通过代理或CORS头解决

解决方案

  1. 方案一:开发环境配置代理(推荐) 以Vite为例,修改 vite.config.js export default { `` server: { `` proxy: { `` '/api': { // 匹配所有以/api开头的请求 `` target: 'http://localhost:8080', // 后端接口地址 `` changeOrigin: true // 开启跨域模拟(修改请求头Origin) `` } `` } `` } ``} 前端请求代码(无需写完整后端地址): fetch('/api/users')(实际转发至 http://localhost:8080/api/users),浏览器认为是同源请求,无CORS报错。
  2. 方案二:后端配置CORS头(生产环境) 后端在响应中添加允许跨域的HTTP头,示例: Access-Control-Allow-Origin: https://your-frontend.com(指定允许的前端域名,生产环境避免设为 *)。

场景四:让同事访问你的本地服务

需求

开发完新功能,需让同局域网的同事/测试直接访问你的本地服务,无需部署。

操作步骤

  1. 第一步:设置服务监听全网地址 默认服务监听 127.0.0.1(仅本机可访问),需改为监听 0.0.0.0(允许局域网内所有设备访问): - Vite项目:vite --host 0.0.0.0 - CRA项目:HOST=0.0.0.0 npm start - 配置文件永久设置(Vite): export default { `` server: { `` host: '0.0.0.0' `` } ``}
  2. 第二步:获取内网IP 执行 ipconfig getifaddr en0(Mac),获取本机内网IP(如 192.168.1.100)。
  3. 第三步:告知同事访问地址 同事在浏览器输入:http://192.168.1.100:5173(端口为服务启动端口,Vite默认5173,CRA默认3000)。

注意事项

  • 双方必须连接同一WiFi/局域网。
  • 检查电脑防火墙,确保服务端口(如5173)允许入站连接。

场景五:多环境API配置

实际项目场景

开发过程中需切换不同环境的API地址(本地、开发、测试、生产),避免手动修改代码。

标准化配置方案

// config/api.ts
const API_URLS = {
  // 本地开发:连接本地后端服务
  local: 'http://localhost:8080',
  // 内网开发:连接公司开发服务器
  dev: 'http://192.168.1.200:8080',
  // 测试环境:测试服务器(需权限)
  test: 'https://test-api.company.com',
  // 预发布环境:模拟生产配置
  staging: 'https://staging-api.company.com',
  // 生产环境:线上正式服务
  production: 'https://api.company.com'
};

// 根据环境变量自动切换(需配置APP_ENV)
export const API_BASE_URL = API_URLS[process.env.APP_ENV || 'local'];

地址类型对比表

地址类型 访问范围 示例
localhost 仅本机 http://localhost:8080
内网IP 同一局域网 http://192.168.1.200:8080
公网域名 全世界可访问 api.company.com

场景六:DNS未生效时提前测试

需求

运维部署新服务器(IP:203.0.113.50),但DNS解析尚未生效,需提前验证服务器可用性。

解决方案:修改hosts文件

通过修改本地hosts文件,强制域名指向新IP,绕过DNS解析:

  1. 编辑hosts文件(Mac/Linux): sudo vim /etc/hosts(Windows路径:C:\Windows\System32\drivers\etc\hosts)。
  2. 添加映射关系: 203.0.113.50 api.company.com(左侧为新服务器IP,右侧为目标域名)。
  3. 保存退出后,访问 api.company.com 会直接指向新服务器。

测试完毕后务必删除该映射行,避免影响后续DNS正常生效。

场景七:排查“网站打不开”问题

用户反馈

“你们网站打不开了!”—— 需按流程快速定位问题根源。

系统排查流程

  1. 第一步:验证站点可用性 用curl命令查看响应状态码: curl -I https://your-website.com(-I参数仅返回响应头)。
  2. 第二步:检查DNS解析 确认域名解析的IP是否正确: nslookup your-website.com
  3. 第三步:测试服务器连通性 用ping命令检查网络链路: ping your-website.com(能ping通说明网络可达)。
  4. 第四步:检查端口是否开放 以HTTPS默认端口443为例: nc -zv your-website.com 443(返回succeeded说明端口开放)。
  5. 第五步:追踪路由节点 定位链路中断位置: traceroute your-website.com(某节点超时可能是运营商或防火墙问题)。

现象-原因-责任人对应表

现象 可能原因 对接责任人
DNS解析失败 DNS配置错误、域名过期 运维
ping不通 服务器宕机、网络链路中断 运维
端口不通 防火墙拦截、服务未启动 运维/后端
某节点超时 运营商网络波动 运维(协调运营商)
返回5xx状态码 后端服务异常 后端
返回4xx状态码 前端请求路径/参数错误 前端自查

场景八:与后端/运维高效沟通

错误示范(低效沟通)

你:“接口报错了” 后端:“什么错?” 你:“就是不行” 后端:“...”

正确示范(精准定位)

你:“请求 POST api.test.com/users 返回 502 Bad Gateway,我用 curl -I 访问根域名返回200,但/users路径报错,请求头和参数已核对正确,怀疑是Nginx路由配置漏了或上游服务超时。” 后端:“我看看... 找到了,新接口的路由配置没同步,马上修复。”

报问题必备关键信息清单

  • 完整请求URL(含环境:测试/生产)。
  • HTTP方法(GET/POST/PUT/DELETE)。
  • 返回状态码+完整错误信息(控制台截图/日志)。
  • 已尝试的排查动作(如curl测试、参数核对)。
  • 复现步骤(是否必现、仅特定环境/设备)。

场景九:理解生产环境架构

典型Web应用架构图

示意图说明: 1. 用户发起请求,先经过CDN获取静态资源(JS/CSS/图片); 2. API请求经DNS解析后,由负载均衡分发至内网Web服务器; 3. Web服务器访问内网数据库,最终将结果返回给用户; 4. 数据库、Web服务器均处于内网,外部无法直接访问。

                         用户
                          │
                    ┌─────┴─────┐
                    │    CDN    │ ← 静态资源(JS/CSS/图片)
                    └─────┬─────┘
                          │
                    ┌─────┴─────┐
                    │   DNS     │ ← 域名解析
                    └─────┬─────┘
                          │
                    ┌─────┴─────┐
                    │ 负载均衡   │ ← 公网 IP,分发请求
                    └─────┬─────┘
                          │
         ┌────────────────┼────────────────┐
         │                │                │
    ┌────┴────┐     ┌────┴────┐     ┌────┴────┐
    │ Web 1   │     │ Web 2   │     │ Web 3   │
    │10.0.0.1 │     │10.0.0.2 │     │10.0.0.3 │ ← 内网,外部无法直接访问
    └────┬────┘     └────┬────┘     └────┬────┘
         │                │                │
         └────────────────┼────────────────┘
                          │
                    ┌─────┴─────┐
                    │  数据库    │ ← 最深层,只有 Web 服务器能访问
                    │ 10.0.1.x  │
                    └───────────┘

前端必知关键点

  • 静态资源走CDN:需配置正确的CDN域名,提升加载速度。
  • API请求走负载均衡:配置正式API域名,由负载均衡分发流量。
  • 内网服务器访问限制:Web/数据库服务器在内网,需通过跳板机访问(本地无法直连)。
  • HTTPS强制要求:生产环境必须使用HTTPS,避免浏览器提示“不安全”。

场景十:WebSocket连接调试

img_v3_02tv_5aba4aac-475f-4897-9357-f8602763dc9g.png

HTTP vs WebSocket 对比

HTTP为“一问一答”模式,轮询获取数据效率低;WebSocket为全双工长连接,服务器可主动推送数据,适用于实时聊天、通知等场景。

示意图说明: HTTP轮询:客户端每秒发送请求询问,无数据时返回空响应,浪费带宽; WebSocket:仅一次握手建立连接,服务器有数据时主动推送,无冗余请求。

多环境WebSocket配置

// 开发环境:内网IP + ws协议(不加密)
const ws = new WebSocket('ws://192.168.1.200:8080/chat');

// 生产环境:域名 + wss协议(加密,需HTTPS证书)
const ws = new WebSocket('wss://api.company.com/chat');

// 按环境自动切换
const WS_URL = process.env.NODE_ENV === 'production'
  ? 'wss://api.company.com/chat'
  : 'ws://192.168.1.200:8080/chat';

常见问题排查

  1. 服务器地址/端口是否正确:用 nc -zv 192.168.1.200 8080 测试端口连通性。
  2. 协议是否匹配:开发用ws,生产用wss(wss依赖HTTPS证书,无证书会连接失败)。
  3. 代理/防火墙拦截:检查是否有中间层阻止WebSocket连接(需运维配置放行)。

场景十一:HTTPS证书问题

img_v3_02tv_8854ac27-8d18-4141-b570-370679750c0g.png

用户反馈

“浏览器提示网站不安全,无法正常访问。”

证书排查命令

  1. 用curl查看证书信息: curl -vI https://your-website.com 2>&1 | grep -A 10 "SSL certificate"
  2. 用openssl深度检测: openssl s_client -connect your-website.com:443 -servername your-website.com(可查看证书链、有效期、绑定域名)。

常见证书问题对照表

错误信息 原因 解决方案
Certificate has expired 证书过期 运维续签证书(Let's Encrypt可自动续签)
Hostname mismatch 证书绑定域名与访问域名不一致 检查证书绑定域名,重新签发证书
Unable to verify 证书链不完整(缺少中间证书) 运维配置中间证书,补充完整证书链
Self-signed certificate 使用自签名证书(浏览器不信任) 替换为正规CA签发的证书(如Let's Encrypt)

场景十二:移动端网络调试(抓包)

抓包原理(Charles/Proxyman)

正常请求:手机 → 路由器 → 互联网 → 服务器 抓包请求:手机 → 电脑(代理)→ 路由器 → 互联网 → 服务器(Charles记录所有请求/响应)

示意图说明:电脑运行Charles作为代理服务器,手机通过WiFi连接该代理,所有网络请求均经过Charles,可查看请求头、响应体、状态码等详情,便于调试移动端网络问题。

配置步骤

  1. 获取电脑内网IP:ipconfig getifaddr en0(如 192.168.1.100)。
  2. 启动Charles代理:默认监听8888端口(可在Charles设置中修改)。
  3. 手机配置代理:连接与电脑相同的WiFi → 长按WiFi名称 → 修改网络 → 手动设置代理 → 服务器填电脑IP(192.168.1.100),端口填8888。
  4. HTTPS抓包额外步骤:在Charles中导出CA证书,安装到手机并信任(iOS需在设置→通用→VPN与设备管理中信任,Android需在安全设置中安装)。

场景十三:VPN与内网访问

为什么需要VPN?

公司内网服务器(测试服、开发服、数据库)仅允许内网访问,外部网络(家里、咖啡厅WiFi)无法直连,需通过VPN建立“虚拟隧道”,将本地电脑接入公司内网。

公司内网架构示意图

                    互联网
                       │
              ┌────────┴────────┐
              │    防火墙        │
              └────────┬────────┘
                       │
    ┌──────────────────┼──────────────────┐
    │                  │                  │
┌───┴───┐        ┌────┴────┐        ┌────┴────┐
│测试服务器│      │ 开发服务器 │      │ 数据库    │
│10.0.0.1│       │10.0.0.2 │       │10.0.0.3 │
└───────┘        └─────────┘        └─────────┘

VPN作用与开发影响

  • 无VPN:本地电脑 → 互联网 → 防火墙(拦截)→ 无法访问内网服务器。
  • 有VPN:本地电脑 → VPN隧道 → 公司内网 → 可访问所有内网IP(10.0.0.1/2/3)。
  • 开发配置:连接VPN后,API地址可直接使用内网IP(如 http://10.0.0.2:8080),与在公司内网开发一致。

场景十四:Docker网络问题

核心问题:容器网络隔离

Docker容器有独立网络空间,与本机网络隔离,直接访问容器内服务会失败,需通过端口映射解决。

示意图说明:本机运行Docker容器,容器内服务监听3306端口(MySQL),通过 -p 3306:3306 映射后,访问 localhost:3306 即可穿透到容器内服务。

关键操作:端口映射

# 启动MySQL容器,将本机3306端口映射到容器3306端口
docker run -p 3306:3306 mysql

# 映射规则:-p 本机端口:容器端口
# 示例:本机8080 → 容器80
docker run -p 8080:80 nginx

避坑点

容器内服务需监听 0.0.0.0 而非 127.0.0.1,否则即使映射端口,外部也无法访问:

# 正确(允许容器外部访问)
node server.js --host 0.0.0.0

# 错误(仅容器内可访问)
node server.js --host 127.0.0.1

场景十五:线上问题快速定位清单

问题1:页面加载慢

  1. 检查DNS解析时间:time nslookup your-website.com(耗时过长需联系运维优化DNS)。
  2. 分析服务器响应时间: curl -w "DNS: %{time_namelookup}s\n连接: %{time_connect}s\n首字节: %{time_starttransfer}s\n总时间: %{time_total}s\n" -o /dev/null -s https://your-website.com
  3. 定位慢资源:浏览器F12 → Network → 按“Time”排序,排查大文件、慢接口。
  4. 验证CDN生效:curl -I https://cdn.your-website.com/main.js | grep -i "x-cache",返回 HIT 表示命中缓存,MISS 需优化CDN配置。

问题2:接口返回5xx(服务器错误)

5xx状态码核心含义与应对:

  • 500:后端代码报错 → 提供完整请求参数给后端,协助排查日志。
  • 502:网关/代理问题(Nginx转发失败)→ 告知后端可能是上游服务宕机或超时。
  • 503:服务不可用 → 可能是服务重启或负载过高,联系运维确认。
  • 504:网关超时 → 后端处理耗时过长,建议后端优化接口性能。

问题3:接口返回4xx(客户端错误)

4xx状态码自查清单:

  • 400:请求格式错误 → 检查JSON格式、参数类型。
  • 401:未授权 → 检查Token是否过期、登录状态是否有效。
  • 403:无权限 → 确认当前用户角色是否有访问接口的权限。
  • 404:接口路径错误 → 核对接口URL是否与后端文档一致。

实战技能总结表

场景 核心知识 关键命令/操作
RN真机调试 内网IP、端口访问规则 ipconfig getifaddr en0
端口占用 进程与端口关联 lsof -i :端口 + kill -9 PID
跨域问题 同源策略 Vite代理配置、后端CORS头
同事测试本地服务 0.0.0.0监听规则 --host 0.0.0.0
多环境配置 公网/内网地址区别 环境变量切换API地址
DNS未生效测试 hosts文件作用 修改/etc/hosts绑定IP
网站打不开 DNS、ping、端口校验 nslookup + ping + nc
接口报错 HTTP状态码含义 按状态码判断前后端责任
移动端抓包 代理原理 Charles/Proxyman配置
VPN访问 内网/公网隔离 连接VPN后访问内网IP
Docker服务 端口映射 -p 主机端口:容器端口
HTTPS问题 证书验证原理 openssl s_client

最终总结:学会这些能带来什么?

✅ 独立解决80%的网络问题

以前遇到红屏、跨域、打不开就求助他人;现在能从“网络链路、配置规则、状态码”三个维度定位问题,自主解决大部分场景。

✅ 高效对接后端/运维

从“接口挂了”的模糊描述,升级为“POST /api/users 返回502,Nginx日志显示upstream timeout”的精准定位,大幅提升协作效率。

✅ 建立全局视野

不再局限于前端代码本身,理解“代码→网络→服务器→用户”的完整链路,能从架构层面规避问题,成为具备全局思维的开发者。


如果您觉得这篇文章对您有帮助,欢迎点赞和收藏,大家的支持是我继续创作优质内容的动力🌹🌹🌹也希望您能在😉😉😉我的主页 😉😉😉找到更多对您有帮助的内容。

  • 致敬每一位赶路人

氪星晚报|国内首只千亿黄金ETF诞生;英国通信管理局称将继续调查X平台伪造图像事件;“十五五”国网公司固定资产投资预计4万亿元

2026年1月15日 23:37

大公司:

英国通信管理局称将继续调查X平台伪造图像事件

英国通信管理局表示,对马斯克旗下人工智能公司xAI近期的政策调整表示欢迎,但仍将继续对该公司及其人工智能聊天机器人“格罗克”伪造色情图像展开正式调查。

爱立信计划在瑞典裁员近1600人,旨在改善成本状况

爱立信1月15日宣布拟在瑞典裁员,旨在改善成本状况,同时维持对爱立信技术领先地位和战略执行至关重要的投资。爱立信已向瑞典公共就业服务局提交裁员通知,此次裁员可能影响约1600个职位。公司已与相关瑞典工会展开谈判。

中资券商开始补充投银人手并提高薪资

据知情人士透露,近几个月来,中信证券、华泰证券和中信建投证券等几家大型券商的投银业务部门招募了数十名初级和中级银行家。招聘的新员工以执行岗位为主,而非资深投银家,说明这些公司需要迅速重建业务能力,同时还要控制成本。此外,知情人士称,一些大型券商初级银行家的基本工资已调整回整顿行动前的水平,但奖金池仍然与交易完成情况和监管机构对该行业的态度密切相关。

贾国龙确认:西贝将关闭102家门店

近日,网传西贝在会议中称将一次性关闭全国102家门店,占门店总数的30%。记者就此事向西贝餐饮创始人贾国龙求证,其称消息属实。

KKR与莱茵集团达成战略合作,共同开发英国海上风电项目

1月14日,美国私募股权巨头KKR与德国莱茵集团(RWE)宣布达成战略合作,将共同将共同开发莱茵集团在英国诺福克先锋东区(Norfolk Vanguard East)和诺福克先锋西区(Norfolk Vanguard West)的海上风电项目。这两个新建风电场总装机容量预计将达到约3吉瓦。KKR与莱茵集团将成立一家合资企业,负责建设和运营这两个风电场。该项目总投资开发和资本支出将超过150亿美元,以确保风电场分别于2029年和2030年投入运营。

新产品:

星辰天合举办AIMesh产品战略发布会

36氪获悉,XSKY星辰天合举办主题为“数据常青 智算无界”的AIMesh产品战略发布会,宣告公司战略重心从“信息技术(IT)”全面跨越至“数据智能(Data Intelligence)”。会上发布全栈AI数据方案AIMesh,通过MeshFS、MeshSpace、MeshFusion三大核心产品。

投融资:

“谐盈科技”完成B轮融资

36氪获悉,“谐盈科技”近日完成近亿元B轮融资,由成都高投创业投资有限公司、淮安盛世国控投资基金联合投资。本轮融资将主要用于深化“焬窗”(E-Spectra)智能可重构操作系统的迭代升级、加速“通信+AI”融合产品的研发与量产、拓展在轨道交通、低空经济等国家战略新兴市场的规模化落地,并进一步加强全国化产能与生态合作体系建设。

柠檬茶品牌“林里LINLEE”获数千万融资

36氪获悉,柠檬茶品牌“林里LINLEE”完成了数千万A轮融资,前海方舟基金为独家投资方,估值近10亿,本轮资金主要用于品牌建设,供应链升级及组织升级。

国内首只千亿黄金ETF诞生

上交所数据显示,截至1月14日,华安黄金ETF的流通规模达到1007.62亿元,突破千亿元大关,成为国内首只突破千亿的黄金ETF。

今日观点:

韩国产业部长:将持续关注美国芯片关税动态,最大限度降低产业影响

据韩国产业部一份声明,该国产业部长金廷官(音译)于周四表示,政府将持续关注美国针对部分人工智能半导体芯片征收关税的相关动态,以最大限度降低其对本土产业的冲击。该部门发布的第二份声明称,产业部已与韩国半导体企业代表召开会议,商讨应对策略。此前一日(周三),美国白宫宣布对部分先进芯片征收25%的关税。

其他值得关注的新闻:

为应对政策快速变化,美资管巨头着手卖出美元资产分散风险

美国联邦储备委员会主席鲍威尔遭刑事调查,促使美国资管巨头品浩投资管理公司(原译太平洋投资管理公司)卖出美元资产,以期分散风险。品浩投资管理公司首席投资官丹·伊瓦什钦称,公司正在对其投资组合进行“多元化配置”,以应对美国总统特朗普快速变化的政策。这些政策已导致市场波动加剧。

报告:我国搭载城市NOA功能的乘用车累计销量达到312.9万辆

36氪获悉,中国汽车工业协会发布的《2025城市NOA汽车辅助驾驶研究报告》显示,2025年1至11月,我国搭载城市NOA功能的乘用车累计销量达到312.9万辆,渗透率占乘用车上险量的15.1%,较2024年全年占比提升5.6个百分点。中汽协数据显示,2025年1-11月,Momenta城市NOA搭载量41.44万辆,占第三方供应商比例约61.06%,全球排名前10大车企中,有8家与Momenta开展合作。

“十五五”国网公司固定资产投资预计4万亿元

1月15日,从国家电网公司获悉,“十五五”期间,国家电网公司固定资产投资预计达到4万亿元,较“十四五”投资增长40%,以扩大有效投资带动新型电力系统产业链供应链高质量发展。

CSPJ 教学思考:背包问题

作者 唐巧
2026年1月11日 22:41

引言

背包问题是动态规划中的经典问题,也是 GESP 六级必考的知识点。其原理虽然需要花一些时间,但大多数孩子都能掌握,但是到了具体的题目时,因为背包问题变化较多,就不那么容易写出代码来。

本文将试图把背包问题的各种考法都列举出来,帮助大家巩固练习。

背包问题

背包问题之所以叫这个名字,是因为其背景故事是:往一个容量有限的背包里面,放入一些物品。每个物品有不同的体积大小,所以会占用相应的背包的容量。物品不能被分割,所以要么整个放入背包中,要么不放入。我们需要找出放入背包的价值最大的方案。

举一个简单的例子,背包容量是 10L:

  • 物品 1:体积 7 L,价值 8
  • 物品 2:体积 5 L,价值 5
  • 物品 3:体积 4 L,价值 4

虽然物品 1 的价值最大,价值/体积(即单位体积的价值)也最大,但是因为放入物品 1 之后,剩余的空间 3L 无法再放入别的物品而浪费掉了。就不如不放物品 1,而放入物品 2 和物品 3 带来的总价值大。

由此我们也能看出,背包问题不能用简单的贪心来解决,而需要用动态规划。

解题思路

背包问题的转移方程可以被优化为一维,但为了方便理解,我们先看没有优化的版本。我们定义:

  • 每个元素的体积为 a[i],价值为 v[i]
  • dp[i][j] 表示用前 i 个物品,放入容量为 j 的背包时,所能达到的最大价值

那对于第 i 个物品,如果我们已经知道了前面的结果,那么我们有两种选择:

  • 不放入 第 i 个物品,这样 dp[i][j] = dp[i-1][j]
  • 放入 第 i 个物品,这样 dp[i][j] = dp[i-1][j-a[i]] + v[i]

而以上就是状态转移方程,我们在上面两种情况下取最优的情况:dp[i][j] = max(dp[i-1][j], dp[i-1][j-a[i]] + v[i])

另外我们需要考虑一下初始化的情况,即 dp[0][1~n] 应该怎么赋值。因为前 0 个物品什么都没选,那么价值肯定都是 0,所以让它们都等于 0 即可。

将以上逻辑写成代码如下:

1
2
3
4
5
6
7
memset(dp, 0, sizeof dp);
for (int i = 1; i <= 3; ++i)
for (int j = 1; j <= 10; ++j) {
dp[i][j] = dp[i-1][j];
if (j-a[i]>=0)
dp[i][j] = max(dp[i][j], dp[i-1][j-a[i]] + v[i]);
}

在这段代码中,为了保证 j-a[i] 的值为正,加了一个 if 来检查,保证没有下标越界的代码。如果下标越界,有可能会读取到随机值,也可能读取到非法地址,造成运行异常(Runtime Error)。

我们再用刚刚的例子来做一下表格演示:背包容量是 10L。

  • 物品 1:体积 7 L,价值 8
  • 物品 2:体积 5 L,价值 5
  • 物品 3:体积 4 L,价值 4

经过转移方程的计算,最终,我们可以填出下面这个二维表格,表格中的每一项都计算出来了用前 i 个物品,体积为 j 时的最优化方案。这也是符合动态规划的最优子结构的特征。

01 背包

所谓的 01 背包,就是指物品的数量只有 1 个,只有选与不选两种方案。刚刚的例子就是一个 01 背包的例子。

我们发现 dp[i][j] 只与两个值相关 dp[i-1][j]dp[i-1][j-a[i]],这样的二维数组利用的效率很低。所以,我们就想到,能不能把第 i 维省略掉,这样可以节省存储空间(但没有节省运算时间)。

压缩后的代码如下:

1
2
3
4
5
memset(dp, 0, sizeof dp);
for (int i = 1; i <= 3; ++i)
for (int j = 10; j >= a[i]; --j) {
dp[j] = max(dp[j], dp[j-a[i]] + v[i]);
}

我们注意到,j 的循环方式从正序变成了逆序。之所以要这么操作,读者可以用表格的方式,把正着循环的结果填一下就能明白。

如果 j 不是倒着循环,在一轮 j 的循环过程中,dp[j] 的值会在修改后,再一次被访问到,这样就会使得一个物品实际上已经计算了放入的价值,又被重复计算第二次。

完全背包

一个物品被多次重复放入和重复计算价值,其实是我们在完全背包问题中需要的效果。所以,刚刚的代码,如果我们把 j 正序循环,就是完全背包的代码,如下所示:

1
2
3
4
5
memset(dp, 0, sizeof dp);
for (int i = 1; i <= 3; ++i)
for (int j = a[i]; j <= 10; ++j) {
dp[j] = max(dp[j], dp[j-a[i]] + v[i]);
}

但是为了方便理解,我们还是把完全背包的非压维代码也一并看一下:

1
2
3
4
5
6
7
8
9
memset(dp, 0, sizeof dp);
for (int i = 1; i <= 3; ++i)
for (int j = 1; j <= 10; ++j) {
dp[i][j] = dp[i-1][j];
if (j-a[i]>=0) {
dp[i][j] = max(dp[i][j], dp[i-1][j-a[i]] + v[i]);
dp[i][j] = max(dp[i][j], dp[i][j-a[i]] + v[i]);
}
}

因为 dp[i][j-a[i]] >= dp[i-1][j-a[i]],所以以上代码可以省略成:

1
2
3
4
5
6
7
8
memset(dp, 0, sizeof dp);
for (int i = 1; i <= 3; ++i)
for (int j = 1; j <= 10; ++j) {
dp[i][j] = dp[i-1][j];
if (j-a[i]>=0) {
dp[i][j] = max(dp[i][j], dp[i][j-a[i]] + v[i]);
}
}

我们可以记住这个写法,因为后面有一些题因为各种情况可能无法压维,就会需要这种写法。

我们还是用刚刚的例子来填写二维表格,背包容量是 10L。物品数量改为无限。

  • 物品 1:体积 7 L,价值 8
  • 物品 2:体积 5 L,价值 5
  • 物品 3:体积 4 L,价值 4

以下是填写出来的值:

题目变为完全背包后,可以看到最后答案变了,最优方案变成了放入两个物品 2,得到最大价值 10。

学习完以上内容后,可以让学生练习以下两道题:

题目名 说明
P1048 采药 01 背包问题。NOIP2005 普及组第三题
P1616 疯狂的采药 完全背包问题

多重背包

多重背包描述了这样一种场景,一个物品将同时受两个限制条件的制约,例如:一个背包,即有体积限制,又有重量限制,让你往里放物品,求最大化物品价值的放法。

P1794 装备运输 就是多重背包的一道典型例题,在题目中,每件武器有体积和重量两个限制条件。

对于多重背包,我们同样用前 i 个物品来划分阶段:

  • dp[i][j] 表示 i 体积 j 重量下的最大火力。
  • 转移方程:dp[i][j] = max(dp[i][j], dp[i-v[k]][j-g[k]] + t[k]);

同理,如果物品的数量是无限的,则正着 for,如果物品的数量是有限的,则倒着 for。

P1794 装备运输 的参考代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <bits/stdc++.h>
using namespace std;

int V, G, N, dp[510][510], v[510], g[510], t[510];

int main() {
cin >> V >> G >> N;
for (int i = 1; i <= N; ++i)
cin >> t[i] >> v[i] >> g[i];
for (int k = 1; k <= N; ++k)
for (int i = V; i>= v[k]; i--)
for (int j = G; j >= g[k]; j--)
dp[i][j] = max(dp[i][j], dp[i-v[k]][j-g[k]] + t[k]);
cout << dp[V][G];
return 0;
}

如果把 01 背包和完全背包想像成填一个一维的表格,那么多重背包就在填一个二维的表格。我们需要保证表格的填写过程符合动态规划的阶段性,表格总是从一个方向往另一个方向填,填过的数字不会再次被修改(在没压维的情况下),这样才能保证状态无后效性。

动态规划题目能够划分出清晰的阶段,后一个阶段只依赖于前面的阶段,问题就解决了一大部分。

背包变型一:物品的相互依赖

P1064 金明的预算方案 描述了一种背包问题的变型:在此题中,物品不是简单的 1 个或多个,而是分为主件或附件,每个主件可以有 0 个、1 个或 2 个附件。

应该如何表示这种复杂的物品关系呢?其实,我们可以把物品的每种组合都枚举出来,因为附件数量最多为 2 个,所以情况就可以枚举出以下情况:

  • 不选主件(当然也就没有附件)
  • 选主件,不选附件
  • 选主件+附件 1
  • 选主件+附件 2
  • 选主件+附件 1+附件 2

于是,我们就可以在处理主件的时候,把以上几种情况都比较一下,选最优的方案。

参考代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <bits/stdc++.h>
using namespace std;

struct Node {
int m;
int w;
int t;
};

int n, m;
vector<Node> va;
vector<vector<Node> > vb;
int dp[40000];

void updateDP(int i, int m, int w) {
if (i-m >= 0) {
dp[i] = max(dp[i], dp[i-m] + w);
}
}

int main() {
scanf("%d%d", &n, &m);
va.resize(m);
vb.resize(m);
for (int i = 0; i < m; ++i) {
Node node;
scanf("%d%d%d", &node.m, &node.w, &node.t);
node.w = node.w*node.m;
va[i] = node;
if (node.t != 0) {
vb[node.t - 1].push_back(node);
}
}
memset(dp, 0, sizeof(dp));
for (int i = 0; i < m; ++i) {
// 只处理主件,附件与主体一并处理
if (va[i].t == 0) {
for (int j = n; j > 0; j--) {
// 选主件,不选附件
updateDP(j, va[i].m,va[i].w);
// 选主件+附件 1
if (vb[i].size() > 0) {
int money = va[i].m + vb[i][0].m;
int weight = va[i].w + vb[i][0].w;
updateDP(j, money, weight);
}
// 选主件+附件 2
if (vb[i].size() == 2) {
int money = va[i].m + vb[i][1].m;
int weight = va[i].w + vb[i][1].w;
updateDP(j , money, weight);
}
// 选主件+附件 1+附件 2
if (vb[i].size() == 2) {
int money = va[i].m + vb[i][0].m + vb[i][1].m;
int weight = va[i].w + vb[i][0].w + vb[i][1].w;
updateDP(j, money, weight);
}
}
}
}
cout << dp[n] << endl;
return 0;
}

背包变型二:求最小值

有些时候,我们不是求背包能够装的物品的最大价值,而是求最小价值。例如 B3873 小杨买饮料 这题,此题我们可以把饮料的容量当作背包的容量,把饮料的价格当作价值,但是此题相对于标准的背包问题有两个变化:

  • 1、题目希望求最小的费用,相当于背包所装的物品价值需要最低。
  • 2、题目给定的背包容量不固定,而是“不低于 L”。

针对以上的变化,我们的状态定义虽然不变,用 dp[i][j] 表示前 i 种饮料在 j 容量下的最小价值,但是状态转移变成了:
dp[i][j] = min(dp[i-1][j-l[i]] + c[i], dp[i-1][j])

在这种情况下,初始的第 0 种饮料什么都喝的值为 0,即:dp[0][0] = 0

但是其它的值就不能设置成 0 了,如果设置成 0,那么任何情况下 dp[i][j]就已经是最小的值了,就不能被更新了。我们需要把 dp[i][j]默认的值设置成“无穷大”,这样才可能更新出有意义的值。

在设置无穷大这件事情上,有一个使用 memset 的技巧,即:memset(dp, 0x7f, sizeof dp);,此技巧将每个字节都填充成了二进制的 01111111(即 0x7f),因为最高为是符号位,所以保留成 0。这种 memset 技巧虽然初始化的值比 INT_MAX 略小一点,但是写起来更快,另外在进行加法运算的时候,也不用担心结果溢出成负数。

以上方案解决了变化一。我们再来看变化二。

变化二使得答案不一定在 dp[i][L],因为答案不一定是刚好 L 升,所以要取 L ~ L+max(l[i]) 这一段范围。这样就解决了变化二。

最后我们用滚动数组压维,然后因为是 01 背包(每个饮料只能选一次),我们压维之后需要倒着 for 循环背包大小。

以下是参考代码,代码中用 STL 的 min_element 来求最小值,读者也可以参考这种写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* 01 背包问题的变化
*
* 假设第 i 种饮料的费用是 c[i], 容量是 l[i]
* dp[i][j] 表示用前 i 种饮料,凑成 j 升的最小费用。
*
* 则,转移方程为:
* - dp[i][j] = min( dp[i-1][j-l[i]] + c[i] , dp[i-1][j] )
*
* 因为 i 只与 i-1 相关,所以这一层可以压缩。转移方式优化为:
* - dp[j] = min(dp[j- l[i]] + c[i], dp[j])
*
* 初使化:
* - dp[0] = 0;
* - dp[1-L] = memset(0x7f)
*
* 其它:
* - 倒着 dp,因为每种饮料只能用一次
* - 最大值检查了一下,不会超 int,就不用 long long 了
* - 因为答案不一定是刚好 L 升,所以要取 L ~ L+max(l[i]) 这一段范围
* - 因为是取最小值,所以初使化设置成 0x7f7f7f7f(接近 21 亿,但是又没到 INT_MAX),
* 这样运算不会超 int,又可以是较大值
*
* Author: Tang Qiao
*/
#include <bits/stdc++.h>
using namespace std;

int dp[1010000], c[550], l[550], N, L, maxL;

int main() {
ios::sync_with_stdio(0);
cin >> N >> L;
for (int i = 0; i < N; ++i) {
cin >> c[i] >> l[i];
maxL = max(maxL, l[i]);
}
maxL += L;
memset(dp, 0x7f, sizeof dp);
dp[0] = 0;
for (int i = 0; i < N; ++i) {
for (int j = maxL; j - l[i] >= 0; --j) {
dp[j] = min(dp[j], dp[j - l[i]] + c[i]);
}
}
// 因为答案不一定是刚好 L 升,所以要取 L ~ L+max(l[i]) 这一段范围
int ans = *min_element(dp+L, dp+maxL+1);
if (ans == 0x7f7f7f7f) cout << "no solution" << endl;
else cout << ans << endl;

return 0;
}

以上代码虽然解决了问题,但是还有一点不完美,就是 dp 数组实在太大了。有没有可能 dp 数组更小呢?我们可以想到,因为每种饮料的价格都是正数,所以,如果有一个答案是超过 2*L 升的情况,同时它的价格极低,这种情况下,我们的答案就是只喝这一种饮料。不会出现超过 2*L 升,我们还叠加喝了两种饮料的情况。

我们可以反证:假如有一个答案是喝两种饮料,总容量超过 2*L 升,那么必定有一个饮料的容量是大于等于 L 升的。那么,我们只喝那个大于等于 L 升的饮料,肯定总价格更低。

所以,我们的优化方案就是:我们只需要把 dp 数组的大小开到 2*L 即 4000 即可(题目规定 L 最大为 2000)。在此优化方案下,我们再特判一下每个大于 L 升的饮料,看是不是更便宜。

以下是参考代码,时间和空间复杂度都更优:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <bits/stdc++.h>
using namespace std;

int dp[4100], c[550], l[550], N, L;

int main() {
ios::sync_with_stdio(0);
cin >> N >> L;
for (int i = 0; i < N; ++i) {
cin >> c[i] >> l[i];
}
memset(dp, 0x7f, sizeof dp);
dp[0] = 0;
for (int i = 0; i < N; ++i) {
for (int j = 4000; j - l[i] >= 0; --j) {
dp[j] = min(dp[j], dp[j - l[i]] + c[i]);
}
}
int ans = *min_element(dp+L, dp+4000);
// 如果单个饮料就可以超 L,则判断一下
for (int i = 0; i < N; ++i)
if (l[i] >= L)
ans = min(ans, c[i]);

if (ans == 0x7f7f7f7f) cout << "no solution" << endl;
else cout << ans << endl;

return 0;
}

相关练习题目

推荐练习:

题目名 说明
P2871 Charm Bracelet S 01 背包, USACO 07 DEC
P1802 5 倍经验日 01 背包
P1060 开心的金明 01 背包,NOIP 2006 普及组第二题
P1049 装箱问题 01 背包,NOIP2001 普及组
P1064 金明的预算方案 01 背包变型,NOIP2006 提高组第二题
P2392 考前临时抱佛脚 01 背包变型
P2639 Bessie’s Weight Problem G 01 背包变型,容量与价值相同
B3873 小杨买饮料 01 背包变型, GESP202309 六级
P12207 划分 01 背包的变型,蓝桥杯 2023 国
P1510 精卫填海 01 背包,但是输出要求有变化
P2430 严酷的训练 01 背包,题目较长
P11377 武器购买 01 背包的变型,GESP202412 七级
P13018 调味平衡 01 背包的变型,GESP202506 七级
P1926 小书童——刷题大军 01 背包,需拆成两个子问题
P13015 学习小组 完全背包,GESP 202506 六级
P1679 神奇的四次方数 完全背包,需要求最小值
P1832 A+B Problem 完全背包变型,计数
P10721 计算得分 背包问题变种,GESP 202406 六级
P2918 Buying Hay S USACO08NOV, 求最小值的完全背包
P1794 装备运输 多重背包
P1910 L 国的战斗之间谍 多重背包
P1855 榨取kkksc03 多重背包
P2663 越越的组队 非多重背包的 DP
昨天 — 2026年1月15日首页

iQOO Z11 Turbo 体验:骁龙 8Gen5 冲 1999,国补后可以交个朋友

作者 梁梦麟
2026年1月15日 21:57

1 月 15 日,iQOO 在过年前推出了新一代入门级性能机 iQOO Z11 Turbo,首销定价 2399 元起,国补后起售价为 2039.15 元。

iQOO Z11 Turbo 首次搭载了第五代高通骁龙 8 移动平台,并加入了 iQOO 自研电竞芯片 Q2 组成新一代旗舰级的双芯组合。储存芯片选用了 LPDDR5X Ultra RAM 和 UFS 4.1 ROM 的组合,最高支持 16GB+1TB 的组合。在开启 Monster 模式的状态下,安兔兔跑分为 3211628。

软件的部分,iQOO Z11 Turbo 用上新一代 Monster 超核引擎,支持提升稳帧表现的「先知调度器」,细化内存管理和显示链路优化的「闪电加速器」,进一步压榨手机性能的「Monster 模式」也做了提升。

受益于 iQOO 和 《王者荣耀》的联合实验室,iQOO Z11 Turbo 支持《王者荣耀》 144FPS + 高清画质同时开启,还会针对触控操作区域进行超感分区触控,同时也会降低语音延迟,提升游戏中的操控和通信体验。

其他游戏方面,iQOO Z11 Turbo 在 Monster+ 模式下支持《原神》 1.5K 纹理超分+ 144fps 超频同时开启,《和平精英》也支持「1.5K 超分+ 144FPS 超帧」模式,在游戏中可开启 VAA 抗闪烁,提升画面精细度。

特别是在开镜狙击的时候,画面显示会更加精准。

续航部分,iQOO Z11 Turbo 搭载了 7600mAh 的超薄蓝海电池。这款电池用上了第四代硅负极技术和第二代半固态电池技术,提升了能量密度可以让电池做得更薄,在极低温的环境下放电性能也有提升,北方冬天户外使用能再稳定一点。

手机采用了全局直驱供电 2.0 设计,支持 100W 超快闪充,通用快充部分也有 49W,具体充电时间为官方 46 分钟,通用快充 53 分钟。

屏幕方面,iQOO Z11 Turbo 搭载了一块 6.59 英寸 1.5K 第二代护眼超冠屏,用上新一代旗舰级发光材质,局部峰值亮度能够达到 5000nits,低光环境下亮度能够降低到 1nit。

屏幕支持类 DC 调光,4320Hz 超高频调光和软件全 DC 调光,护眼软件算法技术的部分升级到「第二代 vivo 悦目护眼」,里面包含会针对游戏画面内容识别和选择画质和色温的游戏护眼 2.0、低光环境下提升护眼效果的夜猫护眼 2.0,还有个性化亮度 2.0 算法,全面提升机身的护眼能力。

还有就是,iQOO 这次在 Z11 Turbo 上也用上了新一代超感触控芯片,最高支持 3200Hz 瞬时触控采样率和 300Hz 稳定 10 指触控采率,减少双指触控的断触现象。

来到了影像部分,没想到 iQOO 这次也给 Z 系列的相机做了升级。

iQOO Z11 Turbo 用的是「主摄+超广」的双摄搭配,镜头组合没有因为高性价比性能机的定位缩水成「主摄+辅助镜头」组合。

主摄采用的是一块 1/1.56 英寸 2 亿像素的三星传感器 HP5,镜头光圈为 F1.88,手机内置神经图像计算引擎 NICE 算法,手机最高支持 4 倍无损变焦和 40 倍数码变焦。

人像模式拍摄的焦段选择也支持 23mm | 35mm | 50mm | 85mm | 100mm 这五个选项,可以说是把高像素的优势用尽了。

另外,Live Photo 和内置滤镜支持全焦段选择,AI 修图的部分新增经典负片、经典正片和清透蓝调三款胶片色彩效果。

相机 DECO 不再是 iQOO 常规的大舷窗设计,DECO 内加入了往内凹落的弧面设计,哑光黑弧面表面有极细的坑纹细节,看起来更有大镜头的感觉。

机身整体设计干净,机身采用了手感丝滑的玻璃纤维后盖,加入了金属中框,支持 IP68 & IP69 防水防尘。机身到中框的过渡做了更顺滑的衔接,裸机手持手感更好。

iQOO Z11 Turbo 有以淡蓝色为主的沧浪浮光,以及光晕粉、天光白、极夜黑四款配色,合共有五个储存选项,定价分别是:

  • 12GB+256GB 定价 2699 元,首销价 2399 元,国补后定价 2039.15 元
  • 12GB+512GB 定价 3199 元,首销价 2899 元,国补后定价 2464.15 元
  • 16GB+256GB 定价 2999 元,首销价 2399 元,国补后定价 2294.15 元
  • 16GB+512GB 定价 3499 元,首销价 3199 元,国补后定价 2719.15 元
  • 16GB+1TB 定价 3999 元,首销价 3699 元,国补后定价 3199元
「买吧,不贵。」

#欢迎关注爱范儿官方微信公众号:爱范儿(微信号:ifanr),更多精彩内容第一时间为您奉上。

爱范儿 | 原文链接 · 查看评论 · 新浪微博


GDAL 创建矢量图层的两种方式

作者 GIS之路
2026年1月15日 21:32

^ 关注我,带你一起学GIS ^

前言

矢量数据的读写效率是决定生产质量的关键指标,如何选择高效且准确的的方法需要开发者根据实际需求进行选择。

由于本文由一些前置知识,在正式开始之前,需要你掌握一定的Python开发基础和GDAL的基本概念。在之前的文章中讲解了如何使用GDAL或者ogr2ogr工具将txt以及csv文本数据转换为Shp格式,可以作为基础入门学习。本篇教程在之前一系列文章的基础上讲解如何使用GDAL 创建矢量图层的两种方式

如果你还没有看过,建议从以上内容开始。

1. 开发环境

本文使用如下开发环境,以供参考。

时间:2025年

系统:Windows 11

Python:3.11.7

GDAL:3.11.1

2. 要素结构创建

根据要素结构创建这种方式,在获取到属性域之后直接根据字段定义创建字段结构。使用图层方法CreateField写入属性字段。

# 获取源数据结构
featureDefn = sourceLayer.GetLayerDefn()
# 获取源数据字段数量
fieldCount = featureDefn.GetFieldCount()

# 添加属性结构
for i in range(fieldCount):
    fieldDefn = featureDefn.GetFieldDefn(i)
    # 添加字段
    targetLayer.CreateField(fieldDefn)

之后遍历图层要素,使用图层方法CreateFeature写入要素数据。

# 添加要素
for feature in sourceLayer:    
    targetLayer.CreateFeature(feature)   

3. 遍历属性创建

直接遍历属性这种方式的话,首先需要根据源数据属性域使用ogr.Feature(featureDefn)方法创建一个空要素,然后向该目标要素写入几何对象和属性字段以及对应的属性值。要素对象方法SetGeometry可用于赋值几何对象,SetField方法用于添加属性字段,该方法的第一个参数具有两种形式,可以传入字段索引值或者字段名称。最后调用图层方法CreateFeature创建要素。

# 获取源数据结构
featureDefn = sourceLayer.GetLayerDefn()
# 获取源数据字段数量
fieldCount = featureDefn.GetFieldCount()

# 写入图层数据
for feature in sourceLayer:
   # 创建投影要素
   tarFeature = ogr.Feature(featureDefn)

   # 添加几何对象
   geom = feature.GetGeometryRef()
   tarFeature.SetGeometry(geom)

   # 添加属性字段
   for i in range(fieldCount):
       # 获取字段信
       fieldDefn = featureDefn.GetFieldDefn(i)
       fieldName = fieldDefn.GetName()
       fieldValue = feature.GetField(i)

       # print(f"字段域:{fieldDefn}")
       # print(f"字段名:{fieldName}")
       # print(f"字段值:{fieldValue}")

       # 写入字段对象
       # tarFeature.SetField(i,fieldValue)
       tarFeature.SetField(fieldName,value)

    targetLayer.CreateFeature(tarFeature)    

4. 注意事项

windows开发环境中同时安装GDALPostGIS,其中投影库PROJ的环境变量指向PostGIS的安装路径,在运行GDAL程序时,涉及到要素、几何与投影操作时会导致异常。具体意思为GDAL不支持PostGIS插件中的投影库版本,需要更换投影库或者升级版本。

RuntimeError: PROJ: proj_identify: D:Program FilesPostgreSQL13sharecontribpostgis-3.5projproj.db contains DATABASE.LAYOUT.VERSION.MINOR = 2 whereas a number >= 5 is expected. It comes from another PROJ installation.

解决办法为修改PROJ的环境变量到GDAL支持的版本或者在GDAL程序开头添加以下代码:

os.environ['PROJ_LIB'] = r'D:\Programs\Python\Python311\Libsite-packages\osgeo\data\proj'

OpenLayers示例数据下载,请在公众号后台回复:ol数据

全国信息化工程师-GIS 应用水平考试资料,请在公众号后台回复:GIS考试

GIS之路 公众号已经接入了智能 助手,可以在对话框进行提问,也可以直接搜索历史文章进行查看。

都看到这了,不要忘记点赞、收藏 + 关注

本号不定时更新有关 GIS开发 相关内容,欢迎关注 


    

GeoTools 开发合集(全)

OpenLayers 开发合集

GDAL 实现矢量数据转换处理(全)

GDAL 实现投影转换

国产版的Google Earth,吉林一号卫星App“共生地球”来了

2026年全国自然资源工作会议召开

日本欲打造“本土版”星链系统

吉林一号国内首张高分辨率彩色夜光卫星影像发布

2025 年度信创领军企业名单出炉!

金融监督管理总局:深入整治无序竞争,持续规范行业秩序

2026年1月15日 20:51
36氪获悉,1月15日,金融监管总局召开2026年监管工作会议。会议要求,切实提高行业高质量发展能力。做好统筹规划,稳妥推进中小金融机构减量提质,合理优化机构布局。深入整治无序竞争,持续规范行业秩序。督促银行保险机构专注主业、错位发展。推进金融高水平对外开放。不断提升金融服务经济社会质效。做好金融“五篇大文章”,坚持投资于物和投资于人紧密结合,持续加大对重大战略、重点领域和薄弱环节的支持力度。强化促消费、扩投资的金融供给,高效服务扩大内需战略。优化科技金融服务,积极培育耐心资本,助力新质生产力发展。加强应急救灾、养老健康、乡村全面振兴等民生领域金融支持。

金融监督管理总局:有力有序有效推进中小金融机构风险化解

2026年1月15日 20:51
36氪获悉,1月15日,金融监管总局召开2026年监管工作会议。会议强调,2026年要有力有序有效推进中小金融机构风险化解。着力处置存量风险,坚决遏制增量风险,牢牢守住不“爆雷”底线。严密防范化解相关领域风险。推动城市房地产融资协调机制常态化运行,助力构建房地产发展新模式。依法合规支持融资平台债务风险化解。严防严打严处非法金融活动。

金龙鱼:拟向玛氏中国转让家乐氏上海和家乐氏昆山各50%股权

2026年1月15日 20:49
36氪获悉,金龙鱼公告,公司于2026年1月14日召开董事会,审议通过转让家乐氏上海和家乐氏昆山各50%股权给玛氏箭牌糖果(中国)有限公司,交易对价分别为4500万美元和1500万美元。本次交易完成后,公司将不再持有两家公司股权,预计对公司2026年度收益的影响超过2024年度经审计归母净利润的10%。

网页版时钟

作者 rocky191
2026年1月15日 20:45

之前看到类似的时钟工具,ai coding 一个类似的!浏览器全屏显示后,当成屏保,也不错。

image.png

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数字时钟</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Arial', sans-serif;
            background-color: #ffffff;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            padding: 20px;
            color: #333;
        }

        .container {
            text-align: center;
            max-width: 800px;
        }

        .date {
            font-size: 2.5rem;
            color: #666;
            margin-bottom: 40px;
            font-weight: 300;
        }

        .clock-container {
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 8px;
            margin-bottom: 60px;
        }

        .time-segment {
            position: relative;
            width: 80px;
            height: 120px;
            background-color: #e0e0e0;
            border-radius: 8px;
            overflow: hidden;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        }

        .time-digit {
            position: absolute;
            width: 100%;
            height: 100%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 4rem;
            font-weight: bold;
            color: #333;
        }

        .time-separator {
            font-size: 3rem;
            color: #333;
            font-weight: bold;
        }

        .ampm {
            font-size: 2.5rem;
            color: #333;
            margin-left: 15px;
            font-weight: bold;
        }

        .quote {
            font-size: 1.2rem;
            color: #666;
            line-height: 1.6;
            margin-bottom: 20px;
            font-style: italic;
        }

        .author {
            font-size: 1rem;
            color: #888;
            text-align: right;
        }

        @media (max-width: 768px) {
            .date {
                font-size: 2rem;
            }

            .time-segment {
                width: 60px;
                height: 90px;
            }

            .time-digit {
                font-size: 3rem;
            }

            .time-separator {
                font-size: 2.5rem;
            }

            .ampm {
                font-size: 2rem;
            }

            .quote {
                font-size: 1rem;
            }
        }

        @media (max-width: 480px) {
            .date {
                font-size: 1.5rem;
            }

            .time-segment {
                width: 45px;
                height: 70px;
            }

            .time-digit {
                font-size: 2.2rem;
            }

            .time-separator {
                font-size: 2rem;
            }

            .ampm {
                font-size: 1.5rem;
            }

            .quote {
                font-size: 0.9rem;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="date" id="date">星期二, 九月 23 2025</div>
        
        <div class="clock-container">
            <div class="time-segment">
                <div class="time-digit" id="hour1">1</div>
            </div>
            <div class="time-segment">
                <div class="time-digit" id="hour2">1</div>
            </div>
            <div class="time-separator">:</div>
            <div class="time-segment">
                <div class="time-digit" id="minute1">3</div>
            </div>
            <div class="time-segment">
                <div class="time-digit" id="minute2">0</div>
            </div>
            <div class="time-separator">:</div>
            <div class="time-segment">
                <div class="time-digit" id="second1">3</div>
            </div>
            <div class="time-segment">
                <div class="time-digit" id="second2">8</div>
            </div>
            <div class="ampm" id="ampm">PM</div>
        </div>
        
        <div class="quote">
            "When I get a little money I buy books; and if any is left I buy food and clothes."
        </div>
        <div class="author">Desiderius Erasmus</div>
    </div>

    <script>
        // 星期和月份的中文映射
        const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
        const months = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];
        
        function updateClock() {
            const now = new Date();
            
            // 获取中文日期
            const year = now.getFullYear();
            const month = now.getMonth();
            const day = now.getDate();
            const weekday = now.getDay();
            
            // 设置日期(使用中文格式)
            const dateElement = document.getElementById('date');
            dateElement.textContent = `${weekdays[weekday]}, ${months[month]} ${day} ${year}`;
            
            // Get current time
            let hours = now.getHours();
            const minutes = now.getMinutes();
            const seconds = now.getSeconds();
            const ampm = hours >= 12 ? 'PM' : 'AM';
            
            // Convert to 12-hour format
            hours = hours % 12;
            hours = hours ? hours : 12; // the hour '0' should be '12'
            
            // Format time with leading zeros
            const formattedHours = hours.toString().padStart(2, '0');
            const formattedMinutes = minutes.toString().padStart(2, '0');
            const formattedSeconds = seconds.toString().padStart(2, '0');
            
            // Update the clock display
            document.getElementById('hour1').textContent = formattedHours[0];
            document.getElementById('hour2').textContent = formattedHours[1];
            document.getElementById('minute1').textContent = formattedMinutes[0];
            document.getElementById('minute2').textContent = formattedMinutes[1];
            document.getElementById('second1').textContent = formattedSeconds[0];
            document.getElementById('second2').textContent = formattedSeconds[1];
            document.getElementById('ampm').textContent = ampm;
        }
        
        // Update clock immediately and then every second
        updateClock();
        setInterval(updateClock, 1000);
    </script>
</body>
</html>

高盛:第四财季净利息收入37.1亿美元 同比增长58%

2026年1月15日 20:45
高盛第四财季净营收134.5亿美元,同比下降3%;投资银行业务营收25.8亿美元,同比增长25%;净利息收入37.1亿美元,同比增长58%;每股收益14.01美元。高盛董事会将股息从每股4美元提高至4.50美元。高盛2025年稀释普通股每股收益(EPS)为51.32美元,第四季度为14.01美元。2025年普通股东股东股本平均回报率(ROE)为15.0%,年化ROE为16.0%。(财联社)

境外收入的补税追溯期最早可至2017年

2026年1月15日 20:41
近日从多方了解到,目前中国内地税务居民境外收入的补税追溯期较此前拉长,最早可至2020年甚至2017年。2025年以来,不少税务居民接到税务部门提示和通知,要求自查个人境内外所得并及时进行纳税申报,补税追溯范围主要为近3年内,以2022年、2023年为主。(第一财经)

摩根士丹利第四季度净营收178.9亿美元

2026年1月15日 20:38
摩根士丹利第四季度净营收178.9亿美元,预估176.2亿美元;每股收益2.68美元;非利息支出121.1亿美元,预估122.7亿美元;薪酬费用70.6亿美元,预估72.4亿美元;非薪酬支出50.5亿美元,预估50.2亿美元;股本回报率16.9%,预估15.1%。(财联社)

利欧股份:股价波动较大,股票明起停牌核查

2026年1月15日 20:37
36氪获悉,利欧股份公告,公司股票于2025年12月31日至2026年1月15日连续10个交易日收盘价涨幅偏离值达96.77%,股价波动较大,投资者较为关注。为维护投资者利益,公司将就股票交易波动情况进行核查。经公司申请,公司股票自2026年1月16日开市起停牌,待核查结束并披露相关公告后复牌,预计停牌时间不超过3个交易日。

华胜天成:目前涉及AI业务的相关收入占公司整体营业收入的比例较低

2026年1月15日 20:28
36氪获悉,华胜天成公告,公司关注到市场将公司列入AI相关热点概念。公司目前涉及AI业务的相关收入占公司整体营业收入的比例较低,对公司业绩预计不构成重大影响。除前述情况外,未发现对公司股票交易价格可能产生重大影响的媒体报道、市场传闻或热点概念。经自查,公司目前生产经营活动正常,主营业务未发生重大变化,公司主要从事IT系统解决方案、数字化基础设施、数字化应用等业务。市场环境没有发生重大调整,生产成本和销售等情况没有出现大幅波动,内部生产经营秩序正常。
❌
❌