Skip to content

Add plugin SQL工具箱 v1.0.28#161

Open
honvin wants to merge 1 commit into
ZToolsCenter:mainfrom
honvin:plugin/sql-utils
Open

Add plugin SQL工具箱 v1.0.28#161
honvin wants to merge 1 commit into
ZToolsCenter:mainfrom
honvin:plugin/sql-utils

Conversation

@honvin
Copy link
Copy Markdown

@honvin honvin commented May 10, 2026

插件信息

  • 名称: SQL工具箱
  • 插件ID: sql-utils
  • 版本: 1.0.28
  • 描述: 一款集成了多种 SQL 相关的实用工具🧰,帮助开发者提高工作效率🚀。多字段测试数据生成 | Excel转SQL | 文本拼接 | DDL代码生成
  • 作者: honvin
  • 类型: 新增

本次变更

优化

  • Excel转SQL:
    • 支持上传Excel文件解析数据
    • 支持字段配置(将空字符串在SQL中转为NULL)
    • 数据表格支持拖拽排序
  • 生成测试数据:
    • 数据表格添加分页,减少页面卡顿

截图 / 演示

自检清单

  • plugin.json 的 name / title / version / description / author 字段均已检查
  • 已移除调试日志、未使用文件、敏感信息(.env、token、密钥等)
  • 本次 PR 的 diff 仅涉及 plugins/sql-utils/ 目录
  • 已在本地 ZTools 客户端实际加载并测试过此插件,主要功能正常
  • 同意以仓库声明的开源协议发布此插件

此 PR 由 ztools-plugin-cli 自动管理:每次 ztools publish 在分支上追加一个 commit,PR 链接保持不变。

- Initial commit
- 删除文件 .trae
- build: 🛠️ 同时兼容uTools和ZTools的配置
- feat(Excel转SQL、生成测试数据): ✨ 功能优化
- docs: 📝 修改版本号
- docs: 📝 CHANGELOG.md
- feat(Excel转SQL): ✨ 优化表格,支持拖拽排序
- docs:  格式化CHANGELOG.md
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements a comprehensive SQL utility plugin for uTools, including features for text manipulation, data conversion, and code generation. The review identifies several high-priority issues, such as a dangerous global modification of ResizeObserver and context errors in exported utility functions. Critical bugs were found in the SQL export logic regarding quote escaping and in the ID card generation algorithm. Additionally, the feedback suggests performance optimizations for DDL parsing, more robust Vue instance management, and better support for multi-table DDL inputs.

Comment on lines +113 to +119
const _ResizeObserver = window.ResizeObserver;
window.ResizeObserver = class ResizeObserver extends _ResizeObserver{
constructor(callback) {
callback = debounce(callback, 50);
super(callback);
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

修改全局的 window.ResizeObserver 是一个非常危险的操作,尤其是在插件开发中。这会影响宿主应用程序中所有使用 ResizeObserver 的组件,可能导致意想不到的副作用或性能问题。建议移除此全局覆盖,如果需要对特定组件的 resize 事件进行防抖处理,请在组件内部实现。

*/
export function getAvatarUrl() {
const avatarStyle = commonConsts.avatarStyles[Math.floor(Math.random() * commonConsts.avatarStyles.length)];
return `https://api.dicebear.com/9.x/${avatarStyle}/svg?seed=` + this.getStr(this.getNumber(4, 16), true, true, true, false);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

在导出的函数 getAvatarUrl 中直接使用 this.getStrthis.getNumber 会导致运行时错误,因为在 ES 模块中,导出函数的 this 通常是 undefined。由于这些函数在同一个文件中定义,应该直接调用它们。

Suggested change
return `https://api.dicebear.com/9.x/${avatarStyle}/svg?seed=` + this.getStr(this.getNumber(4, 16), true, true, true, false);
return "https://api.dicebear.com/9.x/" + avatarStyle + "/svg?seed=" + getStr(getNumber(4, 16), true, true, true, false);

const columns = currentFields.map(field => field.name).join(', ');
const values = currentFields.map(field => `'${row[field.id]}'`).join(', ');
return `INSERT INTO ${tableName} (${columns})
VALUES (${values});`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

在生成 SQL 插入语句时,未对字段值中的单引号进行转义。如果生成的数据包含单引号(例如姓名中包含 '),会导致生成的 SQL 语句语法错误。建议使用 .replace(/'/g, "''") 进行转义。

        const values = currentFields.map(field => "'" + String(row[field.id]).replace(/'/g, "''") + "'").join(', ');

return 'NULL';
}
if (typeof value === 'string') {
return `'${value}'`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

在将 Excel 数据转换为 SQL 时,未对字符串值中的单引号进行转义。这会导致包含单引号的数据产生非法的 SQL 语句。建议对所有字符串类型的字段值进行转义处理。

            if (typeof value === 'string') {
              return "'" + value.replace(/'/g, "''") + "'";
            }

Comment on lines +83 to +86
let sequenceCode;
do {
sequenceCode = ('00' + Math.floor(Math.random() * 999)).slice(-3);
} while (sequenceCode.startsWith('0'));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

身份证顺序码(第15-17位)的生成逻辑存在偏差:\n1. Math.random() * 999 只能生成 0-998 的随机数,无法生成 999。\n2. startsWith('0') 的过滤逻辑是不正确的,顺序码可以是 000999 之间的任何值。建议直接生成 0-999 的随机数并补齐位数。

Suggested change
let sequenceCode;
do {
sequenceCode = ('00' + Math.floor(Math.random() * 999)).slice(-3);
} while (sequenceCode.startsWith('0'));
const sequenceCode = Math.floor(Math.random() * 1000).toString().padStart(3, '0');

Comment on lines +126 to +148
let typeMapping = DEFAULT_TYPE_MAPPING;
try {
const savedMappings = localStorage.getItem('typeMappings');
if (savedMappings) {
const customMappings = JSON.parse(savedMappings);
// 将自定义映射转换为对象形式
typeMapping = {};
customMappings.forEach(mapping => {
if (mapping.mysqlType && mapping.javaType) {
typeMapping[mapping.mysqlType] = mapping.javaType;
}
});
// 合并默认映射,确保未自定义的类型有默认值
Object.keys(DEFAULT_TYPE_MAPPING).forEach(key => {
if (!typeMapping[key]) {
typeMapping[key] = DEFAULT_TYPE_MAPPING[key];
}
});
}
} catch (e) {
console.error('加载类型映射失败,使用默认映射:', e);
typeMapping = DEFAULT_TYPE_MAPPING;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

getJavaType 函数在处理每个列时都会调用 localStorage.getItem 并执行 JSON.parse。当 DDL 包含大量字段时,这会产生显著的性能开销。建议在 convertJson 函数开始处读取一次配置并缓存,或者在模块级别进行缓存。

return null;
}

// 从原始数据中取出第一个对象,这里假设原始数据数组中只有一个对象
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

当前解析逻辑仅处理 DDL 中的第一个表。如果用户输入了包含多个 CREATE TABLE 语句的 DDL,后续的表将被忽略。建议支持多表解析或在界面上提示用户仅支持单表。

// 拷贝为SQL
copyAsSQL() {
const sqlStatements = this.generatedData.map(row => {
const tableName = 'tableName';
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

SQL 导出时的表名被硬编码为 'tableName'。建议允许用户自定义表名,或者根据字段配置推导出一个更合适的默认值。

// 如果无法获取全局Vue实例,尝试通过document获取当前活跃的Vue实例
const app = document.querySelector('#app');
if (app && app.__vue__) {
return app.__vue__;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

通过 app.__vue__ 获取 Vue 实例是依赖于 Vue 内部实现的行为,不够健壮且在生产环境或不同版本的 Vue 中可能会失效。建议通过更标准的方式(如在插件初始化时保存根实例引用)来访问 $notify

@honvin honvin marked this pull request as ready for review May 10, 2026 16:30
@honvin
Copy link
Copy Markdown
Author

honvin commented May 11, 2026

excel转sql 代码生成1 代码生成2 代码生成3 代码生成4 代码生成5 生成测试数据1 生成测试数据2 文本拼接

@LAOBILAXI233
Copy link
Copy Markdown

你好👋 开发者 请问你是如何 改变 ztools 宿主窗口宽度 的 在我尝试更改 弹出窗口的宽度 发现无法修改窗口宽度

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants