Commit c548386d authored by XieZhiXiong's avatar XieZhiXiong

merge

parents 967c13bb d45b058e
......@@ -33,6 +33,10 @@ const router = [
path: '/user/policy',
component: '@/pages/user/policy'
},
{
path: '/user/forget',
component: '@/pages/user/forgetPwd'
}
]
},
{
......
......@@ -139,14 +139,14 @@ const CommodityRoute = {
component: '@/pages/commodity/products/directChannel',
},
{
path: '/memberCenter/commodityAbility/commodity/products/addDirectChannel',
path: '/memberCenter/commodityAbility/commodity/products/directChannel/addDirectChannel',
name: 'addDirectChannel',
hideInMenu: true,
icon: 'smile',
component: '@/pages/commodity/products/addDirectChannel',
},
{
path: '/memberCenter/commodityAbility/commodity/products/viewDirectChannel',
path: '/memberCenter/commodityAbility/commodity/products/directChannel/viewDirectChannel',
name: 'viewDirectChannel',
hideInMenu: true,
icon: 'smile',
......
......@@ -84,6 +84,20 @@ const TranactionRoute = {
},
]
},
// 采购订单
{
path: '/memberCenter/tranactionAbility/purchaseOrder',
name: 'purchaseOrder',
key: 'purchaseOrder',
routes: [
{
path: '/memberCenter/tranactionAbility/purchaseOrder/orderList',
name: 'purchaseOrderSearch',
key: 'purchaseOrderSearch',
component: '@/pages/transaction/purchaseOrder'
},
]
}
]
......
......@@ -12,6 +12,8 @@ import { isDev } from '@/constants'
import { setup } from '@formily/antd-components';
import { getRouters, getAuth, asyncRouter, setAuth, setRouters, removeAuth, removeRouters } from './utils/auth';
import { PublicApi } from './services/api';
// 全局注册虚拟组件
import '@/components/NiceForm/public'
setup()
......@@ -19,6 +21,7 @@ setup()
const userLoginLists = [
'/user/login',
'/user/register',
'/user/forget'
]
// let routeAuthUrls: any[] = []
// 路由白名单
......
......@@ -3,7 +3,6 @@ import SchemaForm, {
IAntdSchemaFormProps, createVirtualBox, registerVirtualBox, Schema, SchemaField, FormButtonGroup, Reset, createControllerBox, registerValidationRules,
} from '@formily/antd';
import { Button, Space, Row, Col } from 'antd';
import styled from 'styled-components'
import CustomUpload from './components/CustomUpload';
import CustomStatus from './components/CustomStatus';
import CustomAddArray from './components/CustomAddArray';
......@@ -24,62 +23,9 @@ import SearchSelect from './components/SearchSelect';
import TableTagList from './components/TableTagList';
import './index.less'
import { Checkbox, Input } from '@formily/antd-components';
import cx from 'classnames'
export interface NiceFormProps extends IAntdSchemaFormProps {}
const RowLayout = styled(props => <Row justify='end' {...props}/>)`
.mega-layout-item {
margin-bottom: 20px !important;
}
.mega-layout-container {
margin-bottom: 0;
}
`
const renderCol = (schema, isLast) => {
const { flexcol = {} } = schema['x-component-props']
return <Col style={isLast ? {} : {marginRight: 24}} {...flexcol} key={schema.path}>
<SchemaField schema={schema.toJSON()} path={schema.path}/>
</Col>
}
// 自定义flex布局容器
registerVirtualBox('flex-box', props => {
const childProperties = props.schema.getOrderProperties()
const { title, required } = props.props
const {labelcol, wrappercol} = props.schema.getExtendsComponentProps()
return <Row>
{ title && <Col span={labelcol} className={cx(required ? 'flex-layout-label-required' : '')}>{title}</Col>}
<Col span={wrappercol}>
<Row>
{
childProperties.map((v, i, arr) => renderCol(v.schema, arr.length - 1 === i))
}
</Row>
</Col>
</Row>
})
registerVirtualBox('flex-layout', (_props) => {
const { children, props } = _props
const rowStyle = props['x-component-props'] ? props['x-component-props'].rowStyle : {}
const colStyle = props['x-component-props'] ? props['x-component-props'].colStyle : {}
return (
<RowLayout style={rowStyle}>
{
children.map((v, i) => <Col style={colStyle} key={i}>{v}</Col>)
}
</RowLayout>
)
})
registerVirtualBox('empty-layout', (_props) => {
const { children, props } = _props
return (
<div>{children}</div>
)
})
const SchemaFormButtonGroup = createVirtualBox('schemaButtonGroup', FormButtonGroup)
const SchemaButton = createVirtualBox('schemaButton', Button)
const SchemaSubmit = createVirtualBox('schemaSubmit', Submit)
......
// 全局注册虚拟布局组件
import React from 'react'
import { registerVirtualBox, SchemaField } from "@formily/antd"
import { Col, Row } from 'antd'
import cx from 'classnames'
import styled from 'styled-components'
const RowLayout = styled(props => <Row justify='end' {...props}/>)`
.mega-layout-item {
margin-bottom: 20px !important;
}
.mega-layout-container {
margin-bottom: 0;
}
`
const renderCol = (schema, isLast) => {
const { flexcol = {} } = schema['x-component-props']
return <Col style={isLast ? {} : {marginRight: 24}} {...flexcol} key={schema.path}>
<SchemaField schema={schema.toJSON()} path={schema.path}/>
</Col>
}
// 自定义flex布局容器
registerVirtualBox('flex-box', props => {
const childProperties = props.schema.getOrderProperties()
const { title, required } = props.props
const {labelcol, wrappercol} = props.schema.getExtendsComponentProps()
return <Row>
{ title && <Col span={labelcol} className={cx(required ? 'flex-layout-label-required' : '')}>{title}</Col>}
<Col span={wrappercol}>
<Row>
{
childProperties.map((v, i, arr) => renderCol(v.schema, arr.length - 1 === i))
}
</Row>
</Col>
</Row>
})
registerVirtualBox('flex-layout', (_props) => {
const { children, props } = _props
const rowStyle = props['x-component-props'] ? props['x-component-props'].rowStyle : {}
const colStyle = props['x-component-props'] ? props['x-component-props'].colStyle : {}
return (
<RowLayout style={rowStyle}>
{
children.map((v, i) => <Col style={colStyle} key={i}>{v}</Col>)
}
</RowLayout>
)
})
registerVirtualBox('empty-layout', (_props) => {
const { children, props } = _props
return (
<div>{children}</div>
)
})
\ No newline at end of file
......@@ -275,4 +275,10 @@ h6 {
.ant-select-dropdown {
top: 36px !important;
}
}
// 强制块级标签居中
.global-block-center {
margin-left: auto !important;
margin-right: auto !important;
}
\ No newline at end of file
import { useState, useMemo } from 'react';
interface stringMethods {
[key: string]: (...args) => any
}
/**
* @description 传入一个值和方法map, 返回对应控制该状态的fn
* @param initialValue 初始状态
* @param methods 控制状态的方法集合对象
* @author xjm
*/
export const useMethods = <T>(initialValue: T, methods: stringMethods) => {
const [value, setValue] = useState<T>(initialValue);
const boundMethods = useMemo(
() => Object.entries(methods).reduce(
(methods, [name, fn]) => {
const method = (...args) => {
setValue(value => fn(value, ...args));
};
methods[name] = method;
return methods;
},
{}
),
[methods]
);
return [value, boundMethods];
};
\ No newline at end of file
......@@ -104,6 +104,8 @@ export default {
'menu.tranactionAbility.enquirySubmit': '需求发布',
'menu.tranactionAbility.enquirySubmit.SearchList': '待新增需求单',
'menu.tranactionAbility.enquirySubmit.addEnquiry': '新增需求单',
'menu.tranactionAbility.purchaseOrder': '采购订单',
'menu.tranactionAbility.purchaseOrder.purchaseOrderSearch': '订单查询',
//物流能力
'menu.logisticsAbility': '物流',
......
......@@ -294,7 +294,7 @@ const CategoryAttributes: React.FC<{}> = () => {
name: {
type: 'string',
'x-component-props': {
placeHolder: '属性名称'
placeholder: '属性名称'
},
'x-component': 'Search'
}
......@@ -324,6 +324,7 @@ const CategoryAttributes: React.FC<{}> = () => {
onCancel={handleSelectCancel}
okText="确认"
cancelText="取消"
destroyOnClose={true}
>
<StandardTable
columns={columnsLink}
......
......@@ -61,50 +61,32 @@ const AddGoods = () => {
}
}, [])
const handleBrandSearch = (value:any) => { // end value
if (value) {
PublicApi.getProductSelectGetSelectBrand({name: value}).then(res=>{
if(res.code === 1000)
setBrandData(res.data)
})
} else {
setBrandData([])
}
const handleBrandSearch = (value?:any) => { // end value
PublicApi.getProductSelectGetSelectBrand({name: value}).then(res=>{
if(res.code === 1000)
setBrandData(res.data)
})
}
const handleBrandChange = (value:any) => {
setBrandValue(value)
// let obj = {...filterParams, brandId: value}
// setFilterParams(obj)
}
const handleClassSearch = (value:any) => {
if (value) {
PublicApi.getProductSelectGetSelectCustomerCategory({name: value}).then(res=>{
if(res.code === 1000)
setClassData(res.data)
})
} else {
setClassData([])
}
const handleClassSearch = (value?:any) => {
PublicApi.getProductSelectGetSelectCustomerCategory({name: value}).then(res=>{
if(res.code === 1000)
setClassData(res.data)
})
}
const handleClassChange = (value:any) => {
setClassValue(value)
// let obj = {...filterParams, customerCategoryId: value}
// setFilterParams(obj)
}
const handleUnitSearch = (value:any) => {
if (value) {
PublicApi.getProductSelectGetSelectCnUnit({name: value}).then(res=>{
if(res.code === 1000)
setUnitData(res.data)
})
} else {
setUnitData([])
}
const handleUnitSearch = (value?:any) => {
PublicApi.getProductSelectGetSelectCnUnit({name: value}).then(res=>{
if(res.code === 1000)
setUnitData(res.data)
})
}
const handleUnitChange = (value:any) => {
setUnitValue(value)
// let obj = {...filterParams, customerCategoryId: value}
// setFilterParams(obj)
}
const onFinish = (values:any) => {
......@@ -188,6 +170,7 @@ const AddGoods = () => {
filterOption={false}
onSearch={handleClassSearch}
onChange={handleClassChange}
onFocus={()=>handleClassSearch(null)}
notFoundContent={null}
style={{width:'100%'}}
disabled={isSee}
......@@ -215,6 +198,7 @@ const AddGoods = () => {
filterOption={false}
onSearch={handleBrandSearch}
onChange={handleBrandChange}
onFocus={()=>handleBrandSearch(null)}
notFoundContent={null}
style={{width:'100%'}}
disabled={isSee}
......@@ -241,6 +225,7 @@ const AddGoods = () => {
filterOption={false}
onSearch={handleUnitSearch}
onChange={handleUnitChange}
onFocus={()=>handleUnitSearch(null)}
notFoundContent={null}
style={{width:'100%'}}
disabled={isSee}
......
......@@ -89,7 +89,7 @@ const AddDirectChannel:React.FC<{}> = (props) => {
const [memberColumn, setMemberColumn] = useState<any[]>([])
const [queryId, setQueryId] = useState<number>()
const [productInfoByEdit, setProductInfoByEdit] = useState<GetProductChannelCommodityGetChannelCommodityResponse>()
// const [productInfoByEdit, setProductInfoByEdit] = useState<GetProductChannelCommodityGetChannelCommodityResponse>()
const productColumns: ColumnType<any>[] = [
{
......@@ -153,7 +153,7 @@ const AddDirectChannel:React.FC<{}> = (props) => {
if(id)
PublicApi.getProductChannelCommodityGetChannelCommodity({id: id}).then(res => {
const { data } = res
setProductInfoByEdit(data)
// setProductInfoByEdit(data)
formProduct.setFieldsValue({source: data.source})
setSource(data.source)
// @ts-ignore
......@@ -192,10 +192,10 @@ const AddDirectChannel:React.FC<{}> = (props) => {
useEffect(() => {
if(visibleAddTabs)
console.log(productRef.current, productFormActions,'132456')
// productRef.current.schemaAction.setFieldState('parentMemberId', state => {
// state.visible = source===1 ? true : false
// })
productRef?.current?.schemaAction?.setFieldState('parentMemberId', state => {
console.log('parentMemberId')
state.visible = source===1 ? true : false
})
}, [visibleAddTabs])
// 获取渠道商品
......@@ -734,7 +734,7 @@ const AddDirectChannel:React.FC<{}> = (props) => {
confirm={handleOkAddTabs}
cancel={handleCancelAddTabs}
visible={visibleAddTabs}
resetModal={{destroyOnClose: true}}
resetModal={{destroyOnClose: true, forceRender: true}}
columns={productColumns}
rowSelection={productRowSelection}
fetchTableData={(params:any) => fetchProductData(params)}
......
......@@ -125,6 +125,8 @@ const AddProducts: React.FC<{}> = (props) => {
if(productAttributeAndImageParams.length>0){
productAttributeAndImageParams.map(_item => {
if(_item.goodsCustomerAttributeList.length>0){
_item.goods = { id: _item.goodsId }
delete _item.goodsId
_item.goodsCustomerAttributeList.map(__item => {
delete __item.customerAttributeName
// __item.customerAttributeValueId = __item.id
......@@ -136,6 +138,8 @@ const AddProducts: React.FC<{}> = (props) => {
delete __item.customerAttributeId
})
}
_item.attributeAndValueList = _item.goodsCustomerAttributeList
delete _item.goodsCustomerAttributeList
if(_item.commodityPic.length>0){
// 编辑情况下兼顾手动添加图片列表属性
_item.commodityPic = _item.commodityPic.map(__item => __item?.response?.data || __item?.url)
......@@ -176,6 +180,16 @@ const AddProducts: React.FC<{}> = (props) => {
_params.packing = productInfoByEdit.packing
_params.afterService = productInfoByEdit.afterService
}
// 校验价格
try{
let hasPriceArray = _params.unitPriceAndPicList.map(item => item.unitPrice)
hasPriceArray.map(item => {
if(JSON.stringify(item) === '{}')
throw new Error('商品价格为必填项!')
})
}catch(e){
return e
}
console.log(_params, 'params')
PublicApi.postProductCommoditySaveOrUpdateCommodity(_params).then(res => {
if(res.code === 1000){
......
......@@ -87,9 +87,9 @@ const ProductImageForm: React.FC<Iprops> = (props) => {
// }
setPriceAttributeParamsByRender(_priceAttributeParams)
setProductAttributeAndImageParams(_priceAttributeParams)
console.log(_priceAttributeParams, priceAttributeParams, '_p')
console.log(_priceAttributeParams, priceAttributeParams, '_p') // 这里可能为空数组
// 初始化若是按所有属性共用做显示处理
if(setImageType){
if(setImageType && _priceAttributeParams.length>0){
setCommonImageList(_priceAttributeParams[0].commodityPic)
}
......@@ -261,7 +261,7 @@ const ProductImageForm: React.FC<Iprops> = (props) => {
banner
showIcon={false}
message=""
description={<>1. (按属性设置)一次可以选择 6 张图片<br />2. 图片尺寸为 800*800,单张大小不超过 600K,仅支持JPEG/JPG/PNG格式<br />3. 图片质量要清晰,不要虚化,建议主图为白色背景正面图</>}
description={<>1. 一次可以选择 6 张图片<br />2. 图片尺寸为 800*800,单张大小不超过 600K,仅支持JPEG/JPG/PNG格式<br />3. 图片质量要清晰,不要虚化,建议主图为白色背景正面图</>}
type="info"
closable
style={{ backgroundColor: '#F0F8FF', color: '#1B9AEE' }}
......@@ -289,7 +289,7 @@ const ProductImageForm: React.FC<Iprops> = (props) => {
banner
showIcon={false}
message=""
description={<>1. (所有属性共用)一次可以选择 6 张图片<br />2. 图片尺寸为 800*800,单张大小不超过 600K,仅支持JPEG/JPG/PNG格式<br />3. 图片质量要清晰,不要虚化,建议主图为白色背景正面图</>}
description={<>1. 一次可以选择 6 张图片<br />2. 图片尺寸为 800*800,单张大小不超过 600K,仅支持JPEG/JPG/PNG格式<br />3. 图片质量要清晰,不要虚化,建议主图为白色背景正面图</>}
type="info"
closable
style={{ backgroundColor: '#F0F8FF', color: '#1B9AEE' }}
......
......@@ -67,7 +67,7 @@ const DirectChannel: React.FC<{}> = () => {
key: 'name',
className: 'commonPickColor',
render: (text:any, record:any) => <EyePreview
url={`/memberCenter/commodityAbility/commodity/products/viewDirectChannel?id=${record.id}`}
url={`/memberCenter/commodityAbility/commodity/products/directChannel/viewDirectChannel?id=${record.id}`}
>
{text}
</EyePreview>
......@@ -162,7 +162,7 @@ const DirectChannel: React.FC<{}> = () => {
];
const clickModify = (paramId: number) => {
history.push(`/memberCenter/commodityAbility/commodity/products/addDirectChannel?id=${paramId}`)
history.push(`/memberCenter/commodityAbility/commodity/products/directChannel/addDirectChannel?id=${paramId}`)
}
// paramId ? 单个删除 : 批量删除
......@@ -294,7 +294,7 @@ const DirectChannel: React.FC<{}> = () => {
<Space>
<Button
type='primary'
onClick={() => history.push('/memberCenter/commodityAbility/commodity/products/addDirectChannel')}
onClick={() => history.push('/memberCenter/commodityAbility/commodity/products/directChannel/addDirectChannel')}
>
<PlusOutlined />新建
</Button>
......@@ -362,7 +362,7 @@ const DirectChannel: React.FC<{}> = () => {
<Checkbox.Group style={{ width: '100%' }} onChange={onChangeUpShop} value={checkedValues}>
<Row>
{
Array.isArray(shopsOption) && shopsOption.map((item, index) => <Col key={index} span={6}>
Array.isArray(shopsOption) && shopsOption.map((item, index) => <Col key={index} span={8}>
<Checkbox value={item}>{item.name}</Checkbox>
</Col>)
}
......
......@@ -228,9 +228,6 @@ export const addChannelSchema: ISchema = {
placeholder: '请选择品类',
className: 'fixed-ant-selected-down', // 该类强制将显示的下拉框出现在select下, 只有这里出现问题, ??
fetchSearch: PublicApi.getProductSelectGetSelectCategory,
style: {
width: 160
}
}
},
brandId: {
......@@ -239,9 +236,6 @@ export const addChannelSchema: ISchema = {
"x-component-props": {
placeholder: '请选择品牌',
fetchSearch: PublicApi.getProductSelectGetSelectBrand,
style: {
width: 160
}
}
},
parentMemberId: {
......@@ -249,9 +243,6 @@ export const addChannelSchema: ISchema = {
enum: [],
'x-component-props': {
placeholder: '上级渠道',
style: {
width: 160
}
},
},
submit: {
......
......@@ -105,13 +105,13 @@ const viewProducts: React.FC<{}> = () => {
key: 'status',
render: (text:any, record:any) => {
let component: ReactNode = null
if(record.status === 1)
component = (<><span className="commonStatusValid"></span>通过</>)
if(record.status === 4)
component = (<><span className="commonStatusValid"></span>审核通过</>)
else if(record.status === 1)
component = (<><span className="commonStatusInvalid"></span>待提交审核</>)
else if(record.status === 2)
component = (<><span className="commonStatusInvalid"></span>待提交</>)
else if(record.status === 3)
component = (<><span className="commonStatusModify"></span>待审核</>)
else if(record.status === 4)
else if(record.status === 3)
component = (<><span className="commonStatusStop"></span>审核不通过</>)
return component
}
......
......@@ -168,6 +168,11 @@ const Trademark: React.FC<{}> = () => {
},
ctx: {
inline: false,
effects: ($, action) => {
$('onFieldValueChange', 'status').subscribe(state => {
ref.current.reload({current:1, pageSize: 10, status: state.value})
})
},
schema: {
type: 'object',
properties: {
......
import React from 'react'
import DetailPage from '@/components/DetailPage'
import { Card } from 'antd'
import { StandardTable } from 'god'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import { PublicApi } from '@/services/api'
// 订单查询
export interface PurchaseOrderProps {}
const orderColumns = [
{
dataIndex: 'orderId',
title: '订单号'
}
]
const fetchTableData = async (params) => {
return []
}
// 最后一步开始调试 TODO
const PurchaseOrder:React.FC<PurchaseOrderProps> = (props) => {
return <PageHeaderWrapper>
<Card>
<StandardTable
fetchTableData={params => fetchTableData(params)}
columns={orderColumns}
/>
</Card>
</PageHeaderWrapper>
}
PurchaseOrder.defaultProps = {}
export default PurchaseOrder
\ No newline at end of file
import React from 'react';
import styles from '../index.less';
import { Radio } from 'antd';
export interface ButtonListProps {
......@@ -8,10 +7,10 @@ export interface ButtonListProps {
}
const ButtonList: React.FC<ButtonListProps> = (props) => {
return (
<div className={styles.margin320}>
<div className={'margin320'}>
<Radio.Group>
{
props.group.map(v => <Radio.Button value={v.value} key={v.key} className={props.size === 'default' ? styles.default : styles.large}>{v.text}</Radio.Button>)
props.group.map(v => <Radio.Button value={v.value} key={v.key} className={props.size === 'default' ? 'default' : 'large'}>{v.text}</Radio.Button>)
}
</Radio.Group>
</div>
......
......@@ -6,7 +6,6 @@ import {
LockOutlined,
ExclamationCircleFilled
} from '@ant-design/icons';
import styles from '../index.less'
import { PublicApi } from '@/services/api';
import { setAuth, setRouters } from '@/utils/auth';
......@@ -77,7 +76,7 @@ const LoginWrap: React.FC = () => {
<Input.Password prefix={<LockOutlined />} placeholder='请输入密码' size='large' />
</Form.Item>
{validButton && (<Form.Item
className={styles.loginVerBtn}
className={'loginVerBtn'}
>
<Button ghost type='primary' block size='large'>点击进行验证</Button>
</Form.Item>)
......
......@@ -6,7 +6,6 @@ import {
ExclamationCircleFilled
} from '@ant-design/icons';
import QRCode from 'qrcode';
import styles from '../index.less'
const ScanLoginWrap: React.FC = () => {
const [qrCode, setQrCode] = useState('')
......@@ -20,9 +19,9 @@ const ScanLoginWrap: React.FC = () => {
})
return (
<div className={styles.scanLoginWrap}>
<div className={'scanLoginWrap'}>
<h2>扫码登录</h2>
<div className={styles.qrCodeImage}>
<div className={'qrCodeImage'}>
<img src={qrCode} alt=""/>
</div>
</div>
......
import React, { useState, useEffect } from 'react'
import { Form, Steps, Button, Row, Col, Radio, Divider, Tooltip, Upload, message, Input as AntdInput } from 'antd'
import {
UploadOutlined,
QuestionCircleOutlined
} from '@ant-design/icons';
import styles from './index.less'
import './index.less'
import globalStyles from '@/global/styles/global.less'
import cx from 'classnames'
import { Link, history } from 'umi'
import im_success from '../../../mockStatic/im_success.png'
import { createFormActions, FormEffectHooks } from '@formily/antd';
import useCountDown from '@/utils/hooks';
import { GlobalConfig } from '@/global/config';
import { omit, transFormSchema } from '@/utils';
import { PATTERN_MAPS } from '@/constants/regExp';
import { PublicApi } from '@/services/api';
import NiceForm from '@/components/NiceForm';
import schemas from './schema';
const { onFieldValueChange$ } = FormEffectHooks
let formCache: any = {}
const CustomInput = props => {
const { help, ...restProps } = props
return (
<AntdInput
{...restProps}
addonAfter={help ? <Tooltip title={help}><QuestionCircleOutlined style={{color: '#6B778C', marginLeft: 5}}/></Tooltip> : undefined}
/>
)
}
// 检验联动
const useLinkageValidateEffects = () => {
const { setFieldState, getFieldState } = createFormActions()
onFieldValueChange$('*(password,confirmPassword)').subscribe(fieldState => {
const selfName = fieldState.name
const selfValue = fieldState.value
const otherName = selfName == 'password' ? 'confirmPassword' : 'password'
const otherValue = getFieldState(otherName, state => state.value)
setFieldState(otherName, state => {
if (selfValue && otherValue && selfValue !== otherValue) {
state.errors = ['两次密码输入不一致']
} else {
state.errors = ['']
}
})
setFieldState(selfName, state => {
if (selfValue && otherValue && selfValue !== otherValue) {
state.errors = ['两次密码输入不一致']
} else {
state.errors = ['']
}
})
})
}
let timeChange: any; // 定时器
const actions = createFormActions()
const UserForgetPwd = () => {
const [current, setCurrent] = useState(0)
const [subStep, setSubStep] = useState(false)
const stepList = [
{ title: '填写信息', key: 'message', name: 'message' },
{ title: '完善资料', key: 'over', name: 'over' },
{ title: '等待审核', key: 'wait', name: 'wait' },
{ title: '注册成功', key: 'success', name: 'success' },
]
const [time, setTime] = useState(5); // timer
// useEffect(() => {
// clearInterval(timeChange)
// handleRegisterTypeList()
// }, [])
const [asyncSchema, setAsyncSchema] = useState(() => {
return schemas[`schema${current}`]
})
useEffect(() => {
setAsyncSchema(schemas[`schema${current}`])
if(current === 2) runTimerJump()
}, [current, actions])
useEffect(() => {
if(time === 0){
clearInterval(timeChange)
setTime(60)
history.push('/user/login')
console.log('执行登录跳转!')
}
}, [time])
const runTimerJump = () => {
timeChange = setInterval(() => setTime(t => --t), 1000)
}
const normFile = (e: any) => {
if (Array.isArray(e)) {
return e;
}
return e && e.fileList;
}
const checkoutFile = (rule: any, value: any) => {
if(value && value.length){
let length = value.length
let obj = value[length-1]
const isLt5M = obj.size / 1024 / 1024 < 5;
if (isLt5M) {
return Promise.resolve();
}else{
return Promise.reject('附件大小不能超过5M!');
}
}else{
return Promise.reject();
}
}
const beforeUpload = (file: any) => {
const isLt5M = file.size / 1024 / 1024 < 5;
if (!isLt5M) {
message.error('附件大小不能超过5M!');
}
console.log(isLt5M)
return isLt5M;
}
const {text, isActive, start} = useCountDown({
maxTime: 60,
minTime: 0,
initText: '获取验证码',
onEnd: () => {},
decayRate: 1,
delay: 1 * 1000
})
const handleActionBtn = () => {
// 校验后触发跳转
actions.submit(data => {
actions.dispatch('onFormStepNext', {})
formCache = Object.assign({}, formCache, data)
}).then(() => {
setCurrent(current + 1)
})
}
const nextStepAction = () => {
actions.submit().then(data => {
const { values } = data
formCache = Object.assign({}, values, formCache)
const { businessTypeId, typeId } = values
PublicApi.getMemberMenuRegisterDetail({
businessTypeId,
memberTypeId: typeId
}).then(res => {
const { data } = res
// 动态渲染第三步
setAsyncSchema(transFormSchema(data))
setSubStep(true)
})
})
}
// @todo 注册成功后 交互功能未完成
const submitForm = () => {
actions.submit().then(data => {
const { values } = data
formCache = Object.assign({}, values, formCache)
// 写死传入的区号
formCache.countryCode = '+86'
const params = omit(formCache, ['isRead', 'confirmPassword'])
PublicApi.postMemberRegister(params).then(() => {
actions.dispatch('onFormStepNext', {})
setCurrent(current + 1)
})
})
}
return (
<div className={cx(styles.register, globalStyles.lingxiBusinessContent1024)}>
<h3>找回密码</h3>
<div className={cx(styles.registerBox, globalStyles.lingxiBusinessMarginContent)}>
<NiceForm
id='registerForm'
schema={asyncSchema}
actions={actions}
components={{
CustomInput
}}
effects={() => {
useLinkageValidateEffects()
}}
expressionScope={{
current: false,
phoneBefore: <div className={styles.formBefore}>+86</div>,
smsCodeAfter: <Button disabled={isActive} style={{minWidth: 110, marginLeft: 8}} size='large' onClick={start}>{text}</Button>,
checkBoxChildren: <span style={{fontSize: 12}}>阅读并同意<span className='commonPickColor'>《会员服务协议》《法律条款》《隐私政策》</span></span>,
memberTypeTitle: <span className={styles.commonPanelTitle}>请选择您的身份</span>,
businessTypeTitle: <span className={styles.commonPanelTitle}>请选择您要开展的业务</span>,
}}
/>
</div>
</div>
)
}
export default UserForgetPwd
\ No newline at end of file
@import '~@/global/styles/global.less';
#root {
.login-item {
flex: 1;
}
.login-ctl {
position: relative;
background: @white;
}
.loginWrap {
padding: 141px 0 102px;
}
.loginMain {
position: relative;
background: @white;
padding: 64px 56px 0;
color: #6B778C;
&>h2 {
font-size: 32px;
margin-bottom: 32px;
.loginItem {
flex: 1;
}
.clickUsernameLogin {
.ab-position(right, top, 8, 8);
font-size: 14px;
color: rgba(107, 119, 140, 1);
.loginCtl {
position: relative;
background: @white;
}
.clickScanLogin {
// .center-text();
.ab-position(right, top, 8, 8);
width: 32px;
height: 32px;
background: url("../../../mockStatic/qr_code1.png") center center no-repeat;
.loginWrap {
padding: 141px 0 102px;
}
.readyLogin {
text-align: center;
margin-top: 24px;
}
.loginMain {
position: relative;
background: @white;
padding: 64px 56px 0;
color: #6B778C;
&>h2 {
font-size: 32px;
margin-bottom: 32px;
}
.clickUsernameLogin {
.ab-position(right, top, 8, 8);
font-size: 14px;
color: rgba(107, 119, 140, 1);
}
.clickScanLogin {
// .center-text();
.ab-position(right, top, 8, 8);
width: 32px;
height: 32px;
background: url("../../../mockStatic/qr_code1.png") center center no-repeat;
background-size: cover;
&:hover {
background: url("../../../mockStatic/qr_code2.png") center center no-repeat;
}
}
.scanTips {
.make-center(flex);
font-size: 12px;
color: rgba(107, 119, 140, 1);
.scanIcon {
font-size: 30px;
margin-right: @margin-sm;
}
}
}
.loginDesc {
background: url("../../../mockStatic/image_ad.png") center center no-repeat;
background-size: cover;
&:hover {
background: url("../../../mockStatic/qr_code2.png") center center no-repeat;
.adBox {
color: @white;
.make-center(text);
& h2 {
margin-top: 20px;
.font-height-color(32, 80, @white);
letter-spacing: 2px;
}
& p {
padding: 10px 60px;
text-indent: 2em;
}
}
}
.scanTips {
.make-center(flex);
font-size: 12px;
color: rgba(107, 119, 140, 1);
.scanIcon {
font-size: 30px;
margin-right: @margin-sm;
.thirdLogin {
height: 64px;
background: #FAFBFC;
margin-top: 90px;
& a {
margin-left: 6px;
.make-center(text);
vertical-align: middle;
}
}
}
.loginDesc {
background: url("../../../mockStatic/image_ad.png") center center no-repeat;
background-size: cover;
.adBox {
color: @white;
.loginVerBtn {
background: #EBF7F2;
}
.scanLoginWrap {
.make-center(text);
& h2 {
margin-top: 20px;
.font-height-color(32, 80, @white);
letter-spacing: 2px;
&>h2 {
color: #6B778C;
}
& p {
padding: 10px 60px;
text-indent: 2em;
.qrCodeImage {
.make-center(text);
width: 224px;
height: 224px;
.make-center-space(margin, 30, 18);
&>img {
.make-center(block);
width: 100%;
height: 100%;
}
}
}
}
.thirdLogin {
height: 64px;
background: #FAFBFC;
margin-top: 90px;
& a {
margin-left: 6px;
.make-center(text);
vertical-align: middle;
.mr_t-40 {
margin-top: 40px;
}
}
.loginVerBtn {
background: #EBF7F2;
}
.scanLoginWrap {
.make-center(text);
&>h2 {
color: #6B778C;
.mr_t-24 {
margin-top: 24px;
}
.qrCodeImage {
.make-center(text);
width: 224px;
height: 224px;
.make-center-space(margin, 30, 18);
&>img {
.make-center(block);
width: 100%;
height: 100%;
// register
.register {
// width: 100%;
&>h3 {
padding: 40px 0;
.make-center(text);
font-size: 32px;
margin-bottom: 0;
}
}
}
// register
.register {
// width: 100%;
&>h3 {
padding: 40px 0;
.registerForm {
max-width: 335px;
margin: 0px auto;
padding-top: 40px;
}
.registerBox {
width: 100%;
min-height: 700px;
padding-bottom: 40px;
background: #fff;
padding-bottom: 40px;
.stepWrap {
height: 72px;
background: #FAFBFC;
padding: 0 115px;
.make-center(flexAlign);
}
}
.formBoxStep1 {
width: 324px;
.make-center-space(margin, 40, 0);
}
.formBefore {
width: 54px;
.font-height-color(undefined, 40, #42526E, #F4F5F7);
.make-center(text);
font-size: 32px;
margin-bottom: 0;
border: 1px solid #DFE1E6;
border-right: 0;
}
}
.registerForm {
max-width: 335px;
margin: 0px auto;
padding-top: 40px;
}
.registerBox {
width: 100%;
min-height: 700px;
padding-bottom: 40px;
background: #fff;
padding-bottom: 40px;
.stepWrap {
height: 72px;
background: #FAFBFC;
padding: 0 115px;
.make-center(flexAlign);
.formBoxStep2 {
width: 704px;
.make-center(margin);
& h3 {
margin-top: 48px;
}
}
}
.formBoxStep1 {
width: 324px;
.make-center-space(margin, 40, 0);
}
.formBefore {
width: 54px;
.font-height-color(undefined, 40, #42526E, #F4F5F7);
.make-center(text);
border: 1px solid #DFE1E6;
border-right: 0;
}
.formBoxStep2 {
width: 704px;
.make-center(margin);
& h3 {
margin-top: 48px;
.continueButton {
.make-center(block);
width: 340px;
height: 40px;
.make-center-space(margin, 8);
}
}
.continueButton {
.make-center(block);
width: 340px;
height: 40px;
.make-center-space(margin, 8);
}
.formBoxStep3 {
width: 704px;
.make-center(margin);
.make-center(text);
& .description {
margin-bottom: 40px;
& p {
.font-height-color(14, 20, #42526e);
.formBoxStep3 {
width: 704px;
.make-center(margin);
.make-center(text);
& .description {
margin-bottom: 40px;
& p {
.font-height-color(14, 20, #42526e);
}
}
&.guid {
.font-height-color(14, 22, #6b778c);
}
& h2 {
font-size: 24px;
color: rgba(23, 43, 77, 1);
margin: 24px 0;
}
& img {
display: block;
.make-center(margin);
}
}
&.guid {
.font-height-color(14, 22, #6b778c);
.agreement {
font-size: 12px;
}
& h2 {
font-size: 24px;
color: rgba(23, 43, 77, 1);
margin: 24px 0;
.checkTypes {
width: 702px;
.make-center(margin);
}
& img {
display: block;
.margin320 {
width: 320px;
.make-center(margin);
display: block;
}
}
.agreement {
font-size: 12px;
}
.checkTypes {
width: 702px;
.make-center(margin);
}
.margin320 {
width: 320px;
.make-center(margin);
display: block;
}
.default {
width: 148px;
margin-right: 24px;
margin-bottom: 16px;
.make-center(text);
height: 32px;
line-height: 32px;
&:nth-child(2n) {
margin-right: 0;
.default {
width: 148px;
margin-right: 24px;
margin-bottom: 16px;
.make-center(text);
height: 32px;
line-height: 32px;
&:nth-child(2n) {
margin-right: 0;
}
}
}
.large {
width: 320px;
margin-bottom: 24px;
.make-center(text);
height: 48px;
line-height: 48px;
}
.btnCenter {
width: 320px;
.make-center(margin);
display: block;
}
// get back password
.getBackBox {
&>h2 {
width: 100%;
.large {
width: 320px;
margin-bottom: 24px;
.make-center(text);
.font-height-color(24, 120, #172B4D);
height: 48px;
line-height: 48px;
}
.getBackForm {
background-color: @white;
.formBox {
width: 320px;
.make-center-space(margin, 40, 40);
.back {
width: 100%;
.make-center(block);
.make-center(text);
color: #6B778C;
.btnCenter {
width: 320px;
.make-center(margin);
display: block;
}
// get back password
.getBackBox {
&>h2 {
width: 100%;
.make-center(text);
.font-height-color(24, 120, #172B4D);
}
.getBackForm {
background-color: @white;
.formBox {
width: 320px;
.make-center-space(margin, 40, 40);
.back {
width: 100%;
.make-center(block);
.make-center(text);
color: #6B778C;
}
}
}
}
}
// policy
.policyBox {
width: 100%;
// height: 100vh;
background-color: #fff;
&>h1 {
.font-height-color(24, 96, #172B4D, #F4F5F7);
.make-center(text)
}
& article {
padding-bottom: 200px;
h4 {
width: 96px;
.font-height-color(16, 48, #172b4d);
font-weight: 500;
margin-top: 24px;
// policy
.policyBox {
width: 100%;
// height: 100vh;
background-color: #fff;
&>h1 {
.font-height-color(24, 96, #172B4D, #F4F5F7);
.make-center(text)
}
p {
font-size: 14px;
color: rgba(66, 82, 110, 1);
line-height: 22px;
& article {
padding-bottom: 200px;
h4 {
width: 96px;
.font-height-color(16, 48, #172b4d);
font-weight: 500;
margin-top: 24px;
}
p {
font-size: 14px;
color: rgba(66, 82, 110, 1);
line-height: 22px;
}
}
}
}
.mr_t-40 {
margin-top: 40px;
}
.mr_t-24 {
margin-top: 24px;
}
\ No newline at end of file
import React, { useState } from 'react';
import globalStyles from '@/global/styles/global.less';
import styles from './index.less'
import './index.less'
import cx from 'classnames';
import { Row, Col, Form, Input, Button, Space } from 'antd';
import TextLink from '@/components/TextLink';
......@@ -29,30 +29,30 @@ const User: React.FC = () => {
}
return (
<Row className={cx(styles.loginWrap, globalStyles.lingxiBusinessContent1024)}>
<Col className={cx(styles.loginItem, styles.loginDesc)}>
<div className={styles.adBox}>
<Row className={cx('loginWrap', globalStyles.lingxiBusinessContent1024)}>
<Col className={cx('loginItem', 'loginDesc')}>
<div className={'adBox'}>
{/*<img src={leftPicture} alt="数商云"/>*/}
<h2>欢迎来到数商云</h2>
<p>数商云是知名云计算及数据服务提供商,在海量文件存储、CDN 内容分发、视频点播、互动直播及大规模异构数据的智能分析与处理等技术深度投入,致力以数据科技驱动数字化未来,赋能各行业全面进入数据时代。</p>
</div>
</Col>
<Col className={cx(styles.loginItem, styles.loginCtl)}>
<div className={styles.loginMain}>
<Col className={cx('loginItem', 'loginCtl')}>
<div className={'loginMain'}>
{/*<a className={styles.guideLogin} />*/}
{/*{ isScanQrCode ? <></> : <h2>欢迎您</h2>}*/}
{ isScanQrCode ? (
<>
<a onClick={()=>handleGuideLogin(false)} className={styles.clickUsernameLogin}>使用账号密码登录</a>
<a onClick={()=>handleGuideLogin(false)} className={'clickUsernameLogin'}>使用账号密码登录</a>
<ScanLoginWrap/>
<div className={styles.scanTips}>
<ScanOutlined className={styles.scanIcon} />
<div className={'scanTips'}>
<ScanOutlined className={'scanIcon'} />
<span>打开 App<br />扫一扫登录</span>
</div>
</>
) : (
<>
<a onClick={()=>handleGuideLogin(true)} className={styles.clickScanLogin} />
<a onClick={()=>handleGuideLogin(true)} className={'clickScanLogin'} />
<h2>欢迎您</h2>
<LoginWrap/>
<Row justify='end' style={{marginTop: 16}}>
......@@ -65,7 +65,7 @@ const User: React.FC = () => {
)
}
</div>
<Row className={styles.thirdLogin} align='middle' justify='center'>
<Row className={'thirdLogin'} align='middle' justify='center'>
<Col>其他方式登录
<a title="微信登陆"><img src={wechat} alt="微信登录"/></a>
<a title="QQ登录"><img src={qq} alt="QQ登录"/></a>
......
......@@ -4,7 +4,6 @@ import {
UploadOutlined,
QuestionCircleOutlined
} from '@ant-design/icons';
import styles from './index.less'
import './index.less'
import globalStyles from '@/global/styles/global.less'
import cx from 'classnames'
......@@ -14,7 +13,7 @@ import { FormStep, FormBlock, Input, Password, Checkbox, setup } from '@formily/
import SchemaForm, { Field, FormMegaLayout, FormButtonGroup, createFormActions, FormEffectHooks } from '@formily/antd';
import useCountDown from '@/utils/hooks';
import { GlobalConfig } from '@/global/config';
import { omit, transFormSchema } from '@/utils';
import { omit, transFormSchema, filterUndef } from '@/utils';
import { PATTERN_MAPS } from '@/constants/regExp';
import { PublicApi } from '@/services/api';
import NiceForm from '@/components/NiceForm';
......@@ -150,16 +149,20 @@ const UserRegistry = () => {
const nextStepAction = () => {
actions.submit().then(data => {
const { values } = data
formCache = Object.assign({}, values, formCache)
formCache = Object.assign({},formCache, filterUndef(values))
const { businessTypeId, typeId } = values
PublicApi.getMemberMenuRegisterDetail({
businessTypeId,
memberTypeId: typeId
}).then(res => {
const { data } = res
// 动态渲染第三步
setAsyncSchema(transFormSchema(data))
setSubStep(true)
const { data, code } = res
if (code === 1000) {
// 动态渲染第三步
setAsyncSchema(transFormSchema(data))
setSubStep(true)
}
}).catch(() => {
})
})
}
......@@ -168,22 +171,28 @@ const UserRegistry = () => {
const submitForm = () => {
actions.submit().then(data => {
const { values } = data
formCache = Object.assign({}, values, formCache)
formCache = Object.assign({}, formCache, filterUndef(values))
// 写死传入的区号
formCache.countryCode = '+86'
const params = omit(formCache, ['isRead', 'confirmPassword'])
PublicApi.postMemberRegister(params).then(() => {
actions.dispatch('onFormStepNext', {})
setCurrent(current + 1)
PublicApi.postMemberRegister(params).then(({code}) => {
if (code === 1000) {
actions.dispatch('onFormStepNext', {})
setCurrent(current + 1)
formCache = {}
}
}).catch(() => {
// 调用接口后 失败需清空缓存的数据
formCache = {}
})
})
}
return (
<div className={cx(styles.register, globalStyles.lingxiBusinessContent1024)}>
<div className={cx('register', globalStyles.lingxiBusinessContent1024)}>
<h3>欢迎您注册数商云账号</h3>
<div className={cx(styles.registerBox, globalStyles.lingxiBusinessMarginContent)}>
<Steps current={current} className={styles.stepWrap} size='small'>
<div className={cx('registerBox', globalStyles.lingxiBusinessMarginContent)}>
<Steps current={current} className={'stepWrap'} size='small'>
{ stepList.map(v => <Steps.Step title={v.title} key={v.key}></Steps.Step>) }
</Steps>
<NiceForm
......@@ -198,43 +207,44 @@ const UserRegistry = () => {
}}
expressionScope={{
current: false,
phoneBefore: <div className={styles.formBefore}>+86</div>,
phoneBefore: <div className={'formBefore'}>+86</div>,
smsCodeAfter: <Button disabled={isActive} style={{minWidth: 110, marginLeft: 8}} size='large' onClick={start}>{text}</Button>,
checkBoxChildren: <span style={{fontSize: 12}}>阅读并同意<span className='commonPickColor'>《会员服务协议》《法律条款》《隐私政策》</span></span>,
memberTypeTitle: <span className={styles.commonPanelTitle}>请选择您的身份</span>,
businessTypeTitle: <span className={styles.commonPanelTitle}>请选择您要开展的业务</span>,
memberTypeTitle: <span className={'commonPanelTitle'}>请选择您的身份</span>,
businessTypeTitle: <span className={'commonPanelTitle'}>请选择您要开展的业务</span>,
}}
/>
<div className={styles.registerForm}>
<div className={cx('registerForm', 'global-block-center')}>
{
current === 0 &&
<Button type='primary' className={styles.continueButton} onClick={handleActionBtn}>同意协议并注册</Button>
<Button type='primary' className={'continueButton'} onClick={handleActionBtn}>同意协议并注册</Button>
}
{
current === 1 && !subStep &&
<Button type='primary' className={styles.continueButton} onClick={nextStepAction}>下一步:继续完善</Button>
<Button type='primary' className={'continueButton'} onClick={nextStepAction}>下一步:继续完善</Button>
}
{
current === 1 && subStep &&
<Button type='primary' className={styles.continueButton} onClick={submitForm}>提交注册资料</Button>
<Button type='primary' className={'continueButton'} onClick={submitForm}>提交注册资料</Button>
}
</div>
{
current === 2 &&
<div className={styles.formBoxStep3}>
<div className={'formBoxStep3'}>
<img src={im_success} alt="待审核"/>
<h2>您的注册资料已经提交成功,请等待平台审核</h2>
<div className={styles.description}>
<div className={'description'}>
<p>审核结果会以短信通知您</p>
<p>您也可以登录平台查看审核结果</p>
</div>
<p className={styles.guid}>
<p className={'guid'}>
<span>{time}s 后自动跳转至登录页</span>
<br />
<span><Link to="/user/login">立即跳转</Link></span>
</p>
</div>
}
<p className={'readyLogin'}>已有平台账号? <Link to="/user/login">去登陆</Link></p>
</div>
</div>
)
......
......@@ -9,7 +9,7 @@ export const registerStep0Schema: ISchema = {
type: 'object',
"x-component": 'mega-layout',
"x-component-props": {
className: 'registerForm',
className: 'registerForm global-block-center',
full: true
},
properties: {
......@@ -106,7 +106,7 @@ export const registerStep1Schema: ISchema = {
type: 'object',
"x-component": 'mega-layout',
"x-component-props": {
className: 'formBoxStep2'
className: 'formBoxStep2 global-block-center'
},
properties: {
BLOCK_LAYOUT1: {
......@@ -162,6 +162,38 @@ export const registerStep1Schema: ISchema = {
}
}
// 忘记密码 TODO
export const forgetPwdSchema: ISchema = {
type: 'object',
properties: {
FORGET_PWD: {
type: 'object',
"x-component": 'mega-layout',
"x-component-props": {
className: 'registerForm global-block-center',
full: true
},
properties: {
email: {
type: 'string',
"x-rules": [
{
pattern: PATTERN_MAPS.email,
message: '请输入正确的邮箱'
}
],
"x-component-props": {
placeholder: '请输入你的邮箱(选填)',
size: 'large',
type: 'email'
}
},
}
}
}
}
export default {
schema0: registerStep0Schema,
schema1: registerStep1Schema
......
......@@ -331,6 +331,17 @@ export const getFieldType = (field) => {
}
}
// 过滤掉undefined属性
export const filterUndef = (originObj) => {
const r = {}
for (const item in originObj) {
if (originObj[item] !== undefined) {
r[item] = originObj[item]
}
}
return r
}
// 树形结构降为一维对象处理
export const treeReduction = (data: any[]) => {
const hashMaps = {}
......
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