Commit 27cb99be authored by 张子雨's avatar 张子雨

feat: 中台一期

parent 3581b8d6
...@@ -273,6 +273,18 @@ export default { ...@@ -273,6 +273,18 @@ export default {
name: 'systemManageLog', name: 'systemManageLog',
component: './systemManage/Log', component: './systemManage/Log',
}, },
{
title: '商户管理后台-合同查看',
path: '/contractView',
name: 'contractView',
component: './contractView',
},
{
title: '商户管理后台-商家资料',
path: '/businessInfo',
name: 'businessInfo',
component: './businessManage/info',
},
{ {
component: './404', component: './404',
}, },
......
This diff is collapsed.
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>
);
};
.table :global .ant-table-row-expand-icon-cell {
visibility: hidden;
}
.table :global .ant-table-expanded-row .ant-pro-table {
margin-left: -17px;
}
.logBtn {
display: inherit;
margin: 20px auto;
}
.pageHeader {
background-color: #fff;
border: 1px solid #ebedf0;
}
.listHeader {
display: flex;
}
.listHeader--item {
position: relative;
display: flex;
align-items: center;
width: 40px;
height: 40px;
text-align: center;
justify-content: center;
box-sizing: border-box;
margin-right: 20px;
font-size: 14px;
line-height: 14px;
border: 1px solid #333;
border-radius: 50%;
}
.listHeader--item::after {
position: absolute;
right: -21px;
width: 20px;
height: 1px;
background-color: #333;
content: '';
}
.listHeader--item:last-child::after {
width: 0;
height: 0;
}
import React from 'react';
import moment from 'moment';
import { PlusOutlined } from '@ant-design/icons';
import { notification, Tag, Tooltip, Input } from 'antd';
// import { reject } from 'lodash-es';
import {
uploadFile,
apiCategoryList,
apiAddrArea,
apiServiceFacility,
apiApplyDetail,
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 async function getInfo(id, type) {
let api = apiApplyDetail;
if (['info', 'edit', 'revision'].includes(type)) {
api = apiBusinessDetail;
}
const [res] = await api(id);
let settlementType = 1;
if (res) {
if (res.facilities) {
res.customList = res.facilities.customList || [];
res.selfList = res.facilities.selfList || [];
}
res.accountOpenPermitImage = [{ uid: 0, url: res.accountOpenPermitImage }];
res.businessLicenseImage = [{ uid: 0, url: res.businessLicenseImage }];
res.idCardEmblemImage = [{ uid: 0, url: res.idCardEmblemImage }];
res.idCardPortraitImage = [{ uid: 0, url: res.idCardPortraitImage }];
res.primaryImage = [{ uid: 0, url: res.primaryImage }];
res.sealImage = [{ uid: 0, url: res.sealImage }];
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;
}
res.legalPersonPeriod = res.legalPersonPeriod.split('-').map(item => moment(item));
res.businessLicensePeriod = moment(res.businessLicensePeriod);
this.setState({
settlementType,
businessInfo: res,
});
}
// 删除图片
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 getCategoryList() {
const [res] = await apiCategoryList();
if (res) {
this.setState({
categoryList: res,
});
}
}
// 获取服务设施
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,
}));
// 编辑时 回显 市、区、街道
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],
});
}
}
This diff is collapsed.
.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 {
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 } = config;
// 获取地址
export const apiAddrArea = params =>
request.post('/api/merchants/addresses/list', {
prefix: kdspApi,
data: params,
emulateJSON: true,
});
// 主营类目
export const apiCategoryList = params =>
request.post('/product/category/list', { prefix: kdspApi, params });
// 服务设施
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 apiNewStoreInfo = params =>
request.post(`${kdspApi}/api/merchants/suppliers/register`, { prefix: kdspApi, data: params });
// 图片内容识别
export const apiRecognize = params =>
request.get(`/api/merchants/images/recognize?${qs.stringify(params)}`, { prefix: kdspApi });
// 编辑商户信息
export const apiEditStoreInfo = params =>
request.post(`${kdspApi}/api/merchants/suppliers/pops/edit`, { prefix: kdspApi, data: params });
// 查询申请详情
export const apiApplyDetail = applyId =>
request.get(`${kdspApi}/api/merchants/suppliers/register/detail?applyId=${applyId}`);
// 查询商户详情
export const apiBusinessDetail = businessId =>
request.get(`${kdspApi}/api/merchants/suppliers/pops/detail/${businessId}`);
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;
}
}
}
...@@ -8,6 +8,7 @@ import { weekOptions, weekDefault, layout } from '../data'; ...@@ -8,6 +8,7 @@ import { weekOptions, weekDefault, layout } from '../data';
import MapModal from '@/components/GaoDeMap'; import MapModal from '@/components/GaoDeMap';
import style from './style.less'; import style from './style.less';
import { isCheckNumberLine } from '@/utils/validator'; import { isCheckNumberLine } from '@/utils/validator';
import Upload from '../../components/upload';
const FormItem = Form.Item; const FormItem = Form.Item;
...@@ -17,6 +18,7 @@ const StoreModal = props => { ...@@ -17,6 +18,7 @@ const StoreModal = props => {
onCancel, onCancel,
form: { getFieldDecorator, setFieldsValue, getFieldsValue, validateFields, resetFields }, form: { getFieldDecorator, setFieldsValue, getFieldsValue, validateFields, resetFields },
formInfo, formInfo,
status,
} = props; } = props;
const [areaAddr, setAreaAddr] = useState([]); const [areaAddr, setAreaAddr] = useState([]);
const [visibleMap, setVisibleMap] = useState(false); const [visibleMap, setVisibleMap] = useState(false);
...@@ -26,9 +28,13 @@ const StoreModal = props => { ...@@ -26,9 +28,13 @@ const StoreModal = props => {
provice: '', provice: '',
address: '', address: '',
}); });
const [disabled, setDisabled] = useState(false);
const divDom = useRef(); const divDom = useRef();
useEffect(() => {
setDisabled(props.status);
}, [props.status]);
const handleCancel = isSuccess => { const handleCancel = isSuccess => {
resetFields(); resetFields();
onCancel(isSuccess); onCancel(isSuccess);
...@@ -197,6 +203,8 @@ const StoreModal = props => { ...@@ -197,6 +203,8 @@ const StoreModal = props => {
setAreaAddr([...arr]); setAreaAddr([...arr]);
}; };
const normFile = fileList => fileList;
useEffect(() => { useEffect(() => {
if (visible) { if (visible) {
resetFields(); resetFields();
...@@ -241,6 +249,14 @@ const StoreModal = props => { ...@@ -241,6 +249,14 @@ const StoreModal = props => {
onCancel={() => handleCancel()} onCancel={() => handleCancel()}
> >
<Form {...layout} name="formData"> <Form {...layout} name="formData">
<FormItem label="门店头像">
{getFieldDecorator('supplement', {
rules: [{ required: true, message: '请上传门店头像' }],
initialValue: formData.shopHeadImage || [],
valuePropName: 'fileList',
getValueFromEvent: normFile,
})(<Upload max={1} accept=".jpg,.png,.jpeg" disabled={disabled} />)}
</FormItem>
<FormItem <FormItem
label="门店名称" label="门店名称"
name="name" name="name"
...@@ -249,7 +265,7 @@ const StoreModal = props => { ...@@ -249,7 +265,7 @@ const StoreModal = props => {
{getFieldDecorator('name', { {getFieldDecorator('name', {
rules: [{ required: true, message: '请输入门店名称!' }], rules: [{ required: true, message: '请输入门店名称!' }],
initialValue: formData.name, initialValue: formData.name,
})(<Input placeholder="请输入门店名称" allowClear maxLength={20} />)} })(<Input placeholder="请输入门店名称" allowClear maxLength={20} disabled={disabled} />)}
</FormItem> </FormItem>
<FormItem label="门店电话" name="phone"> <FormItem label="门店电话" name="phone">
{getFieldDecorator('phone', { {getFieldDecorator('phone', {
...@@ -258,7 +274,7 @@ const StoreModal = props => { ...@@ -258,7 +274,7 @@ const StoreModal = props => {
{ validator: isCheckNumberLine, message: '请输入正确的门店电话!' }, { validator: isCheckNumberLine, message: '请输入正确的门店电话!' },
], ],
initialValue: formData.phone, initialValue: formData.phone,
})(<Input placeholder="请输入门店电话" allowClear maxLength={20} />)} })(<Input placeholder="请输入门店电话" allowClear maxLength={20} disabled={disabled} />)}
</FormItem> </FormItem>
<FormItem label="营业时间" required> <FormItem label="营业时间" required>
{times && {times &&
...@@ -269,18 +285,25 @@ const StoreModal = props => { ...@@ -269,18 +285,25 @@ const StoreModal = props => {
{getFieldDecorator(item.name, { {getFieldDecorator(item.name, {
rules: [{ required: true, message: '请选择营业时间!' }], rules: [{ required: true, message: '请选择营业时间!' }],
initialValue: formData[item.name], initialValue: formData[item.name],
})(<TimePicker.RangePicker format="HH:mm" />)} })(<TimePicker.RangePicker format="HH:mm" disabled={disabled} />)}
</FormItem> </FormItem>
</div> </div>
{i > 0 ? ( {!disabled &&
<div className={style.timerWrapperRight} onClick={() => onTimeMinus(i)}> (i > 0 ? (
<MinusSquareFilled style={{ color: '#ff4d4f', fontSize: '30px' }} /> <div className={style.timerWrapperRight} onClick={() => onTimeMinus(i)}>
</div> <MinusSquareFilled
) : ( style={{ color: '#ff4d4f', fontSize: '30px' }}
<div className={style.timerWrapperRight} onClick={() => onTimePlus()}> disabled={disabled}
<PlusSquareFilled style={{ color: '#1890ff', fontSize: '30px' }} /> />
</div> </div>
)} ) : (
<div className={style.timerWrapperRight} onClick={() => onTimePlus()}>
<PlusSquareFilled
style={{ color: '#1890ff', fontSize: '30px' }}
disabled={disabled}
/>
</div>
))}
</div> </div>
))} ))}
</FormItem> </FormItem>
...@@ -288,7 +311,7 @@ const StoreModal = props => { ...@@ -288,7 +311,7 @@ const StoreModal = props => {
{getFieldDecorator('week', { {getFieldDecorator('week', {
rules: [{ required: true, message: '请选择营业日!' }], rules: [{ required: true, message: '请选择营业日!' }],
initialValue: formData.week || weekDefault, initialValue: formData.week || weekDefault,
})(<Checkbox.Group options={weekOptions} />)} })(<Checkbox.Group options={weekOptions} disabled={disabled} />)}
</FormItem> </FormItem>
<FormItem label="店铺区域"> <FormItem label="店铺区域">
{getFieldDecorator('addr', { {getFieldDecorator('addr', {
...@@ -301,6 +324,7 @@ const StoreModal = props => { ...@@ -301,6 +324,7 @@ const StoreModal = props => {
placeholder="请选择店铺区域" placeholder="请选择店铺区域"
loadData={e => loadData(e)} loadData={e => loadData(e)}
changeOnSelect changeOnSelect
disabled={disabled}
/>, />,
)} )}
</FormItem> </FormItem>
...@@ -308,7 +332,14 @@ const StoreModal = props => { ...@@ -308,7 +332,14 @@ const StoreModal = props => {
{getFieldDecorator('address', { {getFieldDecorator('address', {
rules: [{ required: true, message: '请输入详细地址!' }], rules: [{ required: true, message: '请输入详细地址!' }],
initialValue: formData.address, initialValue: formData.address,
})(<Input placeholder="请输入详细地址,不包含省市区地址" allowClear maxLength={50} />)} })(
<Input
placeholder="请输入详细地址,不包含省市区地址"
allowClear
maxLength={50}
disabled={disabled}
/>,
)}
</FormItem> </FormItem>
<FormItem label="经纬度"> <FormItem label="经纬度">
{getFieldDecorator('lnglat', { {getFieldDecorator('lnglat', {
...@@ -320,6 +351,7 @@ const StoreModal = props => { ...@@ -320,6 +351,7 @@ const StoreModal = props => {
readOnly readOnly
onClick={() => openMap(true)} onClick={() => openMap(true)}
maxLength={100} maxLength={100}
disabled={disabled}
/>, />,
)} )}
</FormItem> </FormItem>
...@@ -328,12 +360,17 @@ const StoreModal = props => { ...@@ -328,12 +360,17 @@ const StoreModal = props => {
rules: [{ required: true, message: '请选择是否启用!' }], rules: [{ required: true, message: '请选择是否启用!' }],
initialValue: formData.state, initialValue: formData.state,
})( })(
<Radio.Group> <Radio.Group disabled={disabled}>
<Radio value={1}></Radio> <Radio value={1}></Radio>
<Radio value={0}></Radio> <Radio value={0}></Radio>
</Radio.Group>, </Radio.Group>,
)} )}
</FormItem> </FormItem>
<FormItem label="门店公告">
{getFieldDecorator('publicNotice', {
initialValue: formData.publicNotice,
})(<Input placeholder="请输入门店公告" maxLength={120} disabled={disabled} />)}
</FormItem>
</Form> </Form>
<MapModal <MapModal
visible={visibleMap} visible={visibleMap}
......
import React, { useState, useRef, useEffect } from 'react'; 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,
} from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import { el } from 'date-fns/locale';
import { searchList, apiEnableStore, apiAddrArea } from './services'; import { searchList, apiEnableStore, apiAddrArea } from './services';
import { stateDesc, weeks, layout } from './data'; import { stateDesc, weeks, layout } from './data';
import StoreModal from './components/storeModal'; import StoreModal from './components/storeModal';
import style from './style.less'; import style from './style.less';
const { confirm } = Modal;
export default () => { export default () => {
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [storeInfo, setStoreInfo] = useState({}); const [storeInfo, setStoreInfo] = useState({});
const [areaAddr, setAreaAddr] = useState([]); const [areaAddr, setAreaAddr] = useState([]);
const [status, setStatus] = useState();
const [dataList, setDataList] = useState([]); const [dataList, setDataList] = useState([]);
const [pageNo, setPageNo] = useState(1); const [pageNo, setPageNo] = useState(1);
const [totalNum, setTotalNum] = useState(0); const [totalNum, setTotalNum] = useState(0);
...@@ -20,8 +34,11 @@ export default () => { ...@@ -20,8 +34,11 @@ export default () => {
setStoreInfo({}); setStoreInfo({});
setVisible(true); setVisible(true);
}; };
const onShowInfo = info => { const onShowInfo = (info, val) => {
setStoreInfo(info); setStoreInfo(info);
const value = val !== 'edit';
console.log(value);
setStatus(value);
setVisible(true); setVisible(true);
}; };
...@@ -101,7 +118,8 @@ export default () => { ...@@ -101,7 +118,8 @@ export default () => {
setStoreInfo({}); setStoreInfo({});
setVisible(false); setVisible(false);
}; };
const onEnableState = async ({ id, state }) => {
const enableStore = async (id, state) => {
const enable = +state === 1 ? 0 : 1; const enable = +state === 1 ? 0 : 1;
const res = await apiEnableStore({ id, state: enable }); const res = await apiEnableStore({ id, state: enable });
if (res === '0000') { if (res === '0000') {
...@@ -109,11 +127,25 @@ export default () => { ...@@ -109,11 +127,25 @@ export default () => {
onSearch(refSearch.current?.getFieldValue?.() || {}); onSearch(refSearch.current?.getFieldValue?.() || {});
} }
}; };
const onEnableState = async ({ id, state }) => {
if (state) {
confirm({
title: '确认要禁用这家门店吗?',
content: '禁用后用户将无法看到该店铺',
onOk() {
enableStore(id, state);
},
});
} else {
enableStore(id, state);
}
};
const onReset = () => { const onReset = () => {
if (refSearch.current && refSearch.current.resetFields) { if (refSearch.current && refSearch.current.resetFields) {
refSearch.current.resetFields(); refSearch.current.resetFields();
} }
getList();
}; };
const onPageChange = (e, size) => { const onPageChange = (e, size) => {
...@@ -233,14 +265,19 @@ export default () => { ...@@ -233,14 +265,19 @@ export default () => {
dataIndex: 'action', dataIndex: 'action',
width: 170, width: 170,
fixed: 'right', fixed: 'right',
render: (val, r) => [ render: (val, r) => (
<Button key="enable1" onClick={() => onEnableState(r)} type="primary"> <div className={style.actionBtn}>
{+r.state ? '禁用' : '启用'} <Button key="look" onClick={() => onShowInfo(r)}>
</Button>, 查看
<Button key="seek" style={{ marginLeft: '10px' }} onClick={() => onShowInfo(r)}> </Button>
查看 <Button key="seek" onClick={() => onShowInfo(r, 'edit')}>
</Button>, 修改
], </Button>
<Button key="enable1" onClick={() => onEnableState(r)} type="primary">
{+r.state ? '禁用' : '启用'}
</Button>
</div>
),
}, },
]; ];
return ( return (
...@@ -285,7 +322,7 @@ export default () => { ...@@ -285,7 +322,7 @@ export default () => {
pagination={false} pagination={false}
scroll={{ x: '100%' }} scroll={{ x: '100%' }}
/> />
{dataList && dataList.length && ( {dataList && dataList.length ? (
<div className={style.pageBox}> <div className={style.pageBox}>
<Pagination <Pagination
style={{ marginBottom: 10 }} style={{ marginBottom: 10 }}
...@@ -298,8 +335,8 @@ export default () => { ...@@ -298,8 +335,8 @@ export default () => {
onShowSizeChange={onPageChange} onShowSizeChange={onPageChange}
/> />
</div> </div>
)} ) : null}
<StoreModal visible={visible} onCancel={closeModal} formInfo={storeInfo} /> <StoreModal visible={visible} onCancel={closeModal} formInfo={storeInfo} status={status} />
</div> </div>
); );
}; };
...@@ -13,3 +13,13 @@ ...@@ -13,3 +13,13 @@
border: 1px solid #f0f0f0; border: 1px solid #f0f0f0;
border-top: 0; border-top: 0;
} }
.actionBtn {
display: flex;
flex-direction: column;
align-items: center;
button {
width: 75px;
margin-bottom: 5px;
}
}
import { PlusOutlined } from '@ant-design/icons'; import { PlusOutlined } from '@ant-design/icons';
import { Upload, Modal, message } from 'antd'; import { Upload, Modal, notification } from 'antd';
import React from 'react'; import React from 'react';
import config from '../../../config/env.config'; import config from '../../../config/env.config';
import { qiniuToken } from '@/services/qiniu'; import { qiniuToken } from '@/services/qiniu';
...@@ -7,7 +7,6 @@ import { qiniuToken } from '@/services/qiniu'; ...@@ -7,7 +7,6 @@ import { qiniuToken } from '@/services/qiniu';
const qiniu = require('@/utils/qiniu.min.js'); const qiniu = require('@/utils/qiniu.min.js');
const { qiniuHost } = config; const { qiniuHost } = config;
function getBase64(file) { function getBase64(file) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const reader = new FileReader(); const reader = new FileReader();
...@@ -26,9 +25,25 @@ class PicturesWall extends React.Component { ...@@ -26,9 +25,25 @@ class PicturesWall extends React.Component {
}; };
async componentDidMount() { async componentDidMount() {
this.initFileList(this.props.fileList || []);
token = await qiniuToken(); token = await qiniuToken();
} }
componentWillReceiveProps(nextProps) {
this.initFileList(nextProps.fileList || []);
}
initFileList = fileList => {
const fileLists =
fileList.map((item, index) => ({
url: item,
name: '',
uid: index,
status: 'done',
})) || [];
this.setState({ fileList: fileLists });
};
handleCancel = () => this.setState({ previewVisible: false }); handleCancel = () => this.setState({ previewVisible: false });
handlePreview = async file => { handlePreview = async file => {
...@@ -43,17 +58,37 @@ class PicturesWall extends React.Component { ...@@ -43,17 +58,37 @@ class PicturesWall extends React.Component {
}); });
}; };
handleChange = info => { handleChange = ({ fileList }) => {
const lastFile = (info.fileList.length && info.fileList[info.fileList.length - 1]) || []; const file = fileList.filter(item => item.url);
const types = ['application/pdf', 'image/png', 'image/jpeg']; this.setState({ fileList: [...file] });
if (lastFile && types.indexOf(lastFile.type) === -1) { const urlList = file.map(item => item.url);
message.error('文件格式错误!'); this.props.onChange(urlList);
}
const fileList = info.fileList.filter(item => types.indexOf(item.type) !== -1);
this.setState({ fileList });
}; };
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 observable = qiniu.upload(file, null, token);
const observer = { const observer = {
next() { next() {
...@@ -67,6 +102,17 @@ class PicturesWall extends React.Component { ...@@ -67,6 +102,17 @@ class PicturesWall extends React.Component {
const comFile = file; const comFile = file;
const url = `${qiniuHost}/${res.hash}`; const url = `${qiniuHost}/${res.hash}`;
comFile.url = url; 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); onSuccess(comFile);
// ... // ...
}, },
...@@ -94,15 +140,17 @@ class PicturesWall extends React.Component { ...@@ -94,15 +140,17 @@ class PicturesWall extends React.Component {
</div> </div>
); );
const { max } = this.props; const { max } = this.props;
return ( return (
<div className="clearfix"> <div className="clearfix">
<Upload <Upload
{...this.props}
customRequest={this.customRequest} customRequest={this.customRequest}
listType="picture-card" listType="picture-card"
fileList={fileList} fileList={fileList}
onPreview={this.handlePreview} onPreview={this.handlePreview}
onChange={this.handleChange} onChange={this.handleChange}
{...this.props} multiple
> >
{max && fileList.length >= max ? null : uploadButton} {max && fileList.length >= max ? null : uploadButton}
</Upload> </Upload>
......
import React, { useState, useRef } from 'react';
import ProTable from '@ant-design/pro-table';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { notification, Button } from 'antd';
import { query } from './services';
const ContractView = () => {
// 查看
const onLook = ({ contractPdfUrl }) => {
console.log(contractPdfUrl);
};
// 下载
const ondown = ({ contractPdfUrl }) => {
console.log(contractPdfUrl);
};
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 }}
/>
</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 = {
pageNo: params.current || 1,
pageSize: params.pageSize || 20,
};
const data = await request.post('/api/kdsp/template/page', {
prefix: goodsApi,
data: stringify(_.omitBy(param, v => !v)),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
if (data.data) {
return {
total: data.data.total,
data: data.data.forbiddenAreaTemplateList,
};
}
return {
total: 0,
data: [],
};
}
// 添加区域受限模板
export async function getAddTemplate(param) {
const data = await request.post('/api/kdsp/add/template', {
prefix: goodsApi,
data: param,
});
return data;
}
// 获取区域地址
export async function areaList(params) {
const { data } = await request.get('/api/merchants/addresses/list', {
prefix: goodsApi,
params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
return data;
}
// 根据模板id查询受限区域
export async function forbiddenAddress(params) {
const data = await request.post('/api/kdsp/edit/template', {
prefix: goodsApi,
data: params,
});
return data;
}
// 根据模板id查询受限区域
export async function addressTree(params) {
const data = await request.post('/api/kdsp/forbidden/address', {
prefix: goodsApi,
params,
});
return data;
}
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