Commit 02339e87 authored by 前端-李俊鑫's avatar 前端-李俊鑫

feat: 新增规则引擎配置

parent 4bfe58ae
......@@ -18,5 +18,6 @@ module.exports = [
{ name: 'MessageV2', token: '7fc4a903c8ce9318fe925b1d95a39a42d7df4ba8d88df2b1260b714e24ab0db8', categoryIds: [0], }, // 消息中心v2
{ name: 'MarketingV2', token: '0b705237f97ac68774bfcbbcbeaaf2a8f2c9381c42f6d5d0eaee219ef041701b', categoryIds: [0], }, // 营销能力
{ name: 'AfterServiceV2', token: '906dfe7bb2cb64b40c45cd9ccc8e7bab09003779e8103be2c7bd11a1ba9dcbb9', categoryIds: [0], }, // 售后能力V2
{ name: 'ManageV2', token: 'b4a98fa71fa56ff34161166e714621810455c790e64f407f8788ef69cdafe234', categoryIds: [0] }, // 平台后台v2 // 平台后台v2
{ name: 'ManageV2', token: '9ed658e616fbc3d317fdbbbaeb16c2f21613903f13787745c460358c41a438ae', categoryIds: [0] }, // 平台后台v2
{ name: 'RuleEngineV2', token: '4fb3cff10950aa9c237a6797e01a8ca4c9f339004efca915ecef5f96989c2519', categoryIds: [0] }, // 规则引擎服务v2
]
......@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'
import { Select, SelectProps } from 'antd'
export interface PropsType<VT> extends SelectProps<VT> {
requestApi: Function
requestApi?: Function
params?: Object
labelKey?: string
valueKey?: string
......
......@@ -5,7 +5,7 @@ export const formItemLayout = {
export enum STATUS {
Effective = 1, // 有效
invalid = 2, // 无效
invalid = 0, // 无效
}
/**
......
import React, { useRef, useState, useCallback, forwardRef, memo } from 'react'
import { Form } from 'antd'
import StandardTable from '@/components/StandardTable'
import { ColumnType } from 'antd/lib/table'
import NiceForm from '@/components/NiceForm'
import { createFormActions } from '@formily/antd'
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch'
import { FORM_FILTER_PATH } from '@/formSchema/const'
import { schema } from './schema'
import React, { useRef, useState, useCallback, forwardRef, memo, useEffect, useImperativeHandle } from 'react'
import { Tree } from 'antd'
import CommonDrawer from '../CommonDrawer'
import { getOrderDeliveryNoticeOrderVendorPage } from '@/services/OrderNewV2Api'
import { getProductPlatformGetCategoryTree } from '@/services/ProductV2Api'
interface PropsType {
onOk?: () => void
onOk?: (values: any) => void
fieldCode?: string
selectCache?: any[]
}
const ConfigDrawer = (props: PropsType, ref) => {
const [form] = Form.useForm()
const formActions = createFormActions()
const { onOk } = props
const CategoryDrawer = (props: PropsType, ref) => {
const { onOk, fieldCode, selectCache } = props
const tableRef = useRef<any>({})
const [categoryTree, setCategoryTree] = useState<any[]>([])
const [checkedKeys, setCheckedKeys] = useState<any[]>([])
const drawRef = useRef<any>()
const handleOk = useCallback(() => {
form.validateFields().then((values) => {
onOk?.()
})
}, [])
onOk?.(checkedKeys.map(item => ({ id: item.id, value: item[fieldCode] })))
}, [checkedKeys])
const handleShow = useCallback((params: Object) => {
}, [])
const fetchData = (params: any) => {
return new Promise((resolve) => {
getOrderDeliveryNoticeOrderVendorPage(params).then(({ code, data }) => {
if (code === 1000) {
resolve(data)
const getCategoryTree = async () => {
const { code, data } = await getProductPlatformGetCategoryTree()
if (code === 1000) {
setCategoryTree(data)
}
}
const _onCheck = (checked: string[], e: any) => {
const newChecks = e.checkedNodes.flatMap(item => !!item.children.length ? [] : [item])
setCheckedKeys(newChecks)
}
const checkAbleCategoryTree = () => {
const newTree = JSON.parse(JSON.stringify(categoryTree))
function delTree(tree, delItem) {
if (delItem) {
if (delItem.children.length) {
delItem.children.forEach(item => {
delTree(tree, item)
})
} else {
if(selectCache.includes(delItem.id)) {
delItem.disableCheckbox = true
}
}
})
}
}
newTree.forEach(item => {
delTree(newTree, item)
})
return newTree
}
const columns: ColumnType<any>[] = [
{
title: '通知单号',
dataIndex: 'noticeNo',
key: 'noticeNo',
width: 160,
useImperativeHandle(ref, () => ({
show(flag: boolean, params = {}, data) {
drawRef?.current?.show(flag, params)
if (data) {
setCheckedKeys(data?.selectData || [])
}
},
{ title: '通知单摘要', dataIndex: 'digest', key: 'digest' },
{ title: '送货日期', dataIndex: 'deliveryTime', key: 'deliveryTime' },
{ title: '采购会员', dataIndex: 'memberName', key: 'memberName' },
{ title: '单据时间', dataIndex: 'createTime', key: 'createTime' },
]
setKeys(keys: any[]) {
setCheckedKeys(keys)
}
}))
useEffect(() => {
getCategoryTree()
}, [])
return (
<CommonDrawer
ref={ref}
title='编辑'
width={400}
ref={drawRef}
title='选择品类'
width={600}
onOk={handleOk}
onCancel={() => {}}
onShow={handleShow}
destroyOnClose
>
<StandardTable
currentRef={tableRef}
columns={columns}
tableProps={{ rowKey: 'id', }}
fetchTableData={(params: unknown) => fetchData(params)}
controlRender={
<NiceForm
actions={formActions}
onSubmit={values => ref.current.reload(values)}
effects={($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'noticeNo',
FORM_FILTER_PATH,
)
}}
schema={schema}
/>
}
<Tree
checkable={true}
onCheck={_onCheck}
treeData={checkAbleCategoryTree()}
blockNode={true}
checkedKeys={checkedKeys.map(item => item.id)}
fieldNames={{ key: 'id' }}
/>
</CommonDrawer>
)
}
export default memo(forwardRef(ConfigDrawer))
export default memo(forwardRef(CategoryDrawer))
import { ISchema } from '@formily/antd'
import { FORM_FILTER_PATH } from '@/formSchema/const'
export const schema: ISchema = {
type: 'object',
properties: {
mageLayout: {
type: 'object',
'x-component': 'mega-layout',
properties: {
topLayout: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
className: 'useMegaStart'
},
properties: {
noticeNo: {
type: 'string',
'x-component': 'Search',
'x-component-props': {
allowClear: true,
placeholder: '请输入通知单号查询'
},
},
},
},
[FORM_FILTER_PATH]: {
type: 'object',
'x-component': 'flex-layout',
'x-component-props': {
rowStyle: {
flexWrap: 'nowrap',
justifyContent: 'flex-start'
},
colStyle: {
marginRight: 20,
},
},
properties: {
digest: {
type: 'string',
'x-component-props': {
allowClear: true,
placeholder: '通知单摘要'
}
},
'[startDate, endDate]': {
type: 'daterange',
'x-component-props': {
allowClear: true,
placeholder: ['送货开始日期', '送货结束日期'],
},
},
memberName: {
type: 'string',
'x-component-props': {
allowClear: true,
placeholder: '采购会员'
}
},
submit: {
'x-component': 'Submit',
'x-mega-props': {
span: 1,
},
'x-component-props': {
children: '查询',
},
},
}
}
}
}
}
}
......@@ -3,7 +3,7 @@ import { Drawer, Space, Button, DrawerProps } from 'antd'
import styles from './index.less'
export type HandleType = {
show: (flag?: boolean, params?: Object) => void;
show: (flag?: boolean, params?: any) => void;
}
interface PropsType extends DrawerProps {
......@@ -12,23 +12,24 @@ interface PropsType extends DrawerProps {
onCancel?: () => void
cancelText?: string
children?: React.ReactNode
onShow?: (params: Object) => void
onShow?: (params: any, flag?: boolean) => void
specialFooter?: React.ReactNode
confirmLoading?: boolean
}
const CommonDrawer = (props: PropsType, ref: any) => {
const { onOk, onCancel, onShow, okText = '确定', cancelText = '取消', specialFooter, children, ...rest } = props
const { onOk, onCancel, onShow, okText = '确定', cancelText = '取消', specialFooter, children, confirmLoading, ...rest } = props
const [visible, setVisible] = useState<boolean>(false)
console.log('confirmLoading', confirmLoading)
const _onCancel = () => {
setVisible(false)
onCancel?.()
}
useImperativeHandle(ref, () => ({
show(flag = true, params = {}) {
show(flag, params = {}) {
setVisible(flag)
onShow?.(params)
onShow?.(params, flag)
}
}))
......@@ -43,7 +44,7 @@ const CommonDrawer = (props: PropsType, ref: any) => {
<div style={{ textAlign: 'right' }}>
<Space size={12} >
{ onCancel && <Button onClick={_onCancel}>{cancelText}</Button> }
{ onOk && <Button type="primary" onClick={onOk}>{okText}</Button> }
{ onOk && <Button type="primary" onClick={onOk} loading={confirmLoading}>{okText}</Button> }
</Space>
</div>
</div>
......
import React from 'react'
interface PropsType {
onChange?: (val: any) => void
value?: any
valueType?: 'string' | 'number' | 'array'
children?: React.ReactNode
}
const CommonValue = (props: PropsType) => {
const { onChange, value, children, valueType = 'string' } = props
const _handleValue = (val) => {
if (Array.isArray(val)) {
return val
}
return [{ value: val }]
}
const _onChange = (val) => {
const newValue = _handleValue(val)
onChange?.(newValue)
}
return (
<div>
{
children && React.Children.map(children, (child: any) => {
return React.cloneElement(child, {
value: valueType === 'array' ? value : value?.value,
onChange: _onChange
});
})
}
</div>
)
}
export default CommonValue
import React, { useState, forwardRef, memo, useCallback } from 'react'
import React, { useState, forwardRef, memo, useCallback, useRef } from 'react'
import { Form } from 'antd'
import CommonDrawer from '../CommonDrawer'
import ProcessRules from '../ProcessRules'
import { getRuleEngineProcessRuleConfigGetProcessRuleConfig, postRuleEngineConfigBatchSaveOrUpdate } from '@/services/RuleEngineV2Api'
interface PropsType {
onChange?: () => void
......@@ -11,17 +12,62 @@ const ConfigDrawer = (props: PropsType, ref) => {
const [form] = Form.useForm()
const { onChange } = props
const [filedTypeOptions, setFiledTypeOptions] = useState<any[]>([])
const [loading, setLoading] = useState<boolean>(false)
const paramsRef = useRef<any>({})
// 获取字段类型下拉数据
const getFiledTypeData = async (params: any) => {
const { code, data } = await getRuleEngineProcessRuleConfigGetProcessRuleConfig(params)
if (code === 1000) {
// Select组件options参数字段不支持驼峰法,这里处理一下
const newData = data.map(({ selectContent, ...rest }) => ({ ...rest, select_content: selectContent }))
setFiledTypeOptions(newData)
}
}
const handleOk = useCallback(() => {
form.validateFields().then((values) => {
onChange?.()
const { id, ruleEngineConfigFieldRelations } = values
const params = {
...paramsRef.current,
id,
ruleEngineConfigFieldRelations: ruleEngineConfigFieldRelations?.map(item => {
let temp = item.ruleEngineConfigFields || []
let ruleEngineConfigFields: any[] = temp?.filter(i => !['', undefined, null].includes(i.value))
return {
...item,
ruleEngineConfigFields: ruleEngineConfigFields.length ? ruleEngineConfigFields : undefined
}
})
}
console.log('params', params)
setLoading(true)
postRuleEngineConfigBatchSaveOrUpdate(params).then(({ code }) => {
if (code === 1000) {
onChange?.()
ref.current.show(false)
}
}).finally(() => {
setLoading(false)
})
})
}, [])
}, [loading])
const handleCancel = useCallback(() => {
onChange?.()
}, [])
const handleShow = useCallback((params: Object) => {
const handleShow = useCallback(async ({ process, formData }: any, flag: boolean) => {
if (flag) {
form.resetFields()
paramsRef.current = process
await getFiledTypeData({ processId: process?.processId, processStep: process?.processStep })
console.log('formData', formData)
formData && form.setFieldsValue(formData)
}
}, [])
return (
......@@ -32,8 +78,13 @@ const ConfigDrawer = (props: PropsType, ref) => {
onOk={handleOk}
onCancel={handleCancel}
onShow={handleShow}
confirmLoading={loading}
destroyOnClose
>
<ProcessRules form={form}/>
<ProcessRules
form={form}
filedTypeOptions={filedTypeOptions}
/>
</CommonDrawer>
)
}
......
......@@ -4,7 +4,8 @@ import styles from './index.less'
export type FlowChartOptionsType = {
label: string,
value: string | number
value: string | number,
other?: any
}
export type RefHandleType = {
......@@ -14,7 +15,8 @@ export type RefHandleType = {
type PropsType = {
children?: React.ReactNode
options?: FlowChartOptionsType[]
onChange?: (value: string | number) => void
onChange?: (value: string | number, item?: any) => void
fieldNames?: { label?: string, value?: string }
}
type ItemPropsType = {
......@@ -25,12 +27,12 @@ type ItemPropsType = {
value?: string | number
}
const FlowChart = ({ children, options, onChange }: PropsType, ref) => {
const FlowChart = ({ children, options, onChange, fieldNames = { label: 'label', value: 'value' } }: PropsType, ref) => {
const [activeValue, setActiveValue] = useState<string | number>()
const onItemChange = (value: string | number) => {
const onItemChange = (value: string | number, item?: any) => {
setActiveValue(value)
onChange?.(value)
onChange?.(value, item)
}
useImperativeHandle(ref, () => ({
......@@ -46,18 +48,18 @@ const FlowChart = ({ children, options, onChange }: PropsType, ref) => {
options ?
options.map(item => (
<FlowChartItem
key={item.value}
active={item.value === activeValue}
onClick={() => { onItemChange(item.value) }}
key={item[fieldNames.value]}
active={item[fieldNames.value] === activeValue}
onClick={() => { onItemChange?.(item[fieldNames.value], item) }}
>
{item.label}
{item[fieldNames.label]}
</FlowChartItem>
))
:
children && React.Children.map(children, (child: any) => {
return React.cloneElement(child, {
active: child.props.value === activeValue,
onClick: (value) => { onItemChange(value) }
onClick: (value) => { onItemChange?.(value) }
});
})
}
......@@ -72,7 +74,7 @@ const FlowChartItem = ({ children, type = 'step', active, onClick, value }: Item
<div className={styles['item-box']}>
<div
className={cs(styles[type], active && styles['active'])}
onClick={() => onClick(value)}
onClick={() => onClick?.(value)}
>
{children}
</div>
......
import React, { useRef, useState, useCallback, forwardRef, memo, useImperativeHandle } from 'react'
import { Form } from 'antd'
import { Cascader, Form, Tabs, Table, Checkbox } from 'antd'
import StandardTable from '@/components/StandardTable'
import { ColumnType } from 'antd/lib/table'
import NiceForm from '@/components/NiceForm'
......@@ -8,37 +8,44 @@ import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilte
import { FORM_FILTER_PATH } from '@/formSchema/const'
import { schema } from './schema'
import CommonDrawer, { HandleType } from '../CommonDrawer'
import { getOrderDeliveryNoticeOrderVendorPage } from '@/services/OrderNewV2Api'
import { getProductGoodsGetDoesNotFreezeGoodsList } from '@/services/ProductV2Api'
import { useAsyncSelect } from '@/formSchema/effects/useAsyncSelect'
import { fetchBrand, fetchCategoryData, fetchTreeData, useAsyncCascader } from '../../effects'
export type RefHandleType = {
show: (flag?: boolean, params?: Object) => void
show: (flag?: boolean, params?: any, data?: any) => void
setRows: (rows: any[]) => void;
}
interface PropsType {
onOk?: (rows: any[], rowKeys: any[]) => void
onQueryAll?: (value?: any) => void
fieldCode?: string
selectCache?: any[]
}
const MaterialDrawer = (props: PropsType, ref) => {
const formActions = createFormActions()
const { onOk } = props
const { onOk, onQueryAll, fieldCode = 'code', selectCache } = props
const [selectedRowKeys, setSelectedRowKeys] = useState<any>([])
const [selectedRows, setSelectedRows] = useState<any>([])
const [isQueryAll, setIsQueryAll] = useState<boolean>(false)
const tableRef = useRef<any>({})
const drawRef = useRef<HandleType>()
const handleOk = useCallback(() => {
onOk?.(selectedRows, selectedRowKeys)
}, [selectedRows, selectedRowKeys])
onQueryAll?.(isQueryAll)
onOk?.(selectedRows.map(item => ({ id: item.id, value: item[fieldCode] })) , selectedRowKeys)
}, [selectedRows, selectedRowKeys, isQueryAll])
const handleShow = useCallback((params: Object) => {
}, [])
const fetchData = (params: any) => {
return new Promise((resolve) => {
getOrderDeliveryNoticeOrderVendorPage(params).then(({ code, data }) => {
getProductGoodsGetDoesNotFreezeGoodsList(params).then(({ code, data }) => {
if (code === 1000) {
resolve(data)
}
......@@ -47,20 +54,14 @@ const MaterialDrawer = (props: PropsType, ref) => {
}
const handleSelectChange = (record, selected, selectedRow, nativeEvent) => {
let childArr = [...selectedRowKeys];
let childArr = [...selectedRowKeys]
let childRowArr = [...selectedRows]
if (selected) {
childArr.push(record.id);
childRowArr.push(record);
childArr.push(record.id)
childRowArr.push(record)
} else {
childArr.splice(
childArr.findIndex((item) => item === record.id),
1
);
childRowArr.splice(
childRowArr.findIndex((item) => item.id === record.id),
1
);
childArr.splice(childArr.findIndex((item) => item === record.id), 1)
childRowArr.splice(childRowArr.findIndex((item) => item.id === record.id), 1)
}
setSelectedRowKeys(childArr)
setSelectedRows(childRowArr)
......@@ -88,9 +89,21 @@ const MaterialDrawer = (props: PropsType, ref) => {
setSelectedRows(childRowArr);
}
const onSelectAllMaterial = (checked: boolean) => {
setIsQueryAll(checked)
setSelectedRows([])
setSelectedRowKeys([])
}
useImperativeHandle(ref, () => ({
show(flag = true, params = {}) {
show(flag: boolean, params = {}, data: any) {
drawRef?.current?.show(flag, params)
if (data) {
setSelectedRows(data?.selectData || [])
const selectKeys = data?.selectData?.map(item => item.id) || []
setSelectedRowKeys(selectKeys)
setIsQueryAll(data?.isQueryAll || false)
}
},
setRows(rows: any[]) {
const rowKeys = rows.map(item => item.id)
......@@ -100,16 +113,18 @@ const MaterialDrawer = (props: PropsType, ref) => {
}))
const columns: ColumnType<any>[] = [
{
title: '通知单号',
dataIndex: 'noticeNo',
key: 'noticeNo',
width: 160,
},
{ title: '通知单摘要', dataIndex: 'digest', key: 'digest' },
{ title: '送货日期', dataIndex: 'deliveryTime', key: 'deliveryTime' },
{ title: '采购会员', dataIndex: 'memberName', key: 'memberName' },
{ title: '单据时间', dataIndex: 'createTime', key: 'createTime' },
{ title: 'ID', dataIndex: 'id', key: 'id', },
{ title: '物料编号', dataIndex: fieldCode, key: fieldCode }
]
const columns2: ColumnType<any>[] = [
{ title: 'ID', dataIndex: 'id', key: 'id' },
{ title: '物料编号', dataIndex: 'code', key: 'code', width: 120 },
{ title: '物料名称', dataIndex: 'name', key: 'name' },
{ title: '物料组', dataIndex: ['materialGroup', 'name'], key: 'materialGroup' },
{ title: '规格型号', dataIndex: 'type', key: 'type' },
{ title: '品类', dataIndex: ['customerCategory', 'name'], key: 'customerCategory' },
{ title: '品牌', dataIndex: ['brand', 'name'], key: 'brand' },
]
return (
......@@ -119,34 +134,61 @@ const MaterialDrawer = (props: PropsType, ref) => {
width={1000}
onOk={handleOk}
onShow={handleShow}
onCancel={() => { }}
onCancel={() => {}}
destroyOnClose
>
<StandardTable
currentRef={tableRef}
columns={columns}
tableProps={{ rowKey: 'id', }}
fetchTableData={(params: unknown) => fetchData(params)}
rowSelection={{
selectedRowKeys: selectedRowKeys,
onSelect: handleSelectChange,
onSelectAll: handleSelectAll,
}}
controlRender={
<NiceForm
actions={formActions}
onSubmit={values => tableRef.current.reload(values)}
effects={($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'noticeNo',
FORM_FILTER_PATH,
)
}}
schema={schema}
<div style={{ position: 'relative', top: 90 }}>
<Checkbox
checked={isQueryAll}
onChange={(e) => onSelectAllMaterial(e.target.checked)}
>
所有物料
</Checkbox>
</div>
<Tabs defaultActiveKey='1' onChange={() => {}}>
<Tabs.TabPane tab='可选择' key='1'>
{
!isQueryAll && (
<StandardTable
currentRef={tableRef}
columns={columns2}
tableProps={{ rowKey: 'id' }}
fetchTableData={(params: any) => fetchData(params)}
rowSelection={{
selectedRowKeys: selectedRowKeys,
onSelect: handleSelectChange,
onSelectAll: handleSelectAll,
getCheckboxProps: (record: any) => ({
disabled: selectCache.includes(record.id)
})
}}
controlRender={
<NiceForm
actions={formActions}
onSubmit={values => tableRef.current.reload(values)}
components={{ Cascader }}
effects={($, actions) => {
useStateFilterSearchLinkageEffect($, actions, 'code', FORM_FILTER_PATH);
useAsyncCascader('materialGroupId', fetchTreeData)
useAsyncCascader('categoryId', fetchCategoryData)
useAsyncSelect('brandId', fetchBrand, ["name", "id"])
}}
schema={schema}
/>
}
/>
)
}
</Tabs.TabPane>
<Tabs.TabPane tab={`已选择(${selectedRows.length})`} key='2'>
<Table
rowKey='id'
dataSource={selectedRows}
columns={columns}
pagination={null}
/>
}
/>
</Tabs.TabPane>
</Tabs>
</CommonDrawer>
)
}
......
import { ISchema } from '@formily/antd'
import { FORM_FILTER_PATH } from '@/formSchema/const'
import { getIntl } from 'umi'
const intl = getIntl()
export const schema: ISchema = {
type: 'object',
......@@ -11,16 +14,16 @@ export const schema: ISchema = {
topLayout: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
className: 'useMegaStart'
},
// 'x-component-props': {
// className: 'useMegaStart'
// },
properties: {
noticeNo: {
code: {
type: 'string',
'x-component': 'Search',
'x-component-props': {
allowClear: true,
placeholder: '请输入通知单号查询'
placeholder: '物料编号'
},
},
},
......@@ -38,25 +41,49 @@ export const schema: ISchema = {
},
},
properties: {
digest: {
name: {
type: 'string',
'x-component-props': {
allowClear: true,
placeholder: '通知单摘要'
placeholder: '物料名称'
}
},
'[startDate, endDate]': {
type: 'daterange',
'x-component-props': {
type: {
type: 'string',
"x-component-props": {
placeholder: '规格型号'
}
},
materialGroupId: {
type: 'string',
enum: [],
'x-component': 'Cascader',
"x-component-props": {
placeholder: intl.formatMessage({ id: 'material.group.title', defaultMessage: '物料组'}),
allowClear: true,
placeholder: ['送货开始日期', '送货结束日期'],
},
style: {
width: 150
},
showSearch: true,
fieldNames: { label: 'title', value: 'id', children: 'children' },
}
},
memberName: {
categoryId: {
type: 'string',
'x-component': 'Cascader',
'x-component-props': {
placeholder: intl.formatMessage({ id: 'material.category', defaultMessage: '品类' }),
allowClear: true,
placeholder: '采购会员'
style: { width: 150 },
showSearch: true,
fieldNames: { label: 'title', value: 'id', children: 'children' },
}
},
brandId: {
type: 'string',
'x-component-props': {
placeholder: intl.formatMessage({ id: 'material.brand', defaultMessage: '品牌' }),
style: { width: 150 },
}
},
submit: {
......
......@@ -11,20 +11,37 @@
}
.rule-wrap {
position: relative;
display: flex;
align-items: center;
width: 368px;
height: 32px;
margin-bottom: 16px;
padding: 0 4px;
border: 1px solid #F5F6F7;
border-radius: 4px;
color: #252D37;
font-size: 14px;
background-color: #F5F6F7;
cursor: pointer;
.rule-delete {
display: none;
align-items: center;
justify-content: center;
position: absolute;
right: 8px;
top: 8px;
width: 16px;
height: 16px;
cursor: pointer;
}
&:hover {
border: 1px solid #00A98F;
.rule-delete {
display: flex;
}
}
:global {
......
import React, { useRef, useState, useCallback, forwardRef, memo, useImperativeHandle } from 'react'
import React, { useRef, forwardRef, memo } from 'react'
import StandardTable from '@/components/StandardTable'
import { ColumnType } from 'antd/lib/table'
import CommonDrawer, { HandleType } from '../CommonDrawer'
import { getOrderDeliveryNoticeOrderVendorPage } from '@/services/OrderNewV2Api'
import CommonDrawer from '../CommonDrawer'
import { getMemberUserPageByRoleId } from '@/services/MemberV2Api'
interface PropsType {
onOk?: (rows: any[], rowKeys: any[]) => void
}
const SeeUserDrawer = (props: PropsType, ref) => {
const tableRef = useRef<any>({})
const roleIdRef = useRef<any>()
const fetchData = (params: any) => {
console.log('roleIdRef.current', roleIdRef.current)
return new Promise((resolve) => {
getOrderDeliveryNoticeOrderVendorPage(params).then(({ code, data }) => {
if (code === 1000) {
resolve(data)
}
})
if (roleIdRef.current) {
getMemberUserPageByRoleId({ ...params, roleId: roleIdRef.current }).then(({ code, data }) => {
if (code === 1000) {
resolve(data)
}
})
} else {
resolve({ total: 0, data: [] })
}
})
}
const columns: ColumnType<any>[] = [
{
title: '通知单号',
dataIndex: 'noticeNo',
key: 'noticeNo',
width: 160,
},
{ title: '通知单摘要', dataIndex: 'digest', key: 'digest' },
{ title: '送货日期', dataIndex: 'deliveryTime', key: 'deliveryTime' },
{ title: '采购会员', dataIndex: 'memberName', key: 'memberName' },
{ title: '单据时间', dataIndex: 'createTime', key: 'createTime' },
{ title: '序号', dataIndex: 'number', key: 'number', render: (text, record, index) => index },
{ title: '姓名', dataIndex: 'name', key: 'name' },
{ title: '手机号码', dataIndex: 'phone', key: 'phone' },
{ title: '所属机构', dataIndex: 'orgName', key: 'orgName' },
{ title: '职位', dataIndex: 'jobTitle', key: 'jobTitle' },
]
return (
<CommonDrawer
ref={ref}
title='用户列表'
width={1000}
width={800}
footer={null}
onShow={(params: any) => {
roleIdRef.current = params?.roleId
}}
destroyOnClose={true}
>
<StandardTable
ref={tableRef}
columns={columns}
tableProps={{ rowKey: 'id', }}
tableProps={{ rowKey: 'userId' }}
fetchTableData={(params: any) => fetchData(params)}
/>
</CommonDrawer>
......
import React, { useState, memo, useCallback, useRef, useEffect } from 'react'
import { HandleType } from '../CommonDrawer'
import MaterialDrawer, { RefHandleType } from '../MaterialDrawer'
import CategoryDrawer from '../CategoryDrawer'
import WrapSelect from '../WrapSelect'
interface PropsType {
onChange?: (data: any[]) => void
onChange?: (data: any) => void
onValueChange?: (data: any[]) => void
value?: any
fieldCode?: string
selectCache?: any[]
}
const SelectMaterial = (props: PropsType) => {
const { onChange, value } = props
const { onChange, value, fieldCode = 'title', onValueChange, ...rest } = props
const [selectData, setSelectData] = useState<any[]>([])
const ref = useRef<RefHandleType>()
const ref = useRef<any>()
const handleOk = useCallback((rows: any[]) => {
onChange?.(rows)
setSelectData(rows)
const handleOk = useCallback((keys: any[]) => {
// 直接处理为JSON字符串
onChange?.(JSON.stringify(keys))
onValueChange?.(keys)
setSelectData(keys)
ref?.current?.show(false)
}, [])
const onItemDelete = (id: string | number) => {
const newSelectData = selectData.filter(item => item.id !== id)
// 直接处理为JSON字符串
onChange?.(JSON.stringify(newSelectData))
onValueChange?.(newSelectData)
setSelectData(newSelectData)
ref?.current?.setRows(newSelectData)
ref?.current?.setKeys(newSelectData)
}
useEffect(() => {
if (value) {
setSelectData(value)
// JSON字符串转为原数据
const keys = JSON.parse(value)
setSelectData(keys)
onValueChange?.(keys)
}
}, [])
}, [value])
return (
<>
<WrapSelect
onIconClick={() => { ref?.current?.show() }}
onIconClick={() => { ref?.current?.show(true, {}, { selectData }) }}
onItemDelete={onItemDelete}
data={selectData}
labelKey='memberName'
labelKey='value'
/>
<MaterialDrawer
<CategoryDrawer
ref={ref}
onOk={handleOk}
fieldCode={fieldCode}
{...rest}
/>
</>
......
......@@ -3,45 +3,72 @@ import MaterialDrawer, { RefHandleType } from '../MaterialDrawer'
import WrapSelect from '../WrapSelect'
interface PropsType {
onChange?: (data: any[]) => void
onChange?: (data: any) => void
onValueChange?: (data: any[]) => void
value?: any
fieldCode?: string
onQueryAll?: (value?: any) => void
selectCache?: any[]
isAll?: boolean
}
const SelectMaterial = (props: PropsType) => {
const { onChange, value } = props
const { onChange, value, fieldCode = 'code', onQueryAll, onValueChange, isAll, ...rest } = props
const [selectData, setSelectData] = useState<any[]>([])
const [isQueryAll, setIsQueryAll] = useState<boolean>(false)
const ref = useRef<RefHandleType>()
const handleOk = useCallback((rows: any[]) => {
onChange?.(rows)
// 直接处理为JSON字符串
onChange?.(JSON.stringify(rows))
onValueChange?.(rows)
setSelectData(rows)
ref?.current?.show(false)
}, [])
const onItemDelete = (id: string | number) => {
const newSelectData = selectData.filter(item => item.id !== id)
// 直接处理为JSON字符串
onChange?.(JSON.stringify(newSelectData))
onValueChange?.(newSelectData)
setSelectData(newSelectData)
ref?.current?.setRows(newSelectData)
}
const _onQueryAll = (val: boolean) => {
setIsQueryAll(val)
onQueryAll?.(val)
}
useEffect(() => {
if (value) {
setSelectData(value)
// JSON字符串转为原数据
const rows = JSON.parse(value)
setSelectData(rows)
onValueChange?.(rows)
}
}, [])
}, [value])
useEffect(() => {
setIsQueryAll(isAll)
}, [isAll])
return (
<>
<WrapSelect
onIconClick={() => { ref?.current?.show() }}
onIconClick={() => { ref?.current?.show(true, {}, { selectData, isQueryAll }) }}
onItemDelete={onItemDelete}
data={selectData}
labelKey='memberName'
labelKey='value'
placeholder={isQueryAll ? '所有物料' : '请选择'}
/>
<MaterialDrawer
ref={ref}
onOk={handleOk}
fieldCode={fieldCode}
onQueryAll={_onQueryAll}
{...rest}
/>
</>
......
......@@ -6,14 +6,15 @@ import { HandleType } from '../CommonDrawer'
import SeeUserDrawer from '../SeeUserDrawer'
const SelectRoles = (props: any) => {
const { onChange, ...rest } = props
const { onChange, onValueChange, ...rest } = props
const valueRef = useRef<any>()
const roleIdRef = useRef<any>(rest?.value)
const drawRef = useRef<HandleType>()
const _onChange = (value) => {
valueRef.current.ref = value
onChange?.(value)
const _onChange = (id) => {
roleIdRef.current = id
onChange?.(id)
onValueChange?.(id)
}
return (
......@@ -22,9 +23,6 @@ const SelectRoles = (props: any) => {
<Col style={{ flex: 1 }}>
<FetchSelect
style={{ width: '100%' }}
labelKey='memberName'
valueKey='id'
requestApi={getOrderDeliveryNoticeOrderVendorPage}
onChange={_onChange}
{...rest}
/>
......@@ -32,13 +30,15 @@ const SelectRoles = (props: any) => {
<Col>
<Button
style={{ marginRight: 0 }}
onClick={() => { drawRef?.current?.show() }}
onClick={() => { drawRef?.current?.show(true, { roleId: roleIdRef.current }) }}
>
查看用户
</Button>
</Col>
</Row>
<SeeUserDrawer ref={drawRef}/>
<SeeUserDrawer
ref={drawRef}
/>
</>
)
......
import React from 'react'
import { DatePicker } from 'antd'
import moment from 'moment'
const StringDatePicker = (props: any) => {
const { onChange, value, ...rest } = props
const _onChange = (date: any, dateString: string) => {
onChange?.(dateString)
}
return (
<DatePicker
style={{ width: '100%' }}
placeholder="请选择"
{...rest}
value={moment(value)}
onChange={_onChange}
/>
)
}
export default StringDatePicker
......@@ -10,10 +10,11 @@ interface PropsType {
data?: any[]
labelKey?: string
valueKey?: string
placeholder?: string
}
const WrapSelect = (props: PropsType) => {
const { onIconClick, onItemClick, onItemDelete, data = [], labelKey = 'name', valueKey='id' } = props
const { onIconClick, onItemClick, onItemDelete, data = [], labelKey = 'name', valueKey='id', placeholder = '请选择' } = props
return (
<div className={styles['wrap-select']}>
......@@ -46,7 +47,7 @@ const WrapSelect = (props: PropsType) => {
}
</>
:
<div className={styles['content-placeholder']}>请选择</div>
<div className={styles['content-placeholder']}>{placeholder}</div>
}
<div className={styles['icon-box']} onClick={() => onIconClick?.()}>
<LinkOutlined style={{ fontSize: 16, color: '#FFF' }} />
......
/** 字段类型 */
export enum Filed_Type {
STRING = 1, // 字符
NUMBER = 2, // 数字
DATE = 3, // 日期
}
/** 选择弹窗类型 */
export enum Select_Content_Type {
SelectMaterial = 1, // 选择物料
SelectCategory = 2, // 选择品类
}
/**
* EQUAL 1 等于
*
* UNEQUAL 2 不等于
*
* GREATER_THAN 3 大于
*
* GREATER_THAN_EQUAL 4 大于等于
*
* LESS_THAN 5 小于
*
* LESS_THAN_EQUAL 6 小于等于
*
* INCLUDED 7 包含
*
* NOT_INCLUDED 8 不包含
*
* ALL 9 所有
*/
export enum CONDITION_VALUE {
EQUAL = 1, // 等于
UNEQUAL = 2, // 不等于
GREATER_THAN = 3, // 大于
GREATER_THAN_EQUAL = 4, // 大于等于
LESS_THAN = 5, // 小于
LESS_THAN_EQUAL = 6, // 小于等于
INCLUDED = 7, // 包含
NOT_INCLUDED = 8, // 不包含
// ALL = 9, // 所有
}
export const conditionOptions = {
[Filed_Type.STRING]: [
{ label: '是', value: CONDITION_VALUE.EQUAL },
{ label: '不是', value: CONDITION_VALUE.UNEQUAL },
{ label: '包含', value: CONDITION_VALUE.INCLUDED },
{ label: '不包含', value: CONDITION_VALUE.NOT_INCLUDED },
// { label: '所有', value: CONDITION_VALUE.ALL },
],
[Filed_Type.NUMBER]: [
{ label: '>', value: CONDITION_VALUE.GREATER_THAN },
{ label: '<', value: CONDITION_VALUE.LESS_THAN },
{ label: '=', value: CONDITION_VALUE.EQUAL },
{ label: '>=', value: CONDITION_VALUE.GREATER_THAN_EQUAL },
{ label: '<=', value: CONDITION_VALUE.LESS_THAN_EQUAL },
{ label: '!=', value: CONDITION_VALUE.UNEQUAL },
],
[Filed_Type.DATE]: [
{ label: '是', value: CONDITION_VALUE.EQUAL },
{ label: '不是', value: CONDITION_VALUE.UNEQUAL },
{ label: '在之前', value: CONDITION_VALUE.LESS_THAN },
{ label: '在之后', value: CONDITION_VALUE.GREATER_THAN },
]
}
export const interrelationOptions = [
{ label: '并且', value: 1 },
{ label: '或者', value: 2 },
]
export enum RULE_TYPE {
MATERIAL_MANAGE = 'MATERIAL_MANAGE', // 物料管理
BUYING_REQUISITION = 'BUYING_REQUISITION', // 请购单
PURCHASE_PROCESS = 'PURCHASE_PROCESS', // 采购流程
CONTRACT_MANAGE = 'CONTRACT_MANAGE', // 合同管理
CONTRACT_COORDINATION = 'CONTRACT_COORDINATION', // 合同协同
REQUEST_FUNDS_MANAGE = 'REQUEST_FUNDS_MANAGE' // 请款单管理
}
/**
* 物料管理 1 等于
*
* 采购单流程 2 不等于
*
* 合同管理 3 大于
*
* 合同协同 4 大于等于
*
* 请购单流程 5 小于
*
* 请款单管理 6 小于等于
*/
export enum RULE_ENR_TYPE {
MATERIAL_MANAGE = 1, // 物料管理
PURCHASE_PROCESS = 2, // 采购单流程
CONTRACT_MANAGE = 3, // 合同管理
CONTRACT_COORDINATION = 4, // 合同协同
BUYING_REQUISITION = 5, // 请购单流程
REQUEST_FUNDS_MANAGE = 6, // 请款单管理
}
import { getProductCustomerGetCustomerCategoryTree, getProductMaterialGroupTree, getProductSelectGetSelectBrand } from "@/services/ProductV2Api"
import { createFormActions, FormEffectHooks, FormPath } from "@formily/antd"
const { onFormMount$ } = FormEffectHooks
const EMPTY_ARRAY = []
export const EMPTY = {
totalCount: 0,
data: [],
}
export const useAsyncCascader = async (name, service: () => Promise<any[]>) => {
const { setFieldState } = createFormActions()
onFormMount$().subscribe(() => {
service().then(res => {
setFieldState(name, state => {
FormPath.setIn(state, 'props.x-component-props.options', res)
})
}).catch(err => {
setFieldState(name, state => {
FormPath.setIn(state, 'props.x-component-props.options', [])
})
})
})
}
export const fetchTreeData = async () => {
try {
const { data, code } = await getProductMaterialGroupTree({ rootNodeId: '0' });
if (code === 1000) {
return data;
}
return EMPTY_ARRAY
} catch {
return EMPTY_ARRAY
}
}
export const fetchCategoryData = async () => {
try {
const { data, code } = await getProductCustomerGetCustomerCategoryTree();
if (code === 1000) {
return data;
}
return EMPTY_ARRAY
} catch {
return EMPTY_ARRAY
}
}
export const fetchBrand = async () => {
try {
const { data, code } = await getProductSelectGetSelectBrand();
if (code === 1000) {
return data;
}
return EMPTY_ARRAY
} catch {
return EMPTY_ARRAY
}
}
......@@ -2,34 +2,87 @@
* 系统能力 - 规则引擎 - 规则引擎配置
* @author: Crayon
*/
import React, { useEffect, useRef, useCallback } from 'react'
import React, { useEffect, useRef, useCallback, useState } from 'react'
import AnchorPage from '@/components/AnchorPage'
import { history } from 'umi'
import usePrompt from '@/hooks/usePrompt'
import FlowChart, { FlowChartOptionsType, RefHandleType } from './components/FlowChart'
import { history, useLocation } from 'umi'
import FlowChart, { RefHandleType } from './components/FlowChart'
import ConfigDrawer from './components/ConfigDrawer'
import { HandleType } from './components/CommonDrawer'
import { Spin } from 'antd'
import { getProductMaterialProcessEngineGet } from '@/services/ProductV2Api'
import { getOrderPurchaseProcessEngineGet } from '@/services/OrderNewV2Api'
import { getPurchaseRequisitionProcessEngineGet } from '@/services/PurchaseV2Api'
import { getContractRuleEngineCoordinationProcess, getContractRuleEngineProcess } from '@/services/ContractV2Api'
import { getSettleAccountsApplyAmountProcessGet } from '@/services/SettleV2Api'
import { getRuleEngineConfigGetRuleEngineInfo } from '@/services/RuleEngineV2Api'
import { RULE_ENR_TYPE, RULE_TYPE } from './constant'
type RuleType = 'MATERIAL_MANAGE' | 'BUYING_REQUISITION' | 'PURCHASE_PROCESS' | 'CONTRACT_MANAGE' | 'CONTRACT_COORDINATION' | 'REQUEST_FUNDS_MANAGE'
const getFetchDetailApi = async (type: RuleType, params: any) => {
switch (type) {
case RULE_TYPE.MATERIAL_MANAGE:
return await getProductMaterialProcessEngineGet(params) // 查询物料流程规则引擎详情
case RULE_TYPE.BUYING_REQUISITION:
return await getPurchaseRequisitionProcessEngineGet(params) // 查询请购单管理规则引擎详情
case RULE_TYPE.PURCHASE_PROCESS:
return await getOrderPurchaseProcessEngineGet(params) // 查询采购流程规则引擎详情
case RULE_TYPE.CONTRACT_MANAGE:
return await getContractRuleEngineProcess(params) // 查询合同管理规则引擎详情
case RULE_TYPE.CONTRACT_COORDINATION:
return await getContractRuleEngineCoordinationProcess(params) // 查询合同协同规则引擎详情
case RULE_TYPE.REQUEST_FUNDS_MANAGE:
return await getSettleAccountsApplyAmountProcessGet(params) // 查询请款单管理规则引擎详情
default:
return { code: 1102, data: null }
}
}
const RuleEngConfig: React.FC = () => {
const location: any = useLocation();
const { type, processId } = location?.query
const [flowOptions, setFlowOptions] = useState<any[]>()
const [spinning, setSpinning] = useState<boolean>(false)
const flowRef = useRef<RefHandleType>()
const drawRef = useRef<HandleType>()
const options: FlowChartOptionsType[] = [
{ label: '提交审核', value: 1 },
{ label: '审核 (一级)', value: 2 },
{ label: '审核 (二级)', value: 3 },
]
const getProcessEngineDetail = async () => {
if (type && processId) {
setSpinning(true)
const { code, data } = await getFetchDetailApi(type, { processId })
if (code === 1000) {
const newOptions = data.responses.map(item => ({
processStepName: item.taskName,
processStep: item.taskStep,
processId: data.processKey,
processName: data.processName
}))
setFlowOptions(newOptions)
setSpinning(false)
}
}
}
const handleDrawer = useCallback(() => {
flowRef?.current?.setActive('')
drawRef?.current?.show(false)
}, [])
const onFlowChartChange = useCallback((value: string | number) => {
drawRef?.current?.show(true, { id: value })
const onFlowChartChange = useCallback(async (processStep: string, optionItem: any) => {
setSpinning(true)
const { code, data } = await getRuleEngineConfigGetRuleEngineInfo({ processId: optionItem.processId, processStep })
setSpinning(false)
if (code === 1000) {
const params = { process: { ...optionItem, type: RULE_ENR_TYPE[type] }, formData: data }
drawRef?.current?.show(true, params)
}
}, [])
useEffect(() => {
getProcessEngineDetail()
}, [])
return (
......@@ -38,15 +91,18 @@ const RuleEngConfig: React.FC = () => {
onBack={() => history.goBack()}
anchors={[]}
>
<FlowChart
ref={flowRef}
options={options}
onChange={onFlowChartChange}
/>
<ConfigDrawer
ref={drawRef}
onChange={handleDrawer}
/>
<Spin spinning={spinning}>
<FlowChart
ref={flowRef}
options={flowOptions}
onChange={onFlowChartChange}
fieldNames={{ label: 'processStepName', value: 'processStep' }}
/>
<ConfigDrawer
ref={drawRef}
onChange={handleDrawer}
/>
</Spin>
</AnchorPage>
)
}
......
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