This commit is contained in:
神仙都没用 2024-06-26 18:13:00 +08:00
parent 37c5b1c0fb
commit 4f366ef636
7 changed files with 2986 additions and 1322 deletions

2982
build/cool/eps.d.ts vendored

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,8 @@ import { getRules } from "./utils";
export default (): ModuleConfig => { export default (): ModuleConfig => {
return { return {
options: { options: {
host: "https://service.cool-js.com" host: "/dev"
// host: "https://service.cool-js.com"
}, },
toolbar: { toolbar: {
order: 1, order: 1,

View File

@ -1,109 +1,105 @@
import { ElNotification } from "element-plus";
import { io, Socket } from "socket.io-client";
import { module, useCool } from "/@/cool";
import { request } from "../utils"; import { request } from "../utils";
import type { EpsColumn } from "../types"; import type { EpsColumn } from "../types";
import { module } from "/@/cool";
import { useBase } from "/$/base";
export function useAi() { export function useAi() {
const { route, router } = useCool();
const { host } = module.config("helper"); const { host } = module.config("helper");
const { user } = useBase();
let socket: Socket | null; // 调用流程
async function invokeFlow(
label: string,
params: any,
streamCb?: ({ isEnd, content }: { isEnd: boolean; content: string }) => void
): Promise<any> {
const stream = !!streamCb;
// 连接 let cacheText = "";
function connect(cb: { onMessage?(content: string): void; onComplete?(): void }) {
if (!socket) {
socket = io(`${host}/code`, {
transports: ["websocket"]
});
if (socket) { return new Promise((resolve, reject) => {
// 连接 fetch(host + "/open/code/gen/data", {
socket.on("connect", () => { method: "POST",
console.log("connect"); headers: {
Authorization: user.token,
"Content-Type": "application/json"
},
body: JSON.stringify({
params,
label,
stream
})
})
.then((res) => {
if (res.body) {
if (stream) {
const reader = res.body.getReader();
const decoder = new TextDecoder("utf-8");
const stream = new ReadableStream({
start(controller) {
function push() {
reader.read().then(({ done, value }) => {
if (done) {
controller.close();
return;
}
let content = ""; let text = decoder.decode(value, { stream: true });
let code = "";
let isEnd = false;
let timer: any;
// 消息 if (streamCb) {
socket?.on("data", (msg: { isEnd: boolean; content: string }) => { if (cacheText) {
isEnd = msg.isEnd; text = cacheText + text;
}
if (msg.isEnd) { if (text.indexOf("data:") == 0) {
if (route.path != "/helper/ai-code") { text = "\n\n" + text;
const notify = ElNotification({ }
title: "提示",
message: "Ai自动生成代码完成点击查看", try {
duration: 0, const arr = text
onClick() { .split(/\n\ndata:/g)
router.push("/helper/ai-code"); .filter(Boolean)
notify.close(); .map((e) => JSON.parse(e));
arr.forEach(streamCb);
cacheText = "";
} catch (err) {
cacheText = text;
}
}
controller.enqueue(text);
push();
});
} }
}); push();
} }
});
return new Response(stream);
} else { } else {
try { return res.json();
// 首行去掉 \n
if (msg.content.includes("\n") && !content) {
msg.content = msg.content.replace(/\n/, "");
}
// 去掉描述
msg.content = msg.content
.replace(/```/g, "")
.replace(/typescript/g, "");
// 拼接内容
content += msg.content || "";
} catch (err) {
console.error(err);
}
} }
}
})
.then((res) => {
if (stream) {
return res;
}
if (!timer) { if (res.code == 1000) {
// 逐字输出 resolve(res.data.result);
timer = setInterval(() => { } else {
const v = content[code.length] || ""; reject(res);
}
if (!v && isEnd) { })
content = ""; .catch(reject);
code = ""; });
isEnd = false;
// 清除事件
clearInterval(timer);
timer = null;
// 完成事件
cb.onComplete?.();
} else {
code += v;
// 消息事件
cb?.onMessage?.(code);
}
}, 10);
}
});
});
// 断开
socket.on("disconnect", (err) => {
console.error(err);
});
}
}
}
// 发送
function send(data: { name: string; columns: string[]; module: string }) {
socket?.emit("instruct", data);
} }
// 匹配组件类型 // 匹配组件类型
function matchType({ columns, name }: { columns: EpsColumn[]; name: string }) { async function matchType({ columns, name }: { columns: EpsColumn[]; name: string }) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const fields = columns.filter((e) => { const fields = columns.filter((e) => {
return !["id", "crateTime", "updateTime"].includes(e.propertyName); return !["id", "crateTime", "updateTime"].includes(e.propertyName);
@ -137,8 +133,7 @@ export function useAi() {
} }
return { return {
connect, matchType,
send, invokeFlow
matchType
}; };
} }

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1719377496622" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6926" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M213.333 128h85.334v85.333h-85.334v213.334A85.333 85.333 0 0 1 128 512a85.333 85.333 0 0 1 85.333 85.333v213.334h85.334V896h-85.334C167.68 884.48 128 857.6 128 810.667V640a85.333 85.333 0 0 0-85.333-85.333H0v-85.334h42.667A85.333 85.333 0 0 0 128 384V213.333A85.333 85.333 0 0 1 213.333 128m597.334 0A85.333 85.333 0 0 1 896 213.333V384a85.333 85.333 0 0 0 85.333 85.333H1024v85.334h-42.667A85.333 85.333 0 0 0 896 640v170.667A85.333 85.333 0 0 1 810.667 896h-85.334v-85.333h85.334V597.333A85.333 85.333 0 0 1 896 512a85.333 85.333 0 0 1-85.333-85.333V213.333h-85.334V128h85.334M512 640a42.667 42.667 0 0 1 42.667 42.667A42.667 42.667 0 0 1 512 725.333a42.667 42.667 0 0 1-42.667-42.666A42.667 42.667 0 0 1 512 640m-170.667 0A42.667 42.667 0 0 1 384 682.667a42.667 42.667 0 0 1-42.667 42.666 42.667 42.667 0 0 1-42.666-42.666A42.667 42.667 0 0 1 341.333 640m341.334 0a42.667 42.667 0 0 1 42.666 42.667 42.667 42.667 0 0 1-42.666 42.666A42.667 42.667 0 0 1 640 682.667 42.667 42.667 0 0 1 682.667 640z" p-id="6927"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1718961548891" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2699" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M330.6 311.2c-16.7-16.7-43.7-16.7-60.3 0L67.6 513.8l202.9 199.3c8.3 8.1 19.1 12.2 29.9 12.2 11 0 22.1-4.2 30.4-12.8 16.5-16.8 16.3-43.8-0.5-60.4l-141.5-139 141.8-141.8c16.7-16.5 16.7-43.5 0-60.1zM757.5 311.4c-16.5-16.8-43.5-17.1-60.3-0.5-16.8 16.5-17 43.5-0.5 60.3l139.5 142-139.3 139.3c-16.7 16.7-16.7 43.7 0 60.3 8.3 8.3 19.2 12.5 30.2 12.5s21.8-4.2 30.2-12.5l199.1-199-198.9-202.4zM564.8 256.8c-23.1-4.5-45.6 10.4-50.2 33.5L429.3 717c-4.6 23.1 10.4 45.6 33.5 50.2 2.8 0.6 5.6 0.8 8.4 0.8 19.9 0 37.8-14 41.8-34.3L598.3 307c4.6-23.1-10.4-45.6-33.5-50.2z" p-id="2700"></path></svg>

Before

Width:  |  Height:  |  Size: 915 B

View File

@ -10,7 +10,7 @@ export async function request(options: any): Promise<any> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
axios({ axios({
...options, ...options,
url: host + "/api" + options.url url: host + options.url
}) })
.then((res) => { .then((res) => {
const { code, data, message } = res.data; const { code, data, message } = res.data;

File diff suppressed because it is too large Load Diff