Commit 7f44678e authored by 前端-钟卫鹏's avatar 前端-钟卫鹏

fix: 锚点抽屉组件嵌入NiceForm表单

parent c5714a56
......@@ -8,6 +8,22 @@
color: #909399;
}
.paneTitle {
margin: 16px 0 16px 0;
font-size: 14px;
font-weight: 500;
color: #909399;
height: 14px;
line-height: 14px;
.longString {
color: #00B37A;
margin-right: 6px;
height: 14px;
line-height: 14px;
font-size: 14px;
font-weight: bolder;
}
}
// 抽屉内部内容样式
......
import React, { ReactNode, useContext, useEffect, useRef, useState } from 'react'
import React, { ReactNode, useCallback, useContext, useEffect, useRef, useState } from 'react'
import { Modal, Drawer, Button, Tabs, Row, Col, Anchor } from 'antd'
import style from './index.less'
import NiceForm from '../NiceForm'
import { IAntdSchemaFormProps, registerVirtualBox } from '@formily/antd'
/**
* 带锚点定位跳转的抽屉 Drawer
......@@ -8,53 +10,76 @@ import style from './index.less'
const { Link } = Anchor
export interface AnchorProps {
/** 源数据 */
export interface AnchorProps extends IAntdSchemaFormProps {
/** 数据源 用于渲染对应的字段值 */
data?: any,
/** 数据项和render渲染函数 */
dataList?: { title: string, name: string, render?(data?), [key: string]: any }[],
/** 数据项和render渲染函数 仅预览功能下使用 */
dataRenderList?: { title: string, name: string, render?(data?: any), [key: string]: any }[],
/** NiceForm表单模式下 锚点定位title和idName列表 此项生效必须isForm属性为true */
dataIdList?: {title: string, idName: string}[],
title?: string,
visible?: boolean,
/** 自定义底部布局 */
footer?: ReactNode,
/** 点击遮罩回调 */
onClose?: any,
/** 是否使用NiceForm表单 */
isForm?: boolean,
}
const AnchorDrawer: React.FC<AnchorProps> = ({
data,
dataList,
dataRenderList = [],
dataIdList = [],
title = "",
visible = false,
footer,
onClose,
isForm = false,
actions,
...restProps
}) => {
const [current, setCurrent] = useState<number>(0)
const [offsetTopList, setOffsetTopList] = useState<number[]>([])
// useEffect(() => {
// if (currentRef) {
// currentRef.current = {
// formActions,
// }
// }
// }, [])
useEffect(() => {
let tempArr: any = []
let floors: any = []
if(visible) {
// 开启滚动事件冒泡
window.addEventListener("scroll", onScroll, true);
// 获取各个子div距父级的高度
let floors = document.querySelectorAll(".drawerContent>div")
let tempArr = []
floors = isForm ? document.querySelectorAll("form.ant-form>div") : document.querySelectorAll(".drawerContent>div")
floors.forEach((floor: any, index: any) => {
tempArr.push(floor.offsetTop)
})
setOffsetTopList(tempArr)
}
/**
* 开启滚动事件冒泡 (传参说明)
* e: 事件对象
* tempArr: 各目标元素距父级顶部距离数组
* floors: 各锚点目标HTML元素
*/
window.addEventListener("scroll", (e?: any) => onScroll(e, tempArr, floors), true);
// @ts-ignore
return () => window.removeEventListener('scroll', onScroll)
}, [visible])
const onScroll = (e) => {
const onScroll = (e?: { target: { className: string } }, arr?: any, floors?: any) => {
if(visible)
if(e.target.className === 'ant-drawer-body') {
let scrollTop = document.querySelectorAll(".ant-drawer-body")[0].scrollTop
let floors = document.querySelectorAll(".drawerContent>div")
floors.forEach((floor: any, index: any) => {
if(floor.offsetTop - 40 <= scrollTop) {
if(arr[index] - 40 <= scrollTop) {
setCurrent(index)
}
})
......@@ -72,6 +97,18 @@ const AnchorDrawer: React.FC<AnchorProps> = ({
}
}
registerVirtualBox("CustomTitle", ({ children, schema }) => {
return (
<div>
<p className={style.paneTitle}>
<span className={style.longString}>|</span>
{schema["x-component-props"]["text"]}
</p>
{children}
</div>
);
});
return (<div id="content">
<Drawer
title={title}
......@@ -88,24 +125,26 @@ const AnchorDrawer: React.FC<AnchorProps> = ({
<div className={style.drawerNav}>
<ul>
{
dataList.map((item, index) => (
isForm
?
dataIdList.map((item, index) => (
<li key={index} onClick={() => handleClick(index)}><a className={current === index ? style.current : null}>{item['title']}</a></li>
)) :
dataRenderList.map((item, index) => (
<li key={index} onClick={() => handleClick(index)}><a className={current === index ? style.current : null}>{item['title']}</a></li>
))
}
</ul>
{/* <Anchor onClick={(e)=>e.preventDefault()} showInkInFixed={false} getContainer={() => document.getElementById("content")}>
{
dataList.map((item, index) => (
<Link href={`#${item['id']}`} title={item['title']} />
))
}
</Anchor> */}
</div>
</Col>
<Col span={18}>
<div className={[style.drawerContent, 'drawerContent'].join(' ')}>
{
dataList.map((item, index) => (
isForm ? (<NiceForm
actions={actions}
{...restProps}
// onSubmit={values => ref.current.reload(values)}
/>) : (dataRenderList.map((item, index) => (
<div className={style.drawerContentItem} id={item['id']} key={index}>
<div className={style.drawerContentTitle}>
<p><span className={style.longString}>|</span>{item['title']}</p>
......@@ -114,7 +153,7 @@ const AnchorDrawer: React.FC<AnchorProps> = ({
{item.render ? item.render(data) : <span>{data[item.name]}</span>}
</div>
</div>
))
)))
}
</div>
</Col>
......
......@@ -359,6 +359,11 @@ a {
}
}
// 重置步骤条顶部边距
.ant-steps-horizontal {
margin-top: 0 !important;
}
// 固定头部
// .ant-layout-header {
// position: fixed;
......
......@@ -637,5 +637,8 @@ export default {
// 采购能力
'menu.procurementAbility': '采购能力',
'menu.procurementAbility.callForBids': '招标',
'menu.procurementAbility.callForBids.callForBidsSearch': '招标查询',
'menu.procurementAbility.purchaseInquiry': '采购询价',
};
import React, { useState, useCallback, useRef, useContext, useEffect, createRef } from 'react';
import { history } from 'umi'
import { Button } from 'antd';
import { Button, Row, Col } from 'antd';
import style from './index.less'
import OrderDetailWrapper from '@/pages/transaction/components/OrderDetailWrapper';
import PreLoading from '@/components/PreLoading';
......@@ -9,12 +9,16 @@ import { BidDetailContext } from '@/pages/procurement/_public/bid/context';
import { useBidDetail } from '@/pages/procurement/_public/bid/effects/useBidDetail';
import BidDetailHeader from '@/pages/procurement/components/bidDetailHeader';
import BidDetailSection from '@/pages/procurement/components/bidDetailSection';
import AnchorDrawer from '@/components/AnchorDrawer';
import { createFormActions } from '@formily/antd';
const formActions = createFormActions();
const ReadySendBidNoticeDetail: React.FC = () => {
const { formContext, id, detailList } = useBidDetail({type: 'purchaseOrder'})
const {data, currentPayInfoId} = formContext
const payRef = useRef<any>({})
const modalRef = useRef<any>({})
const [visible, setVisible] = useState<boolean>(false)
/** 约定好 对应的锚点title和元素id映射 */
// type? 用于区分DescriptionsInfo组件的内容
......@@ -26,6 +30,46 @@ const ReadySendBidNoticeDetail: React.FC = () => {
{ title: '流转记录', id: 'transferRecord', componentName: "BidTransformRecord" },
]
const dataIdList = [
{
title: '中标公示',
idName: 'bidNotice',
},
{
title: '中标通知',
idName: 'bidMessage',
},
{
title: '感谢函',
idName: 'thankLetter',
}
]
const confirmSubmit = () => {
// setVisible(false)
formActions.validate().then((res) => {
console.log(res)
if(res['errors']['length'] === 0) {
formActions.submit(v => console.log(v))
}
})
}
const footer = (<div
style={{
textAlign: 'right',
}}
>
<Button onClick={()=>setVisible(false)} style={{ marginRight: 8 }}>
取消
</Button>
<Button onClick={confirmSubmit} type="primary">
确定
</Button>
</div>)
return (
<div>
<BidDetailContext.Provider value={formContext}>
......@@ -35,7 +79,7 @@ const ReadySendBidNoticeDetail: React.FC = () => {
anchorList={anchorTitleList}
backLink="/memberCenter/procurementAbility/callForBids/callForBidsSearch"
extraRight={
<Button type='primary'>
<Button type='primary' onClick={() => setVisible(true)}>
发送中标公示
</Button>
}
......@@ -46,8 +90,146 @@ const ReadySendBidNoticeDetail: React.FC = () => {
</PreLoading>
</OrderDetailWrapper>
<OrderPayModal
currentRef={payRef}
<AnchorDrawer
title="发送中标公示"
visible={visible}
dataIdList={dataIdList}
footer={footer}
onClose={() => setVisible(false)}
isForm = {true}
actions={formActions}
schema={{
type: 'object',
properties: {
Text_1: {
type: "object",
"x-component": "CustomTitle",
"x-component-props": {
text: "中标公示"
},
properties: {
NO_SUBMIT_LAYOUT_1: {
type: 'object',
"x-component": 'mega-layout',
"x-component-props": {
labelAlign: "top",
full: true
},
properties:{
isSendNotice: {
type: 'string',
"x-component-props": {
children: "发送中标公示"
},
"x-component": "checkboxsingle",
default: true,
readOnly: true,
},
noticeText: {
type: 'textarea',
title: '',
required: true,
'x-component-props': {
placeholder: '请填写中标公示',
rows: 4
}
},
noticeFileList: {
title: '中标公示附件',
'x-component': 'AntUpload',
'x-component-props': {
action: '/api/file/file/upload/prefix',
data: {
fileType: 1,
prefix: '/afterService/returnApplication/',
},
// beforeUpload: '{{beforeUpload}}',
accept: '.xls, .xlsx, .doc, .docx, .wps, .pdf, .jpg, .png, .jpeg',
},
'x-rules': [
{
required: false,
message: '请上传附件',
},
],
// description: '一次上传一个文件,每个附件大小不能超过20M',
},
}
}
}
},
Text_2: {
type: "object",
"x-component": "CustomTitle",
"x-component-props": {
text: "中标通知"
},
properties: {
isSendMessage: {
type: 'string',
"x-component-props": {
children: "发送中标通知"
},
"x-component": "checkboxsingle",
default: false,
},
messageText: {
type: 'textarea',
title: '',
'x-component-props': {
placeholder: '请填写中标通知',
rows: 4
}
},
messageFileList: {
title: '中标通知附件',
'x-component': 'AntUpload',
'x-component-props': {
action: '/api/file/file/upload/prefix',
data: {
fileType: 1,
prefix: '/afterService/returnApplication/',
},
// beforeUpload: '{{beforeUpload}}',
accept: '.xls, .xlsx, .doc, .docx, .wps, .pdf, .jpg, .png, .jpeg',
},
'x-rules': [
{
required: false,
message: '请上传附件',
},
],
// description: '一次上传一个文件,每个附件大小不能超过20M',
},
}
},
Text_3: {
type: "object",
"x-component": "CustomTitle",
"x-component-props": {
text: "感谢信"
},
properties: {
isSendThankLetter: {
type: 'string',
"x-component-props": {
children: "发送感谢信"
},
"x-component": "checkboxsingle",
default: false,
},
thankLetterText: {
type: 'textarea',
title: '',
'x-component-props': {
placeholder: '请填写感谢信',
rows: 4
}
},
}
},
}
}}
/>
</BidDetailContext.Provider>
</div>
......
......@@ -256,7 +256,7 @@ const BidMaterial: React.FC<BidMaterialProps> = ({cardTitle}) => {
<AnchorDrawer
title="物料详情"
visible={visible}
dataList={dataList}
dataRenderList={dataList}
footer={footer}
onClose={() => setVisible(false)}
/>
......
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