Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
merchant-manage-ui
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ui
merchant-manage-ui
Commits
d72841d4
Commit
d72841d4
authored
Apr 11, 2023
by
郭志伟
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature/20230327_public_takeaway' into feat/buildForTest_tmp
parents
bbd6d125
d55b139b
Changes
56
Hide whitespace changes
Inline
Side-by-side
Showing
56 changed files
with
7573 additions
and
422 deletions
+7573
-422
.eslintrc.js
.eslintrc.js
+1
-0
config.js
config/config.js
+12
-0
env.config.js
config/env.config.js
+1
-1
permission.config.js
config/permission.config.js
+1
-0
package-lock.json
package-lock.json
+87
-1
package.json
package.json
+8
-0
app.js
src/app.js
+1
-2
index.jsx
src/components/BaiduMap/index.jsx
+66
-0
index.jsx
src/pages/GoodsManage/SearchForm/index.jsx
+99
-96
ActionBar.jsx
src/pages/GoodsManage/Takeaway/components/ActionBar.jsx
+82
-0
DragTag.jsx
src/pages/GoodsManage/Takeaway/components/DragTag.jsx
+97
-0
GoodsGroup.jsx
src/pages/GoodsManage/Takeaway/components/GoodsGroup.jsx
+192
-0
GroupInfo.jsx
src/pages/GoodsManage/Takeaway/components/GroupInfo.jsx
+86
-0
InsertTag.jsx
src/pages/GoodsManage/Takeaway/components/InsertTag.jsx
+22
-0
MinimumPurchase.jsx
...pages/GoodsManage/Takeaway/components/MinimumPurchase.jsx
+50
-0
SendModal.jsx
src/pages/GoodsManage/Takeaway/components/SendModal.jsx
+53
-0
StockModal.jsx
src/pages/GoodsManage/Takeaway/components/StockModal.jsx
+158
-0
SwitchGroupModal.jsx
...ages/GoodsManage/Takeaway/components/SwitchGroupModal.jsx
+53
-0
WeekTime.jsx
src/pages/GoodsManage/Takeaway/components/WeekTime.jsx
+186
-0
index.jsx
src/pages/GoodsManage/Takeaway/index.jsx
+302
-0
index.jsx
src/pages/GoodsManage/index.jsx
+176
-108
service.js
src/pages/GoodsManage/service.js
+89
-1
staticdata.js
src/pages/GoodsManage/staticdata.js
+197
-3
style.less
src/pages/GoodsManage/style.less
+163
-2
common.less
src/pages/ServiceGoods/common.less
+160
-1
AddMenusModal.jsx
src/pages/ServiceGoods/components/AddMenusModal.jsx
+102
-0
AddMultiSpecModal.jsx
src/pages/ServiceGoods/components/AddMultiSpecModal.jsx
+268
-0
AddRepertoryModal.jsx
src/pages/ServiceGoods/components/AddRepertoryModal.jsx
+184
-0
AddSellTimeModal.jsx
src/pages/ServiceGoods/components/AddSellTimeModal.jsx
+140
-0
FormInformationBasic.jsx
src/pages/ServiceGoods/components/FormInformationBasic.jsx
+219
-27
FormTakeaway.jsx
src/pages/ServiceGoods/components/FormTakeaway.jsx
+1322
-0
TaskTypeSelect.jsx
src/pages/ServiceGoods/components/TaskTypeSelect.jsx
+6
-2
UploadCropImage.jsx
src/pages/ServiceGoods/components/UploadCropImage.jsx
+266
-0
config.js
src/pages/ServiceGoods/config.js
+63
-19
index.jsx
src/pages/ServiceGoods/index.jsx
+174
-50
service.js
src/pages/ServiceGoods/service.js
+50
-0
utils.js
src/pages/ServiceGoods/utils.js
+72
-2
data.js
src/pages/businessManage/info/data.js
+380
-0
index.jsx
src/pages/businessManage/info/index.jsx
+1184
-0
style.less
src/pages/businessManage/info/style.less
+64
-0
model.js
src/pages/businessManage/model.js
+7
-0
service.js
src/pages/businessManage/service.js
+61
-0
staticdata.js
src/pages/businessManage/staticdata.js
+40
-0
style.less
src/pages/businessManage/style.less
+50
-0
storeModal.jsx
src/pages/chainStoreManage/components/storeModal.jsx
+124
-20
data.js
src/pages/chainStoreManage/data.js
+8
-0
index.jsx
src/pages/chainStoreManage/index.jsx
+144
-74
services.js
src/pages/chainStoreManage/services.js
+8
-0
style.less
src/pages/chainStoreManage/style.less
+16
-1
upload.jsx
src/pages/components/upload.jsx
+61
-12
data.js
src/pages/contractView/data.js
+0
-0
index.jsx
src/pages/contractView/index.jsx
+124
-0
services.js
src/pages/contractView/services.js
+31
-0
style.less
src/pages/contractView/style.less
+3
-0
utils.js
src/utils/utils.js
+44
-0
validator.js
src/utils/validator.js
+16
-0
No files found.
.eslintrc.js
View file @
d72841d4
...
@@ -15,5 +15,6 @@ module.exports = {
...
@@ -15,5 +15,6 @@ module.exports = {
'
import/no-unresolved
'
:
0
,
'
import/no-unresolved
'
:
0
,
'
import/extensions
'
:
0
,
'
import/extensions
'
:
0
,
'
no-unused-expressions
'
:
[
'
error
'
,
{
allowShortCircuit
:
true
}],
'
no-unused-expressions
'
:
[
'
error
'
,
{
allowShortCircuit
:
true
}],
'
template-curly-spacing
'
:
'
off
'
,
},
},
};
};
config/config.js
View file @
d72841d4
...
@@ -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
'
,
},
},
...
...
config/env.config.js
View file @
d72841d4
const
isProduction
=
process
.
env
.
NODE_ENV
===
'
production
'
;
const
isProduction
=
process
.
env
.
NODE_ENV
===
'
production
'
;
const
isPre
=
process
.
env
.
PRE_ENV
===
'
pre
'
;
const
isPre
=
process
.
env
.
PRE_ENV
===
'
pre
'
;
const
environment
=
'
xyqb
'
;
const
environment
=
'
yxm2
'
;
const
envAPi
=
{
const
envAPi
=
{
api
:
`https://security-
${
environment
}
.liangkebang.net`
,
//'https://security-xyqb.liangkebang.net',
api
:
`https://security-
${
environment
}
.liangkebang.net`
,
//'https://security-xyqb.liangkebang.net',
kdspOpApi
:
`https://sc-merchant-api-
${
environment
}
.liangkebang.net`
,
kdspOpApi
:
`https://sc-merchant-api-
${
environment
}
.liangkebang.net`
,
...
...
config/permission.config.js
View file @
d72841d4
...
@@ -5,6 +5,7 @@ export const GOOD_MANAGE = {
...
@@ -5,6 +5,7 @@ export const GOOD_MANAGE = {
EDITABLE
:
'
020102
'
,
// 新增/修改
EDITABLE
:
'
020102
'
,
// 新增/修改
ADD_SERVICE_GOODS
:
'
020103
'
,
// 新增服务商品
ADD_SERVICE_GOODS
:
'
020103
'
,
// 新增服务商品
ADD_NORMAL_GOODS
:
'
020104
'
,
// 新增实物商品
ADD_NORMAL_GOODS
:
'
020104
'
,
// 新增实物商品
ADD_TAKEAWAY_GOODS
:
'
020105
'
,
// 新增外卖商品
};
};
// 配送区域
// 配送区域
...
...
package-lock.json
View file @
d72841d4
...
@@ -6960,6 +6960,39 @@
...
@@ -6960,6 +6960,39 @@
}
}
}
}
},
},
"antd-img-crop": {
"version": "4.11.0",
"resolved": "http://npmprivate.quantgroups.com/antd-img-crop/-/antd-img-crop-4.11.0.tgz",
"integrity": "sha512-DWf72AsFc8r2BKRfNMhUrMDh3xg2PvYB6b0gCYPrBEkVbQE1VP7Qt3HnthdeWDapSGdnmUPKFTcMgzML/FyuTA==",
"requires": {
"compare-versions": "6.0.0-rc.1",
"react-easy-crop": "^4.7.4",
"tslib": "^2.5.0"
},
"dependencies": {
"react-easy-crop": {
"version": "4.7.4",
"resolved": "http://npmprivate.quantgroups.com/react-easy-crop/-/react-easy-crop-4.7.4.tgz",
"integrity": "sha512-oDi1375Jo/zuPUvo3oauxnNbfy8L4wsbmHD1KB2vT55fdgu+q8/K0w/rDWzy9jz4jfQ94Q9+3Yu366sDDFVmiA==",
"requires": {
"normalize-wheel": "^1.0.1",
"tslib": "2.0.1"
},
"dependencies": {
"tslib": {
"version": "2.0.1",
"resolved": "http://npmprivate.quantgroups.com/tslib/-/tslib-2.0.1.tgz",
"integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ=="
}
}
},
"tslib": {
"version": "2.5.0",
"resolved": "http://npmprivate.quantgroups.com/tslib/-/tslib-2.5.0.tgz",
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
}
}
},
"antd-mobile": {
"antd-mobile": {
"version": "2.3.4",
"version": "2.3.4",
"resolved": "http://npmprivate.quantgroups.com/antd-mobile/-/antd-mobile-2.3.4.tgz",
"resolved": "http://npmprivate.quantgroups.com/antd-mobile/-/antd-mobile-2.3.4.tgz",
...
@@ -7170,6 +7203,11 @@
...
@@ -7170,6 +7203,11 @@
"integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=",
"integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=",
"dev": true
"dev": true
},
},
"array-move": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/array-move/-/array-move-4.0.0.tgz",
"integrity": "sha512-+RY54S8OuVvg94THpneQvFRmqWdAHeqtMzgMW6JNurHxe8rsS07cHQdfGkXnTUXiBcyZ0j3SiDIxxj0RPiqCkQ=="
},
"array-reduce": {
"array-reduce": {
"version": "0.0.0",
"version": "0.0.0",
"resolved": "http://npmprivate.quantgroups.com/array-reduce/-/array-reduce-0.0.0.tgz",
"resolved": "http://npmprivate.quantgroups.com/array-reduce/-/array-reduce-0.0.0.tgz",
...
@@ -8730,6 +8768,11 @@
...
@@ -8730,6 +8768,11 @@
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
"dev": true
"dev": true
},
},
"compare-versions": {
"version": "6.0.0-rc.1",
"resolved": "http://npmprivate.quantgroups.com/compare-versions/-/compare-versions-6.0.0-rc.1.tgz",
"integrity": "sha512-cFhkjbGY1jLFWIV7KegECbfuyYPxSGvgGkdkfM+ibboQDoPwg2FRHm5BSNTOApiauRBzJIQH7qvOJs2sW5ueKQ=="
},
"component-classes": {
"component-classes": {
"version": "1.2.6",
"version": "1.2.6",
"resolved": "http://npmprivate.quantgroups.com/component-classes/-/component-classes-1.2.6.tgz",
"resolved": "http://npmprivate.quantgroups.com/component-classes/-/component-classes-1.2.6.tgz",
...
@@ -18381,6 +18424,11 @@
...
@@ -18381,6 +18424,11 @@
"object-visit": "^1.0.0"
"object-visit": "^1.0.0"
}
}
},
},
"mapvgl": {
"version": "1.0.0-beta.175",
"resolved": "https://registry.npmjs.org/mapvgl/-/mapvgl-1.0.0-beta.175.tgz",
"integrity": "sha512-BaUPH4EAhgIjcTwqoOEBB6Vk93K7itLdaES7Qz8RnrwJeGBzoQKypRSZtszeueuFjRW/M5GntjxCC8vm5PD+OA=="
},
"markdown-escapes": {
"markdown-escapes": {
"version": "1.0.4",
"version": "1.0.4",
"resolved": "http://npmprivate.quantgroups.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz",
"resolved": "http://npmprivate.quantgroups.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz",
...
@@ -19334,6 +19382,11 @@
...
@@ -19334,6 +19382,11 @@
"integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
"integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
"dev": true
"dev": true
},
},
"normalize-wheel": {
"version": "1.0.1",
"resolved": "http://npmprivate.quantgroups.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
"integrity": "sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU="
},
"normalize.css": {
"normalize.css": {
"version": "7.0.0",
"version": "7.0.0",
"resolved": "http://npmprivate.quantgroups.com/normalize.css/-/normalize.css-7.0.0.tgz",
"resolved": "http://npmprivate.quantgroups.com/normalize.css/-/normalize.css-7.0.0.tgz",
...
@@ -20916,6 +20969,11 @@
...
@@ -20916,6 +20969,11 @@
}
}
}
}
},
},
"pubsub-js": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/pubsub-js/-/pubsub-js-1.9.4.tgz",
"integrity": "sha512-hJYpaDvPH4w8ZX/0Fdf9ma1AwRgU353GfbaVfPjfJQf1KxZ2iHaHl3fAUw1qlJIR5dr4F3RzjGaWohYUEyoh7A=="
},
"pump": {
"pump": {
"version": "3.0.0",
"version": "3.0.0",
"resolved": "http://npmprivate.quantgroups.com/pump/-/pump-3.0.0.tgz",
"resolved": "http://npmprivate.quantgroups.com/pump/-/pump-3.0.0.tgz",
...
@@ -22115,6 +22173,15 @@
...
@@ -22115,6 +22173,15 @@
"resolved": "http://npmprivate.quantgroups.com/react-amap/-/react-amap-1.2.8.tgz",
"resolved": "http://npmprivate.quantgroups.com/react-amap/-/react-amap-1.2.8.tgz",
"integrity": "sha512-uHPEUXti+CcwFyCeqGGqR0ACnXJA9D8S/lQYal9AG3XEOrwkaOFbWUavrvXxjcfAclROIWg8uKxzlRpMQnkHFg=="
"integrity": "sha512-uHPEUXti+CcwFyCeqGGqR0ACnXJA9D8S/lQYal9AG3XEOrwkaOFbWUavrvXxjcfAclROIWg8uKxzlRpMQnkHFg=="
},
},
"react-bmapgl": {
"version": "0.2.17",
"resolved": "https://registry.npmjs.org/react-bmapgl/-/react-bmapgl-0.2.17.tgz",
"integrity": "sha512-pcpPOaUeHY3eMmP3Wfz3qdkcrkmtBcbLy8Ih14exYwCe0XJ3IZpmkkarnMvayLymzhH2iyXAyZv42tGnkmv2LA==",
"requires": {
"mapvgl": "^1.0.0-beta.174",
"shallowequal": "^1.1.0"
}
},
"react-copy-to-clipboard": {
"react-copy-to-clipboard": {
"version": "5.0.2",
"version": "5.0.2",
"resolved": "http://npmprivate.quantgroups.com/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.2.tgz",
"resolved": "http://npmprivate.quantgroups.com/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.2.tgz",
...
@@ -22420,7 +22487,7 @@
...
@@ -22420,7 +22487,7 @@
},
},
"react-router-dom": {
"react-router-dom": {
"version": "5.1.2",
"version": "5.1.2",
"resolved": "http
://npmprivate.quantgroups.com
/react-router-dom/-/react-router-dom-5.1.2.tgz",
"resolved": "http
s://registry.npmjs.org
/react-router-dom/-/react-router-dom-5.1.2.tgz",
"integrity": "sha512-7BPHAaIwWpZS074UKaw1FjVdZBSVWEk8IuDXdB+OkLb8vd/WRQIpA4ag9WQk61aEfQs47wHyjWUoUGGZxpQXew==",
"integrity": "sha512-7BPHAaIwWpZS074UKaw1FjVdZBSVWEk8IuDXdB+OkLb8vd/WRQIpA4ag9WQk61aEfQs47wHyjWUoUGGZxpQXew==",
"requires": {
"requires": {
"@babel/runtime": "^7.1.2",
"@babel/runtime": "^7.1.2",
...
@@ -22479,6 +22546,16 @@
...
@@ -22479,6 +22546,16 @@
"shallowequal": "^1.0.1"
"shallowequal": "^1.0.1"
}
}
},
},
"react-sortable-hoc": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-2.0.0.tgz",
"integrity": "sha512-JZUw7hBsAHXK7PTyErJyI7SopSBFRcFHDjWW5SWjcugY0i6iH7f+eJkY8cJmGMlZ1C9xz1J3Vjz0plFpavVeRg==",
"requires": {
"@babel/runtime": "^7.2.0",
"invariant": "^2.2.4",
"prop-types": "^15.5.7"
}
},
"react-sortablejs": {
"react-sortablejs": {
"version": "6.0.0",
"version": "6.0.0",
"resolved": "http://npmprivate.quantgroups.com/react-sortablejs/-/react-sortablejs-6.0.0.tgz",
"resolved": "http://npmprivate.quantgroups.com/react-sortablejs/-/react-sortablejs-6.0.0.tgz",
...
@@ -22498,6 +22575,15 @@
...
@@ -22498,6 +22575,15 @@
"tween-functions": "^1.0.1"
"tween-functions": "^1.0.1"
}
}
},
},
"react-window": {
"version": "1.8.8",
"resolved": "http://npmprivate.quantgroups.com/react-window/-/react-window-1.8.8.tgz",
"integrity": "sha512-D4IiBeRtGXziZ1n0XklnFGu7h9gU684zepqyKzgPNzrsrk7xOCxni+TCckjg2Nr/DiaEEGVVmnhYSlT2rB47dQ==",
"requires": {
"@babel/runtime": "^7.0.0",
"memoize-one": ">=3.1.1 <6"
}
},
"read-pkg": {
"read-pkg": {
"version": "2.0.0",
"version": "2.0.0",
"resolved": "http://npmprivate.quantgroups.com/read-pkg/-/read-pkg-2.0.0.tgz",
"resolved": "http://npmprivate.quantgroups.com/read-pkg/-/read-pkg-2.0.0.tgz",
package.json
View file @
d72841d4
...
@@ -57,7 +57,9 @@
...
@@ -57,7 +57,9 @@
"
@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.19.3
"
,
"
antd-img-crop
"
:
"
^4.11.0
"
,
"
antd-virtual-select
"
:
"
^1.1.2
"
,
"
antd-virtual-select
"
:
"
^1.1.2
"
,
"
array-move
"
:
"
^4.0.0
"
,
"
babel-eslint
"
:
"
^10.1.0
"
,
"
babel-eslint
"
:
"
^10.1.0
"
,
"
classnames
"
:
"
^2.2.6
"
,
"
classnames
"
:
"
^2.2.6
"
,
"
date-fns
"
:
"
^2.16.1
"
,
"
date-fns
"
:
"
^2.16.1
"
,
...
@@ -67,14 +69,20 @@
...
@@ -67,14 +69,20 @@
"
moment
"
:
"
^2.24.0
"
,
"
moment
"
:
"
^2.24.0
"
,
"
omit.js
"
:
"
^1.0.2
"
,
"
omit.js
"
:
"
^1.0.2
"
,
"
path-to-regexp
"
:
"
^3.1.0
"
,
"
path-to-regexp
"
:
"
^3.1.0
"
,
"
pubsub-js
"
:
"
^1.9.4
"
,
"
qs
"
:
"
^6.9.0
"
,
"
qs
"
:
"
^6.9.0
"
,
"
react
"
:
"
^16.8.6
"
,
"
react
"
:
"
^16.8.6
"
,
"
react-amap
"
:
"
^1.2.8
"
,
"
react-amap
"
:
"
^1.2.8
"
,
"
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-html5-backend
"
:
"
10.0.2
"
,
"
react-dom
"
:
"
^16.8.6
"
,
"
react-dom
"
:
"
^16.8.6
"
,
"
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-sortablejs
"
:
"
^6.0.0
"
,
"
react-sortablejs
"
:
"
^6.0.0
"
,
"
react-window
"
:
"
^1.8.8
"
,
"
slash2
"
:
"
^2.0.0
"
,
"
slash2
"
:
"
^2.0.0
"
,
"
sortablejs
"
:
"
^1.13.0
"
,
"
sortablejs
"
:
"
^1.13.0
"
,
"
umi
"
:
"
^3.0.0
"
,
"
umi
"
:
"
^3.0.0
"
,
...
...
src/app.js
View file @
d72841d4
/* eslint-disable no-console */
/* eslint-disable no-console */
import
*
as
Sentry
from
'
@sentry/react
'
;
import
*
as
Sentry
from
'
@sentry/react
'
;
import
localStorage
from
'
@/utils/localStorage
'
;
import
localStorage
from
'
@/utils/localStorage
'
;
// process.env.SENTRY_ENV !== 'test' 加上测试环境不会报错
if
(
process
.
env
.
NODE_ENV
===
'
production
'
&&
process
.
env
.
SENTRY_ENV
!==
'
test
'
)
{
if
(
process
.
env
.
NODE_ENV
===
'
production
'
)
{
try
{
try
{
Sentry
.
init
({
Sentry
.
init
({
dsn
:
'
https://b3f60c62e1234e26a5b851b9f26fba07@sentry.q-gp.com/34
'
,
dsn
:
'
https://b3f60c62e1234e26a5b851b9f26fba07@sentry.q-gp.com/34
'
,
...
...
src/components/BaiduMap/index.jsx
0 → 100644
View file @
d72841d4
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
>
);
};
src/pages/GoodsManage/SearchForm/index.jsx
View file @
d72841d4
...
@@ -12,6 +12,7 @@ import {
...
@@ -12,6 +12,7 @@ import {
Divider
,
Divider
,
}
from
'
antd
'
;
}
from
'
antd
'
;
import
React
,
{
Component
,
useState
}
from
'
react
'
;
import
React
,
{
Component
,
useState
}
from
'
react
'
;
import
{
SwapRightOutlined
}
from
'
@ant-design/icons
'
;
import
{
connect
}
from
'
dva
'
;
import
{
connect
}
from
'
dva
'
;
import
{
saveAs
}
from
'
file-saver
'
;
import
{
saveAs
}
from
'
file-saver
'
;
import
{
format
}
from
'
date-fns
'
;
import
{
format
}
from
'
date-fns
'
;
...
@@ -31,6 +32,7 @@ class goodsManage extends Component {
...
@@ -31,6 +32,7 @@ class goodsManage extends Component {
state
=
{
state
=
{
loading
:
false
,
loading
:
false
,
productType
:
null
,
};
};
componentDidMount
()
{
componentDidMount
()
{
...
@@ -59,6 +61,10 @@ class goodsManage extends Component {
...
@@ -59,6 +61,10 @@ class goodsManage extends Component {
const
form
=
this
.
formRef
.
current
;
const
form
=
this
.
formRef
.
current
;
form
.
resetFields
();
form
.
resetFields
();
this
.
props
.
onReset
();
this
.
props
.
onReset
();
this
.
props
.
changeProductType
(
1
);
this
.
setState
({
productType
:
1
,
});
};
};
addSpu
=
()
=>
{
addSpu
=
()
=>
{
...
@@ -78,6 +84,24 @@ class goodsManage extends Component {
...
@@ -78,6 +84,24 @@ class goodsManage extends Component {
}
}
};
};
onChangeProductType
=
(
v
=
null
)
=>
{
const
form
=
this
.
formRef
.
current
;
form
.
setFieldsValue
({
skuId
:
''
,
skuName
:
''
,
thirdSkuNo
:
''
,
productCategoryId
:
null
,
state
:
null
,
supplyPriceMin
:
null
,
supplyPriceMax
:
null
,
productType
:
v
,
});
this
.
props
.
changeProductType
(
v
);
this
.
setState
({
productType
:
v
,
});
};
// 导出明细
// 导出明细
onExportGoodsInfo
=
async
()
=>
{
onExportGoodsInfo
=
async
()
=>
{
this
.
setState
({
this
.
setState
({
...
@@ -105,7 +129,6 @@ class goodsManage extends Component {
...
@@ -105,7 +129,6 @@ class goodsManage extends Component {
const
{
treeData
,
permissions
}
=
this
.
props
;
const
{
treeData
,
permissions
}
=
this
.
props
;
const
selectW
=
{
width
:
250
};
const
selectW
=
{
width
:
250
};
const
iptNumWidth
=
{
width
:
118
};
const
iptNumWidth
=
{
width
:
118
};
const
that
=
this
;
const
canEditable
=
permissions
[
GOOD_MANAGE
.
EDITABLE
];
const
canEditable
=
permissions
[
GOOD_MANAGE
.
EDITABLE
];
const
content
=
(
const
content
=
(
<
div
>
<
div
>
...
@@ -130,46 +153,29 @@ class goodsManage extends Component {
...
@@ -130,46 +153,29 @@ class goodsManage extends Component {
</
Button
>
</
Button
>
</
div
>
</
div
>
);
);
// const uploadProps = {
// name: 'file',
// async customRequest(info) {
// const result = await uploadFile(info.file);
// if (result && result.businessCode === '0000') {
// that.handleSearch();
// notification.success({
// message: '操作成功',
// });
// } else {
// notification.warning({
// message: result.msg,
// description: (
// <div>
// {result.data?.length &&
// result.data.map(item => <p>{item.skuNo + item.errSkuMessage}</p>)}
// </div>
// ),
// duration: 6,
// });
// }
// },
// accept: '.xlsx',
// showUploadList: false,
// };
const
filterOption
=
(
input
,
op
)
=>
op
.
props
.
children
.
includes
(
input
);
const
filterOption
=
(
input
,
op
)
=>
op
.
props
.
children
.
includes
(
input
);
return
(
return
(
<
Form
<
Form
ref=
{
this
.
formRef
}
ref=
{
this
.
formRef
}
name=
"horizontal_login"
name=
"horizontal_login"
initialValues=
{
{
productType
:
1
}
}
layout=
"inline"
layout=
"inline"
className=
{
styles
.
searchForm
}
className=
{
styles
.
searchForm
}
>
>
<
FormItem
label=
"SKU编码"
name=
"skuId"
>
<
FormItem
label=
"SKU编码"
name=
"skuId"
>
<
Input
placeholder=
"请输入SKU编码"
allowClear
style=
{
selectW
}
/>
<
Input
Number
placeholder=
"请输入SKU编码"
max=
{
99999999999999999
}
style=
{
selectW
}
/>
</
FormItem
>
</
FormItem
>
<
FormItem
label=
"商品名称"
name=
"skuName"
>
<
FormItem
label=
"商品名称"
name=
"skuName"
>
<
Input
placeholder=
"请输入商品名称"
allowClear
style=
{
selectW
}
/>
<
Input
placeholder=
"请输入商品名称"
allowClear
style=
{
selectW
}
/>
</
FormItem
>
</
FormItem
>
<
FormItem
label=
"商品类型"
name=
"productType"
>
<
Select
style=
{
selectW
}
placeholder=
"请选择商品类型"
onChange=
{
this
.
onChangeProductType
}
>
<
Option
value=
{
1
}
>
实体商品
</
Option
>
<
Option
value=
{
4
}
>
服务类商品
</
Option
>
<
Option
value=
{
5
}
>
外卖商品
</
Option
>
</
Select
>
</
FormItem
>
<
FormItem
label=
"类目"
name=
"productCategoryId"
>
<
FormItem
label=
"类目"
name=
"productCategoryId"
>
<
Cascader
<
Cascader
placeholder=
"请选择类目"
placeholder=
"请选择类目"
...
@@ -180,82 +186,79 @@ class goodsManage extends Component {
...
@@ -180,82 +186,79 @@ class goodsManage extends Component {
options=
{
treeData
}
options=
{
treeData
}
/>
/>
</
FormItem
>
</
FormItem
>
<
FormItem
label=
"审核状态"
name=
"state"
>
{
this
.
state
.
productType
!==
5
&&
(
<
Select
<>
style=
{
selectW
}
<
FormItem
label=
"审核状态"
name=
"state"
>
placeholder=
"请选择审核状态"
<
Select
allowClear
style=
{
selectW
}
filterOption=
{
filterOption
}
placeholder=
"请选择审核状态"
>
allowClear
{
stateList
?.
map
(
item
=>
(
filterOption=
{
filterOption
}
<
Option
key=
{
item
.
value
}
value=
{
item
.
value
}
>
>
{
item
.
label
}
{
stateList
?.
map
(
item
=>
(
</
Option
>
<
Option
key=
{
item
.
value
}
value=
{
item
.
value
}
>
))
}
{
item
.
label
}
</
Select
>
</
Option
>
</
FormItem
>
))
}
<
FormItem
label=
"供货价区间"
>
</
Select
>
<
FormItem
name=
"supplyPriceMin"
className=
{
styles
.
iptNumRight
}
noStyle
>
</
FormItem
>
<
InputNumber
placeholder=
"请输入"
style=
{
iptNumWidth
}
/>
<
FormItem
label=
"供货价区间"
>
</
FormItem
>
<
FormItem
name=
"supplyPriceMin"
className=
{
styles
.
iptNumRight
}
noStyle
>
<
span
>
--
</
span
>
<
InputNumber
placeholder=
"请输入"
min=
{
0
}
max=
{
999999999
}
style=
{
iptNumWidth
}
/>
<
FormItem
name=
"supplyPriceMax"
className=
{
styles
.
iptNumRight
}
noStyle
>
</
FormItem
>
<
InputNumber
style=
{
iptNumWidth
}
placeholder=
"请输入"
onChange=
{
this
.
valueMin
}
/>
<
span
>
</
FormItem
>
<
SwapRightOutlined
/>
</
FormItem
>
</
span
>
<
FormItem
label=
"商品类型"
name=
"productType"
>
<
FormItem
name=
"supplyPriceMax"
className=
{
styles
.
iptNumRight
}
noStyle
>
<
Select
style=
{
selectW
}
placeholder=
"请选择商品类型"
>
<
InputNumber
<
Option
value=
{
1
}
>
实体商品
</
Option
>
style=
{
iptNumWidth
}
<
Option
value=
{
2
}
>
虚拟商品
</
Option
>
min=
{
0
}
<
Option
value=
{
4
}
>
服务类商品
</
Option
>
max=
{
999999999
}
</
Select
>
placeholder=
"请输入"
</
FormItem
>
onChange=
{
this
.
valueMin
}
<
FormItem
name=
"thirdSkuNo"
label=
"第三方SKU编码"
>
/>
<
Input
placeholder=
"请输入第三方SKU编码"
allowClear
style=
{
selectW
}
/>
</
FormItem
>
</
FormItem
>
</
FormItem
>
<
FormItem
name=
"thirdSkuNo"
label=
"第三方SKU编码"
>
<
Input
placeholder=
"请输入第三方SKU编码"
allowClear
style=
{
selectW
}
/>
</
FormItem
>
</>
)
}
<
FormItem
className=
{
styles
.
queryBtn
}
>
<
FormItem
className=
{
styles
.
queryBtn
}
>
<
Button
onClick=
{
()
=>
this
.
handleSearch
()
}
type=
"primary"
className=
{
styles
.
button
}
>
<
Button
onClick=
{
()
=>
this
.
handleSearch
()
}
type=
"primary"
className=
{
styles
.
button
}
>
查询
查询
</
Button
>
</
Button
>
<
Button
onClick=
{
()
=>
this
.
onReset
()
}
type=
"primary"
className=
{
styles
.
button
}
>
<
Button
onClick=
{
()
=>
this
.
onReset
()
}
className=
{
styles
.
button
}
>
重置
重置
</
Button
>
</
Button
>
<
Button
{
this
.
state
.
productType
!==
5
&&
(
loading=
{
this
.
state
.
loading
}
<>
onClick=
{
()
=>
this
.
onExportGoodsInfo
()
}
<
Button
className=
{
styles
.
button
}
loading=
{
this
.
state
.
loading
}
>
onClick=
{
()
=>
this
.
onExportGoodsInfo
()
}
导出
type=
"primary"
</
Button
>
ghost
</
FormItem
>
className=
{
styles
.
button
}
{
canEditable
?
(
>
<
FormItem
style=
{
{
float
:
'
right
'
}
}
>
导出
<
Popover
content=
{
content
}
onVisibleChange=
{
this
.
handleVisibleChange
}
>
<
Button
type=
"primary"
className=
{
styles
.
button
}
>
批量设置
</
Button
>
</
Button
>
</
Popover
>
{
canEditable
?
(
{
this
.
props
.
selectNum
>
0
&&
<
Tag
color=
"green"
>
已选商品
{
this
.
props
.
selectNum
}
</
Tag
>
}
<
FormItem
style=
{
{
float
:
'
right
'
}
}
>
{
/* <Button
<
Popover
content=
{
content
}
onVisibleChange=
{
this
.
handleVisibleChange
}
>
className={styles.button}
<
Button
type=
"primary"
className=
{
styles
.
button
}
>
type="primary"
批量设置
icon="download"
</
Button
>
ghost
</
Popover
>
onClick={() => {
{
this
.
props
.
selectNum
>
0
&&
(
window.location.href = 'https://kdspstatic.q-gp.com/批量修改库存模板.xlsx';
<
Tag
color=
"green"
>
已选商品
{
this
.
props
.
selectNum
}
</
Tag
>
}}
)
}
>
</
FormItem
>
模版
)
:
(
</Button>
''
<Upload {...uploadProps}>
)
}
<Button type="primary" className={styles.button}>
</>
批量库存修改
)
}
</Button>
</
FormItem
>
</Upload> */
}
</
FormItem
>
)
:
(
''
)
}
</
Form
>
</
Form
>
);
);
}
}
...
...
src/pages/GoodsManage/Takeaway/components/ActionBar.jsx
0 → 100644
View file @
d72841d4
import
React
from
'
react
'
;
import
{
Button
,
Dropdown
,
Menu
,
message
,
Modal
}
from
'
antd
'
;
import
{
PlusOutlined
,
DownOutlined
,
ExclamationCircleOutlined
}
from
'
@ant-design/icons
'
;
import
{
batchAction
}
from
'
../../staticdata
'
;
import
styles
from
'
../../style.less
'
;
import
{
apiGoodsActionBatch
}
from
'
../../service
'
;
const
ActionBar
=
options
=>
{
// 上下架
const
changeStatus
=
async
state
=>
{
console
.
log
(
'
options.shopId :>>
'
,
options
.
shopId
);
Modal
.
confirm
({
icon
:
<
ExclamationCircleOutlined
/>,
content
:
`确认
${
+
state
===
6
?
'
下架
'
:
'
上架
'
}
商品?`
,
onOk
:
async
()
=>
{
const
res
=
await
apiGoodsActionBatch
({
skuIds
:
options
.
selectedRowKeys
,
type
:
2
,
shopId
:
options
.
shopId
,
productStatus
:
+
state
===
6
?
0
:
1
,
// 6:上架,7:下架
});
if
(
res
.
businessCode
===
'
0000
'
&&
res
.
code
===
'
0000
'
)
{
options
.
handleSearch
();
message
.
success
(
'
处理成功!
'
);
}
},
});
};
/**
* 批量操作
* up 上架
* down 下架
* stock 修改库存
* time 修改可售时间
* group 修改分组
* send 设置单点不送
* buy 修改最少购买数量
*/
const
onChangeState
=
type
=>
{
if
(
options
.
selectedRowKeys
&&
options
.
selectedRowKeys
.
length
)
{
if
([
'
up
'
,
'
down
'
].
includes
(
type
))
{
changeStatus
(
type
===
'
up
'
?
7
:
6
);
}
else
{
options
.
openModal
(
type
);
}
}
else
{
message
.
warning
(
'
请选择商品!
'
);
}
};
const
eventObj
=
{
onChangeState
,
};
const
actions
=
batchAction
(
eventObj
);
const
menus
=
(
<
Menu
>
{
actions
.
map
(
item
=>
(
<
Menu
.
Item
key=
{
item
.
key
}
>
{
item
.
label
}
</
Menu
.
Item
>
))
}
</
Menu
>
);
return
(
<
div
className=
{
styles
[
'
action-bar-box
'
]
}
>
{
(
options
.
canAddTakeaway
&&
(
<
Button
type=
"primary"
icon=
{
<
PlusOutlined
/>
}
onClick=
{
options
.
newGoods
}
>
该分组下新增商品
</
Button
>
))
||
''
}
<
Dropdown
overlay=
{
menus
}
className=
{
styles
[
'
action-bar-box--down
'
]
}
placement=
"bottomLeft"
>
<
Button
type=
"primary"
>
批量操作
<
DownOutlined
/>
</
Button
>
</
Dropdown
>
</
div
>
);
};
export
default
ActionBar
;
src/pages/GoodsManage/Takeaway/components/DragTag.jsx
0 → 100644
View file @
d72841d4
import
React
,
{
useRef
,
useState
}
from
'
react
'
;
import
{
useDrag
,
useDrop
}
from
'
react-dnd
'
;
import
{
Tag
,
Input
,
Popconfirm
}
from
'
antd
'
;
import
{
HolderOutlined
,
FormOutlined
,
CloseCircleOutlined
}
from
'
@ant-design/icons
'
;
import
styles
from
'
../../style.less
'
;
const
ItemTypes
=
{
CARD
:
'
card
'
,
};
const
DragTag
=
({
text
,
id
,
index
,
changePosition
,
endChangePosition
,
edit
,
del
,
selected
})
=>
{
const
[
isEdit
,
setIsEdit
]
=
useState
(
false
);
const
[
inputValue
,
setInputValue
]
=
useState
(
''
);
const
refInput
=
useRef
();
const
handleEdit
=
()
=>
{
edit
(
id
);
};
const
handleInputChange
=
e
=>
{
setInputValue
(
e
.
target
.
value
);
};
const
handleInputConfirm
=
()
=>
{
setIsEdit
(
false
);
setInputValue
(
''
);
};
const
handleClose
=
()
=>
{
del
(
id
);
};
const
ref
=
useRef
(
null
);
// 因为没有定义收集函数,所以返回值数组第一项不要
const
[,
drop
]
=
useDrop
({
accept
:
ItemTypes
.
CARD
,
hover
:
(
item
,
monitor
)
=>
{
if
(
!
ref
.
current
)
return
;
const
dragIndex
=
item
.
index
;
const
hoverIndex
=
index
;
if
(
dragIndex
===
hoverIndex
)
return
;
// 如果回到自己的坑,那就什么都不做
changePosition
(
dragIndex
,
hoverIndex
);
// 调用传入的方法完成交换
item
.
index
=
hoverIndex
;
// 将当前当前移动到Box的index赋值给当前拖动的box,不然会出现两个盒子疯狂抖动!
},
drop
:
(
item
,
monitor
)
=>
{
endChangePosition
();
// 调用传入的方法完成交换
},
});
const
[{
isDragging
},
drag
]
=
useDrag
({
type
:
ItemTypes
.
CARD
,
item
:
{
id
,
index
,
type
:
ItemTypes
.
CARD
},
end
:
()
=>
{},
isDragging
:
monitor
=>
index
===
monitor
.
getItem
().
index
,
collect
:
monitor
=>
({
isDragging
:
monitor
.
isDragging
(),
}),
});
const
inputRender
=
()
=>
(
<
Input
type=
"text"
size=
"small"
ref=
{
refInput
}
className=
{
styles
[
'
groupBox-body--tag-input
'
]
}
value=
{
inputValue
}
onChange=
{
handleInputChange
}
onBlur=
{
handleInputConfirm
}
onPressEnter=
{
handleInputConfirm
}
/>
);
const
groupEditRender
=
()
=>
(
<
Tag
className=
{
[
styles
[
'
groupBox-body--tag
'
]]
}
ref=
{
drag
(
drop
(
ref
))
}
style=
{
{
opacity
:
isDragging
?
0.3
:
1
,
display
:
isEdit
?
'
none
'
:
'
inline-block
'
,
}
}
>
<
HolderOutlined
className=
{
styles
[
'
groupBox-body--tag__move
'
]
}
/>
<
span
className=
{
styles
[
'
groupBox-body--tag__text
'
]
}
>
{
text
}
</
span
>
<
span
>
<
FormOutlined
className=
{
styles
[
'
groupBox-body--tag__edit
'
]
}
onClick=
{
handleEdit
}
/>
</
span
>
<
Popconfirm
title=
"确定删除该分组吗?"
onConfirm=
{
handleClose
}
okText=
"确定"
cancelText=
"取消"
>
<
CloseCircleOutlined
className=
{
styles
[
'
groupBox-body--tag__close
'
]
}
/>
</
Popconfirm
>
</
Tag
>
);
return
(
<>
{
isEdit
&&
inputRender
()
}
{
groupEditRender
()
}
</>
);
};
export
default
DragTag
;
src/pages/GoodsManage/Takeaway/components/GoodsGroup.jsx
0 → 100644
View file @
d72841d4
import
React
,
{
useState
,
useEffect
,
forwardRef
,
useImperativeHandle
}
from
'
react
'
;
import
{
Button
,
Select
,
Tag
}
from
'
antd
'
;
import
{
DndProvider
}
from
'
react-dnd
'
;
import
HTML5Backend
from
'
react-dnd-html5-backend
'
;
import
styles
from
'
../../style.less
'
;
import
DragTag
from
'
./DragTag
'
;
import
InsertTag
from
'
./InsertTag
'
;
import
GroupInfo
from
'
./GroupInfo
'
;
import
{
apiDelStorage
,
apiSortStorage
,
apiStorageList
,
apiSupplierShopList
}
from
'
../../service
'
;
const
GoodsGroup
=
forwardRef
((
options
,
ref
)
=>
{
const
[
groupEdit
,
setGroupEdit
]
=
useState
(
false
);
const
[
selected
,
setSelected
]
=
useState
(
0
);
const
[
storageId
,
setStorageId
]
=
useState
(
0
);
const
[
isModalOpen
,
setIsModalOpen
]
=
useState
(
false
);
const
[
shops
,
setShops
]
=
useState
([]);
const
[
tags
,
setTags
]
=
useState
([]);
const
getShopList
=
async
()
=>
{
const
res
=
await
apiSupplierShopList
({
state
:
1
,
productBusiness
:
1
,
});
if
(
res
&&
res
.
data
&&
res
.
data
.
length
>
0
)
{
setShops
(
res
.
data
.
map
(
item
=>
({
label
:
item
.
name
,
value
:
+
item
.
id
,
})),
);
options
.
changeShop
(
+
res
.
data
[
0
].
id
);
}
else
{
options
.
changeShop
(
0
);
}
};
const
getGroupList
=
async
()
=>
{
if
(
options
.
shopId
)
{
const
res
=
await
apiStorageList
({
shopId
:
options
.
shopId
,
});
if
(
res
&&
res
.
data
&&
res
.
data
.
length
>
0
)
{
const
arr
=
res
.
data
.
sort
((
x
,
y
)
=>
x
.
priority
-
y
.
priority
)
.
map
(
item
=>
({
text
:
item
.
name
,
id
:
item
.
rackId
,
}));
setTags
(
arr
);
setSelected
(
res
.
data
[
0
].
rackId
);
}
else
{
setTags
([]);
setSelected
(
0
);
}
}
else
{
setTags
([]);
setSelected
(
0
);
}
};
const
handleEdit
=
async
id
=>
{
setStorageId
(
id
||
0
);
setIsModalOpen
(
true
);
};
const
handleDelete
=
async
id
=>
{
const
res
=
await
apiDelStorage
({
shopId
:
options
.
shopId
,
id
,
});
if
(
res
.
businessCode
===
'
0000
'
&&
res
.
code
===
'
0000
'
)
{
getGroupList
();
}
};
// 更换位置
const
changePosition
=
async
(
dIndex
,
hIndex
)
=>
{
const
data
=
tags
.
slice
();
const
temp
=
data
[
dIndex
];
// 交换位置
data
[
dIndex
]
=
data
[
hIndex
];
data
[
hIndex
]
=
temp
;
setTags
(
data
);
};
const
endChangePosition
=
async
()
=>
{
const
data
=
tags
.
slice
();
const
storageRankList
=
data
.
map
((
item
,
i
)
=>
({
id
:
item
.
id
,
priority
:
i
+
1
,
}));
const
params
=
{
shopId
:
options
.
shopId
,
storageRankList
,
};
await
apiSortStorage
(
params
);
getGroupList
();
};
const
onSelect
=
i
=>
{
setSelected
(
i
);
};
useEffect
(()
=>
{
if
(
options
.
shopId
)
{
getGroupList
();
}
},
[
options
.
shopId
]);
useEffect
(()
=>
{
getShopList
();
},
[]);
useEffect
(()
=>
{
options
.
changeGroup
(
selected
);
},
[
selected
]);
useImperativeHandle
(
ref
,
()
=>
({
setSelected
,
}));
return
(
<
div
className=
{
styles
.
groupBox
}
>
{
(
shops
&&
shops
.
length
&&
(
<>
<
div
className=
{
styles
[
'
groupBox-title
'
]
}
>
<
div
className=
{
styles
[
'
groupBox-title--name
'
]
}
>
所属门店
</
div
>
<
Select
showSearch
value=
{
options
.
shopId
}
placeholder=
"请选择所属门店"
onChange=
{
options
.
changeShop
}
filterOption=
{
(
input
,
option
)
=>
(
option
?.
label
??
''
).
toLowerCase
().
includes
(
input
.
toLowerCase
())
}
options=
{
shops
}
/>
</
div
>
<
div
className=
{
styles
[
'
groupBox-title
'
]
}
>
<
div
className=
{
styles
[
'
groupBox-title--name
'
]
}
>
商品分组
</
div
>
<
Button
onClick=
{
()
=>
setGroupEdit
(
!
groupEdit
)
}
>
{
groupEdit
?
'
完成
'
:
'
编辑分组
'
}
</
Button
>
</
div
>
<
div
className=
{
styles
[
'
groupBox-body
'
]
}
>
{
groupEdit
?
(
<
DndProvider
backend=
{
HTML5Backend
}
>
<
div
className=
{
styles
[
'
groupBox-body--dragbox
'
]
}
>
{
tags
.
map
((
item
,
index
)
=>
(
<
DragTag
changePosition=
{
changePosition
}
endChangePosition=
{
endChangePosition
}
index=
{
index
}
{
...
item
}
selected=
{
selected
}
edit=
{
handleEdit
}
del=
{
handleDelete
}
key=
{
item
.
id
}
/>
))
}
<
InsertTag
handleOpen=
{
handleEdit
}
/>
</
div
>
</
DndProvider
>
)
:
(
<
div
className=
{
styles
[
'
groupBox-body--dragbox
'
]
}
>
{
tags
.
map
(
item
=>
(
<
Tag
key=
{
item
.
id
}
onClick=
{
()
=>
onSelect
(
item
.
id
)
}
className=
{
[
styles
[
'
groupBox-body--tag-normal
'
],
selected
===
item
.
id
?
styles
[
'
groupBox-body--tag__cur
'
]
:
''
,
]
}
>
<
span
className=
{
styles
[
'
groupBox-body--tag__text
'
]
}
>
{
item
.
text
}
</
span
>
</
Tag
>
))
}
<
InsertTag
key=
"insert"
handleOpen=
{
handleEdit
}
/>
</
div
>
)
}
</
div
>
</>
))
||
''
}
<
GroupInfo
isModalOpen=
{
isModalOpen
}
id=
{
storageId
}
shopId=
{
options
.
shopId
}
search=
{
getGroupList
}
handleClose=
{
setIsModalOpen
}
/>
</
div
>
);
});
export
default
GoodsGroup
;
src/pages/GoodsManage/Takeaway/components/GroupInfo.jsx
0 → 100644
View file @
d72841d4
import
React
,
{
useEffect
,
useState
}
from
'
react
'
;
import
{
Form
,
Modal
,
Input
,
Switch
,
Alert
,
message
}
from
'
antd
'
;
import
{
apiCreateStorage
,
apiEditStorage
,
apiStorageInfo
}
from
'
../../service
'
;
import
{
stringOrObjectTrim
}
from
'
@/utils/utils
'
;
const
GroupInfo
=
options
=>
{
const
[
form
]
=
Form
.
useForm
();
const
[
isChecked
,
setIsChecked
]
=
useState
(
false
);
// 关闭分组信息弹窗
const
handleCancel
=
()
=>
{
options
.
handleClose
(
false
);
};
// 添加/保存分组
const
handleConfirm
=
async
()
=>
{
const
{
name
,
necessary
}
=
await
form
.
validateFields
();
const
api
=
options
.
id
?
apiEditStorage
:
apiCreateStorage
;
const
res
=
await
api
({
name
:
stringOrObjectTrim
(
name
),
necessary
:
necessary
?
1
:
0
,
shopId
:
options
.
shopId
,
id
:
options
.
id
,
});
if
(
res
.
code
===
'
0000
'
&&
res
.
businessCode
===
'
0000
'
)
{
message
.
success
(
'
保存成功!
'
);
handleCancel
();
options
.
search
();
}
};
const
getInfo
=
async
id
=>
{
const
res
=
await
apiStorageInfo
({
shopId
:
options
.
shopId
,
id
,
});
if
(
res
&&
res
.
data
&&
res
.
data
.
id
)
{
const
{
name
,
necessary
}
=
res
.
data
;
setIsChecked
(
+
necessary
===
1
);
form
.
setFieldsValue
({
name
,
necessary
:
+
necessary
===
1
,
});
}
};
useEffect
(()
=>
{
if
(
options
.
id
&&
options
.
isModalOpen
)
{
getInfo
(
options
.
id
);
}
},
[
options
.
id
,
options
.
isModalOpen
]);
const
extra
=
<
Alert
message=
"选中后,顾客下单需至少选择1个“下单必选分组”"
type=
"error"
/>;
return
(
<
Modal
title=
"分组信息"
visible=
{
options
.
isModalOpen
}
destroyOnClose
maskClosable=
{
false
}
width=
"600px"
onOk=
{
handleConfirm
}
onCancel=
{
handleCancel
}
>
<
Form
name=
"basic"
form=
{
form
}
labelCol=
{
{
span
:
6
}
}
wrapperCol=
{
{
span
:
16
}
}
>
<
Form
.
Item
label=
"分组名称"
name=
"name"
rules=
{
[{
required
:
true
,
message
:
'
请输入分组名称!
'
}]
}
>
<
Input
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"下单必选分组"
name=
"necessary"
extra=
{
extra
}
>
<
Switch
checkedChildren=
"开启"
checked=
{
isChecked
}
unCheckedChildren=
"关闭"
onChange=
{
setIsChecked
}
/>
</
Form
.
Item
>
</
Form
>
</
Modal
>
);
};
export
default
GroupInfo
;
src/pages/GoodsManage/Takeaway/components/InsertTag.jsx
0 → 100644
View file @
d72841d4
import
React
from
'
react
'
;
import
{
Tag
}
from
'
antd
'
;
import
{
PlusOutlined
}
from
'
@ant-design/icons
'
;
import
styles
from
'
../../style.less
'
;
const
InsertTag
=
options
=>
{
const
showInput
=
()
=>
{
options
.
handleOpen
();
};
return
(
<
Tag
className=
{
[
styles
[
'
groupBox-body--tag
'
],
styles
[
'
groupBox-body--new
'
]]
}
color=
"blue"
onClick=
{
showInput
}
>
<
PlusOutlined
/>
添加
</
Tag
>
);
};
export
default
InsertTag
;
src/pages/GoodsManage/Takeaway/components/MinimumPurchase.jsx
0 → 100644
View file @
d72841d4
import
React
from
'
react
'
;
import
{
Modal
,
Form
,
InputNumber
}
from
'
antd
'
;
import
styles
from
'
../../style.less
'
;
const
MinimumPurchase
=
options
=>
{
const
[
form
]
=
Form
.
useForm
();
const
handleCancel
=
()
=>
{
options
.
cancel
(
false
);
};
const
handleOk
=
async
()
=>
{
const
values
=
await
form
.
validateFields
();
console
.
log
(
'
values :>>
'
,
values
);
options
.
confirm
({
type
:
5
,
...
values
,
});
};
return
(
<
Modal
visible=
{
options
.
visible
}
title=
"修改最少购买数量"
onOk=
{
handleOk
}
maskClosable=
{
false
}
keyboard=
{
false
}
confirmLoading=
{
options
.
loading
}
destroyOnClose
onCancel=
{
handleCancel
}
>
<
Form
name=
"basic"
form=
{
form
}
labelCol=
{
{
span
:
6
}
}
wrapperCol=
{
{
span
:
16
}
}
initialValues=
{
{
minPurchaseNum
:
1
}
}
autoComplete=
"off"
>
<
Form
.
Item
label=
"最少购买/份"
name=
"minPurchaseNum"
rules=
{
[{
required
:
true
,
message
:
'
请输入最少购买数量!
'
}]
}
>
<
InputNumber
min=
{
1
}
max=
{
999999
}
className=
{
styles
.
inputWdith
}
/>
</
Form
.
Item
>
</
Form
>
</
Modal
>
);
};
export
default
MinimumPurchase
;
src/pages/GoodsManage/Takeaway/components/SendModal.jsx
0 → 100644
View file @
d72841d4
import
React
from
'
react
'
;
import
{
Modal
,
Form
,
Radio
}
from
'
antd
'
;
const
SendModal
=
options
=>
{
const
[
form
]
=
Form
.
useForm
();
const
handleCancel
=
()
=>
{
options
.
cancel
(
false
);
};
const
handleOk
=
async
()
=>
{
const
values
=
await
form
.
validateFields
();
console
.
log
(
'
values :>>
'
,
values
);
options
.
confirm
({
type
:
6
,
...
values
,
});
};
const
radioOptions
=
[{
label
:
'
是
'
,
value
:
1
},
{
label
:
'
否
'
,
value
:
0
}];
const
initialValues
=
Object
.
assign
({},
options
.
initialValues
);
return
(
<
Modal
visible=
{
options
.
visible
}
title=
"设置单点不送"
onOk=
{
handleOk
}
maskClosable=
{
false
}
keyboard=
{
false
}
confirmLoading=
{
options
.
loading
}
destroyOnClose
onCancel=
{
handleCancel
}
>
<
Form
name=
"basic"
form=
{
form
}
labelCol=
{
{
span
:
6
}
}
wrapperCol=
{
{
span
:
16
}
}
initialValues=
{
initialValues
}
autoComplete=
"off"
>
<
Form
.
Item
label=
"单点不送"
name=
"isSingleDelivery"
rules=
{
[{
required
:
true
,
message
:
'
请选择!
'
}]
}
>
<
Radio
.
Group
options=
{
radioOptions
}
/>
</
Form
.
Item
>
</
Form
>
<
div
>
开启后顾客单点这些商品不可下单
</
div
>
</
Modal
>
);
};
export
default
SendModal
;
src/pages/GoodsManage/Takeaway/components/StockModal.jsx
0 → 100644
View file @
d72841d4
import
React
,
{
useState
,
useEffect
}
from
'
react
'
;
import
{
Modal
,
Form
,
InputNumber
,
Checkbox
,
Switch
}
from
'
antd
'
;
import
{
deepClone
}
from
'
@/utils/utils
'
;
import
styles
from
'
../../style.less
'
;
import
{
apiProductStock
}
from
'
../../service
'
;
import
{
isIntegerNotZero
}
from
'
@/utils/validator
'
;
const
StockModal
=
options
=>
{
const
[
stockType
,
setStockType
]
=
useState
(
0
);
const
[
maxStock
,
setMaxStock
]
=
useState
(
0
);
const
[
isChecked
,
setIsChecked
]
=
useState
(
false
);
const
[
form
]
=
Form
.
useForm
();
const
onChangeType
=
v
=>
{
setStockType
(
v
===
stockType
?
0
:
v
);
if
(
v
===
1
)
{
form
.
setFieldsValue
({
productStock
:
0
,
});
}
};
const
onChangeMaxStock
=
value
=>
{
setMaxStock
(
value
);
};
const
handleCancel
=
()
=>
{
options
.
cancel
(
false
);
};
const
handleOk
=
async
()
=>
{
const
values
=
await
form
.
validateFields
();
const
params
=
deepClone
(
values
);
params
.
autoStock
=
values
.
autoStock
?
1
:
0
;
options
.
confirm
({
type
:
7
,
...
params
,
});
};
const
getStockInfo
=
async
()
=>
{
const
res
=
await
apiProductStock
({
skuId
:
options
.
skuIds
[
0
],
shopId
:
options
.
shopId
,
});
if
(
res
&&
res
.
code
===
'
0000
'
&&
res
.
businessCode
===
'
0000
'
)
{
const
info
=
res
.
data
;
form
.
setFieldsValue
({
autoStockStep
:
info
.
autoStockStep
,
productStock
:
info
.
stock
,
autoStock
:
info
.
autoStock
===
1
,
});
setMaxStock
(
info
.
autoStockStep
);
setIsChecked
(
info
.
autoStock
===
1
);
}
};
const
initialValues
=
Object
.
assign
(
{
productStock
:
''
,
autoStockStep
:
''
,
autoStock
:
false
,
},
options
.
initialValues
,
);
useEffect
(()
=>
{
if
(
stockType
===
2
)
{
form
.
setFieldsValue
({
productStock
:
maxStock
,
});
}
},
[
maxStock
,
stockType
]);
useEffect
(()
=>
{
if
(
options
.
visible
)
{
setStockType
(
0
);
setMaxStock
(
0
);
setIsChecked
(
false
);
form
.
resetFields
();
if
(
options
.
skuIds
&&
options
.
skuIds
.
length
===
1
)
{
getStockInfo
();
}
}
},
[
options
.
visible
]);
const
maxStockRule
=
[{
validator
:
isIntegerNotZero
,
message
:
'
请输入大于0的整数
'
}];
if
(
isChecked
||
stockType
===
2
)
{
maxStockRule
.
push
({
required
:
true
,
message
:
'
请输入最大库存!
'
});
}
return
(
<
Modal
visible=
{
options
.
visible
}
title=
"修改库存"
onOk=
{
handleOk
}
maskClosable=
{
false
}
keyboard=
{
false
}
confirmLoading=
{
options
.
loading
}
destroyOnClose
onCancel=
{
handleCancel
}
>
<
Form
name=
"basic"
form=
{
form
}
labelCol=
{
{
span
:
6
}
}
wrapperCol=
{
{
span
:
16
}
}
initialValues=
{
initialValues
}
autoComplete=
"off"
className=
{
styles
[
'
stock-box
'
]
}
>
<
Form
.
Item
label=
"剩余库存"
name=
"productStock"
labelCol=
{
{
span
:
6
}
}
wrapperCol=
{
{
span
:
8
}
}
rules=
{
[
{
required
:
true
,
message
:
'
请输入剩余库存!
'
},
{
validator
:
isIntegerNotZero
,
message
:
'
请输入大于0的整数
'
},
]
}
>
<
InputNumber
min=
{
0
}
max=
{
999999999
}
className=
{
styles
[
'
stock-box--inputnum
'
]
}
disabled=
{
stockType
>
0
}
/>
</
Form
.
Item
>
<
div
className=
{
styles
[
'
stock-box--btns
'
]
}
>
<
Checkbox
checked=
{
stockType
===
1
}
onChange=
{
()
=>
onChangeType
(
1
)
}
>
清零
</
Checkbox
>
<
Checkbox
checked=
{
stockType
===
2
}
onChange=
{
()
=>
onChangeType
(
2
)
}
>
最大
</
Checkbox
>
</
div
>
<
Form
.
Item
label=
"最大库存"
name=
"autoStockStep"
rules=
{
maxStockRule
}
>
<
InputNumber
min=
{
0
}
max=
{
999999999
}
className=
{
styles
[
'
stock-box--inputnum
'
]
}
onChange=
{
onChangeMaxStock
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"自动补足"
name=
"autoStock"
>
<
Switch
checkedChildren=
"开启"
checked=
{
isChecked
}
unCheckedChildren=
"关闭"
onChange=
{
setIsChecked
}
/>
</
Form
.
Item
>
</
Form
>
<
div
className=
{
styles
[
'
stock-box--red
'
]
}
>
修改成功后,原库存将被替换,请谨慎操作
</
div
>
</
Modal
>
);
};
export
default
StockModal
;
src/pages/GoodsManage/Takeaway/components/SwitchGroupModal.jsx
0 → 100644
View file @
d72841d4
import
React
from
'
react
'
;
import
{
Modal
,
Form
,
Select
}
from
'
antd
'
;
const
SwitchGroupModal
=
options
=>
{
const
[
form
]
=
Form
.
useForm
();
const
handleCancel
=
()
=>
{
options
.
cancel
(
false
);
};
const
handleOk
=
async
()
=>
{
const
values
=
await
form
.
validateFields
();
console
.
log
(
'
values :>>
'
,
values
);
options
.
confirm
({
type
:
3
,
...
values
,
});
};
const
radioOptions
=
[{
label
:
'
是
'
,
value
:
1
},
{
label
:
'
否
'
,
value
:
0
}];
const
initialValues
=
Object
.
assign
({},
options
.
initialValues
);
return
(
<
Modal
visible=
{
options
.
visible
}
title=
"更改分组"
onOk=
{
handleOk
}
maskClosable=
{
false
}
keyboard=
{
false
}
confirmLoading=
{
options
.
loading
}
destroyOnClose
onCancel=
{
handleCancel
}
>
<
Form
name=
"basic"
form=
{
form
}
labelCol=
{
{
span
:
6
}
}
wrapperCol=
{
{
span
:
16
}
}
initialValues=
{
initialValues
}
autoComplete=
"off"
>
<
Form
.
Item
label=
"分组"
name=
"storageRackId"
rules=
{
[{
required
:
true
,
message
:
'
请选择!
'
}]
}
>
<
Select
options=
{
radioOptions
}
/>
</
Form
.
Item
>
</
Form
>
</
Modal
>
);
};
export
default
SwitchGroupModal
;
src/pages/GoodsManage/Takeaway/components/WeekTime.jsx
0 → 100644
View file @
d72841d4
import
React
,
{
useState
,
useEffect
}
from
'
react
'
;
import
{
Modal
,
Radio
,
Form
,
TimePicker
,
Checkbox
}
from
'
antd
'
;
import
{
MinusSquareOutlined
,
PlusSquareOutlined
}
from
'
@ant-design/icons
'
;
import
moment
from
'
moment
'
;
import
{
deepClone
}
from
'
@/utils/utils
'
;
import
{
saleWeeks
}
from
'
../../staticdata
'
;
import
styles
from
'
../../style.less
'
;
const
WeekTime
=
options
=>
{
const
[
form
]
=
Form
.
useForm
();
const
[
type
,
setType
]
=
useState
(
0
);
const
formItemLayout
=
{
labelCol
:
{
xs
:
{
span
:
24
},
sm
:
{
span
:
6
},
},
wrapperCol
:
{
xs
:
{
span
:
24
},
sm
:
{
span
:
16
},
},
};
const
formItemLayoutWithOutLabel
=
{
wrapperCol
:
{
xs
:
{
span
:
22
,
offset
:
0
},
sm
:
{
span
:
16
,
offset
:
6
},
},
};
const
onChangeType
=
({
target
:
{
value
}
})
=>
{
setType
(
value
);
};
const
radioOptions
=
[{
label
:
'
全时段
'
,
value
:
0
},
{
label
:
'
自定义售卖时间
'
,
value
:
1
}];
const
handleCancel
=
()
=>
{
options
.
cancel
(
false
);
};
const
handleOk
=
async
()
=>
{
const
params
=
await
form
.
validateFields
();
// const params = values;
if
(
params
.
saleTimes
&&
params
.
saleTimes
.
length
)
{
params
.
saleTimes
=
params
.
saleTimes
.
map
(
item
=>
({
startTime
:
moment
(
item
[
0
]).
format
(
'
HH:mm
'
),
endTime
:
moment
(
item
[
1
]).
format
(
'
HH:mm
'
),
}));
}
options
.
confirm
({
type
:
4
,
...
params
,
});
};
const
onTimeValidator
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
&&
value
.
length
===
2
)
{
if
(
moment
(
value
[
0
]).
format
(
'
HH:mm
'
)
===
moment
(
value
[
1
]).
format
(
'
HH:mm
'
))
{
callback
(
new
Error
(
'
请输入大于0的数字
'
));
}
else
{
callback
();
}
}
else
{
callback
();
}
};
const
initialValues
=
Object
.
assign
(
{
saleTimeType
:
0
,
saleDates
:
[],
saleTimes
:
[[]],
},
options
.
initialValues
,
);
useEffect
(()
=>
{
options
.
visible
&&
setType
(
0
);
},
[
options
.
visible
]);
return
(
<
Modal
visible=
{
options
.
visible
}
title=
"售卖时间"
onOk=
{
handleOk
}
confirmLoading=
{
options
.
loading
}
maskClosable=
{
false
}
keyboard=
{
false
}
destroyOnClose
onCancel=
{
handleCancel
}
>
<
Form
name=
"basic"
form=
{
form
}
labelCol=
{
{
span
:
6
}
}
wrapperCol=
{
{
span
:
16
}
}
initialValues=
{
initialValues
}
autoComplete=
"off"
>
<
Form
.
Item
label=
"售卖时间段类型"
name=
"saleTimeType"
rules=
{
[{
required
:
true
,
message
:
'
请选择售卖时间段类型!
'
}]
}
>
<
Radio
.
Group
options=
{
radioOptions
}
onChange=
{
onChangeType
}
value=
{
type
}
optionType=
"button"
buttonStyle=
"solid"
/>
</
Form
.
Item
>
{
type
===
1
?
(
<>
<
Form
.
Item
label=
"售卖日期"
name=
"saleDates"
rules=
{
[{
required
:
true
,
message
:
'
请选择售卖日期!
'
}]
}
>
<
Checkbox
.
Group
options=
{
saleWeeks
}
/>
</
Form
.
Item
>
<
Form
.
List
label=
"售卖时间"
name=
"saleTimes"
rules=
{
[
{
validator
:
async
(
_
,
saleTimes
)
=>
{
if
(
!
saleTimes
||
saleTimes
.
length
<
1
)
{
return
Promise
.
reject
(
new
Error
(
'
请选择售卖时间!
'
));
}
return
Promise
.
resolve
();
},
},
]
}
>
{
(
fields
,
{
add
,
remove
})
=>
(
<>
{
fields
.
map
((
field
,
index
)
=>
(
<
Form
.
Item
label=
{
index
===
0
?
'
售卖日期
'
:
''
}
{
...
(
index
===
0
?
formItemLayout
:
formItemLayoutWithOutLabel
)}
required
key=
{
field
.
key
}
>
<
Form
.
Item
{
...
field
}
validateTrigger=
{
[
'
onChange
'
,
'
onBlur
'
]
}
rules=
{
[
{
required
:
true
,
message
:
'
请选择售卖时间
'
,
},
{
validator
:
onTimeValidator
,
message
:
'
结束时间不能和开始时间相同
'
,
},
]
}
noStyle
>
<
TimePicker
.
RangePicker
format=
"HH:mm"
minuteStep=
{
30
}
/>
</
Form
.
Item
>
{
index
>
0
?
(
<
MinusSquareOutlined
className=
{
[
styles
[
'
week-time-box--icon
'
],
styles
.
error
]
}
onClick=
{
()
=>
remove
(
field
.
name
)
}
/>
)
:
(
<
PlusSquareOutlined
className=
{
[
styles
[
'
week-time-box--icon
'
],
styles
.
primary
]
}
onClick=
{
()
=>
add
()
}
/>
)
}
</
Form
.
Item
>
))
}
</>
)
}
</
Form
.
List
>
</>
)
:
(
''
)
}
</
Form
>
</
Modal
>
);
};
export
default
WeekTime
;
src/pages/GoodsManage/Takeaway/index.jsx
0 → 100644
View file @
d72841d4
import
React
,
{
useState
,
useEffect
,
useRef
}
from
'
react
'
;
import
{
Spin
,
Table
,
Pagination
,
message
,
notification
}
from
'
antd
'
;
import
{
unstable_batchedUpdates
}
from
'
react-dom
'
;
import
{
SortableContainer
,
SortableElement
,
SortableHandle
}
from
'
react-sortable-hoc
'
;
import
{
arrayMoveImmutable
}
from
'
array-move
'
;
import
{
GOOD_MANAGE
}
from
'
@/../config/permission.config
'
;
import
PubSub
from
'
pubsub-js
'
;
import
GoodsGroup
from
'
./components/GoodsGroup
'
;
import
{
apiTakeawayGoods
,
apiGoodsActionBatch
,
apiSortTakeawayGoods
,
apiTopTakeawayGoods
,
}
from
'
../service
'
;
import
styles
from
'
../style.less
'
;
import
{
takeawayColumn
}
from
'
../staticdata
'
;
// import VirtualTable from './components/VirtualTable';
import
ActionBar
from
'
./components/ActionBar
'
;
import
WeekTime
from
'
./components/WeekTime
'
;
import
StockModal
from
'
./components/StockModal
'
;
import
SendModal
from
'
./components/SendModal
'
;
import
MinimumPurchaseModal
from
'
./components/MinimumPurchase
'
;
import
SwitchGroupModal
from
'
./components/SwitchGroupModal
'
;
const
Takeaway
=
options
=>
{
const
[
tableData
,
setTableData
]
=
useState
([]);
const
[
selectedRowKeys
,
setSelectedRowKeys
]
=
useState
([]);
const
[
shopId
,
setShopId
]
=
useState
(
0
);
const
[
groupId
,
setGroupId
]
=
useState
(
0
);
const
[
pageNo
,
setPageNo
]
=
useState
(
1
);
const
[
pageSize
,
setPageSize
]
=
useState
(
50
);
const
[
total
,
setTotal
]
=
useState
(
0
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
actionLoading
,
setActionLoading
]
=
useState
(
false
);
const
[
visibleWeekTime
,
setVisibleWeekTime
]
=
useState
(
false
);
const
[
visibleStock
,
setVisibleStock
]
=
useState
(
false
);
const
[
visibleBuy
,
setVisibleBuy
]
=
useState
(
false
);
const
[
visibleSend
,
setVisibleSend
]
=
useState
(
false
);
const
[
visibleSwitchGroup
,
setVisibleSwitchGroup
]
=
useState
(
false
);
const
[
scribeToken
,
setScribeToken
]
=
useState
(
''
);
const
groupRef
=
useRef
(
null
);
const
rowSelection
=
{
selectedRowKeys
,
onChange
:
setSelectedRowKeys
,
};
const
getDataList
=
async
(
page
=
pageNo
,
size
=
pageSize
,
storageRackId
=
groupId
)
=>
{
setLoading
(
true
);
const
params
=
Object
.
assign
({},
options
.
searchValue
,
{
pageNo
:
page
||
pageNo
,
productType
:
5
,
pageSize
:
size
||
pageSize
,
storageRackId
,
});
const
productCategoryId
=
options
.
searchValue
?.
productCategoryId
||
[];
params
.
productCategoryId
=
(
productCategoryId
.
length
&&
productCategoryId
[
productCategoryId
.
length
-
1
])
||
''
;
const
res
=
await
apiTakeawayGoods
(
params
);
setLoading
(
false
);
if
(
res
&&
res
.
data
)
{
setTableData
(
res
.
data
.
records
);
setTotal
(
res
.
data
.
total
);
}
};
const
onPageChange
=
(
page
,
size
)
=>
{
unstable_batchedUpdates
(()
=>
{
setPageNo
(
page
);
setPageSize
(
size
);
});
getDataList
(
page
,
size
);
};
const
onSortEnd
=
async
({
oldIndex
,
newIndex
})
=>
{
if
(
oldIndex
!==
newIndex
)
{
const
newData
=
arrayMoveImmutable
(
tableData
.
slice
(),
oldIndex
,
newIndex
).
filter
(
el
=>
!!
el
);
const
skuSorts
=
newData
.
map
((
item
,
index
)
=>
({
skuId
:
item
.
skuId
,
sort
:
pageSize
*
(
pageNo
-
1
)
+
index
+
1
,
}));
const
params
=
{
storageRackId
:
groupId
,
type
:
1
,
shopId
,
skuSorts
,
};
await
apiSortTakeawayGoods
(
params
);
getDataList
(
pageNo
,
pageSize
);
// setTableData(newData);
}
};
const
SortableItem
=
SortableElement
(
props
=>
<
tr
{
...
props
}
/>);
const
SortableBody
=
SortableContainer
(
props
=>
<
tbody
{
...
props
}
/>);
const
DraggableContainer
=
props
=>
(
<
SortableBody
useDragHandle
disableAutoscroll
helperClass=
{
styles
[
'
row-dragging
'
]
}
onSortEnd=
{
onSortEnd
}
{
...
props
}
/>
);
const
DraggableBodyRow
=
({
className
,
style
,
...
restProps
})
=>
{
// function findIndex base on Table rowKey props and should always be a right array index
const
index
=
tableData
.
findIndex
(
x
=>
x
.
skuId
===
restProps
[
'
data-row-key
'
]);
return
<
SortableItem
index=
{
index
}
{
...
restProps
}
/>;
};
// 批量操作 type 1-是否列出 2-修改上下架 3-改货架 4-售卖时间更新 5-调整商品起购数量 6-调整商品是否单点不送 7-修改库存
const
handleBatchAction
=
async
params
=>
{
const
json
=
{
skuIds
:
selectedRowKeys
,
shopId
,
};
setActionLoading
(
true
);
const
res
=
await
apiGoodsActionBatch
(
Object
.
assign
({},
json
,
params
));
setActionLoading
(
false
);
if
(
res
.
businessCode
===
'
0000
'
&&
res
.
code
===
'
0000
'
)
{
message
.
success
(
'
处理成功!
'
);
unstable_batchedUpdates
(()
=>
{
setActionLoading
(
false
);
setVisibleWeekTime
(
false
);
setVisibleStock
(
false
);
setVisibleSwitchGroup
(
false
);
setVisibleBuy
(
false
);
setVisibleSend
(
false
);
});
getDataList
(
pageNo
,
pageSize
);
}
};
// 显示弹窗
const
openModal
=
type
=>
{
type
===
'
time
'
&&
setVisibleWeekTime
(
true
);
type
===
'
stock
'
&&
setVisibleStock
(
true
);
type
===
'
group
'
&&
setVisibleSwitchGroup
(
true
);
type
===
'
buy
'
&&
setVisibleBuy
(
true
);
type
===
'
send
'
&&
setVisibleSend
(
true
);
};
// 单商品修改库存
const
onShowStockModal
=
({
skuId
})
=>
{
setSelectedRowKeys
([
skuId
]);
openModal
(
'
stock
'
);
};
// 编辑
const
onEdit
=
({
spuId
,
skuId
})
=>
{
options
.
handleEdit
({
shopId
,
spuId
,
skuId
,
});
};
// 新建商品
const
onNew
=
()
=>
{
options
.
handleEdit
({
shopId
,
groupId
,
});
};
// 置顶
const
toTop
=
async
({
skuId
})
=>
{
// onSortEnd({ oldIndex, newIndex: 0 });
const
res
=
await
apiTopTakeawayGoods
({
productItemId
:
skuId
,
shopId
,
storageRackId
:
groupId
,
});
if
(
res
.
businessCode
===
'
0000
'
&&
res
.
code
===
'
0000
'
)
{
getDataList
(
pageNo
,
pageSize
);
message
.
success
(
'
处理成功!
'
);
}
};
useEffect
(()
=>
{
if
(
groupId
)
{
setPageNo
(
1
);
getDataList
(
1
,
pageSize
);
}
else
{
setTableData
([]);
}
},
[
groupId
,
options
.
refresh
]);
useEffect
(()
=>
{
const
stoken
=
PubSub
.
subscribe
(
'
refreshTakeAway
'
,
(
_
,
data
)
=>
{
console
.
log
(
'
refreshTakeAway :>>
'
,
data
);
if
(
data
.
groupId
&&
groupId
!==
data
.
groupId
)
{
setGroupId
(
data
.
groupId
);
if
(
groupRef
.
current
)
{
groupRef
.
current
.
setSelected
(
`
${
data
.
groupId
}
`
);
}
}
});
setScribeToken
(
stoken
);
return
()
=>
{
PubSub
.
unsubscribe
(
scribeToken
);
};
},
[]);
const
actions
=
{
onShowStockModal
,
toTop
,
onEdit
,
getDataList
,
shopId
,
pageNo
,
};
const
canAddTakeaway
=
options
.
permissions
[
GOOD_MANAGE
.
ADD_TAKEAWAY_GOODS
];
return
(
<
div
className=
{
styles
.
takeawayBox
}
>
<
Spin
spinning=
{
loading
}
>
<
GoodsGroup
ref=
{
groupRef
}
shopId=
{
shopId
}
changeShop=
{
setShopId
}
changeGroup=
{
setGroupId
}
/>
{
(
shopId
&&
(
<
ActionBar
selectedRowKeys=
{
selectedRowKeys
}
shopId=
{
shopId
}
canAddTakeaway=
{
canAddTakeaway
}
handleSearch=
{
getDataList
}
openModal=
{
openModal
}
newGoods=
{
onNew
}
/>
))
||
''
}
<
Table
dataSource=
{
tableData
}
bordered
columns=
{
takeawayColumn
(
actions
)
}
rowKey=
{
record
=>
record
.
skuId
}
pagination=
{
false
}
scroll=
{
{
x
:
'
100%
'
,
y
:
500
}
}
rowSelection=
{
rowSelection
}
components=
{
{
body
:
{
wrapper
:
DraggableContainer
,
row
:
DraggableBodyRow
,
},
}
}
/>
<
br
/>
{
(
tableData
&&
(
<
Pagination
className=
{
styles
[
'
takeawayBox--page
'
]
}
onChange=
{
onPageChange
}
total=
{
total
}
showTotal=
{
o
=>
`共${o}条`
}
current=
{
pageNo
}
pageSize=
{
pageSize
}
showSizeChanger
onShowSizeChange=
{
onPageChange
}
/>
))
||
''
}
</
Spin
>
<
WeekTime
visible=
{
visibleWeekTime
}
loading=
{
actionLoading
}
confirm=
{
handleBatchAction
}
cancel=
{
setVisibleWeekTime
}
/>
<
StockModal
visible=
{
visibleStock
}
loading=
{
actionLoading
}
skuIds=
{
selectedRowKeys
}
shopId=
{
shopId
}
confirm=
{
handleBatchAction
}
cancel=
{
setVisibleStock
}
/>
<
SendModal
visible=
{
visibleSend
}
loading=
{
actionLoading
}
confirm=
{
handleBatchAction
}
cancel=
{
setVisibleSend
}
/>
<
MinimumPurchaseModal
visible=
{
visibleBuy
}
loading=
{
actionLoading
}
confirm=
{
handleBatchAction
}
cancel=
{
setVisibleBuy
}
/>
<
SwitchGroupModal
visible=
{
visibleSwitchGroup
}
loading=
{
actionLoading
}
confirm=
{
handleBatchAction
}
cancel=
{
setVisibleSwitchGroup
}
/>
</
div
>
);
};
export
default
Takeaway
;
src/pages/GoodsManage/index.jsx
View file @
d72841d4
...
@@ -12,6 +12,7 @@ import UpdateStock from './UpdateStock';
...
@@ -12,6 +12,7 @@ import UpdateStock from './UpdateStock';
import
{
import
{
spuDetail
,
spuDetail
,
categoryList
,
categoryList
,
apiCategoryListType
,
getVirtualCategory
,
getVirtualCategory
,
getTemplateList
,
getTemplateList
,
specList
,
specList
,
...
@@ -26,6 +27,7 @@ import TempleatModal from './TempleatModal';
...
@@ -26,6 +27,7 @@ import TempleatModal from './TempleatModal';
import
ServiceGoods
from
'
../ServiceGoods
'
;
import
ServiceGoods
from
'
../ServiceGoods
'
;
import
InfoAudit
from
'
./infoAudit
'
;
import
InfoAudit
from
'
./infoAudit
'
;
import
DraftModal
from
'
./DraftModal
'
;
import
DraftModal
from
'
./DraftModal
'
;
import
Takeaway
from
'
./Takeaway
'
;
import
{
GOOD_MANAGE
}
from
'
@/../config/permission.config
'
;
import
{
GOOD_MANAGE
}
from
'
@/../config/permission.config
'
;
...
@@ -38,6 +40,7 @@ class goodsManage extends Component {
...
@@ -38,6 +40,7 @@ class goodsManage extends Component {
pageNo
:
1
,
pageNo
:
1
,
loading
:
false
,
loading
:
false
,
treeData
:
[],
treeData
:
[],
categoryTree
:
[],
virtualTreeData
:
[],
virtualTreeData
:
[],
pageSize
:
20
,
pageSize
:
20
,
priceInfo
:
{},
priceInfo
:
{},
...
@@ -59,6 +62,10 @@ class goodsManage extends Component {
...
@@ -59,6 +62,10 @@ class goodsManage extends Component {
auditRow
:
{},
// 查看审核信息使用
auditRow
:
{},
// 查看审核信息使用
isVisibleDraft
:
false
,
// 显示隐藏草稿箱
isVisibleDraft
:
false
,
// 显示隐藏草稿箱
isEditDraft
:
false
,
// 是否编辑草稿
isEditDraft
:
false
,
// 是否编辑草稿
productType
:
1
,
// 商品类型
takeAway
:
{},
// 弹窗外卖商品参数
searchValue
:
{},
// 搜索条件
refresh
:
''
,
// 外卖刷新
};
};
currentLog
=
null
;
currentLog
=
null
;
...
@@ -71,36 +78,46 @@ class goodsManage extends Component {
...
@@ -71,36 +78,46 @@ class goodsManage extends Component {
componentDidMount
()
{
componentDidMount
()
{
this
.
props
.
goodsManage
.
tableData
=
{};
this
.
props
.
goodsManage
.
tableData
=
{};
this
.
categoryList
();
this
.
categoryList
(
this
.
state
.
productType
);
this
.
categoryListByType
(
this
.
state
.
productType
);
this
.
getVirtualCategory
();
this
.
getVirtualCategory
();
this
.
specList
();
this
.
specList
();
}
}
handleSearch
=
page
=>
{
handleSearch
=
page
=>
{
this
.
onSelectChange
([]);
const
searchValue
=
this
.
searchForm
.
getFieldsValue
()
||
{};
const
currentPage
=
this
.
state
.
pageNo
;
this
.
setState
({
searchValue
});
this
.
setState
(
if
(
searchValue
.
productType
!==
5
)
{
{
this
.
onSelectChange
([]);
pageNo
:
page
||
currentPage
,
const
currentPage
=
this
.
state
.
pageNo
;
loading
:
true
,
this
.
setState
(
},
{
()
=>
{
pageNo
:
page
||
currentPage
,
const
{
dispatch
}
=
this
.
props
;
loading
:
true
,
const
{
pageSize
,
pageNo
}
=
this
.
state
;
},
dispatch
({
()
=>
{
type
:
'
goodsManage/getList
'
,
const
{
dispatch
}
=
this
.
props
;
payload
:
{
const
{
pageSize
,
pageNo
}
=
this
.
state
;
pageNo
,
dispatch
({
pageSize
,
type
:
'
goodsManage/getList
'
,
...
this
.
searchForm
.
getFieldsValue
(),
payload
:
{
},
pageNo
,
}).
finally
(()
=>
{
pageSize
,
this
.
setState
({
...
searchValue
,
loading
:
false
,
},
}).
finally
(()
=>
{
this
.
setState
({
loading
:
false
,
});
});
});
});
},
},
);
);
}
else
{
this
.
setState
({
refresh
:
new
Date
().
getTime
(),
searchValue
,
});
}
};
};
onPageChange
=
page
=>
{
onPageChange
=
page
=>
{
...
@@ -267,7 +284,7 @@ class goodsManage extends Component {
...
@@ -267,7 +284,7 @@ class goodsManage extends Component {
categoryList
=
async
()
=>
{
categoryList
=
async
()
=>
{
try
{
try
{
const
{
data
:
treeData
}
=
await
categoryList
();
const
{
data
:
treeData
}
=
await
categoryList
(
{}
);
if
(
!
treeData
)
return
;
if
(
!
treeData
)
return
;
this
.
setState
({
treeData
});
this
.
setState
({
treeData
});
}
catch
(
e
)
{
}
catch
(
e
)
{
...
@@ -275,6 +292,26 @@ class goodsManage extends Component {
...
@@ -275,6 +292,26 @@ class goodsManage extends Component {
}
}
};
};
categoryListByType
=
async
type
=>
{
try
{
const
{
data
:
categoryTree
}
=
await
apiCategoryListType
(
type
);
if
(
!
categoryTree
)
return
;
this
.
setState
({
categoryTree
});
}
catch
(
e
)
{
console
.
log
(
e
);
}
};
changeProductType
=
e
=>
{
this
.
setState
({
productType
:
e
||
1
,
});
this
.
categoryListByType
(
e
);
if
(
e
!==
5
)
{
this
.
handleSearch
(
1
);
}
};
getVirtualCategory
=
async
()
=>
{
getVirtualCategory
=
async
()
=>
{
try
{
try
{
const
{
data
:
virtualTreeData
}
=
await
getVirtualCategory
();
const
{
data
:
virtualTreeData
}
=
await
getVirtualCategory
();
...
@@ -336,6 +373,7 @@ class goodsManage extends Component {
...
@@ -336,6 +373,7 @@ class goodsManage extends Component {
serviceVisble
:
flag
,
serviceVisble
:
flag
,
isEditDraft
:
false
,
isEditDraft
:
false
,
serviceData
:
{},
serviceData
:
{},
takeAway
:
{},
});
});
if
(
refresh
)
{
if
(
refresh
)
{
this
.
handleSearch
();
this
.
handleSearch
();
...
@@ -355,6 +393,14 @@ class goodsManage extends Component {
...
@@ -355,6 +393,14 @@ class goodsManage extends Component {
this
.
serviceVisbleChange
(
this
.
state
.
auditRow
);
this
.
serviceVisbleChange
(
this
.
state
.
auditRow
);
};
};
// 显示外卖商品弹窗
handleTakeawayEdit
=
params
=>
{
this
.
setState
({
takeAway
:
params
,
serviceVisble
:
true
,
});
};
render
()
{
render
()
{
const
{
const
{
goodsManage
:
{
tableData
=
{}
},
goodsManage
:
{
tableData
=
{}
},
...
@@ -368,10 +414,18 @@ class goodsManage extends Component {
...
@@ -368,10 +414,18 @@ class goodsManage extends Component {
const
canAddService
=
permissions
[
GOOD_MANAGE
.
ADD_SERVICE_GOODS
];
const
canAddService
=
permissions
[
GOOD_MANAGE
.
ADD_SERVICE_GOODS
];
const
canAddNormal
=
permissions
[
GOOD_MANAGE
.
ADD_NORMAL_GOODS
];
const
canAddNormal
=
permissions
[
GOOD_MANAGE
.
ADD_NORMAL_GOODS
];
const
canAddTakeaway
=
permissions
[
GOOD_MANAGE
.
ADD_TAKEAWAY_GOODS
];
this
.
canEditable
=
permissions
[
GOOD_MANAGE
.
EDITABLE
];
this
.
canEditable
=
permissions
[
GOOD_MANAGE
.
EDITABLE
];
// console.log('serviceData', this.state.serviceData);
// console.log('shopList', this.shopList);
// console.log('treeData', this.state.treeData);
// console.log('treeData', this.state.treeData);
// console.log('treeData', this.state.treeData);
// console.log('3333333', permissions);
return
(
return
(
<
PageHeaderWrapper
>
<
PageHeaderWrapper
>
{
canAddNormal
||
canAddService
{
canAddNormal
||
canAddService
||
canAddTakeaway
?
[
?
[
<
Button
<
Button
type=
"primary"
type=
"primary"
...
@@ -400,98 +454,112 @@ class goodsManage extends Component {
...
@@ -400,98 +454,112 @@ class goodsManage extends Component {
onRef=
{
ref
=>
{
onRef=
{
ref
=>
{
this
.
searchForm
=
ref
;
this
.
searchForm
=
ref
;
}
}
}
}
treeData=
{
this
.
state
.
treeData
}
treeData=
{
this
.
state
.
categoryTree
}
shopList=
{
this
.
shopList
}
shopList=
{
this
.
shopList
}
checkStock=
{
this
.
checkEnableUpdateStock
}
checkStock=
{
this
.
checkEnableUpdateStock
}
selectNum=
{
selectedRowKeys
.
length
}
selectNum=
{
selectedRowKeys
.
length
}
changeProductType=
{
this
.
changeProductType
}
setArea=
{
(
isALL
,
type
)
=>
this
.
setArea
(
isALL
,
type
)
}
setArea=
{
(
isALL
,
type
)
=>
this
.
setArea
(
isALL
,
type
)
}
/>
/>
</
Card
>
</
Card
>
<
Spin
spinning=
{
this
.
state
.
loading
}
>
{
this
.
state
.
productType
===
5
?
(
<
Table
<
Takeaway
dataSource=
{
tableData
?.
records
}
handleEdit=
{
this
.
handleTakeawayEdit
}
bordered
searchValue=
{
this
.
state
.
searchValue
}
columns=
{
column
.
call
(
this
)
}
rowKey=
{
record
=>
record
.
skuId
}
pagination=
{
false
}
className=
{
styles
.
tabletop
}
scroll=
{
{
x
:
'
100%
'
,
y
:
500
}
}
rowSelection=
{
rowSelection
}
/>
</
Spin
>
<
br
/>
{
tableData
&&
(
<
Pagination
style=
{
{
marginBottom
:
10
}
}
onChange=
{
this
.
onPageChange
}
total=
{
tableData
.
total
}
showTotal=
{
total
=>
`共${total}条`
}
current=
{
pageNo
}
pageSize=
{
pageSize
}
showSizeChanger
onShowSizeChange=
{
this
.
onPageSizeChange
}
/>
)
}
<
LogModal
visible=
{
this
.
state
.
logVisible
}
spuId=
{
this
.
currentLog
?.
spuId
}
id=
{
this
.
currentLog
?.
skuId
}
onCancel=
{
()
=>
{
this
.
currentLog
=
null
;
this
.
setState
({
logVisible
:
false
});
}
}
/>
<
Drawer
visible=
{
this
.
state
.
previewVisible
}
width=
"450"
onClose=
{
()
=>
{
this
.
setState
({
previewVisible
:
false
});
}
}
title=
"商品预览"
bodyStyle=
{
{
height
:
'
90%
'
}
}
>
<
iframe
src=
{
this
.
state
.
src
}
frameBorder=
"0"
height=
"100%"
width=
"375"
title=
"商品预览"
></
iframe
>
</
Drawer
>
<
UpdateStock
visible=
{
this
.
state
.
updateStockVisible
}
skuIds=
{
this
.
state
.
stockSkuIds
}
info=
{
this
.
state
.
priceInfo
}
onCancel=
{
this
.
cancel
}
/>
<
TempleatModal
visible=
{
this
.
state
.
templeatModalVisible
}
selectedRowKeys=
{
this
.
state
.
selectedRowKeys
}
total=
{
tableData
.
total
||
0
}
onCancel=
{
()
=>
{
this
.
setState
({
templeatModalVisible
:
false
,
selectedRowKeys
:
[]
});
this
.
handleSearch
();
}
}
isALL=
{
this
.
state
.
isAll
}
isType=
{
this
.
state
.
isType
}
templateList=
{
this
.
state
.
templateList
}
/>
{
this
.
state
.
serviceVisble
&&
(
<
ServiceGoods
visible=
{
this
.
state
.
serviceVisble
}
onChange=
{
this
.
serviceVisbleClose
}
SourceData=
{
this
.
state
.
serviceData
}
shopList=
{
this
.
shopList
}
categoryList=
{
this
.
state
.
treeData
}
virtualCategoryList=
{
this
.
state
.
virtualTreeData
}
specListData=
{
this
.
state
.
specListData
}
permissions=
{
permissions
}
permissions=
{
permissions
}
isDraft=
{
this
.
state
.
isEditDraft
}
refresh=
{
this
.
state
.
refresh
}
/>
/>
)
:
(
<>
<
Spin
spinning=
{
this
.
state
.
loading
}
>
<
Table
dataSource=
{
tableData
?.
records
}
bordered
columns=
{
column
.
call
(
this
)
}
rowKey=
{
record
=>
record
.
skuId
}
pagination=
{
false
}
className=
{
styles
.
tabletop
}
scroll=
{
{
x
:
'
100%
'
,
y
:
500
}
}
rowSelection=
{
rowSelection
}
/>
</
Spin
>
<
br
/>
{
tableData
&&
(
<
Pagination
style=
{
{
marginBottom
:
10
}
}
onChange=
{
this
.
onPageChange
}
total=
{
tableData
.
total
}
showTotal=
{
total
=>
`共${total}条`
}
current=
{
pageNo
}
pageSize=
{
pageSize
}
showSizeChanger
onShowSizeChange=
{
this
.
onPageSizeChange
}
/>
)
}
<
LogModal
visible=
{
this
.
state
.
logVisible
}
spuId=
{
this
.
currentLog
?.
spuId
}
id=
{
this
.
currentLog
?.
skuId
}
onCancel=
{
()
=>
{
this
.
currentLog
=
null
;
this
.
setState
({
logVisible
:
false
});
}
}
/>
<
Drawer
visible=
{
this
.
state
.
previewVisible
}
width=
"450"
onClose=
{
()
=>
{
this
.
setState
({
previewVisible
:
false
});
}
}
title=
"商品预览"
bodyStyle=
{
{
height
:
'
90%
'
}
}
>
<
iframe
src=
{
this
.
state
.
src
}
frameBorder=
"0"
height=
"100%"
width=
"375"
title=
"商品预览"
></
iframe
>
</
Drawer
>
<
UpdateStock
visible=
{
this
.
state
.
updateStockVisible
}
skuIds=
{
this
.
state
.
stockSkuIds
}
info=
{
this
.
state
.
priceInfo
}
onCancel=
{
this
.
cancel
}
/>
<
TempleatModal
visible=
{
this
.
state
.
templeatModalVisible
}
selectedRowKeys=
{
this
.
state
.
selectedRowKeys
}
total=
{
tableData
.
total
||
0
}
onCancel=
{
()
=>
{
this
.
setState
({
templeatModalVisible
:
false
,
selectedRowKeys
:
[]
});
this
.
handleSearch
();
}
}
isALL=
{
this
.
state
.
isAll
}
isType=
{
this
.
state
.
isType
}
templateList=
{
this
.
state
.
templateList
}
/>
</>
)
}
)
}
</
Spin
>
</
Spin
>
{
this
.
state
.
serviceVisble
&&
(
<
ServiceGoods
visible=
{
this
.
state
.
serviceVisble
}
onChange=
{
this
.
serviceVisbleClose
}
SourceData=
{
this
.
state
.
serviceData
}
shopList=
{
this
.
shopList
}
categoryList=
{
this
.
state
.
treeData
}
virtualCategoryList=
{
this
.
state
.
virtualTreeData
}
specListData=
{
this
.
state
.
specListData
}
permissions=
{
permissions
}
isDraft=
{
this
.
state
.
isEditDraft
}
productType=
{
this
.
state
.
productType
}
takeAway=
{
this
.
state
.
takeAway
}
/>
)
}
{
this
.
state
.
visibleAuditModal
&&
(
{
this
.
state
.
visibleAuditModal
&&
(
<
InfoAudit
<
InfoAudit
visible=
{
this
.
state
.
visibleAuditModal
}
visible=
{
this
.
state
.
visibleAuditModal
}
...
...
src/pages/GoodsManage/service.js
View file @
d72841d4
...
@@ -89,7 +89,7 @@ export async function categoryList() {
...
@@ -89,7 +89,7 @@ export async function categoryList() {
}
}
/**
/**
* 商品分类
* 商品分类
* type 商品类型:1-实物类,2-虚拟类,4-服务类
* type 商品类型:1-实物类,2-虚拟类,4-服务类
5 外卖
* */
* */
export
async
function
apiCategoryListType
(
type
)
{
export
async
function
apiCategoryListType
(
type
)
{
return
request
.
get
(
`/product/category/getByProductType/
${
type
}
`
,
{
return
request
.
get
(
`/product/category/getByProductType/
${
type
}
`
,
{
...
@@ -289,3 +289,91 @@ export async function apiDraftList(data) {
...
@@ -289,3 +289,91 @@ export async function apiDraftList(data) {
data
,
data
,
});
});
}
}
// 批量操作
export
async
function
apiGoodsActionBatch
(
data
)
{
return
request
.
post
(
'
/api/merchants/products/sku/batchOperation
'
,
{
prefix
:
goodsApi
,
data
,
});
}
// 外卖商品列表
export
async
function
apiTakeawayGoods
(
params
)
{
return
request
.
post
(
'
/product/api/merchant/page
'
,
{
prefix
:
goodsApi
,
data
:
stringify
(
params
),
headers
,
});
}
// 外卖商品排序
export
async
function
apiSortTakeawayGoods
(
data
)
{
return
request
.
post
(
'
/api/merchants/products/sku/batchSort
'
,
{
prefix
:
goodsApi
,
data
,
});
}
// 外卖商品置顶
export
async
function
apiTopTakeawayGoods
(
data
)
{
return
request
.
post
(
'
/api/merchants/products/sku/storageRack/topping
'
,
{
prefix
:
goodsApi
,
data
,
});
}
// 获取供应商门店列表
export
async
function
apiSupplierShopList
(
params
)
{
return
request
.
get
(
`/api/merchants/shops/getBySupplierId?
${
stringify
(
params
)}
`
,
{
prefix
:
goodsApi
,
});
}
// 分组创建(货架—创建货架)
export
async
function
apiCreateStorage
(
data
)
{
return
request
.
post
(
'
/api/merchants/products/storageRack/create
'
,
{
prefix
:
goodsApi
,
data
,
});
}
// 编辑分组(货架—编辑货架)
export
async
function
apiEditStorage
(
data
)
{
return
request
.
post
(
'
/api/merchants/products/storageRack/edit
'
,
{
prefix
:
goodsApi
,
data
,
});
}
// 分组详情(货架—货架详情)
export
async
function
apiStorageInfo
(
params
)
{
return
request
.
post
(
'
/api/merchants/products/storageRack/QueryByShopIdAndStorageRackId
'
,
{
prefix
:
goodsApi
,
data
:
stringify
(
params
),
headers
,
});
}
// 删除分组(货架—删除货架)
export
async
function
apiDelStorage
(
params
)
{
return
request
.
post
(
'
/api/merchants/products/storageRack/removeByShopIdAndId
'
,
{
prefix
:
goodsApi
,
data
:
stringify
(
params
),
headers
,
});
}
// 分组排序(货架—排序货架)
export
async
function
apiSortStorage
(
data
)
{
return
request
.
post
(
'
/api/merchants/products/storageRack/batchSort
'
,
{
prefix
:
goodsApi
,
data
,
});
}
// 分组列表(货架—货架列表)
export
async
function
apiStorageList
(
params
)
{
return
request
.
post
(
'
/api/merchants/products/storageRack/listByShopIdAndStorageRackIds
'
,
{
prefix
:
goodsApi
,
data
:
stringify
(
params
),
headers
,
});
}
// 获取库存信息
export
async
function
apiProductStock
(
data
)
{
return
request
.
get
(
'
/api/merchants/products/sku/getStockInfo
'
,
{
prefix
:
goodsApi
,
params
:
data
,
});
}
src/pages/GoodsManage/staticdata.js
View file @
d72841d4
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
{
Button
,
Badge
,
Switch
,
Modal
}
from
'
antd
'
;
import
{
Button
,
Badge
,
Switch
,
Modal
,
message
}
from
'
antd
'
;
import
{
ExclamationCircleOutlined
}
from
'
@ant-design/icons
'
;
import
{
SortableHandle
}
from
'
react-sortable-hoc
'
;
import
{
ExclamationCircleOutlined
,
MenuOutlined
}
from
'
@ant-design/icons
'
;
import
styles
from
'
./style.less
'
;
import
styles
from
'
./style.less
'
;
import
{
resetTime
}
from
'
../../utils/utils
'
;
import
{
resetTime
}
from
'
../../utils/utils
'
;
import
{
apiChangeStateGoods
,
api
QueryLastAuditRecord
}
from
'
./service
'
;
import
{
apiChangeStateGoods
,
api
GoodsActionBatch
}
from
'
./service
'
;
const
{
confirm
}
=
Modal
;
const
{
confirm
}
=
Modal
;
export
const
NormalProduct
=
1
;
export
const
ServiceProduct
=
4
;
export
const
TakeawayProduct
=
5
;
export
const
GoodTypes
=
{
[
NormalProduct
]:
'
实体商品
'
,
[
ServiceProduct
]:
'
服务类商品
'
,
[
TakeawayProduct
]:
'
外卖商品
'
,
};
export
const
productType
=
[
export
const
productType
=
[
{
{
value
:
1
,
value
:
1
,
...
@@ -244,6 +254,190 @@ export function column() {
...
@@ -244,6 +254,190 @@ export function column() {
},
},
];
];
}
}
export
function
takeawayColumn
(
actions
)
{
const
onChangeState
=
async
({
skuId
,
state
})
=>
{
confirm
({
icon
:
<
ExclamationCircleOutlined
/>
,
content
:
`确认
${
+
state
===
6
?
'
下架
'
:
'
上架
'
}
商品?`
,
onOk
:
async
()
=>
{
const
res
=
await
apiGoodsActionBatch
({
skuIds
:
[
skuId
],
shopId
:
actions
.
shopId
,
productStatus
:
+
state
===
6
?
0
:
1
,
// 6:上架,7:下架
type
:
2
,
});
if
(
res
.
businessCode
===
'
0000
'
&&
res
.
code
===
'
0000
'
)
{
actions
.
getDataList
();
message
.
success
(
'
处理成功!
'
);
}
},
});
};
const
DragHandle
=
SortableHandle
(()
=>
(
<
MenuOutlined
style
=
{{
cursor
:
'
grab
'
,
color
:
'
#999
'
}}
/
>
));
return
[
{
title
:
'
排序
'
,
dataIndex
:
'
sort
'
,
align
:
'
center
'
,
width
:
70
,
className
:
[
styles
[
'
drag-visible
'
]],
render
:
()
=>
<
DragHandle
/>
,
},
{
title
:
'
SKU编码
'
,
dataIndex
:
'
skuId
'
,
width
:
180
,
align
:
'
center
'
,
},
{
title
:
'
SKU商品名称
'
,
// width: 200,
align
:
'
center
'
,
dataIndex
:
'
skuName
'
,
},
{
title
:
'
售卖价格(元)
'
,
dataIndex
:
'
salePrice
'
,
width
:
150
,
align
:
'
center
'
,
},
{
title
:
'
库存
'
,
width
:
120
,
dataIndex
:
'
stock
'
,
align
:
'
center
'
,
},
{
title
:
'
上下架状态
'
,
dataIndex
:
'
stateDesc
'
,
// 5:未上架 ,6 :上架,7:下架
width
:
200
,
align
:
'
center
'
,
},
{
title
:
'
操作
'
,
dataIndex
:
'
action
'
,
width
:
400
,
align
:
'
center
'
,
render
:
(
_
,
row
,
index
)
=>
(
<
div
className
=
{
styles
.
actionBtn
}
>
{(
row
.
state
===
4
||
(
row
.
state
>=
5
&&
row
.
updateState
!==
1
))
&&
(
<
Button
key
=
"
edit
"
type
=
"
primary
"
className
=
{
styles
.
button
}
onClick
=
{()
=>
actions
.
onEdit
(
row
)}
>
编辑
<
/Button
>
)}
<
Button
key
=
"
viewP
"
type
=
"
primary
"
className
=
{
styles
.
button
}
onClick
=
{()
=>
onChangeState
(
row
)}
>
{
+
row
.
state
===
6
?
'
下架
'
:
'
上架
'
}
<
/Button
>
<
Button
key
=
"
log
"
type
=
"
primary
"
className
=
{
styles
.
button
}
onClick
=
{()
=>
actions
.
onShowStockModal
(
row
)}
>
修改库存
<
/Button
>
{(
index
>
0
||
actions
.
pageNo
>
1
)
&&
(
<
Button
key
=
"
top
"
className
=
{
styles
.
button
}
onClick
=
{()
=>
actions
.
toTop
(
row
)}
>
置顶
<
/Button
>
)}
<
/div
>
),
},
];
}
// 外卖商品批量操作
export
const
batchAction
=
event
=>
[
{
key
:
'
up
'
,
type
:
'
2
'
,
label
:
(
<
a
type
=
"
text
"
onClick
=
{()
=>
event
.
onChangeState
(
'
up
'
)}
>
上架
<
/a
>
),
},
{
key
:
'
down
'
,
type
:
'
2
'
,
label
:
(
<
a
type
=
"
text
"
onClick
=
{()
=>
event
.
onChangeState
(
'
down
'
)}
>
下架
<
/a
>
),
},
{
key
:
'
stock
'
,
type
:
'
7
'
,
label
:
(
<
a
type
=
"
text
"
onClick
=
{()
=>
event
.
onChangeState
(
'
stock
'
)}
>
修改库存
<
/a
>
),
},
{
key
:
'
time
'
,
type
:
'
4
'
,
label
:
(
<
a
type
=
"
text
"
onClick
=
{()
=>
event
.
onChangeState
(
'
time
'
)}
>
修改可售时间
<
/a
>
),
},
// {
// key: 'group',
// type: '3',
// label: (
// <a type="text" onClick={() => event.onChangeState('group')}>
// 修改分组
// </a>
// ),
// },
{
key
:
'
send
'
,
type
:
'
6
'
,
label
:
(
<
a
type
=
"
text
"
onClick
=
{()
=>
event
.
onChangeState
(
'
send
'
)}
>
设置单点不送
<
/a
>
),
},
{
key
:
'
buy
'
,
type
:
'
5
'
,
label
:
(
<
a
type
=
"
text
"
onClick
=
{()
=>
event
.
onChangeState
(
'
buy
'
)}
>
修改最少购买数量
<
/a
>
),
},
];
// 外卖商品可售星期
export
const
saleWeeks
=
[
{
label
:
'
周一
'
,
value
:
1
},
{
label
:
'
周二
'
,
value
:
2
},
{
label
:
'
周三
'
,
value
:
3
},
{
label
:
'
周四
'
,
value
:
4
},
{
label
:
'
周五
'
,
value
:
5
},
{
label
:
'
周六
'
,
value
:
6
},
{
label
:
'
周日
'
,
value
:
7
},
];
export
const
disSelectStatus
=
[
2
,
5
];
export
const
disSelectStatus
=
[
2
,
5
];
export
const
stateList
=
[
export
const
stateList
=
[
{
value
:
3
,
label
:
'
待审核
'
},
{
value
:
3
,
label
:
'
待审核
'
},
...
...
src/pages/GoodsManage/style.less
View file @
d72841d4
...
@@ -54,8 +54,14 @@
...
@@ -54,8 +54,14 @@
.searchForm {
.searchForm {
:global {
:global {
.ant-form-item-label {
.ant-form-item-label {
line-height:
40
px;
line-height:
32
px;
}
}
.ant-form-item {
margin-bottom: 12px;
}
}
.button {
margin: 1px 5px;
}
}
}
}
.queryBtn {
.queryBtn {
...
@@ -63,7 +69,7 @@
...
@@ -63,7 +69,7 @@
}
}
.actionBtn {
.actionBtn {
button {
button {
width: 75px;
min-
width: 75px;
}
}
}
}
.pagination {
.pagination {
...
@@ -130,3 +136,158 @@
...
@@ -130,3 +136,158 @@
text-align: left;
text-align: left;
word-break: break-all;
word-break: break-all;
}
}
.takeawayBox {
margin-top: 20px;
padding-bottom: 20px;
background-color: #fff;
&--page {
padding-top: 10px;
padding-left: 30px;
text-align: left;
}
}
.groupBox {
padding: 0 24px 15px 24px;
&-title {
display: flex;
align-items: center;
padding: 10px 0;
font-size: 18px;
&--name {
margin-right: 15px;
}
}
&-body {
padding: 5px 0;
&--tag {
position: relative;
box-sizing: border-box;
height: 34px;
margin-right: 20px;
padding: 0 15px 0 10px;
font-size: 14px;
line-height: 32px;
&__move {
cursor: move;
}
&__edit {
margin-left: 5px;
color: #1890ff;
cursor: pointer;
}
&__close {
position: absolute;
top: 0;
right: 0;
color: #1890ff;
font-size: 16px;
transform: translate(50%, -50%);
cursor: pointer;
}
&__text {
user-select: none;
}
}
&--tag-normal {
position: relative;
height: 34px;
margin-right: 0;
padding: 0 20px;
font-size: 14px;
line-height: 32px;
cursor: pointer;
}
&--tag-input {
width: 80px;
height: 26px;
margin-right: 20px;
}
&--tag__cur {
color: #fff;
background-color: #1890ff;
border: 1px solid #1890ff;
}
&--new {
height: 34px;
margin-right: 0 !important;
margin-left: 10px;
padding: 0 15px;
line-height: 32px;
cursor: pointer;
}
&--dragbox {
padding: 0;
}
}
}
.row-dragging {
background: #fafafa;
border: 1px solid #ccc;
& td {
padding: 16px;
}
}
.drag-visible {
visibility: visible;
}
.td-center {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 0 10px;
word-break: break-all;
}
// .virtual-table {
// table-layout: auto !important;
// table {
// table-layout: auto !important;
// }
// }
.action-bar-box {
padding: 0 0 15px 24px;
&--down {
margin-left: 10px;
}
}
.week-time-box {
&--icon {
position: relative;
top: 4px;
margin: 0 8px;
color: #999;
font-size: 24px;
cursor: pointer;
transition: all 0.3s;
:hover {
box-shadow: 0 0 4px #ccc;
}
}
}
.primary {
color: #1890ff;
}
.error {
color: #ff4d4f;
}
.stock-box {
position: relative;
&--btns {
position: absolute;
top: 0;
right: 0;
height: 32px;
padding-right: 8%;
line-height: 32px;
}
&--red {
color: #ff1616;
}
&--inputnum {
width: 100%;
}
}
.inputWdith {
width: 100%;
}
src/pages/ServiceGoods/common.less
View file @
d72841d4
...
@@ -28,7 +28,17 @@
...
@@ -28,7 +28,17 @@
content: '';
content: '';
}
}
}
}
.week {
background: #f0f0f0;
}
.weekCon {
display: flex;
flex-flow: row nowrap;
color: #319bfe;
}
.weekText {
margin-right: 10px;
}
.prodcutContent {
.prodcutContent {
display: flex;
display: flex;
padding-bottom: 10px;
padding-bottom: 10px;
...
@@ -186,3 +196,152 @@
...
@@ -186,3 +196,152 @@
color: #0e75fd;
color: #0e75fd;
cursor: pointer;
cursor: pointer;
}
}
.required {
:global {
.ant-form-item-label > {
::before {
display: inline-block;
margin-right: 4px;
color: #ff4d4f;
font-size: 14px;
font-family: SimSun, sans-serif;
line-height: 1;
content: '*';
}
}
.ant-form-item {
margin-bottom: 0;
}
.ant-form-item-control-input-content {
display: flex;
}
.ant-form-text {
display: flex;
align-items: center;
justify-content: center;
}
}
}
.itemInline {
:global {
.ant-form-item-control-input-content {
display: flex;
}
.ant-form-item {
margin-bottom: 0;
margin-left: 40px;
}
}
}
.itemInlineModal {
:global {
.ant-form-item-control-input-content {
display: flex;
}
.ant-form-item {
margin-bottom: 0;
}
}
}
.textStyle {
color: red;
}
.multiSpecification {
display: flex;
flex-flow: row wrap;
:global {
.ant-form-item-control {
flex-direction: none;
}
.ant-form-item-control-input-content {
flex: none;
}
}
}
.specsSingularBetween {
display: flex;
align-items: center;
justify-content: flex-start;
width: max-content;
:global {
.ant-form-item-label {
overflow: inherit;
}
.ant-col-sm-3 {
max-width: fit-content;
}
}
}
.specsBetween {
display: flex;
justify-content: flex-end;
:global {
.ant-form-item-label {
overflow: inherit;
}
.ant-col-sm-3 {
max-width: fit-content;
}
}
}
.specRepertory {
height: 20px;
margin: 0 10px;
padding: 0 8px;
color: #fff;
line-height: 20px;
text-align: center;
background-color: #319bfe;
border-radius: 8px;
}
.repertoryLimit {
height: 20px;
color: #fff;
line-height: 20px;
text-align: center;
background-color: #88c0f5;
border-radius: 3px;
}
.deal {
:global {
.ant-form-item-control-input-content {
display: flex;
align-items: center;
}
.ant-form-item {
margin-bottom: 0;
}
}
}
.conBg {
width: fit-content;
min-width: 100%;
background: #f8f8f8;
:global {
.ant-input {
margin: 10px 0;
}
.ant-form-item {
margin-bottom: 8px;
}
}
}
.nameWidth {
width: 300px;
}
.colRow {
display: flex;
flex: none;
max-width: none;
}
.rowWarp {
display: flex;
flex-direction: column;
background: #f8f8f8;
}
:global {
.reactEasyCrop_Container {
height: 550px !important;
}
}
src/pages/ServiceGoods/components/AddMenusModal.jsx
0 → 100644
View file @
d72841d4
import
React
,
{
useState
,
useEffect
,
forwardRef
,
useRef
,
useImperativeHandle
}
from
'
react
'
;
import
{
Button
,
Modal
,
Form
,
Switch
,
Input
,
Select
}
from
'
antd
'
;
import
styles
from
'
../common.less
'
;
import
{
apiCreateShop
}
from
'
../service
'
;
const
AddMenusModal
=
(
props
,
ref
)
=>
{
const
[
confirmLoading
,
setConfirmLoading
]
=
useState
(
false
);
const
[
open
,
setOpen
]
=
useState
(
false
);
const
[
formProject
]
=
Form
.
useForm
();
const
[
menusSwitch
,
setMenusSwitch
]
=
useState
(
0
);
// 分组开启状态
// const {
// queryShopList,
// } = props;
useImperativeHandle
(
ref
,
()
=>
({
// changeVal 就是暴露给父组件的方法
setOpen
:
newVal
=>
{
setOpen
(
newVal
);
},
}));
const
handleOk
=
()
=>
{
formProject
.
validateFields
()
.
then
(
async
values
=>
{
console
.
log
(
'
valuse
'
,
values
,
menusSwitch
);
const
params
=
{
name
:
values
?.
name
,
necessary
:
menusSwitch
,
};
const
data
=
await
apiCreateShop
(
params
);
if
(
data
.
code
===
'
0000
'
)
{
formProject
.
resetFields
();
// 表单清除历史
setConfirmLoading
(
true
);
setTimeout
(()
=>
{
setOpen
(
false
);
setConfirmLoading
(
false
);
},
2000
);
}
})
.
catch
(
info
=>
{
// queryShopList()
console
.
log
(
'
保存异常
'
,
info
);
});
};
const
handleCancel
=
()
=>
{
console
.
log
(
'
Clicked cancel button
'
);
setOpen
(
false
);
};
const
onChange
=
()
=>
{
if
(
menusSwitch
===
0
)
{
setMenusSwitch
(
1
);
return
false
;
}
setMenusSwitch
(
0
);
return
false
;
};
useEffect
(()
=>
{
console
.
log
(
'
open
'
,
open
);
},
[
open
]);
return
(
<>
{
open
&&
(
<
Modal
title=
"添加分组"
visible=
{
open
}
onOk=
{
handleOk
}
confirmLoading=
{
confirmLoading
}
initialValues=
{
{
menusSwitch
:
0
,
}
}
onCancel=
{
handleCancel
}
>
<
Form
form=
{
formProject
}
>
<
Form
.
Item
label=
"Select"
>
<
Select
>
<
Select
.
Option
value=
"shopId"
>
Demo
</
Select
.
Option
>
</
Select
>
</
Form
.
Item
>
<
Form
.
Item
label=
"分组名称"
name=
"name"
rules=
{
[{
required
:
true
}]
}
>
<
Input
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"下单必选分组"
name=
"necessary"
valuePropName=
{
menusSwitch
}
>
<
Switch
defaultChecked=
{
menusSwitch
}
checkedChildren=
"开启"
unCheckedChildren=
"关闭"
onChange=
{
onChange
}
/>
<
div
className=
{
styles
.
textStyle
}
>
选中后,顾客下单需至少选择1个 “下单必须分组” 商品
</
div
>
<
div
className=
{
styles
.
textStyle
}
>
每店仅可设置1个必点分组
</
div
>
</
Form
.
Item
>
</
Form
>
</
Modal
>
)
}
</>
);
};
export
default
forwardRef
(
AddMenusModal
);
src/pages/ServiceGoods/components/AddMultiSpecModal.jsx
0 → 100644
View file @
d72841d4
// import React, { useState, useEffect, forwardRef, useRef, useImperativeHandle } from 'react';
// import { Button, Modal, Radio, Space, Form, InputNumber, Switch, Input } from 'antd';
// import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
// import styles from '../common.less';
// import { ENUM_SET_REPERTORY } from '../config';
// const AddMultiSpecModal = (props, ref) => {
// const [confirmLoading, setConfirmLoading] = useState(false);
// const [modalText, setModalText] = useState('Content of the modal');
// const [multiRepertory, setMultiRepertory] = useState(false);
// // const {
// // open,
// // setOpen,
// // } = props;
// useImperativeHandle(ref, () => ({
// // changeVal 就是暴露给父组件的方法
// setMultiRepertory: newVal => {
// setMultiRepertory(newVal);
// },
// }));
// const onChange3 = () => {};
// const handleOk = () => {
// setModalText('The modal will be closed after two seconds');
// setConfirmLoading(true);
// setTimeout(() => {
// setMultiRepertory(false);
// setConfirmLoading(false);
// }, 2000);
// };
// const handleCancel = () => {
// console.log('Clicked cancel button');
// setMultiRepertory(false);
// };
// useEffect(() => {
// console.log('open', multiRepertory);
// }, [multiRepertory]);
// return (
// <>
// {multiRepertory && (
// <Modal
// title="修改库存"
// visible={multiRepertory}
// onOk={handleOk}
// width={1050}
// confirmLoading={confirmLoading}
// onCancel={handleCancel}
// >
// <Form>
// <Form.Item>
// <div>份量(如大小/小份、微辣/特辣等)</div>
// <Form.List name="users">
// {(fields, { add, remove }) => (
// <>
// {fields.map(({ key, name, ...restField }) => (
// <Space
// key={key}
// style={{
// display: 'flex',
// flexDirection: 'column',
// marginBottom: 8,
// }}
// align="baseline"
// >
// <Form.Item className={styles.deal}>
// <Form.Item
// {...restField}
// name={[name, 'first']}
// rules={[
// {
// required: true,
// message: 'Missing first name',
// },
// ]}
// >
// <Input placeholder="名称" />
// </Form.Item>
// <Form.Item
// {...restField}
// name={[name, 'last']}
// rules={[
// {
// required: true,
// message: 'Missing last name',
// },
// ]}
// >
// <Input placeholder="约 份量(数字)" />
// </Form.Item>
// <Form.Item
// {...restField}
// name={[name, 'last']}
// rules={[
// {
// required: true,
// message: 'Missing last name',
// },
// ]}
// >
// <Input placeholder="约 份量(数字)" />
// </Form.Item>
// <Form.Item
// {...restField}
// name={[name, 'last']}
// rules={[
// {
// required: true,
// message: 'Missing last name',
// },
// ]}
// >
// <Input placeholder="销售价(元)" />
// </Form.Item>
// <Form.Item
// {...restField}
// name={[name, 'last']}
// rules={[
// {
// required: true,
// message: 'Missing last name',
// },
// ]}
// >
// <Input placeholder="活动价(元)" />
// </Form.Item>
// <MinusCircleOutlined onClick={() => remove(name)} />
// </Form.Item>
// <Form.Item>
// <Form.Item>
// <div>添加规格(如加料、甜度、辣度等)</div>
// <Form.Item>
// <Form.List name="names">
// {(fields, { add, remove }, { errors }) => (
// <>
// {fields.map((field, index) => (
// <Form.Item
// // {...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)}
// // label={index === 0 ? 'Passengers' : ''}
// required={false}
// key={field.key}
// >
// <Form.Item
// {...field}
// validateTrigger={['onChange', 'onBlur']}
// className={styles.deal}
// rules={[
// {
// required: true,
// whitespace: true,
// message:
// "Please input passenger's name or delete this field.",
// },
// ]}
// >
// <Input
// placeholder="规格名称"
// className={styles.nameWidth}
// />
// {fields.length > 1 ? (
// <MinusCircleOutlined
// className="dynamic-delete-button"
// onClick={() => remove(field.name)}
// />
// ) : null}
// </Form.Item>
// <Form.Item>
// <Form.List name="sights">
// {(fields, { add, remove }) => (
// <>
// {fields.map(field => (
// <Space key={field.key} align="baseline">
// <Form.Item
// noStyle
// shouldUpdate={(prevValues, curValues) =>
// prevValues.area !== curValues.area ||
// prevValues.sights !== curValues.sights
// }
// >
// {() => (
// <Form.Item
// {...field}
// // label="Sight"
// name={[field.name, 'sight']}
// rules={[
// {
// required: true,
// message: 'Missing sight',
// },
// ]}
// >
// <Input style={{ width: '200px' }} placeholder="加价名称" />
// </Form.Item>
// )}
// </Form.Item>
// <Form.Item
// {...field}
// // label="Price"
// // name={[field.name, 'price']}
// rules={[
// {
// required: true,
// message: 'Missing price',
// },
// ]}
// >
// <InputNumber style={{ width: '200px' }} placeholder="加价名称金额(元)" />
// </Form.Item>
// <MinusCircleOutlined
// onClick={() => remove(field.name)}
// />
// </Space>
// ))}
// <Form.Item>
// <Button
// type="dashed"
// onClick={() => add()}
// block
// icon={<PlusOutlined />}
// >
// 新增加价
// </Button>
// </Form.Item>
// </>
// )}
// </Form.List>
// </Form.Item>
// </Form.Item>
// ))}
// <Form.Item>
// <Button
// type="dashed"
// onClick={() => add()}
// style={{ width: '60%' }}
// icon={<PlusOutlined />}
// >
// 新增规格
// </Button>
// </Form.Item>
// </>
// )}
// </Form.List>
// </Form.Item>
// </Form.Item>
// </Form.Item>
// </Space>
// ))}
// <Form.Item>
// <Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
// 新增份量
// </Button>
// </Form.Item>
// </>
// )}
// </Form.List>
// </Form.Item>
// </Form>
// </Modal>
// )}
// </>
// );
// };
// export default forwardRef(AddMultiSpecModal);
src/pages/ServiceGoods/components/AddRepertoryModal.jsx
0 → 100644
View file @
d72841d4
import
React
,
{
useState
,
useEffect
,
forwardRef
,
useRef
,
useImperativeHandle
}
from
'
react
'
;
import
{
Button
,
Modal
,
Radio
,
Form
,
InputNumber
,
Switch
,
Space
,
message
}
from
'
antd
'
;
import
styles
from
'
../common.less
'
;
import
{
ENUM_SET_REPERTORY
}
from
'
../config
'
;
import
{
debounce
}
from
'
@/utils/utils
'
;
import
{
isCheckPriceTwoDecimal
,
isIntegerNotZero
}
from
'
@/utils/validator
'
;
const
AddRepertoryModal
=
(
props
,
ref
)
=>
{
const
[
confirmLoading
,
setConfirmLoading
]
=
useState
(
false
);
const
[
openRepertory
,
setOpenRepertory
]
=
useState
(
false
);
const
[
form
]
=
Form
.
useForm
();
const
[
repertoryState
,
setRepertoryState
]
=
useState
(
''
);
const
[
initialValues
,
setInitialValues
]
=
useState
({
productStock
:
0
,
maxStock
:
0
,
autoStock
:
false
,
});
const
[
isRequired
,
setIsRequired
]
=
useState
(
true
);
const
{
modifiedInventory
,
intactData
,
repertoryModel
}
=
props
;
const
{
type
,
idx
,
item
}
=
repertoryModel
;
useImperativeHandle
(
ref
,
()
=>
({
// changeVal 就是暴露给父组件的方法
setOpenRepertory
:
newVal
=>
{
setOpenRepertory
(
newVal
);
},
}));
// 自动补全
const
onChangeAutoStock
=
e
=>
{
form
.
setFieldsValue
({
autoStock
:
e
?
1
:
0
,
});
setIsRequired
(
!
e
);
};
// 勾选库存设置
const
onChangeSetRepertory
=
e
=>
{
setRepertoryState
(
`
${
e
.
target
.
value
}
`
);
if
(
+
e
.
target
.
value
===
0
)
{
form
.
setFieldsValue
({
productStock
:
0
,
});
}
else
{
const
{
maxStock
}
=
form
.
getFieldsValue
([
'
maxStock
'
]);
form
.
setFieldsValue
({
productStock
:
maxStock
,
});
}
};
// 最大库存设置
const
onChangeMaxStock
=
e
=>
{
// 已经勾选最大库存 自动更新剩余库存
if
(
+
repertoryState
===
1
)
{
form
.
setFieldsValue
({
productStock
:
e
,
});
}
};
const
getFormValues
=
debounce
(()
=>
{
const
values
=
form
.
getFieldsValue
();
},
400
);
const
handleOk
=
async
()
=>
{
const
values
=
await
form
.
validateFields
();
values
.
autoStock
=
values
.
autoStock
?
1
:
0
;
if
(
+
values
.
autoStock
===
1
&&
+
values
.
maxStock
===
0
)
{
message
.
error
(
'
最大库存不能为0
'
);
return
;
}
// 回调库存
modifiedInventory
(
type
,
idx
,
values
);
setConfirmLoading
(
true
);
setTimeout
(()
=>
{
setOpenRepertory
(
false
);
setConfirmLoading
(
false
);
},
1000
);
};
const
handleCancel
=
()
=>
{
setOpenRepertory
(
false
);
};
useEffect
(()
=>
{
if
(
item
?.
serviceItem
)
{
const
{
productStock
=
1
,
autoStock
=
0
,
maxStock
=
2
}
=
item
?.
serviceItem
;
const
params
=
{
productStock
,
autoStock
:
+
autoStock
===
1
,
maxStock
,
};
switch
(
type
)
{
case
'
all
'
:
// 统一设置
form
.
setFieldsValue
(
params
);
break
;
case
'
multi
'
:
// 多规格设置
form
.
setFieldsValue
(
params
);
break
;
case
'
singular
'
:
// 单规格设置
// setInitialValues(params);
form
.
setFieldsValue
(
params
);
break
;
default
:
break
;
}
}
},
[
openRepertory
,
item
]);
return
(
<>
{
openRepertory
&&
(
<
Modal
title=
"修改库存"
visible=
{
openRepertory
}
onOk=
{
handleOk
}
confirmLoading=
{
confirmLoading
}
onCancel=
{
handleCancel
}
>
<
Form
form=
{
form
}
initialValues=
{
initialValues
}
onValuesChange=
{
getFormValues
}
>
<
Space
>
<
Form
.
Item
className=
{
styles
.
itemInlineModal
}
>
<
Form
.
Item
name=
"productStock"
label=
"剩余库存"
style=
{
{
display
:
'
flex
'
,
marginRight
:
'
8px
'
,
}
}
rules=
{
[
{
required
:
true
,
message
:
'
请填写剩余库存
'
},
{
validator
:
isIntegerNotZero
,
type
:
'
number
'
,
message
:
'
请输入大于0的整数
'
,
},
]
}
>
<
InputNumber
min=
{
0
}
max=
{
999999999
}
style=
{
{
width
:
200
,
display
:
'
inline-block
'
}
}
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
Form
.
Item
style=
{
{
width
:
200
,
display
:
'
inline-block
'
}
}
>
<
Radio
.
Group
value=
{
repertoryState
}
onChange=
{
onChangeSetRepertory
}
>
<
Radio
.
Button
value=
"0"
>
清空
</
Radio
.
Button
>
<
Radio
.
Button
value=
"1"
>
最大
</
Radio
.
Button
>
</
Radio
.
Group
>
</
Form
.
Item
>
</
Form
.
Item
>
</
Space
>
<
Form
.
Item
name=
"maxStock"
label=
"最大库存"
rules=
{
[
{
required
:
!
isRequired
,
message
:
'
请填写最大库存
'
},
{
validator
:
isIntegerNotZero
,
type
:
'
number
'
,
message
:
'
请输入大于0的整数
'
,
},
]
}
>
<
InputNumber
min=
{
0
}
max=
{
999999999
}
style=
{
{
width
:
200
}
}
placeholder=
"请输入"
onChange=
{
onChangeMaxStock
}
/>
</
Form
.
Item
>
<
Form
.
Item
name=
"autoStock"
label=
"自动补足"
valuePropName=
"checked"
>
<
Switch
checkedChildren=
"开启"
unCheckedChildren=
"关闭"
// defaultChecked
onChange=
{
onChangeAutoStock
}
/>
</
Form
.
Item
>
</
Form
>
<
div
className=
{
styles
.
textStyle
}
>
修改成功后,原库存将被替换,请谨慎操作!
</
div
>
</
Modal
>
)
}
</>
);
};
export
default
forwardRef
(
AddRepertoryModal
);
src/pages/ServiceGoods/components/AddSellTimeModal.jsx
0 → 100644
View file @
d72841d4
import
React
,
{
useState
,
useEffect
,
forwardRef
,
useRef
,
useImperativeHandle
}
from
'
react
'
;
import
{
Button
,
Modal
,
Form
,
Checkbox
,
Row
,
Col
,
time
,
DatePicker
}
from
'
antd
'
;
import
{
map
}
from
'
lodash
'
;
import
{
MinusCircleOutlined
,
PlusOutlined
}
from
'
@ant-design/icons
'
;
import
moment
from
'
moment
'
;
import
{
ENUM_WEEK
}
from
'
../config
'
;
import
styles
from
'
../common.less
'
;
const
format
=
'
HH:mm
'
;
const
{
RangePicker
}
=
DatePicker
;
const
AddSellTimeModal
=
(
props
,
ref
)
=>
{
const
[
confirmLoading
,
setConfirmLoading
]
=
useState
(
false
);
const
[
modalText
,
setModalText
]
=
useState
(
'
Content of the modal
'
);
const
[
formProject
]
=
Form
.
useForm
();
const
[
open
,
setOpen
]
=
useState
(
false
);
const
{
saleDates
,
setSaleDates
}
=
props
;
useImperativeHandle
(
ref
,
()
=>
({
// changeVal 就是暴露给父组件的方法
setOpen
:
newVal
=>
{
setOpen
(
newVal
);
},
}));
const
handleOk
=
()
=>
{
formProject
.
validateFields
().
then
(
async
values
=>
{
console
.
log
(
'
valuse
'
,
values
);
setConfirmLoading
(
true
);
setSaleDates
(
values
);
setTimeout
(()
=>
{
setOpen
(
false
);
setConfirmLoading
(
false
);
},
1000
);
});
};
const
handleCancel
=
()
=>
{
console
.
log
(
'
Clicked cancel button
'
);
setOpen
(
false
);
};
useEffect
(()
=>
{
console
.
log
(
'
open
'
,
open
);
// formProject.setFieldsValue({ saleTimes: [['12:00', '13:00']] })
},
[
open
]);
const
onChange
=
()
=>
{};
return
(
<>
{
open
&&
(
<
Modal
title=
"售卖时段"
visible=
{
open
}
onOk=
{
handleOk
}
confirmLoading=
{
confirmLoading
}
onCancel=
{
handleCancel
}
width=
{
1050
}
>
<
Form
name=
"sellTime"
form=
{
formProject
}
//
{
...
formItemLayout
}
// onFinish=
{
onFinish
}
initialValues=
{
saleDates
}
>
<
Form
.
Item
name=
"unavailableDate"
label=
"售卖时期(可多选)"
>
<
Checkbox
.
Group
>
<
Row
>
<
Col
className=
{
styles
.
colRow
}
span=
{
8
}
>
{
ENUM_WEEK
.
map
((
item
,
index
)
=>
(
<
Checkbox
value=
{
item
.
value
}
>
{
item
.
label
}
</
Checkbox
>
))
}
</
Col
>
</
Row
>
</
Checkbox
.
Group
>
</
Form
.
Item
>
<
Form
.
Item
label=
"售卖时段"
>
<
Form
.
List
name=
"saleTimes"
initialValue=
{
[[]]
}
// rules=
{[
//
{
// validator: async (_, times) =>
{
// if (!times || times.length < 2)
{
// return Promise.reject(new Error('At least 2 passengers'));
//
}
//
},
//
},
// ]
}
>
{
(
fields
,
{
add
,
remove
})
=>
(
<>
{
fields
.
map
((
field
,
index
)
=>
(
<
Form
.
Item
//
{
...
(
index
===
0
?
formItemLayout
:
formItemLayoutWithOutLabel
)}
required=
{
false
}
key=
{
field
.
key
}
className=
{
styles
.
deal
}
>
<
Form
.
Item
className=
{
styles
.
deal
}
{
...
field
}
// validateTrigger=
{['
onChange
',
'
onBlur
']}
rules=
{
[
{
required
:
true
,
message
:
'
请输入售卖时间
'
,
},
]
}
>
<
RangePicker
picker=
"time"
format=
{
format
}
onChange=
{
onChange
}
/>
</
Form
.
Item
>
{
fields
.
length
>
1
?
(
<
MinusCircleOutlined
className=
"dynamic-delete-button"
onClick=
{
()
=>
remove
(
field
.
name
)
}
/>
)
:
null
}
</
Form
.
Item
>
))
}
<
Form
.
Item
>
<
Button
type=
"dashed"
onClick=
{
()
=>
add
()
}
style=
{
{
width
:
'
60%
'
}
}
icon=
{
<
PlusOutlined
/>
}
>
新增时段
</
Button
>
</
Form
.
Item
>
</>
)
}
</
Form
.
List
>
</
Form
.
Item
>
</
Form
>
</
Modal
>
)
}
</>
);
};
export
default
forwardRef
(
AddSellTimeModal
);
src/pages/ServiceGoods/components/FormInformationBasic.jsx
View file @
d72841d4
import
React
,
{
useState
,
useContext
,
useEffect
,
forwardRef
,
useImperativeHandle
}
from
'
react
'
;
import
React
,
{
import
{
Cascader
,
Form
,
Input
,
Select
,
Popover
,
Button
,
Checkbox
}
from
'
antd
'
;
useState
,
useContext
,
useEffect
,
forwardRef
,
useImperativeHandle
,
useRef
,
}
from
'
react
'
;
import
{
Cascader
,
Form
,
Input
,
Select
,
Popover
,
Button
,
Checkbox
,
Divider
,
Modal
,
notification
,
}
from
'
antd
'
;
import
{
formItemLayout
}
from
'
../config
'
;
import
{
formItemLayout
}
from
'
../config
'
;
import
{
ServiceContext
}
from
'
../context
'
;
import
{
ServiceContext
}
from
'
../context
'
;
import
{
debounce
}
from
'
@/utils/utils
'
;
import
{
debounce
}
from
'
@/utils/utils
'
;
import
AddMenusModal
from
'
./AddMenusModal
'
;
import
UploadImage
from
'
./UploadImage
'
;
import
UploadCropImage
from
'
./UploadCropImage
'
;
import
{
apiShopIds
,
apiQueryShopList
,
getByProductType
}
from
'
../service
'
;
import
GroupInfo
from
'
../../GoodsManage/Takeaway/components/GroupInfo
'
;
const
CreateSelectOption
=
optionList
=>
const
CreateSelectOption
=
optionList
=>
optionList
.
map
(
brandItem
=>
(
optionList
.
map
(
brandItem
=>
(
...
@@ -12,7 +35,6 @@ const CreateSelectOption = optionList =>
...
@@ -12,7 +35,6 @@ const CreateSelectOption = optionList =>
));
));
const
fileterBrandOptions
=
(
input
,
options
)
=>
options
.
children
.
includes
(
input
);
const
fileterBrandOptions
=
(
input
,
options
)
=>
options
.
children
.
includes
(
input
);
const
filterCategoryOptions
=
(
inputValue
,
path
)
=>
const
filterCategoryOptions
=
(
inputValue
,
path
)
=>
path
.
some
(
option
=>
option
.
name
.
toLowerCase
().
indexOf
(
inputValue
.
toLowerCase
())
>
-
1
);
path
.
some
(
option
=>
option
.
name
.
toLowerCase
().
indexOf
(
inputValue
.
toLowerCase
())
>
-
1
);
...
@@ -23,13 +45,21 @@ const FormInformationBasic = forwardRef((props, ref) => {
...
@@ -23,13 +45,21 @@ const FormInformationBasic = forwardRef((props, ref) => {
categoryList
,
categoryList
,
virtualCategoryList
,
virtualCategoryList
,
brandList
,
brandList
,
shopList
,
afterAddressList
,
afterAddressList
,
specListData
,
specListData
,
shopGetByProductType
,
groupShopData
,
}
=
props
;
}
=
props
;
const
[
form
]
=
Form
.
useForm
();
const
[
form
]
=
Form
.
useForm
();
const
[
noreBrandList
,
setNoreBrandList
]
=
useState
([]);
const
[
noreBrandList
,
setNoreBrandList
]
=
useState
([]);
const
customer
=
useContext
(
ServiceContext
);
const
customer
=
useContext
(
ServiceContext
);
const
childAddMenusModalRef
=
useRef
(
null
);
const
[
takeawayImageList
,
setTakeawayImageList
]
=
useState
([]);
const
[
shopIds
,
setShopIds
]
=
useState
([]);
const
[
shopList
,
setShopList
]
=
useState
([]);
const
[
isEditTakeaway
,
setIsEditTakeaway
]
=
useState
(
false
);
const
[
isModalOpen
,
setIsModalOpen
]
=
useState
(
false
);
const
[
shopIdSource
,
setShopIdSource
]
=
useState
(
''
);
const
onCheck
=
async
()
=>
{
const
onCheck
=
async
()
=>
{
try
{
try
{
...
@@ -54,15 +84,81 @@ const FormInformationBasic = forwardRef((props, ref) => {
...
@@ -54,15 +84,81 @@ const FormInformationBasic = forwardRef((props, ref) => {
}
}
};
};
// 自定义加入菜单
const
showModal
=
()
=>
{
if
(
shopIdSource
)
{
setIsModalOpen
(
true
);
}
else
{
notification
.
error
({
message
:
'
请先选择名店在进行操作!
'
});
}
};
// 自定义菜单下拉
const
dropdownRender
=
menus
=>
(
<
div
>
{
menus
}
<
Divider
style=
{
{
margin
:
0
,
}
}
/>
<
div
style=
{
{
padding
:
8
,
background
:
'
#1890ff
'
,
color
:
'
#fff
'
,
textAlign
:
'
center
'
,
}
}
onClick=
{
showModal
}
>
添加自定义分组
</
div
>
</
div
>
);
const
onTakeawayImageList
=
imgList
=>
{
setTakeawayImageList
(
imgList
);
form
.
setFieldsValue
({
commonImageList
:
imgList
,
});
};
const
getFormValues
=
debounce
(()
=>
{
const
getFormValues
=
debounce
(()
=>
{
const
values
=
form
.
getFieldsValue
();
const
values
=
form
.
getFieldsValue
();
// console.log('infoMation', values);
props
.
onValuesChange
({
infoMation
:
values
});
props
.
onValuesChange
({
infoMation
:
values
});
},
400
);
},
400
);
// 查询shopIds
const
queryShopIds
=
async
()
=>
{
if
(
!
shopIds
.
length
)
{
const
result
=
await
apiShopIds
();
setShopIds
(
result
.
data
||
[]);
}
};
// 查询分组列表
const
queryShopList
=
async
params
=>
{
let
result
=
[];
if
(
params
)
{
result
=
await
apiQueryShopList
(
params
);
}
else
{
result
=
await
apiQueryShopList
({
shopId
:
shopIdSource
});
}
setShopList
(
result
.
data
||
[]);
};
const
onChangeShopId
=
async
e
=>
{
if
(
e
)
{
setShopList
([]);
queryShopList
({
shopId
:
e
});
setShopIdSource
(
e
);
form
.
setFieldsValue
({
storageRackIds
:
''
,
});
}
};
useImperativeHandle
(
ref
,
()
=>
({
useImperativeHandle
(
ref
,
()
=>
({
onCheck
,
onCheck
,
reset
:
form
.
resetFields
,
reset
:
form
.
resetFields
,
}));
}));
useEffect
(()
=>
{
queryShopIds
();
},
[
customer
.
productType
]);
useEffect
(()
=>
{
useEffect
(()
=>
{
const
noreList
=
(
brandList
||
[]).
filter
(
item
=>
item
.
name
===
'
虚拟商品
'
);
const
noreList
=
(
brandList
||
[]).
filter
(
item
=>
item
.
name
===
'
虚拟商品
'
);
...
@@ -71,9 +167,31 @@ const FormInformationBasic = forwardRef((props, ref) => {
...
@@ -71,9 +167,31 @@ const FormInformationBasic = forwardRef((props, ref) => {
useEffect
(()
=>
{
useEffect
(()
=>
{
if
(
!
editData
)
return
;
if
(
!
editData
)
return
;
if
(
editData
.
productType
===
5
&&
editData
?.
name
)
{
shopGetByProductType
(
5
);
queryShopList
({
shopId
:
editData
?.
productRefShopId
});
setShopIdSource
(
editData
?.
productRefShopId
);
setIsEditTakeaway
(
true
);
}
form
.
setFieldsValue
(
editData
);
form
.
setFieldsValue
(
editData
);
if
(
editData
?.
commonImageList
?.
length
)
{
onTakeawayImageList
(
editData
?.
commonImageList
);
}
},
[
customer
.
isEdit
,
editData
]);
},
[
customer
.
isEdit
,
editData
]);
useEffect
(()
=>
{
setShopList
([]);
shopGetByProductType
(
5
);
const
{
shopId
=
''
,
groupId
=
''
}
=
groupShopData
;
if
(
shopId
)
{
setShopIdSource
(
shopId
);
queryShopList
({
shopId
});
}
const
temp
=
{
productRefShopId
:
shopId
?
[
`
${
shopId
}
`
]
:
[],
storageRackIds
:
groupId
?
[
+
groupId
]
:
[],
};
form
.
setFieldsValue
(
temp
);
},
[
groupShopData
]);
return
(
return
(
<
Form
<
Form
{
...
formItemLayout
}
{
...
formItemLayout
}
...
@@ -84,17 +202,71 @@ const FormInformationBasic = forwardRef((props, ref) => {
...
@@ -84,17 +202,71 @@ const FormInformationBasic = forwardRef((props, ref) => {
name
:
''
,
name
:
''
,
categoryId
:
[],
categoryId
:
[],
description
:
''
,
description
:
''
,
productRefShopId
:
[],
storageRackIds
:
null
,
}
}
}
}
scrollToFirstError
scrollToFirstError
onValuesChange=
{
getFormValues
}
onValuesChange=
{
getFormValues
}
>
>
<
Popover
content=
{
form
.
getFieldValue
(
'
name
'
)
}
trigger=
"hover"
>
<
Form
.
Item
key=
"name"
name=
"name"
label=
"商品名称"
rules=
{
[
{
required
:
true
,
min
:
2
,
max
:
30
,
message
:
'
请输入大于2个且小于30字符的商品名称
'
,
whitespace
:
true
,
},
]
}
>
<
Input
placeholder=
"请输入商品名称"
disabled=
{
customer
.
isDisabled
}
/>
</
Form
.
Item
>
</
Popover
>
{
customer
.
isTakeawayService
&&
(
<
Form
.
Item
name=
"productRefShopId"
label=
"所属门店"
rules=
{
[{
required
:
true
,
message
:
'
请选择所属门店
'
}]
}
>
<
Select
fieldNames=
{
{
label
:
'
name
'
,
value
:
'
id
'
}
}
filterOption=
{
fileterBrandOptions
}
placeholder=
"请选择所属门店"
options=
{
shopIds
}
onChange=
{
onChangeShopId
}
></
Select
>
</
Form
.
Item
>
)
}
{
/* 菜单分组 */
}
{
customer
.
isTakeawayService
&&
(
<
Form
.
Item
name=
"storageRackIds"
label=
"菜单分组"
rules=
{
[{
type
:
'
array
'
,
required
:
true
,
message
:
'
请输入菜单分组
'
}]
}
>
<
Cascader
placeholder=
"请选择菜单分组"
disabled=
{
customer
.
isEdit
&&
customer
.
isNormal
}
showSearch=
{
{
filter
:
filterCategoryOptions
}
}
fieldNames=
{
{
label
:
'
name
'
,
value
:
'
id
'
,
children
:
'
children
'
}
}
options=
{
shopList
}
dropdownRender=
{
dropdownRender
}
/>
</
Form
.
Item
>
)
}
{
/* 新增菜单分组弹框 */
}
{
/* <AddMenusModal ref={childAddMenusModalRef} queryShopList={queryShopList} /> */
}
<
Form
.
Item
<
Form
.
Item
name=
"categoryId"
name=
"categoryId"
label=
"商品类目"
label=
"商品类目"
rules=
{
[{
type
:
'
array
'
,
required
:
true
,
message
:
'
请输入商品类目
!
'
}]
}
rules=
{
[{
type
:
'
array
'
,
required
:
true
,
message
:
'
请输入商品类目
'
}]
}
>
>
<
Cascader
<
Cascader
placeholder=
"请选择商品类目
!
"
placeholder=
"请选择商品类目"
disabled=
{
customer
.
isEdit
&&
customer
.
isNormal
}
disabled=
{
customer
.
isEdit
&&
customer
.
isNormal
}
showSearch=
{
{
filter
:
filterCategoryOptions
}
}
showSearch=
{
{
filter
:
filterCategoryOptions
}
}
fieldNames=
{
{
label
:
'
name
'
,
value
:
'
id
'
,
children
:
'
children
'
}
}
fieldNames=
{
{
label
:
'
name
'
,
value
:
'
id
'
,
children
:
'
children
'
}
}
...
@@ -102,11 +274,35 @@ const FormInformationBasic = forwardRef((props, ref) => {
...
@@ -102,11 +274,35 @@ const FormInformationBasic = forwardRef((props, ref) => {
options=
{
newCategoryList
[
customer
.
productType
]
}
options=
{
newCategoryList
[
customer
.
productType
]
}
/>
/>
</
Form
.
Item
>
</
Form
.
Item
>
{
!
customer
.
isCard
&&
(
{
/* 外卖-商品图片 */
}
{
customer
.
isTakeawayService
&&
(
<
Form
.
Item
name=
"commonImageList"
label=
"商品图片"
extra=
"支持.jpg/png格式图片,建议单张比例1:1,大小200kb左右,最多可以上传5张"
rules=
{
[
{
required
:
true
,
type
:
'
array
'
,
message
:
'
请上传商品图片
'
,
},
]
}
>
<
UploadCropImage
name=
"takeawayImageList"
limit=
{
5
}
disabled=
{
customer
.
isDisabled
}
pictures=
{
takeawayImageList
}
setPictureList=
{
list
=>
onTakeawayImageList
(
list
)
}
/>
</
Form
.
Item
>
)
}
{
!
customer
.
isTakeawayService
&&
!
customer
.
isCard
&&
(
<
Form
.
Item
<
Form
.
Item
name=
"brandId"
name=
"brandId"
label=
"商品品牌"
label=
"商品品牌"
rules=
{
[{
required
:
true
,
message
:
'
请选择商品品牌
!
'
}]
}
rules=
{
[{
required
:
true
,
message
:
'
请选择商品品牌
'
}]
}
extra=
"若需新增品牌请联系业务员"
extra=
"若需新增品牌请联系业务员"
>
>
<
Select
<
Select
...
@@ -121,19 +317,8 @@ const FormInformationBasic = forwardRef((props, ref) => {
...
@@ -121,19 +317,8 @@ const FormInformationBasic = forwardRef((props, ref) => {
</
Select
>
</
Select
>
</
Form
.
Item
>
</
Form
.
Item
>
)
}
)
}
<
Popover
content=
{
form
.
getFieldValue
(
'
name
'
)
}
trigger=
"hover"
>
<
Form
.
Item
{
!
customer
.
isTakeawayService
&&
!
customer
.
isCard
&&
(
key=
"name"
name=
"name"
label=
"商品名称"
rules=
{
[
{
required
:
true
,
min
:
2
,
message
:
'
请输入最少两个字符的商品名称!
'
,
whitespace
:
true
},
]
}
>
<
Input
placeholder=
"请输入商品名称"
disabled=
{
customer
.
isDisabled
}
/>
</
Form
.
Item
>
</
Popover
>
{
!
customer
.
isCard
&&
(
<
Form
.
Item
<
Form
.
Item
name=
"character"
name=
"character"
label=
"商品卖点"
label=
"商品卖点"
...
@@ -146,7 +331,7 @@ const FormInformationBasic = forwardRef((props, ref) => {
...
@@ -146,7 +331,7 @@ const FormInformationBasic = forwardRef((props, ref) => {
</
Form
.
Item
>
</
Form
.
Item
>
)
}
)
}
{
!
customer
.
isCard
&&
(
{
!
customer
.
is
TakeawayService
&&
!
customer
.
is
Card
&&
(
<
Form
.
Item
name=
"afterAddressId"
label=
"售后地址"
>
<
Form
.
Item
name=
"afterAddressId"
label=
"售后地址"
>
<
Select
showSearch
placeholder=
"请选择售后地址"
filterOption=
{
fileterBrandOptions
}
>
<
Select
showSearch
placeholder=
"请选择售后地址"
filterOption=
{
fileterBrandOptions
}
>
{
(
afterAddressList
||
[]).
map
(
item
=>
(
{
(
afterAddressList
||
[]).
map
(
item
=>
(
...
@@ -158,7 +343,8 @@ const FormInformationBasic = forwardRef((props, ref) => {
...
@@ -158,7 +343,8 @@ const FormInformationBasic = forwardRef((props, ref) => {
</
Form
.
Item
>
</
Form
.
Item
>
)
}
)
}
{
!
customer
.
isCard
&&
{
!
customer
.
isTakeawayService
&&
!
customer
.
isCard
&&
specListData
.
map
((
item
,
index
)
=>
(
specListData
.
map
((
item
,
index
)
=>
(
<
Form
.
Item
name=
{
item
.
specId
}
key=
{
item
.
specId
}
label=
{
item
.
specName
}
>
<
Form
.
Item
name=
{
item
.
specId
}
key=
{
item
.
specId
}
label=
{
item
.
specName
}
>
<
Checkbox
.
Group
options=
{
item
.
specValues
}
/>
<
Checkbox
.
Group
options=
{
item
.
specValues
}
/>
...
@@ -180,11 +366,17 @@ const FormInformationBasic = forwardRef((props, ref) => {
...
@@ -180,11 +366,17 @@ const FormInformationBasic = forwardRef((props, ref) => {
key=
"description"
key=
"description"
name=
"description"
name=
"description"
label=
"描述"
label=
"描述"
rules=
{
[{
required
:
true
,
message
:
'
请输入描述,100字以内
!
'
}]
}
rules=
{
[{
required
:
true
,
message
:
'
请输入描述,100字以内
'
}]
}
>
>
<
Input
.
TextArea
showCount
maxLength=
{
100
}
placeholder=
"请输入描述, 100字以内
!
"
/>
<
Input
.
TextArea
showCount
maxLength=
{
100
}
placeholder=
"请输入描述, 100字以内"
/>
</
Form
.
Item
>
</
Form
.
Item
>
)
:
null
}
)
:
null
}
<
GroupInfo
isModalOpen=
{
isModalOpen
}
shopId=
{
shopIdSource
}
search=
{
queryShopList
}
handleClose=
{
setIsModalOpen
}
/>
</
Form
>
</
Form
>
);
);
});
});
...
...
src/pages/ServiceGoods/components/FormTakeaway.jsx
0 → 100644
View file @
d72841d4
/* eslint-disable consistent-return */
/* eslint-disable react/no-array-index-key */
/* eslint-disable no-shadow */
import
React
,
{
useContext
,
useState
,
useEffect
,
forwardRef
,
useImperativeHandle
,
useRef
,
}
from
'
react
'
;
import
{
Form
,
Input
,
Select
,
Button
,
Checkbox
,
Radio
,
Space
,
Modal
,
Switch
,
Row
,
Col
,
InputNumber
,
Cascader
,
Divider
,
DatePicker
,
message
,
}
from
'
antd
'
;
import
moment
from
'
moment
'
;
import
{
MinusCircleOutlined
,
PlusOutlined
}
from
'
@ant-design/icons
'
;
import
{
Title
}
from
'
./CommonTemplate
'
;
import
{
formItemLayout
,
ENUM_REPERTORY
,
ENUM_SET_REPERTORY
,
ENUM_WEEK
}
from
'
../config
'
;
import
{
ServiceContext
}
from
'
../context
'
;
import
{
debounce
}
from
'
@/utils/utils
'
;
import
{
isCheckPriceTwoDecimal
,
isIntegerNotZero
}
from
'
@/utils/validator
'
;
import
UploadCropImage
from
'
./UploadCropImage
'
;
// import AddSellTimeModal from './AddSellTimeModal';
import
styles
from
'
../common.less
'
;
import
AddRepertoryModal
from
'
./AddRepertoryModal
'
;
import
AddMultiSpecModal
from
'
./AddMultiSpecModal
'
;
import
{
apiTagList
,
apiUnits
}
from
'
../service
'
;
import
{
localAutoSaveKey
,
calcDescartes
}
from
'
../utils
'
;
import
localStorage
from
'
@/utils/localStorage
'
;
const
createInitValues
=
()
=>
({
description
:
''
,
// 商品描述
detailImageList
:
[],
// 商品图片
stock
:
'
1
'
,
// 库存类型
saleTimeType
:
0
,
// 售卖时间
singleDelivery
:
0
,
// 单点不送
list
:
1
,
// 列出商品
label
:
[],
minPurchaseNum
:
1
,
});
const
format
=
'
HH:mm
'
;
const
{
RangePicker
}
=
DatePicker
;
const
TakeawayGoodsInfo
=
forwardRef
((
props
,
ref
)
=>
{
const
{
editData
,
infoMation
}
=
props
;
const
[
form
]
=
Form
.
useForm
();
const
[
initValue
,
setInitValue
]
=
useState
(
createInitValues
());
const
customer
=
useContext
(
ServiceContext
);
const
[
detailImageList
,
setDetailImageList
]
=
useState
([]);
const
addSellTimeRef
=
useRef
(
null
);
const
AddRepertoryRef
=
useRef
(
null
);
const
AddMultiSpecRef
=
useRef
(
null
);
const
[
saleDates
,
setSaleDates
]
=
useState
({
saleDates
:
[],
saleTimes
:
[],
});
// 可售日期
const
[
timeType
,
setTimeType
]
=
useState
(
0
);
const
[
repertoryType
,
setRepertoryType
]
=
useState
(
'
1
'
);
const
[
tagList
,
setTagList
]
=
useState
([]);
const
[
unitsList
,
setUnitsList
]
=
useState
([]);
const
[
takeawayData
,
setTakeawayData
]
=
useState
({});
// eslint-disable-next-line prefer-const
let
[
multiSpu
,
setMultiSpu
]
=
useState
([]);
const
[
singularSpu
,
setSingularSpu
]
=
useState
([]);
const
[
intactData
,
setIntactData
]
=
useState
({});
const
[
repertoryState
,
setRepertoryState
]
=
useState
(
''
);
const
[
repertoryModel
,
setRepertoryModel
]
=
useState
({});
const
[
tempMultiSpu
,
setTempMultiSpu
]
=
useState
([]);
const
[
tempWeight
,
setTempWeight
]
=
useState
([]);
const
[
tempSpecs
,
setTempSpecs
]
=
useState
([]);
const
[
weightUnits
,
setWeightUnits
]
=
useState
([]);
const
[
peopleUnits
,
setPeopleUnits
]
=
useState
([]);
const
[
isRequired
,
setIsRequired
]
=
useState
(
true
);
// 自定义加入菜单
const
showModal
=
()
=>
{
addSellTimeRef
.
current
.
setOpen
(
true
);
};
const
onCheck
=
async
()
=>
{
try
{
const
values
=
await
form
.
validateFields
();
return
{
...
values
,
temp
:
'
takeawayItem
'
,
intactData
,
};
}
catch
(
errorInfo
)
{
return
null
;
}
};
// // 过滤存在的sku对象
// const objectComparison = (item, itm) => {
// console.log(item, itm, '==========');
// const {
// serviceItem: { maxStock, autoStock, productStock },
// } = itm;
// const params = { maxStock, autoStock, productStock: productStock || itm.productStock };
// const temp = { ...item, ...params };
// return temp;
// };
const
takeawayCalc
=
takeawayData
=>
{
// 商品基本信息编辑商品名称
const
{
infoMation
:
name
,
infoMation
,
takeawayItem
}
=
takeawayData
;
// weight 份量 specs规格 生成sku规则 weight * specs
const
{
specs
=
[],
weight
=
[],
description
,
detailImageList
,
list
,
minPurchaseNum
,
saleDates
,
maxStock
=
0
,
saleTimes
=
[],
label
,
quantity
,
productStock
=
0
,
salePrice
,
singleDelivery
,
saleTimeType
,
autoStock
=
0
,
skuList
,
id
,
categoryId
,
}
=
takeawayItem
;
let
{
unit
}
=
takeawayItem
;
unit
=
(
unit
&&
(
Array
.
isArray
(
unit
)
&&
unit
?.
length
&&
unit
?.
slice
(
1
).
toString
()))
||
unit
;
const
singularSpecList
=
[{
specGroupName
:
'
份量
'
,
generateSku
:
1
,
specs
:
[]
}];
// 单规格
const
multiSpecList
=
[{
specGroupName
:
'
份量
'
,
generateSku
:
1
,
specs
:
[]
}];
// 多规格
let
singularSpuData
=
[];
// 单库存spu
const
saleTimesTemp
=
[];
if
(
saleTimes
.
length
)
{
saleTimes
.
forEach
(
item
=>
{
const
startTime
=
item
?
moment
(
item
[
0
]).
format
(
format
)
:
''
;
const
endTime
=
item
?
moment
(
item
[
1
]).
format
(
format
)
:
''
;
saleTimesTemp
.
push
({
startTime
,
endTime
});
});
}
const
temp
=
{
salePrice
:
salePrice
||
0
,
productStock
,
list
:
1
,
id
:
skuList
?.
length
===
1
?
skuList
[
0
].
id
:
''
,
// 单规格默认取第一个
serviceItem
:
{
description
,
// 商品描述
maxStock
,
// 最大库存
productStock
,
minPurchaseNum
,
// 最少购买
saleTimeType
,
// 售卖时间
singleDelivery
,
// 单点不送
list
,
// 是否列出 1 是 0 否(外卖商品必填)
label
,
// 商品标签id
saleDates
,
// 可售日期 1-8
saleTimes
:
saleTimesTemp
,
// 可售日期 时间段
autoStock
,
// 弹框设置---自动补足
},
};
// 单规格
if
(
+
repertoryType
===
1
)
{
const
specs
=
{
salePrice
,
maxStock
,
quantity
,
// unit: (Array.isArray(unit) && unit?.length && unit?.splice(unit?.length - 1)[0]) || unit,
unit
,
productStock
,
specGroupName
:
'
份量
'
,
};
if
(
peopleUnits
.
includes
(
specs
.
unit
))
{
delete
specs
.
quantity
;
}
singularSpecList
[
0
].
specs
=
[
specs
];
singularSpuData
=
[{
...
temp
,
specs
:
[
specs
]
}];
setSingularSpu
(
singularSpuData
);
}
// 多规格
if
(
+
repertoryType
===
2
)
{
// if (name || editData.name) {
if
(
weight
.
length
)
{
let
tempSku
=
[];
multiSpecList
[
0
].
specs
=
weight
;
// 处理specList
if
(
specs
.
length
)
{
specs
.
forEach
((
specsItem
,
specsIndex
)
=>
{
if
(
specsItem
&&
!
specsItem
.
generateSku
)
{
specsItem
.
generateSku
=
1
;
}
if
(
specsItem
?.
specGroupName
)
{
specsItem
.
specs
.
forEach
(
itm
=>
{
itm
.
specGroupName
=
specsItem
?.
specGroupName
;
});
}
multiSpecList
.
push
(
specsItem
);
});
}
const
sepcx
=
specs
.
map
(
item
=>
item
.
specs
);
sepcx
.
map
(
item
=>
{
item
.
unit
=
''
;
return
item
;
});
// 生成 specs 规格sku
tempSku
=
[[...
weight
],
...
sepcx
].
reduce
(
(
x
,
y
)
=>
{
const
arr
=
[];
x
.
forEach
(
x
=>
y
.
forEach
(
y
=>
arr
.
push
(
x
.
concat
([
y
]))));
return
arr
;
},
[[]],
);
multiSpu
=
tempSku
.
map
((
item
,
index
)
=>
{
const
obj
=
{};
obj
.
salePrice
=
salePrice
;
obj
.
productStock
=
productStock
;
obj
.
list
=
list
;
obj
.
id
=
multiSpu
?.[
index
]?.
id
||
''
;
obj
.
serviceItem
=
{
...
temp
.
serviceItem
,
productStock
:
multiSpu
?.[
index
]?.
serviceItem
?.
productStock
||
productStock
,
maxStock
:
multiSpu
?.[
index
]?.
serviceItem
?.
maxStock
||
maxStock
,
autoStock
:
multiSpu
?.[
index
]?.
serviceItem
?.
autoStock
||
autoStock
,
};
obj
.
unique
=
''
;
multiSpecList
.
forEach
((
itm
,
idx
)
=>
{
if
(
item
[
idx
]
&&
!
item
[
idx
]?.
specGroupName
)
{
if
(
multiSpecList
[
idx
].
specGroupName
)
{
item
[
idx
].
specGroupName
=
multiSpecList
[
idx
].
specGroupName
;
}
}
});
obj
.
specs
=
[...
item
];
return
obj
;
});
}
multiSpu
.
forEach
(
item
=>
{
item
.
salePrice
=
0
;
item
.
unique
=
''
;
item
.
unique
=
item
?.
specs
.
map
(
itm
=>
{
if
(
itm
?.
unit
)
{
itm
.
unit
=
itm
?.
unit
&&
(
Array
.
isArray
(
itm
?.
unit
)
?
itm
?.
unit
.
slice
(
itm
?.
unit
.
length
-
1
)[
0
]
:
itm
?.
unit
);
}
if
(
itm
?.
unit
&&
peopleUnits
.
includes
(
itm
.
unit
))
{
delete
itm
.
quantity
;
}
if
(
itm
?.
specName
)
{
return
itm
.
specName
;
}
return
itm
;
})
.
toString
();
});
// 编辑数据
if
(
customer
.
isEdit
)
{
const
uniqueArr
=
tempMultiSpu
.
map
(
item
=>
item
.
unique
);
const
multiSpuUnique
=
multiSpu
.
map
(
item
=>
item
.
unique
);
const
newArrLen
=
Array
.
from
(
new
Set
(
multiSpuUnique
)).
length
;
if
(
newArrLen
<
multiSpuUnique
.
length
)
{
message
.
error
(
'
份量名称不能重复!
'
);
}
// 新增对比数据
multiSpu
.
forEach
((
item
,
index
)
=>
{
if
(
!
uniqueArr
.
includes
(
item
.
unique
))
{
tempMultiSpu
.
push
({
...
item
,
serviceItem
:
{
...
temp
.
serviceItem
,
maxStock
:
0
,
autoStock
:
0
,
productStock
:
0
},
id
:
''
,
});
}
});
// // 删除对比数据
while
(
multiSpu
.
length
!==
tempMultiSpu
.
length
)
{
tempMultiSpu
.
forEach
((
item
,
index
)
=>
{
if
(
!
multiSpuUnique
.
includes
(
item
.
unique
))
{
tempMultiSpu
.
splice
(
index
,
1
);
}
});
}
// 同步库存设置
multiSpu
.
map
(
item
=>
{
tempMultiSpu
.
forEach
(
itm
=>
{
if
(
item
.
unique
===
itm
.
unique
)
{
// 修改商品售卖信息参数
const
params
=
{
saleDates
:
temp
.
serviceItem
.
saleDates
,
saleTimes
:
temp
.
serviceItem
.
saleTimes
,
saleTimeType
:
temp
.
serviceItem
.
saleTimeType
,
minPurchaseNum
:
temp
.
serviceItem
.
minPurchaseNum
,
};
item
.
serviceItem
=
{
...
item
.
serviceItem
,
...
itm
.
serviceItem
,
...
params
};
itm
.
specs
=
[...
item
.
specs
];
}
});
return
item
;
});
setTempMultiSpu
(
tempMultiSpu
);
setMultiSpu
(
JSON
.
parse
(
JSON
.
stringify
(
multiSpu
)));
}
// 新增
if
(
!
customer
.
isEdit
)
{
setTempMultiSpu
(
multiSpu
);
setMultiSpu
(
multiSpu
);
}
}
// +repertoryType === 1 单规格 2多规格
const
intactDataTemp
=
{
...
takeawayItem
,
id
,
type
:
5
,
// 外卖类型
...
infoMation
,
label
:
label
&&
label
.
toString
(),
list
,
description
,
detailImageList
,
repertoryType
,
singleDelivery
,
specList
:
+
repertoryType
===
1
?
singularSpecList
:
multiSpecList
,
// 单库存和多库存specList
items
:
+
repertoryType
===
1
?
singularSpuData
:
JSON
.
parse
(
JSON
.
stringify
(
multiSpu
)),
// categoryId:
// (
// infoMation?.categoryId &&
// infoMation?.categoryId?.slice(infoMation?.categoryId?.length - 1)
// )?.toString() ||
// (Array.isArray(categoryId) && categoryId?.slice(categoryId?.length - 1)?.toString()),
};
setIntactData
(
intactDataTemp
);
return
intactData
;
};
const
onChange
=
()
=>
{};
const
getFormValues
=
debounce
(()
=>
{
const
values
=
form
.
getFieldsValue
();
console
.
log
(
values
,
'
values===
'
);
props
.
onValuesChange
({
takeawayItem
:
JSON
.
parse
(
JSON
.
stringify
(
values
))
});
const
takeawayData
=
customer
.
isEdit
?
{
takeawayItem
:
Object
.
assign
({},
editData
,
values
)
}
:
{
takeawayItem
:
values
};
// : localStorage.get(localAutoSaveKey) || {};
setTakeawayData
(
takeawayData
);
takeawayCalc
(
takeawayData
);
},
400
);
// 设置库存
const
modifiedInventory
=
(
type
,
idx
,
values
)
=>
{
const
{
productStock
,
maxStock
,
autoStock
}
=
values
;
if
(
type
===
'
multi
'
)
{
tempMultiSpu
.
map
(
item
=>
{
if
(
item
.
unique
===
idx
)
{
item
.
serviceItem
.
productStock
=
productStock
;
item
.
serviceItem
.
autoStock
=
autoStock
;
item
.
serviceItem
.
maxStock
=
maxStock
;
}
return
item
;
});
}
if
(
type
===
'
all
'
)
{
tempMultiSpu
.
map
(
item
=>
{
item
.
serviceItem
.
productStock
=
productStock
;
item
.
serviceItem
.
autoStock
=
autoStock
;
item
.
serviceItem
.
maxStock
=
maxStock
;
return
item
;
});
}
setTempMultiSpu
(
tempMultiSpu
);
getFormValues
();
return
false
;
};
const
filterCategoryOptions
=
(
inputValue
,
path
)
=>
path
.
some
(
option
=>
option
.
name
.
toLowerCase
().
indexOf
(
inputValue
.
toLowerCase
())
>
-
1
);
useImperativeHandle
(
ref
,
()
=>
({
onCheck
,
reset
:
()
=>
{
setInitValue
(
createInitValues
());
form
.
resetFields
();
},
}));
const
startTime
=
moment
(
moment
().
format
(
format
));
const
endTime
=
moment
(
moment
().
format
(
format
));
// 上传图片
const
onCardSuccessImageList
=
imgList
=>
{
setDetailImageList
(
imgList
);
form
.
setFieldsValue
({
detailImageList
:
imgList
,
});
};
// 自定义菜单下拉
const
dropdownRender
=
menus
=>
(
<
div
>
{
menus
}
<
Divider
style=
{
{
margin
:
0
,
}
}
/>
<
div
style=
{
{
padding
:
8
,
background
:
'
#1890ff
'
,
color
:
'
#fff
'
,
textAlign
:
'
center
'
,
}
}
onClick=
{
showModal
}
>
添加自定售卖时间
</
div
>
</
div
>
);
// 切换库存
const
onChangeRepertory
=
e
=>
{
const
{
value
}
=
e
.
target
;
setRepertoryType
(
`
${
value
}
`
);
if
(
+
value
===
1
)
{
form
.
setFieldsValue
({
weight
:
[]
});
form
.
setFieldsValue
({
specs
:
[]
});
}
else
{
const
params
=
{
quantity
:
''
,
unit
:
[],
salePrice
:
''
,
productStock
:
''
,
maxStock
:
''
,
autoStock
:
false
,
};
form
.
setFieldsValue
(
params
);
}
};
// 勾选库存设置
const
onChangeSetRepertory
=
e
=>
{
setRepertoryState
(
`
${
e
.
target
.
value
}
`
);
if
(
+
e
.
target
.
value
===
0
)
{
form
.
setFieldsValue
({
productStock
:
0
,
});
}
else
{
const
{
maxStock
}
=
form
.
getFieldsValue
([
'
maxStock
'
]);
form
.
setFieldsValue
({
productStock
:
maxStock
,
});
}
getFormValues
();
};
// 最大库存设置
const
onChangeMaxStock
=
e
=>
{
// 已经勾选最大库存 自动更新剩余库存
if
(
+
repertoryState
===
1
)
{
form
.
setFieldsValue
({
productStock
:
e
,
});
}
};
// 切换时间
const
onChangeTime
=
e
=>
{
setTimeType
(
e
.
target
.
value
);
};
// 自动补全
const
onChangeAutoStock
=
e
=>
{
form
.
setFieldsValue
({
autoStock
:
e
?
1
:
0
,
});
setIsRequired
(
!
e
);
};
// 显示加入库存弹框
const
showAddRepertoryModal
=
(
type
,
idx
,
item
)
=>
{
AddRepertoryRef
.
current
.
setOpenRepertory
(
true
);
setRepertoryModel
({
type
,
idx
,
item
});
};
// 拼接sku 名称
const
calcLabelName
=
item
=>
{
let
firstName
=
''
;
let
lastName
=
''
;
const
tempName
=
`
${
editData
?.
name
||
''
}
`;
// const tempSpecName = `
$
{
item
?.
specs
[
0
]?.
specName
||
''
}
`;
const tempQuantity = `
(
$
{
item
.
specs
[
0
]?.
quantity
||
''
}
`;
const tempUnit = `
$
{
item
.
specs
[
0
]?.
unit
||
''
}
$
{
item
.
specs
[
0
]?.
unit
?
'
)
'
:
''
}
`;
// const tempSecondSpecName = `
$
{
item
.
specs
[
1
]?.
specName
||
''
}
`;
// const isShow = tempQuantity && tempUnit && '+';
const uniqueName = item?.unique?.split(',') || [];
if (uniqueName && uniqueName.length) {
firstName = uniqueName[0] || '';
lastName = uniqueName?.slice(1).join(' ') || '';
}
//
${
tempName
}
return `
$
{
firstName
}
$
{
tempQuantity
}
$
{
tempUnit
}
$
{
lastName
}
`;
};
const init = async () => {
if (!tagList.length) {
const res = await apiTagList();
setTagList(res.data || []);
}
if (!unitsList.length) {
const res = await apiUnits();
setUnitsList(res.data || []);
const tempWeight = res.data.filter(item => item.name === '准确重量单位');
const tempPeople = res.data.filter(item => item.name === '适用人数');
if (tempWeight.length && tempWeight[0]?.children) {
const tempWeightName = tempWeight[0]?.children.map(item => item.name);
sessionStorage.setItem('weightUnits', JSON.stringify(tempWeightName || []));
setWeightUnits(tempWeightName);
}
if (tempPeople.length && tempPeople[0]?.children) {
const tempPeopleName = tempPeople[0]?.children.map(item => item.name);
sessionStorage.setItem('peopleUnits', JSON.stringify(tempPeopleName || []));
setPeopleUnits(tempPeopleName);
}
}
setTempMultiSpu([]);
return false;
};
useEffect(() => {
if (customer.isEdit || customer.isUseCache) {
if (!editData) return;
const {
label,
firstCategoryId,
secondCategoryId,
thirdCategoryId,
id,
saleTimes,
saleTimeType,
} = editData;
editData.label = label && label.split(',')?.map(item => +item);
const specList = editData?.specList;
const weight = specList?.filter(item => item.specGroupName === '份量');
const specs = specList?.filter(item => item.specGroupName !== '份量');
const tempWeightName = JSON.parse(sessionStorage.getItem('weightUnits'));
weight.forEach(item => {
if (item?.specs?.length) {
item.specs.forEach(itm => {
if (itm?.unit && tempWeightName.includes(itm?.unit)) {
itm.quantity =
itm?.quantity.indexOf('约') > -1 ? itm?.quantity.slice(1) : itm?.quantity || '';
}
});
}
});
editData.saleTimes = saleTimes?.length
? saleTimes.map(item => [moment(item?.startTime, format), moment(item?.endTime, format)])
: [];
if (editData?.skuList?.length) {
// editData.minPurchaseNum = editData?.skuList[0]?.serviceItem.minPurchaseNum;
// 单规格
if (editData?.skuList?.length === 1) {
const {
productStock,
shopId,
specs,
serviceItem: { maxStock, id, autoStock },
} = editData?.skuList[0];
const { quantity, unit, salePrice } = specs[0];
editData.productStock = productStock;
editData.quantity = `
$
{
quantity
}
`.indexOf('约') > -1 ? quantity.slice(1) : quantity || '';
editData.unit = unit;
editData.salePrice = salePrice;
editData.maxStock = maxStock;
editData.categoryId = [firstCategoryId, secondCategoryId, thirdCategoryId];
editData.autoStock = +autoStock === 1;
editData.productRefShopId = editData.shopId;
editData.skuId = id;
// setSingularSpu(JSON.parse(JSON.stringify(tempMultiSpu)) || []);
form.setFieldsValue(editData);
} else {
// 多规格
setRepertoryType('2');
const specList = editData?.specList;
const weight = specList.filter(item => item.specGroupName === '份量');
const tempWeightName = JSON.parse(sessionStorage.getItem('weightUnits'));
weight.forEach(item => {
if (item?.specs?.length) {
item.specs.forEach(itm => {
if (itm?.unit && tempWeightName.includes(itm?.unit)) {
itm.quantity =
itm?.quantity?.indexOf('约') > -1
? itm?.quantity.slice(1)
: itm?.quantity || '';
}
});
}
});
editData.categoryId = [firstCategoryId, secondCategoryId, thirdCategoryId];
editData.productRefShopId = editData.shopId;
// setTempWeight(weight)
// setTempSpecs(specs)
form.setFieldsValue({ weight: weight[0].specs });
form.setFieldsValue(editData);
form.setFieldsValue({ specs });
const tempMultiSpu = editData?.skuList.map(item => {
if (item) {
item.serviceItem.productStock = item.productStock;
const weightIndex = item.specs.findIndex(itm => itm.specGroupName === '份量');
const tempQuantity = item.specs[weightIndex].quantity;
const tempUnit = item.specs[weightIndex].unit;
const specsNameList = item.specs.map(itm => itm.specName);
const lastName = specsNameList.slice(1)?.join(' ');
item.unique = item?.specs.map(itm => itm.specName).toString();
}
return item;
});
setTempMultiSpu(tempMultiSpu || []);
setMultiSpu(JSON.parse(JSON.stringify(tempMultiSpu)) || []);
}
setTimeType(saleTimeType);
form.setFieldsValue({ productRefShopId: editData.shopId });
onCardSuccessImageList(editData?.detailImageList);
getFormValues();
}
}
}, [customer.isEdit, editData]);
useEffect(() => {
setIntactData(intactData);
}, [intactData]);
useEffect(() => {
init();
}, []);
useEffect(() => {
getFormValues();
}, [repertoryType]);
useEffect(() => {
setTempMultiSpu(tempMultiSpu);
}, [tempMultiSpu]);
return (
<>
<Form
{...formItemLayout}
form={form}
name="takeaway"
initialValues={initValue}
scrollToFirstError
onValuesChange={getFormValues}
>
<Title title="商品详细信息" />
<Form.Item name="description" label="商品描述">
<Input.TextArea
showCount
maxLength={200}
style={{ width: 400 }}
placeholder="请输入商品描述"
/>
</Form.Item>
<Form.Item
name="detailImageList"
label="商品图片"
extra="支持.jpg/png格式图片,建议单张切片宽750像素,大小200kb左右,您可以拖拽图片调整顺序,最多上传5张。"
>
<UploadCropImage
name="detailImageList"
limit={5}
disabled={customer.isDisabled}
pictures={detailImageList}
setPictureList={list => onCardSuccessImageList(list)}
/>
</Form.Item>
<Title title="商品售卖信息" />
<Form.Item
name="minPurchaseNum"
label="最少购买"
rules={[
{ required: true, message: '请输入最少购买数' },
{
validator: isIntegerNotZero,
type: 'number',
message: '请输入大于0的整数',
},
]}
>
<InputNumber min={1} max={999999999} style={{ width: 200 }} placeholder="请输入购买量" />
</Form.Item>
<Form.Item
name="saleTimeType"
label="售卖时间"
// rules={[{ type: 'array', required: true, message: '请输入售卖时间!' }]}
>
<Radio.Group onChange={onChangeTime}>
<Radio value={0}>全时段</Radio>
<Radio value={1}>自定义售卖时间</Radio>
</Radio.Group>
</Form.Item>
{+timeType === 1 && (
<>
<Form.Item name="saleDates" label="售卖时期(可多选)">
<Checkbox.Group>
<Row>
<Col className={styles.colRow} span={8}>
{ENUM_WEEK.map((item, index) => (
<Checkbox value={item.value}>{item.label}</Checkbox>
))}
</Col>
</Row>
</Checkbox.Group>
</Form.Item>
<Form.Item label="售卖时段">
<Form.List name="saleTimes" initialValue={[[]]}>
{(fields, { add, remove }) => (
<>
{fields.map((field, index) => (
<Form.Item required={false} key={field.key} className={styles.deal}>
<Form.Item
className={styles.deal}
{...field}
rules={[
{
required: true,
message: '请输入售卖时间',
},
]}
>
<RangePicker
picker="time"
defaultPickerValue={[startTime, endTime]}
format={format}
onChange={onChange}
showTime={{
format: 'HH:mm',
// defaultValue: [moment('00:00', 'HH:mm'), moment('00:00', 'HH:mm')],
hideDisabledOptions: true,
}}
disabledTime={() => ({
disabledMinutes: () => {
const result = [];
for (let i = 1; i < 60; i++) {
if (i !== 30) {
result.push(i);
}
}
return result;
},
})}
/>
</Form.Item>
{fields.length > 1 ? (
<MinusCircleOutlined
className="dynamic-delete-button"
onClick={() => remove(field.name)}
/>
) : null}
</Form.Item>
))}
<Form.Item>
{fields.length < 5 ? (
<Button
type="dashed"
onClick={() => add()}
style={{ width: '60%' }}
icon={<PlusOutlined />}
>
新增售卖时段
</Button>
) : null}
</Form.Item>
</>
)}
</Form.List>
</Form.Item>
</>
)}
<Form.Item name="label" label="商品标签">
<Select
// mode="multiple"
allowClear
placeholder="请选择商品标签"
style={{ width: 400 }}
disabled={customer.isEdit && customer.isNormal}
// showSearch={{ filter: filterCategoryOptions }}
fieldNames={{ label: 'tagName', value: 'tagId' }}
// onChange={props.onCategoryChange}
options={tagList}
/>
</Form.Item>
<Form.Item name="singleDelivery" label="单点不送" extra="开启后顾客点单则此商品不可下单">
<Radio.Group>
<Radio value={1}>是</Radio>
<Radio value={0}>否</Radio>
</Radio.Group>
</Form.Item>
<Form.Item name="list" label="列出商品" extra="开启后平台展示商品">
<Radio.Group>
<Radio value={1}>是</Radio>
<Radio value={0}>否</Radio>
</Radio.Group>
</Form.Item>
<Title title="规格信息" />
{!customer.isEdit && (
<Form.Item label="库存" name="stock">
<Radio.Group
options={ENUM_REPERTORY}
onChange={onChangeRepertory}
value="1"
buttonStyle="solid"
optionType="button"
/>
</Form.Item>
)}
{/* 单规格 */}
{repertoryType === '1' && (
<>
<Form.Item label="份量" className={styles.required}>
{form.getFieldValue(['unit']) &&
Array.isArray(form.getFieldValue(['unit'])) &&
weightUnits.includes(
form
.getFieldValue(['unit'])
.slice(1)
.toString(),
) && <span className="ant-form-text"> 约</span>}
<Form.Item
// noStyle
shouldUpdate={(prevValues, curValues) => false}
>
{form => {
let unit = form.getFieldValue('unit') || '';
unit =
(unit && (Array.isArray(unit) && unit?.length && unit?.slice(1).toString())) ||
unit;
if (!peopleUnits.includes(unit)) {
return (
<Form.Item
name="quantity"
style={{
display: 'inline-block',
}}
rules={[
{ required: true, message: '请输入分量!' },
{
validator: isCheckPriceTwoDecimal,
type: 'number',
message: '保留两位小数',
},
]}
>
<InputNumber
min={1}
max={999999999}
style={{ width: 200 }}
placeholder="请输入数字"
/>
</Form.Item>
);
}
}}
</Form.Item>
<Form.Item
name="unit"
rules={[{ required: true, message: '请选择单位' }]}
// rules={[{ type: 'array', required: true, message: '请选择单位' }]}
style={{
display: 'inline-block',
margin: '0 8px',
}}
>
<Cascader
placeholder="请选择单位"
disabled={customer.isEdit && customer.isNormal}
showSearch={{ filter: filterCategoryOptions }}
fieldNames={{ label: 'name', value: 'name', children: 'children' }}
onChange={() => {
const unit = form.getFieldValue('unit') || [];
if (unit && peopleUnits.includes(unit[1])) {
form.setFieldsValue({ quantity: '' });
}
}}
options={unitsList}
/>
</Form.Item>
</Form.Item>
<Form.Item
name="salePrice"
label="销售价格"
rules={[{ required: true, message: '请输入销售价格' }]}
>
<InputNumber
min={0}
max={999999999}
precision={2}
style={{ width: 200 }}
placeholder="元"
/>
</Form.Item>
<Form.Item className={styles.itemInline}>
<Form.Item
name="productStock"
label="剩余库存"
style={{
display: 'flex',
marginRight: '8px',
}}
rules={[
{ required: true, message: '请填写剩余库存' },
{
validator: isIntegerNotZero,
type: 'number',
message: '请输入大于0的整数',
},
]}
>
<InputNumber
min={0}
max={999999999}
style={{ width: 200, display: 'inline-block' }}
placeholder="请输入"
/>
</Form.Item>
<Form.Item style={{ width: 200, display: 'inline-block' }}>
<Radio.Group value={repertoryState} onChange={onChangeSetRepertory}>
<Radio.Button value="0">清空</Radio.Button>
<Radio.Button value="1">最大</Radio.Button>
</Radio.Group>
</Form.Item>
</Form.Item>
<Form.Item
name="maxStock"
label="最大库存"
rules={[
{ required: !isRequired, message: '请填写最大库存' },
{
validator: isIntegerNotZero,
type: 'number',
message: '请输入大于0的整数',
},
]}
>
<InputNumber
max={999999999}
min={0}
style={{ width: 200 }}
placeholder="请输入"
onChange={onChangeMaxStock}
/>
</Form.Item>
<Form.Item name="autoStock" label="自动补足" valuePropName="checked">
<Switch
checkedChildren="开启"
unCheckedChildren="关闭"
// defaultUnChecked
onChange={onChangeAutoStock}
/>
</Form.Item>
<div className={styles.rowWarp}>
{singularSpu.length > 0 &&
singularSpu[0]?.specs[0]?.unit &&
singularSpu.map((item, index) => (
<div className={styles.specsSingularBetween}>
<Form.Item label={calcLabelName(item, 'singular')}>
<div className={styles.specsSingularBetween}>
<span className={styles.repertoryLimit}>
{item?.specs[0]?.productStock}/{item?.specs[0]?.maxStock}
</span>
{/* <div
className={styles.specRepertory}
onClick={() => {
showAddRepertoryModal('singular', index); // 单规格库存
}}
>
设置库存
</div> */}
</div>
</Form.Item>
</div>
))}
</div>
</>
)}
{/* 多规格 */}
{repertoryType === '2' && (
<>
<Form.Item>
<div>份量(如大小/小份、微辣/特辣等)</div>
<Form.List name="weight" initialValue={[{}]}>
{(weightFields, { add: weightAdd, remove: weightRemove }) => (
<>
{weightFields.map((weightField, index) => (
<Space key={weightField.key} align="baseline" className={styles.conBg}>
<Form.Item
{...weightField}
name={[weightField.name, 'specName']}
rules={[
{
required: true,
message: '请输入名称',
},
]}
>
<Input style={{ width: '200px' }} placeholder="名称" />
</Form.Item>
{weightUnits.includes(form.getFieldValue(['weight'])?.[index]?.unit) && (
<span className="ant-form-text"> 约</span>
)}
<Form.Item
// noStyle
shouldUpdate={(prevValues, curValues) => false}
>
{form => {
let unit = form.getFieldValue(['weight'])?.[index]?.unit || '';
unit =
(unit &&
(Array.isArray(unit) &&
unit?.length &&
unit?.slice(1).toString())) ||
unit;
if (!peopleUnits.includes(unit)) {
return (
<Form.Item
style={{
display:
peopleUnits.includes(
form.getFieldValue(['weight'])?.[index]?.unit,
) && 'none',
}}
{...weightField}
name={[weightField.name, 'quantity']}
rules={[
{
required: !peopleUnits.includes(
form.getFieldValue(['weight'])?.[index]?.unit,
),
message: '份量',
},
{
validator: isIntegerNotZero,
type: 'number',
message: '请输入大于0的整数',
},
]}
>
<InputNumber
style={{ width: '120px' }}
max={999999999}
min={0}
placeholder="约 份量(数字)"
/>
</Form.Item>
);
}
}}
</Form.Item>
<Form.Item
{...weightField}
name={[weightField.name, 'unit']}
rules={[
{
// type: 'array',
required: true,
message: '请选择单位',
},
]}
>
<Cascader
placeholder="请选择单位"
disabled={customer.isEdit && customer.isNormal}
showSearch={{ filter: filterCategoryOptions }}
fieldNames={{
label: 'name',
value: 'name',
children: 'children',
}}
// onChange={props.onCategoryChange}
options={unitsList}
/>
</Form.Item>
<Form.Item
{...weightField}
name={[weightField.name, 'salePrice']}
rules={[
{
required: true,
message: '销售价',
},
]}
>
<InputNumber
max={999999999}
min={0}
precision={2}
style={{ width: '120px' }}
placeholder="销售价(元)"
/>
</Form.Item>
<Form.Item
{...weightField}
name={[weightField.name, 'activityPrice']}
rules={[
{
required: false,
message: '活动价',
},
]}
>
<InputNumber
max={999999999}
min={0}
precision={2}
style={{ width: '120px' }}
placeholder="活动价(元)"
/>
</Form.Item>
{weightFields.length > 1 ? (
<MinusCircleOutlined onClick={() => weightRemove(weightField.name)} />
) : null}
</Space>
))}
<Form.Item>
<Button
type="primary"
onClick={() => weightAdd()}
block
style={{ width: '400px' }}
icon={<PlusOutlined />}
>
新增份量
</Button>
</Form.Item>
</>
)}
</Form.List>
</Form.Item>
{/* takeawayData?.takeawayItem?.weight?.length > 0 && */}
{
<>
<Form.Item>
<div>添加规格(如加料、甜度、辣度等)</div>
<Form.List name="specs" initialValue={[]}>
{(specsFields, { add, remove }) => (
<>
{specsFields.map((specsField, index) => (
<Form.Item key={specsField.key} className={styles.conBg}>
<Form.Item
{...specsField}
// validateTrigger={['onChange', 'onBlur']}
name={[specsField.name, 'specGroupName']}
rules={[
{
required: true,
whitespace: true,
message: '请输入规格名称',
},
]}
noStyle
>
<Input placeholder="规格名称" className={styles.nameWidth} />
</Form.Item>
{/* {specsFields.length > 1 ? ( */}
<MinusCircleOutlined
className="dynamic-delete-button"
onClick={() => remove(specsField.name)}
/>
{/* ) : null} */}
<Form.List
{...specsField}
name={[specsField.name, 'specs']}
initialValue={[{}]}
>
{(specsInfoFields, { add: specsAdd, remove: specsRemove }) => (
<>
{specsInfoFields.map(specsInfofield => (
<Space key={specsInfofield.key} align="baseline">
<Form.Item
{...specsInfofield}
name={[specsInfofield.name, 'specName']}
rules={[
{
required: true,
message: '请输入加价名称',
},
]}
>
<Input style={{ width: '200px' }} placeholder="加价名称" />
</Form.Item>
<Form.Item
{...specsInfofield}
name={[specsInfofield.name, 'salePrice']}
rules={[
{
required: true,
message: '请输入加价金额(元)',
},
]}
>
<InputNumber
max={999999999}
min={0}
precision={2}
style={{ width: '200px' }}
placeholder="加价名称金额(元)"
/>
</Form.Item>
{specsInfoFields.length > 1 ? (
<MinusCircleOutlined
onClick={() => specsRemove(specsInfofield.name)}
/>
) : null}
</Space>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => specsAdd()}
block
style={{ width: '400px' }}
icon={<PlusOutlined />}
>
新增加价
</Button>
</Form.Item>
</>
)}
</Form.List>
</Form.Item>
))}
<Form.Item>
<Button
type="primary"
onClick={() => add()}
style={{ width: '400px' }}
icon={<PlusOutlined />}
>
新增规格
</Button>
</Form.Item>
</>
)}
</Form.List>
</Form.Item>
<div className={styles.textStyle}>修改成功后,原库存将被替换,请谨慎操作!</div>
<Form.Item
name="receptionVolume"
label="多规格库存"
className={styles.multiSpecification}
>
<Button
size="small"
danger
style={{ marginBottom: '10px' }}
onClick={() => {
showAddRepertoryModal('all'); // 统一库存
}}
shape="round"
>
统一设置库存
</Button>
<div className={styles.rowWarp}>
{tempMultiSpu.length > 0 &&
tempMultiSpu?.map((item, idx) => (
<>
{item.unique && (
<>
<div key={idx} className={styles.specsBetween}>
<Form.Item>
<div className={styles.specsBetween}>
<div>{calcLabelName(item)} :</div>
<span className={styles.repertoryLimit}>
{item?.serviceItem?.productStock}/
{item?.serviceItem?.maxStock}
</span>
<div
className={styles.specRepertory}
onClick={() => {
showAddRepertoryModal('multi', `
$
{
item
.
unique
}
`, item); // 多个库存
}}
>
去设置
</div>
</div>
</Form.Item>
</div>
</>
)}
</>
))}
</div>
</Form.Item>
</>
}
</>
)}
</Form>
{/* 加入库存 */}
<AddRepertoryModal
ref={AddRepertoryRef}
modifiedInventory={modifiedInventory}
intactData={intactData}
repertoryModel={repertoryModel}
/>
{/* 加入多规格 */}
<AddMultiSpecModal ref={AddMultiSpecRef} />
</>
);
});
export default TakeawayGoodsInfo;
src/pages/ServiceGoods/components/TaskTypeSelect.jsx
View file @
d72841d4
...
@@ -5,9 +5,13 @@ import commonStyle from '../common.less';
...
@@ -5,9 +5,13 @@ import commonStyle from '../common.less';
export
const
TaskTypeSelect
=
props
=>
{
export
const
TaskTypeSelect
=
props
=>
{
const
customer
=
useContext
(
ServiceContext
);
const
customer
=
useContext
(
ServiceContext
);
const
typeConfig
=
TaskList
(
customer
.
canAddService
,
customer
.
canAddNormal
);
const
typeConfig
=
TaskList
(
customer
.
canAddService
,
customer
.
canAddNormal
,
customer
.
canTakeawayService
,
);
const
selectTabs
=
task
=>
{
const
selectTabs
=
task
=>
{
if
(
!
customer
.
isEdit
)
{
if
(
!
customer
.
isEdit
&&
Object
.
keys
(
props
.
takeAway
).
length
===
0
)
{
props
.
onChange
(
task
);
props
.
onChange
(
task
);
}
}
};
};
...
...
src/pages/ServiceGoods/components/UploadCropImage.jsx
0 → 100644
View file @
d72841d4
import
{
PlusOutlined
,
DeleteOutlined
,
EyeOutlined
}
from
'
@ant-design/icons
'
;
import
{
Modal
,
Upload
,
notification
,
Spin
}
from
'
antd
'
;
import
React
,
{
useState
,
useEffect
,
useRef
,
forwardRef
}
from
'
react
'
;
import
lodash
from
'
lodash
'
;
import
{
ReactSortable
}
from
'
react-sortablejs
'
;
import
ImgCrop
from
'
antd-img-crop
'
;
import
'
antd/es/modal/style
'
;
import
'
antd/es/slider/style
'
;
import
{
merchantUpload
}
from
'
../service
'
;
import
styles
from
'
../common.less
'
;
const
UploadButton
=
(
<
div
>
<
PlusOutlined
/>
<
div
style=
{
{
marginTop
:
8
}
}
>
上传图片
</
div
>
</
div
>
);
const
UploadCropImage
=
forwardRef
((
props
,
ref
)
=>
{
const
{
name
=
`
${
Date
.
now
()}
`
,
limit
=
null
,
multiple
=
true
,
disabled
,
uploadParams
,
pictures
=
[],
setPictureList
=
()
=>
{},
...
imgOptions
}
=
props
;
const
[
uploadLoading
,
setUploadLoading
]
=
useState
(
false
);
const
[
previewVisible
,
setPreviewVisible
]
=
useState
(
false
);
const
[
previewImage
,
setPreviewImage
]
=
useState
(
''
);
const
[
previewTitle
,
setPreviewTitle
]
=
useState
(
''
);
const
[
fileList
,
setFileList
]
=
useState
([]);
const
[
activeImgIndex
,
setActiveImgIndex
]
=
useState
(
null
);
const
fileListRef
=
useRef
([]);
useEffect
(()
=>
{
const
newPictures
=
pictures
.
map
((
url
,
ind
)
=>
({
url
,
name
:
url
,
uid
:
`
${
ind
}
`
,
}));
fileListRef
.
current
=
[...
newPictures
];
setFileList
([...
newPictures
]);
},
[
pictures
]);
const
handleCancel
=
()
=>
setPreviewVisible
(
false
);
const
handlePreview
=
async
file
=>
{
setPreviewImage
(
file
.
url
);
setPreviewVisible
(
true
);
setPreviewTitle
(
file
.
name
||
file
.
url
.
substring
(
file
.
url
.
lastIndexOf
(
'
/
'
)
+
1
));
};
const
bundleChange
=
imgFile
=>
{
// setFileList(imgFile);
const
imgList
=
imgFile
.
map
(
item
=>
item
.
url
);
setPictureList
(
imgList
);
props
.
onChange
(
imgList
);
};
const
handleRemove
=
file
=>
{
const
freshFiles
=
fileList
?.
filter
(
ele
=>
ele
.
uid
!==
file
.
uid
);
bundleChange
(
freshFiles
);
};
const
cleanArray
=
(
actual
=
[])
=>
actual
.
reduce
((
prev
,
cur
)
=>
{
cur
&&
prev
.
push
(
cur
);
return
prev
;
},
[]);
const
warningTip
=
description
=>
{
notification
.
warning
({
message
:
'
图片上传失败
'
,
description
,
});
};
const
getBase64
=
(
img
,
callback
)
=>
{
const
reader
=
new
FileReader
();
reader
.
addEventListener
(
'
load
'
,
()
=>
callback
(
reader
.
result
));
reader
.
readAsDataURL
(
img
);
};
const
ImageInfo
=
file
=>
new
Promise
((
resolve
,
reject
)
=>
{
const
LtMB
=
file
.
size
/
1024
/
1024
;
if
(
LtMB
>
2
)
{
warningTip
(
`[
${
file
.
name
}
] 图片不可以大于2MB`
);
resolve
(
null
);
}
getBase64
(
file
,
url
=>
{
const
image
=
new
Image
();
image
.
addEventListener
(
'
load
'
,
()
=>
{
const
{
width
}
=
image
;
const
{
height
}
=
image
;
file
.
width
=
width
;
file
.
height
=
height
;
file
.
LtMB
=
LtMB
;
resolve
(
file
);
});
image
.
addEventListener
(
'
error
'
,
()
=>
{
warningTip
(
`
${
file
.
name
}
图片上传失败!`
);
resolve
(
null
);
});
image
.
src
=
url
;
});
});
const
CheckImageInfoList
=
async
files
=>
{
const
promiseImage
=
files
.
map
(
file
=>
ImageInfo
(
file
));
const
clearImage
=
await
Promise
.
all
(
promiseImage
);
return
cleanArray
(
clearImage
);
};
const
isUploadNext
=
async
imgFileList
=>
{
const
filterImage
=
imgFileList
.
filter
(
img
=>
{
if
(
(
imgOptions
.
maxWidth
&&
img
.
width
>
imgOptions
.
maxWidth
)
||
(
imgOptions
.
maxHeight
&&
img
.
height
>
imgOptions
.
maxHeight
)
)
{
warningTip
(
`[
${
img
.
name
}
]
${
imgOptions
.
superTips
}
`
);
return
false
;
}
return
true
;
});
return
filterImage
;
};
const
checkFile
=
files
=>
{
const
fileType
=
[
'
jpg
'
,
'
jpeg
'
,
'
png
'
];
const
filterImage
=
files
.
filter
(
file
=>
{
const
curType
=
file
.
name
.
substr
(
file
.
name
.
lastIndexOf
(
'
.
'
)
+
1
).
toLowerCase
();
if
(
!
fileType
.
includes
(
curType
))
{
warningTip
(
'
图片格式须为jpg、jpeg、png!
'
);
return
false
;
}
return
true
;
});
return
filterImage
;
};
const
imageLoading
=
(
file
,
ret
)
=>
new
Promise
(
resolve
=>
{
const
reader
=
new
FileReader
();
// 监听图片转换完成
reader
.
addEventListener
(
'
load
'
,
()
=>
{
const
temFile
=
{
uid
:
file
.
uid
,
status
:
'
done
'
,
name
:
file
.
name
,
url
:
ret
};
resolve
(
temFile
);
},
false
,
);
reader
.
readAsDataURL
(
file
);
});
const
defaultBeforeUpload
=
lodash
.
debounce
(
(
file
,
fileArray
)
=>
// 文件显示
new
Promise
(
async
()
=>
{
console
.
log
(
'
defaultBeforeUpload :>>
'
,
11111
);
if
(
limit
&&
fileListRef
.
current
.
length
+
fileArray
.
length
>
limit
)
{
Modal
.
warning
({
maskClosable
:
true
,
title
:
'
超出上传个数
'
,
});
return
Upload
.
LIST_IGNORE
;
}
const
flies
=
checkFile
(
fileArray
);
const
optionsArray
=
await
CheckImageInfoList
(
flies
);
const
checkFiles
=
await
isUploadNext
(
optionsArray
);
try
{
if
(
checkFiles
.
length
)
{
setUploadLoading
(
true
);
const
res
=
await
merchantUpload
(
checkFiles
);
if
(
res
.
data
)
{
const
proFiles
=
(
res
.
data
||
[]).
map
((
urlItem
,
urlIndex
)
=>
imageLoading
(
checkFiles
[
urlIndex
],
urlItem
),
);
const
imagList
=
await
Promise
.
all
(
proFiles
);
const
newFiles
=
[...
fileListRef
.
current
,
...
imagList
];
bundleChange
(
newFiles
);
}
else
{
notification
.
warning
({
message
:
'
警告
'
,
description
:
res
.
msg
,
});
}
setUploadLoading
(
false
);
}
}
catch
(
error
)
{
console
.
log
(
error
);
setUploadLoading
(
false
);
Modal
.
warning
({
maskClosable
:
true
,
title
:
'
上传失败,请重新尝试!
'
,
});
}
return
null
;
}),
);
return
(
<
Spin
tip=
"正在上传..."
spinning=
{
uploadLoading
}
delay=
{
100
}
>
<
div
className=
{
styles
.
imgContent
}
>
{
fileList
.
length
>
0
&&
(
<
ReactSortable
animation=
{
300
}
list=
{
fileList
}
setList=
{
list
=>
bundleChange
(
list
)
}
>
{
fileList
.
map
((
item
,
index
)
=>
(
<
div
// eslint-disable-next-line react/no-array-index-key
key=
{
index
}
className=
{
styles
.
sortImg
}
onMouseEnter=
{
()
=>
setActiveImgIndex
(
index
)
}
onMouseLeave=
{
()
=>
setActiveImgIndex
(
null
)
}
>
<
div
style=
{
{
width
:
'
90%
'
,
height
:
'
90%
'
,
overflow
:
'
hidden
'
}
}
>
<
img
width=
"100%"
key=
{
item
.
uid
}
src=
{
item
.
url
}
alt=
""
/>
</
div
>
{
activeImgIndex
===
index
&&
(
<
div
className=
{
styles
.
mask
}
>
<
EyeOutlined
className=
{
styles
.
maskIcon
}
onClick=
{
()
=>
handlePreview
(
item
)
}
/>
{
!
disabled
&&
(
<
DeleteOutlined
className=
{
styles
.
maskIcon
}
onClick=
{
()
=>
handleRemove
(
item
)
}
/>
)
}
</
div
>
)
}
</
div
>
))
}
</
ReactSortable
>
)
}
</
div
>
{
limit
!==
null
&&
fileList
.
length
>=
limit
?
(
''
)
:
(
<
ImgCrop
rotationSlider
modalWidth=
{
500
}
modalHeight=
{
500
}
quality=
{
0.5
}
showReset
>
<
Upload
{
...
uploadParams
}
disabled=
{
Boolean
(
disabled
)
}
multiple=
{
multiple
}
name=
{
name
}
customRequest=
{
()
=>
{}
}
listType=
"picture-card"
beforeUpload=
{
defaultBeforeUpload
}
fileList=
{
fileList
}
onPreview=
{
handlePreview
}
onRemove=
{
handleRemove
}
showUploadList=
{
false
}
>
{
UploadButton
}
</
Upload
>
</
ImgCrop
>
)
}
<
Modal
visible=
{
previewVisible
}
title=
{
previewTitle
}
footer=
{
null
}
onCancel=
{
handleCancel
}
>
<
img
alt=
"example"
style=
{
{
width
:
'
100%
'
}
}
src=
{
previewImage
}
/>
</
Modal
>
</
Spin
>
);
});
export
default
UploadCropImage
;
src/pages/ServiceGoods/config.js
View file @
d72841d4
...
@@ -7,7 +7,7 @@ export const formItemLayout = {
...
@@ -7,7 +7,7 @@ export const formItemLayout = {
},
},
};
};
export
const
TaskList
=
(
canAddService
,
canAddNormal
)
=>
[
export
const
TaskList
=
(
canAddService
,
canAddNormal
,
canTakeawayService
)
=>
[
{
{
name
:
'
实体商品
'
,
name
:
'
实体商品
'
,
type
:
1
,
type
:
1
,
...
@@ -33,36 +33,68 @@ export const TaskList = (canAddService, canAddNormal) => [
...
@@ -33,36 +33,68 @@ export const TaskList = (canAddService, canAddNormal) => [
},
},
},
},
},
},
// {
// name: '虚拟商品',
// type: 2,
// desc: '无需物流',
// hide: !canAddNormal,
// imgConfig: {
// commonImageList: {
// title: '公共滑动图',
// rule: false,
// limit: null,
// renderExtra: () => '(图片最大上传2M)',
// },
// imageList: {
// rule: false,
// limit: null,
// renderExtra: () => '(图片最大上传2M)',
// },
// detailImageList: {
// title: '详情图',
// rule: true,
// limit: null,
// renderExtra: () => '(图片最大上传2M)',
// },
// },
// },
{
{
name
:
'
虚拟
商品
'
,
name
:
'
服务类
商品
'
,
type
:
2
,
type
:
4
,
desc
:
'
无需物流
'
,
desc
:
'
无需物流
'
,
hide
:
!
canAdd
Normal
,
hide
:
!
canAdd
Service
,
imgConfig
:
{
imgConfig
:
{
commonImageList
:
{
commonImageList
:
{
title
:
'
公共滑动图
'
,
title
:
'
封面图片
'
,
rule
:
false
,
rule
:
true
,
limit
:
null
,
limit
:
1
,
renderExtra
:
()
=>
'
(图片最大上传2M)
'
,
renderExtra
(
leng
)
{
return
`建议尺寸: ##宽##高 (
${
leng
}
/ 1) 封面图第一张 `
;
},
},
},
imageList
:
{
cardImageList
:
{
rule
:
false
,
title
:
'
商品图片
'
,
limit
:
null
,
rule
:
true
,
renderExtra
:
()
=>
'
(图片最大上传2M)
'
,
limit
:
11
,
renderExtra
(
leng
)
{
return
`建议尺寸: ##宽##高,sku商品轮播图(
${
leng
}
/ 11)`
;
},
},
},
detailImageList
:
{
detailImageList
:
{
title
:
'
详情图
'
,
title
:
'
商品详情图
'
,
rule
:
true
,
// rule: true,
limit
:
null
,
limit
:
30
,
renderExtra
:
()
=>
'
(图片最大上传2M)
'
,
renderExtra
()
{
return
'
最多上传30张
'
;
},
},
},
},
},
},
},
{
{
name
:
'
电子卡卷
'
,
name
:
'
外卖商品
'
,
type
:
4
,
type
:
5
,
desc
:
'
无需物流
'
,
desc
:
'
无需物流
'
,
hide
:
!
can
Add
Service
,
hide
:
!
can
Takeaway
Service
,
imgConfig
:
{
imgConfig
:
{
commonImageList
:
{
commonImageList
:
{
title
:
'
封面图片
'
,
title
:
'
封面图片
'
,
...
@@ -291,3 +323,15 @@ export const StaticColumns = customer => [
...
@@ -291,3 +323,15 @@ export const StaticColumns = customer => [
disabeldRender
:
()
=>
customer
.
isDisabled
,
disabeldRender
:
()
=>
customer
.
isDisabled
,
},
},
];
];
export
const
ENUM_REPERTORY
=
[{
label
:
'
单规格
'
,
value
:
'
1
'
},
{
label
:
'
多规格
'
,
value
:
'
2
'
}];
export
const
ENUM_SET_REPERTORY
=
[{
label
:
'
清零
'
,
value
:
'
0
'
},
{
label
:
'
最大
'
,
value
:
'
1
'
}];
export
const
ENUM_WEEK
=
[
{
value
:
'
1
'
,
label
:
'
周一
'
},
{
value
:
'
2
'
,
label
:
'
周二
'
},
{
value
:
'
3
'
,
label
:
'
周三
'
},
{
value
:
'
4
'
,
label
:
'
周四
'
},
{
value
:
'
5
'
,
label
:
'
周五
'
},
{
value
:
'
6
'
,
label
:
'
周六
'
},
{
value
:
'
7
'
,
label
:
'
周日
'
},
// { value: 8, label: '法定假日' },
];
src/pages/ServiceGoods/index.jsx
View file @
d72841d4
import
React
,
{
useState
,
useRef
,
useEffect
,
useCallback
,
useMemo
}
from
'
react
'
;
import
React
,
{
useState
,
useRef
,
useEffect
,
useCallback
,
useMemo
}
from
'
react
'
;
import
{
Spin
,
Button
,
Modal
,
message
,
notification
}
from
'
antd
'
;
import
{
Spin
,
Button
,
Modal
,
message
,
notification
}
from
'
antd
'
;
import
moment
from
'
moment
'
;
import
moment
from
'
moment
'
;
import
PubSub
from
'
pubsub-js
'
;
import
{
Title
,
WrapperContainer
}
from
'
./components/CommonTemplate
'
;
import
{
Title
,
WrapperContainer
}
from
'
./components/CommonTemplate
'
;
import
{
TaskTypeSelect
}
from
'
./components/TaskTypeSelect
'
;
import
{
TaskTypeSelect
}
from
'
./components/TaskTypeSelect
'
;
import
FormInformationBasic
from
'
./components/FormInformationBasic
'
;
import
FormInformationBasic
from
'
./components/FormInformationBasic
'
;
...
@@ -9,6 +10,7 @@ import FormRuleSetting from './components/FormRuleSetting';
...
@@ -9,6 +10,7 @@ import FormRuleSetting from './components/FormRuleSetting';
import
FormRuleVPictures
from
'
./components/FormRuleVPictures
'
;
import
FormRuleVPictures
from
'
./components/FormRuleVPictures
'
;
import
FormSettlementOthers
from
'
./components/FormSettlementOthers
'
;
import
FormSettlementOthers
from
'
./components/FormSettlementOthers
'
;
import
FormAttr
from
'
./components/FormAttr
'
;
import
FormAttr
from
'
./components/FormAttr
'
;
import
FormTakeaway
from
'
./components/FormTakeaway
'
;
import
localStorage
from
'
@/utils/localStorage
'
;
import
localStorage
from
'
@/utils/localStorage
'
;
import
{
import
{
merchantBrandList
,
merchantBrandList
,
...
@@ -21,6 +23,7 @@ import {
...
@@ -21,6 +23,7 @@ import {
getByProductType
,
getByProductType
,
apiCreateDraft
,
apiCreateDraft
,
apiEditDraft
,
apiEditDraft
,
apiGetShopDetail
,
}
from
'
./service
'
;
}
from
'
./service
'
;
import
{
isUrl
,
filterSendData
,
clearCurrent
,
onAutoSaveValue
,
localAutoSaveKey
}
from
'
./utils
'
;
import
{
isUrl
,
filterSendData
,
clearCurrent
,
onAutoSaveValue
,
localAutoSaveKey
}
from
'
./utils
'
;
import
{
ServiceContext
}
from
'
./context
'
;
import
{
ServiceContext
}
from
'
./context
'
;
...
@@ -33,22 +36,33 @@ import styles from './common.less';
...
@@ -33,22 +36,33 @@ import styles from './common.less';
* @returns ReactDOM
* @returns ReactDOM
*/
*/
const
ServiceGoods
=
options
=>
{
const
ServiceGoods
=
options
=>
{
const
{
SourceData
,
categoryList
,
virtualCategoryList
,
specListData
,
permissions
}
=
options
;
const
{
SourceData
,
categoryList
,
virtualCategoryList
,
specListData
,
permissions
,
takeAway
,
}
=
options
;
const
canAddService
=
permissions
[
GOOD_MANAGE
.
ADD_SERVICE_GOODS
];
const
canAddService
=
permissions
[
GOOD_MANAGE
.
ADD_SERVICE_GOODS
];
const
canAddNormal
=
permissions
[
GOOD_MANAGE
.
ADD_NORMAL_GOODS
];
const
canAddNormal
=
permissions
[
GOOD_MANAGE
.
ADD_NORMAL_GOODS
];
const
canTakeawayService
=
permissions
[
GOOD_MANAGE
.
ADD_TAKEAWAY_GOODS
];
// const canTakeawayService = true
const
basicRef
=
useRef
(
null
);
const
basicRef
=
useRef
(
null
);
const
stockRef
=
useRef
(
null
);
const
stockRef
=
useRef
(
null
);
const
settingRef
=
useRef
(
null
);
const
settingRef
=
useRef
(
null
);
const
picturesRef
=
useRef
(
null
);
const
picturesRef
=
useRef
(
null
);
const
settleOtrRef
=
useRef
(
null
);
const
settleOtrRef
=
useRef
(
null
);
const
attrRef
=
useRef
(
null
);
const
attrRef
=
useRef
(
null
);
const
takeawayRef
=
useRef
(
null
);
const
[
pageId
,
setPageId
]
=
useState
(
null
);
const
[
pageId
,
setPageId
]
=
useState
(
null
);
const
[
categoryIds
,
setCategoryIds
]
=
useState
([]);
// 商品品类ID
const
[
categoryIds
,
setCategoryIds
]
=
useState
([]);
// 商品品类ID
const
[
isEdit
,
setIsEdit
]
=
useState
(
false
);
// 是否是编辑状态
const
[
isEdit
,
setIsEdit
]
=
useState
(
false
);
// 是否是编辑状态
const
[
isUseCache
,
setIsUseCache
]
=
useState
(
false
);
// 是否使用缓存
const
[
isUseCache
,
setIsUseCache
]
=
useState
(
false
);
// 是否使用缓存
const
[
productType
,
setProductType
]
=
useState
(
canAddNormal
?
1
:
4
);
// 商品状态
let
ptype
=
canTakeawayService
?
5
:
4
;
ptype
=
canAddNormal
?
1
:
ptype
;
const
[
productType
,
setProductType
]
=
useState
(
ptype
);
// 商品状态
const
[
pageLoading
,
setPageLoading
]
=
useState
(
false
);
// 页面加载状态
const
[
pageLoading
,
setPageLoading
]
=
useState
(
false
);
// 页面加载状态
const
[
afterAddressList
,
setAfterAddressList
]
=
useState
([]);
// 售后地址
const
[
afterAddressList
,
setAfterAddressList
]
=
useState
([]);
// 售后地址
const
[
supplierIdList
,
setSupplierIdList
]
=
useState
([]);
// 适用们店列表
const
[
supplierIdList
,
setSupplierIdList
]
=
useState
([]);
// 适用们店列表
...
@@ -57,7 +71,10 @@ const ServiceGoods = options => {
...
@@ -57,7 +71,10 @@ const ServiceGoods = options => {
const
[
specList
,
setSpecList
]
=
useState
([]);
// 规格列表
const
[
specList
,
setSpecList
]
=
useState
([]);
// 规格列表
const
[
editData
,
setEditData
]
=
useState
({});
// 编辑保存数据
const
[
editData
,
setEditData
]
=
useState
({});
// 编辑保存数据
const
[
newCategoryList
,
setNewCategoryList
]
=
useState
({});
const
[
newCategoryList
,
setNewCategoryList
]
=
useState
({});
const
[
takeawayEditData
,
setTakeawayEditData
]
=
useState
({});
// 外卖编辑保存数据
const
[
groupShopData
,
setGroupShopData
]
=
useState
(
''
);
// 从分组进入创建
const
[
visibleCacheEdit
,
setVisibleCacheEdit
]
=
useState
(
false
);
// 显示有缓存未保存提示
const
[
visibleCacheEdit
,
setVisibleCacheEdit
]
=
useState
(
false
);
// 显示有缓存未保存提示
const
[
takeawayInfoMation
,
setTakeawayInfoMation
]
=
useState
({});
const
[
checkFormList
]
=
useState
([
const
[
checkFormList
]
=
useState
([
basicRef
,
basicRef
,
attrRef
,
attrRef
,
...
@@ -65,6 +82,7 @@ const ServiceGoods = options => {
...
@@ -65,6 +82,7 @@ const ServiceGoods = options => {
settingRef
,
settingRef
,
settleOtrRef
,
settleOtrRef
,
picturesRef
,
picturesRef
,
takeawayRef
,
]);
]);
const
[
specKeyList
,
setSpecKeyList
]
=
useState
([]);
// 记录一级规格key字段
const
[
specKeyList
,
setSpecKeyList
]
=
useState
([]);
// 记录一级规格key字段
...
@@ -73,17 +91,19 @@ const ServiceGoods = options => {
...
@@ -73,17 +91,19 @@ const ServiceGoods = options => {
const
onValuesChange
=
e
=>
{
const
onValuesChange
=
e
=>
{
if
(
!
isEdit
)
{
if
(
!
isEdit
)
{
const
typeObj
=
{
type
:
productType
,
};
if
(
visibleCacheEdit
)
{
if
(
visibleCacheEdit
)
{
setVisibleCacheEdit
(
false
);
setVisibleCacheEdit
(
false
);
localStorage
.
remove
(
localAutoSaveKey
);
localStorage
.
remove
(
localAutoSaveKey
);
onAutoSaveValue
(
onAutoSaveValue
(
typeObj
,
!
0
);
{
type
:
productType
,
},
!
0
,
);
}
}
onAutoSaveValue
(
e
);
onAutoSaveValue
(
Object
.
assign
(
typeObj
,
e
));
}
if
(
productType
===
5
)
{
setTakeawayInfoMation
(
e
);
// console.log('takeawayInfoMation', takeawayInfoMation);
}
}
};
};
...
@@ -103,32 +123,80 @@ const ServiceGoods = options => {
...
@@ -103,32 +123,80 @@ const ServiceGoods = options => {
},
},
!
0
,
!
0
,
);
);
stockRef
.
current
.
onFinish
();
stockRef
.
current
&&
stockRef
.
current
.
onFinish
();
},
1000
);
},
1000
);
};
};
// 查询外卖商品详情
const
querGetShopDetail
=
async
params
=>
{
const
{
spuId
,
shopId
,
skuId
}
=
params
;
const
temp
=
{
id
:
spuId
,
shopId
,
skuId
,
};
const
{
data
}
=
await
apiGetShopDetail
(
temp
);
const
{
name
,
storageRackIds
,
firstCategoryId
,
secondCategoryId
,
thirdCategoryId
,
commonImageList
,
}
=
data
;
const
categoryId
=
[
firstCategoryId
,
secondCategoryId
,
thirdCategoryId
].
filter
(
item
=>
!!
item
);
const
editInfoMation
=
{
infoMation
:
{
name
,
productRefShopId
:
`
${
shopId
}
`
,
commonImageList
,
categoryId
,
storageRackIds
,
productType
:
5
,
},
};
setEditData
(
editInfoMation
);
setTakeawayEditData
(
data
);
setIsEdit
(
true
);
setPageLoading
(
false
);
};
const
onResetData
=
refresh
=>
{
const
onResetData
=
refresh
=>
{
setPageId
(
null
);
setPageId
(
null
);
setIsEdit
(
false
);
setIsEdit
(
false
);
setProductType
(
canAddNormal
?
1
:
4
);
setProductType
(
ptype
);
setEditData
({});
setEditData
({});
setSpecKeyList
([]);
setSpecKeyList
([]);
resetForm
();
resetForm
();
options
.
onChange
(
false
,
refresh
);
options
.
onChange
(
false
,
refresh
);
};
};
const
handleCancel
=
refresh
=>
{
const
refreshPageList
=
(
refresh
,
sendData
)
=>
{
onResetData
(
refresh
);
// 新增外卖商品 关闭之后列表到跳转对应分组的下
if
(
!
isEdit
&&
sendData
&&
+
sendData
.
type
===
5
&&
sendData
.
storageRackIds
&&
sendData
.
storageRackIds
.
length
>
0
)
{
PubSub
.
publish
(
'
refreshTakeAway
'
,
{
groupId
:
sendData
.
storageRackIds
[
0
],
});
}
};
const
handleCancel
=
(
refresh
,
sendData
)
=>
{
const
info
=
localStorage
.
get
(
localAutoSaveKey
);
const
info
=
localStorage
.
get
(
localAutoSaveKey
);
if
(
info
&&
Object
.
keys
(
info
).
length
>
1
)
{
if
(
info
&&
Object
.
keys
(
info
).
length
>
1
)
{
Modal
.
confirm
({
Modal
.
confirm
({
title
:
'
确认提示
'
,
title
:
'
确认提示
'
,
content
:
'
商品信息还未保存,确认关闭弹窗?
'
,
content
:
'
商品信息还未保存,确认关闭弹窗?
'
,
onOk
()
{
onOk
()
{
onResetData
(
refresh
);
refreshPageList
(
refresh
,
sendData
);
},
},
});
});
}
else
{
}
else
{
onResetData
(
refresh
);
refreshPageList
(
refresh
,
sendData
);
}
}
};
};
...
@@ -146,7 +214,6 @@ const ServiceGoods = options => {
...
@@ -146,7 +214,6 @@ const ServiceGoods = options => {
setSpecList
(
result
.
data
||
[]);
setSpecList
(
result
.
data
||
[]);
}
}
};
};
const
getAfterSalesAddrsPage
=
async
()
=>
{
const
getAfterSalesAddrsPage
=
async
()
=>
{
if
(
!
afterAddressList
.
length
)
{
if
(
!
afterAddressList
.
length
)
{
const
result
=
await
afterSalesAddrsPage
();
const
result
=
await
afterSalesAddrsPage
();
...
@@ -162,7 +229,7 @@ const ServiceGoods = options => {
...
@@ -162,7 +229,7 @@ const ServiceGoods = options => {
if
(
addResponse
.
data
)
{
if
(
addResponse
.
data
)
{
message
.
success
(
`
${
isEdit
?
'
修改
'
:
'
添加
'
}
成功!`
);
message
.
success
(
`
${
isEdit
?
'
修改
'
:
'
添加
'
}
成功!`
);
localStorage
.
remove
(
localAutoSaveKey
);
localStorage
.
remove
(
localAutoSaveKey
);
handleCancel
(
true
);
handleCancel
(
true
,
sendData
);
}
}
setPageLoading
(
false
);
setPageLoading
(
false
);
}
catch
(
error
)
{
}
catch
(
error
)
{
...
@@ -188,7 +255,6 @@ const ServiceGoods = options => {
...
@@ -188,7 +255,6 @@ const ServiceGoods = options => {
});
});
}
}
};
};
// 保存商品
// 保存商品
const
submitEvent
=
async
()
=>
{
const
submitEvent
=
async
()
=>
{
const
checkPromiseList
=
clearCurrent
(
checkFormList
).
map
(({
current
})
=>
current
.
onCheck
());
const
checkPromiseList
=
clearCurrent
(
checkFormList
).
map
(({
current
})
=>
current
.
onCheck
());
...
@@ -196,11 +262,21 @@ const ServiceGoods = options => {
...
@@ -196,11 +262,21 @@ const ServiceGoods = options => {
console
.
log
(
'
resuslt :>>
'
,
resuslt
);
console
.
log
(
'
resuslt :>>
'
,
resuslt
);
if
(
!
resuslt
.
includes
(
null
))
{
if
(
!
resuslt
.
includes
(
null
))
{
const
params
=
resuslt
.
reduce
((
origin
,
item
)
=>
{
const
params
=
resuslt
.
reduce
((
origin
,
item
)
=>
{
console
.
log
(
'
origin
'
,
origin
,
item
);
const
{
temp
,
...
other
}
=
item
;
const
{
temp
,
...
other
}
=
item
;
origin
[
temp
]
=
other
;
origin
[
temp
]
=
other
;
return
origin
;
return
origin
;
},
{});
},
{});
const
sendData
=
filterSendData
(
productType
,
params
);
const
sendData
=
filterSendData
(
productType
,
params
);
if
(
productType
===
5
)
{
console
.
log
(
sendData
,
'
sendData
'
);
if
(
+
sendData
?.
repertoryType
===
2
&&
sendData
?.
items
?.
length
<
2
)
{
message
.
error
(
'
最少生成2个sku
'
);
return
;
}
sendMerchantProductHttpRequest
(
sendData
);
return
;
}
if
(
isEdit
)
{
if
(
isEdit
)
{
sendData
.
id
=
pageId
;
sendData
.
id
=
pageId
;
}
}
...
@@ -285,7 +361,7 @@ const ServiceGoods = options => {
...
@@ -285,7 +361,7 @@ const ServiceGoods = options => {
}
}
}
else
{
}
else
{
// 默认生成一条规格数据
// 默认生成一条规格数据
stockRef
.
current
.
onFinish
();
stockRef
.
current
&&
stockRef
.
current
.
onFinish
();
}
}
setPageLoading
(
false
);
setPageLoading
(
false
);
})();
})();
...
@@ -309,7 +385,7 @@ const ServiceGoods = options => {
...
@@ -309,7 +385,7 @@ const ServiceGoods = options => {
},
[
isEdit
,
options
.
visible
]);
},
[
isEdit
,
options
.
visible
]);
useEffect
(()
=>
{
useEffect
(()
=>
{
setProductType
(
canAddNormal
?
1
:
4
);
setProductType
(
ptype
);
},
[
canAddNormal
]);
},
[
canAddNormal
]);
const
onSpecCommonImgEvent
=
useCallback
(
const
onSpecCommonImgEvent
=
useCallback
(
...
@@ -318,6 +394,19 @@ const ServiceGoods = options => {
...
@@ -318,6 +394,19 @@ const ServiceGoods = options => {
},
},
[
specKeyList
],
[
specKeyList
],
);
);
useEffect
(()
=>
{
// 外卖类型
if
(
Object
.
keys
(
takeAway
)?.
length
)
{
const
{
spuId
=
''
,
groupId
=
''
}
=
takeAway
;
if
(
spuId
)
{
querGetShopDetail
(
takeAway
);
}
if
(
groupId
)
{
setGroupShopData
(
takeAway
);
}
setProductType
(
5
);
}
},
[
takeAway
]);
const
onEventBus
=
(
event
,
params
)
=>
{
const
onEventBus
=
(
event
,
params
)
=>
{
if
(
event
===
'
cloneImg
'
)
{
if
(
event
===
'
cloneImg
'
)
{
...
@@ -396,14 +485,15 @@ const ServiceGoods = options => {
...
@@ -396,14 +485,15 @@ const ServiceGoods = options => {
},
},
});
});
};
};
const
providerValue
=
{
const
providerValue
=
{
pageId
,
pageId
,
isEdit
,
isEdit
,
productType
,
productType
,
canAddService
,
// 是否可以添加服务商品(电子卡券)
canAddService
,
// 是否可以添加服务商品(电子卡券)
canAddNormal
,
// 是否可以添加实物商品
canAddNormal
,
// 是否可以添加实物商品
canTakeawayService
,
// 是否可以添加外卖商品
isCard
:
productType
===
4
,
isCard
:
productType
===
4
,
isTakeawayService
:
productType
===
5
,
// 0, "商品删除" 1, "新建" 2, "提交审核" 3, "待审核" 4, "驳回" 5, "未上架" 6, "已上架" 7, "已下架"
// 0, "商品删除" 1, "新建" 2, "提交审核" 3, "待审核" 4, "驳回" 5, "未上架" 6, "已上架" 7, "已下架"
isNormal
:
SourceData
.
state
&&
SourceData
.
state
!==
4
,
// 商品不是驳回状态
isNormal
:
SourceData
.
state
&&
SourceData
.
state
!==
4
,
// 商品不是驳回状态
// 当商品进行编辑 & 类型不为电子卡券 & 商品状态不为驳回 禁用当前功能
// 当商品进行编辑 & 类型不为电子卡券 & 商品状态不为驳回 禁用当前功能
...
@@ -423,9 +513,13 @@ const ServiceGoods = options => {
...
@@ -423,9 +513,13 @@ const ServiceGoods = options => {
maskClosable=
{
false
}
maskClosable=
{
false
}
keyboard=
{
false
}
keyboard=
{
false
}
footer=
{
[
footer=
{
[
<
Button
key=
"draft"
type=
"primary"
ghost
loading=
{
pageLoading
}
onClick=
{
onSaveDraft
}
>
productType
===
5
?
(
保存草稿
''
</
Button
>,
)
:
(
<
Button
key=
"draft"
type=
"primary"
ghost
loading=
{
pageLoading
}
onClick=
{
onSaveDraft
}
>
保存草稿
</
Button
>
),
<
Button
key=
"submit"
type=
"primary"
loading=
{
pageLoading
}
onClick=
{
submitEvent
}
>
<
Button
key=
"submit"
type=
"primary"
loading=
{
pageLoading
}
onClick=
{
submitEvent
}
>
提交
提交
</
Button
>,
</
Button
>,
...
@@ -446,13 +540,19 @@ const ServiceGoods = options => {
...
@@ -446,13 +540,19 @@ const ServiceGoods = options => {
)
}
)
}
<
ServiceContext
.
Provider
value=
{
providerValue
}
>
<
ServiceContext
.
Provider
value=
{
providerValue
}
>
<
Title
title=
"商品类型"
/>
<
Title
title=
"商品类型"
/>
<
TaskTypeSelect
productType=
{
productType
}
onChange=
{
productChange
}
/>
<
TaskTypeSelect
productType=
{
productType
}
takeAway=
{
takeAway
}
onChange=
{
productChange
}
/>
<
Title
title=
"商品基本信息编辑"
/>
<
Title
title=
"商品基本信息编辑"
/>
<
FormInformationBasic
<
FormInformationBasic
ref=
{
basicRef
}
ref=
{
basicRef
}
editData=
{
editData
.
infoMation
}
editData=
{
editData
.
infoMation
}
groupShopData=
{
groupShopData
}
newCategoryList=
{
newCategoryList
}
newCategoryList=
{
newCategoryList
}
shopGetByProductType=
{
shopGetByProductType
}
categoryList=
{
categoryList
}
categoryList=
{
categoryList
}
virtualCategoryList=
{
virtualCategoryList
}
virtualCategoryList=
{
virtualCategoryList
}
brandList=
{
brandList
}
brandList=
{
brandList
}
...
@@ -460,6 +560,7 @@ const ServiceGoods = options => {
...
@@ -460,6 +560,7 @@ const ServiceGoods = options => {
specListData=
{
specListData
}
specListData=
{
specListData
}
onCategoryChange=
{
onCategoryChange
}
onCategoryChange=
{
onCategoryChange
}
onValuesChange=
{
onValuesChange
}
onValuesChange=
{
onValuesChange
}
// queryShopList={queryShopList}
/>
/>
{
[
1
,
2
].
includes
(
productType
)
&&
[
{
[
1
,
2
].
includes
(
productType
)
&&
[
...
@@ -472,32 +573,43 @@ const ServiceGoods = options => {
...
@@ -472,32 +573,43 @@ const ServiceGoods = options => {
onValuesChange=
{
onValuesChange
}
onValuesChange=
{
onValuesChange
}
/>,
/>,
]
}
]
}
{
productType
!==
5
&&
(
<
Title
title=
"价格与库存"
/>
<>
<
FormPriceOrStock
<
Title
title=
"价格与库存"
/>
ref=
{
stockRef
}
<
FormPriceOrStock
specList=
{
specList
}
ref=
{
stockRef
}
onSpecChange=
{
onSpecCommonImgEvent
}
specList=
{
specList
}
editData=
{
editData
.
infoSpecData
}
onSpecChange=
{
onSpecCommonImgEvent
}
skuList=
{
editData
.
skuList
}
editData=
{
editData
.
infoSpecData
}
onValuesChange=
{
onValuesChange
}
skuList=
{
editData
.
skuList
}
/>
onValuesChange=
{
onValuesChange
}
<
Title
title=
"规则设置"
/>
/>
{
productType
===
4
&&
(
</>
<
FormRuleSetting
)
}
ref=
{
settingRef
}
{
productType
!==
5
&&
(
editData=
{
editData
.
serviceItem
}
<>
supplierIdList=
{
supplierIdList
}
<
Title
title=
"规则设置"
/>
onValuesChange=
{
onValuesChange
}
{
productType
===
4
&&
(
/>
<
FormRuleSetting
ref=
{
settingRef
}
editData=
{
editData
.
serviceItem
}
supplierIdList=
{
supplierIdList
}
onValuesChange=
{
onValuesChange
}
/>
)
}
</>
)
}
{
productType
!==
5
&&
(
<>
<
FormRuleVPictures
ref=
{
picturesRef
}
specKeyItem=
{
specKeyList
}
editData=
{
editData
.
infoImageData
}
onValuesChange=
{
onValuesChange
}
/>
</>
)
}
)
}
<
FormRuleVPictures
ref=
{
picturesRef
}
specKeyItem=
{
specKeyList
}
editData=
{
editData
.
infoImageData
}
onValuesChange=
{
onValuesChange
}
/>
{
productType
===
4
&&
(
{
productType
===
4
&&
(
<
FormSettlementOthers
<
FormSettlementOthers
ref=
{
settleOtrRef
}
ref=
{
settleOtrRef
}
...
@@ -505,6 +617,18 @@ const ServiceGoods = options => {
...
@@ -505,6 +617,18 @@ const ServiceGoods = options => {
onValuesChange=
{
onValuesChange
}
onValuesChange=
{
onValuesChange
}
/>
/>
)
}
)
}
{
productType
===
5
&&
(
<>
<
FormTakeaway
ref=
{
takeawayRef
}
takeAway=
{
takeAway
}
editData=
{
takeawayEditData
}
takeawayInfoMation=
{
takeawayInfoMation
}
supplierIdList=
{
supplierIdList
}
onValuesChange=
{
onValuesChange
}
/>
</>
)
}
</
ServiceContext
.
Provider
>
</
ServiceContext
.
Provider
>
</
WrapperContainer
>
</
WrapperContainer
>
</
Spin
>
</
Spin
>
...
...
src/pages/ServiceGoods/service.js
View file @
d72841d4
...
@@ -117,3 +117,53 @@ export const apiEditDraft = data =>
...
@@ -117,3 +117,53 @@ export const apiEditDraft = data =>
prefix
:
goodsApi
,
prefix
:
goodsApi
,
data
,
data
,
});
});
// 菜单分组 http://yapi.quantgroups.com/project/389/interface/api/64044
export
const
apiQueryShopList
=
data
=>
request
.
post
(
'
/api/merchants/products/storageRack/listByShopIdAndStorageRackIds
'
,
{
prefix
:
goodsApi
,
data
:
stringify
(
_
.
omitBy
(
data
,
v
=>
!
v
)),
headers
:
{
'
Content-Type
'
:
'
application/x-www-form-urlencoded
'
,
},
});
// 新建分组
export
const
apiCreateShop
=
data
=>
request
.
post
(
'
/api/merchants/products/storageRack/create
'
,
{
prefix
:
goodsApi
,
data
,
});
// 新增外卖商品 http://yapi.quantgroups.com/project/389/interface/api/57324
export
const
apiAddTakeawayProducts
=
data
=>
request
.
post
(
'
/v1/channels/products/add
'
,
{
prefix
:
goodsApi
,
data
,
});
// 商品标签列表 http://yapi.quantgroups.com/project/389/interface/api/57979
export
const
apiTagList
=
data
=>
request
.
post
(
'
/api/merchants/products/tag/getAll
'
,
{
prefix
:
goodsApi
,
data
,
});
// 单位列表 http://yapi.quantgroups.com/project/389/interface/api/57179
export
const
apiUnits
=
data
=>
request
.
get
(
'
/api/merchants/products/units
'
,
{
prefix
:
goodsApi
,
data
,
});
// 获取shopids http://yapi.quantgroups.com/project/389/interface/api/38056
export
const
apiShopIds
=
data
=>
request
.
get
(
'
/api/merchants/shops/getBySupplierId?state=1&productBusiness=1
'
,
{
prefix
:
goodsApi
,
data
,
});
// 获取店铺详情 http://yapi.quantgroups.com/project/389/interface/api/57589
export
const
apiGetShopDetail
=
data
=>
request
.
post
(
'
/product/api/merchant/detail
'
,
{
prefix
:
goodsApi
,
data
:
stringify
(
_
.
omitBy
(
data
,
v
=>
!
v
)),
headers
:
{
'
Content-Type
'
:
'
application/x-www-form-urlencoded
'
,
},
});
src/pages/ServiceGoods/utils.js
View file @
d72841d4
...
@@ -109,7 +109,52 @@ const filterItems = (type, props) => {
...
@@ -109,7 +109,52 @@ const filterItems = (type, props) => {
};
};
export
const
filterSendData
=
(
type
,
params
)
=>
{
export
const
filterSendData
=
(
type
,
params
)
=>
{
const
{
infoMation
,
infoImageData
,
attributeApplyList
}
=
params
;
// takeawayItem 外卖商品
const
{
infoMation
,
infoImageData
,
attributeApplyList
,
takeawayItem
}
=
params
;
// 外卖商品
if
(
type
===
5
)
{
const
temp
=
Object
.
assign
({},
takeawayItem
?.
intactData
,
infoMation
);
const
deepTemp
=
JSON
.
parse
(
JSON
.
stringify
(
temp
));
deepTemp
.
categoryId
=
Array
.
isArray
(
deepTemp
.
categoryId
)
&&
deepTemp
.
categoryId
?.
slice
(
deepTemp
.
categoryId
?.
length
-
1
)?.
toString
();
deepTemp
.
productRefShopId
=
deepTemp
.
productRefShopId
.
toString
();
const
tempWeightName
=
JSON
.
parse
(
sessionStorage
.
getItem
(
'
weightUnits
'
));
deepTemp
.
items
.
forEach
(
item
=>
{
item
.
autoStock
=
item
.
autoStock
?
1
:
0
;
item
.
serviceItem
.
autoStock
=
item
?.
serviceItem
?.
autoStock
?
1
:
0
;
item
.
productStock
=
item
?.
serviceItem
?.
productStock
;
item
.
list
=
deepTemp
.
list
;
if
(
item
?.
specs
?.
length
)
{
item
.
specs
.
forEach
(
itm
=>
{
if
(
itm
?.
unit
&&
tempWeightName
.
includes
(
itm
?.
unit
))
{
itm
.
quantity
=
`
${
itm
?.
quantity
}
`.indexOf('约') > -1 ? itm?.quantity : `
约
$
{
itm
?.
quantity
}
`;
}
});
}
});
deepTemp.specList &&
deepTemp.specList.forEach(item => {
if (item?.specs?.length) {
item.specs.forEach(itm => {
if (itm?.unit) {
itm.unit =
(Array.isArray(itm?.unit) &&
itm?.unit?.length >= 2 &&
itm?.unit?.splice(itm?.unit?.length - 1)[0]) ||
itm?.unit;
}
if (itm?.unit && tempWeightName.includes(itm?.unit)) {
itm.quantity =
`
$
{
itm
?.
quantity
}
`.indexOf('约') > -1 ? itm?.quantity : `
约
$
{
itm
?.
quantity
}
`;
}
});
}
});
return deepTemp;
}
const items = filterItems(type, params);
const items = filterItems(type, params);
const commonImageList = type === 4 ? [] : infoImageData.commonImageList;
const commonImageList = type === 4 ? [] : infoImageData.commonImageList;
const obj = {
const obj = {
...
@@ -128,6 +173,7 @@ export const filterSendData = (type, params) => {
...
@@ -128,6 +173,7 @@ export const filterSendData = (type, params) => {
if (attributeApplyList && attributeApplyList.attributeApplyList) {
if (attributeApplyList && attributeApplyList.attributeApplyList) {
obj.attributeApplyList = attributeApplyList.attributeApplyList;
obj.attributeApplyList = attributeApplyList.attributeApplyList;
}
}
return obj;
return obj;
};
};
...
@@ -258,6 +304,11 @@ export const createProductData = (props, isEdit, skuList) => {
...
@@ -258,6 +304,11 @@ export const createProductData = (props, isEdit, skuList) => {
export const localAutoSaveKey = 'good-info-auto-save';
export const localAutoSaveKey = 'good-info-auto-save';
export const onAutoSaveValue = (e, isClear) => {
export const onAutoSaveValue = (e, isClear) => {
// 暂时去掉外卖类型
if (e && e.type === 5) {
localStorage.remove(localAutoSaveKey);
return;
}
const keys = Object.keys(e);
const keys = Object.keys(e);
if (
if (
e &&
e &&
...
@@ -272,6 +323,25 @@ export const onAutoSaveValue = (e, isClear) => {
...
@@ -272,6 +323,25 @@ export const onAutoSaveValue = (e, isClear) => {
localStorage.set(localAutoSaveKey, Object.assign({}, e));
localStorage.set(localAutoSaveKey, Object.assign({}, e));
} else {
} else {
const info = localStorage.get(localAutoSaveKey) || {};
const info = localStorage.get(localAutoSaveKey) || {};
localStorage
.
set
(
localAutoSaveKey
,
Object
.
assign
({
type
:
1
},
info
,
e
));
localStorage.set(localAutoSaveKey, Object.assign({}, info, e));
}
}
};
};
export const calcDescartes = array => {
console.log(array, 'array');
if (array.length < 2) return array[0] || [];
return [].reduce.call(array, (col, set) => {
const res = [];
col.forEach(c => {
set.forEach(s => {
const t = [].concat(Array.isArray(c) ? c : [c]);
t.push(s);
res.push(t);
});
});
return res;
});
};
src/pages/businessManage/info/data.js
0 → 100644
View file @
d72841d4
import
React
from
'
react
'
;
import
moment
from
'
moment
'
;
import
{
PlusOutlined
}
from
'
@ant-design/icons
'
;
import
{
notification
,
Tag
,
Tooltip
,
Input
}
from
'
antd
'
;
import
{
uploadFile
,
apiCategoryList
,
apiAddrArea
,
apiServiceFacility
,
apiBusinessDetail
,
apiBankList
,
}
from
'
../service
'
;
export
const
wrapperCol
=
{
xs
:
{
span
:
24
},
sm
:
{
span
:
12
},
};
export
const
formItemLayout
=
{
labelCol
:
{
xs
:
{
span
:
24
},
sm
:
{
span
:
8
},
},
wrapperCol
:
{
xs
:
{
span
:
24
},
sm
:
{
span
:
16
},
},
};
export
const
businessTypeDesc
=
{
1
:
'
到家业务
'
,
2
:
'
实物业务
'
,
3
:
'
到店业务
'
,
};
// 业务模式
export
const
businessModel
=
[
{
label
:
'
到家外卖业务(外卖配送业务)
'
,
value
:
1
},
{
label
:
'
实物商品业务员
'
,
value
:
2
},
{
label
:
'
到店业务(服务类业务)
'
,
value
:
3
},
];
export
const
signDateTypeList
=
[{
label
:
'
自商品售卖起默认一年
'
,
value
:
1
}];
export
const
legalPersonList
=
[{
label
:
'
长期
'
,
value
:
'
长期
'
}];
// 获取申请信息
export
async
function
getInfo
()
{
const
data
=
await
apiBusinessDetail
();
let
settlementType
=
1
;
const
res
=
data
.
data
;
if
(
res
)
{
if
(
res
.
facilities
)
{
res
.
customList
=
res
.
facilities
.
customList
||
[];
res
.
selfList
=
res
.
facilities
.
selfList
||
[];
}
res
.
signDateType
=
res
.
signDateType
?
[
res
.
signDateType
]
:
[];
res
.
accountOpenPermitImage
=
res
.
accountOpenPermitImage
?
[{
uid
:
0
,
url
:
res
.
accountOpenPermitImage
}]
:
[];
res
.
businessLicenseImage
=
res
.
businessLicenseImage
?
[{
uid
:
0
,
url
:
res
.
businessLicenseImage
}]
:
[];
res
.
idCardEmblemImage
=
res
.
idCardEmblemImage
?
[{
uid
:
0
,
url
:
res
.
idCardEmblemImage
}]
:
[];
res
.
idCardPortraitImage
=
res
.
idCardPortraitImage
?
[{
uid
:
0
,
url
:
res
.
idCardPortraitImage
}]
:
[];
res
.
primaryImage
=
res
.
primaryImage
?
[{
uid
:
0
,
url
:
res
.
primaryImage
}]
:
[];
res
.
sealImage
=
res
.
sealImage
?
[{
uid
:
0
,
url
:
res
.
sealImage
}]
:
[];
res
.
brandCertificate
=
res
.
brandCertificate
?
[{
uid
:
0
,
url
:
res
.
brandCertificate
}]
:
[];
// 非同名结算授权文件
res
.
differentNameAuthorizationImage
=
res
.
differentNameAuthorizationImage
?
[{
uid
:
0
,
url
:
res
.
brandCertificate
}]
:
[];
// 户口本本人页
res
.
householdRegisterImage
=
res
.
householdRegisterImage
?
[{
uid
:
0
,
url
:
res
.
householdRegisterImage
}]
:
[];
// 工商局
res
.
icbProofImage
=
res
.
icbProofImage
?
[{
uid
:
0
,
url
:
res
.
icbProofImage
}]
:
[];
if
(
res
.
categoryQualificateImage
&&
res
.
categoryQualificateImage
.
length
)
{
res
.
categoryQualificateImage
=
res
.
categoryQualificateImage
.
map
((
item
,
index
)
=>
({
uid
:
index
,
url
:
item
,
}));
}
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
);
}
if
(
settlementType
!==
null
)
{
settlementType
=
+
res
.
settlementType
;
}
}
// 身份证有效期处理
let
checkboxDisabled
=
false
;
if
(
res
.
legalPersonPeriod
)
{
const
date
=
res
.
legalPersonPeriod
.
split
(
'
-
'
)
||
[];
res
.
legalPersonStart
=
date
[
0
]
&&
moment
(
date
[
0
]);
res
.
legalPersonEnd
=
date
[
1
]
&&
date
[
1
]
!==
'
长期
'
?
moment
(
date
[
1
])
:
''
;
res
.
checked
=
date
[
1
]
&&
date
[
1
]
===
'
长期
'
?
[
'
长期
'
]
:
[];
checkboxDisabled
=
date
[
1
]
&&
date
[
1
]
===
'
长期
'
;
}
res
.
businessLicensePeriod
=
res
.
businessLicensePeriod
&&
moment
(
res
.
businessLicensePeriod
);
const
companyNamedis
=
!!
res
.
companyName
;
// 获取主营类目
let
categoryList
=
[];
if
(
res
.
productBusiness
?.
length
)
{
const
dataList
=
await
apiCategoryList
(
res
.
productBusiness
);
categoryList
=
dataList
.
data
;
}
this
.
setState
({
settlementType
,
businessInfo
:
res
,
checkboxDisabled
,
companyNamedis
,
categoryList
,
mainCategoryId
:
res
.
mainCategoryId
,
companyType
:
res
.
companyType
,
});
}
// 删除图片
function
delImg
(
keyName
,
e
)
{
this
.
setState
(
state
=>
{
if
(
keyName
===
'
categoryQualificateImage
'
)
{
state
.
businessInfo
.
categoryQualificateImage
.
forEach
((
item
,
index
)
=>
{
if
(
item
.
uid
===
e
.
uid
)
{
state
.
businessInfo
.
categoryQualificateImage
.
splice
(
index
,
1
);
}
});
}
else
{
state
.
businessInfo
[
keyName
].
splice
(
e
.
uid
,
1
);
}
return
{
businessInfo
:
state
.
businessInfo
,
};
});
}
// 上传图片
export
function
uploadPropsFn
(
{
keyName
,
limit
=
1
,
maxSize
=
1024
*
1024
*
5
,
maxSizeMsg
=
'
文件大小不能超过5M!
'
,
type
=
0
},
successCallback
=
()
=>
{},
)
{
const
that
=
this
;
let
timer
=
null
;
return
{
maxSize
,
async
customRequest
(
info
)
{
const
{
file
}
=
info
;
if
(
info
.
file
.
size
>
maxSize
)
{
notification
.
error
({
message
:
maxSizeMsg
});
return
;
}
if
(
that
.
state
.
businessInfo
[
keyName
]
&&
that
.
state
.
businessInfo
[
keyName
].
length
>=
limit
)
{
notification
.
error
({
message
:
`最多只能上传
${
limit
}
个文件!`
});
return
;
}
const
res
=
await
uploadFile
([
file
],
type
);
if
(
res
.
businessCode
!==
'
0000
'
)
{
return
;
}
const
url
=
res
.
data
?.[
0
];
that
.
setState
(
state
=>
{
const
imgList
=
state
.
businessInfo
[
keyName
]
||
[];
const
attachment
=
{
uid
:
imgList
.
length
||
0
,
name
:
file
?.
name
,
status
:
'
done
'
,
url
,
};
imgList
.
push
(
attachment
);
if
(
imgList
.
length
<=
limit
)
{
state
.
businessInfo
[
keyName
]
=
imgList
;
}
else
{
notification
.
error
({
message
:
`最多只能上传
${
limit
}
个文件!`
});
}
return
{
businessInfo
:
state
.
businessInfo
,
};
});
successCallback
(
keyName
,
url
);
// 需要把上传的数据存储下来
},
disabled
:
this
.
state
.
disabled
,
multiple
:
limit
>
1
,
listType
:
'
picture-card
'
,
showUploadList
:
true
,
accept
:
'
.png,.bmp,.gif,.jpeg,.jpg
'
,
onRemove
:
e
=>
delImg
.
call
(
this
,
keyName
,
e
),
beforeUpload
:
(
e
,
flist
)
=>
{
const
imgList
=
that
.
state
.
businessInfo
[
keyName
]
||
[];
if
(
flist
.
length
+
imgList
.
length
>
limit
)
{
clearTimeout
(
timer
);
timer
=
setTimeout
(()
=>
{
notification
.
error
({
message
:
`最多只能上传
${
limit
}
个文件!`
});
},
100
);
return
false
;
}
return
true
;
},
};
}
/** **** 自定义服务设施 start ***************************** */
// 关闭标签输入框
function
handleClose
(
removedTag
)
{
this
.
setState
(
state
=>
{
state
.
businessInfo
.
customList
=
state
.
businessInfo
.
customList
.
filter
(
tag
=>
tag
!==
removedTag
);
return
{
businessInfo
:
state
.
businessInfo
,
};
});
}
// 显示标签输入框
function
showInput
()
{
this
.
setState
({
tagVisible
:
true
},
()
=>
this
.
input
.
focus
());
}
// 标签内容改变
function
handleInputChange
(
e
)
{
if
(
e
&&
e
.
target
)
{
this
.
setState
({
tagValue
:
e
.
target
.
value
});
}
}
// 保存标签
function
handleInputConfirm
()
{
const
{
tagValue
}
=
this
.
state
;
if
(
tagValue
)
{
let
{
customList
}
=
this
.
state
.
businessInfo
;
if
(
tagValue
&&
customList
.
indexOf
(
tagValue
)
===
-
1
)
{
customList
=
[...
customList
,
tagValue
];
}
this
.
setState
(
state
=>
{
state
.
businessInfo
.
customList
=
customList
;
return
{
businessInfo
:
state
.
businessInfo
,
tagVisible
:
false
,
tagValue
:
''
,
};
});
}
}
// 渲染标签
export
function
renderServiceTags
()
{
const
that
=
this
;
return
(
<
div
>
{
that
.
state
.
businessInfo
.
customList
&&
that
.
state
.
businessInfo
.
customList
.
map
(
tag
=>
{
const
isLongTag
=
tag
.
length
>
20
;
const
tagElem
=
(
<
Tag
key
=
{
tag
}
closable
onClose
=
{()
=>
handleClose
.
call
(
that
,
tag
)}
>
{
isLongTag
?
`
${
tag
.
slice
(
0
,
20
)}
...`
:
tag
}
<
/Tag
>
);
return
isLongTag
?
(
<
Tooltip
title
=
{
tag
}
key
=
{
tag
}
>
{
tagElem
}
<
/Tooltip
>
)
:
(
tagElem
);
})}
{
that
.
state
.
tagVisible
&&
(
<
Input
// eslint-disable-next-line react/no-this-in-sfc
ref
=
{
this
.
saveInputRef
}
type
=
"
text
"
size
=
"
small
"
style
=
{{
width
:
78
}}
value
=
{
that
.
state
.
tagValue
}
onChange
=
{
e
=>
handleInputChange
.
call
(
that
,
e
)}
onBlur
=
{
e
=>
handleInputConfirm
.
call
(
that
,
e
)}
onPressEnter
=
{
e
=>
handleInputConfirm
.
call
(
that
,
e
)}
/
>
)}
{
!
that
.
state
.
tagVisible
&&
(
<
Tag
onClick
=
{()
=>
showInput
.
call
(
that
)}
style
=
{{
background
:
'
#fff
'
,
borderStyle
:
'
dashed
'
}}
>
<
PlusOutlined
/>
新增
<
/Tag
>
)}
<
/div
>
);
}
/** **** 自定义服务设施 end ***************************** */
// 获取服务设施
export
async
function
getServiceFacility
()
{
const
res
=
await
apiServiceFacility
();
if
(
res
.
data
)
{
this
.
setState
({
serviceFacilitys
:
res
.
data
,
});
}
}
// 开户行
export
async
function
getBankList
()
{
const
res
=
await
apiBankList
();
if
(
res
.
data
)
{
this
.
setState
({
bankList
:
res
.
data
,
});
}
}
// 获取地址省
export
async
function
getAreaAddr
()
{
const
data
=
await
apiAddrArea
();
const
areaAddr
=
data
.
data
||
null
;
if
(
areaAddr
)
{
const
res
=
areaAddr
.
map
(
item
=>
({
isLeaf
:
false
,
loading
:
false
,
label
:
item
.
addrName
,
value
:
item
.
addrId
,
}));
// 编辑时 回显 市、区、街道
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
],
});
}
}
src/pages/businessManage/info/index.jsx
0 → 100644
View file @
d72841d4
import
React
,
{
Component
}
from
'
react
'
;
import
{
history
}
from
'
umi
'
;
import
moment
from
'
moment
'
;
import
{
ArrowRightOutlined
,
UploadOutlined
}
from
'
@ant-design/icons
'
;
import
{
Form
}
from
'
@ant-design/compatible
'
;
import
'
@ant-design/compatible/assets/index.css
'
;
import
{
Select
,
Input
,
Radio
,
Checkbox
,
DatePicker
,
Upload
,
Button
,
Card
,
Row
,
Col
,
Cascader
,
notification
,
Spin
,
Tabs
,
}
from
'
antd
'
;
import
styles
from
'
./style.less
'
;
import
{
wrapperCol
,
uploadPropsFn
,
formItemLayout
,
renderServiceTags
,
loadData
,
getAreaAddr
,
getServiceFacility
,
businessModel
,
getInfo
,
getBankList
,
businessTypeDesc
,
signDateTypeList
,
legalPersonList
,
}
from
'
./data
'
;
import
{
validatePhone
,
validateEMail
,
validNumber
}
from
'
@/utils/validator
'
;
import
{
getErrorMessage
}
from
'
@/utils/utils
'
;
import
MapModal
from
'
@/components/BaiduMap
'
;
import
{
apiCategoryList
,
apiEditStoreInfo
,
apiRecognize
,
apiRevision
}
from
'
../service
'
;
import
{
infoTypeFind
,
infoTypeChecked
,
infoTypeEdit
,
infoTypeRevision
,
infoTypeInfo
,
}
from
'
../staticdata
'
;
const
{
Option
}
=
Select
;
const
{
Item
:
FormItem
}
=
Form
;
const
{
RangePicker
}
=
DatePicker
;
const
{
TabPane
}
=
Tabs
;
const
carID
=
301008
;
// 汽车类商家
const
fileterBrandOptions
=
(
input
,
options
)
=>
options
.
children
.
includes
(
input
);
class
BusinessInfo
extends
Component
{
getFieldDecorator
=
this
.
props
?.
form
?.
getFieldDecorator
;
setFieldsValue
=
this
.
props
?.
form
?.
setFieldsValue
;
state
=
{
id
:
null
,
type
:
infoTypeFind
,
businessInfo
:
{
customList
:
[],
settlementType
:
1
,
companyType
:
''
,
},
areaAddr
:
[],
// 四级地址列表
categoryList
:
[],
// 主要类目
serviceFacilitys
:
[],
// 服务设施
bankList
:
[],
// 开户行
// eslint-disable-next-line react/no-unused-state
tagVisible
:
false
,
// eslint-disable-next-line react/no-unused-state
tagValue
:
''
,
settlementType
:
1
,
loading
:
false
,
visibleMap
:
false
,
visibleLoading
:
false
,
calculateType
:
[
1
,
1
],
checkboxDisabled
:
false
,
mainCategoryId
:
null
,
companyNamedis
:
false
,
// 公司名称
companyType
:
null
,
// 企业类型
};
async
componentDidMount
()
{
await
getInfo
.
call
(
this
);
getAreaAddr
.
call
(
this
);
getServiceFacility
.
call
(
this
);
getBankList
.
call
(
this
);
}
// 主营类目
onMainCategory
(
e
)
{
this
.
setState
({
mainCategoryId
:
e
,
});
}
// 长期
oncheckedChange
=
e
=>
{
const
str
=
e
.
toString
();
this
.
setState
({
checkboxDisabled
:
str
===
'
长期
'
,
});
this
.
props
.
form
.
setFieldsValue
({
legalPersonEnd
:
''
,
});
};
// eslint-disable-next-line react/sort-comp
getDataInfo
=
type
=>
({
key
:
type
,
name
:
businessTypeDesc
[
type
],
chargeMethod
:
1
,
calculateType
:
1
,
});
// 计费类型改变
onChangeCalculateType
=
(
e
,
i
)
=>
{
this
.
setState
(
state
=>
{
const
{
calculateType
}
=
state
;
calculateType
[
i
]
=
+
e
;
return
{
calculateType
,
};
});
};
static
getDerivedStateFromProps
()
{
return
null
;
}
// 帐号类型切换
onChangeSettlType
(
e
)
{
this
.
setState
({
settlementType
:
e
,
});
}
// 切换企业类型
onChangeCompanyType
=
e
=>
{
const
{
value
}
=
e
.
target
;
this
.
setState
({
companyType
:
value
,
});
let
type
=
null
;
if
([
1
,
3
].
includes
(
value
))
{
type
=
1
;
}
else
{
type
=
2
;
}
this
.
onChangeSettlType
(
type
);
this
.
props
.
form
.
setFieldsValue
({
settlementType
:
type
,
});
};
// 处理图片
dealImgInfo
=
async
(
type
,
url
)
=>
{
const
imgType
=
{
businessLicenseImage
:
2
,
idCardPortraitImage
:
5
,
idCardEmblemImage
:
4
,
};
if
(
!
url
)
{
return
;
}
this
.
setState
({
visibleLoading
:
true
,
});
const
data
=
await
apiRecognize
({
imageUrl
:
url
,
imageType
:
imgType
[
type
],
});
if
(
data
.
businessCode
===
'
0000
'
)
{
const
res
=
data
.
data
;
const
info
=
{};
this
.
setState
(
state
=>
{
if
(
type
===
'
businessLicenseImage
'
)
{
info
.
socialCode
=
res
.
socialCode
||
''
;
info
.
companyName
=
res
.
companyName
||
''
;
info
.
businessLicensePeriod
=
res
.
businessLicensePeriod
?
moment
(
res
.
businessLicensePeriod
)
:
''
;
}
else
if
(
type
===
'
idCardPortraitImage
'
)
{
info
.
legalPersonName
=
res
.
legalPersonName
||
''
;
info
.
legalPersonIdCard
=
res
.
legalPersonIdCard
||
''
;
}
else
if
(
type
===
'
idCardEmblemImage
'
&&
res
.
legalPersonPeriod
)
{
// 身份证有效期处理
const
date
=
res
.
legalPersonPeriod
.
split
(
'
-
'
)
||
[];
info
.
legalPersonStart
=
date
[
0
]
&&
moment
(
date
[
0
]);
info
.
legalPersonEnd
=
date
[
1
]
&&
date
[
1
]
!==
'
长期
'
?
moment
(
date
[
1
])
:
''
;
info
.
checked
=
date
[
1
]
&&
date
[
1
]
===
'
长期
'
?
[
'
长期
'
]
:
[];
const
checkboxDisabled
=
date
[
1
]
&&
date
[
1
]
===
'
长期
'
;
this
.
setState
({
checkboxDisabled
,
});
// info.legalPersonPeriod = res.legalPersonPeriod
// .replace(/\./g, '/')
// .split('-')
// .map(o => moment(o));
}
return
{
businessInfo
:
Object
.
assign
(
state
.
businessInfo
,
info
),
};
});
this
.
props
.
form
.
setFieldsValue
({
...
info
,
});
}
else
{
notification
.
error
({
message
:
data
.
msg
});
}
this
.
setState
({
visibleLoading
:
false
,
});
};
/* eslint-disable no-return-assign */
saveInputRef
=
input
=>
(
this
.
input
=
input
);
// 返回
onCancel
=
()
=>
{
getInfo
.
call
(
this
);
};
// 提交
handleSubmit
=
e
=>
{
e
.
preventDefault
();
this
.
props
.
form
.
validateFields
(
async
(
err
,
values
)
=>
{
const
obj
=
Object
.
assign
({},
values
);
// , this.state.businessInfo
if
(
!
err
)
{
const
imgs
=
this
.
state
.
businessInfo
;
obj
.
businessLicensePeriod
=
moment
(
obj
.
businessLicensePeriod
).
format
(
'
YYYY-MM-DD
'
);
const
legalPersonStart
=
moment
(
obj
.
legalPersonStart
).
format
(
'
YYYY/MM/DD
'
);
const
legalPersonEnd
=
this
.
state
.
checkboxDisabled
?
'
长期
'
:
moment
(
obj
.
legalPersonEnd
).
format
(
'
YYYY/MM/DD
'
);
obj
.
legalPersonPeriod
=
`
${
legalPersonStart
}
-
${
legalPersonEnd
}
`
;
obj
.
facilities
=
{
customList
:
this
.
state
.
businessInfo
.
customList
,
selfList
:
obj
.
selfList
,
};
const
areaArr
=
[
'
provinceId
'
,
'
cityId
'
,
'
countyId
'
,
'
townId
'
];
obj
.
addr
.
forEach
((
item
,
i
)
=>
{
obj
[
areaArr
[
i
]]
=
item
;
});
obj
.
accountOpenPermitImage
=
(
imgs
?.
accountOpenPermitImage
?.
length
&&
imgs
.
accountOpenPermitImage
[
0
].
url
)
||
''
;
if
(
obj
.
supplierRateDTOList
&&
obj
.
supplierRateDTOList
.
length
)
{
obj
.
supplierRateDTOList
.
forEach
(
item
=>
{
if
(
item
.
ratedate
&&
item
.
ratedate
.
length
)
{
item
.
startDate
=
moment
(
item
.
ratedate
[
0
]).
format
(
'
YYYY-MM-DD
'
);
item
.
endDate
=
moment
(
item
.
ratedate
[
1
]).
format
(
'
YYYY-MM-DD
'
);
delete
item
.
ratedate
;
}
});
}
obj
.
businessLicenseImage
=
(
imgs
?.
businessLicenseImage
?.
length
&&
imgs
?.
businessLicenseImage
[
0
].
url
)
||
''
;
obj
.
idCardEmblemImage
=
(
imgs
?.
idCardEmblemImage
?.
length
&&
imgs
?.
idCardEmblemImage
[
0
].
url
)
||
''
;
obj
.
idCardPortraitImage
=
(
imgs
?.
idCardPortraitImage
?.
length
&&
imgs
?.
idCardPortraitImage
[
0
].
url
)
||
''
;
obj
.
primaryImage
=
(
imgs
?.
primaryImage
?.
length
&&
imgs
?.
primaryImage
[
0
].
url
)
||
''
;
obj
.
sealImage
=
(
imgs
?.
sealImage
?.
length
&&
imgs
?.
sealImage
[
0
].
url
)
||
''
;
// 新增
obj
.
brandCertificate
=
(
imgs
?.
brandCertificate
?.
length
&&
imgs
?.
brandCertificate
[
0
]?.
url
)
||
''
;
obj
.
differentNameAuthorizationImage
=
(
imgs
?.
differentNameAuthorizationImage
?.
length
&&
imgs
?.
differentNameAuthorizationImage
[
0
]?.
url
)
||
''
;
obj
.
householdRegisterImage
=
(
imgs
?.
householdRegisterImage
?.
length
&&
imgs
?.
householdRegisterImage
[
0
]?.
url
)
||
''
;
obj
.
icbProofImage
=
(
imgs
?.
icbProofImage
?.
length
&&
imgs
?.
icbProofImage
[
0
]?.
url
)
||
''
;
obj
.
applySource
=
1
;
obj
.
signDateType
=
1
;
if
(
imgs
.
otherImage
&&
imgs
.
otherImage
.
length
)
{
obj
.
otherImage
=
imgs
.
otherImage
.
map
(
item
=>
item
.
url
);
}
else
{
delete
obj
.
otherImage
;
}
if
(
imgs
.
categoryQualificateImage
&&
imgs
.
categoryQualificateImage
.
length
)
{
const
list
=
[];
imgs
.
categoryQualificateImage
.
forEach
(
item
=>
{
list
.
push
(
item
.
url
);
});
obj
.
categoryQualificateImage
=
list
;
}
else
{
delete
obj
.
categoryQualificateImage
;
}
obj
.
legalPersonIdCard
=
obj
.
legalPersonIdCard
?.
toLocaleUpperCase
()
||
''
;
obj
.
bankAccountLicenseNum
=
obj
.
bankAccountLicenseNum
?.
toLocaleUpperCase
()
||
''
;
obj
.
socialCode
=
obj
.
socialCode
?.
toLocaleUpperCase
()
||
''
;
obj
.
id
=
this
.
state
.
id
;
obj
.
headImage
=
obj
.
primaryImage
;
this
.
setState
({
loading
:
true
,
});
const
data
=
await
apiEditStoreInfo
(
obj
);
if
(
data
.
businessCode
===
'
0000
'
)
{
notification
.
success
({
message
:
`
${
data
.
msg
}
!~`
});
}
this
.
setState
({
loading
:
false
,
});
}
else
{
const
message
=
getErrorMessage
(
err
);
notification
.
warning
({
message
});
}
});
};
onSetPoint
=
e
=>
{
this
.
setFieldsValue
({
latitude
:
e
.
lat
,
longitude
:
e
.
lng
,
});
};
// 修改公司名称
setCompanyName
=
()
=>
{
const
val
=
this
.
state
.
companyNamedis
;
this
.
setState
({
companyNamedis
:
!
val
,
});
if
(
!
val
)
{
this
.
props
.
form
.
setFieldsValue
({
companyName
:
this
.
state
.
businessInfo
.
companyName
,
icbProofImage
:
''
,
householdRegisterImage
:
''
,
});
}
};
openMap
(
e
,
disabled
)
{
if
(
!
disabled
)
{
this
.
setState
({
visibleMap
:
e
,
});
}
}
// eslint-disable-next-line class-methods-use-this
disabledDate
(
current
)
{
return
current
&&
current
<
moment
(
moment
().
format
(
'
YYYY-MM-DD
'
));
}
onChangeBusinessModel
=
e
=>
{
this
.
getCategoryList
(
e
);
this
.
props
.
form
.
setFieldsValue
({
mainCategoryId
:
''
,
});
};
// 获取主营类目
async
getCategoryList
(
e
)
{
const
data
=
await
apiCategoryList
(
e
);
if
(
!
data
.
data
)
return
;
this
.
setState
({
categoryList
:
data
.
data
});
}
render
()
{
const
{
form
:
{
getFieldDecorator
},
}
=
this
.
props
;
const
{
businessInfo
,
type
,
checkboxDisabled
,
mainCategoryId
,
companyNamedis
,
companyType
,
}
=
this
.
state
;
return
(
<
div
className=
{
styles
.
infoBox
}
>
<
Form
className=
"login-form"
onSubmit=
{
this
.
handleSubmit
}
{
...
formItemLayout
}
>
<
Card
title=
"店铺基本信息"
>
<
Row
gutter=
{
24
}
>
<
Col
span=
{
24
}
>
<
FormItem
label=
"业务模式"
labelCol=
{
{
span
:
4
}
}
>
{
getFieldDecorator
(
'
productBusiness
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请选择业务模式!
'
}],
initialValue
:
businessInfo
.
productBusiness
,
})(
<
Checkbox
.
Group
options=
{
businessModel
}
onChange=
{
e
=>
this
.
onChangeBusinessModel
(
e
)
}
disabled=
{
+
mainCategoryId
===
carID
}
/>,
)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
24
}
>
<
FormItem
label=
"主营类目"
labelCol=
{
{
span
:
4
}
}
>
{
getFieldDecorator
(
'
mainCategoryId
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请选择主营类目!
'
}],
initialValue
:
businessInfo
.
mainCategoryId
,
})(
<
Select
onChange=
{
e
=>
this
.
onMainCategory
(
e
)
}
showSearch
filterOption=
{
(
input
,
option
)
=>
option
.
props
.
children
.
toLowerCase
().
indexOf
(
input
.
toLowerCase
())
>=
0
}
disabled=
{
+
businessInfo
.
mainCategoryId
===
301008
}
>
{
this
.
state
.
categoryList
.
map
(
item
=>
(
<
Option
value=
{
item
.
id
}
key=
{
item
.
id
}
>
{
item
.
name
}
</
Option
>
))
}
</
Select
>,
)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
24
}
>
<
FormItem
label=
"商户名称"
labelCol=
{
{
span
:
4
}
}
>
{
getFieldDecorator
(
'
name
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请输入商户名称!
'
}],
initialValue
:
businessInfo
.
name
,
})(<
Input
maxLength=
{
32
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
24
}
>
<
FormItem
label=
"店铺区域"
labelCol=
{
{
span
:
4
}
}
>
{
getFieldDecorator
(
'
addr
'
,
{
rules
:
[{
required
:
true
,
type
:
'
array
'
,
message
:
'
请选择店铺区域!
'
}],
initialValue
:
businessInfo
.
addr
,
})(
<
Cascader
options=
{
this
.
state
.
areaAddr
}
loadData=
{
e
=>
loadData
.
call
(
this
,
e
)
}
changeOnSelect
/>,
)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
24
}
>
<
FormItem
label=
"经营地址"
labelCol=
{
{
span
:
4
}
}
>
{
getFieldDecorator
(
'
detailAddress
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请输入经营地址!
'
}],
initialValue
:
businessInfo
.
detailAddress
,
})(<
Input
maxLength=
{
500
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"联系人姓名"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
contactName
'
,
{
rules
:
[
{
required
:
true
,
message
:
'
请输入联系人姓名!
'
},
{
pattern
:
/^
[
A-Za-z
\u
4e00-
\u
9fa5
]
+$/
,
message
:
'
请输入汉字或字母!
'
},
],
initialValue
:
businessInfo
.
contactName
,
})(<
Input
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"联系人手机号"
labelCol=
{
{
span
:
5
}
}
>
{
getFieldDecorator
(
'
contactPhone
'
,
{
rules
:
[
{
required
:
true
,
message
:
'
请输入联系人手机号!
'
},
{
validator
:
validatePhone
,
message
:
'
请输入正确的手机号!
'
},
],
initialValue
:
businessInfo
.
contactPhone
,
})(<
Input
maxLength=
{
11
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"联系人邮箱"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
contactEmail
'
,
{
rules
:
[
{
required
:
true
,
message
:
'
请输入联系人邮箱!
'
},
{
validator
:
validateEMail
,
message
:
'
请输入正确的邮箱!
'
},
],
initialValue
:
businessInfo
.
contactEmail
,
})(<
Input
/>)
}
</
FormItem
>
</
Col
>
{
+
mainCategoryId
!==
carID
&&
(
<>
<
Col
span=
{
12
}
>
<
FormItem
label=
"客服电话"
labelCol=
{
{
span
:
5
}
}
>
{
getFieldDecorator
(
'
servicePhone
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请输入客服电话!
'
}],
initialValue
:
businessInfo
.
servicePhone
,
})(<
Input
maxLength=
{
11
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
24
}
>
<
FormItem
label=
"签约日期"
labelCol=
{
{
span
:
4
}
}
>
{
getFieldDecorator
(
'
signDateType
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请选择签约日期
'
}],
initialValue
:
businessInfo
.
signDateType
,
})(<
Checkbox
.
Group
options=
{
signDateTypeList
}
/>)
}
</
FormItem
>
</
Col
>
</>
)
}
</
Row
>
</
Card
>
<
Card
title=
"店铺营业信息"
>
<
Col
span=
{
12
}
className=
{
styles
.
imgList
}
>
<
FormItem
label=
"商户头图"
labelCol=
{
{
span
:
8
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
primaryImage
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请上传商户头图!
'
}],
initialValue
:
businessInfo
.
primaryImage
,
})(
<
Upload
{
...
uploadPropsFn
.
call
(
this
,
{
keyName
:
'
primaryImage
',
type
:
1
})}
fileList=
{
businessInfo
.
primaryImage
}
>
<
UploadOutlined
/>
上传文件
</
Upload
>,
)
}
</
FormItem
>
</
Col
>
{
+
mainCategoryId
!==
carID
&&
(
<>
<
Col
span=
{
24
}
>
<
FormItem
label=
"服务设施"
labelCol=
{
{
span
:
4
}
}
>
{
getFieldDecorator
(
'
selfList
'
,
{
initialValue
:
businessInfo
.
selfList
,
})(
<
Select
mode=
"multiple"
filterOption=
{
fileterBrandOptions
}
>
{
this
.
state
.
serviceFacilitys
.
map
(
item
=>
(
<
Option
value=
{
item
.
code
}
key=
{
item
.
code
}
>
{
item
.
desc
}
</
Option
>
))
}
</
Select
>,
)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
24
}
>
<
FormItem
label=
"自定义服务设施"
labelCol=
{
{
span
:
4
}
}
>
{
getFieldDecorator
(
'
customList
'
,
{
initialValue
:
businessInfo
.
customList
,
})(
renderServiceTags
.
call
(
this
))
}
</
FormItem
>
</
Col
>
</>
)
}
</
Card
>
<
Card
title=
"证照信息录入区"
>
<
Row
gutter=
{
24
}
>
{
+
mainCategoryId
!==
carID
&&
(
<
Col
span=
{
24
}
>
<
FormItem
label=
"企业类型"
labelCol=
{
{
span
:
4
}
}
>
{
getFieldDecorator
(
'
companyType
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请选择企业类型!
'
}],
initialValue
:
businessInfo
.
companyType
,
})(
<
Radio
.
Group
onChange=
{
this
.
onChangeCompanyType
}
disabled=
{
businessInfo
.
companyType
}
>
<
Radio
value=
{
1
}
>
一般纳税人
</
Radio
>
<
Radio
value=
{
2
}
>
小规模
</
Radio
>
<
Radio
value=
{
3
}
>
个体工商
</
Radio
>
</
Radio
.
Group
>,
)
}
</
FormItem
>
</
Col
>
)
}
<
Col
span=
{
24
}
className=
{
styles
.
imgList
}
>
<
FormItem
label=
"营业执照"
labelCol=
{
{
span
:
4
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
businessLicenseImage
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请上传营业执照!
'
}],
initialValue
:
businessInfo
.
businessLicenseImage
,
})(
<
Upload
{
...
uploadPropsFn
.
call
(
this
,
{
keyName
:
'
businessLicenseImage
',
type
:
2
},
this
.
dealImgInfo
,
)}
fileList=
{
businessInfo
.
businessLicenseImage
}
>
<
UploadOutlined
/>
上传文件
</
Upload
>,
)
}
</
FormItem
>
</
Col
>
{
+
mainCategoryId
!==
carID
&&
(
<>
<
Col
span=
{
12
}
>
<
Row
>
<
Col
span=
{
4
}
style=
{
{
marginTop
:
'
4px
'
}
}
>
{
businessInfo
.
companyName
&&
(
<
Button
onClick=
{
this
.
setCompanyName
}
>
修改
</
Button
>
)
}
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"公司名称"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
companyName
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请输入公司名称!
'
}],
initialValue
:
businessInfo
.
companyName
,
})(<
Input
maxLength=
{
50
}
disabled=
{
companyNamedis
}
/>)
}
</
FormItem
>
</
Col
>
</
Row
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"统一社会信用代码"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
socialCode
'
,
{
rules
:
[
{
required
:
true
,
message
:
'
请输入统一社会信用代码!
'
},
{
pattern
:
/^
[
A-Za-z0-9
]
*$/
,
message
:
'
仅支持输入数字和字母
'
},
],
initialValue
:
businessInfo
.
socialCode
,
})(<
Input
maxLength=
{
18
}
/>)
}
</
FormItem
>
</
Col
>
{
(
!
companyNamedis
&&
businessInfo
.
companyType
&&
businessInfo
.
companyType
!==
2
)
||
(
!
companyNamedis
&&
businessInfo
?.
icbProofImage
?.
length
)
?
(
<
Col
span=
{
12
}
>
<
FormItem
label=
"工商局变更证明"
labelCol=
{
{
span
:
8
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
icbProofImage
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请上传工商局变更证明!
'
}],
initialValue
:
businessInfo
.
icbProofImage
,
})(
<
Upload
{
...
uploadPropsFn
.
call
(
this
,
{
keyName
:
'
icbProofImage
',
limit
:
1,
})}
fileList=
{
businessInfo
.
icbProofImage
}
>
<
UploadOutlined
/>
上传文件
</
Upload
>,
)
}
</
FormItem
>
</
Col
>
)
:
(
''
)
}
{
(
!
companyNamedis
&&
businessInfo
.
companyType
&&
businessInfo
.
companyType
===
2
)
||
(
!
companyNamedis
&&
businessInfo
?.
householdRegisterImage
?.
length
)
?
(
<
Col
span=
{
12
}
>
<
FormItem
label=
"户口本本人页"
labelCol=
{
{
span
:
8
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
householdRegisterImage
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请上传户口本本人页!
'
}],
initialValue
:
businessInfo
.
householdRegisterImage
,
})(
<
Upload
{
...
uploadPropsFn
.
call
(
this
,
{
keyName
:
'
householdRegisterImage
',
limit
:
1,
})}
fileList=
{
businessInfo
.
householdRegisterImage
}
>
<
UploadOutlined
/>
上传文件
</
Upload
>,
)
}
</
FormItem
>
</
Col
>
)
:
(
''
)
}
<
Col
span=
{
24
}
>
<
FormItem
label=
"营业执照有效期"
labelCol=
{
{
span
:
4
}
}
>
{
getFieldDecorator
(
'
businessLicensePeriod
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请选择营业执照有效期!
'
}],
initialValue
:
businessInfo
.
businessLicensePeriod
,
})(<
DatePicker
maxLength=
{
50
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
24
}
>
<
FormItem
label=
"类目所需资质"
labelCol=
{
{
span
:
4
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
categoryQualificateImage
'
,
{
initialValue
:
businessInfo
.
categoryQualificateImage
,
})(
<
Upload
{
...
uploadPropsFn
.
call
(
this
,
{
keyName
:
'
categoryQualificateImage
',
type
:
6,
limit
:
9,
})}
fileList=
{
businessInfo
.
categoryQualificateImage
}
>
<
UploadOutlined
/>
上传文件
</
Upload
>,
)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
24
}
>
<
FormItem
label=
"电子签章"
labelCol=
{
{
span
:
4
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
sealImage
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请上传电子签章!
'
}],
initialValue
:
businessInfo
.
sealImage
,
})(
<
Upload
{
...
uploadPropsFn
.
call
(
this
,
{
keyName
:
'
sealImage
',
type
:
3,
maxSize
:
1024
*
200,
maxSizeMsg
:
'文件大小不能超过200
K
',
limit
:
1,
})}
fileList=
{
businessInfo
.
sealImage
}
>
<
UploadOutlined
/>
上传文件
</
Upload
>,
)
}
</
FormItem
>
</
Col
>
</>
)
}
{
+
mainCategoryId
===
carID
&&
(
<>
<
Col
span=
{
24
}
>
<
FormItem
label=
"授权品牌"
labelCol=
{
{
span
:
4
}
}
>
{
getFieldDecorator
(
'
brand
'
,
{
initialValue
:
businessInfo
.
brand
,
})(<
Input
maxLength=
{
32
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
24
}
>
<
FormItem
label=
"品牌经销商授权书"
labelCol=
{
{
span
:
4
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
brandCertificate
'
,
{
initialValue
:
businessInfo
.
brandCertificate
,
})(
<
Upload
{
...
uploadPropsFn
.
call
(
this
,
{
keyName
:
'
brandCertificate
',
limit
:
1,
})}
fileList=
{
businessInfo
.
brandCertificate
}
>
<
UploadOutlined
/>
上传文件
</
Upload
>,
)
}
</
FormItem
>
</
Col
>
</>
)
}
</
Row
>
</
Card
>
<
Card
title=
"法人信息录入区"
>
<
Row
gutter=
{
24
}
>
{
+
mainCategoryId
!==
carID
&&
(
<>
<
Col
span=
{
12
}
className=
{
styles
.
imgList
}
>
<
FormItem
label=
"法人身份证人像面"
labelCol=
{
{
span
:
8
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
idCardPortraitImage
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请上传身份证人像面!
'
}],
initialValue
:
businessInfo
.
idCardPortraitImage
,
})(
<
Upload
{
...
uploadPropsFn
.
call
(
this
,
{
keyName
:
'
idCardPortraitImage
',
type
:
5
},
this
.
dealImgInfo
,
)}
fileList=
{
businessInfo
.
idCardPortraitImage
}
>
<
UploadOutlined
/>
<
div
>
身份证人像面
</
div
>
</
Upload
>,
)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
className=
{
styles
.
imgList
}
>
<
FormItem
label=
"法人身份证国徽面"
labelCol=
{
{
span
:
8
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
idCardEmblemImage
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请上传身份证国徽面!
'
}],
initialValue
:
businessInfo
.
idCardEmblemImage
,
})(
<
Upload
{
...
uploadPropsFn
.
call
(
this
,
{
keyName
:
'
idCardEmblemImage
',
type
:
4
},
this
.
dealImgInfo
,
)}
fileList=
{
businessInfo
.
idCardEmblemImage
}
>
<
UploadOutlined
/>
<
div
>
身份证国徽面
</
div
>
</
Upload
>,
)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"证件姓名"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
legalPersonName
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请输入证件姓名!
'
}],
initialValue
:
businessInfo
.
legalPersonName
,
})(<
Input
maxLength=
{
8
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"身份证号码"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
legalPersonIdCard
'
,
{
rules
:
[
{
required
:
true
,
message
:
'
请输入身份证号码!
'
},
{
pattern
:
/^
[
A-Za-z0-9
]
*$/
,
message
:
'
请输入数字或字母
'
},
],
initialValue
:
businessInfo
.
legalPersonIdCard
,
})(<
Input
maxLength=
{
18
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"身份证起始有效期"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
legalPersonStart
'
,
{
rules
:
[{
required
:
true
,
message
:
'
身份证起始有效期!
'
}],
initialValue
:
businessInfo
.
legalPersonStart
,
})(<
DatePicker
style=
{
{
width
:
'
200px
'
}
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
Row
gutter=
{
24
}
>
<
Col
span=
{
19
}
>
<
FormItem
label=
"身份证结束有效期"
labelCol=
{
{
span
:
12
}
}
wrapperCol=
{
{
span
:
12
}
}
>
{
getFieldDecorator
(
'
legalPersonEnd
'
,
{
rules
:
[{
required
:
!
checkboxDisabled
,
message
:
'
身份证结束有效期!
'
}],
initialValue
:
businessInfo
.
legalPersonEnd
,
})(<
DatePicker
style=
{
{
width
:
'
200px
'
}
}
disabled=
{
checkboxDisabled
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
5
}
>
<
FormItem
>
{
getFieldDecorator
(
'
checked
'
,
{
initialValue
:
businessInfo
.
checked
,
})(
<
Checkbox
.
Group
options=
{
legalPersonList
}
className=
{
styles
.
radio
}
onChange=
{
e
=>
this
.
oncheckedChange
(
e
)
}
/>,
)
}
</
FormItem
>
</
Col
>
</
Row
>
</
Col
>
</>
)
}
<
Col
span=
{
12
}
>
<
FormItem
label=
"手机号"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
legalPersonPhone
'
,
{
rules
:
[
{
required
:
true
,
message
:
'
请输入手机号!
'
},
{
validator
:
validatePhone
,
message
:
'
请输入正确的手机号!
'
},
],
initialValue
:
businessInfo
.
legalPersonPhone
,
})(<
Input
maxLength=
{
11
}
/>)
}
</
FormItem
>
</
Col
>
{
+
mainCategoryId
!==
carID
&&
(
<
Col
span=
{
24
}
>
<
FormItem
label=
"其它证照"
labelCol=
{
{
span
:
4
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
otherImage
'
,
{
initialValue
:
businessInfo
.
otherImage
,
})(
<
Upload
{
...
uploadPropsFn
.
call
(
this
,
{
keyName
:
'
otherImage
',
limit
:
9,
type
:
7
})}
fileList=
{
businessInfo
.
otherImage
}
>
<
UploadOutlined
/>
上传文件
</
Upload
>,
)
}
</
FormItem
>
</
Col
>
)
}
</
Row
>
</
Card
>
<
Card
title=
"结算信息录入区"
>
{
+
mainCategoryId
!==
carID
&&
(
<>
<
Row
gutter=
{
24
}
>
<
Col
span=
{
24
}
>
<
FormItem
label=
"账户类型"
labelCol=
{
{
span
:
4
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
settlementType
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请选择账户类型!
'
}],
initialValue
:
businessInfo
.
settlementType
,
})(
<
Radio
.
Group
onChange=
{
e
=>
this
.
onChangeSettlType
(
e
?.
target
?.
value
)
}
>
<
Radio
value=
{
1
}
disabled=
{
[
2
].
includes
(
companyType
)
}
>
对公
</
Radio
>
<
Radio
value=
{
2
}
disabled=
{
[
1
,
3
].
includes
(
companyType
)
}
>
对私(小微商户)
</
Radio
>
</
Radio
.
Group
>,
)
}
</
FormItem
>
</
Col
>
</
Row
>
{
this
.
state
.
settlementType
===
1
&&
(
<
Row
gutter=
{
24
}
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"开户许可证"
labelCol=
{
{
span
:
8
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
accountOpenPermitImage
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请上传开户许可证!
'
}],
initialValue
:
businessInfo
.
accountOpenPermitImage
,
})(
<
Upload
{
...
uploadPropsFn
.
call
(
this
,
{
keyName
:
'
accountOpenPermitImage
',
type
:
8,
})}
fileList=
{
businessInfo
.
accountOpenPermitImage
}
>
<
UploadOutlined
/>
上传文件
</
Upload
>,
)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"开户许可证编号"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
bankAccountLicenseNum
'
,
{
rules
:
[
{
required
:
true
,
message
:
'
请输入开户许可证编号!
'
},
{
pattern
:
/^
[
A-Za-z0-9
]
*$/
,
message
:
'
请输入数字或字母
'
},
],
initialValue
:
businessInfo
.
bankAccountLicenseNum
,
})(<
Input
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"开户名称"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
bankAccountName
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请输入开户名称!
'
}],
initialValue
:
businessInfo
.
bankAccountName
,
})(<
Input
maxLength=
{
32
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"开户行"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
accountBankName
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请选择开户行!
'
}],
initialValue
:
businessInfo
.
accountBankName
,
})(
<
Select
showSearch
filterOption=
{
(
input
,
option
)
=>
(
option
?.
value
??
''
).
toLowerCase
().
includes
(
input
.
toLowerCase
())
}
>
{
this
.
state
.
bankList
.
map
(
item
=>
(
<
Option
value=
{
item
.
bankName
}
key=
{
item
.
bankName
}
>
{
item
.
bankName
}
</
Option
>
))
}
</
Select
>,
)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"银行帐号"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
bankAccount
'
,
{
rules
:
[
{
required
:
true
,
message
:
'
请输入银行帐号!
'
},
{
pattern
:
/^
[
0-9
]
*$/
,
message
:
'
请输入数字
'
},
],
initialValue
:
businessInfo
.
bankAccount
,
})(<
Input
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"联行号"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
interbankNum
'
,
{
rules
:
[{
pattern
:
/^
[
0-9
]
*$/
,
message
:
'
请输入数字
'
}],
initialValue
:
businessInfo
.
interbankNum
,
})(<
Input
maxLength=
{
50
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
24
}
>
<
FormItem
label=
"非同名结算授权文件"
labelCol=
{
{
span
:
4
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
differentNameAuthorizationImage
'
,
{
initialValue
:
businessInfo
.
differentNameAuthorizationImage
,
})(
<
Upload
{
...
uploadPropsFn
.
call
(
this
,
{
keyName
:
'
differentNameAuthorizationImage
',
limit
:
1,
})}
fileList=
{
businessInfo
.
differentNameAuthorizationImage
}
>
<
UploadOutlined
/>
上传文件
</
Upload
>,
)
}
</
FormItem
>
</
Col
>
</
Row
>
)
}
{
this
.
state
.
settlementType
===
2
&&
(
<
Row
gutter=
{
24
}
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"银行卡类型"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
bankAccountType
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请选择银行卡类型!
'
}],
initialValue
:
businessInfo
.
bankAccountType
,
})(
<
Select
>
<
Option
value=
{
1
}
key=
{
1
}
>
借记卡
</
Option
>
</
Select
>,
)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"开户名称"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
bankAccountName
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请输入开户名称!
'
}],
initialValue
:
businessInfo
.
bankAccountName
,
})(<
Input
maxLength=
{
32
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"开户行"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
accountBankName
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请选择开户行!
'
}],
initialValue
:
businessInfo
.
accountBankName
,
})(
<
Select
showSearch
filterOption=
{
(
input
,
option
)
=>
(
option
?.
value
??
''
).
toLowerCase
().
includes
(
input
.
toLowerCase
())
}
>
{
this
.
state
.
bankList
.
map
(
item
=>
(
<
Option
value=
{
item
.
bankName
}
key=
{
item
.
bankName
}
>
{
item
.
bankName
}
</
Option
>
))
}
</
Select
>,
)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"银行帐号"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
bankAccount
'
,
{
rules
:
[
{
required
:
true
,
message
:
'
请输入银行帐号!
'
},
{
pattern
:
/^
[
0-9
]
*$/
,
message
:
'
请输入数字
'
},
],
initialValue
:
businessInfo
.
bankAccount
,
})(<
Input
/>)
}
</
FormItem
>
</
Col
>
</
Row
>
)
}
</>
)
}
{
+
mainCategoryId
===
carID
&&
(
<
Row
gutter=
{
24
}
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"开户许可证"
labelCol=
{
{
span
:
8
}
}
wrapperCol=
{
wrapperCol
}
>
{
getFieldDecorator
(
'
accountOpenPermitImage
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请上传开户许可证!
'
}],
initialValue
:
businessInfo
.
accountOpenPermitImage
,
})(
<
Upload
{
...
uploadPropsFn
.
call
(
this
,
{
keyName
:
'
accountOpenPermitImage
',
type
:
8,
})}
fileList=
{
businessInfo
.
accountOpenPermitImage
}
>
<
UploadOutlined
/>
上传文件
</
Upload
>,
)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"开户名称"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
bankAccountName
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请输入开户名称!
'
}],
initialValue
:
businessInfo
.
bankAccountName
,
})(<
Input
maxLength=
{
32
}
/>)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"开户行"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
accountBankName
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请选择开户行!
'
}],
initialValue
:
businessInfo
.
accountBankName
,
})(
<
Select
showSearch
filterOption=
{
(
input
,
option
)
=>
(
option
?.
value
??
''
).
toLowerCase
().
includes
(
input
.
toLowerCase
())
}
>
{
this
.
state
.
bankList
.
map
(
item
=>
(
<
Option
value=
{
item
.
bankName
}
key=
{
item
.
bankName
}
>
{
item
.
bankName
}
</
Option
>
))
}
</
Select
>,
)
}
</
FormItem
>
</
Col
>
<
Col
span=
{
12
}
>
<
FormItem
label=
"银行帐号"
labelCol=
{
{
span
:
8
}
}
>
{
getFieldDecorator
(
'
bankAccount
'
,
{
rules
:
[
{
required
:
true
,
message
:
'
请输入银行帐号!
'
},
{
pattern
:
/^
[
0-9
]
*$/
,
message
:
'
请输入数字
'
},
],
initialValue
:
businessInfo
.
bankAccount
,
})(<
Input
/>)
}
</
FormItem
>
</
Col
>
</
Row
>
)
}
</
Card
>
{
+
mainCategoryId
===
carID
&&
(
<
Card
title=
"其他信息"
>
<
Row
gutter=
{
24
}
>
<
Col
span=
{
24
}
>
<
FormItem
label=
"礼包内容"
labelCol=
{
{
span
:
4
}
}
>
{
getFieldDecorator
(
'
giftPackageContent
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请输入礼包内容!
'
}],
initialValue
:
businessInfo
.
giftPackageContent
,
})(<
Input
style=
{
{
width
:
'
50%
'
}
}
/>)
}
</
FormItem
>
</
Col
>
</
Row
>
</
Card
>
)
}
<
div
className=
{
styles
.
formBtns
}
>
<
Button
type=
"primary"
size=
"large"
htmlType=
"submit"
loading=
{
this
.
state
.
loading
}
>
修改并提交
</
Button
>
<
Button
size=
"large"
onClick=
{
this
.
onCancel
}
>
取消
</
Button
>
</
div
>
</
Form
>
<
MapModal
visible=
{
this
.
state
.
visibleMap
}
onCancel=
{
()
=>
this
.
openMap
(
false
)
}
onSetPoint=
{
e
=>
this
.
onSetPoint
(
e
)
}
></
MapModal
>
{
this
.
state
.
visibleLoading
&&
(
<
div
className=
{
styles
.
spinBox
}
>
<
div
className=
{
styles
.
spinBoxWrapper
}
>
<
Spin
tip=
"Loading..."
/>
</
div
>
</
div
>
)
}
</
div
>
);
}
}
export
default
Form
.
create
()(
BusinessInfo
);
src/pages/businessManage/info/style.less
0 → 100644
View file @
d72841d4
.textArea {
:global {
.ant-form-item-label {
width: 16%;
}
.ant-form-item-control-wrapper {
width: 80%;
}
}
}
.imgList {
:global {
.ant-upload-list-picture-card-container {
width: 200px;
}
.ant-upload-list-item {
width: 200px;
}
// .ant-upload.ant-upload-select-picture-card {
// width: 200px;
// }
}
}
.infoBox {
position: relative;
}
.spinBox {
position: absolute;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.5);
}
.spinBoxWrapper {
position: fixed;
top: 50%;
left: 50%;
display: flex;
align-items: center;
justify-content: center;
width: 200px;
height: 80px;
text-align: center;
transform: translate(-100px, -80px);
}
.addLink {
display: block;
margin: 20px 50px;
}
.formBtns {
display: flex;
align-items: center;
justify-content: space-evenly;
width: 100%;
padding: 20px 0;
background-color: #fff;
}
src/pages/businessManage/model.js
0 → 100644
View file @
d72841d4
const
Model
=
{
namespace
:
'
BusinessManage
'
,
state
:
{},
effects
:
{},
reducers
:
{},
};
export
default
Model
;
src/pages/businessManage/service.js
0 → 100644
View file @
d72841d4
import
request
from
'
@/utils/request
'
;
import
config
from
'
../../../config/env.config
'
;
import
qs
from
'
qs
'
;
import
{
da
}
from
'
date-fns/locale
'
;
const
{
kdspApi
,
goodsApi
}
=
config
;
// 获取地址
export
const
apiAddrArea
=
params
=>
request
.
get
(
`/api/merchants/addresses/list?
${
qs
.
stringify
(
params
)}
`
,
{
prefix
:
kdspApi
,
});
// 主营类目
export
async
function
apiCategoryList
(
param
)
{
return
request
.
post
(
'
/api/merchants/suppliers/main-category/list
'
,
{
data
:
param
,
prefix
:
goodsApi
,
});
}
// 服务设施
export
const
apiServiceFacility
=
()
=>
request
.
get
(
'
/api/merchants/suppliers/facilities/list
'
,
{
prefix
:
kdspApi
});
// 银行
export
const
apiBankList
=
()
=>
request
.
get
(
'
/api/merchants/suppliers/banks/list
'
,
{
prefix
:
kdspApi
});
// 订正
export
const
apiRevision
=
params
=>
request
.
post
(
'
/api/consoles/suppliers/register/revision
'
,
{
prefix
:
kdspApi
,
data
:
params
});
/**
* 上传文件
* imageType: 1-主头图,2-营业执照,3-电子签章,4-法人身份证国徽面,5-法人身份证人像面,6-类目所需资质,7-其它证件,8-开户许可证
* 0: 默认值 不校验
* */
export
async
function
uploadFile
(
files
,
imageType
=
0
)
{
const
params
=
new
FormData
();
files
.
map
(
file
=>
params
.
append
(
'
file
'
,
file
));
params
.
append
(
'
imageType
'
,
imageType
);
// image/upload
const
data
=
await
request
.
post
(
'
/api/merchants/images/upload
'
,
{
prefix
:
kdspApi
,
data
:
params
,
canRepeat
:
true
,
});
return
data
;
}
// 图片内容识别
export
const
apiRecognize
=
params
=>
request
.
get
(
`/api/merchants/images/recognize?
${
qs
.
stringify
(
params
)}
`
,
{
prefix
:
kdspApi
});
// 编辑商户信息
export
const
apiEditStoreInfo
=
params
=>
request
.
post
(
'
/api/merchants/suppliers/edit
'
,
{
prefix
:
kdspApi
,
data
:
params
});
// 查询商户详情
export
const
apiBusinessDetail
=
businessId
=>
request
.
get
(
'
/api/merchants/suppliers/pops/detail
'
,
{
prefix
:
kdspApi
});
src/pages/businessManage/staticdata.js
0 → 100644
View file @
d72841d4
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
:
'
到店业务
'
,
};
src/pages/businessManage/style.less
0 → 100644
View file @
d72841d4
.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;
}
}
}
src/pages/chainStoreManage/components/storeModal.jsx
View file @
d72841d4
...
@@ -2,12 +2,13 @@ import React, { useState, useEffect, useRef } from 'react';
...
@@ -2,12 +2,13 @@ import React, { useState, useEffect, useRef } from 'react';
import
{
Form
}
from
'
@ant-design/compatible
'
;
import
{
Form
}
from
'
@ant-design/compatible
'
;
import
moment
from
'
moment
'
;
import
moment
from
'
moment
'
;
import
{
PlusSquareFilled
,
MinusSquareFilled
}
from
'
@ant-design/icons
'
;
import
{
PlusSquareFilled
,
MinusSquareFilled
}
from
'
@ant-design/icons
'
;
import
{
Modal
,
Input
,
TimePicker
,
Checkbox
,
Cascader
,
Radio
,
notification
}
from
'
antd
'
;
import
{
Modal
,
Input
,
TimePicker
,
Checkbox
,
Cascader
,
Radio
,
notification
,
Button
}
from
'
antd
'
;
import
{
apiAddrArea
,
apiCreatStore
,
apiEditStore
}
from
'
../services
'
;
import
{
apiAddrArea
,
apiCreatStore
,
apiEditStore
}
from
'
../services
'
;
import
{
weekOptions
,
weekDefault
,
layout
}
from
'
../data
'
;
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,9 @@ const StoreModal = props => {
...
@@ -17,6 +18,9 @@ const StoreModal = props => {
onCancel
,
onCancel
,
form
:
{
getFieldDecorator
,
setFieldsValue
,
getFieldsValue
,
validateFields
,
resetFields
},
form
:
{
getFieldDecorator
,
setFieldsValue
,
getFieldsValue
,
validateFields
,
resetFields
},
formInfo
,
formInfo
,
status
,
productBusiness
,
existTakewayShop
,
}
=
props
;
}
=
props
;
const
[
areaAddr
,
setAreaAddr
]
=
useState
([]);
const
[
areaAddr
,
setAreaAddr
]
=
useState
([]);
const
[
visibleMap
,
setVisibleMap
]
=
useState
(
false
);
const
[
visibleMap
,
setVisibleMap
]
=
useState
(
false
);
...
@@ -26,13 +30,20 @@ const StoreModal = props => {
...
@@ -26,13 +30,20 @@ const StoreModal = props => {
provice
:
''
,
provice
:
''
,
address
:
''
,
address
:
''
,
});
});
const
[
disabled
,
setDisabled
]
=
useState
(
false
);
const
[
isDisabled
,
setIsDisabled
]
=
useState
(
false
);
const
[
businessModel
,
setBusinessModel
]
=
useState
([
{
label
:
'
到家外卖业务(外卖配送业务)
'
,
value
:
1
},
{
label
:
'
实物商品业务员
'
,
value
:
2
},
{
label
:
'
到店业务(服务类业务)
'
,
value
:
3
},
]);
const
divDom
=
useRef
();
const
divDom
=
useRef
();
const
handleCancel
=
isSuccess
=>
{
const
handleCancel
=
isSuccess
=>
{
resetFields
();
resetFields
();
onCancel
(
isSuccess
);
onCancel
(
isSuccess
);
};
};
const
onSubmit
=
()
=>
{
const
onSubmit
=
()
=>
{
validateFields
(
async
(
error
,
fieldsValue
)
=>
{
validateFields
(
async
(
error
,
fieldsValue
)
=>
{
if
(
!
error
)
{
if
(
!
error
)
{
...
@@ -43,6 +54,10 @@ const StoreModal = props => {
...
@@ -43,6 +54,10 @@ const StoreModal = props => {
params
[
areaArr
[
i
]]
=
item
;
params
[
areaArr
[
i
]]
=
item
;
});
});
}
}
if
(
params
?.
shopHeadImage
?.
length
)
{
// eslint-disable-next-line prefer-destructuring
params
.
shopHeadImage
=
params
.
shopHeadImage
[
0
];
}
if
(
params
.
lnglat
)
{
if
(
params
.
lnglat
)
{
const
arr
=
params
.
lnglat
.
split
(
'
,
'
);
const
arr
=
params
.
lnglat
.
split
(
'
,
'
);
if
(
arr
.
length
===
2
)
{
if
(
arr
.
length
===
2
)
{
...
@@ -197,10 +212,44 @@ const StoreModal = props => {
...
@@ -197,10 +212,44 @@ const StoreModal = props => {
setAreaAddr
([...
arr
]);
setAreaAddr
([...
arr
]);
};
};
const
normFile
=
fileList
=>
fileList
;
const
timerWrapper
=
async
(
time
,
timeString
,
callback
)
=>
{
if
(
timeString
&&
timeString
.
length
)
{
const
begin
=
moment
(
timeString
[
0
]).
format
(
'
HH:mm
'
);
const
end
=
moment
(
timeString
[
1
]).
format
(
'
HH:mm
'
);
if
(
begin
===
end
)
{
callback
(
new
Error
(
'
选择开始时间结束时间不能一样
'
));
}
}
else
{
callback
();
}
};
const
onBusiness
=
e
=>
{
const
val
=
e
.
includes
(
1
);
setIsDisabled
(
val
);
};
useEffect
(()
=>
{
useEffect
(()
=>
{
if
(
visible
)
{
if
(
visible
)
{
resetFields
();
resetFields
();
const
info
=
Object
.
assign
({},
formInfo
);
const
info
=
Object
.
assign
({},
formInfo
);
const
val
=
info
?.
productBusiness
?.
includes
(
1
);
setIsDisabled
(
val
);
if
(
status
===
'
look
'
)
{
setDisabled
(
true
);
}
else
{
setDisabled
(
false
);
}
const
data
=
[...
businessModel
];
data
.
forEach
(
item
=>
{
item
.
disabled
=
!
productBusiness
.
includes
(
item
.
value
);
if
(
existTakewayShop
&&
item
.
value
===
1
&&
!
val
)
{
item
.
disabled
=
true
;
}
});
console
.
log
(
data
,
'
.........
'
);
setBusinessModel
(
data
);
if
(
info
&&
info
.
id
)
{
if
(
info
&&
info
.
id
)
{
info
.
week
=
info
.
businessHours
.
weeks
;
info
.
week
=
info
.
businessHours
.
weeks
;
const
hours
=
info
.
businessHours
.
hoursItems
;
const
hours
=
info
.
businessHours
.
hoursItems
;
...
@@ -213,8 +262,10 @@ const StoreModal = props => {
...
@@ -213,8 +262,10 @@ const StoreModal = props => {
});
});
});
});
}
}
info
.
lnglat
=
`
${
info
.
longitude
}
,
${
info
.
latitude
}
`
;
info
.
lnglat
=
`
${
info
.
longitude
}
,
${
info
.
latitude
}
`
;
info
.
addr
=
[
info
.
provinceId
,
info
.
cityId
,
info
.
countyId
];
info
.
addr
=
[
info
.
provinceId
,
info
.
cityId
,
info
.
countyId
];
info
.
shopHeadImage
=
(
info
.
shopHeadImage
&&
[
info
.
shopHeadImage
])
||
[];
if
(
info
.
townId
)
{
if
(
info
.
townId
)
{
info
.
addr
.
push
(
info
.
townId
);
info
.
addr
.
push
(
info
.
townId
);
}
}
...
@@ -234,13 +285,40 @@ const StoreModal = props => {
...
@@ -234,13 +285,40 @@ const StoreModal = props => {
<
Modal
<
Modal
title=
"门店信息"
title=
"门店信息"
visible=
{
visible
}
visible=
{
visible
}
width=
"
8
00px"
width=
"
10
00px"
destroyOnClose
destroyOnClose
maskClosable=
{
false
}
maskClosable=
{
false
}
onOk=
{
()
=>
onSubmit
()
}
onCancel=
{
()
=>
handleCancel
()
}
onCancel=
{
()
=>
handleCancel
()
}
footer=
{
<>
<
Button
key=
"back"
onClick=
{
()
=>
handleCancel
()
}
>
取消
</
Button
>
{
!
disabled
&&
(
<
Button
key=
"submit"
type=
"primary"
onClick=
{
()
=>
onSubmit
()
}
>
确定
</
Button
>
)
}
</>
}
>
>
<
Form
{
...
layout
}
name=
"formData"
>
<
Form
{
...
layout
}
name=
"formData"
>
<
FormItem
label=
"业务模式"
>
{
getFieldDecorator
(
'
productBusiness
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请选择业务模式
'
}],
initialValue
:
formData
.
productBusiness
,
})(<
Checkbox
.
Group
disabled=
{
disabled
}
options=
{
businessModel
}
onChange=
{
onBusiness
}
/>)
}
</
FormItem
>
{
isDisabled
&&
(
<
FormItem
label=
"门店头像"
>
{
getFieldDecorator
(
'
shopHeadImage
'
,
{
rules
:
[{
required
:
true
,
message
:
'
请上传门店头像
'
}],
initialValue
:
formData
.
shopHeadImage
||
[],
valuePropName
:
'
fileList
'
,
getValueFromEvent
:
normFile
,
})(<
Upload
max=
{
1
}
accept=
".jpg,.png,.jpeg"
disabled=
{
disabled
}
/>)
}
</
FormItem
>
)
}
<
FormItem
<
FormItem
label=
"门店名称"
label=
"门店名称"
name=
"name"
name=
"name"
...
@@ -249,7 +327,7 @@ const StoreModal = props => {
...
@@ -249,7 +327,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 +336,7 @@ const StoreModal = props => {
...
@@ -258,7 +336,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
&&
...
@@ -267,20 +345,30 @@ const StoreModal = props => {
...
@@ -267,20 +345,30 @@ const StoreModal = props => {
<
div
>
<
div
>
<
FormItem
name=
{
item
.
name
}
>
<
FormItem
name=
{
item
.
name
}
>
{
getFieldDecorator
(
item
.
name
,
{
{
getFieldDecorator
(
item
.
name
,
{
rules
:
[{
required
:
true
,
message
:
'
请选择营业时间!
'
}],
rules
:
[
{
required
:
true
,
message
:
'
请选择营业时间!
'
},
{
validator
:
timerWrapper
,
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 +376,7 @@ const StoreModal = props => {
...
@@ -288,7 +376,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 +389,7 @@ const StoreModal = props => {
...
@@ -301,6 +389,7 @@ const StoreModal = props => {
placeholder=
"请选择店铺区域"
placeholder=
"请选择店铺区域"
loadData=
{
e
=>
loadData
(
e
)
}
loadData=
{
e
=>
loadData
(
e
)
}
changeOnSelect
changeOnSelect
disabled=
{
disabled
}
/>,
/>,
)
}
)
}
</
FormItem
>
</
FormItem
>
...
@@ -308,7 +397,14 @@ const StoreModal = props => {
...
@@ -308,7 +397,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 +416,7 @@ const StoreModal = props => {
...
@@ -320,6 +416,7 @@ const StoreModal = props => {
readOnly
readOnly
onClick=
{
()
=>
openMap
(
true
)
}
onClick=
{
()
=>
openMap
(
true
)
}
maxLength=
{
100
}
maxLength=
{
100
}
disabled=
{
disabled
}
/>,
/>,
)
}
)
}
</
FormItem
>
</
FormItem
>
...
@@ -328,12 +425,19 @@ const StoreModal = props => {
...
@@ -328,12 +425,19 @@ 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
>
{
isDisabled
&&
(
<
FormItem
label=
"门店公告"
>
{
getFieldDecorator
(
'
publicNotice
'
,
{
initialValue
:
formData
.
publicNotice
,
})(<
Input
placeholder=
"请输入门店公告"
maxLength=
{
120
}
disabled=
{
disabled
}
/>)
}
</
FormItem
>
)
}
</
Form
>
</
Form
>
<
MapModal
<
MapModal
visible=
{
visibleMap
}
visible=
{
visibleMap
}
...
...
src/pages/chainStoreManage/data.js
View file @
d72841d4
...
@@ -17,3 +17,11 @@ export const layout = {
...
@@ -17,3 +17,11 @@ export const layout = {
labelCol
:
{
span
:
6
},
labelCol
:
{
span
:
6
},
wrapperCol
:
{
span
:
16
},
wrapperCol
:
{
span
:
16
},
};
};
export
const
businessList
=
[
{
label
:
'
外卖
'
,
value
:
1
},
{
label
:
'
实物类
'
,
value
:
2
},
{
label
:
'
服务类
'
,
value
:
3
},
];
// 营业日
export
const
businessStatus
=
[{
label
:
'
休息中
'
,
value
:
2
},
{
label
:
'
营业中
'
,
value
:
1
}];
src/pages/chainStoreManage/index.jsx
View file @
d72841d4
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
,
Select
,
}
from
'
antd
'
;
import
_
from
'
lodash
'
;
import
_
from
'
lodash
'
;
import
{
searchList
,
apiEnableStore
,
apiAddrArea
}
from
'
./services
'
;
import
{
el
}
from
'
date-fns/locale
'
;
import
{
stateDesc
,
weeks
,
layout
}
from
'
./data
'
;
import
{
searchList
,
apiEnableStore
,
apiAddrArea
,
apiproductBusiness
}
from
'
./services
'
;
import
{
stateDesc
,
weeks
,
layout
,
businessStatus
,
businessList
}
from
'
./data
'
;
import
StoreModal
from
'
./components/storeModal
'
;
import
StoreModal
from
'
./components/storeModal
'
;
import
style
from
'
./style.less
'
;
import
style
from
'
./style.less
'
;
const
{
Option
}
=
Select
;
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
(
false
);
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
);
const
[
pageSize
,
setPageSize
]
=
useState
(
20
);
const
[
pageSize
,
setPageSize
]
=
useState
(
20
);
const
[
productBusiness
,
setProductBusiness
]
=
useState
([]);
const
[
existTakewayShop
,
setExistTakewayShop
]
=
useState
(
false
);
const
refSearch
=
useRef
();
const
refSearch
=
useRef
();
const
divDom
=
useRef
();
const
divDom
=
useRef
();
// 获取业务模式
const
getBusiness
=
async
()
=>
{
const
res
=
await
apiproductBusiness
();
if
(
res
)
{
setProductBusiness
(
res
.
productBusiness
||
[]);
setExistTakewayShop
(
res
.
existTakewayShop
);
}
setVisible
(
true
);
};
const
onCreate
=
()
=>
{
const
onCreate
=
()
=>
{
setStatus
(
'
add
'
);
setStoreInfo
({});
setStoreInfo
({});
setVisible
(
true
);
getBusiness
(
);
};
};
const
onShowInfo
=
info
=>
{
const
onShowInfo
=
(
info
,
val
)
=>
{
setStoreInfo
(
info
);
setStoreInfo
(
info
);
setVisible
(
true
);
setStatus
(
val
);
getBusiness
();
};
};
// 获取市区街道
// 获取市区街道
...
@@ -92,16 +122,25 @@ export default () => {
...
@@ -92,16 +122,25 @@ export default () => {
params
[
ids
[
i
]]
=
item
;
params
[
ids
[
i
]]
=
item
;
});
});
}
}
if
(
val
.
businessStatus
)
{
params
.
businessStatus
=
val
.
businessStatus
;
}
if
(
val
.
productBusiness
)
{
params
.
productBusiness
=
val
.
productBusiness
;
}
getList
(
params
);
getList
(
params
);
};
};
const
closeModal
=
isReload
=>
{
const
closeModal
=
isReload
=>
{
if
(
isReload
)
{
if
(
isReload
)
{
onSearch
(
refSearch
.
current
?.
getFieldValue
?.()
||
{});
onSearch
(
refSearch
.
current
?.
getFieldValue
?.()
||
{});
}
}
setStatus
(
false
);
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 +148,25 @@ export default () => {
...
@@ -109,11 +148,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
)
=>
{
...
@@ -164,83 +217,71 @@ export default () => {
...
@@ -164,83 +217,71 @@ export default () => {
const
columns
=
[
const
columns
=
[
{
{
title
:
'
门店名称
'
,
title
:
'
业务模式
'
,
dataIndex
:
'
name
'
,
dataIndex
:
'
productBusiness
'
,
width
:
120
,
width
:
120
,
},
align
:
'
center
'
,
{
render
:
(
v
,
value
)
=>
title
:
'
门店电话
'
,
value
?.
productBusiness
?.
length
&&
(
dataIndex
:
'
phone
'
,
hideInSearch
:
true
,
width
:
120
,
},
{
title
:
'
营业时间
'
,
dataIndex
:
'
businessHours
'
,
hideInSearch
:
true
,
width
:
150
,
render
:
businessHours
=>
(
<
div
>
<
div
>
{
getWeekSlots
(
businessHours
.
weeks
)
}
</
div
>
<
div
>
<
div
>
{
businessHours
.
hoursItems
.
map
(
item
=>
(
{
v
.
map
(
it
=>
(
<
div
key=
{
item
.
begin
}
>
<
span
>
{
businessList
.
find
(
item
=>
+
it
===
+
item
.
value
).
label
}
 
</
span
>
<
span
>
{
item
.
begin
}
</
span
>
-
<
span
>
{
item
.
end
}
</
span
>
</
div
>
))
}
))
}
</
div
>
</
div
>
</
div
>
),
),
},
},
{
{
title
:
'
地区
'
,
title
:
'
门店名称
'
,
dataIndex
:
'
addr
'
,
dataIndex
:
'
name
'
,
width
:
200
,
width
:
120
,
hideInSearch
:
true
,
align
:
'
center
'
,
render
:
(
addr
,
r
)
=>
(
<
span
>
{
`${r.provinceName}${r.cityName}${r.countyName}${r.townName || ''}`
}
</
span
>
),
},
},
{
{
title
:
'
详细地址
'
,
title
:
'
营业状态
'
,
dataIndex
:
'
address
'
,
dataIndex
:
'
businessStatus
'
,
hideInSearch
:
true
,
width
:
80
,
width
:
150
,
align
:
'
center
'
,
render
:
val
=>
businessStatus
.
find
(
item
=>
item
.
value
===
val
)?.
label
||
'
-
'
,
},
},
{
{
title
:
'
经纬度
'
,
title
:
'
创建时间
'
,
dataIndex
:
'
latlng
'
,
dataIndex
:
'
createdAt
'
,
hideInSearch
:
true
,
width
:
120
,
width
:
120
,
render
:
(
latlng
,
r
)
=>
<
span
>
{
`${r.longitude},${r.latitude}`
}
</
span
>
,
align
:
'
center
'
,
},
},
{
{
title
:
'
状态
'
,
title
:
'
门店电话
'
,
dataIndex
:
'
state
'
,
dataIndex
:
'
phone
'
,
hideInSearch
:
true
,
align
:
'
center
'
,
width
:
120
,
width
:
100
,
render
:
v
=>
<
span
>
{
`${stateDesc[v]}`
}
</
span
>,
},
},
{
{
title
:
'
创建时间
'
,
title
:
'
门店状态
'
,
dataIndex
:
'
createdAt
'
,
dataIndex
:
'
state
'
,
hideInSearch
:
true
,
hideInSearch
:
true
,
width
:
120
,
align
:
'
center
'
,
width
:
80
,
render
:
v
=>
<
span
>
{
`${stateDesc[v]}`
}
</
span
>,
},
},
{
{
title
:
'
操作
'
,
title
:
'
操作
'
,
hideInSearch
:
true
,
hideInSearch
:
true
,
dataIndex
:
'
action
'
,
dataIndex
:
'
action
'
,
width
:
17
0
,
width
:
20
0
,
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
,
'
look
'
)
}
>
</
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
(
...
@@ -264,17 +305,39 @@ export default () => {
...
@@ -264,17 +305,39 @@ export default () => {
</
Form
.
Item
>
</
Form
.
Item
>
</
Col
>
</
Col
>
<
Col
span=
{
8
}
>
<
Col
span=
{
8
}
>
<
Button
type=
"primary"
htmlType=
"submit"
size=
"middle"
>
<
Form
.
Item
label=
"营业状态"
name=
"businessStatus"
>
搜索
<
Select
>
</
Button
>
{
businessStatus
.
map
(
item
=>
(
<
Button
size=
"middle"
className=
{
style
.
searchBtn
}
onClick=
{
()
=>
onReset
()
}
>
<
Option
label=
{
item
.
label
}
value=
{
item
.
value
}
key=
{
item
.
value
}
>
重置
{
item
.
label
}
</
Button
>
</
Option
>
<
Button
type=
"primary"
size=
"middle"
onClick=
{
()
=>
onCreate
()
}
>
))
}
新建
</
Select
>
</
Button
>
</
Form
.
Item
>
</
Col
>
<
Col
span=
{
8
}
>
<
Form
.
Item
label=
"业务模式"
name=
"productBusiness"
>
<
Select
>
{
businessList
.
map
(
item
=>
(
<
Option
label=
{
item
.
label
}
value=
{
item
.
value
}
key=
{
item
.
value
}
>
{
item
.
label
}
</
Option
>
))
}
</
Select
>
</
Form
.
Item
>
</
Col
>
</
Col
>
</
Row
>
</
Row
>
<
div
className=
{
style
.
search
}
>
<
Button
type=
"primary"
htmlType=
"submit"
size=
"middle"
>
搜索
</
Button
>
<
Button
size=
"middle"
className=
{
style
.
searchBtn
}
onClick=
{
()
=>
onReset
()
}
>
重置
</
Button
>
<
Button
type=
"primary"
size=
"middle"
onClick=
{
()
=>
onCreate
()
}
>
新建
</
Button
>
</
div
>
</
Form
>
</
Form
>
</
div
>
</
div
>
<
Table
<
Table
...
@@ -285,7 +348,7 @@ export default () => {
...
@@ -285,7 +348,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 +361,15 @@ export default () => {
...
@@ -298,8 +361,15 @@ 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
}
productBusiness=
{
productBusiness
}
existTakewayShop=
{
existTakewayShop
}
/>
</
div
>
</
div
>
);
);
};
};
src/pages/chainStoreManage/services.js
View file @
d72841d4
...
@@ -65,3 +65,11 @@ export async function apiEditStore(params) {
...
@@ -65,3 +65,11 @@ export async function apiEditStore(params) {
});
});
return
data
.
businessCode
;
return
data
.
businessCode
;
}
}
// 获取商户业务模式
export
async
function
apiproductBusiness
()
{
const
data
=
await
request
.
get
(
'
/api/merchants/suppliers/product-business/list
'
,
{
prefix
:
kdspApi
,
});
return
data
.
data
;
}
src/pages/chainStoreManage/style.less
View file @
d72841d4
.serachForm {
.serachForm {
margin-bottom: 20px;
margin-bottom: 20px;
padding: 20px 50px
0
10px;
padding: 20px 50px
10px
10px;
background-color: #fff;
background-color: #fff;
}
}
.search {
display: flex;
justify-content: end;
}
.searchBtn {
.searchBtn {
margin: 0 10px;
margin: 0 10px;
}
}
...
@@ -13,3 +17,14 @@
...
@@ -13,3 +17,14 @@
border: 1px solid #f0f0f0;
border: 1px solid #f0f0f0;
border-top: 0;
border-top: 0;
}
}
.actionBtn {
display: flex;
align-items: center;
// flex-direction: column;
justify-content: space-around;
button {
width: 75px;
margin-bottom: 5px;
}
}
src/pages/components/upload.jsx
View file @
d72841d4
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,26 @@ class PicturesWall extends React.Component {
...
@@ -26,9 +25,26 @@ class PicturesWall extends React.Component {
};
};
async
componentDidMount
()
{
async
componentDidMount
()
{
this
.
initFileList
(
this
.
props
.
fileList
||
[]);
token
=
await
qiniuToken
();
token
=
await
qiniuToken
();
}
}
static
getDerivedStateFromProps
(
nextProps
)
{
new
PicturesWall
(
nextProps
).
initFileList
();
return
null
;
}
initFileList
=
fileList
=>
{
const
fileLists
=
fileList
?.
map
((
item
,
index
)
=>
({
url
:
item
,
name
:
''
,
uid
:
index
,
status
:
'
done
'
,
}))
||
[];
this
.
setState
({
fileList
:
fileLists
});
};
handleCancel
=
()
=>
this
.
setState
({
previewVisible
:
false
});
handleCancel
=
()
=>
this
.
setState
({
previewVisible
:
false
});
handlePreview
=
async
file
=>
{
handlePreview
=
async
file
=>
{
...
@@ -43,17 +59,37 @@ class PicturesWall extends React.Component {
...
@@ -43,17 +59,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 +103,17 @@ class PicturesWall extends React.Component {
...
@@ -67,6 +103,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 +141,17 @@ class PicturesWall extends React.Component {
...
@@ -94,15 +141,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
>
...
...
src/pages/contractView/data.js
0 → 100644
View file @
d72841d4
src/pages/contractView/index.jsx
0 → 100644
View file @
d72841d4
import
React
,
{
useState
,
useRef
}
from
'
react
'
;
import
ProTable
from
'
@ant-design/pro-table
'
;
import
{
PageHeaderWrapper
}
from
'
@ant-design/pro-layout
'
;
import
{
notification
,
Button
,
Modal
,
Image
,
message
}
from
'
antd
'
;
import
{
query
}
from
'
./services
'
;
import
style
from
'
./style.less
'
;
const
ContractView
=
()
=>
{
const
[
visible
,
setVisible
]
=
useState
(
false
);
const
[
url
,
setUrl
]
=
useState
();
// 查看
const
onLook
=
({
contractPdfUrl
})
=>
{
if
(
contractPdfUrl
)
{
setUrl
(
contractPdfUrl
);
setVisible
(
true
);
}
else
{
message
.
error
(
'
暂无合同
'
);
}
};
// 下载
const
ondown
=
({
contractPdfUrl
})
=>
{
if
(
contractPdfUrl
)
{
window
.
open
(
contractPdfUrl
);
}
else
{
message
.
error
(
'
暂无合同
'
);
}
};
const
columns
=
[
{
title
:
'
合同名称
'
,
dataIndex
:
'
contractName
'
,
key
:
'
contractName
'
,
align
:
'
center
'
,
},
{
title
:
'
签约时间
'
,
dataIndex
:
'
signDate
'
,
key
:
'
signDate
'
,
align
:
'
center
'
,
hideInSearch
:
true
,
render
:
(
val
,
data
)
=>
{
if
(
data
.
signDate
&&
data
?.
signDate
.
length
)
{
let
date
=
''
;
data
.
signDate
.
forEach
((
item
,
index
)
=>
{
if
(
item
&&
item
.
toString
().
length
===
1
)
{
item
=
`0
${
item
}
`
;
}
if
([
0
,
1
].
includes
(
index
))
{
date
+=
`
${
item
}
-`
;
}
else
if
([
3
,
4
].
includes
(
index
))
{
date
+=
`
${
item
}
:`
;
}
else
{
date
+=
`
${
item
}
`
;
}
});
return
date
;
}
return
'
-
'
;
},
},
{
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
>
{
!
visible
&&
(
<
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
}
}
pagination=
{
false
}
/>
)
}
{
visible
&&
(
<
div
className=
{
style
.
contract
}
>
<
iframe
src=
{
url
}
height=
"600"
width=
"100%"
title=
"合同"
></
iframe
>
<
Button
type=
"primary"
onClick=
{
()
=>
setVisible
(
false
)
}
>
取消
</
Button
>
</
div
>
)
}
</
PageHeaderWrapper
>
);
};
export
default
ContractView
;
src/pages/contractView/services.js
0 → 100644
View file @
d72841d4
import
{
stringify
}
from
'
querystring
'
;
import
request
from
'
@/utils/request
'
;
import
_
from
'
lodash
'
;
import
config
from
'
../../../config/env.config
'
;
const
{
goodsApi
}
=
config
;
// 分页查询所有数据
export
async
function
query
(
params
)
{
const
param
=
{
...
params
,
pageIndex
:
params
.
current
,
pageSize
:
params
.
pageSize
||
20
,
};
const
data
=
await
request
.
post
(
'
/api/merchants/suppliers/contract/list
'
,
{
prefix
:
goodsApi
,
data
:
param
,
headers
:
{
'
Content-Type
'
:
'
application/json;charset=UTF-8
'
,
},
});
if
(
data
.
data
)
{
return
{
data
:
data
.
data
,
};
}
return
{
total
:
0
,
data
:
[],
};
}
src/pages/contractView/style.less
0 → 100644
View file @
d72841d4
.contract {
text-align: center;
}
src/utils/utils.js
View file @
d72841d4
/* eslint-disable prefer-destructuring */
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
'
;
...
@@ -126,4 +127,47 @@ export const getClientInfo = () => {
...
@@ -126,4 +127,47 @@ export const getClientInfo = () => {
};
};
};
};
// 字符串或json去空格
export
const
stringOrObjectTrim
=
params
=>
{
if
(
isClass
(
params
)
===
'
String
'
)
{
return
params
.
trim
();
}
if
(
isClass
(
params
)
===
'
Object
'
)
{
Object
.
keys
(
params
).
forEach
(
key
=>
{
if
(
isClass
(
params
[
key
])
===
'
String
'
)
{
params
[
key
]
=
params
[
key
].
trim
();
}
else
if
(
isClass
(
params
[
key
])
===
'
Object
'
)
{
stringOrObjectTrim
(
params
[
key
]);
}
else
if
(
isClass
(
params
[
key
])
===
'
Array
'
)
{
params
[
key
].
forEach
((
item
,
i
)
=>
{
params
[
key
][
i
]
=
stringOrObjectTrim
(
item
);
});
}
});
}
return
params
;
};
export
const
getObjectType
=
v
=>
Object
.
prototype
.
toString
.
call
(
v
).
replace
(
/
\[
object |]/g
,
''
);
export
const
getObjectType
=
v
=>
Object
.
prototype
.
toString
.
call
(
v
).
replace
(
/
\[
object |]/g
,
''
);
// 获取长表单错误提示
export
const
getErrorMessage
=
err
=>
{
const
message
=
'
请检查表单数据!
'
;
// eslint-disable-next-line wrap-iife
(
function
getMsg
(
v
)
{
if
(
Array
.
isArray
(
v
))
{
getMsg
(
v
[
0
]);
}
else
{
const
keys
=
Object
.
keys
(
v
);
if
(
Array
.
isArray
(
v
[
keys
[
0
]]))
{
getMsg
(
v
[
keys
[
0
]][
0
]);
}
else
if
(
v
[
keys
[
0
]].
errors
&&
v
[
keys
[
0
]].
errors
.
length
)
{
// eslint-disable-next-line no-const-assign
message
=
v
[
keys
[
0
]].
errors
[
0
].
message
;
}
else
{
getMsg
(
v
);
}
}
})(
err
);
return
message
;
};
src/utils/validator.js
View file @
d72841d4
...
@@ -419,3 +419,19 @@ export function isCheckPriceOneDecimal(rule, value, callback) {
...
@@ -419,3 +419,19 @@ export function isCheckPriceOneDecimal(rule, value, callback) {
callback
();
callback
();
}
}
}
}
// 验证价格保留小数点2位
export
function
isCheckPriceTwoDecimal
(
rule
,
value
,
callback
)
{
const
num
=
+
value
;
const
arr
=
`
${
value
}
`
.
split
(
'
.
'
);
if
(
!
value
)
{
callback
();
}
else
if
(
Number
.
isNaN
(
num
))
{
callback
(
new
Error
(
'
请输入数字
'
));
}
else
if
(
num
<
0
)
{
callback
(
new
Error
(
'
请输入大于0的数字
'
));
}
else
if
(
arr
.
length
===
2
&&
arr
[
1
].
length
>
2
)
{
callback
(
new
Error
(
'
小数点保留2位
'
));
}
else
{
callback
();
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment