Browse Source

资源消费

master
wenlele 2 years ago
parent
commit
ba5f3f8458
  1. 147
      api/app/lib/controllers/resourceConsumption/index.js
  2. 3
      api/app/lib/index.js
  3. 23
      api/app/lib/routes/resourceConsumption/index.js
  4. 29
      web/client/src/sections/resourceConsumption/actions/approve.js
  5. 2
      web/client/src/sections/resourceConsumption/actions/index.js
  6. 94
      web/client/src/sections/resourceConsumption/components/approveModal.js
  7. 187
      web/client/src/sections/resourceConsumption/containers/approve.js
  8. 134
      web/client/src/sections/resourceConsumption/containers/myApplication.js
  9. 5
      web/client/src/utils/webapi.js

147
api/app/lib/controllers/resourceConsumption/index.js

@ -0,0 +1,147 @@
'use strict';
const moment = require('moment')
function getApproveList (opts) {
return async function (ctx, next) {
const models = ctx.fs.dc.models;
const { page, limit, applyAt, approveState, resourceName, applyBy, applyById } = ctx.query;
let errMsg = { message: '获取消费审批列表失败' }
try {
let option = {
where: {},
order: [["id", "desc"]],
distinct: true,
include: [{
model: models.User,
attributes: ['id', 'name']
},]
}
if (resourceName) {
option.where.resourceName = { $iLike: `%${resourceName}%` }
}
if (applyBy) {
option.include[0].where = { '$user.name$': { $iLike: `%${applyBy}%` } }
}
if (applyById) {
option.where.applyBy = applyById
}
if (limit) {
option.limit = Number(limit)
}
if (page && limit) {
option.offset = Number(page) * Number(limit)
}
if (approveState) {
option.where.approveState = approveState
}
if (applyAt) {
option.where.applyAt = {
$between: [
moment(applyAt).startOf('day').format('YYYY-MM-DD HH:mm:ss'),
moment(applyAt).endOf('day').format('YYYY-MM-DD HH:mm:ss')
]
}
}
const res = await models.ResourceConsumption.findAndCount(option);
ctx.status = 200;
ctx.body = res;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = errMsg
}
}
}
// 新增模型
function addModelManagement (opts) {
return async function (ctx, next) {
const models = ctx.fs.dc.models;
try {
const { attributeName, attributeCode, modelType } = ctx.request.body
const checkName = await models.MetaModel.findOne({ where: { attributeName, modelType } });
const checkCode = await models.MetaModel.findOne({ where: { attributeCode, modelType } });
if (checkName || checkCode) {
ctx.status = 400;
ctx.body = { message: checkName ? '该属性名称已存在' : "该属性代码已存在" }
} else {
let rslt = ctx.request.body;
await models.MetaModel.create(Object.assign({}, rslt))
ctx.status = 204;
ctx.body = { message: '新建模型成功' }
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = { message: '新建模型失败' }
}
}
}
// 修改模型
function postApprove (opts) {
return async function (ctx, next) {
try {
const models = ctx.fs.dc.models;
const data = ctx.request.body;
const { id } = data
await models.ResourceConsumption.update(
data,
{ where: { id: id, } }
)
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = { message: '消费审批失败' }
}
}
}
// 删除模型
function deleteModelManagement (opts) {
return async function (ctx, next) {
try {
const models = ctx.fs.dc.models;
const { id } = ctx.params;
await models.MetaModel.destroy({
where: {
id: id
}
})
ctx.status = 204;
ctx.body = { message: '删除模型成功' }
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = { message: '删除模型失败' }
}
}
}
module.exports = {
// getModelManagementList,
// addModelManagement,
// editModelManagement,
// deleteModelManagement,
getApproveList,
postApprove,
}

3
api/app/lib/index.js

@ -56,7 +56,7 @@ module.exports.models = function (dc) {
const { const {
DataSource, AcquisitionTask, Adapter, User, MetadataDatabase, MetadataFile, MetadataRestapi, AcquisitionLog, ResourceCatalog, DataSource, AcquisitionTask, Adapter, User, MetadataDatabase, MetadataFile, MetadataRestapi, AcquisitionLog, ResourceCatalog,
BusinessMetadataDatabase, BusinessMetadataFile, BusinessMetadataRestapi BusinessMetadataDatabase, BusinessMetadataFile, BusinessMetadataRestapi,ResourceConsumption
} = dc.models; } = dc.models;
AcquisitionTask.belongsTo(DataSource, { foreignKey: 'dataSourceId', targetKey: 'id' }); AcquisitionTask.belongsTo(DataSource, { foreignKey: 'dataSourceId', targetKey: 'id' });
@ -85,4 +85,5 @@ module.exports.models = function (dc) {
BusinessMetadataDatabase.belongsTo(User, { foreignKey: 'createBy', targetKey: 'id' }); BusinessMetadataDatabase.belongsTo(User, { foreignKey: 'createBy', targetKey: 'id' });
BusinessMetadataFile.belongsTo(User, { foreignKey: 'createBy', targetKey: 'id' }); BusinessMetadataFile.belongsTo(User, { foreignKey: 'createBy', targetKey: 'id' });
BusinessMetadataRestapi.belongsTo(User, { foreignKey: 'createBy', targetKey: 'id' }); BusinessMetadataRestapi.belongsTo(User, { foreignKey: 'createBy', targetKey: 'id' });
ResourceConsumption.belongsTo(User, { foreignKey: 'applyBy', targetKey: 'id' });
}; };

23
api/app/lib/routes/resourceConsumption/index.js

@ -0,0 +1,23 @@
'use strict';
const model = require('../../controllers/resourceConsumption/index');
module.exports = function (app, router, opts, AuthCode) {
// app.fs.api.logAttr['POST/meta/model'] = { content: '增加模型信息', visible: true };
// router.post('/meta/model', model.addModelManagement(opts))
// 修改模型信息
app.fs.api.logAttr['POST/resource/approve'] = { content: '消费审批', visible: true };
router.post('/resource/approve', model.postApprove(opts))
// // 删除模型信息
// app.fs.api.logAttr['DEL/meta/model/:id'] = { content: '删除模型信息', visible: true };
// router.del('/meta/model/:id', model.deleteModelManagement(opts))
//获取模型信息列表
app.fs.api.logAttr['GET/resource/approve'] = { content: '获取消费审批列表', visible: true };
router.get('/resource/approve', model.getApproveList(opts));
};

29
web/client/src/sections/resourceConsumption/actions/approve.js

@ -0,0 +1,29 @@
'use strict';
import { basicAction } from '@peace/utils'
import { ApiTable } from '$utils'
export function getApproveList (query = {}) {
return dispatch => basicAction({
type: 'get',
query,
dispatch: dispatch,
actionType: 'GET_APPROVE_LIST',
url: `${ApiTable.approveList}`,
msg: { error: '获取资源消费列表失败' },
reducer: { name: '' }
});
}
export function postApprove (data = {}) {
return dispatch => basicAction({
type: 'post',
data,
dispatch: dispatch,
actionType: 'POST_APPROVE',
url: `${ApiTable.approveList}`,
msg: { option: '资源审批' },
reducer: { name: '' }
});
}

2
web/client/src/sections/resourceConsumption/actions/index.js

@ -1,7 +1,9 @@
'use strict'; 'use strict';
import * as example from './example' import * as example from './example'
import * as approve from './approve'
export default { export default {
...example, ...example,
...approve,
} }

94
web/client/src/sections/resourceConsumption/components/approveModal.js

@ -0,0 +1,94 @@
import React, { useEffect, useState } from 'react'
import { connect } from 'react-redux';
import moment from 'moment';
import { v4 as uuidv4 } from 'uuid'
import { Tabs, Form, Input, DatePicker, Button, Modal, Radio } from 'antd';
function ApproveModal ({ loading, clientHeight, user, actions, dispatch, close, success, editData, }) {
const { resourceConsumption } = actions
const [tabsKey, setTabsKey] = useState("stay")
const [query, setQuery] = useState({ page: 0, limit: 10 });
const [proTableList, setProTableList] = useState({ rows: [], count: 0 });
const [approve, setApprove] = useState()
const [form] = Form.useForm();
useEffect(() => {
}, [])
return <>
<Modal title="数据消费审批" open={true}
onOk={e => {
form.validateFields().then(v => {
console.log(v);
dispatch(resourceConsumption.postApprove({
id: editData?.id, ...v,
approveAt: moment().format('YYYY-MM-DD HH:mm:ss'),
approveBy: user?.id,
approveState: '已审批'
})).then(res => {
if (res.success) {
close()
success()
}
})
})
}}
onCancel={() => {
close()
}}
>
<Form
style={{ marginLeft: 20 }}
form={form}
onValuesChange={v => {
console.log(v);
if (v.approve) {
setApprove(v.approve)
}
// setFormData(v)
}}
autoComplete="off"
>
<Form.Item label="审批意见" name="approve" rules={[{ required: true, message: '请选择审批意见' }]} >
<Radio.Group>
<Radio value="true"> 同意 </Radio>
<Radio value="false"> 不同意 </Radio>
</Radio.Group>
</Form.Item>
{!approve || approve == 'false' ?
<Form.Item label="意见内容" name="approveRemarks" rules={[{ required: true, message: '请输入意见内容' }]}>
<Input allowClear placeholder='请填写意见内容' style={{ width: 300, marginRight: 16 }} />
</Form.Item> : ""}
{!approve || approve == 'true' ? <div style={{ position: 'relative' }}>
<Form.Item label="访问令牌" name="token" rules={[{ required: true, message: '请生成令牌' }]}>
<Input allowClear placeholder='生成令牌' disabled={true} style={{ width: 300, marginRight: 16 }} />
</Form.Item>
<Button type="primary" style={{ position: 'absolute', top: 0, right: 0 }} onClick={() => {
form.setFieldsValue({ token: uuidv4() })
}}>生成</Button>
</div> : ""}
</Form>
</Modal >
</>
}
function mapStateToProps (state) {
const { global, auth, resourceCatalog } = state;
return {
user: auth.user,
actions: global.actions,
clientHeight: global.clientHeight,
// resourceCatalog: resourceCatalog?.data || [],
// isRequesting: resourceCatalog.isRequesting
};
}
export default connect(mapStateToProps)(ApproveModal)

187
web/client/src/sections/resourceConsumption/containers/approve.js

@ -1,7 +1,188 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { connect } from 'react-redux';
import moment from 'moment';
import ApproveModal from '../components/approveModal';
function Approve (props) {
return <>数据消费审批</> import { Tabs, Form, Input, DatePicker, Button, Table } from 'antd';
import { v1 } from 'uuid';
function Approve ({ loading, clientHeight, actions, dispatch, }) {
const { resourceConsumption } = actions
const [tabsKey, setTabsKey] = useState("stay")
const [query, setQuery] = useState({ page: 0, limit: 10 });
const [proTableList, setProTableList] = useState({ rows: [], count: 0 });
const [formData, setFormData] = useState({})
const [approveModal, setApproveModal] = useState(false)
const [editData, setEditData] = useState({})
const [column, setColumn] = useState([])
useEffect(() => {
resourceData()
}, [])
let resourceData = (params) => {
let data = params || query
dispatch(resourceConsumption.getApproveList({ approveState: tabsKey == 'stay' ? "审批中" : '已审批', ...formData, ...data, })).then(res => {
if (res.success) {
setProTableList(res.payload.data)
}
})
}
const columns = [{
title: '资源名称',
dataIndex: 'resourceName',
}, {
title: '申请人',
dataIndex: 'applyBy',
render: (text, record) => record?.user?.name
}, {
title: '需求描述',
dataIndex: 'requirements',
}, {
title: '数据类型',
dataIndex: 'resourceType',
}, {
title: '令牌',
dataIndex: 'token',
render: (text, record) => text || '--'
}, {
title: '申请时间',
dataIndex: 'applyAt',
render: (text, record) => {
return moment(text).format('YYYY-MM-DD HH:mm:ss');
},
sorter: {
compare: (a, b) => moment(b?.applyAt).valueOf() - moment(a?.applyAt).valueOf(),
// multiple: 2,
},
}, {
title: '审批意见',
dataIndex: 'result',
render: (text, record) => record?.token ? "审批通过" : "审批不通过"
}, {
title: '意见内容',
dataIndex: 'approveRemarks',
render: (text, record) => text || '--'
}, {
title: '审批时间',
dataIndex: 'approveAt',
render: (text, record) => {
return moment(text).format('YYYY-MM-DD HH:mm:ss');
},
sorter: {
compare: (a, b) => moment(b?.approveAt).valueOf() - moment(a?.approveAt).valueOf(),
// multiple: 2,
},
}, {
title: '操作',
dataIndex: 'handle',
// ellipsis: true,
render: (text, record) => <Button type="link" onClick={() => {
setEditData(record)
setApproveModal(true);
}}>审批</Button>
},
];
useEffect(() => {
let data = []
columns?.map(v => {
if (tabsKey == 'stay') {
if (v.dataIndex != 'token'
&& v.dataIndex != 'result'
&& v.dataIndex != 'approveRemarks'
&& v.dataIndex != 'approveAt') {
data?.push(v)
}
} else {
if (v.dataIndex != 'handle') {
data?.push(v)
} }
}
})
setColumn(data)
}, [tabsKey])
return <>
<Tabs defaultActiveKey="stay" items={[{ key: 'stay', label: '待审批' }, { key: 'end', label: '已审批' }]} onTabClick={key => {
setTabsKey(key)
resourceData({ limit: 10, page: 0, approveState: key == 'stay' ? "审批中" : '已审批' })
setQuery({ limit: 10, page: 0 });
}} />
<Form
style={{ display: 'flex' }}
onFinish={v => {
setFormData({ ...v, applyAt: v.applyAt ? moment(v.applyAt).format('YYYY-MM-DD HH:mm:ss') : "" })
resourceData({ limit: 10, page: 0, ...v, applyAt: v.applyAt ? moment(v.applyAt).format('YYYY-MM-DD HH:mm:ss') : "" })
setQuery({ limit: 10, page: 0 });
console.log(v);
}}
autoComplete="off"
>
<Form.Item label="资源名称" name="resourceName" >
<Input allowClear placeholder='资源名称关键字' style={{ width: 200, marginRight: 16 }} />
</Form.Item>
<Form.Item label="申请人" name="applyBy" >
<Input allowClear placeholder='申请人关键字' style={{ width: 140, marginRight: 16 }} />
</Form.Item>
<Form.Item label="申请日期" name="applyAt" >
<DatePicker style={{ width: 140, marginRight: 16 }} />
</Form.Item>
<Form.Item >
<Button type="primary" htmlType="submit"> 查询 </Button>
</Form.Item>
</Form>
export default Approve <Table
columns={column}
dataSource={proTableList?.rows || []}
scroll={{ scrollToFirstRowOnChange: true, y: clientHeight - 260 }}
pagination={{
current: query?.page + 1,
pageSize: query?.limit,
total: proTableList?.count,
showSizeChanger: true,
// showQuickJumper: true,
showTotal: (total) => { return <span style={{ fontSize: 15 }}>{`${Math.ceil(total / query?.limit)}页,${total}`}</span> },
onChange: (page, pageSize) => {
setQuery({ limit: pageSize, page: page - 1 });
resourceData({ limit: pageSize, page: page - 1 });
}
}}
/>
{
approveModal ?
<ApproveModal
editData={editData}
close={() => {
setApproveModal(false);
setEditData({})
}}
success={() => {
resourceData({ limit: 10, page: 0 })
setQuery({ limit: 10, page: 0 });
}}
/> : ""
}
</>
}
function mapStateToProps (state) {
const { global, auth, resourceCatalog } = state;
return {
user: auth.user,
actions: global.actions,
clientHeight: global.clientHeight,
// resourceCatalog: resourceCatalog?.data || [],
// isRequesting: resourceCatalog.isRequesting
};
}
export default connect(mapStateToProps)(Approve)

134
web/client/src/sections/resourceConsumption/containers/myApplication.js

@ -1,7 +1,135 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { connect } from 'react-redux';
import moment from 'moment';
import ApproveModal from '../components/approveModal';
function MyApplication (props) {
return <>我的数据消费申请</> import { Tabs, Form, Input, DatePicker, Button, Table } from 'antd';
import { v1 } from 'uuid';
function MyApplication ({ loading, clientHeight, actions, dispatch, user }) {
const { resourceConsumption } = actions
const [query, setQuery] = useState({ page: 0, limit: 10 });
const [proTableList, setProTableList] = useState({ rows: [], count: 0 });
const [formData, setFormData] = useState({})
useEffect(() => {
resourceData()
}, [])
let resourceData = (params) => {
let data = params || query
dispatch(resourceConsumption.getApproveList({ applyById: user?.id, ...formData, ...data, })).then(res => {
if (res.success) {
setProTableList(res.payload.data)
} }
})
}
export default MyApplication const columns = [{
title: '资源名称',
dataIndex: 'resourceName',
}, {
title: '申请人',
dataIndex: 'applyBy',
render: (text, record) => record?.user?.name
}, {
title: '需求描述',
dataIndex: 'requirements',
}, {
title: '数据类型',
dataIndex: 'resourceType',
}, {
title: '令牌',
dataIndex: 'token',
render: (text, record) => text || '--'
}, {
title: '申请时间',
dataIndex: 'applyAt',
render: (text, record) => text && moment(text).format('YYYY-MM-DD HH:mm:ss') || '--',
sorter: {
compare: (a, b) => moment(b?.applyAt).valueOf() - moment(a?.applyAt).valueOf(),
// multiple: 2,
},
}, {
title: '审批意见',
dataIndex: 'result',
render: (text, record) => record?.approveState == '审批中' ? record?.approveState : record?.approveState == '已审批' ? record?.token ? "审批通过" : "审批不通过" : "--"
}, {
title: '意见内容',
dataIndex: 'approveRemarks',
render: (text, record) => text || '--'
}, {
title: '审批时间',
dataIndex: 'approveAt',
render: (text, record) => text && moment(text).format('YYYY-MM-DD HH:mm:ss') || '--',
sorter: {
compare: (a, b) => moment(b?.approveAt).valueOf() - moment(a?.approveAt).valueOf(),
// multiple: 2,
},
}];
return <>
<Form
style={{ display: 'flex' }}
onFinish={v => {
setFormData({ ...v, applyAt: v.applyAt ? moment(v.applyAt).format('YYYY-MM-DD HH:mm:ss') : "" })
resourceData({ limit: 10, page: 0, ...v, applyAt: v.applyAt ? moment(v.applyAt).format('YYYY-MM-DD HH:mm:ss') : "" })
setQuery({ limit: 10, page: 0 });
console.log(v);
}}
autoComplete="off"
>
<Form.Item label="资源名称" name="resourceName" >
<Input allowClear placeholder='资源名称关键字' style={{ width: 200, marginRight: 16 }} />
</Form.Item>
<Form.Item label="申请人" name="applyBy" >
<Input allowClear placeholder='申请人关键字' style={{ width: 140, marginRight: 16 }} />
</Form.Item>
<Form.Item label="申请日期" name="applyAt" >
<DatePicker style={{ width: 140, marginRight: 16 }} />
</Form.Item>
<Form.Item >
<Button type="primary" htmlType="submit"> 查询 </Button>
</Form.Item>
</Form>
<Table
columns={columns}
dataSource={proTableList?.rows || []}
scroll={{ scrollToFirstRowOnChange: true, y: clientHeight - 260 }}
pagination={{
current: query?.page + 1,
pageSize: query?.limit,
total: proTableList?.count,
showSizeChanger: true,
// showQuickJumper: true,
showTotal: (total) => { return <span style={{ fontSize: 15 }}>{`${Math.ceil(total / query?.limit)}页,${total}`}</span> },
onChange: (page, pageSize) => {
setQuery({ limit: pageSize, page: page - 1 });
resourceData({ limit: pageSize, page: page - 1 });
}
}}
/>
</>
}
function mapStateToProps (state) {
const { global, auth, resourceCatalog } = state;
return {
user: auth.user,
actions: global.actions,
clientHeight: global.clientHeight,
// resourceCatalog: resourceCatalog?.data || [],
// isRequesting: resourceCatalog.isRequesting
};
}
export default connect(mapStateToProps)(MyApplication)

5
web/client/src/utils/webapi.js

@ -73,7 +73,10 @@ export const ApiTable = {
runTask: 'run/acq/task', runTask: 'run/acq/task',
//采集日志 //采集日志
getLogs: "meta/acq/logs" getLogs: "meta/acq/logs",
//资源消费
approveList:'resource/approve'
}; };
export const RouteTable = { export const RouteTable = {

Loading…
Cancel
Save