Commit f6093a53 authored by 张子雨's avatar 张子雨

Merge branch 'feature/meal-3.0' into feat/storeManagement

* feature/meal-3.0:
  fix: 修改报错信息
  feat: 添加接口前缀
  feat: 对接企业外卖、虚拟商品接口
  feat: 添加平台校验
  feat: 添加外卖商品列表逻辑
  feat: 添加企业客户逻辑
  feat: 添加外卖商品列表
  feat: 升级antd + react
  feat: 添加外卖商品列表
  feat: 添加企业客户信息
  feat: 添加企业客户
  fix: 修改注释
  fix: 处理token 获取不到的问题
  fix: 处理获取token 问题
  feat: 处理tob 接口请求token过期问题
  feat: 添加tob进入页面入口
parents 700fb950 1930d4c8
import slash from 'slash2'; import slash from 'slash2';
import defaultSettings from './defaultSettings'; // https://umijs.org/config/ import defaultSettings from './defaultSettings'; // https://umijs.org/config/
import webpackPlugin from './plugin.config'; import webpackPlugin from './plugin.config';
import groupMealRoute from './groupMealRoute';
const { pwa, primaryColor } = defaultSettings; // preview.pro.ant.design only do not use in your production ; const { pwa, primaryColor } = defaultSettings; // preview.pro.ant.design only do not use in your production ;
// preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。 // preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。
......
export default [
{
title: '商户管理后台-企业团餐-企业客户',
path: '/businessCustomer',
name: 'BusinessCustomer',
component: './businessCustomer/index',
},
{
title: '商户管理后台-企业团餐-外卖商品',
path: '/takeawayGoods',
name: 'TakeawayGoods',
component: './businessGoods/takeawayGoods',
},
{
title: '商户管理后台-企业团餐-外卖商品',
path: '/takeawayGoods',
name: 'TakeawayGoods',
component: './businessGoods/takeawayGoods',
},
{
title: '商户管理后台-企业团餐-外卖商品-添加商品',
path: '/takeawayGoodsInfo',
name: 'TakeawayGoodsInfo',
component: './businessGoods/takeawayGoodsInfo',
},
{
title: '商户管理后台-企业团餐-虚拟商品',
path: '/virtualGoods',
name: 'VirtualGoods',
component: './businessGoods/virtualGoods',
},
{
title: '商户管理后台-企业团餐-虚拟商品-添加商品',
path: '/takeawayGoodsInfo',
name: 'TakeawayGoodsInfo',
component: './businessGoods/virtualGoodsInfo',
},
];
This diff is collapsed.
...@@ -51,12 +51,14 @@ ...@@ -51,12 +51,14 @@
"dependencies": { "dependencies": {
"@ant-design/colors": "^3.1.0", "@ant-design/colors": "^3.1.0",
"@ant-design/compatible": "^1.1.0", "@ant-design/compatible": "^1.1.0",
"@ant-design/cssinjs": "^1.10.1",
"@ant-design/icons": "^4.7.0", "@ant-design/icons": "^4.7.0",
"@ant-design/pro-components": "^2.3.59",
"@ant-design/pro-layout": "^4.11.4", "@ant-design/pro-layout": "^4.11.4",
"@ant-design/pro-table": "^1.0.31", "@ant-design/pro-table": "^1.0.31",
"@antv/data-set": "^0.10.2", "@antv/data-set": "^0.10.2",
"@sentry/react": "^7.41.0", "@sentry/react": "^7.41.0",
"antd": "^4.19.3", "antd": "^4.24.10",
"antd-img-crop": "4.12.2", "antd-img-crop": "4.12.2",
"antd-virtual-select": "^1.1.2", "antd-virtual-select": "^1.1.2",
"array-move": "^4.0.0", "array-move": "^4.0.0",
...@@ -71,13 +73,13 @@ ...@@ -71,13 +73,13 @@
"path-to-regexp": "^3.1.0", "path-to-regexp": "^3.1.0",
"pubsub-js": "^1.9.4", "pubsub-js": "^1.9.4",
"qs": "^6.9.0", "qs": "^6.9.0",
"react": "^16.8.6", "react": "^16.14.0",
"react-amap": "^1.2.8", "react-amap": "^1.2.8",
"react-bmapgl": "^0.2.17", "react-bmapgl": "^0.2.17",
"react-copy-to-clipboard": "^5.0.1", "react-copy-to-clipboard": "^5.0.1",
"react-dnd": "10.0.2", "react-dnd": "10.0.2",
"react-dnd-html5-backend": "10.0.2", "react-dnd-html5-backend": "10.0.2",
"react-dom": "^16.8.6", "react-dom": "^16.14.0",
"react-helmet": "^5.2.1", "react-helmet": "^5.2.1",
"react-router-dom": "^5.1.2", "react-router-dom": "^5.1.2",
"react-sortable-hoc": "^2.0.0", "react-sortable-hoc": "^2.0.0",
......
...@@ -69,3 +69,10 @@ ol { ...@@ -69,3 +69,10 @@ ol {
} }
} }
} }
.ant-pro-card-body {
padding: 0 !important;
}
.ant-pro-table-list-toolbar-container {
box-sizing: border-box;
padding: 10px 30px !important;
}
...@@ -11,9 +11,10 @@ import { connect } from 'dva'; ...@@ -11,9 +11,10 @@ import { connect } from 'dva';
import { Icon as LegacyIcon } from '@ant-design/compatible'; import { Icon as LegacyIcon } from '@ant-design/compatible';
import { Result, Button, Layout, Menu } from 'antd'; import { Result, Button, Layout, Menu } from 'antd';
import Authorized from '@/utils/Authorized'; import Authorized from '@/utils/Authorized';
import localStorage from '@/utils/localStorage';
import RightContent from '@/components/GlobalHeader/RightContent'; import RightContent from '@/components/GlobalHeader/RightContent';
import MessageReminder from '@/components/MessageReminder'; import MessageReminder from '@/components/MessageReminder';
import { getAuthorityFromRouter } from '@/utils/utils'; import { getAuthorityFromRouter, getUrlSearchParams, getToken } from '@/utils/utils';
import { getSocketUrl } from '@/services/messageReminder'; import { getSocketUrl } from '@/services/messageReminder';
import logo from '../assets/logo.png'; import logo from '../assets/logo.png';
import style from './BasicLayout.less'; import style from './BasicLayout.less';
...@@ -54,11 +55,12 @@ const BasicLayout = props => { ...@@ -54,11 +55,12 @@ const BasicLayout = props => {
const [siderCollapsed, setSiderCollapsed] = useState(false); const [siderCollapsed, setSiderCollapsed] = useState(false);
const messageReminderComplexRef = useRef(); const messageReminderComplexRef = useRef();
// const audioRef = useRef() // const audioRef = useRef()
useEffect(() => { useEffect(() => {
try { try {
const token = window.localStorage.getItem('token'); const token = getToken();
const socket = new Socket({ const socket = new Socket({
url: getSocketUrl({ token, channelId: CHANNEL_ID }), url: getSocketUrl({ token, channelId: CHANNEL_ID }),
}); });
...@@ -131,7 +133,8 @@ const BasicLayout = props => { ...@@ -131,7 +133,8 @@ const BasicLayout = props => {
), ),
); );
return window.__POWERED_BY_QIANKUN__ ? ( // 乾坤嵌套进入系统
const qianKunLayout = () => (
<div id="micro"> <div id="micro">
<Layout className={style.layout}> <Layout className={style.layout}>
<Sider <Sider
...@@ -148,7 +151,10 @@ const BasicLayout = props => { ...@@ -148,7 +151,10 @@ const BasicLayout = props => {
</Layout> </Layout>
</Layout> </Layout>
</div> </div>
) : ( );
// 商家端直接进入系统
const merchantLayout = () => (
<ProLayout <ProLayout
logo={logo} logo={logo}
onCollapse={handleMenuCollapse} onCollapse={handleMenuCollapse}
...@@ -206,6 +212,26 @@ const BasicLayout = props => { ...@@ -206,6 +212,26 @@ const BasicLayout = props => {
{/* <Button ref={audioRef} onClick={() => { socket.play() }}>声音</Button> */} {/* <Button ref={audioRef} onClick={() => { socket.play() }}>声音</Button> */}
</ProLayout> </ProLayout>
); );
// tob后管嵌套进入系统
const tobLayout = () => (
<Layout className={style.tobLayout}>
<Authorized noMatch={noMatch}>{children}</Authorized>
</Layout>
);
// 是否从消费地图后管跳转过来
const searchPrams = getUrlSearchParams();
const isTob = searchPrams.source === 'tob';
if (window.__POWERED_BY_QIANKUN__) {
return qianKunLayout();
}
if (isTob && searchPrams.token) {
console.log('window.parent :>> ', window.parent);
return tobLayout();
}
return merchantLayout();
}; };
export default connect(({ global, settings, menu }) => ({ export default connect(({ global, settings, menu }) => ({
collapsed: global.collapsed, collapsed: global.collapsed,
......
...@@ -44,3 +44,11 @@ ...@@ -44,3 +44,11 @@
} }
} }
} }
.tobLayout {
:global {
.ant-pro-page-header-wrap-page-header-warp {
display: none !important;
}
}
}
...@@ -3,6 +3,8 @@ import { connect } from 'dva'; ...@@ -3,6 +3,8 @@ import { connect } from 'dva';
import { Redirect } from 'umi'; import { Redirect } from 'umi';
import PageLoading from '@/components/PageLoading'; import PageLoading from '@/components/PageLoading';
import localStorage from '@/utils/localStorage'; import localStorage from '@/utils/localStorage';
import sessionStorage from '@/utils/sessionStorage';
import { getUrlSearchParams, getToken } from '@/utils/utils';
class SecurityLayout extends React.Component { class SecurityLayout extends React.Component {
state = { state = {
...@@ -24,13 +26,24 @@ class SecurityLayout extends React.Component { ...@@ -24,13 +26,24 @@ class SecurityLayout extends React.Component {
/* eslint-disable no-underscore-dangle */ /* eslint-disable no-underscore-dangle */
render() { render() {
// 判断是否从tob进入
const searchPrams = getUrlSearchParams();
const isTob = searchPrams.source === 'tob';
if (isTob) {
localStorage.set('tobToken', searchPrams.token || '');
// 角色 searchPrams.isMaster (1:平台 0:pop)
sessionStorage.set('role', +searchPrams.isMaster === 1 ? 'platform' : 'tobMerchant');
}
const { isReady } = this.state; const { isReady } = this.state;
let isLogin = true; let isLogin = true;
// 你可以把它替换成你自己的登录认证规则(比如判断 token 是否存在) // 你可以把它替换成你自己的登录认证规则(比如判断 token 是否存在)
const { children, loading } = this.props; const { children, loading } = this.props;
if (!localStorage.get('token')) { if (!getToken()) {
isLogin = false; isLogin = false;
} }
console.log('getToken() :>> ', getToken());
console.log('isLogin :>> ', isLogin);
// 切换子应用布局 // 切换子应用布局
if (window.__POWERED_BY_QIANKUN__) { if (window.__POWERED_BY_QIANKUN__) {
......
...@@ -4,8 +4,8 @@ import { Card, Pagination, Table, notification, Drawer, Spin, Button, Modal } fr ...@@ -4,8 +4,8 @@ import { Card, Pagination, Table, notification, Drawer, Spin, Button, Modal } fr
import React, { Component } from 'react'; import React, { Component } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { connect } from 'dva'; import { connect } from 'dva';
import { getToken } from '@/utils/utils';
import styles from './style.less'; import styles from './style.less';
import LocalStroage from '@/utils/localStorage';
import configApi from '../../../config/env.config'; import configApi from '../../../config/env.config';
import UpdateStock from './UpdateStock'; import UpdateStock from './UpdateStock';
...@@ -163,9 +163,9 @@ class goodsManage extends Component { ...@@ -163,9 +163,9 @@ class goodsManage extends Component {
audit = skuId => { audit = skuId => {
this.setState({ this.setState({
previewVisible: true, previewVisible: true,
src: `${configApi.prologueDomain}/goods/${skuId}?h=0&token=${LocalStroage.get( src: `${
'token', configApi.prologueDomain
)}&hideReport=1&time=${Date.now()}`, }/goods/${skuId}?h=0&token=${getToken()}&hideReport=1&time=${Date.now()}`,
}); });
}; };
......
import React, { useEffect, useState } from 'react';
import {
Button,
Divider,
Form,
Input,
InputNumber,
Checkbox,
Radio,
Col,
Row,
Modal,
Select,
message,
notification,
} from 'antd';
import { ExclamationCircleOutlined } from '@ant-design/icons';
import { jsonToArray } from '@/utils/utils';
import moment from 'moment';
import {
layout,
mealType,
boolOptions,
hideOptions,
infoOptions,
mealSections,
} from '../staticData/index';
import {
apiEnterpriseInfo,
apiNewEnterprise,
apiEditEnterprise,
apiEnterprisePickSelf,
} from '../service';
import style from '../style/info.less';
import MealSection from './MealSection';
import MealLimit from './MealLimit';
const CheckboxGroup = Checkbox.Group;
const RadioGroup = Radio.Group;
const { confirm } = Modal;
const CustomerInfo = props => {
const [form] = Form.useForm();
const [meals, setMeals] = useState({});
const [mealTypes, setMealTypes] = useState([]);
const [pickSelfList, setPickSelfList] = useState([]);
// 关闭分组信息弹窗
const handleCancel = () => {
props.handleClose(false);
};
// 校验时间
const checkTime = (arr, curren) => {
let valid = false;
arr.forEach(item => {
if (curren > item.beginTime && curren < item.endTime) {
valid = true;
}
});
return valid;
};
// 提交
const handleConfirm = async () => {
const res = await form.validateFields();
console.log('res :>> ', res);
// const res = await form.getFieldsValue();
if (res.mealTimePeriod.length < 1) {
message.warn('请选择餐段');
return;
}
const params = Object.assign(
{
hideImage: 0,
},
res,
);
const arr = [];
let validTime = false;
res.mealTimePeriod.forEach(item => {
if (item.mealPeriodType) {
const obj = Object.assign({}, item);
obj.beginTime = moment(obj.time[0]).format('HH:mm');
obj.endTime = moment(obj.time[1]).format('HH:mm');
delete obj.time;
if (checkTime(arr, obj.beginTime) || checkTime(arr, obj.endTime)) {
validTime = true;
}
arr.push(obj);
}
});
if (validTime) {
notification.error({ message: '时间段不能交叉!' });
return;
}
params.mealTimePeriod = arr;
if (res.hideInfo && res.hideInfo.length) {
params.hidePrice = res.hideInfo.includes('hidePrice') ? 1 : 0;
params.hideImage = res.hideInfo.includes('hideImage') ? 1 : 0;
delete params.hideInfo;
}
const limits = [];
if (!res.mealLimit) {
notification.error({ message: '请输入限额!' });
return;
}
// 处理限额
Object.keys(res.mealLimit).forEach(item => {
const json = {
mealPeriodType: item.replace('limit', ''),
limit: [],
};
Object.keys(res.mealLimit[item]).forEach(t => {
json.limit.push({
mealType: t,
limit: res.mealLimit[item][t],
});
});
limits.push(json);
});
params.mealLimit = limits;
console.log('params :>> ', params);
// let api = apiNewEnterprise;
// if (props.id) {
// params.id = props.id;
// api = apiEditEnterprise;
// }
// await api(params);
notification.success({ message: '保存成功!' });
};
// 风险提示
const checkConfirm = () => {
const mt = '';
return new Promise((resolve, reject) => {
confirm({
title: '风险提示',
icon: <ExclamationCircleOutlined />,
content: `确定关闭${mt}餐品类型?此餐品类型下关联的商户及商品将一并删除,不可逆请谨慎操作!`,
onOk() {
resolve(1);
},
onCancel() {
reject(new Error());
},
});
});
};
// 改变餐品类型
const onChangeMealType = async ms => {
try {
if (props.info && props.info.id && ms.length < mealTypes.length) {
await checkConfirm();
}
if (mealTypes.includes('1') && mealTypes.includes('2')) {
if (!(ms.includes('1') && ms.includes('2'))) {
if (ms.includes('4')) {
ms = ['4'];
} else {
ms = [];
}
}
} else if (ms.length < 3 && ms.length) {
ms = ['1', '2'];
if (ms.includes('4')) {
ms.push('4');
}
}
form.setFieldsValue({
mealType: ms,
});
setMealTypes(ms);
} catch {
form.setFieldsValue({
mealType: mealTypes,
});
}
};
// 改变餐段
const onChangeMealSection = e => {
console.log('e.target :>> ', e.target);
const { id, checked, label } = e.target;
const values = Object.assign({}, meals);
if (checked) {
values[id] = label;
// values.push(value);
// } else if (values.includes(value)) {
// const index = values.findIndex(v => v === value);
// values.splice(index, 1);
} else {
delete values[id];
}
console.log('values :>> ', values);
setMeals(values);
};
// 获取企业客户信息
const getInfo = async () => {
const res = await apiEnterpriseInfo(props.id);
const obj = Object.assign({}, res);
if (res.mealTimePeriod && res.mealTimePeriod.length) {
obj.mealTimePeriod = res.mealTimePeriod.map(item => ({
mealPeriodType: `${item.mealPeriodType}`,
time: [moment(item.beginTime), moment(item.endTime)],
}));
} else {
obj.mealTimePeriod = [];
}
if (res.mealLimit) {
obj.mealLimit = {};
res.mealLimit.forEach(item => {
obj.mealLimit[`limit${item.mealPeriodType}`] = {};
item.limit.forEach(limit => {
obj.mealLimit[`limit${item.mealPeriodType}`][limit.mealType] = limit.limit;
});
});
}
obj.hideInfo = [];
if (+res.hidePrice) {
obj.hideInfo.push('hidePrice');
}
if (+res.hideImage) {
obj.hideInfo.push('hideImage');
}
obj.mealType = res.mealType.map(item => `${item}`);
form.setFieldsValue(obj);
};
// 获取自提点列表
const getPickSelf = async () => {
const res = await apiEnterprisePickSelf({});
setPickSelfList(
res.map(item => ({
[item.id]: { text: item.name },
})),
);
};
useEffect(() => {
if (props.visible) {
if (props.id) {
getInfo();
} else {
getPickSelf();
}
} else {
form.setFieldsValue({});
}
}, [props.visible]);
return (
<Modal
title="企业客户信息"
open={props.visible}
destroyOnClose
maskClosable={false}
width="900px"
onOk={handleConfirm}
onCancel={handleCancel}
>
<Form
name="basicInfo"
initialValues={{ mealTimePeriod: [{}, {}, {}] }}
{...layout}
form={form}
>
<Form.Item
label="公司名称"
name="name"
rules={[{ required: true, message: '请输入公司名称!' }]}
>
<Input />
</Form.Item>
{!props.id && (
<Form.Item label="企业取餐点" name="pickselfIds">
<Select options={pickSelfList} />
</Form.Item>
)}
<Form.Item
label="企业截止时间"
name="endOrderTime"
wrapperCol={{ span: 20 }}
rules={[{ required: true, message: '请输入企业截止时间!' }]}
extra={<span>企业员工下单的截至时间,仅支持正整数,单位为分钟。</span>}
>
<Row>
<InputNumber min={0} max={600} addonAfter="分钟" />
</Row>
</Form.Item>
<Form.Item
label="餐品类型"
name="mealType"
rules={[{ required: true, message: '请选择餐品类型!' }]}
>
<CheckboxGroup options={jsonToArray(mealType)} onChange={onChangeMealType} />
</Form.Item>
<Form.Item label="餐段配置" required wrapperCol={{ span: 12 }}>
<MealSection meals={meals} onChange={onChangeMealSection} />
</Form.Item>
{/* <Form.Item
label="商品展示信息"
name="xinxin"
rules={[{ required: true, message: '请选择商品展示信息!' }]}
>
<CheckboxGroup options={infoOptions} />
</Form.Item> */}
<Divider orientation="left" plain>
企业单笔消费限额
</Divider>
<Form.List name="mealLimit">
{fields => (
<>
{Object.keys(meals).map(meal => (
<Form.Item label={`${mealSections[meal]}订单`} required wrapperCol={{ span: 20 }}>
<Form.List
name={`limit${meal}`}
key={`${meal}limit`}
required
wrapperCol={{ span: 20 }}
>
{fs => (
<Row key={`row${meal}`}>
{mealTypes.map((t, i) => (
<Col span={7} offset={i ? 1 : 0} key={t}>
<MealLimit value={t} label={mealType[t]} name={`${t}`} />
</Col>
))}
</Row>
)}
</Form.List>
</Form.Item>
))}
</>
)}
</Form.List>
<Form.Item label="商品隐藏信息" name="hideInfo">
<CheckboxGroup options={hideOptions} />
</Form.Item>
<Form.Item
label="是否周预览"
name="weekPreview"
rules={[{ required: true, message: '请选择是否周预览!' }]}
>
<RadioGroup options={boolOptions} />
</Form.Item>
</Form>
</Modal>
);
};
export default CustomerInfo;
import React from 'react';
import { Checkbox } from 'antd';
import { mealSections } from '../staticData/index';
const MealCheckbox = props => {
const onChange = e => {
props.onChange(props.field);
props.changeType(e);
};
return (
<Checkbox
onChange={onChange}
checked={props.meals[props.field]}
id={props.field}
label={mealSections[props.field]}
>
{mealSections[props.field]}
</Checkbox>
);
};
export default MealCheckbox;
import React from 'react';
import { Form, InputNumber, Row, Col } from 'antd';
import style from '../style/info.less';
import { validateRequired, isCheckPriceTwoDecimal } from '@/utils/validator';
const MealLimit = props => (
<Form.Item
label={`${props.label}限额`}
name={props.name}
rules={[
{ validator: validateRequired, message: `请输入${props.label}限额` },
{ validator: isCheckPriceTwoDecimal, message: '请输入正确的价格' },
]}
>
<InputNumber addonAfter="元" max={999.99} />
</Form.Item>
);
export default MealLimit;
import React from 'react';
import { Form, Space, TimePicker } from 'antd';
import { mealSections } from '../staticData/index';
import MealCheckbox from './MealCheckbox';
const MealSection = props => (
<Form.List name="mealTimePeriod">
{fields => (
<>
{Object.keys(mealSections).map((field, i) => (
<Space key={field} align="baseline">
<Form.Item label="" name={[fields[i].name, 'mealPeriodType']}>
<MealCheckbox changeType={props.onChange} meals={props.meals} field={field} />
</Form.Item>
<Form.Item
name={[fields[i].name, 'time']}
rules={[
props.meals[field] ? { type: 'array', required: true, message: '请选择!' } : {},
]}
>
<TimePicker.RangePicker format="HH:mm" />
</Form.Item>
</Space>
))}
</>
)}
</Form.List>
);
export default MealSection;
import React, { useState, useRef } from 'react';
import ProTable from '@ant-design/pro-table';
import { Button } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { customerColumn } from './staticData/index';
import CustomerInfo from './components/CustomerInfo';
import { apiEnterpriseList } from './service';
const BusinessCustomer = () => {
const [visible, setVisible] = useState(false);
const query = async params => {
const data = {
page: params.current,
size: params.pageSize,
data: params,
};
return apiEnterpriseList(data);
};
const onEdit = async () => {};
return (
<div>
<ProTable
search={{
collapsed: false,
collapseRender: () => null,
}}
columns={customerColumn({ onEdit })}
request={params => query({ ...params })}
rowKey={r => r.id}
expandIconColumnIndex={10}
bordered
options={false}
toolBarRender={() => [
<Button key="3" icon={<PlusOutlined />} type="primary" onClick={() => setVisible(!0)}>
添加企业客户
</Button>,
]}
scroll={{ x: '100%', y: 400 }}
/>
<CustomerInfo visible={visible} handleClose={setVisible} />
</div>
);
};
export default BusinessCustomer;
import request from '@/utils/request';
import config from '@/../config/env.config';
// import qs from 'qs';
const { kdspApi, goodsApi } = config;
/**
* 获取企业客户列表
* http://yapi.quantgroups.com/project/389/interface/api/65324
*/
export async function apiEnterpriseList(data) {
return request.post('/api/consoles/enterprise/pageList', {
data,
prefix: goodsApi,
});
}
/**
* 获取企业客户详细
* http://yapi.quantgroups.com/project/389/interface/api/65339
*/
export async function apiEnterpriseInfo(id) {
return request.get(`/api/consoles/enterprise/info?id=${id}`, {
prefix: goodsApi,
});
}
/**
* 添加企业客户
* http://yapi.quantgroups.com/project/389/interface/api/65329
*/
export async function apiNewEnterprise(data) {
return request.post('/api/consoles/enterprise/save', {
data,
prefix: goodsApi,
});
}
/**
* 编辑企业客户
* http://yapi.quantgroups.com/project/389/interface/api/65334
*/
export async function apiEditEnterprise(data) {
return request.post('/api/consoles/enterprise/update', {
data,
prefix: goodsApi,
});
}
/**
* 查询自提点列表
* http://yapi.quantgroups.com/project/389/interface/api/65494
*/
export async function apiEnterprisePickSelf(data) {
return request.post('/api/consoles/selfPickUpLocation/list', {
data,
prefix: goodsApi,
});
}
import React from 'react';
import { Button } from 'antd';
export const layout = {
labelCol: { span: 4 },
wrapperCol: { span: 18 },
};
// 餐品类型:(1外卖 2 自助餐 4到店)
export const mealType = {
1: '外卖',
2: '自助餐',
4: '到店',
};
export const infoOptions = [
{ label: '商品价格及图片', value: 1 },
{ label: '仅商品价格', value: 2 },
{ label: '仅商品图片', value: 3 },
{ label: '均不展示', value: 4 },
];
export const boolOptions = [{ label: '', value: 1 }, { label: '', value: 0 }];
export const hideOptions = [
{ label: '隐藏商品价格', value: 'hidePrice' },
{ label: '隐藏商品图片', value: 'hideImage' },
];
// export const mealSections = [
// {
// label: '早餐',
// value: '1',
// key: 'time1',
// },
// {
// label: '中餐',
// value: '2',
// key: 'time2',
// },
// {
// label: '晚餐',
// value: '4',
// key: 'time4',
// },
// ];
export const mealSections = {
1: '早餐',
2: '中餐',
4: '晚餐',
};
// 企业列表字段
export const customerColumn = options => {
const { onEdit } = options;
return [
{
title: 'ID',
dataIndex: 'enterpriseId',
hideInTable: true,
},
{
title: 'ID',
dataIndex: 'id',
width: 120,
align: 'center',
hideInSearch: true,
},
{
title: '公司名称',
dataIndex: 'name',
width: 120,
align: 'center',
},
{
title: '截单时间(分钟)',
dataIndex: 'endOrderTime',
width: 120,
align: 'center',
hideInSearch: true,
},
{
title: '餐品类型',
dataIndex: 'mealType',
width: 120,
align: 'center',
hideInSearch: true,
render(types) {
const arr = types.map(meal => mealType[meal]);
return arr.join('/');
},
},
{
title: '创建人',
dataIndex: 'createdBy',
width: 120,
align: 'center',
hideInSearch: true,
},
{
title: '创建时间',
dataIndex: 'createdAt',
width: 120,
align: 'center',
hideInSearch: true,
},
{
title: '操作',
hideInSearch: true,
dataIndex: 'action',
width: 200,
align: 'center',
fixed: 'right',
render: (val, r) => (
<Button key="edit" onClick={() => onEdit(r, 'edit')}>
编辑
</Button>
),
},
];
};
.tip {
height: 32px;
padding-left: 5px;
line-height: 32px;
}
import React, { useEffect } from 'react';
import { Form, InputNumber, Modal, notification } from 'antd';
import { layout } from '../staticData/goods';
import { isCheckPriceTwoDecimal } from '@/utils/validator';
import { apiMealInfoUpdate } from '../service';
const SaleDateModal = props => {
const [form] = Form.useForm();
// 关闭弹窗
const handleCancel = () => {
props.handleClose(false);
};
// 提交
const handleConfirm = async () => {
const res = await form.validateFields();
console.log('res :>> ', res);
const params = {
id: props.id,
enterprisePrice: res.price,
};
await apiMealInfoUpdate(params);
notification.success({ message: '保存成功' });
handleCancel();
props.handleRefresh();
};
useEffect(() => {
if (props.visible) {
form.setFieldsValue({ price: null });
}
}, [props.visible]);
return (
<Modal
title="修改企业商品价格"
open={props.visible}
destroyOnClose
maskClosable={false}
width="300px"
okText="保存"
onOk={handleConfirm}
onCancel={handleCancel}
>
<Form name="basicInfo" {...layout} form={form}>
<Form.Item
label="企业商品价格"
name="price"
rules={[
{ required: true, message: '请输入企业商品价格!' },
{ validator: isCheckPriceTwoDecimal, message: '请输入正确的价格' },
]}
>
<InputNumber addonAfter="元" max={99999.99} />
</Form.Item>
</Form>
</Modal>
);
};
export default SaleDateModal;
import React, { useEffect } from 'react';
import { Form, InputNumber, Modal, notification } from 'antd';
import { layout } from '../staticData/goods';
import { apiMealInfoUpdate } from '../service';
const SaleDateModal = props => {
const [form] = Form.useForm();
// 关闭弹窗
const handleCancel = () => {
props.handleClose(false);
};
// 提交
const handleConfirm = async () => {
const res = await form.validateFields();
console.log('res :>> ', res);
const params = {
id: props.id,
sort: res.sort,
};
await apiMealInfoUpdate(params);
notification.success({ message: '保存成功' });
handleCancel();
props.handleRefresh();
};
useEffect(() => {
if (props.visible) {
form.setFieldsValue({ sort: null });
}
}, [props.visible]);
return (
<Modal
title="修改商品排序"
open={props.visible}
destroyOnClose
maskClosable={false}
width="300px"
okText="保存"
onOk={handleConfirm}
onCancel={handleCancel}
>
<Form name="basicInfo" initialValues={{ sort: 1000 }} {...layout} form={form}>
<Form.Item label="排序" name="sort" rules={[{ required: true, message: '请输入排序!' }]}>
<InputNumber max={999999} min={1} />
</Form.Item>
</Form>
</Modal>
);
};
export default SaleDateModal;
import React, { useState, useEffect } from 'react';
import { Checkbox, Space, message, Modal, notification } from 'antd';
import { weekOptions } from '../staticData/goods';
import { apiMealInfoUpdate } from '../service';
const SaleDateModal = props => {
const [value, setValue] = useState([]);
// 关闭弹窗
const handleCancel = () => {
props.handleClose(false);
};
const onChangeWeek = e => {
setValue(e);
};
// 提交
const handleConfirm = async () => {
if (!value || value.length < 1) {
message.error('请选择可售日期');
return;
}
if (props.id) {
const params = {
id: props.id,
saleDateList: value,
};
await apiMealInfoUpdate(params);
notification.success({ message: '保存成功' });
}
handleCancel();
props.handleRefresh(value);
};
useEffect(() => {
if (props.visible) {
setValue([]);
}
}, [props.visible]);
return (
<Modal
title={props.title || '设置可售日期'}
open={props.visible}
destroyOnClose
maskClosable={false}
width="200px"
okText="保存"
onOk={handleConfirm}
onCancel={handleCancel}
>
<Checkbox.Group onChange={onChangeWeek} value={value}>
<Space direction="vertical">
{Object.keys(weekOptions).map(key => (
<Checkbox value={key}>{weekOptions[key]}</Checkbox>
))}
</Space>
</Checkbox.Group>
</Modal>
);
};
export default SaleDateModal;
import React, { useState, useEffect } from 'react';
import { Form, Checkbox, Space, Modal, notification, message } from 'antd';
import { mealColumn } from '../staticData/goods';
import { apiMealInfoUpdate } from '../service';
const SaleDateModal = props => {
const [form] = Form.useForm();
const [value, setValue] = useState([]);
// 关闭弹窗
const handleCancel = () => {
props.handleClose(false);
};
const onChangeMeal = e => {
setValue(e);
};
// 提交
const handleConfirm = async () => {
if (!value || value.length < 1) {
message.error('请选择餐段');
return;
}
if (props.id) {
const params = {
id: props.id,
tabIds: value,
};
await apiMealInfoUpdate(params);
notification.success({ message: '保存成功' });
}
handleCancel();
props.handleRefresh(value);
};
useEffect(() => {
if (props.visible) {
setValue([]);
}
}, [props.visible]);
return (
<Modal
title={props.title || '修改可售餐段'}
open={props.visible}
destroyOnClose
maskClosable={false}
width="200px"
okText="保存"
onOk={handleConfirm}
onCancel={handleCancel}
>
<Checkbox.Group onChange={onChangeMeal} value={value}>
<Space direction="vertical">
{Object.keys(mealColumn).map(key => (
<Checkbox value={key}>{mealColumn[key]}</Checkbox>
))}
</Space>
</Checkbox.Group>
</Modal>
);
};
export default SaleDateModal;
import React, { useState, useEffect } from 'react';
import { Select, Modal, Table, Input, Button, Pagination, notification } from 'antd';
import { SearchOutlined } from '@ant-design/icons';
import { apiSelGoodsList, apiSelVirtualGoodsList } from '../service';
import { getShopListByPickSelf } from '../service/bll';
import { SelectGoodsColumn, productType } from '../staticData/goods';
import style from '../style/index.less';
import { jsonToArray, deepClone } from '@/utils/utils';
const { Option } = Select;
const SaleDateModal = props => {
const [searchType, setSearchType] = useState('1');
const [searchKeyword, setSearchKeyword] = useState('');
const [goodsType, setGoodsType] = useState('1');
const [shopId, setShopId] = useState('');
const [searchName, setSearchName] = useState('');
const [loading, setLoading] = useState(false);
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
const [dataSource, setDataSource] = useState([]);
const [shopList, setShopList] = useState(jsonToArray(productType));
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const [selectedRows, setSelectedRows] = useState([]);
const searchList = async params => {
console.log('params :>> ', params);
console.log('searchType :>> ', searchType);
console.log('shopId :>> ', shopId);
const { enterpriseId } = props;
const searchObj = {};
if (searchKeyword && searchType && !params.search) {
if (searchType === '1') {
searchObj.name = searchKeyword;
} else {
searchObj.skuId = searchKeyword;
}
}
const data = {
page: params.current || page,
size: params.pageSize || pageSize,
data: Object.assign(
{
shopId,
productType,
enterpriseId,
},
searchObj,
params,
),
};
setLoading(true);
let api = apiSelGoodsList;
if (props.type === 'virtual') {
api = apiSelVirtualGoodsList;
}
const res = await api(data);
setDataSource(res);
setLoading(false);
};
// 点击搜索
const onSearch = () => {
setSearchKeyword(searchName);
searchList({ [searchType === '1' ? 'name' : 'skuId']: searchName });
};
// 切换店铺
const onChangeShop = v => {
setShopId(v);
searchList({
shopId: v,
});
setSelectedRowKeys([]);
};
// 关闭弹窗
const handleCancel = () => {
props.handleClose(false);
};
// 提交
const handleConfirm = async () => {
if (!selectedRows || selectedRows.length < 1) {
notification.error({ message: '请选择要添加的商品' });
return;
}
props.onSelectChange(deepClone(selectedRows));
handleCancel();
};
// 商品单选
const onSelectChange = (record, selected) => {
const { skuId } = record;
if (selected) {
const keys = [...selectedRowKeys, skuId];
const arr = [...selectedRows, record];
setSelectedRowKeys(keys);
setSelectedRows(arr);
} else {
const rows = [];
const keys = [];
selectedRows.forEach(item => {
if (item.skuId !== skuId) {
rows.push(item);
keys.push(item.skuId);
}
});
setSelectedRowKeys(keys);
setSelectedRows(rows);
}
};
// 商品全选
const onSelectAllChange = (selected, rows) => {
const keys = [...selectedRowKeys];
const arr = [...selectedRows];
if (selected) {
rows.forEach(item => {
if (!keys.includes(item.skuId)) {
keys.push(item.skuId);
arr.push(item);
}
});
setSelectedRowKeys(keys);
setSelectedRows(arr);
} else {
dataSource.forEach(item => {
const index = keys.findIndex(k => k === item.skuId);
if (index > -1) {
keys.splice(index, 1);
arr.splice(index, 1);
}
});
setSelectedRowKeys(keys);
setSelectedRows(arr);
}
};
// 切换页码
const onPageChange = (current, size) => {
setPage(current);
setPageSize(size);
searchList({
current,
pageSize: size,
});
};
// 获取店铺列表
const getShopList = async () => {
const res = await getShopListByPickSelf({
enterpriseId: props.enterpriseId,
pickSelfIdList: props.pickSelfIdList,
});
setShopList(res);
};
const rowSelection = {
selectedRowKeys,
onSelect: onSelectChange,
onSelectAll: onSelectAllChange,
};
const selectBefore = (
<Select defaultValue="1" onChange={setSearchType}>
<Option value="1">名称</Option>
<Option value="2">SKU</Option>
</Select>
);
const selectAfter = <SearchOutlined onClick={onSearch} />;
const footers = () => [
<div className={style.footers}>
<Pagination defaultCurrent={6} total={500} showQuickJumper onChange={onPageChange} />
<div className={style['footers-btn']}>
<div className={style['footers-desc']}>
已选商品(<span className={style['footers-num']}>{selectedRows.length}</span>)
</div>
<Button key="back" onClick={handleCancel}>
取消
</Button>
<Button key="submit" type="primary" loading={loading} onClick={handleConfirm}>
确定
</Button>
</div>
</div>,
];
useEffect(() => {
getShopList();
setGoodsType(props.productType);
searchList({});
}, []);
return (
<Modal
title="选择商品"
open={props.visible}
destroyOnClose
maskClosable={false}
width="1000px"
onOk={handleConfirm}
onCancel={handleCancel}
footer={footers()}
>
<div className={style['select-goods-box']}>
<Select
placeholder="请选择店铺"
options={shopList}
value={shopId}
onChange={onChangeShop}
className={style['select-goods-box--select']}
/>
<Select
placeholder="请选择商品类型"
disabled
value={goodsType}
options={jsonToArray(productType)}
className={style['select-goods-box--select']}
/>
<Input
addonBefore={selectBefore}
addonAfter={selectAfter}
onChange={e => setSearchName(e.target.value)}
className={style['select-goods-box--txt']}
/>
</div>
<Table
rowSelection={rowSelection}
rowKey="skuId"
columns={SelectGoodsColumn}
dataSource={dataSource}
/>
</Modal>
);
};
export default SaleDateModal;
import debounce from 'lodash/debounce';
import { apiEnterpriseList, apiShopList, apiShopListByPickSelfID } from './index';
// 获取企业列表
export const getEnterpriseList = async (name = '') => {
const res = await apiEnterpriseList({ name });
return {
id: res[res.length - 1].id,
list: res.map(item => ({
[item.id]: { text: item.name },
})),
};
};
// 获取店铺列表
export const getShopList = debounce(async e => {
const { name } = e;
const res = await apiShopList({ name });
return {
id: res[res.length - 1].id,
list: res.map(item => ({
[item.id]: { text: item.name },
})),
};
}, 300);
// 获取店铺列表通过自提点ID
export const getShopListByPickSelf = async e => {
const { name } = e;
const res = await apiShopListByPickSelfID({ name });
return {
id: res[res.length - 1].id,
list: res.map(item => ({
[item.id]: { text: item.name },
})),
};
};
import request from '@/utils/request';
import config from '@/../config/env.config';
const { kdspApi, goodsApi, apiPrefix } = config;
/**
* 获取企业外卖商品列表
* http://yapi.quantgroups.com/project/389/interface/api/64794
*/
export async function apiTakeawayList(param) {
return request.post(`${apiPrefix}/product/enterprise/main/pageList`, {
data: param,
prefix: goodsApi,
});
}
/**
* 获取企业虚拟商品列表
* http://yapi.quantgroups.com/project/389/interface/api/64794
*/
export async function apiVirtualList(param) {
return request.post('/api/consoles/product/enterprise/virtual/pageList', {
data: param,
prefix: goodsApi,
});
}
/**
* 企业客户列表
* http://yapi.quantgroups.com/project/389/interface/api/65324
*/
export async function apiEnterpriseList(param) {
return request.post('/api/consoles/enterprise/pageList', {
data: param,
prefix: goodsApi,
});
}
/**
* 模糊查询店铺列表
* http://yapi.quantgroups.com/project/389/interface/api/65289
*/
export async function apiShopList(param) {
return request.post('/api/consoles/shops/getListByName', {
data: param,
prefix: goodsApi,
});
}
/**
* 企业团餐-查询餐段配置
* http://yapi.quantgroups.com/project/389/interface/api/65444
*/
export async function apiMealTimePeriod(param) {
return request.post('/api/consoles/product/enterprise/getMealTimePeriod', {
data: param,
prefix: goodsApi,
});
}
/**
* 企业团餐->信息修改
* http://yapi.quantgroups.com/project/389/interface/api/65099
*/
export async function apiMealInfoUpdate(param) {
return request.post('/api/consoles/product/enterprise/main/update', {
data: param,
prefix: goodsApi,
});
}
/**
* 企业团餐->删除
* http://yapi.quantgroups.com/project/389/interface/api/65109
*/
export async function apiMealInfoDel(param) {
return request.post('/api/consoles/product/enterprise/main/deleteById', {
data: param,
prefix: goodsApi,
});
}
/**
* 企业团餐->查询自提点列表
* http://yapi.quantgroups.com/project/389/interface/api/65494
*/
export async function apiPickSelfList() {
return request.get('/api/consoles/selfPickUpLocation/list', {
prefix: goodsApi,
});
}
/**
* 企业团餐->根据企业ID查询已选择自提点
* http://yapi.quantgroups.com/project/389/interface/api/65449
*/
export async function apiSelPickSelfList(param) {
return request.post('/api/consoles/product/enterprise/queryByEnterpriseId', {
data: param,
prefix: goodsApi,
});
}
/**
* 企业团餐->查询外卖商品 - 选择商品弹窗
* http://yapi.quantgroups.com/project/389/interface/api/65479
*/
export async function apiSelGoodsList(param) {
return request.post('/api/consoles/product/enterprise/sku/page', {
data: param,
prefix: goodsApi,
});
}
/**
* 企业团餐->查询商品 - 选择虚拟商品弹窗
* http://yapi.quantgroups.com/project/389/interface/api/65479
*/
export async function apiSelVirtualGoodsList(param) {
return request.post('/api/consoles/product/enterprise/virtual/sku/page', {
data: param,
prefix: goodsApi,
});
}
/**
* 企业团餐->添加外卖商品保存
* http://yapi.quantgroups.com/project/389/interface/api/65094
*/
export async function apiSaveGoodsList(param) {
return request.post('/api/consoles/product/enterprise/add', {
data: param,
prefix: goodsApi,
});
}
/**
* 企业团餐->添加虚拟商品保存
* http://yapi.quantgroups.com/project/389/interface/api/65484
*/
export async function apiSaveVirtualGoodsList(param) {
return request.post('/api/consoles/products/enterprise/virtual/add', {
data: param,
prefix: goodsApi,
});
}
/**
* 企业团餐->虚拟品->根据企业ID查询店铺列表
* http://yapi.quantgroups.com/project/389/interface/api/65504
*/
export async function apiShopListByEnterpriseID(param) {
return request.post('/api/consoles/product/enterprise/virtual/shops', {
data: param,
prefix: goodsApi,
});
}
/**
* 企业团餐->根据企业ID+自提点列表查询店铺列表
* http://yapi.quantgroups.com/project/389/interface/api/65539
*/
export async function apiShopListByPickSelfID(param) {
return request.post('/api/consoles/product/enterprise/queryByEnterpriseIdAndPickSelfId', {
data: param,
prefix: goodsApi,
});
}
import React from 'react';
import { Button, Space, Switch } from 'antd';
import { FormOutlined } from '@ant-design/icons';
import { jsonToArray } from '@/utils/utils';
import { getShopList } from '../service/bll';
export const layout = {
labelCol: { span: 4 },
wrapperCol: { span: 18 },
};
// 0-推荐 1-早餐 2-午餐 3-下午茶 4-晚餐
export const mealColumn = {
// 0: '推荐',
1: '早餐',
2: '午餐',
// 3: '晚餐',
4: '晚餐',
};
// 商品类型
export const productType = {
1: '实物商品',
2: '虚拟商品',
// 3: '电子卡券'(废弃)
4: '服务类商品',
5: '外卖商品',
};
export const weekOptions = {
1: '周一',
2: '周二',
3: '周三',
4: '周四',
5: '周五',
6: '周六',
7: '周日',
};
export const takeawayGoodsColumn = options => {
const {
onDel,
companyEnum,
shopEnum,
onChangeFlag,
setVisibleSaleDate,
enterprises,
setRecordID,
setVisiblePrice,
setVisibleSaleSection,
setVisibleSort,
} = options;
return [
{
title: '企业名称',
dataIndex: 'enterpriseId',
hideInTable: true,
fieldProps: {
showSearch: true,
filterOption: (v, option) => (option?.label ?? '').toLowerCase().includes(v.toLowerCase()),
},
valueEnum: enterprises, // companyEnum,
},
{
title: '微店名称',
dataIndex: 'shopId',
hideInTable: true,
fieldProps: {
showSearch: true,
},
request: getShopList,
// valueEnum: {}, // shopEnum,
},
{
title: 'SKU编码',
dataIndex: 'skuId',
width: 120,
align: 'center',
},
{
title: '商品名称',
dataIndex: 'skuName',
width: 120,
align: 'center',
},
{
title: '商品图片',
dataIndex: 'primaryImage',
width: 120,
align: 'center',
hideInSearch: true,
valueType: 'image',
},
{
title: '可售日期',
dataIndex: 'saleTimeType',
width: 120,
align: 'center',
hideInSearch: true,
render: (_, record) => (
<Space>
<span>{_}</span>
<span
onClick={() => {
setRecordID(record.id);
setVisibleSaleDate(true);
}}
>
<FormOutlined />
</span>
</Space>
),
},
{
title: '可售餐段',
dataIndex: 'saleDate',
width: 120,
align: 'center',
hideInSearch: true,
render: (_, record) => (
<Space>
<span>{_}</span>
<span
onClick={() => {
setRecordID(record.id);
setVisibleSaleSection(true);
}}
>
<FormOutlined />
</span>
</Space>
),
},
{
title: '企业价格',
dataIndex: 'activityPrice',
width: 120,
align: 'center',
hideInSearch: true,
render: (_, record) => (
<Space>
<span>{_}</span>
<span
onClick={() => {
setRecordID(record.id);
setVisiblePrice(true);
}}
>
<FormOutlined />
</span>
</Space>
),
},
{
title: '商品销售价',
dataIndex: 'price',
width: 120,
align: 'center',
hideInSearch: true,
},
{
title: '状态',
dataIndex: 'status',
width: 120,
align: 'center',
hideInSearch: true,
valueEnum: {
1: '生效中',
2: '已下架',
3: '已售罄',
},
},
{
title: '排序',
dataIndex: 'sort',
width: 120,
align: 'center',
hideInSearch: true,
render: (_, record) => (
<Space>
<span>{_}</span>
<span
onClick={() => {
setRecordID(record.id);
setVisibleSort(true);
}}
>
<FormOutlined />
</span>
</Space>
),
},
{
title: '列出商品',
dataIndex: 'showFlag',
width: 120,
align: 'center',
hideInSearch: true,
render: (_, record) => (
<Space>
<span>
<Switch checked={+_ === 1} onChange={e => onChangeFlag(record.id, e)} />
</span>
</Space>
),
},
{
title: '餐品类型',
dataIndex: 'mealType',
width: 120,
align: 'center',
hideInSearch: true,
},
{
title: '添加时间',
dataIndex: 'createDate',
width: 120,
valueType: 'dateRange',
align: 'center',
},
{
title: '当日餐段',
dataIndex: 'tabId',
width: 120,
align: 'center',
valueEnum: mealColumn,
hideInTable: true,
},
{
title: '操作',
hideInSearch: true,
dataIndex: 'action',
width: '100px',
align: 'center',
fixed: 'right',
render: (val, r) => (
<Button key="del" onClick={() => onDel(r.id)}>
删除
</Button>
),
},
];
};
export const GoodsInfoColumn = options => {
const { onDel, setVisibleSaleDate, setVisibleSaleSection, setEditID } = options;
return [
{
title: '微店名称',
dataIndex: 'shopId',
},
{
title: '商品名称',
dataIndex: 'skuName',
align: 'center',
},
{
title: '商品售价',
dataIndex: 'price',
width: 120,
align: 'center',
},
{
title: '企业价格',
dataIndex: 'activityPrice',
width: 120,
align: 'center',
},
{
title: '库存',
dataIndex: 'status',
width: 120,
align: 'center',
},
{
title: '可售日期',
dataIndex: 'saleDate',
align: 'center',
hideInSearch: true,
render: (_, record) => (
<Space>
{_ &&
(_.length === 7 ? '不限制' : <span>{_.map(item => weekOptions[item]).join('/')}</span>)}
<span
onClick={() => {
setEditID(record.skuId);
setVisibleSaleDate(true);
}}
>
<FormOutlined />
</span>
</Space>
),
},
{
title: '可售餐段',
dataIndex: 'mealType',
align: 'center',
hideInSearch: true,
render: (_, record) => (
<Space>
<span>{_ && _.map(item => mealColumn[item]).join('/')}</span>
<span
onClick={() => {
setEditID(record.skuId);
setVisibleSaleSection(true);
}}
>
<FormOutlined />
</span>
</Space>
),
},
{
title: '餐品类型',
dataIndex: 'mealType',
width: 120,
align: 'center',
hideInSearch: true,
},
{
title: '操作',
hideInSearch: true,
dataIndex: 'action',
width: '100px',
align: 'center',
fixed: 'right',
render: (val, r) => (
<Button key="del" onClick={() => onDel(r, 'del')}>
删除
</Button>
),
},
];
};
export const SelectGoodsColumn = [
{
title: '商品ID',
width: 120,
dataIndex: 'skuId',
},
{
title: '商品名称',
dataIndex: 'skuName',
width: 120,
align: 'center',
},
{
title: '商品编号',
dataIndex: 'skuNo',
width: 120,
align: 'center',
},
{
title: '销售价',
dataIndex: 'price',
width: 120,
align: 'center',
},
{
title: '剩余库存',
dataIndex: 'status',
width: 120,
align: 'center',
},
{
title: '已参与活动',
dataIndex: 'mealType',
align: 'center',
hideInSearch: true,
},
];
.search {
padding: 0;
:global {
.ant-form-item {
display: block !important;
}
}
}
.info-box {
min-height: 100%;
padding: 20px 40px;
background-color: #fff;
&--line {
min-height: 32px;
margin-bottom: 15px;
line-height: 32px;
}
&--label {
text-align: right;
}
&--select {
min-width: 200px;
}
&--btns {
margin-top: 20px;
&__confirm {
margin-right: 15px;
}
}
&--batch-btn {
text-align: right;
}
}
.select-goods-box {
display: flex;
padding: 5px 0;
.select-goods-box--select {
width: 200px;
}
.select-goods-box--txt {
width: 260px;
}
}
.footers {
display: flex;
align-items: center;
justify-content: space-between;
&-btn {
display: flex;
align-items: center;
justify-content: flex-end;
text-align: right;
}
&-desc {
margin-right: 10px;
}
&-num {
color: #1890ff;
}
}
import React, { useState, useEffect, useRef } from 'react';
import { useHistory } from 'react-router-dom';
import { ProTable } from '@ant-design/pro-components';
import { Button, notification } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { takeawayGoodsColumn } from './staticData/goods';
import utilStyle from '@/utils/utils.less';
import { apiTakeawayList, apiSelPickSelfList, apiMealInfoDel, apiMealInfoUpdate } from './service';
import { getEnterpriseList } from './service/bll';
import SaleDateModal from './components/SaleDateModal';
import SaleSectionModal from './components/SaleSectionModal';
import GoodPriceModal from './components/GoodPriceModal';
import GoodSortModal from './components/GoodSortModal';
import { getToUrlQuery } from '@/utils/utils';
// 企业外卖商品
const TakeawayGoods = () => {
const history = useHistory();
const refTable = useRef();
const [pageLoading, setPageLoading] = useState(true); // 可售日期弹窗
const [visibleSaleDate, setVisibleSaleDate] = useState(false); // 可售日期弹窗
const [visibleSaleSection, setVisibleSaleSection] = useState(false); // 可售餐段弹窗
const [visiblePrice, setVisiblePrice] = useState(false); // 修改企业商品价格弹窗
const [visibleSort, setVisibleSort] = useState(false); // 商品排序弹窗
const [enterprises, setEnterprises] = useState([]); // 企业列表
const [activeKey, setActiveKey] = useState('');
const [enterpriseId, setEnterpriseId] = useState('');
const [pickSelfList, setPickSelfList] = useState([]); // 取餐点列表
const [recordID, setRecordID] = useState(''); // 编辑的记录ID
// 搜索商品列表
const searchList = async params => {
if (params.enterpriseId && params.enterpriseId !== enterpriseId) {
setEnterpriseId(params.enterpriseId);
}
const data = {
page: params.current,
size: params.pageSize,
data: params,
};
return apiTakeawayList(data);
};
const onDel = async id => {
await apiMealInfoDel({
id,
});
notification.success({
message: '删除成功',
});
};
const onAdd = async () => {
const query = getToUrlQuery();
history.push({
pathname: '/takeawayGoodsInfo',
query,
});
};
const onChangeFlag = async (id, checked) => {
const params = {
id,
showFlag: checked ? 1 : 0,
};
await apiMealInfoUpdate(params);
notification.success({ message: '保存成功' });
};
const options = {
setVisibleSaleDate,
setVisibleSaleSection,
setVisiblePrice,
setVisibleSort,
onDel,
setRecordID,
enterprises,
onChangeFlag,
};
// 根据企业ID获取取餐点
const getPickSelf = async () => {
const res = await apiSelPickSelfList({});
setPickSelfList(
res.map(item => ({
key: item.pickSelfId,
label: <span>{item.pickSelfName}</span>,
})),
);
setActiveKey(res[0].pickSelfId);
};
// 获取企业列表
const getList = async name => {
const obj = await getEnterpriseList(name);
setEnterprises(obj.list);
setEnterpriseId(obj.id);
getPickSelf(obj.id);
setPageLoading(true);
};
useEffect(() => {
getList('');
// setTimeout(() => {
// // refTable.current.reload();
// }, 1000);
}, []);
return (
<div>
{pageLoading && (
<ProTable
search={{
span: 6,
className: utilStyle.formSearch,
collapsed: false,
collapseRender: () => null,
}}
actionRef={refTable}
tableClassName={utilStyle.formTable}
columns={takeawayGoodsColumn(options)}
request={params => searchList({ ...params })}
rowKey={r => r.id}
expandIconColumnIndex={10}
bordered
options={false}
form={{ initialValues: { enterpriseId } }}
toolbar={{
menu: {
type: 'tab',
activeKey,
items: pickSelfList,
onChange: key => {
setActiveKey(key);
},
},
actions: [
<Button key="1" icon={<PlusOutlined />} type="primary" onClick={onAdd}>
添加外卖商品
</Button>,
],
}}
scroll={{ x: '100%', y: 400 }}
/>
)}
{/* 可售日期弹窗 */}
{visibleSaleDate && (
<SaleDateModal
visible={visibleSaleDate}
id={recordID}
handleRefresh={() => searchList({})}
handleClose={() => setVisibleSaleDate(false)}
/>
)}
{/* 可售餐段弹窗 */}
{visibleSaleSection && (
<SaleSectionModal
visible={visibleSaleSection}
id={recordID}
handleRefresh={() => searchList({})}
handleClose={() => setVisibleSaleSection(false)}
/>
)}
{/* 修改企业商品价格弹窗 */}
{visiblePrice && (
<GoodPriceModal
visible={visiblePrice}
id={recordID}
handleRefresh={() => searchList({})}
handleClose={() => setVisiblePrice(false)}
/>
)}
{/* 商品排序弹窗 */}
{visibleSort && (
<GoodSortModal
visible={visibleSort}
id={recordID}
handleRefresh={() => searchList({})}
handleClose={() => setVisibleSort(false)}
/>
)}
</div>
);
};
export default TakeawayGoods;
import React, { useRef, useState, useEffect } from 'react';
import { Button, notification, Spin, Select, Row, Col, Table, message } from 'antd';
import { useHistory } from 'react-router-dom';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { GoodsInfoColumn } from './staticData/goods';
import SaleDateModal from './components/SaleDateModal';
import SaleSectionModal from './components/SaleSectionModal';
import SelectGoodsModal from './components/SelectGoodsModal';
import { apiSelPickSelfList, apiPickSelfList, apiSaveGoodsList } from './service';
import style from './style/index.less';
const TakeawayGoodsInfo = props => {
const { id } = props.location.query;
const history = useHistory();
const [loading, setLoading] = useState(false);
const [visibleSaleDate, setVisibleSaleDate] = useState(false); // 可售日期弹窗
const [visibleSaleSection, setVisibleSaleSection] = useState(false); // 可售餐段弹窗
const [visibleSelectGoods, setVisibleSelectGoods] = useState(false); // 选择商品弹窗
const [dataSource, setDataSource] = useState([]);
const [pickSelfList, setPickSelfList] = useState([]); // 取餐点列表
const [slePickSelf, setSelPickSelf] = useState([]); // 选中的取餐点列表
const [editID, setEditID] = useState(''); // 编辑ID
// 取消
const onCancel = () => {
history.goBack();
};
// 提交
const onSubmit = async () => {
if (!dataSource || dataSource.length < 1) {
message.error('请添加商品');
return;
}
const skuInfoList = dataSource.map(item => ({
skuId: item.skuId,
enterprisePrice: item.enterprisePrice,
mealTypeList: item.mealType,
saleDateList: item.saleDate,
}));
const params = {
shopId: id,
enterpriseId: id,
pickSelfIdList: slePickSelf,
skuInfoList,
};
await apiSaveGoodsList(params);
notification.success({ message: '添加成功' });
onCancel();
};
// 删除
const onDel = i => {
const arr = dataSource.splice(i, 1);
setDataSource(arr);
};
// 根据企业ID获取取餐点
const getPickSelf = async () => {
const res = await apiPickSelfList();
setPickSelfList(
res.map(item => ({
key: item.pickSelfId,
label: <span>{item.pickSelfName}</span>,
})),
);
};
// 根据企业ID获取已选取餐点
const getSelPickSelf = async () => {
const res = await apiSelPickSelfList({
enterpriseId: id,
});
setSelPickSelf(
res.map(item => ({
key: item.pickSelfId,
label: <span>{item.pickSelfName}</span>,
})),
);
};
// 刷新列表数据
const refreshList = (type, v) => {
const arr = dataSource.map(item => {
if (editID) {
if (item.skuId === editID) {
item[type] = v;
}
} else {
item[type] = v;
}
return item;
});
setDataSource(arr);
};
// const initData = async () => {
// setLoading(true);
// };
useEffect(() => {
getPickSelf();
getSelPickSelf();
}, []);
const options = {
setVisibleSaleDate,
setVisibleSaleSection,
setEditID,
onDel,
};
return (
<PageHeaderWrapper title="添加企业严选商品">
<div className={style['info-box']}>
<Spin spinning={loading}>
<Row className={style['info-box--line']}>
<Col span={3} className={style['info-box--label']}>
企业名称:
</Col>
<Col span={20}>企业名称111</Col>
</Row>
<Row className={style['info-box--line']}>
<Col span={3} className={style['info-box--label']}>
选择取餐点:
</Col>
<Col span={20}>
<Select
mode="multiple"
showSearch
options={pickSelfList}
className={style['info-box--select']}
placeholder="清选择"
onChange={setSelPickSelf}
filterOption={(input, option) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())
}
/>
</Col>
</Row>
<Row className={style['info-box--line']}>
<Col span={3} className={style['info-box--label']}>
添加商品:
</Col>
<Col span={20}>
<Button type="primary" onClick={() => setVisibleSelectGoods(true)}>
选择商品
</Button>
</Col>
</Row>
<Row className={style['info-box--line']}>
<Col span={24}>
<div className={style['info-box--batch-btn']}>
<Button
onClick={() => {
setEditID('');
setVisibleSaleDate(true);
}}
>
批量配置日期
</Button>
<Button
onClick={() => {
setEditID('');
setVisibleSaleSection(true);
}}
>
批量配置餐段
</Button>
</div>
<Table columns={GoodsInfoColumn(options)} dataSource={dataSource} />
</Col>
</Row>
<Row className={style['info-box--btns']}>
<Col span={4} />
<Col span={20}>
<Button
type="primary"
onClick={onSubmit}
className={style['info-box--btns__confirm']}
>
确定
</Button>
<Button onClick={onCancel}>取消</Button>
</Col>
</Row>
</Spin>
{/* 可售日期弹窗 */}
{visibleSaleDate && (
<SaleDateModal
visible={visibleSaleDate}
handleRefresh={v => refreshList('saleDate', v)}
handleClose={() => setVisibleSaleDate(false)}
/>
)}
{/* 可售餐段弹窗 */}
{visibleSaleSection && (
<SaleSectionModal
visible={visibleSaleSection}
handleRefresh={v => refreshList('mealType', v)}
handleClose={() => setVisibleSaleSection(false)}
/>
)}
{/* 选择商品弹窗 */}
{visibleSelectGoods && (
<SelectGoodsModal
visible={visibleSelectGoods}
onSelectChange={setDataSource}
handleClose={() => setVisibleSelectGoods(false)}
/>
)}
</div>
</PageHeaderWrapper>
);
};
export default TakeawayGoodsInfo;
import React, { useState, useEffect, useRef } from 'react';
import { useHistory } from 'react-router-dom';
import { ProTable } from '@ant-design/pro-components';
import { Button, notification } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { takeawayGoodsColumn } from './staticData/goods';
import utilStyle from '@/utils/utils.less';
import { apiVirtualList, apiSelPickSelfList, apiMealInfoDel, apiMealInfoUpdate } from './service';
import { getEnterpriseList } from './service/bll';
import SaleDateModal from './components/SaleDateModal';
import SaleSectionModal from './components/SaleSectionModal';
import GoodPriceModal from './components/GoodPriceModal';
import GoodSortModal from './components/GoodSortModal';
import { getToUrlQuery } from '@/utils/utils';
// 企业虚拟商品
const VirtualGoods = () => {
const history = useHistory();
const refTable = useRef();
const [pageLoading, setPageLoading] = useState(true); // 可售日期弹窗
const [visibleSaleDate, setVisibleSaleDate] = useState(false); // 可售日期弹窗
const [visibleSaleSection, setVisibleSaleSection] = useState(false); // 可售餐段弹窗
const [visiblePrice, setVisiblePrice] = useState(false); // 修改企业商品价格弹窗
const [visibleSort, setVisibleSort] = useState(false); // 商品排序弹窗
const [enterprises, setEnterprises] = useState([]); // 企业列表
const [activeKey, setActiveKey] = useState('');
const [enterpriseId, setEnterpriseId] = useState('');
const [pickSelfList, setPickSelfList] = useState([]); // 取餐点列表
const [recordID, setRecordID] = useState(''); // 编辑的记录ID
// 搜索商品列表
const searchList = async params => {
if (params.enterpriseId && params.enterpriseId !== enterpriseId) {
setEnterpriseId(params.enterpriseId);
}
// const data = {
// page: params.current,
// size: params.pageSize,
// data: params,
// };
// return apiVirtualList(data);
};
const onDel = async id => {
await apiMealInfoDel({
id,
});
notification.success({
message: '删除成功',
});
};
const onAdd = async () => {
const query = getToUrlQuery();
history.push({
pathname: '/takeawayGoodsInfo',
query,
});
};
const onChangeFlag = async (id, checked) => {
const params = {
id,
showFlag: checked ? 1 : 0,
};
await apiMealInfoUpdate(params);
notification.success({ message: '保存成功' });
};
const options = {
setVisibleSaleDate,
setVisibleSaleSection,
setVisiblePrice,
setVisibleSort,
onDel,
setRecordID,
enterprises,
onChangeFlag,
};
// 根据企业ID获取取餐点
const getPickSelf = async () => {
const res = await apiSelPickSelfList({});
setPickSelfList(
res.map(item => ({
key: item.pickSelfId,
label: <span>{item.pickSelfName}</span>,
})),
);
setActiveKey(res[0].pickSelfId);
};
// 获取企业列表
const getList = async name => {
const obj = await getEnterpriseList(name);
setEnterprises(obj.list);
setEnterpriseId(obj.id);
getPickSelf(obj.id);
setPageLoading(true);
};
useEffect(() => {
getList('');
// setTimeout(() => {
// // refTable.current.reload();
// }, 1000);
}, []);
return (
<div>
{pageLoading && (
<ProTable
search={{
span: 6,
className: utilStyle.formSearch,
collapsed: false,
collapseRender: () => null,
}}
actionRef={refTable}
tableClassName={utilStyle.formTable}
columns={takeawayGoodsColumn(options)}
request={params => searchList({ ...params })}
rowKey={r => r.id}
expandIconColumnIndex={10}
bordered
options={false}
form={{ initialValues: { enterpriseId } }}
toolbar={{
menu: {
type: 'tab',
activeKey,
items: pickSelfList,
onChange: key => {
setActiveKey(key);
},
},
actions: [
<Button key="1" icon={<PlusOutlined />} type="primary" onClick={onAdd}>
添加外卖商品
</Button>,
],
}}
scroll={{ x: '100%', y: 400 }}
/>
)}
{/* 可售日期弹窗 */}
{visibleSaleDate && (
<SaleDateModal
visible={visibleSaleDate}
id={recordID}
handleRefresh={() => searchList({})}
handleClose={() => setVisibleSaleDate(false)}
/>
)}
{/* 可售餐段弹窗 */}
{visibleSaleSection && (
<SaleSectionModal
visible={visibleSaleSection}
id={recordID}
handleRefresh={() => searchList({})}
handleClose={() => setVisibleSaleSection(false)}
/>
)}
{/* 修改企业商品价格弹窗 */}
{visiblePrice && (
<GoodPriceModal
visible={visiblePrice}
id={recordID}
handleRefresh={() => searchList({})}
handleClose={() => setVisiblePrice(false)}
/>
)}
{/* 商品排序弹窗 */}
{visibleSort && (
<GoodSortModal
visible={visibleSort}
id={recordID}
handleRefresh={() => searchList({})}
handleClose={() => setVisibleSort(false)}
/>
)}
</div>
);
};
export default VirtualGoods;
import React, { useRef, useState, useEffect } from 'react';
import { Button, notification, Spin, Select, Row, Col, Table, message } from 'antd';
import { useHistory } from 'react-router-dom';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { GoodsInfoColumn } from './staticData/goods';
import SaleDateModal from './components/SaleDateModal';
import SaleSectionModal from './components/SaleSectionModal';
import SelectGoodsModal from './components/SelectGoodsModal';
import { apiSaveVirtualGoodsList, apiShopListByEnterpriseID } from './service';
import style from './style/index.less';
const VirtualGoodsInfo = props => {
const { id } = props.location.query;
const history = useHistory();
const [loading, setLoading] = useState(false);
const [visibleSaleDate, setVisibleSaleDate] = useState(false); // 可售日期弹窗
const [visibleSaleSection, setVisibleSaleSection] = useState(false); // 可售餐段弹窗
const [visibleSelectGoods, setVisibleSelectGoods] = useState(false); // 选择商品弹窗
const [dataSource, setDataSource] = useState([]);
const [shopList, setShopList] = useState([]); // 店铺列表
const [sleShopID, setSelShopID] = useState(''); // 选中的店铺
const [editID, setEditID] = useState(''); // 编辑ID
// 取消
const onCancel = () => {
history.goBack();
};
// 提交
const onSubmit = async () => {
if (!dataSource || dataSource.length < 1) {
message.error('请添加商品');
return;
}
const skuInfoList = dataSource.map(item => ({
skuId: item.skuId,
enterprisePrice: item.enterprisePrice,
mealTypeList: item.mealType,
saleDateList: item.saleDate,
}));
const params = {
shopId: sleShopID,
enterpriseId: id,
skuInfoList,
};
await apiSaveVirtualGoodsList(params);
notification.success({ message: '添加成功' });
onCancel();
};
// 删除
const onDel = i => {
const arr = dataSource.splice(i, 1);
setDataSource(arr);
};
// 根据企业ID获取店铺列表
const getShopList = async () => {
const res = await apiShopListByEnterpriseID({
enterpriseId: id,
});
setShopList(
res.map(item => ({
key: item.id,
label: <span>{item.name}</span>,
})),
);
};
// 刷新列表数据
const refreshList = (type, v) => {
const arr = dataSource.map(item => {
if (editID) {
if (item.skuId === editID) {
item[type] = v;
}
} else {
item[type] = v;
}
return item;
});
setDataSource(arr);
};
// const initData = async () => {
// setLoading(true);
// };
useEffect(() => {
getShopList();
}, []);
const options = {
setVisibleSaleDate,
setVisibleSaleSection,
setEditID,
onDel,
};
return (
<PageHeaderWrapper title="添加企业严选商品">
<div className={style['info-box']}>
<Spin spinning={loading}>
<Row className={style['info-box--line']}>
<Col span={3} className={style['info-box--label']}>
企业名称:
</Col>
<Col span={20}>企业名称111</Col>
</Row>
<Row className={style['info-box--line']}>
<Col span={3} className={style['info-box--label']}>
选择店铺:
</Col>
<Col span={20}>
<Select
showSearch
options={shopList}
className={style['info-box--select']}
placeholder="清选择"
onChange={setSelShopID}
filterOption={(input, option) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())
}
/>
</Col>
</Row>
<Row className={style['info-box--line']}>
<Col span={3} className={style['info-box--label']}>
添加商品:
</Col>
<Col span={20}>
<Button type="primary" onClick={() => setVisibleSelectGoods(true)}>
选择商品
</Button>
</Col>
</Row>
<Row className={style['info-box--line']}>
<Col span={24}>
<div className={style['info-box--batch-btn']}>
<Button
onClick={() => {
setEditID('');
setVisibleSaleDate(true);
}}
>
批量配置日期
</Button>
<Button
onClick={() => {
setEditID('');
setVisibleSaleSection(true);
}}
>
批量配置餐段
</Button>
</div>
<Table columns={GoodsInfoColumn(options)} dataSource={dataSource} />
</Col>
</Row>
<Row className={style['info-box--btns']}>
<Col span={4} />
<Col span={20}>
<Button
type="primary"
onClick={onSubmit}
className={style['info-box--btns__confirm']}
>
确定
</Button>
<Button onClick={onCancel}>取消</Button>
</Col>
</Row>
</Spin>
{/* 可售日期弹窗 */}
{visibleSaleDate && (
<SaleDateModal
visible={visibleSaleDate}
handleRefresh={v => refreshList('saleDate', v)}
handleClose={() => setVisibleSaleDate(false)}
/>
)}
{/* 可售餐段弹窗 */}
{visibleSaleSection && (
<SaleSectionModal
visible={visibleSaleSection}
handleRefresh={v => refreshList('mealType', v)}
handleClose={() => setVisibleSaleSection(false)}
/>
)}
{/* 选择商品弹窗 */}
{visibleSelectGoods && (
<SelectGoodsModal
visible={visibleSelectGoods}
type="virtual"
onSelectChange={setDataSource}
handleClose={() => setVisibleSelectGoods(false)}
/>
)}
</div>
</PageHeaderWrapper>
);
};
export default VirtualGoodsInfo;
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
/* eslint-disable no-underscore-dangle */ /* eslint-disable no-underscore-dangle */
import { extend } from 'umi-request'; import { extend } from 'umi-request';
import { notification } from 'antd'; import { notification } from 'antd';
import { getUrlSearchParams, getToken } from './utils';
import localStorage from './localStorage'; import localStorage from './localStorage';
import config from '../../config/env.config'; import config from '../../config/env.config';
...@@ -70,13 +71,17 @@ const refreshRequest = async (url, options) => { ...@@ -70,13 +71,17 @@ const refreshRequest = async (url, options) => {
} }
return promise; return promise;
}; };
// 判断是否从tob进入
const searchPrams = getUrlSearchParams();
const isTob = searchPrams.source === 'tob';
/** /**
* 异常处理程序 * 异常处理程序
*/ */
// request拦截器, 改变url 或 options. // request拦截器, 改变url 或 options.
request.interceptors.request.use(async (url, options) => { request.interceptors.request.use(async (url, options) => {
const token = localStorage.get('token'); const token = getToken();
if (!token && !url.includes('/v2/oauth/login') && !url.includes('/v2/sms/send')) { if (!token && !url.includes('/v2/oauth/login') && !url.includes('/v2/sms/send')) {
window.location.href = `${window.origin}/user/login`; window.location.href = `${window.origin}/user/login`;
} }
...@@ -120,7 +125,11 @@ request.interceptors.response.use(async (response, options) => { ...@@ -120,7 +125,11 @@ request.interceptors.response.use(async (response, options) => {
notification.warning({ notification.warning({
message: data.msg, message: data.msg,
}); });
window.location.href = loginPath; if (isTob) {
localStorage.remove('tobToken');
} else {
window.location.href = loginPath;
}
} }
if (data.businessCode && data.businessCode !== '0000' && !options.notTip) { if (data.businessCode && data.businessCode !== '0000' && !options.notTip) {
notification.warning({ notification.warning({
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { parse } from 'querystring'; import { parse } from 'querystring';
import pathRegexp from 'path-to-regexp'; import pathRegexp from 'path-to-regexp';
import moment from 'moment'; import moment from 'moment';
import localStorage from './localStorage';
/* eslint no-useless-escape:0 import/prefer-default-export:0 */ /* eslint no-useless-escape:0 import/prefer-default-export:0 */
const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/; const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
...@@ -148,6 +149,13 @@ export const stringOrObjectTrim = params => { ...@@ -148,6 +149,13 @@ export const stringOrObjectTrim = params => {
return params; return params;
}; };
// json转数组用于[Radio/Select/Checkbox]的options
export const jsonToArray = (obj, valueType) =>
Object.keys(obj).map(key => ({
label: obj[key],
value: valueType === 'number' ? +key : key,
}));
export const getObjectType = v => Object.prototype.toString.call(v).replace(/\[object |]/g, ''); export const getObjectType = v => Object.prototype.toString.call(v).replace(/\[object |]/g, '');
// 获取长表单错误提示 // 获取长表单错误提示
...@@ -171,3 +179,45 @@ export const getErrorMessage = err => { ...@@ -171,3 +179,45 @@ export const getErrorMessage = err => {
})(err); })(err);
return message; return message;
}; };
// 获取地址栏参数,name:参数名称
export const getUrlParams = name => {
const regArg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`);
const r = window.location.search.substr(1).match(regArg);
if (r != null) return decodeURIComponent(r[2]);
return null;
};
// 获取地址栏所以参数
export const getUrlSearchParams = () => {
const newObj = {};
const url = window.location.search; // 获取url中"?"符后的字符串
if (url.indexOf('?') !== -1) {
const strs = url.replace('?', '').split('&');
for (let i = 0; i < strs.length; i++) {
newObj[strs[i].split('=')[0]] = strs[i].split('=')[1] || '';
}
}
return newObj;
};
// 获取token
export const getToken = () => {
// 从消费地图后管过来
if (getUrlParams('source') === 'tob' && localStorage.get('tobToken')) {
return localStorage.get('tobToken');
}
return localStorage.get('token');
};
// 获取跳转参数
export const getToUrlQuery = () => {
// 从消费地图后管过来
if (getUrlParams('source') === 'tob' && localStorage.get('tobToken')) {
return {
source: 'tob',
token: localStorage.get('tobToken'),
};
}
return {};
};
...@@ -48,3 +48,14 @@ ...@@ -48,3 +48,14 @@
visibility: hidden; visibility: hidden;
} }
} }
.formSearch {
padding: 0;
:global {
.ant-form-item {
display: block !important;
}
}
}
.formTable {
padding: 0;
}
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