const projectsService = require('../service/projects.service'); const pagesRoleService = require('../service/pagesRole.service'); const pagesService = require('../service/pages.service'); const menuService = require('../service/menu.service'); const roleService = require('../service/roles.service'); const projectUserService = require('../service/project.user.service'); const templateUserService = require('../service/templates.service'); const pageService = require('../service/pages.service'); const publishService = require('../service/publish.service'); const request = require('../utils/request'); const util = require('../utils/util'); const { MODEL_BASE_URL } = require('../config'); module.exports = { async getCategoryList(ctx) { const { userId } = util.decodeToken(ctx); const { pageNum, pageSize, keyword } = ctx.request.query; const { total } = await projectsService.getCategoryCount(keyword, userId); if (total == 0) { return util.success(ctx, { list: [], total: 0, pageSize: +pageSize || 12, pageNum: +pageNum || 1, }); } const list = await projectsService.getCategoryList(pageNum || 1, pageSize || 12, keyword, userId); util.success(ctx, { list, total, pageSize: +pageSize, pageNum: +pageNum, }); }, // mars-admin 项目列表 async getProjectList(ctx) { const { pageNum = 1, pageSize = 10, isTemplate, userId } = ctx.request.query; const template = util.isNumber(isTemplate) ? Number(isTemplate) : ''; const uid = util.isNumber(userId) ? Number(userId) : ''; const { total } = await projectsService.getProjectCount(template, uid); if (total == 0) { return util.success(ctx, { list: [], total: 0, pageSize: +pageSize, pageNum: +pageNum, }); } const list = await projectsService.getProjectList(pageNum, pageSize, template, uid); util.success(ctx, { list, total, pageSize: +pageSize, pageNum: +pageNum, }); }, async create(ctx) { const { id, ...params } = ctx.request.body; const { userId, userName } = util.decodeToken(ctx); if (id) { if (!util.isNumber(id)) { return ctx.throw(400, '模板ID格式异常'); } const project = await projectsService.getProjectByTemplateId(id); if (!project) { return ctx.throw(400, '模板不存在'); } const insertRecord = await projectsService.installProject({ ...project, userId, userName, name: params.name || project.name, remark: params.remark || project.remark, logo: params.logo || project.logo, }); let dictMap = {}; // 开启模型服务后,需要复制模型 if (ENABLE_MODEL_SERVICE) { // 获取项目模型列表 const res = await request .post( `${MODEL_BASE_URL}/api/model/copy`, JSON.stringify({ oldProjectId: String(project.id), newProjectId: String(insertRecord.insertId), }), { headers: { authorization: ctx.request.headers?.authorization, }, }, ) .catch((error) => { ctx.throw(400, '模型创建失败:' + error); }); const result = JSON.parse(res.data); dictMap = result.oldNewDataDictionaryIdMap; } // 获取模板菜单列表 const menusList = await menuService.getMenuByTemplateId(project.id); const originIdMap = {}; let rootList = menusList.filter((menu) => !menu.parentId); // 递归创建菜单和页面 while (rootList.length) { const parentIds = []; for (let menu of rootList) { // 保存父级菜单id parentIds.push(menu.id); if (menu.pageId) { // 获取菜单绑定的页面信息 const page = await pagesService.getPagesById(menu.pageId); let pageRecord = { pageId: 0 }; if (page) { page.pageData && Object.keys(dictMap).forEach((key) => { page.pageData = page.pageData.replaceAll(`"dataDictionaryKey":"${key}"`, `"dataDictionaryKey":"${dictMap[key]}"`); }); // 写入页面数据 pageRecord = await pagesService.createPage(page.name, userId, userName, page.remark, page.pageData, insertRecord.insertId); } // 写入菜单数据 const newRecord = await menuService.create({ ...menu, parentId: originIdMap[menu.parentId], userId, userName, projectId: insertRecord.insertId, pageId: pageRecord.insertId, }); originIdMap[menu.id] = newRecord.insertId; } else { const newRecord = await await menuService.create({ ...menu, parentId: originIdMap[menu.parentId], userId, userName, projectId: insertRecord.insertId, }); originIdMap[menu.id] = newRecord.insertId; } } // 获取下一级菜单 rootList = menusList.filter((menu) => parentIds.find((pid) => pid === menu.parentId)); } await templateUserService.updateInstallCount(id); util.success(ctx, '同步成功'); } else { if (!params.name) { return ctx.throw(400, '项目名称不能为空'); } if (!params.remark) { return ctx.throw(400, '项目描述不能为空'); } if (!params.logo) { return ctx.throw(400, '项目logo不能为空'); } await projectsService.createProject({ ...params, userId, userName, }); util.success(ctx); } }, async delete(ctx) { const { id, type } = ctx.request.body; if (!util.isNumber(id)) { return ctx.throw(400, 'id参数不正确'); } const { userId } = util.decodeToken(ctx); const [projectInfo] = await projectsService.getProjectInfoById(+id); if (!projectInfo || projectInfo.userId != userId) { return ctx.throw(400, '您暂无权限删除该项目'); } // 删除项目本身 const res = await projectsService.deleteProject(id, userId); // 删除项目对应开发者权限 await pagesRoleService.deleteByPageId(id); // 删除项目菜单 await menuService.deleteMenuByProjectId(id); // 删除项目角色 await roleService.deleteByProjectId(id); // 删除项目对应访问者权限 await projectUserService.deleteUserByProjectId(id); // 删除模型表 await request.delete(`${MODEL_BASE_URL}/api/model/projectId/${id}`, { headers: { authorization: ctx.request.headers?.authorization, }, }); if (type == 'all') { await pagesService.deletePageByProjectId(id, userId); } else { await pagesService.updatePageForProjectId(id); } if (res.affectedRows > 0) { util.success(ctx); } else { return ctx.throw(400, '当前暂无权限'); } }, async update(ctx) { const { id, name, remark, logo } = ctx.request.body; if (!util.isNumber(id)) { return ctx.throw(400, 'id参数不正确'); } if (!name) { return ctx.throw(400, '项目名称不能为空'); } if (!remark) { return ctx.throw(400, '项目描述不能为空'); } if (!logo) { return ctx.throw(400, '项目logo不能为空'); } await projectsService.updateProjectInfo(ctx.request.body); util.success(ctx); }, // 检查是否有项目权限 async checkProjectAuth(ctx) { const { id } = ctx.request.body; if (!util.isNumber(id)) { return ctx.throw(400, '项目ID不正确'); } const { userId } = util.decodeToken(ctx); const list = await projectsService.checkAuth(id); if (list.length === 0) { return util.success(ctx, '404'); } if (list[0].userId !== userId && list.filter((item) => item.devUserId === userId).length === 0) { return util.success(ctx, '403'); } util.success(ctx, ''); }, async detail(ctx) { const { id } = ctx.params; if (!util.isNumber(id)) { return ctx.throw(400, '项目ID不能为空'); } const info = await projectsService.getProjectInfoById(id); if (!info?.length) { return util.fail(ctx, '当前项目不存在', 404); } util.success(ctx, info[0]); }, /** * 项目下页面列表 - 一键发布 */ async oneClickPublishing(ctx) { const { userId, userName } = util.decodeToken(ctx); const { id } = ctx.request.body; if (!util.isNumber(id)) { return ctx.throw(400, '项目ID不能为空'); } const info = await projectsService.getProjectInfoById(id); if (!info?.length) { return util.fail(ctx, '当前项目不存在', 404); } const authList = await projectsService.checkAuth(id); if (authList.length === 0) { util.success(ctx, '暂无发布权限'); return false; } if (authList[0].userId !== userId && authList.filter((item) => item.devUserId === userId).length === 0) { util.success(ctx, '暂无发布权限'); return false; } const ids = await pageService.getPageIdsByProjectId(Number(id)); for (let { id: pageId } of ids) { // 获取菜单绑定的页面信息 const page = await pagesService.getPagesById(pageId); // 只发布有数据和未发布的页面 if (page && page.pageData && page.stgState != 3) { const result = await publishService.createPublish(pageId, page.name, page.pageData, userName, userId, 'stg'); await pagesService.updatePageState(result.insertId, pageId, 'stg', ''); } } util.success(ctx, '发布成功'); }, };