Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Y
yudao-cloud
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
hblj
yudao-cloud
Commits
a334e99b
提交
a334e99b
authored
4月 01, 2019
作者:
YunaiV
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
前端:商品推荐。忘记提交了
上级
ba409a63
显示空白字符变更
内嵌
并排
正在显示
30 个修改的文件
包含
758 行增加
和
140 行删除
+758
-140
proxy.dev.js
admin-web/config/proxy/proxy.dev.js
+6
-0
router.config.js
admin-web/config/router.config.js
+5
-5
menu.js
admin-web/src/locales/zh-CN/menu.js
+2
-0
bannerList.js
admin-web/src/models/promotion/bannerList.js
+1
-80
productRecommendList.js
admin-web/src/models/promotion/productRecommendList.js
+178
-0
BannerList.js
admin-web/src/pages/Promotion/BannerList.js
+1
-13
ProductRecommendList.js
admin-web/src/pages/Promotion/ProductRecommendList.js
+399
-0
ProductRecommendList.less
admin-web/src/pages/Promotion/ProductRecommendList.less
+48
-0
promotion.js
admin-web/src/services/promotion.js
+33
-0
promotion.js
mobile-web/src/api/promotion.js
+10
-0
env.js
mobile-web/src/config/env.js
+2
-2
index.vue
mobile-web/src/page/page/index.vue
+23
-9
ProductAttrAndValuePairBO.java
...ocoder/mall/product/api/bo/ProductAttrAndValuePairBO.java
+3
-1
ProductAttrBO.java
...in/java/cn/iocoder/mall/product/api/bo/ProductAttrBO.java
+2
-1
ProductAttrDetailBO.java
...a/cn/iocoder/mall/product/api/bo/ProductAttrDetailBO.java
+2
-1
ProductAttrPageBO.java
...ava/cn/iocoder/mall/product/api/bo/ProductAttrPageBO.java
+2
-1
ProductAttrSimpleBO.java
...a/cn/iocoder/mall/product/api/bo/ProductAttrSimpleBO.java
+2
-1
ProductAttrValueBO.java
...va/cn/iocoder/mall/product/api/bo/ProductAttrValueBO.java
+2
-1
ProductAttrValueDetailBO.java
...iocoder/mall/product/api/bo/ProductAttrValueDetailBO.java
+2
-1
ProductAttrValueSimpleBO.java
...iocoder/mall/product/api/bo/ProductAttrValueSimpleBO.java
+3
-1
ProductCategoryBO.java
...ava/cn/iocoder/mall/product/api/bo/ProductCategoryBO.java
+2
-1
ProductSkuBO.java
...ain/java/cn/iocoder/mall/product/api/bo/ProductSkuBO.java
+3
-1
ProductSkuDetailBO.java
...va/cn/iocoder/mall/product/api/bo/ProductSkuDetailBO.java
+2
-1
ProductSpuBO.java
...ain/java/cn/iocoder/mall/product/api/bo/ProductSpuBO.java
+2
-1
ProductSpuDetailBO.java
...va/cn/iocoder/mall/product/api/bo/ProductSpuDetailBO.java
+2
-1
ProductSpuPageBO.java
...java/cn/iocoder/mall/product/api/bo/ProductSpuPageBO.java
+2
-1
ProductSpuMapper.java
...in/java/cn/iocoder/mall/product/dao/ProductSpuMapper.java
+1
-1
UsersProductRecommendController.java
...ion/controller/users/UsersProductRecommendController.java
+6
-4
ServiceExceptionConfiguration.java
...l/promotion/biz/config/ServiceExceptionConfiguration.java
+2
-2
ProductRecommendMapper.xml
...impl/src/main/resources/mapper/ProductRecommendMapper.xml
+10
-10
没有找到文件。
admin-web/config/proxy/proxy.dev.js
浏览文件 @
a334e99b
...
...
@@ -7,6 +7,12 @@ export default {
changeOrigin
:
true
,
pathRewrite
:
{},
},
'/product-api/'
:
{
// target: 'http://180.167.213.26:18083/',
target
:
'http://127.0.0.1:18081/'
,
changeOrigin
:
true
,
pathRewrite
:
{},
},
'/order-api/'
:
{
target
:
'http://127.0.0.1:18084/'
,
changeOrigin
:
true
,
...
...
admin-web/config/router.config.js
浏览文件 @
a334e99b
...
...
@@ -110,11 +110,11 @@ export default [
name
:
'promotion-banner-list'
,
component
:
'./Promotion/BannerList'
,
},
//
{
// path: '/product/product-spu-add
',
// name: 'product-spu-add
',
// component: './Product/ProductSpuAddOrUpdate
',
//
},
{
path
:
'/promotion/product-recommend-list
'
,
name
:
'product-recommend-list
'
,
component
:
'./Promotion/ProductRecommendList
'
,
},
// {
// path: '/product/product-category-list',
// name: 'product-category-list',
...
...
admin-web/src/locales/zh-CN/menu.js
浏览文件 @
a334e99b
...
...
@@ -55,4 +55,5 @@ export default {
'menu.order.order-refunds'
:
'退货维权'
,
// 营销相关
'menu.promotion.promotion-banner-list'
:
'Banner 管理'
,
'menu.promotion.product-recommend-list'
:
'商品推荐'
,
};
\ No newline at end of file
admin-web/src/models/promotion/bannerList.js
浏览文件 @
a334e99b
import
{
message
}
from
'antd'
;
import
{
buildTreeNode
,
findCheckedKeys
}
from
'../../utils/tree.utils'
;
import
{
import
{
message
}
from
'antd'
;
import
{
addBanner
,
adminRoleAssign
,
deleteBanner
,
queryBanner
,
queryBannerRoleList
,
updateBanner
,
updateBannerStatus
,
}
from
'../../services/promotion'
;
import
{
arrayToStringParams
}
from
'../../utils/request.qs'
;
import
PaginationHelper
from
'../../../helpers/PaginationHelper'
;
const
SEARCH_PARAMS_DEFAULT
=
{
...
...
@@ -31,12 +26,6 @@ export default {
modalType
:
undefined
,
// 'add' or 'update' 表单
formVals
:
{},
// 当前表单值
modalLoading
:
false
,
// 分配角色表单相关
roleList
:
[],
roleModalVisible
:
false
,
roleCheckedKeys
:
[],
// 此处的 Key ,就是角色编号
roleAssignLoading
:
false
,
},
effects
:
{
...
...
@@ -161,78 +150,10 @@ export default {
}
},
*
queryRoleList
({
payload
},
{
call
,
put
})
{
// 显示加载中
yield
put
({
type
:
'changeRoleAssignLoading'
,
payload
:
true
,
});
// 请求
const
response
=
yield
call
(
queryBannerRoleList
,
payload
);
// 响应
if
(
response
.
code
===
0
)
{
const
roleList
=
response
.
data
;
const
roleTreeData
=
buildTreeNode
(
roleList
,
'name'
,
'id'
);
const
roleCheckedKeys
=
findCheckedKeys
(
roleList
);
yield
put
({
type
:
'setAll'
,
payload
:
{
roleList
:
roleTreeData
,
roleCheckedKeys
,
},
});
}
// 隐藏加载中
yield
put
({
type
:
'changeRoleAssignLoading'
,
payload
:
false
,
});
},
*
roleAssign
({
payload
},
{
call
,
put
})
{
const
{
callback
,
body
}
=
payload
;
// 显示加载中
yield
put
({
type
:
'changeRoleAssignLoading'
,
payload
:
true
,
});
// 请求
const
response
=
yield
call
(
adminRoleAssign
,
{
id
:
body
.
id
,
roleIds
:
arrayToStringParams
(
body
.
roleIds
),
});
// 响应
if
(
response
.
code
===
0
)
{
if
(
callback
)
{
callback
(
response
);
}
}
// 隐藏加载中
yield
put
({
type
:
'changeRoleAssignLoading'
,
payload
:
false
,
});
},
},
reducers
:
{
changeRoleCheckedKeys
(
state
,
{
payload
})
{
return
{
...
state
,
roleCheckedKeys
:
payload
,
};
},
// 修改加载中的状态
changeRoleAssignLoading
(
state
,
{
payload
})
{
return
{
...
state
,
roleAssignLoading
:
payload
,
};
},
changeModalLoading
(
state
,
{
payload
})
{
return
{
...
state
,
...
...
admin-web/src/models/promotion/productRecommendList.js
0 → 100644
浏览文件 @
a334e99b
import
{
message
}
from
'antd'
;
import
{
addProductRecommend
,
deleteProductRecommend
,
queryProductRecommend
,
updateProductRecommend
,
updateProductRecommendStatus
,
}
from
'../../services/promotion'
;
import
PaginationHelper
from
'../../../helpers/PaginationHelper'
;
const
SEARCH_PARAMS_DEFAULT
=
{
type
:
undefined
,
};
export
default
{
namespace
:
'productRecommendList'
,
state
:
{
// 分页列表相关
list
:
[],
listLoading
:
false
,
pagination
:
PaginationHelper
.
defaultPaginationConfig
,
searchParams
:
SEARCH_PARAMS_DEFAULT
,
// 添加 or 修改表单相关
modalVisible
:
false
,
modalType
:
undefined
,
// 'add' or 'update' 表单
formVals
:
{},
// 当前表单值
modalLoading
:
false
,
},
effects
:
{
// 查询列表
*
query
({
payload
},
{
call
,
put
})
{
// 显示加载中
yield
put
({
type
:
'changeListLoading'
,
payload
:
true
,
});
// 请求
const
response
=
yield
call
(
queryProductRecommend
,
payload
);
// 响应
yield
put
({
type
:
'setAll'
,
payload
:
{
list
:
response
.
data
.
list
,
pagination
:
PaginationHelper
.
formatPagination
(
response
.
data
,
payload
),
searchParams
:
{
type
:
payload
.
type
}
},
});
// 隐藏加载中
yield
put
({
type
:
'changeListLoading'
,
payload
:
false
,
});
},
*
add
({
payload
},
{
call
,
put
})
{
const
{
callback
,
body
}
=
payload
;
// 显示加载中
yield
put
({
type
:
'changeModalLoading'
,
payload
:
true
,
});
// 请求
const
response
=
yield
call
(
addProductRecommend
,
body
);
// 响应
if
(
response
.
code
===
0
)
{
if
(
callback
)
{
callback
(
response
);
}
// 刷新列表
yield
put
({
type
:
'query'
,
payload
:
{
...
PaginationHelper
.
defaultPayload
},
});
}
// 隐藏加载中
yield
put
({
type
:
'changeModalLoading'
,
payload
:
false
,
});
},
*
update
({
payload
},
{
call
,
put
})
{
const
{
callback
,
body
}
=
payload
;
// 显示加载中
yield
put
({
type
:
'changeModalLoading'
,
payload
:
true
,
});
// 请求
const
response
=
yield
call
(
updateProductRecommend
,
body
);
// 响应
if
(
response
.
code
===
0
)
{
if
(
callback
)
{
callback
(
response
);
}
// 刷新列表
yield
put
({
type
:
'query'
,
payload
:
{
...
PaginationHelper
.
defaultPayload
},
});
}
// 隐藏加载中
yield
put
({
type
:
'changeModalLoading'
,
payload
:
false
,
});
},
*
updateStatus
({
payload
},
{
call
,
put
})
{
// 请求
const
response
=
yield
call
(
updateProductRecommendStatus
,
payload
);
// 响应
if
(
response
.
code
===
0
)
{
message
.
info
(
'更新状态成功!'
);
// 刷新列表
yield
put
({
type
:
'query'
,
payload
:
{
...
PaginationHelper
.
defaultPayload
},
});
}
},
*
delete
({
payload
},
{
call
,
put
})
{
// 请求
const
response
=
yield
call
(
deleteProductRecommend
,
payload
);
// 响应
if
(
response
.
code
===
0
)
{
message
.
info
(
'删除成功!'
);
// 刷新列表
yield
put
({
type
:
'query'
,
payload
:
{
...
PaginationHelper
.
defaultPayload
},
});
}
},
},
reducers
:
{
// 修改加载中的状态
changeModalLoading
(
state
,
{
payload
})
{
return
{
...
state
,
modalLoading
:
payload
,
};
},
changeListLoading
(
state
,
{
payload
})
{
return
{
...
state
,
listLoading
:
payload
,
};
},
// 设置所有属性
setAll
(
state
,
{
payload
})
{
return
{
...
state
,
...
payload
,
};
}
},
};
admin-web/src/pages/Promotion/BannerList.js
浏览文件 @
a334e99b
...
...
@@ -342,24 +342,12 @@ class BannerList extends PureComponent {
});
};
handleRoleAssignModalVisible
=
(
roleModalVisible
,
record
)
=>
{
const
{
dispatch
}
=
this
.
props
;
dispatch
({
type
:
'bannerList/setAll'
,
payload
:
{
roleModalVisible
:
roleModalVisible
,
formVals
:
record
||
{}
},
});
};
render
()
{
// let that = this;
const
{
dispatch
,
list
,
listLoading
,
searchParams
,
pagination
,
modalVisible
,
modalType
,
formVals
,
confirmLoading
,
roleList
,
roleModalVisible
,
roleAssignLoading
,
roleCheckedKeys
}
=
this
.
props
;
confirmLoading
,}
=
this
.
props
;
// 列表属性
const
listProps
=
{
...
...
admin-web/src/pages/Promotion/ProductRecommendList.js
0 → 100644
浏览文件 @
a334e99b
/* eslint-disable */
import
React
,
{
PureComponent
,
Fragment
}
from
'react'
;
import
{
connect
}
from
'dva'
;
import
{
Card
,
Form
,
Input
,
Button
,
Modal
,
message
,
Table
,
Divider
,
Tree
,
Spin
,
Row
,
Col
,
Select
,
Icon
,
InputNumber
}
from
'antd'
;
import
{
checkTypeWithEnglishAndNumbers
}
from
'../../../helpers/validator'
import
PageHeaderWrapper
from
'@/components/PageHeaderWrapper'
;
import
styles
from
'./BannerList.less'
;
import
moment
from
"moment"
;
import
PaginationHelper
from
"../../../helpers/PaginationHelper"
;
const
FormItem
=
Form
.
Item
;
const
SelectOption
=
Select
.
Option
;
const
{
TreeNode
}
=
Tree
;
const
status
=
[
'未知'
,
'正常'
,
'禁用'
];
const
types
=
[
'未知'
,
'新品推荐'
,
'热卖推荐'
];
// 列表
function
List
({
dataSource
,
loading
,
pagination
,
searchParams
,
dispatch
,
handleModalVisible
})
{
function
handleStatus
(
record
)
{
Modal
.
confirm
({
title
:
record
.
status
===
1
?
'确认禁用'
:
'取消禁用'
,
content
:
`
${
record
.
productSpuId
}
`
,
onOk
()
{
dispatch
({
type
:
'productRecommendList/updateStatus'
,
payload
:
{
id
:
record
.
id
,
status
:
record
.
status
===
1
?
2
:
1
,
},
});
},
onCancel
()
{},
});
}
function
handleDelete
(
record
)
{
Modal
.
confirm
({
title
:
`确认删除?`
,
content
:
`
${
record
.
productSpuId
}
`
,
onOk
()
{
dispatch
({
type
:
'productRecommendList/delete'
,
payload
:
{
id
:
record
.
id
,
},
});
},
onCancel
()
{},
});
}
const
columns
=
[
{
title
:
'推荐类型'
,
dataIndex
:
'type'
,
render
(
val
)
{
return
<
span
>
{
types
[
val
]}
<
/span>; /
/
TODO
芋艿,此处要改
},
},
{
title
:
'商品'
,
dataIndex
:
'productSpuId'
,
},
{
title
:
'排序值'
,
dataIndex
:
'sort'
,
},
{
title
:
'状态'
,
dataIndex
:
'status'
,
render
(
val
)
{
return
<
span
>
{
status
[
val
]}
<
/span>; /
/
TODO
芋艿,此处要改
},
},
{
title
:
'备注'
,
dataIndex
:
'memo'
,
},
{
title
:
'创建时间'
,
dataIndex
:
'createTime'
,
render
:
val
=>
<
span
>
{
moment
(
val
).
format
(
'YYYY-MM-DD HH:mm'
)}
<
/span>
,
},
{
title
:
'操作'
,
width
:
360
,
render
:
(
text
,
record
)
=>
{
const
statusText
=
record
.
status
===
1
?
'禁用'
:
'开启'
;
// TODO 芋艿,此处要改
return
(
<
Fragment
>
<
a
onClick
=
{()
=>
handleModalVisible
(
true
,
'update'
,
record
)}
>
编辑
<
/a
>
<
Divider
type
=
"vertical"
/>
<
a
className
=
{
styles
.
tableDelete
}
onClick
=
{()
=>
handleStatus
(
record
)}
>
{
statusText
}
<
/a
>
{
record
.
status
===
2
?
<
span
>
<
Divider
type
=
"vertical"
/>
<
a
className
=
{
styles
.
tableDelete
}
onClick
=
{()
=>
handleDelete
(
record
)}
>
删除
<
/a
>
<
/span> : nul
l
}
<
/Fragment
>
);
},
},
];
function
onPageChange
(
page
)
{
// 翻页
dispatch
({
type
:
'productRecommendList/query'
,
payload
:
{
pageNo
:
page
.
current
,
pageSize
:
page
.
pageSize
,
...
searchParams
}
})
}
return
(
<
Table
columns
=
{
columns
}
dataSource
=
{
dataSource
}
loading
=
{
loading
}
rowKey
=
"id"
pagination
=
{
pagination
}
onChange
=
{
onPageChange
}
/
>
)
}
// 搜索表单
// TODO 芋艿,有没办法换成上面那种写法
const
SearchForm
=
Form
.
create
()(
props
=>
{
const
{
form
,
form
:
{
getFieldDecorator
},
dispatch
}
=
props
;
function
search
()
{
dispatch
({
type
:
'productRecommendList/query'
,
payload
:
{
...
PaginationHelper
.
defaultPayload
,
...
form
.
getFieldsValue
()
}
})
}
// 提交搜索
function
handleSubmit
(
e
)
{
// 阻止默认事件
e
.
preventDefault
();
// 提交搜索
search
();
}
// 重置搜索
function
handleReset
()
{
// 重置表单
form
.
resetFields
();
// 执行搜索
search
();
}
return
(
<
Form
onSubmit
=
{
handleSubmit
}
layout
=
"inline"
>
<
Row
gutter
=
{{
md
:
8
,
lg
:
24
,
xl
:
48
}}
>
<
Col
md
=
{
8
}
sm
=
{
24
}
>
<
FormItem
label
=
"标题"
>
{
getFieldDecorator
(
'title'
)(
<
Input
placeholder
=
"请输入"
/>
)}
<
/FormItem
>
<
/Col
>
<
Col
md
=
{
8
}
sm
=
{
24
}
>
<
span
className
=
{
styles
.
submitButtons
}
>
<
Button
type
=
"primary"
htmlType
=
"submit"
>
查询
<
/Button
>
<
Button
style
=
{{
marginLeft
:
8
}}
onClick
=
{
handleReset
}
>
重置
<
/Button
>
<
/span
>
<
/Col
>
<
/Row
>
<
/Form
>
);
});
// 添加 or 修改 Form 表单
const
AddOrUpdateForm
=
Form
.
create
()(
props
=>
{
const
{
dispatch
,
modalVisible
,
form
,
handleModalVisible
,
modalType
,
formVals
}
=
props
;
const
okHandle
=
()
=>
{
form
.
validateFields
((
err
,
fields
)
=>
{
if
(
err
)
return
;
// 添加表单
if
(
modalType
===
'add'
)
{
dispatch
({
type
:
'productRecommendList/add'
,
payload
:
{
body
:
{
...
fields
,
},
callback
:
()
=>
{
// 清空表单
form
.
resetFields
();
// 提示
message
.
success
(
'添加成功'
);
// 关闭弹窗
handleModalVisible
();
},
},
});
// 修改表单
}
else
{
dispatch
({
type
:
'productRecommendList/update'
,
payload
:
{
body
:
{
id
:
formVals
.
id
,
...
fields
,
},
callback
:
()
=>
{
// 清空表单
form
.
resetFields
();
// 提示
message
.
success
(
'更新成功'
);
// 关闭弹窗
handleModalVisible
();
},
},
});
}
});
};
const
title
=
modalType
===
'add'
?
'新建 Banner'
:
'更新 Banner'
;
return
(
<
Modal
destroyOnClose
title
=
{
title
}
visible
=
{
modalVisible
}
onOk
=
{
okHandle
}
okText
=
'保存'
onCancel
=
{()
=>
handleModalVisible
()}
>
<
FormItem
labelCol
=
{{
span
:
5
}}
wrapperCol
=
{{
span
:
15
}}
label
=
"推荐类型"
>
{
form
.
getFieldDecorator
(
'type'
,
{
rules
:
[{
required
:
true
,
message
:
'请输入推荐类型!'
},
],
initialValue
:
formVals
.
type
,
})(
<
Select
placeholder
=
"请选择"
style
=
{{
maxWidth
:
200
,
width
:
'100%'
}}
>
<
SelectOption
value
=
"1"
>
{
types
[
1
]
}
<
/SelectOption
>
<
SelectOption
value
=
"2"
>
{
types
[
2
]
}
<
/SelectOption
>
<
/Select
>
)}
<
/FormItem
>
<
FormItem
labelCol
=
{{
span
:
5
}}
wrapperCol
=
{{
span
:
15
}}
label
=
"商品"
>
{
form
.
getFieldDecorator
(
'productSpuId'
,
{
rules
:
[{
required
:
true
,
message
:
'请输入商品!'
},
// TODO 芋艿,临时先输入商品编号,后面做成搜索。
],
initialValue
:
formVals
.
productSpuId
,
})(
<
Input
placeholder
=
"请输入"
/>
)}
<
/FormItem
>
<
FormItem
labelCol
=
{{
span
:
5
}}
wrapperCol
=
{{
span
:
15
}}
label
=
"排序值"
>
{
form
.
getFieldDecorator
(
'sort'
,
{
rules
:
[{
required
:
true
,
message
:
'请输入排序值!'
}],
initialValue
:
formVals
.
sort
,
})(
<
InputNumber
placeholder
=
"请输入"
/>
)}
<
/FormItem
>
<
FormItem
labelCol
=
{{
span
:
5
}}
wrapperCol
=
{{
span
:
15
}}
label
=
"备注"
>
{
form
.
getFieldDecorator
(
'memo'
,
{
rules
:
[{
required
:
false
,
message
:
'请输入备注!'
},
{
max
:
255
,
message
:
'最大长度为 255 位'
},
],
initialValue
:
formVals
.
memo
,
})(
<
Input
.
TextArea
placeholder
=
"请输入"
/>
)}
<
/FormItem
>
<
/Modal
>
);
});
@
connect
(({
productRecommendList
})
=>
({
// list: productRecommend.list,
// pagination: productRecommend.pagination,
...
productRecommendList
,
}))
// 主界面
@
Form
.
create
()
class
BannerList
extends
PureComponent
{
componentDidMount
()
{
const
{
dispatch
}
=
this
.
props
;
dispatch
({
type
:
'productRecommendList/query'
,
payload
:
{
...
PaginationHelper
.
defaultPayload
},
});
}
handleModalVisible
=
(
modalVisible
,
modalType
,
record
)
=>
{
const
{
dispatch
}
=
this
.
props
;
dispatch
({
type
:
'productRecommendList/setAll'
,
payload
:
{
modalVisible
,
modalType
,
formVals
:
record
||
{}
},
});
};
render
()
{
// let that = this;
const
{
dispatch
,
list
,
listLoading
,
searchParams
,
pagination
,
modalVisible
,
modalType
,
formVals
,
confirmLoading
,
}
=
this
.
props
;
// 列表属性
const
listProps
=
{
dataSource
:
list
,
pagination
,
searchParams
,
dispatch
,
loading
:
listLoading
,
confirmLoading
,
handleModalVisible
:
this
.
handleModalVisible
,
// Function
};
// 搜索表单属性
const
searchFormProps
=
{
dispatch
,
};
// 添加 or 更新表单属性
const
addOrUpdateFormProps
=
{
modalVisible
,
modalType
,
formVals
,
dispatch
,
handleModalVisible
:
this
.
handleModalVisible
,
// Function
};
return
(
<
PageHeaderWrapper
>
<
Card
bordered
=
{
false
}
>
<
div
className
=
{
styles
.
tableList
}
>
<
div
className
=
{
styles
.
tableListForm
}
>
<
SearchForm
{...
searchFormProps
}
/
>
<
/div
>
<
div
className
=
{
styles
.
tableListOperator
}
>
<
Button
icon
=
"plus"
type
=
"primary"
onClick
=
{()
=>
this
.
handleModalVisible
(
true
,
'add'
,
{})}
>
新建商品推荐
<
/Button
>
<
/div
>
<
/div
>
<
List
{...
listProps
}
/
>
<
/Card
>
<
AddOrUpdateForm
{...
addOrUpdateFormProps
}
/
>
<
/PageHeaderWrapper
>
);
}
}
export
default
BannerList
;
\ No newline at end of file
admin-web/src/pages/Promotion/ProductRecommendList.less
0 → 100644
浏览文件 @
a334e99b
@import '~antd/lib/style/themes/default.less';
@import '~@/utils/utils.less';
.tableList {
.tableListOperator {
margin-bottom: 16px;
button {
margin-right: 8px;
}
}
}
.tableDelete {
color: red;
}
.tableListForm {
:global {
.ant-form-item {
display: flex;
margin-right: 0;
margin-bottom: 24px;
> .ant-form-item-label {
width: auto;
padding-right: 8px;
line-height: 32px;
}
.ant-form-item-control {
line-height: 32px;
}
}
.ant-form-item-control-wrapper {
flex: 1;
}
}
.submitButtons {
display: block;
margin-bottom: 24px;
white-space: nowrap;
}
}
@media screen and (max-width: @screen-lg) {
.tableListForm :global(.ant-form-item) {
margin-right: 24px;
}
}
\ No newline at end of file
admin-web/src/services/promotion.js
浏览文件 @
a334e99b
...
...
@@ -32,3 +32,35 @@ export async function deleteBanner(params) {
method
:
'POST'
,
});
}
// product recommend
export
async
function
queryProductRecommend
(
params
)
{
return
request
(
`/promotion-api/admins/product_recommend/page?
${
stringify
(
params
)}
`
,
{
method
:
'GET'
,
});
}
export
async
function
addProductRecommend
(
params
)
{
return
request
(
`/promotion-api/admins/product_recommend/add?
${
stringify
(
params
)}
`
,
{
method
:
'POST'
,
});
}
export
async
function
updateProductRecommend
(
params
)
{
return
request
(
`/promotion-api/admins/product_recommend/update?
${
stringify
(
params
)}
`
,
{
method
:
'POST'
,
});
}
export
async
function
updateProductRecommendStatus
(
params
)
{
return
request
(
`/promotion-api/admins/product_recommend/update_status?
${
stringify
(
params
)}
`
,
{
method
:
'POST'
,
});
}
export
async
function
deleteProductRecommend
(
params
)
{
return
request
(
`/promotion-api/admins/product_recommend/delete?
${
stringify
(
params
)}
`
,
{
method
:
'POST'
,
});
}
\ No newline at end of file
mobile-web/src/api/promotion.js
浏览文件 @
a334e99b
...
...
@@ -8,3 +8,12 @@ export function getBannerList() {
method
:
'get'
,
});
}
// Product Recommend
export
function
getProductRecommendList
()
{
return
request
({
url
:
'promotion-api/users/product_recommend/list'
,
method
:
'get'
,
});
}
\ No newline at end of file
mobile-web/src/config/env.js
浏览文件 @
a334e99b
...
...
@@ -19,8 +19,8 @@ if (process.env.NODE_ENV == 'development') {
// baseUrl = 'http://127.0.0.1';
// baseUrl = 'http://180.167.213.26:18099';
//
dataSources = 'remote';
dataSources
=
'local'
;
dataSources
=
'remote'
;
//
dataSources = 'local';
export
{
baseUrl
,
...
...
mobile-web/src/page/page/index.vue
浏览文件 @
a334e99b
...
...
@@ -13,14 +13,15 @@
</van-swipe-item>
</van-swipe>
<van-panel
title=
"新品推荐"
>
<div
v-for=
"(item,index) in page.Sections"
:key=
"index"
>
<product
v-if=
"item.Code=='Product'"
:data=
"item"
></product>
<!--
<product
:data=
"productRecommends['1']"
></product>
-->
<div
v-for=
"(product,i) in productRecommends['1']"
:key=
"i"
>
<product-card
:product=
'product'
@
click=
"showProduct(product)"
/>
</div>
</van-panel>
<van-panel
title=
"热卖推荐"
>
<div
v-for=
"(
item,index) in page.Sections"
:key=
"index
"
>
<product
v-if=
"item.Code=='Product'"
:data=
"item"
></product
>
<div
v-for=
"(
product,i) in productRecommends['2']"
:key=
"i
"
>
<product
-card
:product=
'product'
@
click=
"showProduct(product)"
/
>
</div>
</van-panel>
...
...
@@ -39,7 +40,7 @@ import imageAd from "../../components/page/imageAd.vue";
import
imageText
from
"../../components/page/imageText.vue"
;
import
product
from
"../../components/page/product.vue"
;
import
{
GetPage
}
from
"../../api/page.js"
;
import
{
getBannerList
}
from
'../../api/promotion.js'
;
import
{
getBannerList
,
getProductRecommendList
}
from
'../../api/promotion.js'
;
export
default
{
name
:
"page"
,
...
...
@@ -60,6 +61,7 @@ export default {
topheight
:
0
,
page
:{},
banners
:
[],
// Banner 列表
productRecommends
:
[],
// 推荐商品列表
}
},
created
:
function
(){
...
...
@@ -69,18 +71,30 @@ export default {
},
mounted
:
function
()
{
// 加载 Banner
{
let
response
=
getBannerList
();
response
.
then
(
data
=>
{
this
.
banners
=
data
;
});
}
// 加载 getProductRecommendList
{
let
response
=
getProductRecommendList
();
response
.
then
(
data
=>
{
this
.
productRecommends
=
data
;
});
}
},
methods
:{
onBannerClick
:
function
(
event
,
index
)
{
debugger
;
console
.
log
(
event
);
},
//
onBannerClick: function(event, index) {
//
debugger;
//
console.log(event);
//
},
settopheight
:
function
(
value
){
this
.
topheight
=
value
;
},
showProduct
(
product
){
this
.
$router
.
push
(
'/product/'
+
product
.
id
);
}
}
}
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductAttrAndValuePairBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
java.io.Serializable
;
/**
* 商品规格明细 BO
*/
public
class
ProductAttrAndValuePairBO
{
public
class
ProductAttrAndValuePairBO
implements
Serializable
{
/**
* 规格编号
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductAttrBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
java.io.Serializable
;
import
java.util.Date
;
/**
* 商品规格 VO
*/
public
class
ProductAttrBO
{
public
class
ProductAttrBO
implements
Serializable
{
/**
* 规格编号
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductAttrDetailBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
java.io.Serializable
;
import
java.util.Date
;
import
java.util.List
;
/**
* 商品规格明细 VO
*/
public
class
ProductAttrDetailBO
{
public
class
ProductAttrDetailBO
implements
Serializable
{
/**
* 规格编号
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductAttrPageBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
java.io.Serializable
;
import
java.util.List
;
/**
* 商品规格明细分页 BO
*/
public
class
ProductAttrPageBO
{
public
class
ProductAttrPageBO
implements
Serializable
{
/**
* 规格数组
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductAttrSimpleBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
java.io.Serializable
;
import
java.util.List
;
/**
* 商品规格精简 VO
*/
public
class
ProductAttrSimpleBO
{
public
class
ProductAttrSimpleBO
implements
Serializable
{
/**
* 规格编号
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductAttrValueBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
java.io.Serializable
;
import
java.util.Date
;
/**
* 商品规格值 VO
*/
public
class
ProductAttrValueBO
{
public
class
ProductAttrValueBO
implements
Serializable
{
/**
* 规格值编号
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductAttrValueDetailBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
java.io.Serializable
;
import
java.util.Date
;
/**
* 商品规格值 VO
*/
public
class
ProductAttrValueDetailBO
{
public
class
ProductAttrValueDetailBO
implements
Serializable
{
/**
* 规格值编号
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductAttrValueSimpleBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
java.io.Serializable
;
/**
* 商品规格值 VO
*/
public
class
ProductAttrValueSimpleBO
{
public
class
ProductAttrValueSimpleBO
implements
Serializable
{
/**
* 规格值编号
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductCategoryBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
java.io.Serializable
;
import
java.util.Date
;
/**
* 商品分类 BO
*/
public
class
ProductCategoryBO
{
public
class
ProductCategoryBO
implements
Serializable
{
/**
* 分类编号
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductSkuBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
public
class
ProductSkuBO
{
import
java.io.Serializable
;
public
class
ProductSkuBO
implements
Serializable
{
private
Integer
id
;
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductSkuDetailBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
java.io.Serializable
;
import
java.util.List
;
/**
* 商品 Sku 明细 BO
*/
public
class
ProductSkuDetailBO
{
public
class
ProductSkuDetailBO
implements
Serializable
{
/**
* sku 编号
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductSpuBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
java.io.Serializable
;
import
java.util.List
;
public
class
ProductSpuBO
{
public
class
ProductSpuBO
implements
Serializable
{
/**
* SPU 编号
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductSpuDetailBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
java.io.Serializable
;
import
java.util.List
;
/**
* 商品 Spu 明细 BO(包括 Sku 明细)
*/
public
class
ProductSpuDetailBO
{
public
class
ProductSpuDetailBO
implements
Serializable
{
/**
* SPU 编号
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductSpuPageBO.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
java.io.Serializable
;
import
java.util.List
;
public
class
ProductSpuPageBO
{
public
class
ProductSpuPageBO
implements
Serializable
{
/**
* Spu 数组
...
...
product/product-service-impl/src/main/java/cn/iocoder/mall/product/dao/ProductSpuMapper.java
浏览文件 @
a334e99b
...
...
@@ -12,7 +12,7 @@ public interface ProductSpuMapper {
ProductSpuDO
selectById
(
Integer
id
);
List
<
ProductSpuDO
>
selectByIds
(
Collection
<
Integer
>
ids
);
List
<
ProductSpuDO
>
selectByIds
(
@Param
(
"ids"
)
Collection
<
Integer
>
ids
);
void
insert
(
ProductSpuDO
productSpuDO
);
...
...
promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/controller/users/UsersProductRecommendController.java
浏览文件 @
a334e99b
...
...
@@ -17,13 +17,14 @@ import org.springframework.web.bind.annotation.GetMapping;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.Collection
;
import
java.util.Comparator
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
@RestController
@RequestMapping
(
"users/
banner
"
)
@RequestMapping
(
"users/
product_recommend
"
)
@Api
(
"商品推荐模块"
)
public
class
UsersProductRecommendController
{
...
...
@@ -34,7 +35,7 @@ public class UsersProductRecommendController {
@GetMapping
(
"/list"
)
@ApiOperation
(
"获得所有 Banner 列表"
)
public
CommonResult
<
M
ultimap
<
Integer
,
UsersProductRecommendVO
>>
list
()
{
public
CommonResult
<
M
ap
<
Integer
,
Collection
<
UsersProductRecommendVO
>
>>
list
()
{
// 查询商品推荐列表
List
<
ProductRecommendBO
>
productRecommends
=
productRecommendService
.
getProductRecommendList
(
null
,
CommonStatusEnum
.
ENABLE
.
getValue
()).
getData
();
...
...
@@ -43,11 +44,11 @@ public class UsersProductRecommendController {
productRecommends
.
stream
().
map
(
ProductRecommendBO:
:
getProductSpuId
).
collect
(
Collectors
.
toSet
())).
getData
();
Map
<
Integer
,
ProductSpuBO
>
spuMap
=
spus
.
stream
().
collect
(
Collectors
.
toMap
(
ProductSpuBO:
:
getId
,
account
->
account
));
// 组合结果,返回
Multimap
<
Integer
,
UsersProductRecommendVO
>
result
=
new
HashMultimap
<>
();
Multimap
<
Integer
,
UsersProductRecommendVO
>
result
=
HashMultimap
.
create
();
productRecommends
.
sort
(
Comparator
.
comparing
(
ProductRecommendBO:
:
getSort
));
// 排序,按照 sort 升序
productRecommends
.
forEach
(
productRecommendBO
->
result
.
put
(
productRecommendBO
.
getType
(),
ProductRecommendConvert
.
INSTANCE
.
convert
(
spuMap
.
get
(
productRecommendBO
.
getProductSpuId
()))));
// 将 ProductSpuBO 添加到 results 中
return
CommonResult
.
success
(
result
);
return
CommonResult
.
success
(
result
.
asMap
()
);
}
}
\ No newline at end of file
promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/config/ServiceExceptionConfiguration.java
浏览文件 @
a334e99b
package
cn
.
iocoder
.
mall
.
promotion
.
biz
.
config
;
import
cn.iocoder.common.framework.util.ServiceExceptionUtil
;
import
cn.iocoder.mall.
user.service.api.constant.User
ErrorCodeEnum
;
import
cn.iocoder.mall.
promotion.api.constant.Promotion
ErrorCodeEnum
;
import
org.springframework.boot.context.event.ApplicationReadyEvent
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.event.EventListener
;
...
...
@@ -18,7 +18,7 @@ public class ServiceExceptionConfiguration {
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
for
(
UserErrorCodeEnum
item
:
User
ErrorCodeEnum
.
values
())
{
for
(
PromotionErrorCodeEnum
item
:
Promotion
ErrorCodeEnum
.
values
())
{
ServiceExceptionUtil
.
put
(
item
.
getCode
(),
item
.
getMessage
());
}
}
...
...
promotion/promotion-service-impl/src/main/resources/mapper/ProductRecommendMapper.xml
浏览文件 @
a334e99b
...
...
@@ -7,7 +7,7 @@
status, memo, create_time
</sql>
<!-- <select id="selectListByPidAndStatusOrderBySort" resultType="
Banner
DO">-->
<!-- <select id="selectListByPidAndStatusOrderBySort" resultType="
ProductRecommend
DO">-->
<!-- SELECT-->
<!-- <include refid="FIELDS" />-->
<!-- FROM product_recommend-->
...
...
@@ -17,14 +17,14 @@
<!-- ORDER BY sort ASC-->
<!-- </select>-->
<!-- <select id="selectList" resultType="
Banner
DO">-->
<!-- <select id="selectList" resultType="
ProductRecommend
DO">-->
<!-- SELECT-->
<!-- <include refid="FIELDS" />-->
<!-- FROM product_recommend-->
<!-- WHERE deleted = 0-->
<!-- </select>-->
<select
id=
"selectById"
parameterType=
"Integer"
resultType=
"
Banner
DO"
>
<select
id=
"selectById"
parameterType=
"Integer"
resultType=
"
ProductRecommend
DO"
>
SELECT
<include
refid=
"FIELDS"
/>
FROM product_recommend
...
...
@@ -32,7 +32,7 @@
AND deleted = 0
</select>
<select
id=
"selectByProductSpuIdAndType"
resultType=
"
Banner
DO"
>
<select
id=
"selectByProductSpuIdAndType"
resultType=
"
ProductRecommend
DO"
>
SELECT
<include
refid=
"FIELDS"
/>
FROM product_recommend
...
...
@@ -41,13 +41,13 @@
product_spu_id = #{productSpuId}
</if>
<if
test=
"type != null"
>
type = #{type}
AND
type = #{type}
</if>
AND deleted = 0
</where>
</select>
<select
id=
"selectListByTypeAndStatus"
parameterType=
"Integer"
resultType=
"
Banner
DO"
>
<select
id=
"selectListByTypeAndStatus"
parameterType=
"Integer"
resultType=
"
ProductRecommend
DO"
>
SELECT
<include
refid=
"FIELDS"
/>
FROM product_recommend
...
...
@@ -56,13 +56,13 @@
type = #{type}
</if>
<if
test=
"status != null"
>
status = #{status}
AND
status = #{status}
</if>
AND deleted = 0
</where>
</select>
<select
id=
"selectPageByType"
resultType=
"
Banner
DO"
>
<select
id=
"selectPageByType"
resultType=
"
ProductRecommend
DO"
>
SELECT
<include
refid=
"FIELDS"
/>
FROM product_recommend
...
...
@@ -87,7 +87,7 @@
</where>
</select>
<insert
id=
"insert"
parameterType=
"
Banner
DO"
useGeneratedKeys=
"true"
keyColumn=
"id"
keyProperty=
"id"
>
<insert
id=
"insert"
parameterType=
"
ProductRecommend
DO"
useGeneratedKeys=
"true"
keyColumn=
"id"
keyProperty=
"id"
>
INSERT INTO product_recommend (
type, product_spu_id, sort, status, memo,
create_time, deleted
...
...
@@ -97,7 +97,7 @@
)
</insert>
<update
id=
"update"
parameterType=
"
Banner
DO"
>
<update
id=
"update"
parameterType=
"
ProductRecommend
DO"
>
UPDATE product_recommend
<set>
<if
test=
"type != null"
>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论