2026年3月

背景

SpreadJS 是一款企业级纯前端表格控件,不仅完整兼容 Excel 的核心功能,更提供了强大的深度定制与二次开发能力。在实际项目中,用户往往不满足于原生功能,需要将表格与其他前端生态无缝整合。

为什么需要集成第三方图表?

  • 原生图表局限:SpreadJS 虽兼容 Excel 图表,但复杂可视化场景(如动态交互、自定义样式、特殊图表类型)需要更灵活的方案。
  • 生态整合需求:前端项目中已广泛使用 ECharts、AntV 等图表库,重复造轮子成本高。
  • 定制化场景:金融看板、量化报表、数据大屏等场景需要表格与高级图表深度联动。

SpreadJS 的扩展优势:

  • 浮动对象机制:支持嵌入任意 DOM 内容,为第三方控件提供容器。
  • 事件系统完善ValueChangedTopRowChanged 等事件支持精细化的交互控制。
  • API 开放度高:从数据绑定到导出渲染,各环节均可自定义扩展。

本文以 ECharts 为例,演示如何将主流图表库与 SpreadJS 深度集成,实现数据联动、可见性同步及 PDF 导出。该方案同样适用于其他 DOM 依赖型控件,展现 SpreadJS 作为前端表格基座的生态整合能力。

核心方案:容器嵌套

利用 SpreadJS 的 FloatingObject 支持嵌入 HTML 内容的特性,为 ECharts 提供 DOM 容器。

1. 创建浮动容器

通过 FloatingObject.content() 将 div 插入表格指定单元格区域。

function initFloatingObject(sheet, chart) {
    let floatObj = new GC.Spread.Sheets.FloatingObjects.FloatingObject(chart.id);
    floatObj.startRow(chart.startRow);
    floatObj.endRow(chart.endRow);
    floatObj.startColumn(chart.startColumn);
    floatObj.endColumn(chart.endColumn);

    let div = document.createElement('div');
    div.innerHTML = `<div id="${chart.id}" style="width:100%;height:100%;"></div>`;
    
    floatObj.content(div);
    sheet.floatingObjects.add(floatObj);
}

在这里插入图片描述

2. 初始化 ECharts

容器挂载后,实例化图表。

function initBarECharts(chart) {
    let dom = document.getElementById(chart.id);
    if (!dom) return;
    
    let myChart = echarts.init(dom);
    let data = getChartDataFromTables(chart.source);
    
    myChart.setOption({
        xAxis: { data: data.categories },
        series: [{
            type: 'bar',
            data: data.data,
            animation: true
        }]
    });
    return myChart;
}

在这里插入图片描述

数据双向绑定

利用 ValueChanged 事件监听单元格修改,实现表格驱动图表更新。

实现逻辑

  1. 监听全局 ValueChanged 事件。
  2. 校验修改位置是否命中图表数据源区域。
  3. 命中则提取新数据,调用 chart.setOption 刷新。
spread.bind(GC.Spread.Sheets.Events.ValueChanged, function (e, info) {
    for (let key in charts) {
        let range = new GC.Spread.Sheets.Range(
            charts[key].table.row, charts[key].table.col, 
            charts[key].table.rowCount, charts[key].table.colCount
        );
        // 判断修改是否在当前图表数据范围内
        if (range.contains(info.row, info.col, 1, 1)) {
            refreshCharts(charts[key].id, getChartDataFromTables(charts[key].source));
            break;
        }
    }
});

refreshCharts方法是用于动态设置ECharts数据的方法,这里就展示详细的内部实现了。
在这里插入图片描述

可见性同步:模拟原生滚动渲染

SpreadJS 原生图表具备可视区域自动渲染机制(滚动到可见区域才渲染),但嵌入的自定义 DOM 内容不会自动触发此逻辑。若不处理,滚动到图表位置时会发现内容为空。

监听滚动事件

需手动监听 TopRowChanged 事件,当图表行进入可视区附近时,触发初始化。

spread.bind(GC.Spread.Sheets.Events.TopRowChanged, function (s, e) {
    let newTopRow = e.newTopRow;
    // 判断图表起始行是否进入可视区,且尚未初始化
    if ((charts["line"].startRow - 5 < newTopRow) && (!charts["line"].echart)) {
        initCharts(charts["line"]);
    }
});

在这里插入图片描述

难点突破:导出 PDF

ECharts 的 DOM 节点无法被 SpreadJS 原生 PDF 导出功能捕获。解决方案:临时 Workbook + 图片转换

导出流程

  1. 克隆 Workbook:深拷贝当前 JSON 配置到临时实例,隔离操作。
  2. 强制渲染:确保临时实例中图表已初始化。
  3. 转图片:调用 echarts.getDataURL() 获取 Base64。
  4. 替换对象:移除 FloatingObject,在原位置添加 Picture Shape。
  5. 生成 PDF:调用临时实例的 savePDF

document.getElementById("saveAsPdf").addEventListener("click", function () {
    // 1. 克隆临时实例
    let tempSpread = new GC.Spread.Sheets.Workbook();
    tempSpread.fromJSON(JSON.parse(JSON.stringify(spread.toJSON({ includeBindingSource: true }))));
    let tempSheet = tempSpread.getSheet(0);
    
    // 2. 图表转图片
    for (let key in charts) {
        // 确保图表已渲染
        if (!charts[key].echart) {
            // 触发初始化逻辑...
        }
        
        let imgData = charts[key].echart.getDataURL();
        tempSheet.floatingObjects.remove(charts[key].id); // 移除 DOM 容器
        
        // 添加图片形状
        let pic = tempSheet.shapes.addPictureShape(charts[key].id, imgData, 0, 0, 100, 100);
        pic.startRow(charts[key].startRow);
        pic.endRow(charts[key].endRow);
    }
    
    // 3. 导出
    tempSpread.savePDF(function (blob) {
        saveAs(blob, 'report.pdf');
    });
});

在这里插入图片描述

总结

通过本文的实践,我们验证了 SpreadJS 在深度定制与生态整合方面的强大能力:

集成维度实现方式扩展价值
容器嵌入FloatingObject.content() 嵌入 DOM可集成任意前端控件(图表、地图、富文本等)
数据联动ValueChanged 事件监听实现表格与外部组件的双向数据同步
渲染同步TopRowChanged 事件模拟原生逻辑保持与 SpreadJS 原生组件一致的用户体验
导出扩展临时 Workbook + 图片转换突破原生导出限制,支持自定义内容输出

核心价值:

  1. 不重复造轮子:直接复用 ECharts 等成熟图表库,降低开发成本。
  2. 保持体验一致:通过事件监听模拟原生行为,用户无感知切换。
  3. 方案可迁移:该集成模式适用于其他 DOM 依赖型第三方控件。

SpreadJS 不仅是一个表格控件,更是一个可扩展的前端数据交互基座。通过开放的事件系统与 API,开发者可以将表格与现有前端生态无缝融合,快速构建满足复杂业务需求的在线报表系统。

完整demo请查看:在SpreadJS中集成ECharts并导出为PDF

作者:vivo 互联网服务器团队- Lei Zezheng
本文探讨了分布式架构下可观测体系的建设实践,提出了基于业务视角的可观测体系建设框架:明确业务核心边界、建立指标体系(业务指标+SLO指标)、构建多维度观测(业务观测、链路观测、异常观测、变更观测)和固化排障路径,以游戏中心项目为例,介绍了项目在问题发现与问题定位上的实践,有效提升了问题发现与故障处理的效率。

1分钟看图掌握核心观点👇

动图封面

动图封面

图 1 VS 图 2,您更倾向于哪张图来辅助理解全文呢?欢迎在评论区留言

一、背景介绍与痛点分析

当分布式架构渐成主流,可观测性(Observability)在行业内也越来越受到重视。可观测性是指系统可以由其外部输出,来推断其内部状态,系统的可观测性越强,我们对系统的可控制性就越强。现如今如何提升整体系统的可观测性,应用可观测工具达成业务保障可用性目标,成为了每个SRE与业务开发都必须思考的课题。但是随着业务复杂度与”1-5-10"(1分钟内发现问题,5分钟内定位问题原因,10分钟内恢复故障)可用性保障目标等的日益提升,我们也发现了可观测体系在我们业务落地上的一些问题。

  • 观测视角的差异。可观测工具建设与落地方向大多处于运维视角,而非业务视角。
  • 业务的差异。不同的业务、业务发展的不同阶段,对于观测的建设重点差异很大。

这些差异,为平台侧提供观测工具与业务开发使用工具之间带来了不少痛点。游戏中心作为toC的分发类业务的一个典型项目,可观测体系的建设过程可圈可点,现总结其中一些经验,希望对于其他业务项目有所帮助。

二、可观测体系的数据基座

对于可观测,大家或多或少都听过可观测性的”三大支柱“:指标、日志和链路,2017 年Peter Bourgon 撰写的文章《Metrics, Tracing, and Logging》 系统地阐述了这三者的定义:

那么我们监控团队已经基本很完备的采集好了这些数据,并且呈现了诸如日志中心,应用监控,调用链指标监控等工具,是否就代表了能保证我们系统的可观测性?答案当然是否定的,有了西红柿、鸡蛋、盐,并不能代表我们就已经能吃到西红柿炒鸡蛋了,三大指标都有着自己的明显特征与使用场景:

独立的使用各种指标,永远只适用于部分场景,虽不能说完全无效,但想系统化达成目标一定会比较吃力,且无条理。面对较为简单的问题,比如日志突然打印了空指针异常、数组越界的错误,我们看下日志中心就很快能定位到具体代码行上,进而分析上层参数的情况,并去迅速排除故障。但是当问题复杂度略微提升,比如:

  • 我们依赖的服务耗时缓慢上升,直至导致我们服务的可用性下降;
  • 服务调用者缺陷导致对我们某个服务的调用流量异常上涨,进而影响redis、mysql等基础组件,最终导致同样依赖该组件的核心服务受损。

出现这类问题时,日志中心、应用指标,超时链路都会有异常反应。除此以外,绝大多数系统问题其实都是由于变更导致或触发的,所以除了以上三个核心数据外,还需要结合一些变更系统事件来做辅助根因定位。我们无法24小时时刻关注各项指标,必须通过配置检测与告警来主动通知。

日志、指标、链路、变更事件以及告警,共同构成了我们可观测的数据基座。

三、业务视角的可观测体系建设框架

3.1 业务核心分治

对于大多数系统来说,我们建设可观测体系都是为了及时发现系统中出现的各类故障,但是作为业务开发,实践中我们会发现在这个标准下:都是故障,亦有差距。“游戏中心首页白屏”、“登录失败”、“下载失败” 这类问题出现即是致命伤,等故障爆发后再发现是不可接受的。但是对于“游戏评论刷新延迟”,“我的页成就刷新延迟”之类的故障,在资源有限时,可能慢一点处理也无妨。

所以基于分治的思路,首先要做的就是“明确业务核心边界”。如果拆解出的核心业务依然很复杂,那么应当持续视角向内,将业务拆解至最小的核心单元后,再分部进行观测。

3.2 指标体系的建立

对于业务系统,首要的观测指标当然是业务指标,能够直接反应业务的健康度,比如:“游戏下载成功率”,“游戏登录成功率”,“游戏订单成功率”等。不过我们很多业务场景无法直接拟定业务指标,经过实践,一定程度上可以通过SLO指标进行替代。

SLO指标是我们观测可用性的重要手段,但不是越多越好,SLO的意义在于通过告警帮助我们快速发现影响服务SLI的异常,配置过多会带来告警过多的困扰。上文已经提及到核心业务的拆分,对于微服务架构我们大部分服务是以接口调用的形式去对外提供的,那么抽离出一组或多组的核心服务接口,并对于这一批接口的SLI指标进行度量,就可以制定自己系统的SLO目标。

3.3 明确数据观测目的与意义

通过建立指标体系,我们就能够识别出系统中包含各式各样的指标数据,通过对数据进行分类,我们也能够进一步理解其对于系统的价值所在。

分象限观测

四、游戏中心可观测体系实践

4.1 明确核心边界

首先我们对游戏中心进行了核心业务的划分:游戏中心首页、游戏下载、游戏预约,对这三块业务进行最高优先级的保障。由于可观测体系的搭建必须依赖平台能力,相关能力最终也必须沉淀回平台,所以在边界划分上需要结合整体微服务架构设计:

公司的微服务拓扑视角

  • 上游节点调用,重要调用方
  • 下游节点调用,核心依赖方

游戏中心服务架构视角

  • 客户端
  • 网络环境
  • 容器环境
  • 代码
  • 中间件、核心依赖组件
  • 运营后台

4.2 指标体系建立

(1)业务指标的观测

对于游戏中心下载业务,下载CPD指标是很核心的业务指标,且直接与收入数据挂钩,可以通过检测cpd接口的状态来反映业务情况。

(2)SLO指标的观测

对于首页上游客户端调用,无法简单与日活、营收等数据相关联,为了达成“1-5”的目标,对于游戏中心的SLO指标的制定我们选取了核心接口的P95耗时与可用性指标,并配置相关监控。首页接口的pageData/home p95范围大概在200-300ms,根据akamai研究用户体验能明显感知到慢的程度大概是加载2秒以上,附带算上网络传输与客户端渲染时间,我们的服务目标定为P95<800ms,在可用性上全年项目SLA可用性级别为4个9,在接口服务上也保持一致。

4.3 多维度的观测

(1)整体健康度的定时观测与发版后观测

抽离核心观测数据来快速实现整体核心SLI指标的观测,是发现一些全局影响故障最直接的手段。如果一段时间所有接口的rt都缓慢上涨,那么一定代表着系统出现了影响面最大的故障。通过定时报告的配置,既防范了个人的观测习惯风险,也提升了移动端的观测能力。版本发布后的定期报告观测,也是我们当前观测版本变更后可用性的主要手段。

(2)服务的核心依赖观测

在游戏中心业务中,需要从推荐、dmp标签、游戏资讯、大数据四个业务方获取核心数据,那么这四个服务相关接口的SLO就需要作为核心依赖观测项。

(3)服务的日志观测

  • 通过错误日志治理,降低error数量,来有效呈现异常error数据。
  • 除了进行阈值数量监控外,对ERROR日志聚合1分钟级别的趋势分析,聚合topN,有效识别异常error的变化。

(4)中间件的观测

对于游戏中心业务,redis是最为核心的中间件,redis的稳定直接影响首页各个业务的健康度。对于redis的ops、实例cpu都进行检测,结合热key、大key分析,能够有效识别问题和风险。

4.4 固化排障路径

通过告警入口的下钻串联,搭建了 “告警通知→问题详情→业务看板→关联拓扑” 的通用问题排障路径。

在专家经验的沉淀上,对于业务、SLO等相关告警,通过处理流程建议文档、文档知识库、日志知识库,构建agent值班助手来共享团队知识。

五、总结与展望

  • 在问题发现上:对于游戏中心的三大核心业务场景明确了业务边界之后,用户侧接口访问变慢、出错的风险告警可以在3分钟内完成告警推送;通过与监控团队合作提升自定义监控数据采集,对于游戏预约首发、游戏礼券发放等业务,可以做到1分钟的问题告警推送。
  • 在问题定位上:通过关联到下游依赖、服务基础指标与专家经验,游戏核心业务的组件、服务异常等问题,基本可以5分钟内做到识别风险和问题边界或原因。

可观测体系建设并非一劳永逸的事情,随着业务变化而变化,也随着团队组织架构变化而变化。对于监控平台,构建统一可观测体系的难点,一方面在于技术本身的制约,如何应对大规模数据的存储、性能挑战;另一方面则在于如何与千差万别的业务进行沟通、合作,融合业务专家经验,抽象出共性的问题。那么作为业务开发,持续提升可观测理解水平,深入挖掘沉淀业务专家经验,才能协同好平台一起做好这件事。现如今,行业AIOPS的发展日新月异,我们系统化的构建可观测体系也是融入该浪潮中,在实现的工具自动化的目标之后,我们也希望朝着智能化的建设迈出一步。

鉴于 antigravity 已经基本残废,打算投靠 codex 的怀抱,有下面几个问题想问下大家:

  1. 如果使用 Codex 的云端编译,一般是怎么部署项目的?是直接把仓库同步到云端环境吗?

  2. 在实际开发中,大家更推荐:


    • 直接让 codex 在 本地写代码
    • 还是把开发流程更多放在 Codex 的云端环境
  3. 另外一个比较纠结的是工具选择:


    • 日常是 CLI 为主 还是 IDE 插件为主
    • CLI 场景下通常怎么 review / 管理 AI 修改的代码?

感谢分享经验 🙏

一直用 iPhone 做主力机,

picsew 这个长截图很好用。

然后在 gplay 上搜长截图 app ,

试了前边十来个,

没有一个能简简单单通过录屏来自动拼接完成的。

又要悬浮窗权限,

又要无障碍权限,

但还是没有能实现这么简单功能的。也不知道是不是我搜的不太行。

所以 vibe 手搓了一个。

需要 12 个朋友们帮助内测一下,

https://play.google.com/apps/internaltest/4701553743426784586

功能非常单一,

就是开启录屏,

转到要长截图的 app ,从通知栏点击开始截图,关闭通知栏,2s 后会开始录屏

在要截图的 app 慢慢下滑,

完事后切回 app 停止并自动拼接。

可以自定义忽略上方一定高度,为了应对有的 app 会在左上角放置一个悬浮的返回按钮。

接受内测邀请需要提供 gplay 邮箱,可以发送到 [email protected]

或者不介意可以直接留言下方。

1. 开源

1.1 AI 应用

Dify

Dify: Production-ready platform for agentic workflow development.

开源的 LLM(大语言模型)应用开发平台,旨在帮助开发者快速构建、部署和管理基于大语言模型的 AI 应用。

https://github.com/langgenius/dify

1.2 AI 编程

OpenCode

OpenCode: The open source AI coding agent.

开源的 AI 编程智能体(AI Coding Agent),它旨在通过终端(TUI)或桌面应用,为开发者提供深度的自动化编程辅助。

https://github.com/anomalyco/opencode

Vibe Coding

Vibe Coding 指南: 一个通过与 AI 结对编程,将想法变为现实的终极工作站

https://github.com/2025Emma/vibe-coding-cn

Vue Skills

Vue Skills(来自 Anthony Fu,Vue 核心成员):

https://github.com/antfu/skills

1.3 AI 推理

nndeploy

nndeploy: 一款简单易用和高性能的AI部署框架。基于可视化工作流和多端推理,可让 AI 算法在上述平台和硬件更高效、更高性能的落地。

侧重端侧部署,包含:桌面端(Windows、macOS)、移动端(Android、iOS)、边缘计算设备(NVIDIA Jetson、Ascend310B、RK 等)以及单机服务器(RTX 系列、T4、Ascend310P 等)。

https://github.com/nndeploy/nndeploy

VideoPipe

VideoPipe: 跨平台的视频结构化(视频分析)框架。适用于视频结构化、图片搜索、人脸识别、交通/安防领域的行为分析(如交通事件检测)等场景。

模型推理: 默认采用OpenCV::DNN实现。如果要适配其他硬件平台,比如瑞芯微的RKNN、华为的CANN等,需要参考其厂家提供的推理Demo代码,将其封装成VideoPipe中的一个推理Node即可。

侧重视频分析,包含拉流、推流等,适合快速集成与落地。

https://github.com/sherlockchou86/VideoPipe

MediaPipe

MediaPipe: cross-platform, customizable ML solutions for live and streaming media.

侧重端侧模型解决方案与部署。支持视觉、文本、音频和LLM任务,且每种任务都包含一个或多个模型,可部署 Android, iOS, Web 等。

https://github.com/google-ai-edge/mediapipe

NVIDIA Triton

NVIDIA Triton Inference Server provides an optimized cloud and edge inferencing solution.

NVIDIA Triton 是一个高性能的推理服务器,通过深度优化硬件利用率和并发处理能力,为云端和边缘提供超低延迟、高吞吐的模型推理服务。

它通过 Ensemble Models(模型集成)功能来实现多模型工作流,这是一种“服务器内部、紧密耦合”的流水线编排。支持 KServe 协议。

侧重极致性能和硬件优化,尤其适合生产级高吞吐、低延迟场景。

https://github.com/triton-inference-server/server

KServe

KServe is a standardized distributed generative and predictive AI inference platform for scalable, multi-framework deployment on Kubernetes.

KServe 是一个专为Kubernetes设计的标准化模型部署平台,支持在云原生环境中大规模、多框架地部署AI模型。

侧重标准化和多框架,是云原生的编排标准。

https://github.com/kserve/kserve

BentoML

BentoML is the easiest way to serve AI apps and models - Build Model Inference APIs, Job queues, LLM apps, Multi-model pipelines, and more!

BentoML 是一个灵活的AI应用服务框架,致力于简化从模型到生产级API服务的打包和部署过程。

侧重易用性和应用构建,适合打包完整AI云端服务。

https://github.com/bentoml/BentoML

1.4 知识库

PandaWiki

PandaWiki 是一款 AI 大模型驱动的开源知识库搭建系统。

旨在帮助你快速构建智能化的产品文档、技术文档、FAQ、博客系统,借助大模型的力量为你提供 AI 创作、AI 问答、AI 搜索等能力。

https://github.com/chaitin/PandaWiki

2 好物

2.1 助手

NotebookLM

NotebookLM: 以您信赖的信息为基础,搭载最新的 Gemini 模型,是您的研究和思考好帮手。

https://notebooklm.google/

ima

ima: 会思考的知识库,开启搜读写新体验(支持混元+DeepSeek双模型)。

https://ima.qq.com/

Claude Code

Claude Code: Work with Claude directly in your codebase. Build, debug, and ship from your terminal, IDE, Slack, or the web. Describe what you need, and Claude handles the rest.

Claude Code 是一个 AI 编程助手,能够直接在你的代码环境中工作,通过终端、IDE 或网页帮你构建、调试和交付项目。

https://claude.com/product/claude-code

    Go 的并发优势很大程度上来自 用户态调度器(Goroutine Scheduler)。它不依赖 OS 线程创建大量轻量级任务,通过 G/M/P模型 和智能调度策略保证高吞吐、低延迟。

一、为什么需要 Go 调度器?

操作系统的线程有两个天然缺陷

  • 创建成本高:一个线程大概要1MB栈内存,创建和切换开销大
  • 调度不可控:操作系统调度器不了解你的程序逻辑

而Go的调度器能做到:

  • 协程创建成本极低(首次栈2KB)
  • 可以几百万级创建
  • 全用户态调度
  • 明确知道哪些协程可能阻塞、哪些需要抢占、哪些必须让出CPU

二、G / M / P 模型详解

Go调度器用三个核心实体表示执行模型

image.png

    1. G - Goroutine

  • 状态:idle、runnable、running、waiting、dead
  • 轻量:默认2KB栈,根据需要增长和收缩
  • 被调度器分配到P本地队列中,等待M执行

    2. M - Machine (操作系统线程)

  • 每个M对应一个真实操作系统线程
  • M必须绑定一个P才能执行G
  • 如果G执行涉及syscall阻塞,M会被卡住,P会被移交给其他M

  3. P - Processor (逻辑处理器)

  • 控制执行G的各项资源(例如运行队列)
  • P的数量定义为GOMAXPROCS
  • 每个P持有一个本地run queue,也就是运行队列
  • M只有只有P才能执行G
  • P是调度系统的灵魂:没有P,M就像没有CPU的线程,只能一直等。

三、G 的生命周期(敲黑板)

new
->
->
running
->
->
->
->

最重要的两个状态转换:

3.1 running -> waiting : G会从P的队列里消失,即标记为waiting状态

    3.1.1 channel里没有数据/不能发送--等别人

<-ch //阻塞 
ch <- v // 阻塞

    3.1.2 mutex已经被别人锁住--等锁

Lock
//锁住

    3.1.3 IO要等系统返回--等网络/磁盘

Read
// netpoll等待系统通知

    3.1.4 明确休眠--等事件

time
.Sleep

3.2 waiting -> runnable :把G唤醒

    3.2.1 channel有数据了/能发送了

  • channel 接收方等到发送者了
  • channel 发送方等到接收者了

把等待的G放回队列,状态改为runnable

    3.2.2 mutex解锁了

mu.Unlock()

这个时候,调度器会查看有没有goroutine因为这个锁阻塞,有的话就唤醒它并返回队列

    3.2.3 netpoll:网络IO就绪了

当epoll/kqueue发现socket可以读/写

内核就通知Go运行时,运行时把对应的G标记为runnable,并放入可运行队列里

    3.2.4 timer到点了

time.Sleep结束后,timer管理器发现时间到了,把对应的G唤醒,重新放到P的可运行队列里

四、调度循环(抢工作+ 本地队列优先)

Go的调度器使用组合策略,核心要点:

    4.1 优先从本地P队列取G

    4.2 本地队列空了就去抢任务,从其他P抢一半goroutine

    4.3 新建G优先放入本地队列

    4.4 syscall/unblock G,可能丢到全局队列

    4.5 定期检查全局队列,只在需要的时候取任务

整体思路:尽可能在本地消化任务,没有任务就去抢,确保所有P都不会闲着。

五、调度触发点(什么时候会调度?)

Go调度不是随时都切换,调度仅发生在特定时机:

5.1 主动让出

Gosched
//告诉调度器,我先不跑了,你切出去吧

5.2 阻塞操作

    一旦发送阻塞,就会触发调度,调度器会把协程变成waiting

5.3 函数调用边界

    Go会在函数调用入口插入检查点,当一个G运行太久,调度器就会发抢占信号,在下一个函数调用点检查到信号,就会自动让出

5.4 GC安全点

    GC需要STW或扫描所有栈,这也会触发抢占。

六、调度器的图示说明(ASCII)

        ┌──────────┐
        │   Global  │
        │ RunQueue  │
        └─────┬────┘
              │
   ┌──────────┼──────────┐
   ▼          ▼           ▼
┌─────┐   ┌─────┐    ┌─────┐
│  P0 │   │  P1 │    │  P2 │   ...   (P = GOMAXPROCS)
└─┬───┘   └──┬──┘    └──┬──┘
  │          │          │
LocalRQ   LocalRQ    LocalRQ
  │          │          │
  ▼          ▼          ▼
 ┌───┐     ┌───┐      ┌───┐
 │ M │     │ M │      │ M │   (OS Thread)
 └─▲─┘     └─▲─┘      └─▲─┘
   │         │          │
   └─────────┴──────────┘
           Syscalls, Block, Wakeup

七、经典问题解析

7.1 Go能否用多线程跑同一个goroutine?

    答:不能,每个G在任意时刻只能在一个M上运行。调度点可以迁移,但不会并行执行。

7.2 Go会频繁切换goroutine吗?

    答:不会,Go的调度是协作式+抢占式混合;多数切换发生在阻塞点,少量切换在函数入口抢占点。

7.3 为什么设置GOMAXPROCS大了反而变慢?

    答:因为P=并发能力。P增多就会导致更多队列、更多抢任务、更多GC、更多竞争。一半设置为CPU核心数是最佳。

    Goroutine 调度器就像一个巨大餐厅:P 是厨房,M 是厨师,G 是订单。厨师想做菜必须占到厨房;订单在每个厨房的本地栏里排队,没订单的厨房可以跑去别的厨房抢订单,保证每个厨房都不闲着。

*源码地址*

1、公众号“Codee君”回复“每日一Go”获取源码

2、https://pan.baidu.com/s/1B6pgLWfSgMngVeFfSTcPdg?pwd=jc1s 


如果您喜欢这篇文章,请您(点赞、分享、亮爱心),万分感谢!

一个自托管的个人网页归档系统,自动捕获并保存你在 Chrome 中浏览过的网页 — HTML 、CSS 、JavaScript 、图片等一应俱全。当原始网页无法访问时,你仍然可以通过归档副本还原当时的页面样式和内容。

index

v2ex

x

工作原理

Chrome + Tampermonkey ──HTTP POST──▶ Go 服务器 ──▶ PostgreSQL (元数据)
  (关闭标签页 / 页面跳转                │              + 文件系统 (静态资源)
   时自动捕获)                          │
                                        ▼
                                     Web UI ──▶ 浏览 / 搜索 / 还原
  1. Tampermonkey 用户脚本在浏览器中运行,当你离开页面时自动捕获完整的 DOM 和资源。
  2. Go 服务器接收快照,下载浏览器因 CORS 限制无法获取的跨域资源,基于内容哈希去重后存储到本地。
  3. 内置 Web UI 可以浏览、搜索和还原任意归档页面 — 完全离线,不依赖外部服务。

功能特性

  • 高保真还原 — CSSOM 序列化、计算样式内联、防刷新保护,尽可能还原页面原始效果
  • 完整页面捕获 — HTML 、CSS 、JS 、图片、字体;资源 URL 自动重写为本地路径
  • 跨域资源恢复 — 服务器端自动提取并下载被 CORS 拦截的资源
  • 内容哈希去重 — 相同资源跨页面共享,仅存储一份( SHA-256 )
  • 版本历史 — 同一 URL 可多次归档,按时间戳区分
  • 智能去重 — 会话级 + 服务器级双重去重,内容无变化时仅更新访问时间
  • 动态内容支持 — 捕获实时 DOM 状态; MutationObserver 监听变化,超过阈值自动提交一次更新
  • SPA 感知 — 检测单页应用导航,按路由重置捕获状态
  • 防刷新保护 — 归档页面被冻结:定时器、WebSocket 和导航 API 均被拦截
  • Web UI — 响应式界面,支持全文搜索(页面内容、URL 、标题)、按时间范围筛选和还原归档页面
  • RESTful API — 提供完整的归档和查询接口

欢迎体验

https://github.com/icodeface/wayback-archiver

在互联网时代,很多用户都会遇到一种现象:同一款产品或服务,在不同国家或地区访问时,价格可能完全不同。例如机票、酒店、软件订阅甚至电商商品,在不同地区看到的价格往往存在明显差异。这种现象并不是偶然,而是企业常用的一种商业策略,被称为“地理定价”。
地理定价是一种根据用户所在地区调整商品价格的定价策略。企业通过分析不同地区的消费能力、市场需求以及竞争环境,为同一产品制定不同的价格,从而实现收益最大化。

什么是地理定价机制

地理定价指的是企业根据不同地区的市场环境,为同一产品设定不同价格的一种商业模式。企业在制定价格时,通常会综合考虑多个因素,例如当地经济水平、用户消费能力、竞争情况以及市场需求。
例如,一款软件订阅服务在高收入国家可能定价较高,而在发展中国家则可能提供更低的价格,以吸引更多用户购买。通过这种方式,企业既可以保持利润,也能够扩大市场覆盖范围。
在互联网平台中,这种定价策略通常会结合用户 IP 地址、设备信息以及账户数据进行判断,从而确定用户所在地区。

哪些行业常见地理定价

地理定价在许多行业中都非常普遍,其中最典型的包括旅游、电商和数字服务行业。
航空公司和酒店平台经常根据用户访问地区显示不同价格。例如,一些机票在不同国家搜索时,价格可能会出现明显变化。在线旅游平台会根据市场需求、汇率以及当地竞争情况进行动态定价。
电商平台也常常采用类似策略。不同地区的用户可能看到不同的商品价格或促销活动,这种策略有助于平台根据市场环境灵活调整销售策略。在数字服务领域,软件订阅和流媒体平台也会使用地理定价。例如某些软件服务在不同国家提供不同订阅价格,以适应当地市场。

企业为什么使用地理定价

从商业角度来看,地理定价能够帮助企业实现更高的整体收益。如果所有地区都采用统一价格,那么在消费能力较低的市场可能会导致销量下降,而在高消费市场又可能错失更高利润空间。
通过差异化定价,企业可以在不同市场中找到更合适的价格区间。例如,在消费能力较高的地区保持较高价格,而在新兴市场降低价格以扩大用户规模。地理定价还可以帮助企业更灵活地应对市场竞争。如果某个地区竞争激烈,企业可以通过调整价格提升竞争力。

地理定价是如何实现的

在技术层面,地理定价通常依赖多种数据来识别用户位置。其中最常见的方式是通过 IP 地址判断访问者所在国家或地区。
当用户访问网站时,服务器会根据 IP 地址识别其地理位置,并根据预设的定价规则显示相应价格。除了 IP 地址之外,一些平台还会结合浏览器语言、设备信息以及账户资料来进一步判断用户所在地区。这种技术使企业能够快速调整价格策略,并根据市场变化进行动态更新。

跨境业务如何应对地理定价

对于从事跨境电商或国际市场研究的团队来说,了解不同地区的价格信息非常重要。通过分析不同地区的定价策略,企业可以更好地制定市场竞争策略。
在实际操作中,一些团队会通过不同地区的网络环境访问网站,以查看不同国家用户看到的价格。例如,使用不同国家的代理 IP 可以模拟目标市场用户访问,从而更准确地分析价格差异。

总结

地理定价是一种被广泛应用的商业策略,通过根据不同地区调整价格,企业可以在全球市场中实现更高的收益和更灵活的竞争策略。
随着互联网技术的发展,IP 地址识别和数据分析使这种定价方式变得更加精准。对于消费者来说,理解地理定价可以帮助更好地理解价格差异的原因。而对于跨境企业来说,研究不同地区的定价策略则有助于制定更加有效的市场策略。

找工作的时候感觉明显增加多的岗位,实在想不到可以转什么岗位,但是 Ai 这一块目前是趋势,但是未来还未明了,包括龙虾大部分人还是拿着不知道干什么的过程

新闻大事问AI,P图剪辑找AI、外卖下单也能交给AI......随着AI深度融入人们工作、生活的方方面面,所有App正面临同一个关键问题:用好AI能力、让AI融入APP提升服务质量,才能在未来的发展中牢牢把握主动权。

近期,个推对旗下AI SDK能力进行了全面升级,聚焦自然语言交互核心痛点,深度强化意图理解能力,助力新闻资讯、出行、生活服务、电商等各类App升级AI交互体验,实现产品竞争力与用户满意度双重跃升。

「 5大核心能力,重构AI交互体验 」

本次个推AI SDK升级,围绕精准意图理解打造全链路智能交互能力,从上下文感知、需求拆解到意图精准识别、实时响应,全方位贴近人类真实沟通逻辑,让APP拥有更加自然、高效、精准的AI服务能力和交互体验。

1.上下文记忆与智能总结,多轮对话无需重复说明

基于大模型长期记忆(Memory)能力,个推AI SDK可自动记住并理解历史对话主题、用户意图与核心信息,在多轮交互中智能补全用户省略的关键内容,无需反复确认。以投资理财类APP为例:当用户只问“当前黄金的收益如何”,SDK会结合对话记忆+用户端内行为数据,精准识别真实意图是“查询本月黄金基金收益”,并直接回复:“当前主流黄金基金近1个月涨幅为XX,您于X月X日购买的XX基金截至本月收益为XX。”全程无需用户重复表述,意图理解更准,沟通效率大幅提升。

2.复杂问题智能拆解,需求响应零遗漏

用户常对AI一次性提出复合型需求(如 “订机票 + 酒店 + 景点门票”),单一的处理流程难以同时承接多意图,极易出现子任务遗漏的问题。个推AI SDK可将这类复杂需求智能拆解为多个独立的原子任务,并行分发至对应模块处理。以旅游出行类APP为例,当用户交代需求:“我下班后要出差到成都,帮我定下机票,要便宜,但是不要红眼航班”。AI会自动拆解为:出差出行、目的地成都、下班后时段、预订机票、价格优先、排除红眼航班等多层意图与约束条件,精准识别主需求与附加限制,避免信息遗漏或理解偏差。

3.意图主动追问,模糊需求精准落地

此外,当用户需求表达模糊时,AI很容易出现推荐偏差,强行猜测易引发用户不满,并且会造成不必要的成本浪费。针对此问题,个推AI SDK实现意图主动追问,辅助用户生成更加精准的提问逻辑。比如,当用户向旅游出行类APP提问“推荐个周末去玩的地方”,AI会自动追问“请问您所在城市是?希望预算在多少以内?有同行小孩吗?”,待用户明细需求后生成精准行程。

4.融合行业知识,赋能AI专业问答

个推AI SDK可深度结合APP自有知识库,依托行业权威结构化意图体系与大模型深度语义理解能力,穿透用户的表层表述识别核心意图。比如对于K12教育类APP来讲,集成个推AI SDK后,可深度调用平台的K12专业知识库,无论用户是问知识点解析,还是题型解法,亦或是学习方法,AI都能精准匹配专业知识库内容,结合场景给出精准专业建议。

5.MCP工具智能调用,服务能力无缝拓展

个推AI SDK全面支持MCP协议工具调用,可根据用户需求自动对接第三方服务,将联网资讯、实时交通、本地生活、专业平台等工具能力整合输出,让AI响应更贴合实际场景需求。例如在玩转杭州的场景中,用户问本地美食,AI将则自动调用相对应的用餐评价、餐厅评分、餐厅地址等第三方MCP服务,确保用户能够有效获取各类时效性、专业性信息,实现APP服务能力的无缝拓展与高效响应。

此外,随着生成式AI全面普及与行业监管持续深化,内容安全已成为AI应用发展的关键问题。个推AI SDK实现了AI驱动的敏感词过滤能力,构建全覆盖、动态更新的敏感关键词库,结合大模型对拼音、谐音、变体、隐晦表述的深度识别能力,实现对高危违规信息的精准拦截与前置治理,以技术筑牢内容安全防线,助力各类APP健康发展。

「 极简集成,赋能APP智能化升级 」

作为开箱即用的AI能力集成工具,个推AI SDK无需开发者从零搭建复杂AI架构,通过极简集成即可让APP快速完成智能化升级,大幅降低企业的研发成本与时间成本,助其加速抢占市场先机。

PS:目前个推AI SDK已经上线多种Demo,更有教育、电商、新闻资讯、旅游出行等多个垂直行业的案例,欢迎感兴趣的开发者登录个推开发者中心深度体验。如果您对个推AI SDK感兴趣,欢迎和我们联系集成~

我们常用的图灵测试方案基础的图形验证码、复杂点的图形验证码+计算数学题,再进一步的就是各种混淆干扰线之类的。还有一种验证方式是识别图形、拼图之类的交互式验证码。

在现在 AI 发展迅速的当下,这些验证手段会不会即将(或已经)失效,那我们有没有什么方法去更好的区分 “人类” 和 “AI” 呢?

我能想到的就是手机验证码这种,尽可能增加获取验证码的成本

发现只要涉及到跨平台大多数人讨论的都是 Flutter vs React Native

微软的 MAUI 很少被人提起,像是路边一条

加上现在的 AI 时代,Flutter RN 的训练数据明显高于 MAUI

MAUI 是不是可以基本宣布凉了,再去了解等于浪费时间?

浏览器 ctrl+0 可以恢复成默认比例,但是在 2 站,有富文本编辑器的页面,使用 ctrl+0 恢复比例就会默认全屏/非全屏编辑器。这个算不算 bug @Jimmy

如果有一天,你的 AI Agent 不仅能帮你写邮件、订机票,还能主动去“市场”上雇佣人类来完成它搞不定的任务——你会不会觉得,这离科幻片又近了一步?

这不是想象,OpenClaw 正在让这一切成为可能。

3 月 13 日(周五)17:30-18:30,「虾塘造物」系列直播第一期正式开播。极客邦科技创始人霍太稳,与 白话 Agent 主理人、100agent 计划发起人古德白,将展开一场关于“AI 雇佣人类”的脑洞对谈。主题很直接:

当我用 OpenClaw 建造了一个帮 Agent 雇佣人类的市场

嘉宾阵容

霍太稳

极客邦科技创始人、模力工场创始人,技术社区构建者。作为观察者与赋能者,他将从行业高度拆解 OpenClaw 带来的可能性。

古德白

TGO 鲲鹏会上海会员、白话 Agent 主理人,全网粉丝 10 万+。自媒体圈最懂 AI 技术,AI 圈最会玩短视频的科技博主。他正在挑战 6 个月开发 100 个行业 AI 智能体,是真正的实战派。

直播看点

看点一:古德白现场跑任务,OpenClaw 实战演示

自我介绍之后,古德白会当场用 OpenClaw 跑一个小任务。5-10 分钟后回收结果——是骡子是马,拉出来遛遛。

看点二:OpenClaw 在 AI 历史中的位置

如果 ChatGPT 是 AI 的 iPhone 时刻,那 OpenClaw 可能是什么?两位嘉宾将展开一场“AI 编年史”式讨论。

看点三:未来预测——AI 雇佣人类的协作模式

当 AI 足够强大,它会不会反过来“雇佣”人类完成那些它不擅长的活儿?一个叫 “硅碳交易所” 的新概念将在直播中首次公开。

看点四:福利放送

直播间将免费开放 OpenClaw 资源包(含入门教程、AI Agent 案例合集、模力虾塘社群邀请)。

另外,我们会在直播社群中抽出 5 位用户赠送古德白一对一线上装机指导,并送出 1 张价值 330 元的 2050 大会门票——4 月 26 日,杭州,一场属于年轻创造者的聚会等你来。

直播信息

  • 时间:3 月 13 日(周五)17:30-18:30

  • 平台:模力工场视频号、InfoQ 视频号、AI 前线视频号、霍太稳视频号 联合直播

  • 预约方式:点击下方按钮预约直播,或扫码加入「模力虾塘群」,获取资源包及抽奖资格。

如果你也在思考 AI Agent 的下一站,或者单纯好奇 OpenClaw 到底能玩出什么花活——周五傍晚,直播间见。

扫码预约直播或扫码进群,提前和“龙虾”互动 👇

扫码进群,抢红包,抽小龙虾 AI 主机!实现 OpenClaw 龙虾自由!!!

最近 OpenClaw 小龙虾特别火爆,它能帮你处理很多事情,特别是打杂任务是它的专精项。
这么好的软件,需要部署在一台有网络共享能力的电脑之上,懒猫微服正是一款这样的设备。

现在懒猫微服送好礼,参与活动就有机会获得小龙虾 AI 主机一台!!!


抽奖规则(必看)

  1. 收藏帖子,在评论区评论:
    “扫码进群,抢红包,抽小龙虾 AI 主机!实现 OpenClaw 龙虾自由!”
  2. 扫二维码进「懒猫微服小龙虾抽奖群」
    二维码满员可添加帖子底部工作人员微信邀请进群。


开奖时间和规则

  • 开奖时间:3 月 17 日(周二)晚上
  • 开奖方式:拼手气红包开奖
    所有奖品对应拼手气红包,运气王获得对应奖品
    (多个红包时,金额最高者为运气王)


💎 奖品列表

  1. 价值 4399 元「懒猫微服 LC-02 小龙虾 AI 主机」× 1 套
  2. 价值 299 元「 CHERRY MX1.1 茶轴机械键盘」+「 499 元懒猫微服小龙虾 AI 主机优惠券」× 2 套
  3. 价值 99 元「懒猫微服文化 T 恤」+「 499 元懒猫微服小龙虾 AI 主机优惠券」× 3 套


优惠券使用规则

  • 中奖优惠券仅用于小程序购买
  • 不与京东分期优惠叠加
  • LC-03 基础款利润微薄,不参与任何优惠活动


特别提醒

  1. 必须进入「懒猫微服小龙虾抽奖群」,才能参与抢红包拼手气。
  2. 中奖用户需将活动参与截图 + 主页截图发给工作人员验证。


购买渠道和优惠

  1. 京东
    搜索「懒猫微服」下单,享受京东免息分期:


    • 32G+2T:6 期免息分期
    • 48G 无盘:6 期免息分期
  2. 全新系列懒猫 AI 算力舱已上线
    添加微信获取最新优惠价格。

  3. 懒猫零元购
    微服用户每移植一款应用到懒猫商店,即可得百元红包
    原创应用奖励翻倍
    撰写一篇攻略可得 50 元红包,多移多得,无上限。

我目前的工作流是自己写个阶段大纲,然后和文字材料一起输入给 Gemini ,让他输出一份逐页的大纲,最后交给 Agent 输出 PPT 。

目前只使用过 GenSpark ,效果还是挺让我惊讶的,省了我不少时间,但仍然有一些问题。

  1. 即使调用了不同的模板,产出的页面风格依然很类似,浓重的通用 AI 网页味,希望能用插件增强 UI/UX 设计能力,交由用户来挑选风格。
  2. 图片嵌入的能力不理想,我在大纲中写“Page 1 ,需要嵌入 fig1.png”这种指令遵循比较差,agent 倾向于自己去联网搜索图片然后嵌入,这一块不清楚是不是我使用方法有问题。
  3. 布局不准,不少页面都需要手动调整。
  4. 在线编辑功能比较受限。
  5. 导出为 PPT 格式时,总会有布局错乱、元素缺漏情况。

麻烦各位来推荐下觉得好用的 PPT Agent ,最好还能讲下使用成本。

在日常办公中,我们经常需要在Excel文件里添加水印,例如印上公司Logo维护品牌形象,或者加上“草稿”字样避免被当作最终版本使用。这些需求看似简单,但当我们把这些表格搬到Web系统中,面对多用户访问、动态数据更新、安全审计等场景时,传统的Excel水印方案就开始显得力不从心了。如何在企业Web应用中优雅的解决水印问题,是企业应用系统规范化、安全化始终要考虑的问题之一。

一、水印的第一种境界:静态标识

这是最基础、最常见的水印需求——在文件上固定显示一段文字或一个图片,用来标识文档的当前状态。

Excel中的实现方式

Excel用户通常会采用三种手工方法:

1.页眉页脚法

插入图片到页眉页脚,可实现打印水印。通过调整图片尺寸(如设置为500%以上)并设置“冲蚀”效果,可以铺满全页作为背景。

优点:操作简单,打印时自动显示,不影响单元格内容编辑。

缺点:只能插入图片,且在所有页面上位置固定,无法实现编辑时水印。
在这里插入图片描述
在这里插入图片描述

2.形状/艺术字法

插入文本框或者艺术字,并调整透明度、旋转角度,视觉效果灵活。

优点:自定义程度高,可任意旋转,调整颜色及透明度。

缺点:可能会影响单元格编辑,无法快速填充完整个显示界面。
在这里插入图片描述

在这里插入图片描述

3.背景图片法

在页面布局中设置背景图,操作最简单但无法打印,背景图片单独作用在某个工作表上,因此可以为不同的工作表设置不同的背景图片。

优点:操作简便快捷,图片可以平铺整个工作表区域。

缺点:无法实现打印水印。

这些方法足以应对个人办公场景下的基本需求,操作直观,无需特殊产品权限。

SpreadJS的对应实现

作为一款对标Excel的纯前端表格控件,SpreadJS继承了Excel的操作体验,同时提供了更灵活的编程接口:

// 单元格级水印 - 在空白单元格显示提示文字
let style = new GC.Spread.Sheets.Style();
style.watermark = "请输入内容";
sheet.setStyle(0, 1, style);

在这里插入图片描述

// 打印水印 - 精确控制位置和样式
var printInfo = sheet.printInfo();
var watermark = {
    x: 100, y: 200, width: 300, height: 150,
    imageSrc: "logo.png",
    page: "all"
};
printInfo.watermark([watermark]);

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/0cfb621375324d52b88e97c1463f...

// 背景图水印
sheet.backgroundImage("imageURL/base64")

在这里插入图片描述

在Web应用中,SpreadJS的这些能力可以很好地集成到业务系统中,结合业务流程,调用相关API,让水印根据业务流程动态呈现,而非手工添加的“补丁”。

二、水印的第二种境界:动态生成及安全追朔

当表格从个人办公走向企业协作,水印的需求也会随之升级。它不再是一成不变的静态内容,而是需要根据上下文动态生成。

典型场景

  • 财务报表需要显示当前的导出时间;
  • 人事报表需要根据查看者角色显示不同权限提示或登录名称;
  • 客户资料需要在每个页面角落印上查询条件。

Excel中的动态水印方案

很多人可能不知道,Excel其实也具备这种动态水印能力,只是它属于企业级安全功能,门槛较高:

  1. 技术原理:这是Microsoft 365的信息保护体系的一部分,基于敏感度标签自动生成。IT管理员在Microsoft Purview合规门户中配置动态水印策略,设置水印显示的内容变量,如{UserName}{UserEmail}{DateTime}
  2. 配置流程

    1. 企业需购买Microsoft 365 E5、E3等特定许可证
    2. IT管理员创建并配置敏感度标签,开启“动态水印”选项
    3. 文档作者为文件应用该标签
    4. 此后任何人打开文件,系统会自动读取登录人信息并渲染水印
  3. 优缺点分析

    1. 优点:安全可追溯、策略强制、自动生效
    2. 缺点:需要高级许可证、依赖IT配置、普通用户无法自行启用

这意味着,Excel的动态水印虽然强大,但对绝大多数企业来说,实施门槛较高,且无法灵活定制。相比之下,SpreadJS提供了一种更亲民的实现方式,只需几行代码,就能达到同样的安全效果:

SpreadJS的轻量化实现

借助Web技术的灵活性和SpreadJS内置的设置水印相关API,SpreadJS可以轻松实现这些动态需求:

// 根据当前时间动态生成水印
function createWatermarkImage(text, width, height) {
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d');
    // 清空背景(透明)
    ctx.clearRect(0, 0, width, height);
    // 设置文字样式
    ctx.font = 'bold 36px Microsoft YaHei, SimHei, sans-serif';
    ctx.fillStyle = 'rgba(180, 180, 180, 0.35)';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    // 旋转并平铺文字
    ctx.save();
    ctx.translate(width / 2, height / 2);
    ctx.rotate(-Math.PI / 6); // 倾斜 -30 度
    ctx.fillText(text, 0, 0);
    ctx.restore();
    return canvas.toDataURL('image/png');
}
const now = new Date();
const pad = n => String(n).padStart(2, '0');
const timeText = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
const watermarkDataUrl = createWatermarkImage(timeText, 600, 250);
sheet.backgroundImage(watermarkDataUrl);

在这里插入图片描述

这种动态生成能力,让水印真正成为业务数据的一部分,而不是一个孤立的装饰元素。

企业级的防泄露手段

在一些高度敏感的业务场景中(如财务报表、客户信息、研发文档),仅仅标记“机密”是不够的。当文件被拍照或截图流出时,我们需要能够追溯到是谁泄露了这份文件。

这正是“动态用户水印”的价值所在,张三打开文件,背景显示“张三的信息”;李四打开文件,背景自动变成“李四的信息”。每一份流出文件上都带着查看者本人的身份信息,形成有效的威慑和追溯依据。

在这里插入图片描述

三、SpreadJS的独特价值:在兼容中超越

作为一款纯前端的JavaScript表格控件,SpreadJS一直坚持一个理念:深度兼容Excel,同时发挥Web优势

让Excel资产保值增值

我们深知,绝大多数企业都积累了海量的Excel模板和历史数据。因此,SpreadJS在设计和开发过程中,始终把Excel兼容性作为核心指标:

  • 文件格式兼容:支持导入导出Excel文件(xlsx、xlsm、csv等),保留数据、样式、公式、图表等元素,历史文件资产得以最大程度复用。
  • 操作体验继承:熟悉Excel的用户可以快速上手SpreadJS,学习成本极低,无需二次培训。

为Web应用而生

在兼容的基础上,SpreadJS充分发挥了Web技术的优势,实现了Excel难以企及的能力:

能力维度SpreadJS的优势
部署便捷纯前端控件,无需安装任何插件,浏览器即开即用
系统集成可无缝对接各类后端API,实现数据实时交互
协同支持支持多用户在线编辑,数据实时同步
二次开发提供丰富的API接口,可按需扩展功能
动态水印深度业务融合,基于业务需求完成各种水印需求

从静态标识到动态生成及安全追溯,水印能力的层层递进,正是SpreadJS在兼容Excel的同时,不断拓展表格应用边界的缩影。回到水印这个话题本身。无论是Excel还是SpreadJS,水印都只是一个工具,真正重要的是它背后承载的业务价值:

  • 它可以是文档管理中的一道“提醒线”,防止误操作;
  • 它可以是品牌形象的“展示窗”,在每份输出上留下印记;
  • 它更可以是数据安全的“防护网”,对每一次访问留下可追溯的证据。

如果企业正在规划WEB表格应用系统,不妨思考一下:你的水印需求停留在哪个境界?现有的Excel方案能否满足?当表格从桌面走向云端,从单机走向协同,水印这件事,或许值得重新考虑一下。

免费体验活动

官网地址:https://ai.17nas.com/

10 名随机直接送 50 美元

记得说明你的需求,这样会优先赠送体验

回帖时记得带上 ID,参考下图 👇

回帖示意图


另外,其他国产模型也可以免费使用:

国产模型示意图


🧪 Mini 新人体验套餐(可用 Opus 4.6 )

适合刚入门试用的小套餐:

项目 说明
体验时长 3 天
每日额度 $10 / 天
总额度(合计) $30
有效期 3 天
额度重置 每天重置
升级分组 svip


温馨提示

  • 前 10 名为随机赠送;
  • 描述清楚自己的使用需求,更容易获得优先体验资格;
  • 回帖时别忘了附上自己的 ID

通勤路上、开会前、临时要改数据的时候,表格问题往往都是现在就得处理。
但手机操作表格这件事,确实不太方便。

所以这次,我们把表答做进了小程序:【表答】说句话让 AI 处理表格 excel
你只需要用语音或打字告诉 AI 需求,剩下的表格整理、计算处理和数据分析,都会自动完成。

目前,小程序已经支持这些场景:

1. 表格编辑 / 计算处理

上传表格或 Excel 后,AI 可以直接帮你完成整理格式、拆表并表、优化结构、公式处理、批量计算等常见操作,也支持图生表
如果不想从零开始做表格,还可以直接使用现有的 100+ 种表格模板。不管你手里已经有表,还是想直接做一张新的,都能更快搞定。
!!

2. 数据分析 / 报告生成

除了处理表格,小程序现在也支持直接做数据分析。你可以基于表格内容完成趋势分析、结构分析、异常识别、情感分析、共词分析、词频统计等任务。
分析完成后,AI 还会自动生成包含 19+ 图表 的完整报告,方便直接用于汇报和决策参考

3. 复制内容,一键生成表格

有时候,你手里的内容并不是现成表格,而是网页信息、零散数据,或者一段文字。直接复制进来,AI 就会自动帮你整理成结构化表格
![图片]

如果你也有临时处理表格、做数据分析的需求,快来试试表答小程序。