Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
jinfa-platform
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
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
前端-黄佳鑫
jinfa-platform
Commits
2c0fcf86
Commit
2c0fcf86
authored
Aug 27, 2020
by
LeeJiancong
Browse files
Options
Browse Files
Download
Plain Diff
'修改支付'
parents
5bca989b
c86a0aec
Hide whitespace changes
Inline
Side-by-side
Showing
60 changed files
with
2189 additions
and
372 deletions
+2189
-372
.gitignore
.gitignore
+4
-0
index.ts
config/mallRoutes/index.ts
+8
-0
authConfigRoute.ts
config/routes/authConfigRoute.ts
+49
-0
index.ts
config/routes/index.ts
+2
-1
index.js
scripts/services/index.js
+42
-3
app.tsx
src/app.tsx
+11
-10
index.less
src/components/DetailPage/index.less
+4
-2
index.tsx
src/components/DetailPage/index.tsx
+16
-9
index.tsx
src/components/ModalTable/index.tsx
+1
-1
SearchSelect.tsx
src/components/NiceForm/components/SearchSelect.tsx
+8
-2
TableTagList.tsx
src/components/NiceForm/components/TableTagList.tsx
+29
-0
index.tsx
src/components/NiceForm/index.tsx
+2
-0
index.tsx
src/components/StatusSwitch/index.tsx
+2
-2
index.tsx
src/components/TabTree/index.tsx
+1
-1
index.ts
src/constants/index.ts
+68
-0
global.d.ts~1610bddb1460cd81f648409972bfc813bc51b7ae
...nfig/global.d.ts~1610bddb1460cd81f648409972bfc813bc51b7ae
+0
-58
global.less
src/global/styles/global.less
+13
-0
useHistoryContainer.ts
src/hooks/useHistoryContainer.ts
+3
-0
BasicLayout.tsx
src/layouts/BasicLayout.tsx
+33
-2
AvatarDropdown.tsx
src/layouts/components/AvatarDropdown.tsx
+2
-2
menu.ts
src/locales/zh-CN/menu.ts
+10
-0
index.less
src/pages/authConfig/memberSystem/index.less
+5
-0
index.tsx
src/pages/authConfig/memberSystem/index.tsx
+152
-0
memberDetail.tsx
src/pages/authConfig/memberSystem/memberDetail.tsx
+236
-0
index.tsx
src/pages/authConfig/organ/index.tsx
+136
-0
index.ts
src/pages/authConfig/organ/schema/index.ts
+36
-0
index.less
src/pages/authConfig/userSystem/index.less
+6
-0
index.tsx
src/pages/authConfig/userSystem/index.tsx
+180
-0
index.ts
src/pages/authConfig/userSystem/schema/index.ts
+136
-0
userDetail.tsx
src/pages/authConfig/userSystem/userDetail.tsx
+246
-0
index.tsx
src/pages/editor/components/toolBar/index.tsx
+14
-1
index.tsx
src/pages/editor/shopEdit/index.tsx
+1
-1
index.less
src/pages/lxMall/commodity/index.less
+0
-45
index.tsx
src/pages/lxMall/commodity/index.tsx
+39
-24
search.tsx
src/pages/lxMall/commodity/search.tsx
+233
-0
index.tsx
src/pages/lxMall/components/Category/index.tsx
+5
-3
index.tsx
...es/lxMall/components/Filter/components/Category/index.tsx
+42
-5
index.tsx
src/pages/lxMall/components/Filter/index.tsx
+10
-4
index.tsx
src/pages/lxMall/components/Header/index.tsx
+30
-23
index.less
src/pages/lxMall/components/SearchNoResult/index.less
+44
-0
index.tsx
src/pages/lxMall/components/SearchNoResult/index.tsx
+15
-5
index.tsx
src/pages/lxMall/components/TopBar/index.tsx
+37
-22
index.tsx
src/pages/lxMall/index/index.tsx
+1
-0
index.less
src/pages/lxMall/information/index.less
+9
-1
index.tsx
src/pages/lxMall/information/index.tsx
+38
-29
LXChannelLayout.tsx
src/pages/lxMall/layouts/LXChannelLayout.tsx
+9
-6
LXMallLayout.tsx
src/pages/lxMall/layouts/LXMallLayout.tsx
+10
-6
LXShopLayout.tsx
src/pages/lxMall/layouts/LXShopLayout.tsx
+8
-6
index.tsx
src/pages/lxMall/shopList/index.tsx
+0
-17
PositionSetting.tsx
src/pages/repositories/components/PositionSetting.tsx
+85
-9
index.tsx
src/pages/repositories/schema/index.tsx
+6
-5
LoginWrap.tsx
src/pages/user/components/LoginWrap.tsx
+1
-5
api.ts
src/services/api.ts
+20
-9
index.ts
src/store/category/index.ts
+32
-5
index.ts
src/store/filter/index.ts
+24
-0
index.tsx
src/store/index.tsx
+2
-2
index.ts
src/store/user/index.ts
+3
-2
category.less
src/theme/science/styles/category.less
+3
-2
auth.ts
src/utils/auth.ts
+1
-0
ytt.config.ts
ytt.config.ts
+26
-42
No files found.
.gitignore
View file @
2c0fcf86
...
...
@@ -27,3 +27,6 @@
/src/services/index.ts
.vscode
config/base.config.json
src/global/config/global.d.ts
src/services/*Api.ts
\ No newline at end of file
config/mallRoutes/index.ts
View file @
2c0fcf86
...
...
@@ -18,6 +18,14 @@ const mallRoute = {
component
:
'@/pages/lxMall/commodity'
,
},
{
// 商品搜索
path
:
`/commodity/search`
,
name
:
'mallCommoditySearch'
,
key
:
'mallCommoditySearch'
,
hide
:
true
,
component
:
'@/pages/lxMall/commodity/search'
,
},
{
// 订单
path
:
`/order`
,
name
:
'order'
,
...
...
config/routes/authConfigRoute.ts
0 → 100644
View file @
2c0fcf86
const
AuthConfigRoute
=
{
path
:
'/memberCenter/systemSetting'
,
name
:
'systemSetting'
,
key
:
'systemSetting'
,
icon
:
'smile'
,
routes
:
[
{
path
:
'/memberCenter/systemSetting/authConfig'
,
key
:
'authConfig'
,
name
:
'authConfig'
,
routes
:
[
{
path
:
'/memberCenter/systemSetting/authConfig/organ'
,
name
:
'organ'
,
component
:
'@/pages/authConfig/organ'
,
},
{
path
:
'/memberCenter/systemSetting/authConfig/memberSystem'
,
name
:
'memberSystem'
,
component
:
'@/pages/authConfig/memberSystem'
,
},
{
path
:
'/memberCenter/systemSetting/authConfig/memberSystem/memberDetail'
,
name
:
'memberDetail'
,
component
:
'@/pages/authConfig/memberSystem/memberDetail'
,
hideInMenu
:
true
,
hidePageHeader
:
true
},
{
path
:
'/memberCenter/systemSetting/authConfig/userSystem'
,
name
:
'userSystem'
,
component
:
'@/pages/authConfig/userSystem'
,
},
{
path
:
'/memberCenter/systemSetting/authConfig/userSystem/userDetail'
,
name
:
'userSystem'
,
component
:
'@/pages/authConfig/userSystem/userDetail'
,
hideInMenu
:
true
,
hidePageHeader
:
true
},
]
}
],
}
export
default
AuthConfigRoute
\ No newline at end of file
config/routes/index.ts
View file @
2c0fcf86
...
...
@@ -11,8 +11,9 @@ import ChannelRoute from './channelRoute' // 渠道能力路由
import
TranactionRoute
from
'./tranactionRoute'
// 交易能力路由
import
LogisticsRoute
from
'./logisticsRoutes'
// 物流能力路由
import
PayandSettleRoute
from
'./payandSettle'
//支付与结算
import
AuthConfigRoute
from
'./authConfigRoute'
const
routes
=
[
CommodityRoute
,
MemberRoute
,
ShopRoute
,
ChannelRoute
,
TranactionRoute
,
PayandSettleRoute
,
LogisticsRoute
]
const
routes
=
[
CommodityRoute
,
MemberRoute
,
ShopRoute
,
ChannelRoute
,
TranactionRoute
,
PayandSettleRoute
,
LogisticsRoute
,
AuthConfigRoute
]
const
memberCenterRoute
=
{
path
:
'/memberCenter'
,
...
...
scripts/services/index.js
View file @
2c0fcf86
...
...
@@ -50,7 +50,18 @@ const serviceConfig = {
// // }
// // }
// }
<<<<<<<
HEAD
}
=======
},
//初始化会员支付策略配置
// payConfig:{
// paymemberConfig:{
// url:'/pay/member/pay/config',
// method: 'get'
// }
// }
>>>>>>>
c86a0aec36df53e09e3699378805531daf993223
}
...
...
@@ -75,19 +86,47 @@ async function batchAxiosHttps() {
// }
// }
// serverFn(asyncHttpQueue)
const
httpErrorQueue
=
[]
const
serverErrorQueue
=
[]
console
.
log
(
'
\
n'
)
for
(
const
item
in
serviceConfig
)
{
if
(
JSON
.
stringify
(
item
)
!==
'{}'
){
for
(
const
subItem
in
serviceConfig
[
item
])
{
try
{
const
data
=
await
axios
(
serviceConfig
[
item
][
subItem
])
asyncHttpQueue
[
item
][
subItem
]
=
data
.
data
.
data
// 当接口出错时 不写入json文件
if
(
data
.
data
.
code
===
1000
)
{
asyncHttpQueue
[
item
][
subItem
]
=
data
.
data
.
data
}
else
{
serverErrorQueue
.
push
({
...
asyncHttpQueue
[
item
][
subItem
],
...
data
.
data
})
// 默认置为null
asyncHttpQueue
[
item
][
subItem
]
=
null
}
}
catch
(
err
)
{
console
.
log
(
serviceConfig
[
item
][
subItem
].
url
)
console
.
log
(
err
.
response
.
data
)
httpErrorQueue
.
push
({...
serviceConfig
[
item
][
subItem
],
...
err
.
response
.
data
})
}
}
}
}
if
(
httpErrorQueue
.
length
>
0
)
{
console
.
log
(
'
\
n网络错误
\
n'
)
// 可在此做日志收集
console
.
log
(
httpErrorQueue
)
}
if
(
serverErrorQueue
.
length
>
0
)
{
console
.
log
(
'
\
n接口服务错误
\
n'
)
// 可在此做日志收集
console
.
log
(
serverErrorQueue
)
}
if
(
httpErrorQueue
.
length
>
0
||
serverErrorQueue
.
length
>
0
)
{
// 退出构建
console
.
log
(
'
\
n脚本构建失败!!!!!!'
)
// 终止当前进程
process
.
exit
(
1
)
}
return
isDemo
?
Object
.
assign
(
asyncHttpQueue
,
await
demoFetch
())
:
asyncHttpQueue
}
...
...
src/app.tsx
View file @
2c0fcf86
...
...
@@ -26,15 +26,15 @@ const whiteLists = [
...
userLoginLists
,
'/'
,
'/channelmall'
,
'/shop'
,
'/purchaseOnline'
,
'/pointsMall'
,
'/memberCenter'
,
//
'/memberCenter',
'/memberCenter/noAuth'
,
'/commodity'
,
'/shops'
,
'/shop/commodity/detail'
,
'/shop/commodity'
,
'/shop'
,
'/infomation'
,
'/403'
,
'/404'
,
...
...
@@ -70,22 +70,23 @@ export function patchRoutes({ routes }: IRoutes) {
* @export
*/
export
function
render
(
oldRender
:
Function
)
{
const
{
pathname
}
=
history
.
location
// 白名单页面不进行权限校验
if
(
whiteLists
.
includes
(
pathname
))
{
oldRender
()
return
;
}
const
authInfo
=
getAuth
()
if
(
authInfo
)
{
PublicApi
.
getMemberLoginReget
().
then
(
res
=>
{
const
{
data
,
code
}
=
res
if
(
code
===
1000
)
{
setAuth
({
memberId
:
data
.
memberId
,
userId
:
data
.
userId
,
token
:
data
.
token
})
setAuth
(
data
)
setRouters
(
data
.
urls
)
}
else
{
removeAuth
()
removeRouters
()
history
.
push
(
'/user/login'
)
history
.
replace
(
'/user/login'
)
}
oldRender
()
...
...
@@ -117,7 +118,7 @@ export function onRouteChange({ routes, matchedRoutes, location, action }) {
if
(
userLoginLists
.
includes
(
pathname
))
{
// 当登录过, 并且尝试访问登录相关页面, 需重定向到首页
history
.
replace
(
'/memberCenter/home'
)
return
;
return
;
}
// 固定配置, 出现此参数说明需携带参数校验权限路由
if
(
query
.
page_type
&&
routeAuthUrls
.
find
(
authPath
=>
{
...
...
src/components/DetailPage/index.less
View file @
2c0fcf86
.common_detail_page {
margin: -24px;
//
margin: -24px;
.common_header {
display: flex;
height: 64px;
min-
height: 64px;
align-items: center;
background: #ffffff;
justify-content: space-between;
padding: 0 24px;
.title {
margin-left: 16px;
...
...
src/components/DetailPage/index.tsx
View file @
2c0fcf86
import
React
,
{
useEffect
}
from
'react'
import
React
,
{
useEffect
,
useContext
}
from
'react'
import
{
history
}
from
'umi'
import
{
ArrowLeftOutlined
}
from
'@ant-design/icons'
import
styles
from
'./index.less'
import
{
historyContainer
}
from
'@/hooks/useHistoryContainer'
import
{
Row
}
from
'antd'
interface
DetailPagePropsType
{
children
?:
React
.
ReactNode
;
title
:
string
;
title
?:
React
.
ReactNode
;
extra
?:
React
.
ReactNode
}
const
DetailPage
:
React
.
FC
<
DetailPagePropsType
>
=
(
props
)
=>
{
const
{
children
,
title
}
=
props
const
{
children
,
title
,
extra
}
=
props
const
routerInfo
=
useContext
(
historyContainer
)
const
defaultTitle
=
routerInfo
?
routerInfo
.
name
:
''
useEffect
(()
=>
{
window
.
scrollTo
(
0
,
0
)
},
[])
return
(
<
div
className=
{
styles
.
common_detail_page
}
>
<
div
className=
{
styles
.
common_header
}
>
<
div
className=
{
styles
.
back_btn
}
onClick=
{
()
=>
history
.
goBack
()
}
>
<
ArrowLeftOutlined
/>
<
span
>
返回
</
span
>
</
div
>
<
div
className=
{
styles
.
title
}
>
{
title
}
</
div
>
<
Row
>
<
div
className=
{
styles
.
back_btn
}
onClick=
{
()
=>
history
.
goBack
()
}
>
<
ArrowLeftOutlined
/>
<
span
>
返回
</
span
>
</
div
>
<
div
className=
{
styles
.
title
}
>
{
title
||
defaultTitle
}
</
div
>
</
Row
>
<
div
>
{
extra
}
</
div
>
</
div
>
<
div
className=
{
styles
.
detail_page_contaner
}
>
{
children
}
...
...
src/components/ModalTable/index.tsx
View file @
2c0fcf86
...
...
@@ -38,7 +38,7 @@ const ModalTable:React.FC<ModalTableProps> = (props) => {
tableType=
'small'
currentRef=
{
selfRef
}
formRender=
{
(
child
,
ps
)
=>
<
Row
justify=
'space-between'
>
<
Col
>
{
child
}
</
Col
>
<
Col
span=
{
18
}
>
{
child
}
</
Col
>
<
Col
style=
{
{
marginTop
:
4
}
}
>
{
ps
}
</
Col
>
</
Row
>
}
{
...
resetTable
}
...
...
src/components/NiceForm/components/SearchSelect.tsx
View file @
2c0fcf86
...
...
@@ -116,6 +116,10 @@ const SearchSelect = (props: ISchemaFieldComponentProps) => {
// }
// const { run } = useDebounceFn(dispatchSearch, 500)
const
multipleProps
=
multiple
?
{
open
:
openSelect
,
onFocus
:
()
=>
setOpenSelect
(
true
),
}
:
{}
return
(
<
Select
ref=
{
ref
}
...
...
@@ -124,10 +128,12 @@ const SearchSelect = (props: ISchemaFieldComponentProps) => {
filterOption=
{
false
}
loading=
{
loading
}
options=
{
dataSource
}
onFocus=
{
()
=>
setOpenSelect
(
true
)
}
getPopupContainer=
{
triggerNode
=>
{
return
triggerNode
}
}
value=
{
props
.
value
}
open=
{
multiple
?
openSelect
:
null
}
dropdownRender=
{
originNode
=>
<
SelectContent
confirm=
{
confirm
}
resetField=
{
resetField
}
parentRef=
{
ref
}
handleChange=
{
handleChange
}
multiple=
{
multiple
}
value=
{
props
.
value
}
>
{
originNode
}
</
SelectContent
>
}
{
...
multipleProps
}
{
...
resetProps
}
>
</
Select
>
...
...
src/components/NiceForm/components/TableTagList.tsx
0 → 100644
View file @
2c0fcf86
import
React
,
{
useState
}
from
'react'
import
{
Tag
,
Row
}
from
'antd'
import
{
useFormEffects
}
from
'@formily/antd'
const
TableTagList
=
(
props
)
=>
{
const
{
value
=
[],
mutators
,
editable
}
=
props
const
{
extra
=
null
,
callback
=
null
}
=
props
.
props
[
'x-component-props'
]
?
props
.
props
[
'x-component-props'
]
:
{}
const
handleClose
=
(
id
)
=>
{
callback
&&
callback
(
id
)
mutators
.
remove
(
value
.
findIndex
(
v
=>
v
.
id
===
id
))
}
return
(
<
div
className=
"table-tag-list"
style=
{
{
width
:
'100%'
}
}
>
<
Row
style=
{
{
flexWrap
:
'wrap'
}
}
>
{
value
.
map
(
v
=>
<
Tag
closable=
{
editable
}
onClose=
{
()
=>
handleClose
(
v
.
id
)
}
color=
"#4279DF"
key=
{
v
.
id
}
style=
{
{
marginBottom
:
8
}
}
>
{
v
.
roleName
}
</
Tag
>)
}
</
Row
>
{
extra
}
</
div
>
)
}
TableTagList
.
defaultProps
=
{}
TableTagList
.
isFieldComponent
=
true
;
export
default
TableTagList
\ No newline at end of file
src/components/NiceForm/index.tsx
View file @
2c0fcf86
...
...
@@ -22,6 +22,7 @@ import CircleBox from './components/CircleBox';
import
Phone
from
'./components/Phone'
;
import
CustomRadio
from
'./components/CustomRadio'
;
import
SearchSelect
from
'./components/SearchSelect'
;
import
TableTagList
from
'./components/TableTagList'
;
import
'./index.less'
import
{
Checkbox
}
from
'@formily/antd-components'
;
import
cx
from
'classnames'
...
...
@@ -141,6 +142,7 @@ export const componentExport = {
Phone
,
SearchSelect
,
Input
,
TableTagList
,
}
const
NiceForm
:
React
.
FC
<
NiceFormProps
>
=
props
=>
{
const
{
children
,
components
,
...
reset
}
=
props
;
...
...
src/components/StatusSwitch/index.tsx
View file @
2c0fcf86
...
...
@@ -4,14 +4,14 @@ import { PlayCircleOutlined,PauseCircleOutlined } from '@ant-design/icons'
export
interface
StatusSwitchProps
{
record
:
any
,
fieldNames
?:
string
,
// 自定义字段名称 默认'stat
e
'
fieldNames
?:
string
,
// 自定义字段名称 默认'stat
us
'
expectTrueValue
?:
boolean
|
number
|
string
,
//期望为ture(有效)的值 默认1
handleConfirm
?(),
handleCancel
?()
}
const
StatusSwitch
:
React
.
FC
<
StatusSwitchProps
>
=
(
props
)
=>
{
const
{
record
,
fieldNames
=
'stat
e
'
,
expectTrueValue
=
1
}
=
props
const
{
record
,
fieldNames
=
'stat
us
'
,
expectTrueValue
=
1
}
=
props
return
(
<
Popconfirm
title=
"确定要执行这个操作?"
...
...
src/components/TabTree/index.tsx
View file @
2c0fcf86
...
...
@@ -51,7 +51,7 @@ export interface RenderIconsProps {
export
const
useTreeActions
=
(
action
?):
TabTreeActions
=>
{
const
actionRef
=
useRef
<
any
>
(
null
);
actionRef
.
current
=
actionRef
.
current
||
{}
;
actionRef
.
current
=
actionRef
.
current
||
action
||
createTreeActions
()
;
return
actionRef
.
current
;
};
...
...
src/constants/index.ts
View file @
2c0fcf86
...
...
@@ -8,6 +8,12 @@ export const MALL_TYPE = {
5
:
'渠道积分商城'
}
export
enum
LAYOUT_TYPE
{
mall
=
'mall'
,
shop
=
'shop'
,
channel
=
'channel'
}
// 本地环境跳过权限校验
export
const
isDev
=
process
.
env
.
NODE_ENV
===
"development"
// export const isDev = false
...
...
@@ -19,6 +25,53 @@ export const Environment_Status = {
3
:
"APP"
}
export
enum
FILTE_RTYPE
{
/**
* 常用筛选
*/
commonlyUsed
=
'commonlyUsed'
,
/**
* 分类
*/
category
=
'category'
,
/**
* 风格
*/
style
=
'style'
,
/**
* 品牌
*/
brand
=
'brand'
,
/**
* 价格
*/
price
=
'price'
,
/**
* 发货地
*/
useArea
=
'useArea'
,
/**
* 商品类型
*/
commodityType
=
'commodityType'
,
/**
* 活跃店铺
*/
activeStores
=
'activeStores'
,
/**
* 最新加入
*/
newJoin
=
'newJoin'
,
/**
* 所需积分
*/
points
=
'points'
,
/**
* 商品名称
*/
name
=
'name'
}
// 商城类型
export
const
SHOP_TYPES
=
[
{
...
...
@@ -43,6 +96,21 @@ export const SHOP_TYPES = [
},
]
export
const
STATUS_ENUM
=
[
{
label
:
'全部'
,
value
:
null
},
{
label
:
'有效'
,
value
:
1
},
{
label
:
'无效'
,
value
:
0
}
]
// 1是阿里云oss服务器, 2是本地文件服务器
export
const
UPLOAD_TYPE
=
isDev
?
2
:
1
...
...
src/global/config/global.d.ts~1610bddb1460cd81f648409972bfc813bc51b7ae
deleted
100644 → 0
View file @
5bca989b
export interface MemberType {
id: number;
typeName: string;
}
export interface BusinessType {
id: number;
typeName: string;
}
export interface UseType {
memberType: MemberType[];
businessType: BusinessType[];
}
export interface UserRegister {
useType: UseType;
}
export interface ShopInfo {
id: number;
name: string;
type: number;
environment: number;
logoUrl: string;
describe: string;
state: number;
url: string;
}
export interface Web {
shopInfo: ShopInfo[];
}
export interface PayConfig {
paymemberConfig?: any;
}
export interface CountryList {
name: string;
key: string;
icon: string;
}
export interface Global {
siteId: number;
siteUrl: string;
logo: string;
countryList: CountryList[];
}
export interface RootObject {
userRegister: UserRegister;
web: Web;
payConfig: PayConfig;
global: Global;
}
\ No newline at end of file
src/global/styles/global.less
View file @
2c0fcf86
...
...
@@ -149,6 +149,9 @@ h6 {
background: none;
}
}
.white-wrapper {
background-color: #fff;
}
//addonAfter 有选择弹窗时
.input_addonAfter{
...
...
@@ -203,6 +206,8 @@ h6 {
}
}
.tree-node-circle {
width: 4px;
height: 4px;
...
...
@@ -263,4 +268,11 @@ h6 {
position: absolute;
top: 100%;
font-size: 12px;
}
// 强制覆盖下拉框固定位置
.fixed-ant-selected-down {
.ant-select-dropdown {
top: 36px !important;
}
}
\ No newline at end of file
src/hooks/useHistoryContainer.ts
0 → 100644
View file @
2c0fcf86
import
React
,
{
createContext
}
from
'react'
export
const
historyContainer
=
createContext
<
any
>
(
null
);
src/layouts/BasicLayout.tsx
View file @
2c0fcf86
...
...
@@ -12,6 +12,7 @@ import RightContent from './components/RightContent';
// import logo from '../assets/logo.svg';
import
logo
from
'../../mockStatic/logo.png'
import
MenuSlider
from
'./components/MenuSlider'
import
{
getMatchMenu
}
from
'@umijs/route-utils'
;
export
interface
BasicLayoutProps
extends
ProLayoutProps
{
breadcrumbNameMap
:
{
...
...
@@ -31,6 +32,23 @@ export type BasicLayoutContext = { [K in 'location']: BasicLayoutProps[K] } & {
};
};
export
const
getSelectedMenuKeys
=
(
pathname
:
string
,
menuData
:
MenuDataItem
[],
):
string
[]
=>
{
const
menus
=
getMatchMenu
(
pathname
,
menuData
);
const
dispatchMenu
=
menus
.
map
(
v
=>
{
if
(
v
.
hideInMenu
)
{
const
flag
=
v
.
key
||
v
.
path
||
''
const
substr
=
flag
.
substr
(
0
,
flag
.
lastIndexOf
(
'/'
))
v
.
path
=
substr
v
.
key
=
substr
}
return
v
})
return
dispatchMenu
.
map
(
item
=>
item
.
key
||
item
.
path
||
''
);
};
const
defaultFooterDom
=
(
<
DefaultFooter
copyright=
{
`${new Date().getFullYear()} 技术组体验出品`
}
...
...
@@ -63,7 +81,7 @@ const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
};
const
[
openKeys
,
setOpenKeys
]
=
useState
<
string
[]
>
([])
const
[
collapsed
,
setCollapsed
]
=
useState
(
false
)
const
[
selectedKeys
,
setSelectedKeys
]
=
useState
<
string
[]
|
undefined
>
([]);
const
handleMenuCollapse
=
(
payload
:
boolean
):
void
=>
{
setCollapsed
(
payload
)
if
(
payload
)
{
...
...
@@ -90,6 +108,19 @@ const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
const
menuRouter
=
getMenuRouter
(
menuData
,
location
.
pathname
)
useEffect
(()
=>
{
// if pathname can't match, use the nearest parent's key
const
keys
=
getSelectedMenuKeys
(
location
.
pathname
||
'/'
,
basicInfo
.
menuData
||
[],
);
const
animationFrameId
=
requestAnimationFrame
(()
=>
{
setSelectedKeys
(
keys
);
});
return
()
=>
window
.
cancelAnimationFrame
&&
window
.
cancelAnimationFrame
(
animationFrameId
);
},
[
location
.
pathname
]);
useEffect
(()
=>
{
if
(
menuRouter
&&
menuRouter
.
children
)
{
if
(
collapsed
)
{
setOpenKeys
([])
...
...
@@ -118,7 +149,7 @@ const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
]
}
menuRender=
{
()
=>
<
MenuSlider
currentSelectKey=
{
[
location
.
pathname
]
}
currentSelectKey=
{
selectedKeys
}
openKeys=
{
openKeys
}
menuData=
{
menuData
}
pathname=
{
location
.
pathname
}
...
...
src/layouts/components/AvatarDropdown.tsx
View file @
2c0fcf86
...
...
@@ -5,7 +5,7 @@ import React from 'react';
import
{
history
}
from
'umi'
;
import
PersonDropdown
from
'./PersonDropdown'
import
styles
from
'../styles/RightContent.less'
;
import
{
removeAuth
,
removeRouters
}
from
'@/utils/auth'
;
import
{
removeAuth
,
removeRouters
,
getAuth
}
from
'@/utils/auth'
;
const
AvatarDropdown
=
()
=>
{
...
...
@@ -16,7 +16,7 @@ const AvatarDropdown = () => {
}
const
currentUser
=
{
name
:
'Serati Ma
'
,
name
:
getAuth
().
name
||
'未知用户
'
,
avatar
:
'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png'
,
}
...
...
src/locales/zh-CN/menu.ts
View file @
2c0fcf86
...
...
@@ -123,4 +123,13 @@ export default {
'menu.payandSettle'
:
'支付'
,
'menu.payandSettle.paySetting'
:
'支付方式管理'
,
'menu.payandSettle.paySetting.payParamsSetting'
:
'会员支付参数配置'
,
// 权限管理
'menu.systemSetting'
:
'系统'
,
'menu.systemSetting.authConfig'
:
'平台权限'
,
'menu.systemSetting.authConfig.organ'
:
'组织机构'
,
'menu.systemSetting.authConfig.memberSystem'
:
'角色管理'
,
'menu.systemSetting.authConfig.memberDetail'
:
'角色详情'
,
'menu.systemSetting.authConfig.userSystem'
:
'用户管理'
,
'menu.systemSetting.authConfig.userDetail'
:
'用户详情'
,
};
\ No newline at end of file
src/pages/authConfig/memberSystem/index.less
0 → 100644
View file @
2c0fcf86
.menu-role-tree {
padding: 24px;
border: 1px solid #F4F5F7;
}
\ No newline at end of file
src/pages/authConfig/memberSystem/index.tsx
0 → 100644
View file @
2c0fcf86
import
React
,
{
ReactNode
,
useRef
}
from
'react'
;
import
{
history
,
Link
}
from
'umi'
import
{
Button
,
Popconfirm
,
Card
}
from
'antd'
;
import
{
PlusCircleOutlined
,
PlayCircleOutlined
,
PauseCircleOutlined
,
PlusOutlined
,
EyeOutlined
}
from
'@ant-design/icons'
;
import
{
StandardTable
}
from
'god'
import
{
ColumnType
}
from
'antd/lib/table/interface'
import
{
IButtonFilter
,
IFormFilter
}
from
'god/dist/src/standard-table/TableController'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
StatusSwitch
from
'@/components/StatusSwitch'
;
import
EyePreview
from
'@/components/EyePreview'
;
import
{
STATUS_ENUM
}
from
'@/constants'
;
import
{
PageHeaderWrapper
}
from
'@ant-design/pro-layout'
;
const
fetchData
=
async
(
params
)
=>
{
const
{
data
}
=
await
PublicApi
.
getMemberRolePage
(
params
)
return
data
}
const
MemberSystem
:
React
.
FC
<
{}
>
=
()
=>
{
const
ref
=
useRef
<
any
>
({})
const
deleteItem
=
async
(
record
)
=>
{
// 删除该项
await
PublicApi
.
postMemberRoleDelete
({
memberRoleId
:
record
.
id
})
ref
.
current
.
reload
()
}
const
updateItem
=
(
record
)
=>
{
history
.
push
(
`/memberCenter/systemSetting/authConfig/memberSystem/memberDetail?id=
${
record
.
id
}
&preview=0`
)
}
const
handleStatus
=
async
(
record
)
=>
{
await
PublicApi
.
postMemberRoleUpdatestatus
({
id
:
record
.
id
,
status
:
record
.
status
===
1
?
0
:
1
})
ref
.
current
.
reload
()
}
const
columns
:
ColumnType
<
any
>
[]
=
[
{
title
:
'ID'
,
dataIndex
:
'id'
,
align
:
'center'
,
key
:
'id'
,
},
{
title
:
'角色名称'
,
dataIndex
:
'roleName'
,
align
:
'center'
,
key
:
'roleName'
,
className
:
'commonPickColor'
,
render
:
(
text
,
record
)
=>
<
EyePreview
url=
{
`/memberCenter/systemSetting/authConfig/memberSystem/memberDetail?id=${record.id}&preview=1`
}
>
{
text
}
</
EyePreview
>
},
{
title
:
'描述'
,
align
:
'center'
,
dataIndex
:
'remark'
,
key
:
'remark'
,
},
{
title
:
'状态'
,
align
:
'center'
,
dataIndex
:
'status'
,
key
:
'status'
,
render
:
(
text
:
any
,
record
:
any
)
=>
<
StatusSwitch
record=
{
record
}
handleConfirm=
{
()
=>
handleStatus
(
record
)
}
/>
},
{
title
:
'操作'
,
dataIndex
:
'option'
,
align
:
'center'
,
render
:
(
text
:
any
,
record
:
any
)
=>
{
return
record
.
status
===
0
?
(
<>
<
Popconfirm
title=
"确定要执行这个操作?"
onConfirm=
{
()
=>
deleteItem
(
record
)
}
okText=
"是"
cancelText=
"否"
>
<
Button
type=
'link'
>
删除
</
Button
>
</
Popconfirm
>
<
Button
type=
'link'
onClick=
{
()
=>
updateItem
(
record
)
}
>
修改
</
Button
>
</>
)
:
null
}
}
];
return
(
<
PageHeaderWrapper
>
<
Card
className=
"common-wrapper"
>
<
StandardTable
columns=
{
columns
}
currentRef=
{
ref
}
fetchTableData=
{
(
params
:
any
)
=>
fetchData
(
params
)
}
formilyLayouts=
{
{
justify
:
'space-between'
}
}
formilyChilds=
{
{
layouts
:
{
order
:
2
},
children
:
<
Button
style=
{
{
width
:
140
}
}
icon=
{
<
PlusOutlined
/>
}
onClick=
{
()
=>
history
.
push
(
'/memberCenter/systemSetting/authConfig/memberSystem/memberDetail'
)
}
type=
'primary'
>
新建
</
Button
>
}
}
formilyProps=
{
{
layouts
:
{
order
:
3
},
ctx
:
{
effects
:
(
$
)
=>
{
$
(
'onFieldInputChange'
,
'status'
).
subscribe
(()
=>
{
ref
.
current
.
reload
()
})
},
schema
:
{
type
:
'object'
,
properties
:
{
roleName
:
{
type
:
'Search'
,
"x-component-props"
:
{
placeholder
:
'请输入角色名称'
}
},
status
:
{
type
:
'string'
,
enum
:
STATUS_ENUM
,
"x-component-props"
:
{
placeholder
:
'请选择状态'
}
}
}
}
}
}
}
/>
</
Card
>
</
PageHeaderWrapper
>
)
}
export
default
MemberSystem
src/pages/authConfig/memberSystem/memberDetail.tsx
0 → 100644
View file @
2c0fcf86
import
React
,
{
useContext
,
useState
,
useEffect
,
useRef
,
useLayoutEffect
,
useCallback
}
from
'react'
;
import
{
Row
,
Col
,
Button
,
Form
,
Input
,
Space
,
Tabs
,
message
,
Badge
,
Card
}
from
'antd'
;
import
{
IntegrateTree
}
from
'god'
import
{
history
}
from
'umi'
;
import
{
historyContainer
}
from
'@/hooks/useHistoryContainer'
;
import
NiceForm
from
'@/components/NiceForm'
;
import
TabTree
,
{
useTreeActions
,
createTreeActions
}
from
'@/components/TabTree'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
styled
from
'./index.less'
import
CheckboxTree
from
'@/components/CheckBoxTree'
;
import
{
useTreeTabs
}
from
'@/hooks/useTreeTabs'
;
import
{
createFormActions
}
from
'@formily/antd'
;
import
{
usePageStatus
,
PageStatus
}
from
'@/hooks/usePageStatus'
;
import
DetailPage
from
'@/components/DetailPage'
;
import
{
PageHeaderWrapper
}
from
'@ant-design/pro-layout'
;
import
ReutrnEle
from
'@/components/ReturnEle'
;
const
pageTitles
=
[
'新增'
,
'编辑'
,
'预览'
]
const
TabFormErrors
=
(
props
)
=>
{
return
(
<
Badge
dot=
{
props
.
dot
}
offset=
{
[
5
,
-
5
]
}
>
{
props
.
children
}
</
Badge
>
)
}
const
fetchMenuData
=
async
()
=>
{
const
res
=
await
PublicApi
.
getMemberRoleAuthTree
()
return
res
}
const
TabsItem
=
Tabs
.
TabPane
const
menuActions
=
createFormActions
()
const
treeActions
=
createTreeActions
()
const
MemberDetail
:
React
.
FC
<
{}
>
=
()
=>
{
const
[
form
]
=
Form
.
useForm
();
const
value
=
useContext
(
historyContainer
)
const
{
treeData
,
handleSelect
,
nodeRecord
,
isEditForm
,
setIsEditForm
,
getTreeMaps
,
}
=
useTreeTabs
({
fetchMenuData
,
fetchItemDetailData
:
({
id
})
=>
PublicApi
.
getMemberRoleAuthButton
({
menuId
:
id
})
})
const
actionRef
=
useRef
<
any
>
({})
const
formInitValue
=
nodeRecord
?
getTreeMaps
(
nodeRecord
.
key
)
:
{}
const
[
errors
,
setErrors
]
=
useState
<
boolean
>
(
false
)
const
[
formValue
,
setFormValue
]
=
useState
<
any
>
(
null
)
const
{
pageStatus
,
id
}
=
usePageStatus
()
// 编辑和预览模式下需回显数据
const
fetchRoleMenuDetail
=
async
(
id
)
=>
{
// 10秒缓存
const
res
=
await
PublicApi
.
getMemberRoleGet
({
memberRoleId
:
id
},
{
useCache
:
true
,
ttl
:
10
*
1000
})
return
res
}
// 储存的按钮数据
const
[
buttonInfos
,
setButtonInfos
]
=
useState
<
any
>
([])
useEffect
(()
=>
{
if
(
!
id
)
return
;
fetchRoleMenuDetail
(
id
).
then
(
res
=>
{
const
{
data
}
=
res
setFormValue
(
data
)
})
},
[])
useEffect
(()
=>
{
if
(
formInitValue
)
{
// 显示右侧checkbox
setButtonInfos
(
formInitValue
.
buttons
||
[])
// 回显右侧checkbox的值
if
(
actionRef
.
current
.
setSelected
)
{
actionRef
.
current
.
setSelected
()
}
}
},
[
getTreeMaps
])
const
handleSubmit
=
()
=>
{
menuActions
.
submit
().
then
(
async
({
values
})
=>
{
setErrors
(
false
)
// 如果未点击过操作权限tab, 则无法获取到actionRef实例, 需补充手动补充回显的ids, 新增的时候如果未设置按钮,则返回空数组
const
buttonCheckIds
=
actionRef
.
current
.
selected
||
(
formValue
&&
formValue
.
ids
)
||
[]
const
treeCheckIds
=
treeActions
.
getSelectKeys
()
const
menuIds
=
[...
buttonCheckIds
,
...
treeCheckIds
]
if
(
pageStatus
===
PageStatus
.
EDIT
)
{
await
PublicApi
.
postMemberRoleUpdate
({
...
values
,
memberRoleId
:
id
,
menuIds
})
}
else
{
await
PublicApi
.
postMemberRoleAdd
({
...
values
,
menuIds
})
}
history
.
goBack
(
-
1
)
}).
catch
(
err
=>
{
console
.
log
(
err
)
if
(
Array
.
isArray
(
err
))
{
setErrors
(
true
)
}
})
}
const
changeTabs
=
(
key
)
=>
{
if
(
key
===
'2'
&&
id
)
{
fetchRoleMenuDetail
(
id
).
then
(
res
=>
{
const
{
data
}
=
res
// 获取菜单id选中的集合
const
{
checkIds
,
...
reset
}
=
data
treeActions
.
setSelectKeys
(
checkIds
)
})
}
}
const
extraButtons
=
(
<
Space
>
<
Button
type=
'primary'
disabled=
{
pageStatus
===
PageStatus
.
PREVIEW
}
onClick=
{
handleSubmit
}
>
保存
</
Button
>
</
Space
>
)
return
(
<
PageHeaderWrapper
onBack=
{
()
=>
history
.
goBack
()
}
backIcon=
{
<
ReutrnEle
description=
"返回"
/>
}
className=
'addRepository'
title=
{
pageTitles
[
pageStatus
]
}
extra=
{
[
extraButtons
]
}
>
<
Card
>
<
Tabs
type=
'card'
className=
'black-tabs'
onChange=
{
changeTabs
}
>
<
TabsItem
tab=
{
<
TabFormErrors
dot=
{
errors
}
>
基本信息
</
TabFormErrors
>
}
key=
'1'
>
<
NiceForm
labelCol=
{
4
}
wrapperCol=
{
12
}
initialValues=
{
formValue
}
labelAlign=
'left'
actions=
{
menuActions
}
editable=
{
pageStatus
!==
PageStatus
.
PREVIEW
}
previewPlaceholder=
' '
schema=
{
{
type
:
'object'
,
properties
:
{
roleName
:
{
type
:
'string'
,
title
:
'角色名称'
,
required
:
true
},
remark
:
{
type
:
'textarea'
,
title
:
'备注'
,
"x-rules"
:
[
{
limitByte
:
true
,
maxByte
:
120
}
],
"x-component-props"
:
{
rows
:
4
}
},
state
:
{
type
:
'number'
,
title
:
'状态'
,
"x-component"
:
'CustomStatus'
,
default
:
1
}
}
}
}
>
</
NiceForm
>
</
TabsItem
>
<
TabsItem
tab=
'操作权限'
key=
'2'
>
<
Row
justify=
'space-between'
>
<
Col
span=
{
17
}
className=
{
styled
[
'menu-role-tree'
]
}
>
<
TabTree
title=
'菜单访问权限'
fetchData=
{
params
=>
fetchMenuData
()
}
checkable
actions=
{
treeActions
}
treeData=
{
treeData
}
handleSelect=
{
handleSelect
}
customKey=
'id'
disabled=
{
pageStatus
===
PageStatus
.
PREVIEW
}
/>
</
Col
>
<
Col
span=
{
6
}
className=
{
styled
[
'menu-role-tree'
]
}
>
<
CheckboxTree
actions=
{
actionRef
}
disabled=
{
pageStatus
===
PageStatus
.
PREVIEW
}
checkedNodes=
{
buttonInfos
}
title=
'菜单接口访问权限'
/>
</
Col
>
</
Row
>
</
TabsItem
>
</
Tabs
>
</
Card
>
</
PageHeaderWrapper
>
)
}
export
default
MemberDetail
src/pages/authConfig/organ/index.tsx
0 → 100644
View file @
2c0fcf86
import
React
,
{
useState
,
ReactText
,
useEffect
}
from
'react'
;
import
{
Row
,
Col
,
Tree
,
Form
,
Table
,
InputNumber
,
Popconfirm
,
Button
,
Input
,
Modal
,
Card
}
from
'antd'
;
import
{
CarryOutOutlined
,
FormOutlined
,
PlusOutlined
}
from
'@ant-design/icons'
;
import
TabTree
,
{
useTreeActions
,
createTreeActions
}
from
'@/components/TabTree'
;
import
SchemaForm
,
{
createFormActions
,
LifeCycleTypes
,
FormEffectHooks
}
from
'@formily/antd'
;
import
{
menuSchema
}
from
'./schema'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
{
omit
}
from
'@/utils'
;
import
{
useMap
,
useBoolean
}
from
'@umijs/hooks'
;
import
{
useTreeTabs
}
from
'@/hooks/useTreeTabs'
;
import
{
isObject
}
from
'@antv/util'
;
// import "./index.less"
const
{
ON_FORM_INPUT_CHANGE
}
=
LifeCycleTypes
const
{
onFieldInputChange$
}
=
FormEffectHooks
enum
FormState
{
FREE
,
// 空闲状态
EDIT
,
// 编辑状态
ADD
,
// 新增状态
}
const
formActions
=
createFormActions
()
const
treeActions
=
createTreeActions
()
const
fetchMenuData
=
async
(
params
?)
=>
{
const
res
=
await
PublicApi
.
getMemberOrgTree
()
return
res
}
const
Organ
:
React
.
FC
<
{}
>
=
()
=>
{
const
{
treeStatus
,
setTreeStatus
,
treeData
,
setIsEditForm
,
nodeRecord
,
setNodeRecord
,
handleSelect
,
getTreeMaps
,
setTreeMaps
,
resetMenu
,
toolsRender
,
handleDeleteMenu
}
=
useTreeTabs
({
treeActions
,
formActions
,
deleteMenu
:
PublicApi
.
postMemberOrgDelete
,
fetchMenuData
:
fetchMenuData
,
fetchItemDetailData
:
PublicApi
.
getMemberOrgGet
})
// 当拥有节点数据并且当前状态是编辑状态时 需回显表单
const
formInitValue
=
(
nodeRecord
&&
treeStatus
===
FormState
.
EDIT
)
?
getTreeMaps
(
nodeRecord
.
key
)
:
{}
const
handleSubmitAllSetting
=
()
=>
{
formActions
.
submit
()
}
// 保存设置提交
const
handleSubmit
=
(
value
)
=>
{
// 去掉模拟的key, 为true的时候是编辑
const
editOrAdd
=
nodeRecord
&&
treeStatus
===
FormState
.
EDIT
const
params
=
editOrAdd
?
{
...
value
,
parentId
:
nodeRecord
.
id
}
:
{
...
value
,
parentId
:
nodeRecord
?
nodeRecord
.
parentId
:
0
,
}
const
fn
=
editOrAdd
?
PublicApi
.
postMemberOrgUpdate
:
PublicApi
.
postMemberOrgAdd
fn
(
params
).
then
(
res
=>
{
resetMenu
()
setTreeStatus
(
FormState
.
FREE
)
setNodeRecord
(
undefined
)
// 保存后要将是否填写过表单设为false
setIsEditForm
(
false
)
})
}
return
<
Card
className=
"common-wrapper white-wrapper"
>
<
Row
gutter=
{
[
36
,
36
]
}
>
<
Col
span=
{
8
}
>
<
h3
className=
"commonPanelTitle mb-30"
>
选择要编辑的项目
</
h3
>
{
treeData
&&
treeData
.
length
>
0
?
<
TabTree
fetchData
=
{
params
=
>
fetchMenuData(params)}
treeData=
{
treeData
}
toolsRender=
{
toolsRender
}
actions=
{
treeActions
}
customKey='id'
handleSelect=
{
(
key
,
node
)
=>
handleSelect
(
key
,
node
)
}
/
>
:
<
Button
block
type=
'primary'
onClick=
{
()
=>
handleSelect
()
}
>
暂无菜单, 开始新增
</
Button
>
}
</
Col
>
<
Col
span=
{
16
}
>
{
treeStatus
!==
FormState
.
FREE
&&
<>
<
h3
className=
"commonPanelTitle mb-30"
>
{
treeStatus
===
FormState
.
ADD
?
'新增'
:
'编辑'
}
</
h3
>
<
SchemaForm
schema=
{
menuSchema
}
value=
{
formInitValue
}
actions=
{
formActions
}
effects=
{
(
$
)
=>
{
$
(
ON_FORM_INPUT_CHANGE
).
subscribe
(()
=>
{
setIsEditForm
(
true
)
})
$
(
'onFormReset'
).
subscribe
(()
=>
{
console
.
log
(
'mount'
)
})
}
}
onSubmit=
{
handleSubmit
}
>
</
SchemaForm
>
<
Button
onClick=
{
handleSubmitAllSetting
}
type=
"primary"
style=
{
{
marginTop
:
32
,
marginBottom
:
16
,
marginRight
:
24
}
}
>
保存设置
</
Button
>
<
Popconfirm
title=
"确定要删除吗?"
okText=
"是"
cancelText=
"否"
onConfirm=
{
handleDeleteMenu
}
>
<
Button
style=
{
{
marginTop
:
32
,
marginBottom
:
16
}
}
>
删除菜单
</
Button
>
</
Popconfirm
>
</>
}
</
Col
>
</
Row
>
</
Card
>
}
export
default
Organ
src/pages/authConfig/organ/schema/index.ts
0 → 100644
View file @
2c0fcf86
import
{
ISchema
}
from
'@formily/antd'
;
export
const
menuSchema
:
ISchema
=
{
type
:
'object'
,
properties
:
{
MEGA_LAYOUT
:
{
type
:
'object'
,
"x-component"
:
'mega-layout'
,
"x-component-props"
:
{
labelAlign
:
'top'
,
wrapperCol
:
12
},
properties
:
{
code
:
{
type
:
'string'
,
title
:
'组织代码'
,
required
:
true
,
},
title
:
{
type
:
'string'
,
title
:
'组织机构'
,
required
:
true
},
remark
:
{
type
:
'textarea'
,
title
:
'描述'
,
"x-component-props"
:
{
rows
:
4
}
}
}
}
}
}
\ No newline at end of file
src/pages/authConfig/userSystem/index.less
0 → 100644
View file @
2c0fcf86
.user-system {
.ant-input-group-addon {
padding: 0;
border: none;
}
}
src/pages/authConfig/userSystem/index.tsx
0 → 100644
View file @
2c0fcf86
import
React
,
{
ReactNode
,
useRef
}
from
'react'
;
import
{
history
,
Link
}
from
'umi'
import
{
Button
,
Popconfirm
,
Card
}
from
'antd'
;
import
{
PlusCircleOutlined
,
PlayCircleOutlined
,
PauseCircleOutlined
,
PlusOutlined
,
EyeOutlined
}
from
'@ant-design/icons'
;
import
{
StandardTable
}
from
'god'
import
{
ColumnType
}
from
'antd/lib/table/interface'
import
{
IButtonFilter
,
IFormFilter
}
from
'god/dist/src/standard-table/TableController'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
EyePreview
from
'@/components/EyePreview'
;
import
StatusSwitch
from
'@/components/StatusSwitch'
;
import
{
STATUS_ENUM
}
from
'@/constants'
;
import
{
PageHeaderWrapper
}
from
'@ant-design/pro-layout'
;
// 模拟请求
const
fetchData
=
async
(
params
)
=>
{
const
{
data
}
=
await
PublicApi
.
getMemberUserPage
(
params
)
return
data
}
const
UserSystem
:
React
.
FC
<
{}
>
=
()
=>
{
const
ref
=
useRef
<
any
>
({})
const
addItem
=
()
=>
{
history
.
push
(
'/memberCenter/systemSetting/authConfig/userSystem/userDetail'
)
}
const
deleteItem
=
(
record
)
=>
{
// 删除该项
PublicApi
.
postMemberUserDelete
({
userId
:
record
.
userId
}).
then
(()
=>
{
ref
.
current
.
reload
()
})
}
const
updateItem
=
(
record
)
=>
{
history
.
push
(
`/memberCenter/systemSetting/authConfig/userSystem/userDetail?id=
${
record
.
userId
}
&preview=0`
)
}
const
handleStatus
=
(
record
)
=>
{
PublicApi
.
postMemberUserUpdatestatus
({
userId
:
record
.
userId
,
status
:
record
.
status
===
1
?
0
:
1
}).
then
(
res
=>
{
ref
.
current
.
reload
()
})
}
const
columns
:
ColumnType
<
any
>
[]
=
[
{
title
:
'账号'
,
dataIndex
:
'account'
,
align
:
'center'
,
key
:
'account'
,
className
:
'commonPickColor'
,
render
:
(
text
,
record
)
=>
<
EyePreview
url=
{
`/memberCenter/systemSetting/authConfig/userSystem/userDetail?id=${record.userId}&preview=1`
}
>
{
text
}
</
EyePreview
>
},
{
title
:
'用户姓名'
,
dataIndex
:
'name'
,
align
:
'center'
,
key
:
'name'
,
},
{
title
:
'所属机构'
,
dataIndex
:
'orgName'
,
align
:
'center'
,
key
:
'orgName'
},
{
title
:
'绑定手机号码'
,
align
:
'center'
,
dataIndex
:
'phone'
,
key
:
'phone'
,
},
{
title
:
'所属角色'
,
align
:
'center'
,
dataIndex
:
'roleName'
,
key
:
'roleName'
,
},
{
title
:
'最后登录时间'
,
align
:
'center'
,
dataIndex
:
'lastLoginTime'
,
key
:
'lastLoginTime'
,
},
{
title
:
'状态'
,
align
:
'center'
,
dataIndex
:
'status'
,
key
:
'status'
,
render
:
(
text
:
any
,
record
:
any
)
=>
<
StatusSwitch
handleConfirm=
{
()
=>
handleStatus
(
record
)
}
record=
{
record
}
/>
},
{
title
:
'操作'
,
dataIndex
:
'option'
,
align
:
'center'
,
render
:
(
text
:
any
,
record
:
any
)
=>
{
return
record
.
status
===
0
&&
(
<>
<
Popconfirm
title=
"确定要执行这个操作?"
onConfirm=
{
()
=>
deleteItem
(
record
)
}
okText=
"是"
cancelText=
"否"
>
<
Button
type=
'link'
>
删除
</
Button
>
</
Popconfirm
>
<
Button
type=
'link'
onClick=
{
()
=>
updateItem
(
record
)
}
>
修改
</
Button
>
</>
)
}
}
];
return
(
<
PageHeaderWrapper
>
<
Card
className=
"common-wrapper"
>
<
StandardTable
columns=
{
columns
}
currentRef=
{
ref
}
fetchTableData=
{
(
params
:
any
)
=>
fetchData
(
params
)
}
formilyLayouts=
{
{
justify
:
'space-between'
}
}
formilyChilds=
{
{
layouts
:
{
order
:
2
},
children
:
<
Button
style=
{
{
width
:
140
}
}
icon=
{
<
PlusOutlined
/>
}
onClick=
{
addItem
}
type=
'primary'
>
新建
</
Button
>
}
}
formilyProps=
{
{
layouts
:
{
order
:
3
},
ctx
:
{
effects
:
(
$
)
=>
{
$
(
'onFieldInputChange'
,
'status'
).
subscribe
(()
=>
{
ref
.
current
.
reload
()
})
},
schema
:
{
type
:
'object'
,
properties
:
{
account
:
{
type
:
'Search'
,
"x-component-props"
:
{
placeholder
:
'请输入账号'
}
},
name
:
{
type
:
'Search'
,
"x-component-props"
:
{
placeholder
:
'请输入用户姓名'
}
},
status
:
{
type
:
'string'
,
enum
:
STATUS_ENUM
,
"x-component-props"
:
{
placeholder
:
'请选择状态'
}
}
}
}
}
}
}
/>
</
Card
>
</
PageHeaderWrapper
>
)
}
export
default
UserSystem
src/pages/authConfig/userSystem/schema/index.ts
0 → 100644
View file @
2c0fcf86
import
{
ISchema
}
from
'@formily/antd'
;
import
{
PATTERN_MAPS
}
from
'@/constants/regExp'
;
export
const
UserDetailSchema
:
ISchema
=
{
type
:
'object'
,
properties
:
{
MEGA_LAYOUT
:
{
type
:
'object'
,
"x-component"
:
'mega-layout'
,
"x-component-props"
:
{
labelCol
:
6
,
labelAlign
:
'left'
,
full
:
true
,
wrapperCol
:
12
},
properties
:
{
account
:
{
type
:
'string'
,
title
:
'登录账号'
,
"x-rules"
:
[
{
pattern
:
/^
\w{6,20}
$/
,
message
:
'请输入由数字字母或者下划线组成的6-20位账号'
}
],
required
:
true
},
password
:
{
type
:
'password'
,
title
:
'登录密码'
,
"x-rules"
:
[
{
pattern
:
PATTERN_MAPS
.
password
,
message
:
'请输入由大小写字母和数字组成的8位密码'
}
],
required
:
true
},
name
:
{
type
:
'string'
,
title
:
'姓名'
,
maxLength
:
16
,
required
:
true
},
phoneLayout
:
{
type
:
'object'
,
"x-component"
:
'flex-box'
,
title
:
'手机号'
,
"x-component-props"
:
{
labelcol
:
6
,
wrappercol
:
12
},
required
:
true
,
properties
:
{
countryCode
:
{
required
:
true
,
type
:
'string'
,
enum
:
[
'+86'
],
"x-mega-props"
:
{
wrapperCol
:
24
},
"x-component-props"
:
{
flexcol
:
{
span
:
6
}
}
},
phone
:
{
type
:
'number'
,
required
:
true
,
"x-mega-props"
:
{
wrapperCol
:
24
,
full
:
true
},
"x-rules"
:
[
{
pattern
:
PATTERN_MAPS
.
phone
,
message
:
'请输入正确的手机号'
}
],
"x-component-props"
:
{
flexcol
:
{
flex
:
1
}
}
}
}
},
idCardNo
:
{
type
:
'string'
,
title
:
'身份证号'
},
email
:
{
type
:
'string'
,
title
:
'邮箱'
,
"x-rules"
:
[
{
pattern
:
PATTERN_MAPS
.
email
,
message
:
'请输入正确的邮箱'
}
]
},
jobTitle
:
{
type
:
'string'
,
title
:
'职位'
,
maxLength
:
20
,
},
orgName
:
{
type
:
'string'
,
title
:
'所属组织机构'
,
required
:
true
,
'x-component-props'
:
{
disabled
:
true
,
addonAfter
:
"{{connectCategory}}"
},
},
orgId
:
{
type
:
'string'
,
visible
:
false
},
memberRoleIds
:
{
required
:
true
,
type
:
'array:string'
,
"x-component"
:
'tableTagList'
,
"x-component-props"
:
{
extra
:
"{{addRoles}}"
,
callback
:
"{{callback}}"
},
title
:
'关联角色'
},
}
}
}
}
\ No newline at end of file
src/pages/authConfig/userSystem/userDetail.tsx
0 → 100644
View file @
2c0fcf86
import
React
,
{
useRef
,
useState
,
useEffect
}
from
'react'
;
import
{
Button
,
Modal
,
Card
}
from
'antd'
;
import
{
createFormActions
,
FormButtonGroup
}
from
'@formily/antd'
import
{
LinkOutlined
}
from
'@ant-design/icons'
;
import
{
ColumnType
}
from
'antd/lib/table/interface'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
{
history
}
from
'umi'
;
import
{
usePageStatus
,
PageStatus
}
from
'@/hooks/usePageStatus'
;
import
DetailPage
from
'@/components/DetailPage'
;
import
NiceForm
from
'@/components/NiceForm'
;
import
{
UserDetailSchema
}
from
'./schema'
;
import
'./index.less'
import
ModalTable
from
'@/components/ModalTable'
;
import
{
useRowSelectionTable
}
from
'@/hooks/useRowSelectionTable'
;
import
{
findItemAndDelete
,
omit
,
getParentTreeTitles
}
from
'@/utils'
;
import
TabTree
,
{
useTreeActions
,
createTreeActions
}
from
'@/components/TabTree'
;
import
{
useTreeTabs
}
from
'@/hooks/useTreeTabs'
;
import
{
useHttpRequest
}
from
'@/hooks/useHttpRequest'
;
import
{
PageHeaderWrapper
}
from
'@ant-design/pro-layout'
;
import
ReutrnEle
from
'@/components/ReturnEle'
;
const
titleRender
=
(
title
)
=>
{
if
(
title
===
PageStatus
.
PREVIEW
)
return
'查看用户'
if
(
title
===
PageStatus
.
ADD
)
return
'新增用户'
if
(
title
===
PageStatus
.
EDIT
)
return
'编辑用户'
return
''
}
const
fetchOriginTreeData
=
async
(
params
?)
=>
{
// 平台后台树
const
res
=
await
PublicApi
.
getMemberOrgTree
({},
{
ttl
:
10
,
useCache
:
true
})
return
res
}
const
userActions
=
createFormActions
()
const
originTreeActions
=
createTreeActions
()
const
AddUser
:
React
.
FC
<
{}
>
=
()
=>
{
const
[
originVisible
,
setOriginVisible
]
=
useState
(
false
)
const
[
roleVisible
,
setRoleVisible
]
=
useState
(
false
)
const
ref
=
useRef
<
any
>
({})
const
[
formData
,
setFormData
]
=
useState
<
any
>
(
null
)
const
{
id
,
pageStatus
}
=
usePageStatus
()
const
[
roleSelection
,
roleSelectCtl
]
=
useRowSelectionTable
()
const
[
originSelectNode
,
setOriginSelectNode
]
=
useState
<
any
>
()
const
{
data
,
loading
,
err
,
run
}
=
useHttpRequest
(
id
?
PublicApi
.
postMemberUserUpdate
:
PublicApi
.
postMemberUserAdd
)
const
{
treeData
:
originTreeData
,
}
=
useTreeTabs
({
fetchMenuData
:
fetchOriginTreeData
,
})
useEffect
(()
=>
{
if
(
id
)
{
PublicApi
.
getMemberUserGet
({
userId
:
id
}).
then
(
async
res
=>
{
const
{
data
}
=
res
fetchOriginTreeData
().
then
(({
data
:
dataSource
})
=>
{
setFormData
({...
data
,
orgName
:
getParentTreeTitles
(
dataSource
,
data
.
orgId
),
memberRoleIds
:
data
.
memberRoleIds
.
map
((
v
,
i
)
=>
{
return
{
id
:
v
,
roleName
:
data
.
memberRoleNames
[
i
]
}
})})
})
})
}
},
[])
const
onFinish
=
async
(
values
:
any
)
=>
{
values
.
memberRoleIds
=
values
.
memberRoleIds
.
map
(
v
=>
v
.
id
)
const
omitValue
=
omit
(
values
,
[
'orgName'
])
const
params
=
id
?
{
...
omitValue
,
userId
:
Number
(
id
)
}
:
omitValue
await
run
(
params
)
setTimeout
(()
=>
{
history
.
goBack
(
-
1
)
},
300
)
};
// 角色确认弹窗
const
roleConfirm
=
()
=>
{
setRoleVisible
(
false
)
userActions
.
setFieldValue
(
'memberRoleIds'
,
roleSelectCtl
.
selectRow
)
}
const
handleSelectCancel
=
()
=>
{
setRoleVisible
(
false
)
}
const
handleRoleBtn
=
()
=>
{
setRoleVisible
(
true
)
const
selectRoles
=
userActions
.
getFieldValue
(
'memberRoleIds'
)
roleSelectCtl
.
setSelectRow
(
selectRoles
)
roleSelectCtl
.
setSelectedRowKeys
(
selectRoles
.
map
(
v
=>
v
.
id
))
}
// 模拟请求
const
fetchUserList
=
async
(
params
:
any
)
=>
{
const
data
=
await
PublicApi
.
getMemberRolePage
(
params
)
return
data
.
data
}
const
columns
:
ColumnType
<
any
>
[]
=
[
{
title
:
'角色ID'
,
dataIndex
:
'id'
,
align
:
'center'
,
key
:
'id'
,
},
{
title
:
'角色名称'
,
dataIndex
:
'roleName'
,
align
:
'center'
,
key
:
'roleName'
,
},
{
title
:
'描述'
,
align
:
'center'
,
dataIndex
:
'remark'
,
key
:
'remark'
,
ellipsis
:
true
}
]
const
handleOrigin
=
()
=>
{
setOriginVisible
(
false
)
if
(
originSelectNode
?.
id
){
userActions
.
setFieldValue
(
'orgName'
,
originTreeActions
.
getParentPath
(
originSelectNode
.
id
))
userActions
.
setFieldValue
(
'orgId'
,
originSelectNode
.
id
)
}
}
const
handleAddRole
=
()
=>
{
setRoleVisible
(
true
);
}
const
handlePlateformSelect
=
(
key
,
node
)
=>
{
setOriginSelectNode
({
id
:
key
*
1
,
name
:
node
.
_title
})
}
const
openOriginTree
=
()
=>
{
setOriginVisible
(
true
)
}
const
connectCategory
=
pageStatus
!==
PageStatus
.
PREVIEW
?
<
div
className=
'connectBtn'
onClick=
{
openOriginTree
}
><
LinkOutlined
style=
{
{
marginRight
:
4
}
}
/>
关联
</
div
>
:
''
const
addRoles
=
pageStatus
!==
PageStatus
.
PREVIEW
?
<
Button
block
onClick=
{
handleRoleBtn
}
>
添加角色
</
Button
>
:
''
return
(
<
PageHeaderWrapper
onBack=
{
()
=>
history
.
goBack
()
}
backIcon=
{
<
ReutrnEle
description=
"返回"
/>
}
className=
'addRepository'
title=
{
titleRender
(
pageStatus
)
}
>
<
Card
>
<
div
className=
"common-wrapper user-system useConnectBtnWrapper"
>
<
NiceForm
onSubmit=
{
onFinish
}
schema=
{
UserDetailSchema
}
initialValues=
{
formData
}
actions=
{
userActions
}
editable=
{
pageStatus
!==
PageStatus
.
PREVIEW
}
effects=
{
(
$
,
{
setFieldState
})
=>
{
$
(
'onFormInit'
).
subscribe
(()
=>
{
if
(
id
)
{
setFieldState
(
'password'
,
state
=>
{
state
.
visible
=
false
})
}
})
}
}
expressionScope=
{
{
connectCategory
,
addRoles
,
callback
:
(
id
)
=>
{
roleSelectCtl
.
setSelectRow
(
findItemAndDelete
(
roleSelectCtl
.
selectRow
,
id
))
roleSelectCtl
.
setSelectedRowKeys
(
findItemAndDelete
(
roleSelectCtl
.
selectedRowKeys
,
id
))
}
}
}
>
<
FormButtonGroup
offset=
{
6
}
>
<
Button
htmlType=
'submit'
type=
'primary'
hidden=
{
pageStatus
===
PageStatus
.
PREVIEW
}
loading=
{
loading
}
>
提交
</
Button
>
<
Button
onClick=
{
()
=>
history
.
goBack
()
}
>
取消
</
Button
>
</
FormButtonGroup
>
</
NiceForm
>
<
ModalTable
modalTitle=
'选择角色'
visible=
{
roleVisible
}
confirm=
{
roleConfirm
}
cancel=
{
handleSelectCancel
}
columns=
{
columns
}
rowSelection=
{
roleSelection
}
currentRef=
{
ref
}
fetchTableData=
{
(
params
:
any
)
=>
fetchUserList
(
params
)
}
tableProps=
{
{
rowKey
:
'id'
}
}
formilyProps=
{
{
layouts
:
{
order
:
3
},
ctx
:
{
schema
:
{
type
:
'object'
,
properties
:
{
roleName
:
{
type
:
'Search'
,
"x-component-props"
:
{
placeholder
:
'请输入角色名称'
}
}
}
}
}
}
}
/>
<
Modal
title=
"选择组织机构"
visible=
{
originVisible
}
onOk=
{
handleOrigin
}
onCancel=
{
()
=>
setOriginVisible
(
false
)
}
okText=
"确认"
cancelText=
"取消"
getContainer=
'#root'
// destroyOnClose={true}
>
<
TabTree
fetchData
=
{
params
=
>
fetchOriginTreeData(params)}
treeData=
{
originTreeData
}
handleSelect=
{
(
key
,
node
)
=>
handlePlateformSelect
(
key
,
node
)
}
actions=
{
originTreeActions
}
customKey="id"
/
>
</
Modal
>
</
div
>
</
Card
>
</
PageHeaderWrapper
>
);
};
export default AddUser
src/pages/editor/components/toolBar/index.tsx
View file @
2c0fcf86
import
React
from
'react'
import
{
ArrowLeftOutlined
}
from
'@ant-design/icons'
import
{
history
}
from
'umi'
import
{
Modal
}
from
'antd'
import
styles
from
'./index.less'
const
ToolBar
:
React
.
FC
=
()
=>
{
const
handleGoBack
=
()
=>
{
Modal
.
confirm
({
content
:
"是否确认离开模板装修页面?"
,
okText
:
"确认"
,
cancelText
:
"取消"
,
onOk
:
()
=>
{
history
.
goBack
()
}
})
}
return
(
<
div
className=
{
styles
.
toolbar
}
>
<
div
className=
{
styles
.
toolbar_back_btn
}
onClick=
{
()
=>
h
istory
.
g
oBack
()
}
>
<
div
className=
{
styles
.
toolbar_back_btn
}
onClick=
{
()
=>
h
andleG
oBack
()
}
>
<
ArrowLeftOutlined
/>
</
div
>
<
div
className=
{
styles
.
toolbar_title
}
>
...
...
src/pages/editor/shopEdit/index.tsx
View file @
2c0fcf86
...
...
@@ -174,7 +174,7 @@ const ShopEdit: React.FC<ShopEditPropsType> = (props) => {
...
InformationConfig
,
...
FooterConfig
}
console
.
log
(
config
)
setComponentConfigs
(
config
)
setLoading
(
false
)
}
...
...
src/pages/lxMall/commodity/index.less
View file @
2c0fcf86
...
...
@@ -188,48 +188,4 @@
}
}
}
}
.no_result {
padding-top: 120px;
padding-left: 287px;
&_tip {
font-size: 14px;
color: #D32F2F;
font-weight: 500;
display: flex;
&_search {
color: #333333;
}
&_img {
width: 30px;
height: 30px;
overflow: hidden;
margin-right: 16px;
&>img {
width: 30px;
height: 30px;
}
}
}
&_suggest {
margin-top: 12px;
font-size: 12px;
color: #999999;
padding-left: 46px;
&_list {
padding: 0;
margin: 0;
&>li {
list-style: none;
}
}
}
}
\ No newline at end of file
src/pages/lxMall/commodity/index.tsx
View file @
2c0fcf86
...
...
@@ -4,34 +4,26 @@ import Filter, { FilterType } from '../components/Filter'
import
cx
from
'classnames'
import
{
Pagination
}
from
'antd'
import
CommodityList
from
'./list'
import
NoResult
from
'./n
oResult'
import
SearchNoResult
from
'../components/SearchN
oResult'
import
isEmpty
from
'lodash/isEmpty'
import
{
Spin
}
from
'antd'
import
{
PublicApi
}
from
'@/services/api'
import
{
GetSearchCommodityShopGetCommodityListResponseDetail
}
from
'@/services'
import
{
LAYOUT_TYPE
}
from
'@/constants'
import
{
GetSearchShopEnterpriseGetCommodityListResponseDetail
}
from
'@/services'
import
bannerImg
from
'@/assets/imgs/banner_2.png'
import
arrowDownIcon
from
'@/assets/imgs/arrow_down.png'
import
arrowDownActiveIcon
from
'@/assets/imgs/arrow_down_active.png'
import
styles
from
'./index.less'
interface
filterValueType
{
key
:
string
;
key
:
string
|
string
[]
;
title
:
string
;
type
:
FILTER_TYPE
;
}
enum
FILTER_TYPE
{
category
=
'category'
,
// 分类
brand
=
'brand'
,
// 品牌
style
=
'style'
,
// 风格
price
=
'price'
,
// 价格
area
=
'area'
,
// 适用地区
commodityType
=
'commodityType'
,
// 商品类型
type
:
FilterType
;
}
interface
CommodityPropsType
{
location
:
any
,
layoutType
:
'mall'
|
'shop'
|
'channel'
layoutType
:
LAYOUT_TYPE
.
mall
|
LAYOUT_TYPE
.
shop
|
LAYOUT_TYPE
.
channel
}
interface
filterQuery
{
...
...
@@ -52,11 +44,11 @@ interface filterQuery {
const
Commodity
:
React
.
FC
<
CommodityPropsType
>
=
(
props
)
=>
{
const
{
layoutType
}
=
props
const
{
query
:
{
search
=
""
}
}
=
props
.
location
const
{
query
:
{
categoryId
,
categoryName
}
}
=
props
.
location
const
[
loading
,
setLoading
]
=
useState
<
boolean
>
(
true
)
const
[
showType
,
setShowType
]
=
useState
<
number
>
(
1
)
// 展示方式:1:矩阵排列; 2:列表排列
const
[
filterList
,
setFilterList
]
=
useState
([])
const
[
commodityList
,
setCommodityList
]
=
useState
<
GetSearch
CommodityShop
GetCommodityListResponseDetail
[]
>
([])
const
[
commodityList
,
setCommodityList
]
=
useState
<
GetSearch
ShopEnterprise
GetCommodityListResponseDetail
[]
>
([])
const
[
current
,
setCurrent
]
=
useState
<
number
>
(
1
)
const
[
pageSize
,
setPageSize
]
=
useState
<
number
>
(
20
)
const
[
totalCount
,
setTotalCount
]
=
useState
<
number
>
(
0
)
...
...
@@ -65,24 +57,31 @@ const Commodity: React.FC<CommodityPropsType> = (props) => {
useEffect
(()
=>
{
fetchCommodityList
()
},
[
filterParam
,
current
])
useEffect
(()
=>
{
if
(
categoryId
&&
categoryName
)
{
handleFilter
({
key
:
[
categoryId
],
title
:
decodeURIComponent
(
atob
(
categoryName
)),
type
:
FilterType
.
category
,
})
}
},
[
filterParam
,
current
,
search
])
},
[
props
.
location
.
query
])
const
fetchCommodityList
=
()
=>
{
let
param
:
filterQuery
=
{
current
,
pageSize
}
if
(
!!
search
)
{
param
.
name
=
search
}
if
(
!
isEmpty
(
filterParam
))
{
param
=
Object
.
assign
(
param
,
filterParam
)
}
setLoading
(
true
)
//@ts-ignore
PublicApi
.
getSearch
CommodityShop
GetCommodityList
(
param
).
then
(
res
=>
{
PublicApi
.
getSearch
ShopEnterprise
GetCommodityList
(
param
).
then
(
res
=>
{
setLoading
(
false
)
if
(
res
.
code
===
1000
)
{
setCommodityList
(
res
.
data
.
data
)
...
...
@@ -105,14 +104,29 @@ const Commodity: React.FC<CommodityPropsType> = (props) => {
}
else
{
tempFilterList
=
[...
tempFilterList
,
filterValue
]
}
console
.
log
(
tempFilterList
,
"tempFilterList"
)
setFilterList
(
tempFilterList
)
handleFilterChange
(
tempFilterList
)
}
const
handleFilterChange
=
(
newFilterList
:
any
)
=>
{
let
tempFilterParam
:
any
=
{}
for
(
let
filterItem
of
newFilterList
)
{
switch
(
filterItem
.
type
)
{
case
FilterType
.
category
:
tempFilterParam
.
categoryId
=
filterItem
.
key
[
0
]
break
default
:
break
}
}
setFilterParam
(
tempFilterParam
)
}
const
handleDeleteFilterItem
=
(
key
:
string
)
=>
{
let
tempFilterList
=
[...
filterList
]
tempFilterList
=
tempFilterList
.
filter
(
item
=>
String
(
item
.
key
)
!==
String
(
key
))
setFilterList
(
tempFilterList
)
handleFilterChange
(
tempFilterList
)
}
/**
...
...
@@ -120,6 +134,7 @@ const Commodity: React.FC<CommodityPropsType> = (props) => {
*/
const
handleResetFilter
=
()
=>
{
setFilterList
([])
handleFilterChange
([])
}
const
handlePageChange
=
(
page
)
=>
{
...
...
@@ -130,7 +145,7 @@ const Commodity: React.FC<CommodityPropsType> = (props) => {
<
div
className=
{
styles
.
commodity
}
>
<
div
className=
{
styles
.
mall_container
}
>
<
div
className=
{
styles
.
commodity_container
}
>
<
Filter
onFilter=
{
handleFilter
}
filterConfig=
{
filterConfig
}
/>
<
Filter
onFilter=
{
handleFilter
}
filterConfig=
{
filterConfig
}
layoutType=
{
layoutType
}
/>
<
div
className=
{
styles
.
commodity_main
}
>
<
div
className=
{
styles
.
banner
}
>
<
img
src=
{
bannerImg
}
/>
...
...
@@ -185,7 +200,7 @@ const Commodity: React.FC<CommodityPropsType> = (props) => {
</
div
>
</
div
>
{
(
commodityList
.
length
===
0
||
!
commodityList
)
?
<
NoResult
search=
{
search
}
/>
:
(
(
commodityList
.
length
===
0
||
!
commodityList
)
?
<
SearchNoResult
search=
""
/>
:
(
<>
<
Spin
spinning=
{
loading
}
>
<
CommodityList
showType=
{
showType
}
commodityList=
{
commodityList
}
layoutType=
{
layoutType
}
/>
...
...
src/pages/lxMall/commodity/search.tsx
0 → 100644
View file @
2c0fcf86
import
React
,
{
useState
,
useEffect
}
from
'react'
import
{
CaretUpOutlined
,
CaretDownOutlined
,
UnorderedListOutlined
,
AppstoreOutlined
,
CloseOutlined
}
from
'@ant-design/icons'
import
Filter
,
{
FilterType
}
from
'../components/Filter'
import
cx
from
'classnames'
import
{
history
}
from
'umi'
import
{
Pagination
}
from
'antd'
import
CommodityList
from
'./list'
import
SearchNoResult
from
'../components/SearchNoResult'
import
isEmpty
from
'lodash/isEmpty'
import
{
Spin
}
from
'antd'
import
{
PublicApi
}
from
'@/services/api'
import
{
GetSearchShopEnterpriseGetCommodityListResponseDetail
}
from
'@/services'
import
arrowDownIcon
from
'@/assets/imgs/arrow_down.png'
import
arrowDownActiveIcon
from
'@/assets/imgs/arrow_down_active.png'
import
styles
from
'./index.less'
interface
filterValueType
{
key
:
string
;
title
:
string
;
type
:
FilterType
;
}
interface
CommodityPropsType
{
location
:
any
,
layoutType
:
'mall'
|
'shop'
|
'channel'
}
interface
filterQuery
{
current
:
number
;
pageSize
:
number
;
name
?:
string
;
categoryId
?:
number
;
customerCategoryId
?:
number
;
provinceCode
?:
number
;
cityCode
?:
number
;
brandId
?:
number
;
customerAttributeList
?:
any
;
Min
?:
number
;
Max
?:
number
;
priceType
?:
number
;
}
const
CommoditySearch
:
React
.
FC
<
CommodityPropsType
>
=
(
props
)
=>
{
const
{
layoutType
}
=
props
const
{
query
:
{
search
=
""
}
}
=
props
.
location
const
[
loading
,
setLoading
]
=
useState
<
boolean
>
(
true
)
const
[
showType
,
setShowType
]
=
useState
<
number
>
(
1
)
// 展示方式:1:矩阵排列; 2:列表排列
const
[
filterList
,
setFilterList
]
=
useState
([])
const
[
commodityList
,
setCommodityList
]
=
useState
<
GetSearchShopEnterpriseGetCommodityListResponseDetail
[]
>
([])
const
[
current
,
setCurrent
]
=
useState
<
number
>
(
1
)
const
[
pageSize
,
setPageSize
]
=
useState
<
number
>
(
20
)
const
[
totalCount
,
setTotalCount
]
=
useState
<
number
>
(
0
)
const
[
filterParam
,
setFilterParam
]
=
useState
<
filterQuery
|
{}
>
({})
const
filterConfig
=
[
FilterType
.
commonlyUsed
,
FilterType
.
category
,
FilterType
.
style
,
FilterType
.
brand
,
FilterType
.
price
,
FilterType
.
useArea
,
FilterType
.
commodityType
]
useEffect
(()
=>
{
fetchCommodityList
()
},
[
filterParam
,
current
,
search
])
const
fetchCommodityList
=
()
=>
{
let
param
:
filterQuery
=
{
current
,
pageSize
}
if
(
!!
search
)
{
param
.
name
=
search
}
if
(
!
isEmpty
(
filterParam
))
{
param
=
Object
.
assign
(
param
,
filterParam
)
}
setLoading
(
true
)
//@ts-ignore
PublicApi
.
getSearchShopEnterpriseGetCommodityList
(
param
).
then
(
res
=>
{
setLoading
(
false
)
if
(
res
.
code
===
1000
)
{
setCommodityList
(
res
.
data
.
data
)
setTotalCount
(
res
.
data
.
totalCount
)
}
})
}
const
handleFilter
=
(
filterValue
:
filterValueType
)
=>
{
let
filteState
=
filterList
.
some
(
item
=>
item
.
type
===
filterValue
.
type
)
let
tempFilterList
=
[...
filterList
]
if
(
filteState
)
{
tempFilterList
=
tempFilterList
.
map
(
item
=>
{
if
(
item
.
type
===
filterValue
.
type
)
{
return
filterValue
}
return
item
})
}
else
{
tempFilterList
=
[...
tempFilterList
,
filterValue
]
}
setFilterList
(
tempFilterList
)
handleFilterChange
(
tempFilterList
)
}
const
handleFilterChange
=
(
newFilterList
:
any
)
=>
{
let
tempFilterParam
:
any
=
{}
for
(
let
filterItem
of
newFilterList
)
{
switch
(
filterItem
.
type
)
{
case
FilterType
.
category
:
tempFilterParam
.
categoryId
=
filterItem
.
key
[
0
]
break
default
:
break
}
}
setFilterParam
(
tempFilterParam
)
}
const
handleDeleteFilterItem
=
(
key
:
string
)
=>
{
let
tempFilterList
=
[...
filterList
]
tempFilterList
=
tempFilterList
.
filter
(
item
=>
String
(
item
.
key
)
!==
String
(
key
))
setFilterList
(
tempFilterList
)
handleFilterChange
(
tempFilterList
)
}
/**
* 重置筛选
*/
const
handleResetFilter
=
()
=>
{
if
(
search
)
{
setFilterList
([])
history
.
push
(
'/commodity/search'
)
}
else
{
setFilterList
([])
handleFilterChange
([])
}
}
const
handlePageChange
=
(
page
)
=>
{
setCurrent
(
page
)
}
/**
* 清除搜索
*/
const
handleClearSearch
=
()
=>
{
history
.
push
(
'/commodity/search'
)
}
return
(
<
div
className=
{
styles
.
commodity
}
>
<
div
className=
{
styles
.
mall_container
}
>
<
div
className=
{
styles
.
commodity_container
}
>
<
Filter
onFilter=
{
handleFilter
}
filterConfig=
{
filterConfig
}
/>
<
div
className=
{
styles
.
commodity_main
}
>
<
div
className=
{
styles
.
tool_bar
}
>
<
div
className=
{
styles
.
tool_bar_left
}
>
<
div
className=
{
styles
.
tool_bar_filter_item
}
>
<
span
>
销量
</
span
>
<
i
className=
{
styles
.
icon
}
>
<
img
src=
{
arrowDownIcon
}
/>
</
i
>
</
div
>
<
div
className=
{
styles
.
tool_bar_filter_item
}
>
<
span
>
信用
</
span
>
<
i
className=
{
styles
.
icon
}
>
<
img
src=
{
arrowDownIcon
}
/>
</
i
>
</
div
>
<
div
className=
{
styles
.
tool_bar_filter_item
}
>
<
span
>
价格
</
span
>
<
div
className=
{
styles
.
price_filter_box
}
>
<
CaretUpOutlined
className=
{
styles
.
icon
}
/>
<
CaretDownOutlined
className=
{
styles
.
icon
}
/>
</
div
>
</
div
>
</
div
>
<
div
className=
{
styles
.
tool_bar_right
}
>
<
div
className=
{
styles
.
count
}
>
<
span
>
共
</
span
>
<
label
>
{
totalCount
}
</
label
>
<
span
>
个商品
</
span
>
</
div
>
<
AppstoreOutlined
className=
{
cx
(
styles
.
icon
,
showType
===
1
?
styles
.
active
:
''
)
}
onClick=
{
()
=>
setShowType
(
1
)
}
/>
<
UnorderedListOutlined
className=
{
cx
(
styles
.
icon
,
showType
===
2
?
styles
.
active
:
''
)
}
onClick=
{
()
=>
setShowType
(
2
)
}
/>
</
div
>
</
div
>
<
div
className=
{
styles
.
filter_bar
}
>
<
div
className=
{
styles
.
filter_bar_left
}
>
<
div
className=
{
styles
.
filter_bar_left_text1
}
>
当前搜索:
</
div
>
{
/* <div className={styles.filter_bar_left_split}></div>
<div className={styles.filter_bar_left_text} onClick={handleResetFilter}>重置</div> */
}
</
div
>
<
div
className=
{
styles
.
filter_bar_list
}
>
{
search
&&
(
<
div
className=
{
styles
.
filter_bar_list_item
}
>
<
span
className=
{
styles
.
filter_bar_list_item_text
}
>
{
search
}
</
span
>
<
CloseOutlined
className=
{
styles
.
filter_bar_list_item_icon
}
onClick=
{
()
=>
handleClearSearch
()
}
/>
</
div
>
)
}
{
filterList
.
map
(
item
=>
(
<
div
className=
{
styles
.
filter_bar_list_item
}
key=
{
item
.
key
}
>
<
span
className=
{
styles
.
filter_bar_list_item_text
}
>
{
item
.
title
}
</
span
>
<
CloseOutlined
className=
{
styles
.
filter_bar_list_item_icon
}
onClick=
{
()
=>
handleDeleteFilterItem
(
item
.
key
)
}
/>
</
div
>
))
}
{
(
search
||
filterList
.
length
>
0
)
&&
<
div
className=
{
styles
.
filter_bar_reset
}
onClick=
{
handleResetFilter
}
>
重置
</
div
>
}
</
div
>
</
div
>
{
(
commodityList
.
length
===
0
||
!
commodityList
)
?
<
SearchNoResult
search=
{
search
}
/>
:
(
<>
<
Spin
spinning=
{
loading
}
>
<
CommodityList
showType=
{
showType
}
commodityList=
{
commodityList
}
layoutType=
{
layoutType
}
/>
</
Spin
>
<
div
className=
{
styles
.
pagination_wrap
}
>
<
Pagination
showQuickJumper
showSizeChanger=
{
false
}
onChange=
{
handlePageChange
}
current=
{
current
}
pageSize=
{
pageSize
}
total=
{
totalCount
}
/>
</
div
>
</>
)
}
</
div
>
</
div
>
</
div
>
</
div
>
)
}
export
default
CommoditySearch
src/pages/lxMall/components/Category/index.tsx
View file @
2c0fcf86
import
React
,
{
useEffect
}
from
'react'
import
{
MenuOutlined
,
RightOutlined
}
from
'@ant-design/icons'
import
{
inject
,
observer
}
from
'mobx-react'
import
'./index.less'
import
{
Link
}
from
'umi'
import
{
isEmpty
}
from
'@formily/antd/esm/shared'
import
{
LAYOUT_TYPE
}
from
'@/constants'
import
isEmpty
from
'lodash/isEmpty'
import
'./index.less'
interface
CategoryPropsType
{
CategoryStore
?:
any
;
layoutType
?:
LAYOUT_TYPE
.
mall
|
LAYOUT_TYPE
.
shop
|
LAYOUT_TYPE
.
channel
}
const
Category
:
React
.
FC
<
CategoryPropsType
>
=
(
props
)
=>
{
...
...
@@ -14,7 +16,7 @@ const Category: React.FC<CategoryPropsType> = (props) => {
useEffect
(()
=>
{
if
(
isEmpty
(
categoryList
))
{
fetchCategoryList
()
//
fetchCategoryList()
}
},
[])
...
...
src/pages/lxMall/components/Filter/components/Category/index.tsx
View file @
2c0fcf86
import
React
,
{
useEffect
,
useState
}
from
'react'
import
{
Tree
}
from
'antd'
import
FilterBox
from
'../FilterBox'
import
{
LAYOUT_TYPE
}
from
'@/constants'
import
{
inject
,
observer
}
from
'mobx-react'
import
isEmpty
from
'lodash/isEmpty'
import
styles
from
'./index.less'
interface
CategoryPropsType
{
onFilter
?:
Function
;
CategoryStore
?:
any
;
layoutType
?:
LAYOUT_TYPE
.
mall
|
LAYOUT_TYPE
.
shop
|
LAYOUT_TYPE
.
channel
}
const
Category
:
React
.
FC
<
CategoryPropsType
>
=
(
props
)
=>
{
const
{
onFilter
,
CategoryStore
:
{
categoryList
}
}
=
props
const
{
onFilter
,
CategoryStore
:
{
enterpriseCategoryList
,
storeCategoryList
,
fetchEnterpriseCategoryList
,
fetchStoreCategoryList
},
layoutType
=
LAYOUT_TYPE
.
mall
}
=
props
const
[
expandedKeys
,
setExpandedKeys
]
=
useState
<
string
[]
>
([])
const
[
treeData
,
setTreeData
]
=
useState
<
any
>
([])
useEffect
(()
=>
{
if
(
categoryList
&&
categoryList
.
length
>
0
)
{
initTreeData
(
categoryList
)
switch
(
layoutType
)
{
case
LAYOUT_TYPE
.
mall
:
fetchEnterpriseCategoryList
()
break
case
LAYOUT_TYPE
.
shop
:
break
case
LAYOUT_TYPE
.
channel
:
fetchStoreCategoryList
()
break
}
},
[
categoryList
])
},
[
layoutType
])
useEffect
(()
=>
{
if
(
!
isEmpty
(
enterpriseCategoryList
)
||
!
isEmpty
(
storeCategoryList
))
{
switch
(
layoutType
)
{
case
LAYOUT_TYPE
.
mall
:
initTreeData
(
enterpriseCategoryList
)
break
case
LAYOUT_TYPE
.
shop
:
break
case
LAYOUT_TYPE
.
channel
:
initTreeData
(
storeCategoryList
)
break
}
}
},
[
enterpriseCategoryList
,
storeCategoryList
])
const
initTreeData
=
(
list
:
any
)
=>
{
let
initExpandKeys
=
[]
let
result
:
any
=
list
.
map
(
item
=>
{
initExpandKeys
.
push
(
item
.
id
)
return
{
title
:
item
.
title
,
key
:
item
.
id
,
children
:
item
.
children
.
map
(
secondCategoryItem
=>
{
initExpandKeys
.
push
(
secondCategoryItem
.
id
)
return
{
title
:
secondCategoryItem
.
title
,
key
:
secondCategoryItem
.
id
,
...
...
@@ -39,6 +69,8 @@ const Category: React.FC<CategoryPropsType> = (props) => {
})
}
})
// setExpandedKeys(initExpandKeys)
setTreeData
(
result
)
}
...
...
@@ -51,15 +83,20 @@ const Category: React.FC<CategoryPropsType> = (props) => {
})
}
const
handleExpand
=
(
expandedKeys
)
=>
{
setExpandedKeys
(
expandedKeys
)
}
return
(
<
FilterBox
title=
"分类"
>
<
div
className=
{
styles
.
filter_category
}
>
<
Tree
defaultExpandedKeys=
{
[
2
,
"4"
]
}
expandedKeys=
{
expandedKeys
}
onSelect=
{
handleSelect
}
treeData=
{
treeData
}
onExpand=
{
handleExpand
}
/>
</
div
>
</
FilterBox
>
...
...
src/pages/lxMall/components/Filter/index.tsx
View file @
2c0fcf86
...
...
@@ -10,11 +10,13 @@ import CommodityType from './components/CommodityType'
import
ActiveStores
from
'./components/ActiveStores'
import
NewJoin
from
'./components/NewJoin'
import
Points
from
'./components/Points'
import
{
LAYOUT_TYPE
}
from
'@/constants'
import
'./index.less'
interface
FilterPropsType
{
onFilter
?:
Function
;
filterConfig
?:
string
[]
filterConfig
?:
string
[],
layoutType
?:
LAYOUT_TYPE
.
mall
|
LAYOUT_TYPE
.
shop
|
LAYOUT_TYPE
.
channel
}
export
enum
FilterType
{
...
...
@@ -57,11 +59,15 @@ export enum FilterType {
/**
* 所需积分
*/
points
=
'points'
points
=
'points'
,
/**
* 商品名称
*/
name
=
'name'
}
const
Filter
:
React
.
FC
<
FilterPropsType
>
=
(
props
)
=>
{
const
{
onFilter
,
filterConfig
=
[]
}
=
props
const
{
onFilter
,
filterConfig
=
[]
,
layoutType
=
LAYOUT_TYPE
.
mall
}
=
props
const
handleFilter
=
(
filterValue
:
any
)
=>
{
onFilter
(
filterValue
)
...
...
@@ -74,7 +80,7 @@ const Filter: React.FC<FilterPropsType> = (props) => {
case
FilterType
.
commonlyUsed
:
return
<
CommonlyUsed
key=
{
type
}
/>
case
FilterType
.
category
:
return
<
Category
onFilter=
{
handleFilter
}
key=
{
type
}
/>
return
<
Category
onFilter=
{
handleFilter
}
key=
{
type
}
layoutType=
{
layoutType
}
/>
case
FilterType
.
style
:
return
<
Style
onFilter=
{
handleFilter
}
key=
{
type
}
/>
case
FilterType
.
brand
:
...
...
src/pages/lxMall/components/Header/index.tsx
View file @
2c0fcf86
...
...
@@ -5,7 +5,7 @@ import { Link, history } from 'umi'
import
{
FileTextOutlined
}
from
'@ant-design/icons'
import
logo
from
'@/theme/imgs/logo_w.png'
import
isEmpty
from
'lodash/isEmpty'
import
'./index.less'
import
styles
from
'./index.less'
interface
HeaderPropsType
{
...
...
@@ -14,13 +14,14 @@ interface HeaderPropsType {
const
Header
:
React
.
FC
<
HeaderPropsType
>
=
(
props
)
=>
{
const
[
searchType
,
setSearchType
]
=
useState
<
number
>
(
1
)
// 1:商品; 2:店铺
const
[
searchValue
,
setSearchValue
]
=
useState
<
string
>
(
""
)
const
{
search
}
=
history
.
location
.
query
useEffect
(()
=>
{
const
{
search
}
=
history
.
location
.
query
if
(
!!
search
)
{
setSearchValue
(
search
)
}
else
{
setSearchValue
(
""
)
}
},
[])
},
[
search
])
const
handleChangeSearchType
=
(
type
:
number
)
=>
{
if
(
searchType
!==
type
)
{
...
...
@@ -30,34 +31,40 @@ const Header: React.FC<HeaderPropsType> = (props) => {
const
handleSearchCommodity
=
()
=>
{
if
(
!
isEmpty
(
searchValue
))
{
history
.
push
(
`/commodity?search=
${
encodeURIComponent
(
searchValue
)}
`
)
if
(
searchType
===
1
)
{
history
.
push
(
`/commodity/search?search=
${
encodeURIComponent
(
searchValue
)}
`
)
}
else
{
history
.
push
(
`/shops?search=
${
encodeURIComponent
(
searchValue
)}
`
)
}
}
else
{
history
.
push
(
`/commodity`
)
if
(
searchType
===
1
)
{
history
.
push
(
`/commodity`
)
}
else
{
history
.
push
(
`/shops`
)
}
}
}
return
(
<
div
className=
"header"
>
<
div
className=
"header_container"
>
<
div
className=
"logo"
>
<
Link
to=
"/"
>
<
img
src=
{
logo
}
/>
</
Link
>
<
div
className=
{
styles
.
header
}
>
<
div
className=
{
styles
.
header_container
}
>
<
div
className=
{
styles
.
logo
}
>
<
img
src=
{
logo
}
/>
</
div
>
<
div
className=
"mall_search"
>
<
div
className=
"mall_search_tags"
>
<
div
className=
{
cx
(
"mall_search_tags_item"
,
searchType
===
1
?
'active'
:
''
)
}
onClick=
{
()
=>
handleChangeSearchType
(
1
)
}
>
商品
</
div
>
<
div
className=
{
cx
(
"mall_search_tags_item"
,
searchType
===
2
?
'active'
:
''
)
}
onClick=
{
()
=>
handleChangeSearchType
(
2
)
}
>
店铺
</
div
>
<
div
className=
{
styles
.
mall_search
}
>
<
div
className=
{
styles
.
mall_search_tags
}
>
<
div
className=
{
cx
(
styles
.
mall_search_tags_item
,
searchType
===
1
?
styles
.
active
:
''
)
}
onClick=
{
()
=>
handleChangeSearchType
(
1
)
}
>
商品
</
div
>
<
div
className=
{
cx
(
styles
.
mall_search_tags_item
,
searchType
===
2
?
styles
.
active
:
''
)
}
onClick=
{
()
=>
handleChangeSearchType
(
2
)
}
>
店铺
</
div
>
</
div
>
<
div
className=
"mall_search_box"
>
<
Input
className=
"mall_search_input"
value=
{
searchValue
}
placeholder=
"请输入关键词"
onChange=
{
e
=>
setSearchValue
(
e
.
target
.
value
)
}
onPressEnter=
{
()
=>
handleSearchCommodity
()
}
/>
<
div
className=
"search_btn"
onClick=
{
()
=>
handleSearchCommodity
()
}
>
搜索
</
div
>
<
div
className=
{
styles
.
mall_search_box
}
>
<
Input
className=
{
styles
.
mall_search_input
}
value=
{
searchValue
}
placeholder=
"请输入关键词"
onChange=
{
e
=>
setSearchValue
(
e
.
target
.
value
)
}
onPressEnter=
{
()
=>
handleSearchCommodity
()
}
/>
<
div
className=
{
styles
.
search_btn
}
onClick=
{
()
=>
handleSearchCommodity
()
}
>
搜索
</
div
>
</
div
>
</
div
>
<
div
className=
"shopping_cart mall"
onClick=
{
()
=>
history
.
push
(
'/purchaseOrder'
)
}
>
<
div
className=
"badge"
>
0
</
div
>
<
FileTextOutlined
className=
"card_icon"
/>
<
div
className=
{
cx
(
styles
.
shopping_cart
,
styles
.
mall
)
}
onClick=
{
()
=>
history
.
push
(
'/purchaseOrder'
)
}
>
<
div
className=
{
styles
.
badge
}
>
0
</
div
>
<
FileTextOutlined
className=
{
styles
.
card_icon
}
/>
<
span
>
进货单
</
span
>
</
div
>
</
div
>
...
...
src/pages/lxMall/components/SearchNoResult/index.less
0 → 100644
View file @
2c0fcf86
.no_result {
padding-top: 120px;
padding-left: 287px;
&_tip {
font-size: 14px;
color: #D32F2F;
font-weight: 500;
display: flex;
&_search {
color: #333333;
}
&_img {
width: 30px;
height: 30px;
overflow: hidden;
margin-right: 16px;
&>img {
width: 30px;
height: 30px;
}
}
}
&_suggest {
margin-top: 12px;
font-size: 12px;
color: #999999;
padding-left: 46px;
&_list {
padding: 0;
margin: 0;
&>li {
list-style: none;
}
}
}
}
\ No newline at end of file
src/pages/lxMall/com
modity/noResult
.tsx
→
src/pages/lxMall/com
ponents/SearchNoResult/index
.tsx
View file @
2c0fcf86
...
...
@@ -5,16 +5,26 @@ interface NoResultPropsType {
search
?:
string
}
const
NoResult
:
React
.
FC
<
NoResultPropsType
>
=
(
props
)
=>
{
const
Search
NoResult
:
React
.
FC
<
NoResultPropsType
>
=
(
props
)
=>
{
const
{
search
}
=
props
return
(
<
div
className=
{
styles
.
no_result
}
>
<
div
className=
{
styles
.
no_result_tip
}
>
<
div
className=
{
styles
.
no_result_tip_img
}
></
div
>
<
div
className=
{
styles
.
no_result_tip_text
}
>
抱歉,没有找到与“
<
span
className=
{
styles
.
no_result_tip_search
}
>
{
search
}
</
span
>
”相关的商品
{
search
?
(
<>
抱歉,没有找到与“
<
span
className=
{
styles
.
no_result_tip_search
}
>
{
search
}
</
span
>
”相关的商品
</>
)
:
(
<>
抱歉,没有找到相关的商品
</>
)
}
</
div
>
</
div
>
<
div
className=
{
styles
.
no_result_suggest
}
>
...
...
@@ -29,4 +39,4 @@ const NoResult: React.FC<NoResultPropsType> = (props) => {
)
}
export
default
NoResult
export
default
Search
NoResult
src/pages/lxMall/components/TopBar/index.tsx
View file @
2c0fcf86
import
React
from
'react'
import
{
EnvironmentOutlined
}
from
'@ant-design/icons'
import
'./index.less'
import
{
inject
,
observer
}
from
'mobx-react'
import
cx
from
'classnames'
import
styles
from
'./index.less'
interface
TopBarPropsType
{
langComponent
?:
React
.
ReactNode
langComponent
?:
React
.
ReactNode
;
UserStore
?:
any
;
}
const
TopBar
:
React
.
FC
<
TopBarPropsType
>
=
(
props
)
=>
{
const
{
langComponent
}
=
props
const
{
userInfo
}
=
props
.
UserStore
return
(
<
div
className=
"topbar"
>
<
div
className=
"topbar_container"
>
<
ul
className=
"topbar_menu left"
>
<
li
className=
"topbar_menu_item pad_left_0"
>
<
div
className=
{
styles
.
topbar
}
>
<
div
className=
{
styles
.
topbar_container
}
>
<
ul
className=
{
cx
(
styles
.
topbar_menu
,
styles
.
left
)
}
>
<
li
className=
{
cx
(
styles
.
topbar_menu_item
,
styles
.
pad_left_0
)
}
>
<
span
>
XX商城欢迎你!
</
span
>
</
li
>
<
li
className=
"topbar_menu_item"
>
<
EnvironmentOutlined
className=
"icon"
/>
<
li
className=
{
styles
.
topbar_menu_item
}
>
<
EnvironmentOutlined
className=
{
styles
.
icon
}
/>
<
span
>
广州
</
span
>
</
li
>
</
ul
>
<
ul
className=
"topbar_menu right"
>
<
li
className=
"topbar_menu_item"
>
<
a
href=
"/user/login"
>
请登录
</
a
>
</
li
>
<
li
className=
"topbar_menu_item"
>
<
a
href=
"/user/register"
>
注册
</
a
>
</
li
>
<
li
className=
"topbar_menu_item"
>
<
ul
className=
{
cx
(
styles
.
topbar_menu
,
styles
.
right
)
}
>
{
userInfo
?
(
<
li
className=
{
styles
.
topbar_menu_item
}
>
<
span
>
{
userInfo
?.
name
}
</
span
>
</
li
>
)
:
(
<>
<
li
className=
{
styles
.
topbar_menu_item
}
>
<
a
href=
"/user/login"
>
请登录
</
a
>
</
li
>
<
li
className=
{
styles
.
topbar_menu_item
}
>
<
a
href=
"/user/register"
>
注册
</
a
>
</
li
>
</>
)
}
<
li
className=
{
styles
.
topbar_menu_item
}
>
<
a
href=
"/memberCenter/home"
>
会员中心
</
a
>
</
li
>
<
li
className=
"topbar_menu_item"
>
我的消息
</
li
>
<
li
className=
"topbar_menu_item"
>
客户服务
</
li
>
<
li
className=
{
styles
.
topbar_menu_item
}
>
我的消息
</
li
>
<
li
className=
{
styles
.
topbar_menu_item
}
>
<
a
href=
"http://p.qiao.baidu.com/cps/chat?siteId=11220066&userId=24534830&siteToken=49f62d4365e46c0f2c81538e4d168ab9"
target=
"_blank"
>
客户服务
</
a
>
</
li
>
{
langComponent
&&
(<
li
className=
"topbar_menu_item nopad"
>
{
langComponent
}
</
li
>)
langComponent
&&
(<
li
className=
{
cx
(
styles
.
topbar_menu_item
,
styles
.
nopad
)
}
>
{
langComponent
}
</
li
>)
}
</
ul
>
</
div
>
...
...
@@ -42,4 +57,4 @@ const TopBar: React.FC<TopBarPropsType> = (props) => {
)
}
export
default
TopBar
\ No newline at end of file
export
default
inject
(
'UserStore'
)(
observer
(
TopBar
))
\ No newline at end of file
src/pages/lxMall/index/index.tsx
View file @
2c0fcf86
...
...
@@ -92,6 +92,7 @@ const MallIndex: React.FC<MallIndexPropsType> = (props) => {
let
categoryDetail
:
any
=
await
fetchCategoryById
(
item
.
id
)
result
.
push
(
<
FloorLine
linkUrl=
{
`/commodity?categoryId=${item.id}&categoryName=${btoa(encodeURIComponent(item.name))}`
}
anchor=
{
`floorline_${item.id}`
}
key=
{
item
.
id
}
title=
{
item
.
name
}
...
...
src/pages/lxMall/information/index.less
View file @
2c0fcf86
...
...
@@ -13,6 +13,12 @@
.information_focus {
display: flex;
.information_focus_carousel {
width: 598px;
height: 444px;
}
&_left {
position: relative;
margin-right: 4px;
...
...
@@ -22,7 +28,9 @@
&_img {
width: 598px;
height: 444px;
.common_background()
cursor: pointer;
transition: all 1s;
.common_background();
}
}
}
...
...
src/pages/lxMall/information/index.tsx
View file @
2c0fcf86
import
React
,
{
Fragment
}
from
'react'
import
cx
from
'classnames'
import
{
Input
,
Pagination
}
from
'antd'
import
{
Carousel
,
Pagination
}
from
'antd'
import
{
Link
}
from
'umi'
import
{
ClockCircleOutlined
,
EyeOutlined
}
from
'@ant-design/icons'
import
informationImg1
from
'@/assets/imgs/information_1.png'
...
...
@@ -16,92 +16,92 @@ interface InformationPropsType {
const
MockList
=
[
{
id
:
new
Date
().
getTime
(),
id
:
new
Date
().
getTime
()
+
1
,
title
:
'今日热点'
,
list
:
[
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
11
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
12
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
13
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
14
},
]
},
{
id
:
new
Date
().
getTime
(),
id
:
new
Date
().
getTime
()
+
2
,
title
:
'今日热点'
,
list
:
[
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
21
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
22
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
23
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
24
},
]
},
{
id
:
new
Date
().
getTime
(),
id
:
new
Date
().
getTime
()
+
3
,
title
:
'行业头条'
,
list
:
[
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
31
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
32
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
33
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
34
},
]
},
{
id
:
new
Date
().
getTime
(),
id
:
new
Date
().
getTime
()
+
4
,
title
:
'专题报道'
,
list
:
[
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
41
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
42
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
43
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
44
},
]
},
{
id
:
new
Date
().
getTime
(),
id
:
new
Date
().
getTime
()
+
5
,
title
:
'政策法规'
,
list
:
[
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
51
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
52
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
53
},
{
id
:
new
Date
().
getTime
()
id
:
new
Date
().
getTime
()
+
54
},
]
},
...
...
@@ -115,9 +115,18 @@ const Information: React.FC<InformationPropsType> = (props) => {
<
BreadCrumbs
/>
<
div
className=
{
styles
.
information_focus
}
>
<
div
className=
{
styles
.
information_focus_left
}
>
<
div
className=
{
styles
.
information_focus_imgbox_main
}
>
<
div
className=
{
styles
.
information_focus_imgbox_main_img
}
style=
{
{
backgroundImage
:
`url(${informationImg1})`
}
}
/>
</
div
>
<
Carousel
className=
{
styles
.
information_focus_carousel
}
pauseOnDotsHover
>
<
div
className=
{
styles
.
information_focus_carousel_item
}
>
<
div
className=
{
styles
.
information_focus_imgbox_main
}
>
<
div
className=
{
styles
.
information_focus_imgbox_main_img
}
style=
{
{
backgroundImage
:
`url(${informationImg1})`
}
}
/>
</
div
>
</
div
>
<
div
className=
{
styles
.
information_focus_carousel_item
}
>
<
div
className=
{
styles
.
information_focus_imgbox_main
}
>
<
div
className=
{
styles
.
information_focus_imgbox_main_img
}
style=
{
{
backgroundImage
:
`url(${informationImg2})`
}
}
/>
</
div
>
</
div
>
</
Carousel
>
</
div
>
<
div
className=
{
styles
.
information_focus_right
}
>
<
div
className=
{
styles
.
information_focus_imgbox_sub_1
}
>
...
...
src/pages/lxMall/layouts/LXChannelLayout.tsx
View file @
2c0fcf86
import
React
,
{
useEffect
}
from
'react'
import
React
,
{
useEffect
,
useState
}
from
'react'
import
{
BasicLayoutProps
as
ProLayoutProps
,
getMenuData
}
from
'@ant-design/pro-layout'
;
}
from
'@ant-design/pro-layout'
import
SelectLang
from
'@/layouts/components/SelectLang'
import
{
useIntl
}
from
'umi'
;
import
{
useIntl
}
from
'umi'
import
{
inject
,
observer
}
from
'mobx-react'
import
TopBar
from
'../components/TopBar'
import
ChannelHeader
from
'../components/ChannelHeader'
import
MainNav
from
'../components/MainNav'
...
...
@@ -18,10 +19,12 @@ interface LXMallLayoutPropsType {
routes
:
Array
<
any
>
};
location
:
any
;
SiteStore
?:
any
;
}
const
LXChannelLayout
:
React
.
FC
<
LXMallLayoutPropsType
>
=
(
props
)
=>
{
const
{
children
,
location
}
=
props
const
[
templateName
]
=
useState
<
string
>
(
'theme-channel-science'
)
const
getMenuRouter
=
(
routes
:
any
,
pathname
:
any
)
=>
{
let
list
=
routes
.
filter
((
item
:
any
)
=>
pathname
.
indexOf
(
item
.
key
)
>
-
1
)
...
...
@@ -33,8 +36,8 @@ const LXChannelLayout: React.FC<LXMallLayoutPropsType> = (props) => {
const
menuRouter
=
getMenuRouter
(
menuData
,
location
.
pathname
)
useEffect
(()
=>
{
let
body
=
document
.
getElementsByTagName
(
'body'
)[
0
]
;
body
.
className
=
`theme-channel-science`
;
let
body
=
document
.
getElementsByTagName
(
'body'
)[
0
]
body
.
className
=
templateName
},
[])
return
(
...
...
@@ -65,4 +68,4 @@ const LXChannelLayout: React.FC<LXMallLayoutPropsType> = (props) => {
)
}
export
default
LXChannelLayout
export
default
inject
(
"SiteStore"
)(
observer
(
LXChannelLayout
))
src/pages/lxMall/layouts/LXMallLayout.tsx
View file @
2c0fcf86
import
React
,
{
useEffect
}
from
'react'
import
React
,
{
useEffect
,
useState
}
from
'react'
import
{
BasicLayoutProps
as
ProLayoutProps
,
getMenuData
}
from
'@ant-design/pro-layout'
;
}
from
'@ant-design/pro-layout'
import
SelectLang
from
'@/layouts/components/SelectLang'
import
{
useIntl
}
from
'umi'
;
import
{
useIntl
}
from
'umi'
import
{
inject
,
observer
}
from
'mobx-react'
import
TopBar
from
'../components/TopBar'
import
Header
from
'../components/Header'
import
MainNav
from
'../components/MainNav'
...
...
@@ -18,10 +19,13 @@ interface LXMallLayoutPropsType {
routes
:
Array
<
any
>
};
location
:
any
;
SiteStore
?:
any
;
}
const
LXMallLayout
:
React
.
FC
<
LXMallLayoutPropsType
>
=
(
props
)
=>
{
const
{
children
,
location
}
=
props
const
[
templateName
]
=
useState
<
string
>
(
'theme-mall-science'
)
const
{
siteId
}
=
props
.
SiteStore
const
getMenuRouter
=
(
routes
:
any
,
pathname
:
any
)
=>
{
let
list
=
routes
.
filter
((
item
:
any
)
=>
pathname
.
indexOf
(
item
.
key
)
>
-
1
)
...
...
@@ -31,10 +35,10 @@ const LXMallLayout: React.FC<LXMallLayoutPropsType> = (props) => {
const
basicInfo
=
getMenuData
(
props
.
route
.
routes
,
{
locale
:
true
},
formatMessage
)
const
menuData
=
basicInfo
.
menuData
?
basicInfo
.
menuData
.
filter
(
item
=>
!
item
.
redirect
)
:
[]
const
menuRouter
=
getMenuRouter
(
menuData
,
location
.
pathname
)
useEffect
(()
=>
{
console
.
log
(
`tempalteName=theme-mall-science`
)
let
body
=
document
.
getElementsByTagName
(
'body'
)[
0
];
body
.
className
=
`theme-mall-science`
;
body
.
className
=
templateName
;
},
[])
return
(
...
...
@@ -65,4 +69,4 @@ const LXMallLayout: React.FC<LXMallLayoutPropsType> = (props) => {
)
}
export
default
LXMallLayout
export
default
inject
(
"SiteStore"
)(
observer
(
LXMallLayout
))
src/pages/lxMall/layouts/LXShopLayout.tsx
View file @
2c0fcf86
import
React
,
{
useEffect
}
from
'react'
import
React
,
{
useEffect
,
useState
}
from
'react'
import
{
BasicLayoutProps
as
ProLayoutProps
,
getMenuData
}
from
'@ant-design/pro-layout'
;
import
{
useIntl
}
from
'umi'
;
import
TopBar
from
'../components/TopBar'
import
Advert
from
'../components/Adver
t'
import
{
inject
,
observer
}
from
'mobx-reac
t'
import
ShopHeader
from
'../components/ShopHeader'
import
MainNav
from
'../components/MainNav'
import
SideNav
from
'../components/SideNav'
...
...
@@ -18,16 +18,17 @@ interface LXMallLayoutPropsType {
routes
:
Array
<
any
>
};
location
:
any
;
SiteStore
?:
any
;
}
const
LXMallLayout
:
React
.
FC
<
LXMallLayoutPropsType
>
=
(
props
)
=>
{
const
LXShopLayout
:
React
.
FC
<
LXMallLayoutPropsType
>
=
(
props
)
=>
{
const
{
children
,
location
}
=
props
const
[
templateName
]
=
useState
<
string
>
(
'theme-shop-science'
)
useEffect
(()
=>
{
console
.
log
(
'当前使用店铺模板'
)
let
body
=
document
.
getElementsByTagName
(
'body'
)[
0
];
body
.
className
=
`
${
body
.
className
}
theme-shop-science`
;
body
.
className
=
templateName
;
},
[])
const
{
formatMessage
}
=
useIntl
();
...
...
@@ -56,4 +57,5 @@ const LXMallLayout: React.FC<LXMallLayoutPropsType> = (props) => {
)
}
export
default
LXMallLayout
export
default
inject
(
"SiteStore"
)(
observer
(
LXShopLayout
))
src/pages/lxMall/shopList/index.tsx
View file @
2c0fcf86
...
...
@@ -88,23 +88,6 @@ const ShopList: React.FC<ShopListPropsType> = (props) => {
</
div
>
</
div
>
</
div
>
{
/* <div className="filter_bar">
<div className="filter_bar_left">
<div className="filter_bar_left_text">保存为常用筛选</div>
<div className="filter_bar_left_split"></div>
<div className="filter_bar_left_text" onClick={handleResetFilter}>重置</div>
</div>
<div className="filter_bar_list">
{
filterList.map(item => (
<div className="filter_bar_list_item" key={item.key}>
<span className="filter_bar_list_item_text">{item.title}</span>
<CloseOutlined className="filter_bar_list_item_icon" onClick={() => handleDeleteFilterItem(item.key)} />
</div>
))
}
</div>
</div> */
}
{
!!
search
?
<
NoResult
search=
{
search
}
/>
:
(
<>
...
...
src/pages/repositories/components/PositionSetting.tsx
View file @
2c0fcf86
...
...
@@ -11,10 +11,15 @@ import {
PlusOutlined
,
LinkOutlined
,
}
from
'@ant-design/icons'
import
{
Button
}
from
'antd'
import
{
Button
,
message
}
from
'antd'
import
NiceForm
from
'@/components/NiceForm'
import
ModalTable
from
'@/components/ModalTable'
import
{
GlobalConfig
}
from
'@/global/config'
import
{
FORM_FILTER_PATH
}
from
'@/formSchema/const'
import
SearchSelect
from
'@/components/NiceForm/components/SearchSelect'
import
Search
from
'@/components/NiceForm/components/Search'
import
{
useStateFilterSearchLinkageEffect
}
from
'@/formSchema/effects/useFilterSearch'
import
Submit
from
'@/components/NiceForm/components/Submit'
export
interface
PositionSettingProps
{
addSchemaAction
:
ISchemaFormActions
,
...
...
@@ -27,10 +32,7 @@ const fetchMemberList = async (params) => {
return
res
.
data
}
const
fetchProductList
=
async
(
params
)
=>
{
const
res
=
await
PublicApi
.
getProductCommodityGetCommodityDetailList
(
params
)
return
res
.
data
}
const
PositionSetting
:
React
.
FC
<
PositionSettingProps
>
=
(
props
)
=>
{
const
{
addSchemaAction
,
schema
,
formSubmit
}
=
props
...
...
@@ -47,6 +49,14 @@ const PositionSetting:React.FC<PositionSettingProps> = (props) => {
const
initValue
=
useInitValue
(
PublicApi
.
getWarehouseFreightSpaceDetails
)
useUnitPreview
(
initValue
,
addSchemaAction
)
const
fetchProductList
=
async
(
params
)
=>
{
const
res
=
await
PublicApi
.
getProductCommodityCommonGetCommodityDetailList
({
...
params
,
shopType
:
addSchemaAction
.
getFieldValue
(
'shopType'
)
})
return
res
.
data
}
// 会员选择后的表格
const
handleDeleteTable
=
(
id
)
=>
{
const
value
=
addSchemaAction
.
getFieldValue
(
'applyMember'
)
...
...
@@ -62,6 +72,11 @@ const PositionSetting:React.FC<PositionSettingProps> = (props) => {
// 弹出商品选择
const
handleAddProductBtn
=
()
=>
{
const
shopType
=
addSchemaAction
.
getFieldValue
(
'shopType'
)
if
(
!
shopType
)
{
message
.
error
(
'请先选择商城类型'
)
return
false
}
productRowCtl
.
setSelectedRowKeys
([])
productRowCtl
.
setSelectRow
([])
setVisibleChannelRroduct
(
true
)
...
...
@@ -211,9 +226,59 @@ const PositionSetting:React.FC<PositionSettingProps> = (props) => {
properties
:
{
name
:
{
type
:
'string'
,
"x-component"
:
'Search'
,
"x-component-props"
:
{
placeholder
:
'请输入商品名称'
'x-component'
:
'ModalSearch'
,
'x-component-props'
:
{
placeholder
:
'请输入商品名称/ID'
,
align
:
'flex-left'
,
},
},
[
FORM_FILTER_PATH
]:
{
type
:
'object'
,
'x-component'
:
'flex-layout'
,
'x-component-props'
:
{
rowStyle
:
{
flexWrap
:
'nowrap'
,
style
:
{
marginRight
:
0
}
},
colStyle
:
{
marginTop
:
20
,
},
},
properties
:
{
categoryId
:
{
type
:
'string'
,
"x-component"
:
'SearchSelect'
,
"x-component-props"
:
{
placeholder
:
'请选择品类'
,
className
:
'fixed-ant-selected-down'
,
// 该类强制将显示的下拉框出现在select下, 只有这里出现问题, ??
fetchSearch
:
PublicApi
.
getProductSelectGetSelectCategory
,
style
:
{
width
:
160
}
}
},
brandId
:
{
type
:
'string'
,
"x-component"
:
'SearchSelect'
,
"x-component-props"
:
{
placeholder
:
'请选择品牌'
,
fetchSearch
:
PublicApi
.
getProductSelectGetSelectBrand
,
style
:
{
width
:
160
}
}
},
submit
:
{
"x-component"
:
'Submit'
,
"x-mega-props"
:
{
span
:
1
},
"x-component-props"
:
{
children
:
'查询'
}
}
}
}
}
...
...
@@ -272,7 +337,18 @@ const PositionSetting:React.FC<PositionSettingProps> = (props) => {
fetchTableData=
{
params
=>
fetchProductList
(
params
)
}
formilyProps=
{
{
ctx
:
{
schema
:
formProduct
}
ctx
:
{
schema
:
formProduct
,
components
:
{
ModalSearch
:
Search
,
SearchSelect
,
Submit
}
,
effects
:
(
$
,
actions
)
=>
{
useStateFilterSearchLinkageEffect
(
$
,
actions
,
'name'
,
FORM_FILTER_PATH
,
);
}
}
}
}
tableProps=
{
{
...
...
src/pages/repositories/schema/index.tsx
View file @
2c0fcf86
...
...
@@ -8,11 +8,12 @@ import { SHOP_TYPES } from '@/constants';
// 将获取的商城转化为可用类型
const
getShopTypeMap
=
(()
=>
{
return
GlobalConfig
.
web
.
shopInfo
.
reduce
((
prev
,
next
)
=>
{
if
(
!
prev
.
find
(
v
=>
v
.
value
===
next
.
id
))
{
prev
.
push
({
label
:
next
.
name
,
value
:
next
.
id
})
const
shopTypeEnumValue
=
SHOP_TYPES
.
find
(
v
=>
v
.
value
===
next
.
type
)
if
(
!
shopTypeEnumValue
)
{
return
prev
}
if
(
!
prev
.
find
(
v
=>
v
.
value
===
shopTypeEnumValue
.
value
))
{
prev
.
push
(
shopTypeEnumValue
)
}
return
prev
},
[])
...
...
src/pages/user/components/LoginWrap.tsx
View file @
2c0fcf86
...
...
@@ -18,11 +18,7 @@ const LoginWrap: React.FC = () => {
PublicApi
.
postMemberLogin
(
value
).
then
(
res
=>
{
const
{
data
,
code
}
=
res
if
(
code
===
1000
)
{
setAuth
({
memberId
:
data
.
memberId
,
userId
:
data
.
userId
,
token
:
data
.
token
})
setAuth
(
data
)
setRouters
(
data
.
urls
)
// 此处需使用href跳转, 否则无法触发app.ts中的路由初始化校验
window
.
location
.
href
=
'/memberCenter/home'
...
...
src/services/api.ts
View file @
2c0fcf86
/*
* @Author: LeeJiancong
* @Date: 2020-07-22 09:54:50
* @LastEditors: LeeJiancong
* @LastEditTime: 2020-07-22 10:23:38
*/
import
*
as
Api
from
'./index'
import
request
from
'@/utils/request'
import
*
as
LogisticsApi
from
'./LogisticsApi'
import
*
as
PassApi
from
'./PassApi'
import
*
as
WarehouseApi
from
'./WarehouseApi'
import
*
as
MemberApi
from
'./MemberApi'
import
*
as
ProductApi
from
'./ProductApi'
import
*
as
TemplateApi
from
'./TemplateApi'
import
*
as
PayApi
from
'./PayApi'
import
*
as
SearchApi
from
'./SearchApi'
import
*
as
OrderApi
from
'./OrderApi'
/**
* 可在这里写入自定义的接口
...
...
@@ -15,4 +16,14 @@ export const CustomApi = {
}
// 公共的接口,从yapi拉下
export
const
PublicApi
=
Api
export
const
PublicApi
=
{
...
LogisticsApi
,
...
PassApi
,
...
WarehouseApi
,
...
MemberApi
,
...
ProductApi
,
...
TemplateApi
,
...
PayApi
,
...
SearchApi
,
...
OrderApi
,
}
src/store/category/index.ts
View file @
2c0fcf86
import
{
action
,
computed
,
observable
,
runInAction
}
from
'mobx'
import
{
GlobalConfig
}
from
'@/global/config'
import
{
PublicApi
}
from
'@/services/api'
import
{
GetSearchCommodityGetCategoryTreeResponse
}
from
'@/services'
const
defaultCategory
=
[
{
...
...
@@ -47,16 +45,45 @@ const defaultCategory = [
]
class
CategoryStore
{
@
observable
public
categoryList
:
GetSearchCommodityGetCategoryTreeResponse
=
[];
// 品类列表
@
observable
public
categoryList
:
any
=
[];
// 品类列表
@
observable
public
enterpriseCategoryList
:
any
=
[]
@
observable
public
storeCategoryList
:
any
=
[]
/**
* 企业商城商品分类列表
*/
@
action
.
bound
public
async
fetchCategoryList
()
{
let
res
=
await
PublicApi
.
getSearchCommodityGetCategoryTree
()
let
res
=
await
PublicApi
.
getSearchShopEnterpriseGetCategoryTree
()
runInAction
(()
=>
{
this
.
enterpriseCategoryList
=
res
.
data
||
[]
})
}
/**
* 企业商城商品分类列表
*/
@
action
.
bound
public
async
fetchEnterpriseCategoryList
()
{
let
res
=
await
PublicApi
.
getSearchShopEnterpriseGetCategoryTree
()
runInAction
(()
=>
{
this
.
enterpriseCategoryList
=
res
.
data
||
[]
})
}
/**
* 店铺商城商品分类列表
*/
@
action
.
bound
public
async
fetchStoreCategoryList
()
{
let
res
=
await
PublicApi
.
getSearchShopStoreGetCustomerCategoryTree
()
runInAction
(()
=>
{
this
.
c
ategoryList
=
res
.
data
||
[]
this
.
storeC
ategoryList
=
res
.
data
||
[]
})
}
}
export
default
CategoryStore
src/store/filter/index.ts
0 → 100644
View file @
2c0fcf86
import
{
action
,
computed
,
observable
,
runInAction
}
from
'mobx'
import
{
FILTE_RTYPE
}
from
'@/constants'
interface
filterValueType
{
key
:
string
|
string
[];
title
:
string
;
type
:
FILTE_RTYPE
;
}
class
FilterStore
{
/**
* 筛选条件列表
*/
@
observable
filterList
=
[]
@
action
public
handleFilter
=
(
filterValue
:
filterValueType
)
=>
{
}
}
export
default
FilterStore
\ No newline at end of file
src/store/index.tsx
View file @
2c0fcf86
...
...
@@ -27,12 +27,12 @@ import { IProductModule } from '@/module/productModule'
*/
export
interface
IStore
{
u
serStore
:
ILoginModule
;
U
serStore
:
ILoginModule
;
ProductStore
:
IProductModule
;
}
export
const
store
=
{
u
serStore
:
new
UserStore
,
U
serStore
:
new
UserStore
,
ThemeStore
:
new
ThemeStore
,
ProductStore
:
new
ProductStroe
,
SiteStore
:
new
SiteStore
,
...
...
src/store/user/index.ts
View file @
2c0fcf86
import
{
action
,
computed
,
observable
,
runInAction
}
from
'mobx'
import
{
ILoginModule
}
from
'@/module/userModule'
;
import
{
ILoginModule
}
from
'@/module/userModule'
import
{
getAuth
}
from
'@/utils/auth'
import
{
localStorage
}
from
'@/utils/storage'
// import { userDetailGet } from '@/services/user'
...
...
@@ -9,7 +10,7 @@ class LoginStore implements ILoginModule {
@
observable
public
username
:
string
=
'admin'
;
@
observable
public
password
:
string
=
"123456"
;
@
observable
public
res
:
object
=
{};
@
observable
public
userInfo
=
{}
//userInfo ? JSON.parse(userInfo) : {}
@
observable
public
userInfo
=
getAuth
()
// 可以改变对应的状态值
// @todo 接入更新用户信息接口
...
...
src/theme/science/styles/category.less
View file @
2c0fcf86
...
...
@@ -47,9 +47,10 @@
margin: 0;
&_item {
position: relative;
padding-left: 20px;
padding: 12px 19px 8px 20px;
padding-top: 12px;
height: 56px;
list-style: none;
cursor: pointer;
...
...
src/utils/auth.ts
View file @
2c0fcf86
...
...
@@ -3,6 +3,7 @@ import { isDev } from '@/constants'
export
interface
AuthInfo
{
userId
:
number
,
memberId
:
number
,
name
:
string
,
token
:
string
}
...
...
ytt.config.ts
View file @
2c0fcf86
/*
* @Author: LeeJiancong
* @Date: 2020-07-22 09:54:50
* @LastEditors: LeeJiancong
* @Copyright: 1549414730@qq.com
* @LastEditTime: 2020-08-24 16:09:13
*/
import
{
Config
}
from
'god-yapi2ts'
const
tokens
=
[
'b063a0a29fb1a570d9f00eaabbdd8ccfe8e6e10e24739441990cc1098e79b601'
,
// 业务中台管理平台
'7c8f235d95f6224ceb97c4d832b09658f9a75fb8721a95699b230af0733d7fa4'
,
// 仓库服务
'8d14d945507d1f8cd89afe139ca6d111bbad25f702fafe0aec59d3c9cd2e0ffe'
,
// 物流服务
'3a46198c5b97ac7147e5b07ad2dff5ac5c93c1afed47e1911961db87149e6ebf'
,
// 商户会员管理服务
'efe99e20ed1375dc0db3e809e4fc7692f42ecebaf60cd77e65c50ed65d6ba6c4'
,
// 商品服务
'7ec923520215c7e2f771867cb4d29cafbf823daf0fb2d3d9fa70b57a523c8bfb'
,
// 店铺服务
'c789e0e56ee8a8cc2fbd85f930eb2928c58fc1014583c6643acf29cff954da49'
,
// 支付服务
'ca19f532efba91f7773cbfbd526b798c6ac83df670071e97d72c50dca1d53a48'
,
// 搜索服务
'5de0aaeaac12c8d911d86dada6cd128993e34cd6e13135fa79246aa5979a2bcd'
//订单服务
const
tokenList
=
[
{
name
:
'Pass'
,
token
:
'b063a0a29fb1a570d9f00eaabbdd8ccfe8e6e10e24739441990cc1098e79b601'
},
// 业务中台管理平台
{
name
:
'Warehouse'
,
token
:
'7c8f235d95f6224ceb97c4d832b09658f9a75fb8721a95699b230af0733d7fa4'
},
// 仓库服务
{
name
:
'Logistics'
,
token
:
'8d14d945507d1f8cd89afe139ca6d111bbad25f702fafe0aec59d3c9cd2e0ffe'
},
// 物流服务
{
name
:
'Member'
,
token
:
'3a46198c5b97ac7147e5b07ad2dff5ac5c93c1afed47e1911961db87149e6ebf'
},
// 商户会员管理服务
{
name
:
'Product'
,
token
:
'efe99e20ed1375dc0db3e809e4fc7692f42ecebaf60cd77e65c50ed65d6ba6c4'
},
// 商品服务
{
name
:
'Template'
,
token
:
'7ec923520215c7e2f771867cb4d29cafbf823daf0fb2d3d9fa70b57a523c8bfb'
},
// 店铺模板服务
{
name
:
'Pay'
,
token
:
'c789e0e56ee8a8cc2fbd85f930eb2928c58fc1014583c6643acf29cff954da49'
},
// 支付服务
{
name
:
'Search'
,
token
:
'ca19f532efba91f7773cbfbd526b798c6ac83df670071e97d72c50dca1d53a48'
},
// 搜索服务
{
name
:
'Order'
,
token
:
'5de0aaeaac12c8d911d86dada6cd128993e34cd6e13135fa79246aa5979a2bcd'
},
//订单服务
]
const
genMap
=
(
tokens
)
=>
{
return
tokens
.
map
(
v
=>
{
return
{
token
:
v
,
const
getConfigMap
=
(
tokens
)
=>
tokens
.
map
(
v
=>
({
serverUrl
:
'http://10.0.0.25:4000/'
,
typesOnly
:
false
,
reactHooks
:
{
enabled
:
false
,
},
outputFilePath
:
`src/services/
${
v
.
name
}
Api.ts`
,
requestFunctionFilePath
:
'request.ts'
,
dataKey
:
'data'
,
projects
:
[
{
token
:
v
.
token
,
categories
:
[
{
id
:
0
,
...
...
@@ -33,21 +31,7 @@ const genMap = (tokens) => {
},
]
}
})
}
const
config
:
Config
=
[
{
serverUrl
:
'http://10.0.0.25:4000/'
,
typesOnly
:
false
,
reactHooks
:
{
enabled
:
false
,
},
outputFilePath
:
'src/services/index.ts'
,
requestFunctionFilePath
:
'request.ts'
,
dataKey
:
'data'
,
projects
:
genMap
(
tokens
),
},
]
],
}))
export
default
config
\ No newline at end of file
export
default
getConfigMap
(
tokenList
)
\ No newline at end of file
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