wenlele 2 years ago
parent
commit
d521a03f3c
  1. 89
      api/app/lib/controllers/alarm/app.js
  2. 22
      api/app/lib/controllers/organization/index.js
  3. 37
      api/app/lib/controllers/project/index.js
  4. 7
      api/app/lib/index.js
  5. 15
      api/app/lib/models/app_alarm.js
  6. 10
      api/app/lib/routes/alarm/index.js
  7. 5
      api/app/lib/routes/project/index.js
  8. 2
      api/sequelize-automate.config.js
  9. 2
      script/0.0.3/1.alert_app_alarm.sql
  10. 47
      web/client/src/sections/install/components/adminModal.jsx
  11. 34
      web/client/src/sections/install/components/memberModal.jsx
  12. 18
      web/client/src/sections/install/containers/roles.jsx

89
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) { async function notedInspection (ctx) {
try { try {
const models = ctx.fs.dc.models; const models = ctx.fs.dc.models;
@ -58,7 +125,7 @@ async function notedInspection (ctx) {
async function apiError (ctx) { async function apiError (ctx) {
try { try {
const models = ctx.fs.dc.models; 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() const now = moment().format()
let storageData = { let storageData = {
@ -86,6 +153,7 @@ async function apiError (ctx) {
}) })
storageData.serialNumber = 'WEB' + (existCount < 9 ? '0' + (existCount + 1) : existCount) storageData.serialNumber = 'WEB' + (existCount < 9 ? '0' + (existCount + 1) : existCount)
storageData.createTime = now storageData.createTime = now
storageData.screenshot = screenshot
await models.AppAlarm.create(storageData) 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) { async function confirmApiError (ctx) {
try { try {
const models = ctx.fs.dc.models; const models = ctx.fs.dc.models;
@ -124,7 +209,9 @@ async function confirmApiError (ctx) {
module.exports = { module.exports = {
inspection, inspection,
inspectionList,
notedInspection, notedInspection,
apiError, apiError,
apiErrorList,
confirmApiError, confirmApiError,
}; };

22
api/app/lib/controllers/organization/index.js

@ -48,11 +48,19 @@ async function editUser (ctx) {
// 存在且传递id 或者 不传id也存在 // 存在且传递id 或者 不传id也存在
// 修改 update // 修改 update
storageData.deleted = false storageData.deleted = false
storageData.role = [...new Set([...existUserRes.role, ...role])]
if ( 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, { await models.User.update(storageData, {
where: { where: {
@ -64,7 +72,7 @@ async function editUser (ctx) {
await models.User.create(storageData) await models.User.create(storageData)
} }
ctx.status = 200 ctx.status = 204
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; 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 '成员不能既是管理员又是普通成员' throw '成员不能既是管理员又是普通成员'
} }
@ -193,7 +201,9 @@ async function user (ctx) {
for (let u of userRes.rows.concat(adminRes)) { for (let u of userRes.rows.concat(adminRes)) {
userIds.add(u.pepUserId) 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)) { for (let u of userRes.rows.concat(adminRes)) {
const corUsers = userPepRes.filter(up => up.id == u.pepUserId) const corUsers = userPepRes.filter(up => up.id == u.pepUserId)

37
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 = { module.exports = {
appList, appList,
projectAnxincloud,
projectPManage,
}; };

7
api/app/lib/index.js

@ -55,7 +55,12 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq
}); });
const { const {
AppInspection, ProjectApp, ProjectCorrelation
} = dc.models; } = 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' });
}; };

15
api/app/lib/models/app_alarm.js

@ -31,7 +31,11 @@ module.exports = dc => {
comment: "对应的项目id", comment: "对应的项目id",
primaryKey: false, primaryKey: false,
field: "project_app_id", field: "project_app_id",
autoIncrement: false autoIncrement: false,
references: {
key: "id",
model: "projectApp"
}
}, },
appDomain: { appDomain: {
type: DataTypes.STRING, type: DataTypes.STRING,
@ -95,6 +99,15 @@ module.exports = dc => {
primaryKey: false, primaryKey: false,
field: "status_code", field: "status_code",
autoIncrement: false autoIncrement: false
},
screenshot: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "screenshot",
autoIncrement: false
} }
}, { }, {
tableName: "app_alarm", tableName: "app_alarm",

10
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 }; app.fs.api.logAttr['POST/alarm/application/inspection'] = { content: '保存应用巡检信息', visible: true };
router.post('/alarm/application/inspection', application.inspection); 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 }; app.fs.api.logAttr['PUT/alarm/application/noted'] = { content: '保存检验状态', visible: true };
router.put('/alarm/application/noted', application.notedInspection); 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); 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); router.post('/alarm/application/api_confirm', application.confirmApiError);
}; };

5
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 }; app.fs.api.logAttr['POST/project/bind'] = { content: '绑定安心云、项目管理项目', visible: true };
router.post('/project/bind', projectBind.bindAnxin2pep); 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);
}; };

2
api/sequelize-automate.config.js

@ -26,7 +26,7 @@ module.exports = {
dir: './app/lib/models', // 指定输出 models 文件的目录 dir: './app/lib/models', // 指定输出 models 文件的目录
typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义 typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义
emptyDir: false, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir` 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,则忽略改属性 skipTables: [], // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性
tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中 tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中
ignorePrefix: [], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面 ignorePrefix: [], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面

2
script/0.0.3/1.alert_app_alarm.sql

@ -0,0 +1,2 @@
alter table app_alarm
add screenshot varchar(1024);

47
web/client/src/sections/install/components/adminModal.jsx

@ -31,7 +31,7 @@ function adminModal (props) {
} }
setPeopleList(departmentList) setPeopleList(departmentList)
setDepartmentId(editObj.departments[0].id) setDepartmentId(editObj.departments[0].id)
setPeopleId(editObj.id) setPeopleId(editObj.pepUserId)
setDisablePeople(false) setDisablePeople(false)
} }
}, []); }, []);
@ -42,13 +42,19 @@ function adminModal (props) {
.validate() .validate()
.then((values) => { .then((values) => {
if (adminEdit) { if (adminEdit) {
dispatch(install.postOrganizationUser({ role: ['admin'], pepUserId: values.pepUserId })).then((res) => {//(PEP) dispatch(install.deteleOrganizationAdmin(editObj.id)).then(
close(); dispatch(install.postOrganizationUser({ role: ['admin'], pepUserId: values.pepUserId })).then((res) => {//(PEP)
}) if(res.success){
close();
}
})
)
} }
else { else {
dispatch(install.postOrganizationUser({ role: ['admin'], pepUserId: values.pepUserId })).then((res) => {//(PEP) 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" labelAlign="right"
labelWidth="90px" labelWidth="90px"
onValueChange={(values, field) => { onValueChange={(values, field) => {
if (values.department >= 0) { for (var key in field) {
let departmentList = [] if (key == 'department') {
for (let i = 0; i < pepList.length; i++) { if (values.department >= 0) {
if (pepList[i].id == values.department) { let departmentList = []
departmentList = pepList[i].users 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)} getFormApi={(formApi) => (form.current = formApi)}

34
web/client/src/sections/install/components/memberModal.jsx

@ -40,7 +40,7 @@ function memberModal (props) {
]); // ]); //
// //
useEffect(() => { useEffect(() => {
if(editObj.id){ if (editObj.id) {
let departmentList = [] let departmentList = []
for (let i = 0; i < pepList.length; i++) { for (let i = 0; i < pepList.length; i++) {
if (pepList[i].id == editObj.departments[0].id) { if (pepList[i].id == editObj.departments[0].id) {
@ -57,8 +57,14 @@ function memberModal (props) {
form.current form.current
.validate() .validate()
.then((values) => { .then((values) => {
dispatch(install.postOrganizationUser({ role: values.role, pepUserId: values.pepUserId })).then((res) => {//(PEP) let roleArr=JSON.parse(JSON.stringify(values.role))
close(); 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" labelAlign="right"
labelWidth="90px" labelWidth="90px"
onValueChange={(values, field) => { onValueChange={(values, field) => {
for(var key in field){ for (var key in field) {
if(key=='department'){ if (key == 'department') {
if (values.department >= 0) { 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) setDisablePeople(false)
setPeopleList(pepList[values.department].users) form.current.setValue('pepUserId', undefined);
} }
else { else {
setPeopleList([]) setPeopleList([])
setDisablePeople(true) setDisablePeople(true)
form.current.setValue('pepUserId', undefined);
} }
} }
} }
}} }}
getFormApi={(formApi) => (form.current = formApi)} getFormApi={(formApi) => (form.current = formApi)}
> >
@ -118,7 +132,7 @@ function memberModal (props) {
{ {
pepList.map((item, index) => { pepList.map((item, index) => {
return ( return (
<Form.Select.Option key={item.id} value={index}> <Form.Select.Option key={item.id} value={item.id}>
{item.name} {item.name}
</Form.Select.Option> </Form.Select.Option>
) )
@ -134,7 +148,7 @@ function memberModal (props) {
style={{ width: 417 }} style={{ width: 417 }}
rules={[{ required: true, message: "请选择人员" }]} rules={[{ required: true, message: "请选择人员" }]}
showClear showClear
initValue={editObj.id || ""} initValue={editObj.pepUserId || ""}
disabled={disablePeople} disabled={disablePeople}
> >
{ {
@ -153,7 +167,7 @@ function memberModal (props) {
field="role" field="role"
label='权限配置:' label='权限配置:'
showClear showClear
initValue={editObj.role||[]} initValue={editObj.role || []}
> >
{ {
jurisdiction.map((item, index) => { jurisdiction.map((item, index) => {

18
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)', borderRadius: 2, background: "url(/assets/images/install/cardBackground0" + (index + 1) + '.png)',
backgroundSize: "100% 100%", marginRight: 20, marginBottom: 20, backgroundSize: "100% 100%", marginRight: 20, marginBottom: 20,
}}> }}>
{ {
item.id ? ( item.id ? (
<div style={{ display: 'flex', marginLeft: 21, }}> <div style={{ display: 'flex', marginLeft: 21, }}>
{ {
item.departments?.map((itm, idx) => { item.departments?.map((itm, idx) => {
let mydepartmentsArr=[]
for (let index = 0; index < item.departments.length; index++) {
mydepartmentsArr.push(item.departments[index].name)
}
return ( return (
<div key={idx} style={{ <div key={idx} style={{
background: '#52A4F6', borderRadius: 2, height: 18, padding: '2px 4px', background: '#52A4F6', borderRadius: 2, height: 18, padding: '2px 4px',
fontSize: 10, marginTop: 17, width: 'max-content', color: '#FFFFFF', fontSize: 10, marginTop: 17, width: 'max-content', color: '#FFFFFF',
display: 'flex', alignItems: 'center', marginRight: 4, display: 'flex', alignItems: 'center', marginRight: 4,
}}> }}>
{itm.name} {
idx > 2 ? (
<Tooltip content={mydepartmentsArr.join(',')}>
<div style={{ fontSize: 14, cursor: "pointer", }}>
...
</div>
</Tooltip>
) : (
itm.name
)
}
</div> </div>
) )
}) })

Loading…
Cancel
Save