Commit 87f9bf0f by fanyj

tijiao

parent 984a5316
......@@ -15,6 +15,7 @@ import AssetManage from './view/Manage/AssetManage';
import AssetBrowse from './view/Manage/AssetBrowse';
import DatasourceManage from './view/Manage/DatasourceManage';
import AssetDetailPage from './view/Manage/AssetManage/Component/AssetDetailPage';
import FlowAcceptDetail from './view/Manage/AssetManage/Component/FlowAcceptDetail';
import ImportAction from './view/Manage/Model/Component/ImportAction';
import EditModel from './view/Manage/Model/Component/EditModel';
import EditTemplate from './view/Manage/ModelConfig/Component/EditTemplate';
......@@ -202,6 +203,7 @@ export class App extends React.Component {
<Route path={`${ContextPath}/model-template-action`} component={EditTemplate} exact />
<Route path={`${ContextPath}/asset-detail`} component={AssetDetailPage} exact />
<Route path={`${ContextPath}/asset-review-detail`} component={AssetReviewDetail} />
<Route path={`${ContextPath}/assetflowdetail`} component={FlowAcceptDetail} />
<Route path={'/center-home/menu/datasource-manage'} component={DatasourceManage} exact />
<Route path={'/center-home/menu/data-model'} component={Model} exact />
......@@ -215,6 +217,7 @@ export class App extends React.Component {
<Route path={'/center-home/data-model-action'} component={EditModel} exact />
<Route path={'/center-home/asset-detail'} component={AssetDetailPage} exact />
<Route path={'/center-home/session/asset-detail'} component={AssetDetailPage} exact />
<Route path={'/center-home/assetflowdetail'} component={FlowAcceptDetail} exact />
<Route path={'/data-govern/spreadjs-view'} component={SpreadjsView} exact />
</Switch>
</Router>
......
.omodel {
position: relative;
.header {
display: flex;
width: 100%;
height: 44px;
padding: 0 15px;
background-color: #464d6e;
align-items: center;
position: fixed;
justify-content: space-between;
border-bottom: 1px solid #EFEFEF;
z-index: 100;
}
.container {
top: 44px;
width: 100%;
height: calc(100vh - 44px - 64px);
overflow: auto;
background: #EDF0F5;
padding: 10px 20px;
position: absolute;
:global{
.ant-table-thead > tr > th {
padding: 8px 8px !important;
}
.ant-table-tbody > tr > td {
padding: 12px 8px !important;
}
.ant-table-tbody > .ant-table-measure-row > td {
padding: 0px !important;
}
.ant-table-tbody > tr .ant-table-row-selected > td {
background: #fff !important;
}
tr.ant-table-expanded-row > td {
background: #fff !important;
}
.ant-table-thead > tr > th {
background-color: #F2F5FC !important;
}
}
}
.containermore {
top: 44px;
width: 100%;
height: calc(100vh - 44px);
overflow: auto;
background: #EDF0F5;
padding: 10px 20px;
position: absolute;
:global{
.ant-table-thead > tr > th {
padding: 8px 8px !important;
}
.ant-table-tbody > tr > td {
padding: 12px 8px !important;
}
.ant-table-tbody > .ant-table-measure-row > td {
padding: 0px !important;
}
.ant-table-tbody > tr .ant-table-row-selected > td {
background: #fff !important;
}
tr.ant-table-expanded-row > td {
background: #fff !important;
}
.ant-table-thead > tr > th {
background-color: #F2F5FC !important;
}
}
}
.containercard {
padding: 20px;
background: #fff;
}
.footer {
display: flex;
bottom: 0;
width: 100%;
height: 64px;
position: fixed;
justify-content: flex-end;
opacity: 0.9;
background: #fff;
box-shadow: 0 -1px 4px 0 #e5e9ea;
padding: 0 20px;
}
}
\ No newline at end of file
import React from "react"
import styles from "./index.module.less"
interface outside{
title:string;
body:any;
footer?:any;
}
const OutSidePanel:React.FC<outside>=(props)=>{
const {title,body,footer} = props
return(
<div className={styles.omodel}>
<div className={styles.header}>
<span style={{ fontSize: 16, fontWeight: 'bold', color: '#fff' }}>{title}</span>
</div>
<div className={footer?styles.container:styles.containermore}>
<div className={styles.containercard}>
{body}
</div>
</div>
{footer&&<div className={styles.footer}>
{footer}
</div>}
</div>
)
}
export default OutSidePanel
\ No newline at end of file
......@@ -24,6 +24,33 @@ class AssetsManageService{
return result;
}
async getProcessDetail(payload={},autotip=false){
let result = await request({ url: `${asset}/takeResponsibilityApi/processDetail`, method: "get", data: payload },autotip).then(data=>{
return data;
}).catch(error=>{
return error
})
return result;
}
async saveQuestionNext(payload={},autotip=false){
let result = await request({ url: `${asset}/takeResponsibilityApi/reDistribute`, method: "post", data: payload },autotip).then(data=>{
return data;
}).catch(error=>{
return error
})
return result;
}
async saveQuestionFinal(payload={},autotip=false){
let result = await request({ url: `${asset}/takeResponsibilityApi/auditProcess`, method: "post", data: payload },autotip).then(data=>{
return data;
}).catch(error=>{
return error
})
return result;
}
}
export default new AssetsManageService()
\ No newline at end of file
......@@ -307,7 +307,8 @@ const List = React.forwardRef(function ({ items }, ref) {
)
})
export const AuditUsersItem = ({ value, onChange }) => {
export const AuditUsersItem = (props) => {
const { value, onChange } = props
const [loading, setLoading] = React.useState(false)
const [options, setOptions] = React.useState()
......
import React,{useState,useEffect,useMemo} from "react"
import {Modal,Spin,Button,Form,Row,Col,Upload,Input,Tooltip,Typography,Table} from "antd"
import {Modal,Spin,Button,Form,Row,Col,Upload,Input,Tooltip,Typography,Table, message} from "antd"
import {UploadOutlined} from "@ant-design/icons"
import { useSetState } from "ahooks"
import { AuditUsersItem,AttachesItem } from "../../AssetDraft/start-flow"
import { showMessage, showNotifaction } from '@/util'
import { dispatch } from '@/model'
......@@ -13,9 +12,6 @@ const AssetFlow:React.FC<any>=(props)=>{
const {visible,onCancel,item} = props
const [uploading, setUploading] = useState(false)
const [tableDatas, setTableData] = React.useState()
const [state,setState] = useSetState({
loading:false
})
const {loading,saveQuestionItem} = useGetFlowAction()
......@@ -39,20 +35,21 @@ const AssetFlow:React.FC<any>=(props)=>{
},[tableData])
const close=()=>{
onCancel?.()
onCancel?.()
form.resetFields()
setTableData(tableData)
}
const save=()=>{
form.validateFields().then((data)=>{
data.submitItems=tableDatas;
saveQuestionItem(data)
saveQuestionItem(data,()=>{
message.success("操作成功")
close()
})
})
}
const onValuesChange=()=>{
}
const uploadProps = {
beforeUpload: file => {
const isLt5M = file.size / 1024 / 1024 <= 100
......@@ -195,13 +192,12 @@ const AssetFlow:React.FC<any>=(props)=>{
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
autoComplete="off"
onValuesChange={onValuesChange}
>
<Row gutter={10}>
<Col span={12}>
<Form.Item
label='评审人员'
name="applyUser"
name="nextAuditUsers"
style={{ marginBottom:15 }}
rules={[{ required: true, message: '请选择评审人员!' }]}
>
......@@ -213,7 +209,7 @@ const AssetFlow:React.FC<any>=(props)=>{
style={{ marginBottom:15 }}
>
<Upload {...uploadProps }>
<Button icon={<UploadOutlined />}>点击上传</Button>
<Button loading={uploading} icon={<UploadOutlined />}>点击上传</Button>
</Upload>
</Form.Item>
......@@ -241,6 +237,7 @@ const AssetFlow:React.FC<any>=(props)=>{
dataSource={tableDatas??[]}
pagination={false}
loading={tableloading}
rowKey="dataAssetId"
/>
</Spin>
</Modal>
......
import OutSidePanel from "@/component/layout/outsidepanel"
import { httpUtil } from "@/utils"
import { Descriptions, Spin, Tag,Table,Tooltip,Typography,Space,Button,Divider,Modal,Form,Input,Timeline } from "antd"
import React,{useMemo,useState,useEffect} from "react"
import { useGetFlowAction, useGetProcessDetail } from "../hooks"
import moment from "moment"
import config from "@/commons"
import { useGetModalInfoAndAction } from "@/hooks/common"
import produce from 'immer'
import { AuditUsersItem } from "../../AssetDraft/start-flow"
import {showMessage} from "@/util"
const {api:{asset}} =config
const FlowAcceptDetail:React.FC<any>=(props)=>{
const {location} = props
const [dataSource,setDataSource] = useState([])
const [form] = Form.useForm()
const {loading,saveQuestionItemFinal,saveQuestionItemNext} = useGetFlowAction()
const processId:string = useMemo(()=>{
return httpUtil.getQueryVariable('processId',location.search)||''
},[location.search])
const {detail,detalLoading} = useGetProcessDetail({processId})
const editmodal = useGetModalInfoAndAction()
useEffect(()=>{
if(detail?.submitItems){
setDataSource(detail.submitItems)
}
},[detail])
const openDetail=(id)=>{
window.open(`${asset}/fileApi/downloadFile?fileId=${id}`)
}
const openEdit=(record:any)=>{
const list = Object.values(record.responsibilityAttributeMap);
editmodal.openModal({listinfo:list},{item:record})
}
const save=(values)=>{
const map = {};
const data = editmodal.item;
const list = Object.values(data.responsibilityAttributeMap);
list.forEach((item:any)=>{
map[item.enName] = {...item,value:values[item.enName]}
})
setDataSource(prev => {
return produce(prev, (draft) => {
const index = dataSource.findIndex((item)=>(item.dataAssetId===data.dataAssetId))
draft[index].responsibilityAttributeMap = map
})
})
editmodal.cancelModal()
}
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}>
{text}
</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: 'path',
width: 120,
render: (text, record) => (
<Tooltip title={text}>
<Typography.Text ellipsis={true}>
{text}
</Typography.Text>
</Tooltip>
)
},
{
title: '待完成属性',
key: 'columns',
dataIndex:'responsibilityAttributeMap',
render: (text, record) => {
const name = Object.values((text||{})).map((item:any)=>{
return `${item.cnName}:${item?.value}`
})
return (
<Tooltip title={name.join(',')}>
<Typography.Text ellipsis={true}>
{name.join(',')}
</Typography.Text>
</Tooltip>
)
}
},
{
title: '操作',
key: 'aciton',
render: (text, record) => {
return (
<Space>
<Button type='link' size='small' style={{ padding: 0 }} onClick={()=>{openEdit(record)}}>编辑</Button>
{/* <Divider type='vertical' style={{margin:0}} />
<Button type='link' size='small' disabled={support} style={{ padding: 0 }} onClick={()=>{dosupport(record,false)}}>反对</Button> */}
</Space>
)
}
},
]
const nextUser=()=>{
form.validateFields().then((data)=>{
if(data?.nextAuditUsers&&data?.nextAuditUsers.length){
const playload = {...detail,...data,submitItems:dataSource}
saveQuestionItemNext(playload,()=>{
showMessage('success','操作成功')
})
}else{
showMessage('info','请选择下一步处理人')
}
})
}
const finishFlow=()=>{
form.validateFields().then((data)=>{
if((data?.nextAuditUsers||[]).length===0){
let allow = true;
dataSource.forEach((item)=>{
Object.values(item.responsibilityAttributeMap).forEach((i:any)=>{
if(!i.value){
allow=false
}
})
})
if(allow){
const playload = {...detail,...data,submitItems:dataSource}
saveQuestionItemFinal(playload,()=>{
showMessage("success",'操作成功')
})
}else{
showMessage('info','请完成待完成项')
}
}else{
showMessage('info',"结束流程不需要下一步处理人")
}
})
}
return(
<OutSidePanel
title="资产认责审批"
body={
<React.Fragment>
<Spin spinning={detalLoading}>
<h2 style={{marginRight:12}}>基本信息</h2>
<Descriptions>
<Descriptions.Item label="创建人">
{`${detail?.applyUser?.userName}(${detail?.applyUser?.userDisplayName})`}
</Descriptions.Item>
<Descriptions.Item label="创建时间">
{detail?.createTimestamp&&moment(detail.createTimestamp).format("YYYY-MM-DD HH:mm:ss")}
</Descriptions.Item>
<Descriptions.Item label="附件">
{
(detail?.attachments||[]).map((item:any)=>{
return <Tag color="blue" style={{cursor:'pointer'}} onClick={()=>{openDetail(item.fileId)}} >{item?.fileName}</Tag>
})
}
</Descriptions.Item>
</Descriptions>
<h2 style={{marginRight:12,marginTop:10}}>问责数据</h2>
<Table
columns={cols??[]}
dataSource={dataSource??[]}
pagination={false}
rowKey="dataAssetId"
/>
<h2 style={{marginRight:12,marginTop:20,marginBottom:20}}>审批意见列表</h2>
<Timeline>
{
(detail?.processInfos||[]).map((item:any,key:number)=>{
return(
<Timeline.Item key={key}>
<p>{`${item.userName}(${item.userDisplayName})`}<span style={{marginLeft:10}}>{item.auditTimestamp&&moment(item.auditTimestamp).format("YYYY-MM-DD HH:mm:ss")}</span></p>
<p>审批意见:{item.opinion}</p>
</Timeline.Item>
)
})
}
</Timeline>
<h2 style={{marginRight:12,marginTop:20,marginBottom:20}}>我的答复</h2>
<Form form={form} layout="vertical">
<Form.Item
label='答复内容'
name="opinion"
rules={[{ required: true, message: '必填项!' }]}
>
<Input.TextArea
placeholder="请输入审批已经"
autoSize={{minRows:3,maxRows:6}}
/>
</Form.Item>
<Form.Item
label='下一步处理人'
name="nextAuditUsers"
style={{ marginBottom:15 }}
rules={[{ required: false, message: '请选择评审人员!' }]}
>
<AuditUsersItem />
</Form.Item>
</Form>
</Spin>
<DynamicFormModal visible={editmodal.visible} onSubmit={save} onCancel={()=>{editmodal.cancelModal()}} list={editmodal.currentItem} />
</React.Fragment>
}
footer={
<div style={{display:'flex',justifyContent:'center',width:'100%'}}>
<Space>
<Button loading={loading} onClick={nextUser} type="primary">转分配</Button>
<Button loading={loading} onClick={finishFlow} type="primary">保存</Button>
</Space>
</div>
}
/>
)
}
export default FlowAcceptDetail
const DynamicFormModal: React.FC<{ visible: boolean; list: any; onCancel: () => void; onSubmit: (values: any) => void }> = ({
visible,
list,
onCancel,
onSubmit,
}) => {
const [form] = Form.useForm();
const {listinfo} = list
return (
<Modal
visible={visible}
title="补全信息"
onCancel={onCancel}
onOk={() => {
form
.validateFields()
.then((values) => {
onSubmit(values);
form.resetFields();
})
.catch((info) => {
console.log('Validate Failed:', info);
});
}}
>
<Form form={form} layout="vertical">
{(listinfo||[]).map((item) => (
<Form.Item
key={item.enName}
name={item.enName}
label={item.cnName}
rules={[{ required: true, message: '必填项!' }]}
>
{item.component || <Input />}
</Form.Item>
))}
</Form>
</Modal>
);
};
\ No newline at end of file
......@@ -34,12 +34,12 @@ export const useGetAssetQuestion = (props) => {
export const useGetFlowAction = () => {
const [loading, setLoading] = useState<boolean>(false);
const saveQuestionItem = useCallback(async (params: any)=>{
const saveQuestionItem = useCallback(async (params: any,callback?:any)=>{
try {
setLoading(true);
const response: any = await assetsManageService.saveQuestionItem(params);
if (httpUtil.checkSuccess(response, 1)) {
return response.data;
callback?.()
} else {
httpUtil.showError(response, 1);
}
......@@ -48,5 +48,59 @@ export const useGetFlowAction = () => {
}
},[])
return { saveQuestionItem, loading };
const saveQuestionItemNext = useCallback(async (params: any,callback?:any)=>{
try {
setLoading(true);
const response: any = await assetsManageService.saveQuestionNext(params);
if (httpUtil.checkSuccess(response, 1)) {
callback?.()
} else {
httpUtil.showError(response, 1);
}
} finally {
setLoading(false);
}
},[])
const saveQuestionItemFinal = useCallback(async (params: any,callback?:any)=>{
try {
setLoading(true);
const response: any = await assetsManageService.saveQuestionFinal(params);
if (httpUtil.checkSuccess(response, 1)) {
callback?.()
} else {
httpUtil.showError(response, 1);
}
} finally {
setLoading(false);
}
},[])
return { saveQuestionItem, loading,saveQuestionItemNext,saveQuestionItemFinal };
};
export const useGetProcessDetail = (props: {processId: string}) => {
const {processId} = props;
const [detail, setDetail] = useState<any>(null);
const [loading, setLoading] = useState<boolean>(false);
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const response: any = await assetsManageService.getProcessDetail({processId});
if (httpUtil.checkSuccess(response, 1)) {
setDetail(response.data);
} else {
httpUtil.showError(response, 1);
}
} finally {
setLoading(false);
}
};
if(processId)
fetchData();
}, [processId]);
return { detail, detalLoading:loading };
};
\ 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