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
8d5d77d7
Commit
8d5d77d7
authored
Mar 27, 2023
by
baxibaba
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature/20230327_public_takeaway' into feature/20230315_take_out_goods
parents
a0b8634f
67cb6678
Changes
25
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
2063 additions
and
420 deletions
+2063
-420
.sentryclirc.js
.sentryclirc.js
+17
-0
plugin.config.js
config/plugin.config.js
+5
-1
package-lock.json
package-lock.json
+308
-245
package.json
package.json
+7
-0
app.js
src/app.js
+29
-0
data.js
src/pages/AfterSaleManage/data.js
+6
-2
index.jsx
src/pages/AfterSaleManage/index.jsx
+1
-1
index.jsx
src/pages/GoodsManage/SearchForm/index.jsx
+53
-74
ActionBar.jsx
src/pages/GoodsManage/Takeaway/components/ActionBar.jsx
+76
-0
DragTag.jsx
src/pages/GoodsManage/Takeaway/components/DragTag.jsx
+100
-0
GoodsGroup.jsx
src/pages/GoodsManage/Takeaway/components/GoodsGroup.jsx
+175
-0
GroupInfo.jsx
src/pages/GoodsManage/Takeaway/components/GroupInfo.jsx
+87
-0
InsertTag.jsx
src/pages/GoodsManage/Takeaway/components/InsertTag.jsx
+22
-0
MinimumPurchase.jsx
...pages/GoodsManage/Takeaway/components/MinimumPurchase.jsx
+47
-0
SendModal.jsx
src/pages/GoodsManage/Takeaway/components/SendModal.jsx
+52
-0
StockModal.jsx
src/pages/GoodsManage/Takeaway/components/StockModal.jsx
+107
-0
SwitchGroupModal.jsx
...ages/GoodsManage/Takeaway/components/SwitchGroupModal.jsx
+52
-0
WeekTime.jsx
src/pages/GoodsManage/Takeaway/components/WeekTime.jsx
+168
-0
index.jsx
src/pages/GoodsManage/Takeaway/index.jsx
+210
-0
index.jsx
src/pages/GoodsManage/index.jsx
+115
-85
service.js
src/pages/GoodsManage/service.js
+71
-5
staticdata.js
src/pages/GoodsManage/staticdata.js
+196
-2
style.less
src/pages/GoodsManage/style.less
+152
-2
data.js
src/pages/cancelBillManage/data.js
+1
-0
websocket.js
src/utils/websocket.js
+6
-3
No files found.
.sentryclirc.js
0 → 100644
View file @
8d5d77d7
const
pkgInfo
=
require
(
'
./package.json
'
);
const
project
=
pkgInfo
.
name
;
module
.
exports
=
{
org
:
'
sentry
'
,
project
,
authToken
:
'
3f1f6f3789594e3a81280c1cd8d4d1008037a7abad714698b60b6f358c3d7562
'
,
url
:
'
http://newsentry.quantgroups.com
'
,
release
:
`
${
project
}
@1.0.0`
,
ignore
:
[
'
node_modules
'
,
'
tests
'
],
silent
:
true
,
include
:
[
{
paths
:
[
'
./dist
'
],
},
],
};
config/plugin.config.js
View file @
8d5d77d7
...
@@ -5,7 +5,8 @@
...
@@ -5,7 +5,8 @@
import
ThemeColorReplacer
from
'
webpack-theme-color-replacer
'
;
import
ThemeColorReplacer
from
'
webpack-theme-color-replacer
'
;
import
generate
from
'
@ant-design/colors/lib/generate
'
;
import
generate
from
'
@ant-design/colors/lib/generate
'
;
import
path
from
'
path
'
;
import
path
from
'
path
'
;
const
SentryPlugin
=
require
(
'
@qg/sentry-webpack-plugin
'
);
const
SentryConfig
=
require
(
'
../.sentryclirc
'
);
function
getModulePackageName
(
module
)
{
function
getModulePackageName
(
module
)
{
if
(
!
module
.
context
)
return
null
;
if
(
!
module
.
context
)
return
null
;
const
nodeModulesPath
=
path
.
join
(
__dirname
,
'
../node_modules/
'
);
const
nodeModulesPath
=
path
.
join
(
__dirname
,
'
../node_modules/
'
);
...
@@ -27,6 +28,9 @@ function getModulePackageName(module) {
...
@@ -27,6 +28,9 @@ function getModulePackageName(module) {
}
}
export
default
config
=>
{
export
default
config
=>
{
if
(
process
.
env
.
NODE_ENV
===
'
production
'
)
{
config
.
plugin
(
'
sentry-webpack-plugin
'
).
use
(
SentryPlugin
,
[
SentryConfig
]);
}
// preview.pro.ant.design only do not use in your production;
// preview.pro.ant.design only do not use in your production;
if
(
if
(
process
.
env
.
ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION
===
'
site
'
||
process
.
env
.
ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION
===
'
site
'
||
...
...
package-lock.json
View file @
8d5d77d7
This diff is collapsed.
Click to expand it.
package.json
View file @
8d5d77d7
...
@@ -54,8 +54,10 @@
...
@@ -54,8 +54,10 @@
"
@ant-design/pro-layout
"
:
"
^4.11.4
"
,
"
@ant-design/pro-layout
"
:
"
^4.11.4
"
,
"
@ant-design/pro-table
"
:
"
^1.0.31
"
,
"
@ant-design/pro-table
"
:
"
^1.0.31
"
,
"
@antv/data-set
"
:
"
^0.10.2
"
,
"
@antv/data-set
"
:
"
^0.10.2
"
,
"
@sentry/react
"
:
"
^7.41.0
"
,
"
antd
"
:
"
^4.19.3
"
,
"
antd
"
:
"
^4.19.3
"
,
"
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
"
,
...
@@ -69,10 +71,14 @@
...
@@ -69,10 +71,14 @@
"
react
"
:
"
^16.8.6
"
,
"
react
"
:
"
^16.8.6
"
,
"
react-amap
"
:
"
^1.2.8
"
,
"
react-amap
"
:
"
^1.2.8
"
,
"
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
"
,
...
@@ -81,6 +87,7 @@
...
@@ -81,6 +87,7 @@
},
},
"devDependencies"
:
{
"devDependencies"
:
{
"
@ant-design/pro-cli
"
:
"
^1.0.13
"
,
"
@ant-design/pro-cli
"
:
"
^1.0.13
"
,
"
@qg/sentry-webpack-plugin
"
:
"
^1.19.0
"
,
"
@types/classnames
"
:
"
^2.2.7
"
,
"
@types/classnames
"
:
"
^2.2.7
"
,
"
@types/express
"
:
"
^4.17.0
"
,
"
@types/express
"
:
"
^4.17.0
"
,
"
@types/history
"
:
"
^4.7.2
"
,
"
@types/history
"
:
"
^4.7.2
"
,
...
...
src/app.js
View file @
8d5d77d7
/* eslint-disable no-console */
/* eslint-disable no-console */
import
*
as
Sentry
from
'
@sentry/react
'
;
import
localStorage
from
'
@/utils/localStorage
'
;
// process.env.SENTRY_ENV !== 'test' 加上测试环境不会报错
if
(
process
.
env
.
NODE_ENV
===
'
production
'
&&
process
.
env
.
SENTRY_ENV
!==
'
test
'
)
{
try
{
Sentry
.
init
({
dsn
:
'
https://b3f60c62e1234e26a5b851b9f26fba07@sentry.q-gp.com/34
'
,
release
:
'
merchant-manage-ui@1.0.0
'
,
maxBreadcrumbs
:
50
,
tracesSampleRate
:
1
,
beforeSend
:
e
=>
{
const
err
=
e
.
exception
?.
values
||
[];
// XXX 不上报[object Object]此类基础库异常
if
(
err
.
some
(
item
=>
item
.
value
.
indexOf
(
'
ResizeObserver
'
)
>
-
1
))
{
return
null
;
}
return
e
;
},
});
Sentry
.
configureScope
(
scope
=>
{
scope
.
setUser
({
token
:
localStorage
.
get
(
'
token
'
)
||
null
,
});
});
}
catch
(
e
)
{
console
.
log
(
'
Sentry无法加载
'
,
e
);
}
}
export
const
dva
=
{
export
const
dva
=
{
config
:
{
config
:
{
...
...
src/pages/AfterSaleManage/data.js
View file @
8d5d77d7
...
@@ -257,6 +257,9 @@ export const getColumns = props => {
...
@@ -257,6 +257,9 @@ export const getColumns = props => {
<
/span
>
<
/span
>
);
);
}
}
if
(
+
serviceType
===
4
)
{
return
<
span
style
=
{{
color
:
'
#ff1616
'
}}
>
仅退款
(
发货中
)
<
/span>
;
}
return
<
span
>
退货退款
<
/span>
;
return
<
span
>
退货退款
<
/span>
;
},
},
},
},
...
@@ -268,6 +271,7 @@ export const getColumns = props => {
...
@@ -268,6 +271,7 @@ export const getColumns = props => {
<
div
>
<
div
>
{
r
.
timeout
?
<
Tag
color
=
"
red
"
>
{
serviceNo
}
<
/Tag> : serviceNo
}
{
r
.
timeout
?
<
Tag
color
=
"
red
"
>
{
serviceNo
}
<
/Tag> : serviceNo
}
{
<
Badge
count
=
{
r
.
reminderFlag
?
'
催
'
:
''
}
size
=
"
default
"
/>
}
{
<
Badge
count
=
{
r
.
reminderFlag
?
'
催
'
:
''
}
size
=
"
default
"
/>
}
{
<
Badge
count
=
{
+
r
.
autoCancelTimeType
===
1
?
'
大额支付
'
:
''
}
size
=
"
default
"
/>
}
<
/div
>
<
/div
>
),
),
},
},
...
@@ -512,8 +516,8 @@ export const getColumns = props => {
...
@@ -512,8 +516,8 @@ export const getColumns = props => {
}
}
}
}
// 实物商品-仅退款未发货 serviceType = 0
// 实物商品-仅退款未发货 serviceType = 0
, 仅退款(发货中) serviceType = 4
if
(
serviceType
===
0
)
{
if
(
serviceType
===
0
||
serviceType
===
4
)
{
// 待商户审核14 待审核0
// 待商户审核14 待审核0
if
([
14
,
0
].
includes
(
status
))
{
if
([
14
,
0
].
includes
(
status
))
{
return
[
cancelAuditBtn
,
cancelDetailBtn
,
viewLogBtn
];
return
[
cancelAuditBtn
,
cancelDetailBtn
,
viewLogBtn
];
...
...
src/pages/AfterSaleManage/index.jsx
View file @
8d5d77d7
...
@@ -300,7 +300,7 @@ const AfterSale = props => {
...
@@ -300,7 +300,7 @@ const AfterSale = props => {
const
clientInfo
=
getClientInfo
();
const
clientInfo
=
getClientInfo
();
const
calculationLayoutHeight
=
e
=>
{
const
calculationLayoutHeight
=
e
=>
{
const
otherHeight
=
typeof
e
===
'
number
'
?
e
:
330
;
const
otherHeight
=
typeof
e
===
'
number
'
?
e
:
330
;
const
h
=
clientInfo
.
height
-
scrollYRef
.
current
.
offsetTop
-
otherHeight
;
const
h
=
clientInfo
.
height
-
(
scrollYRef
?.
current
?.
offsetTop
||
0
)
-
otherHeight
;
setTableScrollY
(
h
<
500
?
'
500px
'
:
h
);
setTableScrollY
(
h
<
500
?
'
500px
'
:
h
);
};
};
...
...
src/pages/GoodsManage/SearchForm/index.jsx
View file @
8d5d77d7
...
@@ -31,6 +31,7 @@ class goodsManage extends Component {
...
@@ -31,6 +31,7 @@ class goodsManage extends Component {
state
=
{
state
=
{
loading
:
false
,
loading
:
false
,
productType
:
null
,
};
};
componentDidMount
()
{
componentDidMount
()
{
...
@@ -78,6 +79,13 @@ class goodsManage extends Component {
...
@@ -78,6 +79,13 @@ class goodsManage extends Component {
}
}
};
};
onChangeProductType
=
(
v
=
null
)
=>
{
this
.
props
.
changeProductType
(
v
);
this
.
setState
({
productType
:
v
,
});
};
// 导出明细
// 导出明细
onExportGoodsInfo
=
async
()
=>
{
onExportGoodsInfo
=
async
()
=>
{
this
.
setState
({
this
.
setState
({
...
@@ -105,7 +113,6 @@ class goodsManage extends Component {
...
@@ -105,7 +113,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 +137,35 @@ class goodsManage extends Component {
...
@@ -130,46 +137,35 @@ 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编码"
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=
"请选择商品类型"
allowClear
onChange=
{
this
.
onChangeProductType
}
>
<
Option
value=
{
1
}
>
实体商品
</
Option
>
<
Option
value=
{
2
}
>
虚拟商品
</
Option
>
<
Option
value=
{
4
}
>
服务类商品
</
Option
>
<
Option
value=
{
5
}
>
外卖商品
</
Option
>
</
Select
>
</
FormItem
>
<
FormItem
label=
"类目"
name=
"productCategoryId"
>
<
FormItem
label=
"类目"
name=
"productCategoryId"
>
<
Cascader
<
Cascader
placeholder=
"请选择类目"
placeholder=
"请选择类目"
...
@@ -180,6 +176,7 @@ class goodsManage extends Component {
...
@@ -180,6 +176,7 @@ class goodsManage extends Component {
options=
{
treeData
}
options=
{
treeData
}
/>
/>
</
FormItem
>
</
FormItem
>
{
this
.
state
.
productType
!==
5
&&
(
<
FormItem
label=
"审核状态"
name=
"state"
>
<
FormItem
label=
"审核状态"
name=
"state"
>
<
Select
<
Select
style=
{
selectW
}
style=
{
selectW
}
...
@@ -194,6 +191,7 @@ class goodsManage extends Component {
...
@@ -194,6 +191,7 @@ class goodsManage extends Component {
))
}
))
}
</
Select
>
</
Select
>
</
FormItem
>
</
FormItem
>
)
}
<
FormItem
label=
"供货价区间"
>
<
FormItem
label=
"供货价区间"
>
<
FormItem
name=
"supplyPriceMin"
className=
{
styles
.
iptNumRight
}
noStyle
>
<
FormItem
name=
"supplyPriceMin"
className=
{
styles
.
iptNumRight
}
noStyle
>
<
InputNumber
placeholder=
"请输入"
style=
{
iptNumWidth
}
/>
<
InputNumber
placeholder=
"请输入"
style=
{
iptNumWidth
}
/>
...
@@ -203,16 +201,11 @@ class goodsManage extends Component {
...
@@ -203,16 +201,11 @@ class goodsManage extends Component {
<
InputNumber
style=
{
iptNumWidth
}
placeholder=
"请输入"
onChange=
{
this
.
valueMin
}
/>
<
InputNumber
style=
{
iptNumWidth
}
placeholder=
"请输入"
onChange=
{
this
.
valueMin
}
/>
</
FormItem
>
</
FormItem
>
</
FormItem
>
</
FormItem
>
<
FormItem
label=
"商品类型"
name=
"productType"
>
{
this
.
state
.
productType
!==
5
&&
(
<
Select
style=
{
selectW
}
placeholder=
"请选择商品类型"
>
<
Option
value=
{
1
}
>
实体商品
</
Option
>
<
Option
value=
{
2
}
>
虚拟商品
</
Option
>
<
Option
value=
{
4
}
>
服务类商品
</
Option
>
</
Select
>
</
FormItem
>
<
FormItem
name=
"thirdSkuNo"
label=
"第三方SKU编码"
>
<
FormItem
name=
"thirdSkuNo"
label=
"第三方SKU编码"
>
<
Input
placeholder=
"请输入第三方SKU编码"
allowClear
style=
{
selectW
}
/>
<
Input
placeholder=
"请输入第三方SKU编码"
allowClear
style=
{
selectW
}
/>
</
FormItem
>
</
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
}
>
查询
查询
...
@@ -220,6 +213,7 @@ class goodsManage extends Component {
...
@@ -220,6 +213,7 @@ class goodsManage extends Component {
<
Button
onClick=
{
()
=>
this
.
onReset
()
}
type=
"primary"
className=
{
styles
.
button
}
>
<
Button
onClick=
{
()
=>
this
.
onReset
()
}
type=
"primary"
className=
{
styles
.
button
}
>
重置
重置
</
Button
>
</
Button
>
{
this
.
state
.
productType
!==
5
&&
(
<
Button
<
Button
loading=
{
this
.
state
.
loading
}
loading=
{
this
.
state
.
loading
}
onClick=
{
()
=>
this
.
onExportGoodsInfo
()
}
onClick=
{
()
=>
this
.
onExportGoodsInfo
()
}
...
@@ -227,6 +221,7 @@ class goodsManage extends Component {
...
@@ -227,6 +221,7 @@ class goodsManage extends Component {
>
>
导出
导出
</
Button
>
</
Button
>
)
}
</
FormItem
>
</
FormItem
>
{
canEditable
?
(
{
canEditable
?
(
<
FormItem
style=
{
{
float
:
'
right
'
}
}
>
<
FormItem
style=
{
{
float
:
'
right
'
}
}
>
...
@@ -236,22 +231,6 @@ class goodsManage extends Component {
...
@@ -236,22 +231,6 @@ class goodsManage extends Component {
</
Button
>
</
Button
>
</
Popover
>
</
Popover
>
{
this
.
props
.
selectNum
>
0
&&
<
Tag
color=
"green"
>
已选商品
{
this
.
props
.
selectNum
}
</
Tag
>
}
{
this
.
props
.
selectNum
>
0
&&
<
Tag
color=
"green"
>
已选商品
{
this
.
props
.
selectNum
}
</
Tag
>
}
{
/* <Button
className={styles.button}
type="primary"
icon="download"
ghost
onClick={() => {
window.location.href = 'https://kdspstatic.q-gp.com/批量修改库存模板.xlsx';
}}
>
模版
</Button>
<Upload {...uploadProps}>
<Button type="primary" className={styles.button}>
批量库存修改
</Button>
</Upload> */
}
</
FormItem
>
</
FormItem
>
)
:
(
)
:
(
''
''
...
...
src/pages/GoodsManage/Takeaway/components/ActionBar.jsx
0 → 100644
View file @
8d5d77d7
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
=>
{
Modal
.
confirm
({
icon
:
<
ExclamationCircleOutlined
/>,
content
:
`确认
${
+
state
===
6
?
'
下架
'
:
'
上架
'
}
商品?`
,
onOk
:
async
()
=>
{
const
res
=
await
apiGoodsActionBatch
({
ids
:
options
.
selectedRowKeys
,
type
:
2
,
productState
:
+
state
===
6
?
7
:
6
,
// 6:上架,7:下架
});
if
(
res
.
businessCode
===
'
0000
'
&&
res
.
code
===
'
0000
'
)
{
options
.
handleSearch
();
}
},
});
};
/**
* 批量操作
* 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
'
]
}
>
<
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 @
8d5d77d7
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
})
=>
{
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
)
=>
{
const
dragIndex
=
item
.
index
;
const
hoverIndex
=
index
;
if
(
dragIndex
===
hoverIndex
)
return
;
// 如果回到自己的坑,那就什么都不做
endChangePosition
(
dragIndex
,
hoverIndex
);
// 调用传入的方法完成交换
},
});
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 @
8d5d77d7
import
React
,
{
useState
,
useEffect
}
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
=
options
=>
{
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
user
=
localStorage
.
getItem
(
'
user
'
);
const
json
=
JSON
.
parse
(
user
);
const
res
=
await
apiSupplierShopList
(
json
.
id
);
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
);
}
};
const
getGroupList
=
async
()
=>
{
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
);
}
};
const
handleEdit
=
async
id
=>
{
setStorageId
(
id
||
0
);
setIsModalOpen
(
true
);
};
const
handleDelete
=
async
id
=>
{
await
apiDelStorage
({
shopId
:
options
.
shopId
,
id
,
});
getGroupList
();
};
// 更换位置
const
changePosition
=
async
(
dragIndex
,
hoverIndex
)
=>
{
const
data
=
tags
.
slice
();
const
temp
=
data
[
dragIndex
];
// 交换位置
data
[
dragIndex
]
=
data
[
hoverIndex
];
data
[
hoverIndex
]
=
temp
;
setTags
(
data
);
};
const
endChangePosition
=
async
(
dragIndex
,
hoverIndex
)
=>
{
const
data
=
tags
.
slice
();
const
temp
=
data
[
dragIndex
];
// 交换位置
data
[
dragIndex
]
=
data
[
hoverIndex
];
data
[
hoverIndex
]
=
temp
;
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
]);
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 @
8d5d77d7
import
React
,
{
useEffect
,
useState
}
from
'
react
'
;
import
{
Form
,
Modal
,
Input
,
Switch
,
Alert
,
message
}
from
'
antd
'
;
import
{
apiCreateStorage
,
apiEditStorage
,
apiStorageInfo
}
from
'
../../service
'
;
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
;
await
api
({
name
,
necessary
:
necessary
?
1
:
0
,
shopId
:
options
.
shopId
,
id
:
options
.
id
,
});
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个“下单必选分组”商品每店仅可设置1个必点分组"
type=
"error"
/>
);
return
(
<
Modal
title=
"分组信息"
visible=
{
options
.
isModalOpen
}
destroyOnClose
maskClosable=
{
false
}
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 @
8d5d77d7
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 @
8d5d77d7
import
React
from
'
react
'
;
import
{
Modal
,
Form
,
Input
}
from
'
antd
'
;
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
}
confirmLoading=
{
options
.
loading
}
destroyOnClose
onCancel=
{
handleCancel
}
>
<
Form
name=
"basic"
form=
{
form
}
labelCol=
{
{
span
:
6
}
}
wrapperCol=
{
{
span
:
16
}
}
autoComplete=
"off"
>
<
Form
.
Item
label=
"最少购买/份"
name=
"minPurchaseNum"
rules=
{
[{
required
:
true
,
message
:
'
请输入最少购买数量!
'
}]
}
>
<
Input
maxLength=
{
6
}
type=
"number"
/>
</
Form
.
Item
>
</
Form
>
</
Modal
>
);
};
export
default
MinimumPurchase
;
src/pages/GoodsManage/Takeaway/components/SendModal.jsx
0 → 100644
View file @
8d5d77d7
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
}
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 @
8d5d77d7
import
React
,
{
useState
,
useEffect
}
from
'
react
'
;
import
{
Modal
,
Form
,
Input
,
Checkbox
,
Radio
,
Switch
}
from
'
antd
'
;
import
{
deepClone
}
from
'
@/utils/utils
'
;
import
styles
from
'
../../style.less
'
;
const
StockModal
=
options
=>
{
const
[
stockType
,
setStockType
]
=
useState
(
0
);
const
[
maxStock
,
setMaxStock
]
=
useState
(
0
);
const
[
form
]
=
Form
.
useForm
();
const
onChangeType
=
v
=>
{
setStockType
(
v
===
stockType
?
0
:
v
);
if
(
v
===
1
)
{
form
.
setFieldsValue
({
productStock
:
0
,
});
}
};
const
onChangeMaxStock
=
({
target
:
{
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
;
console
.
log
(
'
values :>>
'
,
values
);
options
.
confirm
({
type
:
7
,
...
values
,
});
};
const
initialValues
=
Object
.
assign
(
{
productStock
:
''
,
autoStockStep
:
''
,
autoStock
:
false
,
},
options
.
initialValues
,
);
useEffect
(()
=>
{
if
(
stockType
===
2
)
{
form
.
setFieldsValue
({
productStock
:
maxStock
,
});
}
},
[
maxStock
,
stockType
]);
return
(
<
Modal
visible=
{
options
.
visible
}
title=
"修改库存"
onOk=
{
handleOk
}
maskClosable=
{
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
:
'
请输入剩余库存!
'
}]
}
>
<
Input
type=
"number"
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=
{
[{
required
:
true
,
message
:
'
请输入最大库存!
'
}]
}
>
<
Input
type=
"number"
onChange=
{
onChangeMaxStock
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"自动补足"
name=
"autoStock"
>
<
Switch
checkedChildren=
"开启"
unCheckedChildren=
"关闭"
/>
</
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 @
8d5d77d7
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
}
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 @
8d5d77d7
import
React
,
{
useState
}
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
(
1
);
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
values
=
await
form
.
validateFields
();
const
params
=
deepClone
(
values
);
if
(
params
.
saleTimes
&&
params
.
saleTimes
.
length
)
{
params
.
saleTimes
=
values
.
saleTimes
.
map
(
item
=>
{
if
(
item
&&
item
.
length
>
1
)
{
item
[
0
]
=
moment
(
item
[
0
]).
format
(
'
HH:mm
'
);
item
[
1
]
=
moment
(
item
[
1
]).
format
(
'
HH:mm
'
);
}
return
item
;
});
}
options
.
confirm
({
type
:
4
,
...
params
,
});
};
const
initialValues
=
Object
.
assign
(
{
saleTimeType
:
1
,
saleDates
:
[],
saleTimes
:
[[]],
},
options
.
initialValues
,
);
return
(
<
Modal
visible=
{
options
.
visible
}
title=
"售卖时间"
onOk=
{
handleOk
}
maskClosable=
{
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=
"saleTimeType"
rules=
{
[{
required
:
true
,
message
:
'
请选择售卖时间段类型!
'
}]
}
>
<
Radio
.
Group
options=
{
radioOptions
}
onChange=
{
onChangeType
}
value=
{
type
}
optionType=
"button"
buttonStyle=
"solid"
/>
</
Form
.
Item
>
{
type
===
2
?
(
<>
<
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
:
'
请选择售卖时间
'
,
},
]
}
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 @
8d5d77d7
import
React
,
{
useState
,
useEffect
,
useCallback
,
useMemo
}
from
'
react
'
;
import
{
Spin
,
Table
,
Modal
,
message
,
notification
}
from
'
antd
'
;
import
{
MenuOutlined
,
HolderOutlined
,
FormOutlined
,
CloseCircleOutlined
}
from
'
@ant-design/icons
'
;
import
{
SortableContainer
,
SortableElement
,
SortableHandle
}
from
'
react-sortable-hoc
'
;
import
{
arrayMoveImmutable
}
from
'
array-move
'
;
import
GoodsGroup
from
'
./components/GoodsGroup
'
;
import
{
apiTakeawayGoods
,
apiGoodsActionBatch
,
apiSortTakeawayGoods
}
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
[
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
rowSelection
=
{
selectedRowKeys
,
onChange
:
setSelectedRowKeys
,
};
const
getDataList
=
async
()
=>
{
setLoading
(
true
);
const
params
=
{
pageNo
:
1
,
productType
:
5
,
pageSize
:
100000
,
storageRackId
:
groupId
,
};
const
res
=
await
apiTakeawayGoods
(
params
);
setLoading
(
false
);
if
(
res
&&
res
.
data
)
{
setTableData
(
res
.
data
.
records
);
}
};
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
:
index
+
1
,
}));
const
params
=
{
storageRackId
:
groupId
,
type
:
1
,
shopId
,
skuSorts
,
};
await
apiSortTakeawayGoods
(
params
);
getDataList
();
// 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
params2
=
{
...
json
,
...
params
,
};
console
.
log
(
'
params2 :>>
'
,
params2
);
const
res
=
await
apiGoodsActionBatch
(
Object
.
assign
({},
json
,
params
));
setActionLoading
(
false
);
getDataList
();
message
.
success
(
'
处理成功!
'
);
};
// 显示弹窗
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
})
=>
{
options
.
handleEdit
({
shopId
,
spuId
,
});
};
// 新建商品
const
onNew
=
()
=>
{
options
.
handleEdit
({
shopId
,
groupId
,
});
};
// 置顶
const
toTop
=
row
=>
{};
useEffect
(()
=>
{
if
(
groupId
)
{
getDataList
();
}
},
[
groupId
]);
const
actions
=
{
onShowStockModal
,
toTop
,
onEdit
,
};
return
(
<
div
className=
{
styles
.
takeawayBox
}
>
<
Spin
spinning=
{
loading
}
>
<
GoodsGroup
shopId=
{
shopId
}
changeShop=
{
setShopId
}
changeGroup=
{
setGroupId
}
/>
<
ActionBar
selectedRowKeys=
{
selectedRowKeys
}
handleSearch=
{
getDataList
}
openModal=
{
openModal
}
newGoods=
{
onNew
}
/>
<
Table
dataSource=
{
tableData
}
bordered
columns=
{
takeawayColumn
(
actions
)
}
rowKey=
{
record
=>
record
.
skuId
}
pagination=
{
false
}
scroll=
{
{
x
:
'
100%
'
,
y
:
1000
}
}
rowSelection=
{
rowSelection
}
components=
{
{
body
:
{
wrapper
:
DraggableContainer
,
row
:
DraggableBodyRow
,
},
}
}
/>
</
Spin
>
<
WeekTime
visible=
{
visibleWeekTime
}
loading=
{
actionLoading
}
confirm=
{
handleBatchAction
}
cancel=
{
setVisibleWeekTime
}
/>
<
StockModal
visible=
{
visibleStock
}
loading=
{
actionLoading
}
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 @
8d5d77d7
...
@@ -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
'
;
...
@@ -59,6 +61,8 @@ class goodsManage extends Component {
...
@@ -59,6 +61,8 @@ class goodsManage extends Component {
auditRow
:
{},
// 查看审核信息使用
auditRow
:
{},
// 查看审核信息使用
isVisibleDraft
:
false
,
// 显示隐藏草稿箱
isVisibleDraft
:
false
,
// 显示隐藏草稿箱
isEditDraft
:
false
,
// 是否编辑草稿
isEditDraft
:
false
,
// 是否编辑草稿
productType
:
1
,
// 商品类型
takeAway
:
{},
// 弹窗外卖商品参数
};
};
currentLog
=
null
;
currentLog
=
null
;
...
@@ -74,6 +78,7 @@ class goodsManage extends Component {
...
@@ -74,6 +78,7 @@ class goodsManage extends Component {
this
.
categoryList
();
this
.
categoryList
();
this
.
getVirtualCategory
();
this
.
getVirtualCategory
();
this
.
specList
();
this
.
specList
();
this
.
setState
({
productType
:
5
});
}
}
handleSearch
=
page
=>
{
handleSearch
=
page
=>
{
...
@@ -265,9 +270,10 @@ class goodsManage extends Component {
...
@@ -265,9 +270,10 @@ class goodsManage extends Component {
}
}
};
};
categoryList
=
async
()
=>
{
categoryList
=
async
type
=>
{
const
api
=
type
?
apiCategoryListType
:
categoryList
;
try
{
try
{
const
{
data
:
treeData
}
=
await
categoryList
(
);
const
{
data
:
treeData
}
=
await
api
(
type
);
if
(
!
treeData
)
return
;
if
(
!
treeData
)
return
;
this
.
setState
({
treeData
});
this
.
setState
({
treeData
});
}
catch
(
e
)
{
}
catch
(
e
)
{
...
@@ -275,6 +281,13 @@ class goodsManage extends Component {
...
@@ -275,6 +281,13 @@ class goodsManage extends Component {
}
}
};
};
changeProductType
=
e
=>
{
this
.
setState
({
productType
:
e
||
1
,
});
this
.
categoryList
(
e
);
};
getVirtualCategory
=
async
()
=>
{
getVirtualCategory
=
async
()
=>
{
try
{
try
{
const
{
data
:
virtualTreeData
}
=
await
getVirtualCategory
();
const
{
data
:
virtualTreeData
}
=
await
getVirtualCategory
();
...
@@ -355,6 +368,14 @@ class goodsManage extends Component {
...
@@ -355,6 +368,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
=
{}
},
...
@@ -411,9 +432,14 @@ class goodsManage extends Component {
...
@@ -411,9 +432,14 @@ class goodsManage extends Component {
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
>
{
this
.
state
.
productType
===
5
?
(
<
Takeaway
handleEdit=
{
this
.
handleTakeawayEdit
}
/>
)
:
(
<>
<
Spin
spinning=
{
this
.
state
.
loading
}
>
<
Spin
spinning=
{
this
.
state
.
loading
}
>
<
Table
<
Table
dataSource=
{
tableData
?.
records
}
dataSource=
{
tableData
?.
records
}
...
@@ -485,6 +511,9 @@ class goodsManage extends Component {
...
@@ -485,6 +511,9 @@ class goodsManage extends Component {
isType=
{
this
.
state
.
isType
}
isType=
{
this
.
state
.
isType
}
templateList=
{
this
.
state
.
templateList
}
templateList=
{
this
.
state
.
templateList
}
/>
/>
</>
)
}
</
Spin
>
{
this
.
state
.
serviceVisble
&&
(
{
this
.
state
.
serviceVisble
&&
(
<
ServiceGoods
<
ServiceGoods
visible=
{
this
.
state
.
serviceVisble
}
visible=
{
this
.
state
.
serviceVisble
}
...
@@ -496,9 +525,10 @@ class goodsManage extends Component {
...
@@ -496,9 +525,10 @@ class goodsManage extends Component {
specListData=
{
this
.
state
.
specListData
}
specListData=
{
this
.
state
.
specListData
}
permissions=
{
permissions
}
permissions=
{
permissions
}
isDraft=
{
this
.
state
.
isEditDraft
}
isDraft=
{
this
.
state
.
isEditDraft
}
productType=
{
this
.
state
.
productType
}
takeAway=
{
this
.
state
.
takeAway
}
/>
/>
)
}
)
}
</
Spin
>
{
this
.
state
.
visibleAuditModal
&&
(
{
this
.
state
.
visibleAuditModal
&&
(
<
InfoAudit
<
InfoAudit
visible=
{
this
.
state
.
visibleAuditModal
}
visible=
{
this
.
state
.
visibleAuditModal
}
...
...
src/pages/GoodsManage/service.js
View file @
8d5d77d7
...
@@ -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
}
`
,
{
...
@@ -290,10 +290,76 @@ export async function apiDraftList(data) {
...
@@ -290,10 +290,76 @@ export async function apiDraftList(data) {
});
});
}
}
//
新增外卖商品
//
批量操作
export
async
function
a
ddTakeOutGoods
(
params
)
{
export
async
function
a
piGoodsActionBatch
(
data
)
{
return
request
.
post
(
'
/
v1/channels/products/add
'
,
{
return
request
.
post
(
'
/
api/merchants/products/sku/batchOperation
'
,
{
prefix
:
goodsApi
,
prefix
:
goodsApi
,
data
:
params
,
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
apiSupplierShopList
()
{
return
request
.
get
(
'
/api/merchants/shops/getBySupplierId?state=1
'
,
{
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
,
});
});
}
}
src/pages/GoodsManage/staticdata.js
View file @
8d5d77d7
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
{
Button
,
Badge
,
Switch
,
Modal
}
from
'
antd
'
;
import
{
Button
,
Badge
,
Switch
,
Modal
}
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
,
apiQueryLastAuditRecord
}
from
'
./service
'
;
import
{
apiChangeStateGoods
}
from
'
./service
'
;
const
{
confirm
}
=
Modal
;
const
{
confirm
}
=
Modal
;
...
@@ -244,6 +245,199 @@ export function column() {
...
@@ -244,6 +245,199 @@ export function column() {
},
},
];
];
}
}
export
function
takeawayColumn
(
actions
)
{
const
onChangeState
=
async
({
skuId
,
state
})
=>
{
confirm
({
icon
:
<
ExclamationCircleOutlined
/>
,
content
:
`确认
${
+
state
===
6
?
'
下架
'
:
'
上架
'
}
商品?`
,
onOk
:
async
()
=>
{
const
res
=
await
apiChangeStateGoods
({
skuIds
:
skuId
,
productStatus
:
+
state
===
6
?
7
:
6
,
// 6:上架,7:下架
});
if
(
res
.
businessCode
===
'
0000
'
&&
res
.
code
===
'
0000
'
)
{
this
.
handleSearch
();
}
},
});
};
const
onShowAudit
=
row
=>
{
this
.
setState
({
auditRow
:
row
,
visibleAuditModal
:
true
,
});
};
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
:
'
marketPrice
'
,
width
:
150
,
align
:
'
center
'
,
render
:
(
_
,
row
)
=>
(
<
div
className
=
{
styles
.
price
}
>
<
div
>
供货价:
{(
row
.
supplyPrice
||
0
).
toFixed
(
2
)}
<
/div
>
<
div
>
市场价:
{(
row
.
marketPrice
||
0
).
toFixed
(
2
)}
<
/div
>
<
/div
>
),
},
{
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
&&
(
<
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 @
8d5d77d7
...
@@ -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,147 @@
...
@@ -130,3 +136,147 @@
text-align: left;
text-align: left;
word-break: break-all;
word-break: break-all;
}
}
.takeawayBox {
margin-top: 20px;
padding-bottom: 40px;
background-color: #fff;
}
.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;
}
}
src/pages/cancelBillManage/data.js
View file @
8d5d77d7
...
@@ -14,6 +14,7 @@ export const column = [
...
@@ -14,6 +14,7 @@ export const column = [
<
div
>
<
div
>
{
r
.
auditTimeOut
?
<
Tag
color
=
"
red
"
>
{
orderId
}
<
/Tag> : orderId
}
{
r
.
auditTimeOut
?
<
Tag
color
=
"
red
"
>
{
orderId
}
<
/Tag> : orderId
}
{
<
Badge
count
=
{
r
.
reminderFlag
?
'
催
'
:
''
}
size
=
"
small
"
/>
}
{
<
Badge
count
=
{
r
.
reminderFlag
?
'
催
'
:
''
}
size
=
"
small
"
/>
}
{
<
Badge
count
=
{
+
r
.
autoCancelTimeType
===
1
?
'
大额支付
'
:
''
}
size
=
"
default
"
/>
}
<
/div
>
<
/div
>
),
),
},
},
...
...
src/utils/websocket.js
View file @
8d5d77d7
...
@@ -100,9 +100,12 @@ class Socket extends EventEmitter {
...
@@ -100,9 +100,12 @@ class Socket extends EventEmitter {
};
};
onerror
=
e
=>
{
onerror
=
e
=>
{
console
.
log
(
'
ws: error
'
,
e
);
try
{
this
.
socket
=
null
;
this
.
socket
=
null
;
this
.
event
.
emit
(
'
error
'
,
e
);
this
.
event
.
emit
(
'
error
'
,
e
);
}
catch
{
console
.
log
(
'
ws: error
'
,
e
);
}
};
};
sendMessage
=
value
=>
{
sendMessage
=
value
=>
{
...
...
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