Commit 0988d5b1 by zhaochengxiang

资产送审

parent 987d6449
...@@ -548,4 +548,16 @@ export function* getPrivilegeByRange(payload) { ...@@ -548,4 +548,16 @@ export function* getPrivilegeByRange(payload) {
export function* getPrivilegeByRangeAndDirId(payload) { export function* getPrivilegeByRangeAndDirId(payload) {
return yield call(service.getPrivilegeByRangeAndDirId, payload); return yield call(service.getPrivilegeByRangeAndDirId, payload);
}
export function* submitForAudit(payload) {
return yield call(service.submitForAudit, payload);
}
export function* listSubmitForAuditAssetsInfo(payload) {
return yield call(service.listSubmitForAuditAssetsInfo, payload);
}
export function* uploadAttachment(payload) {
return yield call(service.uploadAttachment, payload);
} }
\ No newline at end of file
...@@ -555,4 +555,16 @@ export function getPrivilegeByRange(payload) { ...@@ -555,4 +555,16 @@ export function getPrivilegeByRange(payload) {
export function getPrivilegeByRangeAndDirId(payload) { export function getPrivilegeByRangeAndDirId(payload) {
return GetJSON("/dataassetmanager/AuthorityApi/listAllowButtonsByRangeAndOptionId", payload); return GetJSON("/dataassetmanager/AuthorityApi/listAllowButtonsByRangeAndOptionId", payload);
}
export function submitForAudit(payload) {
return PostJSON("/dataassetmanager/flowApi/submitForAudit", payload)
}
export function listSubmitForAuditAssetsInfo(payload) {
return GetJSON("/dataassetmanager/flowApi/listSubmitForAuditAssetsInfo", payload)
}
export function uploadAttachment(payload) {
return PostFile("/dataassetmanager/fileApi/uploadAttachment", payload)
} }
\ No newline at end of file
...@@ -15,6 +15,7 @@ import ImportAsset from "./import" ...@@ -15,6 +15,7 @@ import ImportAsset from "./import"
import DistributeTask from './distribute-task' import DistributeTask from './distribute-task'
import RedistributeTask from './redistribute-task' import RedistributeTask from './redistribute-task'
import PermissionButton from '../../../util/Component/PermissionButton' import PermissionButton from '../../../util/Component/PermissionButton'
import StartFlow from './start-flow'
// const specialCol = ['数据关键用户', '业务数据owner', 'it责任人', '创建人', '更新人'] // const specialCol = ['数据关键用户', '业务数据owner', 'it责任人', '创建人', '更新人']
const specialCol = ['创建人', '更新人'] const specialCol = ['创建人', '更新人']
...@@ -80,6 +81,10 @@ const FC = (props) => { ...@@ -80,6 +81,10 @@ const FC = (props) => {
visible: false, visible: false,
items: undefined items: undefined
}) })
const [startFlowParams, setStartFlowParams] = React.useState({
visible: false,
ids: undefined
})
const [rightRow, setRightRow] = React.useState() const [rightRow, setRightRow] = React.useState()
const [modal, contextHolder] = Modal.useModal(); const [modal, contextHolder] = Modal.useModal();
...@@ -104,14 +109,16 @@ const FC = (props) => { ...@@ -104,14 +109,16 @@ const FC = (props) => {
} }
}, [currentTemplateValue, keyword, currentElementValue, pagination, isAdmin, draftState], { wait: 300 }) }, [currentTemplateValue, keyword, currentElementValue, pagination, isAdmin, draftState], { wait: 300 })
const [canExport, canPublish, canDelete] = React.useMemo(() => { const [canExport, canPublish, canDelete, canFlow] = React.useMemo(() => {
if ((selectedRows??[]).length === 0) return [false, false] if ((selectedRows??[]).length === 0) return [false, false, false, false]
let [_canExport, _canPublish, _canDelete] = [true, true, true] let [_canExport, _canPublish, _canDelete, _canFlow] = [true, true, true, true]
for (const item of (selectedRows??[])) { for (const item of (selectedRows??[])) {
const exportIndex = (item.allowButtons??[]).findIndex(item => item==='export') const exportIndex = (item.allowButtons??[]).findIndex(item => item==='export')
const publishIndex = (item.allowButtons??[]).findIndex(item => item==='publish') const publishIndex = (item.allowButtons??[]).findIndex(item => item==='publish')
const deleteIndex = (item.allowButtons??[]).findIndex(item => item==='delete') const deleteIndex = (item.allowButtons??[]).findIndex(item => item==='delete')
const flowIndex = (item.allowButtons??[]).findIndex(item => item==='flowSubmitForAudit')
if (exportIndex === -1) { if (exportIndex === -1) {
_canExport = false _canExport = false
} }
...@@ -121,9 +128,12 @@ const FC = (props) => { ...@@ -121,9 +128,12 @@ const FC = (props) => {
if (deleteIndex === -1) { if (deleteIndex === -1) {
_canDelete = false _canDelete = false
} }
if (flowIndex === -1) {
_canFlow = false
}
} }
return [_canExport, _canPublish, _canDelete] return [_canExport, _canPublish, _canDelete, _canFlow]
}, [selectedRows]) }, [selectedRows])
const menuData = React.useMemo(() => { const menuData = React.useMemo(() => {
...@@ -404,6 +414,13 @@ const FC = (props) => { ...@@ -404,6 +414,13 @@ const FC = (props) => {
window.open(`/api/dataassetmanager/draftApi/exportByDraftIds?draftIds=${(selectedRows??[]).map(item => item.id).toString()}&templateType=${currentTemplateValue}`); window.open(`/api/dataassetmanager/draftApi/exportByDraftIds?draftIds=${(selectedRows??[]).map(item => item.id).toString()}&templateType=${currentTemplateValue}`);
} }
const onFlowClick = () => {
setStartFlowParams({
visible: true,
ids: (selectedRows??[]).map(item => item.id)
})
}
const onPublishClick = () => { const onPublishClick = () => {
if (isAdmin) { if (isAdmin) {
modal.confirm({ modal.confirm({
...@@ -571,6 +588,15 @@ const FC = (props) => { ...@@ -571,6 +588,15 @@ const FC = (props) => {
</PermissionButton> </PermissionButton>
<PermissionButton <PermissionButton
defaultPermission={canFlow}
tip={(selectedRows||[]).length===0?'请先选择资产':''}
onClick={onFlowClick}
disabled={(selectedRows||[]).length===0}
>
送审
</PermissionButton>
<PermissionButton
defaultPermission={canPublish} defaultPermission={canPublish}
tip={(selectedRows||[]).length===0?'请先选择资产':''} tip={(selectedRows||[]).length===0?'请先选择资产':''}
onClick={onPublishClick} onClick={onPublishClick}
...@@ -739,6 +765,17 @@ const FC = (props) => { ...@@ -739,6 +765,17 @@ const FC = (props) => {
refresh && getDrafts() refresh && getDrafts()
}} }}
/> />
<StartFlow
{...startFlowParams}
onCancel={(refresh) => {
setStartFlowParams({
visible: false,
ids: undefined
})
refresh && getDrafts()
}}
/>
{contextHolder} {contextHolder}
</div> </div>
) )
......
import React from 'react'
import { Modal, Button, Spin, Form, Input, Select, Space, Radio, Row, Col, Upload, Typography, Tooltip } from 'antd'
import { UploadOutlined } from '@ant-design/icons'
import { useDebounceEffect } from 'ahooks'
import produce from 'immer'
import { showMessage, showNotifaction } from '../../../util'
import Table from '../../../util/Component/Table'
import { dispatch } from '../../../model'
const FC = (props) => {
const { visible, ids, onCancel } = props
const [loading, setLoading] = React.useState(false)
const [waiting, setWaiting] = React.useState(false)
const [items, setItems] = React.useState()
const basicRef = React.useRef()
const listRef = React.useRef()
React.useEffect(() => {
if (visible && (ids??[]).length > 0) {
getItems()
}
}, [visible, ids])
const getItems = () => {
setLoading(true)
dispatch({
type: 'assetmanage.listSubmitForAuditAssetsInfo',
payload: {
draftIds: (ids??[]).toString(),
},
callback: data => {
setLoading(false)
setItems(data)
},
error: () => {
setLoading(false)
}
})
}
const close = (refresh = false) => {
setWaiting(false)
onCancel?.(refresh)
}
const save = async () => {
try {
const basicRows = await basicRef.current?.validate()
const tableData = listRef.current?.tableData
if (basicRef.current?.uploading) {
showMessage('warn', '文件上传中,请稍后')
return
}
console.log('basic rows', basicRows)
console.log('table data', tableData)
setWaiting(true)
dispatch({
type: 'assetmanage.submitForAudit',
payload: {
data: {
...basicRows,
submitItems: tableData,
},
},
callback: (data) => {
if (data) {
showNotifaction('送审提示', data, 5);
}
close(true)
},
error: () => {
setWaiting(false)
}
})
} catch (e) {
}
}
const footer = React.useMemo(() => {
return [
<Button key={'cancel'}
onClick={() => close()}
>取消</Button>,
<Button key={'save'} type='primary'
disabled={waiting}
onClick={() => save()}
>保存</Button>
]
}, [close, save, waiting])
return (
<Modal
visible={visible}
footer={footer}
width='80%'
bodyStyle={{ padding: '15px', overflowX: 'auto', height: '80vh' }}
title='模型送审'
centered destroyOnClose
onCancel={() => { close() }}
>
<Spin spinning={loading||waiting}>
<Basic ref={basicRef} />
<List ref={listRef} items={items} />
</Spin>
</Modal>
)
}
export default FC
const Basic = React.forwardRef(function ({}, ref) {
const [uploading, setUploading] = React.useState(false)
const [form] = Form.useForm()
React.useImperativeHandle(ref, () => ({
validate: async () => {
return await form.validateFields()
},
uploading,
}), [form, uploading])
const marginBottom = React.useMemo(() => {
return 15
}, [])
const onValuesChange = (changedValues, allValues) => {
}
const uploadProps = {
beforeUpload: file => {
const isLt5M = file.size / 1024 / 1024 <= 100
if (!isLt5M) {
showMessage('error', '上传文件限制最大100M')
return false
}
setUploading(true)
dispatch({
type: 'assetmanage.uploadAttachment',
payload: {
fileList: [file],
},
callback: (data) => {
setUploading(false)
const prev = form?.getFieldValue('attachments')
const newFileList = [...prev??[], data]
form?.setFieldsValue({ attachments: newFileList })
},
error: () => {
setUploading(false)
}
})
return false
},
fileList: [],
}
return (
<Form
form={form}
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
autoComplete="off"
onValuesChange={onValuesChange}
>
<Row gutter={10}>
<Col span={12}>
<Form.Item
label='评审人员'
name="nextAuditUsers"
style={{ marginBottom }}
rules={[{ required: true, message: '请选择评审人员!' }]}
>
<AuditUsersItem />
</Form.Item>
<Form.Item
label='附件'
style={{ marginBottom }}
>
<Upload {...uploadProps }>
<Button icon={<UploadOutlined />}>点击上传</Button>
</Upload>
</Form.Item>
<Form.Item
label='已上传附件'
name='attachments'
>
<AttachesItem />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label='送审说明'
name="desc"
style={{ marginBottom }}
rules={[{ required: true, message: '请填写送审说明!' }]}
>
<Input.TextArea rows={4} placeholder='请输入送审说明' />
</Form.Item>
</Col>
</Row>
</Form>
)
})
const List = React.forwardRef(function ({ items }, ref) {
const [tableData, setTableData] = React.useState()
React.useImperativeHandle(ref, () => ({
tableData,
}), [tableData])
React.useEffect(() => {
setTableData(items)
}, [items])
const cols = [
{
title: '序号',
dataIndex: 'index',
width:60,
render:(_, __, index)=> (index+1)
},
{
title: '资产名称',
dataIndex: 'enName',
width: 160,
render: (text, record) => (
<Tooltip title={text}>
<Typography.Text ellipsis={true}>
<a onClick={() => {
}}>{text}</a>
</Typography.Text>
</Tooltip>
)
},
{
title: '中文名称',
dataIndex: 'cnName',
width: 160,
render: (text, record) => (
<Tooltip title={text}>
<Typography.Text ellipsis={true}>
{text}
</Typography.Text>
</Tooltip>
)
},
{
title: '编码',
dataIndex: ' code',
width: 160,
render: (text, record) => (
<Tooltip title={text}>
<Typography.Text ellipsis={true}>
{text}
</Typography.Text>
</Tooltip>
)
},
{
title: '备注信息',
dataIndex: 'remarks',
render: (text, record) => (
<Tooltip title={text}>
<Typography.Text ellipsis={true}>
{text}
</Typography.Text>
</Tooltip>
)
},
{
title: '路径',
dataIndex: 'path',
width: 120,
ellipsis: false,
render: (text, record) => (
<Tooltip title={text}>
<Typography.Text ellipsis={true}>
{text}
</Typography.Text>
</Tooltip>
)
},
{
title: '送审备注',
dataIndex: 'auditMsg',
render: (_, __, index) => (
<Input.TextArea rows={1}
autoSize={{ minRows: 1, maxRows: 3 }}
allowClear
onChange={(e) => {
setTableData(prev => {
return produce(prev, (draft) => {
draft[index].auditMsg = e.target.value
})
})
}}
/>
)
},
]
return (
<Table
columns={cols??[]}
dataSource={tableData??[]}
pagination={false}
/>
)
})
const AuditUsersItem = ({ value, onChange }) => {
const [loading, setLoading] = React.useState(false)
const [options, setOptions] = React.useState()
React.useEffect(() => {
getUsers()
}, [])
const getUsers = () => {
setLoading(true)
dispatch({
type: 'user.getUsers',
callback: data => {
setLoading(false)
setOptions(
(data??[]).map(item => ({
label: `${item.dname}(${item.name})`,
value: item.id,
userDisplayName: item.dname,
userId: item.id,
userName: item.name,
}))
)
},
error: () => {
setLoading(false)
}
})
}
return (
<Select mode='multiple' allowClear
placeholder='请选择评审人员'
value={value?.map(item => item.userId)}
filterOption={true}
options={options??[]}
optionFilterProp='label'
notFoundContent={loading ? <Spin size="small" /> : null}
onChange={(val) => {
onChange?.(
(options??[])
.filter(item => (val??[]).indexOf(item.value)!==-1)
)
}}
/>
)
}
export const AttachesItem = ({ value, onChange, readOnly }) => {
return (
<Row>
{
value?.map((item, index) => {
return (
<Col key={index} span={24} style={{ lineHeight: '32px' }}>
<Row>
<Col span={readOnly?24:12}>
{item.fileName}
</Col>
{
!readOnly && <Col span={4}>
<Button
size='small'
type='danger'
onClick={() => {
const newValue = [...value]
newValue.splice(index, 1)
onChange?.(newValue)
}}
>删除</Button>
</Col>
}
</Row>
</Col>
)
})
}
</Row>
)
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment