1
This commit is contained in:
426
api/service/autoFile.js
Normal file
426
api/service/autoFile.js
Normal file
@@ -0,0 +1,426 @@
|
||||
var ejs = require("ejs");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const db = require("../../middleware/db");
|
||||
const funTool = require("../../tool/funTool");
|
||||
const logsUtil = require("../../tool/logs");
|
||||
const Sequelize = require("sequelize");
|
||||
const { sys_project, sys_model, sys_model_field, sys_form, sys_form_field, op, querySql } = require("../../middleware/baseModel");
|
||||
|
||||
module.exports = {
|
||||
configTemplate(curPath) {
|
||||
let tempPath = path.join(__dirname, `../../config/template/${curPath}`);
|
||||
return tempPath;
|
||||
},
|
||||
|
||||
mapMySQLTypeToSequelize(mysqlType) {
|
||||
const typeMapping = {
|
||||
'INT': "INTEGER",
|
||||
'VARCHAR': "STRING",
|
||||
'TEXT': "TEXT",
|
||||
'DATE': "DATE",
|
||||
'DATETIME': "DATE",
|
||||
'TIMESTAMP': "DATE",
|
||||
'BOOLEAN': "BOOLEAN",
|
||||
'FLOAT': "FLOAT",
|
||||
'DOUBLE': "DOUBLE",
|
||||
'DECIMAL': "DECIMAL",
|
||||
'BLOB': "BLOB",
|
||||
'JSON': "JSON",
|
||||
};
|
||||
|
||||
const baseType = mysqlType.replace(/\(.*?\)/, '').toUpperCase();
|
||||
|
||||
return typeMapping[baseType] || "STRING";
|
||||
},
|
||||
async outBuildPath(curPath, projectId) {
|
||||
let PROJECT_PATH = ``;
|
||||
if (projectId) {
|
||||
let projectRow = await sys_project.findOne({ where: { id: projectId } });
|
||||
if (projectRow) {
|
||||
let { key } = projectRow;
|
||||
PROJECT_PATH = `${key}/`;
|
||||
}
|
||||
}
|
||||
|
||||
let tempPath = path.join(__dirname, `../../build/${PROJECT_PATH}${curPath}`);
|
||||
|
||||
let directoryPath = path.dirname(tempPath);
|
||||
if (!fs.existsSync(directoryPath)) {
|
||||
// 如果目录不存在,创建目录
|
||||
fs.mkdirSync(directoryPath, { recursive: true });
|
||||
console.log("目录已创建");
|
||||
}
|
||||
return tempPath;
|
||||
},
|
||||
|
||||
getBuildUrl(curPath) {
|
||||
let dirPath = path.join(__dirname, "../../");
|
||||
let newFilePath = curPath.replace(dirPath, "");
|
||||
newFilePath = newFilePath.replace("build", "");
|
||||
return newFilePath;
|
||||
},
|
||||
|
||||
async querySql(sql, project_id) {
|
||||
let dbPath = await this.outBuildPath(`api/db.js`, project_id);
|
||||
let db = require(dbPath);
|
||||
return await db.sequelize.query(sql, { type: Sequelize.QueryTypes.RAW });
|
||||
},
|
||||
|
||||
async ddlSql(sql, project_id) {
|
||||
let dbPath = await this.outBuildPath(`api/db.js`, project_id);
|
||||
let db = require(dbPath);
|
||||
return await db.sequelize.query(sql, { type: Sequelize.QueryTypes.RAW });
|
||||
},
|
||||
|
||||
async autoConfig(project_id) {
|
||||
let projectRow = await sys_project.findOne({ where: { id: project_id } });
|
||||
|
||||
if (projectRow) {
|
||||
let { key: project_key } = projectRow
|
||||
let projectConfig = await sys_project_config.findOne({ where: { project_id: project_id } });
|
||||
|
||||
let tempPath = this.configTemplate(`config.ejs`);
|
||||
let dbTxt = await fs.readFileSync(tempPath, "utf-8");
|
||||
let htmlDbConnect = ejs.render(dbTxt, { project_key, config: projectConfig }, { rmWhitespace: true });
|
||||
let dbTempBuildPath = await this.outBuildPath(`config/config.json`, project_id);
|
||||
await fs.writeFileSync(dbTempBuildPath, htmlDbConnect);
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
async autoDbConfig(project_id) {
|
||||
let projectRow = await sys_project.findOne({ where: { id: project_id } });
|
||||
if (projectRow) {
|
||||
let projectConfigRow = await sys_project_config.findOne({ where: { project_id } });
|
||||
if (projectConfigRow) {
|
||||
let dbConfig = projectConfigRow.db;
|
||||
|
||||
let tempPath = this.configTemplate(`db.ejs`);
|
||||
let dbTxt = await fs.readFileSync(tempPath, "utf-8");
|
||||
let htmlDbConnect = ejs.render(dbTxt, { dbConfig }, { rmWhitespace: true });
|
||||
let dbTempBuildPath = await this.outBuildPath(`api/db.js`, project_id);
|
||||
|
||||
if (await funTool.isExist(dbTempBuildPath)) {
|
||||
fs.unlinkSync(dbTempBuildPath);
|
||||
}
|
||||
|
||||
await fs.writeFileSync(dbTempBuildPath, htmlDbConnect);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async autoInitDb(project_id) {
|
||||
|
||||
let dbDdlPath = this.configTemplate(`dbInit/ddl.db`);
|
||||
let ddlSql = await fs.readFileSync(dbDdlPath, "utf-8");
|
||||
let ddlRows = ddlSql.split(';')
|
||||
|
||||
// 创建ddl表
|
||||
if (ddlRows && ddlRows.length > 0) {
|
||||
for (let i = 0; i < ddlRows.length; i++) {
|
||||
try {
|
||||
let sql = ddlRows[i].trim()
|
||||
|
||||
await this.ddlSql(sql, project_id)
|
||||
}
|
||||
catch (e) {
|
||||
logsUtil.errError(e.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let dbInsertPath = this.configTemplate(`dbInit/insert.db`);
|
||||
let insertSql = await fs.readFileSync(dbInsertPath, "utf-8");
|
||||
let insertRows = insertSql.split(';')
|
||||
|
||||
// 初始化表 数据
|
||||
if (insertRows && insertRows.length > 0) {
|
||||
for (let i = 0; i < insertRows.length; i++) {
|
||||
try {
|
||||
let sql = insertRows[i].trim()
|
||||
let projectRow = await sys_project.findOne({ where: { id: project_id } });
|
||||
if (projectRow) {
|
||||
sql = sql.replace("${demo系统管理}", projectRow.name)
|
||||
}
|
||||
|
||||
await this.ddlSql(sql, project_id)
|
||||
}
|
||||
catch (e) {
|
||||
logsUtil.errError(e.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
async autoModel(id, uuid) {
|
||||
let modelRow = await sys_model.findOne({ where: { id: id } });
|
||||
if (modelRow) {
|
||||
let tempPath = this.configTemplate(`model.ejs`);
|
||||
let modelTxt = await fs.readFileSync(tempPath, "utf-8");
|
||||
let columnsRows = await sys_model_field.findAll({
|
||||
where: {
|
||||
model_id: id,
|
||||
key: {
|
||||
[op.notIn]: ["id", "create_time", "last_modify_time"]
|
||||
}
|
||||
}, order: [["sort", "asc"]]
|
||||
});
|
||||
if (columnsRows) {
|
||||
let html = ejs.render(modelTxt, { columns: columnsRows, table_name: modelRow.key, isProjectDb: false }, { rmWhitespace: true });
|
||||
let modelBuildPath = await this.outBuildPath(`api/model/${modelRow.key}.js`, modelRow.project_id);
|
||||
await fs.writeFileSync(modelBuildPath, html);
|
||||
|
||||
let htmlDb = ejs.render(modelTxt, { columns: columnsRows, table_name: modelRow.key, isProjectDb: true }, { rmWhitespace: true });
|
||||
let modelTempBuildPath = await this.outBuildPath(`api/model/${modelRow.key}_${uuid}.js`, modelRow.project_id);
|
||||
await fs.writeFileSync(modelTempBuildPath, htmlDb);
|
||||
}
|
||||
}
|
||||
},
|
||||
async autoDb(id, uuid) {
|
||||
let modelRow = await sys_model.findOne({ where: { id: id } });
|
||||
if (modelRow) {
|
||||
let { project_id, key } = modelRow;
|
||||
let modelPath = await this.outBuildPath(`api/model/${key}_${uuid}.js`, project_id);
|
||||
try {
|
||||
// 延时调用 重新生成数据库
|
||||
let modelDb = require(modelPath);
|
||||
await modelDb.sync({ force: true });
|
||||
fs.unlinkSync(modelPath); // 重新删除文件
|
||||
} catch (e) {
|
||||
console.error(e.message);
|
||||
fs.unlinkSync(modelPath); // 重新删除文件
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async autoController(id) {
|
||||
let modelRow = await sys_model.findOne({ where: { id: id } });
|
||||
if (modelRow) {
|
||||
let { key: table_name } = modelRow.toJSON();
|
||||
let controllerPath = this.configTemplate("controller.ejs");
|
||||
let controllerTxt = await fs.readFileSync(controllerPath, "utf-8", { rmWhitespace: true });
|
||||
let html = ejs.render(controllerTxt, { table_name });
|
||||
|
||||
let controllerAdminPath = await this.outBuildPath(`api/controller_admin/${table_name}.js`, modelRow.project_id);
|
||||
await fs.writeFileSync(controllerAdminPath, html);
|
||||
}
|
||||
},
|
||||
|
||||
async getFrontTemplatePath(form_id) {
|
||||
let fileName = "";
|
||||
let model_id = "";
|
||||
let modelName = "custom_template";
|
||||
|
||||
let sysFormRow = await sys_form.findOne({ where: { id: form_id } });
|
||||
if (sysFormRow) {
|
||||
fileName = path.basename(sysFormRow.component).replace(".vue", "");
|
||||
model_id = sysFormRow.model_id;
|
||||
let modelRow = await sys_model.findOne({ where: { id: model_id } });
|
||||
if (modelRow) {
|
||||
modelName = modelRow.key;
|
||||
}
|
||||
}
|
||||
|
||||
return { modelName, fileName, model_id };
|
||||
},
|
||||
|
||||
async createForm(row) {
|
||||
if (row) {
|
||||
let { model_id, component, api_path } = row;
|
||||
let formRow = await sys_form.findOne({ where: { model_id, component, api_path } });
|
||||
|
||||
if (formRow) {
|
||||
await sys_form_field.destroy({ where: { form_id: formRow.id } }); // 删除所有字段
|
||||
} else {
|
||||
let modelRow = await sys_model.findOne({ where: { id: model_id } });
|
||||
let { name, project_id } = modelRow;
|
||||
formRow = await sys_form.create({ name, project_id, model_id, component, api_path });
|
||||
}
|
||||
|
||||
// 创建表单
|
||||
if (formRow) {
|
||||
let form_id = formRow.id;
|
||||
let fieldRows = await sys_model_field.findAll({ where: { model_id: model_id }, order: [["sort", "asc"]] });
|
||||
if (fieldRows && fieldRows.length > 0) {
|
||||
for (let i = 0; i < fieldRows.length; i++) {
|
||||
let { id: model_field_id, name: model_field_name, control, data_type } = fieldRows[i];
|
||||
let is_show_list = data_type === "TEXT" ? 0 : 1;
|
||||
|
||||
await sys_form_field.create({ form_id, model_field_id, model_field_name, control, is_show_edit: 1, is_edit_disable: 0, is_show_list, is_show_seach: 1, sort: i });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 生成前端文件Api
|
||||
async autoFrontApi(row) {
|
||||
if (row) {
|
||||
let { id: form_id, api_path, project_id } = row;
|
||||
let api_path_index = api_path.lastIndexOf("/");
|
||||
let folderPath = await this.outBuildPath(`admin/src/api/${api_path.substr(0, api_path_index)}`, project_id);
|
||||
let filePath = api_path.substr(api_path_index, api_path.length - 1);
|
||||
|
||||
let apihtml = "";
|
||||
let { modelName, fileName } = await this.getFrontTemplatePath(form_id);
|
||||
if (fileName) {
|
||||
let apiServerPath = this.configTemplate("vue_file/apiServer.ejs");
|
||||
let controllerTxt = await fs.readFileSync(apiServerPath, "utf-8");
|
||||
apihtml = ejs.render(controllerTxt, { modelName, fileName });
|
||||
}
|
||||
|
||||
//创建文件夹
|
||||
await funTool.mkdirsSync(folderPath);
|
||||
|
||||
let newFilePath = `${folderPath}/${filePath}`;
|
||||
|
||||
// 创建api文件
|
||||
await fs.writeFileSync(newFilePath, apihtml);
|
||||
|
||||
let buildUrl = this.getBuildUrl(newFilePath);
|
||||
|
||||
return buildUrl;
|
||||
}
|
||||
},
|
||||
|
||||
// 创建page 下Vue文件
|
||||
async autoFrontVue(row) {
|
||||
if (row) {
|
||||
let { id: form_id, component, api_path } = row;
|
||||
let component_index = component.lastIndexOf("/");
|
||||
let folderRoot = `${component.substr(0, component_index)}`;
|
||||
|
||||
let { fileName, model_id } = await this.getFrontTemplatePath(form_id);
|
||||
if (fileName) {
|
||||
let sysFormRow = await sys_form.findOne({ where: { id: form_id } });
|
||||
if (sysFormRow && sysFormRow.id) {
|
||||
let sysFormFields = await sys_form_field.findAll({
|
||||
where: { form_id: sysFormRow.id },
|
||||
include: [
|
||||
{
|
||||
association: sys_form_field.associations.field,
|
||||
attributes: ["key", "name", "data_type", "default_value"],
|
||||
},
|
||||
],
|
||||
order: [["sort", "asc"]],
|
||||
});
|
||||
let newcolumnsRows = sysFormFields.map((p) => {
|
||||
let newRow = p.toJSON();
|
||||
|
||||
// 设置默认值
|
||||
if (newRow.field && newRow.field.default_value) {
|
||||
newRow.default_value = newRow.field.default_value;
|
||||
} else {
|
||||
newRow.default_value = "";
|
||||
}
|
||||
|
||||
newRow.name = newRow.model_field_name;
|
||||
|
||||
if (newRow.field && newRow.field.key) {
|
||||
newRow.key = newRow.field.key;
|
||||
newRow.data_type = newRow.field.data_type;
|
||||
}
|
||||
|
||||
if (typeof newRow.control === "string") {
|
||||
newRow.control = JSON.parse(newRow.control);
|
||||
}
|
||||
|
||||
if (newRow.control.interfaceType === "本地数据") {
|
||||
newRow.source = newRow.control.localData || [];
|
||||
} else {
|
||||
newRow.source = [];
|
||||
}
|
||||
return newRow;
|
||||
});
|
||||
|
||||
let pagePath = this.configTemplate(`vue_file/page.ejs`);
|
||||
let controllerTxt = await fs.readFileSync(pagePath, "utf-8");
|
||||
|
||||
let pageHtml = ejs.render(controllerTxt, { api_path, fileName, columns: newcolumnsRows, model_id }, { rmWhitespace: true });
|
||||
|
||||
let folderPath = await this.outBuildPath(`admin/src/view/${folderRoot}`, sysFormRow.project_id);
|
||||
|
||||
//创建文件夹
|
||||
await funTool.mkdirsSync(folderPath);
|
||||
|
||||
let filePath = `${folderPath}/${fileName}.vue`;
|
||||
|
||||
await fs.writeFileSync(filePath, pageHtml);
|
||||
|
||||
let buildUrl = this.getBuildUrl(filePath);
|
||||
|
||||
return buildUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 删除vueApiServer文件
|
||||
async destroyApiFile(form_id) {
|
||||
try {
|
||||
let formRow = await sys_form.findOne({ where: { id: form_id } });
|
||||
if (formRow) {
|
||||
let { model_id, project_id } = formRow;
|
||||
let modelRow = await sys_model.findOne({ where: { id: model_id } });
|
||||
if (modelRow) {
|
||||
let modelKey = modelRow.key;
|
||||
|
||||
// 删除后端 controller
|
||||
let controller_admin_path = await this.outBuildPath(`api/controller_admin/${modelKey}.js`, project_id);
|
||||
if (await funTool.isExist(controller_admin_path)) {
|
||||
fs.unlinkSync(controller_admin_path);
|
||||
}
|
||||
|
||||
// 删除后端 modelPath
|
||||
let modelPath = await this.outBuildPath(`api/model/${modelKey}.js`, project_id);
|
||||
if (await funTool.isExist(modelPath)) {
|
||||
fs.unlinkSync(modelPath);
|
||||
}
|
||||
|
||||
// 删除数据库
|
||||
await ddlSql(`DROP TABLE ${modelKey}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logsUtil.errError(error.message);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
// 删除vue文件
|
||||
async destroyVueFile(form_id) {
|
||||
let formRow = await sys_form.findOne({ where: { id: form_id } });
|
||||
|
||||
if (formRow) {
|
||||
let { id, component, api_path, project_id } = formRow;
|
||||
|
||||
// 删除前端page
|
||||
if (component) {
|
||||
let pagePath = await this.outBuildPath(`admin/src/view/${component}`, project_id);
|
||||
if (await funTool.isExist(pagePath)) {
|
||||
fs.unlinkSync(pagePath);
|
||||
}
|
||||
}
|
||||
|
||||
// 删除前端apiServe
|
||||
if (api_path) {
|
||||
let apiPath = await this.outBuildPath(`admin/src/api/${api_path}`, project_id);
|
||||
if (await funTool.isExist(apiPath)) {
|
||||
fs.unlinkSync(apiPath);
|
||||
}
|
||||
}
|
||||
|
||||
// 删除表单
|
||||
let formRow = await sys_form.findOne({ where: { id } });
|
||||
if (formRow) {
|
||||
await sys_form_field.destroy({ where: { form_id: formRow.id } });
|
||||
await formRow.destroy({});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user