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
aeac15f4
Commit
aeac15f4
authored
Oct 26, 2022
by
杨鑫
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature/commodity-properties' into 'master'
Feature/commodity properties See merge request
!62
parents
7eefd136
24e5ad8c
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
484 additions
and
67 deletions
+484
-67
.eslintrc.js
.eslintrc.js
+1
-0
env.config.js
config/env.config.js
+10
-15
index.jsx
src/pages/GoodsManage/createModal/index.jsx
+264
-12
infoAudit.jsx
src/pages/GoodsManage/createModal/infoAudit.jsx
+60
-0
index.jsx
src/pages/GoodsManage/index.jsx
+34
-14
service.js
src/pages/GoodsManage/service.js
+29
-0
staticdata.js
src/pages/GoodsManage/staticdata.js
+16
-2
style.less
src/pages/GoodsManage/style.less
+16
-0
upload.jsx
src/pages/PaymentMange/ToExamine/upload.jsx
+7
-5
EditFormTable.jsx
src/pages/ServiceGoods/components/EditFormTable.jsx
+0
-1
FormRuleSetting.jsx
src/pages/ServiceGoods/components/FormRuleSetting.jsx
+23
-2
FormRuleVPictures.jsx
src/pages/ServiceGoods/components/FormRuleVPictures.jsx
+1
-0
UploadImage.jsx
src/pages/ServiceGoods/components/UploadImage.jsx
+19
-15
config.js
src/pages/ServiceGoods/config.js
+1
-1
qiniu.js
src/services/qiniu.js
+3
-0
No files found.
.eslintrc.js
View file @
aeac15f4
...
@@ -14,5 +14,6 @@ module.exports = {
...
@@ -14,5 +14,6 @@ module.exports = {
'
@typescript-eslint/no-unused-vars
'
:
[
'
off
'
],
'
@typescript-eslint/no-unused-vars
'
:
[
'
off
'
],
'
import/no-unresolved
'
:
0
,
'
import/no-unresolved
'
:
0
,
'
import/extensions
'
:
0
,
'
import/extensions
'
:
0
,
'
no-unused-expressions
'
:
[
'
error
'
,
{
allowShortCircuit
:
true
}],
},
},
};
};
config/env.config.js
View file @
aeac15f4
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
envAPi
=
{
const
envAPi
=
{
api
:
'
https://security-xyqb.liangkebang.net
'
,
//'https://security-xyqb.liangkebang.net',
api
:
`https://security-
${
environment
}
.liangkebang.net`
,
kdspOpApi
:
'
https://sc-merchant-api-xyqb.liangkebang.net
'
,
kdspOpApi
:
`https://sc-merchant-api-
${
environment
}
.liangkebang.net`
,
kdspApi
:
'
https://sc-merchant-api-xyqb.liangkebang.net
'
,
kdspApi
:
`https://sc-merchant-api-
${
environment
}
.liangkebang.net`
,
goodsApi
:
'
https://sc-merchant-api-xyqb.liangkebang.net
'
,
goodsApi
:
`https://sc-merchant-api-
${
environment
}
.liangkebang.net`
,
// kdspOpApi: 'https://kdsp-operation-xyqb.liangkebang.net',
querysApi
:
`https://sc-merchant-api-
${
environment
}
.liangkebang.net/admin/merchant/sc-settlement`
,
// kdspApi: 'https://sc-op-api-xyqb.liangkebang.net',
prologueDomain
:
`https://mall-
${
environment
}
.liangkebang.net`
,
// goodsApi: 'https://sc-op-api-xyqb.liangkebang.net',
qiniuHost
:
`https://kdspstatic.q-gp.com/`
,
querysApi
:
'
https://sc-merchant-api-sc.liangkebang.net
'
,
opapiHost
:
`https://yxm-gateway-
${
environment
}
.liangkebang.net`
,
// goodsApi: '//192.168.188.111:7000',
prologueDomain
:
'
https://mall-sc.liangkebang.net
'
,
// qiniuHost: 'https://appsync.lkbang.net',
qiniuHost
:
'
https://kdspstatic.q-gp.com/
'
,
opapiHost
:
'
https://opapi-sc.liangkebang.net
'
,
};
};
const
prodApi
=
{
const
prodApi
=
{
...
@@ -26,7 +21,7 @@ const prodApi = {
...
@@ -26,7 +21,7 @@ const prodApi = {
goodsApi
:
'
https://sc-merchant-api.q-gp.com
'
,
// 线上环境打包域名
goodsApi
:
'
https://sc-merchant-api.q-gp.com
'
,
// 线上环境打包域名
qiniuHost
:
'
https://kdspstatic.q-gp.com/
'
,
qiniuHost
:
'
https://kdspstatic.q-gp.com/
'
,
// talos 后面要下线
// talos 后面要下线
opapiHost
:
'
//
talos.xyqb
.com
'
,
opapiHost
:
'
//
gw.yxmie
.com
'
,
// opapiHost: 'https://opapi.q-gp.com',
// opapiHost: 'https://opapi.q-gp.com',
// querysApi: 'https://sc-settlement-api.q-gp.com',
// querysApi: 'https://sc-settlement-api.q-gp.com',
querysApi
:
'
https://sc-merchant-api.q-gp.com/admin/merchant/sc-settlement
'
,
querysApi
:
'
https://sc-merchant-api.q-gp.com/admin/merchant/sc-settlement
'
,
...
...
src/pages/GoodsManage/createModal/index.jsx
View file @
aeac15f4
...
@@ -2,7 +2,13 @@
...
@@ -2,7 +2,13 @@
import
{
Form
}
from
'
@ant-design/compatible
'
;
import
{
Form
}
from
'
@ant-design/compatible
'
;
import
'
@ant-design/compatible/assets/index.css
'
;
import
'
@ant-design/compatible/assets/index.css
'
;
import
{
MinusCircleOutlined
,
PlusOutlined
,
RestOutlined
}
from
'
@ant-design/icons
'
;
import
{
MinusCircleOutlined
,
PlusOutlined
,
RestOutlined
,
DownOutlined
,
UpOutlined
,
}
from
'
@ant-design/icons
'
;
import
{
import
{
Modal
,
Modal
,
Table
,
Table
,
...
@@ -37,6 +43,7 @@ import {
...
@@ -37,6 +43,7 @@ import {
addGoods
,
addGoods
,
editGoods
,
editGoods
,
queryAllAfterAddress
,
queryAllAfterAddress
,
apiGetAttribute
,
}
from
'
../service
'
;
}
from
'
../service
'
;
import
styles
from
'
../style.less
'
;
import
styles
from
'
../style.less
'
;
import
Upload
from
'
../../components/sortablUpload
'
;
import
Upload
from
'
../../components/sortablUpload
'
;
...
@@ -68,17 +75,31 @@ class goodsManage extends Component {
...
@@ -68,17 +75,31 @@ class goodsManage extends Component {
productType
:
1
,
productType
:
1
,
confirmLoading
:
false
,
confirmLoading
:
false
,
afterAddressList
:
{},
afterAddressList
:
{},
// isAttrLoading: false,
categoryAttrs
:
[],
// 获取类目下属性
};
};
componentDidMount
()
{
componentDidMount
()
{
this
.
getSpecData
();
this
.
getSpecData
();
this
.
getBrandData
();
this
.
getBrandData
();
this
.
getAfterAddressData
();
this
.
getAfterAddressData
();
const
{
initData
=
{}
}
=
this
.
props
;
const
isEdit
=
Object
.
keys
(
initData
).
length
!==
0
;
if
(
isEdit
)
{
this
.
getAttribute
(
initData
.
thirdCategoryId
||
initData
.
secondCategoryId
||
initData
.
firstCategoryId
,
);
}
}
}
componentWillReceiveProps
()
{
// componentWillReceiveProps(nextProps) {
this
.
setState
({
isCancel
:
false
});
// if (nextProps.visible && !this.state.isAttrLoading) {
}
// this.setState({
// isAttrLoading: true,
// });
// }
// this.setState({ isCancel: false });
// }
// 获取售后地址
// 获取售后地址
getAfterAddressData
=
async
()
=>
{
getAfterAddressData
=
async
()
=>
{
...
@@ -204,8 +225,24 @@ class goodsManage extends Component {
...
@@ -204,8 +225,24 @@ class goodsManage extends Component {
this
.
setState
({
initForm
});
this
.
setState
({
initForm
});
};
};
// 获取属性
getAttribute
=
async
categoryId
=>
{
const
res
=
await
apiGetAttribute
(
categoryId
);
let
categoryAttrs
=
[];
if
(
res
&&
res
.
data
&&
res
.
data
.
length
)
{
categoryAttrs
=
res
.
data
;
}
this
.
setState
({
categoryAttrs
,
});
};
treeChange
=
value
=>
{
treeChange
=
value
=>
{
this
.
setState
({
categoryId
:
value
[
value
.
length
-
1
],
initCascader
:
value
});
const
cid
=
value
[
value
.
length
-
1
];
this
.
setState
({
categoryId
:
cid
,
initCascader
:
value
});
if
(
value
.
length
===
3
)
{
this
.
getAttribute
(
cid
);
}
};
};
remove
=
(
flag
,
k
)
=>
{
remove
=
(
flag
,
k
)
=>
{
...
@@ -350,6 +387,18 @@ class goodsManage extends Component {
...
@@ -350,6 +387,18 @@ class goodsManage extends Component {
});
});
};
};
deal
=
attr
=>
{
try
{
const
json
=
JSON
.
parse
(
attr
);
if
(
typeof
json
===
'
object
'
&&
this
.
checkInAttrList
(
json
.
attributeValueId
))
{
return
json
;
}
return
{
attributeValueName
:
json
};
}
catch
{
return
{
attributeValueName
:
attr
};
}
};
// 最终提交
// 最终提交
confirm
=
async
isContinue
=>
{
confirm
=
async
isContinue
=>
{
const
{
const
{
...
@@ -359,6 +408,7 @@ class goodsManage extends Component {
...
@@ -359,6 +408,7 @@ class goodsManage extends Component {
}
=
this
.
props
;
}
=
this
.
props
;
const
{
editData
,
productType
}
=
this
.
state
;
const
{
editData
,
productType
}
=
this
.
state
;
validateFields
(
async
(
errors
,
values
)
=>
{
validateFields
(
async
(
errors
,
values
)
=>
{
console
.
log
(
'
values :>>
'
,
values
);
if
(
!
values
.
afterAddressId
)
{
if
(
!
values
.
afterAddressId
)
{
notification
.
error
({
notification
.
error
({
message
:
'
请选择售后地址
'
,
message
:
'
请选择售后地址
'
,
...
@@ -390,6 +440,45 @@ class goodsManage extends Component {
...
@@ -390,6 +440,45 @@ class goodsManage extends Component {
});
});
}
}
});
});
const
attributeApplyList
=
[];
let
isMaxLength
=
false
;
if
(
values
.
attributeApplyList
&&
values
.
attributeApplyList
.
length
)
{
values
.
attributeApplyList
.
forEach
(
item
=>
{
const
key
=
Object
.
keys
(
item
)[
0
];
let
attrs
=
item
[
key
];
if
(
Array
.
isArray
(
item
[
key
]))
{
attrs
=
[];
item
[
key
].
forEach
(
attr
=>
{
const
json
=
this
.
deal
(
attr
);
if
(
!
json
)
{
return
;
}
// eslint-disable-next-line no-unused-expressions
json
.
attributeValueName
.
length
>
30
&&
(
isMaxLength
=
true
);
attrs
.
push
(
json
);
});
}
else
{
const
json
=
this
.
deal
(
item
[
key
]);
if
(
!
json
)
{
return
;
}
// eslint-disable-next-line no-unused-expressions
json
.
attributeValueName
.
length
>
30
&&
(
isMaxLength
=
true
);
attrs
=
[
json
];
}
attributeApplyList
.
push
({
attributeId
:
key
.
replace
(
'
attr
'
,
''
),
attributeApplyValueList
:
attrs
,
});
});
if
(
isMaxLength
)
{
notification
.
error
({
message
:
'
自定义属性不能超过30个字符
'
,
});
return
;
}
}
await
this
.
setState
(
prev
=>
({
await
this
.
setState
(
prev
=>
({
confirmLoading
:
true
,
confirmLoading
:
true
,
createData
:
{
createData
:
{
...
@@ -406,6 +495,7 @@ class goodsManage extends Component {
...
@@ -406,6 +495,7 @@ class goodsManage extends Component {
specs
,
specs
,
character
:
values
.
character
,
character
:
values
.
character
,
afterAddressId
:
values
.
afterAddressId
,
afterAddressId
:
values
.
afterAddressId
,
attributeApplyList
,
},
},
}));
}));
const
data
=
initData
.
id
const
data
=
initData
.
id
...
@@ -475,6 +565,70 @@ class goodsManage extends Component {
...
@@ -475,6 +565,70 @@ class goodsManage extends Component {
this
.
BatchSetting
.
formRef
.
current
.
resetFields
();
this
.
BatchSetting
.
formRef
.
current
.
resetFields
();
};
};
/**
* 获取下拉框类型
* supportCustomValue:是否支持自定义:1 是 0 否
* optionType:选项类型:1 单选 2 多选
*/
getMode
=
(
supportCustomValue
,
optionType
)
=>
{
if
(
+
supportCustomValue
.
code
===
1
)
{
return
'
tags
'
;
}
if
(
+
optionType
.
code
===
2
)
{
return
'
multiple
'
;
}
return
'
default
'
;
};
// 验证是否失效属性(已失效的商品不显示)
checkInAttrList
=
id
=>
this
.
state
.
categoryAttrs
.
some
(
item
=>
item
.
valueList
.
some
(
v
=>
+
v
.
id
===
+
id
));
// 获取初始化属性数据
getInitAttrValue
=
(
id
,
supportCustomValue
,
optionType
)
=>
{
const
skuAttr
=
this
.
props
.
initData
.
productAttributeApplyList
?.
productAttributeApplyList
||
[];
const
v
=
skuAttr
.
filter
(
item
=>
id
===
item
.
productAttributeId
);
if
(
v
.
length
&&
v
[
0
].
productAttributeApplyValueList
&&
v
[
0
].
productAttributeApplyValueList
.
length
)
{
const
values
=
[];
v
[
0
].
productAttributeApplyValueList
.
forEach
(
attr
=>
{
if
(
+
attr
.
attributeValueId
)
{
if
(
this
.
checkInAttrList
(
attr
.
attributeValueId
))
{
values
.
push
(
JSON
.
stringify
({
attributeValueId
:
attr
.
attributeValueId
,
attributeValueName
:
attr
.
attributeValueName
,
}),
);
}
}
else
{
values
.
push
(
attr
.
attributeValueName
);
}
return
values
;
});
if
(
+
supportCustomValue
.
code
===
1
||
+
optionType
.
code
===
2
)
{
return
values
;
}
if
(
v
[
0
].
productAttributeApplyValueList
.
length
)
{
const
atvalue
=
v
[
0
].
productAttributeApplyValueList
[
0
];
if
(
this
.
checkInAttrList
(
atvalue
.
attributeValueId
))
{
return
JSON
.
stringify
({
attributeValueId
:
atvalue
.
attributeValueId
,
attributeValueName
:
atvalue
.
attributeValueName
,
});
}
}
return
''
;
}
if
(
+
supportCustomValue
.
code
===
1
||
+
optionType
.
code
===
2
)
{
return
[];
}
return
''
;
};
validateToInputName
=
(
rule
,
value
,
callback
)
=>
{
validateToInputName
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
.
trim
().
length
<
2
)
{
if
(
value
.
trim
().
length
<
2
)
{
callback
(
new
Error
(
'
商品名称不可小于2个字符
'
));
callback
(
new
Error
(
'
商品名称不可小于2个字符
'
));
...
@@ -515,6 +669,10 @@ class goodsManage extends Component {
...
@@ -515,6 +669,10 @@ class goodsManage extends Component {
labelCol
:
{
span
:
2
},
labelCol
:
{
span
:
2
},
wrapperCol
:
{
span
:
22
},
wrapperCol
:
{
span
:
22
},
};
};
const
formItemAttr
=
{
labelCol
:
{
span
:
6
},
wrapperCol
:
{
span
:
16
},
};
const
{
const
{
colorImg
,
colorImg
,
productType
,
productType
,
...
@@ -525,6 +683,7 @@ class goodsManage extends Component {
...
@@ -525,6 +683,7 @@ class goodsManage extends Component {
}
=
this
.
state
;
}
=
this
.
state
;
const
skuSpeFirstKeys
=
initData
.
firstSpecList
||
[];
const
skuSpeFirstKeys
=
initData
.
firstSpecList
||
[];
const
skuSpeSecondKeys
=
initData
.
secondSpecList
||
[];
const
skuSpeSecondKeys
=
initData
.
secondSpecList
||
[];
const
skuOldAttr
=
initData
.
productAttributeApplyList
?.
oldProductAttributeApplyList
||
[];
const
treeDataArray
=
productType
===
2
?
virtualTreeData
:
treeData
;
const
treeDataArray
=
productType
===
2
?
virtualTreeData
:
treeData
;
const
brandListArray
=
productType
===
2
?
brandList
:
normalBrandList
;
const
brandListArray
=
productType
===
2
?
brandList
:
normalBrandList
;
dataInit
(
this
.
state
.
editData
);
dataInit
(
this
.
state
.
editData
);
...
@@ -534,11 +693,6 @@ class goodsManage extends Component {
...
@@ -534,11 +693,6 @@ class goodsManage extends Component {
if
(
isEdit
&&
!
initData
.
editData
[
0
]?.
firstSpec
&&
!
initData
.
editData
[
0
]?.
secondSpec
)
{
if
(
isEdit
&&
!
initData
.
editData
[
0
]?.
firstSpec
&&
!
initData
.
editData
[
0
]?.
secondSpec
)
{
colorKeys
=
colorKeys
.
length
>
1
?
colorKeys
.
filter
(
item
=>
item
!==
'
null
'
)
:
colorKeys
;
colorKeys
=
colorKeys
.
length
>
1
?
colorKeys
.
filter
(
item
=>
item
!==
'
null
'
)
:
colorKeys
;
}
}
const
optionsWithDisabled
=
[
{
label
:
'
Apple
'
,
value
:
'
Apple
'
},
{
label
:
'
Pear
'
,
value
:
'
Pear
'
},
{
label
:
'
Orange
'
,
value
:
'
Orange
'
,
disabled
:
false
},
];
return
(
return
(
<
Modal
<
Modal
...
@@ -721,6 +875,103 @@ class goodsManage extends Component {
...
@@ -721,6 +875,103 @@ class goodsManage extends Component {
:
''
}
:
''
}
</
Row
>
</
Row
>
</
Card
>
</
Card
>
{
/* 商品属性 */
}
<
Card
className=
{
styles
.
card
}
bordered=
{
false
}
>
<
div
className=
{
styles
.
cardTitle
}
>
商品属性
</
div
>
<
div
className=
{
styles
.
attrbox
+
(
this
.
state
.
isMore
?
styles
.
attrboxMore
:
''
)
}
more=
{
this
.
state
.
isMore
}
>
<
Row
>
{
this
.
state
.
categoryAttrs
.
length
>
0
&&
this
.
state
.
categoryAttrs
.
map
((
k
,
i
)
=>
(
<
Col
span=
{
12
}
key=
{
k
.
id
}
>
<
FormItem
label=
{
k
.
name
}
{
...
formItemAttr
}
key=
{
k
.
id
}
>
{
getFieldDecorator
(
`attributeApplyList[${i}]['attr${k.id}']`
,
{
initialValue
:
this
.
getInitAttrValue
(
k
.
id
,
k
.
supportCustomValue
,
k
.
optionType
,
),
// +k.supportCustomValue.code === 1 || +k.optionType.code === 2 ? [] : '',
validateTrigger
:
[
'
onChange
'
],
rules
:
+
k
.
required
.
code
===
1
?
[
{
required
:
true
,
type
:
+
k
.
supportCustomValue
.
code
===
1
||
+
k
.
optionType
.
code
===
2
?
'
array
'
:
'
string
'
,
message
:
'
请选择
'
,
},
]
:
[],
})(
<
Select
mode=
{
this
.
getMode
(
k
.
supportCustomValue
,
k
.
optionType
)
}
maxTagTextLength=
{
8
}
allowClear
>
{
k
.
valueList
&&
k
.
valueList
.
length
&&
k
.
valueList
.
map
(
a
=>
(
<
Option
key=
{
a
.
id
}
value=
{
JSON
.
stringify
({
attributeValueId
:
a
.
id
,
attributeValueName
:
a
.
name
,
})
}
>
{
a
.
name
}
</
Option
>
))
}
</
Select
>,
)
}
</
FormItem
>
</
Col
>
))
}
</
Row
>
</
div
>
{
this
.
state
.
categoryAttrs
.
length
>
12
&&
(
<
div
>
<
Button
type=
"link"
onClick=
{
()
=>
this
.
setState
(
state
=>
({
isMore
:
!
state
.
isMore
,
}))
}
>
{
this
.
state
.
isMore
?
'
收起
'
:
'
展示更多
'
}
{
this
.
state
.
isMore
?
<
UpOutlined
/>
:
<
DownOutlined
/>
}
</
Button
>
</
div
>
)
}
{
skuOldAttr
.
length
>
0
&&
(
<
div
>
<
Row
>
注:以下商品属性已失效,请使用新的属性
</
Row
>
<
Row
>
{
skuOldAttr
.
map
(
s
=>
(
<
Col
span=
{
12
}
key=
{
s
.
id
}
>
<
FormItem
label=
{
s
.
productAttributeName
}
{
...
formItemAttr
}
required=
{
false
}
key=
{
s
.
id
}
>
{
s
.
productAttributeApplyValueList
.
map
(
item
=>
item
.
attributeValueName
)
.
join
(
'
;
'
)
}
</
FormItem
>
</
Col
>
))
}
</
Row
>
</
div
>
)
}
</
Card
>
<
Card
className=
{
styles
.
card
}
bordered=
{
false
}
>
<
Card
className=
{
styles
.
card
}
bordered=
{
false
}
>
<
Row
>
<
Row
>
<
FormItem
label=
"一级规格"
>
<
FormItem
label=
"一级规格"
>
...
@@ -760,7 +1011,7 @@ class goodsManage extends Component {
...
@@ -760,7 +1011,7 @@ class goodsManage extends Component {
value=
{
k
}
value=
{
k
}
disabled
disabled
placeholder=
"请输入规格名称"
placeholder=
"请输入规格名称"
style=
{
{
width
:
'
15%
'
,
margin
:
5
}
}
style=
{
{
width
:
'
15%
'
,
margin
:
'
5px 5px 28px 5px
'
}
}
/>
/>
),
),
)
}
)
}
...
@@ -785,6 +1036,7 @@ class goodsManage extends Component {
...
@@ -785,6 +1036,7 @@ class goodsManage extends Component {
{
firstKeys
.
length
>
0
?
(
{
firstKeys
.
length
>
0
?
(
<
MinusCircleOutlined
<
MinusCircleOutlined
className=
"dynamic-delete-button"
className=
"dynamic-delete-button"
style=
{
{
marginBottom
:
0
}
}
onClick=
{
()
=>
this
.
remove
(
'
firstKeys
'
,
k
)
}
onClick=
{
()
=>
this
.
remove
(
'
firstKeys
'
,
k
)
}
/>
/>
)
:
null
}
)
:
null
}
...
@@ -835,7 +1087,7 @@ class goodsManage extends Component {
...
@@ -835,7 +1087,7 @@ class goodsManage extends Component {
value=
{
k
}
value=
{
k
}
disabled
disabled
placeholder=
"请输入规格名称"
placeholder=
"请输入规格名称"
style=
{
{
width
:
'
15%
'
,
margin
:
5
}
}
style=
{
{
width
:
'
15%
'
,
margin
:
'
5px 5px 28px 5px
'
}
}
/>
/>
))
}
))
}
{
secondKeys
.
map
(
k
=>
(
{
secondKeys
.
map
(
k
=>
(
...
...
src/pages/GoodsManage/createModal/infoAudit.jsx
0 → 100644
View file @
aeac15f4
import
React
,
{
useState
,
useEffect
}
from
'
react
'
;
import
{
Modal
,
Button
}
from
'
antd
'
;
import
{
apiQueryLastAuditRecord
}
from
'
../service
'
;
const
InfoAudit
=
props
=>
{
const
[
audit
,
setAudit
]
=
useState
({});
const
getRecord
=
async
()
=>
{
const
res
=
await
apiQueryLastAuditRecord
(
props
.
skuInfo
.
skuId
);
if
(
res
&&
res
.
data
)
{
console
.
log
(
'
res :>>
'
,
res
);
setAudit
(
res
.
data
);
}
};
const
getContent
=
()
=>
{
const
obj
=
{
1
:
'
-
'
,
2
:
'
审核通过
'
,
3
:
`审核拒绝,
${
audit
.
rejectReason
}
`
,
};
if
(
audit
)
{
return
obj
[
audit
.
status
]
||
''
;
}
return
''
;
};
useEffect
(()
=>
{
if
(
props
.
visible
)
{
getRecord
();
}
},
[
props
.
visible
]);
return
(
<
Modal
title=
"商品信息变更审核"
visible=
{
props
.
visible
}
closable=
{
false
}
footer=
{
[
audit
.
status
===
3
&&
props
.
canEditable
&&
(
props
.
skuInfo
.
state
===
4
||
(
props
.
skuInfo
.
state
>=
5
&&
props
.
skuInfo
.
updateState
!==
1
))
&&
(
<
Button
key=
"back"
type=
"primary"
onClick=
{
()
=>
props
.
onEdit
()
}
>
再次编辑
</
Button
>
),
<
Button
key=
"close"
onClick=
{
()
=>
props
.
onCancel
()
}
>
关闭
</
Button
>,
]
}
>
<
p
>
审核状态:
{
audit
.
statusDesc
}
</
p
>
<
p
>
申请时间:
{
audit
.
createdAt
}
</
p
>
<
p
>
审核结果:
{
getContent
()
}
</
p
>
</
Modal
>
);
};
export
default
InfoAudit
;
src/pages/GoodsManage/index.jsx
View file @
aeac15f4
import
{
Form
}
from
'
@ant-design/compatible
'
;
import
{
Form
}
from
'
@ant-design/compatible
'
;
import
'
@ant-design/compatible/assets/index.css
'
;
import
'
@ant-design/compatible/assets/index.css
'
;
import
{
Card
,
Pagination
,
Table
,
notification
,
Drawer
,
Spin
,
Button
}
from
'
antd
'
;
import
{
Card
,
Pagination
,
Table
,
notification
,
Drawer
,
Spin
,
Button
,
Modal
}
from
'
antd
'
;
import
React
,
{
Component
}
from
'
react
'
;
import
React
,
{
Component
}
from
'
react
'
;
import
{
PageHeaderWrapper
}
from
'
@ant-design/pro-layout
'
;
import
{
PageHeaderWrapper
}
from
'
@ant-design/pro-layout
'
;
import
{
connect
}
from
'
dva
'
;
import
{
connect
}
from
'
dva
'
;
import
{
sortBy
}
from
'
lodash
'
;
import
{
sortBy
}
from
'
lodash
'
;
import
{
da
}
from
'
date-fns/locale
'
;
import
styles
from
'
./style.less
'
;
import
styles
from
'
./style.less
'
;
import
LocalStroage
from
'
@/utils/localStorage
'
;
import
LocalStroage
from
'
@/utils/localStorage
'
;
import
configApi
from
'
../../../config/env.config
'
;
import
configApi
from
'
../../../config/env.config
'
;
...
@@ -27,6 +26,7 @@ import { column, JDSHOPID, ProcessEditData } from './staticdata';
...
@@ -27,6 +26,7 @@ import { column, JDSHOPID, ProcessEditData } from './staticdata';
import
SearchForm
from
'
./SearchForm
'
;
import
SearchForm
from
'
./SearchForm
'
;
import
TempleatModal
from
'
./TempleatModal
'
;
import
TempleatModal
from
'
./TempleatModal
'
;
import
ServiceGoods
from
'
../ServiceGoods
'
;
import
ServiceGoods
from
'
../ServiceGoods
'
;
import
InfoAudit
from
'
./createModal/infoAudit
'
;
import
{
GOOD_MANAGE
}
from
'
@/../config/permission.config
'
;
import
{
GOOD_MANAGE
}
from
'
@/../config/permission.config
'
;
...
@@ -58,6 +58,8 @@ class goodsManage extends Component {
...
@@ -58,6 +58,8 @@ class goodsManage extends Component {
serviceVisble
:
false
,
serviceVisble
:
false
,
serviceData
:
{},
serviceData
:
{},
visibleAuditModal
:
false
,
auditRow
:
{},
// 查看审核信息使用
};
};
currentLog
=
null
;
currentLog
=
null
;
...
@@ -495,18 +497,20 @@ class goodsManage extends Component {
...
@@ -495,18 +497,20 @@ class goodsManage extends Component {
title=
"商品预览"
title=
"商品预览"
></
iframe
>
></
iframe
>
</
Drawer
>
</
Drawer
>
<
CreateModal
{
this
.
state
.
createVisible
&&
(
initData=
{
this
.
state
.
initData
}
<
CreateModal
visible=
{
this
.
state
.
createVisible
}
initData=
{
this
.
state
.
initData
}
onCancel=
{
()
=>
{
visible=
{
this
.
state
.
createVisible
}
this
.
setState
({
createVisible
:
false
,
initData
:
{}
});
onCancel=
{
()
=>
{
}
}
this
.
setState
({
createVisible
:
false
,
initData
:
{}
});
query=
{
()
=>
this
.
handleSearch
()
}
}
}
shopList=
{
this
.
filterShopList
(
this
.
shopList
,
Object
.
keys
(
this
.
state
.
initData
).
length
)
}
query=
{
()
=>
this
.
handleSearch
()
}
treeData=
{
this
.
state
.
treeData
}
shopList=
{
this
.
filterShopList
(
this
.
shopList
,
Object
.
keys
(
this
.
state
.
initData
).
length
)
}
virtualTreeData=
{
this
.
state
.
virtualTreeData
}
treeData=
{
this
.
state
.
treeData
}
specListData=
{
this
.
state
.
specListData
}
virtualTreeData=
{
this
.
state
.
virtualTreeData
}
></
CreateModal
>
specListData=
{
this
.
state
.
specListData
}
></
CreateModal
>
)
}
<
UpdateStock
<
UpdateStock
visible=
{
this
.
state
.
updateStockVisible
}
visible=
{
this
.
state
.
updateStockVisible
}
...
@@ -537,6 +541,22 @@ class goodsManage extends Component {
...
@@ -537,6 +541,22 @@ class goodsManage extends Component {
specListData=
{
this
.
state
.
specListData
}
specListData=
{
this
.
state
.
specListData
}
/>
/>
</
Spin
>
</
Spin
>
<
InfoAudit
visible=
{
this
.
state
.
visibleAuditModal
}
skuInfo=
{
this
.
state
.
auditRow
}
canEditable=
{
this
.
canEditable
}
onCancel=
{
()
=>
{
this
.
setState
({
visibleAuditModal
:
false
,
auditRow
:
{}
});
}
}
onEdit=
{
()
=>
{
this
.
setState
({
visibleAuditModal
:
false
,
auditRow
:
{}
});
if
(
this
.
state
.
auditRow
.
type
===
4
)
{
this
.
serviceVisbleChange
(
this
.
state
.
auditRow
);
}
else
{
this
.
onUpdateInfo
(
this
.
state
.
auditRow
);
}
}
}
/>
</
PageHeaderWrapper
>
</
PageHeaderWrapper
>
);
);
}
}
...
...
src/pages/GoodsManage/service.js
View file @
aeac15f4
...
@@ -9,6 +9,10 @@ const headers = {
...
@@ -9,6 +9,10 @@ const headers = {
'
Content-Type
'
:
'
application/x-www-form-urlencoded
'
,
'
Content-Type
'
:
'
application/x-www-form-urlencoded
'
,
};
};
/**
* 商品列表
* yapi: http://yapi.quantgroups.com/project/389/interface/api/23814
*/
export
async
function
searchList
(
params
)
{
export
async
function
searchList
(
params
)
{
return
request
.
post
(
'
/product/api/merchant/page
'
,
{
return
request
.
post
(
'
/product/api/merchant/page
'
,
{
prefix
:
goodsApi
,
prefix
:
goodsApi
,
...
@@ -42,6 +46,16 @@ export async function getBrandList() {
...
@@ -42,6 +46,16 @@ export async function getBrandList() {
});
});
}
}
// 获取类目关联属性
export
async
function
apiGetAttribute
(
categoryId
)
{
const
data
=
await
request
.
get
(
`/api/kdsp/category/template/ref/attribute/detail?categoryId=
${
categoryId
}
`
,
{
prefix
:
goodsApi
,
},
);
return
data
;
}
// 编辑--获取详情
// 编辑--获取详情
export
async
function
spuDetail
(
params
)
{
export
async
function
spuDetail
(
params
)
{
return
request
.
post
(
'
/product/api/merchant/detail
'
,
{
return
request
.
post
(
'
/product/api/merchant/detail
'
,
{
...
@@ -73,6 +87,15 @@ export async function categoryList() {
...
@@ -73,6 +87,15 @@ export async function categoryList() {
prefix
:
goodsApi
,
prefix
:
goodsApi
,
});
});
}
}
/**
* 商品分类
* type 商品类型:1-实物类,2-虚拟类,4-服务类
* */
export
async
function
apiCategoryListType
(
type
)
{
return
request
.
get
(
`/product/category/getByProductType/
${
type
}
`
,
{
prefix
:
goodsApi
,
});
}
// 批量修改
// 批量修改
export
async
function
uploadFile
(
file
)
{
export
async
function
uploadFile
(
file
)
{
...
@@ -240,3 +263,9 @@ export const apiChangeStateGoods = async params => {
...
@@ -240,3 +263,9 @@ export const apiChangeStateGoods = async params => {
});
});
return
data
;
return
data
;
};
};
// 查询sku最后一条审核记录
export
const
apiQueryLastAuditRecord
=
skuId
=>
request
.
get
(
`/api/kdsp/sku/last/audit/record?skuId=
${
skuId
}
`
,
{
prefix
:
goodsApi
,
});
src/pages/GoodsManage/staticdata.js
View file @
aeac15f4
...
@@ -3,7 +3,7 @@ import { Button, Badge, Switch, Modal } from 'antd';
...
@@ -3,7 +3,7 @@ import { Button, Badge, Switch, Modal } from 'antd';
import
{
ExclamationCircleOutlined
}
from
'
@ant-design/icons
'
;
import
{
ExclamationCircleOutlined
}
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
}
from
'
./service
'
;
import
{
apiChangeStateGoods
,
apiQueryLastAuditRecord
}
from
'
./service
'
;
const
{
confirm
}
=
Modal
;
const
{
confirm
}
=
Modal
;
...
@@ -50,6 +50,12 @@ export function column() {
...
@@ -50,6 +50,12 @@ export function column() {
},
},
});
});
};
};
const
onShowAudit
=
row
=>
{
this
.
setState
({
auditRow
:
row
,
visibleAuditModal
:
true
,
});
};
return
[
return
[
{
{
...
@@ -183,7 +189,15 @@ export function column() {
...
@@ -183,7 +189,15 @@ export function column() {
render
:
(
_
,
row
)
=>
(
render
:
(
_
,
row
)
=>
(
<
div
>
<
div
>
<
p
>
{
row
.
state
>=
5
?
'
审核通过
'
:
_
}
<
/p
>
<
p
>
{
row
.
state
>=
5
?
'
审核通过
'
:
_
}
<
/p
>
<
p
>
{
row
.
updateStateDesc
||
'
_ _
'
}
<
/p
>
<
div
>
{
row
.
updateState
?
(
<
Button
onClick
=
{()
=>
onShowAudit
(
row
)}
type
=
"
link
"
>
{
row
.
updateStateDesc
}
<
/Button
>
)
:
(
'
--
'
)}
<
/div
>
<
/div
>
<
/div
>
),
),
},
},
...
...
src/pages/GoodsManage/style.less
View file @
aeac15f4
...
@@ -110,3 +110,19 @@
...
@@ -110,3 +110,19 @@
color: #d9363e;
color: #d9363e;
line-height: 1;
line-height: 1;
}
}
.cardTitle {
padding: 15px;
font-weight: bold;
font-size: 18px;
}
.stateAuditTxt {
color: #1890ff;
cursor: pointer;
}
.attrbox {
max-height: 384px;
overflow: hidden;
}
.attrboxMore {
max-height: max-content;
}
src/pages/PaymentMange/ToExamine/upload.jsx
View file @
aeac15f4
...
@@ -46,19 +46,21 @@ class PicturesWall extends React.Component {
...
@@ -46,19 +46,21 @@ class PicturesWall extends React.Component {
};
};
customRequest
=
({
file
,
onError
,
onSuccess
})
=>
{
customRequest
=
({
file
,
onError
,
onSuccess
})
=>
{
let
filename
=
''
;
let
suffix
=
''
;
if
(
file
.
name
)
{
if
(
file
.
name
)
{
const
lastFile
=
file
.
name
.
split
(
'
.
'
);
const
index
=
file
.
name
.
lastIndexOf
(
'
.
'
);
const
index
=
lastFile
.
length
-
1
;
filename
=
file
.
name
.
substr
(
0
,
index
);
suffix
=
file
.
name
.
substr
(
index
+
1
,
file
.
name
.
length
-
1
);
const
types
=
[
'
pdf
'
,
'
doc
'
,
'
docx
'
,
'
zip
'
,
'
rar
'
,
'
png
'
,
'
jpeg
'
];
const
types
=
[
'
pdf
'
,
'
doc
'
,
'
docx
'
,
'
zip
'
,
'
rar
'
,
'
png
'
,
'
jpeg
'
];
if
(
!
types
.
includes
(
lastFile
[
index
]
))
{
if
(
!
types
.
includes
(
suffix
))
{
message
.
error
(
'
文件格式错误!
'
);
message
.
error
(
'
文件格式错误!
'
);
return
;
return
;
}
}
}
}
const
vm
=
this
;
const
vm
=
this
;
const
name
=
file
.
name
+
file
.
uid
;
// eslint-disable-next-line new-cap
// eslint-disable-next-line new-cap
const
data
=
file
.
name
+
new
Date
().
getTime
()
;
const
data
=
`
${
filename
}
-
${
new
Date
().
getTime
()}
.
${
suffix
}
`
;
const
observable
=
qiniu
.
upload
(
file
,
data
,
token
);
const
observable
=
qiniu
.
upload
(
file
,
data
,
token
);
const
observer
=
{
const
observer
=
{
next
()
{
next
()
{
...
...
src/pages/ServiceGoods/components/EditFormTable.jsx
View file @
aeac15f4
...
@@ -172,7 +172,6 @@ const EditFormTable = forwardRef((props, ref) => {
...
@@ -172,7 +172,6 @@ const EditFormTable = forwardRef((props, ref) => {
return
(
return
(
<>
<>
<
Form
form=
{
form
}
scrollToFirstError
component=
{
false
}
>
<
Form
form=
{
form
}
scrollToFirstError
component=
{
false
}
>
{
/* <Button onClick={onCheck}>测试</Button> */
}
<
EditableContext
.
Provider
value=
{
form
}
>
<
EditableContext
.
Provider
value=
{
form
}
>
<
Table
<
Table
scroll=
{
{
y
:
300
,
x
:
1000
}
}
scroll=
{
{
y
:
300
,
x
:
1000
}
}
...
...
src/pages/ServiceGoods/components/FormRuleSetting.jsx
View file @
aeac15f4
...
@@ -24,10 +24,24 @@ const FormRuleSetting = forwardRef((props, ref) => {
...
@@ -24,10 +24,24 @@ const FormRuleSetting = forwardRef((props, ref) => {
const
[
form
]
=
Form
.
useForm
();
const
[
form
]
=
Form
.
useForm
();
const
customer
=
useContext
(
ServiceContext
);
const
customer
=
useContext
(
ServiceContext
);
// 判断是否有禁用的店铺 禁用店铺不显示
const
getIsInShops
=
arr
=>
{
const
list
=
[];
arr
.
forEach
(
item
=>
{
supplierIdList
.
some
(
s
=>
+
s
.
id
===
+
item
)
&&
list
.
push
(
item
);
});
return
list
;
};
useEffect
(()
=>
{
useEffect
(()
=>
{
if
(
customer
.
isEdit
)
{
if
(
customer
.
isEdit
)
{
if
(
!
editData
)
return
;
if
(
!
editData
)
return
;
form
.
setFieldsValue
(
editData
);
const
goodInfo
=
Object
.
assign
({},
editData
);
if
(
goodInfo
.
shopIds
)
{
const
shopIds
=
getIsInShops
(
editData
.
shopIds
);
goodInfo
.
shopIds
=
shopIds
;
}
form
.
setFieldsValue
(
goodInfo
);
}
}
},
[
customer
.
isEdit
,
editData
]);
},
[
customer
.
isEdit
,
editData
]);
...
@@ -98,7 +112,14 @@ const FormRuleSetting = forwardRef((props, ref) => {
...
@@ -98,7 +112,14 @@ const FormRuleSetting = forwardRef((props, ref) => {
label=
"适用门店"
label=
"适用门店"
rules=
{
[{
required
:
true
,
message
:
'
请选择适用门店!
'
,
type
:
'
array
'
}]
}
rules=
{
[{
required
:
true
,
message
:
'
请选择适用门店!
'
,
type
:
'
array
'
}]
}
>
>
<
Select
mode=
"multiple"
placeholder=
"请选择适用门店"
>
<
Select
mode=
"multiple"
placeholder=
"请选择适用门店"
showSearch
filterOption=
{
(
input
,
option
)
=>
option
.
props
.
children
.
toLowerCase
().
indexOf
(
input
.
toLowerCase
())
>=
0
}
>
{
(
supplierIdList
||
[]).
map
(
item
=>
(
{
(
supplierIdList
||
[]).
map
(
item
=>
(
<
Option
value=
{
+
item
.
id
}
key=
{
item
.
id
}
>
<
Option
value=
{
+
item
.
id
}
key=
{
item
.
id
}
>
{
item
.
name
}
{
item
.
name
}
...
...
src/pages/ServiceGoods/components/FormRuleVPictures.jsx
View file @
aeac15f4
...
@@ -142,6 +142,7 @@ const FormRuleVPictures = forwardRef((props, ref) => {
...
@@ -142,6 +142,7 @@ const FormRuleVPictures = forwardRef((props, ref) => {
>
>
<
UploadImage
<
UploadImage
disabled=
{
customer
.
isService
}
disabled=
{
customer
.
isService
}
multiple=
{
false
}
name=
"commonImageList"
name=
"commonImageList"
limit=
{
imgConfig
.
commonImageList
.
limit
}
limit=
{
imgConfig
.
commonImageList
.
limit
}
pictures=
{
commonImageList
}
pictures=
{
commonImageList
}
...
...
src/pages/ServiceGoods/components/UploadImage.jsx
View file @
aeac15f4
...
@@ -192,21 +192,25 @@ const UploadImage = forwardRef((props, ref) => {
...
@@ -192,21 +192,25 @@ const UploadImage = forwardRef((props, ref) => {
</
ReactSortable
>
</
ReactSortable
>
)
}
)
}
</
div
>
</
div
>
<
Upload
{
limit
!==
null
&&
fileList
.
length
>=
limit
?
(
{
...
uploadParams
}
''
disabled=
{
Boolean
(
disabled
)
}
)
:
(
multiple=
{
multiple
}
<
Upload
name=
{
name
}
{
...
uploadParams
}
customRequest=
{
()
=>
{}
}
disabled=
{
Boolean
(
disabled
)
}
listType=
"picture-card"
multiple=
{
multiple
}
beforeUpload=
{
defaultBeforeUpload
}
name=
{
name
}
fileList=
{
fileList
}
customRequest=
{
()
=>
{}
}
onPreview=
{
handlePreview
}
listType=
"picture-card"
onRemove=
{
handleRemove
}
beforeUpload=
{
defaultBeforeUpload
}
showUploadList=
{
false
}
fileList=
{
fileList
}
>
onPreview=
{
handlePreview
}
{
limit
!==
null
&&
fileList
.
length
>=
limit
?
null
:
UploadButton
}
onRemove=
{
handleRemove
}
</
Upload
>
showUploadList=
{
false
}
>
{
UploadButton
}
</
Upload
>
)
}
<
Modal
visible=
{
previewVisible
}
title=
{
previewTitle
}
footer=
{
null
}
onCancel=
{
handleCancel
}
>
<
Modal
visible=
{
previewVisible
}
title=
{
previewTitle
}
footer=
{
null
}
onCancel=
{
handleCancel
}
>
<
img
alt=
"example"
style=
{
{
width
:
'
100%
'
}
}
src=
{
previewImage
}
/>
<
img
alt=
"example"
style=
{
{
width
:
'
100%
'
}
}
src=
{
previewImage
}
/>
</
Modal
>
</
Modal
>
...
...
src/pages/ServiceGoods/config.js
View file @
aeac15f4
...
@@ -236,7 +236,7 @@ export const StaticColumns = customer => [
...
@@ -236,7 +236,7 @@ export const StaticColumns = customer => [
min
:
0
,
min
:
0
,
},
},
roleRules
:
{
required
:
true
},
roleRules
:
{
required
:
true
},
disabeldRender
:
()
=>
customer
.
isService
,
disabeldRender
:
v
=>
v
.
id
&&
customer
.
isService
,
},
},
{
{
title
:
'
库存预警
'
,
title
:
'
库存预警
'
,
...
...
src/services/qiniu.js
View file @
aeac15f4
...
@@ -4,6 +4,9 @@ import config from '../../config/env.config';
...
@@ -4,6 +4,9 @@ import config from '../../config/env.config';
export
async
function
qiniuToken
()
{
export
async
function
qiniuToken
()
{
const
data
=
await
request
.
get
(
'
/api/kdsp/common/upload/token
'
,
{
const
data
=
await
request
.
get
(
'
/api/kdsp/common/upload/token
'
,
{
prefix
:
config
.
opapiHost
,
prefix
:
config
.
opapiHost
,
headers
:
{
'
qg-tenant-id
'
:
560761
,
},
});
});
return
data
?.
data
?.
token
;
return
data
?.
data
?.
token
;
}
}
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