diff --git a/api/app/lib/controllers/alarm/app.js b/api/app/lib/controllers/alarm/app.js index e970300..58fe6e8 100644 --- a/api/app/lib/controllers/alarm/app.js +++ b/api/app/lib/controllers/alarm/app.js @@ -30,6 +30,73 @@ async function inspection (ctx) { } } +async function inspectionList (ctx) { + try { + const models = ctx.fs.dc.models; + const { clickHouse } = ctx.app.fs + const { timeStart, timeEnd, projectId, appId, noted } = ctx.query + + let findOption = { + where: { + + }, + order: [['id', 'DESC']], + include: [{ + model: models.ProjectApp, + required: Boolean(appId || projectId), + where: appId ? { + id: appId + } : undefined, + include: { + model: models.ProjectCorrelation, + required: Boolean(projectId), + where: projectId ? { + id: projectId + } : undefined, + attributes: { + exclude: ['anxinProjectId', 'createTime', 'createUser'] + } + } + }] + } + if (timeStart && timeEnd) { + findOption.where.createTime = { $between: [moment(timeStart).format(), moment(timeEnd).format()] } + } + if (noted) { + if (noted == 'noted') { + findOption.where.notedTime = { $ne: null } + } else if (noted == 'unnote') { + findOption.where.notedTime = null + } + } + + const inspectionRes = await models.AppInspection.findAll(findOption) + let notedUserIds = new Set() + for (let ins of inspectionRes) { + if (ins.notedPepUserId) { + notedUserIds.add(ins.notedPepUserId) + } + } + let userPepRes = notedUserIds.size ? + await clickHouse.pepEmis.query(`SELECT DISTINCT user.id AS id, "user"."name" AS name FROM user WHERE user.id IN (${[...notedUserIds].join(',')})`).toPromise() : + [] + for (let ins of inspectionRes) { + if (ins.notedPepUserId) { + const corUser = userPepRes.find(up => up.id == ins.notedPepUserId) + ins.dataValues.notedPepUser = corUser ? corUser.name : '' + } + } + ctx.status = 200; + ctx.body = inspectionRes + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: error`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } +} + async function notedInspection (ctx) { try { const models = ctx.fs.dc.models; @@ -58,7 +125,7 @@ async function notedInspection (ctx) { async function apiError (ctx) { try { const models = ctx.fs.dc.models; - const { projectAppId, alarmContent, router, statusCode } = ctx.request.body + const { projectAppId, alarmContent, router, statusCode, screenshot = '' } = ctx.request.body const now = moment().format() let storageData = { @@ -86,6 +153,7 @@ async function apiError (ctx) { }) storageData.serialNumber = 'WEB' + (existCount < 9 ? '0' + (existCount + 1) : existCount) storageData.createTime = now + storageData.screenshot = screenshot await models.AppAlarm.create(storageData) } @@ -99,6 +167,23 @@ async function apiError (ctx) { } } +async function apiErrorList (ctx) { + try { + const models = ctx.fs.dc.models; + const { clickHouse } = ctx.app.fs + const { } = ctx.query + + ctx.status = 200; + ctx.body = [] + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: error`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } +} + async function confirmApiError (ctx) { try { const models = ctx.fs.dc.models; @@ -124,7 +209,9 @@ async function confirmApiError (ctx) { module.exports = { inspection, + inspectionList, notedInspection, apiError, + apiErrorList, confirmApiError, }; \ No newline at end of file diff --git a/api/app/lib/controllers/organization/index.js b/api/app/lib/controllers/organization/index.js index c525290..f8c4ba7 100644 --- a/api/app/lib/controllers/organization/index.js +++ b/api/app/lib/controllers/organization/index.js @@ -48,11 +48,19 @@ async function editUser (ctx) { // 存在且传递id 或者 不传id也存在 // 修改 update storageData.deleted = false - storageData.role = [...new Set([...existUserRes.role, ...role])] if ( - storageData.role.includes('admin') + role.includes('admin') ) { - storageData.disabled = false + if (existUserRes.role.includes('admin')) { + // 已是管理员 + throw '当前人员已是管理员' + } + // 正在修改为管理员 + storageData.disabled = true + storageData.role = [...new Set([...existUserRes.role, ...role])] + } else if (existUserRes.role.includes('admin')) { + // 正在修改成员 但是此时还是管理员 + storageData.role = [...role, 'admin'] } await models.User.update(storageData, { where: { @@ -64,7 +72,7 @@ async function editUser (ctx) { await models.User.create(storageData) } - ctx.status = 200 + ctx.status = 204 } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; @@ -85,7 +93,7 @@ async function putUser (ctx) { } }) - if (existUserRes && existUserRes.role.includes('admin') && disabled) { + if (existUserRes && existUserRes.role.includes('admin') && !disabled) { throw '成员不能既是管理员又是普通成员' } @@ -193,7 +201,9 @@ async function user (ctx) { for (let u of userRes.rows.concat(adminRes)) { userIds.add(u.pepUserId) } - let userPepRes = await clickHouse.pepEmis.query(`SELECT user.id AS id, "user"."name" AS name, department.name AS depName, department.id AS depId FROM department_user LEFT JOIN user ON department_user.user=user.id LEFT JOIN department ON department.id=department_user.department WHERE user.id IN (${[...userIds].join(',')}) AND department.delete=false`).toPromise() + let userPepRes = userIds.size ? + await clickHouse.pepEmis.query(`SELECT DISTINCT user.id AS id, "user"."name" AS name, department.name AS depName, department.id AS depId FROM department_user LEFT JOIN user ON department_user.user=user.id LEFT JOIN department ON department.id=department_user.department WHERE user.id IN (${[...userIds].join(',')}) AND department.delete=false`).toPromise() : + [] for (let u of userRes.rows.concat(adminRes)) { const corUsers = userPepRes.filter(up => up.id == u.pepUserId) diff --git a/api/app/lib/controllers/project/index.js b/api/app/lib/controllers/project/index.js index df0008f..70af536 100644 --- a/api/app/lib/controllers/project/index.js +++ b/api/app/lib/controllers/project/index.js @@ -20,7 +20,44 @@ async function appList (ctx) { } } +async function projectAnxincloud (ctx) { + try { + const models = ctx.fs.dc.models; + const { clickHouse } = ctx.app.fs + + const projectRes = await clickHouse.anxinyun.query(`SELECT * FROM t_project WHERE project_state = 4 ORDER BY id DESC`).toPromise() + + ctx.status = 200; + ctx.body = projectRes + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: error`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } +} + +async function projectPManage (ctx) { + try { + const models = ctx.fs.dc.models; + const { clickHouse } = ctx.app.fs + + const projectRes = await clickHouse.projectManage.query(`SELECT * FROM t_project WHERE project_state = 4 ORDER BY id DESC`).toPromise() + + ctx.status = 200; + ctx.body = projectRes + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: error`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } +} module.exports = { appList, + projectAnxincloud, + projectPManage, }; \ No newline at end of file diff --git a/api/app/lib/index.js b/api/app/lib/index.js index 2862fce..323a254 100644 --- a/api/app/lib/index.js +++ b/api/app/lib/index.js @@ -55,7 +55,12 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq }); const { - + AppInspection, ProjectApp, ProjectCorrelation } = dc.models; + AppInspection.belongsTo(ProjectApp, { foreignKey: 'projectAppId', targetKey: 'id' }); + ProjectApp.hasMany(AppInspection, { foreignKey: 'projectAppId', sourceKey: 'id' }); + + ProjectApp.belongsTo(ProjectCorrelation, { foreignKey: 'projectId', targetKey: 'id' }); + ProjectCorrelation.hasMany(ProjectApp, { foreignKey: 'projectId', sourceKey: 'id' }); }; diff --git a/api/app/lib/models/app_alarm.js b/api/app/lib/models/app_alarm.js index 6d6bdbb..fb958c7 100644 --- a/api/app/lib/models/app_alarm.js +++ b/api/app/lib/models/app_alarm.js @@ -31,7 +31,11 @@ module.exports = dc => { comment: "对应的项目id", primaryKey: false, field: "project_app_id", - autoIncrement: false + autoIncrement: false, + references: { + key: "id", + model: "projectApp" + } }, appDomain: { type: DataTypes.STRING, @@ -95,6 +99,15 @@ module.exports = dc => { primaryKey: false, field: "status_code", autoIncrement: false + }, + screenshot: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "screenshot", + autoIncrement: false } }, { tableName: "app_alarm", diff --git a/api/app/lib/routes/alarm/index.js b/api/app/lib/routes/alarm/index.js index 50dc0cb..7872086 100644 --- a/api/app/lib/routes/alarm/index.js +++ b/api/app/lib/routes/alarm/index.js @@ -9,12 +9,18 @@ module.exports = function (app, router, opts) { app.fs.api.logAttr['POST/alarm/application/inspection'] = { content: '保存应用巡检信息', visible: true }; router.post('/alarm/application/inspection', application.inspection); + app.fs.api.logAttr['GET/alarm/application/inspection'] = { content: '查询应用巡检信息', visible: true }; + router.get('/alarm/application/inspection', application.inspectionList); + app.fs.api.logAttr['PUT/alarm/application/noted'] = { content: '保存检验状态', visible: true }; router.put('/alarm/application/noted', application.notedInspection); - app.fs.api.logAttr['POST/alarm/application/api'] = { content: '保存应用接口错误信息', visible: true }; + app.fs.api.logAttr['POST/alarm/application/api'] = { content: '保存应用接口/元素错误信息', visible: true }; router.post('/alarm/application/api', application.apiError); - app.fs.api.logAttr['POST/alarm/application/api_confirm'] = { content: '确认应用接口错误信息', visible: true }; + app.fs.api.logAttr['GET/alarm/application/api'] = { content: '查询应用接口/元素错误信息', visible: true }; + router.get('/alarm/application/api', application.apiErrorList); + + app.fs.api.logAttr['POST/alarm/application/api_confirm'] = { content: '确认应用接口/元素错误信息', visible: true }; router.post('/alarm/application/api_confirm', application.confirmApiError); }; diff --git a/api/app/lib/routes/project/index.js b/api/app/lib/routes/project/index.js index 8f980de..8c41c72 100644 --- a/api/app/lib/routes/project/index.js +++ b/api/app/lib/routes/project/index.js @@ -10,4 +10,9 @@ module.exports = function (app, router, opts) { app.fs.api.logAttr['POST/project/bind'] = { content: '绑定安心云、项目管理项目', visible: true }; router.post('/project/bind', projectBind.bindAnxin2pep); + app.fs.api.logAttr['GET/project/anxincloud'] = { content: '获取安心云项目', visible: true }; + router.get('/project/anxincloud', project.projectAnxincloud); + + app.fs.api.logAttr['GET/project/pmanage'] = { content: '获取PEP项目管理项目', visible: true }; + router.get('/project/pmanage', project.projectPManage); }; \ No newline at end of file diff --git a/api/sequelize-automate.config.js b/api/sequelize-automate.config.js index ae7d5c4..e34d53b 100644 --- a/api/sequelize-automate.config.js +++ b/api/sequelize-automate.config.js @@ -26,7 +26,7 @@ module.exports = { dir: './app/lib/models', // 指定输出 models 文件的目录 typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义 emptyDir: false, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir` - tables: ['app_inspection'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性 + tables: ['app_alarm'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性 skipTables: [], // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性 tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中 ignorePrefix: [], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面 diff --git a/script/0.0.3/1.alert_app_alarm.sql b/script/0.0.3/1.alert_app_alarm.sql new file mode 100644 index 0000000..0bee93d --- /dev/null +++ b/script/0.0.3/1.alert_app_alarm.sql @@ -0,0 +1,2 @@ +alter table app_alarm + add screenshot varchar(1024); \ No newline at end of file diff --git a/web/client/src/sections/install/components/adminModal.jsx b/web/client/src/sections/install/components/adminModal.jsx index cb1219a..98a7b8c 100644 --- a/web/client/src/sections/install/components/adminModal.jsx +++ b/web/client/src/sections/install/components/adminModal.jsx @@ -31,7 +31,7 @@ function adminModal (props) { } setPeopleList(departmentList) setDepartmentId(editObj.departments[0].id) - setPeopleId(editObj.id) + setPeopleId(editObj.pepUserId) setDisablePeople(false) } }, []); @@ -42,13 +42,19 @@ function adminModal (props) { .validate() .then((values) => { if (adminEdit) { - dispatch(install.postOrganizationUser({ role: ['admin'], pepUserId: values.pepUserId })).then((res) => {//获取项企(PEP)全部部门及其下用户 - close(); - }) + dispatch(install.deteleOrganizationAdmin(editObj.id)).then( + dispatch(install.postOrganizationUser({ role: ['admin'], pepUserId: values.pepUserId })).then((res) => {//获取项企(PEP)全部部门及其下用户 + if(res.success){ + close(); + } + }) + ) } else { dispatch(install.postOrganizationUser({ role: ['admin'], pepUserId: values.pepUserId })).then((res) => {//获取项企(PEP)全部部门及其下用户 - close(); + if(res.success){ + close(); + } }) } }) @@ -79,22 +85,25 @@ function adminModal (props) { labelAlign="right" labelWidth="90px" onValueChange={(values, field) => { - if (values.department >= 0) { - let departmentList = [] - for (let i = 0; i < pepList.length; i++) { - if (pepList[i].id == values.department) { - departmentList = pepList[i].users + for (var key in field) { + if (key == 'department') { + if (values.department >= 0) { + let departmentList = [] + for (let i = 0; i < pepList.length; i++) { + if (pepList[i].id == values.department) { + departmentList = pepList[i].users + } + } + setPeopleList(departmentList) + setDisablePeople(false) + form.current.setValue('pepUserId', undefined); + } + else { + setPeopleList([]) + setDisablePeople(true) + form.current.setValue('pepUserId', undefined); } } - setPeopleList(departmentList) - setDisablePeople(false) - // if(disablePeople){ - // form.current.setValue(pepUserId, undefined); - // } - } - else { - setPeopleList([]) - setDisablePeople(true) } }} getFormApi={(formApi) => (form.current = formApi)} diff --git a/web/client/src/sections/install/components/memberModal.jsx b/web/client/src/sections/install/components/memberModal.jsx index 6e04ab7..7302c5d 100644 --- a/web/client/src/sections/install/components/memberModal.jsx +++ b/web/client/src/sections/install/components/memberModal.jsx @@ -40,7 +40,7 @@ function memberModal (props) { ]); //权限配置 //初始化 useEffect(() => { - if(editObj.id){ + if (editObj.id) { let departmentList = [] for (let i = 0; i < pepList.length; i++) { if (pepList[i].id == editObj.departments[0].id) { @@ -57,8 +57,14 @@ function memberModal (props) { form.current .validate() .then((values) => { - dispatch(install.postOrganizationUser({ role: values.role, pepUserId: values.pepUserId })).then((res) => {//获取项企(PEP)全部部门及其下用户 - close(); + let roleArr=JSON.parse(JSON.stringify(values.role)) + if (roleArr.indexOf('admin') != -1) { + roleArr.splice(roleArr.indexOf('admin'),1) + } + dispatch(install.postOrganizationUser({ role: roleArr, pepUserId: values.pepUserId })).then((res) => {//获取项企(PEP)全部部门及其下用户 + if(res.success){ + close(); + } }) }) } @@ -88,19 +94,27 @@ function memberModal (props) { labelAlign="right" labelWidth="90px" onValueChange={(values, field) => { - for(var key in field){ - if(key=='department'){ + for (var key in field) { + if (key == 'department') { if (values.department >= 0) { + let departmentList = [] + for (let i = 0; i < pepList.length; i++) { + if (pepList[i].id == values.department) { + departmentList = pepList[i].users + } + } + setPeopleList(departmentList) setDisablePeople(false) - setPeopleList(pepList[values.department].users) + form.current.setValue('pepUserId', undefined); } else { setPeopleList([]) setDisablePeople(true) + form.current.setValue('pepUserId', undefined); } } } - + }} getFormApi={(formApi) => (form.current = formApi)} > @@ -118,7 +132,7 @@ function memberModal (props) { { pepList.map((item, index) => { return ( - + {item.name} ) @@ -134,7 +148,7 @@ function memberModal (props) { style={{ width: 417 }} rules={[{ required: true, message: "请选择人员" }]} showClear - initValue={editObj.id || ""} + initValue={editObj.pepUserId || ""} disabled={disablePeople} > { @@ -153,7 +167,7 @@ function memberModal (props) { field="role" label='权限配置:' showClear - initValue={editObj.role||[]} + initValue={editObj.role || []} > { jurisdiction.map((item, index) => { diff --git a/web/client/src/sections/install/containers/roles.jsx b/web/client/src/sections/install/containers/roles.jsx index 5bb5a4b..2360319 100644 --- a/web/client/src/sections/install/containers/roles.jsx +++ b/web/client/src/sections/install/containers/roles.jsx @@ -322,19 +322,33 @@ const Roles = (props) => { borderRadius: 2, background: "url(/assets/images/install/cardBackground0" + (index + 1) + '.png)', backgroundSize: "100% 100%", marginRight: 20, marginBottom: 20, }}> - { item.id ? (
{ item.departments?.map((itm, idx) => { + let mydepartmentsArr=[] + for (let index = 0; index < item.departments.length; index++) { + mydepartmentsArr.push(item.departments[index].name) + } return (
- {itm.name} + { + idx > 2 ? ( + +
+ ... +
+
+ + ) : ( + itm.name + ) + }
) })