427 lines
14 KiB
JavaScript
427 lines
14 KiB
JavaScript
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({});
|
|
}
|
|
}
|
|
},
|
|
};
|