vue3实现包含表格的Word文件导出
vue3实现包含表格的Word文件导出
近期遇到一个要求,需要在网页上导出Word文档,文档中有表格,也有普通的数据,查阅了很多资料,总算比较完美的解决了,记录一下
先上一下最终效果
演示视频
vue3项目根据Word模板导出Word文件
当然,个人的项目要比这个演示的视频复杂多了,需要配合后端完成
实现过程主要参考了这篇文章
一、第三方库的安装
要实现Word的导出功能,需要额外安装以下第三方包:
"dependencies": {"angular-expressions": "^1.2.1","docx-preview": "^0.3.2","docxtemplater": "^3.49.1","docxtemplater-image-module-free": "^1.1.1","file-saver": "^2.0.5","lodash": "^4.17.21","pizzip": "^3.1.7",},
版本安装最新的就行了,这是我自己的目前最新的版本(2024年8月)
二、Word模板的创建
必须要有一个Word模板,根据自己的需求创建,我的模板如下:

这个模板中有常规变量、图片变量和表格变量,表格变量需要循环表格数据获取
1、普通变量
普通变量直接用{变量名}的形式放在模板中就行了,注意这里的变量名必须与前端vue组件中的变量名保持一致
2、图片变量
图片变量用{%变量名}表示,就是普通变量前加%符号
3、表格变量
通常情况下,表格都是多行的,也就是说需要循环遍历前端的表格数据,表格数据的处理比较复杂,处理步骤如下:
- 需要循环的表格数据用
{#变量名}开始,用{/变量名}结束循环,也就是{#tableData}和{/tableData} - 列变量用
{变量名}表示,也就是{order}、{col1}、{col}和{col3}、{col5}
看下我前端的tableData变量:
const tableData = ref([{ order: 0, col1: "合计", col: 6266, col3: 23, col5: 2 },{ order: 1, col1: "徐州", col: 706, col3: 1, col5: 0 },{ order: 2, col1: "苏州", col: 668, col3: 2, col5: 0 },{ order: 3, col1: "盐城", col: 624, col3: 2, col5: 0 },{ order: 4, col1: "南通", col: 518, col3: 0, col5: 0 },{ order: 5, col1: "连云港", col: 498, col3: 3, col5: 0 },{ order: 6, col1: "淮安", col: 490, col3: 3, col5: 1 },{ order: 7, col1: "常州", col: 458, col3: 1, col5: 0 },{ order: 8, col1: "泰州", col: 454, col3: 1, col5: 0 },{ order: 9, col1: "无锡", col: 433, col3: 2, col5: 0 },{ order: 10, col1: "南京", col: 400, col3: 2, col5: 1 },{ order: 11, col1: "扬州", col: 383, col3: 3, col5: 0 },{ order: 12, col1: "宿迁", col: 363, col3: 1, col5: 0 },{ order: 13, col1: "镇江", col: 271, col3: 2, col5: 0 },
]);
在看下最后生成的表格:

创建好Word模板后,放在静态文件夹中就行了
三、编写导出Word的工具函数
在utils文件夹中创建exportFile.js文件,编写以下代码:
// 引入基本模块
import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import PizZipUtils from "pizzip/utils/index.js";
import { saveAs } from "file-saver";
// 图片模块
import ImageModule from "docxtemplater-image-module-free";
// 解析语法模块
import expressions from "angular-expressions";
import assign from "lodash/assign";
// 文档预览模块
import { renderAsync } from "docx-preview";expressions.filters.lower = function (input) {if (!input) return input;return input.toLowerCase();
};function angularParser(tag) {tag = tag.replace(/^\.$/, "this").replace(/('|')/g, "'").replace(/("|")/g, '"');const expr = expressions.compile(tag);return {get: function (scope, context) {let obj = {};const scopeList = context.scopeList;const num = context.num;for (let i = 0, len = num + 1; i < len; i++) {obj = assign(obj, scopeList[i]);}return expr(scope, obj);},};
}// 加载文件
function loadFile(url, callback) {PizZipUtils.getBinaryContent(url, callback);
}// 配置空值替换函数 作为配置参数可配置在setOptions中
function nullGetter(part, scopeManager) {if (!part.module) {return "-null-";}if (part.module === "rawxml") {return "";}return "--";
}/*** 预览word,支持图片* @param {Object} tempDocxPath 模板文件路径* @param {Object} wordData 导出数据* @param {Object} fileName 导出文件名* @param {Arrsy} imgSize 自定义图片尺寸*/
export const getWordImage = (tempDocxPath, wordData, imgSize, file) => {// 本地word.docx文件需要放在public目录下loadFile(tempDocxPath, (error, content) => {if (error) {throw error;}// 图片配置const imageOpts = {getImage: function (tagValue, tagName) {return new Promise(function (resolve, reject) {PizZipUtils.getBinaryContent(tagValue, function (error, content) {if (error) {return reject(error);}return resolve(content);});});},getSize: function (img, tagValue, tagName) {const size = imgSize[tagName] ? imgSize[tagName] : [150, 150];return size;},};let imageModule = new ImageModule(imageOpts);const zip = new PizZip(content);// 实例化有两种方式 这里是链式const doc = new Docxtemplater().loadZip(zip).setOptions({// delimiters: { start: "[[", end: "]]" },paragraphLoop: true,linebreaks: true,nullGetter: nullGetter,parser: angularParser,}).attachModule(imageModule).compile();doc.renderAsync(wordData).then(() => {const out = doc.getZip().generate({type: "blob",mimeType:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",});renderAsync(out, file);});});
};/*** 导出word,不支持图片* @param {Object} tempDocxPath 模板文件路径* @param {Object} wordData 导出数据* @param {Object} fileName 导出文件名*/
export const exportWord = (tempDocxPath, wordData, fileName) => {// 本地word.docx文件需要放在public目录下loadFile(tempDocxPath, (error, content) => {if (error) {throw error;}const zip = new PizZip(content);// 没有配置解析语法,深层次对象语法(obj.xx.xx)不可识别const doc = new Docxtemplater(zip, {paragraphLoop: true,linebreaks: true,});doc.render(wordData);const out = doc.getZip().generate({type: "blob",mimeType:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",});// Output the document using Data-URIsaveAs(out, `${fileName}.docx`);});
}/*** 导出word,支持图片* @param {Object} tempDocxPath 模板文件路径* @param {Object} wordData 导出数据* @param {Object} fileName 导出文件名* @param {Arrsy} imgSize 自定义图片尺寸*/
export const exportWordImage = (tempDocxPath, wordData, fileName, imgSize) => {// 本地word.docx文件需要放在public目录下loadFile(tempDocxPath, (error, content) => {if (error) {throw error;}// 图片配置const imageOpts = {getImage: function (tagValue, tagName) {return new Promise(function (resolve, reject) {PizZipUtils.getBinaryContent(tagValue, function (error, content) {if (error) {return reject(error);}return resolve(content);});});},getSize: function (img, tagValue, tagName) {const size = imgSize[tagName] ? imgSize[tagName] : [150, 150]return size;},};let imageModule = new ImageModule(imageOpts);const zip = new PizZip(content);// 实例化有两种方式 这里是链式const doc = new Docxtemplater().loadZip(zip).setOptions({// delimiters: { start: "[[", end: "]]" },paragraphLoop: true,linebreaks: true,nullGetter: nullGetter,parser: angularParser,}).attachModule(imageModule).compile();doc.renderAsync(wordData).then(function () {const out = doc.getZip().generate({type: "blob",mimeType:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",});saveAs(out, `${fileName}.docx`);});});
}
这里有Word的预览以及Word的导出处理函数,我直接参考的他人的,没做修改,可以自己根据需求进行修改,后面有时间我再慢慢理解
四、前端页面预览和导出
先上代码,我这里只写了个演示,所有没有用路由什么的,就是直接放在App.vue根组件中
<script setup>
import { exportWordImage, getWordImage } from "@/utils/exportFile";
import { ref } from "vue";const dialogVisible = ref(false);
const startSchemeTemplate = ref({name: "启动方案名称",time: "2023-12-12",scope: `1.XXXX所有一、二次设备 2.XXXX主变、XXXX主变(XX管辖)`,projectAdjuster: `1.XXXX,XXXX主变冲击五次、核相。2.XXXXX设备冲击一次,XXXXXXX二次定相。3.XXXXXX,XXXX差动保护带负荷试验。(XX管辖)4.XXXXXX备自投实跳试验。`,condition: `1.XXX启动范围内的所有一、二次设备施工结束,验收合格,监控信息与相应调控人员核对完备,设备可以带电,站内一次设备相位正确。2.XXX待用XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、银标XXXXXX、银阳XXXXXX、银区XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、XXXXXX开关保护按定值单整定并投入。3.启动范围内所有设备均为冷备用状态。`,stepAdjuster: `1.XXXXXX冲击一次、定相。2.XXXXXX一次设备冲击(见附图2)`,imgPath: "https://docxtemplater.com/puffin.png",tableData: []
});
const imgSize = ref({imgPath: [150, 150],imgPath1: [550, 250],
});const tableData = ref([{ order: 0, col1: "合计", col: 6266, col3: 23, col5: 2 },{ order: 1, col1: "徐州", col: 706, col3: 1, col5: 0 },{ order: 2, col1: "苏州", col: 668, col3: 2, col5: 0 },{ order: 3, col1: "盐城", col: 624, col3: 2, col5: 0 },{ order: 4, col1: "南通", col: 518, col3: 0, col5: 0 },{ order: 5, col1: "连云港", col: 498, col3: 3, col5: 0 },{ order: 6, col1: "淮安", col: 490, col3: 3, col5: 1 },{ order: 7, col1: "常州", col: 458, col3: 1, col5: 0 },{ order: 8, col1: "泰州", col: 454, col3: 1, col5: 0 },{ order: 9, col1: "无锡", col: 433, col3: 2, col5: 0 },{ order: 10, col1: "南京", col: 400, col3: 2, col5: 1 },{ order: 11, col1: "扬州", col: 383, col3: 3, col5: 0 },{ order: 12, col1: "宿迁", col: 363, col3: 1, col5: 0 },{ order: 13, col1: "镇江", col: 271, col3: 2, col5: 0 },
]);const htmlTitle = ref("启动方案");const downLoad = () => {exportWordImage("../template.docx",startSchemeTemplate.value,htmlTitle.value,imgSize.value);
};const goPreview = () => {dialogVisible.value = true;
};const file = ref(null);
const handleOpened = () => {startSchemeTemplate.value.tableData = tableData.valuegetWordImage("../template.docx",startSchemeTemplate.value,imgSize.value,file.value);
};
</script><template><div style="height: 90%; background: #fff; padding: 24px"><div style="margin-bottom: 17px; text-align: left"><el-button type="primary" @click="downLoad"> 下载启动方案 </el-button><el-button type="primary" @click="goPreview"> 预览启动方案 </el-button></div><el-divider /><div style="margin-top: 24px"><!--搜索区域--><el-form :model="startSchemeTemplate" label-width="110px"><el-row :gutter="24"><el-col :span="12"><el-form-item label="启动方案名称:"><el-inputv-model="startSchemeTemplate.name"placeholder="请输入"/></el-form-item></el-col><el-col :span="12"><el-form-item label="预定启动时间:"><el-date-pickerv-model="startSchemeTemplate.time"type="date"placeholder="请选择"/></el-form-item></el-col></el-row><el-row :gutter="24" style="height: 280px"><el-col :span="12"><el-form-item label="启动范围:"><el-inputv-model="startSchemeTemplate.scope"placeholder="请输入"type="textarea":autosize="{ minRows: 13.5, maxRows: 14 }"/></el-form-item></el-col><el-col :span="12"><el-form-item label="调试项目:"><el-inputv-model="startSchemeTemplate.projectAdjuster"placeholder="请输入"type="textarea":autosize="{ minRows: 13.5, maxRows: 14 }"/></el-form-item></el-col></el-row><el-row :gutter="24" style="height: 280px"><el-col :span="12"><el-form-item label="启动条件:"><el-inputv-model="startSchemeTemplate.condition"placeholder="请输入"type="textarea":autosize="{ minRows: 13.5, maxRows: 14 }"/></el-form-item></el-col><el-col :span="12"><el-form-item label="调试步骤:"><el-inputv-model="startSchemeTemplate.stepAdjuster"placeholder="请输入"type="textarea":autosize="{ minRows: 13.5, maxRows: 14 }"/></el-form-item></el-col></el-row></el-form></div></div><el-dialogv-model="dialogVisible"@opened="handleOpened"title="流程图"width="1200px"top="5vh"><div class="docWrap"><div ref="file"></div></div></el-dialog>
</template><style scoped>
.btn {float: left;margin: 0 0 24px;
}
.docWrap {height: 700px;overflow: auto;clear: both;
}
</style>
变量全部放在startSchemeTemplate这个响应式变量中,根据前端的表单(或者输入)来更改模板中的数据,把模板和模板中需要的数据对应起来看就更直观了
const startSchemeTemplate = ref({name: "启动方案名称",time: "2023-12-12",scope: `1.XXXX所有一、二次设备 2.XXXX主变、XXXX主变(XX管辖)`,projectAdjuster: `1.XXXX,XXXX主变冲击五次、核相。2.XXXXX设备冲击一次,XXXXXXX二次定相。3.XXXXXX,XXXX差动保护带负荷试验。(XX管辖)4.XXXXXX备自投实跳试验。`,condition: `1.XXX启动范围内的所有一、二次设备施工结束,验收合格,监控信息与相应调控人员核对完备,设备可以带电,站内一次设备相位正确。2.XXX待用XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、银标XXXXXX、银阳XXXXXX、银区XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、XXXXXX开关保护按定值单整定并投入。3.启动范围内所有设备均为冷备用状态。`,stepAdjuster: `1.XXXXXX冲击一次、定相。2.XXXXXX一次设备冲击(见附图2)`,imgPath: "https://docxtemplater.com/puffin.png",tableData: []
});

一言蔽之,把Word模板中需要动态变化的数据放在响应式数据中(这里是startSchemeTemplate),然后根据响应式数据填充模板
预览和导出功能,调用utils/exportFile.js中对应的方法就可以了
五、代码仓库
我已经把这个程序的所有代码和模板文件都传到了代码仓库,有需要的可以自行下载理解
相关文章:
vue3实现包含表格的Word文件导出
vue3实现包含表格的Word文件导出 近期遇到一个要求,需要在网页上导出Word文档,文档中有表格,也有普通的数据,查阅了很多资料,总算比较完美的解决了,记录一下 先上一下最终效果 演示视频 vue3项目根据Wor…...
【深度学习】TTS,CosyVoice,推理部署的代码原理讲解分享
文章目录 demo代码加载配置文件speech_tokenizer_v1.onnx(只在zero_shot的时候使用)campplus.onnx(只为了提取说话人音色embedding)`campplus_model` 的作用代码解析具体过程解析总结示意图CosyVoiceFrontEndCosyVoiceModel推理过程总体推理过程推理速度很慢: https://git…...
flask高频面试题
目录 高频面试题及答案1. 如何在Flask中处理数据库迁移?2. Flask如何处理文件上传?3. 如何在Flask中处理跨域请求(CORS)?4. 如何在Flask中实现用户认证?5. Flask如何处理会话?6. Flask如何处理表…...
尚硅谷谷粒商城项目笔记——五、使用docker安装mysql
五、使用docker安装mysql 注意: 因为电脑是AMD芯片,自己知识储备不够,无法保证和课程中用到的环境一样,所以环境都是自己根据适应硬件软件环境重新配置的,这里的虚拟机使用的是VMware。 使用 Docker 安装 MySQL 与安…...
filebeat + logstash使用笔记
背景 本文中有2台主机: (1)1.1.1.1是OpenStack的nova节点,安装filebeat (2)1.1.1.2是logstash节点 在1.1.1.1上通过filebeat读取OpenStack的nova-compute组件日志(/var/log/nova/nova-compute.…...
学校考场电子钟设置自动开关机,节能环保
在标准化考试中,准确的时间显示对于确保考试的公正性和秩序至关重要。然而,传统的电子钟系统往往存在一些问题,影响了考试管理的效率。 一、学校普通电子钟使用问题 二、学校考场电子钟优点 学校同步时钟系统通过自动同步网络或卫星时间的方式…...
短剧APP系统开发带来了哪些发展空间?
在影视行业快速发展的时期,短剧作为一种新兴的影视模式,获得了大众的欢迎。目前,短剧行业巨大的发展空间,再次成为大众关注的焦点。 随着移动互联网的发展,信息技术不断升级进步,短剧APP系统的开发&#x…...
PaddlePaddle / PaddleOCR踩坑记,动手实现一个OCR服务器
文章目录 一、环境搭建1、官网2、准备环境 二、编码实现一个web程序 一、环境搭建 1、官网 https://gitee.com/paddlepaddle/PaddleOCR#/paddlepaddle/PaddleOCR/blob/main/doc/doc_ch/quickstart.md 2、准备环境 本地环境坑太多了,好在官网还有一种基于docker搭…...
JeecgBoot低代码平台简单记录
BasicModal弹窗 Usage 由于弹窗内代码一般作为单文件组件存在,也推荐这样做,所以示例都为单文件组件形式 注意v-bind"$attrs"记得写,用于将弹窗组件的attribute传入BasicModal组件 attribute:是属性的意思,…...
零基础入门转录组数据分析——机器学习算法之xgboost(筛选特征基因)
零基础入门转录组数据分析——机器学习算法之xgboost(筛选特征基因) 目录 零基础入门转录组数据分析——机器学习算法之xgboost(筛选特征基因)1. xgboost基础知识2. xgboost(Rstudio)——代码实操2. 1 数据…...
C#开发常见面试题三(浅复制和深复制的区别)
C#开发常见面试题三(浅复制和深复制的区别) 一.浅复制和深复制定义 (1)浅复制:复制一个对象的时候,仅仅复制原始对象中所有的非静态类型成员和所有的引用类型成员的引用。(新对象和原对象将共享所有引用类型成员的实…...
Linux/C 高级——Linux命令
从这里开始,我们展开对Linux/c 高级的学习,首先介绍的是在Linux/c高级中,Linux的部分 目录 1.Linux简介 1.1Linux起源 1.2查看系统版本命令 1.3分层结构 1.4系统关机重启命令 2.Linux安装工具 2.1软件包安装 2.1.1软件包的管理机制 …...
怎么在 tailwindcss 项目中自定义一些可复用的样式
在 Tailwind CSS 项目中自定义可复用的样式有几种常用方法: 使用 apply 指令 你可以在 CSS 文件中使用 apply 指令来创建可复用的样式类: layer components {.btn-primary {apply py-2 px-4 bg-blue-500 text-white font-semibold rounded-lg shadow-md hover:bg-blue-700 f…...
在vue3中 引入echarts
安装:npm install echarts --save 方式一:直接在组件中引用 <template><divref"myChart"id"myChart":style"{ width: 800px, height: 400px }"></div></template><script>import * as echa…...
栈和队列(数据结构)
1. 栈(Stack) 1.1 概念 栈 :一种特殊的线性表,其 只允许在固定的一端进行插入和删除元素操作 。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO ( Last In First Out )的原…...
如何实现ElementUI表单项label的文字提示?
在Vue和ElementUI的丰富组件库中,定制化表单是常见的需求之一。那么如何在表单项label后添加文字提示,以提升用户体验呢? 首先我们来看一下效果图: 这里我们鼠标移动到❓图标上就会出现提示 在 ElementUI 中,el-form-item 组件允许使用 slot 自定义 label。通过在 el-fo…...
c++中的标准库
前言 hello,我是文宇。 正文 C标准库是C编程语言的基本组成部分之一,它为开发人员提供了一套丰富和强大的工具和功能,以便快速开发高效、可靠和可移植的应用程序。C标准库由两个主要部分组成:STL(Standard Template…...
洛谷 B2145 digit 函数 B2146 Hermite 多项式 题解
题目目录: No.1 B2145 digit 函数 No.2 B2146 Hermite 多项式 OK,开始正文! 第一题:B2145 digit 函数 题目描述 在程序中定义一函数 digit(n,k),它能分离出整数 n 从右边数第 k 个数字。 输入格式 正整数 n …...
tailwindcss @apply 和 @layer 有什么区别
在 Tailwind CSS 中,apply 和 layer 是两个不同的指令,它们各自有不同的用途和功能。以下是它们的区别和使用方法: apply 指令 apply 指令用于将一组现有的 Tailwind CSS 工具类应用到一个自定义的 CSS 类中。这对于简化和复用复杂的样式非…...
React 中的 useMemo 和 useCallback
1. useMemo语法 const memoizedValue useMemo(() > computeExpensiveValue(a, b), deps); 1. 传入一个函数进去,会返回一个 memoized 值,需要注意的是,函数内必须有返回值; 2. 第二个参数会依赖值,当依赖值更新…...
科学/技术路线之争、天才 vs 体制、创新 vs 实用的对立故事
文章目录一、最像「交流电 vs 直流电」的路线大战1. **尼古拉特斯拉 vs 托马斯爱迪生**(你已知的原型)二、同级别的「史诗级科学互怼」2. **伽利略 vs 教会/亚里士多德学派**3. **牛顿 vs 莱布尼茨**4. **爱因斯坦 vs 玻尔**5. **巴斯德 vs 普歇**三、技…...
ReplaceItems.jsx:Illustrator对象替换的终极指南,5种模式彻底解放设计师双手
ReplaceItems.jsx:Illustrator对象替换的终极指南,5种模式彻底解放设计师双手 【免费下载链接】illustrator-scripts Adobe Illustrator scripts 项目地址: https://gitcode.com/gh_mirrors/il/illustrator-scripts 在Adobe Illustrator的日常设计…...
终极指南:使用smcFanControl彻底解决Intel Mac散热问题
终极指南:使用smcFanControl彻底解决Intel Mac散热问题 【免费下载链接】smcFanControl Control the fans of every Intel Mac to make it run cooler 项目地址: https://gitcode.com/gh_mirrors/smc/smcFanControl 在MacBook Pro运行大型编译任务或视频渲染…...
保姆级教程:在YOLOv8.yaml里手动添加P2层,让你的模型看清8x8像素的小目标
在YOLOv8中集成P2层的实战指南:从配置文件修改到性能优化 当面对监控摄像头中快速移动的蚂蚁群或是卫星图像里的小型车辆时,传统目标检测模型往往会力不从心。这些8x8像素级别的微小目标,恰恰是许多实际应用场景中的关键检测对象。本文将彻底…...
手把手教你部署coze-loop:让AI帮你重构代码,提升编程效率
手把手教你部署coze-loop:让AI帮你重构代码,提升编程效率 1. 项目概述 coze-loop是一款基于Ollama框架的AI代码优化助手,它能像一位专业软件工程师一样,帮你重构和优化代码。这个工具特别适合那些希望提升代码质量但时间有限的开…...
开源工具助力音频内容管理:打破平台限制的跨平台解决方案
开源工具助力音频内容管理:打破平台限制的跨平台解决方案 【免费下载链接】xmly-downloader-qt5 喜马拉雅FM专辑下载器. 支持VIP与付费专辑. 使用GoQt5编写(Not Qt Binding). 项目地址: https://gitcode.com/gh_mirrors/xm/xmly-downloader-qt5 你是否曾遇到…...
SimpleX协议标准化之路:终极隐私通信的完整指南
SimpleX协议标准化之路:终极隐私通信的完整指南 SimpleX是全球首个完全不需要任何用户标识符的通信平台,为隐私保护设立了新的标准。作为100%隐私设计理念的先行者,SimpleX通过其革命性的协议架构,彻底改变了我们对安全通信的认知…...
计算机二级C语言常考选择题
经原国家教育委员会(现教育部)批准、由教育部考试中心主办、面向社会、用于考查非计算机专业应试人员计算机应用知识与技能的全国性计算机水平考试体系,是全国计算机等级考试(National Computer Rank Examination,以下…...
Lite-Avatar与ChatGPT结合的智能对话系统实现
Lite-Avatar与ChatGPT结合的智能对话系统实现 1. 引言 想象一下,你正在和一个数字人进行视频对话,它不仅能够听懂你的问题,还能用生动的表情和自然的语气回答你,就像和一个真人交流一样。这种体验现在已经不再是科幻电影里的场景…...
Curvature as Safety: A Geometric Framework for Detecting Cognitive Singularities in Agentic AI
Curvature as Safety: A Geometric Framework for Detecting Cognitive Singularities in Agentic AI (曲率即安全:面向Agentic AI认知奇点的几何检测框架)作者:方见华 单位:世毫九实验室第一部分:问题定义(The Hook&a…...
