实际场景:后端对某个字段的下拉选项定义如下
甲方承担费用,1-电费,2-水费,3-煤气费,4-电视费,5-电话费,6-上网费,7-车位费,8-供暖费,9-物业费,10-其它
前端为了给下拉框做选项定义、纯文本展示,要写如下的代码:
export const costOfPartyBOptions = [
{ value: '1', label: '电费' },
{ value: '2', label: '水费' },
{ value: '3', label: '煤气费' },
{ value: '4', label: '电视费' },
{ value: '5', label: '电话费' },
{ value: '6', label: '上网费' },
{ value: '7', label: '车位费' },
{ value: '8', label: '供暖费' },
{ value: '9', label: '物业费' },
{ value: '10', label: '其它' },
];
export const costOfPartyBMap = costOfPartyBOptions.reduce(
(obj, { label, value }) => {
obj[value] = label;
return obj;
},
{},
);
本人一直坚持重复的工作工具化,这种重复无聊的代码写过几遍之后都会弄成代码片段或工具。
直接展示:
生成的代码:
export const 请手动修改名称Options = [
{ value: '1', label: '电费' },
{ value: '2', label: '水费' },
{ value: '3', label: '煤气费' },
{ value: '4', label: '电视费' },
{ value: '5', label: '电话费' },
{ value: '6', label: '上网费' },
{ value: '7', label: '车位费' },
{ value: '8', label: '供暖费' },
{ value: '9', label: '物业费' },
{ value: '10', label: '其它' },
];
export const 请手动修改名称Map = 请手动修改名称Options.reduce(
(obj, { label, value }) => {
obj[value] = label;
return obj;
},
{},
);
还需要手动修改变量名,换个可视化的界面,支持输入变量名:
生成代码:
export const costOptions = [
{ value: '1', label: '电费' },
{ value: '2', label: '水费' },
{ value: '3', label: '煤气费' },
{ value: '4', label: '电视费' },
{ value: '5', label: '电话费' },
{ value: '6', label: '上网费' },
{ value: '7', label: '车位费' },
{ value: '8', label: '供暖费' },
{ value: '9', label: '物业费' },
{ value: '10', label: '其它' },
];
export const costMap = costOptions.reduce((obj, { label, value }) => {
obj[value] = label;
return obj;
}, {});
实现上面的功能,用到了 uTools 软件以及 uTools 官方 “自动化脚本” 插件。
自动化脚本插件里面可以下载别人分享的脚本,也可以上传分享自己写的脚本
脚本里面的内容就是 nodejs 代码
我常用代码片段以及 ChatGPT Prompt 就是放在 “我的脚本” 里
可以看到并不是所有的代码都放到脚本内容里,而是通过 require 一个 js 文件,执行指定的方法来实现具体功能的。这样做有以下几个原因:
第一个原因是 “自动化脚本这个插件” 会检查具体的脚本内容,很多 API 不允许调用,而 require 一个文件可以绕过这个限制。
第二个原因是作为一个专业的切图仔,必须要用工程化的方式来管理这些代码片段,而且脚本内容里只能写 nodejs , 写了好几年 TypeScript,如果不用 TS 写,本人表示写不了一点。
管理代码片段的项目结构如下:
每个脚本的目录结构大致如下:
index.ts 是入口文件,内容都是固定的:
import { bootstrap } from './src/main';
const res = bootstrap();
// @ts-ignore
return res;
编译之后目录结构如下:
入口文件会有变化:
"use strict";
const mainFilePath = "H:/Github/lowcode-scaffolds/lowcode-materials/dist/uTools/Ask ChatGPT-生成 value-label 格式 JSON/script/src/main";
const main_1 = require(mainFilePath);
const res = (0, main_1.bootstrap)(mainFilePath);
return res;
把这段代码粘贴到 “自动化脚本” 插件的脚本内容里就行了,之后更新代码,重新编译一次就行了,不需要修改入口代码。
下面是上述用到的代码片段脚本的核心代码:
import path from 'path';
import fs from 'fs';
import { clipboard } from 'electron';
import { validate } from '@share/TypeChatSlim/utools';
import { compile as compileEjs } from '@share/utils/ejs';
import {
askChatGPT as askOpenai,
getBlockConfigPath,
getBlockJsonValidSchema,
} from '@share/utils/uTools';
export const bootstrap = async (scriptFile?: string) => {
const configPath = getBlockConfigPath(scriptFile!);
const schema = getBlockJsonValidSchema(scriptFile!);
const clipboardText =
(clipboard.readText() || '').trim() ||
'客户验收状态:1.无需验收、2.待验收、3已验收';
const typeName = 'IOption';
const requestPrompt =
`You are a service that translates user requests into JSON objects of type "${typeName}" according to the following TypeScript definitions:\n` +
`\`\`\`\n${schema}\`\`\`\n` +
`The following is a user request:\n` +
`"""\n${clipboardText}\n"""\n` +
`The following is the user request translated into a JSON object with 2 spaces of indentation and no properties with the value undefined:\n`;
const content = await askOpenai({
messages: [{ role: 'user', content: requestPrompt }],
handleChunk: () => {},
});
const valid = validate(content.content, schema, typeName);
if (valid.success) {
const template = fs.readFileSync(
path.join(configPath, 'template.ejs'),
'utf8',
);
const code = compileEjs(template, {
rawSelectedText: '请手动修改名称',
content: JSON.stringify(valid.data),
} as any);
utools.outPlugin();
utools.hideMainWindowPasteText(code);
} else {
return valid.message;
}
};
先水到这,后面再说说可视化界面的内容。