mirror of
https://github.com/cool-team-official/cool-admin-vue.git
synced 2025-12-12 05:32:48 +00:00
1
This commit is contained in:
parent
50898b291f
commit
9dd647645d
107
packages/vite-plugin/src/eps/flatten.ts
Normal file
107
packages/vite-plugin/src/eps/flatten.ts
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import { firstUpperCase } from "../utils";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析结果的接口定义
|
||||||
|
* @interface ParseResult
|
||||||
|
*/
|
||||||
|
interface ParseResult {
|
||||||
|
/** 解析出的键名 */
|
||||||
|
key: string;
|
||||||
|
/** 解析出的内容 */
|
||||||
|
content: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将模板字符串扁平化处理,转换为 Service 类型定义
|
||||||
|
* @param template - 包含 Service 类型定义的模板字符串
|
||||||
|
* @returns 处理后的 Service 类型定义字符串
|
||||||
|
* @throws {Error} 当模板中找不到 Service 类型定义时抛出错误
|
||||||
|
*/
|
||||||
|
export function flatten(template: string): string {
|
||||||
|
// 查找 Service 类型定义的起始位置
|
||||||
|
const startIndex = template.indexOf("export type Service = {");
|
||||||
|
|
||||||
|
// 保留 Service 类型定义前的内容
|
||||||
|
let header = template.substring(0, startIndex);
|
||||||
|
|
||||||
|
// 获取 Service 类型定义及其内容,去除换行和制表符
|
||||||
|
const serviceContent = template.substring(startIndex).replace(/\n|\t/g, "");
|
||||||
|
|
||||||
|
let interfaces = "";
|
||||||
|
let serviceFields = "";
|
||||||
|
|
||||||
|
// 解析内容并生成接口定义
|
||||||
|
parse(serviceContent).forEach(({ key, content }) => {
|
||||||
|
interfaces += `\nexport interface ${firstUpperCase(key)}Interface {${content}}\n`;
|
||||||
|
serviceFields += `${key}: ${firstUpperCase(key)}Interface;`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return `${header}${interfaces}\nexport type Service = {${serviceFields}}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找匹配的右花括号位置
|
||||||
|
* @param str - 要搜索的字符串
|
||||||
|
* @param startIndex - 开始搜索的位置
|
||||||
|
* @returns 匹配的右花括号位置
|
||||||
|
* @throws {Error} 当找不到匹配的右花括号时抛出错误
|
||||||
|
*/
|
||||||
|
function findClosingBrace(str: string, startIndex: number): number {
|
||||||
|
let braceCount = 1;
|
||||||
|
let currentIndex = startIndex;
|
||||||
|
|
||||||
|
while (currentIndex < str.length && braceCount > 0) {
|
||||||
|
if (str[currentIndex] === "{") braceCount++;
|
||||||
|
if (str[currentIndex] === "}") braceCount--;
|
||||||
|
currentIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (braceCount !== 0) {
|
||||||
|
throw new Error("Unmatched braces in the template");
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentIndex - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析内容中的嵌套结构
|
||||||
|
* @param content - 要解析的内容字符串
|
||||||
|
* @returns 解析结果数组,包含解析出的键值对
|
||||||
|
*/
|
||||||
|
function parse(content: string): ParseResult[] {
|
||||||
|
// 匹配形如 xxx: { ... } 的结构
|
||||||
|
const interfacePattern = /(\w+)\s*:\s*\{/g;
|
||||||
|
const result: ParseResult[] = [];
|
||||||
|
let match: RegExpExecArray | null;
|
||||||
|
|
||||||
|
while ((match = interfacePattern.exec(content)) !== null) {
|
||||||
|
const startIndex = match.index + match[0].length;
|
||||||
|
const endIndex = findClosingBrace(content, startIndex);
|
||||||
|
|
||||||
|
if (endIndex > startIndex) {
|
||||||
|
let parsedContent = content.substring(startIndex, endIndex).trim();
|
||||||
|
|
||||||
|
// 处理嵌套结构
|
||||||
|
if (parsedContent.includes("{") && parsedContent.includes("}")) {
|
||||||
|
const nestedInterfaces = parse(parsedContent);
|
||||||
|
|
||||||
|
// 替换嵌套的内容为接口引用
|
||||||
|
if (nestedInterfaces.length > 0) {
|
||||||
|
nestedInterfaces.forEach((nestedInterface) => {
|
||||||
|
const pattern = `${nestedInterface.key}: {${nestedInterface.content}};`;
|
||||||
|
const replacement = `${nestedInterface.key}: ${firstUpperCase(nestedInterface.key)}Interface`;
|
||||||
|
parsedContent = parsedContent.replace(pattern, replacement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将解析结果添加到数组开头
|
||||||
|
result.unshift({
|
||||||
|
key: match[1],
|
||||||
|
content: parsedContent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@ -6,12 +6,18 @@ import { createWriteStream } from "fs";
|
|||||||
import prettier from "prettier";
|
import prettier from "prettier";
|
||||||
import { config } from "../config";
|
import { config } from "../config";
|
||||||
import type { Eps } from "../../types";
|
import type { Eps } from "../../types";
|
||||||
|
import { flatten } from "./flatten";
|
||||||
|
|
||||||
|
// 全局 service 对象,用于存储服务结构
|
||||||
const service = {};
|
const service = {};
|
||||||
|
// eps 实体列表
|
||||||
let list: Eps.Entity[] = [];
|
let list: Eps.Entity[] = [];
|
||||||
|
|
||||||
// 获取请求地址
|
/**
|
||||||
function getEpsUrl() {
|
* 获取 eps 请求地址
|
||||||
|
* @returns {string} eps url
|
||||||
|
*/
|
||||||
|
function getEpsUrl(): string {
|
||||||
let url = config.eps.api;
|
let url = config.eps.api;
|
||||||
|
|
||||||
if (!url) {
|
if (!url) {
|
||||||
@ -23,7 +29,6 @@ function getEpsUrl() {
|
|||||||
case "uniapp-x":
|
case "uniapp-x":
|
||||||
url = "/app/base/comm/eps";
|
url = "/app/base/comm/eps";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "admin":
|
case "admin":
|
||||||
url = "/admin/base/open/eps";
|
url = "/admin/base/open/eps";
|
||||||
break;
|
break;
|
||||||
@ -32,29 +37,46 @@ function getEpsUrl() {
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取路径
|
/**
|
||||||
function getEpsPath(filename?: string) {
|
* 获取 eps 路径
|
||||||
|
* @param filename 文件名
|
||||||
|
* @returns {string} 完整路径
|
||||||
|
*/
|
||||||
|
function getEpsPath(filename?: string): string {
|
||||||
return join(
|
return join(
|
||||||
config.type == "admin" ? config.eps.dist : rootDir(config.eps.dist),
|
config.type == "admin" ? config.eps.dist : rootDir(config.eps.dist),
|
||||||
filename || "",
|
filename || "",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取方法名
|
/**
|
||||||
function getNames(v: any) {
|
* 获取对象方法名(排除 namespace、permission 字段)
|
||||||
|
* @param v 对象
|
||||||
|
* @returns {string[]} 方法名数组
|
||||||
|
*/
|
||||||
|
function getNames(v: any): string[] {
|
||||||
return Object.keys(v).filter((e) => !["namespace", "permission"].includes(e));
|
return Object.keys(v).filter((e) => !["namespace", "permission"].includes(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 找字段
|
/**
|
||||||
function findColumns(sources: string[], item: Eps.Entity) {
|
* 查找字段
|
||||||
|
* @param sources 字段 source 数组
|
||||||
|
* @param item eps 实体
|
||||||
|
* @returns {Eps.Column[]} 字段数组
|
||||||
|
*/
|
||||||
|
function findColumns(sources: string[], item: Eps.Entity): Eps.Column[] {
|
||||||
const columns = [item.columns, item.pageColumns].flat().filter(Boolean);
|
const columns = [item.columns, item.pageColumns].flat().filter(Boolean);
|
||||||
return (sources || [])
|
return (sources || [])
|
||||||
.map((e) => columns.find((c) => c.source == e))
|
.map((e) => columns.find((c) => c.source == e))
|
||||||
.filter(Boolean) as Eps.Column[];
|
.filter(Boolean) as Eps.Column[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 格式化代码
|
/**
|
||||||
async function formatCode(text: string) {
|
* 使用 prettier 格式化 TypeScript 代码
|
||||||
|
* @param text 代码文本
|
||||||
|
* @returns {Promise<string|null>} 格式化后的代码
|
||||||
|
*/
|
||||||
|
async function formatCode(text: string): Promise<string | null> {
|
||||||
return prettier
|
return prettier
|
||||||
.format(text, {
|
.format(text, {
|
||||||
parser: "typescript",
|
parser: "typescript",
|
||||||
@ -71,27 +93,27 @@ async function formatCode(text: string) {
|
|||||||
error(
|
error(
|
||||||
`[cool-eps] Failed to format /build/cool/eps.d.ts. Please delete the file and try again`,
|
`[cool-eps] Failed to format /build/cool/eps.d.ts. Please delete the file and try again`,
|
||||||
);
|
);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取数据
|
/**
|
||||||
|
* 获取 eps 数据(本地优先,远程兜底)
|
||||||
|
*/
|
||||||
async function getData() {
|
async function getData() {
|
||||||
// 读取本地数据
|
// 读取本地 eps.json
|
||||||
list = readFile(getEpsPath("eps.json"), true) || [];
|
list = readFile(getEpsPath("eps.json"), true) || [];
|
||||||
|
|
||||||
// 请求地址
|
// 拼接请求地址
|
||||||
const url = config.reqUrl + getEpsUrl();
|
const url = config.reqUrl + getEpsUrl();
|
||||||
|
|
||||||
// 请求数据
|
// 请求远程 eps 数据
|
||||||
await axios
|
await axios
|
||||||
.get(url, {
|
.get(url, {
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
const { code, data, message } = res.data;
|
const { code, data, message } = res.data;
|
||||||
|
|
||||||
if (code === 1000) {
|
if (code === 1000) {
|
||||||
if (!isEmpty(data) && data) {
|
if (!isEmpty(data) && data) {
|
||||||
list = values(data).flat();
|
list = values(data).flat();
|
||||||
@ -104,18 +126,11 @@ async function getData() {
|
|||||||
error(`[cool-eps] API service is not running → ${url}`);
|
error(`[cool-eps] API service is not running → ${url}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 初始化处理
|
// 初始化处理,补全缺省字段
|
||||||
list.forEach((e) => {
|
list.forEach((e) => {
|
||||||
if (!e.namespace) {
|
if (!e.namespace) e.namespace = "";
|
||||||
e.namespace = "";
|
if (!e.api) e.api = [];
|
||||||
}
|
if (!e.columns) e.columns = [];
|
||||||
if (!e.api) {
|
|
||||||
e.api = [];
|
|
||||||
}
|
|
||||||
if (!e.columns) {
|
|
||||||
e.columns = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!e.search) {
|
if (!e.search) {
|
||||||
e.search = {
|
e.search = {
|
||||||
fieldEq: findColumns(e.pageQueryOp?.fieldEq, e),
|
fieldEq: findColumns(e.pageQueryOp?.fieldEq, e),
|
||||||
@ -126,19 +141,20 @@ async function getData() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建 json 文件
|
/**
|
||||||
function createJson() {
|
* 创建 eps.json 文件
|
||||||
|
* @returns {boolean} 是否有更新
|
||||||
|
*/
|
||||||
|
function createJson(): boolean {
|
||||||
const arr = list.map((e) => {
|
const arr = list.map((e) => {
|
||||||
return {
|
return {
|
||||||
prefix: e.prefix,
|
prefix: e.prefix,
|
||||||
name: e.name || "",
|
name: e.name || "",
|
||||||
api: e.api.map((e) => {
|
api: e.api.map((apiItem) => ({
|
||||||
return {
|
name: apiItem.name,
|
||||||
name: e.name,
|
method: apiItem.method,
|
||||||
method: e.method,
|
path: apiItem.path,
|
||||||
path: e.path,
|
})),
|
||||||
};
|
|
||||||
}),
|
|
||||||
search: e.search,
|
search: e.search,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -146,7 +162,7 @@ function createJson() {
|
|||||||
const content = JSON.stringify(arr);
|
const content = JSON.stringify(arr);
|
||||||
const local_content = readFile(getEpsPath("eps.json"));
|
const local_content = readFile(getEpsPath("eps.json"));
|
||||||
|
|
||||||
// 是否需要更新
|
// 判断是否需要更新
|
||||||
const isUpdate = content != local_content;
|
const isUpdate = content != local_content;
|
||||||
|
|
||||||
if (isUpdate) {
|
if (isUpdate) {
|
||||||
@ -158,9 +174,14 @@ function createJson() {
|
|||||||
return isUpdate;
|
return isUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建描述文件
|
/**
|
||||||
|
* 创建 eps 类型描述文件(d.ts/ts)
|
||||||
|
* @param param0 list: eps实体列表, service: service对象
|
||||||
|
*/
|
||||||
async function createDescribe({ list, service }: { list: Eps.Entity[]; service: any }) {
|
async function createDescribe({ list, service }: { list: Eps.Entity[]; service: any }) {
|
||||||
// 获取类型
|
/**
|
||||||
|
* 获取字段类型
|
||||||
|
*/
|
||||||
function getType({ propertyName, type }: any) {
|
function getType({ propertyName, type }: any) {
|
||||||
for (const map of config.eps.mapping) {
|
for (const map of config.eps.mapping) {
|
||||||
if (map.custom) {
|
if (map.custom) {
|
||||||
@ -174,20 +195,25 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 格式化方法名
|
/**
|
||||||
|
* 格式化方法名,去除特殊字符
|
||||||
|
*/
|
||||||
function formatName(name: string) {
|
function formatName(name: string) {
|
||||||
return (name || "").replace(/[:,\s,\/,-]/g, "");
|
return (name || "").replace(/[:,\s,\/,-]/g, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查方法名,包含特殊字符则忽略
|
/**
|
||||||
|
* 检查方法名是否合法(不包含特殊字符)
|
||||||
|
*/
|
||||||
function checkName(name: string) {
|
function checkName(name: string) {
|
||||||
return name && !["{", "}", ":"].some((e) => name.includes(e));
|
return name && !["{", "}", ":"].some((e) => name.includes(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建 Entity
|
/**
|
||||||
|
* 创建 Entity 接口定义
|
||||||
|
*/
|
||||||
function createEntity() {
|
function createEntity() {
|
||||||
const ignore: string[] = [];
|
const ignore: string[] = [];
|
||||||
|
|
||||||
let t0 = "";
|
let t0 = "";
|
||||||
|
|
||||||
for (const item of list) {
|
for (const item of list) {
|
||||||
@ -195,18 +221,14 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
|
|
||||||
let t = `interface ${formatName(item.name)} {`;
|
let t = `interface ${formatName(item.name)} {`;
|
||||||
|
|
||||||
// 合并多个列
|
// 合并 columns 和 pageColumns,去重
|
||||||
const columns: Eps.Column[] = [];
|
const columns: Eps.Column[] = [];
|
||||||
|
|
||||||
[item.columns, item.pageColumns]
|
[item.columns, item.pageColumns]
|
||||||
.flat()
|
.flat()
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.forEach((e) => {
|
.forEach((e) => {
|
||||||
const d = columns.find((c) => c.source == e.source);
|
const d = columns.find((c) => c.source == e.source);
|
||||||
|
if (!d) columns.push(e);
|
||||||
if (!d) {
|
|
||||||
columns.push(e);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const col of columns || []) {
|
for (const col of columns || []) {
|
||||||
@ -217,7 +239,7 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
${col.propertyName}?: ${getType({
|
${col.propertyName}?: ${getType({
|
||||||
propertyName: col.propertyName,
|
propertyName: col.propertyName,
|
||||||
type: col.type,
|
type: col.type,
|
||||||
})}
|
})};
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,12 +260,18 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
return t0;
|
return t0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建 Controller
|
/**
|
||||||
|
* 创建 Controller 接口定义
|
||||||
|
*/
|
||||||
async function createController() {
|
async function createController() {
|
||||||
let controller = "";
|
let controller = "";
|
||||||
let chain = "";
|
let chain = "";
|
||||||
|
|
||||||
// 处理数据
|
/**
|
||||||
|
* 递归处理 service 树,生成接口定义
|
||||||
|
* @param d 当前节点
|
||||||
|
* @param k 前缀
|
||||||
|
*/
|
||||||
function deep(d: any, k?: string) {
|
function deep(d: any, k?: string) {
|
||||||
if (!k) k = "";
|
if (!k) k = "";
|
||||||
|
|
||||||
@ -258,6 +286,7 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
const item = list.find((e) => (e.prefix || "") === `/${d[i].namespace}`);
|
const item = list.find((e) => (e.prefix || "") === `/${d[i].namespace}`);
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
|
//
|
||||||
let t = `interface ${name} {`;
|
let t = `interface ${name} {`;
|
||||||
|
|
||||||
// 插入方法
|
// 插入方法
|
||||||
@ -292,7 +321,7 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
const a = `${p.name}${p.required ? "" : "?"}`;
|
const a = `${p.name}${p.required ? "" : "?"}`;
|
||||||
const b = `${p.schema.type || "string"}`;
|
const b = `${p.schema.type || "string"}`;
|
||||||
|
|
||||||
q.push(`${a}: ${b},`);
|
q.push(`${a}: ${b};`);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isEmpty(q)) {
|
if (isEmpty(q)) {
|
||||||
@ -310,29 +339,30 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
|
|
||||||
switch (a.path) {
|
switch (a.path) {
|
||||||
case "/page":
|
case "/page":
|
||||||
|
if (config.type == "uniapp-x") {
|
||||||
|
res = `PageResponse<${en}>`;
|
||||||
|
} else {
|
||||||
res = `
|
res = `
|
||||||
{
|
{
|
||||||
pagination: { size: number; page: number; total: number; [key: string]: any; };
|
pagination: PaginationData;
|
||||||
list: ${en} [];
|
list: ${en} [];
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "/list":
|
case "/list":
|
||||||
res = `${en} []`;
|
res = `${en} []`;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "/info":
|
case "/info":
|
||||||
res = en;
|
res = en;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
res = "any";
|
res = "any";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 描述
|
// 方法描述
|
||||||
t += `
|
t += `
|
||||||
/**
|
/**
|
||||||
* ${a.summary || n}
|
* ${a.summary || n}
|
||||||
@ -346,6 +376,7 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (config.type != "uniapp-x") {
|
||||||
// 权限标识
|
// 权限标识
|
||||||
t += `
|
t += `
|
||||||
/**
|
/**
|
||||||
@ -361,6 +392,7 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
*/
|
*/
|
||||||
_permission: { ${permission.map((e) => `${e}: boolean;`).join("\n")} };
|
_permission: { ${permission.map((e) => `${e}: boolean;`).join("\n")} };
|
||||||
`;
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
t += `
|
t += `
|
||||||
request: Request
|
request: Request
|
||||||
@ -375,17 +407,28 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
} else {
|
} else {
|
||||||
chain += `${formatName(i)}: {`;
|
chain += `${formatName(i)}: {`;
|
||||||
deep(d[i], name);
|
deep(d[i], name);
|
||||||
chain += "},";
|
chain += "};";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 遍历
|
// 遍历 service 树
|
||||||
deep(service);
|
deep(service);
|
||||||
|
|
||||||
return `
|
return `
|
||||||
type json = any;
|
type json = any;
|
||||||
|
|
||||||
|
type PaginationData = {
|
||||||
|
size: number;
|
||||||
|
page: number;
|
||||||
|
total: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PageResponse<T> = {
|
||||||
|
pagination: PaginationData;
|
||||||
|
list: T[];
|
||||||
|
};
|
||||||
|
|
||||||
${controller}
|
${controller}
|
||||||
|
|
||||||
interface RequestOptions {
|
interface RequestOptions {
|
||||||
@ -402,7 +445,9 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
|
|
||||||
type Request = (options: RequestOptions) => Promise<any>;
|
type Request = (options: RequestOptions) => Promise<any>;
|
||||||
|
|
||||||
interface Service {
|
${await createDict()}
|
||||||
|
|
||||||
|
type Service = {
|
||||||
/**
|
/**
|
||||||
* 基础请求
|
* 基础请求
|
||||||
*/
|
*/
|
||||||
@ -410,12 +455,10 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
|
|
||||||
${chain}
|
${chain}
|
||||||
}
|
}
|
||||||
|
|
||||||
${await createDict()}
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 文件内容
|
// 组装文件内容
|
||||||
let text = `
|
let text = `
|
||||||
${createEntity()}
|
${createEntity()}
|
||||||
${await createController()}
|
${await createController()}
|
||||||
@ -426,11 +469,12 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
|
|
||||||
if (config.type == "uniapp-x") {
|
if (config.type == "uniapp-x") {
|
||||||
name = "eps.ts";
|
name = "eps.ts";
|
||||||
|
|
||||||
text = text
|
text = text
|
||||||
.replaceAll("interface ", "export interface ")
|
.replaceAll("interface ", "export interface ")
|
||||||
.replaceAll("type ", "export type ")
|
.replaceAll("type ", "export type ")
|
||||||
.replaceAll("[key: string]: any;", "");
|
.replaceAll("[key: string]: any;", "");
|
||||||
|
|
||||||
|
text = flatten(text);
|
||||||
} else {
|
} else {
|
||||||
text = `
|
text = `
|
||||||
declare namespace Eps {
|
declare namespace Eps {
|
||||||
@ -439,7 +483,7 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 文本内容
|
// 格式化文本内容
|
||||||
const content = await formatCode(text);
|
const content = await formatCode(text);
|
||||||
|
|
||||||
const local_content = readFile(getEpsPath(name));
|
const local_content = readFile(getEpsPath(name));
|
||||||
@ -453,7 +497,9 @@ async function createDescribe({ list, service }: { list: Eps.Entity[]; service:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建 service
|
/**
|
||||||
|
* 构建 service 对象树
|
||||||
|
*/
|
||||||
function createService() {
|
function createService() {
|
||||||
// 路径第一层作为 id 标识
|
// 路径第一层作为 id 标识
|
||||||
const id = getEpsUrl().split("/")[1];
|
const id = getEpsUrl().split("/")[1];
|
||||||
@ -462,10 +508,14 @@ function createService() {
|
|||||||
// 请求地址
|
// 请求地址
|
||||||
const path = e.prefix[0] == "/" ? e.prefix.substring(1, e.prefix.length) : e.prefix;
|
const path = e.prefix[0] == "/" ? e.prefix.substring(1, e.prefix.length) : e.prefix;
|
||||||
|
|
||||||
// 分隔路径
|
// 分隔路径,去除 id,转驼峰
|
||||||
const arr = path.replace(id, "").split("/").filter(Boolean).map(toCamel);
|
const arr = path.replace(id, "").split("/").filter(Boolean).map(toCamel);
|
||||||
|
|
||||||
// 遍历
|
/**
|
||||||
|
* 递归构建 service 树
|
||||||
|
* @param d 当前节点
|
||||||
|
* @param i 当前索引
|
||||||
|
*/
|
||||||
function deep(d: any, i: number) {
|
function deep(d: any, i: number) {
|
||||||
const k = arr[i];
|
const k = arr[i];
|
||||||
|
|
||||||
@ -475,7 +525,6 @@ function createService() {
|
|||||||
if (!d[k]) {
|
if (!d[k]) {
|
||||||
d[k] = {};
|
d[k] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
deep(d[k], i + 1);
|
deep(d[k], i + 1);
|
||||||
} else {
|
} else {
|
||||||
// 不存在则创建
|
// 不存在则创建
|
||||||
@ -504,7 +553,6 @@ function createService() {
|
|||||||
e.api.forEach((a) => {
|
e.api.forEach((a) => {
|
||||||
// 方法名
|
// 方法名
|
||||||
const n = a.path.replace("/", "");
|
const n = a.path.replace("/", "");
|
||||||
|
|
||||||
if (n && !/[-:]/g.test(n)) {
|
if (n && !/[-:]/g.test(n)) {
|
||||||
d[k][n] = a;
|
d[k][n] = a;
|
||||||
}
|
}
|
||||||
@ -517,8 +565,11 @@ function createService() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建 dict
|
/**
|
||||||
async function createDict() {
|
* 获取字典类型定义
|
||||||
|
* @returns {Promise<string>} 字典类型 type 定义
|
||||||
|
*/
|
||||||
|
async function createDict(): Promise<string> {
|
||||||
let p = "";
|
let p = "";
|
||||||
|
|
||||||
switch (config.type) {
|
switch (config.type) {
|
||||||
@ -526,7 +577,6 @@ async function createDict() {
|
|||||||
case "uniapp-x":
|
case "uniapp-x":
|
||||||
p = "/app";
|
p = "/app";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "admin":
|
case "admin":
|
||||||
p = "/admin";
|
p = "/admin";
|
||||||
break;
|
break;
|
||||||
@ -541,11 +591,9 @@ async function createDict() {
|
|||||||
|
|
||||||
if (code === 1000) {
|
if (code === 1000) {
|
||||||
let v = "string";
|
let v = "string";
|
||||||
|
|
||||||
if (!isEmpty(data)) {
|
if (!isEmpty(data)) {
|
||||||
v = data.map((e) => `"${e.key}"`).join(" | ");
|
v = data.map((e) => `"${e.key}"`).join(" | ");
|
||||||
}
|
}
|
||||||
|
|
||||||
return `type DictKey = ${v}`;
|
return `type DictKey = ${v}`;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -556,22 +604,25 @@ async function createDict() {
|
|||||||
return text || "";
|
return text || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建 eps
|
/**
|
||||||
|
* 主入口:创建 eps 相关文件和 service
|
||||||
|
* @returns {Promise<{service: any, list: Eps.Entity[], isUpdate?: boolean}>}
|
||||||
|
*/
|
||||||
export async function createEps() {
|
export async function createEps() {
|
||||||
if (config.eps.enable) {
|
if (config.eps.enable) {
|
||||||
// 获取数据
|
// 获取 eps 数据
|
||||||
await getData();
|
await getData();
|
||||||
|
|
||||||
// 创建 service
|
// 构建 service 对象
|
||||||
createService();
|
createService();
|
||||||
|
|
||||||
// 创建目录
|
// 创建 eps 目录
|
||||||
createDir(getEpsPath(), true);
|
createDir(getEpsPath(), true);
|
||||||
|
|
||||||
// 创建 json 文件
|
// 创建 eps.json 文件
|
||||||
const isUpdate = createJson();
|
const isUpdate = createJson();
|
||||||
|
|
||||||
// 创建描述文件
|
// 创建类型描述文件
|
||||||
createDescribe({ service, list });
|
createDescribe({ service, list });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -2,27 +2,34 @@ import type { Plugin } from "vite";
|
|||||||
import { SAFE_CHAR_MAP } from "./config";
|
import { SAFE_CHAR_MAP } from "./config";
|
||||||
import { createCtx } from "../ctx";
|
import { createCtx } from "../ctx";
|
||||||
import { readFile, rootDir } from "../utils";
|
import { readFile, rootDir } from "../utils";
|
||||||
|
import { createEps } from "../eps";
|
||||||
|
|
||||||
|
export async function codePlugin(): Promise<Plugin[]> {
|
||||||
|
const ctx = await createCtx();
|
||||||
|
const eps = await createEps();
|
||||||
|
const theme = await readFile(rootDir("theme.json"), true);
|
||||||
|
|
||||||
export function codePlugin(): Plugin[] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: "vite-cool-uniappx-code-pre",
|
name: "vite-cool-uniappx-code-pre",
|
||||||
enforce: "pre",
|
enforce: "pre",
|
||||||
async transform(code, id) {
|
async transform(code, id) {
|
||||||
if (id.includes("/cool/ctx.ts")) {
|
if (id.includes("/cool/virtual.ts")) {
|
||||||
const ctx = await createCtx();
|
|
||||||
|
|
||||||
ctx["SAFE_CHAR_MAP"] = [];
|
ctx["SAFE_CHAR_MAP"] = [];
|
||||||
for (const i in SAFE_CHAR_MAP) {
|
for (const i in SAFE_CHAR_MAP) {
|
||||||
ctx["SAFE_CHAR_MAP"].push([i, SAFE_CHAR_MAP[i]]);
|
ctx["SAFE_CHAR_MAP"].push([i, SAFE_CHAR_MAP[i]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const theme = await readFile(rootDir("theme.json"), true);
|
|
||||||
ctx["theme"] = theme;
|
ctx["theme"] = theme;
|
||||||
|
|
||||||
code = code.replace(
|
code = code.replace(
|
||||||
"export const ctx = {}",
|
"const ctx = {}",
|
||||||
`export const ctx = ${JSON.stringify(ctx, null, 4)}`,
|
`const ctx = ${JSON.stringify(ctx, null, 4)}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
code = code.replace(
|
||||||
|
"const eps = {}",
|
||||||
|
`const eps = ${JSON.stringify(eps, null, 4).replaceAll("[]", "[] as any[]")}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -8,11 +8,11 @@ import { codePlugin } from "./code";
|
|||||||
* @param options 配置项
|
* @param options 配置项
|
||||||
* @returns Vite 插件数组
|
* @returns Vite 插件数组
|
||||||
*/
|
*/
|
||||||
export function uniappX() {
|
export async function uniappX() {
|
||||||
const plugins: Plugin[] = [];
|
const plugins: Plugin[] = [];
|
||||||
|
|
||||||
if (config.type == "uniapp-x") {
|
if (config.type == "uniapp-x") {
|
||||||
plugins.push(...codePlugin());
|
plugins.push(...(await codePlugin()));
|
||||||
|
|
||||||
if (config.tailwind.enable) {
|
if (config.tailwind.enable) {
|
||||||
plugins.push(...tailwindPlugin());
|
plugins.push(...tailwindPlugin());
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user