Commit 6fec3ca3 authored by 武广's avatar 武广

Merge branch 'feat/constructionOne' of git.quantgroup.cn:ui/merchant-manage-ui...

Merge branch 'feat/constructionOne' of git.quantgroup.cn:ui/merchant-manage-ui into feature/20230327_public_takeaway
parents 3129b404 0f7c1776
......@@ -273,6 +273,18 @@ export default {
name: 'systemManageLog',
component: './systemManage/Log',
},
{
title: '商户管理后台-合同查看',
path: '/contractView',
name: 'contractView',
component: './contractView',
},
{
title: '商户管理后台-商家资料',
path: '/businessInfo',
name: 'businessInfo',
component: './businessManage/info',
},
{
component: './404',
},
......
This source diff could not be displayed because it is too large. You can view the blob instead.
import React, { useState } from 'react';
import { Map, Marker, ZoomControl, CityListControl } from 'react-bmapgl';
import { Modal, Input } from 'antd';
export default props => {
const { visible, onSetPoint, onCancel, lngLat } = props;
const defaultLnglat = { lng: 116.404449, lat: 39.914889 };
if (lngLat) {
defaultLnglat.lng = lngLat.lng;
defaultLnglat.lat = lngLat.lat;
}
const [lnglatPoint, setLnglatPoint] = useState(defaultLnglat);
const [lnglatText, setLnglatText] = useState(`${defaultLnglat.lng},${defaultLnglat.lat}`);
const handleOk = () => {
onSetPoint(lnglatPoint);
onCancel(true);
};
const handleCancle = () => onCancel(true);
const onGetPoint = e => {
setLnglatPoint({
lng: e.latlng.lng,
lat: e.latlng.lat,
});
setLnglatText(`${e.latlng.lng},${e.latlng.lat}`);
};
return (
<Modal
title="门店信息"
visible={visible}
width="800px"
onOk={() => handleOk()}
onCancel={() => handleCancle()}
>
<div style={{ marginBottom: '20px' }}>
<Input value={lnglatText} placeholder="点击地图选择经纬度" />
</div>
<div style={{ width: '100%', height: '360px' }}>
<Map
center={lnglatPoint}
enableScrollWheelZoom
enableDoubleClickZoom
coordType="gcj02"
onClick={e => onGetPoint(e)}
zoom={15}
>
<Marker
position={lnglatPoint}
Icon
coordType="gcj02"
autoViewport
viewportOptions={{
zoomFactor: -12,
}}
/>
<CityListControl />
<ZoomControl />
</Map>
</div>
</Modal>
);
};
import React from 'react';
import moment from 'moment';
import { PlusOutlined } from '@ant-design/icons';
import { notification, Tag, Tooltip, Input } from 'antd';
import {
uploadFile,
apiCategoryList,
apiAddrArea,
apiServiceFacility,
apiBusinessDetail,
apiBankList,
} from '../service';
export const wrapperCol = {
xs: { span: 24 },
sm: { span: 12 },
};
export const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 8 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
};
export const businessTypeDesc = {
1: '到家业务',
2: '实物业务',
3: '到店业务',
};
// 业务模式
export const businessModel = [
{ label: '到家外卖业务(外卖配送业务)', value: 1 },
{ label: '实物商品业务员', value: 2 },
{ label: '到店业务(服务类业务)', value: 3 },
];
export const signDateTypeList = [{ label: '自商品售卖起默认一年', value: 1 }];
export const legalPersonList = [{ label: '长期', value: '长期' }];
// 获取申请信息
export async function getInfo() {
const data = await apiBusinessDetail();
let settlementType = 1;
const res = data.data;
if (res) {
if (res.facilities) {
res.customList = res.facilities.customList || [];
res.selfList = res.facilities.selfList || [];
}
res.signDateType = [res.signDateType] || [];
res.accountOpenPermitImage = res.accountOpenPermitImage
? [{ uid: 0, url: res.accountOpenPermitImage }]
: [];
res.businessLicenseImage = res.businessLicenseImage
? [{ uid: 0, url: res.businessLicenseImage }]
: [];
res.idCardEmblemImage = res.idCardEmblemImage ? [{ uid: 0, url: res.idCardEmblemImage }] : [];
res.idCardPortraitImage = res.idCardPortraitImage
? [{ uid: 0, url: res.idCardPortraitImage }]
: [];
res.primaryImage = res.primaryImage ? [{ uid: 0, url: res.primaryImage }] : [];
res.sealImage = res.sealImage ? [{ uid: 0, url: res.sealImage }] : [];
res.brandCertificate = res.brandCertificate ? [{ uid: 0, url: res.brandCertificate }] : [];
// 非同名结算授权文件
res.differentNameAuthorizationImage = res.differentNameAuthorizationImage
? [{ uid: 0, url: res.brandCertificate }]
: [];
// 户口本本人页
res.householdRegisterImage = res.householdRegisterImage
? [{ uid: 0, url: res.householdRegisterImage }]
: [];
// 工商局
res.icbProofImage = res.icbProofImage ? [{ uid: 0, url: res.icbProofImage }] : [];
if (res.categoryQualificateImage) {
res.categoryQualificateImage = [{ uid: 0, url: res.categoryQualificateImage }];
}
if (res.otherImage && res.otherImage.length) {
res.otherImage = res.otherImage.map((item, index) => ({
uid: index,
url: item,
}));
}
res.addr = [res.provinceId, res.cityId, res.countyId];
if (res.townId) {
res.addr.push(res.townId);
}
settlementType = +res.settlementType;
}
// 身份证有效期处理
const date = res.legalPersonPeriod.split('-') || [];
res.legalPersonStart = date[0] && moment(date[0]);
res.legalPersonEnd = date[1] && date[1] !== '长期' ? moment(date[1]) : '';
res.checked = date[1] && date[1] === '长期' ? ['长期'] : [];
const checkboxDisabled = date[1] && date[1] === '长期';
res.businessLicensePeriod = res.businessLicensePeriod && moment(res.businessLicensePeriod);
const companyNamedis = !!res.companyName;
// 获取主营类目
let categoryList = [];
if (res.productBusiness.length) {
const dataList = await apiCategoryList(res.productBusiness);
categoryList = dataList.data;
}
this.setState({
settlementType,
businessInfo: res,
checkboxDisabled,
companyNamedis,
categoryList,
mainCategoryId: res.mainCategoryId,
});
}
// 删除图片
function delImg(keyName, e) {
this.setState(state => {
state.businessInfo[keyName].splice(e.uid, 1);
return {
businessInfo: state.businessInfo,
};
});
}
// 上传图片
export function uploadPropsFn(
{ keyName, limit = 1, maxSize = 1024 * 1024 * 5, maxSizeMsg = '文件大小不能超过5M!', type = 0 },
successCallback = () => {},
) {
const that = this;
let timer = null;
return {
maxSize,
async customRequest(info) {
const { file } = info;
if (info.file.size > maxSize) {
notification.error({ message: maxSizeMsg });
return;
}
if (that.state.businessInfo[keyName] && that.state.businessInfo[keyName].length >= limit) {
notification.error({ message: `最多只能上传${limit}个文件!` });
return;
}
const res = await uploadFile([file], type);
if (res.businessCode !== '0000') {
return;
}
const url = res.data?.[0];
that.setState(state => {
const imgList = state.businessInfo[keyName] || [];
const attachment = {
uid: imgList.length || 0,
name: file?.name,
status: 'done',
url,
};
imgList.push(attachment);
if (imgList.length <= limit) {
state.businessInfo[keyName] = imgList;
} else {
notification.error({ message: `最多只能上传${limit}个文件!` });
}
return {
businessInfo: state.businessInfo,
};
});
successCallback(keyName, url);
// 需要把上传的数据存储下来
},
disabled: this.state.disabled,
multiple: limit > 1,
listType: 'picture-card',
showUploadList: true,
accept: '.png,.bmp,.gif,.jpeg,.jpg',
onRemove: e => delImg.call(this, keyName, e),
beforeUpload: (e, flist) => {
const imgList = that.state.businessInfo[keyName] || [];
if (flist.length + imgList.length > limit) {
clearTimeout(timer);
timer = setTimeout(() => {
notification.error({ message: `最多只能上传${limit}个文件!` });
}, 100);
return false;
}
return true;
},
};
}
/** **** 自定义服务设施 start ***************************** */
// 关闭标签输入框
function handleClose(removedTag) {
this.setState(state => {
state.businessInfo.customList = state.businessInfo.customList.filter(tag => tag !== removedTag);
return {
businessInfo: state.businessInfo,
};
});
}
// 显示标签输入框
function showInput() {
this.setState({ tagVisible: true }, () => this.input.focus());
}
// 标签内容改变
function handleInputChange(e) {
if (e && e.target) {
this.setState({ tagValue: e.target.value });
}
}
// 保存标签
function handleInputConfirm() {
const { tagValue } = this.state;
if (tagValue) {
let { customList } = this.state.businessInfo;
if (tagValue && customList.indexOf(tagValue) === -1) {
customList = [...customList, tagValue];
}
this.setState(state => {
state.businessInfo.customList = customList;
return {
businessInfo: state.businessInfo,
tagVisible: false,
tagValue: '',
};
});
}
}
// 渲染标签
export function renderServiceTags() {
const that = this;
return (
<div>
{that.state.businessInfo.customList &&
that.state.businessInfo.customList.map(tag => {
const isLongTag = tag.length > 20;
const tagElem = (
<Tag key={tag} closable onClose={() => handleClose.call(that, tag)}>
{isLongTag ? `${tag.slice(0, 20)}...` : tag}
</Tag>
);
return isLongTag ? (
<Tooltip title={tag} key={tag}>
{tagElem}
</Tooltip>
) : (
tagElem
);
})}
{that.state.tagVisible && (
<Input
// eslint-disable-next-line react/no-this-in-sfc
ref={this.saveInputRef}
type="text"
size="small"
style={{ width: 78 }}
value={that.state.tagValue}
onChange={e => handleInputChange.call(that, e)}
onBlur={e => handleInputConfirm.call(that, e)}
onPressEnter={e => handleInputConfirm.call(that, e)}
/>
)}
{!that.state.tagVisible && (
<Tag
onClick={() => showInput.call(that)}
style={{ background: '#fff', borderStyle: 'dashed' }}
>
<PlusOutlined /> 新增
</Tag>
)}
</div>
);
}
/** **** 自定义服务设施 end ***************************** */
// 获取服务设施
export async function getServiceFacility() {
const res = await apiServiceFacility();
if (res.data) {
this.setState({
serviceFacilitys: res.data,
});
}
}
// 开户行
export async function getBankList() {
const res = await apiBankList();
if (res.data) {
this.setState({
bankList: res.data,
});
}
}
// 获取地址省
export async function getAreaAddr() {
const data = await apiAddrArea();
const areaAddr = data.data || null;
if (areaAddr) {
const res = areaAddr.map(item => ({
isLeaf: false,
loading: false,
label: item.addrName,
value: item.addrId,
}));
console.log(this.state.businessInfo, '......');
// 编辑时 回显 市、区、街道
if (this.state.businessInfo.provinceId) {
const pros = res.filter(item => +item.value === +this.state.businessInfo.provinceId);
await loadData.call(this, pros);
const citys = pros[0].children.filter(
item => +item.value === +this.state.businessInfo.cityId,
);
await loadData.call(this, citys);
if (this.state.businessInfo.townId) {
const countys = citys[0].children.filter(
item => +item.value === +this.state.businessInfo.countyId,
);
await loadData.call(this, countys);
}
}
this.setState({
areaAddr: res,
});
}
}
// 获取市区街道
export async function loadData(selectedOptions) {
const targetOption = selectedOptions[selectedOptions.length - 1];
targetOption.loading = true;
const data = await apiAddrArea({
parentId: targetOption.value,
});
const areaAddr = data.data || null;
if (areaAddr) {
const children = areaAddr.map(item => ({
isLeaf: +item.addrLevel === 4,
loading: false,
label: item.addrName,
value: item.addrId,
}));
targetOption.loading = false;
if (children.length > 0) {
targetOption.children = children;
} else {
targetOption.isLeaf = true;
}
this.setState({
// eslint-disable-next-line react/no-access-state-in-setstate
areaAddr: [...this.state.areaAddr],
});
}
}
import React, { Component } from 'react';
import { history } from 'umi';
import moment from 'moment';
import { ArrowRightOutlined, UploadOutlined } from '@ant-design/icons';
import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css';
import {
Select,
Input,
Radio,
Checkbox,
DatePicker,
Upload,
Button,
Card,
Row,
Col,
Cascader,
notification,
Spin,
Tabs,
} from 'antd';
import styles from './style.less';
import {
wrapperCol,
uploadPropsFn,
formItemLayout,
renderServiceTags,
loadData,
getAreaAddr,
getServiceFacility,
businessModel,
getInfo,
getBankList,
businessTypeDesc,
signDateTypeList,
legalPersonList,
} from './data';
import { validatePhone, validateEMail, validNumber } from '@/utils/validator';
import { getErrorMessage } from '@/utils/utils';
import MapModal from '@/components/BaiduMap';
import { apiCategoryList, apiEditStoreInfo, apiRecognize, apiRevision } from '../service';
import {
infoTypeFind,
infoTypeChecked,
infoTypeEdit,
infoTypeRevision,
infoTypeInfo,
} from '../staticdata';
const { Option } = Select;
const { Item: FormItem } = Form;
const { RangePicker } = DatePicker;
const { TabPane } = Tabs;
class BusinessInfo extends Component {
getFieldDecorator = this.props?.form?.getFieldDecorator;
setFieldsValue = this.props?.form?.setFieldsValue;
state = {
id: null,
type: infoTypeFind,
businessInfo: {
customList: [],
settlementType: 1,
companyType: '',
},
areaAddr: [], // 四级地址列表
categoryList: [], // 主要类目
serviceFacilitys: [], // 服务设施
bankList: [], // 开户行
// eslint-disable-next-line react/no-unused-state
tagVisible: false,
// eslint-disable-next-line react/no-unused-state
tagValue: '',
settlementType: 1,
loading: false,
visibleMap: false,
visibleLoading: false,
calculateType: [1, 1],
checkboxDisabled: false,
mainCategoryId: null,
companyNamedis: false, // 公司名称
};
async componentDidMount() {
await getInfo.call(this);
getAreaAddr.call(this);
getServiceFacility.call(this);
getBankList.call(this);
}
// 主营类目
onMainCategory(e) {
this.setState({
mainCategoryId: e,
});
}
// 长期
oncheckedChange = e => {
const str = e.toString();
this.setState({
checkboxDisabled: str === '长期',
});
this.props.form.setFieldsValue({
legalPersonEnd: '',
});
};
// eslint-disable-next-line react/sort-comp
getDataInfo = type => ({
key: type,
name: businessTypeDesc[type],
chargeMethod: 1,
calculateType: 1,
});
// 计费类型改变
onChangeCalculateType = (e, i) => {
this.setState(state => {
const { calculateType } = state;
calculateType[i] = +e;
return {
calculateType,
};
});
};
static getDerivedStateFromProps() {
return null;
}
// 帐号类型切换
onChangeSettlType(e) {
this.setState({
settlementType: e.target.value,
});
}
// 处理图片
dealImgInfo = async (type, url) => {
const imgType = {
businessLicenseImage: 2,
idCardPortraitImage: 5,
idCardEmblemImage: 4,
};
if (!url) {
return;
}
this.setState({
visibleLoading: true,
});
const data = await apiRecognize({
imageUrl: url,
imageType: imgType[type],
});
if (data.businessCode === '0000') {
const res = data.data;
const info = {};
this.setState(state => {
if (type === 'businessLicenseImage') {
info.socialCode = res.socialCode || '';
info.companyName = res.companyName || '';
info.businessLicensePeriod = moment(res.businessLicensePeriod) || '';
} else if (type === 'idCardPortraitImage') {
info.legalPersonName = res.legalPersonName || '';
info.legalPersonIdCard = res.legalPersonIdCard || '';
} else if (type === 'idCardEmblemImage' && res.legalPersonPeriod) {
// 身份证有效期处理
const date = res.legalPersonPeriod.split('-') || [];
res.legalPersonStart = date[0] && moment(date[0]);
res.legalPersonEnd = date[1] && date[1] !== '长期' ? moment(date[1]) : '';
res.checked = date[1] && date[1] === '长期' ? ['长期'] : [];
const checkboxDisabled = date[1] && date[1] === '长期';
this.setState({
checkboxDisabled,
});
// info.legalPersonPeriod = res.legalPersonPeriod
// .replace(/\./g, '/')
// .split('-')
// .map(o => moment(o));
}
return {
businessInfo: Object.assign(state.businessInfo, info),
};
});
this.props.form.setFieldsValue({
...info,
});
} else {
notification.error({ message: data.msg });
}
this.setState({
visibleLoading: false,
});
};
/* eslint-disable no-return-assign */
saveInputRef = input => (this.input = input);
// 返回
onCancel = () => {
getInfo.call(this);
};
// 提交
handleSubmit = e => {
e.preventDefault();
this.props.form.validateFields(async (err, values) => {
const obj = Object.assign({}, values); // , this.state.businessInfo
if (!err) {
const imgs = this.state.businessInfo;
obj.businessLicensePeriod = moment(obj.businessLicensePeriod).format('YYYY-MM-DD');
const legalPersonStart = moment(obj.legalPersonStart).format('YYYY/MM/DD');
const legalPersonEnd = this.state.checkboxDisabled
? '长期'
: moment(obj.legalPersonEnd).format('YYYY/MM/DD');
obj.legalPersonPeriod = `${legalPersonStart}-${legalPersonEnd}`;
obj.facilities = {
customList: this.state.businessInfo.customList,
selfList: obj.selfList,
};
const areaArr = ['provinceId', 'cityId', 'countyId', 'townId'];
obj.addr.forEach((item, i) => {
obj[areaArr[i]] = item;
});
if (this.state.settlementType === 1) {
obj.accountOpenPermitImage = imgs.accountOpenPermitImage[0].url;
}
if (obj.supplierRateDTOList && obj.supplierRateDTOList.length) {
obj.supplierRateDTOList.forEach(item => {
if (item.ratedate && item.ratedate.length) {
item.startDate = moment(item.ratedate[0]).format('YYYY-MM-DD');
item.endDate = moment(item.ratedate[1]).format('YYYY-MM-DD');
delete item.ratedate;
}
});
}
obj.businessLicenseImage = imgs.businessLicenseImage[0].url;
obj.idCardEmblemImage = imgs.idCardEmblemImage[0].url;
obj.idCardPortraitImage = imgs.idCardPortraitImage[0].url;
obj.primaryImage = imgs.primaryImage[0].url;
obj.sealImage = imgs.sealImage[0].url;
obj.brandCertificate = imgs?.brandCertificate[0]?.url || '';
obj.differentNameAuthorizationImage = imgs?.differentNameAuthorizationImage[0]?.url || '';
obj.householdRegisterImage = imgs?.householdRegisterImage[0]?.url || '';
obj.icbProofImage = imgs?.icbProofImage[0]?.url || '';
obj.applySource = 1;
obj.signDateType = 1;
if (imgs.otherImage && imgs.otherImage.length) {
obj.otherImage = imgs.otherImage.map(item => item.url);
} else {
delete obj.otherImage;
}
if (imgs.categoryQualificateImage && imgs.categoryQualificateImage.length) {
obj.categoryQualificateImage = imgs.categoryQualificateImage[0].url;
} else {
delete obj.categoryQualificateImage;
}
obj.legalPersonIdCard = obj.legalPersonIdCard?.toLocaleUpperCase() || '';
obj.bankAccountLicenseNum = obj.bankAccountLicenseNum?.toLocaleUpperCase() || '';
obj.socialCode = obj.socialCode?.toLocaleUpperCase() || '';
obj.id = this.state.id;
obj.headImage = obj.primaryImage;
// this.setState({
// loading: true,
// });
console.log('obj :>>提交 ', obj);
const data = await apiEditStoreInfo(obj);
console.log(data, '.........');
if (data.businessCode === '0000') {
// const msg = this.state.type === infoTypeChecked ? '审核完成' : '保存成功';
notification.success({ message: `${data.msg}!~` });
}
this.setState({
loading: false,
});
} else {
const message = getErrorMessage(err);
notification.warning({ message });
}
});
};
onSetPoint = e => {
this.setFieldsValue({
latitude: e.lat,
longitude: e.lng,
});
};
// 修改公司名称
setCompanyName = () => {
const val = this.state.companyNamedis;
this.setState({
companyNamedis: !val,
});
if (!val) {
this.props.form.setFieldsValue({
companyName: this.state.businessInfo.companyName,
icbProofImage: '',
householdRegisterImage: '',
});
}
};
openMap(e, disabled) {
if (!disabled) {
this.setState({
visibleMap: e,
});
}
}
// eslint-disable-next-line class-methods-use-this
disabledDate(current) {
return current && current < moment(moment().format('YYYY-MM-DD'));
}
onChangeBusinessModel = e => {
this.getCategoryList(e);
this.props.form.setFieldsValue({
mainCategoryId: '',
});
};
// 获取主营类目
async getCategoryList(e) {
const data = await apiCategoryList(e);
if (!data.data) return;
this.setState({ categoryList: data.data });
}
render() {
const {
form: { getFieldDecorator },
} = this.props;
const { businessInfo, type, checkboxDisabled, mainCategoryId, companyNamedis } = this.state;
return (
<div className={styles.infoBox}>
<Form className="login-form" onSubmit={this.handleSubmit} {...formItemLayout}>
<Card title="店铺基本信息">
<Row gutter={24}>
<Col span={24}>
<FormItem label="业务模式" labelCol={{ span: 4 }}>
{getFieldDecorator('productBusiness', {
rules: [{ required: true, message: '请选择业务模式!' }],
initialValue: businessInfo.productBusiness,
})(
<Checkbox.Group
options={businessModel}
onChange={e => this.onChangeBusinessModel(e)}
/>,
)}
</FormItem>
</Col>
<Col span={24}>
<FormItem label="商户名称" labelCol={{ span: 4 }}>
{getFieldDecorator('name', {
rules: [{ required: true, message: '请输入商户名称!' }],
initialValue: businessInfo.name,
})(<Input maxLength={32} />)}
</FormItem>
</Col>
<Col span={24}>
<FormItem label="店铺区域" labelCol={{ span: 4 }}>
{getFieldDecorator('addr', {
rules: [{ required: true, type: 'array', message: '请选择店铺区域!' }],
initialValue: businessInfo.addr,
})(
<Cascader
options={this.state.areaAddr}
loadData={e => loadData.call(this, e)}
changeOnSelect
/>,
)}
</FormItem>
</Col>
<Col span={24}>
<FormItem label="经营地址" labelCol={{ span: 4 }}>
{getFieldDecorator('detailAddress', {
rules: [{ required: true, message: '请输入经营地址!' }],
initialValue: businessInfo.detailAddress,
})(<Input maxLength={500} />)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="联系人姓名" labelCol={{ span: 8 }}>
{getFieldDecorator('contactName', {
rules: [{ required: true, message: '请输入联系人姓名!' }],
initialValue: businessInfo.contactName,
})(<Input maxLength={8} />)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="联系人手机号" labelCol={{ span: 5 }}>
{getFieldDecorator('contactPhone', {
rules: [
{ required: true, message: '请输入联系人手机号!' },
{ validator: validatePhone, message: '请输入正确的手机号!' },
],
initialValue: businessInfo.contactPhone,
})(<Input maxLength={11} />)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="联系人邮箱" labelCol={{ span: 8 }}>
{getFieldDecorator('contactEmail', {
rules: [
{ required: true, message: '请输入联系人邮箱!' },
{ validator: validateEMail, message: '请输入正确的邮箱!' },
],
initialValue: businessInfo.contactEmail,
})(<Input />)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="客服电话" labelCol={{ span: 5 }}>
{getFieldDecorator('servicePhone', {
rules: [{ required: true, message: '请输入客服电话!' }],
initialValue: businessInfo.servicePhone,
})(<Input maxLength={11} />)}
</FormItem>
</Col>
<Col span={24}>
<FormItem label="签约日期" labelCol={{ span: 4 }}>
{getFieldDecorator('signDateType', {
rules: [{ required: true, message: '请选择签约日期' }],
initialValue: businessInfo.signDateType,
})(<Checkbox.Group options={signDateTypeList} />)}
</FormItem>
</Col>
</Row>
</Card>
<Card title="店铺营业信息">
<Col span={12} className={styles.imgList}>
<FormItem label="商户头图" labelCol={{ span: 8 }} wrapperCol={wrapperCol}>
{getFieldDecorator('primaryImage', {
rules: [{ required: true, message: '请上传商户头图!' }],
initialValue: businessInfo.primaryImage,
})(
<Upload
{...uploadPropsFn.call(this, { keyName: 'primaryImage', type: 1 })}
fileList={businessInfo.primaryImage}
>
<UploadOutlined /> 上传文件
</Upload>,
)}
</FormItem>
</Col>
<Col span={24}>
<FormItem label="服务设施" labelCol={{ span: 4 }}>
{getFieldDecorator('selfList', {
initialValue: businessInfo.selfList,
})(
<Select mode="multiple">
{this.state.serviceFacilitys.map(item => (
<Option value={item.code} key={item.code}>
{item.desc}
</Option>
))}
</Select>,
)}
</FormItem>
</Col>
<Col span={24}>
<FormItem label="自定义服务设施" labelCol={{ span: 4 }}>
{getFieldDecorator('customList', {
initialValue: businessInfo.customList,
})(renderServiceTags.call(this))}
</FormItem>
</Col>
</Card>
<Card title="证照信息录入区">
<Row gutter={24}>
<Col span={24}>
<FormItem label="主营类目" labelCol={{ span: 4 }}>
{getFieldDecorator('mainCategoryId', {
rules: [{ required: true, message: '请选择主营类目!' }],
initialValue: businessInfo.mainCategoryId,
})(
<Select
onChange={e => this.onMainCategory(e)}
showSearch
filterOption={(input, option) =>
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
disabled={+businessInfo.mainCategoryId === 301008}
>
{this.state.categoryList.map(item => (
<Option value={item.id} key={item.id}>
{item.name}
</Option>
))}
</Select>,
)}
</FormItem>
</Col>
<Col span={24}>
<FormItem label="企业类型" labelCol={{ span: 4 }}>
{getFieldDecorator('companyType', {
rules: [{ required: true, message: '请选择企业类型!' }],
initialValue: businessInfo.companyType,
})(
<Radio.Group disabled={businessInfo.companyType}>
<Radio value={1}>一般纳税人</Radio>
<Radio value={2}>小规模</Radio>
<Radio value={3}>个体工商</Radio>
</Radio.Group>,
)}
</FormItem>
</Col>
<Col span={24} className={styles.imgList}>
<FormItem label="营业执照" labelCol={{ span: 4 }} wrapperCol={wrapperCol}>
{getFieldDecorator('businessLicenseImage', {
rules: [{ required: true, message: '请上传营业执照!' }],
initialValue: businessInfo.businessLicenseImage,
})(
<Upload
{...uploadPropsFn.call(
this,
{ keyName: 'businessLicenseImage', type: 2 },
this.dealImgInfo,
)}
fileList={businessInfo.businessLicenseImage}
>
<UploadOutlined /> 上传文件
</Upload>,
)}
</FormItem>
</Col>
<Col span={12}>
<Row>
<Col span={4} style={{ marginTop: '4px' }}>
{businessInfo.companyName && (
<Button onClick={this.setCompanyName}>修改</Button>
)}
</Col>
<Col span={12}>
<FormItem label="公司名称" labelCol={{ span: 8 }}>
{getFieldDecorator('companyName', {
rules: [{ required: true, message: '请输入公司名称!' }],
initialValue: businessInfo.companyName,
})(<Input maxLength={50} disabled={companyNamedis} />)}
</FormItem>
</Col>
</Row>
</Col>
<Col span={12}>
<FormItem label="统一社会信用代码" labelCol={{ span: 8 }}>
{getFieldDecorator('socialCode', {
rules: [{ required: true, message: '请输入统一社会信用代码!' }],
initialValue: businessInfo.socialCode,
})(<Input maxLength={32} />)}
</FormItem>
</Col>
{(!companyNamedis && businessInfo.companyType && businessInfo.companyType !== 2) ||
(!companyNamedis && businessInfo?.icbProofImage?.length) ? (
<Col span={12}>
<FormItem label="工商局变更证明" labelCol={{ span: 8 }} wrapperCol={wrapperCol}>
{getFieldDecorator('icbProofImage', {
rules: [{ required: true, message: '请上传工商局变更证明!' }],
initialValue: businessInfo.icbProofImage,
})(
<Upload
{...uploadPropsFn.call(this, {
keyName: 'icbProofImage',
limit: 1,
})}
fileList={businessInfo.icbProofImage}
>
<UploadOutlined /> 上传文件
</Upload>,
)}
</FormItem>
</Col>
) : (
''
)}
{(!companyNamedis && businessInfo.companyType && businessInfo.companyType === 2) ||
(!companyNamedis && businessInfo?.householdRegisterImage?.length) ? (
<Col span={12}>
<FormItem label="户口本本人页" labelCol={{ span: 8 }} wrapperCol={wrapperCol}>
{getFieldDecorator('householdRegisterImage', {
rules: [{ required: true, message: '请上传户口本本人页!' }],
initialValue: businessInfo.householdRegisterImage,
})(
<Upload
{...uploadPropsFn.call(this, {
keyName: 'householdRegisterImage',
limit: 1,
})}
fileList={businessInfo.householdRegisterImage}
>
<UploadOutlined /> 上传文件
</Upload>,
)}
</FormItem>
</Col>
) : (
''
)}
<Col span={24}>
<FormItem label="营业执照有效期" labelCol={{ span: 4 }}>
{getFieldDecorator('businessLicensePeriod', {
rules: [{ required: true, message: '请选择营业执照有效期!' }],
initialValue: businessInfo.businessLicensePeriod,
})(<DatePicker maxLength={50} />)}
</FormItem>
</Col>
<Col span={24}>
<FormItem label="类目所需资质" labelCol={{ span: 4 }} wrapperCol={wrapperCol}>
{getFieldDecorator('categoryQualificateImage', {
initialValue: businessInfo.categoryQualificateImage,
})(
<Upload
{...uploadPropsFn.call(this, {
keyName: 'categoryQualificateImage',
type: 6,
})}
fileList={businessInfo.categoryQualificateImage}
>
<UploadOutlined /> 上传文件
</Upload>,
)}
</FormItem>
</Col>
<Col span={24}>
<FormItem label="电子签章" labelCol={{ span: 4 }} wrapperCol={wrapperCol}>
{getFieldDecorator('sealImage', {
rules: [{ required: true, message: '请上传电子签章!' }],
initialValue: businessInfo.sealImage,
})(
<Upload
{...uploadPropsFn.call(this, {
keyName: 'sealImage',
type: 3,
maxSize: 1024 * 200,
maxSizeMsg: '文件大小不能超过200K',
limit: 1,
})}
fileList={businessInfo.sealImage}
>
<UploadOutlined /> 上传文件
</Upload>,
)}
</FormItem>
</Col>
{+mainCategoryId === 301008 && (
<>
<Col span={24}>
<FormItem label="授权品牌" labelCol={{ span: 4 }}>
{getFieldDecorator('brand', {
initialValue: businessInfo.brand,
})(<Input maxLength={32} />)}
</FormItem>
</Col>
<Col span={24}>
<FormItem
label="品牌经销商授权书"
labelCol={{ span: 4 }}
wrapperCol={wrapperCol}
>
{getFieldDecorator('brandCertificate', {
initialValue: businessInfo.brandCertificate,
})(
<Upload
{...uploadPropsFn.call(this, {
keyName: 'brandCertificate',
limit: 1,
})}
fileList={businessInfo.brandCertificate}
>
<UploadOutlined /> 上传文件
</Upload>,
)}
</FormItem>
</Col>
</>
)}
</Row>
</Card>
<Card title="法人信息录入区">
<Row gutter={24}>
<Col span={12} className={styles.imgList}>
<FormItem label="法人身份证人像面" labelCol={{ span: 8 }} wrapperCol={wrapperCol}>
{getFieldDecorator('idCardPortraitImage', {
rules: [{ required: true, message: '请上传身份证人像面!' }],
initialValue: businessInfo.idCardPortraitImage,
})(
<Upload
{...uploadPropsFn.call(
this,
{ keyName: 'idCardPortraitImage', type: 5 },
this.dealImgInfo,
)}
fileList={businessInfo.idCardPortraitImage}
>
<UploadOutlined />
<div>身份证人像面</div>
</Upload>,
)}
</FormItem>
</Col>
<Col span={12} className={styles.imgList}>
<FormItem label="法人身份证国徽面" labelCol={{ span: 8 }} wrapperCol={wrapperCol}>
{getFieldDecorator('idCardEmblemImage', {
rules: [{ required: true, message: '请上传身份证国徽面!' }],
initialValue: businessInfo.idCardEmblemImage,
})(
<Upload
{...uploadPropsFn.call(
this,
{ keyName: 'idCardEmblemImage', type: 4 },
this.dealImgInfo,
)}
fileList={businessInfo.idCardEmblemImage}
>
<UploadOutlined />
<div>身份证国徽面</div>
</Upload>,
)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="证件姓名" labelCol={{ span: 8 }}>
{getFieldDecorator('legalPersonName', {
rules: [{ required: true, message: '请输入证件姓名!' }],
initialValue: businessInfo.legalPersonName,
})(<Input maxLength={8} />)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="身份证号码" labelCol={{ span: 8 }}>
{getFieldDecorator('legalPersonIdCard', {
rules: [{ required: true, message: '请输入身份证号码!' }],
initialValue: businessInfo.legalPersonIdCard,
})(<Input maxLength={18} />)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="身份证起始有效期" labelCol={{ span: 8 }}>
{getFieldDecorator('legalPersonStart', {
rules: [{ required: true, message: '身份证起始有效期!' }],
initialValue: businessInfo.legalPersonStart,
})(<DatePicker style={{ width: '200px' }} />)}
</FormItem>
</Col>
<Col span={12}>
<Row gutter={24}>
<Col span={19}>
<FormItem label="身份证结束有效期" labelCol={{ span: 12 }}>
{getFieldDecorator('legalPersonEnd', {
rules: [{ required: !checkboxDisabled, message: '身份证结束有效期!' }],
initialValue: businessInfo.legalPersonEnd,
})(<DatePicker style={{ width: '200px' }} disabled={checkboxDisabled} />)}
</FormItem>
</Col>
<Col span={5}>
<FormItem>
{getFieldDecorator('legalPersonPeriod', {
initialValue: businessInfo.checked,
})(
<Checkbox.Group
options={legalPersonList}
className={styles.radio}
onChange={e => this.oncheckedChange(e)}
/>,
)}
</FormItem>
</Col>
</Row>
</Col>
<Col span={12}>
<FormItem label="手机号" labelCol={{ span: 8 }}>
{getFieldDecorator('legalPersonPhone', {
rules: [
{ required: true, message: '请输入手机号!' },
{ validator: validatePhone, message: '请输入正确的手机号!' },
],
initialValue: businessInfo.legalPersonPhone,
})(<Input maxLength={11} />)}
</FormItem>
</Col>
<Col span={24}>
<FormItem label="其它证照" labelCol={{ span: 4 }} wrapperCol={wrapperCol}>
{getFieldDecorator('otherImage', {
initialValue: businessInfo.otherImage,
})(
<Upload
{...uploadPropsFn.call(this, { keyName: 'otherImage', limit: 9, type: 7 })}
fileList={businessInfo.otherImage}
>
<UploadOutlined /> 上传文件
</Upload>,
)}
</FormItem>
</Col>
</Row>
</Card>
<Card title="结算信息录入区">
<Row gutter={24}>
<Col span={24}>
<FormItem label="账户类型" labelCol={{ span: 4 }} wrapperCol={wrapperCol}>
{getFieldDecorator('settlementType', {
rules: [{ required: true, message: '请选择账户类型!' }],
initialValue: businessInfo.settlementType,
})(
<Radio.Group onChange={e => this.onChangeSettlType(e)}>
<Radio value={1}>对公</Radio>
<Radio value={2}>对私(小微商户)</Radio>
</Radio.Group>,
)}
</FormItem>
</Col>
</Row>
{this.state.settlementType === 1 && (
<Row gutter={24}>
<Col span={12}>
<FormItem label="开户许可证" labelCol={{ span: 8 }} wrapperCol={wrapperCol}>
{getFieldDecorator('accountOpenPermitImage', {
rules: [{ required: true, message: '请上传开户许可证!' }],
initialValue: businessInfo.accountOpenPermitImage,
})(
<Upload
{...uploadPropsFn.call(this, {
keyName: 'accountOpenPermitImage',
type: 8,
})}
fileList={businessInfo.accountOpenPermitImage}
>
<UploadOutlined /> 上传文件
</Upload>,
)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="开户许可证编号" labelCol={{ span: 8 }}>
{getFieldDecorator('bankAccountLicenseNum', {
rules: [{ required: true, message: '请输入开户许可证编号!' }],
initialValue: businessInfo.bankAccountLicenseNum,
})(<Input maxLength={32} />)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="开户名称" labelCol={{ span: 8 }}>
{getFieldDecorator('bankAccountName', {
rules: [{ required: true, message: '请输入开户名称!' }],
initialValue: businessInfo.bankAccountName,
})(<Input maxLength={32} />)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="开户行" labelCol={{ span: 8 }}>
{getFieldDecorator('accountBankName', {
rules: [{ required: true, message: '请选择开户行!' }],
initialValue: businessInfo.accountBankName,
})(
<Select
showSearch
filterOption={(input, option) =>
(option?.value ?? '').toLowerCase().includes(input.toLowerCase())
}
>
{this.state.bankList.map(item => (
<Option value={item.bankName} key={item.bankName}>
{item.bankName}
</Option>
))}
</Select>,
)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="银行帐号" labelCol={{ span: 8 }}>
{getFieldDecorator('bankAccount', {
rules: [{ required: true, message: '请输入银行帐号!' }],
initialValue: businessInfo.bankAccount,
})(<Input maxLength={20} />)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="联行号" labelCol={{ span: 8 }}>
{getFieldDecorator('interbankNum', {
initialValue: businessInfo.interbankNum,
})(<Input maxLength={50} />)}
</FormItem>
</Col>
<Col span={24}>
<FormItem
label="非同名结算授权文件"
labelCol={{ span: 4 }}
wrapperCol={wrapperCol}
>
{getFieldDecorator('differentNameAuthorizationImage', {
initialValue: businessInfo.differentNameAuthorizationImage,
})(
<Upload
{...uploadPropsFn.call(this, {
keyName: 'differentNameAuthorizationImage',
limit: 1,
})}
fileList={businessInfo.differentNameAuthorizationImage}
>
<UploadOutlined /> 上传文件
</Upload>,
)}
</FormItem>
</Col>
</Row>
)}
{this.state.settlementType === 2 && (
<Row gutter={24}>
<Col span={12}>
<FormItem label="银行卡类型" labelCol={{ span: 8 }}>
{getFieldDecorator('bankAccountType', {
rules: [{ required: true, message: '请选择银行卡类型!' }],
initialValue: businessInfo.bankAccountType,
})(
<Select>
<Option value={1} key={1}>
借记卡
</Option>
</Select>,
)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="开户名称" labelCol={{ span: 8 }}>
{getFieldDecorator('bankAccountName', {
rules: [{ required: true, message: '请输入开户名称!' }],
initialValue: businessInfo.bankAccountName,
})(<Input maxLength={32} />)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="开户行" labelCol={{ span: 8 }}>
{getFieldDecorator('accountBankName', {
rules: [{ required: true, message: '请选择开户行!' }],
initialValue: businessInfo.accountBankName,
})(
<Select
showSearch
filterOption={(input, option) =>
(option?.value ?? '').toLowerCase().includes(input.toLowerCase())
}
>
{this.state.bankList.map(item => (
<Option value={item.bankName} key={item.bankName}>
{item.bankName}
</Option>
))}
</Select>,
)}
</FormItem>
</Col>
<Col span={12}>
<FormItem label="银行帐号" labelCol={{ span: 8 }}>
{getFieldDecorator('bankAccount', {
rules: [{ required: true, message: '请输入银行帐号!' }],
initialValue: businessInfo.bankAccount,
})(<Input maxLength={20} />)}
</FormItem>
</Col>
</Row>
)}
</Card>
{/* 汽车301008 */}
{+mainCategoryId === 301008 ? (
<Card title="其他信息">
<Row gutter={24}>
<Col span={24}>
<FormItem label="礼包内容" labelCol={{ span: 4 }}>
{getFieldDecorator('giftPackageContent', {
rules: [{ required: true, message: '请输入礼包内容!' }],
initialValue: businessInfo.giftPackageContent,
})(<Input style={{ width: '50%' }} />)}
</FormItem>
</Col>
</Row>
</Card>
) : (
''
)}
<div className={styles.formBtns}>
<Button type="primary" size="large" htmlType="submit" loading={this.state.loading}>
修改并提交
</Button>
<Button size="large" onClick={this.onCancel}>
取消
</Button>
</div>
</Form>
<MapModal
visible={this.state.visibleMap}
onCancel={() => this.openMap(false)}
onSetPoint={e => this.onSetPoint(e)}
></MapModal>
{this.state.visibleLoading && (
<div className={styles.spinBox}>
<div className={styles.spinBoxWrapper}>
<Spin tip="Loading..." />
</div>
</div>
)}
</div>
);
}
}
export default Form.create()(BusinessInfo);
.textArea {
:global {
.ant-form-item-label {
width: 16%;
}
.ant-form-item-control-wrapper {
width: 80%;
}
}
}
.imgList {
:global {
.ant-upload-list-picture-card-container {
width: 200px;
}
.ant-upload-list-item {
width: 200px;
}
// .ant-upload.ant-upload-select-picture-card {
// width: 200px;
// }
}
}
.infoBox {
position: relative;
}
.spinBox {
position: absolute;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.5);
}
.spinBoxWrapper {
position: fixed;
top: 50%;
left: 50%;
display: flex;
align-items: center;
justify-content: center;
width: 200px;
height: 80px;
text-align: center;
transform: translate(-100px, -80px);
}
.addLink {
display: block;
margin: 20px 50px;
}
.formBtns {
display: flex;
align-items: center;
justify-content: space-evenly;
width: 100%;
padding: 20px 0;
background-color: #fff;
}
const Model = {
namespace: 'BusinessManage',
state: {},
effects: {},
reducers: {},
};
export default Model;
import request from '@/utils/request';
import config from '../../../config/env.config';
import qs from 'qs';
import { da } from 'date-fns/locale';
const { kdspApi, goodsApi } = config;
// 获取地址
export const apiAddrArea = params =>
request.get(`/api/merchants/addresses/list?${qs.stringify(params)}`, {
prefix: kdspApi,
});
// 主营类目
export async function apiCategoryList(param) {
return request.post('/api/merchants/suppliers/main-category/list', {
data: param,
prefix: goodsApi,
});
}
// 服务设施
export const apiServiceFacility = () =>
request.get('/api/merchants/suppliers/facilities/list', { prefix: kdspApi });
// 银行
export const apiBankList = () =>
request.get('/api/merchants/suppliers/banks/list', { prefix: kdspApi });
// 订正
export const apiRevision = params =>
request.post('/api/consoles/suppliers/register/revision', { prefix: kdspApi, data: params });
/**
* 上传文件
* imageType: 1-主头图,2-营业执照,3-电子签章,4-法人身份证国徽面,5-法人身份证人像面,6-类目所需资质,7-其它证件,8-开户许可证
* 0: 默认值 不校验
* */
export async function uploadFile(files, imageType = 0) {
const params = new FormData();
files.map(file => params.append('file', file));
params.append('imageType', imageType);
// image/upload
const data = await request.post('/api/merchants/images/upload', {
prefix: kdspApi,
data: params,
canRepeat: true,
});
return data;
}
// 图片内容识别
export const apiRecognize = params =>
request.get(`/api/merchants/images/recognize?${qs.stringify(params)}`, { prefix: kdspApi });
// 编辑商户信息
export const apiEditStoreInfo = params =>
request.post('/api/merchants/suppliers/edit', { prefix: kdspApi, data: params });
// 查询商户详情
export const apiBusinessDetail = businessId =>
request.get('/api/merchants/suppliers/pops/detail', { prefix: kdspApi });
import { Button, Popconfirm } from 'antd';
import React from 'react';
// import router from 'umi/router';
import { history } from 'umi';
// 状态:0-填写未完成,1-待审核,2-待易宝入网,3-易宝入网中,4-待易宝签约,5-待平台签约,6-完成,7-驳回
export const checkStatus = {
// 0: { text: '填写未完成' },
1: { text: '待审核' },
// 2: { text: '待易宝入网' },
3: { text: '易宝入网中' },
4: { text: '待易宝签约' },
5: { text: '待平台签约' },
// 6: { text: '完成' },
// 7: { text: '驳回' },
};
// 详情类型
export const infoTypeFind = 'find'; // 查看
export const infoTypeChecked = 'checked'; // 审核
export const infoTypeEdit = 'edit'; // 编辑
export const infoTypeRevision = 'revision'; // 订正
export const infoTypeInfo = 'info'; // 审核之后查看
export const infoTypeAdd = 'add'; // 添加
// 商户类型
export const supplierType = {
pop: { text: 'POP商户' },
供应商: { text: '供应商' },
};
export const toInfo = ({ id }, type = 'find') => {
history.push(`/BusinessInfo?id=${id}&type=${type}`);
};
export const businessTypeDesc = {
1: '到家业务',
2: '实物业务',
3: '到店业务',
};
.table {
:global {
.ant-table-row-expand-icon-cell {
visibility: hidden;
}
.ant-table-expanded-row {
.ant-pro-table {
margin-left: -17px;
}
}
}
}
.logBtn {
display: inherit;
margin: 20px auto;
}
.pageHeader {
background-color: #fff;
border: 1px solid rgb(235, 237, 240);
}
.listHeader {
display: flex;
&--item {
position: relative;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
width: 40px;
height: 40px;
margin-right: 20px;
font-size: 14px;
line-height: 14px;
text-align: center;
border: 1px solid #333;
border-radius: 50%;
&::after {
position: absolute;
right: -21px;
width: 20px;
height: 1px;
background-color: #333;
content: '';
}
&:last-child::after {
width: 0;
height: 0;
}
}
}
......@@ -4,10 +4,11 @@ import moment from 'moment';
import { PlusSquareFilled, MinusSquareFilled } from '@ant-design/icons';
import { Modal, Input, TimePicker, Checkbox, Cascader, Radio, notification } from 'antd';
import { apiAddrArea, apiCreatStore, apiEditStore } from '../services';
import { weekOptions, weekDefault, layout } from '../data';
import { weekOptions, weekDefault, layout, businessModel } from '../data';
import MapModal from '@/components/GaoDeMap';
import style from './style.less';
import { isCheckNumberLine } from '@/utils/validator';
import Upload from '../../components/upload';
const FormItem = Form.Item;
......@@ -17,6 +18,8 @@ const StoreModal = props => {
onCancel,
form: { getFieldDecorator, setFieldsValue, getFieldsValue, validateFields, resetFields },
formInfo,
status,
productBusiness,
} = props;
const [areaAddr, setAreaAddr] = useState([]);
const [visibleMap, setVisibleMap] = useState(false);
......@@ -26,9 +29,22 @@ const StoreModal = props => {
provice: '',
address: '',
});
const [disabled, setDisabled] = useState(false);
const [isDisabled, setIsDisabled] = useState(true);
const divDom = useRef();
useEffect(() => {
setDisabled(props.status);
}, [props.status]);
useEffect(() => {
if (props.productBusiness.length) {
const val = props.productBusiness.includes(2) || props.productBusiness.includes(3);
setIsDisabled(val);
}
}, [props.productBusiness]);
const handleCancel = isSuccess => {
resetFields();
onCancel(isSuccess);
......@@ -43,6 +59,10 @@ const StoreModal = props => {
params[areaArr[i]] = item;
});
}
if (params.shopHeadImage.length) {
// eslint-disable-next-line prefer-destructuring
params.shopHeadImage = params.shopHeadImage[0];
}
if (params.lnglat) {
const arr = params.lnglat.split(',');
if (arr.length === 2) {
......@@ -197,6 +217,8 @@ const StoreModal = props => {
setAreaAddr([...arr]);
};
const normFile = fileList => fileList;
useEffect(() => {
if (visible) {
resetFields();
......@@ -215,9 +237,11 @@ const StoreModal = props => {
}
info.lnglat = `${info.longitude},${info.latitude}`;
info.addr = [info.provinceId, info.cityId, info.countyId];
info.shopHeadImage = [info.shopHeadImage] || [];
if (info.townId) {
info.addr.push(info.townId);
}
console.log(info);
setTimes(harr);
setFormData(info);
getLazyAddr(info);
......@@ -234,13 +258,28 @@ const StoreModal = props => {
<Modal
title="门店信息"
visible={visible}
width="800px"
width="1000px"
destroyOnClose
maskClosable={false}
onOk={() => onSubmit()}
onCancel={() => handleCancel()}
>
<Form {...layout} name="formData">
<FormItem label="业务模式">
{getFieldDecorator('productBusiness', {
initialValue: productBusiness,
})(<Checkbox.Group disabled options={businessModel} />)}
</FormItem>
{isDisabled && (
<FormItem label="门店头像">
{getFieldDecorator('shopHeadImage', {
rules: [{ required: true, message: '请上传门店头像' }],
initialValue: formData.shopHeadImage || [],
valuePropName: 'fileList',
getValueFromEvent: normFile,
})(<Upload max={1} accept=".jpg,.png,.jpeg" disabled={disabled} />)}
</FormItem>
)}
<FormItem
label="门店名称"
name="name"
......@@ -249,7 +288,7 @@ const StoreModal = props => {
{getFieldDecorator('name', {
rules: [{ required: true, message: '请输入门店名称!' }],
initialValue: formData.name,
})(<Input placeholder="请输入门店名称" allowClear maxLength={20} />)}
})(<Input placeholder="请输入门店名称" allowClear maxLength={20} disabled={disabled} />)}
</FormItem>
<FormItem label="门店电话" name="phone">
{getFieldDecorator('phone', {
......@@ -258,7 +297,7 @@ const StoreModal = props => {
{ validator: isCheckNumberLine, message: '请输入正确的门店电话!' },
],
initialValue: formData.phone,
})(<Input placeholder="请输入门店电话" allowClear maxLength={20} />)}
})(<Input placeholder="请输入门店电话" allowClear maxLength={20} disabled={disabled} />)}
</FormItem>
<FormItem label="营业时间" required>
{times &&
......@@ -269,18 +308,25 @@ const StoreModal = props => {
{getFieldDecorator(item.name, {
rules: [{ required: true, message: '请选择营业时间!' }],
initialValue: formData[item.name],
})(<TimePicker.RangePicker format="HH:mm" />)}
})(<TimePicker.RangePicker format="HH:mm" disabled={disabled} />)}
</FormItem>
</div>
{i > 0 ? (
{!disabled &&
(i > 0 ? (
<div className={style.timerWrapperRight} onClick={() => onTimeMinus(i)}>
<MinusSquareFilled style={{ color: '#ff4d4f', fontSize: '30px' }} />
<MinusSquareFilled
style={{ color: '#ff4d4f', fontSize: '30px' }}
disabled={disabled}
/>
</div>
) : (
<div className={style.timerWrapperRight} onClick={() => onTimePlus()}>
<PlusSquareFilled style={{ color: '#1890ff', fontSize: '30px' }} />
<PlusSquareFilled
style={{ color: '#1890ff', fontSize: '30px' }}
disabled={disabled}
/>
</div>
)}
))}
</div>
))}
</FormItem>
......@@ -288,7 +334,7 @@ const StoreModal = props => {
{getFieldDecorator('week', {
rules: [{ required: true, message: '请选择营业日!' }],
initialValue: formData.week || weekDefault,
})(<Checkbox.Group options={weekOptions} />)}
})(<Checkbox.Group options={weekOptions} disabled={disabled} />)}
</FormItem>
<FormItem label="店铺区域">
{getFieldDecorator('addr', {
......@@ -301,6 +347,7 @@ const StoreModal = props => {
placeholder="请选择店铺区域"
loadData={e => loadData(e)}
changeOnSelect
disabled={disabled}
/>,
)}
</FormItem>
......@@ -308,7 +355,14 @@ const StoreModal = props => {
{getFieldDecorator('address', {
rules: [{ required: true, message: '请输入详细地址!' }],
initialValue: formData.address,
})(<Input placeholder="请输入详细地址,不包含省市区地址" allowClear maxLength={50} />)}
})(
<Input
placeholder="请输入详细地址,不包含省市区地址"
allowClear
maxLength={50}
disabled={disabled}
/>,
)}
</FormItem>
<FormItem label="经纬度">
{getFieldDecorator('lnglat', {
......@@ -320,6 +374,7 @@ const StoreModal = props => {
readOnly
onClick={() => openMap(true)}
maxLength={100}
disabled={disabled}
/>,
)}
</FormItem>
......@@ -328,12 +383,19 @@ const StoreModal = props => {
rules: [{ required: true, message: '请选择是否启用!' }],
initialValue: formData.state,
})(
<Radio.Group>
<Radio.Group disabled={disabled}>
<Radio value={1}></Radio>
<Radio value={0}></Radio>
</Radio.Group>,
)}
</FormItem>
{isDisabled && (
<FormItem label="门店公告">
{getFieldDecorator('publicNotice', {
initialValue: formData.publicNotice,
})(<Input placeholder="请输入门店公告" maxLength={120} disabled={disabled} />)}
</FormItem>
)}
</Form>
<MapModal
visible={visibleMap}
......
......@@ -17,3 +17,13 @@ export const layout = {
labelCol: { span: 6 },
wrapperCol: { span: 16 },
};
// 业务模式
export const businessModel = [
{ label: '到家外卖业务(外卖配送业务)', value: 1 },
{ label: '实物商品业务员', value: 2 },
{ label: '到店业务(服务类业务)', value: 3 },
];
// 营业日
export const businessStatus = [{ label: '停业', value: 2 }, { label: '营业中', value: 1 }];
import React, { useState, useRef, useEffect } from 'react';
import { notification, Button, Form, Input, Cascader, Col, Row, Table, Pagination } from 'antd';
import {
notification,
Button,
Form,
Input,
Cascader,
Col,
Row,
Table,
Pagination,
Modal,
Select,
} from 'antd';
import _ from 'lodash';
import { searchList, apiEnableStore, apiAddrArea } from './services';
import { stateDesc, weeks, layout } from './data';
import { el } from 'date-fns/locale';
import { searchList, apiEnableStore, apiAddrArea, apiproductBusiness } from './services';
import { stateDesc, weeks, layout, businessStatus, businessModel } from './data';
import StoreModal from './components/storeModal';
import style from './style.less';
const { Option } = Select;
const { confirm } = Modal;
export default () => {
const [visible, setVisible] = useState(false);
const [storeInfo, setStoreInfo] = useState({});
const [areaAddr, setAreaAddr] = useState([]);
const [status, setStatus] = useState();
const [dataList, setDataList] = useState([]);
const [pageNo, setPageNo] = useState(1);
const [totalNum, setTotalNum] = useState(0);
const [pageSize, setPageSize] = useState(20);
const [productBusiness, setProductBusiness] = useState([]);
const refSearch = useRef();
const divDom = useRef();
// 获取业务模式
const getBusiness = async () => {
const res = await apiproductBusiness();
setProductBusiness(res);
};
const onCreate = () => {
setStoreInfo({});
setVisible(true);
getBusiness();
};
const onShowInfo = info => {
const onShowInfo = (info, val) => {
setStoreInfo(info);
const value = val !== 'edit';
setStatus(value);
setVisible(true);
getBusiness();
};
// 获取市区街道
......@@ -92,16 +119,22 @@ export default () => {
params[ids[i]] = item;
});
}
if (val.businessStatus) {
params.businessStatus = val.businessStatus;
}
getList(params);
};
const closeModal = isReload => {
if (isReload) {
onSearch(refSearch.current?.getFieldValue?.() || {});
}
setStatus(false);
setStoreInfo({});
setVisible(false);
};
const onEnableState = async ({ id, state }) => {
const enableStore = async (id, state) => {
const enable = +state === 1 ? 0 : 1;
const res = await apiEnableStore({ id, state: enable });
if (res === '0000') {
......@@ -109,11 +142,25 @@ export default () => {
onSearch(refSearch.current?.getFieldValue?.() || {});
}
};
const onEnableState = async ({ id, state }) => {
if (state) {
confirm({
title: '确认要禁用这家门店吗?',
content: '禁用后用户将无法看到该店铺',
onOk() {
enableStore(id, state);
},
});
} else {
enableStore(id, state);
}
};
const onReset = () => {
if (refSearch.current && refSearch.current.resetFields) {
refSearch.current.resetFields();
}
getList();
};
const onPageChange = (e, size) => {
......@@ -164,83 +211,74 @@ export default () => {
const columns = [
{
title: '门店名称',
dataIndex: 'name',
title: '业务模式',
dataIndex: 'productBusiness',
width: 120,
align: 'center',
render: v => {
let str = '';
v.forEach(it => {
businessModel.forEach(item => {
if (+it === +item.value) {
str += `${item.label}`;
}
});
});
return str;
},
{
title: '门店电话',
dataIndex: 'phone',
hideInSearch: true,
width: 120,
},
{
title: '营业时间',
dataIndex: 'businessHours',
hideInSearch: true,
width: 150,
render: businessHours => (
<div>
<div>{getWeekSlots(businessHours.weeks)}</div>
<div>
{businessHours.hoursItems.map(item => (
<div key={item.begin}>
<span>{item.begin}</span>-<span>{item.end}</span>
</div>
))}
</div>
</div>
),
title: '门店名称',
dataIndex: 'name',
width: 120,
align: 'center',
},
{
title: '地区',
dataIndex: 'addr',
width: 200,
hideInSearch: true,
render: (addr, r) => (
<span>{`${r.provinceName}${r.cityName}${r.countyName}${r.townName || ''}`}</span>
),
title: '营业状态',
dataIndex: 'businessStatus',
width: 80,
align: 'center',
render: val => businessStatus.find(item => item.value === val)?.label || '-',
},
{
title: '详细地址',
dataIndex: 'address',
hideInSearch: true,
width: 150,
title: '创建时间',
dataIndex: 'createdAt',
width: 120,
align: 'center',
},
{
title: '经纬度',
dataIndex: 'latlng',
hideInSearch: true,
width: 120,
render: (latlng, r) => <span>{`${r.longitude},${r.latitude}`}</span>,
title: '门店电话',
dataIndex: 'phone',
align: 'center',
width: 100,
},
{
title: '状态',
title: '门店状态',
dataIndex: 'state',
hideInSearch: true,
width: 120,
align: 'center',
width: 80,
render: v => <span>{`${stateDesc[v]}`}</span>,
},
{
title: '创建时间',
dataIndex: 'createdAt',
hideInSearch: true,
width: 120,
},
{
title: '操作',
hideInSearch: true,
dataIndex: 'action',
width: 170,
width: 200,
fixed: 'right',
render: (val, r) => [
render: (val, r) => (
<div className={style.actionBtn}>
<Button key="look" onClick={() => onShowInfo(r)}>
查看
</Button>
<Button key="seek" onClick={() => onShowInfo(r, 'edit')}>
修改
</Button>
<Button key="enable1" onClick={() => onEnableState(r)} type="primary">
{+r.state ? '禁用' : '启用'}
</Button>,
<Button key="seek" style={{ marginLeft: '10px' }} onClick={() => onShowInfo(r)}>
查看
</Button>,
],
</Button>
</div>
),
},
];
return (
......@@ -264,6 +302,18 @@ export default () => {
</Form.Item>
</Col>
<Col span={8}>
<Form.Item label="营业状态" name="businessStatus">
<Select>
{businessStatus.map(item => (
<Option label={item.label} value={item.value} key={item.value}>
{item.label}
</Option>
))}
</Select>
</Form.Item>
</Col>
</Row>
<div className={style.search}>
<Button type="primary" htmlType="submit" size="middle">
搜索
</Button>
......@@ -273,8 +323,7 @@ export default () => {
<Button type="primary" size="middle" onClick={() => onCreate()}>
新建
</Button>
</Col>
</Row>
</div>
</Form>
</div>
<Table
......@@ -285,7 +334,7 @@ export default () => {
pagination={false}
scroll={{ x: '100%' }}
/>
{dataList && dataList.length && (
{dataList && dataList.length ? (
<div className={style.pageBox}>
<Pagination
style={{ marginBottom: 10 }}
......@@ -298,8 +347,14 @@ export default () => {
onShowSizeChange={onPageChange}
/>
</div>
)}
<StoreModal visible={visible} onCancel={closeModal} formInfo={storeInfo} />
) : null}
<StoreModal
visible={visible}
onCancel={closeModal}
formInfo={storeInfo}
status={status}
productBusiness={productBusiness}
/>
</div>
);
};
......@@ -65,3 +65,11 @@ export async function apiEditStore(params) {
});
return data.businessCode;
}
// 获取商户业务模式
export async function apiproductBusiness() {
const data = await request.get('/api/merchants/suppliers/product-business/list', {
prefix: kdspApi,
});
return data.data;
}
.serachForm {
margin-bottom: 20px;
padding: 20px 50px 0 10px;
padding: 20px 50px 10px 10px;
background-color: #fff;
}
.search {
display: flex;
justify-content: end;
}
.searchBtn {
margin: 0 10px;
}
......@@ -13,3 +17,14 @@
border: 1px solid #f0f0f0;
border-top: 0;
}
.actionBtn {
display: flex;
align-items: center;
// flex-direction: column;
justify-content: space-around;
button {
width: 75px;
margin-bottom: 5px;
}
}
import { PlusOutlined } from '@ant-design/icons';
import { Upload, Modal, message } from 'antd';
import { Upload, Modal, notification } from 'antd';
import React from 'react';
import config from '../../../config/env.config';
import { qiniuToken } from '@/services/qiniu';
......@@ -7,7 +7,6 @@ import { qiniuToken } from '@/services/qiniu';
const qiniu = require('@/utils/qiniu.min.js');
const { qiniuHost } = config;
function getBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
......@@ -26,9 +25,26 @@ class PicturesWall extends React.Component {
};
async componentDidMount() {
this.initFileList(this.props.fileList || []);
token = await qiniuToken();
}
static getDerivedStateFromProps(nextProps) {
new PicturesWall(nextProps).initFileList();
return null;
}
initFileList = fileList => {
const fileLists =
fileList?.map((item, index) => ({
url: item,
name: '',
uid: index,
status: 'done',
})) || [];
this.setState({ fileList: fileLists });
};
handleCancel = () => this.setState({ previewVisible: false });
handlePreview = async file => {
......@@ -43,17 +59,37 @@ class PicturesWall extends React.Component {
});
};
handleChange = info => {
const lastFile = (info.fileList.length && info.fileList[info.fileList.length - 1]) || [];
const types = ['application/pdf', 'image/png', 'image/jpeg'];
if (lastFile && types.indexOf(lastFile.type) === -1) {
message.error('文件格式错误!');
}
const fileList = info.fileList.filter(item => types.indexOf(item.type) !== -1);
this.setState({ fileList });
handleChange = ({ fileList }) => {
const file = fileList.filter(item => item.url);
this.setState({ fileList: [...file] });
const urlList = file.map(item => item.url);
this.props.onChange(urlList);
};
customRequest = ({ file, onError, onSuccess }) => {
imageSize = async file =>
new Promise((resolve, reject) => {
const fileObj = file;
// 获取上传的图片的宽高
const reader = new FileReader();
reader.readAsDataURL(fileObj);
reader.onload = evt => {
const replaceSrc = evt.target.result;
const imageObj = new Image();
imageObj.src = replaceSrc;
imageObj.onload = () => {
const { width } = imageObj;
const { height } = imageObj;
file.width = width;
file.height = height;
resolve(file);
};
};
reader.onerror = error => reject(error);
});
customRequest = async ({ file, onError, onSuccess }) => {
const imgSize = await this.imageSize(file);
const vm = this;
const observable = qiniu.upload(file, null, token);
const observer = {
next() {
......@@ -67,6 +103,17 @@ class PicturesWall extends React.Component {
const comFile = file;
const url = `${qiniuHost}/${res.hash}`;
comFile.url = url;
const list = vm.state.fileList;
list.push({
url: file.url,
name: file.name,
uid: list.length,
status: 'done',
});
vm.setState({ fileList: [...list] });
const urlList = list.map(item => item.url);
vm.props.onChange(urlList);
onSuccess(comFile);
// ...
},
......@@ -94,15 +141,17 @@ class PicturesWall extends React.Component {
</div>
);
const { max } = this.props;
return (
<div className="clearfix">
<Upload
{...this.props}
customRequest={this.customRequest}
listType="picture-card"
fileList={fileList}
onPreview={this.handlePreview}
onChange={this.handleChange}
{...this.props}
multiple
>
{max && fileList.length >= max ? null : uploadButton}
</Upload>
......
import React, { useState, useRef } from 'react';
import ProTable from '@ant-design/pro-table';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { notification, Button, Modal, Image, message } from 'antd';
import { query } from './services';
const ContractView = () => {
const [visible, setVisible] = useState(false);
const [url, setUrl] = useState();
// 查看
const onLook = ({ contractPdfUrl }) => {
if (contractPdfUrl) {
setUrl(contractPdfUrl);
setVisible(true);
} else {
message.error('暂无合同');
}
};
// 下载
const ondown = ({ contractPdfUrl }) => {
if (contractPdfUrl) {
window.open(contractPdfUrl);
} else {
message.error('暂无合同');
}
};
const columns = [
{
title: '合同名称',
dataIndex: 'contractName',
key: 'contractName',
align: 'center',
},
{
title: '签约时间',
dataIndex: 'signDate',
key: 'signDate',
align: 'center',
hideInSearch: true,
},
{
title: '合同状态',
dataIndex: 'state',
key: 'state',
align: 'center',
filters: false,
valueEnum: {
0: '失效',
1: '有效',
},
},
{
title: '操作',
dataIndex: 'action',
width: 200,
align: 'center',
hideInSearch: true,
render: (text, record) => (
<>
<Button
key="edit"
type="primary"
onClick={() => onLook(record)}
style={{ marginRight: '10px' }}
>
查看
</Button>
<Button key="del" type="primary" onClick={() => ondown(record)}>
下载
</Button>
</>
),
},
];
return (
<PageHeaderWrapper>
<ProTable
search={{
collapsed: false,
collapseRender: () => null,
}}
columns={columns}
request={params => query({ ...params })}
rowKey={r => r.appealNo}
expandIconColumnIndex={10}
bordered
toolBarRender={false}
scroll={{ x: '100%', y: 400 }}
/>
<Modal visible={visible} width="1000px" onCancel={() => setVisible(false)}>
<iframe src={url} height="500" width="95%" title="合同"></iframe>
</Modal>
</PageHeaderWrapper>
);
};
export default ContractView;
import { stringify } from 'querystring';
import request from '@/utils/request';
import _ from 'lodash';
import config from '../../../config/env.config';
const { goodsApi } = config;
// 分页查询所有数据
export async function query(params) {
const param = {
...params,
pageIndex: params.current,
pageSize: params.pageSize || 20,
};
const data = await request.post('/api/merchants/suppliers/contract/list', {
prefix: goodsApi,
data: param,
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
});
if (data.data) {
return {
data: data.data,
};
}
return {
total: 0,
data: [],
};
}
/* eslint-disable prefer-destructuring */
import { parse } from 'querystring';
import pathRegexp from 'path-to-regexp';
import moment from 'moment';
......@@ -127,3 +128,25 @@ export const getClientInfo = () => {
};
export const getObjectType = v => Object.prototype.toString.call(v).replace(/\[object |]/g, '');
// 获取长表单错误提示
export const getErrorMessage = err => {
const message = '请检查表单数据!';
// eslint-disable-next-line wrap-iife
// (function getMsg(v) {
// if (Array.isArray(v)) {
// getMsg(v[0]);
// } else {
// const keys = Object.keys(v);
// if (Array.isArray(v[keys[0]])) {
// getMsg(v[keys[0]][0]);
// } else if (v[keys[0]].errors && v[keys[0]].errors.length) {
// // eslint-disable-next-line no-const-assign
// message = v[keys[0]].errors[0].message;
// } else {
// getMsg(v);
// }
// }
// })(err);
return message;
};
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