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({}); } } }, };