当前位置: 首页 > news >正文

从CSV到数据库(简易)

需求:客户上传CSV文档,要求CSV文档内容查重/插入/更新相关数据。
框架:jdbcTemplate、commons-io、
DB:oracle

相关依赖:
这里本来打算用的2.11.0,无奈正式项目那边用老版本1.3.1,新版本对类型支持和转换好一点。不过无伤大雅。

        <dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>1.3.1</version></dependency>

CSV文档格式:

Xxx Code,Yerial,OP
600001,2024082400305, OP20240818_XDFD
600001,2024082400306, OP20240818_XDFD
600001,2024082400307, OP20240818_XDFD
600001,2024082400308, OP20240818_XDFD
600001,2024082400309, OP20240818_XDFD
600001,2024082400310, OP20240818_XDFD
600001,2024082400311, OP20240818_XDFD
600001,2024082400312, OP20240818_XDFD
600001,2024082400313, OP20240818_XDFD
600001,2024082400314, OP20240818_XDFD
600001,2024082400315, OP20240818_XDFD
600001,2024082400316, OP20240818_XDFD
600001,2024082400317, OP20240818_XDFD
600001,2024082400318, OP20240818_XDFD
600001,2024082400319, OP20240818_XDFD
600001,2024082400320, OP20240818_XDFD
600001,2024082400321, OP20240818_XDFD
600001,2024082400322, OP20240818_XDFD
600001,2024082400323, OP20240818_XDFD
600001,2024082400324, OP20240818_XDFD
600001,2024082400325, OP20240818_XDFD

接口:

MultipartFile接受CSV文件

    @PostMapping("/import")public ResponseEntity<BaseResponse<?>> importCSV(@RequestBody MultipartFile files) {xxxService.importSerial(files);return new ResponseEntity<>(new BaseResponse<>(), HttpStatus.OK);}

前段需要在Request-Body中以form-data的形式上传文档
在这里插入图片描述

CSV解析

简单转成Json

    private String convertCsvToJson(MultipartFile multipartFile) throws IOException {// read csv as listList<String> lines = IOUtils.readLines(multipartFile.getInputStream(), "UTF-8");List<List<String>> data = lines.stream().skip(1) // skip label line.filter(line -> !line.trim().isEmpty()) // filtering empty line.map(line -> Arrays.asList(line.split(","))).collect(Collectors.toList());return objectMapper.writeValueAsString(data);}

转换后是这样的:
注意这是print出来的json对象,本来应该是json字符串。

[["600001","2024082400305","OP20240818_XDFD"],["600001","2024082400306","OP20240818_XDFD"],["600001","2024082400307","OP20240818_XDFD"],["600001","2024082400308","OP20240818_XDFD"],["600001","2024082400309","OP20240818_XDFD"],["600001","2024082400310","OP20240818_XDFD"],["600001","2024082400311","OP20240818_XDFD"],["600001","2024082400312","OP20240818_XDFD"],["600001","2024082400313","OP20240818_XDFD"],["600001","2024082400314","OP20240818_XDFD"],["600001","2024082400315","OP20240818_XDFD"],["600001","2024082400316","OP20240818_XDFD"],["600001","2024082400317","OP20240818_XDFD"],["600001","2024082400318","OP20240818_XDFD"],["600001","2024082400319","OP20240818_XDFD"],["600001","2024082400320","OP20240818_XDFD"],["600001","2024082400321","OP20240818_XDFD"],["600001","2024082400322","OP20240818_XDFD"],["600001","2024082400323","OP20240818_XDFD"],["600001","2024082400324","OP20240818_XDFD"],["600001","2024082400325","OP20240818_XDFD"]
]

以clob参数的形式传到oracle存储过程中处理

    public void import(MultipartFile files) {final int[] status = new int[1];Object result = jdbcTemplate.execute(new ConnectionCallback<Object>() {@Overridepublic Object doInConnection(Connection con) throws SQLException, DataAccessException {CallableStatement cs = con.prepareCall("{call TEST_PACKAGE.pro_add_csv_data(?, ?)}");Clob clob = con.createClob(); // 创建一个Clob对象try {String s = convertCsvToJson(files); // csv 转 json字符串clob.setString(1, s); // 把json字符串封装进clob对象中cs.setClob(1, clob);  // 入参cs.registerOutParameter(2, Types.INTEGER); // 出参cs.execute();status[0] = cs.getInt(2); // 取结果} catch (IOException e) {throw new RuntimeException("Import failed.");}return null;}});}

存储过程

PROCEDURE pro_add_csv_data(v_data_list IN CLOB,v_status OUT NUMBER) 
AS v_code VARCHAR2(10);  v_yerial VARCHAR2(20);v_op VARCHAR2(20);v_cur SYS_REFCURSOR;EXC_EXIST EXCEPTION;v_count NUMBER;v_ref VARCHAR2(30) := TO_CHAR(SYSDATE, 'YYYYMMDDHH24MI');
BEGIN    -- 解析成表OPEN v_cur FOR    SELECT jt.*      FROM (    SELECT j.*    FROM JSON_TABLE(    v_data_list , '$[*]' COLUMNS (code VARCHAR2(10) PATH '$[0]',        yerial VARCHAR2(20) PATH '$[1]',        op VARCHAR2(20) PATH '$[2]'        )              ) j    ) jt;  -- 遍历插入LOOP FETCH v_cur INTO v_code, v_yerial, v_op;  EXIT WHEN v_cur%NOTFOUND;INSERT INTO table_oneVALUES( v_code,v_yerial,v_op);END LOOP;COMMIT;CLOSE v_cur;v_status := 0;
EXCEPTION  WHEN EXC_EXIST THEN ROLLBACK;v_status:=2;WHEN OTHERS THENROLLBACK;v_status:=1;
END pro_add_csv_data;

完美

相关文章:

从CSV到数据库(简易)

需求&#xff1a;客户上传CSV文档&#xff0c;要求CSV文档内容查重/插入/更新相关数据。 框架&#xff1a;jdbcTemplate、commons-io、 DB&#xff1a;oracle 相关依赖&#xff1a; 这里本来打算用的2.11.0&#xff0c;无奈正式项目那边用老版本1.3.1&#xff0c;新版本对类型…...

K210视觉识别模块学习笔记3:内存卡写入拍摄图片_LED三色灯的操作_按键操作_定时器的配置使用

今日开始学习K210视觉识别模块: LED三色灯的操作_按键操作_定时器的配置使用_内存卡写入拍摄图片 亚博智能的K210视觉识别模块...... 固件库版本: canmv_yahboom_v2.1.1.bin 本文最终目的是编写一个按键拍照的例程序&#xff1a; 为以后的专用场景的模型训练做准备&#xf…...

如何定义“智慧校园”这个概念

在信息爆炸的时代&#xff0c;教育面临着前所未有的挑战&#xff1a;如何让每个学生在海量知识中找到属于自己的路径&#xff1f;如何让教师的智慧与科技的力量相得益彰&#xff1f;如何让校园成为培养创新思维的摇篮&#xff1f;智慧校园&#xff0c;这一概念的提出&#xff0…...

OpenSSL自签名证书

文章目录 生成1. 生成根证书的私钥&#xff08;root_private_key.pem&#xff09;2. 创建根证书的CSR和自签名证书&#xff08;root_csr.pem&#xff09;3. 生成服务器证书的私钥&#xff08;server_private_key.pem&#xff09;4. 创建服务器证书的CSR&#xff08;server_priv…...

QtCreator调试运行工程报错,无法找到相关库的的解决方案

最新在使用国产化平台做qt应用开发时&#xff0c;总是遇到qtcreator内调试运行 找不到动态库的问题&#xff0c;为什么会出现这种问题呢&#xff1f;明明编译的时候能够正常通过&#xff0c;运行或者调试的时候找不到相关的库呢&#xff1f;先说结论&#xff0c;排除库本身的问…...

【Python系列】Python 元组(Tuple)详解

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

特征融合篇 | YOLOv8 引入动态上采样模块 | 超过了其他上采样器

1. 介绍 本篇介绍了一种将动态上采样模块引入 YOLOv8 目标检测算法的新方法&#xff0c;该方法在 COCO 数据集上获得了 55.7% 的 mAP&#xff0c;超越了其他上采样器。该方法将动态上采样模块引入到 YOLOv8 的特征融合阶段&#xff0c;能够根据输入图像的特征分辨率动态调整上…...

​​​​​​​Beyond Compare 3密钥被撤销的解决办法

首先&#xff0c;BCompare3的链接如下 链接&#xff1a;https://pan.baidu.com/s/1vuSxY0cVQCt0-8CpFzUhvg 提取码&#xff1a;8888 --来自百度网盘超级会员V7的分享 1.问题现象 激活之后在使用过程中有时候会出现密钥被撤销的警告&#xff0c;而且该工具无法使用&#xff…...

知识见闻 - 人和动物的主要区别

人类和动物的主要区别之一确实在于理性&#xff0c;但这只是众多区别中的一个方面。以下是一些更全面的比较&#xff0c;突出人类和动物之间的主要区别&#xff1a; 理性和抽象思维&#xff1a; 人类&#xff1a;人类具有高度发展的理性能力&#xff0c;可以进行抽象思维、逻辑…...

Javaweb基础之工程路径

大家好&#xff0c;这里是教授.F 引入&#xff1a; 工程路径有一个知识点需要注意&#xff1a;就是相对路径。所谓相对路径就是依赖当前位置&#xff1a; 相对路径的定位依赖于当前位置或参考位置。 使用相对路径来解决&#xff0c; 一个非常重要的规则&#xff1a;页面所有的…...

国际荐酒师(香港)协会受邀出席广州意大利国庆晚宴

2024年5月30日&#xff0c;意大利驻广州总领事馆举办的2024年意大利国庆招待会及晚宴&#xff0c;庆祝意大利共和国成立。此次晚宴旨在促进中意两国之间的文化交流与合作。国际荐酒师&#xff08;香港&#xff09;协会受主办方邀请参与了这一重要活动。 国际荐酒师&#xff08;…...

让驰骋BPM系统插上AI的翅膀

让驰骋BPM系统插上AI的翅膀 在当今日益复杂多变的商业环境中&#xff0c;业务流程管理&#xff08;BPM&#xff09;系统的应用愈发广泛&#xff0c;成为企业提高效率、优化流程、降低成本的重要工具。驰骋BPM系统凭借其出色的性能和丰富的功能&#xff0c;赢得了众多企业的青睐…...

排队论 | 基于排队机制实现智能仓储机器人巡逻及避碰

研究背景: 智能仓储机器人在现代物流行业中扮演着重要的角色,能够提高仓库的运作效率和准确性。然而,仓储机器人在巡逻过程中可能会遇到其他机器人或障碍物,这就需要解决排队和避碰问题,以确保安全和高效的运作。 研究路线: 背景调研:了解智能仓储机器人的发展和应用…...

Node.js和npm常用命令

一、Node.js简介 Node.js是一个免费、开源、跨平台的JavaScript运行时环境&#xff0c;允许开发人员创建服务器、web应用程序、命令行工具和脚本。 点击查看node.js中文官网 点击查看node.js英文官网 二、npm简介 npm(Node Package Manager)是Node.js的软件包管理器&#xff0…...

pytest +allure在测试中的应用

一、allure配置&#xff1a; 1、安装allure库 pip install allure-pytest2、代码中导入 import allure3、常用命令&#xff1a; 1)、 pytest --alluredir报告目录 测试脚本.py比如&#xff1a;pytest --alluredir./allure_report &#xff08;未指定执行所有&#xff09; 2&…...

004 CentOS 7.9 mongodb7.0.11安装及配置

https://www.mongodb.com/try/download/shell https://www.mongodb.com/try/download/community 文章目录 /etc/mongod.conf在 /etc/systemd/system/ 目录下创建一个名为 mongod.service 的文件重新加载 systemd 配置&#xff1a;启用服务&#xff1a;现在&#xff0c;可以手动…...

Docker安装Redis(云服务器)

准备&#xff1a; 在云服务器中开启6370端口号 docker run -d --name redis -p 6379:6379 redis 这条命令使用docker运行一个名为"redis"的容器&#xff0c;映射容器的6379端口到主机的6379端口&#xff0c;并且使用redis镜像来运行容器。REDIS是一个开源的内存数据…...

springboot中抽象类无法注入到ioc容器

1、背景 在写代码时&#xff0c;发现service接口有两个实现类&#xff0c;并且两个实现类中没有对类名重命名&#xff0c;属性注入的时候也没有使用byName或Qualifier&#xff0c;正确情况下会发生多实现报错的问题&#xff0c;以前对这个问题进行解析过。 2、调试过程 我想…...

Java关键字大冒险:深入浅出地理解Java的精髓

Java编程语言中的关键字就像是魔法咒语&#xff0c;每一个都有自己独特的作用。在这篇博客中&#xff0c;我们将探讨Java中最常见的关键字&#xff0c;并通过有趣的例子和形象的比喻&#xff0c;让你轻松掌握它们的用法。 1. public: 万能钥匙 public关键字是Java中的“万能钥…...

Android Kotlin 打开相册选择图片(多选)

1. 核心代码 打开系统相册功能&#xff0c;本代码使用两种方式打开本地相册&#xff0c;startActivityForResult 已经废弃&#xff0c;可以使用新的方式。 package com.example.facedetectordemoimport android.content.pm.PackageManager import androidx.appcompat.app.App…...

java学习路径

ProcessOn Mindmap...

[线程与网络] 网络编程与通信原理(四):深入理解传输层UDP与TCP协议

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …...

IEEE编程语言排行榜:深度解析编程语言的四大维度、五大趋势、六大热门与七大挑战

IEEE编程语言排行榜&#xff1a;深度解析编程语言的四大维度、五大趋势、六大热门与七大挑战 在信息技术领域&#xff0c;编程语言排行榜一直是衡量各种编程语言流行度和影响力的重要指标。IEEE&#xff08;电气电子工程师协会&#xff09;作为全球最具影响力的科技专业组织之…...

【C++面试50题】

以下是针对C程序员面试可能遇到的一些问题&#xff0c;涵盖了从基础语法、面向对象、STL、内存管理、模板、异常处理、并发编程等多个方面。 ### 基础概念与语法 1. C与C的主要区别是什么&#xff1f; 2. 什么是构造函数和析构函数&#xff1f;它们何时被调用&#xff1f; 3. 什…...

外汇天眼:ESMA发布针对在投资服务中使用人工智能的公司的指导意见

欧洲证券和市场管理局&#xff08;ESMA&#xff09;&#xff0c;欧盟的金融市场监管机构和监督机构&#xff0c;发布了一份声明&#xff0c;为在向零售客户提供投资服务时使用人工智能技术&#xff08;AI&#xff09;的公司提供初步指导。 尽管人工智能的普及仍处于初期阶段&am…...

【前缀和 记忆化搜索】LeetCode1444. 切披萨的方案数

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 动态规划 记忆化搜索 LeetCode1444. 切披萨的方案数 给你一个 rows x cols 大小的矩形披萨和一个整数 k &#xff0c;矩形包含两种字符&#xff1a; ‘A’ &#xff…...

异常处理1--5.31

try--catch--finally格式&#xff1a; try{ }catch(错误类型){ }finally{ } 执行情况&#xff1a; package javatest5;public class test {public static void main(String[] args) {int num115;int num20;try{System.out.println("商等于&#xff1a;"num1/num…...

AI免费插件 批量条码大师,支持100多种条码类型

没想到在网上看到一款和之前 悟空条码 类似的条码插件&#xff0c;叫批量条码大师&#xff0c;他做的比 悟空条码 功能更强&#xff0c;界面更美观&#xff0c;特分享出来给大家。 本插件采用了BWIPJS条码库&#xff0c;支持110种条码、二维码的生成; 支持批量生成&#xff0c;…...

使用 Django 连接 MySQL 数据库

文章目录 步骤一&#xff1a;安装必要的库和驱动步骤二&#xff1a;配置数据库连接步骤三&#xff1a;执行数据库迁移步骤四&#xff1a;开始使用 MySQL 数据库创建一个模型迁移模型到数据库使用模型进行数据操作创建新记录&#xff1a;查询记录&#xff1a;更新记录&#xff1…...

【谷歌开发者月刊】五月内容汇总,Google I/O 点燃您的创新灵感

五月因 Google I/O 大会的成功举办而备受瞩目&#xff0c;我们在为开发者们带来技术更新的同时&#xff0c;更提供了丰富的学习资源。一起在本期月刊中回顾精彩内容&#xff0c;带着学习热情继续探索技术的更新与发展吧&#xff01; 本月看点 精彩看点多多&#xff0c;请上下滑…...

wpf 实现长时间未操作自动退出登录

思路 在WPF应用程序中实现长时间未操作自动退出&#xff0c;主要思路是先收集用户操作行为&#xff0c;用一个全局变量记录用户最后操作时间&#xff0c;再用一个异步线程去监控用户的最后操作时间和当前时间进行比较如果超过了设定时间认为长时间未操作自动退出登录并显示相关…...

pytorch学习笔记3

标量数据 标量数据通常指的是单个数值&#xff0c;比如一个损失值、准确率、学习率等。这些单个的数值数据可以被记录下来&#xff0c;用于分析模型的训练过程、性能等。在代码中&#xff0c;writer.add_scalar() 的作用就是将这些标量数据添加到日志中&#xff0c;以便后续在可…...

开源监控工具monit安装部署

Monit 简介 Monit是一个轻量级(500KB)跨平台的用来监控Unix/linux系统的开源工具。部署简单&#xff0c;并且不依赖任何第三方程序、插件或者库。 Monit可以监控服务器进程、文件、文件系统、网络状态&#xff08;HTTP/SMTP等协议&#xff09;、远程主机、服务器资源变化等等。…...

Python 时间戳转时间

一、 10 位 时间戳 &#xff0c;秒级 转换为时间 方式一&#xff1a; import timetimeStamp 1717149862 timeArray time.localtime(timeStamp) timeStr time.strftime("%Y-%m-%d %H:%M:%S", timeArray) print(timeStr) 输出: 2024-05-31 18:04:22方式二&#xf…...

【网络层】IP地址基础 与 子网掩码

文章目录 IP地址基础IP地址概念IP地址分类公网地址和私网地址 子网掩码子网掩码作用默认子网掩码网络地址、主机地址、广播地址 IP地址基础 IP地址概念 IP地址&#xff1a;IP Address 在网络中&#xff0c;通信节点都需要有一个IP地址 IP地址以点分十进制表示&#xff0c;有…...

Cholesky分解(A=L * L^T)

Cholesky分解是一种用于解线性方程组和计算矩阵平方根的算法&#xff0c;特别适用于对称正定矩阵。这种方法相比于其他解法&#xff08;如高斯消元法&#xff09;在数值稳定性上通常有更好的表现&#xff0c;并且能够有效地利用矩阵的对称性和正定性。下面简要介绍如何使用Chol…...

2024大模型新应用井喷即将到来,算力问题如何解决?

#大模型新应用 #NLP #智合同 随着人工智能技术的加速演进&#xff0c;AI大模型已成为全球科技竞争的新高地、未来产业的新赛道、经济发展的新引擎。大模型的快速发展&#xff0c;特别是在自然语言处理&#xff08;NLP&#xff09;和计算机视觉&#xff08;CV&#xff09;等…...

SpringBoot 七牛云 OSS 私有模式 获取访问链接

目录 一、问题引出 二、在SpringBoot中获取私有访问路径的操作 一、问题引出 由于七牛云OSS的公有模式存在被盗刷的风险&#xff0c;可能导致服务器额外的费用&#xff0c;于是我选择私有模式进行操作。私有模式的访问路径是一个问题&#xff0c;因为需要对应着token和e这两…...

python-模块-网络编程-多任务

一、模块 1-1 Python 自带模块 Json模块 处理json数据 {"key":"value"} json不是字典 本质是一个有引号的字符串数据 json注意点 {} 中的数据是字符串引号必须是双引号 使用json模块可以实现将json转为字典&#xff0c;使用字典的方法操作数据 。 或者将…...

火狐浏览器网页翻译

火狐浏览器网页翻译 火狐浏览器的翻译功能并不支持中文&#xff0c;无法将中文翻译成其他语言&#xff0c;也不支持将其他语言翻译成中文。如果需要翻译英文网页&#xff0c;可以安装翻译插件来帮助解决这个问题。 安装翻译插件的步骤如下&#xff1a; 打开火狐浏览器&#xff…...

R语言数据分析案例以及要点和难点

该案例将涵盖数据读取、数据清洗、探索性数据分析(EDA)、数据可视化和简单的统计分析等多个方面。本案例将以一家零售商店的销售数据为例,使用R语言进行数据分析。 1. 数据准备 假设我们有一个名为sales_data.csv的CSV文件,其中包含了零售商店的销售数据。该文件包含以下列…...

【STL源码剖析-空间配置器】stack、queue简单实现

举头天外望 无我这般人 目录 stack 的概述 stack 的实现 queue 的概述 queue 的实现 契子✨ 我们之前学过了 vector、list 这些 STL 的&#xff08;容器&#xff09; 而我们今天将要学习空间配置器 -- stack、queue&#xff0c;那什么是空间配置器呢&#xff1f; 简单来讲就是…...

VR导航的实现原理、技术优势和应用场景

VR导航通过虚拟现实技术提供沉浸式环境&#xff0c;结合室内定位技术实现精准导航。目前&#xff0c;VR导航已在多个领域展现出其独特的价值和潜力&#xff0c;预示着智能导航系统的未来发展。 一、实现原理 VR导航技术依托于虚拟现实(VR)和室内定位系统。VR技术利用计算机模…...

淘宝镜像的https证书过期

错误原因&#xff1a; 淘宝镜像过期 早在 2021 年&#xff0c;淘宝就发文称&#xff0c;npm 淘宝镜像已经从 http://registry.npm.taobao.org 切换到了 http://registry.npmmirror.com。旧域名也将于 2022 年 5 月 31 日停止服务&#xff08;直到 HTTPS 证书到期才真正不能用了…...

VSCODE 常用快捷键

快捷按键 注释 CTRL /CTRL KSHIFT ALT A取消注释 CTRL /CTRL KSHIFT ALT A搜索文件 Ctrl P移动到某一行 Ctrl g打开一个新窗口 Ctrl Shift N关闭窗口 Ctrl Shift W新建文件 Ctrl N文件间切换 Ctrl Tab全部文件搜索 Ctrl Shift F全屏 F11 打开文件出现中文乱码 文件右下角…...

医院该如何应对网络安全?

在线医生咨询受到很多人的关注&#xff0c;互联网医疗行业的未来发展空间巨大&#xff0c;但随着医院信息化建设高速发展 医院积累了大量的患者基本信息、化验结果、电子处方、生产数据和运营信息等数据 这些数据涉及公民隐私、医院运作和发展等多因素&#xff0c;医疗行业办…...

【qt】多窗口开发

多窗口开发 一.应用场景二.嵌入的窗口1.设计Widget窗口2.创建窗口3.添加窗口4.总代码 三.独立的窗口1.创建窗口2.显示窗口 四.总结 一.应用场景 多窗口,顾名思义,有多个窗口可以供我们进行操作! 截个小图,你应该就知道了 OK,话不多说,直接开干,先来设计我们的主窗口 需要蔬菜…...

iOS Hittest 机制和实际应用

Hittest 机制原理 hitTest的原理就是&#xff0c;当我们点击的时候&#xff0c;会触发 window的 hittest方法&#xff0c;在该方法中会首先使用point inside方法判断 点击的地方是否在window范围内&#xff0c;如果在的话&#xff0c;就倒序遍历姿子视图&#xff0c;然后将poi…...

C# 工厂模式学习

工厂模式&#xff08;Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它提供了一种创建对象的接口&#xff0c;而不是通过具体类来实例化对象。工厂模式可以将对象的创建过程封装起来&#xff0c;使代码更具有灵活性和可扩展性。 工厂模式有几种常见的实现方式&…...

AI生成微信职业头像

加油&#xff0c;新时代打工人&#xff01; 真别说&#xff0c;还挺好看的 https://chatglm.cn/main/alltoolsdetail...